trackswitch/main.c

changeset 19
40a309c9c135
child 20
e333cf0e4d84
equal deleted inserted replaced
18:cc2274b92647 19:40a309c9c135
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

mercurial