Subversion Repositories HomeAutomation

Rev

Rev 601 | Rev 613 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * IR receiver driver.
  3.  *
  4.  * @date    2006-12-10
  5.  *
  6.  * @author  Anders Runeson
  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. //static uint16_t times[MAX_NR_TIMES];          //stores
  23. uint16_t *rxbuf, *txbuf;
  24. uint8_t rxlen, txlen;
  25.  
  26. //static uint8_t timesCounter=0;                    //counts the items in Times, always less then MAX_NR_TIMES
  27. static uint8_t bufIndex;                            //selects the pulse width in buffer to send
  28. volatile uint8_t data_received;
  29. volatile uint8_t data_transmitted;
  30. uint8_t detect_edge;
  31. uint8_t store;
  32.  
  33. /*-----------------------------------------------------------------------------
  34.  * Prerequisites
  35.  *---------------------------------------------------------------------------*/
  36. #define IR_RX_ACTIVE_LOW    1
  37. #define IR_TX_ACTIVE_LOW    0       //Only 0 is implemented
  38.  
  39.  
  40. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  41. #define TIMSK1  TIMSK
  42. #define TIFR1   TIFR
  43. #define ICIE1   TICIE1
  44. #endif
  45.  
  46. #define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
  47. #define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
  48. #define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
  49. #define IR_TIMEOUT_REG          OCR1A
  50. #define IR_COMPARE_REG          OCR1B
  51. #define IR_CAPTURE_REG          ICR1
  52. #define IR_COUNT_REG            TCNT1
  53. #define IR_MODULATION_REG       OCR0A
  54. #define IR_TIMER_INIT()         TCCR1A = 0; \
  55.                                 TCCR1B = (1<<ICNC1)|(2<<CS10);
  56. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  57. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  58. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  59. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  60. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  61. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  62. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  63.                                 TIFR1 = (1<<ICF1);
  64. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  65.                                 TIFR1 = (1<<ICF1);
  66.  
  67. //TODO: if active low is 0 then make port 5V at LOW
  68. #if IR_TX_ACTIVE_LOW==1
  69. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  70. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  71. #else
  72. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  73. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  74. #endif
  75.  
  76.  
  77. /*-----------------------------------------------------------------------------
  78.  * Interrupt Handlers
  79.  *---------------------------------------------------------------------------*/
  80.  
  81. ISR(IR_COMPARE_VECTOR)
  82. {
  83.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  84.         IR_OUTP_LOW();
  85.     } else {
  86.         IR_OUTP_HIGH();
  87.     }
  88.    
  89.     if (bufIndex < txlen)
  90.     {
  91.         IR_COMPARE_REG += txbuf[bufIndex++];       
  92.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  93.     }
  94.     else
  95.     {
  96.         IR_MASK_COMPARE();
  97.         data_transmitted = 1;
  98.     }
  99. }
  100.  
  101. ISR(IR_TIMEOUT_VECTOR)
  102. {
  103.     if (rxlen)
  104.     {
  105.         /* Disable interrupts until the application has taken action on the
  106.          * current data and reenabled reception. */
  107.         IR_MASK_CAPTURE();
  108.         IR_MASK_TIMEOUT();
  109.         /* Notify the application that a pulse train has been received. */
  110.         data_received = 1;
  111.     }
  112.     store = 0;
  113. }
  114.  
  115. ISR(IR_CAPTURE_VECTOR)
  116. {
  117.     static uint16_t prev_time;
  118.     uint16_t pulsewidth;
  119.  
  120.     /* Read the measured transition time from the capture register. */
  121.     uint16_t time = IR_CAPTURE_REG;
  122.    
  123.     /* Toggle the edge detection. */
  124.     if (detect_edge == 0)
  125.     {
  126.         IR_CAPTURE_RISING();
  127.         detect_edge = 1;
  128.     }
  129.     else
  130.     {
  131.         IR_CAPTURE_FALLING();
  132.         detect_edge = 0;
  133.     }
  134.    
  135.     /* Subtract the current measurement from the previous to get the pulse
  136.      * width. */
  137.     pulsewidth = time - prev_time;
  138.     prev_time = time;
  139.    
  140.     /* Set the timeout. */
  141.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  142.    
  143.     if (store)
  144.     {
  145.         /* Store the measurement. */
  146.         rxbuf[rxlen++] = pulsewidth;
  147.         //*(rxbuf+rxlen++) = pulsewidth;
  148.         /* Disable future measurements if we've filled the buffer. */
  149.         //TODO: Report overflow to application
  150.         if (rxlen == MAX_NR_TIMES)
  151.         {
  152.             IR_MASK_CAPTURE();
  153.         }
  154.     }
  155.     else
  156.     {
  157.         /* The first edge of the pulse train has been detected. Enable the
  158.          * storage of the following pulsewidths. */
  159.         store = 1;
  160.         /* Enable timeout interrupt for detection of the end of the pulse
  161.          * train. */
  162.         IR_UNMASK_TIMEOUT();
  163.     }
  164. }
  165.  
  166.  
  167.  
  168. /*-----------------------------------------------------------------------------
  169.  * Public Functions
  170.  *---------------------------------------------------------------------------*/
  171.  
  172. void IrTransceiver_Init(void)
  173. {
  174.     /* Set up receiver */
  175.     IR_TIMER_INIT();
  176.     IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  177.     IR_R_DDR &= ~(1<<IR_R_BIT);
  178.     //DDRC |= (1<<PC5);
  179.    
  180.     /* Set up transmitter */
  181.     IR_T_DDR |= (1<<IR_T_BIT);
  182.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
  183.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  184.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  185.     #endif
  186.  
  187. }
  188.  
  189. void IrTransceiver_Start(uint16_t *buffer)
  190. {
  191.      /* Setup buffer and arm the edge detection. */
  192.     rxbuf = buffer;
  193.     rxlen = 0;
  194.     data_received = 0;
  195.     store = 0;
  196. #if (IR_RX_ACTIVE_LOW == 1)
  197.     IR_CAPTURE_FALLING();
  198.     detect_edge = 0;
  199. #else
  200.     IR_CAPTURE_RISING();
  201.     detect_edge = 1;
  202. #endif
  203.     IR_UNMASK_CAPTURE();
  204. }
  205.  
  206. uint8_t IrTransceiver_Poll(void)
  207. {
  208.     if (data_received)
  209.     {
  210.         return rxlen;
  211.         /**buffer = times;
  212.         *length = timesCounter;
  213.         return IR_OK;*/
  214.     }
  215.     else
  216.     {
  217.         return 0;
  218.     }
  219. }
  220.  
  221. uint8_t IrTransceiver_Transmit_Poll(void) {
  222.     if (data_transmitted == 0) {
  223.         return IR_NOT_FINISHED;
  224.     } else {
  225.         return IR_OK;
  226.     }
  227. }
  228.  
  229. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  230. {
  231.     data_transmitted = 0;
  232.    
  233.     if (length == 0) return IR_NO_DATA;
  234.  
  235.     txbuf = buffer;
  236.     txlen = length;
  237.     bufIndex = 1;
  238.    
  239.     IR_MODULATION_REG = modfreq;
  240.    
  241.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  242.    
  243.     IR_OUTP_HIGH();
  244.    
  245.     IR_UNMASK_COMPARE();
  246.    
  247.     //while (!data_transmitted);
  248.    
  249.     return IR_OK;
  250. }
  251.  
  252. #if 0
  253. //varför är denna funktion så komplex? jo den filtrerar bort korta ir-pulser
  254. //TODO: skriv doxygen-header som för de andra funktionerna
  255. uint8_t IrReceive_CheckIdle(void) {
  256.     if (IR_R_PIN & (1<<IR_R_BIT)) return IR_NO_DATA;        //om irmodulen ger en etta så återgå
  257.    
  258.     //nu lägger irmodulen ut en nolla, "startbiten" alltså
  259.    
  260.     uint16_t timerVal;
  261.    
  262.     //Läs in längden på startbiten
  263.     initTimer();
  264.     while (!(IR_R_PIN & (1<<IR_R_BIT))) {       //vänta på att irmodulen lägger ut en etta
  265.         //om timeout (om timer-ovflow-flaggan sätt)
  266.         if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  267.     }
  268.     timerVal = getTimerVal();
  269.    
  270.     if ((timerVal < IR_MAX_PULSE_WIDTH) && (timerVal > IR_MIN_PULSE_WIDTH)) {
  271.         return IR_OK;
  272.     } //else if ...
  273.    
  274.    
  275.     return IR_NO_PROTOCOL;
  276. }
  277. #endif
  278.