Subversion Repositories HomeAutomation

Rev

Rev 727 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * IR receiver and transmitter driver.
  3.  *
  4.  * @date    2006-12-10
  5.  *
  6.  * @author  Anders Runeson, Andreas Fritiofson
  7.  *  
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13. #include <config.h>
  14. #include <drivers/ir/transceiver/irtransceiver.h>
  15. #include <drivers/ir/protocols.h>
  16. #include <avr/io.h>
  17. #include <avr/interrupt.h>
  18.  
  19. /*-----------------------------------------------------------------------------
  20.  * Globals
  21.  *---------------------------------------------------------------------------*/
  22. uint16_t *rxbuf, *txbuf;
  23. uint8_t rxlen, txlen;
  24.  
  25. static uint8_t bufIndex;                            //selects the pulse width in buffer to send
  26. volatile uint8_t data_received;
  27. volatile uint8_t data_transmitted;
  28. uint8_t detect_edge;
  29. uint8_t store;
  30.  
  31. /*-----------------------------------------------------------------------------
  32.  * Prerequisites
  33.  *---------------------------------------------------------------------------*/
  34. #define IR_RX_ACTIVE_LOW    1
  35. #define IR_TX_ACTIVE_LOW    0       //Only 0 is implemented
  36.  
  37.  
  38. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  39. #define TIMSK1  TIMSK
  40. #define TIFR1   TIFR
  41. #define ICIE1   TICIE1
  42. #endif
  43.  
  44. #define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
  45. #define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
  46. #define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
  47. #define IR_TIMEOUT_REG          OCR1A
  48. #define IR_COMPARE_REG          OCR1B
  49. #define IR_CAPTURE_REG          ICR1
  50. #define IR_COUNT_REG            TCNT1
  51. #define IR_MODULATION_REG       OCR0A
  52. #define IR_TIMER_INIT()         TCCR1A = 0; \
  53.                                 TCCR1B = (1<<ICNC1)|(2<<CS10);
  54. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  55. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  56. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  57. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  58. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  59. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  60. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  61.                                 TIFR1 = (1<<ICF1);
  62. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  63.                                 TIFR1 = (1<<ICF1);
  64.  
  65. //TODO: if active low is 0 then make port 5V at "LOW"
  66. #if IR_TX_ACTIVE_LOW==1
  67. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  68. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  69. #else
  70. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  71. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  72. #endif
  73.  
  74.  
  75. /*-----------------------------------------------------------------------------
  76.  * Interrupt Handlers
  77.  *---------------------------------------------------------------------------*/
  78.  
  79. ISR(IR_COMPARE_VECTOR)
  80. {
  81.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  82.         IR_OUTP_LOW();
  83.     } else {
  84.         IR_OUTP_HIGH();
  85.     }
  86.    
  87.     //The following three lines is just to allow a start signal to be zero.
  88. /*  bufIndex++;
  89.     while (txbuf[bufIndex] == 0){
  90.         bufIndex++;
  91.     }*/
  92.    
  93.     if (bufIndex < txlen)
  94.     {      
  95.         IR_COMPARE_REG += txbuf[bufIndex++];       
  96.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  97.     }
  98.     else
  99.     {
  100.         IR_MASK_COMPARE();
  101.         data_transmitted = 1;
  102.     }
  103. }
  104.  
  105. ISR(IR_TIMEOUT_VECTOR)
  106. {
  107.     if (rxlen)
  108.     {
  109.         /* Disable interrupts until the application has taken action on the
  110.          * current data and reenabled reception. */
  111.         IR_MASK_CAPTURE();
  112.         IR_MASK_TIMEOUT();
  113.         /* Notify the application that a pulse train has been received. */
  114.         data_received = 1;
  115.     }
  116.     store = 0;
  117. }
  118.  
  119. ISR(IR_CAPTURE_VECTOR)
  120. {
  121.     static uint16_t prev_time;
  122.     uint16_t pulsewidth;
  123.  
  124.     /* Read the measured transition time from the capture register. */
  125.     uint16_t time = IR_CAPTURE_REG;
  126.    
  127.     /* Toggle the edge detection. */
  128.     if (detect_edge == 0)
  129.     {
  130.         IR_CAPTURE_RISING();
  131.         detect_edge = 1;
  132.     }
  133.     else
  134.     {
  135.         IR_CAPTURE_FALLING();
  136.         detect_edge = 0;
  137.     }
  138.    
  139.     /* Subtract the current measurement from the previous to get the pulse
  140.      * width. */
  141.     pulsewidth = time - prev_time;
  142.     prev_time = time;
  143.    
  144.     /* Set the timeout. */
  145.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  146.    
  147.     if (store)
  148.     {
  149.         /* Store the measurement. */
  150.         rxbuf[rxlen++] = pulsewidth;
  151.         //*(rxbuf+rxlen++) = pulsewidth;
  152.         /* Disable future measurements if we've filled the buffer. */
  153.         //TODO: Report overflow to application
  154.         if (rxlen == MAX_NR_TIMES)
  155.         {
  156.             IR_MASK_CAPTURE();
  157.         }
  158.     }
  159.     else
  160.     {
  161.         /* The first edge of the pulse train has been detected. Enable the
  162.          * storage of the following pulsewidths. */
  163.         store = 1;
  164.         /* Enable timeout interrupt for detection of the end of the pulse
  165.          * train. */
  166.         IR_UNMASK_TIMEOUT();
  167.     }
  168. }
  169.  
  170.  
  171.  
  172. /*-----------------------------------------------------------------------------
  173.  * Public Functions
  174.  *---------------------------------------------------------------------------*/
  175.  
  176. void IrTransceiver_Init(void)
  177. {
  178.     /* Set up receiver */
  179.     IR_TIMER_INIT();
  180.     IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  181.     IR_R_DDR &= ~(1<<IR_R_BIT);
  182.     //DDRC |= (1<<PC5);
  183.    
  184.     /* Set up transmitter */
  185.     IR_T_DDR |= (1<<IR_T_BIT);
  186.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
  187.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  188.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  189.     #endif
  190.  
  191. }
  192.  
  193. void IrTransceiver_Receive_Start(uint16_t *buffer)
  194. {
  195.      /* Setup buffer and arm the edge detection. */
  196.     rxbuf = buffer;
  197.     rxlen = 0;
  198.     data_received = 0;
  199.     store = 0;
  200. #if (IR_RX_ACTIVE_LOW == 1)
  201.     IR_CAPTURE_FALLING();
  202.     detect_edge = 0;
  203. #else
  204.     IR_CAPTURE_RISING();
  205.     detect_edge = 1;
  206. #endif
  207.     IR_UNMASK_CAPTURE();
  208. }
  209.  
  210. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  211. {
  212.     *len = rxlen;
  213.     if (data_received)
  214.     {
  215.         return IR_OK;
  216.     }
  217.     else if (rxlen > 0)
  218.     {
  219.         return IR_NOT_FINISHED;
  220.     } else {
  221.         return IR_NO_DATA;
  222.     }
  223. }
  224.  
  225. uint8_t IrTransceiver_Transmit_Poll(void) {
  226.     if (data_transmitted == 0) {
  227.         return IR_NOT_FINISHED;
  228.     } else {
  229.         return IR_OK;
  230.     }
  231. }
  232.  
  233. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  234. {
  235.     data_transmitted = 0;
  236.    
  237.     if (length == 0) return IR_NO_DATA;
  238.  
  239.     txbuf = buffer;
  240.     txlen = length;
  241.     bufIndex = 1;
  242.    
  243.     IR_MODULATION_REG = modfreq;
  244.    
  245.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  246.    
  247.     IR_OUTP_HIGH();
  248.    
  249.     IR_UNMASK_COMPARE();
  250.    
  251.     //while (!data_transmitted);
  252.    
  253.     return IR_OK;
  254. }
  255.