mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-05-01 15:14:22 +02:00
Compare commits
2 commits
f0945b9227
...
65d615407c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65d615407c | ||
|
|
bd0238bb2d |
7 changed files with 136 additions and 128 deletions
|
|
@ -89,7 +89,7 @@ base85_encode:
|
||||||
.global mul85
|
.global mul85
|
||||||
mul85:
|
mul85:
|
||||||
# endif
|
# endif
|
||||||
|
;; TODO for SPACE: inline this
|
||||||
_mul85:
|
_mul85:
|
||||||
ldi r21, 85
|
ldi r21, 85
|
||||||
mul r25, r21
|
mul r25, r21
|
||||||
|
|
|
||||||
166
src/cmd.c
166
src/cmd.c
|
|
@ -11,14 +11,7 @@
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
|
|
||||||
uint8_t cmd_buffer[16];
|
uint8_t cmd_buffer[16];
|
||||||
uint8_t cmd_buffer_valid;
|
uint8_t flash_buffer_valid;
|
||||||
|
|
||||||
static __attribute__((noinline))
|
|
||||||
const uint8_t *skip_space(const uint8_t *s) {
|
|
||||||
if (*s == ' ')
|
|
||||||
s++;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t base85_str[6];
|
uint8_t base85_str[6];
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -69,23 +62,11 @@ void base85_send_buffer(const uint8_t *buf)
|
||||||
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;
|
||||||
s = skip_space(s);
|
|
||||||
for (int i=0; !base85_error && i<FB_SIZE; i+=4)
|
for (int i=0; !base85_error && i<FB_SIZE; i+=4)
|
||||||
s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
|
s = base85_decode(s, (uint32_t *)(cmd_buffer + i));
|
||||||
s = skip_space(s);
|
|
||||||
return 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 * poke_addr;
|
||||||
uint8_t peek_size;
|
uint8_t peek_size;
|
||||||
struct peak_poke {
|
struct peak_poke {
|
||||||
|
|
@ -132,95 +113,122 @@ uint8_t poke(struct peak_poke *p, uint8_t hp, uint8_t poke)
|
||||||
return s && !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)
|
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++;
|
uint8_t cmd = *s++;
|
||||||
if (*s =='`')
|
if (cmd < 'A' || cmd > 'Z')
|
||||||
return;
|
return;
|
||||||
uint8_t r = 0x08|cmd;
|
send_char('#');
|
||||||
send_char('`');
|
|
||||||
send_char(cmd);
|
send_char(cmd);
|
||||||
uint8_t have_b = !(cmd & 0x20);
|
uint8_t bflg = *s - '0';
|
||||||
cmd |= 0x20;
|
uint8_t *bptr = cmd_buffer;
|
||||||
if (cmd > 'z')
|
if (bflg <= 5) {
|
||||||
goto error;
|
bptr = flash_buffer + 16*bflg;
|
||||||
if (have_b) {
|
bflg = 1<<bflg;
|
||||||
s = base85_fill_buffer(s);
|
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) {
|
if (base85_error) {
|
||||||
r = base85_error;
|
r = base85_error;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
cmd_buffer_valid |= 0x80;
|
have_b = 1;
|
||||||
}
|
}
|
||||||
s = skip_space(s);
|
if (*s != '\n')
|
||||||
uint8_t flag = *s++;
|
goto error;
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case 'a':
|
case 'A':
|
||||||
r = adc_current;
|
r = adc_current;
|
||||||
if (r >= N_ADC) {
|
if (r >= N_ADC) {
|
||||||
if (flag=='=') {
|
if (cmd_flag('<'))
|
||||||
memcpy(cmd_buffer, adc_readings, 16);
|
|
||||||
cmd_buffer_valid |= 0x40;
|
|
||||||
flag = *s++;
|
|
||||||
}
|
|
||||||
if (flag == '<') {
|
|
||||||
base85_send_buffer((void*)adc_readings);
|
base85_send_buffer((void*)adc_readings);
|
||||||
flag = *s++;
|
if (cmd_flag('!'))
|
||||||
}
|
|
||||||
if (flag == '+')
|
|
||||||
start_adc();
|
start_adc();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'B':
|
||||||
r = cmd_buffer_valid;
|
if (have_b && bflg) {
|
||||||
if (have_b) {
|
if (cmd_flag('|'))
|
||||||
flag -= '0';
|
flash_buffer_valid |= bflg;
|
||||||
if (flag < 5 && flag==cmd_buffer_valid) {
|
memcpy(bptr, cmd_buffer, 16);
|
||||||
memcpy(flash_buffer+16*flag, cmd_buffer, 16);
|
|
||||||
r = cmd_buffer_valid |= 1<<flag;
|
|
||||||
flag = *++s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (flag == '%') {
|
if (cmd_flag('%')) {
|
||||||
if (*s=='<')
|
if (cmd_flag('!'))
|
||||||
base85_send_buffer(bch_parity);
|
memset(bch_parity, 0, 16);
|
||||||
if (have_b)
|
bch4369_str(bptr, 16);
|
||||||
bch4369_feed_buffer(*++s);
|
|
||||||
}
|
}
|
||||||
else if (flag == '<') {
|
if (cmd_flag('<')) {
|
||||||
flag = *s - '0';
|
if (cmd_flag('|'))
|
||||||
uint8_t *b;
|
flash_buffer_valid &=~ bflg;
|
||||||
if (flag < 5)
|
base85_send_buffer(bptr);
|
||||||
b = flash_buffer + 16*flag;
|
|
||||||
else {
|
|
||||||
b = cmd_buffer;
|
|
||||||
}
|
|
||||||
base85_send_buffer(b);
|
|
||||||
}
|
}
|
||||||
|
r = flash_buffer_valid;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'F':
|
||||||
if (have_b) {
|
if (have_b)
|
||||||
r = flash_submit_command(cmd_buffer);
|
r = flash_submit_command(cmd_buffer);
|
||||||
cmd_buffer_valid &=~ 0x80;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
r = flash_poll(flag=='!');
|
r = flash_poll(cmd_flag('!'));
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'P':
|
||||||
if (have_b) {
|
if (have_b)
|
||||||
r = pipe_config(cmd_buffer, flag);
|
r = pipe_config(cmd_buffer);
|
||||||
cmd_buffer_valid &= ~0x80;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
r = pipe_poll(flag=='!');
|
r = pipe_poll(cmd_flag('!'));
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'M':
|
||||||
if (poke((void*)cmd_buffer, have_b, have_b && flag=='!'))
|
if (poke((void*)cmd_buffer, have_b, have_b && cmd_flag('!')))
|
||||||
base85_send_buffer(cmd_buffer);
|
base85_send_buffer(cmd_buffer);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error:
|
error:
|
||||||
send_char('?');
|
send_char('?');
|
||||||
}
|
}
|
||||||
send_hex_byte_eol(r);
|
send_hex_byte_eol(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
13
src/flash.c
13
src/flash.c
|
|
@ -264,12 +264,6 @@ void bch_flash_init()
|
||||||
uint8_t flash_poll(uint8_t rr)
|
uint8_t flash_poll(uint8_t rr)
|
||||||
{
|
{
|
||||||
uint8_t r = fs.status;
|
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)
|
if ((r & FS_Error) == FS_Error)
|
||||||
return r;
|
return r;
|
||||||
if (r & FS_StBsy) {
|
if (r & FS_StBsy) {
|
||||||
|
|
@ -285,7 +279,6 @@ uint8_t flash_poll(uint8_t rr)
|
||||||
if (!(r & FS_Busy))
|
if (!(r & FS_Busy))
|
||||||
goto ready;
|
goto ready;
|
||||||
if (rr) {
|
if (rr) {
|
||||||
collision:
|
|
||||||
r |= FS_Error;
|
r |= FS_Error;
|
||||||
fs.status = r;
|
fs.status = r;
|
||||||
return r;
|
return r;
|
||||||
|
|
@ -311,11 +304,12 @@ uint8_t flash_poll(uint8_t rr)
|
||||||
}
|
}
|
||||||
|
|
||||||
ready:
|
ready:
|
||||||
|
r &= ~(FS_Busy | FS_StBsy);
|
||||||
if (rr)
|
if (rr)
|
||||||
r |= FS_Ack;
|
r |= FS_Ack;
|
||||||
// clear the Bsy bits
|
|
||||||
r &= ~(FS_Busy | FS_StBsy);
|
|
||||||
fs.status = r;
|
fs.status = r;
|
||||||
|
if (spi_busy_p())
|
||||||
|
return r;
|
||||||
if (r & FS_Dir == FS_Write && fs.block == 8)
|
if (r & FS_Dir == FS_Write && fs.block == 8)
|
||||||
flash_burn_page();
|
flash_burn_page();
|
||||||
else if (!flash_stream_done()) {
|
else if (!flash_stream_done()) {
|
||||||
|
|
@ -331,6 +325,7 @@ ready:
|
||||||
}
|
}
|
||||||
else if (r & FS_Dir == FS_Erase)
|
else if (r & FS_Dir == FS_Erase)
|
||||||
flash_erase_next_page();
|
flash_erase_next_page();
|
||||||
|
fs.status &=~ FS_Ack;
|
||||||
}
|
}
|
||||||
return fs.status;
|
return fs.status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include <pipe.h>
|
#include "pipe.h"
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
struct pipe pipe;
|
struct pipe pipe;
|
||||||
|
|
||||||
|
|
@ -11,12 +12,15 @@ struct pipe_config {
|
||||||
uint8_t flash_page;
|
uint8_t flash_page;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t pipe_config(const uint8_t *, uint8_t flag)
|
uint8_t pipe_config(const uint8_t *)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint8_t pipe_poll(uint8_t flag)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#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);
|
uint8_t pipe_poll(uint8_t flag);
|
||||||
|
|
||||||
enum pipe_ports {
|
enum pipe_ports {
|
||||||
|
|
|
||||||
11
src/uart.c
11
src/uart.c
|
|
@ -51,7 +51,7 @@ ISR(USART0_DRE_vect)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
__attribute__ ((noinline, noclone))
|
__attribute__ ((noinline, naked))
|
||||||
void tx()
|
void tx()
|
||||||
{
|
{
|
||||||
// This uses only three registers, to save stack in the ISR.
|
// This uses only three registers, to save stack in the ISR.
|
||||||
|
|
@ -76,13 +76,13 @@ void tx()
|
||||||
" lds r31, uart_tx_w \n"
|
" lds r31, uart_tx_w \n"
|
||||||
" cp r30, r31 \n"
|
" cp r30, r31 \n"
|
||||||
" breq 3f \n"
|
" breq 3f \n"
|
||||||
" lds r30, %[STATUS] \n"
|
" lds r31, %[STATUS] \n"
|
||||||
" sbrc r30, %[DRE] \n"
|
" sbrc r31, %[DRE] \n"
|
||||||
" rjmp 1b \n"
|
" rjmp 1b \n"
|
||||||
" ori r25, 1<<%[DRE] \n"
|
" ori r25, 1<<%[DRE] \n"
|
||||||
"3: \n"
|
"3: \n"
|
||||||
" sts %[CTRLA], r25 \n"
|
" sts %[CTRLA], r25 \n"
|
||||||
" sts uart_tx_r, r21 \n"
|
" ret \n"
|
||||||
:
|
:
|
||||||
:
|
:
|
||||||
[TXC] "n" (USART_TXCIF_bp),
|
[TXC] "n" (USART_TXCIF_bp),
|
||||||
|
|
@ -96,8 +96,7 @@ void tx()
|
||||||
|
|
||||||
ISR(USART0_DRE_vect, ISR_NAKED)
|
ISR(USART0_DRE_vect, ISR_NAKED)
|
||||||
{
|
{
|
||||||
// Doing this naked is a bit dangerous,
|
// This saves five instructions and two bytes stack (r0, r1).
|
||||||
// but saves five instructions and two bytes stack (r0, r1).
|
|
||||||
// OTOH, the C implementation of tx() is not bad either,
|
// OTOH, the C implementation of tx() is not bad either,
|
||||||
// if we are doing this asm, then we do it agressively.
|
// if we are doing this asm, then we do it agressively.
|
||||||
__asm__("\n"
|
__asm__("\n"
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
.global send_hex_byte
|
.global send_hex_byte
|
||||||
.global send_hex_byte_eol
|
.global send_hex_byte_eol
|
||||||
.global send_char
|
.global send_char
|
||||||
|
.global _send_char22
|
||||||
.global send_str
|
.global send_str
|
||||||
.global _send_str26
|
.global _send_str26
|
||||||
.global uart_busy
|
.global uart_busy
|
||||||
|
|
@ -17,37 +18,16 @@
|
||||||
|
|
||||||
// `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.
|
||||||
|
|
||||||
put_char:
|
// r18, r26, and 27 must be preseved in the hex functions
|
||||||
// non-global, non-C
|
// …, r20, r21, r24, must be preserved in `uart_busy()` and `put_char()'
|
||||||
// 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()'
|
|
||||||
|
|
||||||
send_hex_byte_eol:
|
send_hex_byte_eol:
|
||||||
ldi r22, ' '
|
ldi r22, ' '
|
||||||
rcall send_char22
|
rcall _send_char22
|
||||||
rcall send_hex_byte
|
rcall send_hex_byte
|
||||||
send_eol:
|
send_eol:
|
||||||
ldi r22, '\n'
|
ldi r22, '\n'
|
||||||
rcall send_char22
|
rcall _send_char22
|
||||||
uart_busy:
|
uart_busy:
|
||||||
cli
|
cli
|
||||||
rcall tx ; gobbles r25, r30, and r31
|
rcall tx ; gobbles r25, r30, and r31
|
||||||
|
|
@ -57,11 +37,13 @@ uart_busy:
|
||||||
9:
|
9:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#ifdef HEX_WORD
|
||||||
send_hex_word:
|
send_hex_word:
|
||||||
mov r20, r24
|
mov r20, r24
|
||||||
mov r24, r25
|
mov r24, r25
|
||||||
rcall send_hex_byte
|
rcall send_hex_byte
|
||||||
mov r24, r20
|
mov r24, r20
|
||||||
|
#endif
|
||||||
send_hex_byte:
|
send_hex_byte:
|
||||||
mov r21, r24
|
mov r21, r24
|
||||||
swap r24
|
swap r24
|
||||||
|
|
@ -75,24 +57,43 @@ send_hex_nibble:
|
||||||
subi r24, '9'+1-'A'
|
subi r24, '9'+1-'A'
|
||||||
send_char:
|
send_char:
|
||||||
mov r22, r24
|
mov r22, r24
|
||||||
send_char22:
|
rjmp _send_char22
|
||||||
rcall put_char
|
1:
|
||||||
brne 9f
|
|
||||||
rcall uart_busy
|
rcall uart_busy
|
||||||
sleep
|
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:
|
send_str:
|
||||||
movw r26, r24
|
movw r26, r24
|
||||||
rjmp _send_str26
|
rjmp _send_str26
|
||||||
1:
|
1:
|
||||||
rcall send_char22
|
__send_char22_str26:
|
||||||
|
rcall _send_char22
|
||||||
_send_str26:
|
_send_str26:
|
||||||
ld r22, X+
|
ld r22, X+
|
||||||
tst r22
|
tst r22
|
||||||
brne 1b
|
brne 1b
|
||||||
|
9:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#ifdef SEND_HEX
|
||||||
send_hex:
|
send_hex:
|
||||||
movw r26, r24
|
movw r26, r24
|
||||||
mov r18, r22
|
mov r18, r22
|
||||||
|
|
@ -103,6 +104,7 @@ send_hex:
|
||||||
brcc 1b
|
brcc 1b
|
||||||
9:
|
9:
|
||||||
ret
|
ret
|
||||||
|
#endif
|
||||||
|
|
||||||
command:
|
command:
|
||||||
;; when any frame errors occured, dismiss the buffer
|
;; when any frame errors occured, dismiss the buffer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue