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 "timer.h"
#include "wait.h"
#include "ringbuf.h"
#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_error = IBMPC_ERR_NONE;
/* 2-byte buffer for data received from keyboard
* buffer states:
* FFFF: empty
* FFss: one data
* 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;
/* buffer for data received from device */
#define RINGBUF_SIZE 16
static uint8_t rbuf[RINGBUF_SIZE];
static ringbuf_t rb = {};
/* internal state of receiving data */
static volatile uint16_t isr_state = 0x8000;
static uint8_t timer_start = 0;
@ -80,6 +77,7 @@ void ibmpc_host_init(void)
inhibit();
IBMPC_INT_INIT();
IBMPC_INT_OFF();
ringbuf_init(&rb, rbuf, RINGBUF_SIZE);
}
void ibmpc_host_enable(void)
@ -180,60 +178,19 @@ ERROR:
*/
int16_t ibmpc_host_recv(void)
{
uint16_t data = 0;
uint8_t ret = 0xFF;
int16_t ret = -1;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
data = recv_data;
// 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) {
// Enable ISR if buffer was full
if (ringbuf_is_full(&rb)) {
ibmpc_host_isr_clear();
IBMPC_INT_ON();
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;
}
@ -254,7 +211,7 @@ void ibmpc_host_isr_clear(void)
ibmpc_protocol = 0;
ibmpc_error = 0;
isr_state = 0x8000;
recv_data = 0xFFFF;
ringbuf_reset(&rb);
}
#define LO8(w) (*((uint8_t *)&(w)))
@ -407,32 +364,19 @@ ISR(IBMPC_INT_VECT)
break;
}
ERROR:
// error: eeFF
recv_data = (ibmpc_error<<8) | 0x00FF;
goto CLEAR;
DONE:
if ((isr_state & 0x00FF) == 0x00FF) {
// receive error code 0xFF
ibmpc_error = IBMPC_ERR_FF;
goto ERROR;
}
if (HI8(recv_data) != 0xFF && LO8(recv_data) != 0xFF) {
// store data
if (!ringbuf_put(&rb, isr_state & 0xFF)) {
// buffer overflow
ibmpc_error = IBMPC_ERR_FULL;
goto ERROR;
}
// 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) {
// Disable ISR if buffer is full
IBMPC_INT_OFF();
// inhibit: clock_lo
IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT);
IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT);
}
ERROR:
// clear for next data
isr_state = 0x8000;
NEXT: