2 #include <util/delay.h>
3 #include <avr/pgmspace.h>
4 #include <avr/interrupt.h>
16 uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(115201, F_CPU
));
17 //Stuff for the SWITCH
23 DDRL
= 0xFF; //PWM outputs
24 //The DDRs of the led matrix outputs are set in the mux loop.
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
;
35 uint8_t switch_last_state
= 0;
36 int switch_debounce_timeout
= 0;
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
){
55 frameBuffer
[num
>>3] &= ~(1<<(num
&7));
57 frameBuffer
[num
>>3] |= 1<<(num
&7);
61 int parseHex(char* buf
){
64 for(int i
=0; i
<len
; i
++){
69 }else if(c
>='a' && c
<= 'f'){
71 }else if(c
>='A' && c
<= 'F'){
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;
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
98 receive_state
|= 0x02;
118 case 0: //Do not assume anything about the variables used
142 secondFrameBuffer
[(uint8_t) nbuf
] = c
;
156 pwm_val
[(uint8_t) nbuf
] = c
;
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----]
166 Q
|= frameBuffer
[i
&3] >> i
;
168 Q
|= frameBuffer
[i
&3] & (0xFF << (i
&3));
177 Q
|= frameBuffer
[4+(i
&3)] >> i
;
179 Q
|= frameBuffer
[4+(i
&3)] & (0xFF << (i
&3));
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
)){
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
){
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
;