From: Phil Hagelberg Date: Fri, 25 Apr 2014 14:50:11 +0000 (-0700) Subject: Add C firmware. X-Git-Url: https://git.armaanb.net/?p=atreides.git;a=commitdiff_plain;h=8d16090f74a7bf363b2c92070e61bc0727946ca5 Add C firmware. --- diff --git a/firmware/.gitignore b/firmware/.gitignore new file mode 100644 index 0000000..a7c2cd1 --- /dev/null +++ b/firmware/.gitignore @@ -0,0 +1,3 @@ +*.o +atreus +atreus.hex \ No newline at end of file diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100644 index 0000000..2ea7aee --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,15 @@ +MCU=atmega32u4 + +F_CPU=16000000 + +TARGET=atreus + +build: + avr-gcc -std=gnu99 -Os -D F_CPU=$(F_CPU)UL -mmcu=$(MCU) -c -o $(TARGET).o $(TARGET).c + avr-gcc -std=gnu99 -Os -D F_CPU=$(F_CPU)UL -mmcu=$(MCU) -c -o usb_keyboard.o usb_keyboard.c + avr-gcc -mmcu=$(MCU) usb_keyboard.o $(TARGET).o -o $(TARGET) + avr-size $(TARGET) + avr-objcopy -O ihex -R .eeprom $(TARGET) $(TARGET).hex + +upload: build + teensy_loader_cli -w -mmcu=$(MCU) $(TARGET).hex diff --git a/firmware/atreus.c b/firmware/atreus.c new file mode 100644 index 0000000..4e2bb75 --- /dev/null +++ b/firmware/atreus.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include "usb_keyboard.h" + +#define ROW_COUNT 4 +#define COL_COUNT 11 + +#define FN_PRESSED (~PINB & 128) + +#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) + +void reset(void); + + + +// Outputs +// |------------+----+----+----+----| +// | row number | 0 | 1 | 2 | 3 | +// |------------+----+----+----+----| +// | pin number | D0 | D1 | D2 | D3 | +// |------------+----+----+----+----| + +// Inputs +// |---------------+----+----+----+----+----+----+----+----+----+----+----| +// | column number | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | +// |---------------+----+----+----+----+----+----+----+----+----+----+----| +// | pin number | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | F4 | F5 | F6 | +// |---------------+----+----+----+----+----+----+----+----+----+----+----| + + + +// numbers under 100: normal keys +// numbers between 100 and 200: shifted keys +// numbers over 200: function invocations + +int base_layout[ROW_COUNT][COL_COUNT] = \ + { {20, 26, 8, 21, 23, 0, 28, 24, 12, 18, 19}, \ + {4, 22, 7, 9, 10, 0, 11, 13, 14, 15, 51}, \ + {29, 27, 6, 25, 5, 101, 17, 16, 54, 55, 56}, \ + {41, 43, 108, 102, 42, 104, 44, 0, 52, 47, 40} }; + +int fn_layout[ROW_COUNT][COL_COUNT] = \ + { {108+30, 108+31, 108+45, 108+46, 108 + 49, 0, 75, 36, 37, 38, 108+37}, \ + {108+32, 108+33, 108+38, 108+39, 53, 0, 78, 33, 34, 35, 108+46}, \ + {108 + 34, 108 + 35, 45, 46, 108+53, 101, 49, 30, 31, 32, 108+47}, \ + {255, 108 + 73, 108, 102, 0, 104, 0, 0, 55, 39, 48} }; + +int *current_row; + +int pressed_count = 0; + + + +void press(int keycode) { + if(!keycode || pressed_count >= 6) return; + if(keycode == 255 || keycode == 5) { + reset(); // TODO: make a table of codes -> functions + } else if(keycode > 108) { + keyboard_modifier_keys |= KEY_SHIFT; + keyboard_keys[pressed_count++] = (keycode - 108); + } else if(keycode > 100) { + keyboard_modifier_keys |= (keycode - 100); + } else { + keyboard_keys[pressed_count++] = keycode; + }; +}; + +void activate_row(int row) { + PORTD = (char)(~(1 << row)) | 32; // leave the LED on +}; + +void scan_row(int row) { + int cols = (~(PINB + ((PINF >> 4) << 8))) & 2047; + for(int col = 0; col < 8; col++) { + if(cols & 1) { + press(current_row[col]); + }; + cols = cols >> 1; + }; +}; + + + +void init() { + CPU_PRESCALE(0); + DDRD = 255; + DDRB = 0; + DDRF = 0; + PORTB = 255; + PORTF = 255; + usb_init(); + while (!usb_configured()) /* wait */ ; + _delay_ms(1000); +}; + +void clear_keys() { + keyboard_modifier_keys = 0; + pressed_count = 0; + for(int i = 0; i < 6; i++) { + keyboard_keys[i] = 0; + }; +}; + +int main() { + init(); + while(1) { + // 4th row is still active from last scan + current_row = FN_PRESSED ? fn_layout : base_layout; + for(int i = 0; i < ROW_COUNT; i++) { + activate_row(i); + scan_row(i); + current_row += COL_COUNT; + _delay_us(50); + }; + usb_keyboard_send(); + clear_keys(); + }; +}; + +void reset(void) { + UDCON = 1; + USBCON = (1<= NUM_DESC_LIST) { + UECONX = (1< desc_length) len = desc_length; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1<= 1 && i <= MAX_ENDPOINT) { + usb_send_in(); + UENUM = i; + if (bRequest == SET_FEATURE) { + UECONX = (1<> 8); + keyboard_idle_count = 0; + usb_send_in(); + return; + } + if (bRequest == HID_SET_PROTOCOL) { + keyboard_protocol = wValue; + usb_send_in(); + return; + } + } + } + } + UECONX = (1< + +void usb_init(void); // initialize everything +uint8_t usb_configured(void); // is the USB port configured + +int8_t usb_keyboard_press(uint8_t key, uint8_t modifier); +int8_t usb_keyboard_send(void); +extern uint8_t keyboard_modifier_keys; +extern uint8_t keyboard_keys[6]; +extern volatile uint8_t keyboard_leds; + +// This file does not include the HID debug functions, so these empty +// macros replace them with nothing, so users can compile code that +// has calls to these functions. +#define usb_debug_putchar(c) +#define usb_debug_flush_output() + + +#define KEY_CTRL 0x01 +#define KEY_SHIFT 0x02 +#define KEY_ALT 0x04 +#define KEY_GUI 0x08 +#define KEY_LEFT_CTRL 0x01 +#define KEY_LEFT_SHIFT 0x02 +#define KEY_LEFT_ALT 0x04 +#define KEY_LEFT_GUI 0x08 +#define KEY_RIGHT_CTRL 0x10 +#define KEY_RIGHT_SHIFT 0x20 +#define KEY_RIGHT_ALT 0x40 +#define KEY_RIGHT_GUI 0x80 + +#define KEY_A 4 +#define KEY_B 5 +#define KEY_C 6 +#define KEY_D 7 +#define KEY_E 8 +#define KEY_F 9 +#define KEY_G 10 +#define KEY_H 11 +#define KEY_I 12 +#define KEY_J 13 +#define KEY_K 14 +#define KEY_L 15 +#define KEY_M 16 +#define KEY_N 17 +#define KEY_O 18 +#define KEY_P 19 +#define KEY_Q 20 +#define KEY_R 21 +#define KEY_S 22 +#define KEY_T 23 +#define KEY_U 24 +#define KEY_V 25 +#define KEY_W 26 +#define KEY_X 27 +#define KEY_Y 28 +#define KEY_Z 29 +#define KEY_1 30 +#define KEY_2 31 +#define KEY_3 32 +#define KEY_4 33 +#define KEY_5 34 +#define KEY_6 35 +#define KEY_7 36 +#define KEY_8 37 +#define KEY_9 38 +#define KEY_0 39 +#define KEY_ENTER 40 +#define KEY_ESC 41 +#define KEY_BACKSPACE 42 +#define KEY_TAB 43 +#define KEY_SPACE 44 +#define KEY_MINUS 45 +#define KEY_EQUAL 46 +#define KEY_LEFT_BRACE 47 +#define KEY_RIGHT_BRACE 48 +#define KEY_BACKSLASH 49 +#define KEY_NUMBER 50 +#define KEY_SEMICOLON 51 +#define KEY_QUOTE 52 +#define KEY_TILDE 53 +#define KEY_COMMA 54 +#define KEY_PERIOD 55 +#define KEY_SLASH 56 +#define KEY_CAPS_LOCK 57 +#define KEY_F1 58 +#define KEY_F2 59 +#define KEY_F3 60 +#define KEY_F4 61 +#define KEY_F5 62 +#define KEY_F6 63 +#define KEY_F7 64 +#define KEY_F8 65 +#define KEY_F9 66 +#define KEY_F10 67 +#define KEY_F11 68 +#define KEY_F12 69 +#define KEY_PRINTSCREEN 70 +#define KEY_SCROLL_LOCK 71 +#define KEY_PAUSE 72 +#define KEY_INSERT 73 +#define KEY_HOME 74 +#define KEY_PAGE_UP 75 +#define KEY_DELETE 76 +#define KEY_END 77 +#define KEY_PAGE_DOWN 78 +#define KEY_RIGHT 79 +#define KEY_LEFT 80 +#define KEY_DOWN 81 +#define KEY_UP 82 +#define KEY_NUM_LOCK 83 +#define KEYPAD_SLASH 84 +#define KEYPAD_ASTERIX 85 +#define KEYPAD_MINUS 86 +#define KEYPAD_PLUS 87 +#define KEYPAD_ENTER 88 +#define KEYPAD_1 89 +#define KEYPAD_2 90 +#define KEYPAD_3 91 +#define KEYPAD_4 92 +#define KEYPAD_5 93 +#define KEYPAD_6 94 +#define KEYPAD_7 95 +#define KEYPAD_8 96 +#define KEYPAD_9 97 +#define KEYPAD_0 98 +#define KEYPAD_PERIOD 99 + + + + +// Everything below this point is only intended for usb_serial.c +#ifdef USB_SERIAL_PRIVATE_INCLUDE +#include +#include +#include + +#define EP_TYPE_CONTROL 0x00 +#define EP_TYPE_BULK_IN 0x81 +#define EP_TYPE_BULK_OUT 0x80 +#define EP_TYPE_INTERRUPT_IN 0xC1 +#define EP_TYPE_INTERRUPT_OUT 0xC0 +#define EP_TYPE_ISOCHRONOUS_IN 0x41 +#define EP_TYPE_ISOCHRONOUS_OUT 0x40 + +#define EP_SINGLE_BUFFER 0x02 +#define EP_DOUBLE_BUFFER 0x06 + +#define EP_SIZE(s) ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))) + +#define MAX_ENDPOINT 4 + +#define LSB(n) (n & 255) +#define MSB(n) ((n >> 8) & 255) + +#if defined(__AVR_AT90USB162__) +#define HW_CONFIG() +#define PLL_CONFIG() (PLLCSR = ((1<