mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-05-01 15:14:22 +02:00
Compare commits
4 commits
0fa9cdbc14
...
873a2ba93a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
873a2ba93a | ||
|
|
6fcdb271d3 | ||
|
|
302b6bb8d7 | ||
|
|
d1e6a031ab |
21 changed files with 1190 additions and 125 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -25,3 +25,5 @@ src/data
|
||||||
BCH-Codes/
|
BCH-Codes/
|
||||||
*.odt
|
*.odt
|
||||||
*.userrow
|
*.userrow
|
||||||
|
*.m
|
||||||
|
src/data
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 31 KiB |
15
src/Makefile
15
src/Makefile
|
|
@ -6,8 +6,15 @@ PATH:=/usr/local/bin:$(PATH)
|
||||||
default: all
|
default: all
|
||||||
all: $(PROJ).hex $(PROJ)_all
|
all: $(PROJ).hex $(PROJ)_all
|
||||||
|
|
||||||
dose_all: dose.eeprom dose.userrow
|
|
||||||
|
|
||||||
|
hallo_all: hallo.eeprom
|
||||||
|
CFLAGS_hallo = -DHAVE_nFETs -DSEND_HEX -DHALLO
|
||||||
|
MCU_hallo = attiny424
|
||||||
|
SN_hallo = 1
|
||||||
|
C_FILES_hallo = config.c uart.c cmd.c base85.c rtc.c adc.c pwm.c
|
||||||
|
S_FILES_hallo = uart_tx.S base85a.S
|
||||||
|
|
||||||
|
dose_all: dose.eeprom dose.userrow
|
||||||
SN_dose = 1
|
SN_dose = 1
|
||||||
MCU_dose = $(MCU_$(VAR))
|
MCU_dose = $(MCU_$(VAR))
|
||||||
MCU_nFETs = attiny424
|
MCU_nFETs = attiny424
|
||||||
|
|
@ -48,6 +55,9 @@ OBJS = $(patsubst %.c, %.o, $(C_FILES)) $(patsubst %.S, %.o, $(S_FILES))
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) $(CFLAGS) -c $<
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
%.m: %.S
|
||||||
|
$(CC) $(CFLAGS) -E -dM $< > $@
|
||||||
|
|
||||||
-include *.d
|
-include *.d
|
||||||
|
|
||||||
LDFLAGS = -Teeprom.ld
|
LDFLAGS = -Teeprom.ld
|
||||||
|
|
@ -97,6 +107,7 @@ AVRDUDE_PORT = /dev/ttyUSB1
|
||||||
AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||||
|
|
||||||
sig_dose = 0x1e 0x92 0x2c
|
sig_dose = 0x1e 0x92 0x2c
|
||||||
|
sig_hallo = 0x1e 0x92 0x2c
|
||||||
|
|
||||||
id: $(PROJ).id
|
id: $(PROJ).id
|
||||||
%.id:
|
%.id:
|
||||||
|
|
@ -132,3 +143,5 @@ eeprom.eeprom:
|
||||||
%.eeprom.burn: %.eeprom
|
%.eeprom.burn: %.eeprom
|
||||||
$(AD) -U eeprom:v:$< || $(AD) -U eeprom:w:$<
|
$(AD) -U eeprom:v:$< || $(AD) -U eeprom:w:$<
|
||||||
|
|
||||||
|
%.userrow.burn: %.userrow
|
||||||
|
$(AD) -U userrow:v:$< || $(AD) -U userrow:w:$<
|
||||||
|
|
|
||||||
35
src/adc.c
35
src/adc.c
|
|
@ -8,12 +8,18 @@
|
||||||
#include "pwm.h"
|
#include "pwm.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
|
|
||||||
|
#ifdef ADC_IMMEDIATE
|
||||||
|
# define ADC_TRIGGER ADC_MODE_BURST_SCALING_gc | ADC_START_IMMEDIATE_gc
|
||||||
|
#else
|
||||||
|
# define ADC_TRIGGER ADC_MODE_SERIES_SCALING_gc | ADC_START_EVENT_TRIGGER_gc
|
||||||
|
#endif
|
||||||
|
|
||||||
enum adc_conf_parameter {
|
enum adc_conf_parameter {
|
||||||
INP = ADC_VIA_ADC_gc,
|
INP = ADC_VIA_ADC_gc,
|
||||||
INN = ADC_VIA_ADC_gc,
|
INN = ADC_VIA_ADC_gc,
|
||||||
REF = 10 << ADC_TIMEBASE_gp,
|
REF = 10 << ADC_TIMEBASE_gp,
|
||||||
MODE = ADC_MODE_SERIES_SCALING_gc | ADC_START_EVENT_TRIGGER_gc,
|
MODE = ADC_TRIGGER,
|
||||||
MODE_DIFF = ADC_MODE_BURST_SCALING_gc | ADC_START_IMMEDIATE_gc | ADC_DIFF_bm,
|
MODE_DIFF = ADC_TRIGGER | ADC_DIFF_bm,
|
||||||
};
|
};
|
||||||
|
|
||||||
__attribute__((section(".eeprom1")))
|
__attribute__((section(".eeprom1")))
|
||||||
|
|
@ -81,7 +87,7 @@ struct_ioconf(adc_config) = {
|
||||||
conf_prefix(ADC),
|
conf_prefix(ADC),
|
||||||
conf_io(ADC.CTRLA, ADC_ENABLE_bm),
|
conf_io(ADC.CTRLA, ADC_ENABLE_bm),
|
||||||
conf_io(ADC.CTRLB, ADC_PRESC_DIV10_gc),
|
conf_io(ADC.CTRLB, ADC_PRESC_DIV10_gc),
|
||||||
conf_io(ADC.CTRLE, 250 << ADC_SAMPDUR_gp),
|
conf_io(ADC.CTRLE, 250),
|
||||||
conf_io(ADC.CTRLF, ADC_SAMPNUM_ACC256_gc | ADC_LEFTADJ_bm),
|
conf_io(ADC.CTRLF, ADC_SAMPNUM_ACC256_gc | ADC_LEFTADJ_bm),
|
||||||
conf_io(ADC.INTCTRL, ADC_RESRDY_bm),
|
conf_io(ADC.INTCTRL, ADC_RESRDY_bm),
|
||||||
conf_prefix(EVSYS),
|
conf_prefix(EVSYS),
|
||||||
|
|
@ -91,8 +97,6 @@ struct_ioconf(adc_config) = {
|
||||||
|
|
||||||
void start_adc()
|
void start_adc()
|
||||||
{
|
{
|
||||||
if (!adc_conf->mode)
|
|
||||||
return;
|
|
||||||
ADC.COMMAND = 0;
|
ADC.COMMAND = 0;
|
||||||
adc_current = 0;
|
adc_current = 0;
|
||||||
start_conversion(adc_conf);
|
start_conversion(adc_conf);
|
||||||
|
|
@ -114,7 +118,7 @@ ISR(ADC0_RESRDY_vect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop:
|
stop:
|
||||||
ADC.CTRLA = 0;
|
ADC.COMMAND = 0;
|
||||||
adc_current = N_ADC;
|
adc_current = N_ADC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +140,7 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
||||||
"push r31" "\n\t"
|
"push r31" "\n\t"
|
||||||
"lds r24, adc_current" "\n\t"
|
"lds r24, adc_current" "\n\t"
|
||||||
"cpi r24, %[NADC]" "\n\t"
|
"cpi r24, %[NADC]" "\n\t"
|
||||||
"brcc 3f" "\n\t"
|
"brcc 2f" "\n\t"
|
||||||
"mov r30, r24" "\n\t"
|
"mov r30, r24" "\n\t"
|
||||||
"ldi r31, 0" "\n\t"
|
"ldi r31, 0" "\n\t"
|
||||||
"lsl r30" "\n\t"
|
"lsl r30" "\n\t"
|
||||||
|
|
@ -148,7 +152,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
||||||
"std Z+1, r25" "\n"
|
"std Z+1, r25" "\n"
|
||||||
"1:" "\n\t"
|
"1:" "\n\t"
|
||||||
"subi r24, -1" "\n\t"
|
"subi r24, -1" "\n\t"
|
||||||
"cpi r24, %[NADC]" "\n\t"
|
"cpi r24, %[NADC]" "\n"
|
||||||
|
"2:" "\n\t"
|
||||||
|
"clr r25" "\n\t"
|
||||||
"brcc 3f" "\n\t"
|
"brcc 3f" "\n\t"
|
||||||
"mov r30, r24" "\n\t"
|
"mov r30, r24" "\n\t"
|
||||||
"ldi r31, 0" "\n\t"
|
"ldi r31, 0" "\n\t"
|
||||||
|
|
@ -164,9 +170,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
||||||
"sts %[MUXPOS], r25" "\n\t"
|
"sts %[MUXPOS], r25" "\n\t"
|
||||||
"ld r25, Z" "\n\t"
|
"ld r25, Z" "\n\t"
|
||||||
"tst r25" "\n\t"
|
"tst r25" "\n\t"
|
||||||
"breq 1b" "\n\t"
|
"breq 1b" "\n"
|
||||||
"sts %[COMMAND], r25" "\n"
|
"3:" "\n\t"
|
||||||
"2:" "\n\t"
|
"sts %[COMMAND], r25" "\n\t"
|
||||||
"sts adc_current, r24" "\n\t"
|
"sts adc_current, r24" "\n\t"
|
||||||
"pop r31" "\n\t"
|
"pop r31" "\n\t"
|
||||||
"pop r30" "\n\t"
|
"pop r30" "\n\t"
|
||||||
|
|
@ -175,16 +181,9 @@ ISR(ADC0_RESRDY_vect, ISR_NAKED)
|
||||||
"out __SREG__, r24" "\n\t"
|
"out __SREG__, r24" "\n\t"
|
||||||
"pop r24" "\n\t"
|
"pop r24" "\n\t"
|
||||||
"reti" "\n"
|
"reti" "\n"
|
||||||
"3:" "\n\t"
|
|
||||||
"clr r24" "\n\t"
|
|
||||||
"sts %[COMMAND], r24" "\n\t"
|
|
||||||
"sts %[CTRLA], r24" "\n\t"
|
|
||||||
"ldi r24, %[NADC]" "\n\t"
|
|
||||||
"rjmp 2b" "\n"
|
|
||||||
: :
|
: :
|
||||||
[NADC] "n" (N_ADC),
|
[NADC] "n" (N_ADC),
|
||||||
[RESULT] "n" (&ADC.RESULT),
|
[RESULT] "n" (&ADC.RESULT),
|
||||||
[CTRLA] "n" (&ADC.CTRLA),
|
|
||||||
[CTRLC] "n" (&ADC.CTRLC),
|
[CTRLC] "n" (&ADC.CTRLC),
|
||||||
[MUXPOS] "n" (&ADC.MUXPOS),
|
[MUXPOS] "n" (&ADC.MUXPOS),
|
||||||
[MUXNEG] "n" (&ADC.MUXNEG),
|
[MUXNEG] "n" (&ADC.MUXNEG),
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ int base85_encode(uint32_t u, uint8_t *s)
|
||||||
{
|
{
|
||||||
s += 5;
|
s += 5;
|
||||||
*s = 0;
|
*s = 0;
|
||||||
u = divmod85(u, s);
|
u = divmod85(u, --s);
|
||||||
u = divmod85(u, s);
|
u = divmod85(u, --s);
|
||||||
u = divmod85(u, s);
|
u = divmod85(u, --s);
|
||||||
u = divmod85(u, s);
|
u = divmod85(u, --s);
|
||||||
*--s = (u>>24) + 33;
|
*--s = (u>>24) + 33;
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
src/base85.py
Normal file
25
src/base85.py
Normal 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
132
src/base85_test.c
Normal 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);
|
||||||
|
}
|
||||||
165
src/base85a.S
165
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
|
.global divmod85
|
||||||
divmod85:
|
divmod85:
|
||||||
movw r26, r20
|
movw r26, r20
|
||||||
# endif
|
#endif
|
||||||
|
;; ! C-ABI: m=X
|
||||||
;; ! C-ABI: gobbles r1, m=X
|
_divmod85: ; r25,r24,r23,r22 = A,B,C,D
|
||||||
_divmod85: ; r25,r24,r23,r22 = A,B,C,D
|
movw r18, r22
|
||||||
mov r18, r25
|
movw r20, r24
|
||||||
add r18, r24
|
lsl r21
|
||||||
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
|
|
||||||
rol r20
|
rol r20
|
||||||
|
rol r19
|
||||||
|
rol r18
|
||||||
|
clr r0
|
||||||
|
rol r0
|
||||||
|
sec
|
||||||
|
adc r21, r25
|
||||||
|
adc r20, r24
|
||||||
|
adc r19, r23
|
||||||
|
adc r18, r22
|
||||||
|
adc r0, r1 ; r21,r20,r19,r18,r0 = 3u + 1
|
||||||
|
|
||||||
|
mov r30, r21
|
||||||
|
add r30, r20
|
||||||
|
clr r31
|
||||||
rol r31
|
rol r31
|
||||||
rol r30
|
add r30, r19
|
||||||
add r18, r19
|
adc r31, r1
|
||||||
adc r25, r21
|
add r30, r18
|
||||||
adc r24, r20
|
adc r31, r1
|
||||||
adc r23, r31
|
add r30, r0
|
||||||
adc r22, r30
|
adc r31, r1 ; r30,r31 = A+B+C+D+E
|
||||||
|
|
||||||
|
mov r22, r31 ;
|
||||||
|
add r22, r30 ; just for the carry bit
|
||||||
|
mov r18, r31
|
||||||
|
adc r18, r30 ; r18 = r
|
||||||
|
mov r25, r31
|
||||||
|
adc r25, r1
|
||||||
|
|
||||||
|
sub r30, r21
|
||||||
|
sbc r31, r1 ; r30,r31 = B+C+D+E
|
||||||
|
add r25, r30
|
||||||
|
mov r24, r31
|
||||||
|
adc r24, r1
|
||||||
|
|
||||||
|
sub r30, r20
|
||||||
|
sbc r31, r1 ; r30,r31 = C+D+E
|
||||||
|
add r24, r30
|
||||||
|
mov r23, r31
|
||||||
|
adc r23, r1
|
||||||
|
|
||||||
|
sub r30, r19
|
||||||
|
sbc r31, r1 ; r30,r31 = D+E
|
||||||
|
add r23, r30
|
||||||
|
mov r22, r31
|
||||||
|
adc r22, r0
|
||||||
|
|
||||||
ldi r19, 85
|
ldi r19, 85
|
||||||
mul r18, r19
|
mul r18, r19
|
||||||
lsl r0
|
lsl r0
|
||||||
ldi r18, 33
|
ldi r19, '!'
|
||||||
adc r1, r18
|
adc r1, r19
|
||||||
# ifdef BASE85C
|
|
||||||
st X, r1
|
|
||||||
clr r1
|
|
||||||
# else
|
|
||||||
st -X, r1
|
st -X, r1
|
||||||
# endif
|
clr r1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#ifndef BASE85C
|
#ifndef BASE85C
|
||||||
.global base85_encode
|
.global base85_encode
|
||||||
base85_encode:
|
base85_encode:
|
||||||
movw r26, r20
|
movw r26, r20
|
||||||
|
|
@ -76,20 +101,20 @@ base85_encode:
|
||||||
rcall _divmod85
|
rcall _divmod85
|
||||||
rcall _divmod85
|
rcall _divmod85
|
||||||
rcall _divmod85
|
rcall _divmod85
|
||||||
subi r25, -33
|
subi r25, -'!'
|
||||||
st X, r25
|
st -X, r25
|
||||||
ldi r24, 5
|
|
||||||
clr r1
|
|
||||||
ret
|
ret
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
; uint32_t mul85(uint32_t u, uint8_t m);
|
; uint32_t mul85(uint32_t u, uint8_t m);
|
||||||
|
|
||||||
#ifdef BASE85C
|
#ifdef BASE85C
|
||||||
.global mul85
|
.global mul85
|
||||||
mul85:
|
mul85:
|
||||||
# endif
|
#endif
|
||||||
;; TODO for SPACE: inline this
|
;; TODO for SPACE: inline this
|
||||||
|
|
||||||
|
;; big endian r22/r23/r24/r25 *= 85; … += r20
|
||||||
_mul85:
|
_mul85:
|
||||||
ldi r21, 85
|
ldi r21, 85
|
||||||
mul r25, r21
|
mul r25, r21
|
||||||
|
|
@ -106,12 +131,12 @@ _mul85:
|
||||||
mov r25, r18
|
mov r25, r18
|
||||||
mov r23, r30
|
mov r23, r30
|
||||||
mov r22, r31
|
mov r22, r31
|
||||||
# ifdef BASE85C
|
#ifdef BASE85C
|
||||||
clr r1
|
clr r1
|
||||||
# endif
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#ifndef BASE85C
|
#ifndef BASE85C
|
||||||
|
|
||||||
.global base85_decode
|
.global base85_decode
|
||||||
base85_decode:
|
base85_decode:
|
||||||
|
|
@ -125,7 +150,9 @@ base85_decode:
|
||||||
clr r22
|
clr r22
|
||||||
ldi r17, 5
|
ldi r17, 5
|
||||||
1:
|
1:
|
||||||
ld r20, Y+
|
ld r20, X+
|
||||||
|
subi r20, '!'
|
||||||
|
brcs 2f
|
||||||
cpi r20, 85
|
cpi r20, 85
|
||||||
brcc 2f
|
brcc 2f
|
||||||
rcall _mul85
|
rcall _mul85
|
||||||
|
|
@ -145,4 +172,4 @@ base85_decode:
|
||||||
clr r1
|
clr r1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
# endif
|
#endif
|
||||||
|
|
|
||||||
34
src/cmd.c
34
src/cmd.c
|
|
@ -58,14 +58,13 @@ void base85_send_buffer(const uint8_t *buf)
|
||||||
"rjmp _send_str26" "\n"
|
"rjmp _send_str26" "\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
const uint8_t *base85_fill_buffer(const uint8_t *s) {
|
const uint8_t *base85_fill_buffer(const uint8_t *s) {
|
||||||
base85_error = 0;
|
base85_error = 0;
|
||||||
for (int i=0; !base85_error && i<FB_SIZE; i+=4)
|
for (int i=0; !base85_error && i<16; i+=4)
|
||||||
s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
|
s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -133,13 +132,13 @@ uint8_t cmd_flag(uint8_t f)
|
||||||
"ld r22, Z+" "\n\t"
|
"ld r22, Z+" "\n\t"
|
||||||
"cp r22, r24" "\n\t"
|
"cp r22, r24" "\n\t"
|
||||||
"mov r24, r1" "\n\t"
|
"mov r24, r1" "\n\t"
|
||||||
"brne 9f" "\n\t"
|
"breq 1f" "\n\t"
|
||||||
|
"ret" "\n"
|
||||||
|
"1:" "\n\t"
|
||||||
"mov r24, r22" "\n\t"
|
"mov r24, r22" "\n\t"
|
||||||
"sts cmd_flags, r30" "\n\t"
|
"sts cmd_flags, r30" "\n\t"
|
||||||
"sts cmd_flags+1, r31" "\n\t"
|
"sts cmd_flags+1, r31" "\n\t"
|
||||||
"rcall _send_char22" "\n"
|
"rjmp _send_char22" "\n"
|
||||||
"9:" "\n\t"
|
|
||||||
"ret" "\n"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -160,7 +159,9 @@ void parse_command(const uint8_t *s, uint8_t n)
|
||||||
uint8_t bflg = *s - '0';
|
uint8_t bflg = *s - '0';
|
||||||
uint8_t *bptr = cmd_buffer;
|
uint8_t *bptr = cmd_buffer;
|
||||||
if (bflg <= 5) {
|
if (bflg <= 5) {
|
||||||
|
#ifndef HALLO
|
||||||
bptr = flash_buffer + 16*bflg;
|
bptr = flash_buffer + 16*bflg;
|
||||||
|
#endif
|
||||||
bflg = 1<<bflg;
|
bflg = 1<<bflg;
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
@ -173,26 +174,27 @@ void parse_command(const uint8_t *s, uint8_t n)
|
||||||
if (*s==' ') {
|
if (*s==' ') {
|
||||||
cmd_pending = 0;
|
cmd_pending = 0;
|
||||||
s = base85_fill_buffer(s+1);
|
s = base85_fill_buffer(s+1);
|
||||||
if (base85_error) {
|
r = base85_error;
|
||||||
r = base85_error;
|
if (r)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
have_b = 1;
|
have_b = 1;
|
||||||
cmd_pending = cmd;
|
cmd_pending = cmd;
|
||||||
} else if (cmd_flag('~'))
|
}
|
||||||
|
else if (cmd_flag('='))
|
||||||
have_b = cmd_pending == cmd;
|
have_b = cmd_pending == cmd;
|
||||||
if (*s != '\n')
|
if (*s != '\n')
|
||||||
goto error;
|
goto error;
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case 'A':
|
case 'A':
|
||||||
r = adc_current;
|
r = adc_current;
|
||||||
if (r >= N_ADC) {
|
if (cmd_flag('!'))
|
||||||
if (cmd_flag('<'))
|
start_adc();
|
||||||
base85_send_buffer((void*)adc_readings);
|
if (cmd_flag('<')) {
|
||||||
if (cmd_flag('!'))
|
bptr = (void*)adc_readings;
|
||||||
start_adc();
|
goto send_buffer;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifndef HALLO
|
||||||
case 'B':
|
case 'B':
|
||||||
if (cmd_flag('@'))
|
if (cmd_flag('@'))
|
||||||
pipe.valid = 0;
|
pipe.valid = 0;
|
||||||
|
|
@ -246,11 +248,13 @@ void parse_command(const uint8_t *s, uint8_t n)
|
||||||
fpga_cmd((void*)cmd_buffer);
|
fpga_cmd((void*)cmd_buffer);
|
||||||
goto send_buffer;
|
goto send_buffer;
|
||||||
#endif
|
#endif
|
||||||
|
#endif // HALLO
|
||||||
case 'M':
|
case 'M':
|
||||||
if (!have_b)
|
if (!have_b)
|
||||||
goto error;
|
goto error;
|
||||||
r = poke((void*)cmd_buffer, cmd_flag('!'));
|
r = poke((void*)cmd_buffer, cmd_flag('!'));
|
||||||
send_buffer:
|
send_buffer:
|
||||||
|
send_char(' ');
|
||||||
base85_send_buffer(bptr);
|
base85_send_buffer(bptr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ struct config {
|
||||||
uint8_t cron;
|
uint8_t cron;
|
||||||
uint8_t flash_page_size;
|
uint8_t flash_page_size;
|
||||||
uint16_t burn_page;
|
uint16_t burn_page;
|
||||||
uint16_t erase_page;
|
|
||||||
uint16_t write_buffer;
|
uint16_t write_buffer;
|
||||||
uint16_t read_array;
|
uint16_t read_array;
|
||||||
uint16_t read_buffer[2];
|
uint16_t read_buffer[2];
|
||||||
|
|
@ -28,7 +27,7 @@ struct config {
|
||||||
enum magic_flags {
|
enum magic_flags {
|
||||||
#ifdef HAVE_nFETs
|
#ifdef HAVE_nFETs
|
||||||
MAGIC = 0xD0,
|
MAGIC = 0xD0,
|
||||||
VERSION = 0x01,
|
VERSION = 0x00,
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_FPGA
|
#ifdef HAVE_FPGA
|
||||||
MAGIC = 0xC5,
|
MAGIC = 0xC5,
|
||||||
|
|
@ -131,9 +130,9 @@ void apply_config()
|
||||||
"ldi r30, lo8(ee9_start)" "\n\t"
|
"ldi r30, lo8(ee9_start)" "\n\t"
|
||||||
"ldi r31, hi8(ee9_start)" "\n\t"
|
"ldi r31, hi8(ee9_start)" "\n\t"
|
||||||
"ldi r24, lo8(ee9_size)" "\n\t"
|
"ldi r24, lo8(ee9_size)" "\n\t"
|
||||||
"clr r26" "\n"
|
"clr r25" "\n"
|
||||||
"1:" "\n\t"
|
"1:" "\n\t"
|
||||||
"mov r27, r26" "\n\t"
|
"mov r27, r25" "\n\t"
|
||||||
"subi r24, 2" "\n\t"
|
"subi r24, 2" "\n\t"
|
||||||
"brcs 3f" "\n"
|
"brcs 3f" "\n"
|
||||||
"2:" "\n\t"
|
"2:" "\n\t"
|
||||||
|
|
|
||||||
208
src/dose.py
Executable file
208
src/dose.py
Executable file
|
|
@ -0,0 +1,208 @@
|
||||||
|
#! /usr/bin/ipython3 --profile=turbo_dose
|
||||||
|
|
||||||
|
import sys, time, getopt, fileinput, struct
|
||||||
|
import uart
|
||||||
|
from base85 import base85_encode, base85_decode
|
||||||
|
from map import memmap
|
||||||
|
from iotn424 import SFR
|
||||||
|
|
||||||
|
options, files = getopt.gnu_getopt(sys.argv[1:], "F:o:M:", ["debug", "tty=", "output=", "map="])
|
||||||
|
|
||||||
|
tty = "/dev/ttyUSB1"
|
||||||
|
baud = 115200
|
||||||
|
out = None
|
||||||
|
debug = None
|
||||||
|
map_fn = "hallo.map"
|
||||||
|
|
||||||
|
def Debug(e, *a):
|
||||||
|
if debug:
|
||||||
|
import traceback
|
||||||
|
sys.stdout.flush()
|
||||||
|
print("xdebug", a, repr(e), file=sys.stderr)
|
||||||
|
traceback.print_exception(e, limit=-2, file=sys.stderr)
|
||||||
|
|
||||||
|
for o,v in options:
|
||||||
|
|
||||||
|
if o == "--debug":
|
||||||
|
debug = True
|
||||||
|
|
||||||
|
if o in "-F --tty":
|
||||||
|
tty = v
|
||||||
|
v = v.split(",", 1)
|
||||||
|
if v[1:]:
|
||||||
|
tty = v[0]
|
||||||
|
baud = int(v[1])
|
||||||
|
do_clock = True
|
||||||
|
|
||||||
|
if o in "--output":
|
||||||
|
if out:
|
||||||
|
raise ValueError("cannot have multiple --outputs")
|
||||||
|
if v=="-":
|
||||||
|
out = sys.stdout
|
||||||
|
elif v=="--":
|
||||||
|
out = sys.stderr
|
||||||
|
else:
|
||||||
|
out = open(v, "a")
|
||||||
|
|
||||||
|
if o in "-M --map":
|
||||||
|
map_fn = v
|
||||||
|
|
||||||
|
if not out:
|
||||||
|
out = sys.stdout
|
||||||
|
|
||||||
|
if len(files)==1:
|
||||||
|
if "/dev/tty" in files[0]:
|
||||||
|
tty = files[0]
|
||||||
|
files = []
|
||||||
|
|
||||||
|
mmap = memmap(map_fn)
|
||||||
|
|
||||||
|
class dose_cmd(uart.uart):
|
||||||
|
|
||||||
|
def cmd(self, c, d=None, timeout=0.2):
|
||||||
|
if not isinstance(c, bytes):
|
||||||
|
c = c.encode()
|
||||||
|
if d:
|
||||||
|
c += b" " + base85_encode(d)
|
||||||
|
self.flush()
|
||||||
|
self.ucmd(c)
|
||||||
|
r = self.resp(timeout)
|
||||||
|
while r and (r[0] != b'#'[0] or r[1] != c[0]):
|
||||||
|
r = self.resp(timeout)
|
||||||
|
d = None
|
||||||
|
if not r:
|
||||||
|
return r, d
|
||||||
|
r = r.split()
|
||||||
|
e = int(r[-1], 16)
|
||||||
|
if len(r)==3:
|
||||||
|
d = base85_decode(r[1])
|
||||||
|
if self.verbose:
|
||||||
|
print(f"{r[0]}[{r[2]}] {"".join([f"{b:02x}" for b in d])}", file=sys.stderr)
|
||||||
|
self.last_cmd = c[0:1]
|
||||||
|
return r[0], e, d
|
||||||
|
|
||||||
|
def poke(self, a, d, s=None, ccp=0):
|
||||||
|
return self.peek(a, d, s, ccp)
|
||||||
|
|
||||||
|
def peek(self, a=None, d=None, s=None, ccp=0):
|
||||||
|
name = None
|
||||||
|
if a in SFR:
|
||||||
|
name = a
|
||||||
|
a, ss = SFR[a]
|
||||||
|
if s is None:
|
||||||
|
s = ss
|
||||||
|
if a in mmap:
|
||||||
|
a, ss = mmap[a]
|
||||||
|
if ss and s is None:
|
||||||
|
s = ss
|
||||||
|
if s is None and isinstance(d, int):
|
||||||
|
s = d
|
||||||
|
d = None
|
||||||
|
FF = {1: "B", 2: "H", 4:"I"}
|
||||||
|
if a is None:
|
||||||
|
cc, nn, dd = self.cmd(b"M=")
|
||||||
|
else:
|
||||||
|
if d is None:
|
||||||
|
c = b"M"
|
||||||
|
d = b''
|
||||||
|
if s is None:
|
||||||
|
s = 12
|
||||||
|
else:
|
||||||
|
c = b'M!'
|
||||||
|
if isinstance(d, int) and s in FF:
|
||||||
|
d = struct.pack(f"<{FF[s]}", d)
|
||||||
|
else:
|
||||||
|
d = bytes(d)
|
||||||
|
if s is None:
|
||||||
|
s = len(d)
|
||||||
|
d = struct.pack("<HBB", a,s,ccp) + d + b'\0\0\0\0\0\0\0\0\0\0\0\0'
|
||||||
|
cc, nn, dd = self.cmd(c, d[:16])
|
||||||
|
if dd and nn:
|
||||||
|
print(" ".join([f"{x:02x}" for x in dd[4:4+nn]]), file=sys.stderr)
|
||||||
|
if name is not None and nn in FF:
|
||||||
|
d = struct.unpack(f"<{FF[nn]}", dd[4:4+nn])
|
||||||
|
print(f"{name}: {d[0]:#x}", file=sys.stderr)
|
||||||
|
return name, d
|
||||||
|
return cc, nn, dd
|
||||||
|
o
|
||||||
|
def more(self, flags=b''):
|
||||||
|
return self.cmd(self.last_cmd + b'=' + flags)
|
||||||
|
|
||||||
|
def read_mem(self, a, s=None):
|
||||||
|
cc, nn, dd = self.peek(a=a, s=s)
|
||||||
|
r = dd[4:4+nn]
|
||||||
|
while dd[2]:
|
||||||
|
cc, nn, dd = self.more()
|
||||||
|
r += dd[4:4+nn]
|
||||||
|
return r
|
||||||
|
|
||||||
|
adc_conf = None
|
||||||
|
sigrow = None
|
||||||
|
|
||||||
|
ADC_MUX = {
|
||||||
|
0: "GND",
|
||||||
|
6: "Gate",
|
||||||
|
7: "Drain1",
|
||||||
|
10: "Drain2",
|
||||||
|
0x30: "GND",
|
||||||
|
0x31: ("Vdd", 10, 0, 0),
|
||||||
|
0x32: "T",
|
||||||
|
0x33: "DACREF",
|
||||||
|
}
|
||||||
|
ADC_REF = {
|
||||||
|
0: (3.3, "VDD"),
|
||||||
|
4: (1.024,),
|
||||||
|
5: (2.048,),
|
||||||
|
6: (2.5,),
|
||||||
|
7: (4.096,),
|
||||||
|
}
|
||||||
|
|
||||||
|
def adc(self, start=False, read_conf=False):
|
||||||
|
if not self.adc_conf or read_conf:
|
||||||
|
self.adc_conf = self.read_mem("adc_conf")
|
||||||
|
self.sigrow = self.read_mem(0x1100, 0x24)
|
||||||
|
g = self.sigrow[0x20]
|
||||||
|
o = self.sigrow[0x21]
|
||||||
|
if o & 0x80:
|
||||||
|
o -= 0x100
|
||||||
|
o <<= 6
|
||||||
|
g /= 1 << 14
|
||||||
|
self.ADC_MUX[0x32] = ("T°C", g, o, 273)
|
||||||
|
c = "A!<" if start else "A<"
|
||||||
|
cc, nn, dd = self.cmd(c)
|
||||||
|
dd = struct.unpack("<8H", dd)
|
||||||
|
r = []
|
||||||
|
for i in range(nn):
|
||||||
|
pos = self.adc_conf[4*i+2] & 0x3f
|
||||||
|
ref = self.adc_conf[4*i+1] & 0x07
|
||||||
|
if ref in self.ADC_REF:
|
||||||
|
ref = self.ADC_REF[ref]
|
||||||
|
else:
|
||||||
|
ref = (1,)
|
||||||
|
a = dd[i]
|
||||||
|
if pos != 0x32:
|
||||||
|
a *= ref[0]/0x10000
|
||||||
|
if pos in self.ADC_MUX:
|
||||||
|
pos = self.ADC_MUX[pos]
|
||||||
|
else:
|
||||||
|
pos = f"Ain{pos}"
|
||||||
|
if isinstance(pos, tuple):
|
||||||
|
a = (a - pos[2])*pos[1] - pos[3]
|
||||||
|
pos = pos[0]
|
||||||
|
r.append((a, pos, ref))
|
||||||
|
print(f"{i} {pos:6s} {a:.4f} {ref!r}", file=sys.stderr)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def nfet_scan(self, t=1, dcs=(0x1000,)):
|
||||||
|
r = []
|
||||||
|
for dc in range(*dcs):
|
||||||
|
self.poke("TCA0_SINGLE_CMP0", dc)
|
||||||
|
time.sleep(t)
|
||||||
|
self.cmd("A!")
|
||||||
|
time.sleep(1)
|
||||||
|
r.append((dc, self.adc()))
|
||||||
|
return r
|
||||||
|
|
||||||
|
if tty:
|
||||||
|
tty = dose_cmd(tty, baud)
|
||||||
|
uart.set_prompt("TurboD")
|
||||||
47
src/hallo.c
Normal file
47
src/hallo.c
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// hallo.c
|
||||||
|
//
|
||||||
|
|
||||||
|
// int = int8_t
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/sleep.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "pwm.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// main()
|
||||||
|
|
||||||
|
section_status(main) struct magic magic;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
while (CLKCTRL.MCLKCTRLB != config.cpu_clk) {
|
||||||
|
CCP = CCP_IOREG_gc;
|
||||||
|
CLKCTRL.MCLKCTRLB = config.cpu_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep_enable();
|
||||||
|
magic.magic = config.magic;
|
||||||
|
while (magic.magic != MAGIC || config.version != VERSION)
|
||||||
|
sleep_cpu();
|
||||||
|
|
||||||
|
apply_config();
|
||||||
|
magic.reset_source = RSTCTRL.RSTFR;
|
||||||
|
|
||||||
|
RSTCTRL.RSTFR = magic.reset_source;
|
||||||
|
send_str("\nV Turbo Hallo V0.0");
|
||||||
|
send_hex_byte_eol(magic.reset_source);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
sei();
|
||||||
|
sleep_cpu();
|
||||||
|
command();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/io.S
Normal file
1
src/io.S
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include <avr/io.h>
|
||||||
443
src/iotn424.py
Normal file
443
src/iotn424.py
Normal 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
33
src/map.py
Normal 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
20
src/prompt.py
Normal 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
|
||||||
11
src/rtc.c
11
src/rtc.c
|
|
@ -25,7 +25,7 @@ uint8_t rtc_cnt_tick()
|
||||||
|
|
||||||
struct_ioconf(rtc_config) = {
|
struct_ioconf(rtc_config) = {
|
||||||
conf_prefix(RTC),
|
conf_prefix(RTC),
|
||||||
conf_iow(RTC.CMP, 3600),
|
conf_iow(RTC.CMP, 10), // rtc_cnt_tick() period [s]
|
||||||
conf_io(RTC.CLKSEL, RTC_CLKSEL_INT1K_gc),
|
conf_io(RTC.CLKSEL, RTC_CLKSEL_INT1K_gc),
|
||||||
conf_io(RTC.PITINTCTRL, 1),
|
conf_io(RTC.PITINTCTRL, 1),
|
||||||
conf_io(RTC.PITCTRLA, RTC_PERIOD_CYC1024_gc | RTC_PITEN_bm),
|
conf_io(RTC.PITCTRLA, RTC_PERIOD_CYC1024_gc | RTC_PITEN_bm),
|
||||||
|
|
@ -43,8 +43,7 @@ ISR(RTC_PIT_vect, ISR_NAKED)
|
||||||
"ldi r24, 1" "\n\t"
|
"ldi r24, 1" "\n\t"
|
||||||
"sts %[flag], r24" "\n\t"
|
"sts %[flag], r24" "\n\t"
|
||||||
"sts pit_tick, r24" "\n\t"
|
"sts pit_tick, r24" "\n\t"
|
||||||
"ldi r24, " "\n\t"
|
"pop r24" "\n\t"
|
||||||
"sts %[flag], r24" "\n\t"
|
|
||||||
"reti" "\n"
|
"reti" "\n"
|
||||||
::[flag] "n" (&RTC.PITINTFLAGS)
|
::[flag] "n" (&RTC.PITINTFLAGS)
|
||||||
);
|
);
|
||||||
|
|
@ -66,11 +65,11 @@ ISR(RTC_CNT_vect, ISR_NAKED)
|
||||||
"push r26" "\n\t"
|
"push r26" "\n\t"
|
||||||
"lds r24, %[CMPL]" "\n\t"
|
"lds r24, %[CMPL]" "\n\t"
|
||||||
"lds r25, %[CMPH]" "\n\t"
|
"lds r25, %[CMPH]" "\n\t"
|
||||||
"lds r26, config+3" "\n\t"
|
"lds r26, rtc_config+3" "\n\t"
|
||||||
"add r24, r26" "\n\t"
|
"add r24, r26" "\n\t"
|
||||||
"sts %[CMPL], r24" "\n\t"
|
"sts %[CMPL], r24" "\n\t"
|
||||||
"lds r26, config+5" "\n\t"
|
"lds r26, rtc_config+5" "\n\t"
|
||||||
"add r25, r26" "\n\t"
|
"adc r25, r26" "\n\t"
|
||||||
"sts %[CMPH], r25" "\n\t"
|
"sts %[CMPH], r25" "\n\t"
|
||||||
"pop r26" "\n\t"
|
"pop r26" "\n\t"
|
||||||
"pop r25" "\n\t"
|
"pop r25" "\n\t"
|
||||||
|
|
|
||||||
10
src/uart.c
10
src/uart.c
|
|
@ -10,10 +10,10 @@
|
||||||
|
|
||||||
struct_ioconf(uart_config) = {
|
struct_ioconf(uart_config) = {
|
||||||
conf_prefix(USART0),
|
conf_prefix(USART0),
|
||||||
conf_iow(USART0.BAUD, UART_BAUD),
|
conf_iow(USART0.BAUD, 40000000/115200), // 115200 baud
|
||||||
conf_io(USART0.CTRLB, UART_MODE & 0xff),
|
conf_io(USART0.CTRLC, USART_CHSIZE_8BIT_gc),
|
||||||
conf_io(USART0.CTRLC, UART_MODE >> 8),
|
conf_io(USART0.CTRLB, USART_TXEN_bm | USART_RXEN_bm),
|
||||||
conf_io(USART0.CTRLA,USART_RXCIE_bm),
|
conf_io(USART0.CTRLA, USART_RXCIE_bm),
|
||||||
};
|
};
|
||||||
|
|
||||||
// `uart_tx` buffer size must be a power of 2, max 256.
|
// `uart_tx` buffer size must be a power of 2, max 256.
|
||||||
|
|
@ -163,7 +163,7 @@ ISR(USART0_RXC_vect, ISR_NAKED)
|
||||||
" push r31 \n"
|
" push r31 \n"
|
||||||
" lds r24, %[DH] \n"
|
" lds r24, %[DH] \n"
|
||||||
" lds r30, uart_rx_s \n"
|
" lds r30, uart_rx_s \n"
|
||||||
" and r24, r30 \n"
|
" or r24, r30 \n"
|
||||||
" sts uart_rx_s, r24 \n"
|
" sts uart_rx_s, r24 \n"
|
||||||
" lds r24, %[DL] \n"
|
" lds r24, %[DL] \n"
|
||||||
" lds r30, uart_rx_w \n"
|
" lds r30, uart_rx_w \n"
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,6 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define UART_MODE 0x03c0
|
|
||||||
#define UART_BAUD 5555 // 115200 baud
|
|
||||||
|
|
||||||
void init_uart(uint16_t mode, uint16_t div);
|
void init_uart(uint16_t mode, uint16_t div);
|
||||||
|
|
||||||
void send_char(uint8_t c);
|
void send_char(uint8_t c);
|
||||||
|
|
|
||||||
115
src/uart.py
Executable file
115
src/uart.py
Executable file
|
|
@ -0,0 +1,115 @@
|
||||||
|
#! /usr/bin/ipython3 --profile=uart
|
||||||
|
|
||||||
|
import sys, serial, threading, struct
|
||||||
|
from prompt import set_prompt
|
||||||
|
|
||||||
|
class uart(threading.Thread):
|
||||||
|
|
||||||
|
def __init__(self, port, baudrate=115200, parity='N'):
|
||||||
|
self.baudrate=baudrate
|
||||||
|
self.serial = serial.Serial(baudrate=baudrate, parity=parity, timeout=10.0,
|
||||||
|
xonxoff=False, rtscts=False, dsrdtr=False)
|
||||||
|
self.serial.port = port
|
||||||
|
self.portname = port.split('/')[-1]
|
||||||
|
self.serial.open()
|
||||||
|
self.write = self.serial.write
|
||||||
|
self.responses = []
|
||||||
|
self.readbuffer = b""
|
||||||
|
self.reader_lock = threading.Lock()
|
||||||
|
self.resp_ready = threading.Condition()
|
||||||
|
self.alive = True
|
||||||
|
threading.Thread.__init__(self, target=self.reader)
|
||||||
|
self.daemon = True
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def reader(self):
|
||||||
|
data = b""
|
||||||
|
while self.alive:
|
||||||
|
data += self.serial.read_until(b'\n')
|
||||||
|
data += self.serial.read_all()
|
||||||
|
if data and self.reader_lock.acquire(False):
|
||||||
|
self.readbuffer += data
|
||||||
|
data = b""
|
||||||
|
self.parser()
|
||||||
|
self.reader_lock.release()
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
if self.reader_lock.acquire(False):
|
||||||
|
self.parser()
|
||||||
|
self.reader_lock.release()
|
||||||
|
|
||||||
|
def kill(self):
|
||||||
|
self.alive = False
|
||||||
|
self.join()
|
||||||
|
|
||||||
|
def parser(self):
|
||||||
|
"do something with received chars in .readbuffer"
|
||||||
|
if not self.resp_ready.acquire(False):
|
||||||
|
return
|
||||||
|
lines = self.readbuffer.split(b'\n')
|
||||||
|
self.readbuffer = lines[-1]
|
||||||
|
lines[-1:] = []
|
||||||
|
|
||||||
|
for ll in lines:
|
||||||
|
if ll:
|
||||||
|
self.parse_line(ll)
|
||||||
|
if self.responses:
|
||||||
|
self.resp_ready.notify()
|
||||||
|
self.resp_ready.release()
|
||||||
|
|
||||||
|
verbose = True
|
||||||
|
|
||||||
|
def parse_line(self, l):
|
||||||
|
self.responses.append(l)
|
||||||
|
if self.verbose:
|
||||||
|
try:
|
||||||
|
s = l.decode()
|
||||||
|
print(f"{self.portname}<- {s}", file=sys.stderr)
|
||||||
|
except:
|
||||||
|
print(f"{self.portname}<- {repr(l)}", file=sys.stderr)
|
||||||
|
|
||||||
|
def resp(self, timeout=10, blocking=True):
|
||||||
|
self.parse()
|
||||||
|
if not self.resp_ready.acquire(blocking):
|
||||||
|
return b""
|
||||||
|
if blocking and not self.responses:
|
||||||
|
self.resp_ready.wait(timeout)
|
||||||
|
l = b""
|
||||||
|
if self.responses:
|
||||||
|
l = self.responses[0]
|
||||||
|
self.responses[:1] = []
|
||||||
|
self.resp_ready.release()
|
||||||
|
return l
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
r = []
|
||||||
|
while self.responses:
|
||||||
|
r.append(self.resp())
|
||||||
|
return r
|
||||||
|
|
||||||
|
def ucmd(self, c):
|
||||||
|
if not isinstance(c, bytes):
|
||||||
|
c = c.encode()
|
||||||
|
if c[-1:] != b'\n':
|
||||||
|
c = c + b'\n'
|
||||||
|
if self.verbose:
|
||||||
|
print(f"{self.portname}-> {c.decode().rstrip()}", file=sys.stderr)
|
||||||
|
self.write(c)
|
||||||
|
|
||||||
|
def cmd(self, c):
|
||||||
|
self.ucmd(c)
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
import getopt
|
||||||
|
oo,ff = getopt.getopt(sys.argv[1:], "F:", ["tty="])
|
||||||
|
port = "/dev/ttyUSB1"
|
||||||
|
baud = 115200
|
||||||
|
for o,v in oo:
|
||||||
|
if o=="-F" or v=="--tty":
|
||||||
|
v = v.split(",")
|
||||||
|
port = v[0]
|
||||||
|
if len(v)>1:
|
||||||
|
baud = int(v[1])
|
||||||
|
u = uart(port, baud)
|
||||||
|
c = u.ucmd
|
||||||
|
set_prompt(u.portname)
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
.global _send_str26
|
.global _send_str26
|
||||||
.global uart_busy
|
.global uart_busy
|
||||||
.global send_hex
|
.global send_hex
|
||||||
|
.global send_eol
|
||||||
.global command
|
.global command
|
||||||
|
|
||||||
// `tx()` and `put_char()` do not gobble r18, r20, r21, r22, r24, r26, and r27.
|
// `tx()` and `put_char()` do not gobble r18, r20, r21, r22, r24, r26, and r27.
|
||||||
|
|
@ -101,7 +102,7 @@ send_hex:
|
||||||
ld r24, X+
|
ld r24, X+
|
||||||
rcall send_hex_byte
|
rcall send_hex_byte
|
||||||
subi r18, 1
|
subi r18, 1
|
||||||
brcc 1b
|
brne 1b
|
||||||
9:
|
9:
|
||||||
ret
|
ret
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue