Subversion Repositories HomeAutomation

Rev

Rev 547 | 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 <avr/io.h>
  16. #include <avr/interrupt.h>
  17.  
  18. /*-----------------------------------------------------------------------------
  19.  * Globals
  20.  *---------------------------------------------------------------------------*/
  21. static uint16_t times[MAX_NR_TIMES];            //stores
  22. static uint8_t timesCounter=0;                  //counts the items in Times, always less then MAX_NR_TIMES
  23. volatile uint8_t data_received;
  24. uint8_t detect_edge;
  25. uint8_t store;
  26.  
  27. /*-----------------------------------------------------------------------------
  28.  * Prerequisites
  29.  *---------------------------------------------------------------------------*/
  30. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  31. #define TIMSK1  TIMSK
  32. #define TIFR1   TIFR
  33. #define ICIE1   TICIE1
  34. #endif
  35.  
  36. #define IR_COMP_VECTOR  TIMER1_COMPB_vect
  37. #define IR_OVF_VECTOR   TIMER1_COMPA_vect
  38. #define IR_CAPT_VECTOR  TIMER1_CAPT_vect
  39. #define IR_TIMEOUT_REG  OCR1A
  40. #define IR_PW_REG       OCR1B
  41. #define IR_CAPT_REG     ICR1
  42. #define IR_TIMER_INIT() TCCR1A = 0; \
  43.                         TCCR1B = (1<<ICNC1)|(1<<WGM12)|(2<<CS10);
  44. #define IR_MASK_COMP()  TIMSK1 &= ~(1<<OCIE1B);
  45. #define IR_UNMASK_COMP()    TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  46. #define IR_MASK_OVF()   TIMSK1 &= ~(1<<OCIE1A);
  47. #define IR_UNMASK_OVF() TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  48. #define IR_MASK_CAPT()  TIMSK1 &= ~(1<<ICIE1);
  49. #define IR_UNMASK_CAPT()    TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  50. #define IR_CAPT_FALLING()   TCCR1B &= ~(1<<ICES1); \
  51.                             TIFR1 = (1<<ICF1);
  52. #define IR_CAPT_RISING()    TCCR1B |= (1<<ICES1); \
  53.                             TIFR1 = (1<<ICF1);
  54.  
  55. #define IR_RX_ACTIVE_LOW    1
  56. #define IR_TX_ACTIVE_LOW    1
  57.  
  58. /*-----------------------------------------------------------------------------
  59.  * Interrupt Handlers
  60.  *---------------------------------------------------------------------------*/
  61.  
  62. ISR(IR_COMP_VECTOR)
  63. {
  64.    
  65. }
  66.  
  67. ISR(IR_OVF_VECTOR)
  68. {
  69.     if (timesCounter)
  70.     {
  71.         /* Disable interrupts until the application has taken action on the
  72.          * current data and reenabled reception. */
  73.         IR_MASK_CAPT();
  74.         IR_MASK_OVF();
  75.         /* Notify the application that a pulse train has been received. */
  76.         data_received = 1;
  77.     }
  78.     store = 0;
  79. }
  80.  
  81. ISR(IR_CAPT_VECTOR)
  82. {
  83.     /* Read the measured pulse time from the capture register. */
  84.     uint16_t pulsewidth = IR_CAPT_REG;
  85.    
  86.     /* Subtract the current measurement from the counter instead of setting it
  87.      * to zero so that the following measurement is not affected by variations
  88.      * in the interrupt response time. */
  89.     TCNT1 -= pulsewidth;
  90.     //TCNT1 = 0;
  91.    
  92.     /* Toggle the edge detection. */
  93.     if (detect_edge == 0)
  94.     {
  95.         IR_CAPT_RISING();
  96.         detect_edge = 1;
  97.         PORTC &= ~(1<<PC5);
  98.     }
  99.     else
  100.     {
  101.         IR_CAPT_FALLING();
  102.         detect_edge = 0;
  103.         PORTC |= (1<<PC5);
  104.     }
  105.    
  106.     if (store)
  107.     {
  108.         /* Store the measurement. */
  109.         times[timesCounter++] = pulsewidth;
  110.         /* Disable future measurements if we've filled the buffer. */
  111.         //TODO: Report overflow to application
  112.         if (timesCounter == MAX_NR_TIMES)
  113.         {
  114.             IR_MASK_CAPT();
  115.         }
  116.     }
  117.     else
  118.     {
  119.         /* The first edge of the pulse train has been detected. Enable the
  120.          * storage of the following pulsewidths. */
  121.         store = 1;
  122.         /* Enable timeout interrupt for detection of the end of the pulse
  123.          * train. */
  124.         IR_UNMASK_OVF();
  125.     }
  126. }
  127.  
  128.  
  129. /*-----------------------------------------------------------------------------
  130.  * Public Functions
  131.  *---------------------------------------------------------------------------*/
  132.  
  133. void IrTransceiver_Init(void)
  134. {
  135.     IR_TIMER_INIT();
  136.     IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  137.     IRDDR &= ~(1<<IRBIT);
  138. }
  139.  
  140. void IrTransceiver_Start(void)
  141. {
  142.     /* Clear buffer and arm the edge detection. */
  143.     timesCounter = 0;
  144.     data_received = 0;
  145.     store = 0;
  146. #if (IR_RX_ACTIVE_LOW == 1)
  147.     IR_CAPT_FALLING();
  148.     detect_edge = 0;
  149. #else
  150.     IR_CAPT_RISING();
  151.     detect_edge = 1;
  152. #endif
  153.     IR_UNMASK_CAPT();
  154. }
  155.  
  156. uint8_t IrTransceiver_Poll(uint16_t **buffer, uint8_t *length)
  157. {
  158.     if (data_received)
  159.     {
  160.         *buffer = times;
  161.         *length = timesCounter;
  162.         return IR_OK;
  163.     }
  164.     else
  165.     {
  166.         return IR_NO_DATA;
  167.     }
  168. }
  169.  
  170. /**
  171.  * Get an ir-time from the stored array, this can be used
  172.  * when a proper protocol is not found.
  173.  *
  174.  * @param index
  175.  *      Which time to get
  176.  * @return
  177.  *      The 16bit value at index index
  178.  */
  179. uint16_t getRawData(uint8_t index) {
  180.     return times[index];
  181. }
  182.  
  183. /**
  184.  * Get the number of stored ir-times in the array
  185.  *
  186.  * @return
  187.  *      The number of stored ir-times in the array
  188.  */
  189. uint8_t getRawDataCnt(void) {
  190.     return timesCounter;
  191. }
  192.  
  193. #if 1
  194.  
  195. /**
  196.  * Test data on SIRC protocol, 12-bit version
  197.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  198.  *
  199.  * @param address
  200.  *      Pointer to store the address of the received data
  201.  * @param command
  202.  *      Pointer to store the command of the received data
  203.  * @return
  204.  *      IR_OK if data parsed successfully, one of several errormessages if not
  205.  */
  206. uint8_t testSIRC(uint8_t *address, uint8_t *command) {
  207.     /* parse times[], max is timesCounter */
  208.  
  209.     /* check if we have correct amount of data */
  210.     if (timesCounter != 25) {
  211.         return IR_NOT_CORRECT_DATA;
  212.     }
  213.    
  214.     /* check startbit */
  215.     if (times[0] > IR_SIRC_ST_BIT + IR_SIRC_ST_BIT/IR_SIRC_TOL_DIV || times[0] < IR_SIRC_ST_BIT - IR_SIRC_ST_BIT/IR_SIRC_TOL_DIV) {
  216.         return IR_NOT_CORRECT_DATA;
  217.     }
  218.    
  219.     uint16_t rawbits=0;
  220.    
  221.     for (uint8_t i = 1; i < timesCounter; i++) {
  222.         if ((i&1) == 1) {       /* if odd, ir-pause */
  223.             /* check length of pause between bits */
  224.             if (times[i] > IR_SIRC_LOW + IR_SIRC_LOW/IR_SIRC_TOL_DIV || times[i] < IR_SIRC_LOW - IR_SIRC_LOW/IR_SIRC_TOL_DIV) {
  225.                 return IR_NOT_CORRECT_DATA;
  226.             }
  227.         } else {            /* if even, ir-bit */
  228.             if (times[i] > IR_SIRC_HIGH_ONE - IR_SIRC_HIGH_ONE/IR_SIRC_TOL_DIV && times[i] < IR_SIRC_HIGH_ONE + IR_SIRC_HIGH_ONE/IR_SIRC_TOL_DIV) {
  229.                 /* write a one */
  230.                 rawbits |= 1<<((i-2)>>1);
  231.             } else if (times[i] > IR_SIRC_HIGH_ZERO - IR_SIRC_HIGH_ZERO/IR_SIRC_TOL_DIV && times[i] < IR_SIRC_HIGH_ZERO + IR_SIRC_HIGH_ZERO/IR_SIRC_TOL_DIV) {
  232.                 /* do nothing, a zero is already in rawbits */
  233.             } else {
  234.                 return IR_NOT_CORRECT_DATA;
  235.             }
  236.         }
  237.     }
  238.    
  239.     *command = ((uint8_t)rawbits&0x7f);
  240.     *address = ((uint8_t)(rawbits>>7)&0x1f);
  241.    
  242.     return IR_OK;
  243. }
  244.  
  245. /**
  246.  * Test data on RC5 protocol
  247.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  248.  *
  249.  * @param address
  250.  *      Pointer to store the address of the received data
  251.  * @param command
  252.  *      Pointer to store the command of the received data
  253.  * @return
  254.  *      IR_OK if data parsed successfully, one of several errormessages if not
  255.  */
  256. uint8_t testRC5(uint8_t *address, uint8_t *command) {
  257.     uint8_t halfbitscnt = 1;
  258.     uint16_t rawbits = 0;
  259.    
  260.     for (uint8_t i = 0; i<timesCounter; i++) {
  261.         //halfbitscnt&1==1 in the middle of bits
  262.         //i&1==0 positive flank
  263.  
  264.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  265.             rawbits |= (1<<(13-(halfbitscnt>>1)));
  266.         }
  267.        
  268.         if (times[i] > IR_RC5_HALF_BIT - IR_RC5_HALF_BIT/IR_RC5_TOL_DIV && times[i] < IR_RC5_HALF_BIT + IR_RC5_HALF_BIT/IR_RC5_TOL_DIV) {
  269.             halfbitscnt += 1;
  270.         } else if (times[i] > IR_RC5_BIT - IR_RC5_BIT/IR_RC5_TOL_DIV && times[i] < IR_RC5_BIT + IR_RC5_BIT/IR_RC5_TOL_DIV) {
  271.             halfbitscnt += 2;
  272.         } else {
  273.             return IR_NOT_CORRECT_DATA;
  274.         }
  275.        
  276.     }
  277.  
  278.     *command = ((uint8_t)rawbits&0x3f);
  279.     *address = ((uint8_t)(rawbits>>6)&0x7f);   
  280.  
  281.     //support RC5-extended by putting the inversion of startbit 2 as the 7th commandbit
  282.     *command |= (~(*address) & 0x40);
  283.     *address &= 0x1f;       //remove togglebit and both startbits from address
  284.    
  285.     return IR_OK;
  286. }
  287.  
  288. /**
  289.  * Test data on SHARP protocol
  290.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  291.  *
  292.  * @param address
  293.  *      Pointer to store the address of the received data
  294.  * @param command
  295.  *      Pointer to store the command of the received data
  296.  * @return
  297.  *      IR_OK if data parsed successfully, one of several errormessages if not
  298.  */
  299. uint8_t testSharp(uint8_t *address, uint8_t *command) {
  300.     /* parse times[], max is timesCounter */
  301.  
  302.     /* check if we have correct amount of data */
  303.     if (timesCounter != 31) {
  304.         return IR_NOT_CORRECT_DATA;
  305.     }
  306.    
  307.     uint16_t rawbits=0;
  308.    
  309.     for (uint8_t i = 1; i < timesCounter; i++) {
  310.         if ((i&1) == 1) {       /* if odd, ir-pause */
  311.             /* check length of pause between bits */
  312.             if (times[i] > IR_SHARP_LOW_ONE - IR_SHARP_LOW_ONE/IR_SHARP_TOL_DIV && times[i] < IR_SHARP_LOW_ONE + IR_SHARP_LOW_ONE/IR_SHARP_TOL_DIV) {
  313.                 /* write a one */
  314.                 rawbits |= 1<<((i-1)>>1);
  315.             } else if (times[i] > IR_SHARP_LOW_ZERO - IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV && times[i] < IR_SHARP_LOW_ZERO + IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV) {
  316.                 /* do nothing, a zero is already in rawbits */
  317.             } else {
  318.                 return IR_NOT_CORRECT_DATA;
  319.             }
  320.         } else {            /* if even, ir-bit */
  321.             if (times[i] > IR_SHARP_HIGH + IR_SHARP_HIGH/IR_SHARP_TOL_DIV || times[i] < IR_SHARP_HIGH - IR_SHARP_HIGH/IR_SHARP_TOL_DIV) {
  322.                 return IR_NOT_CORRECT_DATA;
  323.             }
  324.         }
  325.     }
  326.    
  327.     *command = ((uint8_t)(rawbits>>5)&0xff);
  328.     *address = ((uint8_t)rawbits&0x1f);
  329.    
  330.     return IR_OK;
  331. }
  332.  
  333. /**
  334.  * Test data on NEC protocol
  335.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  336.  *
  337.  * @param address
  338.  *      Pointer to store the address of the received data
  339.  * @param command
  340.  *      Pointer to store the command of the received data
  341.  * @return
  342.  *      IR_OK if data parsed successfully, one of several errormessages if not
  343.  */
  344. uint8_t testNEC(uint8_t *address, uint8_t *command) {
  345.     /* parse times[], max is timesCounter */
  346.  
  347.     /* check if we have correct amount of data */
  348.     if (timesCounter != 67) {
  349.         return IR_NOT_CORRECT_DATA;
  350.     }
  351.    
  352.     /* check startbit */
  353.     if (times[0] > IR_NEC_ST_BIT + IR_NEC_ST_BIT/IR_NEC_TOL_DIV || times[0] < IR_NEC_ST_BIT - IR_NEC_ST_BIT/IR_NEC_TOL_DIV) {
  354.         return IR_NOT_CORRECT_DATA;
  355.     }
  356.  
  357.     /* check pause after startbit */
  358.     if (times[1] > IR_NEC_ST_PAUSE + IR_NEC_ST_PAUSE/IR_NEC_TOL_DIV || times[1] < IR_NEC_ST_PAUSE - IR_NEC_ST_PAUSE/IR_NEC_TOL_DIV) {
  359.         return IR_NOT_CORRECT_DATA;
  360.     }
  361.  
  362.     *command = 0;
  363.     *address = 0;
  364.    
  365.     for (uint8_t i = 3; i < timesCounter; i++) {
  366.         if ((i&1) == 1) {       /* if odd, ir-pause */
  367.             /* check length of pause between bits */
  368.             if (times[i] > IR_NEC_LOW_ONE - IR_NEC_LOW_ONE/IR_NEC_TOL_DIV && times[i] < IR_NEC_LOW_ONE + IR_NEC_LOW_ONE/IR_NEC_TOL_DIV) {
  369.                 if (i>2 && i<18) {
  370.                     /* write a one */
  371.                     *address |= 1<<((i-3)>>1);
  372.                 }
  373.                 if (i>34 && i<50) {
  374.                     /* write a one */
  375.                     *command |= 1<<((i-35)>>1);
  376.                 }
  377.             } else if (times[i] > IR_NEC_LOW_ZERO - IR_NEC_LOW_ZERO/IR_NEC_TOL_DIV && times[i] < IR_NEC_LOW_ZERO + IR_NEC_LOW_ZERO/IR_NEC_TOL_DIV) {
  378.                 /* do nothing, a zero is already in rawbits */
  379.             } else {
  380.                 return IR_NOT_CORRECT_DATA;
  381.             }
  382.         } else {            /* if even, ir-bit */
  383.             if (times[i] > IR_NEC_HIGH + IR_NEC_HIGH/IR_NEC_TOL_DIV || times[i] < IR_NEC_HIGH - IR_NEC_HIGH/IR_NEC_TOL_DIV) {
  384.                 return IR_NOT_CORRECT_DATA;
  385.             }
  386.         }
  387.     }
  388.    
  389.     return IR_OK;
  390. }
  391.  
  392.  
  393. /**
  394.  * Test data on Samsung protocol
  395.  * Very much like NEC, different start bit/pause lengths etc.
  396.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  397.  *
  398.  * @param address
  399.  *      Pointer to store the address of the received data
  400.  * @param command
  401.  *      Pointer to store the command of the received data
  402.  * @return
  403.  *      IR_OK if data parsed successfully, one of several errormessages if not
  404.  */
  405. uint8_t testSamsung(uint8_t *address, uint8_t *command) {
  406.     /* parse times[], max is timesCounter */
  407.  
  408.     /* check if we have correct amount of data */
  409.     if (timesCounter != 67) {
  410.         return IR_NOT_CORRECT_DATA;
  411.     }
  412.    
  413.     /* check startbit */
  414.     if (times[0] > IR_SAMS_ST_BIT + IR_SAMS_ST_BIT/IR_SAMS_TOL_DIV || times[0] < IR_SAMS_ST_BIT - IR_SAMS_ST_BIT/IR_SAMS_TOL_DIV) {
  415.         return IR_NOT_CORRECT_DATA;
  416.     }
  417.  
  418.     /* check pause after startbit */
  419.     if (times[1] > IR_SAMS_ST_PAUSE + IR_SAMS_ST_PAUSE/IR_SAMS_TOL_DIV || times[1] < IR_SAMS_ST_PAUSE - IR_SAMS_ST_PAUSE/IR_SAMS_TOL_DIV) {
  420.         return IR_NOT_CORRECT_DATA;
  421.     }
  422.  
  423.     *command = 0;
  424.     *address = 0;
  425.    
  426.     for (uint8_t i = 3; i < timesCounter; i++) {
  427.         if ((i&1) == 1) {       /* if odd, ir-pause */
  428.             /* check length of pause between bits */
  429.             if (times[i] > IR_SAMS_LOW_ONE - IR_SAMS_LOW_ONE/IR_SAMS_TOL_DIV && times[i] < IR_SAMS_LOW_ONE + IR_SAMS_LOW_ONE/IR_SAMS_TOL_DIV) {
  430.                 if (i>2 && i<18) {
  431.                     /* write a one */
  432.                     *address |= 1<<((i-3)>>1);
  433.                 }
  434.                 if (i>34 && i<50) {
  435.                     /* write a one */
  436.                     *command |= 1<<((i-35)>>1);
  437.                 }
  438.             } else if (times[i] > IR_SAMS_LOW_ZERO - IR_SAMS_LOW_ZERO/IR_SAMS_TOL_DIV && times[i] < IR_SAMS_LOW_ZERO + IR_SAMS_LOW_ZERO/IR_SAMS_TOL_DIV) {
  439.                 /* do nothing, a zero is already in rawbits */
  440.             } else {
  441.                 return IR_NOT_CORRECT_DATA;
  442.             }
  443.         } else {            /* if even, ir-bit */
  444.             if (times[i] > IR_SAMS_HIGH + IR_SAMS_HIGH/IR_SAMS_TOL_DIV || times[i] < IR_SAMS_HIGH - IR_SAMS_HIGH/IR_SAMS_TOL_DIV) {
  445.                 return IR_NOT_CORRECT_DATA;
  446.             }
  447.         }
  448.     }
  449.    
  450.     return IR_OK;
  451. }
  452.  
  453. uint8_t IrReceive_CheckIR(uint8_t *proto, uint8_t *address, uint8_t *command, uint16_t *timeout) {
  454.     IrTransceiver_Start();
  455.    
  456.     while (!data_received);
  457.    
  458.    
  459. #if 0
  460.     if (IRPIN & (1<<IRBIT)) return IR_NO_DATA;      //om irmodulen ger en etta så återgå
  461.    
  462.     initTimer();
  463.    
  464.     //this routine should sample the timings for received irdata
  465.     timesCounter = 0;
  466.    
  467.     uint8_t gotTimout = 0;  // a timeout is a very long break in irdata (such as occurs between ir pulsetrains)
  468.     while (!gotTimout && timesCounter < MAX_NR_TIMES-1) { //loop as long as no timeout occured and not to many pulses received
  469.         setTimerVal(TIM_OVFL_RELOAD_VAL);
  470.         //wait for positiv slope, while checking timer overflow
  471.         while (!(IRPIN & (1<<IRBIT))) {
  472.             //if timeout (if timer-ovflow-flaggan is set)
  473.             if (isTimerOvfl() == 1) return IR_TIME_OVFL;    //this timeout is not good (irsignal low which means active)
  474.         }
  475.        
  476.         times[timesCounter] = getTimerVal()-TIM_OVFL_RELOAD_VAL;
  477.         //TODO: should we check times[timesCounter] so its a realistic time-value? use IR_MIN_PULSE_WIDTH
  478.         timesCounter++;
  479.        
  480.         setTimerVal(TIM_OVFL_RELOAD_VAL);
  481.         //wait for negative slope, while checking timer overflow
  482.         while ((IRPIN & (1<<IRBIT)) && !gotTimout) {
  483.             //om timeout (om timer-ovflow-flaggan sätt)
  484.             if (isTimerOvfl() == 1) gotTimout=1;    //return IR_TIME_OVFL;
  485.         }
  486.  
  487.         if (!gotTimout) {
  488.             times[timesCounter] = getTimerVal()-TIM_OVFL_RELOAD_VAL;
  489.             //TODO: should we check times[timesCounter] so its a realistic time-value?
  490.             timesCounter++;
  491.         }
  492.     }
  493.     if (timesCounter >= MAX_NR_TIMES-1) {
  494.         //to much irdata, not good, abort
  495.         return IR_TO_MUCH_DATA;
  496.     }
  497. #endif
  498.    
  499.     if (testSIRC(&*address, &*command) == IR_OK) {
  500.         *proto = IR_PROTO_SIRC;
  501.         *timeout = IR_SIRC_REPETITION;
  502.         return IR_OK;
  503.     } else if (testRC5(&*address, &*command) == IR_OK) {
  504.         *proto = IR_PROTO_RC5;
  505.         *timeout = IR_RC5_REPETITION;
  506.         return IR_OK;
  507.     } else if (testSharp(&*address, &*command) == IR_OK) {
  508.         *proto = IR_PROTO_SHARP;
  509.         *timeout = IR_SHARP_REPETITION;
  510.         return IR_OK;
  511.     } else if (testNEC(&*address, &*command) == IR_OK) {
  512.         *proto = IR_PROTO_NEC;
  513.         *timeout = IR_NEC_REPETITION;
  514.         return IR_OK;
  515.     } else if (testSamsung(&*address, &*command) == IR_OK) {
  516.         *proto = IR_PROTO_SAMS;
  517.         *timeout = IR_SAMS_REPETITION;
  518.         return IR_OK;
  519.     }
  520.        
  521.     return IR_NO_PROTOCOL;
  522.    
  523. }
  524. #endif
  525.  
  526. //TODO: skriv doxygen-header som för de andra funktionerna
  527. /**
  528.  *
  529.  *
  530.  *
  531.  *
  532.  */
  533. void IrReceive_Init(void) {
  534.     IrTransceiver_Init();
  535.     /*IRDDR &= ~(1<<IRBIT);*/
  536. }
  537.  
  538. //varför är denna funktion så komplex? jo den filtrerar bort korta ir-pulser
  539. //TODO: skriv doxygen-header som för de andra funktionerna
  540. uint8_t IrReceive_CheckIdle(void) {
  541.     if (IRPIN & (1<<IRBIT)) return IR_NO_DATA;      //om irmodulen ger en etta så återgå
  542.    
  543.     //nu lägger irmodulen ut en nolla, "startbiten" alltså
  544.    
  545.     uint16_t timerVal;
  546.    
  547.     //Läs in längden på startbiten
  548.     initTimer();
  549.     while (!(IRPIN & (1<<IRBIT))) {     //vänta på att irmodulen lägger ut en etta
  550.         //om timeout (om timer-ovflow-flaggan sätt)
  551.         if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  552.     }
  553.     timerVal = getTimerVal();
  554.    
  555.     if ((timerVal < IR_MAX_PULSE_WIDTH) && (timerVal > IR_MIN_PULSE_WIDTH)) {
  556.         return IR_OK;
  557.     } //else if ...
  558.    
  559.    
  560.     return IR_NO_PROTOCOL;
  561. }
  562.