PS/2: request to resend when error is occured.
This commit is contained in:
parent
3015f191a5
commit
239bdbf419
4 changed files with 93 additions and 110 deletions
|
@ -106,6 +106,7 @@ void keyboard_proc(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: should send only when changed from last report
|
||||||
if (matrix_is_modified()) {
|
if (matrix_is_modified()) {
|
||||||
host_send_keyboard_report();
|
host_send_keyboard_report();
|
||||||
#ifdef DEBUG_LED
|
#ifdef DEBUG_LED
|
||||||
|
|
123
ps2.c
123
ps2.c
|
@ -96,13 +96,15 @@ void ps2_host_init(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: send using interrupt if available
|
||||||
uint8_t ps2_host_send(uint8_t data)
|
uint8_t ps2_host_send(uint8_t data)
|
||||||
{
|
{
|
||||||
bool parity;
|
uint8_t res = 0;
|
||||||
RETRY:
|
bool parity = true;
|
||||||
parity = true;
|
ps2_error = PS2_ERR_NONE;
|
||||||
ps2_error = 0;
|
#ifdef PS2_INT_DISABLE
|
||||||
|
PS2_INT_DISABLE();
|
||||||
|
#endif
|
||||||
/* terminate a transmission if we have */
|
/* terminate a transmission if we have */
|
||||||
inhibit();
|
inhibit();
|
||||||
_delay_us(100);
|
_delay_us(100);
|
||||||
|
@ -139,15 +141,15 @@ RETRY:
|
||||||
WAIT(clock_hi, 50, 8);
|
WAIT(clock_hi, 50, 8);
|
||||||
WAIT(data_hi, 50, 9);
|
WAIT(data_hi, 50, 9);
|
||||||
|
|
||||||
uint8_t res = ps2_host_recv_response();
|
res = ps2_host_recv_response();
|
||||||
if (res == 0xFE && data != 0xFE)
|
|
||||||
goto RETRY;
|
|
||||||
|
|
||||||
inhibit();
|
|
||||||
return res;
|
|
||||||
ERROR:
|
ERROR:
|
||||||
|
#ifdef PS2_INT_ENABLE
|
||||||
|
PS2_INT_ENABLE();
|
||||||
|
idle();
|
||||||
|
#else
|
||||||
inhibit();
|
inhibit();
|
||||||
return 0;
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive data when host want else inhibit communication */
|
/* receive data when host want else inhibit communication */
|
||||||
|
@ -209,46 +211,99 @@ static inline uint8_t pbuf_dequeue(void)
|
||||||
/* get data received by interrupt */
|
/* get data received by interrupt */
|
||||||
uint8_t ps2_host_recv(void)
|
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();
|
return pbuf_dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0)
|
||||||
|
#define DEBUGP(x) do { PORTC = x; } while (0)
|
||||||
ISR(PS2_INT_VECT)
|
ISR(PS2_INT_VECT)
|
||||||
{
|
{
|
||||||
/* interrupt means start bit comes */
|
static enum {
|
||||||
pbuf_enqueue(recv_data());
|
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) */
|
// TODO: abort if elapse 100us from previous interrupt
|
||||||
idle();
|
|
||||||
_delay_us(5);
|
// 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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
static void ps2_reset(void)
|
static void ps2_reset(void)
|
||||||
{
|
{
|
||||||
ps2_host_send(0xFF);
|
ps2_host_send(0xFF);
|
||||||
if (ps2_host_recv_response() == 0xFA) {
|
|
||||||
_delay_ms(1000);
|
|
||||||
ps2_host_recv_response();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/* send LED state to keyboard */
|
/* send LED state to keyboard */
|
||||||
void ps2_host_set_led(uint8_t led)
|
void ps2_host_set_led(uint8_t led)
|
||||||
{
|
{
|
||||||
#ifdef PS2_INT_DISABLE
|
|
||||||
PS2_INT_DISABLE();
|
|
||||||
#endif
|
|
||||||
ps2_host_send(0xED);
|
ps2_host_send(0xED);
|
||||||
ps2_host_recv_response();
|
|
||||||
ps2_host_send(led);
|
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;
|
uint8_t data = 0;
|
||||||
bool parity = true;
|
bool parity = true;
|
||||||
ps2_error = 0;
|
ps2_error = PS2_ERR_NONE;
|
||||||
|
|
||||||
/* start bit [1] */
|
/* start bit [1] */
|
||||||
WAIT(clock_lo, 1, 1);
|
WAIT(clock_lo, 1, 1);
|
||||||
|
@ -307,6 +362,7 @@ static inline bool clock_in()
|
||||||
{
|
{
|
||||||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
|
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
|
||||||
PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
|
PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
|
||||||
|
_delay_us(1);
|
||||||
return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
|
return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
|
||||||
}
|
}
|
||||||
static inline void data_lo()
|
static inline void data_lo()
|
||||||
|
@ -324,6 +380,7 @@ static inline bool data_in()
|
||||||
{
|
{
|
||||||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
|
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
|
||||||
PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
|
PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
|
||||||
|
_delay_us(1);
|
||||||
return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
|
return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ int main(void)
|
||||||
usbInit();
|
usbInit();
|
||||||
|
|
||||||
print_enable = true;
|
print_enable = true;
|
||||||
//debug_enable = true;
|
debug_enable = true;
|
||||||
keyboard_init();
|
keyboard_init();
|
||||||
|
|
||||||
/* enforce re-enumeration, do this while interrupts are disabled! */
|
/* enforce re-enumeration, do this while interrupts are disabled! */
|
||||||
|
@ -64,56 +64,9 @@ int main(void)
|
||||||
|
|
||||||
//uint8_t fn_bits = 0;
|
//uint8_t fn_bits = 0;
|
||||||
while (1) { /* main event loop */
|
while (1) { /* main event loop */
|
||||||
DEBUGP(0x01);
|
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
usbPoll();
|
usbPoll();
|
||||||
host_vusb_keyboard_send();
|
|
||||||
|
|
||||||
DEBUGP(0x02);
|
|
||||||
keyboard_proc();
|
keyboard_proc();
|
||||||
DEBUGP(0x03);
|
host_vusb_keyboard_send();
|
||||||
/*
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
vusb/host.c
28
vusb/host.c
|
@ -258,33 +258,6 @@ PROGMEM uchar keyboard_hid_report[] = {
|
||||||
*/
|
*/
|
||||||
PROGMEM uchar mouse_hid_report[] = {
|
PROGMEM uchar mouse_hid_report[] = {
|
||||||
/* from HID 1.11 spec example */
|
/* 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)
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
0x09, 0x02, // USAGE (Mouse)
|
0x09, 0x02, // USAGE (Mouse)
|
||||||
0xa1, 0x01, // COLLECTION (Application)
|
0xa1, 0x01, // COLLECTION (Application)
|
||||||
|
@ -355,7 +328,6 @@ PROGMEM uchar mouse_hid_report[] = {
|
||||||
0xc0, // END_COLLECTION
|
0xc0, // END_COLLECTION
|
||||||
0xc0, // END_COLLECTION
|
0xc0, // END_COLLECTION
|
||||||
0xc0 // END_COLLECTION
|
0xc0 // END_COLLECTION
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue