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
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
View file

@ -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

View file

@ -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];

View file

@ -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
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 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

View file

@ -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),

View file

@ -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');
}

View file

@ -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++);
}