Subversion Repositories HomeAutomation

Rev

Rev 1972 | 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. #if IR_RX_ENABLE==1
  23. uint16_t *rxbuf;
  24. uint8_t rxlen;
  25. #endif
  26. #if IR_TX_ENABLE==1
  27. uint16_t *txbuf;
  28. uint8_t txlen;
  29. #endif
  30.  
  31. #if IR_TX_ENABLE==1
  32. static uint8_t bufIndex;                            //selects the pulse width in buffer to send
  33. #endif
  34. volatile uint8_t data_received;
  35. volatile uint8_t data_transmitted;
  36. uint8_t detect_edge;
  37. uint8_t store;
  38.  
  39. /*-----------------------------------------------------------------------------
  40.  * Prerequisites
  41.  *---------------------------------------------------------------------------*/
  42. #ifndef IR_RX_ACTIVE_LOW
  43. #define IR_RX_ACTIVE_LOW    1
  44. #endif
  45.  
  46. #ifndef IR_TX_ACTIVE_LOW
  47. #define IR_TX_ACTIVE_LOW    0
  48. #endif
  49.  
  50. #ifndef IR_TX_ENABLE
  51. #define IR_TX_ENABLE    0
  52. #endif
  53.  
  54. #ifndef IR_RX_ENABLE
  55. #define IR_RX_ENABLE    0
  56. #endif
  57.  
  58. #ifndef IR_TX_HACK
  59. #define IR_TX_HACK 0
  60. #endif
  61.  
  62.  
  63. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  64. #define TIMSK1  TIMSK
  65. #define TIFR1   TIFR
  66. #define ICIE1   TICIE1
  67. #endif
  68.  
  69. #define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
  70. #define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
  71. #define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
  72. #define IR_TIMEOUT_REG          OCR1A
  73. #define IR_COMPARE_REG          OCR1B
  74. #define IR_CAPTURE_REG          ICR1
  75. #define IR_COUNT_REG            TCNT1
  76. #define IR_MODULATION_REG       OCR0A
  77. #define IR_TIMER_INIT()         TCCR1A = 0; \
  78.                                 TCCR1B = (1<<ICNC1)|(2<<CS10);
  79. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  80. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  81. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  82. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  83. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  84. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  85. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  86.                                 TIFR1 = (1<<ICF1);
  87. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  88.                                 TIFR1 = (1<<ICF1);
  89.  
  90. #if IR_TX_HACK==0
  91. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  92. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  93. #endif
  94.  
  95. #if IR_TX_HACK==1
  96. #define IR_T_PORT_HACK          PORTD
  97. #define IR_T_PIN_HACK           PIND
  98. #define IR_T_DDR_HACK           DDRD
  99. #define IR_T_BIT_HACK           PD5
  100.  
  101. #define IR_OUTP_HIGH()          IR_T_PORT_HACK &= ~(1<<IR_T_BIT_HACK);
  102. #define IR_OUTP_LOW()           IR_T_PORT_HACK |= (1<<IR_T_BIT_HACK);
  103. #endif
  104.  
  105.  
  106.  
  107. /*-----------------------------------------------------------------------------
  108.  * Interrupt Handlers
  109.  *---------------------------------------------------------------------------*/
  110.  
  111. #if IR_TX_ENABLE==1
  112. ISR(IR_COMPARE_VECTOR)
  113. {
  114.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  115.         IR_OUTP_LOW();
  116.     } else {
  117.         IR_OUTP_HIGH();
  118.     }
  119.    
  120.     //The following three lines is just to allow a start signal to be zero.
  121. /*  bufIndex++;
  122.     while (txbuf[bufIndex] == 0){
  123.         bufIndex++;
  124.     }*/
  125.    
  126.     if (bufIndex < txlen)
  127.     {      
  128.         IR_COMPARE_REG += txbuf[bufIndex++];       
  129.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  130.     }
  131.     else
  132.     {
  133.         IR_MASK_COMPARE();
  134.         data_transmitted = 1;
  135.     }
  136. }
  137. #endif
  138.  
  139. #if IR_RX_ENABLE==1
  140. ISR(IR_TIMEOUT_VECTOR)
  141. {
  142.     if (rxlen)
  143.     {
  144.         /* Disable interrupts until the application has taken action on the
  145.          * current data and reenabled reception. */
  146.         IR_MASK_CAPTURE();
  147.         IR_MASK_TIMEOUT();
  148.         /* Notify the application that a pulse train has been received. */
  149.         data_received = 1;
  150.     }
  151.     store = 0;
  152. }
  153. #endif
  154.  
  155. #if IR_RX_ENABLE==1
  156. ISR(IR_CAPTURE_VECTOR)
  157. {
  158.     static uint16_t prev_time;
  159.     uint16_t pulsewidth;
  160.  
  161.     /* Read the measured transition time from the capture register. */
  162.     uint16_t time = IR_CAPTURE_REG;
  163.    
  164.     /* Toggle the edge detection. */
  165.     if (detect_edge == 0)
  166.     {
  167.         IR_CAPTURE_RISING();
  168.         detect_edge = 1;
  169.     }
  170.     else
  171.     {
  172.         IR_CAPTURE_FALLING();
  173.         detect_edge = 0;
  174.     }
  175.    
  176.     /* Subtract the current measurement from the previous to get the pulse
  177.      * width. */
  178.     pulsewidth = time - prev_time;
  179.     prev_time = time;
  180.    
  181.     /* Set the timeout. */
  182.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  183.    
  184.     if (store)
  185.     {
  186.         /* Store the measurement. */
  187.         rxbuf[rxlen++] = pulsewidth;
  188.         //*(rxbuf+rxlen++) = pulsewidth;
  189.         /* Disable future measurements if we've filled the buffer. */
  190.         //TODO: Report overflow to application
  191.         if (rxlen == MAX_NR_TIMES)
  192.         {
  193.             IR_MASK_CAPTURE();
  194.         }
  195.     }
  196.     else
  197.     {
  198.         /* The first edge of the pulse train has been detected. Enable the
  199.          * storage of the following pulsewidths. */
  200.         store = 1;
  201.         /* Enable timeout interrupt for detection of the end of the pulse
  202.          * train. */
  203.         IR_UNMASK_TIMEOUT();
  204.     }
  205. }
  206. #endif
  207.  
  208.  
  209. /*-----------------------------------------------------------------------------
  210.  * Public Functions
  211.  *---------------------------------------------------------------------------*/
  212.  
  213. void IrTransceiver_Init(void)
  214. {
  215.     IR_TIMER_INIT();
  216. #if IR_RX_ENABLE==1
  217.     /* Set up receiver */
  218.     IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  219.     IR_R_DDR &= ~(1<<IR_R_BIT);
  220.     //DDRC |= (1<<PC5);
  221. #endif
  222.    
  223. #if IR_TX_ENABLE==1
  224.     /* Set up transmitter */
  225.     IR_T_DDR |= (1<<IR_T_BIT);
  226.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  227.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  228.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  229.     #endif
  230.    
  231. #if IR_TX_HACK==0
  232. #if IR_TX_ACTIVE_LOW==1
  233.     /* when pwm is disconnected from port (during low) the port should output 5V */
  234.     IR_T_PORT |= (1<<IR_T_BIT);
  235. #else
  236.     /* when pwm is disconnected from port (during low) the port should output 0V */
  237.     IR_T_PORT &= ~(1<<IR_T_BIT);
  238. #endif
  239. #endif
  240.  
  241. #if IR_TX_HACK==1
  242.     /* Set up transmitter */
  243.     IR_T_DDR_HACK |= (1<<IR_T_BIT_HACK);
  244.    
  245.     /* when pwm is disconnected from port (during low) the port should output 5V */
  246.     IR_T_PORT_HACK |= (1<<IR_T_BIT_HACK);
  247.    
  248.     IR_MODULATION_REG = (((F_CPU/2000)/38) -1);
  249.    
  250.     /* start pwm generator */
  251.     TCCR0A |= (1<<COM0A0);
  252. #endif
  253.  
  254. #endif
  255. }
  256.  
  257. void IrTransceiver_Receive_Start(uint16_t *buffer)
  258. {
  259. #if IR_RX_ENABLE==1
  260.      /* Setup buffer and arm the edge detection. */
  261.     rxbuf = buffer;
  262.     rxlen = 0;
  263.     data_received = 0;
  264.     store = 0;
  265. #if (IR_RX_ACTIVE_LOW == 1)
  266.     IR_CAPTURE_FALLING();
  267.     detect_edge = 0;
  268. #else
  269.     IR_CAPTURE_RISING();
  270.     detect_edge = 1;
  271. #endif
  272.     IR_UNMASK_CAPTURE();
  273. #endif
  274. }
  275.  
  276. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  277. {
  278. #if IR_RX_ENABLE==1
  279.     *len = rxlen;
  280.     if (data_received)
  281.     {
  282.         return IR_OK;
  283.     }
  284.     else if (rxlen > 0)
  285.     {
  286.         return IR_NOT_FINISHED;
  287.     } else {
  288.         return IR_NO_DATA;
  289.     }
  290. #else
  291.     return 0;
  292. #endif
  293. }
  294.  
  295. uint8_t IrTransceiver_Transmit_Poll(void) {
  296. #if IR_TX_ENABLE==1
  297.     if (data_transmitted == 0) {
  298.         return IR_NOT_FINISHED;
  299.     } else {
  300.         return IR_OK;
  301.     }
  302. #else
  303.     return 0;
  304. #endif
  305. }
  306.  
  307. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  308. {
  309. #if IR_TX_ENABLE==1
  310.     data_transmitted = 0;
  311.    
  312.     if (length == 0) return IR_NO_DATA;
  313.  
  314.     txbuf = buffer;
  315.     txlen = length;
  316.     bufIndex = 1;
  317.    
  318.     IR_MODULATION_REG = (((F_CPU/2000)/modfreq) -1);
  319.    
  320.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  321.    
  322.     IR_OUTP_HIGH();
  323.    
  324.     IR_UNMASK_COMPARE();
  325.    
  326.     //while (!data_transmitted);
  327.    
  328.     return IR_OK;
  329. #else
  330.     return 0;
  331. #endif
  332. }
  333.