2 Copyright (C) 2012 jaseg <s@jaseg.de>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 version 3 as published by the Free Software Foundation.
10 #include <util/delay.h>
11 #include <avr/pgmspace.h>
12 #include <avr/interrupt.h>
14 #include "r0ketbeam.h"
25 uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(115200, F_CPU
));
26 //s/w "BCM"(<== "Binary Code Modulation") timer setup
28 TCCR0A |= _BV(WGM00)|_BV(WGM01);
32 //FIXME set PWM output DDRs
33 //The DDRs of the led matrix outputs are set in the mux loop.
38 //this scary construct is in place to make the compiler happy. if you know a better way, feel free to improve.
39 uint8_t _frameBuffer
[] = {0,0,0,0};
40 uint8_t _secondFrameBuffer
[] = {0,0,0,0};
41 uint8_t* frameBuffer
= _frameBuffer
;
42 uint8_t* secondFrameBuffer
= _secondFrameBuffer
;
45 uint8_t switch_last_state
= 0;
46 int switch_debounce_timeout
= 0;
51 uint8_t pwm_cycle
= 0;
52 uint8_t pwm_val
[PWM_COUNT
];
54 uint8_t debounce_timeouts
[INPUT_COUNT
];
55 uint8_t switch_states
[INPUT_COUNT
];
57 void swapBuffers(void){
58 uint8_t* tmp
= frameBuffer
;
59 frameBuffer
= secondFrameBuffer
;
60 secondFrameBuffer
= tmp
;
63 void setLED(int num
, int val
){
65 frameBuffer
[num
>>3] &= ~(1<<(num
&7));
67 frameBuffer
[num
>>3] |= 1<<(num
&7);
71 int parseHex(char* buf
){
74 for(int i
=0; i
<len
; i
++){
79 }else if(c
>='a' && c
<= 'f'){
81 }else if(c
>='A' && c
<= 'F'){
89 inline char hex_nibble(uint8_t data
){
96 void put_hex(uint8_t data
){
97 uart_putc(hex_nibble(data
&15));
98 uart_putc(hex_nibble(data
>>4));
101 void loop(){ //one frame
102 static uint8_t escape_state
= 0;
103 uint16_t receive_state
= 1;
104 //primitive somewhat messy state machine of the uart interface
105 do{ //Always empty the receive buffer since there are _delay_xxs in the following code and thus this might not run all that often.
106 receive_state
= uart_getc();
107 char c
= receive_state
&0xFF;
108 receive_state
&= 0xFF00;
109 //escape code format:
113 //eats three commands: 's' (0x73) led value sets led number [led] to [value]
114 // 'b' (0x62) buffer buffer buffer buffer sets the whole frame buffer
115 // 'a' (0x61) meter value sets analog meter number [meter] to [value]
116 // 'r' (0x72) read the frame buffer
117 //this device will utter a "'c' (0x63) num state" when switch [num] changes state to [state]
118 //commands are terminated by \n
122 receive_state
|= 0x02;
125 receive_state
|= 0x02;
142 case 0: //Do not assume anything about the variables used
158 for(uint8_t i
=0; i
<sizeof(frameBuffer
); i
++){
159 put_hex(frameBuffer
[i
]);
174 secondFrameBuffer
[(uint8_t) nbuf
] = c
;
188 pwm_val
[(uint8_t) nbuf
] = c
;
192 }while(!receive_state
);
193 for(int i
=0; i
<8; i
++){
194 uint8_t Q
= 0x80>>i
; //select the currently active "row" of the matrix. On the protoboards I make, this actually corresponds to physical traces.
195 //uint8_t DDRQ = 0xFF>>i; //This is supposed to be an optimization. It is untested and will probably not work.
196 uint8_t DDRQ
= 0xFF; //Just for testing: reactivating the old behavioor
197 //unpacking of frame data: data is packed like this: [11111117][22222266][33333555][4444----]
199 Q
|= frameBuffer
[i
&3] >> i
;
201 Q
|= frameBuffer
[i
&3] & (0xFF << (i
&3));
202 //FIXME this whole mapping shit should be done in h/w!!1!
203 //FIXME this whole mapping is not even correct!!1!
204 //FIXME IT DOES NOT WORK!!1!
226 DDRB
|=(DDRQ
&0xC0)>>2;
229 /* second channel skeleton
232 Q |= frameBuffer[4+(i&3)] >> i;
234 Q |= frameBuffer[4+(i&3)] & (0xFF << (i&3));
246 switch_states[0] |= !!(PINH&0x02);
247 for(int i=0; i<INPUT_COUNT; i++){
248 debounce_timeouts[i]--;
249 //A #define for the debounce time would be great
250 if(debounce_timeouts[i] == 0){
251 uint8_t new_switch_state = switch_states[i]<<1;
252 if(!(switch_states[i]^new_switch_state)){
255 uart_putc(switch_states[i]&1);
256 debounce_timeouts[i] = 0xFF;
257 switch_states[i] = new_switch_state&3;
265 //Called every 256 cpu clks (i.e should not get overly long)
266 ISR(TIMER0_OVF_vect
){
268 Q
|= (pwm_val
[0] & pwm_cycle
);
269 Q
|= (pwm_val
[1] & pwm_cycle
)?2:0;
270 Q
|= (pwm_val
[2] & pwm_cycle
)?4:0;
271 Q
|= (pwm_val
[3] & pwm_cycle
)?8:0;
272 Q
|= (pwm_val
[4] & pwm_cycle
)?16:0;