Compare commits

..

14 commits

Author SHA1 Message Date
Stephan I. Böttcher
c348b6a271 python: pipe() fixes 2026-04-07 17:29:53 +02:00
Stephan I. Böttcher
69b27506a4 pipe: use generated parity w/ non-flash source 2026-04-07 17:29:11 +02:00
Stephan I. Böttcher
0bda97fd39 minor whitespace fix 2026-04-07 17:27:22 +02:00
Stephan I. Böttcher
6bb065d3c5 flash_stream: fix FS_528 2026-04-07 17:26:39 +02:00
Stephan I. Böttcher
d684d51554 allow cmd("B%") parity ops with cmd_buffer 2026-04-07 17:25:19 +02:00
Stephan I. Böttcher
d64e1fd749 peek("X+«hex»") 2026-04-01 08:15:44 +02:00
Stephan I. Böttcher
db9709f7a8 pipe: can read flash 2026-04-01 08:03:34 +02:00
Stephan I. Böttcher
6db31a6c7d pipe: can read flash 2026-04-01 08:03:06 +02:00
Stephan I. Böttcher
025417be68 main: slimmer sleep condition 2026-04-01 08:02:40 +02:00
Stephan I. Böttcher
a9f83f8628 invert the condition for spi-wait in ISR 2026-04-01 07:58:14 +02:00
Stephan I. Böttcher
3a0e72eb52 magic.flags, hold_pipe 2026-03-31 14:51:17 +02:00
Stephan I. Böttcher
b6cdc1991f magic.flags, hold_pipe 2026-03-31 14:45:35 +02:00
Stephan I. Böttcher
f7c1e27d48 uart.py: verbosity 2026-03-31 14:44:44 +02:00
Stephan I. Böttcher
b1356355db cmd: 'P' fixes 2026-03-31 14:43:40 +02:00
10 changed files with 285 additions and 134 deletions

View file

