mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-05-01 15:14:22 +02:00
Compare commits
7 commits
8e4d4f1120
...
b222407beb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b222407beb | ||
|
|
ea52a15e5b | ||
|
|
9afa792b56 | ||
|
|
3269949c0f | ||
|
|
7bad559314 | ||
|
|
d13c920471 | ||
|
|
e1e0d63df1 |
9 changed files with 265 additions and 262 deletions
10
src/Makefile
10
src/Makefile
|
|
@ -8,7 +8,7 @@ all: $(PROJ).hex
|
|||
|
||||
SN_bate = 1
|
||||
MCU_bate = attiny424
|
||||
C_FILES_bate = uart.c rtc.c calib.c mul.c
|
||||
C_FILES_bate = uart.c rtc.c calib.c mul.c adc.c
|
||||
|
||||
BATE_PERIOD=76
|
||||
bate_CFLAGS = -DPERIOD=$(BATE_PERIOD)
|
||||
|
|
@ -122,16 +122,18 @@ fuse: $(PROJ).fuse$F
|
|||
|
||||
# see bate.c: Configuration in USERROW
|
||||
BC_MAGIC = 0xba
|
||||
BC_VERS = 1
|
||||
BC_VERS = 2
|
||||
BC_CLK = 1
|
||||
BC_PWR = 0x00
|
||||
BC_SEND = 0x0f
|
||||
BC_SEND = 0x07
|
||||
BC_TRIG = 0x08
|
||||
BC_MCLK = 0
|
||||
BC_MDEL = 32
|
||||
BC_PIT = 0xff
|
||||
BC_BAUD = 0 0
|
||||
BC_TEST = 4
|
||||
BATE_CONFIG = $(BC_MAGIC) $(BC_VERS) $(BC_PWR) $(BC_SEND) $(BC_TRIG) \
|
||||
BATE_CONFIG = $(BC_MAGIC) $(BC_VERS) $(BC_CLK) \
|
||||
$(BC_PWR) $(BC_SEND) $(BC_TRIG) \
|
||||
$(BC_MCLK) $(BC_MDEL) $(BC_PIT) $(BC_BAUD) $(BC_TEST)
|
||||
bate.config:
|
||||
$(AD) -U userrow:v:"$(BATE_CONFIG)":m \
|
||||
|
|
|
|||
185
src/adc.c
185
src/adc.c
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
|
||||
#include "adc.h"
|
||||
#include "bate.h"
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
enum adc_conf_parameter {
|
||||
|
|
@ -16,7 +17,6 @@ enum adc_conf_parameter {
|
|||
V_BAT = ADC_MUXPOS_AIN7_gc,
|
||||
};
|
||||
|
||||
static const
|
||||
struct adc_conf adc_conf[N_ADC] = {
|
||||
{ // Internal Temperature
|
||||
.mode = MODE,
|
||||
|
|
@ -52,39 +52,49 @@ struct adc_conf adc_conf[N_ADC] = {
|
|||
};
|
||||
|
||||
uint16_t adc_readings[N_ADC];
|
||||
uint8_t adc_current;
|
||||
uint8_t adc_current = 0xff;
|
||||
|
||||
static inline
|
||||
void start_conversion(const struct adc_conf *c)
|
||||
{
|
||||
ADC.CTRLA = ADC_ENABLE_bm | ADC_RUNSTDBY_bm;
|
||||
ADC.CTRLC = c->ref;
|
||||
ADC.MUXNEG = c->inn;
|
||||
ADC.MUXPOS = c->inp;
|
||||
ADC.COMMAND = c->mode;
|
||||
}
|
||||
|
||||
void init_adc()
|
||||
{
|
||||
PORTA.PIN4CTRL |= PORT_ISC_INPUT_DISABLE_gc;
|
||||
PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
|
||||
PORTA.PIN7CTRL |= PORT_ISC_INPUT_DISABLE_gc;
|
||||
}
|
||||
|
||||
void start_adc()
|
||||
{
|
||||
if (!adc_conf->mode)
|
||||
return;
|
||||
ADC.CTRLA = ADC_ENABLE_bm | ADC_RUNSTDBY_bm;
|
||||
ADC.COMMAND = 0;
|
||||
ADC.CTRLB = ADC_PRESC_DIV10_gc;
|
||||
ADC.INTCTRL = ADC_RESRDY_bm;
|
||||
ADC.CTRLE = 32 << ADC_SAMPDUR_gp;
|
||||
ADC.CTRLF = ADC_SAMPNUM_ACC64_gc;
|
||||
ADC.CTRLF = ADC_SAMPNUM_ACC64_gc | ADC_LEFTADJ_bm;
|
||||
adc_current = 0;
|
||||
ADC.INTFLAGS = 0xff;
|
||||
ADC.INTCTRL = ADC_RESRDY_bm; // this seems to be ineffective, for some reason.
|
||||
start_conversion(adc_conf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
ISR(ADC0_RESRDY_vect)
|
||||
static inline
|
||||
void adc_next()
|
||||
{
|
||||
uint8_t i = adc_current;
|
||||
if (!(ADC.INTFLAGS & ADC_RESRDY_bm))
|
||||
return;
|
||||
if (i >= N_ADC)
|
||||
goto stop;
|
||||
adc_readings[i] = ADC.RESULT;
|
||||
// ADC.RESULT is a DWORD, 32-bit.
|
||||
// gcc load all four bytes, then stores two
|
||||
// and thus requires four extra regs
|
||||
// to be pushed on the stack
|
||||
ADC.INTFLAGS = ADC_RESRDY_bm;
|
||||
while (++i < N_ADC) {
|
||||
const struct adc_conf *c = adc_conf + i;
|
||||
if (c->mode && c->mode != 0xff) {
|
||||
|
|
@ -97,12 +107,30 @@ stop:
|
|||
ADC.CTRLA = 0;
|
||||
adc_current = N_ADC;
|
||||
}
|
||||
|
||||
uint8_t adc_finished()
|
||||
{
|
||||
cli();
|
||||
adc_next();
|
||||
sei();
|
||||
return adc_current;
|
||||
}
|
||||
|
||||
// For unknow reasons, this ISR never executes …
|
||||
|
||||
#if 1
|
||||
ISR(ADC0_RESRDY_vect)
|
||||
{
|
||||
DEBUG_COUNTER(adc_irqs);
|
||||
adc_next();
|
||||
}
|
||||
#else
|
||||
// This saves
|
||||
// This saved (at some earlier point of debugging)
|
||||
// - 29 of 86 instructions,
|
||||
// - 24 of 110 clk cycles in the common path
|
||||
// - 9 of 14 bytes of stack space,
|
||||
// - and avoids unlikely branches.
|
||||
|
||||
ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
||||
{
|
||||
__asm__(
|
||||
|
|
@ -128,7 +156,7 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
|||
"brsh 4f" "\n\t"
|
||||
"subi r24, 0xff" "\n\t"
|
||||
"mov r30, r24" "\n\t"
|
||||
"ldi r31, 0" "\n\t"
|
||||
"clr r31" "\n\t"
|
||||
"lsl r30" "\n\t"
|
||||
"lsl r30" "\n\t"
|
||||
"subi r30, lo8(-(adc_conf))" "\n\t"
|
||||
|
|
@ -138,8 +166,6 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
|||
"subi r25, 1" "\n\t"
|
||||
"cpi r25, 0xfe" "\n\t"
|
||||
"brsh 3f" "\n\t"
|
||||
"ldi r25, %[MODE]" "\n\t"
|
||||
"sts %[CTRLA], r25" "\n\t"
|
||||
"ldd r25, Z+1" "\n\t"
|
||||
"sts %[CTRLC], r25" "\n\t"
|
||||
"ldd r25, Z+3" "\n\t"
|
||||
|
|
@ -170,7 +196,6 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
|||
: :
|
||||
[NADC] "n" (N_ADC),
|
||||
[RESULT] "n" (&ADC.RESULT),
|
||||
[MODE] "n" (ADC_ENABLE_bm | ADC_RUNSTDBY_bm),
|
||||
[CTRLA] "n" (&ADC.CTRLA),
|
||||
[CTRLC] "n" (&ADC.CTRLA),
|
||||
[MUXPOS] "n" (&ADC.MUXPOS),
|
||||
|
|
@ -179,131 +204,3 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
|||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
gcc-14.0.1 output
|
||||
|
||||
__vector_22:
|
||||
push r1 ;
|
||||
push r0 ;
|
||||
in r0,__SREG__ ; ,
|
||||
push r0 ;
|
||||
clr __zero_reg__ ;
|
||||
push r18 ;
|
||||
push r20 ;
|
||||
push r21 ;
|
||||
push r22 ;
|
||||
push r23 ;
|
||||
push r24 ;
|
||||
push r25 ;
|
||||
push r26 ;
|
||||
push r27 ;
|
||||
push r30 ;
|
||||
push r31 ;
|
||||
/* prologue: Signal */
|
||||
/* frame size = 0 */
|
||||
/* stack size = 14 */
|
||||
.L__stack_usage = 14
|
||||
; adc.c:80: uint8_t i = adc_current;
|
||||
lds r24,adc_current ; i, adc_current
|
||||
; adc.c:81: if (i >= N_ADC)
|
||||
cpi r24,lo8(6) ; i,
|
||||
brsh .L8 ; ,
|
||||
; adc.c:83: adc_readings[i] = ADC.RESULT;
|
||||
lds r20,1552 ; _1, MEM[(struct ADC_t *)1536B].D.1628.RESULT
|
||||
lds r21,1552+1 ; _1, MEM[(struct ADC_t *)1536B].D.1628.RESULT
|
||||
lds r22,1552+2 ; _1, MEM[(struct ADC_t *)1536B].D.1628.RESULT
|
||||
lds r23,1552+3 ; _1, MEM[(struct ADC_t *)1536B].D.1628.RESULT
|
||||
; adc.c:83: adc_readings[i] = ADC.RESULT;
|
||||
mov r30,r24 ; i, i
|
||||
ldi r31,0 ; i
|
||||
lsl r30 ; tmp62
|
||||
rol r31 ; tmp62
|
||||
subi r30,lo8(-(adc_readings)) ; tmp63,
|
||||
sbci r31,hi8(-(adc_readings)) ; tmp63,
|
||||
st Z,r20 ; adc_readings[i_11], _1
|
||||
std Z+1,r21 ; adc_readings[i_11], _1
|
||||
subi r24,lo8(-(1)) ; i,
|
||||
mov r30,r24 ; _33, i
|
||||
ldi r31,0 ; _33
|
||||
lsl r30 ; _34
|
||||
rol r31 ; _34
|
||||
lsl r30 ; _34
|
||||
rol r31 ; _34
|
||||
subi r30,lo8(-(adc_conf)) ; ivtmp.11,
|
||||
sbci r31,hi8(-(adc_conf)) ; ivtmp.11,
|
||||
; adc.c:84: while (++i < N_ADC) {
|
||||
rjmp .L6 ;
|
||||
.L7:
|
||||
; adc.c:85: const struct adc_conf *c = adc_conf + i;
|
||||
movw r26,r30 ; c, ivtmp.11
|
||||
; adc.c:86: if (c->mode && c->mode != 0xff) {
|
||||
ld r25,Z ; _5, MEM[(unsigned int *)c_14]
|
||||
; adc.c:86: if (c->mode && c->mode != 0xff) {
|
||||
adiw r30,4 ; ivtmp.11,
|
||||
; adc.c:86: if (c->mode && c->mode != 0xff) {
|
||||
ldi r18,lo8(-1) ; _6,
|
||||
add r18,r25 ; _6, _5
|
||||
; adc.c:86: if (c->mode && c->mode != 0xff) {
|
||||
cpi r18,lo8(-2) ; _6,
|
||||
brlo .L10 ; ,
|
||||
subi r24,lo8(-(1)) ; i,
|
||||
.L6:
|
||||
; adc.c:84: while (++i < N_ADC) {
|
||||
cpi r24,lo8(6) ; i,
|
||||
brne .L7 ; ,
|
||||
.L8:
|
||||
; adc.c:93: ADC.CTRLA = 0;
|
||||
sts 1536,__zero_reg__ ; MEM[(struct ADC_t *)1536B].CTRLA,
|
||||
; adc.c:94: adc_current = N_ADC;
|
||||
ldi r24,lo8(6) ; tmp58,
|
||||
sts adc_current,r24 ; adc_current, tmp58
|
||||
.L3:
|
||||
/* epilogue start */
|
||||
; adc.c:95: }
|
||||
pop r31 ;
|
||||
pop r30 ;
|
||||
pop r27 ;
|
||||
pop r26 ;
|
||||
pop r25 ;
|
||||
pop r24 ;
|
||||
pop r23 ;
|
||||
pop r22 ;
|
||||
pop r21 ;
|
||||
pop r20 ;
|
||||
pop r18 ;
|
||||
pop r0 ;
|
||||
out __SREG__,r0 ; ,
|
||||
pop r0 ;
|
||||
pop r1 ;
|
||||
reti
|
||||
.L10:
|
||||
; adc.c:87: adc_current = i;
|
||||
sts adc_current,r24 ; adc_current, i
|
||||
; adc.c:60: ADC.CTRLA = ADC_ENABLE_bm | ADC_RUNSTDBY_bm;
|
||||
ldi r24,lo8(-127) ; tmp69,
|
||||
sts 1536,r24 ; MEM[(struct ADC_t *)1536B].CTRLA, tmp69
|
||||
; adc.c:61: ADC.CTRLC = c->ref;
|
||||
adiw r26,1 ; c_14->ref
|
||||
ld r24,X ; _18
|
||||
sbiw r26,1 ; c_14->ref
|
||||
; adc.c:61: ADC.CTRLC = c->ref;
|
||||
sts 1538,r24 ; MEM[(struct ADC_t *)1536B].CTRLC, _18
|
||||
; adc.c:62: ADC.MUXNEG = c->inn;
|
||||
adiw r26,3 ; c_14->inn
|
||||
ld r24,X ; _19
|
||||
sbiw r26,3 ; c_14->inn
|
||||
; adc.c:62: ADC.MUXNEG = c->inn;
|
||||
sts 1549,r24 ; MEM[(struct ADC_t *)1536B].MUXNEG, _19
|
||||
; adc.c:63: ADC.MUXPOS = c->inp;
|
||||
adiw r26,2 ; c_14->inp
|
||||
ld r24,X ; _20
|
||||
; adc.c:63: ADC.MUXPOS = c->inp;
|
||||
sts 1548,r24 ; MEM[(struct ADC_t *)1536B].MUXPOS, _20
|
||||
; adc.c:64: ADC.COMMAND = c->mode;
|
||||
sts 1546,r25 ; MEM[(struct ADC_t *)1536B].COMMAND, _5
|
||||
; adc.c:89: return;
|
||||
rjmp .L3 ;
|
||||
.size __vector_22, .-__vector_22
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,8 +14,11 @@ struct adc_conf {
|
|||
uint8_t inn;
|
||||
};
|
||||
|
||||
uint16_t adc_readings[N_ADC];
|
||||
uint8_t adc_current;
|
||||
extern uint16_t adc_readings[N_ADC];
|
||||
extern uint8_t adc_current;
|
||||
|
||||
uint8_t adc_finished();
|
||||
void start_adc();
|
||||
void init_adc();
|
||||
static inline uint8_t adc_busy() { return ADC.STATUS & 1; }
|
||||
extern struct adc_conf adc_conf[N_ADC];
|
||||
|
|
|
|||
235
src/bate.c
235
src/bate.c
|
|
@ -12,10 +12,11 @@
|
|||
#include <avr/sleep.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
#include "uart.h"
|
||||
#include "bate.h"
|
||||
#include "rtc.h"
|
||||
#include "calib.h"
|
||||
#include "mul.h"
|
||||
#include "adc.h"
|
||||
|
||||
#define Bit(x) (1<<(x))
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ void rfen(uint8_t on)
|
|||
//
|
||||
// BATE, read data from an MS5534C pressure sensor
|
||||
|
||||
#define BATE_PORT PORTA
|
||||
#define BATE_PORT VPORTA
|
||||
#define SCK_PORT 3
|
||||
#define DOUT_PORT 2
|
||||
#define DIN_PORT 1
|
||||
|
|
@ -97,6 +98,8 @@ void init_mclk(uint8_t p)
|
|||
MCLK.CMP0 = p;
|
||||
MCLK.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc | TCA_SINGLE_ENABLE_bm;
|
||||
MCLK.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_FRQ_gc;
|
||||
BATE_PORT.DIR |= Bit(DIN_PORT);
|
||||
BATE_PORT.DIR |= Bit(SCK_PORT);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
|
@ -130,84 +133,97 @@ ISR(TCA0_CMP0_vect, ISR_NAKED)
|
|||
union bate bate;
|
||||
struct pressure pressure;
|
||||
|
||||
|
||||
// Spec:
|
||||
// _____ _____ _____
|
||||
// SCK ____/ \_____/ \_____/ \_____
|
||||
// _____ _____ _____ __
|
||||
// DIN -<_____>-----<_____>-----<_____>-----<__
|
||||
// _____ ___________ ___________ __________
|
||||
// DOUT _____X___________X___________X__________
|
||||
//
|
||||
// Impl:
|
||||
// _______
|
||||
// SCK _______/ \_
|
||||
// _ _______________
|
||||
// DIN _X_______________
|
||||
//
|
||||
// DOUT xxxxxSxxxxxxxxxxx
|
||||
//
|
||||
|
||||
__attribute__ ((noinline, noclone))
|
||||
static
|
||||
uint8_t bate_bit(uint8_t r, uint8_t c, uint8_t ii)
|
||||
{
|
||||
#if 1
|
||||
#if 0
|
||||
uint8_t clkl = 10;
|
||||
uint8_t clkh = 30;
|
||||
if (c & ii)
|
||||
BATE_PORT.OUT |= Bit(DIN_PORT);
|
||||
else
|
||||
BATE_PORT.OUT &=~ Bit(DIN_PORT);
|
||||
if (BATE_PORT.IN & Bit(DOUT_PORT))
|
||||
r |= ii;
|
||||
else
|
||||
r &= ~ii;
|
||||
while(clkl)
|
||||
clkl--;
|
||||
BATE_PORT.OUT |= Bit(SCK_PORT);
|
||||
while(clkh)
|
||||
clkh--;
|
||||
BATE_PORT.OUT &=~ Bit(SCK_PORT);
|
||||
#else
|
||||
__asm__(
|
||||
"ldi r25, %[DI]" "\n\t"
|
||||
"and %[c], %[ii]" "\n\t"
|
||||
"brne .+6" "\n\t"
|
||||
"sts %[PC], r25" "\n\t"
|
||||
"breq .+6" "\n\t"
|
||||
"sts %[PS], r25" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"lds r25, %[PI]" "\n\t"
|
||||
"sbrc r25, %[DO]" "\n\t"
|
||||
"or %[r], %[ii]" "\n\t"
|
||||
"com %[ii]" "\n\t"
|
||||
"sbrs r25, %[DO]" "\n\t"
|
||||
"and %[r], %[ii]" "\n\t"
|
||||
"ldi r25, %[SK]" "\n\t"
|
||||
"and %[c], %[ii]" "\n\t"
|
||||
"brne 1f" "\n\t"
|
||||
"cbi %[PORT], %[DIN]" "\n\t"
|
||||
"1:" "\n\t"
|
||||
"breq 2f" "\n\t"
|
||||
"sbi %[PORT], %[DIN]" "\n\t"
|
||||
"2:" "\n\t"
|
||||
"sbic %[PIN], %[DOUT]" "\n\t"
|
||||
"or %[r], %[ii]" "\n\t"
|
||||
"com %[ii]" "\n\t"
|
||||
"sbis %[PIN], %[DOUT]" "\n\t"
|
||||
"and %[r], %[ii]" "\n\t"
|
||||
|
||||
"sts %[PS], r25" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"sbi %[PORT], %[SCK]" "\n\t"
|
||||
|
||||
"sts %[PC], r25" "\n"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
"nop" "\n\t"
|
||||
|
||||
"cbi %[PORT], %[SCK]" "\n"
|
||||
|
||||
:[r] "+r" (r),
|
||||
[c] "+r" (c)
|
||||
:[ii] "r" (ii),
|
||||
[PS] "n" (&BATE_PORT.OUTSET),
|
||||
[PC] "n" (&BATE_PORT.OUTCLR),
|
||||
[PI] "n" (&BATE_PORT.IN),
|
||||
[DI] "n" (Bit(DIN_PORT)),
|
||||
[DO] "n" (DOUT_PORT),
|
||||
[SK] "n" (Bit(SCK_PORT))
|
||||
: "r25", "memory"
|
||||
[PORT] "n" (_SFR_IO_ADDR(BATE_PORT.OUT)),
|
||||
[PIN] "n" (_SFR_IO_ADDR(BATE_PORT.IN)),
|
||||
[DIN] "n" (DIN_PORT),
|
||||
[DOUT] "n" (DOUT_PORT),
|
||||
[SCK] "n" (SCK_PORT)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
if (c&ii)
|
||||
BATE_PORT.OUTSET = Bit(DIN_PORT);
|
||||
else
|
||||
BATE_PORT.OUTCLR = Bit(DIN_PORT);
|
||||
if (BATE_PORT.IN & Bit(DOUT_PORT))
|
||||
r |= ii;
|
||||
else
|
||||
r &=~ ii;
|
||||
BATE_PORT.OUTSET = Bit(SCK_PORT);
|
||||
BATE_PORT.OUTCLR = Bit(SCK_PORT);
|
||||
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__attribute__ ((noinline, noclone))
|
||||
static
|
||||
uint16_t bate_frame(uint16_t d, uint8_t n)
|
||||
|
|
@ -288,9 +304,8 @@ void read_bate()
|
|||
bate_frame(0,1);
|
||||
bate.D2 = bate_frame(0, 16);
|
||||
bate.H1 = 0xba7e;
|
||||
# ifndef WDT_TRIGGERED
|
||||
bate.H2 += 1;
|
||||
# endif
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -301,6 +316,7 @@ void read_bate()
|
|||
struct config {
|
||||
uint8_t magic;
|
||||
uint8_t version;
|
||||
uint8_t cpu_clk;
|
||||
uint8_t power;
|
||||
uint8_t send;
|
||||
uint8_t triggers;
|
||||
|
|
@ -313,7 +329,7 @@ struct config {
|
|||
|
||||
enum magic_flags {
|
||||
USE_USERROW = 0xBA,
|
||||
USE_VERSION = 0x01,
|
||||
USE_VERSION = 0x02,
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -327,6 +343,7 @@ enum send_flags {
|
|||
SEND_CLOCK = 0x02,
|
||||
SEND_HEX = 0x04,
|
||||
SEND_CALIB = 0x08,
|
||||
SEND_ADC = 0x10,
|
||||
SEND_DEBUG = 0x80,
|
||||
};
|
||||
enum trigger_flags {
|
||||
|
|
@ -337,36 +354,40 @@ enum trigger_flags {
|
|||
TRIGGER_BREAK = 0x10,
|
||||
};
|
||||
|
||||
static struct config config_ram = {
|
||||
static struct config config = {
|
||||
.send = SEND_BOOT_MESSAGE | SEND_CLOCK | SEND_HEX,
|
||||
.triggers = TRIGGER_CONT,
|
||||
.cpu_clk = CLKCTRL_PDIV_2X_gc | 1,
|
||||
.triggers = TRIGGER_CLOCK,
|
||||
.mclk_delay = 0xff,
|
||||
.pit_period = RTC_CLKSEL_INT1K_gc,
|
||||
};
|
||||
static struct config *config = & config_ram;
|
||||
static const struct config *userrow = (struct config *) & USERROW;
|
||||
|
||||
#ifdef DEBUG
|
||||
struct debug debug_data;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// main()
|
||||
|
||||
int main()
|
||||
{
|
||||
CCP = CCP_IOREG_gc;
|
||||
CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_2X_gc | 1;
|
||||
BATE_PORT.DIRSET = Bit(SCK_PORT) | Bit(DIN_PORT);
|
||||
|
||||
if (userrow->magic == USE_USERROW
|
||||
&& userrow->version == USE_VERSION)
|
||||
memcpy(config, &USERROW, sizeof(struct config));
|
||||
memcpy(&config, userrow, sizeof(struct config));
|
||||
|
||||
init_mclk(config->mclk_period);
|
||||
while (CLKCTRL.MCLKCTRLB != config.cpu_clk) {
|
||||
CCP = CCP_IOREG_gc;
|
||||
CLKCTRL.MCLKCTRLB = config.cpu_clk;
|
||||
}
|
||||
|
||||
init_adc();
|
||||
init_mclk(config.mclk_period);
|
||||
init_led();
|
||||
init_rfen();
|
||||
init_uart(config->baud_div);
|
||||
init_rtc(config->pit_period);
|
||||
|
||||
rfen(1);
|
||||
init_uart(config.baud_div);
|
||||
init_rtc(config.pit_period);
|
||||
|
||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||
sleep_enable();
|
||||
|
|
@ -374,18 +395,18 @@ int main()
|
|||
|
||||
send_str("Hallo\n");
|
||||
|
||||
if (config->send & SEND_BOOT_MESSAGE) {
|
||||
if (config.send & SEND_BOOT_MESSAGE) {
|
||||
send_str("V Turbo Weather V0.01\n");
|
||||
send_hex('S', (uint8_t *)&SIGROW, sizeof(SIGROW_t));
|
||||
send_hex('F', (uint8_t *)&FUSE, sizeof(FUSE_t));
|
||||
send_hex('U', (uint8_t *)&USERROW, sizeof(USERROW_t));
|
||||
send_hex('C', (uint8_t *)config, sizeof(struct config));
|
||||
send_hex('C', (uint8_t *)&config, sizeof(struct config));
|
||||
}
|
||||
|
||||
uint8_t trigger = TRIGGER_CONT | TRIGGER_ONCE;
|
||||
uint8_t mclk_delay = config->mclk_delay;
|
||||
uint8_t mclk_delay = config.mclk_delay;
|
||||
|
||||
uint8_t test_calib = config->calib_test;
|
||||
uint8_t test_calib = config.calib_test;
|
||||
static const union bate testdata[4] = {
|
||||
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x470c, 0x773f }, }, // 21.2 °C, 1021.7 mbar
|
||||
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x1a51, 0x6fed }, }, // 7.5 °C, 5.4 mbar
|
||||
|
|
@ -397,13 +418,30 @@ int main()
|
|||
|
||||
sleep_cpu();
|
||||
|
||||
if (config.send & SEND_ADC) {
|
||||
uint8_t nadc = adc_finished();
|
||||
if (nadc < N_ADC) {
|
||||
if (config.send & SEND_DEBUG) {
|
||||
DEBUG_PRINT(0xaa, nadc);
|
||||
DEBUG_HEX(&ADC, 14);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (adc_current == N_ADC) {
|
||||
adc_current = 0xff;
|
||||
send_hex('A', (uint8_t *)adc_readings,
|
||||
sizeof(adc_readings));
|
||||
}
|
||||
}
|
||||
if (uart_busy()) {
|
||||
uart_tick();
|
||||
continue;
|
||||
}
|
||||
|
||||
wdt_reset();
|
||||
|
||||
rfen(0);
|
||||
led(0);
|
||||
|
||||
if (uart_tick())
|
||||
trigger |= TRIGGER_UART;
|
||||
|
|
@ -412,10 +450,10 @@ int main()
|
|||
if (clock_tick)
|
||||
trigger |= TRIGGER_CLOCK;
|
||||
|
||||
if (!(trigger & config->triggers)) {
|
||||
if (config->power & POWER_DOWN) {
|
||||
if (!(trigger & config.triggers)) {
|
||||
if (config.power & POWER_DOWN) {
|
||||
mclk(0);
|
||||
if (config->power & POWER_DOWN_CLI)
|
||||
if (config.power & POWER_DOWN_CLI)
|
||||
cli();
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
sleep_enable();
|
||||
|
|
@ -429,37 +467,42 @@ int main()
|
|||
continue;
|
||||
tick = 0;
|
||||
|
||||
rfen(1);
|
||||
led(1);
|
||||
|
||||
if (!mclk_status()) {
|
||||
mclk(1);
|
||||
mclk_delay = config->mclk_delay;
|
||||
mclk_delay = config.mclk_delay;
|
||||
}
|
||||
if (mclk_delay) {
|
||||
mclk_delay--;
|
||||
continue;
|
||||
}
|
||||
|
||||
rfen(1);
|
||||
read_bate();
|
||||
if (config.power & STOP_MCLK)
|
||||
mclk(0);
|
||||
|
||||
if (config.send & SEND_ADC)
|
||||
start_adc();
|
||||
|
||||
cli();
|
||||
uint32_t time = clock;
|
||||
read_bate();
|
||||
if (config->power & STOP_MCLK)
|
||||
mclk(0);
|
||||
sei();
|
||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||
sleep_enable();
|
||||
if (config->send & SEND_CLOCK) {
|
||||
if (config.send & SEND_CLOCK) {
|
||||
send_str("T 0x");
|
||||
send_hex_long(time);
|
||||
send_str(" 0x");
|
||||
send_hex_byte(trigger);
|
||||
send_char_sleep('\n');
|
||||
}
|
||||
|
||||
const union bate *b = &bate;
|
||||
if (test_calib)
|
||||
b = testdata + (--test_calib & 3);
|
||||
if (config->send & SEND_HEX)
|
||||
if (config.send & SEND_HEX)
|
||||
send_hex('B', b->b, sizeof(union bate));
|
||||
if (config->send & SEND_CALIB) {
|
||||
if (config.send & SEND_CALIB) {
|
||||
bate_calib(b, &pressure);
|
||||
send_str("P ");
|
||||
send_str(decimal_str(pressure.p, 1));
|
||||
|
|
|
|||
37
src/bate.h
Normal file
37
src/bate.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// bate.h
|
||||
//
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#define DEBUG
|
||||
#ifdef DEBUG
|
||||
|
||||
struct debug {
|
||||
uint8_t value;
|
||||
uint8_t magic;
|
||||
uint16_t adc_irqs;
|
||||
};
|
||||
|
||||
extern struct debug debug_data;
|
||||
|
||||
#define DEBUG_COUNTER(c) (debug_data.c ++)
|
||||
|
||||
static inline
|
||||
void DEBUG_PRINT(uint8_t magic, uint8_t value) {
|
||||
debug_data.magic = magic;
|
||||
debug_data.value = value;
|
||||
send_hex('X', &debug_data.value, sizeof(struct debug));
|
||||
}
|
||||
|
||||
#define DEBUG_HEX(d, s) send_hex('X', (const uint8_t *)(d), s)
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_COUNTER(c) 0
|
||||
|
||||
void DEBUG_PRINT(uint8_t magic, uint8_t value) {}
|
||||
|
||||
#define DEBUG_HEX(d, s) 0
|
||||
|
||||
#endif
|
||||
|
|
@ -25,7 +25,7 @@ void bate_calib(const union bate *bate, struct pressure *pt)
|
|||
uint16_t D2 = bate->D2;
|
||||
|
||||
uint16_t UT1 = C5 + 20224;
|
||||
int32_t dT = D2 - UT1;
|
||||
uint16_t dT = D2 - UT1;
|
||||
|
||||
uint16_t TEMPSENS = C6 + 50;
|
||||
int16_t TEMP = mul16sun(dT, TEMPSENS, 6) + 200;
|
||||
|
|
@ -75,7 +75,7 @@ void bate_calib(const union bate *bate, struct pressure *pt)
|
|||
}
|
||||
|
||||
static const union bate testdata[] = {
|
||||
{ .w = { 0x7EBA, 0xA41A, 0x91A6, 0x970A, 0x9F98, 0x28AF, 0xB848, 0x2771 }, },
|
||||
{ .w = { 0x7EBA, 0xA41A, 0xA691, 0x0A93, 0x989F, 0x28AF, 0x4896, 0x71F4 }, },
|
||||
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x470c, 0x773f }, }, // 21.2 °C, 1021.7 mbar
|
||||
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x1a51, 0x6fed }, }, // 7.5 °C, 5.4 mbar
|
||||
{ .W = { 0xaa3d, 0x35d9, 0xcbe5, 0xb736}, .D = { 0x4bb7, 0x7487 }, }, // 17.7 °C, 1023.0 mbar
|
||||
|
|
|
|||
|
|
@ -97,18 +97,21 @@ int16_t mul16sun(int16_t s, uint16_t u, uint8_t n)
|
|||
"add r21, r0" "\n\t"
|
||||
"adc %A[s], r1" "\n\t"
|
||||
"adc %B[s], r18" "\n\t"
|
||||
"cpi %[n], 0" "\n\t"
|
||||
"breq 3f" "\n\t"
|
||||
"sbrs %[n], 3" "\n\t"
|
||||
"rjmp .+14" "\n\t"
|
||||
"rjmp 2f" "\n\t"
|
||||
"mov %B[s], %A[s]" "\n\t"
|
||||
"mov %A[s], r21" "\n\t"
|
||||
"rjmp 2f" "\n"
|
||||
"rjmp 3f" "\n"
|
||||
"1:" "\t"
|
||||
"lsl r21" "\n\t"
|
||||
"rol %A[s]" "\n\t"
|
||||
"rol %B[s]" "\n\t"
|
||||
"2:" "\t"
|
||||
"dec %[n]" "\n\t"
|
||||
"brpl 1b" "\n"
|
||||
"2:" "\t"
|
||||
"3:" "\t"
|
||||
"clr r1" "\n\t"
|
||||
: [s] "+r" (s)
|
||||
: [u] "a" (u),
|
||||
|
|
|
|||
22
src/uart.c
22
src/uart.c
|
|
@ -27,7 +27,7 @@ void init_uart(uint16_t div)
|
|||
USART0.CTRLA = USART_RXCIE_bm;
|
||||
}
|
||||
|
||||
static uint8_t rx_tick;
|
||||
uint8_t rx_tick;
|
||||
|
||||
ISR(PORTB_PORT_vect, ISR_NAKED)
|
||||
{
|
||||
|
|
@ -52,9 +52,9 @@ uint8_t uart_tick()
|
|||
return r;
|
||||
}
|
||||
|
||||
static uint8_t uart_tx[64];
|
||||
static uint8_t uart_tx_w;
|
||||
static uint8_t uart_tx_r;
|
||||
uint8_t uart_tx[64];
|
||||
uint8_t uart_tx_w;
|
||||
uint8_t uart_tx_r;
|
||||
static const uint8_t uart_tx_m = sizeof(uart_tx) - 1;
|
||||
|
||||
static inline void tx()
|
||||
|
|
@ -180,10 +180,16 @@ void send_hex_long(uint32_t b)
|
|||
__attribute__ ((noinline, noclone))
|
||||
void send_hex(uint8_t header, const uint8_t *s, uint8_t n)
|
||||
{
|
||||
// dump little endian words.
|
||||
send_char_sleep(header);
|
||||
send_char_sleep(' ');
|
||||
while (n--)
|
||||
send_hex_byte(*(s++));
|
||||
while (n--) {
|
||||
send_char_sleep(' ');
|
||||
uint8_t l = *(s++);
|
||||
if (n&1) {
|
||||
send_hex_byte(*(s++));
|
||||
n--;
|
||||
}
|
||||
send_hex_byte(l);
|
||||
}
|
||||
send_char_sleep('\n');
|
||||
}
|
||||
|
||||
|
|
|
|||
12
src/uart.h
12
src/uart.h
|
|
@ -10,6 +10,10 @@ void init_uart(uint16_t div);
|
|||
uint8_t uart_tick();
|
||||
uint8_t uart_busy();
|
||||
uint8_t send_char(uint8_t c);
|
||||
extern uint8_t uart_tx[64];
|
||||
extern uint8_t uart_tx_w;
|
||||
extern uint8_t uart_tx_r;
|
||||
|
||||
extern uint8_t uart_rx[16];
|
||||
extern uint8_t uart_rx_n;
|
||||
extern uint8_t uart_rx_mes;
|
||||
|
|
@ -42,3 +46,11 @@ void send_str(const char *s)
|
|||
send_char_sleep(*s++);
|
||||
}
|
||||
|
||||
static inline
|
||||
void panic(const char *s)
|
||||
{
|
||||
uart_tx_w = 0;
|
||||
uart_tx_r = 0;
|
||||
while (*s)
|
||||
send_char(*s++);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue