|
@@ -46,13 +46,16 @@ ISR(USART1_UDRE_vect)
|
|
|
static struct cas_block *blk = &block[0];
|
|
|
uint8_t pattern;
|
|
|
|
|
|
- if (!tx_bits) {
|
|
|
+ while (!tx_bits) {
|
|
|
if (!blk->ready || !motor_relay()) {
|
|
|
/* Hold the line for one pattern time, then idle */
|
|
|
UCSR1A = TX_IDLE;
|
|
|
UDR1 = parity;
|
|
|
fmtx_disable(); /* Nothing left to do */
|
|
|
return;
|
|
|
+ } else if (blk->divisor) {
|
|
|
+ fmtx_set_speed(blk->divisor);
|
|
|
+ blk->divisor = 0;
|
|
|
} else if (tx_offset < sizeof blk->data) {
|
|
|
tx_data = ((const uint8_t *)&blk->data)[tx_offset++];
|
|
|
tx_bits = 8;
|
|
@@ -63,14 +66,9 @@ ISR(USART1_UDRE_vect)
|
|
|
blk->pause--;
|
|
|
return;
|
|
|
} else {
|
|
|
- if (blk->data.blktype == 0xff &&
|
|
|
- blk->data.hdr.divisor) {
|
|
|
- fmtx_set_speed(blk->data.hdr.divisor);
|
|
|
- }
|
|
|
- blk->ready = false; /* Free to use */
|
|
|
+ blk->ready = false; /* Free buffer */
|
|
|
blk = blk->next;
|
|
|
tx_offset = 0;
|
|
|
- return; /* Will probably re-trigger immediately */
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -186,18 +184,21 @@ bool fmtx_full(void)
|
|
|
return rx_blk->ready;
|
|
|
}
|
|
|
|
|
|
-static enum rx_state setup_block(unsigned int divisor, unsigned int blkno)
|
|
|
+static void fmtx_wait_for_free_buffer(void)
|
|
|
{
|
|
|
- uint8_t blktype;
|
|
|
+ while (rx_blk->ready)
|
|
|
+ do_usb_tasks();
|
|
|
+}
|
|
|
|
|
|
- fmtx_drain();
|
|
|
- fmtx_set_speed(divisor);
|
|
|
+static enum rx_state setup_block(unsigned int blkno)
|
|
|
+{
|
|
|
+ uint8_t blktype;
|
|
|
|
|
|
rx_blk->data.blkno = blkno;
|
|
|
blktype = -(blkno == -1U);
|
|
|
rx_blk->data.blktype = blktype;
|
|
|
|
|
|
- rx_blk->pause = block_pause(blktype, divisor);
|
|
|
+ rx_blk->pause = block_pause(blktype, rx_blk->divisor);
|
|
|
|
|
|
/* Initialize checksum */
|
|
|
rx_blk->data.csum = 0x03 /* ETX is part of the checksum */
|
|
@@ -230,28 +231,38 @@ static enum rx_state do_cmd(uint8_t cmd, const uint16_t *arg)
|
|
|
case 'R':
|
|
|
/* Set receive baudrate divisor */
|
|
|
/* &R divisor */
|
|
|
- fmrx_set_speed(arg[0]);
|
|
|
+ fmtx_wait_for_free_buffer();
|
|
|
+ rx_blk->divisor = arg[0];
|
|
|
return rx_idle;
|
|
|
|
|
|
case 'H':
|
|
|
/* Send header block */
|
|
|
- /* &H divisor */
|
|
|
+ /* &H */
|
|
|
rx_blk_cnt = 1;
|
|
|
- return setup_block(arg[0], -1);
|
|
|
+ return setup_block(-1);
|
|
|
|
|
|
case 'D':
|
|
|
/* Send data block */
|
|
|
- /* &D divisor,blocknr */
|
|
|
+ /* &D blocknr */
|
|
|
rx_blk_cnt = 1;
|
|
|
- return setup_block(arg[0], arg[1]);
|
|
|
+ return setup_block(arg[0]);
|
|
|
|
|
|
case 'F':
|
|
|
+ {
|
|
|
+ uint8_t divisor;
|
|
|
+
|
|
|
/* Send file */
|
|
|
/* &F filename,blocks[,divisor] */
|
|
|
+ setup_block(-1);
|
|
|
+
|
|
|
rx_blk_cnt = arg[0];
|
|
|
- setup_block(arg[1], -1);
|
|
|
- rx_blk->data.hdr.divisor =
|
|
|
- (arg[1] == CAS_DIVISOR_ABC80) ? 0 : arg[1];
|
|
|
+ rx_blk->divisor = CAS_DIVISOR_ABC80; /* Header always slow */
|
|
|
+
|
|
|
+ divisor = arg[1];
|
|
|
+ if (divisor == CAS_DIVISOR_ABC80)
|
|
|
+ divisor = 0;
|
|
|
+
|
|
|
+ rx_blk->data.hdr.divisor = divisor;
|
|
|
memset(rx_blk->data.hdr.zero, 0, sizeof rx_blk->data.hdr.zero);
|
|
|
rx_blk->data.hdr.nblocks = rx_blk_cnt;
|
|
|
|
|
@@ -262,7 +273,17 @@ static enum rx_state do_cmd(uint8_t cmd, const uint16_t *arg)
|
|
|
|
|
|
rx_blk->ready = true;
|
|
|
rx_blk = rx_blk->next;
|
|
|
- return rx_blk_cnt ? rx_data : rx_idle;
|
|
|
+
|
|
|
+ if (!rx_blk_cnt)
|
|
|
+ return rx_idle;
|
|
|
+
|
|
|
+ if (divisor) {
|
|
|
+ fmtx_wait_for_free_buffer();
|
|
|
+ rx_blk->divisor = divisor;
|
|
|
+ }
|
|
|
+
|
|
|
+ return rx_data;
|
|
|
+ }
|
|
|
|
|
|
default:
|
|
|
return rx_idle; /* Unknown/unimplemented command */
|
|
@@ -280,6 +301,7 @@ void fmtx_recv_byte(uint8_t byte)
|
|
|
if (byte == '&')
|
|
|
rx_state = rx_cmd;
|
|
|
break;
|
|
|
+
|
|
|
case rx_cmd:
|
|
|
ctr = 0;
|
|
|
memset(arg, 0, sizeof arg);
|
|
@@ -293,6 +315,7 @@ void fmtx_recv_byte(uint8_t byte)
|
|
|
else
|
|
|
rx_state = rx_idle;
|
|
|
break;
|
|
|
+
|
|
|
case rx_filename:
|
|
|
switch (byte) {
|
|
|
case '\n':
|
|
@@ -318,6 +341,7 @@ void fmtx_recv_byte(uint8_t byte)
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
case rx_num:
|
|
|
if (byte == '\n') {
|
|
|
ctr = 0;
|
|
@@ -331,16 +355,21 @@ void fmtx_recv_byte(uint8_t byte)
|
|
|
arg[ctr] = arg[ctr]*10 + byte;
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
case rx_data:
|
|
|
rx_blk->data.data[ctr++] = byte;
|
|
|
rx_blk->data.csum += byte;
|
|
|
- if (ctr == 253) {
|
|
|
+ if (ctr >= 253) {
|
|
|
+ uint16_t nextblk = rx_blk->data.blkno + 1;
|
|
|
rx_blk->ready = true;
|
|
|
rx_blk = rx_blk->next;
|
|
|
- if (!--rx_blk_cnt) {
|
|
|
+ fmtx_enable();
|
|
|
+ if (--rx_blk_cnt) {
|
|
|
+ fmtx_wait_for_free_buffer();
|
|
|
+ setup_block(nextblk);
|
|
|
+ } else {
|
|
|
rx_state = rx_idle;
|
|
|
}
|
|
|
- fmtx_enable();
|
|
|
}
|
|
|
break;
|
|
|
}
|