Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
65d615407c parse_command refactor 2026-01-06 13:58:50 +01:00
Stephan I. Böttcher
bd0238bb2d fixes and cleanups 2026-01-06 00:11:01 +01:00
7 changed files with 136 additions and 128 deletions

View file

@ -89,7 +89,7 @@ base85_encode:
.global mul85
mul85:
# endif
;; TODO for SPACE: inline this
_mul85:
ldi r21, 85
mul r25, r21

166
src/cmd.c
View file

@ -11,14 +11,7 @@
#include "pipe.h"
uint8_t cmd_buffer[16];
uint8_t cmd_buffer_valid;
static __attribute__((noinline))
const uint8_t *skip_space(const uint8_t *s) {
if (*s == ' ')
s++;
return s;
}
uint8_t flash_buffer_valid;
uint8_t base85_str[6];
#if 0
@ -69,23 +62,11 @@ void base85_send_buffer(const uint8_t *buf)
static inline
const uint8_t *base85_fill_buffer(const uint8_t *s) {
base85_error = 0;
s = skip_space(s);
for (int i=0; !base85_error && i<FB_SIZE; i+=4)
s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
s = skip_space(s);
return s;
}
static inline
void bch4369_feed_buffer(uint8_t flag)
{
if (flag=='0') {
memset(bch_parity, 0, 16);
}
bch4369_str(cmd_buffer,16);
}
uint8_t * poke_addr;
uint8_t peek_size;
struct peak_poke {
@ -132,95 +113,122 @@ uint8_t poke(struct peak_poke *p, uint8_t hp, uint8_t poke)
return s && !poke;
}
const uint8_t *cmd_flags;
#if 0
static __attribute__((noinline))
uint8_t cmd_flag(uint8_t f)
{
if (*cmd_flags == f) {
cmd_flags++;
send_char(f);
return f;
}
return 0;
}
#else
static __attribute__((noinline, naked))
uint8_t cmd_flag(uint8_t f)
{
// _send_char22 does not gobble r24.
__asm__(
""
"lds r30, cmd_flags" "\n\t"
"lds r31, cmd_flags+1" "\n\t"
"ld r22, Z+" "\n\t"
"cp r22, r24" "\n\t"
"mov r24, r1" "\n\t"
"brne 9f" "\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"
);
}
#endif
void parse_command(const uint8_t *s, uint8_t n)
{
// ^[A-Z][!-@]+( [!-u]{20}])?$
// cmd flags base85
uint8_t r = 0;
uint8_t cmd = *s++;
if (*s =='`')
if (cmd < 'A' || cmd > 'Z')
return;
uint8_t r = 0x08|cmd;
send_char('`');
send_char('#');
send_char(cmd);
uint8_t have_b = !(cmd & 0x20);
cmd |= 0x20;
if (cmd > 'z')
goto error;
if (have_b) {
s = base85_fill_buffer(s);
uint8_t bflg = *s - '0';
uint8_t *bptr = cmd_buffer;
if (bflg <= 5) {
bptr = flash_buffer + 16*bflg;
bflg = 1<<bflg;
s++;
}
else
bflg = 0;
cmd_flags = s;
while (*s > ' ' && *s < 'A')
s++;
uint8_t have_b = 0;
if (*s==' ') {
s = base85_fill_buffer(s+1);
if (base85_error) {
r = base85_error;
goto error;
}
cmd_buffer_valid |= 0x80;
have_b = 1;
}
s = skip_space(s);
uint8_t flag = *s++;
if (*s != '\n')
goto error;
switch(cmd) {
case 'a':
case 'A':
r = adc_current;
if (r >= N_ADC) {
if (flag=='=') {
memcpy(cmd_buffer, adc_readings, 16);
cmd_buffer_valid |= 0x40;
flag = *s++;
}
if (flag == '<') {
if (cmd_flag('<'))
base85_send_buffer((void*)adc_readings);
flag = *s++;
}
if (flag == '+')
if (cmd_flag('!'))
start_adc();
}
break;
case 'b':
r = cmd_buffer_valid;
if (have_b) {
flag -= '0';
if (flag < 5 && flag==cmd_buffer_valid) {
memcpy(flash_buffer+16*flag, cmd_buffer, 16);
r = cmd_buffer_valid |= 1<<flag;
flag = *++s;
}
case 'B':
if (have_b && bflg) {
if (cmd_flag('|'))
flash_buffer_valid |= bflg;
memcpy(bptr, cmd_buffer, 16);
}
if (flag == '%') {
if (*s=='<')
base85_send_buffer(bch_parity);
if (have_b)
bch4369_feed_buffer(*++s);
if (cmd_flag('%')) {
if (cmd_flag('!'))
memset(bch_parity, 0, 16);
bch4369_str(bptr, 16);
}
else if (flag == '<') {
flag = *s - '0';
uint8_t *b;
if (flag < 5)
b = flash_buffer + 16*flag;
else {
b = cmd_buffer;
}
base85_send_buffer(b);
if (cmd_flag('<')) {
if (cmd_flag('|'))
flash_buffer_valid &=~ bflg;
base85_send_buffer(bptr);
}
r = flash_buffer_valid;
break;
case 'f':
if (have_b) {
case 'F':
if (have_b)
r = flash_submit_command(cmd_buffer);
cmd_buffer_valid &=~ 0x80;
}
else
r = flash_poll(flag=='!');
r = flash_poll(cmd_flag('!'));
break;
case 'p':
if (have_b) {
r = pipe_config(cmd_buffer, flag);
cmd_buffer_valid &= ~0x80;
}
case 'P':
if (have_b)
r = pipe_config(cmd_buffer);
else
r = pipe_poll(flag=='!');
r = pipe_poll(cmd_flag('!'));
break;
case 'm':
if (poke((void*)cmd_buffer, have_b, have_b && flag=='!'))
case 'M':
if (poke((void*)cmd_buffer, have_b, have_b && cmd_flag('!')))
base85_send_buffer(cmd_buffer);
break;
default:
error:
send_char('?');
}
send_hex_byte_eol(r);
}

View file

@ -264,12 +264,6 @@ void bch_flash_init()
uint8_t flash_poll(uint8_t rr)
{
uint8_t r = fs.status;
if (spi_busy_p()) {
if (rr)
goto collision;
fs.status = r | FS_Busy;
return r;
}
if ((r & FS_Error) == FS_Error)
return r;
if (r & FS_StBsy) {
@ -285,7 +279,6 @@ uint8_t flash_poll(uint8_t rr)
if (!(r & FS_Busy))
goto ready;
if (rr) {
collision:
r |= FS_Error;
fs.status = r;
return r;
@ -311,11 +304,12 @@ uint8_t flash_poll(uint8_t rr)
}
ready:
r &= ~(FS_Busy | FS_StBsy);
if (rr)
r |= FS_Ack;
// clear the Bsy bits
r &= ~(FS_Busy | FS_StBsy);
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()) {
@ -331,6 +325,7 @@ ready:
}
else if (r & FS_Dir == FS_Erase)
flash_erase_next_page();
fs.status &=~ FS_Ack;
}
return fs.status;
}

View file

@ -1,5 +1,6 @@
#include <pipe.h>
#include "pipe.h"
#include "flash.h"
struct pipe pipe;
@ -11,12 +12,15 @@ struct pipe_config {
uint8_t flash_page;
};
uint8_t pipe_config(const uint8_t *, uint8_t flag)
uint8_t pipe_config(const uint8_t *)
{
return 0;
}
uint8_t pipe_poll(uint8_t flag)
{
uint8_t r = pipe.status;
if (spi_busy_p() || flash_poll(0) & FS_Busy)
return r;
return 0;
}

View file

@ -1,7 +1,7 @@
#include <stdint.h>
uint8_t pipe_config(const uint8_t *, uint8_t flag);
uint8_t pipe_config(const uint8_t *);
uint8_t pipe_poll(uint8_t flag);
enum pipe_ports {

View file

@ -51,7 +51,7 @@ ISR(USART0_DRE_vect)
#else
__attribute__ ((noinline, noclone))
__attribute__ ((noinline, naked))
void tx()
{
// This uses only three registers, to save stack in the ISR.
@ -76,13 +76,13 @@ void tx()
" lds r31, uart_tx_w \n"
" cp r30, r31 \n"
" breq 3f \n"
" lds r30, %[STATUS] \n"
" sbrc r30, %[DRE] \n"
" lds r31, %[STATUS] \n"
" sbrc r31, %[DRE] \n"
" rjmp 1b \n"
" ori r25, 1<<%[DRE] \n"
"3: \n"
" sts %[CTRLA], r25 \n"
" sts uart_tx_r, r21 \n"
" ret \n"
:
:
[TXC] "n" (USART_TXCIF_bp),
@ -96,8 +96,7 @@ void tx()
ISR(USART0_DRE_vect, ISR_NAKED)
{
// Doing this naked is a bit dangerous,
// but saves five instructions and two bytes stack (r0, r1).
// This saves five instructions and two bytes stack (r0, r1).
// OTOH, the C implementation of tx() is not bad either,
// if we are doing this asm, then we do it agressively.
__asm__("\n"

View file

@ -9,6 +9,7 @@
.global send_hex_byte
.global send_hex_byte_eol
.global send_char
.global _send_char22
.global send_str
.global _send_str26
.global uart_busy
@ -17,37 +18,16 @@
// `tx()` and `put_char()` do not gobble r18, r20, r21, r22, r24, r26, and r27.
put_char:
// non-global, non-C
// arg: char r22
lds r23, uart_tx_r
lds r30, uart_tx_w
ldi r19, 1
add r19, r30
eor r23, r19
andi r30, 0x1f // uart_tx_m
ldi r31, 0
subi r30, lo8(-(uart_tx))
sbci r31, hi8(-(uart_tx))
andi r23, 0x1f // uart_tx_m
breq 1f
st Z, r22
sts uart_tx_w, r19
1:
// r22 preserved
// r23 full when zero
ret
// r18, r26, and 27 must be preseved in the hex functions
// , r20, r21, r24, must be preserved in `uart_busy()` and `put_char()'
// r18, r26, and 27 must be preseved in the hex functions
// , r20, r21, r24, must be preserved in `uart_busy()` and `put_char()'
send_hex_byte_eol:
ldi r22, ' '
rcall send_char22
rcall _send_char22
rcall send_hex_byte
send_eol:
ldi r22, '\n'
rcall send_char22
rcall _send_char22
uart_busy:
cli
rcall tx ; gobbles r25, r30, and r31
@ -57,11 +37,13 @@ uart_busy:
9:
ret
#ifdef HEX_WORD
send_hex_word:
mov r20, r24
mov r24, r25
rcall send_hex_byte
mov r24, r20
#endif
send_hex_byte:
mov r21, r24
swap r24
@ -75,24 +57,43 @@ send_hex_nibble:
subi r24, '9'+1-'A'
send_char:
mov r22, r24
send_char22:
rcall put_char
brne 9f
rjmp _send_char22
1:
rcall uart_busy
sleep
rjmp send_char22
_send_char22:
// non-global, non-C
// arg: char r22
lds r23, uart_tx_r
lds r30, uart_tx_w
ldi r19, 1
add r19, r30
sub r23, r19
andi r30, 0x1f // uart_tx_m
ldi r31, 0
subi r30, lo8(-(uart_tx))
sbci r31, hi8(-(uart_tx))
subi r23, 0xe0
brcs 1b
st Z, r22
sts uart_tx_w, r19
9:
ret
send_str:
movw r26, r24
rjmp _send_str26
1:
rcall send_char22
__send_char22_str26:
rcall _send_char22
_send_str26:
ld r22, X+
tst r22
brne 1b
9:
ret
#ifdef SEND_HEX
send_hex:
movw r26, r24
mov r18, r22
@ -103,6 +104,7 @@ send_hex:
brcc 1b
9:
ret
#endif
command:
;; when any frame errors occured, dismiss the buffer