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