ibmpc: Replace unit16_t recv_data with ringbuf

This commit is contained in:
tmk 2021-06-20 00:38:29 +09:00
parent d13ce4d06f
commit c3a0141878

View file

@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "debug.h" #include "debug.h"
#include "timer.h" #include "timer.h"
#include "wait.h" #include "wait.h"
#include "ringbuf.h"
#define WAIT(stat, us, err) do { \ #define WAIT(stat, us, err) do { \
@ -60,15 +61,11 @@ volatile uint16_t ibmpc_isr_debug = 0;
volatile uint8_t ibmpc_protocol = IBMPC_PROTOCOL_NO; volatile uint8_t ibmpc_protocol = IBMPC_PROTOCOL_NO;
volatile uint8_t ibmpc_error = IBMPC_ERR_NONE; volatile uint8_t ibmpc_error = IBMPC_ERR_NONE;
/* 2-byte buffer for data received from keyboard /* buffer for data received from device */
* buffer states: #define RINGBUF_SIZE 16
* FFFF: empty static uint8_t rbuf[RINGBUF_SIZE];
* FFss: one data static ringbuf_t rb = {};
* sstt: two data
* eeFF: error
* where ss, tt and ee are 0x00-0xFE. 0xFF means empty or no data in buffer.
*/
static volatile uint16_t recv_data = 0xFFFF;
/* internal state of receiving data */ /* internal state of receiving data */
static volatile uint16_t isr_state = 0x8000; static volatile uint16_t isr_state = 0x8000;
static uint8_t timer_start = 0; static uint8_t timer_start = 0;
@ -80,6 +77,7 @@ void ibmpc_host_init(void)
inhibit(); inhibit();
IBMPC_INT_INIT(); IBMPC_INT_INIT();
IBMPC_INT_OFF(); IBMPC_INT_OFF();
ringbuf_init(&rb, rbuf, RINGBUF_SIZE);
} }
void ibmpc_host_enable(void) void ibmpc_host_enable(void)
@ -180,60 +178,19 @@ ERROR:
*/ */
int16_t ibmpc_host_recv(void) int16_t ibmpc_host_recv(void)
{ {
uint16_t data = 0; int16_t ret = -1;
uint8_t ret = 0xFF;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { // Enable ISR if buffer was full
data = recv_data; if (ringbuf_is_full(&rb)) {
// remove data from buffer:
// FFFF(empty) -> FFFF
// FFss(one data) -> FFFF
// sstt(two data) -> FFtt
// eeFF(errror) -> FFFF
recv_data = data | (((data&0xFF00) == 0xFF00) ? 0x00FF : 0xFF00);
}
if ((data&0x00FF) == 0x00FF) {
// error: eeFF
switch (data>>8) {
case IBMPC_ERR_FF:
// 0xFF(Overrun/Error) from keyboard
dprintf("!FF! ");
ret = 0xFF;
break;
case IBMPC_ERR_FULL:
// buffer overflow
dprintf("!OVF! ");
ret = 0xFF;
break;
case 0xFF:
// empty: FFFF
return -1;
default:
// other errors
dprintf("e%02X ", data>>8);
return -1;
}
} else {
if ((data | 0x00FF) != 0xFFFF) {
// two data: sstt
dprintf("b:%04X ", data);
ret = (data>>8);
} else {
// one data: FFss
ret = (data&0x00FF);
}
}
// Enable ISR if recv_data is not full
if ((recv_data | 0x00FF) == 0xFFFF) {
ibmpc_host_isr_clear(); ibmpc_host_isr_clear();
IBMPC_INT_ON(); IBMPC_INT_ON();
idle(); idle();
} }
//dprintf("i%04X ", ibmpc_isr_debug); ibmpc_isr_debug = 0;
dprintf("r%02X ", ret); ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
ret = ringbuf_get(&rb);
}
if (ret != -1) dprintf("r%02X ", ret&0xFF);
return ret; return ret;
} }
@ -254,7 +211,7 @@ void ibmpc_host_isr_clear(void)
ibmpc_protocol = 0; ibmpc_protocol = 0;
ibmpc_error = 0; ibmpc_error = 0;
isr_state = 0x8000; isr_state = 0x8000;
recv_data = 0xFFFF; ringbuf_reset(&rb);
} }
#define LO8(w) (*((uint8_t *)&(w))) #define LO8(w) (*((uint8_t *)&(w)))
@ -407,32 +364,19 @@ ISR(IBMPC_INT_VECT)
break; break;
} }
ERROR:
// error: eeFF
recv_data = (ibmpc_error<<8) | 0x00FF;
goto CLEAR;
DONE: DONE:
if ((isr_state & 0x00FF) == 0x00FF) { // store data
// receive error code 0xFF if (!ringbuf_put(&rb, isr_state & 0xFF)) {
ibmpc_error = IBMPC_ERR_FF;
goto ERROR;
}
if (HI8(recv_data) != 0xFF && LO8(recv_data) != 0xFF) {
// buffer overflow // buffer overflow
ibmpc_error = IBMPC_ERR_FULL; ibmpc_error = IBMPC_ERR_FULL;
goto ERROR;
} // Disable ISR if buffer is full
// store data
recv_data = recv_data<<8;
recv_data |= isr_state & 0xFF;
CLEAR:
// Disable ISR if recv_data is full
if ((recv_data | 0x00FF) != 0xFFFF) {
IBMPC_INT_OFF(); IBMPC_INT_OFF();
// inhibit: clock_lo // inhibit: clock_lo
IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT); IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT);
IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT); IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT);
} }
ERROR:
// clear for next data // clear for next data
isr_state = 0x8000; isr_state = 0x8000;
NEXT: NEXT: