Compare commits

..

7 commits

Author SHA1 Message Date
Stephan I. Böttcher
b222407beb adc: worknow, but w/o isr
The RESRDY vector is never called, neither the SAMPRDY, when enabled.
No idea why. We do polling now.
No idea what wakes the CPU from sleep with STOP_MCLK.
2024-04-09 19:08:23 +02:00
Stephan I. Böttcher
ea52a15e5b uart: panic(), spaces in hexdump 2024-04-09 18:14:39 +02:00
Stephan I. Böttcher
9afa792b56 bate: fixes
- adc.h: adc_init(), disable inputs used for analog inputs.
- bate: PORTA → VPORTA, restore blinkenlight's bate_bit()
- config V2: add cpu_clk, remove config pointer indirection
- CLKCTRL: make extra sure we run at 10 MHz
    → regained telemetry at 2400 baud
- turn on LED while digitizing and transmitting
2024-04-09 00:43:34 +02:00
Stephan I. Böttcher
3269949c0f Makefile: BV_VERS=2 2024-04-09 00:42:25 +02:00
Stephan I. Böttcher
7bad559314 calib: fix bitsize of dT, add test case 2024-04-09 00:41:13 +02:00
Stephan I. Böttcher
d13c920471 adc: fix globals, add adc_init() 2024-04-09 00:40:07 +02:00
Stephan I. Böttcher
e1e0d63df1 mul16sun: fix case n=0 2024-04-09 00:38:13 +02:00
9 changed files with 265 additions and 262 deletions

View file

@ -8,7 +8,7 @@ all: $(PROJ).hex
SN_bate = 1 SN_bate = 1
MCU_bate = attiny424 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_PERIOD=76
bate_CFLAGS = -DPERIOD=$(BATE_PERIOD) bate_CFLAGS = -DPERIOD=$(BATE_PERIOD)
@ -122,16 +122,18 @@ fuse: $(PROJ).fuse$F
# see bate.c: Configuration in USERROW # see bate.c: Configuration in USERROW
BC_MAGIC = 0xba BC_MAGIC = 0xba
BC_VERS = 1 BC_VERS = 2
BC_CLK = 1
BC_PWR = 0x00 BC_PWR = 0x00
BC_SEND = 0x0f BC_SEND = 0x07
BC_TRIG = 0x08 BC_TRIG = 0x08
BC_MCLK = 0 BC_MCLK = 0
BC_MDEL = 32 BC_MDEL = 32
BC_PIT = 0xff BC_PIT = 0xff
BC_BAUD = 0 0 BC_BAUD = 0 0
BC_TEST = 4 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) $(BC_MCLK) $(BC_MDEL) $(BC_PIT) $(BC_BAUD) $(BC_TEST)
bate.config: bate.config:
$(AD) -U userrow:v:"$(BATE_CONFIG)":m \ $(AD) -U userrow:v:"$(BATE_CONFIG)":m \

185
src/adc.c
View file

