There, I fixed it! It does compile, though I did not yet test it. I
[cerebrum.git] / cerebrum_firmware.c
blob2df295774918069030dcf720cdd6ab63e45ffdf2
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 //Stuff for the SWITCH
18 //DDRH |= 0x20;
19 //PORTH |= 0x20;
20 //s/w PWM
21 TCCR0B |= _BV(CS00);
22 TIMSK0 |= _BV(TOIE0);
23 DDRL = 0xFF; //PWM outputs
24 //The DDRs of the led matrix outputs are set in the mux loop.
25 sei();
28 //this scary construct is in place to make the compiler happy. if you know a better way, feel free to improve.
29 uint8_t _frameBuffer[] = {0,0,0,0};
30 uint8_t _secondFrameBuffer[] = {0,0,0,0};
31 uint8_t* frameBuffer = _frameBuffer;
32 uint8_t* secondFrameBuffer = _secondFrameBuffer;
33 char nbuf;
34 int state = 0;
35 uint8_t switch_last_state = 0;
36 int switch_debounce_timeout = 0;
37 uint8_t mcnt = 0;
38 uint8_t ccnt = 0;
40 #define PWM_COUNT 8
41 uint8_t pwm_cycle = 0;
42 uint8_t pwm_val[PWM_COUNT];
43 #define INPUT_COUNT 12
44 uint8_t debounce_timeouts[INPUT_COUNT];
45 uint8_t switch_states[INPUT_COUNT];
47 void swapBuffers(void){
48 uint8_t* tmp = frameBuffer;
49 frameBuffer = secondFrameBuffer;
50 secondFrameBuffer = tmp;
53 void setLED(int num, int val){
54 if(num<32){
55 frameBuffer[num>>3] &= ~(1<<(num&7));
56 if(val)
57 frameBuffer[num>>3] |= 1<<(num&7);
61 int parseHex(char* buf){
62 int result = 0;
63 int len = 2;
64 for(int i=0; i<len; i++){
65 char c = buf[len-i];
66 int v = 0;
67 if(c>='0' && c<='9'){
68 v=(c-'0');
69 }else if(c>='a' && c<= 'f'){
70 v=(c-'a'+10);
71 }else if(c>='A' && c<= 'F'){
72 v=(c-'A'+10);
74 result |= v<<(4*i);
76 return result;
79 void loop(){ //one frame
80 static uint8_t escape_state = 0;
81 uint16_t receive_state = 1;
82 //primitive somewhat messy state machine of the uart interface
83 do{ //Always empty the receive buffer since there are _delay_xxs in the following code and thus this might not run all that often.
84 receive_state = uart_getc();
85 char c = receive_state&0xFF;
86 receive_state &= 0xFF00;
87 //escape code format:
88 // \\ - backslash
89 // \n - newline
90 // \[x] - x
91 //eats three commands: 's' (0x73) led value sets led number [led] to [value]
92 // 'b' (0x62) buffer buffer buffer buffer sets the whole frame buffer
93 // 'a' (0x61) meter value sets analog meter number [meter] to [value]
94 //this device will utter a "'c' (0x63) num state" when switch [num] changes state to [state]
95 //commands are terminated by \n
96 if(!receive_state){
97 if(!escape_state){
98 receive_state |= 0x02;
99 if(c == '\\'){
100 escape_state = 1;
101 }else if(c == '\n'){
102 state = 0;
104 }else{
105 receive_state = 0;
106 escape_state = 0;
107 switch(c){
108 case '\\':
109 break;
110 case 'n':
111 c = '\n';
112 break;
116 if(!receive_state){
117 switch(state){
118 case 0: //Do not assume anything about the variables used
119 switch(c){
120 case 's':
121 state = 2;
122 break;
123 case 'b':
124 nbuf = 0;
125 state = 4;
126 break;
127 case 'a':
128 state = 5;
129 nbuf = 0;
130 break;
132 break;
133 case 2:
134 nbuf=c;
135 state = 3;
136 break;
137 case 3:
138 setLED(nbuf, c);
139 state = 0;
140 break;
141 case 4:
142 secondFrameBuffer[(uint8_t) nbuf] = c;
143 nbuf++;
144 if(nbuf == 4){
145 swapBuffers();
146 state = 0;
148 break;
149 case 5:
150 if(c > PWM_COUNT)
151 c = 0;
152 nbuf = c;
153 state = 6;
154 break;
155 case 6:
156 pwm_val[(uint8_t) nbuf] = c;
157 state = 0;
160 }while(!receive_state);
161 for(int i=0; i<8; i++){
162 uint8_t Q = 0x80>>i; //select the currently active "row" of the matrix. On the protoboards I make, this actually corresponds to physical traces.
163 uint8_t DDRQ = 0xFF>>i; //This is supposed to be an optimization. It is untested and will probably not work.
164 //de-packing of frame data: data is packed like this: [11111117][22222266][33333555][4444----]
165 if(!(i&4))
166 Q |= frameBuffer[i&3] >> i;
167 else
168 Q |= frameBuffer[i&3] & (0xFF << (i&3));
169 DDRC = DDRQ;
170 PORTC = Q;
171 //PORTD &= 0x0F;
172 //PORTD |= Q&0xF0;
173 //PORTB &= 0xF0;
174 //PORTB |= Q&0x0F;
175 Q = 0x80>>i;
176 if(!(i&4))
177 Q |= frameBuffer[4+(i&3)] >> i;
178 else
179 Q |= frameBuffer[4+(i&3)] & (0xFF << (i&3));
180 DDRA = DDRQ;
181 PORTA = Q;
182 //PORTD &= 0x0F;
183 //PORTD |= Q&0xF0;
184 //PORTB &= 0xF0;
185 //PORTB |= Q&0x0F;
186 _delay_ms(1); //Should result in >100Hz refresh rate
188 switch_states[0] |= !!(PINH&0x02);
189 for(int i=0; i<INPUT_COUNT; i++){
190 debounce_timeouts[i]--;
191 //A #define for the debounce time would be great
192 if(debounce_timeouts[i] == 0){
193 uint8_t new_switch_state = switch_states[i]<<1;
194 if(!(switch_states[i]^new_switch_state)){
195 uart_putc('c');
196 uart_putc(i);
197 uart_putc(switch_states[i]&1);
198 debounce_timeouts[i] = 0xFF;
199 switch_states[i] = new_switch_state&3;
205 //Called every 256 cpu clks (i.e should not get overly long)
206 ISR(TIMER0_OVF_vect){
207 pwm_cycle++;
208 //example code
209 uint8_t Q = 0;
210 //The following loop NEEDS to be unrolled.
211 for(uint8_t i=0; i<8; i++){
212 Q |= (pwm_val[i] > pwm_cycle)<<i;
214 PORTL = Q;