Compare commits

...

10 commits

Author SHA1 Message Date
Stephan I. Böttcher
18f6ba9c2f replace BOM with _dose version 2026-06-09 10:59:12 +02:00
Stephan I. Böttcher
cce9ded5a2 bch commits 2026-03-04 15:39:22 +01:00
Stephan I. Böttcher
8a56b61f79 uart: hide _reader() 2026-03-04 15:31:41 +01:00
Stephan I. Böttcher
e5af295232 flash debugging, no known issues left 2026-02-09 09:04:35 +01:00
Stephan I. Böttcher
2aab85975a flash fixes 2026-02-06 11:05:48 +01:00
Stephan I. Böttcher
13407292dd hallo: add flash 2026-02-04 21:41:19 +01:00
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
32 changed files with 1546 additions and 308 deletions

3
.gitignore vendored
View file

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

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "src/bch4369"]
path = src/bch4369
url = git@codeberg.org:SiB64/bch4369

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before After
Before After

View file

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

View file

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

View file

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

View file

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

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,69 +1,94 @@
; 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
;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
;; ! C-ABI: 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
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
@ -76,10 +101,8 @@ 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
@ -90,6 +113,8 @@ base85_encode:
mul85:
#endif
;; TODO for SPACE: inline this
;; big endian r22/r23/r24/r25 *= 85; … += r20
_mul85:
ldi r21, 85
mul r25, r21
@ -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

1
src/bch4369 Submodule

@ -0,0 +1 @@
Subproject commit eebd4bb43039a2ecf63aa7c2fdbe1c4edf469393

View file

@ -1,114 +0,0 @@
/*********************************************************************
galois.BCH(4369, 4369-128, extension_field=galois.GF(2**16))
<BCH Code: [4369, 4241, 17] over GF(2)>
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

View file

@ -1,24 +0,0 @@
#include <stdint.h>
#include <string.h>
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;
}

View file

@ -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 && i<FB_SIZE; i+=4)
for (int i=0; !base85_error && i<16; i+=4)
s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
return s;
}
@ -90,18 +89,27 @@ uint8_t poke(struct peak_poke *p, uint8_t poke)
if (!n)
return 0;
if (poke) {
if (p->ccp)
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<<bflg;
s++;
send_char(*s++);
}
else
bflg = 0;
@ -173,24 +181,24 @@ void parse_command(const uint8_t *s, uint8_t n)
if (*s==' ') {
cmd_pending = 0;
s = base85_fill_buffer(s+1);
if (base85_error) {
r = base85_error;
if (r)
goto error;
}
have_b = 1;
cmd_pending = cmd;
} else if (cmd_flag('~'))
}
else if (cmd_flag('='))
have_b = cmd_pending == cmd;
if (*s != '\n')
goto error;
switch(cmd) {
case 'A':
r = adc_current;
if (r >= N_ADC) {
if (cmd_flag('<'))
base85_send_buffer((void*)adc_readings);
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:

View file

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

View file

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

370
src/dose.py Executable file
View file

@ -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("<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:
aa,ss,cc = struct.unpack("<HBB", dd[:4])
print(f"PEEK: {aa-nn:04x}[{nn}+{ss}]: {b2hex(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
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
def flash(self, op=None, abort=False, buf=False, **aa):
if op is None:
c = "F"
if abort:
c = "F!"
if buf:
c += "<"
return self.cmd(c)
r = self.cmd("F", flash_cmd.cmd_buffer(op, **aa))
if r[1]:
raise flash_cmd.Flash_Error(op)
return r
def write2fbuffer(self, d, op="WriteBuffer2"):
for i in range(0, 512, 16):
b = i>>4
if not b:
c = "B0@%@"
elif not (b&3):
c = "B0@%"
elif b==31:
c = "B3%!"
else:
c = f"B{b&3}%"
self.cmd(c, d=d[i:i+16])
if (b&3) == 3:
if b==31:
s = 80
else:
s = 64
self.flash(op, byte=i & 0x1c0, size=s)[1]
self.wait_for_spi()
def wait_for_spi(self):
while True:
r = self.cmd("F")[1]
if not r:
break
print(f"SPI busy {r:02x}", file=sys.stderr)
def readfbuffer(self, op="ReadBuffer2"):
d = b''
for i in range(0, 512, 16):
b = i>>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}<!")[2]
d += self.cmd(f"B4<!")[2]
self._last_page = d
if min(d) == 255:
print(f"FLASH: page is erased")
elif bch.check_page(d):
if not bch.galois:
raise bch.BCHError("galois module not loaded for Parity Error correction")
d = bch.fix_page(d)
return d[:512]
def read_flash(self, page):
print(f"FLASH: reading from {page=}")
self.flash("Transfer2", page=page)
self.flash_status(True)
return self.readfbuffer()
def read_flash2file(self, fn, page, n):
with open(fn, "wb") as f:
while n > 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])

View file

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

View file

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

113
src/flash.py Normal file
View file

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

48
src/hallo.c Normal file
View file

@ -0,0 +1,48 @@
//
// 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 "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();
}
}

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) = {
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"

View file

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

View file

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

View file

@ -10,9 +10,9 @@
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_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),
};
@ -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"

View file

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

132
src/uart.py Executable file
View file

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

View file

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