@ -3,6 +3,7 @@
// //
#include "adc.h" #include "adc.h"
#include "bate.h"
#include <avr/interrupt.h> #include <avr/interrupt.h>
enum adc_conf_parameter { enum adc_conf_parameter {
@ -16,7 +17,6 @@ enum adc_conf_parameter {
V_BAT = ADC_MUXPOS_AIN7_gc, V_BAT = ADC_MUXPOS_AIN7_gc,
}; };
static const
struct adc_conf adc_conf[N_ADC] = { struct adc_conf adc_conf[N_ADC] = {
{ // Internal Temperature { // Internal Temperature
.mode = MODE, .mode = MODE,
@ -52,39 +52,49 @@ struct adc_conf adc_conf[N_ADC] = {
}; };
uint16_t adc_readings[N_ADC]; uint16_t adc_readings[N_ADC];
uint8_t adc_current; uint8_t adc_current = 0xff;
static inline static inline
void start_conversion(const struct adc_conf *c) void start_conversion(const struct adc_conf *c)
{ {
ADC.CTRLA = ADC_ENABLE_bm | ADC_RUNSTDBY_bm;
ADC.CTRLC = c->ref; ADC.CTRLC = c->ref;
ADC.MUXNEG = c->inn; ADC.MUXNEG = c->inn;
ADC.MUXPOS = c->inp; ADC.MUXPOS = c->inp;
ADC.COMMAND = c->mode; 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() 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.CTRLB = ADC_PRESC_DIV10_gc;
ADC.INTCTRL = ADC_RESRDY_bm;
ADC.CTRLE = 32 << ADC_SAMPDUR_gp; 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_current = 0;
ADC.INTFLAGS = 0xff;
ADC.INTCTRL = ADC_RESRDY_bm; // this seems to be ineffective, for some reason.
start_conversion(adc_conf); start_conversion(adc_conf);
} }
#if 0 static inline
ISR(ADC0_RESRDY_vect) void adc_next()
{ {
uint8_t i = adc_current; uint8_t i = adc_current;
if (!(ADC.INTFLAGS & ADC_RESRDY_bm))
return;
if (i >= N_ADC) if (i >= N_ADC)
goto stop; goto stop;
adc_readings[i] = ADC.RESULT; adc_readings[i] = ADC.RESULT;
// ADC.RESULT is a DWORD, 32-bit. ADC.INTFLAGS = ADC_RESRDY_bm;
// gcc load all four bytes, then stores two
// and thus requires four extra regs
// to be pushed on the stack
while (++i < N_ADC) { while (++i < N_ADC) {
const struct adc_conf *c = adc_conf + i; const struct adc_conf *c = adc_conf + i;
if (c->mode && c->mode != 0xff) { if (c->mode && c->mode != 0xff) {
@ -97,12 +107,30 @@ stop:
ADC.CTRLA = 0; ADC.CTRLA = 0;
adc_current = N_ADC; 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 #else
// This saves // This saved (at some earlier point of debugging)
// - 29 of 86 instructions, // - 29 of 86 instructions,
// - 24 of 110 clk cycles in the common path // - 24 of 110 clk cycles in the common path
// - 9 of 14 bytes of stack space, // - 9 of 14 bytes of stack space,
// - and avoids unlikely branches. // - and avoids unlikely branches.
ISR(ADC0_RESRDY_vect, ISR_NAKED) ISR(ADC0_RESRDY_vect, ISR_NAKED)
{ {
__asm__( __asm__(
@ -128,7 +156,7 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
"brsh 4f" "\n\t" "brsh 4f" "\n\t"
"subi r24, 0xff" "\n\t" "subi r24, 0xff" "\n\t"
"mov r30, r24" "\n\t" "mov r30, r24" "\n\t"
"ldi r31, 0" "\n\t" "clr r31" "\n\t"
"lsl r30" "\n\t" "lsl r30" "\n\t"
"lsl r30" "\n\t" "lsl r30" "\n\t"
"subi r30, lo8(-(adc_conf))" "\n\t" "subi r30, lo8(-(adc_conf))" "\n\t"
@ -138,8 +166,6 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
"subi r25, 1" "\n\t" "subi r25, 1" "\n\t"
"cpi r25, 0xfe" "\n\t" "cpi r25, 0xfe" "\n\t"
"brsh 3f" "\n\t" "brsh 3f" "\n\t"
"ldi r25, %[MODE]" "\n\t"
"sts %[CTRLA], r25" "\n\t"
"ldd r25, Z+1" "\n\t" "ldd r25, Z+1" "\n\t"
"sts %[CTRLC], r25" "\n\t" "sts %[CTRLC], r25" "\n\t"
"ldd r25, Z+3" "\n\t" "ldd r25, Z+3" "\n\t"
@ -170,7 +196,6 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
: : : :
[NADC] "n" (N_ADC), [NADC] "n" (N_ADC),
[RESULT] "n" (&ADC.RESULT), [RESULT] "n" (&ADC.RESULT),
[MODE] "n" (ADC_ENABLE_bm | ADC_RUNSTDBY_bm),
[CTRLA] "n" (&ADC.CTRLA), [CTRLA] "n" (&ADC.CTRLA),
[CTRLC] "n" (&ADC.CTRLA), [CTRLC] "n" (&ADC.CTRLA),
[MUXPOS] "n" (&ADC.MUXPOS), [MUXPOS] "n" (&ADC.MUXPOS),
@ -179,131 +204,3 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
); );
} }
#endif #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

View file

@ -14,8 +14,11 @@ struct adc_conf {
uint8_t inn; uint8_t inn;
}; };
uint16_t adc_readings[N_ADC]; extern uint16_t adc_readings[N_ADC];
uint8_t adc_current; extern uint8_t adc_current;
uint8_t adc_finished();
void start_adc(); void start_adc();
void init_adc();
static inline uint8_t adc_busy() { return ADC.STATUS & 1; } static inline uint8_t adc_busy() { return ADC.STATUS & 1; }
extern struct adc_conf adc_conf[N_ADC];

View file

@ -12,10 +12,11 @@
#include <avr/sleep.h> #include <avr/sleep.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include "uart.h" #include "bate.h"
#include "rtc.h" #include "rtc.h"
#include "calib.h" #include "calib.h"
#include "mul.h" #include "mul.h"
#include "adc.h"
#define Bit(x) (1<<(x)) #define Bit(x) (1<<(x))
@ -67,7 +68,7 @@ void rfen(uint8_t on)
// //
// BATE, read data from an MS5534C pressure sensor // BATE, read data from an MS5534C pressure sensor
#define BATE_PORT PORTA #define BATE_PORT VPORTA
#define SCK_PORT 3 #define SCK_PORT 3
#define DOUT_PORT 2 #define DOUT_PORT 2
#define DIN_PORT 1 #define DIN_PORT 1
@ -97,6 +98,8 @@ void init_mclk(uint8_t p)
MCLK.CMP0 = p; MCLK.CMP0 = p;
MCLK.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc | TCA_SINGLE_ENABLE_bm; MCLK.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc | TCA_SINGLE_ENABLE_bm;
MCLK.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_FRQ_gc; 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 static inline
@ -130,84 +133,97 @@ ISR(TCA0_CMP0_vect, ISR_NAKED)
union bate bate; union bate bate;
struct pressure pressure; struct pressure pressure;
// Spec:
// _____ _____ _____
// SCK ____/ \_____/ \_____/ \_____
// _____ _____ _____ __
// DIN -<_____>-----<_____>-----<_____>-----<__
// _____ ___________ ___________ __________
// DOUT _____X___________X___________X__________
//
// Impl:
// _______
// SCK _______/ \_
// _ _______________
// DIN _X_______________
//
// DOUT xxxxxSxxxxxxxxxxx
//
__attribute__ ((noinline, noclone)) __attribute__ ((noinline, noclone))
static static
uint8_t bate_bit(uint8_t r, uint8_t c, uint8_t ii) 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__( __asm__(
"ldi r25, %[DI]" "\n\t" "and %[c], %[ii]" "\n\t"
"and %[c], %[ii]" "\n\t" "brne 1f" "\n\t"
"brne .+6" "\n\t" "cbi %[PORT], %[DIN]" "\n\t"
"sts %[PC], r25" "\n\t" "1:" "\n\t"
"breq .+6" "\n\t" "breq 2f" "\n\t"
"sts %[PS], r25" "\n\t" "sbi %[PORT], %[DIN]" "\n\t"
"nop" "\n\t" "2:" "\n\t"
"lds r25, %[PI]" "\n\t" "sbic %[PIN], %[DOUT]" "\n\t"
"sbrc r25, %[DO]" "\n\t" "or %[r], %[ii]" "\n\t"
"or %[r], %[ii]" "\n\t" "com %[ii]" "\n\t"
"com %[ii]" "\n\t" "sbis %[PIN], %[DOUT]" "\n\t"
"sbrs r25, %[DO]" "\n\t" "and %[r], %[ii]" "\n\t"
"and %[r], %[ii]" "\n\t"
"ldi r25, %[SK]" "\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" "sbi %[PORT], %[SCK]" "\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"
"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), :[r] "+r" (r),
[c] "+r" (c) [c] "+r" (c)
:[ii] "r" (ii), :[ii] "r" (ii),
[PS] "n" (&BATE_PORT.OUTSET), [PORT] "n" (_SFR_IO_ADDR(BATE_PORT.OUT)),
[PC] "n" (&BATE_PORT.OUTCLR), [PIN] "n" (_SFR_IO_ADDR(BATE_PORT.IN)),
[PI] "n" (&BATE_PORT.IN), [DIN] "n" (DIN_PORT),
[DI] "n" (Bit(DIN_PORT)), [DOUT] "n" (DOUT_PORT),
[DO] "n" (DOUT_PORT), [SCK] "n" (SCK_PORT)
[SK] "n" (Bit(SCK_PORT)) : "memory"
: "r25", "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 #endif
return r; return r;
} }
__attribute__ ((noinline, noclone)) __attribute__ ((noinline, noclone))
static static
uint16_t bate_frame(uint16_t d, uint8_t n) uint16_t bate_frame(uint16_t d, uint8_t n)
@ -288,9 +304,8 @@ void read_bate()
bate_frame(0,1); bate_frame(0,1);
bate.D2 = bate_frame(0, 16); bate.D2 = bate_frame(0, 16);
bate.H1 = 0xba7e; bate.H1 = 0xba7e;
# ifndef WDT_TRIGGERED
bate.H2 += 1; bate.H2 += 1;
# endif sei();
} }
@ -301,6 +316,7 @@ void read_bate()
struct config { struct config {
uint8_t magic; uint8_t magic;
uint8_t version; uint8_t version;
uint8_t cpu_clk;
uint8_t power; uint8_t power;
uint8_t send; uint8_t send;
uint8_t triggers; uint8_t triggers;
@ -313,7 +329,7 @@ struct config {
enum magic_flags { enum magic_flags {
USE_USERROW = 0xBA, USE_USERROW = 0xBA,
USE_VERSION = 0x01, USE_VERSION = 0x02,
}; };
@ -327,6 +343,7 @@ enum send_flags {
SEND_CLOCK = 0x02, SEND_CLOCK = 0x02,
SEND_HEX = 0x04, SEND_HEX = 0x04,
SEND_CALIB = 0x08, SEND_CALIB = 0x08,
SEND_ADC = 0x10,
SEND_DEBUG = 0x80, SEND_DEBUG = 0x80,
}; };
enum trigger_flags { enum trigger_flags {
@ -337,36 +354,40 @@ enum trigger_flags {
TRIGGER_BREAK = 0x10, TRIGGER_BREAK = 0x10,
}; };
static struct config config_ram = { static struct config config = {
.send = SEND_BOOT_MESSAGE | SEND_CLOCK | SEND_HEX, .send = SEND_BOOT_MESSAGE | SEND_CLOCK | SEND_HEX,
.triggers = TRIGGER_CONT, .cpu_clk = CLKCTRL_PDIV_2X_gc | 1,
.triggers = TRIGGER_CLOCK,
.mclk_delay = 0xff, .mclk_delay = 0xff,
.pit_period = RTC_CLKSEL_INT1K_gc, .pit_period = RTC_CLKSEL_INT1K_gc,
}; };
static struct config *config = & config_ram;
static const struct config *userrow = (struct config *) & USERROW; static const struct config *userrow = (struct config *) & USERROW;
#ifdef DEBUG
struct debug debug_data;
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
// main() // main()
int 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 if (userrow->magic == USE_USERROW
&& userrow->version == USE_VERSION) && 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_led();
init_rfen(); init_rfen();
init_uart(config->baud_div); init_uart(config.baud_div);
init_rtc(config->pit_period); init_rtc(config.pit_period);
rfen(1);
set_sleep_mode(SLEEP_MODE_IDLE); set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable(); sleep_enable();
@ -374,18 +395,18 @@ int main()
send_str("Hallo\n"); 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_str("V Turbo Weather V0.01\n");
send_hex('S', (uint8_t *)&SIGROW, sizeof(SIGROW_t)); send_hex('S', (uint8_t *)&SIGROW, sizeof(SIGROW_t));
send_hex('F', (uint8_t *)&FUSE, sizeof(FUSE_t)); send_hex('F', (uint8_t *)&FUSE, sizeof(FUSE_t));
send_hex('U', (uint8_t *)&USERROW, sizeof(USERROW_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 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] = { 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 = { 0x470c, 0x773f }, }, // 21.2 °C, 1021.7 mbar
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x1a51, 0x6fed }, }, // 7.5 °C, 5.4 mbar { .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x1a51, 0x6fed }, }, // 7.5 °C, 5.4 mbar
@ -397,13 +418,30 @@ int main()
sleep_cpu(); 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()) { if (uart_busy()) {
uart_tick(); uart_tick();
continue; continue;
} }
wdt_reset(); wdt_reset();
rfen(0); rfen(0);
led(0);
if (uart_tick()) if (uart_tick())
trigger |= TRIGGER_UART; trigger |= TRIGGER_UART;
@ -412,10 +450,10 @@ int main()
if (clock_tick) if (clock_tick)
trigger |= TRIGGER_CLOCK; trigger |= TRIGGER_CLOCK;
if (!(trigger & config->triggers)) { if (!(trigger & config.triggers)) {
if (config->power & POWER_DOWN) { if (config.power & POWER_DOWN) {
mclk(0); mclk(0);
if (config->power & POWER_DOWN_CLI) if (config.power & POWER_DOWN_CLI)
cli(); cli();
set_sleep_mode(SLEEP_MODE_PWR_DOWN); set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable(); sleep_enable();
@ -429,37 +467,42 @@ int main()
continue; continue;
tick = 0; tick = 0;
rfen(1);
led(1);
if (!mclk_status()) { if (!mclk_status()) {
mclk(1); mclk(1);
mclk_delay = config->mclk_delay; mclk_delay = config.mclk_delay;
} }
if (mclk_delay) { if (mclk_delay) {
mclk_delay--; mclk_delay--;
continue; continue;
} }
rfen(1); read_bate();
if (config.power & STOP_MCLK)
mclk(0);
if (config.send & SEND_ADC)
start_adc();
cli(); cli();
uint32_t time = clock; uint32_t time = clock;
read_bate();
if (config->power & STOP_MCLK)
mclk(0);
sei(); sei();
set_sleep_mode(SLEEP_MODE_IDLE); if (config.send & SEND_CLOCK) {
sleep_enable();
if (config->send & SEND_CLOCK) {
send_str("T 0x"); send_str("T 0x");
send_hex_long(time); send_hex_long(time);
send_str(" 0x"); send_str(" 0x");
send_hex_byte(trigger); send_hex_byte(trigger);
send_char_sleep('\n'); send_char_sleep('\n');
} }
const union bate *b = &bate; const union bate *b = &bate;
if (test_calib) if (test_calib)
b = testdata + (--test_calib & 3); b = testdata + (--test_calib & 3);
if (config->send & SEND_HEX) if (config.send & SEND_HEX)
send_hex('B', b->b, sizeof(union bate)); send_hex('B', b->b, sizeof(union bate));
if (config->send & SEND_CALIB) { if (config.send & SEND_CALIB) {
bate_calib(b, &pressure); bate_calib(b, &pressure);
send_str("P "); send_str("P ");
send_str(decimal_str(pressure.p, 1)); send_str(decimal_str(pressure.p, 1));

37
src/bate.h Normal file
View 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

View file

@ -25,7 +25,7 @@ void bate_calib(const union bate *bate, struct pressure *pt)
uint16_t D2 = bate->D2; uint16_t D2 = bate->D2;
uint16_t UT1 = C5 + 20224; uint16_t UT1 = C5 + 20224;
int32_t dT = D2 - UT1; uint16_t dT = D2 - UT1;
uint16_t TEMPSENS = C6 + 50; uint16_t TEMPSENS = C6 + 50;
int16_t TEMP = mul16sun(dT, TEMPSENS, 6) + 200; 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[] = { 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 = { 0x470c, 0x773f }, }, // 21.2 °C, 1021.7 mbar
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x1a51, 0x6fed }, }, // 7.5 °C, 5.4 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 { .W = { 0xaa3d, 0x35d9, 0xcbe5, 0xb736}, .D = { 0x4bb7, 0x7487 }, }, // 17.7 °C, 1023.0 mbar

View file

@ -97,18 +97,21 @@ int16_t mul16sun(int16_t s, uint16_t u, uint8_t n)
"add r21, r0" "\n\t" "add r21, r0" "\n\t"
"adc %A[s], r1" "\n\t" "adc %A[s], r1" "\n\t"
"adc %B[s], r18" "\n\t" "adc %B[s], r18" "\n\t"
"cpi %[n], 0" "\n\t"
"breq 3f" "\n\t"
"sbrs %[n], 3" "\n\t" "sbrs %[n], 3" "\n\t"
"rjmp .+14" "\n\t" "rjmp 2f" "\n\t"
"mov %B[s], %A[s]" "\n\t" "mov %B[s], %A[s]" "\n\t"
"mov %A[s], r21" "\n\t" "mov %A[s], r21" "\n\t"
"rjmp 2f" "\n" "rjmp 3f" "\n"
"1:" "\t" "1:" "\t"
"lsl r21" "\n\t" "lsl r21" "\n\t"
"rol %A[s]" "\n\t" "rol %A[s]" "\n\t"
"rol %B[s]" "\n\t" "rol %B[s]" "\n\t"
"2:" "\t"
"dec %[n]" "\n\t" "dec %[n]" "\n\t"
"brpl 1b" "\n" "brpl 1b" "\n"
"2:" "\t" "3:" "\t"
"clr r1" "\n\t" "clr r1" "\n\t"
: [s] "+r" (s) : [s] "+r" (s)
: [u] "a" (u), : [u] "a" (u),

View file

@ -27,7 +27,7 @@ void init_uart(uint16_t div)
USART0.CTRLA = USART_RXCIE_bm; USART0.CTRLA = USART_RXCIE_bm;
} }
static uint8_t rx_tick; uint8_t rx_tick;
ISR(PORTB_PORT_vect, ISR_NAKED) ISR(PORTB_PORT_vect, ISR_NAKED)
{ {
@ -52,9 +52,9 @@ uint8_t uart_tick()
return r; return r;
} }
static uint8_t uart_tx[64]; uint8_t uart_tx[64];
static uint8_t uart_tx_w; uint8_t uart_tx_w;
static uint8_t uart_tx_r; uint8_t uart_tx_r;
static const uint8_t uart_tx_m = sizeof(uart_tx) - 1; static const uint8_t uart_tx_m = sizeof(uart_tx) - 1;
static inline void tx() static inline void tx()
@ -180,10 +180,16 @@ void send_hex_long(uint32_t b)
__attribute__ ((noinline, noclone)) __attribute__ ((noinline, noclone))
void send_hex(uint8_t header, const uint8_t *s, uint8_t n) void send_hex(uint8_t header, const uint8_t *s, uint8_t n)
{ {
// dump little endian words.
send_char_sleep(header); send_char_sleep(header);
send_char_sleep(' '); while (n--) {
while (n--) send_char_sleep(' ');
send_hex_byte(*(s++)); uint8_t l = *(s++);
if (n&1) {
send_hex_byte(*(s++));
n--;
}
send_hex_byte(l);
}
send_char_sleep('\n'); send_char_sleep('\n');
} }

View file

@ -10,6 +10,10 @@ void init_uart(uint16_t div);
uint8_t uart_tick(); uint8_t uart_tick();
uint8_t uart_busy(); uint8_t uart_busy();
uint8_t send_char(uint8_t c); 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[16];
extern uint8_t uart_rx_n; extern uint8_t uart_rx_n;
extern uint8_t uart_rx_mes; extern uint8_t uart_rx_mes;
@ -42,3 +46,11 @@ void send_str(const char *s)
send_char_sleep(*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++);
}