ibmpc: ringbuf optimization for cpp
This commit is contained in:
parent
bff5cff1f2
commit
369b5cb21e
2 changed files with 55 additions and 20 deletions
|
|
@ -69,7 +69,6 @@ void IBMPC::host_init(void)
|
|||
inhibit();
|
||||
int_init();
|
||||
int_off();
|
||||
ringbuf_init(&rb, rbuf, RINGBUF_SIZE);
|
||||
host_isr_clear();
|
||||
}
|
||||
|
||||
|
|
@ -174,14 +173,14 @@ int16_t IBMPC::host_recv(void)
|
|||
int16_t ret = -1;
|
||||
|
||||
// Enable ISR if buffer was full
|
||||
if (ringbuf_is_full(&rb)) {
|
||||
if (ringbuf_is_full()) {
|
||||
host_isr_clear();
|
||||
int_on();
|
||||
idle();
|
||||
}
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
ret = ringbuf_get(&rb);
|
||||
ret = ringbuf_get();
|
||||
}
|
||||
if (ret != -1) dprintf("r%02X ", ret&0xFF);
|
||||
return ret;
|
||||
|
|
@ -204,7 +203,7 @@ void IBMPC::host_isr_clear(void)
|
|||
protocol = 0;
|
||||
error = 0;
|
||||
isr_state = 0x8000;
|
||||
ringbuf_reset(&rb);
|
||||
ringbuf_reset();
|
||||
}
|
||||
|
||||
inline void IBMPC::isr(void)
|
||||
|
|
@ -281,8 +280,8 @@ inline void IBMPC::isr(void)
|
|||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of b7 of XT_IBM
|
||||
if (!protocol) {
|
||||
while (!(IBMPC_CLOCK_PIN&(1<<clock_bit)) && us) { wait_us(1); us--; }
|
||||
while ( IBMPC_CLOCK_PIN&(1<<clock_bit) && us) { wait_us(1); us--; }
|
||||
while (!(IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
while ( (IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
} else if (protocol == IBMPC_PROTOCOL_XT_CLONE) {
|
||||
us = 0;
|
||||
}
|
||||
|
|
@ -311,8 +310,8 @@ inline void IBMPC::isr(void)
|
|||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of AT stop bit to discriminate between XT and AT
|
||||
if (!protocol) {
|
||||
while (!(IBMPC_CLOCK_PIN&(1<<clock_bit)) && us) { wait_us(1); us--; }
|
||||
while ( IBMPC_CLOCK_PIN&(1<<clock_bit) && us) { wait_us(1); us--; }
|
||||
while (!(IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
while ( (IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
} else if (protocol == IBMPC_PROTOCOL_XT_IBM) {
|
||||
us = 0;
|
||||
}
|
||||
|
|
@ -363,15 +362,17 @@ inline void IBMPC::isr(void)
|
|||
|
||||
DONE:
|
||||
// store data
|
||||
if (!ringbuf_put(&rb, isr_state & 0xFF)) {
|
||||
// buffer overflow
|
||||
error = IBMPC_ERR_FULL;
|
||||
|
||||
ringbuf_put(isr_state & 0xFF);
|
||||
if (ringbuf_is_full()) {
|
||||
// Disable ISR if buffer is full
|
||||
int_off();
|
||||
// inhibit: clock_lo() instead of inhibit() for ISR optimization
|
||||
clock_lo();
|
||||
}
|
||||
if (ringbuf_is_empty()) {
|
||||
// buffer overflow
|
||||
error = IBMPC_ERR_FULL;
|
||||
}
|
||||
ERROR:
|
||||
// clear for next data
|
||||
isr_state = 0x8000;
|
||||
|
|
@ -388,9 +389,9 @@ void IBMPC::host_set_led(uint8_t led)
|
|||
}
|
||||
|
||||
|
||||
// NOTE: With this ISR data line can be read within 2us after clock falling edge.
|
||||
// To read data line early as possible:
|
||||
// write naked ISR with asembly code to read the line and call C func to do other job?
|
||||
// NOTE: With this ISR data line should be read within 5us after clock falling edge.
|
||||
// Confirmed that ATmega32u4 can read data line in 2.5us from interrupt after
|
||||
// ISR prologue pushs r18, r19, r20, r21, r24, r25 r30 and r31 with GCC 5.4.0
|
||||
ISR(IBMPC_INT_VECT)
|
||||
{
|
||||
IBMPC::interface0.isr();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <stdbool.h>
|
||||
#include "wait.h"
|
||||
#include "ringbuf.h"
|
||||
|
||||
/*
|
||||
* IBM PC keyboard protocol
|
||||
|
|
@ -91,8 +90,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define IBMPC_LED_NUM_LOCK 1
|
||||
#define IBMPC_LED_CAPS_LOCK 2
|
||||
|
||||
#define RINGBUF_SIZE 16
|
||||
|
||||
|
||||
class IBMPC
|
||||
{
|
||||
|
|
@ -127,8 +124,14 @@ class IBMPC
|
|||
private:
|
||||
volatile uint16_t isr_state;
|
||||
uint8_t timer_start;
|
||||
ringbuf_t rb;
|
||||
uint8_t rbuf[RINGBUF_SIZE];
|
||||
|
||||
/* ring buffer */
|
||||
// Size should be power of 2
|
||||
#define RINGBUF_SIZE 16
|
||||
uint8_t rb_head;
|
||||
uint8_t rb_tail;
|
||||
uint8_t rb_buffer[RINGBUF_SIZE];
|
||||
|
||||
const uint8_t clock_bit, data_bit;
|
||||
const uint8_t clock_mask, data_mask;
|
||||
|
||||
|
|
@ -237,6 +240,37 @@ class IBMPC
|
|||
{
|
||||
EIMSK &= ~clock_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* ring buffer
|
||||
*/
|
||||
inline int16_t ringbuf_get(void) __attribute__((__always_inline__))
|
||||
{
|
||||
if (ringbuf_is_empty()) return -1;
|
||||
uint8_t data = rb_buffer[rb_tail];
|
||||
rb_tail++;
|
||||
rb_tail &= (RINGBUF_SIZE - 1);
|
||||
return data;
|
||||
}
|
||||
inline void ringbuf_put(uint8_t data) __attribute__((__always_inline__))
|
||||
{
|
||||
rb_buffer[rb_head] = data;
|
||||
rb_head++;
|
||||
rb_head &= (RINGBUF_SIZE - 1);
|
||||
}
|
||||
inline bool ringbuf_is_empty(void) __attribute__((__always_inline__))
|
||||
{
|
||||
return (rb_head == rb_tail);
|
||||
}
|
||||
inline bool ringbuf_is_full(void) __attribute__((__always_inline__))
|
||||
{
|
||||
return (((rb_head + 1) & (RINGBUF_SIZE - 1)) == rb_tail);
|
||||
}
|
||||
inline void ringbuf_reset(void) __attribute__((__always_inline__))
|
||||
{
|
||||
rb_head = 0;
|
||||
rb_tail = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue