Core functionality should be restored. Implemented escape codes. Added a
[cerebrum.git] / cerebrum_firmware.c
blobc6b58d11fe393c5a2c5b41184ad4a9145bc5d4fc
1 #include <avr/io.h>
2 #include <util/delay.h>
3 #include <avr/pgmspace.h>
4 #include <avr/interrupt.h>
5 #include "uart.h"
7 void setup(void);
8 void loop(void);
10 int main(void){
11 setup();
12 for(;;) loop();
15 void setup(){
16 uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(115201, F_CPU));
17 //software PWM init FIXME
18 DDRH |= 0x20;
19 PORTH |= 0x20;
20 sei();
23 //this scary construct is in place to make the compiler happy. if you know a better way, feel free to improve.
24 uint8_t _frameBuffer[] = {0,0,0,0};
25 uint8_t _secondFrameBuffer[] = {0,0,0,0};
26 uint8_t* frameBuffer = _frameBuffer;
27 uint8_t* secondFrameBuffer = _secondFrameBuffer;
28 char nbuf;
29 int state = 0;
30 uint8_t switch_last_state = 0;
31 int switch_debounce_timeout = 0;
32 uint8_t mcnt = 0;
33 uint8_t ccnt = 0;
35 uint8_t pwm_cycle = 0;
36 uint8_t pwm_val[4];
38 void swapBuffers(void){
39 uint8_t* tmp = frameBuffer;
40 frameBuffer = secondFrameBuffer;
41 secondFrameBuffer = tmp;
44 void setLED(int num, int val){
45 if(num<32){
46 frameBuffer[num>>3] &= ~(1<<(num&7));
47 if(val)
48 frameBuffer[num>>3] |= 1<<(num&7);
52 int parseHex(char* buf){
53 int result = 0;
54 int len = 2;
55 for(int i=0; i<len; i++){
56 char c = buf[len-i];
57 int v = 0;
58 if(c>='0' && c<='9'){
59 v=(c-'0');
60 }else if(c>='a' && c<= 'f'){
61 v=(c-'a'+10);
62 }else if(c>='A' && c<= 'F'){
63 v=(c-'A'+10);
65 result |= v<<(4*i);
67 return result;
70 void loop(){ //one frame
71 static uint8_t escape_state = 0;
72 uint16_t receive_status = 1;
73 //primitive somewhat messy state machine of the uart interface
74 do{ //Always empty the receive buffer since there are _delay_xxs in the following code and thus this might not run all that often.
75 receive_status = uart_getc();
76 char c = receive_status&0xFF;
77 receive_status &= 0xFF00;
78 //eats three commands: 's' (0x73) led value sets led number [led] to [value]
79 // 'b' (0x62) buffer buffer buffer buffer sets the whole frame buffer
80 // 'a' (0x61) meter value sets analog meter number [meter] to [value]
81 if(!receive_state){
82 if(!escape_state){
83 receive_state |= 0x02;
84 if(c == '\\'){
85 escape_state = 1;
86 }else if(c == '\n'){
87 state = 0;
89 }else{
90 receive_state = 0;
91 escape_state = 0;
92 switch(c){
93 case '\\':
94 break;
95 case 'n':
96 c = '\n';
97 break;
101 if(!receive_status){
102 switch(state){
103 case 0: //Do not assume anything about the variables used
104 switch(c){
105 case 's':
106 state = 2;
107 break;
108 case 'b':
109 nbuf = 0;
110 state = 4;
111 break;
112 case 'a':
113 state = 5;
114 nbuf = 0;
115 break;
117 break;
118 case 2:
119 nbuf=c;
120 state = 3;
121 break;
122 case 3:
123 setLED(nbuf, c);
124 state = 0;
125 break;
126 case 4:
127 secondFrameBuffer[(uint8_t) nbuf] = c;
128 nbuf++;
129 if(nbuf == 4){
130 swapBuffers();
131 state = 0;
133 break;
134 case 5:
135 nbuf = c;
136 state = 6;
137 if(nbuf >= 4) //prevent array overflows
138 nbuf = 0;
139 break;
140 case 6:
141 pwm_val[(uint8_t) nbuf] = c;
142 state = 0;
145 }while(!receive_status);
146 for(int i=0; i<8; i++){
147 uint8_t Q = 0x80>>i; //select the currently active "row" of the matrix. On the protoboards I make, this actually corresponds to physical traces.
148 //de-packing of frame data: data is packed like this: [11111117][22222266][33333555][4444----]
149 if(!(i&4))
150 Q |= frameBuffer[i&3] >> i;
151 else
152 Q |= frameBuffer[i&3] & (0xFF << (i&3));
153 //equivalent to the code above: <== revisiting this, I'm not quite sure about this anymore.
154 //Q |= frameBuffer[i&3]>>(i&(0x30>>(i&4))) & (0xFF<<(i&(0x30>>(!i&4))));
155 PORTD &= 0x0F;
156 PORTD |= Q&0xF0;
157 PORTB &= 0xF0;
158 PORTB |= Q&0x0F;
159 _delay_ms(1); //Should result in >100Hz refresh rate