]> git.armaanb.net Git - atreides.git/blob - firmware/atreus.c
Move layouts to their own file; unroll scan_row loop.
[atreides.git] / firmware / atreus.c
1 #include <stdlib.h>
2 #include <avr/io.h>
3 #include <util/delay.h>
4 #include "usb_keyboard.h"
5
6 #define ROW_COUNT 4
7 #define COL_COUNT 11
8
9 #define FN_PRESSED (~PINB & 8)
10
11 #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
12
13 void reset(void);
14
15 \f
16
17 // Outputs
18 // |------------+----+----+----+----|
19 // | row number |  0 |  1 |  2 |  3 |
20 // |------------+----+----+----+----|
21 // | pin number | D0 | D1 | D2 | D3 |
22 // |------------+----+----+----+----|
23
24 // Inputs
25 // |---------------+----+----+----+----+----+----+----+----+----+----+----|
26 // | column number |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 |
27 // |---------------+----+----+----+----+----+----+----+----+----+----+----|
28 // | pin number    | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | F4 | F5 | F6 |
29 // |---------------+----+----+----+----+----+----+----+----+----+----+----|
30
31 \f
32
33 #include "layouts.h"
34
35 int *current_row;
36 int pressed_count = 0;
37
38 \f
39
40 void press(int keycode) {
41   if(!keycode) return;
42   if(keycode == 255) {
43     reset(); // TODO: make a table of codes -> functions
44   } else if(keycode > 108 && pressed_count < 6) {
45     keyboard_modifier_keys |= KEY_SHIFT;
46     keyboard_keys[pressed_count++] = (keycode - 108);
47   } else if(keycode > 100) {
48     keyboard_modifier_keys |= (keycode - 100);
49   } else if(pressed_count < 6){
50     keyboard_keys[pressed_count++] = keycode;
51   };
52 };
53
54 void activate_row(int row) {
55   PORTD = (char)(~(1 << row)) | 32; // leave the LED on
56 };
57
58 void scan_row(int row) {
59   // if((~PINF) & 64) reset();
60   unsigned int col_bits = ((~PINF << 4) & (1024 | 512 | 256)) | (~PINB & 255);
61   /* for(int col = 0; col < COL_COUNT; col++) { */
62   /*   if(col_bits & 1024) { */
63   /*     press(current_row[col]); */
64   /*   } */
65   /*   col_bits << 1; */
66   /* } */
67   if(col_bits & 1024) press(current_row[0]);
68   if(col_bits & 512) press(current_row[1]);
69   if(col_bits & 256) press(current_row[2]);
70   if(col_bits & 128) press(current_row[3]);
71   if(col_bits & 64) press(current_row[4]);
72   if(col_bits & 32) press(current_row[5]);
73   if(col_bits & 16) press(current_row[6]);
74   if(col_bits & 8) press(current_row[7]);
75   if(col_bits & 4) press(current_row[8]);
76   if(col_bits & 2) press(current_row[9]);
77   if(col_bits & 1) press(current_row[10]);
78 };
79
80 \f
81
82 void init() {
83   CPU_PRESCALE(0);
84   DDRD = 255;
85   DDRB = DDRF = 0;
86   PORTB = PORTF = 255;
87   usb_init();
88   while (!usb_configured()) /* wait */ ;
89   _delay_ms(1000);
90 };
91
92 void clear_keys() {
93   keyboard_modifier_keys = 0;
94   pressed_count = 0;
95   for(int i = 0; i < 6; i++) {
96     keyboard_keys[i] = 0;
97   };
98 };
99
100 int main() {
101   init();
102   while(1) {
103     // 4th row is still active from last scan
104     current_row = FN_PRESSED ? fn_layout : base_layout;
105     for(int i = 0; i < ROW_COUNT; i++) {
106       activate_row(i);
107       scan_row(i);
108       current_row += COL_COUNT;
109       _delay_us(50);
110     };
111     usb_keyboard_send();
112     clear_keys();
113   };
114 };
115
116 void reset(void) {
117   UDCON = 1; USBCON = (1<<FRZCLK); UCSR1B = 0;
118   _delay_ms(5);
119   EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
120   TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
121   DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
122   PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
123   asm volatile("jmp 0x7E00");
124 };