X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=ROM2%2Fsci.c;h=fe59f75b1b6c478a9cfaa5d5e7ebbbec1ce77e4a;hb=31352d878e591a3e7deb159fd9b65a2fb6706fa9;hp=3241f23c2cd971b34b6a31f7705ebfe8b5ab1426;hpb=c34cbe163ce52f1d8fc553993701054f4942152f;p=uccvend-snackrom.git diff --git a/ROM2/sci.c b/ROM2/sci.c index 3241f23..fe59f75 100644 --- a/ROM2/sci.c +++ b/ROM2/sci.c @@ -5,6 +5,9 @@ char sci_tx_buf[BUFFER_LEN]; volatile char sci_rx_buf[BUFFER_LEN]; volatile bool sci_have_packet; volatile u8 sci_rx_buf_ptr; +volatile u8 sci_rx_buf_ptr_start; +volatile bool sci_echo; +bool sci_doing_xmodem; void sci_init() { /* assumes clock of 4.91Mhz */ @@ -14,13 +17,16 @@ void sci_init() { _io_ports[M6811_SCCR1] = 0; /* Enable reciever and transmitter & rx interrupt. */ - _io_ports[M6811_SCCR2] = 0x2c; + _io_ports[M6811_SCCR2] = M6811_RIE | M6811_TE | M6811_RE; sci_have_packet = 0; sci_rx_buf_ptr = 0; + sci_rx_buf_ptr_start = 0; + sci_echo = 0; + sci_doing_xmodem = 0; } -void send_packet() { +void send_buffer(bool crlf) { char* c; for (c = sci_tx_buf; *c; c++) { /* wait for TX ready */ @@ -29,24 +35,62 @@ void send_packet() { /* send byte */ _io_ports[M6811_SCDR] = *c; } + if (!crlf) return; + /* send CRLF */ + while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); + _io_ports[M6811_SCDR] = '\r'; + while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); + _io_ports[M6811_SCDR] = '\n'; } -void rx_int() { - if (sci_have_packet) return; - if (sci_rx_buf_ptr >= BUFFER_LEN) { +void send_string(char* c) { + for (; *c; c++) { + while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); /* wait for TX ready */ + _io_ports[M6811_SCDR] = *c; /* send byte */ + } +} + +void sci_rx_int() { + char buf = _io_ports[M6811_SCDR]; + if (sci_doing_xmodem) { + if ((sci_rx_buf_ptr+1)%BUFFER_LEN == sci_rx_buf_ptr_start) { + /* we drop following bytes :( */ + return; + } + sci_rx_buf[sci_rx_buf_ptr] = buf; + sci_rx_buf_ptr++; + sci_rx_buf_ptr %= BUFFER_LEN; + return; + } + if (sci_echo) { + while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); /* wait for TX ready */ + _io_ports[M6811_SCDR] = buf; /* send byte */ + } + + /* XXX FIXME we should do something about errors. nack? */ + if (sci_have_packet) { /* overrun :( */ - sci_rx_buf[BUFFER_LEN] = '\0'; - sci_have_packet = 1; - sci_rx_buf_ptr = 0; return; } - sci_rx_buf[sci_rx_buf_ptr] = _io_ports[M6811_SCDR]; - if (sci_rx_buf[sci_rx_buf_ptr] == '\n') { + sci_rx_buf[sci_rx_buf_ptr] = buf; + + if (buf == '\n' || buf == '\r') { sci_rx_buf[sci_rx_buf_ptr] = '\0'; sci_have_packet = 1; - sci_rx_buf_ptr = 0; } - sci_rx_buf_ptr++; + + if (sci_rx_buf_ptr+1 < BUFFER_LEN) + sci_rx_buf_ptr++; + else { + sci_rx_buf[BUFFER_LEN-1] = '\0'; /* this is as much as we could fit */ + } +} + +void sci_interrupt_serial() { + if (_io_ports[M6811_SCSR] & M6811_RDRF) sci_rx_int(); + + if (_io_ports[M6811_SCSR] & M6811_OR) + _io_ports[M6811_SCDR]; /* declare it a lost cause */ } void msg_clr() { @@ -54,20 +98,32 @@ void msg_clr() { sci_rx_buf_ptr = 0; } -void sci_interrupt_serial() { - if (_io_ports[M6811_SCSR] & M6811_RDRF) rx_int(); -} - void send_ack() { - sci_tx_buf[0] = '!'; - sci_tx_buf[1] = '\n'; - sci_tx_buf[2] = '\0'; - send_packet(); + send_string("!" CRLF); } void send_nack() { - sci_tx_buf[0] = '?'; - sci_tx_buf[1] = '\n'; - sci_tx_buf[2] = '\0'; - send_packet(); + send_string("?" CRLF); +} + +u16 sci_timer; +void serial_rti() { /* called every 6.6 ms */ + if (sci_timer) sci_timer--; +} + +/* for gdb compatibility */ +int serial_readchar(u8 timeout) { + sci_timer = timeout * 152; + while (sci_timer && sci_rx_buf_ptr_start == sci_rx_buf_ptr); /* spin */ + if (sci_timer == 0) return SERIAL_TIMEOUT; + return sci_rx_buf[sci_rx_buf_ptr_start++]; +} + +void serial_write(const char *str, int len) { + char *c, *end; + end = (char*)(str + len); + for (c = (char*)str; c < end; c++) { + while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); /* wait for TX ready */ + _io_ports[M6811_SCDR] = *c; /* send byte */ + } }