Compare commits

...

4 commits

Author SHA1 Message Date
Stephan I. Böttcher
873a2ba93a uart, adc, pwm debugged
hallo.c is a temporary slim version of dose.c.
With python support code.
The First nFET characteristic is recorded.
2026-02-04 21:19:21 +01:00
Stephan I. Böttcher
6fcdb271d3 update assy drawing 2026-02-04 21:09:07 +01:00
Stephan I. Böttcher
302b6bb8d7 hallo: early debaug code, about to be removed 2026-02-03 16:00:14 +01:00
Stephan I. Böttcher
d1e6a031ab divmod85 implementation fixed and tested 2026-01-29 11:26:33 +01:00
21 changed files with 1190 additions and 125 deletions

2
.gitignore vendored
View file

@ -25,3 +25,5 @@ src/data
BCH-Codes/ BCH-Codes/
*.odt *.odt
*.userrow *.userrow
*.m
src/data

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before After
Before After

View file

@ -6,8 +6,15 @@ PATH:=/usr/local/bin:$(PATH)
default: all default: all
all: $(PROJ).hex $(PROJ)_all all: $(PROJ).hex $(PROJ)_all
dose_all: dose.eeprom dose.userrow
hallo_all: hallo.eeprom
CFLAGS_hallo = -DHAVE_nFETs -DSEND_HEX -DHALLO
MCU_hallo = attiny424
SN_hallo = 1
C_FILES_hallo = config.c uart.c cmd.c base85.c rtc.c adc.c pwm.c
S_FILES_hallo = uart_tx.S base85a.S
dose_all: dose.eeprom dose.userrow
SN_dose = 1 SN_dose = 1
MCU_dose = $(MCU_$(VAR)) MCU_dose = $(MCU_$(VAR))
MCU_nFETs = attiny424 MCU_nFETs = attiny424
@ -48,6 +55,9 @@ OBJS = $(patsubst %.c, %.o, $(C_FILES)) $(patsubst %.S, %.o, $(S_FILES))
%.o: %.S %.o: %.S
$(CC) $(CFLAGS) -c $< $(CC) $(CFLAGS) -c $<
%.m: %.S
$(CC) $(CFLAGS) -E -dM $< > $@
-include *.d -include *.d
LDFLAGS = -Teeprom.ld LDFLAGS = -Teeprom.ld
@ -97,6 +107,7 @@ AVRDUDE_PORT = /dev/ttyUSB1
AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
sig_dose = 0x1e 0x92 0x2c sig_dose = 0x1e 0x92 0x2c
sig_hallo = 0x1e 0x92 0x2c
id: $(PROJ).id id: $(PROJ).id
%.id: %.id:
@ -132,3 +143,5 @@ eeprom.eeprom:
%.eeprom.burn: %.eeprom %.eeprom.burn: %.eeprom
$(AD) -U eeprom:v:$< || $(AD) -U eeprom:w:$< $(AD) -U eeprom:v:$< || $(AD) -U eeprom:w:$<
%.userrow.burn: %.userrow
$(AD) -U userrow:v:$< || $(AD) -U userrow:w:$<

View file

@ -8,12 +8,18 @@
#include "pwm.h" #include "pwm.h"
#include "rtc.h" #include "rtc.h"
#ifdef ADC_IMMEDIATE
# define ADC_TRIGGER ADC_MODE_BURST_SCALING_gc | ADC_START_IMMEDIATE_gc
#else
# define ADC_TRIGGER ADC_MODE_SERIES_SCALING_gc | ADC_START_EVENT_TRIGGER_gc
#endif
enum adc_conf_parameter { enum adc_conf_parameter {
INP = ADC_VIA_ADC_gc, INP = ADC_VIA_ADC_gc,
INN = ADC_VIA_ADC_gc, INN = ADC_VIA_ADC_gc,
REF = 10 << ADC_TIMEBASE_gp, REF = 10 << ADC_TIMEBASE_gp,
MODE = ADC_MODE_SERIES_SCALING_gc | ADC_START_EVENT_TRIGGER_gc, MODE = ADC_TRIGGER,
MODE_DIFF = ADC_MODE_BURST_SCALING_gc | ADC_START_IMMEDIATE_gc | ADC_DIFF_bm, MODE_DIFF = ADC_TRIGGER | ADC_DIFF_bm,
}; };
__attribute__((section(".eeprom1"))) __attribute__((section(".eeprom1")))
@ -81,7 +87,7 @@ struct_ioconf(adc_config) = {
conf_prefix(ADC), conf_prefix(ADC),
conf_io(ADC.CTRLA, ADC_ENABLE_bm), conf_io(ADC.CTRLA, ADC_ENABLE_bm),
conf_io(ADC.CTRLB, ADC_PRESC_DIV10_gc), conf_io(ADC.CTRLB, ADC_PRESC_DIV10_gc),
conf_io(ADC.CTRLE, 250 << ADC_SAMPDUR_gp), conf_io(ADC.CTRLE, 250),
conf_io(ADC.CTRLF, ADC_SAMPNUM_ACC256_gc | ADC_LEFTADJ_bm), conf_io(ADC.CTRLF, ADC_SAMPNUM_ACC256_gc | ADC_LEFTADJ_bm),
conf_io(ADC.INTCTRL, ADC_RESRDY_bm), conf_io(ADC.INTCTRL, ADC_RESRDY_bm),
conf_prefix(EVSYS), conf_prefix(EVSYS),
@ -91,8 +97,6 @@ struct_ioconf(adc_config) = {
void start_adc() void start_adc()
{ {
if (!adc_conf->mode)
return;
ADC.COMMAND = 0; ADC.COMMAND = 0;
adc_current = 0; adc_current = 0;
start_conversion(adc_conf); start_conversion(adc_conf);
@ -114,7 +118,7 @@ ISR(ADC0_RESRDY_vect)
} }
} }
stop: stop:
ADC.CTRLA = 0; ADC.COMMAND = 0;
adc_current = N_ADC; adc_current = N_ADC;
} }
@ -136,7 +140,7 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
"push r31" "\n\t" "push r31" "\n\t"
"lds r24, adc_current" "\n\t" "lds r24, adc_current" "\n\t"
"cpi r24, %[NADC]" "\n\t" "cpi r24, %[NADC]" "\n\t"
"brcc 3f" "\n\t" "brcc 2f" "\n\t"
"mov r30, r24" "\n\t" "mov r30, r24" "\n\t"
"ldi r31, 0" "\n\t" "ldi r31, 0" "\n\t"
"lsl r30" "\n\t" "lsl r30" "\n\t"
@ -148,7 +152,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
"std Z+1, r25" "\n" "std Z+1, r25" "\n"
"1:" "\n\t" "1:" "\n\t"
"subi r24, -1" "\n\t" "subi r24, -1" "\n\t"
"cpi r24, %[NADC]" "\n\t" "cpi r24, %[NADC]" "\n"
"2:" "\n\t"
"clr r25" "\n\t"
"brcc 3f" "\n\t" "brcc 3f" "\n\t"
"mov r30, r24" "\n\t" "mov r30, r24" "\n\t"
"ldi r31, 0" "\n\t" "ldi r31, 0" "\n\t"
@ -164,9 +170,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
"sts %[MUXPOS], r25" "\n\t" "sts %[MUXPOS], r25" "\n\t"
"ld r25, Z" "\n\t" "ld r25, Z" "\n\t"
"tst r25" "\n\t" "tst r25" "\n\t"
"breq 1b" "\n\t" "breq 1b" "\n"
"sts %[COMMAND], r25" "\n" "3:" "\n\t"
"2:" "\n\t" "sts %[COMMAND], r25" "\n\t"
"sts adc_current, r24" "\n\t" "sts adc_current, r24" "\n\t"
"pop r31" "\n\t" "pop r31" "\n\t"
"pop r30" "\n\t" "pop r30" "\n\t"
@ -175,16 +181,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
"out __SREG__, r24" "\n\t" "out __SREG__, r24" "\n\t"
"pop r24" "\n\t" "pop r24" "\n\t"
"reti" "\n" "reti" "\n"
"3:" "\n\t"
"clr r24" "\n\t"
"sts %[COMMAND], r24" "\n\t"
"sts %[CTRLA], r24" "\n\t"
"ldi r24, %[NADC]" "\n\t"
"rjmp 2b" "\n"
: : : :
[NADC] "n" (N_ADC), [NADC] "n" (N_ADC),
[RESULT] "n" (&ADC.RESULT), [RESULT] "n" (&ADC.RESULT),
[CTRLA] "n" (&ADC.CTRLA),
[CTRLC] "n" (&ADC.CTRLC), [CTRLC] "n" (&ADC.CTRLC),
[MUXPOS] "n" (&ADC.MUXPOS), [MUXPOS] "n" (&ADC.MUXPOS),
[MUXNEG] "n" (&ADC.MUXNEG), [MUXNEG] "n" (&ADC.MUXNEG),

