Rewrote send and receive routines using coroutines
This commit is contained in:
parent
befc326c7f
commit
3b0fb96364
275
src/keyboard.c
275
src/keyboard.c
|
@ -1,4 +1,5 @@
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
@ -10,8 +11,7 @@ volatile struct {
|
||||||
struct FIFO buffer;
|
struct FIFO buffer;
|
||||||
|
|
||||||
uint8_t sending : 1;
|
uint8_t sending : 1;
|
||||||
uint16_t value;
|
uint8_t cmd;
|
||||||
uint8_t counter;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t shift : 1;
|
uint8_t shift : 1;
|
||||||
|
@ -22,7 +22,7 @@ volatile struct {
|
||||||
uint8_t released : 1;
|
uint8_t released : 1;
|
||||||
} keyboard = {0};
|
} keyboard = {0};
|
||||||
|
|
||||||
// Send a command to the keyboard (BLOCKS)
|
// Send a command to the keyboard (THIS BLOCKS)
|
||||||
void send_keyboard_cmd(uint8_t value) {
|
void send_keyboard_cmd(uint8_t value) {
|
||||||
// Pull clock low
|
// Pull clock low
|
||||||
DDRD |= (1<<KEYBOARD_CLK);
|
DDRD |= (1<<KEYBOARD_CLK);
|
||||||
|
@ -38,7 +38,7 @@ void send_keyboard_cmd(uint8_t value) {
|
||||||
DDRD &= ~(1<<KEYBOARD_CLK);
|
DDRD &= ~(1<<KEYBOARD_CLK);
|
||||||
|
|
||||||
keyboard.sending = 1;
|
keyboard.sending = 1;
|
||||||
keyboard.value = value;
|
keyboard.cmd = value;
|
||||||
|
|
||||||
while (keyboard.sending) {};
|
while (keyboard.sending) {};
|
||||||
}
|
}
|
||||||
|
@ -64,161 +64,166 @@ uint8_t parity(uint8_t value) {
|
||||||
return (~value) & 1;
|
return (~value) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void receive_scancode_bit(void (*callback)(uint8_t)) {
|
void process_scancode(uint8_t value, void (*callback)(uint8_t)) {
|
||||||
keyboard.value |= ((PIND >> KEYBOARD_DATA) & 1) << keyboard.counter;
|
switch (value) {
|
||||||
keyboard.counter++;
|
// Left and right shift
|
||||||
|
case 18:
|
||||||
|
case 89:
|
||||||
|
keyboard.modifier.shift = !keyboard.released;
|
||||||
|
keyboard.released = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
// Check that the first bit is 0
|
// Caps lock
|
||||||
if (keyboard.counter == 1 && keyboard.value & 1) {
|
case 0x58:
|
||||||
keyboard.counter = 0;
|
if (!keyboard.released) {
|
||||||
keyboard.value = 0;
|
keyboard.modifier.caps_lock = !keyboard.modifier.caps_lock;
|
||||||
|
|
||||||
return;
|
queue_keyboard_cmd(0xED);
|
||||||
}
|
queue_keyboard_cmd(keyboard.modifier.caps_lock << 2);
|
||||||
|
}
|
||||||
|
keyboard.released = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
// Check the parity
|
// Left ctrl
|
||||||
if (keyboard.counter == 10 && parity(keyboard.value >> 1) != ((keyboard.value >> 9) & 1)) {
|
case 0x14:
|
||||||
keyboard.counter = 0;
|
keyboard.modifier.ctrl = !keyboard.released;
|
||||||
keyboard.value = 0;
|
keyboard.released = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
return;
|
case 240:
|
||||||
}
|
keyboard.released = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
// Check that the last bit is 1
|
default:
|
||||||
if (keyboard.counter == 11 && !((keyboard.value >> 10) & 1)) {
|
if (!keyboard.released) {
|
||||||
keyboard.counter = 0;
|
char c = convert_scancode(keyboard.modifier.shift, value & 127);
|
||||||
keyboard.value = 0;
|
|
||||||
|
|
||||||
return;
|
if (keyboard.modifier.caps_lock && !keyboard.modifier.shift && c >= 'a' && c <= 'z') {
|
||||||
}
|
c -= 0x20;
|
||||||
|
|
||||||
// Process the scancode
|
|
||||||
if (keyboard.counter == 11) {
|
|
||||||
uint8_t value = keyboard.value >> 1;
|
|
||||||
|
|
||||||
keyboard.counter = 0;
|
|
||||||
keyboard.value = 0;
|
|
||||||
|
|
||||||
switch (value) {
|
|
||||||
// Left and right shift
|
|
||||||
case 18:
|
|
||||||
case 89:
|
|
||||||
keyboard.modifier.shift = !keyboard.released;
|
|
||||||
keyboard.released = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Caps lock
|
|
||||||
case 0x58:
|
|
||||||
if (!keyboard.released) {
|
|
||||||
keyboard.modifier.caps_lock = !keyboard.modifier.caps_lock;
|
|
||||||
|
|
||||||
queue_keyboard_cmd(0xED);
|
|
||||||
queue_keyboard_cmd(keyboard.modifier.caps_lock << 2);
|
|
||||||
}
|
}
|
||||||
keyboard.released = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Left ctrl
|
if (keyboard.modifier.ctrl) {
|
||||||
case 0x14:
|
switch (c) {
|
||||||
keyboard.modifier.ctrl = !keyboard.released;
|
case 'c':
|
||||||
keyboard.released = 0;
|
c = 0x03;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 240:
|
case 'e':
|
||||||
keyboard.released = 1;
|
c = 0x05;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 'p':
|
||||||
if (!keyboard.released) {
|
c = 0x10;
|
||||||
char c = convert_scancode(keyboard.modifier.shift, value & 127);
|
break;
|
||||||
|
|
||||||
if (keyboard.modifier.caps_lock && !keyboard.modifier.shift && c >= 'a' && c <= 'z') {
|
case 'r':
|
||||||
c -= 0x20;
|
c = 0x12;
|
||||||
}
|
break;
|
||||||
|
|
||||||
if (keyboard.modifier.ctrl) {
|
case 's':
|
||||||
switch (c) {
|
c = 0x13;
|
||||||
case 'c':
|
break;
|
||||||
c = 0x03;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'e':
|
case 'u':
|
||||||
c = 0x05;
|
c = 0x15;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'x':
|
||||||
c = 0x10;
|
c = 0x18;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'z':
|
||||||
c = 0x12;
|
c = 0x1A;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
default:
|
||||||
c = 0x13;
|
c = 0x00;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
|
||||||
c = 0x15;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'x':
|
|
||||||
c = 0x18;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'z':
|
|
||||||
c = 0x1A;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
c = 0x00;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c) {
|
|
||||||
callback(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyboard.released = 0;
|
|
||||||
break;
|
if (c) {
|
||||||
}
|
callback(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyboard.released = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_cmd_bit() {
|
void receive_scancode_bit(void (*callback)(uint8_t)) {
|
||||||
if (keyboard.counter == 8) {
|
uint8_t in = (PIND >> KEYBOARD_DATA) & 1;
|
||||||
// Send parity
|
|
||||||
if (parity(keyboard.value)) {
|
|
||||||
PORTD |= (1<<KEYBOARD_DATA);
|
|
||||||
} else {
|
|
||||||
PORTD &= ~(1<<KEYBOARD_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
++keyboard.counter;
|
CO_BEGIN;
|
||||||
} else if (keyboard.counter == 9) {
|
|
||||||
// Release data line
|
|
||||||
PORTD &= ~(1<<KEYBOARD_DATA);
|
|
||||||
DDRD &= ~(1<<KEYBOARD_DATA);
|
|
||||||
|
|
||||||
++keyboard.counter;
|
// Check that the first bit is 0
|
||||||
} else if (keyboard.counter == 10) {
|
if (in != 0) {
|
||||||
// Wait for data to go low as ack
|
CO_BREAK;
|
||||||
if (!((PIND >> KEYBOARD_DATA) & 1)) {
|
|
||||||
keyboard.counter = 0;
|
|
||||||
keyboard.value = 0;
|
|
||||||
keyboard.sending = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Send bit
|
|
||||||
if ((keyboard.value >> keyboard.counter) & 1) {
|
|
||||||
PORTD |= (1<<KEYBOARD_DATA);
|
|
||||||
} else {
|
|
||||||
PORTD &= ~(1<<KEYBOARD_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
++keyboard.counter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CO_YIELD;
|
||||||
|
|
||||||
|
static uint8_t value;
|
||||||
|
value = 0;
|
||||||
|
|
||||||
|
static int i = 0;
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
value |= in << i;
|
||||||
|
CO_YIELD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the parity
|
||||||
|
if (in != parity(value)) {
|
||||||
|
CO_BREAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CO_YIELD;
|
||||||
|
|
||||||
|
// Check that the last bit is 1
|
||||||
|
if (in != 1) {
|
||||||
|
CO_BREAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_scancode(value, callback);
|
||||||
|
|
||||||
|
CO_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_cmd_bit() {
|
||||||
|
CO_BEGIN;
|
||||||
|
|
||||||
|
static int i;
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
// Send bit
|
||||||
|
if ((keyboard.cmd >> i) & 1) {
|
||||||
|
PORTD |= (1<<KEYBOARD_DATA);
|
||||||
|
} else {
|
||||||
|
PORTD &= ~(1<<KEYBOARD_DATA);
|
||||||
|
}
|
||||||
|
CO_YIELD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send parity
|
||||||
|
if (parity(keyboard.cmd)) {
|
||||||
|
PORTD |= (1<<KEYBOARD_DATA);
|
||||||
|
} else {
|
||||||
|
PORTD &= ~(1<<KEYBOARD_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
CO_YIELD;
|
||||||
|
|
||||||
|
// Release data line
|
||||||
|
PORTD &= ~(1<<KEYBOARD_DATA);
|
||||||
|
DDRD &= ~(1<<KEYBOARD_DATA);
|
||||||
|
|
||||||
|
CO_YIELD;
|
||||||
|
|
||||||
|
// Wait for data to go low as ack
|
||||||
|
if (!((PIND >> KEYBOARD_DATA) & 1)) {
|
||||||
|
keyboard.sending = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CO_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyboard_interrupt(void (*callback)(uint8_t)) {
|
void keyboard_interrupt(void (*callback)(uint8_t)) {
|
||||||
|
|
Reference in New Issue
Block a user