Subversion Repositories HomeAutomation

Rev

Rev 1467 | Rev 1470 | 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/irtransceiverMulti.h>
  15. #include <drivers/ir/protocols.h>
  16. #include <avr/io.h>
  17. #include <avr/interrupt.h>
  18. #include <drivers/mcu/pcint.h>
  19.  
  20. /*-----------------------------------------------------------------------------
  21.  * Globals
  22.  *---------------------------------------------------------------------------*/
  23. #if IR_RX_ENABLE==1
  24. uint16_t *rxbuf;
  25. uint8_t rxlen;
  26.  
  27. /*struct {
  28.     uint8_t     dataReceived;
  29.     uint16_t    timeout;
  30.     uint8_t     timeoutEnable;
  31.     uint16_t    *rxbuf;
  32.     uint8_t     rxlen;
  33.     uint8_t     storeEnable;
  34. } irRxChannel[3];
  35. */
  36.  
  37. #endif
  38. #if IR_TX_ENABLE==1
  39. uint16_t *txbuf;
  40. uint8_t txlen;
  41. #endif
  42.  
  43. #if IR_TX_ENABLE==1
  44. static uint8_t bufIndex;                            //selects the pulse width in buffer to send
  45. #endif
  46. volatile uint8_t data_received;
  47. volatile uint8_t data_transmitted;
  48. //uint8_t detect_edge;
  49. uint8_t store;
  50.  
  51.  
  52. /*-----------------------------------------------------------------------------
  53.  * Prerequisites
  54.  *---------------------------------------------------------------------------*/
  55. #ifndef IR_RX_ACTIVE_LOW
  56. #define IR_RX_ACTIVE_LOW    1
  57. #endif
  58.  
  59. #ifndef IR_TX_ACTIVE_LOW
  60. #define IR_TX_ACTIVE_LOW    0
  61. #endif
  62.  
  63. #ifndef IR_TX_ENABLE
  64. #define IR_TX_ENABLE    0
  65. #endif
  66.  
  67. #ifndef IR_RX_ENABLE
  68. #define IR_RX_ENABLE    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.                                 */
  89. #define IR_TIMER_INIT()         TCCR1A = 0; \
  90.                                 TCCR1B = (2<<CS10);
  91. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  92. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  93. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  94. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  95. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  96. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  97. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  98.                                 TIFR1 = (1<<ICF1);
  99. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  100.                                 TIFR1 = (1<<ICF1);
  101.  
  102. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  103. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  104.  
  105.  
  106. /*-----------------------------------------------------------------------------
  107.  * Interrupt Handlers
  108.  *---------------------------------------------------------------------------*/
  109.  
  110.  
  111. /*
  112. timer 1 has two comprare registers and compare ISRs, one is used below for "timeout" on receive and the other is used here for transmitter
  113. //TODO: how to handle more than one transmitter on one compare interrupt, spara en array med tider och nån enableflagga för varje kanal
  114. */
  115.  
  116. #if IR_TX_ENABLE==1
  117. ISR(IR_COMPARE_VECTOR)
  118. {
  119.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  120.         IR_OUTP_LOW();
  121.     } else {
  122.         IR_OUTP_HIGH();
  123.     }
  124.    
  125.     //The following three lines is just to allow a start signal to be zero.
  126. /*  bufIndex++;
  127.     while (txbuf[bufIndex] == 0){
  128.         bufIndex++;
  129.     }*/
  130.    
  131.     if (bufIndex < txlen)
  132.     {      
  133.         IR_COMPARE_REG += txbuf[bufIndex++];       
  134.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  135.     }
  136.     else
  137.     {
  138.         IR_MASK_COMPARE();
  139.         data_transmitted = 1;
  140.     }
  141. }
  142. #endif
  143.  
  144. #if IR_RX_ENABLE==1
  145. //TODO: hur hantera detta i multi receiver
  146. //TODO: ha en array med tider och nån enableflagga för varje kanal
  147. //TODO: mot slutet av ISRen laddas nästa tid in...
  148. ISR(IR_TIMEOUT_VECTOR)
  149. {
  150.     if (rxlen)
  151.     {
  152.         /* Disable interrupts until the application has taken action on the
  153.          * current data and reenabled reception. */
  154. //      IR_MASK_CAPTURE();
  155. //      IR_MASK_TIMEOUT();
  156.         PCMSK0 &= ~(1<<IR_TRANS_CH0_MASK);
  157.  
  158.         /* Notify the application that a pulse train has been received. */
  159.         data_received = 1;
  160.     }
  161.     store = 0;
  162. }
  163. #endif
  164.  
  165. #if 0
  166.  
  167. //ISR(IR_CAPTURE_VECTOR)
  168. //TODO: skriv denna för multi receiver
  169. ISR(PCINT0_vect) {
  170. //  uint8_t p;
  171.     uint8_t rPinB=PINB;
  172.     uint8_t rPinC=PINC;
  173.     uint8_t rPinD=PIND;
  174.    
  175.     /* check if channel 0 pin was changed */
  176.     if ((rPinB ^ gPinB)&(1<<IR_TRANS_CH0_MASK))
  177.     {
  178.         IrTransceiver_Store(0);
  179.     }
  180.    
  181.     gPinB=rPinB;
  182.     gPinC=rPinC;
  183.     gPinD=rPinD;
  184. } /* ISR(PCINT0_vect) */
  185. #endif
  186.  
  187.  
  188. /*-----------------------------------------------------------------------------
  189.  * Private Functions
  190.  *---------------------------------------------------------------------------*/
  191.  
  192. #if IR_RX_ENABLE==1
  193. void IrTransceiver_Store_ch0(uint8_t id, uint8_t status)
  194. {
  195.     IrTransceiver_Store(0);
  196. }
  197. void IrTransceiver_Store_ch1(uint8_t id, uint8_t status)
  198. {
  199.     IrTransceiver_Store(1);
  200. }
  201. void IrTransceiver_Store_ch2(uint8_t id, uint8_t status)
  202. {
  203.     IrTransceiver_Store(2);
  204. }
  205.  
  206. void IrTransceiver_Store(uint8_t channel)
  207. {
  208.     static uint16_t prev_time;
  209.     uint16_t pulsewidth;
  210.  
  211.     /* Read the measured transition time from the capture register. */
  212.     //uint16_t time = IR_CAPTURE_REG;
  213.     /* Read the timer counter register to get the current "time". */
  214.     uint16_t time = IR_COUNT_REG;
  215.        
  216.     /* Subtract the current measurement from the previous to get the pulse
  217.      * width. */
  218.     pulsewidth = time - prev_time;
  219.     prev_time = time;
  220.    
  221.     /* Set the timeout. */
  222.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  223.    
  224.     if (store)
  225.     {
  226.         /* Store the measurement. */
  227.         rxbuf[rxlen++] = pulsewidth;
  228.         //*(rxbuf+rxlen++) = pulsewidth;
  229.         /* Disable future measurements if we've filled the buffer. */
  230.         //TODO: What to do in multi recevier?
  231.         //TODO: Report overflow to application
  232.         if (rxlen == MAX_NR_TIMES)
  233.         {
  234.             //IR_MASK_CAPTURE();
  235.         }
  236.     }
  237.     else
  238.     {
  239.         /* The first edge of the pulse train has been detected. Enable the
  240.          * storage of the following pulsewidths. */
  241.         store = 1;
  242.         /* Enable timeout interrupt for detection of the end of the pulse
  243.          * train. */
  244.         IR_UNMASK_TIMEOUT();
  245.  
  246.         //TODO: if buffer resource coordinator is implemented this is where a buffer should be assinged to this channel
  247.     }
  248. }
  249. #endif
  250.  
  251.  
  252. /*-----------------------------------------------------------------------------
  253.  * Public Functions
  254.  *---------------------------------------------------------------------------*/
  255.  
  256. /* call this function like this:
  257.     IrTransceiver_Init_TX_Channel(0, buffer, callback, pcint-id, GPIO_D6);
  258.     buffer is a memory location
  259.     callback is a function to call when a receive/transmitt is complete
  260.     also call with IO port to use
  261.    
  262.     function to deactivate channel may later be needed
  263. */
  264.  
  265. 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)
  266. {
  267.     if (channel == 0)
  268.     {
  269.         Pcint_SetCallback(uint8_t pcint_id, uint8_t pcint, &IrTransceiver_Store_ch0);
  270.     }
  271.     else if (channel == 1)
  272.     {
  273.         Pcint_SetCallback(uint8_t pcint_id, uint8_t pcint, &IrTransceiver_Store_ch1);
  274.     }
  275.     else if (channel == 2)
  276.     {
  277.         Pcint_SetCallback(uint8_t pcint_id, uint8_t pcint, &IrTransceiver_Store_ch2);
  278.     }
  279. }
  280.  
  281. /*
  282. 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)
  283. {
  284.    
  285. }
  286. */
  287.  
  288. void IrTransceiver_Init(void)
  289. {
  290.     IR_TIMER_INIT();
  291.    
  292. #if IR_RX_ENABLE==1
  293.     /* Set up receiver */
  294.     //IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  295.     IR_R_DDR &= ~(1<<IR_R_BIT);
  296.     //DDRC |= (1<<PC5);
  297. #endif
  298.    
  299. #if IR_TX_ENABLE==1
  300.     /* Set up transmitter */
  301.     IR_T_DDR |= (1<<IR_T_BIT);
  302.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  303.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  304.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  305.     #endif
  306.    
  307. #if IR_TX_ACTIVE_LOW==1
  308.     /* when pwm is disconnected from port (during low) the port should output 5V */
  309.     IR_T_PORT |= (1<<IR_T_BIT);
  310. #else
  311.     /* when pwm is disconnected from port (during low) the port should output 0V */
  312.     IR_T_PORT &= ~(1<<IR_T_BIT);
  313. #endif
  314.  
  315. #endif
  316.  
  317. }
  318.  
  319. void IrTransceiver_Receive_Start(uint16_t *buffer)
  320. {
  321. #if IR_RX_ENABLE==1
  322.      /* Setup buffer and arm the edge detection. */
  323.     rxbuf = buffer;
  324.     rxlen = 0;
  325.     data_received = 0;
  326.     store = 0;
  327. #if (IR_RX_ACTIVE_LOW == 1)
  328.     //IR_CAPTURE_FALLING();
  329.     //detect_edge = 0;
  330. #else
  331.     //IR_CAPTURE_RISING();
  332.     //detect_edge = 1;
  333. #endif
  334.     //IR_UNMASK_CAPTURE();
  335.  
  336.     gPinB=PINB;
  337.     gPinC=PINC;
  338.     gPinD=PIND;
  339.     PCIFR=(1<<PCIF0|1<<PCIF1|1<<PCIF2); /* clear any pending interrupt before enabling interrupts */
  340. //  PCICR|=(1<<PCIE0|1<<PCIE1|1<<PCIE2);    /* enable interrupt for PCINT0-2 */
  341.     PCICR|=(1<<PCIE0);  /* enable interrupt for PCINT0 */
  342.     PCMSK0 |= (1<<IR_TRANS_CH0_MASK);
  343. //  PCMSK1 |= (1<<pcints[pcint_id].pcintBit%8);
  344. //  PCMSK2 |= (1<<pcints[pcint_id].pcintBit%8);
  345. #endif
  346.  
  347. }
  348.  
  349. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  350. {
  351. #if IR_RX_ENABLE==1
  352.     *len = rxlen;
  353.     if (data_received)
  354.     {
  355.         return IR_OK;
  356.     }
  357.     else if (rxlen > 0)
  358.     {
  359.         return IR_NOT_FINISHED;
  360.     } else {
  361.         return IR_NO_DATA;
  362.     }
  363. #else
  364.     return 0;
  365. #endif
  366. }
  367.  
  368. uint8_t IrTransceiver_Transmit_Poll(void) {
  369. #if IR_TX_ENABLE==1
  370.     if (data_transmitted == 0) {
  371.         return IR_NOT_FINISHED;
  372.     } else {
  373.         return IR_OK;
  374.     }
  375. #else
  376.     return 0;
  377. #endif
  378. }
  379.  
  380. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  381. {
  382. #if IR_TX_ENABLE==1
  383.     data_transmitted = 0;
  384.    
  385.     if (length == 0) return IR_NO_DATA;
  386.  
  387.     txbuf = buffer;
  388.     txlen = length;
  389.     bufIndex = 1;
  390.    
  391.     IR_MODULATION_REG = modfreq;
  392.    
  393.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  394.    
  395.     IR_OUTP_HIGH();
  396.    
  397.     IR_UNMASK_COMPARE();
  398.    
  399.     //while (!data_transmitted);
  400.    
  401.     return IR_OK;
  402. #else
  403.     return 0;
  404. #endif
  405. }
  406.