View file

@ -12,10 +12,10 @@ int base85_encode(uint32_t u, uint8_t *s)
{ {
s += 5; s += 5;
*s = 0; *s = 0;
u = divmod85(u, s); u = divmod85(u, --s);
u = divmod85(u, s); u = divmod85(u, --s);
u = divmod85(u, s); u = divmod85(u, --s);
u = divmod85(u, s); u = divmod85(u, --s);
*--s = (u>>24) + 33; *--s = (u>>24) + 33;
return 5; return 5;
} }

25
src/base85.py Normal file
View file

@ -0,0 +1,25 @@
import struct
def base85_encode(b):
uu = list(struct.unpack(f">{len(b)//4}I", b))
uu.reverse()
r = []
for u in uu:
for i in range(5):
r[0:0] = [u % 85 + 33]
u //= 85
return bytes(r)
def base85_decode(s):
uu = [];
for j in range(0,len(s),5):
u = 0
for i in range(5):
m = ord(s[j+i:j+i+1]) - 33;
if m < 0 or m >= 85:
raise ValueError(f"invalid base85 char {s}[{i}]")
u *= 85
u += m
uu.append(u)
return struct.pack(f">{len(uu)}I", *uu)

132
src/base85_test.c Normal file
View file

@ -0,0 +1,132 @@
#include <stdio.h>
#include <stdint.h>
uint8_t m;
uint64_t f;
static inline
uint32_t divmod85(uint32_t u)
{
uint64_t uu = u;
uu += uu << 1;
uu += 1;
// f = (uu << 16) + (uu << 8) + uu + (uu >> 8) + (uu >> 16) + (uu >> 24);
f = (uu << 16) + (uu << 8) + uu + (uu >> 8) + (uu >> 16) + (uu >> 24) + (uu>>32);
f >>= 16;
m = ((f & 0xff) * 85 + 0x80) >> 8;
return f >> 8;
}
int d = 0;
typedef uint8_t r;
uint32_t divmod85avr(uint32_t u)
{
#define D(_m) if(d) printf("%-8s c=%x r0=%02x r1=%02x r18=%02x r19=%02x r20=%02x r21=%02x " \
"r22=%02x r23=%02x r24=%02x r25=%02x r30=%02x r31=%02x\n", \
_m, c, r0, r1, r18, r19, r20, r21, r23, r23, r24, r25, r30, r31)
#define ADD(_x, _y) { _c = (_x + _y) >>8; _x += _y; c = _c & 1; D("ADD "#_x);}
#define ADC(_x, _y) { _c = (_x + _y + c) >>8; _x += _y + c; c = _c & 1; D("ADC "#_x);}
#define SUB(_x, _y) { _c = (_x - _y) >>8; _x -= _y; c = _c & 1; D("SUB "#_x);}
#define SBC(_x, _y) { _c = (_x - _y - c) >>8; _x -= _y + c; c = _c & 1; D("SBC "#_x);}
#define LSL(_x) { c = _x >> 7; _x <<= 1; D("LSL "#_x);}
#define ROL(_x) { _c = _x >> 7; _x <<= 1; _x |= c; c = _c; D("ROL "#_x);}
#define CLR(_x) { _x = 0; D("CLR "#_x);}
#define MOV(_x, _y) { _x = _y; D("MOV "#_x);}
#define MOVW(_x, _xh, _y, _yh) { _x = _y; _xh = _yh; D("MOVW "#_x);}
#define SEC {c=1; D("SEC");}
#define LDI(_x, _n) { _x = _n; D("LDI "#_x);}
#define MUL(_x, _y) { r0 = _x * _y; r1 = (_x * _y) >> 8; D("MUL "#_x);}
r c, _c, r0, r18, r19, r20, r21, r30, r31;
r r1 = 0;
r r22 = u>>24;
r r23 = u>>16;
r r24 = u>>8;
r r25 = u;
MOVW(r18,r19, r22,r23);
MOVW(r20,r21, r24,r25);
LSL(r21);
ROL(r20);
ROL(r19);
ROL(r18);
CLR(r0);
ROL(r0);
SEC;
ADC(r21, r25);
ADC(r20, r24);
ADC(r19, r23);
ADC(r18, r22);
ADC(r0, r1);
MOV(r30, r21);
ADD(r30, r20);
CLR(r31);
ROL(r31);
ADD(r30, r19);
ADC(r31, r1);
ADD(r30, r18);
ADC(r31, r1);
ADD(r30, r0);
ADC(r31, r1);
MOV(r22, r31);
ADD(r22, r30);
MOV(r18, r31);
ADC(r18, r30);
MOV(r25, r31);
ADC(r25, r1);
SUB(r30, r21);
SBC(r31, r1);
ADD(r25, r30);
MOV(r24, r31);
ADC(r24, r1);
SUB(r30, r20);
SBC(r31, r1);
ADD(r24, r30);
MOV(r23, r31);
ADC(r23, r1);
SUB(r30, r19);
SBC(r31, r1);
ADD(r23, r30);
MOV(r22, r31);
ADC(r22, r0);
LDI(r19, 85);
MUL(r18, r19);
LSL(r0);
LDI(r19, 0)
ADC(r1, r19);
m = r1;
CLR(r1);
return (r22<<24) | (r23<<16) | (r24<<8) | r25;
}
int main()
{
uint32_t u = 0;
int did_d = 0;
do {
if (!(u & 0xffff))
fprintf(stderr, "%08x\r", u);
uint32_t nn = u / 85;
uint8_t mm = u % 85;
uint32_t n = divmod85avr(u);
if (nn != n || mm != m) {
printf("%08x = %08x × 85 + %02x : %08x %02x : %014lx\n",
u, nn, mm, n, m, f);
if (!did_d) {
did_d = d = 1;
divmod85avr(u);
d = 0;
}
}
} while (++u);
}

View file

