From bec3721e463d469d833e176133c693cca615a40e Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Wed, 30 Dec 2020 03:22:45 +0100 Subject: [PATCH] Initial commit --- .gitignore | 3 + Makefile | 39 ++++++++ generate_scancode.py | 147 +++++++++++++++++++++++++++ include/fifo.h | 19 ++++ include/keyboard.h | 15 +++ include/scancode.h | 9 ++ src/fifo.c | 37 +++++++ src/keyboard.c | 231 +++++++++++++++++++++++++++++++++++++++++++ src/main.c | 53 ++++++++++ src/scancode.c | 10 ++ 10 files changed, 563 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 generate_scancode.py create mode 100644 include/fifo.h create mode 100644 include/keyboard.h create mode 100644 include/scancode.h create mode 100644 src/fifo.c create mode 100644 src/keyboard.c create mode 100644 src/main.c create mode 100644 src/scancode.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8de739 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.build/ +.clangd +compile_commands.json diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0bcdd2e --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +OBJCOPY = avr-objcopy +CC = avr-gcc +BUILD = .build +TARGET = main + +OPT = s +CFLAGS = -Wall -Wextra -std=c18 -O$(OPT) -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mmcu=atmega328p -DF_CPU=16000000L -Iinclude +LDFLAGS = -Wall -Wextra -O$(OPT) -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p + +SRC = \ +src/main.c \ +src/keyboard.c \ +src/fifo.c \ +src/scancode.c + +OBJ = $(addprefix $(BUILD)/, $(notdir $(SRC:.c=.o))) +vpath %.c $(sort $(dir $(SRC))) + +.PHONY: all clean + +all: $(BUILD) $(BUILD)/$(TARGET).bin + +%.hex: %.elf | $(BUILD) + $(OBJCOPY) -O ihex -R .eeprom $< $@ + +%.bin: %.hex | $(BUILD) + $(OBJCOPY) -I ihex -O binary $< $@ + +$(BUILD)/%.o: %.c Makefile | $(BUILD) + $(CC) -c $(CFLAGS) $< -o $@ + +$(BUILD)/$(TARGET).elf: $(OBJ) Makefile + $(CC) $(LDFLAGS) $(OBJ) -o $@ + +$(BUILD): + mkdir $@ + +clean: + rm -fr $(BUILD) diff --git a/generate_scancode.py b/generate_scancode.py new file mode 100644 index 0000000..b4a1655 --- /dev/null +++ b/generate_scancode.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +scancode = [[0]*128, [0]*128] + +scancode[0][0x0D] = '\t' +scancode[0][0x0E] = '`' +scancode[0][0x15] = 'q' +scancode[0][0x16] = '1' +scancode[0][0x1A] = 'z' +scancode[0][0x1B] = 's' +scancode[0][0x1C] = 'a' +scancode[0][0x1D] = 'w' +scancode[0][0x1E] = '2' +scancode[0][0x21] = 'c' +scancode[0][0x22] = 'x' +scancode[0][0x23] = 'd' +scancode[0][0x24] = 'e' +scancode[0][0x25] = '4' +scancode[0][0x26] = '3' +scancode[0][0x29] = ' ' +scancode[0][0x2A] = 'v' +scancode[0][0x2B] = 'f' +scancode[0][0x2C] = 't' +scancode[0][0x2D] = 'r' +scancode[0][0x2E] = '5' +scancode[0][0x31] = 'n' +scancode[0][0x32] = 'b' +scancode[0][0x33] = 'h' +scancode[0][0x34] = 'g' +scancode[0][0x35] = 'y' +scancode[0][0x36] = '6' +scancode[0][0x3A] = 'm' +scancode[0][0x3B] = 'j' +scancode[0][0x3C] = 'u' +scancode[0][0x3D] = '7' +scancode[0][0x3E] = '8' +scancode[0][0x41] = ',' +scancode[0][0x42] = 'k' +scancode[0][0x43] = 'i' +scancode[0][0x44] = 'o' +scancode[0][0x45] = '0' +scancode[0][0x46] = '9' +scancode[0][0x49] = '.' +scancode[0][0x4A] = '/' +scancode[0][0x4B] = 'l' +scancode[0][0x4C] = ';' +scancode[0][0x4D] = 'p' +scancode[0][0x4E] = '-' +scancode[0][0x52] = '\'' +scancode[0][0x54] = '[' +scancode[0][0x55] = '=' +scancode[0][0x5A] = '\r' +scancode[0][0x5B] = ']' +scancode[0][0x5D] = '\\' +scancode[0][0x66] = 0x08 +scancode[0][0x69] = '1' +scancode[0][0x6B] = '2' +scancode[0][0x6C] = '7' +scancode[0][0x70] = '0' +scancode[0][0x71] = '.' +scancode[0][0x72] = '2' +scancode[0][0x73] = '5' +scancode[0][0x74] = '6' +scancode[0][0x75] = '8' +scancode[0][0x76] = 0x1B +scancode[0][0x79] = '+' +scancode[0][0x7A] = '3' +scancode[0][0x7B] = '-' +scancode[0][0x7C] = '*' +scancode[0][0x7D] = '9' + +scancode[1][0x0D] = '\t' +scancode[1][0x0E] = '~' +scancode[1][0x15] = 'Q' +scancode[1][0x16] = '!' +scancode[1][0x1A] = 'Z' +scancode[1][0x1B] = 'S' +scancode[1][0x1C] = 'A' +scancode[1][0x1D] = 'W' +scancode[1][0x1E] = '@' +scancode[1][0x21] = 'C' +scancode[1][0x22] = 'X' +scancode[1][0x23] = 'D' +scancode[1][0x24] = 'E' +scancode[1][0x25] = '$' +scancode[1][0x26] = '#' +scancode[1][0x29] = ' ' +scancode[1][0x2A] = 'V' +scancode[1][0x2B] = 'F' +scancode[1][0x2C] = 'T' +scancode[1][0x2D] = 'R' +scancode[1][0x2E] = '%' +scancode[1][0x31] = 'N' +scancode[1][0x32] = 'B' +scancode[1][0x33] = 'H' +scancode[1][0x34] = 'G' +scancode[1][0x35] = 'Y' +scancode[1][0x36] = '^' +scancode[1][0x3A] = 'M' +scancode[1][0x3B] = 'J' +scancode[1][0x3C] = 'U' +scancode[1][0x3D] = '&' +scancode[1][0x3E] = '*' +scancode[1][0x41] = '<' +scancode[1][0x42] = 'K' +scancode[1][0x43] = 'I' +scancode[1][0x44] = 'O' +scancode[1][0x45] = ')' +scancode[1][0x46] = '(' +scancode[1][0x49] = '>' +scancode[1][0x4A] = '?' +scancode[1][0x4B] = 'L' +scancode[1][0x4C] = ':' +scancode[1][0x4D] = 'P' +scancode[1][0x4E] = '_' +scancode[1][0x52] = '"' +scancode[1][0x54] = '{' +scancode[1][0x55] = '+' +scancode[1][0x5A] = '\r' +scancode[1][0x5B] = '}' +scancode[1][0x5D] = '|' +scancode[1][0x66] = 0X08 +scancode[1][0x69] = '1' +scancode[1][0x6B] = '2' +scancode[1][0x6C] = '7' +scancode[1][0x70] = '0' +scancode[1][0x71] = '.' +scancode[1][0x72] = '2' +scancode[1][0x73] = '5' +scancode[1][0x74] = '6' +scancode[1][0x75] = '8' +scancode[1][0x76] = 0X1B +scancode[1][0x79] = '+' +scancode[1][0x7A] = '3' +scancode[1][0x7B] = '-' +scancode[1][0x7C] = '*' +scancode[1][0x7D] = '9' + +print("char scancode[2][128] = {") +for i in scancode: + print("\t{", end="") + for j in i: + if (type(j) == str): + j = ord(j) + print(f"0x{j:02x},", end="") + print("},") +print("};") diff --git a/include/fifo.h b/include/fifo.h new file mode 100644 index 0000000..7ab2394 --- /dev/null +++ b/include/fifo.h @@ -0,0 +1,19 @@ +#ifndef FIFO_h +#define FIFO_h + +#include + +#define FIFO_SIZE 64 + +struct FIFO { + int head; + int tail; + int size; + uint8_t buffer[FIFO_SIZE]; +}; + +void FIFO_push(volatile struct FIFO* fifo, uint8_t value); +uint8_t FIFO_pop(volatile struct FIFO* fifo); +int FIFO_size(volatile struct FIFO* fifo); + +#endif diff --git a/include/keyboard.h b/include/keyboard.h new file mode 100644 index 0000000..b63841c --- /dev/null +++ b/include/keyboard.h @@ -0,0 +1,15 @@ +#ifndef KEYBOARD_h +#define KEYBOARD_h + +#include + +#define KEYBOARD_CLK 2 +#define KEYBOARD_DATA 7 + +void send_keyboard_cmd(uint8_t value); +void queue_keyboard_cmd(uint8_t value); +void send_keyboard_cmd_queue(); + +void keyboard_interrupt(void (*callback)(uint8_t)); + +#endif diff --git a/include/scancode.h b/include/scancode.h new file mode 100644 index 0000000..656b6e3 --- /dev/null +++ b/include/scancode.h @@ -0,0 +1,9 @@ +#ifndef SCANCODE_H +#define SCANCODE_H + +#include + +void setup_scancode(); +// uint8_t convert_scancode(uint8_t shift, uint8_t code); + +#endif diff --git a/src/fifo.c b/src/fifo.c new file mode 100644 index 0000000..6653ad0 --- /dev/null +++ b/src/fifo.c @@ -0,0 +1,37 @@ +#include "fifo.h" + +void FIFO_push(volatile struct FIFO* fifo, uint8_t value) { + if (fifo->size == FIFO_SIZE) { + return; + } + + fifo->size++; + + if (fifo->size > 1) { + fifo->tail++; + fifo->tail %= FIFO_SIZE; + } + + fifo->buffer[fifo->tail] = value; +} + +uint8_t FIFO_pop(volatile struct FIFO* fifo) { + if (fifo->size == 0) { + return 0; + } + + fifo->size--; + + uint8_t data = fifo->buffer[fifo->head]; + + if (fifo->size >= 1) { + fifo->head++; + fifo->head %= FIFO_SIZE; + } + + return data; +} + +int FIFO_size(volatile struct FIFO* fifo) { + return fifo->size; +} diff --git a/src/keyboard.c b/src/keyboard.c new file mode 100644 index 0000000..8574007 --- /dev/null +++ b/src/keyboard.c @@ -0,0 +1,231 @@ +#include +#include + +#include "keyboard.h" +#include "scancode.h" +#include "fifo.h" + +volatile struct { + struct FIFO buffer; + + uint8_t sending : 1; + uint16_t value; + uint8_t counter; + + struct { + uint8_t shift : 1; + uint8_t caps_lock : 1; + uint8_t ctrl : 1; + } modifier; + + uint8_t released : 1; +} keyboard = {0}; + +// Send a command to the keyboard (BLOCKS) +void send_keyboard_cmd(uint8_t value) { + // Pull clock low + DDRD |= (1<> 4; + value ^= value >> 2; + value ^= value >> 1; + + return (~value) & 1; +} + +void receive_scancode_bit(void (*callback)(uint8_t)) { + keyboard.value |= ((PIND >> KEYBOARD_DATA) & 1) << keyboard.counter; + keyboard.counter++; + + // Check that the first bit is 0 + if (keyboard.counter == 1 && keyboard.value & 1) { + keyboard.counter = 0; + keyboard.value = 0; + + return; + } + + // Check the parity + if (keyboard.counter == 10 && parity(keyboard.value >> 1) != ((keyboard.value >> 9) & 1)) { + keyboard.counter = 0; + keyboard.value = 0; + + return; + } + + // Check that the last bit is 1 + if (keyboard.counter == 11 && !((keyboard.value >> 10) & 1)) { + keyboard.counter = 0; + keyboard.value = 0; + + return; + } + + // 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 + case 0x14: + keyboard.modifier.ctrl = !keyboard.released; + keyboard.released = 0; + break; + + case 240: + keyboard.released = 1; + break; + + default: + if (!keyboard.released) { + char c = convert_scancode(keyboard.modifier.shift, value & 127); + + if (keyboard.modifier.caps_lock && !keyboard.modifier.shift && c >= 'a' && c <= 'z') { + c -= 0x20; + } + + if (keyboard.modifier.ctrl) { + switch (c) { + case 'c': + c = 0x03; + break; + + case 'e': + c = 0x05; + break; + + case 'p': + c = 0x10; + break; + + case 'r': + c = 0x12; + break; + + case 's': + c = 0x13; + 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; + } + } +} + +void send_cmd_bit() { + if (keyboard.counter == 8) { + // Send parity + if (parity(keyboard.value)) { + PORTD |= (1<> KEYBOARD_DATA) & 1)) { + keyboard.counter = 0; + keyboard.value = 0; + keyboard.sending = 0; + } + } else { + // Send bit + if ((keyboard.value >> keyboard.counter) & 1) { + PORTD |= (1<>KEYBOARD_CLK & 1)) { + send_cmd_bit(); + } +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c76ff59 --- /dev/null +++ b/src/main.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +#include "scancode.h" +#include "keyboard.h" + +#define CLK 4 +#define DATA 5 + +// Clock the value to 74164 +void write_value(uint8_t value) { + for (uint8_t i = 0; i < 8; ++i) { + uint8_t bit = (value >> i) & 1; + PORTD |= (1<