Rev 1474 | Rev 1483 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed
| Rev 1474 | Rev 1479 | ||
|---|---|---|---|
| Line 10... | Line 10... | ||
| 10 | /*----------------------------------------------------------------------------- |
10 | /*----------------------------------------------------------------------------- |
| 11 | * Includes |
11 | * Includes |
| 12 | *---------------------------------------------------------------------------*/ |
12 | *---------------------------------------------------------------------------*/ |
| 13 | #include <config.h> |
13 | #include <config.h> |
| 14 | #include <drivers/mcu/pcint.h> |
14 | #include <drivers/mcu/pcint.h> |
| - | 15 | #include <drivers/mcu/gpio.h> |
|
| 15 | #include <drivers/ir/transceiver/irtransceiverMulti.h> |
16 | #include <drivers/ir/transceiver/irtransceiverMulti.h> |
| 16 | #include <drivers/ir/protocols.h> |
17 | #include <drivers/ir/protocols.h> |
| 17 | #include <avr/io.h> |
18 | #include <avr/io.h> |
| 18 | #include <avr/interrupt.h> |
19 | #include <avr/interrupt.h> |
| 19 | 20 | ||
| 20 | /*----------------------------------------------------------------------------- |
21 | /*----------------------------------------------------------------------------- |
| 21 | * Globals |
22 | * Globals |
| 22 | *---------------------------------------------------------------------------*/ |
23 | *---------------------------------------------------------------------------*/ |
| 23 | #if IR_RX_ENABLE==1 |
24 | #if IR_RX_ENABLE==1 |
| 24 | struct { |
25 | struct { |
| - | 26 | uint8_t enable; |
|
| 25 | uint16_t timeout; |
27 | uint16_t timeout; |
| 26 | uint8_t timeoutEnable; |
28 | uint8_t timeoutEnable; |
| 27 | uint16_t *rxbuf; |
29 | uint16_t *rxbuf; |
| 28 | uint8_t rxlen; |
30 | uint8_t rxlen; |
| 29 | uint8_t storeEnable; |
31 | uint8_t storeEnable; |
| 30 | irCallback_t callback; |
32 | irCallback_t callback; |
| 31 | } |
33 | } drvIrRxChannel[3]; |
| 32 | 34 | ||
| 33 | 35 | ||
| 34 | #endif |
36 | #endif |
| 35 | #if IR_TX_ENABLE==1 |
37 | #if IR_TX_ENABLE==1 |
| 36 | uint16_t *txbuf; |
38 | uint16_t *txbuf; |
| 37 | uint8_t txlen; |
39 | uint8_t txlen; |
| 38 | static uint8_t bufIndex; //selects the pulse width in buffer to send |
40 | static uint8_t bufIndex; //selects the pulse width in buffer to send |
| - | 41 | volatile uint8_t data_transmitted; |
|
| 39 | #endif |
42 | #endif |
| 40 | 43 | ||
| 41 | volatile uint8_t data_transmitted; |
- | |
| 42 | 44 | ||
| 43 | 45 | ||
| 44 | /*----------------------------------------------------------------------------- |
46 | /*----------------------------------------------------------------------------- |
| 45 | * Prerequisites |
47 | * Prerequisites |
| 46 | *---------------------------------------------------------------------------*/ |
48 | *---------------------------------------------------------------------------*/ |
| 47 | #ifndef IR_RX_ACTIVE_LOW |
49 | #ifndef IR_RX_ACTIVE_LOW |
| 48 | #define IR_RX_ACTIVE_LOW 1 |
50 | #define IR_RX_ACTIVE_LOW 1 |
| 49 | #endif |
51 | #endif |
| 50 | 52 | ||
| 51 | #ifndef IR_TX_ACTIVE_LOW |
53 | #ifndef IR_TX_ACTIVE_LOW |
| 52 | #define IR_TX_ACTIVE_LOW 0 |
54 | #define IR_TX_ACTIVE_LOW 0 |
| 53 | #endif |
55 | #endif |
| 54 | 56 | ||
| 55 | #ifndef IR_TX_ENABLE |
57 | #ifndef IR_TX_ENABLE |
| 56 | #define IR_TX_ENABLE 0 |
58 | #define IR_TX_ENABLE 0 |
| 57 | #endif |
59 | #endif |
| 58 | 60 | ||
| 59 | #ifndef IR_RX_ENABLE |
61 | #ifndef IR_RX_ENABLE |
| 60 | #define IR_RX_ENABLE 0 |
62 | #define IR_RX_ENABLE 0 |
| 61 | #endif |
63 | #endif |
| 62 | 64 | ||
| 63 | 65 | ||
| 64 | #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) |
66 | #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) |
| 65 | #define TIMSK1 TIMSK |
67 | #define TIMSK1 TIMSK |
| 66 | #define TIFR1 TIFR |
68 | #define TIFR1 TIFR |
| 67 | #define ICIE1 TICIE1 |
69 | #define ICIE1 TICIE1 |
| 68 | #endif |
70 | #endif |
| 69 | 71 | ||
| 70 | #define IR_COMPARE_VECTOR TIMER1_COMPB_vect |
72 | #define IR_COMPARE_VECTOR TIMER1_COMPB_vect |
| 71 | #define IR_TIMEOUT_VECTOR TIMER1_COMPA_vect |
73 | #define IR_TIMEOUT_VECTOR TIMER1_COMPA_vect |
| 72 | #define IR_CAPTURE_VECTOR TIMER1_CAPT_vect |
74 | #define IR_CAPTURE_VECTOR TIMER1_CAPT_vect |
| 73 | #define IR_TIMEOUT_REG OCR1A |
75 | #define IR_TIMEOUT_REG OCR1A |
| 74 | #define IR_COMPARE_REG OCR1B |
76 | #define IR_COMPARE_REG OCR1B |
| Line 139... | Line 141... | ||
| 139 | //TODO: mot slutet av ISRen laddas nästa tid in... |
141 | //TODO: mot slutet av ISRen laddas nästa tid in... |
| 140 | 142 | ||
| 141 | /* When this timeout occurs a pulsetrain is complete */ |
143 | /* When this timeout occurs a pulsetrain is complete */ |
| 142 | ISR(IR_TIMEOUT_VECTOR) |
144 | ISR(IR_TIMEOUT_VECTOR) |
| 143 | { |
145 | { |
| 144 | - | ||
| 145 | /* Find which channel timed out */ |
146 | /* Find which channel timed out */ |
| 146 | uint16_t timeDiff = 0xffff; |
147 | uint16_t timeDiff = 0xffff; |
| 147 | uint8_t channel = 0; |
148 | uint8_t channel = 0; |
| 148 |
|
149 | /* for (uint8_t i=0; i < 3; i++) |
| 149 | { |
150 | { |
| 150 |
|
151 | if ((drvIrRxChannel[channel].timeoutEnable==TRUE) && (IR_TIMEOUT_REG-drvIrRxChannel[i].timeout < timeDiff)) |
| 151 | { |
152 | { |
| 152 | timeDiff |
153 | timeDiff = IR_TIMEOUT_REG-drvIrRxChannel[i].timeout; |
| 153 | channel = i; |
154 | channel = i; |
| 154 | } |
155 | } |
| 155 | } |
156 | } |
| 156 | 157 | */ |
|
| 157 | /* If more than 3 flanks was recevied */ |
158 | /* If more than 3 flanks was recevied */ |
| 158 | if ( |
159 | if (drvIrRxChannel[channel].rxlen > 3) |
| 159 | { |
160 | { |
| 160 | /* Notify the application that a pulse train has been received. */ |
161 | /* Notify the application that a pulse train has been received. */ |
| 161 |
|
162 | drvIrRxChannel[channel].callback(channel, drvIrRxChannel[channel].rxbuf, drvIrRxChannel[channel].rxlen); |
| 162 | } |
163 | } |
| 163 | 164 | ||
| 164 |
|
165 | drvIrRxChannel[channel].storeEnable = FALSE; |
| 165 |
|
166 | drvIrRxChannel[channel].timeoutEnable = FALSE; |
| 166 | 167 | ||
| 167 |
|
168 | IR_MASK_TIMEOUT(); |
| 168 | 169 | ||
| 169 | //TODO: reset the timeout for next enabled channel |
170 | //TODO: reset the timeout for next enabled channel |
| 170 | /* |
171 | /* |
| 171 | uint16_t nextTimeout = |
172 | uint16_t nextTimeout = drvIrRxChannel[channel].timeout; |
| 172 | for (uint8_t i=0; i < 3; i++) |
173 | for (uint8_t i=0; i < 3; i++) |
| 173 | { |
174 | { |
| 174 | //TODO: hitta den med timeout härnäst (svårt med tanke på att den tiden kan ha passerat eftersom vi är under interrupt) |
175 | //TODO: hitta den med timeout härnäst (svårt med tanke på att den tiden kan ha passerat eftersom vi är under interrupt) |
| 175 | //kanske inte är så noga, i värsta fall tar det 65ms extra |
176 | //kanske inte är så noga, i värsta fall tar det 65ms extra |
| 176 | if (( |
177 | if ((drvIrRxChannel[channel].timeoutEnable) && (drvIrRxChannel[i].timeout < nextTimeout)) |
| 177 | { |
178 | { |
| 178 | nextTimeout = |
179 | nextTimeout = drvIrRxChannel[i].timeout; |
| 179 | } |
180 | } |
| 180 | } |
181 | } |
| 181 | |
182 | IR_UNMASK_TIMEOUT(); |
| 182 | IR_TIMEOUT_REG = nextTimeout; |
183 | IR_TIMEOUT_REG = nextTimeout; |
| 183 | */ |
184 | */ |
| 184 | } |
185 | } |
| 185 | #endif |
186 | #endif |
| 186 | 187 | ||
| Line 205... | Line 206... | ||
| 205 | IrTransceiver_Store(2); |
206 | IrTransceiver_Store(2); |
| 206 | } |
207 | } |
| 207 | 208 | ||
| 208 | void IrTransceiver_Store(uint8_t channel) |
209 | void IrTransceiver_Store(uint8_t channel) |
| 209 | { |
210 | { |
| 210 | static uint16_t prev_time; |
211 | static uint16_t prev_time[3]; |
| 211 | uint16_t pulsewidth; |
212 | uint16_t pulsewidth; |
| 212 | 213 | ||
| 213 | /* Read the measured transition time from the capture register. */ |
- | |
| 214 | //uint16_t time = IR_CAPTURE_REG; |
- | |
| 215 | /* Read the timer counter register to get the current "time". */ |
214 | /* Read the timer counter register to get the current "time". */ |
| 216 | uint16_t time = IR_COUNT_REG; |
215 | uint16_t time = IR_COUNT_REG; |
| 217 | 216 | ||
| 218 | /* Subtract the current measurement from the previous to get the pulse |
217 | /* Subtract the current measurement from the previous to get the pulse width. */ |
| 219 | * width. */ |
- | |
| 220 | pulsewidth = time - prev_time; |
218 | pulsewidth = time - prev_time[channel]; |
| 221 | prev_time = time; |
219 | prev_time[channel] = time; |
| 222 | 220 | ||
| 223 | /* Set the timeout. */ |
- | |
| 224 | irRxChannel[channel].timeout = time + IR_MAX_PULSE_WIDTH; |
- | |
| 225 | irRxChannel[channel].timeoutEnable = TRUE; |
- | |
| 226 | uint16_t nextTimeout = irRxChannel[channel].timeout; |
- | |
| 227 | for (uint8_t i=0; i < 3; i++) |
- | |
| 228 | { |
- | |
| 229 | //TODO: hitta den med timeout härnäst (svårt med tanke på att den tiden kan ha passerat eftersom vi är under interrupt) |
- | |
| 230 | //kanske inte är så noga, i värsta fall tar det 65ms extra |
- | |
| 231 | if ((irRxChannel[channel].timeoutEnable) && (irRxChannel[i].timeout < nextTimeout)) |
- | |
| 232 | { |
- | |
| 233 | nextTimeout = irRxChannel[i].timeout; |
- | |
| 234 | } |
- | |
| 235 | } |
- | |
| 236 | IR_TIMEOUT_REG = nextTimeout; |
- | |
| 237 | - | ||
| 238 | if ( |
221 | if (drvIrRxChannel[channel].storeEnable) |
| 239 | { |
222 | { |
| 240 | /* Store the measurement. */ |
223 | /* Store the measurement. */ |
| 241 |
|
224 | drvIrRxChannel[channel].rxbuf[drvIrRxChannel[channel].rxlen++] = pulsewidth; |
| 242 | 225 | ||
| 243 | /* Disable future measurements if we've filled the buffer. */ |
226 | /* Disable future measurements if we've filled the buffer. */ |
| 244 | //TODO: What to do in multi recevier? |
227 | //TODO: What to do in multi recevier? |
| 245 | //TODO: Report overflow to application |
228 | //TODO: Report overflow to application |
| 246 | if ( |
229 | if (drvIrRxChannel[channel].rxlen == MAX_NR_TIMES) |
| 247 | { |
230 | { |
| 248 |
|
231 | drvIrRxChannel[channel].rxlen = MAX_NR_TIMES-1; |
| 249 | //IR_MASK_CAPTURE(); |
- | |
| 250 | } |
232 | } |
| 251 | } |
233 | } |
| 252 | else |
234 | else if (drvIrRxChannel[channel].enable == TRUE) |
| 253 | { |
235 | { |
| 254 | /* The first edge of the pulse train has been detected. Enable the |
236 | /* The first edge of the pulse train has been detected. Enable the storage of the following pulsewidths. */ |
| 255 |
|
237 | drvIrRxChannel[channel].storeEnable = TRUE; |
| 256 |
|
238 | drvIrRxChannel[channel].rxlen = 0; |
| 257 |
|
239 | drvIrRxChannel[channel].timeoutEnable = TRUE; |
| - | 240 | ||
| - | 241 | /* Set the timeout for detection of the end of the pulse train. */ |
|
| - | 242 | drvIrRxChannel[channel].timeout = time + IR_MAX_PULSE_WIDTH; |
|
| - | 243 | uint16_t nextTimeout = drvIrRxChannel[channel].timeout; |
|
| - | 244 | for (uint8_t i=0; i < 3; i++) |
|
| - | 245 | { |
|
| - | 246 | //TODO: hitta den med timeout härnäst (svårt med tanke på att den tiden kan ha passerat eftersom vi är under interrupt) |
|
| - | 247 | //kanske inte är så noga, i värsta fall tar det 65ms extra |
|
| - | 248 | if ((drvIrRxChannel[channel].timeoutEnable) && (drvIrRxChannel[i].timeout < nextTimeout)) |
|
| - | 249 | { |
|
| - | 250 | nextTimeout = drvIrRxChannel[i].timeout; |
|
| - | 251 | } |
|
| - | 252 | } |
|
| - | 253 | IR_TIMEOUT_REG = nextTimeout; |
|
| - | 254 | ||
| 258 | /* Enable timeout interrupt for detection of the end of the pulse train. */ |
255 | /* Enable timeout interrupt for detection of the end of the pulse train. */ |
| 259 | IR_UNMASK_TIMEOUT(); |
256 | IR_UNMASK_TIMEOUT(); |
| 260 | 257 | ||
| 261 | //TODO: if buffer resource coordinator is implemented this is where a buffer should be assinged to this channel |
258 | //TODO: if buffer resource coordinator is implemented this is where a buffer should be assinged to this channel |
| 262 | } |
259 | } |
| 263 | } |
260 | } |
| 264 | #endif |
261 | #endif |
| 265 | 262 | ||
| 266 | 263 | ||
| 267 | /*----------------------------------------------------------------------------- |
264 | /*----------------------------------------------------------------------------- |
| 268 | * Public Functions |
265 | * Public Functions |
| 269 | *---------------------------------------------------------------------------*/ |
266 | *---------------------------------------------------------------------------*/ |
| 270 | 267 | ||
| 271 | /* call this function like this: |
268 | /* call this function like this: |
| 272 | IrTransceiver_Init_TX_Channel( |
269 | IrTransceiver_Init_TX_Channel(channelnumber, buffer, callback, pcint-id, GPIO_D6); |
| 273 | buffer is a memory location |
270 | buffer is a memory location |
| 274 | callback is a function to call when a receive/transmitt is complete |
271 | callback is a function to call when a receive/transmitt is complete |
| 275 | also call with IO port to use |
272 | also call with IO port to use |
| 276 | |
- | |
| 277 | function to deactivate channel may later be needed |
- | |
| 278 | */ |
273 | */ |
| 279 | 274 | ||
| 280 | #if IR_RX_ENABLE==1 |
275 | #if IR_RX_ENABLE==1 |
| 281 | void IrTransceiver_Init_TX_Channel(uint8_t channel, uint16_t *buffer, irCallback_t callback, uint8_t pcint_id, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint) |
276 | void IrTransceiver_Init_TX_Channel(uint8_t channel, uint16_t *buffer, irCallback_t callback, uint8_t pcint_id, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint) |
| 282 | { |
277 | { |
| 283 | if (channel == 0) |
278 | if (channel == 0) |
| 284 | { |
279 | { |
| 285 | Pcint_SetCallback(pcint_id, pcint, &IrTransceiver_Store_ch0); |
280 | Pcint_SetCallback(pcint_id, pcint, &IrTransceiver_Store_ch0); |
| 286 | } |
281 | } |
| 287 | else if (channel == 1) |
282 | else if (channel == 1) |
| 288 | { |
283 | { |
| 289 | Pcint_SetCallback(pcint_id, pcint, &IrTransceiver_Store_ch1); |
284 | Pcint_SetCallback(pcint_id, pcint, &IrTransceiver_Store_ch1); |
| 290 | } |
285 | } |
| 291 | else if (channel == 2) |
286 | else if (channel == 2) |
| 292 | { |
287 | { |
| 293 | Pcint_SetCallback(pcint_id, pcint, &IrTransceiver_Store_ch2); |
288 | Pcint_SetCallback(pcint_id, pcint, &IrTransceiver_Store_ch2); |
| 294 | } |
289 | } |
| 295 | 290 | ||
| 296 | if (channel < 3) |
291 | if (channel < 3) |
| 297 | { |
292 | { |
| 298 | /* Set port direction to input */ |
293 | /* Set port direction to input */ |
| 299 | *ddr &= ~(1 << nr); |
294 | *ddr &= ~(1 << nr); |
| 300 | 295 | ||
| 301 |
|
296 | drvIrRxChannel[channel].rxbuf = buffer; |
| 302 |
|
297 | drvIrRxChannel[channel].rxlen = 0; |
| 303 |
|
298 | drvIrRxChannel[channel].storeEnable = FALSE; |
| 304 |
|
299 | drvIrRxChannel[channel].timeoutEnable = FALSE; |
| 305 |
|
300 | drvIrRxChannel[channel].callback = callback; |
| - | 301 | drvIrRxChannel[channel].enable = TRUE; |
|
| - | 302 | } |
|
| - | 303 | } |
|
| - | 304 | ||
| - | 305 | /* call this function like this: |
|
| - | 306 | IrTransceiver_DeInit_TX_Channel(channelnumber, pcint-id, GPIO_D6); |
|
| - | 307 | */ |
|
| - | 308 | ||
| - | 309 | void IrTransceiver_DeInit_TX_Channel(uint8_t channel, uint8_t pcint_id, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint) |
|
| - | 310 | { |
|
| - | 311 | /* Deactivate interrupt */ |
|
| - | 312 | Pcint_SetCallback(pcint_id, pcint, 0); |
|
| - | 313 | ||
| - | 314 | if (channel < 3) |
|
| - | 315 | { |
|
| - | 316 | /* Deactivate channel */ |
|
| - | 317 | drvIrRxChannel[channel].enable = FALSE; |
|
| - | 318 | drvIrRxChannel[channel].rxlen = 0; |
|
| - | 319 | drvIrRxChannel[channel].storeEnable = FALSE; |
|
| - | 320 | drvIrRxChannel[channel].timeoutEnable = FALSE; |
|
| - | 321 | drvIrRxChannel[channel].callback = 0; |
|
| - | 322 | } |
|
| - | 323 | } |
|
| - | 324 | ||
| - | 325 | uint8_t IrTransceiver_GetStoreEnable(uint8_t channel) |
|
| - | 326 | { |
|
| - | 327 | return drvIrRxChannel[channel].storeEnable; |
|
| - | 328 | } |
|
| - | 329 | ||
| - | 330 | void IrTransceiver_Disable(uint8_t channel) |
|
| - | 331 | { |
|
| - | 332 | if (channel < 3) |
|
| - | 333 | { |
|
| - | 334 | /* Soft disable channel */ |
|
| - | 335 | drvIrRxChannel[channel].enable = FALSE; |
|
| - | 336 | } |
|
| - | 337 | } |
|
| - | 338 | void IrTransceiver_Enable(uint8_t channel) |
|
| - | 339 | { |
|
| - | 340 | if (channel < 3) |
|
| - | 341 | { |
|
| - | 342 | /* Soft enable channel */ |
|
| - | 343 | drvIrRxChannel[channel].enable = TRUE; |
|
| - | 344 | } |
|
| - | 345 | } |
|
| - | 346 | void IrTransceiver_Reset(uint8_t channel) |
|
| - | 347 | { |
|
| - | 348 | if (channel < 3) |
|
| 306 | 349 | { |
|
| - | 350 | /* Reset channel */ |
|
| - | 351 | drvIrRxChannel[channel].rxlen = 0; |
|
| - | 352 | drvIrRxChannel[channel].storeEnable = FALSE; |
|
| - | 353 | drvIrRxChannel[channel].timeoutEnable = FALSE; |
|
| 307 | } |
354 | } |
| 308 | } |
355 | } |
| - | 356 | ||
| 309 | #endif |
357 | #endif |
| 310 | 358 | ||
| 311 | /* |
359 | /* |
| 312 | void IrTransceiver_Init_RX_Channel(uint8_t channel, uint16_t *buffer, irCallback_t callback, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint) |
360 | void IrTransceiver_Init_RX_Channel(uint8_t channel, uint16_t *buffer, irCallback_t callback, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint) |
| 313 | { |
361 | { |
| Line 315... | Line 363... | ||
| 315 | } |
363 | } |
| 316 | */ |
364 | */ |
| 317 | 365 | ||
| 318 | void IrTransceiver_Init(void) |
366 | void IrTransceiver_Init(void) |
| 319 | { |
367 | { |
| - | 368 | for (uint8_t i = 0; i < 3; i++) |
|
| - | 369 | { |
|
| - | 370 | drvIrRxChannel[i].storeEnable = FALSE; |
|
| - | 371 | drvIrRxChannel[i].timeoutEnable = FALSE; |
|
| - | 372 | drvIrRxChannel[i].rxlen = 0; |
|
| - | 373 | } |
|
| - | 374 | ||
| 320 | IR_TIMER_INIT(); |
375 | IR_TIMER_INIT(); |
| 321 | 376 | ||
| 322 | #if IR_TX_ENABLE==1 |
377 | #if IR_TX_ENABLE==1 |
| 323 | /* Set up transmitter */ |
378 | /* Set up transmitter */ |
| 324 | IR_T_DDR |= (1<<IR_T_BIT); |
379 | IR_T_DDR |= (1<<IR_T_BIT); |