|
1 #include <avr/interrupt.h> |
|
2 #include <avr/io.h> |
|
3 #include <avr/wdt.h> |
|
4 #include <avr/eeprom.h> |
|
5 #include <stdlib.h> |
|
6 #include <stdint.h> |
|
7 #include <avr/pgmspace.h> |
|
8 |
|
9 #include "main.h" |
|
10 |
|
11 #include "driver/rs232.h" |
|
12 #include "util/delay.h" |
|
13 |
|
14 |
|
15 ISR ( USART_RXC_vect ) { |
|
16 } |
|
17 |
|
18 #define PULSE_PORT PORTD |
|
19 #define PULSE_BIT PD2 |
|
20 |
|
21 volatile uint16_t data = 0; |
|
22 volatile uint8_t data_len = 0; |
|
23 volatile uint8_t bitbuf_len = 0; |
|
24 volatile uint16_t bitbuf = 0; |
|
25 |
|
26 ISR ( INT0_vect ) { |
|
27 GICR &= ~_BV(INT0) ; // Disable INT0 |
|
28 // Startsignal erkannt, ab hier den Timer2 starten, |
|
29 // der liest dann alle 50µs den Zustand ein und schreibt das |
|
30 // empfangene Bit in den Puffer |
|
31 bitbuf = 0; // init |
|
32 bitbuf_len = 0b10000000; // init 1 pulse received |
|
33 TCNT2 = 0; |
|
34 TIMSK |= _BV(OCIE2); //enable timer2 interrupt |
|
35 } |
|
36 |
|
37 |
|
38 ISR ( TIMER2_COMP_vect ) { |
|
39 |
|
40 uint8_t clock; |
|
41 uint8_t state; |
|
42 uint8_t state2; |
|
43 if ((bitbuf_len & 0b10000000) == 0) clock = 0; else clock = 0xff; |
|
44 if ((bitbuf_len & 0b01000000) == 0) state = 0; else state = 0xff; |
|
45 if ((PIN(PULSE_PORT) & _BV(PULSE_BIT)) == 0) state2 = 0xff; else state2 = 0; |
|
46 |
|
47 if (clock) { |
|
48 bitbuf_len &= ~_BV(7); // switch clock to low |
|
49 // second pulse of bit |
|
50 if ((state==state2) & state2) { |
|
51 // two cycles high: packet end received |
|
52 data_len = (bitbuf_len & 0b00111111); |
|
53 TIMSK &= ~_BV(OCIE2); //disable timer2 interrupt |
|
54 GICR |= _BV(INT0) ; // Enable INT0 |
|
55 data = bitbuf; // output data |
|
56 } else { |
|
57 bitbuf_len++; // increment bit counter |
|
58 bitbuf = bitbuf << 1; // shift bits |
|
59 if (state2 == 0) bitbuf |= 1; // receive logic one |
|
60 } |
|
61 } else { |
|
62 bitbuf_len |= _BV(7); // switch clock to high |
|
63 // first pulse of bit |
|
64 if (state2) { |
|
65 bitbuf_len |= _BV(6); // store new state |
|
66 } else { |
|
67 bitbuf_len &= ~_BV(6); // store new state |
|
68 } |
|
69 } |
|
70 |
|
71 } |
|
72 |
|
73 |
|
74 uint16_t car0_new, car0_old; |
|
75 uint16_t car1_new, car1_old; |
|
76 volatile uint16_t car0, car1; |
|
77 ISR (TIMER1_OVF_vect) { |
|
78 // reset both car counters to overflow |
|
79 car0_old = 0xffff; |
|
80 car1_old = 0xffff; |
|
81 } |
|
82 |
|
83 ISR (INT1_vect) { |
|
84 // car0 detector |
|
85 uint16_t tmp = 0; |
|
86 car0_new = TCNT1; // get current counter |
|
87 if (car0_old < car0_new) { |
|
88 // calculate difference |
|
89 if (car0 == 0) tmp = car0_new-car0_old; |
|
90 if ( (tmp > 54) && (tmp < 74) ) car0 = 1; |
|
91 if ( (tmp > 118) && (tmp < 138) ) car0 = 2; |
|
92 if ( (tmp > 186) && (tmp < 206) ) car0 = 3; |
|
93 if ( (tmp > 246) && (tmp < 266) ) car0 = 4; |
|
94 } |
|
95 car0_old = car0_new; |
|
96 } |
|
97 |
|
98 ISR (TIMER1_CAPT_vect) { |
|
99 // car1 detector |
|
100 uint16_t tmp = 0; |
|
101 car1_new = TCNT1; // get current counter |
|
102 if (car1_old < car1_new) { |
|
103 // calculate difference |
|
104 if (car1 == 0) tmp = car1_new-car1_old; |
|
105 if ( (tmp > 54) && (tmp < 74) ) car1 = 1; |
|
106 if ( (tmp > 118) && (tmp < 138) ) car1 = 2; |
|
107 if ( (tmp > 186) && (tmp < 206) ) car1 = 3; |
|
108 if ( (tmp > 246) && (tmp < 266) ) car1 = 4; |
|
109 } |
|
110 car1_old = car1_new; |
|
111 } |
|
112 |
|
113 #define OSC_OFFSET 0 |
|
114 |
|
115 int main(void) |
|
116 { |
|
117 uint16_t i, data_tmp; |
|
118 uint8_t tmp, datalen_tmp; |
|
119 unsigned char s[30]; |
|
120 |
|
121 |
|
122 uint8_t car_speed[8]; |
|
123 uint8_t car_switch[8]; |
|
124 uint8_t car_switch_old[8]; |
|
125 |
|
126 // setup data bit timer2 |
|
127 TCCR2 = (1<<CS21) | (1<<WGM21); //divide by 8, set compare match |
|
128 OCR2 = TIMER2_50US+OSC_OFFSET; // insert OSC_OFFSET |
|
129 |
|
130 // initialize timer1 for IR signal detection |
|
131 TCCR1B = _BV(CS01) | _BV(ICNC1) | _BV(ICES1); // 1mhz clock, enable ICP on rising edge |
|
132 |
|
133 // enable both external interrupts |
|
134 // int 0 = data RX |
|
135 // int 1 = car0 input |
|
136 MCUCR = _BV(ISC00) | _BV(ISC01) | _BV(ISC10) | _BV(ISC11); // INT0/1 rising edge |
|
137 GICR = _BV(INT0) | _BV(INT1) ; // Enable INT0 + INT1 |
|
138 |
|
139 // enable timer interrupts |
|
140 TIMSK = _BV(OCIE2) | _BV(TOIE1) | _BV(TICIE1); //enable timer1+2 |
|
141 |
|
142 // oscillator calibration |
|
143 // atmega8@1mhz = 0xac |
|
144 // @4mhz = ca 0xa0 |
|
145 //OSCCAL = 0xa0; |
|
146 //OSCCAL = 0x9A; |
|
147 //OSCCAL = 0xa0; // internal oscillator @ 4 mhz.... doesnt work accurate! |
|
148 |
|
149 RS232_init(); // initialize RS232 interface |
|
150 RS232_puts_p(PSTR("Freeslot TrackSwitch Ready\n")); |
|
151 sei(); |
|
152 |
|
153 DDR(PORTC) = 0b00011100; |
|
154 |
|
155 i = 0; |
|
156 while (1) { |
|
157 // main loop |
|
158 |
|
159 // keep the data of all available cars (0..7) up to date |
|
160 if (data != 0) { |
|
161 data_tmp = data; |
|
162 datalen_tmp = data_len; |
|
163 if (datalen_tmp >= 5) { |
|
164 if (datalen_tmp == 13) { // sync to first packet |
|
165 i = 1; |
|
166 } else i++; |
|
167 if (datalen_tmp == 10) { // controller data packet |
|
168 tmp = (data_tmp >> 6) & 0b111; |
|
169 if (tmp < 6) { |
|
170 car_speed[tmp] = (data_tmp >> 1) & 0x0F; |
|
171 car_switch[tmp] = (data_tmp >> 5) & 1; |
|
172 } |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 for (i=0; i<6; i++) { |
|
178 if (car_switch[i] != car_switch_old[i]) { |
|
179 RS232_putc('0'+i); |
|
180 RS232_putc('0'+car_switch[i]); |
|
181 RS232_putc('\n'); |
|
182 } |
|
183 car_switch_old[i] = car_switch[i]; |
|
184 } |
|
185 |
|
186 |
|
187 /* |
|
188 i = get_car(_BV(PD3)); |
|
189 if (i > 0) { |
|
190 itoa ( i , s, 10); |
|
191 RS232_puts(s); |
|
192 RS232_putc('\n'); |
|
193 } |
|
194 _delay_ms(50); |
|
195 */ |
|
196 |
|
197 if (car0 > 0) { |
|
198 itoa ( car0 , s, 10); |
|
199 car0 = 0; |
|
200 RS232_putc('A'); |
|
201 RS232_puts(s); |
|
202 RS232_putc('\n'); |
|
203 } |
|
204 |
|
205 if (car1 > 0) { |
|
206 itoa ( car1 , s, 10); |
|
207 car1 = 0; |
|
208 RS232_putc('B'); |
|
209 RS232_puts(s); |
|
210 RS232_putc('\n'); |
|
211 } |
|
212 |
|
213 } // main loop end |
|
214 }; |
|
215 |