Subversion Repositories HomeAutomation

Rev

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