@ -206,11 +206,11 @@ void parse_command(const uint8_t *s, uint8_t n)
pipe.valid = 0;
r = pipe.valid;
if (have_b) {
if (cmd_flag('!') || ~r & bflg) {
if (bflg && cmd_flag('!') || ~r & bflg) {
memcpy(bptr, cmd_buffer, 16);
r = pipe.valid |= bflg;
pipe.valid = r |= bflg;
}
else
else if (bflg)
goto error;
}
if (cmd_flag('%')) {
@ -220,14 +220,15 @@ void parse_command(const uint8_t *s, uint8_t n)
if (cmd_flag('!')) {
bch4369_fini();
memcpy(flash_buffer+64, bch_parity, 16);
r = pipe.valid |= 0x10;
pipe.valid = r |= 0x10;
}
}
if (cmd_flag('<')) {
if (cmd_flag('!')) goto send_buffer;
if (~r & bflg)
goto error;
pipe.valid &=~ bflg;
pipe.valid = r &=~ bflg;
r |= pipe.status << 4;
goto send_buffer;
}
break;
@ -240,17 +241,23 @@ void parse_command(const uint8_t *s, uint8_t n)
r = flash_submit_command(cmd_buffer);
else
r = spi_busy_p();
if (cmd_flag('@'))
if (cmd_flag('!'))
spi_poll();
if (cmd_flag('<'))
goto send_buffer;
break;
case 'P':
if (cmd_flag('!'))
if (cmd_flag('@'))
pipe.dest = 0;
if (have_b)
pipe_config((void*)cmd_buffer, (void*)bptr);
r = pipe_poll();
if (cmd_flag('.'))
flash_poll(0);
else if (cmd_flag(','))
flash_poll(1);
if (cmd_flag('!'))
pipe_poll();
r = pipe.status;
break;
#ifdef HAVE_FPGA
case 'O':

View file

@ -38,6 +38,7 @@ enum magic_flags {
MAGIC = 0xC5,
VERSION = 0x00,
#endif
hold_pipe = 0x01,
};
extern const struct config config;
@ -158,6 +159,7 @@ void apply_config()
extern struct magic {
uint8_t magic;
uint8_t reset_source;
uint8_t flags;
} magic;
#if 0

View file

@ -66,6 +66,16 @@ mmap = memmap(map_fn)
class dose_cmd(uart.uart):
def parse_line(self, l):
self.responses.append(l)
v = self._verbose
if v>=4 or v and (l[:1]!=b'#' or b'?' in l.split()[0]):
try:
s = l.decode()
print(f"{self.portname}<- {s}", file=sys.stderr)
except:
print(f"{self.portname}<- {repr(l)}", file=sys.stderr)
def cmd(self, c, d=None, timeout=0.2):
if not isinstance(c, bytes):
c = c.encode()
@ -83,7 +93,7 @@ class dose_cmd(uart.uart):
e = int(r[-1], 16)
if len(r)==3:
d = base85_decode(r[1])
if self._verbose:
if self._verbose >= 3:
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
@ -91,26 +101,32 @@ class dose_cmd(uart.uart):
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):
def peek(self, a=None, s=None, d=None, ccp=0, o=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)
aa = a.split('+',1)
if aa[1:]:
o += int(aa[1], 0)
aa = aa[0]
if aa in SFR:
name = aa
a, ss = SFR[aa]
if s is None:
s = ss
elif aa in mmap:
a, ss = mmap[aa]
if ss and s is None:
s = ss
else:
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)
a += o
FF = {1: "B", 2: "H", 4:"I"}
if a is None:
cc, nn, dd = self.cmd(b"M=")
@ -223,7 +239,10 @@ class dose_cmd(uart.uart):
def flash(self, op=None, resp=False, poll=False, **aa):
c = "F"
if poll:
c = "F@"
if poll in ".,!":
c = "F"+poll
else:
c = "F!"
if resp:
c += "<"
if op is None:
@ -278,10 +297,8 @@ class dose_cmd(uart.uart):
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]
d = self.fix_page(d)
return d
def read_flash(self, page):
print(f"FLASH: reading from {page=}")
@ -355,6 +372,17 @@ class dose_cmd(uart.uart):
self.flash(op, size=s, what=what, byte=i)
self.wait_for_spi()
def make_parity(self, page):
for i in range(32):
if i==0:
c = "B4!%@"
elif i!=31:
c = "B4!%"
else:
c = "B4!%!"
self.cmd(c, page[16*i:16*(i+1)])
return self.cmd("B4<!")
def power(self, on=None):
if on==True:
c = 'O1'
@ -372,7 +400,6 @@ class dose_cmd(uart.uart):
return self.cmd("C@")
FPGA_FLGS = {
"ABORT": 0x01,
"DEAD": 0x10,
"BUSY": 0x20,
"SUBMITTED": 0x40,
@ -396,7 +423,7 @@ class dose_cmd(uart.uart):
c = bytes((n, z)) + c + bytes(14)
r, e, d = self.cmd("C", c[:16])
s = int2flags(self.FPGA_FLGS, d[0])
if self._verbose:
if self._verbose >= 2:
print(f"FPGA cmd status {s!r}", file=sys.stderr)
return d
@ -462,7 +489,7 @@ class dose_cmd(uart.uart):
w.extend([0x8001]*(r-1))
w.append(0)
d = struct.pack(f">{len(w)}H", *w)
if self._verbose:
if self._verbose >= 2:
if mes:
mes = f"[{mes}]"
else:
@ -470,13 +497,13 @@ class dose_cmd(uart.uart):
print(f"icmd{mes}{[f"{ww:04x}" for ww in w]}")
d = self.fpga_cmd(d)
r = struct.unpack(f">{len(w)+1}H", d[:2*len(w)+2])
if self._verbose:
if self._verbose >= 2:
print(f" {mes}{[f"{rr:04x}" for rr in r]}", file=sys.stderr)
return r
def acmd(self, c, v=None, task=None, verb=True):
_v = self._verbose
self._verbose = _v
self._verbose = verb+1
r = self.icmd(c, v, mes=task)[-1]
self._verbose = _v
return r
@ -500,7 +527,7 @@ class dose_cmd(uart.uart):
nnn -= nn
d += dd[2:]
r = struct.unpack(f">{len(d)//2}H", d)[:n]
if self._verbose:
if self._verbose >= 2:
print(f"FIFO[{fifo}] ← {[f"{rr:04x}" for rr in r]}", file=sys.stderr)
return r
@ -522,9 +549,140 @@ class dose_cmd(uart.uart):
else:
self.icmd("MCONF_CLR", what)
PIPE = {
"CMD" : 1,
"ADC" : 2,
"FLASH" : 4,
"FPGA" : 8,
"CONFIG" : 0x208,
"FPGA_CMD" : 0x408,
}
def pipe(self, source=None, dest=None,
fpga_cmd=4, psize=64, n=0,
page=0, npages=0,
poll=True, stop=False):
astatus = flags2int(self.PIPE, dest)
astatus |= flags2int(self.PIPE, source)
astatus >>= 8
dest = flags2int(self.PIPE, dest) & 0xff
source = flags2int(self.PIPE, source) & 0xff
flash = 0x80 # FS_528
status = 0x80 # PS_OUT
c = 'P'
if astatus & self.PIPE["FPGA_CMD"]:
if not isinstance(fpga_cmd, int):
self.cmd("B4!", fpga_cmd)
fpga_cmd = 4
c = 'P{fpga_cmd}'
if stop:
c += '@'
if poll:
c += '!'
if source & self.PIPE["FLASH"]:
source = self.PIPE["FLASH"]
flash |= 4
status |= 0x30 # PS_528 | PS_BCH
dest &=~ self.PIPE["FLASH"]
if dest & self.PIPE["FPGA"] and not n:
n = 512/64 * npages
if dest & self.PIPE["FLASH"]:
flash |= 8
status |= 0x30 # PS_528 | PS_BCH
if source == self.PIPE["FPGA"] and not n:
n = (512*npages+psize-1) // psize
d = struct.pack("<6BH3B2HB",
source, dest, status, 0, 0,
astatus, n, psize, 0, 0,
page, npages-1, flash)
return self.cmd(c, d)
Sync = False
def read_pipe(self, n=0, file=None, timeout=2, parity=False):
if isinstance(file, str):
f = open(file, "ab")
else:
f = file
result = []
i = 0
page = []
t = time.time()
s = 1/256
while i < n:
cc, nn, dd = self.cmd("B")
if not parity or len(page) < 7:
bflg = 0x0f
else:
bflg = 0x1f
tt = time.time()
if ~nn & bflg:
if tt > t+timeout:
if self._verbose:
print("read_pipe timeout", file=sys.stderr)
break
time.sleep(s)
s *= 2
if s > 1:
s = 1
continue
t = tt
s = 1/256
if len(result) >= n:
break
if nn & 0x10:
p = self.cmd("B4<")[2]
else:
p = None
data = [self.cmd(f"B{i}<")[2] for i in range(4)]
data = b''.join(data)
page.append(data)
if len(page)==8:
if p:
page.append(p)
page = b''.join(page)
i += 1
if parity:
if bch.check_page(page):
print(f"parity error on page {i}", file=sys.stderr)
if parity == "fix":
page = self.fix_page(page)
if f and parity == "fix":
file.write(page[:512])
if not f:
result.append(page)
page = []
if f and parity != "fix":
f.write(data)
if len(page) and parity == "save":
f.write_flash(p)
if f and self.Sync:
f.sync()
if isinstance(file, str):
f.close()
return result
def fix_page(self, page):
if self.load_galois():
page = bch.fix_page(page)
def load_galois(self):
if not bch.galois:
raise bch.BCHError("galois module not loaded for Parity Error correction")
return True
def flags2int(FLAGS, flags):
r = 0
if flags is None:
return r
if isinstance(flags, int):
return flags
if isinstance(flags, str):
@ -546,7 +704,7 @@ def int2flags(FLAGS, flags):
if tty:
tty = dose_cmd(tty, baud)
tty._export(globals())
tty._verbose = False
tty._verbose = True
import dorn
from dorn import *
dorn._connect(tty)

View file

@ -150,7 +150,7 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
spi_start_read(csize, flash_cmd_buffer, size, b);
break;
case FM_WAIT:
spi.mask = 0x80;
spi.mask = spi.wait = 0x80;
spi_start_read(csize, flash_cmd_buffer, 2, b);
break;
}
@ -173,7 +173,7 @@ uint8_t flash_stream_submit(uint16_t mode, uint8_t size)
{
uint8_t b = fs.block;
uint16_t p = fs.page;
uint8_t r = fs.status & ~FS_Ready;
uint8_t r = fs.status & ~FS_Ready | FS_Busy;
mode |= (uint16_t)config.flash_page_size << 8;
if (size) {
if (b & 8) {
@ -193,21 +193,9 @@ uint8_t flash_stream_submit(uint16_t mode, uint8_t size)
uint8_t e = flash_cmd(mode, size, p, (uint16_t)(b&7) << 6);
if (e)
r |= FS_Ready; // FS_Error
r |= FS_Busy;
r |= FS_Error;
fs.status = r;
return e;
}
__attribute__ ((noinline, noclone))
uint8_t flash_stream_done()
{
uint8_t r = fs.status & FS_Error;
if (!r || r == FS_Error)
return 1;
if (fs.npages || !(fs.block & 8))
return 0;
return 1;
return r;
}
static inline
@ -253,55 +241,50 @@ uint8_t flash_burn_page()
uint8_t flash_poll(uint8_t rr)
{
uint8_t r = fs.status;
if (rr)
r |= FS_Ack;
if (spi_busy_p())
return r;
if ((r & FS_Error) == FS_Error)
if (flash_stream_done())
return r;
if (r & FS_StBsy) {
// status bytes arrived
if (~flash_status_bytes[0] & 0x80)
// flash is still busy burning
goto rd_status;
// not busy any more, move Bsy → Rdy
if (r & FS_Busy)
r |= FS_Ready;
goto ready;
}
if (!(r & FS_Busy))
if (r & FS_Ready)
goto ready;
if (rr) {
r |= FS_Error;
fs.status = r;
return r;
if (r & FS_StBsy && flash_status_bytes[0] & 0x80)
// flash is done burning
goto ready;
if (r & FS_Write && fs.block == 9) {
// Write or Erase
r |= FS_StBsy;
flash_status_bytes[0] = 0;
flash_cmd_na(0xd7 | FM_READ, 0xf002);
goto done;
}
if (r & FS_Write) {
if (fs.block == 9) {
rd_status:
// request status bytes for pending Write or Error
r |= FS_StBsy;
fs.status = r;
flash_cmd_na(0xd7 | FM_READ, 0xf002);
return r;
}
if (r & FS_Dir == FS_Write && fs.block == 8) {
// Write
r = flash_burn_page();
goto done;
}
ready:
r &= ~(FS_Busy | FS_StBsy);
if (rr)
r |= FS_Ack;
fs.status = r;
if (r & FS_Dir == FS_Write && fs.block == 8)
flash_burn_page();
else if (!flash_stream_done()) {
if (r & (FS_Dir|FS_Ack) == (FS_Read|FS_Ack))
flash_read_next_block();
else if (r & (FS_Dir|FS_Ack) == (FS_Write|FS_Ack))
flash_write_next_block();
else if (r & FS_Dir == FS_Erase)
flash_erase_next_page();
fs.status &=~ FS_Ack;
r &= ~(FS_Error | FS_StBsy);
if (!(r & FS_Ack)) {
r |= FS_Ready;
goto done;
}
return fs.status;
r &=~ FS_Ack;
if (!fs.npages && fs.block & 8)
goto done;
if ((r & FS_Dir) == FS_Read)
r = flash_read_next_block();
else if ((r & FS_Dir) == FS_Write)
r = flash_write_next_block();
else if ((r & FS_Dir) == FS_Erase)
r = flash_erase_next_page();
done:
fs.status = r;
return r;
}
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags)
@ -310,14 +293,12 @@ uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags)
if ((r & FS_Error) == FS_Busy)
return FS_Error;
r = flags | FS_Ready;
if (config.flash_page_size != FM_528)
r &=~ FS_528;
fs.page = page;
fs.block = 0;
fs.npages = npages;
flash_status_bytes[0] = 0;
fs.block = 0;
fs.status = r;
flash_status_bytes[0] = 0xff;
return flash_poll(0);
return r;
}
static inline

View file

@ -28,7 +28,6 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte);
extern uint8_t flash_buffer[FB_SIZE];
uint8_t flash_submit_command(uint8_t *cmd);
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags);
uint8_t flash_stream_done();
uint8_t flash_poll(uint8_t rr);
uint16_t flash_find_free();
@ -55,5 +54,7 @@ enum {
};
static inline uint8_t flash_current_block() { return fs.block; }
static inline uint8_t flash_stream_done()
{ return !(fs.status & FS_Error) || !(~fs.status & FS_Error); }
#endif

