Subversion Repositories HomeAutomation

Rev

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

  1. /**
  2.  * IR receiver and transmitter protocols.
  3.  *
  4.  * @date    2006-12-10
  5.  *
  6.  * @author  Anders Runeson, Andreas Fritiofson, Martin Nordin
  7.  *  
  8.  */
  9.  
  10. #include "protocols.h"
  11. #include <bios.h>
  12.  
  13.  
  14.  
  15. //#include <drivers/mcu/gpio.h>
  16.  
  17.  
  18.  
  19. int8_t parseProtocol(const uint16_t *buf, uint8_t len, uint8_t index, Ir_Protocol_Data_t *proto) {
  20.     proto->protocol=IR_PROTO_UNKNOWN;
  21.     proto->data=0;
  22.     proto->timeout=1;
  23.     /* Try all protocols in order. */
  24. #if (IR_PROTOCOLS_USE_SIRC)
  25.     if (parseSIRC(buf, len, proto)==IR_OK) return IR_OK;
  26. #endif
  27. #if (IR_PROTOCOLS_USE_RC5)
  28.     if (parseRC5(buf, len, proto)==IR_OK) return IR_OK;
  29. #endif
  30. #if (IR_PROTOCOLS_USE_SHARP)
  31.     if (parseSharp(buf, len, proto)==IR_OK) return IR_OK;
  32. #endif
  33. #if (IR_PROTOCOLS_USE_NEC)
  34.     if (parseNEC(buf, len, proto)==IR_OK) return IR_OK;
  35. #endif
  36. #if (IR_PROTOCOLS_USE_SAMSUNG)
  37.     if (parseSamsung(buf, len, proto)==IR_OK) return IR_OK;
  38. #endif
  39. #if (IR_PROTOCOLS_USE_MARANTZ)
  40.     if (parseMarantz(buf, len, proto)==IR_OK) return IR_OK;
  41. #endif
  42. #if (IR_PROTOCOLS_USE_PANASONIC)
  43.     if (parsePanasonic(buf, len, proto)==IR_OK) return IR_OK;
  44. #endif
  45. #if (IR_PROTOCOLS_USE_SKY)
  46.     if (parseSky(buf, len, proto)==IR_OK) return IR_OK;
  47. #endif
  48.  
  49.  
  50. /* RF protocols needs index parameter */
  51. #if (IR_PROTOCOLS_USE_NEXA2)
  52.     if (parseNexa2(buf, len, index, proto)==IR_OK) return IR_OK;
  53. #endif
  54. #if (IR_PROTOCOLS_USE_NEXA1)
  55.     if (parseNexa1(buf, len, index, proto)==IR_OK) return IR_OK;
  56. #endif
  57. #if (IR_PROTOCOLS_USE_VIKING)
  58.     if (parseViking(buf, len, index, proto)==IR_OK) return IR_OK;
  59. #endif
  60.     /* No protocol matched. */
  61.     proto->protocol = IR_PROTO_UNKNOWN;
  62.     return IR_NOT_CORRECT_DATA;
  63. }
  64.  
  65. int8_t parseHash(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  66.     //TODO: Transform the buffer in some clever way to a 32 bit word. */
  67.     proto->protocol = IR_PROTO_HASH;
  68.     proto->timeout = 200;
  69.     proto->data = 0;
  70.    
  71.     return 0;
  72. }
  73.  
  74. int8_t expandProtocol(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  75.     /* Call the expand function for the specified protocol. */
  76.     switch (proto->protocol) {
  77.     case IR_PROTO_SIRC:
  78.         return expandSIRC(buf, len, proto);
  79.     case IR_PROTO_RC5:
  80.         return expandRC5(buf, len, proto);
  81.     case IR_PROTO_SHARP:
  82.         return expandSharp(buf, len, proto);
  83.     case IR_PROTO_NEC:
  84.         return expandNEC(buf, len, proto);
  85.     case IR_PROTO_SAMS:
  86.         return expandSamsung(buf, len, proto);
  87.     case IR_PROTO_MARANTZ:
  88.         return expandMarantz(buf, len, proto);
  89.     case IR_PROTO_PANASONIC:
  90.         return expandPanasonic(buf, len, proto);
  91.     case IR_PROTO_SKY:
  92.         return expandSky(buf, len, proto);
  93.     case IR_PROTO_NEXA2:
  94.         return expandNexa2(buf, len, proto);
  95.     case IR_PROTO_NEXA1:
  96.         return expandNexa1(buf, len, proto);
  97.     }
  98.     /* Invalid protocol specified. */
  99.     return IR_NOT_CORRECT_DATA;
  100. }
  101.  
  102. #if (IR_PROTOCOLS_USE_SIRC)
  103. /**
  104.  * Test data on SIRC protocol, 12-bit version
  105.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  106.  * http://picprojects.org.uk/projects/sirc/sonysirc.pdf
  107.  *
  108.  * @param buf
  109.  *      Pointer to buffer to where to data to parse is stored
  110.  * @param len
  111.  *      Length of the data
  112.  * @param proto
  113.  *      Pointer to protocol information
  114.  * @return
  115.  *      IR_OK if data parsed successfully, one of several errormessages if not
  116.  */
  117. int8_t parseSIRC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  118.     /* parse buf[], max is len */
  119.  
  120.     /* check if we have correct amount of data.
  121.            supporting two versions of SIRC:
  122.            12 bit = 25, 15 bit = 31
  123.            there is also a 20 bit protocol, but we don't support it
  124.          */
  125.     if (len != 25 && len != 31) {
  126.         return IR_NOT_CORRECT_DATA;
  127.     }
  128.    
  129.     /* check startbit */
  130.     if (buf[0] > IR_SIRC_ST_BIT + IR_SIRC_ST_BIT/IR_SIRC_TOL_DIV || buf[0] < IR_SIRC_ST_BIT - IR_SIRC_ST_BIT/IR_SIRC_TOL_DIV) {
  131.         return IR_NOT_CORRECT_DATA;
  132.     }
  133.    
  134.     uint16_t rawbits=0;
  135.    
  136.     for (uint8_t i = 1; i < len; i++) {
  137.         if ((i&1) == 1) {       /* if odd, ir-pause */
  138.             /* check length of pause between bits */
  139.             if (buf[i] > IR_SIRC_LOW + IR_SIRC_LOW/IR_SIRC_TOL_DIV || buf[i] < IR_SIRC_LOW - IR_SIRC_LOW/IR_SIRC_TOL_DIV) {
  140.                 return IR_NOT_CORRECT_DATA;
  141.             }
  142.         } else {            /* if even, ir-bit */
  143.             if (buf[i] > IR_SIRC_HIGH_ONE - IR_SIRC_HIGH_ONE/IR_SIRC_TOL_DIV && buf[i] < IR_SIRC_HIGH_ONE + IR_SIRC_HIGH_ONE/IR_SIRC_TOL_DIV) {
  144.                 /* write a one */
  145.                 rawbits |= 1<<((i-2)>>1);
  146.             } else if (buf[i] > IR_SIRC_HIGH_ZERO - IR_SIRC_HIGH_ZERO/IR_SIRC_TOL_DIV && buf[i] < IR_SIRC_HIGH_ZERO + IR_SIRC_HIGH_ZERO/IR_SIRC_TOL_DIV) {
  147.                 /* do nothing, a zero is already in rawbits */
  148.             } else {
  149.                 return IR_NOT_CORRECT_DATA;
  150.             }
  151.         }
  152.     }
  153.    
  154.     proto->protocol = IR_PROTO_SIRC;
  155.     proto->timeout = IR_SIRC_TIMEOUT;
  156.     proto->data = rawbits;
  157.    
  158.     return IR_OK;
  159. }
  160. #endif
  161.  
  162. /**
  163.  * Expand data from SIRC protocol
  164.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  165.  *
  166.  * @param buf
  167.  *      Pointer to buffer to store the expanded data
  168.  * @param len
  169.  *      Pointer to length of the data
  170.  * @param proto
  171.  *      Pointer to protocol information
  172.  * @return
  173.  *      IR_OK if data expanded successfully, one of several errormessages if not
  174.  */
  175. int8_t expandSIRC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  176.     buf[0] = IR_SIRC_ST_BIT;
  177.     buf[1] = IR_SIRC_LOW; //start pulse finished
  178.  
  179.         /* Assume 12 bit protocol */
  180.         *len = 25;
  181.         /* If data to big, use 15 bit protocol */
  182.         if (proto->data > (1<<11)) { // cannot be represented by 12 bits
  183.           *len = 31;
  184.         }
  185.         for (uint8_t i = 0; i < *len-2; i++) {
  186.           if ((i&1) == 1) {     /* if odd, ir-pause */
  187.             buf[i+2] = IR_SIRC_LOW;
  188.           } else {          /* if even, ir-bit */
  189.             if ((proto->data>>(i>>1))&1) {
  190.               buf[i+2] = IR_SIRC_HIGH_ONE;
  191.             } else {
  192.               buf[i+2] = IR_SIRC_HIGH_ZERO;
  193.             }
  194.           }
  195.         }  
  196.  
  197.     proto->modfreq=IR_SIRC_F_MOD;
  198.     proto->timeout=IR_SIRC_TIMEOUT;
  199.     proto->repeats=IR_SIRC_REPS;
  200.        
  201.     return IR_OK;
  202. }
  203.  
  204.  
  205. #if (IR_PROTOCOLS_USE_RC5)
  206. /**
  207.  * Test data on RC5 protocol
  208.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  209.  *
  210.  * @param buf
  211.  *      Pointer to buffer to where to data to parse is stored
  212.  * @param len
  213.  *      Length of the data
  214.  * @param proto
  215.  *      Pointer to protocol information
  216.  * @return
  217.  *      IR_OK if data parsed successfully, one of several errormessages if not
  218.  */
  219. int8_t parseRC5(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  220.     uint8_t halfbitscnt = 1;
  221.     uint16_t rawbits = 0;
  222.    
  223.     for (uint8_t i = 0; i<len; i++) {
  224.         //halfbitscnt&1==1 in the middle of bits
  225.         //i&1==0 positive flank
  226.  
  227.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  228.             rawbits |= (1<<(13-(halfbitscnt>>1)));
  229.         }
  230.        
  231.         if (buf[i] > IR_RC5_HALF_BIT - IR_RC5_HALF_BIT/IR_RC5_TOL_DIV && buf[i] < IR_RC5_HALF_BIT + IR_RC5_HALF_BIT/IR_RC5_TOL_DIV) {
  232.             halfbitscnt += 1;
  233.         } else if (buf[i] > IR_RC5_BIT - IR_RC5_BIT/IR_RC5_TOL_DIV && buf[i] < IR_RC5_BIT + IR_RC5_BIT/IR_RC5_TOL_DIV) {
  234.             halfbitscnt += 2;
  235.         } else {
  236.             return IR_NOT_CORRECT_DATA;
  237.         }
  238.        
  239.     }
  240.  
  241.     proto->protocol=IR_PROTO_RC5;
  242.     proto->timeout=IR_RC5_TIMEOUT;
  243.     //support RC5-extended keeping second startbit
  244.     //remove togglebit
  245.     proto->data = rawbits&0x37ff; //This seems to be wrong? Does not invert second start bit and keeps first start bit
  246.     //proto->data = (rawbits&0x07ff) | ((~rawbits)&0x0100);
  247.  
  248.    
  249.     return IR_OK;
  250. }
  251. #endif
  252.  
  253. /**
  254.  * Used by the expandRC5 to ensure that we toggle the signal with each button press.
  255.  */
  256. int8_t rc5_toggle=0;
  257.  
  258. /**
  259.  * Expand data from RC5 protocol
  260.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  261.  *
  262.  * One is defined as low then high
  263.  * Zero is defined as high then low
  264.  *
  265.  * @param buf
  266.  *      Pointer to buffer to store the expanded data
  267.  * @param len
  268.  *      Pointer to length of the data
  269.  * @param proto
  270.  *      Pointer to protocol information
  271.  * @return
  272.  *      IR_OK if data expanded successfully, one of several errormessages if not
  273.  */
  274. int8_t expandRC5(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  275.  
  276.     //This is the raw message that we should create the IR times for
  277.     //Lets copy the data locally to ensure that no interups will modify the vector.
  278.     uint16_t rawMessage=proto->data & 0x3fff;
  279.    
  280.     uint8_t previousBit;
  281.     /* Set up startbit */
  282.     //Bit = 0
  283.     //We start with a low signal since the diode
  284.     //isn't active before we send anything,
  285.     buf[0] = IR_RC5_HALF_BIT;//first start bit
  286.    
  287.     // Bit = 1
  288.     buf[1] = IR_RC5_HALF_BIT;
  289.     buf[2] = IR_RC5_HALF_BIT;//second start bit
  290.  
  291.     if (rc5_toggle==0){
  292.         buf[3] = IR_RC5_HALF_BIT;
  293.         buf[4] = IR_RC5_HALF_BIT; //toggle bit (yes i know it should not be hardcoded)
  294.         *len = 5;
  295.         previousBit = 1; //Same as last startbit
  296.     } else {
  297.         //We are reusing the signal from the previous signal
  298.         //and extend the time into this bit.
  299.         buf[2] = IR_RC5_BIT;
  300.         buf[3] = IR_RC5_HALF_BIT;
  301.         *len = 4;
  302.         previousBit = 0; //Toggled from last startbit
  303.     }
  304.     //Invert the toggle for next time
  305.     rc5_toggle=!rc5_toggle & 1;
  306.    
  307.     //Decode the message
  308.     //We know that RC5 messages are 14 bits long
  309.     for(uint8_t pos=11;pos>0;pos--)
  310.     {      
  311.         // Check the current bit
  312.         if(previousBit == ((rawMessage>>(pos-1)) & 1))
  313.         {
  314.             buf[*len]=IR_RC5_HALF_BIT;
  315.             buf[*len+1]=IR_RC5_HALF_BIT;
  316.             *len=*len+2;
  317.         }
  318.         else
  319.         {
  320.             //We are having the same signal as we ended the last bit with,
  321.             //Expand the time that that signal is active to cover
  322.             //half of this bit aswell
  323.             buf[*len-1]=IR_RC5_BIT;
  324.             buf[*len]=IR_RC5_HALF_BIT;
  325.             *len=*len+1;
  326.            
  327.             //Invert the previous bit
  328.             previousBit = (!previousBit) & 1;
  329.         }
  330.     }
  331.     //We have to handle the last bit specially since we have to
  332.     //end with low signal on the IR diod
  333.     if(previousBit == 0)
  334.     {
  335.         //We have to remove the last time since that would bring us to a high signal again.
  336.         *len=*len-1;
  337.         buf[*len]=0;
  338.     }
  339.    
  340.     proto->modfreq=IR_RC5_F_MOD;
  341.     proto->timeout=IR_RC5_TIMEOUT;
  342.     proto->repeats=IR_RC5_REPS;
  343.     return IR_OK;
  344. }
  345.  
  346.  
  347. #if (IR_PROTOCOLS_USE_SHARP)
  348. /**
  349.  * Test data on SHARP protocol
  350.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  351.  *
  352.  * @param buf
  353.  *      Pointer to buffer to where to data to parse is stored
  354.  * @param len
  355.  *      Length of the data
  356.  * @param proto
  357.  *      Pointer to protocol information
  358.  * @return
  359.  *      IR_OK if data parsed successfully, one of several errormessages if not
  360.  */
  361. int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  362.     /* parse buf[], max is len */
  363.  
  364.     /* check if we have correct amount of data */
  365.     if (len != 31) {
  366.         return IR_NOT_CORRECT_DATA;
  367.     }
  368.    
  369.     uint16_t rawbits=0;
  370.    
  371.     for (uint8_t i = 1; i < len; i++) {
  372.         if ((i&1) == 1) {       /* if odd, ir-pause */
  373.             /* check length of pause between bits */
  374.             if (buf[i] > IR_SHARP_LOW_ONE - IR_SHARP_LOW_ONE/IR_SHARP_TOL_DIV && buf[i] < IR_SHARP_LOW_ONE + IR_SHARP_LOW_ONE/IR_SHARP_TOL_DIV) {
  375.                 /* write a one */
  376.                 rawbits |= 1<<((i-1)>>1);
  377.             } else if (buf[i] > IR_SHARP_LOW_ZERO - IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV && buf[i] < IR_SHARP_LOW_ZERO + IR_SHARP_LOW_ZERO/IR_SHARP_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 (buf[i] > IR_SHARP_HIGH + IR_SHARP_HIGH/IR_SHARP_TOL_DIV || buf[i] < IR_SHARP_HIGH - IR_SHARP_HIGH/IR_SHARP_TOL_DIV) {
  384.                 return IR_NOT_CORRECT_DATA;
  385.             }
  386.         }
  387.     }
  388.    
  389.     proto->protocol=IR_PROTO_SHARP;
  390.     proto->timeout=IR_SHARP_TIMEOUT;
  391.     proto->data=rawbits;
  392.     return IR_OK;
  393. }
  394. #endif
  395.  
  396. /**
  397.  * Expand data from Sharp protocol
  398.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  399.  *
  400.  * @param buf
  401.  *      Pointer to buffer to store the expanded data
  402.  * @param len
  403.  *      Pointer to length of the data
  404.  * @param proto
  405.  *      Pointer to protocol information
  406.  * @return
  407.  *      IR_OK if data expanded successfully, one of several errormessages if not
  408.  */
  409. int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  410.     //TODO: Implement this function.
  411.     return IR_NOT_CORRECT_DATA;
  412. }
  413.  
  414.  
  415. #if (IR_PROTOCOLS_USE_NEC)
  416. /**
  417.  * Test data on NEC protocol
  418.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  419.  *
  420.  * @param buf
  421.  *      Pointer to buffer to where to data to parse is stored
  422.  * @param len
  423.  *      Length of the data
  424.  * @param proto
  425.  *      Pointer to protocol information
  426.  * @return
  427.  *      IR_OK if data parsed successfully, one of several errormessages if not
  428.  */
  429. int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  430.     /* parse buf[], max is len */
  431.  
  432.     /* check if we have correct amount of data */
  433.     if (len != 67) {
  434.         return IR_NOT_CORRECT_DATA;
  435.     }
  436.    
  437.     /* check startbit */
  438.     if (buf[0] > IR_NEC_ST_BIT + IR_NEC_ST_BIT/IR_NEC_TOL_DIV || buf[0] < IR_NEC_ST_BIT - IR_NEC_ST_BIT/IR_NEC_TOL_DIV) {
  439.         return IR_NOT_CORRECT_DATA;
  440.     }
  441.  
  442.     /* check pause after startbit */
  443.     if (buf[1] > IR_NEC_ST_PAUSE + IR_NEC_ST_PAUSE/IR_NEC_TOL_DIV || buf[1] < IR_NEC_ST_PAUSE - IR_NEC_ST_PAUSE/IR_NEC_TOL_DIV) {
  444.         return IR_NOT_CORRECT_DATA;
  445.     }
  446.  
  447.     uint32_t rawbits = 0;
  448.  
  449.     for (uint8_t i = 3; i < len; i++) {
  450.         if ((i&1) == 1) {       /* if odd, ir-pause */
  451.             /* check length of pause between bits */
  452.             if (buf[i] > IR_NEC_LOW_ONE - IR_NEC_LOW_ONE/IR_NEC_TOL_DIV && buf[i] < IR_NEC_LOW_ONE + IR_NEC_LOW_ONE/IR_NEC_TOL_DIV) {
  453.                 /* write a one */
  454.                 rawbits |= 1UL<<((i-3)>>1);
  455.             } else if (buf[i] > IR_NEC_LOW_ZERO - IR_NEC_LOW_ZERO/IR_NEC_TOL_DIV && buf[i] < IR_NEC_LOW_ZERO + IR_NEC_LOW_ZERO/IR_NEC_TOL_DIV) {
  456.                 /* do nothing, a zero is already in place */
  457.             } else {
  458.                 return IR_NOT_CORRECT_DATA;
  459.             }
  460.         } else {            /* if even, ir-bit */
  461.             if (buf[i] > IR_NEC_HIGH + IR_NEC_HIGH/IR_NEC_TOL_DIV || buf[i] < IR_NEC_HIGH - IR_NEC_HIGH/IR_NEC_TOL_DIV) {
  462.                 return IR_NOT_CORRECT_DATA;
  463.             }
  464.         }
  465.     }
  466.  
  467.     proto->protocol=IR_PROTO_NEC;
  468.     proto->timeout=IR_NEC_TIMEOUT;
  469.     proto->data=rawbits;   
  470.     return IR_OK;
  471. }
  472. #endif
  473.  
  474. /**
  475.  * Expand data from NEC protocol
  476.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  477.  *
  478.  * @param buf
  479.  *      Pointer to buffer to store the expanded data
  480.  * @param len
  481.  *      Pointer to length of the data
  482.  * @param proto
  483.  *      Pointer to protocol information
  484.  * @return
  485.  *      IR_OK if data expanded successfully, one of several errormessages if not
  486.  */
  487. int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  488.     /* Set up startbit */
  489.     buf[0] = IR_NEC_ST_BIT;
  490.    
  491.     if (proto->framecnt == 0) {
  492.         buf[1] = IR_NEC_ST_PAUSE;
  493.    
  494.         *len = 67;
  495.         for (uint8_t i = 0; i < 65; i++) {
  496.             if ((i&1) == 1) {       /* if odd, ir-pause */
  497.                 if ((proto->data>>(i>>1))&1) {
  498.                     buf[i+2] = IR_NEC_LOW_ONE;
  499.                 } else {
  500.                     buf[i+2] = IR_NEC_LOW_ZERO;
  501.                 }
  502.             } else {            /* if even, ir-bit */
  503.                 buf[i+2] = IR_NEC_HIGH;
  504.             }
  505.         }
  506.         proto->timeout=IR_NEC_TIMEOUT;
  507.     } else {
  508.         buf[1] = IR_NEC_ST_PAUSE/2;
  509.         buf[2] = IR_NEC_HIGH;
  510.         proto->timeout=IR_NEC_ST_TIMEOUT;
  511.         *len = 3;
  512.     }
  513.     proto->modfreq=IR_NEC_F_MOD;
  514.     proto->repeats=IR_NEC_REPS;
  515.     return IR_OK;
  516. }
  517.  
  518.  
  519. #if (IR_PROTOCOLS_USE_SAMSUNG)
  520. /**
  521.  * Test data on Samsung protocol
  522.  * Very much like NEC, different start bit/pause lengths etc.
  523.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  524.  *
  525.  * @param buf
  526.  *      Pointer to buffer to where to data to parse is stored
  527.  * @param len
  528.  *      Length of the data
  529.  * @param proto
  530.  *      Pointer to protocol information
  531.  * @return
  532.  *      IR_OK if data parsed successfully, one of several errormessages if not
  533.  */
  534. int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  535.     /* parse buf[], max is len */
  536.  
  537.     /* check if we have correct amount of data */
  538.     if (len != 67) {
  539.         return IR_NOT_CORRECT_DATA;
  540.     }
  541.    
  542.     /* check startbit */
  543.     if (buf[0] > IR_SAMS_ST_BIT + IR_SAMS_ST_BIT/IR_SAMS_TOL_DIV || buf[0] < IR_SAMS_ST_BIT - IR_SAMS_ST_BIT/IR_SAMS_TOL_DIV) {
  544.         return IR_NOT_CORRECT_DATA;
  545.     }
  546.  
  547.     /* check pause after startbit */
  548.     if (buf[1] > IR_SAMS_ST_PAUSE + IR_SAMS_ST_PAUSE/IR_SAMS_TOL_DIV || buf[1] < IR_SAMS_ST_PAUSE - IR_SAMS_ST_PAUSE/IR_SAMS_TOL_DIV) {
  549.         return IR_NOT_CORRECT_DATA;
  550.     }
  551.  
  552.     uint32_t rawbits = 0;
  553.    
  554.     for (uint8_t i = 3; i < len; i++) {
  555.         if ((i&1) == 1) {       /* if odd, ir-pause */
  556.             /* check length of pause between bits */
  557.             if (buf[i] > IR_SAMS_LOW_ONE - IR_SAMS_LOW_ONE/IR_SAMS_TOL_DIV && buf[i] < IR_SAMS_LOW_ONE + IR_SAMS_LOW_ONE/IR_SAMS_TOL_DIV) {
  558.                 /* write a one */
  559.                 rawbits |= 1UL<<((i-3)>>1);
  560.             } else if (buf[i] > IR_SAMS_LOW_ZERO - IR_SAMS_LOW_ZERO/IR_SAMS_TOL_DIV && buf[i] < IR_SAMS_LOW_ZERO + IR_SAMS_LOW_ZERO/IR_SAMS_TOL_DIV) {
  561.                 /* do nothing, a zero is already in rawbits */
  562.             } else {
  563.                 return IR_NOT_CORRECT_DATA;
  564.             }
  565.         } else {            /* if even, ir-bit */
  566.             if (buf[i] > IR_SAMS_HIGH + IR_SAMS_HIGH/IR_SAMS_TOL_DIV || buf[i] < IR_SAMS_HIGH - IR_SAMS_HIGH/IR_SAMS_TOL_DIV) {
  567.                 return IR_NOT_CORRECT_DATA;
  568.             }
  569.         }
  570.     }
  571.    
  572.     proto->protocol=IR_PROTO_SAMS;
  573.     proto->timeout=IR_SAMS_TIMEOUT;
  574.     proto->data=rawbits;   
  575.     return IR_OK;
  576. }
  577. #endif
  578.  
  579. /**
  580.  * Expand data from Samsung protocol
  581.  * Very much like NEC, different start bit/pause lengths etc.
  582.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  583.  *
  584.  * @param buf
  585.  *      Pointer to buffer to store the expanded data
  586.  * @param len
  587.  *      Pointer to length of the data
  588.  * @param proto
  589.  *      Pointer to protocol information
  590.  * @return
  591.  *      IR_OK if data expanded successfully, one of several errormessages if not
  592.  */
  593. int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  594.     /* Set up startbit */
  595.     buf[0] = IR_SAMS_ST_BIT;
  596.     buf[1] = IR_SAMS_ST_PAUSE;
  597.    
  598.     for (uint8_t i = 0; i < 65; i++) {
  599.         if ((i&1) == 1) {       /* if odd, ir-pause */
  600.             if ((proto->data>>(i>>1))&1) {
  601.                 buf[i+2] = IR_SAMS_LOW_ONE;
  602.             } else {
  603.                 buf[i+2] = IR_SAMS_LOW_ZERO;
  604.             }
  605.         } else {                /* if even, ir-bit */
  606.             buf[i+2] = IR_SAMS_HIGH;
  607.         }
  608.     }
  609.    
  610.     *len = 67;
  611.    
  612.     proto->modfreq=IR_SAMS_F_MOD;
  613.     proto->timeout=IR_SAMS_TIMEOUT;
  614.     proto->repeats=IR_SAMS_REPS;
  615.     return IR_OK;
  616. }
  617.  
  618. #if (IR_PROTOCOLS_USE_MARANTZ)
  619. /**
  620.  * Test data on Marantz protocol
  621.  * Reverse-Engineered by Noddan, very similar to RC-5.
  622.  * Not tested with odd adresses since I have no remote that sends them.
  623.  * Don't know what happens with the extra long bit in that case.
  624.  *
  625.  * @param buf
  626.  *      Pointer to buffer to where to data to parse is stored
  627.  * @param len
  628.  *      Length of the data
  629.  * @param proto
  630.  *      Pointer to protocol information
  631.  * @return
  632.  *      IR_OK if data parsed successfully, one of several errormessages if not
  633.  */
  634. int8_t parseMarantz(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  635.     uint8_t halfbitscnt = 1;
  636.     uint32_t rawbits = 0;
  637.    
  638.     for (uint8_t i = 0; i<len; i++) {
  639.         //halfbitscnt&1==1 in the middle of bits
  640.         //i&1==0 positive flank
  641.  
  642.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  643.             rawbits |= (uint32_t)1<<(19-(halfbitscnt>>1));
  644.         }
  645.        
  646.         if (buf[i] > IR_MARANTZ_HALF_BIT - IR_MARANTZ_HALF_BIT/IR_MARANTZ_TOL_DIV && buf[i] < IR_MARANTZ_HALF_BIT + IR_MARANTZ_HALF_BIT/IR_MARANTZ_TOL_DIV) {
  647.             halfbitscnt += 1;
  648.         } else if (buf[i] > IR_MARANTZ_BIT - IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV && buf[i] < IR_MARANTZ_BIT + IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV) {
  649.             halfbitscnt += 2;
  650.         } else if (buf[i] > IR_MARANTZ_BIT - IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV && buf[i] < 5*IR_MARANTZ_HALF_BIT + IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV) {
  651.             halfbitscnt += 1; //It seems to work, not entirely sure of the purpose of this long zero though.
  652.         } else {
  653.             return IR_NOT_CORRECT_DATA;
  654.         }
  655.        
  656.     }
  657.    
  658.     proto->protocol=IR_PROTO_MARANTZ;
  659.     proto->timeout=IR_MARANTZ_TIMEOUT;
  660.     proto->data = rawbits&0x0001ffff;
  661.    
  662.     return IR_OK;
  663. }
  664. #endif
  665.  
  666. /**
  667.  * Expand data from Marantz. Written by Martin Nordin
  668.  *
  669.  * @param buf
  670.  *      Pointer to buffer to store the expanded data
  671.  * @param len
  672.  *      Pointer to length of the data
  673.  * @param proto
  674.  *      Pointer to protocol information
  675.  * @return
  676.  *      IR_OK if data expanded successfully, one of several errormessages if not
  677.  */
  678. int8_t expandMarantz(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  679.     uint8_t previousBit;
  680.     uint32_t tempdata;
  681.    
  682.     /* Set up startbits */
  683.     buf[0] = IR_MARANTZ_HALF_BIT;//first start bit
  684.     buf[1] = IR_MARANTZ_HALF_BIT;
  685.     buf[2] = IR_MARANTZ_HALF_BIT;//second start bit
  686.     //TODO: Toggle bit should be better, not hard-coded
  687.     buf[3] = IR_MARANTZ_HALF_BIT;
  688.     buf[4] = IR_MARANTZ_HALF_BIT;//toggle bit
  689.     *len=5;
  690.     previousBit = 1;
  691.    
  692.     tempdata = (uint32_t)(proto->data)<<14;
  693.        
  694.     for(uint8_t i = 0; i < 17; i++) {
  695.         tempdata = (uint32_t)tempdata<<1;
  696.  
  697.         if (((uint32_t)tempdata>>31)==1){
  698.             if (previousBit == 1){//11
  699.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  700.                 buf[*len+1] = IR_MARANTZ_HALF_BIT;
  701.                 *len = *len + 2;
  702.             } else {//01
  703.                 buf[*len-1] = IR_MARANTZ_BIT;
  704.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  705.                 *len = *len + 1;
  706.             }
  707.             previousBit = 1;
  708.         } else {
  709.             if (previousBit == 1){//10
  710.                 buf[*len-1] = IR_MARANTZ_BIT;
  711.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  712.                 *len = *len + 1;
  713.             } else {//00
  714.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  715.                 if (i==4){
  716.                     buf[*len+1] = IR_MARANTZ_HALF_BIT*5;
  717.                 } else {
  718.                     buf[*len+1] = IR_MARANTZ_HALF_BIT;
  719.                 }
  720.                
  721.                 *len = *len + 2;
  722.             }
  723.             previousBit = 0;
  724.         }
  725.     }
  726.     //make sure that we finish high by removing the last zero if needed
  727.     if (*len%2 == 0){
  728.         *len = *len - 1;
  729.     }
  730.  
  731.     proto->modfreq=IR_MARANTZ_F_MOD;
  732.     proto->timeout=IR_MARANTZ_TIMEOUT;
  733.     proto->repeats=IR_MARANTZ_REPS;
  734.     return IR_OK;
  735. }
  736.  
  737. #if (IR_PROTOCOLS_USE_PANASONIC)
  738. /**
  739.  * Test data on Panasonic protocol
  740.  *
  741.  * @param buf
  742.  *      Pointer to buffer to where to data to parse is stored
  743.  * @param len
  744.  *      Length of the data
  745.  * @param proto
  746.  *      Pointer to protocol information
  747.  * @return
  748.  *      IR_OK if data parsed successfully, one of several errormessages if not
  749.  */
  750. int8_t parsePanasonic(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  751.     /* parse buf[], max is len */
  752.  
  753.     /* check if we have correct amount of data */
  754.     if (len != 99) {
  755.         return IR_NOT_CORRECT_DATA;
  756.     }
  757.    
  758.     /* check startbit */
  759.     if (buf[0] > IR_PANA_ST_BIT + IR_PANA_ST_BIT/IR_PANA_TOL_DIV || buf[0] < IR_PANA_ST_BIT - IR_PANA_ST_BIT/IR_PANA_TOL_DIV) {
  760.         return IR_NOT_CORRECT_DATA;
  761.     }
  762.  
  763.     /* check pause after startbit */
  764.     if (buf[1] > IR_PANA_ST_PAUSE + IR_PANA_ST_PAUSE/IR_PANA_TOL_DIV || buf[1] < IR_PANA_ST_PAUSE - IR_PANA_ST_PAUSE/IR_PANA_TOL_DIV) {
  765.         return IR_NOT_CORRECT_DATA;
  766.     }
  767.  
  768.     uint32_t rawbits = 0;
  769.    
  770.     /* skip start bit, start bit pause and first 16 bits (32 values) */
  771.     for (uint8_t i = (3+16*2); i < len; i++) {
  772.         if ((i&1) == 1) {       /* if odd, ir-pause */
  773.             /* check length of pause between bits */
  774.             if (buf[i] > IR_PANA_LOW_ONE - IR_PANA_LOW_ONE/IR_PANA_TOL_DIV && buf[i] < IR_PANA_LOW_ONE + IR_PANA_LOW_ONE/IR_PANA_TOL_DIV) {
  775.                 /* write a one */
  776.                 rawbits |= 1UL<<((i-(3+16*2))>>1);
  777.             } else if (buf[i] > IR_PANA_LOW_ZERO - IR_PANA_LOW_ZERO/IR_PANA_TOL_DIV && buf[i] < IR_PANA_LOW_ZERO + IR_PANA_LOW_ZERO/IR_PANA_TOL_DIV) {
  778.                 /* do nothing, a zero is already in rawbits */
  779.             } else {
  780.                 return IR_NOT_CORRECT_DATA;
  781.             }
  782.         } else {            /* if even, ir-bit */
  783.             if (buf[i] > IR_PANA_HIGH + IR_PANA_HIGH/IR_PANA_TOL_DIV || buf[i] < IR_PANA_HIGH - IR_PANA_HIGH/IR_PANA_TOL_DIV) {
  784.                 return IR_NOT_CORRECT_DATA;
  785.             }
  786.         }
  787.     }
  788.    
  789.     proto->protocol=IR_PROTO_PANASONIC;
  790.     proto->timeout=IR_PANA_TIMEOUT;
  791.     proto->data=rawbits;   
  792.     return IR_OK;
  793. }
  794. #endif
  795.  
  796. /**
  797.  * Expand data from Panasonic protocol
  798.  *
  799.  * @param buf
  800.  *      Pointer to buffer to store the expanded data
  801.  * @param len
  802.  *      Pointer to length of the data
  803.  * @param proto
  804.  *      Pointer to protocol information
  805.  * @return
  806.  *      IR_OK if data expanded successfully, one of several errormessages if not
  807.  */
  808. int8_t expandPanasonic(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  809.     /* Set up startbit */
  810.     buf[0] = IR_PANA_ST_BIT;
  811.     buf[1] = IR_PANA_ST_PAUSE;
  812.    
  813.     /* add the first 16 static bits */
  814.     uint16_t staticBits = 0x2002;
  815.     for (uint8_t i = 0; i < 32; i++) {
  816.         if ((i&1) == 1) {       /* if odd, ir-pause */
  817.             if ((staticBits>>(i>>1))&1) {
  818.                 buf[i+2] = IR_PANA_LOW_ONE;
  819.             } else {
  820.                 buf[i+2] = IR_PANA_LOW_ZERO;
  821.             }
  822.         } else {                /* if even, ir-bit */
  823.             buf[i+2] = IR_PANA_HIGH;
  824.         }
  825.     }
  826.    
  827.     /* then add the value bits */
  828.     for (uint8_t i = 0; i < 65; i++) {
  829.         if ((i&1) == 1) {       /* if odd, ir-pause */
  830.             if ((proto->data>>(i>>1))&1) {
  831.                 buf[i+2+32] = IR_PANA_LOW_ONE;
  832.             } else {
  833.                 buf[i+2+32] = IR_PANA_LOW_ZERO;
  834.             }
  835.         } else {                /* if even, ir-bit */
  836.             buf[i+2+32] = IR_PANA_HIGH;
  837.         }
  838.     }
  839.    
  840.     *len = 99;
  841.    
  842.     proto->modfreq=IR_PANA_F_MOD;
  843.     proto->timeout=IR_PANA_TIMEOUT;
  844.     proto->repeats=IR_PANA_REPS;
  845.     return IR_OK;
  846. }
  847.  
  848. #if (IR_PROTOCOLS_USE_SKY)
  849. /**
  850.  * Test data on Sky protocol
  851.  *
  852.  *
  853.  * @param buf
  854.  *      Pointer to buffer to where to data to parse is stored
  855.  * @param len
  856.  *      Length of the data
  857.  * @param proto
  858.  *      Pointer to protocol information
  859.  * @return
  860.  *      IR_OK if data parsed successfully, one of several errormessages if not
  861.  */
  862. int8_t parseSky(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  863.     /* parse buf[], max is len */
  864.  
  865.     /* check startbit */
  866.     if (buf[0] > IR_SKY_ST_BIT + IR_SKY_ST_BIT/IR_SKY_TOL_DIV || buf[0] < IR_SKY_ST_BIT - IR_SKY_ST_BIT/IR_SKY_TOL_DIV) {
  867.         return IR_NOT_CORRECT_DATA;
  868.     }
  869.    
  870.     uint32_t rawbits=0;
  871.     uint8_t current=0;
  872.     uint8_t previous=0;
  873.     uint8_t cnt=0;
  874. #define SKYLONG 0
  875. #define SKYSHORT 1
  876.     for (uint8_t i = 1; i < len; i++)
  877.     {
  878.         if (buf[i] > IR_SKY_SHORT - IR_SKY_SHORT/IR_SKY_TOL_DIV && buf[i] < IR_SKY_SHORT + IR_SKY_SHORT/IR_SKY_TOL_DIV) {
  879.             current = SKYSHORT;
  880.         }
  881.         else if (buf[i] > IR_SKY_LONG - IR_SKY_LONG/IR_SKY_TOL_DIV && buf[i] < IR_SKY_LONG + IR_SKY_LONG/IR_SKY_TOL_DIV) {
  882.             current = SKYLONG;
  883.         }
  884.         else {
  885.             return IR_NOT_CORRECT_DATA;
  886.         }
  887.        
  888.         /* if level is low */
  889.         if ((rawbits&1)==0) {
  890.             /* and there is a long pulse */
  891.             if (current == SKYLONG) {
  892.                 /* push a one */
  893.                 rawbits = rawbits<<1;
  894.                 rawbits |= 1;
  895.                 cnt = 0;
  896.             }
  897.             else if (cnt == 0) {
  898.                 cnt=1;
  899.                 /* push a zero */
  900.                 rawbits = rawbits<<1;
  901.                
  902.             }
  903.             else {
  904.                 cnt = 0;
  905.             }
  906.         }
  907.        
  908.         /* if level is high */
  909.         if ((rawbits&1)==1) {
  910.             /* and there is a long pulse */
  911.             if (current == SKYLONG) {
  912.                 /* push a zero */
  913.                 rawbits = rawbits<<1;
  914.                
  915.                 if (previous == SKYLONG) {
  916.                     cnt = 1;
  917.                 }
  918.                 else {
  919.                     cnt = 0;
  920.                 }
  921.             }
  922.             else if (cnt == 0) {
  923.                 cnt=1;
  924.                 /* push a one */
  925.                 rawbits = rawbits<<1;
  926.                 rawbits |= 1;
  927.             }
  928.             else {
  929.                 cnt = 0;
  930.             }
  931.         }
  932.        
  933.         previous=current;
  934.        
  935.     }
  936.    
  937.     proto->protocol = IR_PROTO_SKY;
  938.     proto->timeout = IR_SKY_TIMEOUT;
  939.     proto->data = rawbits;
  940.    
  941.     return IR_OK;
  942. }
  943. #endif
  944.  
  945. /**
  946.  * Expand data from Sky protocol
  947.  *
  948.  *
  949.  * @param buf
  950.  *      Pointer to buffer to store the expanded data
  951.  * @param len
  952.  *      Pointer to length of the data
  953.  * @param proto
  954.  *      Pointer to protocol information
  955.  * @return
  956.  *      IR_OK if data expanded successfully, one of several errormessages if not
  957.  */
  958. int8_t expandSky(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  959.     //TODO: Implement this function.
  960.     buf[0] = IR_SKY_ST_BIT;
  961.     buf[1] = IR_SKY_LONG;   //
  962.    
  963.    
  964.     return IR_NOT_CORRECT_DATA;
  965. }
  966.  
  967. #if (IR_PROTOCOLS_USE_NEXA2)
  968. /**
  969.  * Test data on NEXA protocol
  970.  * http://elektronikforumet.com/wiki/index.php?title=RF_Protokoll_-_Nexa_sj%C3%A4lvl%C3%A4rande
  971.  * http://pastebin.com/PJX3bRAs
  972.  *
  973.  * @param buf
  974.  *      Pointer to buffer to where to data to parse is stored
  975.  * @param len
  976.  *      Length of the data
  977.  * @param proto
  978.  *      Pointer to protocol information
  979.  * @return
  980.  *      IR_OK if data parsed successfully, one of several errormessages if not
  981.  */
  982.  
  983. int8_t parseNexa2(const uint16_t *buf, uint8_t len, uint8_t index, Ir_Protocol_Data_t *proto)
  984. {
  985.     /* check if we have correct amount of data */
  986.     if (len < 132) {
  987.         return IR_NOT_CORRECT_DATA;
  988.     }
  989.     uint8_t i;
  990. #if IR_RX_CONTINUOUS_MODE==0
  991.     i = 0;
  992. #else
  993.     i=index-132;
  994.     if (i>index)
  995.         i+=MAX_NR_TIMES;
  996. #endif
  997.     if ((buf[i] < IR_NEXA2_START1 - IR_NEXA2_START1/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_START1 + IR_NEXA2_START1/IR_NEXA2_TOL_DIV)) { //check start bit
  998.         return IR_NOT_CORRECT_DATA;
  999.     }
  1000. #if IR_RX_CONTINUOUS_MODE==0
  1001.     i = 1;
  1002. #else
  1003.     i=index-131;
  1004.     if (i>index)
  1005.         i+=MAX_NR_TIMES;
  1006. #endif
  1007.     if ((buf[i] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_HIGH + IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV)) { //check start bit
  1008.         return IR_NOT_CORRECT_DATA;
  1009.     }
  1010. #if IR_RX_CONTINUOUS_MODE==0
  1011.     i = 2;
  1012. #else
  1013.     i=index-130;
  1014.     if (i>index)
  1015.         i+=MAX_NR_TIMES;
  1016. #endif
  1017.     if ((buf[i] < IR_NEXA2_START2 - IR_NEXA2_START2/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_START2 + IR_NEXA2_START2/IR_NEXA2_TOL_DIV)) { //check start bit
  1018.         return IR_NOT_CORRECT_DATA;
  1019.     }
  1020.  
  1021.     /* Incoming data could actually be longer than 32bits when a dimming command is received */
  1022.     uint64_t rawbitsTemp = 0;
  1023.     uint8_t bitCounter = 0;
  1024.     uint8_t i2;
  1025.     for (i = 3; i < 132; i++) {
  1026. #if IR_RX_CONTINUOUS_MODE==0
  1027.         i2 = i;
  1028. #else
  1029.         i2=index-(132-i);
  1030.         if (i2>index)
  1031.             i2+=MAX_NR_TIMES;
  1032. #endif
  1033.         if ((i&1) == 0) {       /* if even, data */
  1034.             /* check length of transmit pulse */
  1035.             if ((buf[i2] > IR_NEXA2_LOW_ONE - IR_NEXA2_LOW_ONE/IR_NEXA2_TOL_DIV) && (buf[i2] < IR_NEXA2_LOW_ONE + IR_NEXA2_LOW_ONE/IR_NEXA2_TOL_DIV)) {
  1036.                 /* write a one */
  1037.                 rawbitsTemp |= (1UL)<<(bitCounter++);
  1038.             } else if ((buf[i2] > IR_NEXA2_LOW_ZERO - IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV) && (buf[i2] < IR_NEXA2_LOW_ZERO + IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV)) {
  1039.                 /* do nothing, a zero is already in rawbits */
  1040.                 bitCounter++;
  1041.             } else {
  1042.                 return IR_NOT_CORRECT_DATA;
  1043.             }
  1044.             i+=2;   // skip every other bit, implement check here in the future
  1045.         } else {            /* if odd, no data */
  1046.             if ((buf[i2] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) || (buf[i2] > IR_NEXA2_HIGH + IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV)) {
  1047.                 return IR_NOT_CORRECT_DATA;
  1048.             }
  1049.         }
  1050.     }
  1051.    
  1052.     proto->protocol=IR_PROTO_NEXA2;
  1053.     proto->timeout=IR_NEXA2_TIMEOUT;
  1054.     proto->data=rawbitsTemp;
  1055.  
  1056.     return IR_OK;
  1057. }
  1058. #endif
  1059.  
  1060. /**
  1061.  * Expand data from Nexa2 protocol
  1062.  *
  1063.  *
  1064.  * @param buf
  1065.  *      Pointer to buffer to store the expanded data
  1066.  * @param len
  1067.  *      Pointer to length of the data
  1068.  * @param proto
  1069.  *      Pointer to protocol information
  1070.  * @return
  1071.  *      IR_OK if data expanded successfully, one of several errormessages if not
  1072.  */
  1073. int8_t expandNexa2(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  1074.     buf[0] = IR_NEXA2_HIGH;
  1075.     buf[1] = IR_NEXA2_START2;
  1076.  
  1077.     uint64_t tempshift = proto->data;
  1078.  
  1079.     /* No dimming */
  1080.     *len = 131;
  1081.     uint8_t dimming = 0;
  1082.     /* If most significant bit is set, then dimming should be sent */
  1083.     if ((uint32_t)(tempshift>> 32)&0x80)
  1084.     {
  1085.         /* Dimming */
  1086.         *len = 147;
  1087.         dimming=1;
  1088.     }
  1089.    
  1090.     for (uint8_t i = 2; i < *len; i+=4)
  1091.     {
  1092.         buf[i] = IR_NEXA2_HIGH;
  1093.         buf[i+2] = IR_NEXA2_HIGH;
  1094.         if (tempshift&1) {
  1095.             buf[i+1] = IR_NEXA2_LOW_ONE;
  1096.             buf[i+3] = IR_NEXA2_LOW_ZERO;
  1097.         } else {
  1098.             buf[i+1] = IR_NEXA2_LOW_ZERO;
  1099.             buf[i+3] = IR_NEXA2_LOW_ONE;
  1100.         }
  1101.         tempshift = tempshift>>1;
  1102.     }
  1103.    
  1104.     if (dimming)
  1105.     {
  1106.         buf[111] = IR_NEXA2_LOW_ONE;
  1107.         buf[113] = IR_NEXA2_LOW_ONE;
  1108.     }
  1109.     proto->modfreq=IR_NEXA2_F_MOD;
  1110.     proto->timeout=IR_NEXA2_START1/1000;
  1111.     proto->repeats=IR_NEXA2_REPS;
  1112.     return IR_OK;
  1113. }
  1114.  
  1115.  
  1116. #if (IR_PROTOCOLS_USE_NEXA1)
  1117. /**
  1118.  * Test data on NEXA protocol
  1119.  * http://www.elektronikforumet.com/wiki/index.php/RF_Protokoll_-_Nexa/Proove_(%C3%A4ldre,_ej_sj%C3%A4lvl%C3%A4rande)
  1120.  *
  1121.  * @param buf
  1122.  *      Pointer to buffer to where to data to parse is stored
  1123.  * @param len
  1124.  *      Length of the data
  1125.  * @param proto
  1126.  *      Pointer to protocol information
  1127.  * @return
  1128.  *      IR_OK if data parsed successfully, one of several errormessages if not
  1129.  */
  1130. int8_t parseNexa1(const uint16_t *buf, uint8_t len, uint8_t index, Ir_Protocol_Data_t *proto) {
  1131.     /* parse buf[], max is len */
  1132.  
  1133.     /* check if we have correct amount of data */
  1134.     if (len != 50) {
  1135.         return IR_NOT_CORRECT_DATA;
  1136.     }
  1137.     if (buf[0] < IR_NEXA1_START - IR_NEXA1_START/IR_NEXA1_TOL_DIV || buf[0] > IR_NEXA1_START + IR_NEXA1_START/IR_NEXA1_TOL_DIV) { //check start bit
  1138.         return IR_NOT_CORRECT_DATA;
  1139.     }
  1140.  
  1141.     uint32_t rawbitsTemp = 0;
  1142.     uint8_t bitCounter = 0;
  1143.  
  1144.     for (uint8_t i = 1; i < len; i+=4) {
  1145.         /* Check if '0' bit */
  1146.         if (
  1147.             (buf[i+0] > IR_NEXA1_SHORT - IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV && buf[i+0] < IR_NEXA1_SHORT + IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV) &&
  1148.             (buf[i+1] > IR_NEXA1_LONG  - IR_NEXA1_LONG/IR_NEXA1_TOL_DIV  && buf[i+1] < IR_NEXA1_LONG  + IR_NEXA1_LONG/IR_NEXA1_TOL_DIV) &&
  1149.             (buf[i+2] > IR_NEXA1_SHORT - IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV && buf[i+2] < IR_NEXA1_SHORT + IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV) &&
  1150.             (buf[i+3] > IR_NEXA1_LONG  - IR_NEXA1_LONG/IR_NEXA1_TOL_DIV  && buf[i+3] < IR_NEXA1_LONG  + IR_NEXA1_LONG/IR_NEXA1_TOL_DIV))
  1151.         {
  1152.             /* write a one */
  1153.             rawbitsTemp |= (1UL)<<(bitCounter++);
  1154.         }
  1155.         /* Check if 'X' bit */
  1156.         else if (
  1157.             (buf[i+0] > IR_NEXA1_SHORT - IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV && buf[i+0] < IR_NEXA1_SHORT + IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV) &&
  1158.             (buf[i+1] > IR_NEXA1_LONG  - IR_NEXA1_LONG/IR_NEXA1_TOL_DIV  && buf[i+1] < IR_NEXA1_LONG  + IR_NEXA1_LONG/IR_NEXA1_TOL_DIV) &&
  1159.             (buf[i+2] > IR_NEXA1_LONG  - IR_NEXA1_LONG/IR_NEXA1_TOL_DIV  && buf[i+2] < IR_NEXA1_LONG  + IR_NEXA1_LONG/IR_NEXA1_TOL_DIV) &&
  1160.             (buf[i+3] > IR_NEXA1_SHORT - IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV && buf[i+3] < IR_NEXA1_SHORT + IR_NEXA1_SHORT/IR_NEXA1_TOL_DIV))
  1161.         {
  1162.             /* do nothing, a zero is already in rawbits */
  1163.             bitCounter++;
  1164.         }
  1165.     }
  1166.  
  1167.     if (rawbitsTemp==0)
  1168.     {
  1169.         /* Bogus RF data */
  1170.         return IR_NOT_CORRECT_DATA;
  1171.     }
  1172.    
  1173.     proto->protocol=IR_PROTO_NEXA1;
  1174.     proto->timeout=IR_NEXA1_TIMEOUT;
  1175.     proto->data=rawbitsTemp;
  1176.     return IR_OK;
  1177. }
  1178.  
  1179. #endif
  1180.  
  1181. /**
  1182.  * Expand data from Nexa1 protocol
  1183.  *
  1184.  *
  1185.  * @param buf
  1186.  *      Pointer to buffer to store the expanded data
  1187.  * @param len
  1188.  *      Pointer to length of the data
  1189.  * @param proto
  1190.  *      Pointer to protocol information
  1191.  * @return
  1192.  *      IR_OK if data expanded successfully, one of several errormessages if not
  1193.  */
  1194. int8_t expandNexa1(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  1195.     uint64_t tempshift = proto->data;
  1196.  
  1197.     /* 12 data bits + 1 stop bit */
  1198.     *len = 49;
  1199.  
  1200.     /* encode data bits */
  1201.     for (uint8_t i = 0; i < 45; i += 4)
  1202.     {
  1203.         if (tempshift & 1) {
  1204.             /* encode 0 bit */
  1205.             buf[i+0] = IR_NEXA1_SHORT;
  1206.             buf[i+1] = IR_NEXA1_LONG;
  1207.             buf[i+2] = IR_NEXA1_SHORT;
  1208.             buf[i+3] = IR_NEXA1_LONG;
  1209.         } else {
  1210.             /* encode X bit */
  1211.             buf[i+0] = IR_NEXA1_SHORT;
  1212.             buf[i+1] = IR_NEXA1_LONG;
  1213.             buf[i+2] = IR_NEXA1_LONG;
  1214.             buf[i+3] = IR_NEXA1_SHORT;
  1215.         }
  1216.         tempshift = tempshift>>1;
  1217.     }
  1218.  
  1219.     /* encode stop/sync bit */
  1220.     buf[48] = IR_NEXA1_SHORT;
  1221.    
  1222.     proto->modfreq = IR_NEXA1_F_MOD;
  1223.     proto->timeout = IR_NEXA1_START/1000;
  1224.     proto->repeats = IR_NEXA1_REPS;
  1225.     return IR_OK;  
  1226. }
  1227.  
  1228.  
  1229. #if (IR_PROTOCOLS_USE_VIKING)
  1230. /**
  1231.  * Test data on Viking temperature sensor protocol
  1232.  *
  1233.  *
  1234.  *
  1235.  * @param buf
  1236.  *      Pointer to buffer to where to data to parse is stored
  1237.  * @param len
  1238.  *      Length of the data
  1239.  * @param proto
  1240.  *      Pointer to protocol information
  1241.  * @return
  1242.  *      IR_OK if data parsed successfully, one of several errormessages if not
  1243.  */
  1244.  
  1245. int8_t parseViking(const uint16_t *buf, uint8_t len, uint8_t index, Ir_Protocol_Data_t *proto)
  1246. {
  1247.     /* check if we have correct amount of data */
  1248.     if (len < 94) {
  1249.         return IR_NOT_CORRECT_DATA;
  1250.     }
  1251.     uint8_t i, i2;
  1252.     uint32_t rawbitsTemp = 0;
  1253.     uint8_t bitCounter = 0;
  1254.     for (i = 0; i < 94; i++) {
  1255. #if IR_RX_CONTINUOUS_MODE==0
  1256.         i2 = i;
  1257. #else
  1258.         i2=index-(94-i);
  1259.         if (i2>index)
  1260.             i2+=MAX_NR_TIMES;
  1261. #endif
  1262.         if ((i&1) == 0)
  1263.         {       /* if even, no data */
  1264.             if ((buf[i2] < IR_VIKING_LOW - IR_VIKING_LOW/IR_VIKING_TOL_DIV) || (buf[i2] > IR_VIKING_LOW + IR_VIKING_LOW/IR_VIKING_TOL_DIV))
  1265.             {
  1266.                 return IR_NOT_CORRECT_DATA;
  1267.             }
  1268.         }
  1269.         else
  1270.         {           /* if odd, data */
  1271.             /* check length of transmit pulse */
  1272.             if ((buf[i2] > IR_VIKING_HIGH_ONE - IR_VIKING_HIGH_ONE/IR_VIKING_TOL_DIV) && (buf[i2] < IR_VIKING_HIGH_ONE + IR_VIKING_HIGH_ONE/IR_VIKING_TOL_DIV))
  1273.             {
  1274.                 /* write a one */
  1275.                 rawbitsTemp |= (1UL)<<(bitCounter++);
  1276.             }
  1277.             else if ((buf[i2] > IR_VIKING_HIGH_ZERO - IR_VIKING_HIGH_ZERO/IR_VIKING_TOL_DIV) && (buf[i2] < IR_VIKING_HIGH_ZERO + IR_VIKING_HIGH_ZERO/IR_VIKING_TOL_DIV))
  1278.             {
  1279.                 /* do nothing, a zero is already in rawbits */
  1280.                 bitCounter++;
  1281.             }
  1282.             else
  1283.             {
  1284.                 return IR_NOT_CORRECT_DATA;
  1285.             }
  1286.         }
  1287.     }
  1288.    
  1289.     proto->protocol=IR_PROTO_VIKING;
  1290.     proto->timeout=0;
  1291.     proto->data=rawbitsTemp;
  1292.  
  1293.     return IR_OK;
  1294. }
  1295. #endif
  1296.