@ -1,72 +1,97 @@
; uint32_t divmod85(uint32_t u, uint8_t *m)
; r26/r27 = m
; r25 = A LSB, big endian
; r24 = B
; r23 = C
; r22 = D MSB
; r1 = undef
#ifdef BASE85C ;uint32_t divmod85(uint32_t u)
;{
; uint64_t uu = u;
; f = (uu << 16) + (uu << 8) + uu + (uu >> 8) + (uu >> 16) + (uu >> 24);
; f += 0x0100;
; f &= 0xffffffffffff00LL;
; f += f << 1;
; m = (((f >> 16) & 0xff) * 85 + 0x80) >> 8;
; return f >> 24;
;}
;
; E,A,B,C,D = 3 × (r25,r24,r23,r22 big endian)
; 3*(A+B+C+D+E) = r30, r31
;
; E D C B A
; E D C B A
; E D C B A
; E D C B
; E D C
; E D
; E
; =============
; u u u u r -
#ifdef BASE85C
.global divmod85 .global divmod85
divmod85: divmod85:
movw r26, r20 movw r26, r20
# endif #endif
;; ! C-ABI: m=X
;; ! C-ABI: gobbles r1, m=X
_divmod85: ; r25,r24,r23,r22 = A,B,C,D _divmod85: ; r25,r24,r23,r22 = A,B,C,D
mov r18, r25 movw r18, r22
add r18, r24 movw r20, r24
clr r21 lsl r21
rol r21 ; r18,r21 = A+B
add r23, r18
clr r31
adc r31, r21 ; r23,r31 = A+B+C
add r21, r23
clr r18
adc r18, r31 ; r21,r18 = A+B>>8 + A+B+C
add r23, r22
clr r20
adc r31, r20 ; r23,r31 = A+B+C+D
add r18, r23
adc r21, r31 ; r18,r21 = A+B>>16 + A+B+C>>8 + A+B+C+D
sub r23, r25
sbc r31, r20 ; r23,r31 = B+C+D
add r21, r23
adc r20, r31 ; r18,r21,r20 = … + B+C+D<<8
sub r23, r24
clr r30
sbc r31, r30 ; r23,r31 = C+D
add r20, r23
adc r31, r22
rol r30 ; r18,r21,r20,r31,r30 = … + C+D<<16 + D<<24
mov r19, r18
movw r22, r20
movw r24, r30
lsl r19
rol r21
rol r20 rol r20
rol r19
rol r18
clr r0
rol r0
sec
adc r21, r25
adc r20, r24
adc r19, r23
adc r18, r22
adc r0, r1 ; r21,r20,r19,r18,r0 = 3u + 1
mov r30, r21
add r30, r20
clr r31
rol r31 rol r31
rol r30 add r30, r19
add r18, r19 adc r31, r1
adc r25, r21 add r30, r18
adc r24, r20 adc r31, r1
adc r23, r31 add r30, r0
adc r22, r30 adc r31, r1 ; r30,r31 = A+B+C+D+E
mov r22, r31 ;
add r22, r30 ; just for the carry bit
mov r18, r31
adc r18, r30 ; r18 = r
mov r25, r31
adc r25, r1
sub r30, r21
sbc r31, r1 ; r30,r31 = B+C+D+E
add r25, r30
mov r24, r31
adc r24, r1
sub r30, r20
sbc r31, r1 ; r30,r31 = C+D+E
add r24, r30
mov r23, r31
adc r23, r1
sub r30, r19
sbc r31, r1 ; r30,r31 = D+E
add r23, r30
mov r22, r31
adc r22, r0
ldi r19, 85 ldi r19, 85
mul r18, r19 mul r18, r19
lsl r0 lsl r0
ldi r18, 33 ldi r19, '!'
adc r1, r18 adc r1, r19
# ifdef BASE85C
st X, r1
clr r1
# else
st -X, r1 st -X, r1
# endif clr r1
ret ret
#ifndef BASE85C #ifndef BASE85C
.global base85_encode .global base85_encode
base85_encode: base85_encode:
movw r26, r20 movw r26, r20
@ -76,20 +101,20 @@ base85_encode:
rcall _divmod85 rcall _divmod85
rcall _divmod85 rcall _divmod85
rcall _divmod85 rcall _divmod85
subi r25, -33 subi r25, -'!'
st X, r25 st -X, r25
ldi r24, 5
clr r1
ret ret
# endif #endif
; uint32_t mul85(uint32_t u, uint8_t m); ; uint32_t mul85(uint32_t u, uint8_t m);
#ifdef BASE85C #ifdef BASE85C
.global mul85 .global mul85
mul85: mul85:
# endif #endif
;; TODO for SPACE: inline this ;; TODO for SPACE: inline this
;; big endian r22/r23/r24/r25 *= 85; … += r20
_mul85: _mul85:
ldi r21, 85 ldi r21, 85
mul r25, r21 mul r25, r21
@ -106,12 +131,12 @@ _mul85:
mov r25, r18 mov r25, r18
mov r23, r30 mov r23, r30
mov r22, r31 mov r22, r31
# ifdef BASE85C #ifdef BASE85C
clr r1 clr r1
# endif #endif
ret ret
#ifndef BASE85C #ifndef BASE85C
.global base85_decode .global base85_decode
base85_decode: base85_decode:
@ -125,7 +150,9 @@ base85_decode:
clr r22 clr r22
ldi r17, 5 ldi r17, 5
1: 1:
ld r20, Y+ ld r20, X+
subi r20, '!'
brcs 2f
cpi r20, 85 cpi r20, 85
brcc 2f brcc 2f
rcall _mul85 rcall _mul85
@ -145,4 +172,4 @@ base85_decode:
clr r1 clr r1
ret ret
# endif #endif

View file

