Rewrote send and receive routines using coroutines

This commit is contained in:
Dreaded_X 2021-01-18 17:58:30 +01:00
parent befc326c7f
commit 3b0fb96364

View File

@ -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)) {