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
|
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
185
src/adc.c
|
|
@ -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
|
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
|
||||||
235
src/bate.c
235
src/bate.c
|
|
@ -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
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 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
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
22
src/uart.c
22
src/uart.c
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
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_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++);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue