diff --git a/.gitignore b/.gitignore index abf7b0f..f6b9432 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ src/data BCH-Codes/ *.odt *.userrow +*.m +src/data +galois diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..640e812 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/bch4369"] + path = src/bch4369 + url = git@codeberg.org:SiB64/bch4369 diff --git a/gerber/turbo-bot.png b/gerber/turbo-bot.png index d634351..e1245b1 100644 Binary files a/gerber/turbo-bot.png and b/gerber/turbo-bot.png differ diff --git a/gerber/turbo_bom.txt b/gerber/turbo_dose_bom.txt similarity index 51% rename from gerber/turbo_bom.txt rename to gerber/turbo_dose_bom.txt index 1ed7ed0..f938f31 100644 --- a/gerber/turbo_bom.txt +++ b/gerber/turbo_dose_bom.txt @@ -1,30 +1,26 @@ # PcbBOM Version 1.0 -# Date: So 21 Apr 2024 10:57:09 GMT UTC -# Author: +# Date: Di 09 Jun 2026 08:58:28 GMT UTC +# Author: Stephan Boettcher # Title: TURBO - PCB BOM # Quantity, Description, Value, RefDes # -------------------------------------------- C0603 -BYP_100nF 1/1 C4 -C0603 100nF 6/6 C1 C10 C11 C12 C2 C3 +C0603 100nF 6/6 C11 C12 C30 C32 C33 C34 C0603 SMD-LED 1/1 D1 C0603.fp -SD:_10kΩ 1/1 R13 -C0603.fp 10MΩ 1/1 R9 -C0603.fp 10kΩ 4/4 R11 R5 R7 R8 -C0603.fp 10kΩ_NTC 1/1 R6 -C0603.fp 1MΩ 1/1 R10 +C0603.fp 100kΩ 7/7 R30 R31 R32 R33 R34 R35 R36 +C0603.fp 10kΩ 1/1 R11 C0603.fp 2.2MΩ 1/1 R4 -C0603.fp 220kΩ 1/1 R2 C0603.fp 3.3MΩ 1/1 R3 -C0603.fp 330kΩ 1/1 R1 C0603.fp ∞Ω 1/1 R12 +C0603.fp ∞Ω/0Ω 1/1 R10 KEYSTONE-1025-7 6V 1/1 B1 -MS5534C MS5534C 1/1 U2 -P1206 10µF 11/11 C20 C21 C22 C23 C24 C25 C26 C27 C28 C29 - C30 +P1206 10µF 4/4 C20 C26 C29 C31 SIL_100_3 HE_100_1×3 1/1 J1 -SIL_100_4 WRL-10534 1/1 U3 +SIL_100_4 SIL4 1/1 U3 SOIC_150_14 ATtiny4x4SS 1/1 U1 -SOT23_5 LT1761-SD 1/1 U4 +SOIC_150_8 AT45DB161E 1/1 U2 +SOT23_3 2N7002 2/2 Q1 Q2 SOT23_5 LT1761-SD_/_-BYP 1/1 U5 SUBD9_PINS D9_pigtail 1/1 CONN1 gseboard turbo 1/1 BOARD diff --git a/src/Makefile b/src/Makefile index a28ac24..5d27d40 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,13 +1,20 @@ -PROJ=dose +PROJ=hallo PATH:=/usr/local/bin:$(PATH) +VPATH=.:bch4369 default: all all: $(PROJ).hex $(PROJ)_all -dose_all: dose.eeprom dose.userrow +hallo_all: hallo.eeprom +CFLAGS_hallo = -Ibch4369 -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 spi.c flash.c bch4369.c +S_FILES_hallo = uart_tx.S base85a.S +dose_all: dose.eeprom dose.userrow SN_dose = 1 MCU_dose = $(MCU_$(VAR)) MCU_nFETs = attiny424 @@ -48,6 +55,9 @@ OBJS = $(patsubst %.c, %.o, $(C_FILES)) $(patsubst %.S, %.o, $(S_FILES)) %.o: %.S $(CC) $(CFLAGS) -c $< +%.m: %.S + $(CC) $(CFLAGS) -E -dM $< > $@ + -include *.d LDFLAGS = -Teeprom.ld @@ -97,6 +107,7 @@ AVRDUDE_PORT = /dev/ttyUSB1 AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) sig_dose = 0x1e 0x92 0x2c +sig_hallo = 0x1e 0x92 0x2c id: $(PROJ).id %.id: @@ -132,3 +143,5 @@ eeprom.eeprom: %.eeprom.burn: %.eeprom $(AD) -U eeprom:v:$< || $(AD) -U eeprom:w:$< +%.userrow.burn: %.userrow + $(AD) -U userrow:v:$< || $(AD) -U userrow:w:$< diff --git a/src/adc.c b/src/adc.c index d9cf8a9..03e45b6 100644 --- a/src/adc.c +++ b/src/adc.c @@ -8,12 +8,18 @@ #include "pwm.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 { INP = ADC_VIA_ADC_gc, INN = ADC_VIA_ADC_gc, REF = 10 << ADC_TIMEBASE_gp, - MODE = ADC_MODE_SERIES_SCALING_gc | ADC_START_EVENT_TRIGGER_gc, - MODE_DIFF = ADC_MODE_BURST_SCALING_gc | ADC_START_IMMEDIATE_gc | ADC_DIFF_bm, + MODE = ADC_TRIGGER, + MODE_DIFF = ADC_TRIGGER | ADC_DIFF_bm, }; __attribute__((section(".eeprom1"))) @@ -81,7 +87,7 @@ struct_ioconf(adc_config) = { conf_prefix(ADC), conf_io(ADC.CTRLA, ADC_ENABLE_bm), 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.INTCTRL, ADC_RESRDY_bm), conf_prefix(EVSYS), @@ -91,8 +97,6 @@ struct_ioconf(adc_config) = { void start_adc() { - if (!adc_conf->mode) - return; ADC.COMMAND = 0; adc_current = 0; start_conversion(adc_conf); @@ -114,7 +118,7 @@ ISR(ADC0_RESRDY_vect) } } stop: - ADC.CTRLA = 0; + ADC.COMMAND = 0; adc_current = N_ADC; } @@ -136,7 +140,7 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED) "push r31" "\n\t" "lds r24, adc_current" "\n\t" "cpi r24, %[NADC]" "\n\t" - "brcc 3f" "\n\t" + "brcc 2f" "\n\t" "mov r30, r24" "\n\t" "ldi r31, 0" "\n\t" "lsl r30" "\n\t" @@ -148,7 +152,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED) "std Z+1, r25" "\n" "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" "mov r30, r24" "\n\t" "ldi r31, 0" "\n\t" @@ -164,9 +170,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED) "sts %[MUXPOS], r25" "\n\t" "ld r25, Z" "\n\t" "tst r25" "\n\t" - "breq 1b" "\n\t" - "sts %[COMMAND], r25" "\n" - "2:" "\n\t" + "breq 1b" "\n" + "3:" "\n\t" + "sts %[COMMAND], r25" "\n\t" "sts adc_current, r24" "\n\t" "pop r31" "\n\t" "pop r30" "\n\t" @@ -175,16 +181,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED) "out __SREG__, r24" "\n\t" "pop r24" "\n\t" "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), [RESULT] "n" (&ADC.RESULT), - [CTRLA] "n" (&ADC.CTRLA), [CTRLC] "n" (&ADC.CTRLC), [MUXPOS] "n" (&ADC.MUXPOS), [MUXNEG] "n" (&ADC.MUXNEG), diff --git a/src/base85.c b/src/base85.c index d33b2b0..e92e478 100644 --- a/src/base85.c +++ b/src/base85.c @@ -12,10 +12,10 @@ int base85_encode(uint32_t u, uint8_t *s) { s += 5; *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; return 5; } diff --git a/src/base85.py b/src/base85.py new file mode 100644 index 0000000..43b4339 --- /dev/null +++ b/src/base85.py @@ -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) diff --git a/src/base85_test.c b/src/base85_test.c new file mode 100644 index 0000000..b534da2 --- /dev/null +++ b/src/base85_test.c @@ -0,0 +1,132 @@ + +#include +#include + +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); +} diff --git a/src/base85a.S b/src/base85a.S index e6ef42f..b92119c 100644 --- a/src/base85a.S +++ b/src/base85a.S @@ -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 divmod85: movw r26, r20 - # endif - - ;; ! C-ABI: gobbles r1, m=X -_divmod85: ; r25,r24,r23,r22 = A,B,C,D - mov r18, r25 - add r18, r24 - clr 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 +#endif + ;; ! C-ABI: m=X +_divmod85: ; r25,r24,r23,r22 = A,B,C,D + movw r18, r22 + movw r20, r24 + 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 ; r21,r20,r19,r18,r0 = 3u + 1 + + mov r30, r21 + add r30, r20 + clr r31 rol r31 - rol r30 - add r18, r19 - adc r25, r21 - adc r24, r20 - adc r23, r31 - adc r22, r30 + add r30, r19 + adc r31, r1 + add r30, r18 + adc r31, r1 + add r30, r0 + 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 mul r18, r19 lsl r0 - ldi r18, 33 - adc r1, r18 - # ifdef BASE85C - st X, r1 - clr r1 - # else + ldi r19, '!' + adc r1, r19 st -X, r1 - # endif + clr r1 ret - - #ifndef BASE85C + +#ifndef BASE85C .global base85_encode base85_encode: movw r26, r20 @@ -76,20 +101,20 @@ base85_encode: rcall _divmod85 rcall _divmod85 rcall _divmod85 - subi r25, -33 - st X, r25 - ldi r24, 5 - clr r1 + subi r25, -'!' + st -X, r25 ret - # endif +#endif ; uint32_t mul85(uint32_t u, uint8_t m); - #ifdef BASE85C +#ifdef BASE85C .global mul85 mul85: - # endif +#endif ;; TODO for SPACE: inline this + + ;; big endian r22/r23/r24/r25 *= 85; … += r20 _mul85: ldi r21, 85 mul r25, r21 @@ -106,12 +131,12 @@ _mul85: mov r25, r18 mov r23, r30 mov r22, r31 - # ifdef BASE85C +#ifdef BASE85C clr r1 - # endif +#endif ret - #ifndef BASE85C +#ifndef BASE85C .global base85_decode base85_decode: @@ -125,7 +150,9 @@ base85_decode: clr r22 ldi r17, 5 1: - ld r20, Y+ + ld r20, X+ + subi r20, '!' + brcs 2f cpi r20, 85 brcc 2f rcall _mul85 @@ -145,4 +172,4 @@ base85_decode: clr r1 ret - # endif +#endif diff --git a/src/bch4369 b/src/bch4369 new file mode 160000 index 0000000..eebd4bb --- /dev/null +++ b/src/bch4369 @@ -0,0 +1 @@ +Subproject commit eebd4bb43039a2ecf63aa7c2fdbe1c4edf469393 diff --git a/src/bch4369.c b/src/bch4369.c deleted file mode 100644 index dc3f4c2..0000000 --- a/src/bch4369.c +++ /dev/null @@ -1,114 +0,0 @@ -/********************************************************************* - -galois.BCH(4369, 4369-128, extension_field=galois.GF(2**16)) -→ - -hex(bch.generator_poly) -→ '0x124a5eda5ec0cbce2104522c1782ed521' - -A flash page is 512 + 16 bytes. Use the extended page size for parity -bits. A code size of n=4369 is achievable with m=16. There are n-k = -128 parity bits. The code has a Hamming distance of d=17. That allows -correction of up to 8 error bits. The message is padded with 145 bits -of zeros. - -*********************************************************************/ - - -#include "bch4369.h" - -uint8_t bch_parity[16]; -const -uint8_t bch_genpoly[16] = { - 0x24, 0xa5, 0xed, 0xa5, - 0xec, 0x0c, 0xbc, 0xe2, - 0x10, 0x45, 0x22, 0xc1, - 0x78, 0x2e, 0xd5, 0x21 -}; - -#ifdef BCH_C - -void bch4369(uint8_t d) -{ - uint8_t *p = bch_parity; - uint8_t m = *p; - for (int i=0; i<8; i++) { - p += 16; - const uint8_t *pp = bch_genpoly + 16; - uint8_t b = d; - d <<= 1; - uint8_t mm = m; - for (int j=0; j<16; j++) { - uint8_t bb = *--p; - m = bb << 1 | b >> 7; - if (mm & 0x80) - m ^= *--pp; - *p = m; - b = bb; - } - } -} - -void bch4369_str(uint8_t *b, uint8_t n) -{ - do - bch4369(*b++); - while (--n); -} - -#else - -__attribute__ ((noinline, naked)) -void bch4369(uint8_t d) -{ - __asm__ __volatile__( - "" - "ldi r30, lo8(bch_parity)" "\n\t" - "ldi r31, hi8(bch_parity)" "\n\t" - "ld r25, Z" "\n\t" - "bst r25, 7" "\n\t" // copy MSB of parity → T-bit - "ldi r20, 8" "\n\t" // loop r20 = 8 → 1 - "1:" "\n\t" - "adiw r30, 16" "\n\t" - "ldi r26, lo8(bch_genpoly+16)" "\n\t" - "ldi r27, hi8(bch_genpoly+16)" "\n\t" - "rol r24" "\n\t" // move next input bit → r25.7 - "ror r25" "\n\t" - "2:" "\n\t" - "rol r25" "\n\t" // Move r25.7 → C-bit - "ld r25, -Z" "\n\t" // Rotage input bit into parity byte - "rol r25" "\n\t" - "brtc 3f" "\n\t" // if T-bit: - "ld r0, -X" "\n\t" // xor with gen_poly - "eor r25, r0" "\n\t" - "3:" "\n\t" - "st Z, r25" "\n\t" - "ror r25" "\n\t" // save C-bit → r25.7 and MSB → r25.6 - "cpi r30, lo8(bch_parity)" "\n\t" - "brne 2b" "\n\t" - "bst r25, 6" "\n\t" // copy MSB r25.6 → T-bit - "subi r20, 1" "\n\t" - "brne 1b" "\n\t" - "ret" "\n" - ); -} - -__attribute__ ((noinline, naked)) -void bch4369_str(const uint8_t *b, uint8_t n) -{ - // _bch4369 preserves r22, r23, r18, r19 - __asm__ __volatile__ ( - "" - "movw r18, r28" "\n\t" - "movw r28, r24" "\n" - "1:" "\n\t" - "ld r24, Y+" "\n\t" - "rcall bch4369" "\n\t" - "subi r22, 1" "\n\t" - "brne 1b" "\n\t" - "mov r28, r18" "\n\t" - "ret" "\n" - ); -} - -#endif diff --git a/src/bch4369.h b/src/bch4369.h deleted file mode 100644 index e213d75..0000000 --- a/src/bch4369.h +++ /dev/null @@ -1,24 +0,0 @@ - -#include -#include -extern uint8_t bch_parity[16]; -void bch4369(uint8_t d); -static inline void bch4369_init() { memset(bch_parity, 0 , 16); } -void bch4369_str(const uint8_t *b, uint8_t n); - -static inline -uint8_t *bch4369_stri(uint8_t *b, uint8_t n) -{ - __asm__ volatile( - "1:" "\n\t" - "ld r24, Y+" "\n\t" - "rcall bch4369" "\n\t" - "subi %[N], 1" "\n\t" - "brne 1b" "\n" - : [N] "+r" (n), [B] "+y" (b) - :: "r0", - "r20", "r21", "r24", "r25", - "r26", "r27", "r30", "r31" - ); - return b; -} diff --git a/src/cmd.c b/src/cmd.c index e3be56e..64d2c3b 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -58,14 +58,13 @@ void base85_send_buffer(const uint8_t *buf) "rjmp _send_str26" "\n" ); } - #endif static inline const uint8_t *base85_fill_buffer(const uint8_t *s) { base85_error = 0; - for (int i=0; !base85_error && iccp) - NVMCTRL.CTRLA = NVMCTRL_CMD_PAGEBUFCLR_gc; - _memcopy(a, p->data, n); - if (p->ccp && !(0x8000 & (uint16_t)a)) + uint8_t ccp = p->ccp; + if (ccp) __asm__( - "out %[ccp], %[key] \n\t" + "out __CCP__, %[key] \n\t" "sts %[ctrla], %[cmd] \n" - :: [ccp] "n" (&CCP), + :: [ctrla] "n" (&NVMCTRL.CTRLA), - [key] "r" (p->ccp), + [key] "r" (ccp), + [cmd] "r" (NVMCTRL_CMD_PAGEBUFCLR_gc) + : "memory" + ); + _memcopy(a, p->data, n); + if (ccp && !(0x8000 & (uint16_t)a)) + __asm__( + "out __CCP__, %[key] \n\t" + "sts %[ctrla], %[cmd] \n" + :: + [ctrla] "n" (&NVMCTRL.CTRLA), + [key] "r" (ccp), [cmd] "r" (NVMCTRL_CMD_PAGEERASEWRITE_gc) - : "memory", "r0" + : "memory" ); } else @@ -133,13 +141,13 @@ uint8_t cmd_flag(uint8_t f) "ld r22, Z+" "\n\t" "cp r22, r24" "\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" "sts cmd_flags, r30" "\n\t" "sts cmd_flags+1, r31" "\n\t" - "rcall _send_char22" "\n" - "9:" "\n\t" - "ret" "\n" + "rjmp _send_char22" "\n" ); } #endif @@ -162,7 +170,7 @@ void parse_command(const uint8_t *s, uint8_t n) if (bflg <= 5) { bptr = flash_buffer + 16*bflg; bflg = 1<= N_ADC) { - if (cmd_flag('<')) - base85_send_buffer((void*)adc_readings); - if (cmd_flag('!')) - start_adc(); + if (cmd_flag('!')) + start_adc(); + if (cmd_flag('<')) { + bptr = (void*)adc_readings; + goto send_buffer; } break; case 'B': @@ -199,34 +207,43 @@ void parse_command(const uint8_t *s, uint8_t n) r = pipe.valid; if (have_b) { if (cmd_flag('!') || ~r & bflg) { - pipe.valid |= bflg; memcpy(bptr, cmd_buffer, 16); + r = pipe.valid |= bflg; } else goto error; } if (cmd_flag('%')) { if (cmd_flag('@')) - memset(bch_parity, 0, 16); + bch4369_init(config.bch_salt); bch4369_str(bptr, 16); if (cmd_flag('!')) { - memcpy(flash_buffer+64, cmd_buffer, 16); - pipe.valid |= 0x10; + bch4369_fini(); + memcpy(flash_buffer+64, bch_parity, 16); + r = pipe.valid |= 0x10; } } if (cmd_flag('<')) { - if (!cmd_flag('!') && ~r & bflg) + if (cmd_flag('!')) goto send_buffer; + if (~r & bflg) goto error; pipe.valid &=~ bflg; goto send_buffer; } break; + case 'D': + flash_find_free(); + bptr = (void*)&fs; + goto send_buffer; case 'F': if (have_b) r = flash_submit_command(cmd_buffer); else - r = flash_poll(cmd_flag('!')); + r = spi_busy_p(); + if (cmd_flag('<')) + goto send_buffer; break; +#ifndef HALLO case 'P': if (have_b) pipe_config((void*)cmd_buffer); @@ -246,11 +263,13 @@ void parse_command(const uint8_t *s, uint8_t n) fpga_cmd((void*)cmd_buffer); goto send_buffer; #endif +#endif // HALLO case 'M': if (!have_b) goto error; r = poke((void*)cmd_buffer, cmd_flag('!')); send_buffer: + send_char(' '); base85_send_buffer(bptr); break; default: diff --git a/src/config.c b/src/config.c index 740907d..25ee61e 100644 --- a/src/config.c +++ b/src/config.c @@ -13,12 +13,13 @@ const struct config config = { .version = VERSION, .cpu_clk = CLKCTRL_PDIV_2X_gc | 1, // 10MHz (max @ 3V) .flash_page_size = FM_528 >> 8, + .bch_salt = 1, .burn_page = 0x88, // Buffer 1 Page Program w/o Erase - .write_buffer = 0x84 | FM_WRITE>>8, // Buffer 1 Write - .read_array = 0x03 | FM_READ>>8, // Continuous Array Read (Low-Frequency) + .write_buffer = 0x84 | FM_WRITE, // Buffer 1 Write + .read_array = 0x03 | FM_READ, // Continuous Array Read (Low-Frequency) .read_buffer = { - [0] = 0xd1 | FM_READ>>8, // Buffer 1 Read (Low-Frequency) - [1] = 0xd3 | FM_READ>>8, // Buffer 2 Read (Low-Frequency) + [0] = 0xd1 | FM_READ, // Buffer 1 Read (Low-Frequency) + [1] = 0xd3 | FM_READ, // Buffer 2 Read (Low-Frequency) }, .page_start = 0x0800, .page_end = 0x1000, diff --git a/src/config.h b/src/config.h index 155a483..39d346d 100644 --- a/src/config.h +++ b/src/config.h @@ -12,8 +12,8 @@ struct config { uint8_t cpu_clk; uint8_t cron; uint8_t flash_page_size; + uint8_t bch_salt; uint16_t burn_page; - uint16_t erase_page; uint16_t write_buffer; uint16_t read_array; uint16_t read_buffer[2]; @@ -28,7 +28,7 @@ struct config { enum magic_flags { #ifdef HAVE_nFETs MAGIC = 0xD0, - VERSION = 0x01, + VERSION = 0x00, #endif #ifdef HAVE_FPGA MAGIC = 0xC5, @@ -131,9 +131,9 @@ void apply_config() "ldi r30, lo8(ee9_start)" "\n\t" "ldi r31, hi8(ee9_start)" "\n\t" "ldi r24, lo8(ee9_size)" "\n\t" - "clr r26" "\n" + "clr r25" "\n" "1:" "\n\t" - "mov r27, r26" "\n\t" + "mov r27, r25" "\n\t" "subi r24, 2" "\n\t" "brcs 3f" "\n" "2:" "\n\t" diff --git a/src/dose.py b/src/dose.py new file mode 100755 index 0000000..f625a9c --- /dev/null +++ b/src/dose.py @@ -0,0 +1,370 @@ +#! /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 +import flash as flash_cmd +flash_cmd = flash_cmd.flash_cmd() +sys.path[1:1] = ["./bch4369"] +from bch4369 import bch + +options, files = getopt.gnu_getopt(sys.argv[1:], "F:o:M:", ["debug", "tty=", "output=", "map=", "galois"]) + +tty = None +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 o == "--galois": + bch.load_galois() + +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, s=s, d=d, ccp=ccp) + + def peek(self, a=None, s=None, d=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 isinstance(a, str): + print(f"PEEK: unknown addr {a}", file=sys.stderr) + for k in mmap.keys(): + if a in k: + print(f"PEEK: in RAM we have {k}", file=sys.stderr) + for k in SFR.keys(): + if a in k: + print(f"PEEK: IO SFR we have {k}", file=sys.stderr) + raise ValueError(a) + 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(">4 + if (b&3) == 0: + if b==28: + s = 80 + else: + s = 64 + self.flash(op, byte=i, size=s) + self.wait_for_spi() + d += self.cmd(f"B{b&3} 0: + f.write(self.read_flash(page)) + page += 1 + n -= 1 + + def flash_status(self, blocking=False): + r = (0,0,bytes(2)) + while not r[2][0] & 0x80: + self.flash("Status", what="cmdbuf") + r = self.cmd("F<") + while r[1]: + r = self.cmd("F<") + if not blocking: + break + return tuple(r[2][:2]) + + def write_flash(self, page, d): + print(f"FLASH: writing to {page=}") + self.write2fbuffer(d) + self.flash("Program2", page=page) + self.flash_status(True) + + def write_file2flash(self, page, fn): + n = 0 + with open(fn, "rb") as f: + while True: + b =f.read(512) + if not b: + break + if len(b)<512: + b += bytes(512-len(b)) + self.write_flash(page+n, b) + n += 1 + return n + + def erase_flash_sector(self, page, op="EraseSector"): + """ + op="EraseSector" (default) + page=0: pages 0 … 7 + page=8: pages 8 … 0xff + page=0x100: pages 0x100 … 0x1ff + … + op="ErasePage", page=n + op="EraseBlock", page=n [n&~7 … n|7] + op="EraseChip" + """ + self.flash(op, page=page) + self.flash_status(True) + + def flash_power(self, on=True): + op = "PowerUp" if on else "PowerDown" + self.flash(op) + + def flash_Id(self): + self.flash("Id", what="cmdbuf") + while True: + r = self.cmd("F<") + if not r[1]: + break + i = r[2][:5] + print(f"FLASH chip {b2hex(i)}", file=sys.stderr) + return i + + def memsetfbuffer(self, byte=0, what=0xff, size=528, op=0x0887): + for i in range(byte, byte+size, 255): + s = byte+size - i + if s > 255: + s = 255 + self.flash(op, size=s, what=what, byte=i) + self.wait_for_spi() + +if tty: + tty = dose_cmd(tty, baud) + tty._export(globals()) + tty._verbose = False + +uart.set_prompt("TurboD") + +def b2hex(b, sep=" "): + return sep.join([f"{x:02x}" for x in b]) + diff --git a/src/flash.c b/src/flash.c index c2958e6..2739ce0 100644 --- a/src/flash.c +++ b/src/flash.c @@ -130,7 +130,7 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte) spi_start_cmd(csize, flash_cmd_buffer); return 0; } - if (size >= 128) { + if (size > 80) { // for read of the security register pads += size-64; size = 64; @@ -253,11 +253,13 @@ uint8_t flash_burn_page() uint8_t flash_poll(uint8_t rr) { uint8_t r = fs.status; + if (spi_busy_p()) + return r; if ((r & FS_Error) == FS_Error) return r; if (r & FS_StBsy) { // status bytes arrived - if (flash_status_bytes[0] & 0x80) + if (~flash_status_bytes[0] & 0x80) // flash is still busy burning goto rd_status; // not busy any more, move Bsy → Rdy @@ -288,8 +290,6 @@ ready: if (rr) r |= FS_Ack; fs.status = r; - if (spi_busy_p()) - return r; if (r & FS_Dir == FS_Write && fs.block == 8) flash_burn_page(); else if (!flash_stream_done()) { @@ -324,7 +324,7 @@ static inline uint8_t flash_memset_buffer2() { for (uint16_t i=0; i<528; i += 176) { - uint8_t r = flash_cmd((uint16_t)config.flash_page_size << 8 | 0xff87, 176, 0, i); + uint8_t r = flash_cmd((uint16_t)config.flash_page_size << 8 | 0x87, 176|0xff00, 0, i); if (r) return r; while (spi_busy_p()) ; @@ -355,9 +355,10 @@ uint16_t flash_find_free() while (e > a) { uint16_t p = (a+e)>>1; if (flash_compare_buffer2(p)) - a = p; + a = p+1; else e = p; } + fs.free = a; return a; } diff --git a/src/flash.h b/src/flash.h index 8ce5e61..c509eee 100644 --- a/src/flash.h +++ b/src/flash.h @@ -33,6 +33,7 @@ uint16_t flash_find_free(); extern struct flash_stream { + uint16_t free; // first free page uint16_t page; // page address of buffer number uint16_t npages; // more pages to read uint8_t block; // next block to read 0…9 diff --git a/src/flash.py b/src/flash.py new file mode 100644 index 0000000..c5e5cf3 --- /dev/null +++ b/src/flash.py @@ -0,0 +1,113 @@ + +import struct + +class flash_cmd: + + class Flash_Error(IOError): + pass + + M = { + 0: 0x0000, + 1: 0x0100, + 2: 0x0200, + 4: 0x0300, + 512: 0x0400, + 528: 0x0800, + "addr": 0x0c00, + "secure": 0x0c00, + "write": 0x1000, + "read": 0x2000, + "wait": 0x3000, + "start": 0x3000, + } + + def __init__(self, pagesize=528): + self.set_pagesize(pagesize) + + def set_pagesize(self, pagesize): + self.pagesize = pagesize + M = self.M + A = M[pagesize] + self.A = A + self.OP = { + "ReadPage": (0xd2 | A | M["read"] | M[4],), + "ReadLPower": (0x01 | A | M["read"] | M[0],), + "Read": (0x03 | A | M["read"] | M[0],), + "ReadHFreq1": (0x0b | A | M["read"] | M[1],), + "ReadHFreq2": (0x1b | A | M["read"] | M[2],), + "ReadLegacy": (0xe8 | A | M["read"] | M[4],), + "ReadBuffer1": (0xd1 | A | M["read"] | M[0],), + "ReadBuffer2": (0xd3 | A | M["read"] | M[0],), + "ReadBufHF1": (0xd4 | A | M["read"] | M[1],), + "ReadBufHF2": (0xd6 | A | M["read"] | M[1],), + "WriteBuffer1": (0x84 | A | M["write"],), + "WriteBuffer2": (0x87 | A | M["write"],), + "ProgErase1": (0x83 | A,), + "ProgErase2": (0x86 | A,), + "Program1": (0x88 | A,), + "Program2": (0x89 | A,), + "Transfer1": (0x53 | A,), + "Transfer2": (0x55 | A,), + "Compare1": (0x60 | A,), + "Compare2": (0x61 | A,), + "ErasePage": (0x81 | A,), + "EraseBlock": (0x50 | A,), + "EraseSector": (0x7c | A,), + "EraseChip": (0xc7 | M["secure"], 0x9a8094), + "Status": (0xd7 | M["read"], 2), + "PowerDown": (0xb9,), + "PowerUp": (0xab,), + "Id": (0x9f | M["read"], 5), + "PageSize512": (0x3d | M["secure"], 0xa6802a), + "PageSize528": (0x3d | M["secure"], 0xa7802a), + "Reset": (0xf0 | M["secure"], 0x0), + } + + WHAT = { + "buffer": 0, + "cmdbuf": 96, + "cmd": 96+8, + "status": 128, + } + + def cmd_buffer(self, op, mode=0, size=None, page=0, byte=0, what=0, data=None): + if op in self.OP: + opp = self.OP[op] + op = opp[0] + if len(opp) > 1: + if (op & self.M["addr"]) == self.M["secure"]: + page = opp[1] >> 16 + byte = opp[1] & 0xffff; + elif op & self.M["read"] and size is None: + size = opp[1] + if mode: + op = op & 0xff | mode & 0xff00 + if what in self.WHAT: + what = self.WHAT[what] + if size is None: + size = 0 + if op & self.M["start"]: + if what >=112: + size = 2 + elif what >= 96: + size = 112 - what + elif what < 80: + if byte == 448 and self.pagesize == 528: + size = 80 + else: + size = 64 + if size + byte > self.pagesize: + size = self.pagesize - byte + if what+size > 80: + size = 80 - what + elif data is not None and not what and size <= 8: + what = self.WHAT["cmd"] + if data is None: + data = 0 + size |= what << 8; + if self.verbose: + from sys import stderr + print("Flash cmd", *map(hex,(op, size, page, byte, data)), file=stderr) + return struct.pack("<4HQ", op, size, page, byte, data) + + verbose = False diff --git a/src/hallo.c b/src/hallo.c new file mode 100644 index 0000000..c2baa0b --- /dev/null +++ b/src/hallo.c @@ -0,0 +1,48 @@ +// +// hallo.c +// + +// int = int8_t + +#include +#include + +#include +#include + +#include "config.h" +#include "uart.h" +#include "pipe.h" + +//////////////////////////////////////////////////////////////////////////////// +// +// main() + +section_status(pipe) struct pipe pipe; +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(); + } +} diff --git a/src/io.S b/src/io.S new file mode 100644 index 0000000..cf51b78 --- /dev/null +++ b/src/io.S @@ -0,0 +1 @@ +#include diff --git a/src/iotn424.py b/src/iotn424.py new file mode 100644 index 0000000..f62cb93 --- /dev/null +++ b/src/iotn424.py @@ -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), +} diff --git a/src/map.py b/src/map.py new file mode 100644 index 0000000..d19a4c2 --- /dev/null +++ b/src/map.py @@ -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) diff --git a/src/prompt.py b/src/prompt.py new file mode 100644 index 0000000..f6573c6 --- /dev/null +++ b/src/prompt.py @@ -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 diff --git a/src/rtc.c b/src/rtc.c index 0d04c75..ee3486a 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -25,7 +25,7 @@ uint8_t rtc_cnt_tick() struct_ioconf(rtc_config) = { 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.PITINTCTRL, 1), 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" "sts %[flag], r24" "\n\t" "sts pit_tick, r24" "\n\t" - "ldi r24, " "\n\t" - "sts %[flag], r24" "\n\t" + "pop r24" "\n\t" "reti" "\n" ::[flag] "n" (&RTC.PITINTFLAGS) ); @@ -66,11 +65,11 @@ ISR(RTC_CNT_vect, ISR_NAKED) "push r26" "\n\t" "lds r24, %[CMPL]" "\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" "sts %[CMPL], r24" "\n\t" - "lds r26, config+5" "\n\t" - "add r25, r26" "\n\t" + "lds r26, rtc_config+5" "\n\t" + "adc r25, r26" "\n\t" "sts %[CMPH], r25" "\n\t" "pop r26" "\n\t" "pop r25" "\n\t" diff --git a/src/spi.c b/src/spi.c index e7dc365..b1425ac 100644 --- a/src/spi.c +++ b/src/spi.c @@ -90,8 +90,6 @@ ISR(SPI0_INT_vect, ISR_NAKED) "push r30" "\n\t" "push r31" "\n\t" "lds r24, %[IFLGS]" "\n\t" - - "3:" "\n\t" "sbrs r24, %[DRE]" "\n\t" "rjmp 3f" "\n" @@ -136,6 +134,7 @@ ISR(SPI0_INT_vect, ISR_NAKED) "1:" "\n\t" "sts %[ICTRL], r26" "\n\t" "lds r24, %[IFLGS]" "\n" + "3:" "\n\t" "sbrs r24, %[RXC]" "\n\t" "rjmp 3f" "\n\t" "lds r25, %[DATA]" "\n\t" @@ -217,7 +216,7 @@ ISR(SPI0_INT_vect, ISR_NAKED) [AIFLGS] "n" (SPI_TXCIF_bm | SPI_RXCIF_bm | SPI_DREIF_bm), [ICTRL] "n" (&SPI.INTCTRL), [DATA] "n" (&SPI.DATA), - [SPORT] "n" (_SFR_IO_ADDR(SSEL_VPORT)), + [SPORT] "n" (_SFR_IO_ADDR(SSEL_VPORT.OUT)), [SSEL] "n" (SSEL_PIN) ); } diff --git a/src/spi.h b/src/spi.h index 79d7478..e1e01cc 100644 --- a/src/spi.h +++ b/src/spi.h @@ -46,14 +46,13 @@ uint8_t spi_abort() static inline uint8_t spi_busy_p() { - return SPI.INTFLAGS & SPI_TXCIF_bm; + return SPI.INTCTRL & SPI_TXCIF_bm; } static inline void spi_start() { - SPI.INTCTRL = SPI_DREIF_bm; - // the ISR will immediately set SPI_TXCIF_bm. + SPI.INTCTRL = SPI_DREIF_bm | SPI_TXCIF_bm| SPI_RXCIF_bm; } static inline void barrier() { __asm__("":::"memory"); } diff --git a/src/uart.c b/src/uart.c index 0772547..0ac11c9 100644 --- a/src/uart.c +++ b/src/uart.c @@ -10,10 +10,10 @@ struct_ioconf(uart_config) = { conf_prefix(USART0), - conf_iow(USART0.BAUD, UART_BAUD), - conf_io(USART0.CTRLB, UART_MODE & 0xff), - conf_io(USART0.CTRLC, UART_MODE >> 8), - conf_io(USART0.CTRLA,USART_RXCIE_bm), + conf_iow(USART0.BAUD, 40000000/115200), // 115200 baud + conf_io(USART0.CTRLC, USART_CHSIZE_8BIT_gc), + conf_io(USART0.CTRLB, USART_TXEN_bm | USART_RXEN_bm), + conf_io(USART0.CTRLA, USART_RXCIE_bm), }; // `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" " lds r24, %[DH] \n" " lds r30, uart_rx_s \n" - " and r24, r30 \n" + " or r24, r30 \n" " sts uart_rx_s, r24 \n" " lds r24, %[DL] \n" " lds r30, uart_rx_w \n" diff --git a/src/uart.h b/src/uart.h index cf1b6aa..6438874 100644 --- a/src/uart.h +++ b/src/uart.h @@ -4,9 +4,6 @@ #include "config.h" -#define UART_MODE 0x03c0 -#define UART_BAUD 5555 // 115200 baud - void init_uart(uint16_t mode, uint16_t div); void send_char(uint8_t c); diff --git a/src/uart.py b/src/uart.py new file mode 100755 index 0000000..e8bdba3 --- /dev/null +++ b/src/uart.py @@ -0,0 +1,132 @@ +#! /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) + + def _export(self, scope=None, prefix=""): + """usage: ..._export(globals()) + return a dict with all names in self that + do not begin with an '_' + and are not all uppercase. + The scope is updated with the dict. + """ + r = { + prefix+k: getattr(self, k) + for k in dir(self) + if k.upper() != k + and k[0] != '_' + } + if scope: + scope.update(r) + return r + +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]) + tty = uart(port, baud) + tty._export(globals()) + set_prompt(tty.portname) diff --git a/src/uart_tx.S b/src/uart_tx.S index 8ae5c60..45b3a8c 100644 --- a/src/uart_tx.S +++ b/src/uart_tx.S @@ -14,6 +14,7 @@ .global _send_str26 .global uart_busy .global send_hex + .global send_eol .global command // `tx()` and `put_char()` do not gobble r18, r20, r21, r22, r24, r26, and r27. @@ -101,7 +102,7 @@ send_hex: ld r24, X+ rcall send_hex_byte subi r18, 1 - brcc 1b + brne 1b 9: ret #endif