PS/2: request to resend when error is occured.
This commit is contained in:
parent
3015f191a5
commit
239bdbf419
@ -106,6 +106,7 @@ void keyboard_proc(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: should send only when changed from last report
|
||||
if (matrix_is_modified()) {
|
||||
host_send_keyboard_report();
|
||||
#ifdef DEBUG_LED
|
||||
|
123
ps2.c
123
ps2.c
@ -96,13 +96,15 @@ void ps2_host_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: send using interrupt if available
|
||||
uint8_t ps2_host_send(uint8_t data)
|
||||
{
|
||||
bool parity;
|
||||
RETRY:
|
||||
parity = true;
|
||||
ps2_error = 0;
|
||||
|
||||
uint8_t res = 0;
|
||||
bool parity = true;
|
||||
ps2_error = PS2_ERR_NONE;
|
||||
#ifdef PS2_INT_DISABLE
|
||||
PS2_INT_DISABLE();
|
||||
#endif
|
||||
/* terminate a transmission if we have */
|
||||
inhibit();
|
||||
_delay_us(100);
|
||||
@ -139,15 +141,15 @@ RETRY:
|
||||
WAIT(clock_hi, 50, 8);
|
||||
WAIT(data_hi, 50, 9);
|
||||
|
||||
uint8_t res = ps2_host_recv_response();
|
||||
if (res == 0xFE && data != 0xFE)
|
||||
goto RETRY;
|
||||
|
||||
inhibit();
|
||||
return res;
|
||||
res = ps2_host_recv_response();
|
||||
ERROR:
|
||||
#ifdef PS2_INT_ENABLE
|
||||
PS2_INT_ENABLE();
|
||||
idle();
|
||||
#else
|
||||
inhibit();
|
||||
return 0;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
/* receive data when host want else inhibit communication */
|
||||
@ -209,46 +211,99 @@ static inline uint8_t pbuf_dequeue(void)
|
||||
/* get data received by interrupt */
|
||||
uint8_t ps2_host_recv(void)
|
||||
{
|
||||
// TODO: release clock line after 100us when inhibited by error
|
||||
if (ps2_error) {
|
||||
ps2_host_send(0xFE); // request to resend
|
||||
ps2_error = PS2_ERR_NONE;
|
||||
}
|
||||
return pbuf_dequeue();
|
||||
}
|
||||
|
||||
#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0)
|
||||
#define DEBUGP(x) do { PORTC = x; } while (0)
|
||||
ISR(PS2_INT_VECT)
|
||||
{
|
||||
/* interrupt means start bit comes */
|
||||
pbuf_enqueue(recv_data());
|
||||
static enum {
|
||||
INIT,
|
||||
START,
|
||||
BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
|
||||
PARITY,
|
||||
STOP,
|
||||
} state = INIT;
|
||||
static uint8_t data = 0;
|
||||
static uint8_t parity = 1;
|
||||
|
||||
/* release lines(idle state) */
|
||||
idle();
|
||||
_delay_us(5);
|
||||
// TODO: abort if elapse 100us from previous interrupt
|
||||
|
||||
// return unless falling edge
|
||||
if (clock_in()) {
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
state++;
|
||||
DEBUGP(state);
|
||||
switch (state) {
|
||||
case START:
|
||||
if (data_in())
|
||||
goto ERROR;
|
||||
break;
|
||||
case BIT0:
|
||||
case BIT1:
|
||||
case BIT2:
|
||||
case BIT3:
|
||||
case BIT4:
|
||||
case BIT5:
|
||||
case BIT6:
|
||||
case BIT7:
|
||||
data >>= 1;
|
||||
if (data_in()) {
|
||||
data |= 0x80;
|
||||
parity++;
|
||||
}
|
||||
break;
|
||||
case PARITY:
|
||||
if (data_in()) {
|
||||
if (!(parity & 0x01))
|
||||
goto ERROR;
|
||||
} else {
|
||||
if (parity & 0x01)
|
||||
goto ERROR;
|
||||
}
|
||||
break;
|
||||
case STOP:
|
||||
if (!data_in())
|
||||
goto ERROR;
|
||||
pbuf_enqueue(data);
|
||||
goto DONE;
|
||||
break;
|
||||
default:
|
||||
goto ERROR;
|
||||
}
|
||||
goto RETURN;
|
||||
ERROR:
|
||||
DEBUGP(0xFF);
|
||||
inhibit();
|
||||
ps2_error = state;
|
||||
DONE:
|
||||
state = INIT;
|
||||
data = 0;
|
||||
parity = 1;
|
||||
RETURN:
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
static void ps2_reset(void)
|
||||
{
|
||||
ps2_host_send(0xFF);
|
||||
if (ps2_host_recv_response() == 0xFA) {
|
||||
_delay_ms(1000);
|
||||
ps2_host_recv_response();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* send LED state to keyboard */
|
||||
void ps2_host_set_led(uint8_t led)
|
||||
{
|
||||
#ifdef PS2_INT_DISABLE
|
||||
PS2_INT_DISABLE();
|
||||
#endif
|
||||
ps2_host_send(0xED);
|
||||
ps2_host_recv_response();
|
||||
ps2_host_send(led);
|
||||
ps2_host_recv_response();
|
||||
#ifdef PS2_INT_ENABLE
|
||||
PS2_INT_ENABLE();
|
||||
idle();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -257,7 +312,7 @@ static uint8_t recv_data(void)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
bool parity = true;
|
||||
ps2_error = 0;
|
||||
ps2_error = PS2_ERR_NONE;
|
||||
|
||||
/* start bit [1] */
|
||||
WAIT(clock_lo, 1, 1);
|
||||
@ -307,6 +362,7 @@ static inline bool clock_in()
|
||||
{
|
||||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
|
||||
PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
|
||||
_delay_us(1);
|
||||
return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
|
||||
}
|
||||
static inline void data_lo()
|
||||
@ -324,6 +380,7 @@ static inline bool data_in()
|
||||
{
|
||||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
|
||||
PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
|
||||
_delay_us(1);
|
||||
return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ int main(void)
|
||||
usbInit();
|
||||
|
||||
print_enable = true;
|
||||
//debug_enable = true;
|
||||
debug_enable = true;
|
||||
keyboard_init();
|
||||
|
||||
/* enforce re-enumeration, do this while interrupts are disabled! */
|
||||
@ -64,56 +64,9 @@ int main(void)
|
||||
|
||||
//uint8_t fn_bits = 0;
|
||||
while (1) { /* main event loop */
|
||||
DEBUGP(0x01);
|
||||
wdt_reset();
|
||||
usbPoll();
|
||||
host_vusb_keyboard_send();
|
||||
|
||||
DEBUGP(0x02);
|
||||
keyboard_proc();
|
||||
DEBUGP(0x03);
|
||||
/*
|
||||
matrix_scan();
|
||||
fn_bits = 0;
|
||||
host_swap_keyboard_report();
|
||||
host_clear_keyboard_report();
|
||||
mousekey_clear_report();
|
||||
for (int row = 0; row < matrix_rows(); row++) {
|
||||
for (int col = 0; col < matrix_cols(); col++) {
|
||||
if (!matrix_is_on(row, col)) continue;
|
||||
|
||||
uint8_t code = layer_get_keycode(row, col);
|
||||
if (code == KB_NO) {
|
||||
// do nothing
|
||||
}
|
||||
else if (IS_MOD(code)) {
|
||||
host_add_mod_bit(MOD_BIT(code));
|
||||
}
|
||||
else if (IS_KEY(code)) {
|
||||
host_add_key(code);
|
||||
}
|
||||
else if (IS_FN(code)) {
|
||||
fn_bits |= FN_BIT(code);
|
||||
}
|
||||
else if (IS_MOUSEKEY(code)) {
|
||||
mousekey_decode(code);
|
||||
}
|
||||
else {
|
||||
debug("ignore keycode: "); debug_hex(code); debug("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUGP(0x03);
|
||||
layer_switching(fn_bits);
|
||||
if (matrix_is_modified()) {
|
||||
host_send_keyboard_report();
|
||||
}
|
||||
mousekey_send();
|
||||
|
||||
if (last_led != host_keyboard_led()) {
|
||||
led_set(host_keyboard_led());
|
||||
last_led = host_keyboard_led();
|
||||
}
|
||||
*/
|
||||
host_vusb_keyboard_send();
|
||||
}
|
||||
}
|
||||
|
28
vusb/host.c
28
vusb/host.c
@ -258,33 +258,6 @@ PROGMEM uchar keyboard_hid_report[] = {
|
||||
*/
|
||||
PROGMEM uchar mouse_hid_report[] = {
|
||||
/* from HID 1.11 spec example */
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x02, // Usage (Mouse),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x09, 0x01, // Usage (Pointer),
|
||||
0xA1, 0x00, // Collection (Physical),
|
||||
0x05, 0x09, // Usage Page (Buttons),
|
||||
0x19, 0x01, // Usage Minimum (01),
|
||||
0x29, 0x03, // Usage Maximun (03),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x01, // Logical Maximum (1),
|
||||
0x95, 0x03, // Report Count (3),
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;3 button bits
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x05, // Report Size (5),
|
||||
0x81, 0x01, // Input (Constant), ;5 bit padding
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x30, // Usage (X),
|
||||
0x09, 0x31, // Usage (Y),
|
||||
0x15, 0x81, // Logical Minimum (-127),
|
||||
0x25, 0x7F, // Logical Maximum (127),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x95, 0x02, // Report Count (2),
|
||||
0x81, 0x06, // Input (Data, Variable, Relative), ;2 position bytes (X & Y)
|
||||
0xC0, // End Collection,
|
||||
0xC0, // End Collection
|
||||
/*
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
@ -355,7 +328,6 @@ PROGMEM uchar mouse_hid_report[] = {
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0 // END_COLLECTION
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user