@ -58,14 +58,13 @@ void base85_send_buffer(const uint8_t *buf)
"rjmp _send_str26" "\n" "rjmp _send_str26" "\n"
); );
} }
#endif #endif
static inline static inline
const uint8_t *base85_fill_buffer(const uint8_t *s) { const uint8_t *base85_fill_buffer(const uint8_t *s) {
base85_error = 0; base85_error = 0;
for (int i=0; !base85_error && i<FB_SIZE; i+=4) for (int i=0; !base85_error && i<16; i+=4)
s = base85_decode(s, (uint32_t *)(cmd_buffer + i)); s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
return s; return s;
} }
@ -133,13 +132,13 @@ uint8_t cmd_flag(uint8_t f)
"ld r22, Z+" "\n\t" "ld r22, Z+" "\n\t"
"cp r22, r24" "\n\t" "cp r22, r24" "\n\t"
"mov r24, r1" "\n\t" "mov r24, r1" "\n\t"
"brne 9f" "\n\t" "breq 1f" "\n\t"
"ret" "\n"
"1:" "\n\t"
"mov r24, r22" "\n\t" "mov r24, r22" "\n\t"
"sts cmd_flags, r30" "\n\t" "sts cmd_flags, r30" "\n\t"
"sts cmd_flags+1, r31" "\n\t" "sts cmd_flags+1, r31" "\n\t"
"rcall _send_char22" "\n" "rjmp _send_char22" "\n"
"9:" "\n\t"
"ret" "\n"
); );
} }
#endif #endif
@ -160,7 +159,9 @@ void parse_command(const uint8_t *s, uint8_t n)
uint8_t bflg = *s - '0'; uint8_t bflg = *s - '0';
uint8_t *bptr = cmd_buffer; uint8_t *bptr = cmd_buffer;
if (bflg <= 5) { if (bflg <= 5) {
#ifndef HALLO
bptr = flash_buffer + 16*bflg; bptr = flash_buffer + 16*bflg;
#endif
bflg = 1<<bflg; bflg = 1<<bflg;
s++; s++;
} }
@ -173,26 +174,27 @@ void parse_command(const uint8_t *s, uint8_t n)
if (*s==' ') { if (*s==' ') {
cmd_pending = 0; cmd_pending = 0;
s = base85_fill_buffer(s+1); s = base85_fill_buffer(s+1);
if (base85_error) {
r = base85_error; r = base85_error;
if (r)
goto error; goto error;
}
have_b = 1; have_b = 1;
cmd_pending = cmd; cmd_pending = cmd;
} else if (cmd_flag('~')) }
else if (cmd_flag('='))
have_b = cmd_pending == cmd; have_b = cmd_pending == cmd;
if (*s != '\n') if (*s != '\n')
goto error; goto error;
switch(cmd) { switch(cmd) {
case 'A': case 'A':
r = adc_current; r = adc_current;
if (r >= N_ADC) {
if (cmd_flag('<'))
base85_send_buffer((void*)adc_readings);
if (cmd_flag('!')) if (cmd_flag('!'))
start_adc(); start_adc();
if (cmd_flag('<')) {
bptr = (void*)adc_readings;
goto send_buffer;
} }
break; break;
#ifndef HALLO
case 'B': case 'B':
if (cmd_flag('@')) if (cmd_flag('@'))
pipe.valid = 0; pipe.valid = 0;
@ -246,11 +248,13 @@ void parse_command(const uint8_t *s, uint8_t n)
fpga_cmd((void*)cmd_buffer); fpga_cmd((void*)cmd_buffer);
goto send_buffer; goto send_buffer;
#endif #endif
#endif // HALLO
case 'M': case 'M':
if (!have_b) if (!have_b)
goto error; goto error;
r = poke((void*)cmd_buffer, cmd_flag('!')); r = poke((void*)cmd_buffer, cmd_flag('!'));
send_buffer: send_buffer:
send_char(' ');
base85_send_buffer(bptr); base85_send_buffer(bptr);
break; break;
default: default:

View file

@ -13,7 +13,6 @@ struct config {
uint8_t cron; uint8_t cron;
uint8_t flash_page_size; uint8_t flash_page_size;
uint16_t burn_page; uint16_t burn_page;
uint16_t erase_page;
uint16_t write_buffer; uint16_t write_buffer;
uint16_t read_array; uint16_t read_array;
uint16_t read_buffer[2]; uint16_t read_buffer[2];
@ -28,7 +27,7 @@ struct config {
enum magic_flags { enum magic_flags {
#ifdef HAVE_nFETs #ifdef HAVE_nFETs
MAGIC = 0xD0, MAGIC = 0xD0,
VERSION = 0x01, VERSION = 0x00,
#endif #endif
#ifdef HAVE_FPGA #ifdef HAVE_FPGA
MAGIC = 0xC5, MAGIC = 0xC5,
@ -131,9 +130,9 @@ void apply_config()
"ldi r30, lo8(ee9_start)" "\n\t" "ldi r30, lo8(ee9_start)" "\n\t"
"ldi r31, hi8(ee9_start)" "\n\t" "ldi r31, hi8(ee9_start)" "\n\t"
"ldi r24, lo8(ee9_size)" "\n\t" "ldi r24, lo8(ee9_size)" "\n\t"
"clr r26" "\n" "clr r25" "\n"
"1:" "\n\t" "1:" "\n\t"
"mov r27, r26" "\n\t" "mov r27, r25" "\n\t"
"subi r24, 2" "\n\t" "subi r24, 2" "\n\t"
"brcs 3f" "\n" "brcs 3f" "\n"
"2:" "\n\t" "2:" "\n\t"

208
src/dose.py Executable file
View file

@ -0,0 +1,208 @@
#! /usr/bin/ipython3 --profile=turbo_dose
import sys, time, getopt, fileinput, struct
import uart
from base85 import base85_encode, base85_decode
from map import memmap
from iotn424 import SFR
options, files = getopt.gnu_getopt(sys.argv[1:], "F:o:M:", ["debug", "tty=", "output=", "map="])
tty = "/dev/ttyUSB1"
baud = 115200
out = None
debug = None
map_fn = "hallo.map"
def Debug(e, *a):
if debug:
import traceback
sys.stdout.flush()
print("xdebug", a, repr(e), file=sys.stderr)
traceback.print_exception(e, limit=-2, file=sys.stderr)
for o,v in options:
if o == "--debug":
debug = True
if o in "-F --tty":
tty = v
v = v.split(",", 1)
if v[1:]:
tty = v[0]
baud = int(v[1])
do_clock = True
if o in "--output":
if out:
raise ValueError("cannot have multiple --outputs")
if v=="-":
out = sys.stdout
elif v=="--":
out = sys.stderr
else:
out = open(v, "a")
if o in "-M --map":
map_fn = v
if not out:
out = sys.stdout
if len(files)==1:
if "/dev/tty" in files[0]:
tty = files[0]
files = []
mmap = memmap(map_fn)
class dose_cmd(uart.uart):
def cmd(self, c, d=None, timeout=0.2):
if not isinstance(c, bytes):
c = c.encode()
if d:
c += b" " + base85_encode(d)
self.flush()
self.ucmd(c)
r = self.resp(timeout)
while r and (r[0] != b'#'[0] or r[1] != c[0]):
r = self.resp(timeout)
d = None
if not r:
return r, d
r = r.split()
e = int(r[-1], 16)
if len(r)==3:
d = base85_decode(r[1])
if self.verbose:
print(f"{r[0]}[{r[2]}] {"".join([f"{b:02x}" for b in d])}", file=sys.stderr)
self.last_cmd = c[0:1]
return r[0], e, d
def poke(self, a, d, s=None, ccp=0):
return self.peek(a, d, s, ccp)
def peek(self, a=None, d=None, s=None, ccp=0):
name = None
if a in SFR:
name = a
a, ss = SFR[a]
if s is None:
s = ss
if a in mmap:
a, ss = mmap[a]
if ss and s is None:
s = ss
if s is None and isinstance(d, int):
s = d
d = None
FF = {1: "B", 2: "H", 4:"I"}
if a is None:
cc, nn, dd = self.cmd(b"M=")
else:
if d is None:
c = b"M"
d = b''
if s is None:
s = 12
else:
c = b'M!'
if isinstance(d, int) and s in FF:
d = struct.pack(f"<{FF[s]}", d)
else:
d = bytes(d)
if s is None:
s = len(d)
d = struct.pack("<HBB", a,s,ccp) + d + b'\0\0\0\0\0\0\0\0\0\0\0\0'
cc, nn, dd = self.cmd(c, d[:16])
if dd and nn:
print(" ".join([f"{x:02x}" for x in dd[4:4+nn]]), file=sys.stderr)
if name is not None and nn in FF:
d = struct.unpack(f"<{FF[nn]}", dd[4:4+nn])
print(f"{name}: {d[0]:#x}", file=sys.stderr)
return name, d
return cc, nn, dd
o
def more(self, flags=b''):
return self.cmd(self.last_cmd + b'=' + flags)
def read_mem(self, a, s=None):
cc, nn, dd = self.peek(a=a, s=s)
r = dd[4:4+nn]
while dd[2]:
cc, nn, dd = self.more()
r += dd[4:4+nn]
return r
adc_conf = None
sigrow = None
ADC_MUX = {
0: "GND",
6: "Gate",
7: "Drain1",
10: "Drain2",
0x30: "GND",
0x31: ("Vdd", 10, 0, 0),
0x32: "T",
0x33: "DACREF",
}
ADC_REF = {
0: (3.3, "VDD"),
4: (1.024,),
5: (2.048,),
6: (2.5,),
7: (4.096,),
}
def adc(self, start=False, read_conf=False):
if not self.adc_conf or read_conf:
self.adc_conf = self.read_mem("adc_conf")
self.sigrow = self.read_mem(0x1100, 0x24)
g = self.sigrow[0x20]
o = self.sigrow[0x21]
if o & 0x80:
o -= 0x100
o <<= 6
g /= 1 << 14
self.ADC_MUX[0x32] = ("T°C", g, o, 273)
c = "A!<" if start else "A<"
cc, nn, dd = self.cmd(c)
dd = struct.unpack("<8H", dd)
r = []
for i in range(nn):
pos = self.adc_conf[4*i+2] & 0x3f
ref = self.adc_conf[4*i+1] & 0x07
if ref in self.ADC_REF:
ref = self.ADC_REF[ref]
else:
ref = (1,)
a = dd[i]
if pos != 0x32:
a *= ref[0]/0x10000
if pos in self.ADC_MUX:
pos = self.ADC_MUX[pos]
else:
pos = f"Ain{pos}"
if isinstance(pos, tuple):
a = (a - pos[2])*pos[1] - pos[3]
pos = pos[0]
r.append((a, pos, ref))
print(f"{i} {pos:6s} {a:.4f} {ref!r}", file=sys.stderr)
return r
def nfet_scan(self, t=1, dcs=(0x1000,)):
r = []
for dc in range(*dcs):
self.poke("TCA0_SINGLE_CMP0", dc)
time.sleep(t)
self.cmd("A!")
time.sleep(1)
r.append((dc, self.adc()))
return r
if tty:
tty = dose_cmd(tty, baud)
uart.set_prompt("TurboD")

47
src/hallo.c Normal file
View file

@ -0,0 +1,47 @@
//
// hallo.c
//
// int = int8_t
#include <stdint.h>
#include <string.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "config.h"
#include "uart.h"
#include "pwm.h"
////////////////////////////////////////////////////////////////////////////////
//
// main()
section_status(main) struct magic magic;
int main()
{
while (CLKCTRL.MCLKCTRLB != config.cpu_clk) {
CCP = CCP_IOREG_gc;
CLKCTRL.MCLKCTRLB = config.cpu_clk;
}
sleep_enable();
magic.magic = config.magic;
while (magic.magic != MAGIC || config.version != VERSION)
sleep_cpu();
apply_config();
magic.reset_source = RSTCTRL.RSTFR;
RSTCTRL.RSTFR = magic.reset_source;
send_str("\nV Turbo Hallo V0.0");
send_hex_byte_eol(magic.reset_source);
while (1) {
sei();
sleep_cpu();
command();
}
}

1
src/io.S Normal file
View file

@ -0,0 +1 @@
#include <avr/io.h>

443
src/iotn424.py Normal file
View file

@ -0,0 +1,443 @@
SFR = {
"USART0_TXDATAL": (0x0802, 1),
"PORTB_PIN0CTRL": (0x0430, 1),
"ADC0_WINHTH": (0x061F, 1),
"ADC0_WINHTL": (0x061E, 1),
"RTC_PITCTRLA": (0x0150, 1),
"USERROW_USERROW13": (0x130D, 1),
"USART0_RXDATAH": (0x0801, 1),
"USART0_RXDATAL": (0x0800, 1),
"USERROW_USERROW17": (0x1311, 1),
"TCA0_SPLIT_LCMP0": (0x0A28, 1),
"PORTB_DIRCLR": (0x0422, 1),
"TCA0_SINGLE_CMP1H": (0x0A2B, 1),
"USERROW_USERROW19": (0x1313, 1),
"PORTB_OUTSET": (0x0425, 1),
"USART0_BAUDH": (0x0809, 1),
"USART0_BAUDL": (0x0808, 1),
"TCA0_SPLIT_LCNT": (0x0A20, 1),
"TWI0_SCTRLB": (0x08AA, 1),
"PORTC_PORTCTRL": (0x044A, 1),
"PORTB_INTFLAGS": (0x0429, 1),
"CCL_LUT0CTRLA": (0x01C8, 1),
"CCL_LUT0CTRLB": (0x01C9, 1),
"CCL_LUT0CTRLC": (0x01CA, 1),
"TCA0_SPLIT_CTRLECLR": (0x0A04, 1),
"NVMCTRL_INTFLAGS": (0x1004, 1),
"CPUINT_CTRLA": (0x0110, 1),
"EVSYS_USERTCB1COUNT": (0x01B3, 1),
"VPORTA_OUT": (0x0001, 1),
"BOD_INTFLAGS": (0x008A, 1),
"ADC0_PGACTRL": (0x060B, 1),
"CLKCTRL_OSC20MCALIBA": (0x0071, 1),
"BOD_VLMCTRLA": (0x0088, 1),
"TCA0_SPLIT_LPER": (0x0A26, 1),
"USERROW_USERROW21": (0x1315, 1),
"USERROW_USERROW25": (0x1319, 1),
"PORTC_OUTSET": (0x0445, 1),
"USERROW_USERROW29": (0x131D, 1),
"EVSYS_USERTCB1CAPT": (0x01B2, 1),
"SLPCTRL_CTRLA": (0x0050, 1),
"ADC0_WINLTL": (0x061C, 1),
"TCA0_SPLIT_CTRLB": (0x0A01, 1),
"TCA0_SPLIT_CTRLD": (0x0A03, 1),
"TCA0_SINGLE_CMP0H": (0x0A29, 1),
"TCA0_SINGLE_CMP0L": (0x0A28, 1),
"PORTC_DIR": (0x0440, 1),
"TCA0_SINGLE_CMP1L": (0x0A2A, 1),
"ADC0_INTFLAGS": (0x0605, 1),
"USERROW_USERROW2": (0x1302, 1),
"USART1_DBGCTRL": (0x082B, 1),
"TWI0_MDATA": (0x08A8, 1),
"CCL_TRUTH0": (0x01CB, 1),
"PORTB_PIN3CTRL": (0x0433, 1),
"TCA0_SINGLE_CMP2H": (0x0A2D, 1),
"PORTA_PIN0CTRL": (0x0410, 1),
"TCA0_SINGLE_CMP2L": (0x0A2C, 1),
"CCL_LUT1CTRLA": (0x01CC, 1),
"CCL_LUT1CTRLC": (0x01CE, 1),
"SIGROW_SERNUM0": (0x1103, 1),
"SIGROW_SERNUM1": (0x1104, 1),
"SIGROW_SERNUM2": (0x1105, 1),
"SIGROW_SERNUM3": (0x1106, 1),
"SIGROW_SERNUM4": (0x1107, 1),
"SIGROW_SERNUM5": (0x1108, 1),
"SIGROW_SERNUM6": (0x1109, 1),
"SIGROW_SERNUM7": (0x110A, 1),
"SIGROW_SERNUM8": (0x110B, 1),
"SIGROW_SERNUM9": (0x110C, 1),
"TCA0_SINGLE_PERBUFH": (0x0A37, 1),
"TCA0_SINGLE_PERBUFL": (0x0A36, 1),
"USERROW_USERROW31": (0x131F, 1),
"TCB0_CTRLA": (0x0A80, 1),
"TCB0_CTRLB": (0x0A81, 1),
"CPUINT_LVL0PRI": (0x0112, 1),
"VPORTA_IN": (0x0002, 1),
"EVSYS_USERTCB0CAPT": (0x01B0, 1),
"PORTC_OUT": (0x0444, 1),
"RTC_PITINTCTRL": (0x0152, 1),
"PORTB_IN": (0x0428, 1),
"TCA0_SINGLE_CTRLB": (0x0A01, 1),
"ADC0_TEMP0": (0x0618, 1),
"PORTB_DIR": (0x0420, 1),
"ADC0_TEMP2": (0x061A, 1),
"GPIO0": (0x001C, 1),
"GPIO1": (0x001D, 1),
"GPIO3": (0x001F, 1),
"RTC_CNTH": (0x0149, 1),
"EVSYS_CHANNEL0": (0x0190, 1),
"EVSYS_CHANNEL1": (0x0191, 1),
"EVSYS_CHANNEL2": (0x0192, 1),
"EVSYS_CHANNEL3": (0x0193, 1),
"EVSYS_CHANNEL4": (0x0194, 1),
"EVSYS_CHANNEL5": (0x0195, 1),
"PORTC_DIRSET": (0x0441, 1),
"CCL_LUT3CTRLA": (0x01D4, 1),
"TWI0_SADDRMASK": (0x08AE, 1),
"TCA0_SINGLE_CTRLECLR": (0x0A04, 1),
"PORTA_DIRCLR": (0x0402, 1),
"PORTC_PIN2CTRL": (0x0452, 1),
"CCP": (0x0034, 1),
"CLKCTRL_OSC20MCALIBB": (0x0072, 1),
"USART0_CTRLA": (0x0805, 1),
"TWI0_SCTRLA": (0x08A9, 1),
"TCB1_CCMPL": (0x0A9C, 1),
"PORTC_IN": (0x0448, 1),
"SIGROW_DEVICEID2": (0x1102, 1),
"TCB1_INTCTRL": (0x0A95, 1),
"USART0_TXPLCTRL": (0x080D, 1),
"FUSE_WDTCFG": (0x1280, 1),
"CCL_LUT2CTRLB": (0x01D1, 1),
"CCL_LUT2CTRLC": (0x01D2, 1),
"PORTB_OUT": (0x0424, 1),
"PORTMUX_USARTROUTEA": (0x05E2, 1),
"CLKCTRL_OSC32KCTRLA": (0x0078, 1),
"TWI0_SDATA": (0x08AD, 1),
"PORTA_DIR": (0x0400, 1),
"PORTA_IN": (0x0408, 1),
"ADC0_DBGCTRL": (0x0607, 1),
"TCB1_CNTL": (0x0A9A, 1),
"PORTA_PIN1CTRL": (0x0411, 1),
"TCB0_TEMP": (0x0A89, 1),
"TCA0_SINGLE_CTRLA": (0x0A00, 1),
"TCA0_SINGLE_CTRLC": (0x0A02, 1),
"TCA0_SINGLE_CTRLD": (0x0A03, 1),
"ADC0_MUXPOS": (0x060C, 1),
"TCB1_INTFLAGS": (0x0A96, 1),
"EVSYS_USERADC0START": (0x01A8, 1),
"NVMCTRL_ADDRH": (0x1009, 1),
"NVMCTRL_ADDRL": (0x1008, 1),
"TWI0_DBGCTRL": (0x08A2, 1),
"RTC_PITDBGCTRL": (0x0155, 1),
"SIGROW_OSCCAL20M1": (0x111B, 1),
"VREF_CTRLA": (0x00A0, 1),
"TCA0_SPLIT_INTCTRL": (0x0A0A, 1),
"TCA0_SINGLE_CMP0BUFH": (0x0A39, 1),
"AC0_INTCTRL": (0x0686, 1),
"TCA0_SINGLE_CNTL": (0x0A20, 1),
"TCA0_SPLIT_HCMP0": (0x0A29, 1),
"TCA0_SPLIT_HCMP1": (0x0A2B, 1),
"TCA0_SPLIT_HCMP2": (0x0A2D, 1),
"TCA0_SINGLE_CMP2BUFH": (0x0A3D, 1),
"TCA0_SINGLE_CMP2BUFL": (0x0A3C, 1),
"USART1_TXPLCTRL": (0x082D, 1),
"PORTA_OUT": (0x0404, 1),
"CLKCTRL_MCLKSTATUS": (0x0063, 1),
"PORTC_PIN4CTRL": (0x0454, 1),
"PORTC_OUTCLR": (0x0446, 1),
"CCL_LUT3CTRLB": (0x01D5, 1),
"WDT_CTRLA": (0x0100, 1),
"SIGROW_DEVICEID0": (0x1100, 1),
"SIGROW_DEVICEID1": (0x1101, 1),
"TCB0_CNTL": (0x0A8A, 1),
"USERROW_USERROW1": (0x1301, 1),
"PORTMUX_CCLROUTEA": (0x05E1, 1),
"PORTC_PIN7CTRL": (0x0457, 1),
"ADC0_CTRLB": (0x0601, 1),
"ADC0_CTRLC": (0x0602, 1),
"ADC0_CTRLD": (0x0603, 1),
"ADC0_CTRLE": (0x0608, 1),
"ADC0_CTRLF": (0x0609, 1),
"RTC_INTCTRL": (0x0142, 1),
"RTC_PERL": (0x014A, 1),
"GPIO2": (0x001E, 1),
"PORTA_PIN7CTRL": (0x0417, 1),
"LOCKBIT_LOCKBIT": (0x128A, 1),
"SIGROW_OSCCAL20M0": (0x111A, 1),
"TCB1_TEMP": (0x0A99, 1),
"FUSE_SYSCFG1": (0x1286, 1),
"PORTB_DIRSET": (0x0421, 1),
"PORTC_OUTTGL": (0x0447, 1),
"ADC0_CTRLA": (0x0600, 1),
"TCA0_SPLIT_LCMP1": (0x0A2A, 1),
"TCA0_SPLIT_LCMP2": (0x0A2C, 1),
"TCA0_SINGLE_CMP1BUFH": (0x0A3B, 1),
"TCA0_SINGLE_CMP1BUFL": (0x0A3A, 1),
"USART1_TXDATAL": (0x0822, 1),
"ADC0_TEMP1": (0x0619, 1),
"TCA0_SPLIT_INTFLAGS": (0x0A0B, 1),
"PORTMUX_SPIROUTEA": (0x05E3, 1),
"TCA0_SPLIT_CTRLESET": (0x0A05, 1),
"TCA0_SINGLE_CTRLFSET": (0x0A07, 1),
"SPI0_INTCTRL": (0x08C2, 1),
"PORTC_PIN6CTRL": (0x0456, 1),
"NVMCTRL_STATUS": (0x1002, 1),
"CCL_TRUTH1": (0x01CF, 1),
"CCL_TRUTH2": (0x01D3, 1),
"CLKCTRL_MCLKLOCK": (0x0062, 1),
"SYSCFG_REVID": (0x0F01, 1),
"USERROW_USERROW10": (0x130A, 1),
"USERROW_USERROW11": (0x130B, 1),
"USERROW_USERROW12": (0x130C, 1),
"USERROW_USERROW14": (0x130E, 1),
"USERROW_USERROW15": (0x130F, 1),
"USERROW_USERROW16": (0x1310, 1),
"USERROW_USERROW18": (0x1312, 1),
"USART1_CTRLA": (0x0825, 1),
"USART1_CTRLB": (0x0826, 1),
"USART1_CTRLC": (0x0827, 1),
"USART1_CTRLD": (0x082A, 1),
"USERROW_USERROW20": (0x1314, 1),
"USERROW_USERROW22": (0x1316, 1),
"USERROW_USERROW23": (0x1317, 1),
"USERROW_USERROW24": (0x1318, 1),
"USERROW_USERROW26": (0x131A, 1),
"USERROW_USERROW27": (0x131B, 1),
"USERROW_USERROW28": (0x131C, 1),
"VPORTC_OUT": (0x0009, 1),
"CCL_LUT2CTRLA": (0x01D0, 1),
"USERROW_USERROW30": (0x131E, 1),
"TCA0_SINGLE_CMP0BUFL": (0x0A38, 1),
"PORTA_OUTSET": (0x0405, 1),
"FUSE_OSCCFG": (0x1282, 1),
"ADC0_STATUS": (0x0606, 1),
"CPU_SREG": (0x003F, 1),
"AC0_CTRLA": (0x0680, 1),
"TCA0_SINGLE_PERH": (0x0A27, 1),
"EVSYS_USEREVSYSEVOUTA": (0x01A9, 1),
"EVSYS_USEREVSYSEVOUTB": (0x01AA, 1),
"TCA0_SINGLE_PERL": (0x0A26, 1),
"TCA0_SPLIT_DBGCTRL": (0x0A0E, 1),
"PORTB_PIN7CTRL": (0x0437, 1),
"TCB0_INTCTRL": (0x0A85, 1),
"PORTC_PIN5CTRL": (0x0455, 1),
"AC0_STATUS": (0x0687, 1),
"CLKCTRL_OSC20MCTRLA": (0x0070, 1),
"TCB0_INTFLAGS": (0x0A86, 1),
"ADC0_SAMPLEL": (0x0614, 1),
"RTC_DBGCTRL": (0x0145, 1),
"CLKCTRL_MCLKCTRLA": (0x0060, 1),
"CLKCTRL_MCLKCTRLB": (0x0061, 1),
"USART1_BAUDH": (0x0829, 1),
"USART1_BAUDL": (0x0828, 1),
"VPORTB_IN": (0x0006, 1),
"GPIO_GPIOR0": (0x001C, 1),
"GPIO_GPIOR1": (0x001D, 1),
"GPIO_GPIOR2": (0x001E, 1),
"GPIO_GPIOR3": (0x001F, 1),
"BOD_INTCTRL": (0x0089, 1),
"CPU_SPH": (0x003E, 1),
"CPU_SPL": (0x003D, 1),
"SIGROW_TEMPSENSE0": (0x1120, 1),
"SIGROW_TEMPSENSE1": (0x1121, 1),
"CLKCTRL_XOSC32KCTRLA": (0x007C, 1),
"AC0_DACREF": (0x0684, 1),
"ADC0_SAMPLEH": (0x0615, 1),
"CRCSCAN_STATUS": (0x0122, 1),
"RTC_PERH": (0x014B, 1),
"TCA0_SINGLE_CTRLESET": (0x0A05, 1),
"TCA0_SINGLE_CTRLFCLR": (0x0A06, 1),
"PORTC_INTFLAGS": (0x0449, 1),
"PORTA_DIRSET": (0x0401, 1),
"PORTB_OUTTGL": (0x0427, 1),
"TCB0_STATUS": (0x0A87, 1),
"PORTB_PIN6CTRL": (0x0436, 1),
"TCA0_SINGLE_CNTH": (0x0A21, 1),
"USERROW_USERROW0": (0x1300, 1),
"USERROW_USERROW3": (0x1303, 1),
"USERROW_USERROW4": (0x1304, 1),
"USERROW_USERROW5": (0x1305, 1),
"USERROW_USERROW7": (0x1307, 1),
"USERROW_USERROW8": (0x1308, 1),
"USERROW_USERROW9": (0x1309, 1),
"TCB1_EVCTRL": (0x0A94, 1),
"TCB1_DBGCTRL": (0x0A98, 1),
"SIGROW_OSCCAL16M0": (0x1118, 1),
"SIGROW_OSCCAL16M1": (0x1119, 1),
"EVSYS_USERUSART1IRDA": (0x01AD, 1),
"RTC_CLKSEL": (0x0147, 1),
"TCA0_SINGLE_INTCTRL": (0x0A0A, 1),
"USART0_DBGCTRL": (0x080B, 1),
"TCA0_SPLIT_HCNT": (0x0A21, 1),
"WDT_STATUS": (0x0101, 1),
"PORTMUX_TCAROUTEA": (0x05E4, 1),
"USART1_STATUS": (0x0824, 1),
"GPIOR0": (0x001C, 1),
"GPIOR1": (0x001D, 1),
"GPIOR2": (0x001E, 1),
"GPIOR3": (0x001F, 1),
"TCA0_SPLIT_HPER": (0x0A27, 1),
"RSTCTRL_RSTFR": (0x0040, 1),
"CCL_INTFLAGS": (0x01C7, 1),
"PORTB_OUTCLR": (0x0426, 1),
"TWI0_SSTATUS": (0x08AB, 1),
"BOD_STATUS": (0x008B, 1),
"VPORTC_INTFLAGS": (0x000B, 1),
"PORTB_PIN5CTRL": (0x0435, 1),
"SPH": (0x003E, 1),
"SPL": (0x003D, 1),
"PORTC_PIN3CTRL": (0x0453, 1),
"TCB1_CTRLA": (0x0A90, 1),
"EVSYS_USERTCA0CNTA": (0x01AE, 1),
"EVSYS_USERTCA0CNTB": (0x01AF, 1),
"NVMCTRL_INTCTRL": (0x1003, 1),
"CRCSCAN_CTRLA": (0x0120, 1),
"PORTB_DIRTGL": (0x0423, 1),
"ADC0_MUXNEG": (0x060D, 1),
"NVMCTRL_CTRLA": (0x1000, 1),
"NVMCTRL_CTRLB": (0x1001, 1),
"USART1_EVCTRL": (0x082C, 1),
"PORTC_DIRTGL": (0x0443, 1),
"CCL_CTRLA": (0x01C0, 1),
"USART1_RXPLCTRL": (0x082E, 1),
"RTC_INTFLAGS": (0x0143, 1),
"FUSE_SYSCFG0": (0x1285, 1),
"AC0_MUXCTRLA": (0x0682, 1),
"TWI0_MSTATUS": (0x08A5, 1),
"SPI0_CTRLA": (0x08C0, 1),
"SPI0_CTRLB": (0x08C1, 1),
"TCB0_CNTH": (0x0A8B, 1),
"PORTB_PORTCTRL": (0x042A, 1),
"EVSYS_USERCCLLUT0A": (0x01A0, 1),
"EVSYS_SWEVENTA": (0x0180, 1),
"PORTA_PIN6CTRL": (0x0416, 1),
"EVSYS_USERCCLLUT0B": (0x01A1, 1),
"CCL_LUT1CTRLB": (0x01CD, 1),
"EVSYS_USERCCLLUT1A": (0x01A2, 1),
"EVSYS_USERCCLLUT1B": (0x01A3, 1),
"PORTB_PIN4CTRL": (0x0434, 1),
"EVSYS_USERCCLLUT2A": (0x01A4, 1),
"EVSYS_USERCCLLUT2B": (0x01A5, 1),
"EVSYS_USERCCLLUT3A": (0x01A6, 1),
"EVSYS_USERCCLLUT3B": (0x01A7, 1),
"RTC_PITSTATUS": (0x0151, 1),
"TCA0_SINGLE_INTFLAGS": (0x0A0B, 1),
"TWI0_MBAUD": (0x08A6, 1),
"TCB0_EVCTRL": (0x0A84, 1),
"TCB1_CTRLB": (0x0A91, 1),
"TCB0_CCMPH": (0x0A8D, 1),
"TCB0_CCMPL": (0x0A8C, 1),
"PORTA_OUTTGL": (0x0407, 1),
"USART1_TXDATAH": (0x0823, 1),
"TCA0_SINGLE_EVCTRL": (0x0A09, 1),
"TCA0_SINGLE_DBGCTRL": (0x0A0E, 1),
"BOD_CTRLA": (0x0080, 1),
"USART1_RXDATAH": (0x0821, 1),
"USART1_RXDATAL": (0x0820, 1),
"TWI0_CTRLA": (0x08A0, 1),
"VPORTB_OUT": (0x0005, 1),
"RTC_TEMP": (0x0144, 1),
"PORTB_PIN1CTRL": (0x0431, 1),
"VPORTB_INTFLAGS": (0x0007, 1),
"ADC0_RESULT0": (0x0610, 1),
"ADC0_RESULT1": (0x0611, 1),
"ADC0_RESULT2": (0x0612, 1),
"PORTA_PIN5CTRL": (0x0415, 1),
"CCL_TRUTH3": (0x01D7, 1),
"CPUINT_LVL1VEC": (0x0113, 1),
"CCL_INTCTRL0": (0x01C5, 1),
"TCB1_CNTH": (0x0A9B, 1),
"PORTC_PIN1CTRL": (0x0451, 1),
"SPI0_DATA": (0x08C4, 1),
"USART0_STATUS": (0x0804, 1),
"CPU_CCP": (0x0034, 1),
"RTC_CTRLA": (0x0140, 1),
"RTC_STATUS": (0x0141, 1),
"PORTA_INTFLAGS": (0x0409, 1),
"CPUINT_STATUS": (0x0111, 1),
"BOD_CTRLB": (0x0081, 1),
"USART0_RXPLCTRL": (0x080E, 1),
"CRCSCAN_CTRLB": (0x0121, 1),
"PORTA_PORTCTRL": (0x040A, 1),
"TCB0_DBGCTRL": (0x0A88, 1),
"RTC_PITINTFLAGS": (0x0153, 1),
"PORTC_DIRCLR": (0x0442, 1),
"PORTA_DIRTGL": (0x0403, 1),
"CCL_SEQCTRL0": (0x01C1, 1),
"CCL_SEQCTRL1": (0x01C2, 1),
"PORTA_PIN4CTRL": (0x0414, 1),
"VPORTC_DIR": (0x0008, 1),
"TCB1_STATUS": (0x0A97, 1),
"FUSE_BODCFG": (0x1281, 1),
"PORTB_PIN2CTRL": (0x0432, 1),
"TWI0_MADDR": (0x08A7, 1),
"FUSE_BOOTEND": (0x1288, 1),
"EVSYS_USERUSART0IRDA": (0x01AC, 1),
"RTC_CALIB": (0x0146, 1),
"TWI0_MCTRLA": (0x08A3, 1),
"TWI0_MCTRLB": (0x08A4, 1),
"PORTC_PIN0CTRL": (0x0450, 1),
"ADC0_WINLTH": (0x061D, 1),
"RSTCTRL_SWRR": (0x0041, 1),
"PORTMUX_TCBROUTEA": (0x05E5, 1),
"VPORTC_IN": (0x000A, 1),
"TCA0_SINGLE_TEMP": (0x0A0F, 1),
"TCA0_SPLIT_CTRLA": (0x0A00, 1),
"FUSE_APPEND": (0x1287, 1),
"RTC_CMPH": (0x014D, 1),
"RTC_CMPL": (0x014C, 1),
"TCA0_SPLIT_CTRLC": (0x0A02, 1),
"CCL_LUT3CTRLC": (0x01D6, 1),
"RTC_CNTL": (0x0148, 1),
"USERROW_USERROW6": (0x1306, 1),
"VPORTA_INTFLAGS": (0x0003, 1),
"PORTA_OUTCLR": (0x0406, 1),
"PORTMUX_EVSYSROUTEA": (0x05E0, 1),
"PORTA_PIN3CTRL": (0x0413, 1),
"VPORTB_DIR": (0x0004, 1),
"ADC0_INTCTRL": (0x0604, 1),
"NVMCTRL_DATAH": (0x1007, 1),
"VPORTA_DIR": (0x0000, 1),
"VREF_CTRLB": (0x00A1, 1),
"NVMCTRL_DATAL": (0x1006, 1),
"TWI0_SADDR": (0x08AC, 1),
"USART0_CTRLB": (0x0806, 1),
"USART0_CTRLC": (0x0807, 1),
"USART0_CTRLD": (0x080A, 1),
"EVSYS_USERTCB0COUNT": (0x01B1, 1),
"TCB1_CCMPH": (0x0A9D, 1),
"SPI0_INTFLAGS": (0x08C3, 1),
"ADC0_COMMAND": (0x060A, 1),
"ADC0_RESULT3": (0x0613, 1),
"SREG": (0x003F, 1),
"PORTA_PIN2CTRL": (0x0412, 1),
"USART0_EVCTRL": (0x080C, 1),
"USART0_TXDATAH": (0x0803, 1),
"ADC0_SAMPLE": (0x0614, 2),
"TCA0_SINGLE_CMP0": (0x0A28, 2),
"TCA0_SINGLE_CMP1": (0x0A2A, 2),
"TCA0_SINGLE_CNT": (0x0A20, 2),
"RTC_CMP": (0x014C, 2),
"RTC_CNT": (0x0148, 2),
"CPU_SP": (0x003D, 2),
"TCA0_SINGLE_CMP2": (0x0A2C, 2),
"TCA0_SINGLE_CMP2BUF": (0x0A3C, 2),
"NVMCTRL_DATA": (0x1006, 2),
"TCA0_SINGLE_CMP1BUF": (0x0A3A, 2),
"NVMCTRL_ADDR": (0x1008, 2),
"USART0_BAUD": (0x0808, 2),
"TCA0_SINGLE_CMP0BUF": (0x0A38, 2),
"TCB0_CCMP": (0x0A8C, 2),
"RTC_PER": (0x014A, 2),
"TCB1_CNT": (0x0A9A, 2),
"TCB1_CCMP": (0x0A9C, 2),
"USART1_BAUD": (0x0828, 2),
"TCB0_CNT": (0x0A8A, 2),
"ADC0_WINHT": (0x061E, 2),
"ADC0_WINLT": (0x061C, 2),
"SP": (0x003D, 2),
"TCA0_SINGLE_PERBUF": (0x0A36, 2),
"TCA0_SINGLE_PER": (0x0A26, 2),
"ADC0_RESULT": (0x0610, 4),
}

33
src/map.py Normal file
View file

@ -0,0 +1,33 @@
class memmap(dict):
def __init__(self, fn="hallo.map"):
self.parsemap(fn)
def parsemap(self, fn):
with open(fn) as f:
laddr = None
for l in f:
try:
ll = l.split()
if l[:1] == "." and len(ll) >= 3:
section = ll[0]
saddr = int(ll[1], 0) & 0xffff
slen = int(ll[2], 0)
self[section] = (saddr, slen)
laddr = saddr
last = None
continue
if l[:1] != " ":
continue
if len(ll)==2 and ll[0][:2] == "0x" or len(ll)==4 and ll[2]=="=" and ll[3]==".":
cur = ll[1]
addr = int(ll[0],0) & 0xffff
self[cur] = (addr,0)
if last is not None:
self[last] = (self[last][0], addr-laddr)
last = cur
laddr = addr
except Exception as e:
from sys import stderr
print(f"{repr(e)}\n{l}", file=stderr)

20
src/prompt.py Normal file
View file

@ -0,0 +1,20 @@
import sys
def set_prompt(prompt):
sys.ps1 = prompt + "> "
sys.ps2 = prompt + ". "
try:
ip=get_ipython()
from IPython.terminal.prompts import Prompts, Token
class myprompts(Prompts):
def in_prompt_tokens(self, *wtf):
return [(Token, prompt+'> ')]
def continuation_prompt_tokens(self, *wtf):
return [(Token, prompt+'. ')]
def out_prompt_tokens(self, *wtf):
return [(Token, prompt+'= ')]
def rewrite_prompt_tokens(self, *wtf):
return [(Token, prompt+'- ')]
ip.prompts=myprompts(ip)
except:
pass

View file

@ -25,7 +25,7 @@ uint8_t rtc_cnt_tick()
struct_ioconf(rtc_config) = { struct_ioconf(rtc_config) = {
conf_prefix(RTC), conf_prefix(RTC),
conf_iow(RTC.CMP, 3600), conf_iow(RTC.CMP, 10), // rtc_cnt_tick() period [s]
conf_io(RTC.CLKSEL, RTC_CLKSEL_INT1K_gc), conf_io(RTC.CLKSEL, RTC_CLKSEL_INT1K_gc),
conf_io(RTC.PITINTCTRL, 1), conf_io(RTC.PITINTCTRL, 1),
conf_io(RTC.PITCTRLA, RTC_PERIOD_CYC1024_gc | RTC_PITEN_bm), conf_io(RTC.PITCTRLA, RTC_PERIOD_CYC1024_gc | RTC_PITEN_bm),
@ -43,8 +43,7 @@ ISR(RTC_PIT_vect, ISR_NAKED)
"ldi r24, 1" "\n\t" "ldi r24, 1" "\n\t"
"sts %[flag], r24" "\n\t" "sts %[flag], r24" "\n\t"
"sts pit_tick, r24" "\n\t" "sts pit_tick, r24" "\n\t"
"ldi r24, " "\n\t" "pop r24" "\n\t"
"sts %[flag], r24" "\n\t"
"reti" "\n" "reti" "\n"
::[flag] "n" (&RTC.PITINTFLAGS) ::[flag] "n" (&RTC.PITINTFLAGS)
); );
@ -66,11 +65,11 @@ ISR(RTC_CNT_vect, ISR_NAKED)
"push r26" "\n\t" "push r26" "\n\t"
"lds r24, %[CMPL]" "\n\t" "lds r24, %[CMPL]" "\n\t"
"lds r25, %[CMPH]" "\n\t" "lds r25, %[CMPH]" "\n\t"
"lds r26, config+3" "\n\t" "lds r26, rtc_config+3" "\n\t"
"add r24, r26" "\n\t" "add r24, r26" "\n\t"
"sts %[CMPL], r24" "\n\t" "sts %[CMPL], r24" "\n\t"
"lds r26, config+5" "\n\t" "lds r26, rtc_config+5" "\n\t"
"add r25, r26" "\n\t" "adc r25, r26" "\n\t"
"sts %[CMPH], r25" "\n\t" "sts %[CMPH], r25" "\n\t"
"pop r26" "\n\t" "pop r26" "\n\t"
"pop r25" "\n\t" "pop r25" "\n\t"

View file

@ -10,10 +10,10 @@
struct_ioconf(uart_config) = { struct_ioconf(uart_config) = {
conf_prefix(USART0), conf_prefix(USART0),
conf_iow(USART0.BAUD, UART_BAUD), conf_iow(USART0.BAUD, 40000000/115200), // 115200 baud
conf_io(USART0.CTRLB, UART_MODE & 0xff), conf_io(USART0.CTRLC, USART_CHSIZE_8BIT_gc),
conf_io(USART0.CTRLC, UART_MODE >> 8), conf_io(USART0.CTRLB, USART_TXEN_bm | USART_RXEN_bm),
conf_io(USART0.CTRLA,USART_RXCIE_bm), conf_io(USART0.CTRLA, USART_RXCIE_bm),
}; };
// `uart_tx` buffer size must be a power of 2, max 256. // `uart_tx` buffer size must be a power of 2, max 256.
@ -163,7 +163,7 @@ ISR(USART0_RXC_vect, ISR_NAKED)
" push r31 \n" " push r31 \n"
" lds r24, %[DH] \n" " lds r24, %[DH] \n"
" lds r30, uart_rx_s \n" " lds r30, uart_rx_s \n"
" and r24, r30 \n" " or r24, r30 \n"
" sts uart_rx_s, r24 \n" " sts uart_rx_s, r24 \n"
" lds r24, %[DL] \n" " lds r24, %[DL] \n"
" lds r30, uart_rx_w \n" " lds r30, uart_rx_w \n"

View file

@ -4,9 +4,6 @@
#include "config.h" #include "config.h"
#define UART_MODE 0x03c0
#define UART_BAUD 5555 // 115200 baud
void init_uart(uint16_t mode, uint16_t div); void init_uart(uint16_t mode, uint16_t div);
void send_char(uint8_t c); void send_char(uint8_t c);

115
src/uart.py Executable file
View file

@ -0,0 +1,115 @@
#! /usr/bin/ipython3 --profile=uart
import sys, serial, threading, struct
from prompt import set_prompt
class uart(threading.Thread):
def __init__(self, port, baudrate=115200, parity='N'):
self.baudrate=baudrate
self.serial = serial.Serial(baudrate=baudrate, parity=parity, timeout=10.0,
xonxoff=False, rtscts=False, dsrdtr=False)
self.serial.port = port
self.portname = port.split('/')[-1]
self.serial.open()
self.write = self.serial.write
self.responses = []
self.readbuffer = b""
self.reader_lock = threading.Lock()
self.resp_ready = threading.Condition()
self.alive = True
threading.Thread.__init__(self, target=self.reader)
self.daemon = True
self.start()
def reader(self):
data = b""
while self.alive:
data += self.serial.read_until(b'\n')
data += self.serial.read_all()
if data and self.reader_lock.acquire(False):
self.readbuffer += data
data = b""
self.parser()
self.reader_lock.release()
def parse(self):
if self.reader_lock.acquire(False):
self.parser()
self.reader_lock.release()
def kill(self):
self.alive = False
self.join()
def parser(self):
"do something with received chars in .readbuffer"
if not self.resp_ready.acquire(False):
return
lines = self.readbuffer.split(b'\n')
self.readbuffer = lines[-1]
lines[-1:] = []
for ll in lines:
if ll:
self.parse_line(ll)
if self.responses:
self.resp_ready.notify()
self.resp_ready.release()
verbose = True
def parse_line(self, l):
self.responses.append(l)
if self.verbose:
try:
s = l.decode()
print(f"{self.portname}<- {s}", file=sys.stderr)
except:
print(f"{self.portname}<- {repr(l)}", file=sys.stderr)
def resp(self, timeout=10, blocking=True):
self.parse()
if not self.resp_ready.acquire(blocking):
return b""
if blocking and not self.responses:
self.resp_ready.wait(timeout)
l = b""
if self.responses:
l = self.responses[0]
self.responses[:1] = []
self.resp_ready.release()
return l
def flush(self):
r = []
while self.responses:
r.append(self.resp())
return r
def ucmd(self, c):
if not isinstance(c, bytes):
c = c.encode()
if c[-1:] != b'\n':
c = c + b'\n'
if self.verbose:
print(f"{self.portname}-> {c.decode().rstrip()}", file=sys.stderr)
self.write(c)
def cmd(self, c):
self.ucmd(c)
if __name__=="__main__":
import getopt
oo,ff = getopt.getopt(sys.argv[1:], "F:", ["tty="])
port = "/dev/ttyUSB1"
baud = 115200
for o,v in oo:
if o=="-F" or v=="--tty":
v = v.split(",")
port = v[0]
if len(v)>1:
baud = int(v[1])
u = uart(port, baud)
c = u.ucmd
set_prompt(u.portname)

View file

@ -14,6 +14,7 @@
.global _send_str26 .global _send_str26
.global uart_busy .global uart_busy
.global send_hex .global send_hex
.global send_eol
.global command .global command
// `tx()` and `put_char()` do not gobble r18, r20, r21, r22, r24, r26, and r27. // `tx()` and `put_char()` do not gobble r18, r20, r21, r22, r24, r26, and r27.
@ -101,7 +102,7 @@ send_hex:
ld r24, X+ ld r24, X+
rcall send_hex_byte rcall send_hex_byte
subi r18, 1 subi r18, 1
brcc 1b brne 1b
9: 9:
ret ret
#endif #endif