View file

@ -113,7 +113,6 @@ uint8_t fpga_start_read()
uint8_t n = 64 - pipe.fpga.val;
if (!n)
return n;
spi.rdata = flash_buffer + pipe.fpga.val;
n >>= 1;
if (~pipe.fpga.status & AS_CONT) {
if (!pipe.fpga.count)
@ -130,7 +129,10 @@ uint8_t fpga_start_read()
pipe.fpga.pos += n;
if (pipe.fpga.pos == pipe.fpga.size)
pipe.fpga.status &=~ AS_CONT;
spi.rdata = flash_buffer + pipe.fpga.val;
spi.rsize = n << 1;
spi.zsize += spi.rsize;
pipe.fpga.val += spi.rsize;
spi_start();
return n;

View file

@ -18,7 +18,7 @@ uint8_t pipe_busy()
// call this with cli() before sei();sleep()
if (spi_busy_p()) return 1;
if (flash_poll(0) & FS_Busy) return 1;
if (adc_poll(0)) return 1;
if (adc_busy()) return 1;
return 0;
}
@ -77,14 +77,14 @@ uint8_t pipe_poll()
// Return if next ADC reading is not yet due.
// Come back here, until is is.
if (pipe.source & pipe_adc && !adc_poll(pipe.adc))
if (pipe.source == pipe_adc && !adc_poll(pipe.adc))
goto done;
// Continue the flash stream.
// PS_BLK is the 64-Bytes buffer number in the page
valid = 0;
if (pipe.source & pipe_flash) {
if (pipe.source == pipe_flash) {
r &= ~ PS_BLK;
r |= flash_current_block() & PS_BLK;
flash_poll(1);
@ -92,9 +92,9 @@ uint8_t pipe_poll()
#ifdef HAVE_FPGA
// Continue the FPGA stream.
else if (pipe.source & pipe_fpga) {
else if (pipe.source == pipe_fpga) {
if (~fpga_start_read())
pipe.source &=~ pipe_fpga;
pipe.source = 0;
}
#endif
goto done;
@ -109,7 +109,7 @@ uint8_t pipe_poll()
bflgs = 0x1f;
// Data from the ADC is in named .bss segments. We send
// 16, 32, or 64 Bytes from the .bss segement for ead ADC reading.
// 16, 32, or 64 Bytes from the .bss segement for each ADC reading.
// The first named .bss segment is `magic`. Observe the link order
// in the Makefile.
//
@ -118,7 +118,7 @@ uint8_t pipe_poll()
// `o` is the addr in the flash_buffer
// `v` are the currently valid cmd_buffer flags
// `f` are the fresh valid cmd_buffer flags
if (pipe.source & pipe_adc) {
if (pipe.source == pipe_adc) {
uint8_t n = pipe.adc & 0x70;
if (!n)
goto adc_done;
@ -160,11 +160,11 @@ adc_done:
// When the flash is done, flag the buffer valid,
// including BCH Bytes.
if (pipe.source & pipe_flash && fs.status & FS_Ready)
if (pipe.source == pipe_flash && fs.status & FS_Ready)
valid = bflgs;
#ifdef HAVE_FPGA
// The FPGA delivers 64 Bytes.
else if (pipe.source & pipe_fpga && fpga_pipe_ready())
else if (pipe.source == pipe_fpga && fpga_pipe_ready())
valid = 0x0f;
#endif
// The buffer is not here, yet. Nothing we can do now.
@ -181,10 +181,10 @@ adc_done:
// Last buffer of the page:
if (!(~r & PS_BLK)) {
bch4369_fini();
valid = 0x01f;
// When the Flash is not the source,
// and cmd did not provide the parity
// copy the computed parity into the buffer.
if (~pipe.source & pipe_flash)
if (~valid & 0x10)
_memcopyyz(bend, bch_parity, 16);
// When the page as read from flash has invalid parity,
// stop writing to the FPGA.
@ -192,6 +192,7 @@ adc_done:
dest &=~ pipe_fpga;
r |= PS_ERR;
}
valid = 0x1f;
}
}
// We still do not have all data we need
@ -203,7 +204,7 @@ adc_done:
#ifdef HAVE_FPGA
// Resume the FPGA stream
if (dest & pipe_fpga & ~fpga_start_write())
if (dest & pipe_fpga && ~fpga_start_write())
dest &=~ pipe_fpga;
else
#endif
@ -227,7 +228,7 @@ void pipe_config(const struct pipe_config *c, const struct pipe_fpga_cmd *a)
{
/************************************************************
* cmd("B0!", «fpga-cmd») optionally configure an FPGA cmd
* cmd("P0:, «pipe-cfg») with `AS_CMD` in `.status`
* cmd("P0", «pipe-cfg») with `AS_CMD` in `.status`
***********************************************************/
if (c->pipe.dest) {
@ -238,6 +239,7 @@ void pipe_config(const struct pipe_config *c, const struct pipe_fpga_cmd *a)
else {
// new source (NOT flash)
pipe.source = c->pipe.source;
pipe.adc = c->pipe.adc;
}
if (pipe.source & pipe_adc)
adc_start_stream(pipe.adc);
@ -247,6 +249,7 @@ void pipe_config(const struct pipe_config *c, const struct pipe_fpga_cmd *a)
_memcopyzy((void*)&pipe_fpga_cmd, (void*)a, sizeof(*a));
else
memset(&pipe_fpga_cmd, 0, sizeof(*a));
pipe.fpga = c->pipe.fpga;
fpga_start_read();
}
#endif

View file

@ -387,23 +387,18 @@ ISR(SPI0_INT_vect, ISR_NAKED)
"rjmp 4f" "\n"
"1:" "\n\t"
"lds r26, %[MASK]" "\n\t"
"cpi r26, 0" "\n\t"
"breq 1f" "\n\t"
"and r26, r25" "\n\t"
"lds r24, %[WAIT]" "\n\t"
"cp r24, r26" "\n\t"
"brne 2f" "\n\t"
"lds r26, %[WAIT]" "\n\t"
"eor r26, r25" "\n\t"
"lds r24, %[MASK]" "\n\t"
"and r26, r24" "\n\t"
"breq 2f" "\n\t"
"lds r25, %[ZSZ]" "\n\t"
"subi r25, -1" "\n\t"
"sts %[ZSZ], r25" "\n\t"
"rjmp 4f" "\n"
"2:" "\n\t"
"clr r26" "\n\t"
"sts %[MASK], r26" "\n"
"1:" "\n\t"
"sts %[MASK], r26" "\n\t"
"lds r26, %[RSZ]" "\n\t"
"subi r26, 1" "\n\t"
"brcs 4f" "\n\t"

View file

@ -13,6 +13,7 @@
#include "config.h"
#include "uart.h"
#include "pipe.h"
#include "adc.h"
////////////////////////////////////////////////////////////////////////////////
//
@ -40,17 +41,18 @@ int main()
send_hex_byte_eol(magic.reset_source);
while (1) {
// The pipe may become idle before we reach sleep.
// Make sure we have nothing to do before we sleep.
// The sleep command will execute even when an irq
// is pending. It will wake us immediately.
// The irq sources may become idle before we reach sleep.
// Make sure we have nothing pending before we sleep.
// The sleep command will execute even when an irq becomes
// pending after cli(). It will wake us immediately.
cli();
if (!command_pending() && (!pipe.dest || pipe_busy())) {
if (!command_pending() || adc_busy() || spi_busy_p()) {
sei();
sleep_cpu();
}
sei();
command();
pipe_poll();
if (~magic.flags & hold_pipe)
pipe_poll();
}
}

View file

@ -61,7 +61,7 @@ class uart(threading.Thread):
def parse_line(self, l):
self.responses.append(l)
if self._verbose:
if self._verbose >= 4:
try:
s = l.decode()
print(f"{self.portname}<- {s}", file=sys.stderr)
@ -92,7 +92,7 @@ class uart(threading.Thread):
c = c.encode()
if c[-1:] != b'\n':
c = c + b'\n'
if self._verbose:
if self._verbose >= 4:
print(f"{self.portname}-> {c.decode().rstrip()}", file=sys.stderr)
self.write(c)