Subversion Repositories HomeAutomation

Rev

Rev 1875 | Rev 1906 | 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, 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. #if (IR_PROTOCOLS_USE_NEXA2)
  49.     if (parseNexa2(buf, len, proto)==IR_OK) return IR_OK;
  50. #endif
  51.     /* No protocol matched. */
  52.     proto->protocol = IR_PROTO_UNKNOWN;
  53.     return IR_NOT_CORRECT_DATA;
  54. }
  55.  
  56. int8_t parseHash(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  57.     //TODO: Transform the buffer in some clever way to a 32 bit word. */
  58.     proto->protocol = IR_PROTO_HASH;
  59.     proto->timeout = 200;
  60.     proto->data = 0;
  61.    
  62.     return 0;
  63. }
  64.  
  65. int8_t expandProtocol(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  66.     /* Call the expand function for the specified protocol. */
  67.     switch (proto->protocol) {
  68.     case IR_PROTO_SIRC:
  69.         return expandSIRC(buf, len, proto);
  70.     case IR_PROTO_RC5:
  71.         return expandRC5(buf, len, proto);
  72.     case IR_PROTO_SHARP:
  73.         return expandSharp(buf, len, proto);
  74.     case IR_PROTO_NEC:
  75.         return expandNEC(buf, len, proto);
  76.     case IR_PROTO_SAMS:
  77.         return expandSamsung(buf, len, proto);
  78.     case IR_PROTO_MARANTZ:
  79.         return expandMarantz(buf, len, proto);
  80.     case IR_PROTO_PANASONIC:
  81.         return expandPanasonic(buf, len, proto);
  82.     case IR_PROTO_SKY:
  83.         return expandSky(buf, len, proto);
  84.     case IR_PROTO_NEXA2:
  85.         return expandNexa2(buf, len, proto);
  86.     }
  87.     /* Invalid protocol specified. */
  88.     return IR_NOT_CORRECT_DATA;
  89. }
  90.  
  91. #if (IR_PROTOCOLS_USE_SIRC)
  92. /**
  93.  * Test data on SIRC protocol, 12-bit version
  94.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  95.  * http://picprojects.org.uk/projects/sirc/sonysirc.pdf
  96.  *
  97.  * @param buf
  98.  *      Pointer to buffer to where to data to parse is stored
  99.  * @param len
  100.  *      Length of the data
  101.  * @param proto
  102.  *      Pointer to protocol information
  103.  * @return
  104.  *      IR_OK if data parsed successfully, one of several errormessages if not
  105.  */
  106. int8_t parseSIRC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  107.     /* parse buf[], max is len */
  108.  
  109.     /* check if we have correct amount of data.
  110.            supporting two versions of SIRC:
  111.            12 bit = 25, 15 bit = 31
  112.            there is also a 20 bit protocol, but we don't support it
  113.          */
  114.     if (len != 25 && len != 31) {
  115.         return IR_NOT_CORRECT_DATA;
  116.     }
  117.    
  118.     /* check startbit */
  119.     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) {
  120.         return IR_NOT_CORRECT_DATA;
  121.     }
  122.    
  123.     uint16_t rawbits=0;
  124.    
  125.     for (uint8_t i = 1; i < len; i++) {
  126.         if ((i&1) == 1) {       /* if odd, ir-pause */
  127.             /* check length of pause between bits */
  128.             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) {
  129.                 return IR_NOT_CORRECT_DATA;
  130.             }
  131.         } else {            /* if even, ir-bit */
  132.             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) {
  133.                 /* write a one */
  134.                 rawbits |= 1<<((i-2)>>1);
  135.             } 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) {
  136.                 /* do nothing, a zero is already in rawbits */
  137.             } else {
  138.                 return IR_NOT_CORRECT_DATA;
  139.             }
  140.         }
  141.     }
  142.    
  143.     proto->protocol = IR_PROTO_SIRC;
  144.     proto->timeout = IR_SIRC_TIMEOUT;
  145.     proto->data = rawbits;
  146.    
  147.     return IR_OK;
  148. }
  149. #endif
  150.  
  151. /**
  152.  * Expand data from SIRC protocol
  153.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  154.  *
  155.  * @param buf
  156.  *      Pointer to buffer to store the expanded data
  157.  * @param len
  158.  *      Pointer to length of the data
  159.  * @param proto
  160.  *      Pointer to protocol information
  161.  * @return
  162.  *      IR_OK if data expanded successfully, one of several errormessages if not
  163.  */
  164. int8_t expandSIRC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  165.     buf[0] = IR_SIRC_ST_BIT;
  166.     buf[1] = IR_SIRC_LOW; //start pulse finished
  167.  
  168.         /* Assume 12 bit protocol */
  169.         *len = 25;
  170.         /* If data to big, use 15 bit protocol */
  171.         if (proto->data > (1<<11)) { // cannot be represented by 12 bits
  172.           *len = 31;
  173.         }
  174.         for (uint8_t i = 0; i < *len-2; i++) {
  175.           if ((i&1) == 1) {     /* if odd, ir-pause */
  176.             buf[i+2] = IR_SIRC_LOW;
  177.           } else {          /* if even, ir-bit */
  178.             if ((proto->data>>(i>>1))&1) {
  179.               buf[i+2] = IR_SIRC_HIGH_ONE;
  180.             } else {
  181.               buf[i+2] = IR_SIRC_HIGH_ZERO;
  182.             }
  183.           }
  184.         }  
  185.  
  186.     proto->modfreq=IR_SIRC_F_MOD;
  187.     proto->timeout=IR_SIRC_TIMEOUT;
  188.     proto->repeats=IR_SIRC_REPS;
  189.        
  190.     return IR_OK;
  191. }
  192.  
  193.  
  194. #if (IR_PROTOCOLS_USE_RC5)
  195. /**
  196.  * Test data on RC5 protocol
  197.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  198.  *
  199.  * @param buf
  200.  *      Pointer to buffer to where to data to parse is stored
  201.  * @param len
  202.  *      Length of the data
  203.  * @param proto
  204.  *      Pointer to protocol information
  205.  * @return
  206.  *      IR_OK if data parsed successfully, one of several errormessages if not
  207.  */
  208. int8_t parseRC5(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  209.     uint8_t halfbitscnt = 1;
  210.     uint16_t rawbits = 0;
  211.    
  212.     for (uint8_t i = 0; i<len; i++) {
  213.         //halfbitscnt&1==1 in the middle of bits
  214.         //i&1==0 positive flank
  215.  
  216.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  217.             rawbits |= (1<<(13-(halfbitscnt>>1)));
  218.         }
  219.        
  220.         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) {
  221.             halfbitscnt += 1;
  222.         } 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) {
  223.             halfbitscnt += 2;
  224.         } else {
  225.             return IR_NOT_CORRECT_DATA;
  226.         }
  227.        
  228.     }
  229.  
  230.     proto->protocol=IR_PROTO_RC5;
  231.     proto->timeout=IR_RC5_TIMEOUT;
  232.     //support RC5-extended keeping second startbit
  233.     //remove togglebit
  234.     proto->data = rawbits&0x37ff; //This seems to be wrong? Does not invert second start bit and keeps first start bit
  235.     //proto->data = (rawbits&0x07ff) | ((~rawbits)&0x0100);
  236.  
  237.    
  238.     return IR_OK;
  239. }
  240. #endif
  241.  
  242. /**
  243.  * Used by the expandRC5 to ensure that we toggle the signal with each button press.
  244.  */
  245. int8_t rc5_toggle=0;
  246.  
  247. /**
  248.  * Expand data from RC5 protocol
  249.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  250.  *
  251.  * One is defined as low then high
  252.  * Zero is defined as high then low
  253.  *
  254.  * @param buf
  255.  *      Pointer to buffer to store the expanded data
  256.  * @param len
  257.  *      Pointer to length of the data
  258.  * @param proto
  259.  *      Pointer to protocol information
  260.  * @return
  261.  *      IR_OK if data expanded successfully, one of several errormessages if not
  262.  */
  263. int8_t expandRC5(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  264.  
  265.     //This is the raw message that we should create the IR times for
  266.     //Lets copy the data locally to ensure that no interups will modify the vector.
  267.     uint16_t rawMessage=proto->data & 0x3fff;
  268.    
  269.     uint8_t previousBit;
  270.     /* Set up startbit */
  271.     //Bit = 0
  272.     //We start with a low signal since the diode
  273.     //isn't active before we send anything,
  274.     buf[0] = IR_RC5_HALF_BIT;//first start bit
  275.    
  276.     // Bit = 1
  277.     buf[1] = IR_RC5_HALF_BIT;
  278.     buf[2] = IR_RC5_HALF_BIT;//second start bit
  279.  
  280.     if (rc5_toggle==0){
  281.         buf[3] = IR_RC5_HALF_BIT;
  282.         buf[4] = IR_RC5_HALF_BIT; //toggle bit (yes i know it should not be hardcoded)
  283.         *len = 5;
  284.         previousBit = 1; //Same as last startbit
  285.     } else {
  286.         //We are reusing the signal from the previous signal
  287.         //and extend the time into this bit.
  288.         buf[2] = IR_RC5_BIT;
  289.         buf[3] = IR_RC5_HALF_BIT;
  290.         *len = 4;
  291.         previousBit = 0; //Toggled from last startbit
  292.     }
  293.     //Invert the toggle for next time
  294.     rc5_toggle=!rc5_toggle & 1;
  295.    
  296.     //Decode the message
  297.     //We know that RC5 messages are 14 bits long
  298.     for(uint8_t pos=11;pos>0;pos--)
  299.     {      
  300.         // Check the current bit
  301.         if(previousBit == ((rawMessage>>(pos-1)) & 1))
  302.         {
  303.             buf[*len]=IR_RC5_HALF_BIT;
  304.             buf[*len+1]=IR_RC5_HALF_BIT;
  305.             *len=*len+2;
  306.         }
  307.         else
  308.         {
  309.             //We are having the same signal as we ended the last bit with,
  310.             //Expand the time that that signal is active to cover
  311.             //half of this bit aswell
  312.             buf[*len-1]=IR_RC5_BIT;
  313.             buf[*len]=IR_RC5_HALF_BIT;
  314.             *len=*len+1;
  315.            
  316.             //Invert the previous bit
  317.             previousBit = (!previousBit) & 1;
  318.         }
  319.     }
  320.     //We have to handle the last bit specially since we have to
  321.     //end with low signal on the IR diod
  322.     if(previousBit == 0)
  323.     {
  324.         //We have to remove the last time since that would bring us to a high signal again.
  325.         *len=*len-1;
  326.         buf[*len]=0;
  327.     }
  328.    
  329.     proto->modfreq=IR_RC5_F_MOD;
  330.     proto->timeout=IR_RC5_TIMEOUT;
  331.     proto->repeats=IR_RC5_REPS;
  332.     return IR_OK;
  333. }
  334.  
  335.  
  336. #if (IR_PROTOCOLS_USE_SHARP)
  337. /**
  338.  * Test data on SHARP protocol
  339.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  340.  *
  341.  * @param buf
  342.  *      Pointer to buffer to where to data to parse is stored
  343.  * @param len
  344.  *      Length of the data
  345.  * @param proto
  346.  *      Pointer to protocol information
  347.  * @return
  348.  *      IR_OK if data parsed successfully, one of several errormessages if not
  349.  */
  350. int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  351.     /* parse buf[], max is len */
  352.  
  353.     /* check if we have correct amount of data */
  354.     if (len != 31) {
  355.         return IR_NOT_CORRECT_DATA;
  356.     }
  357.    
  358.     uint16_t rawbits=0;
  359.    
  360.     for (uint8_t i = 1; i < len; i++) {
  361.         if ((i&1) == 1) {       /* if odd, ir-pause */
  362.             /* check length of pause between bits */
  363.             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) {
  364.                 /* write a one */
  365.                 rawbits |= 1<<((i-1)>>1);
  366.             } 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) {
  367.                 /* do nothing, a zero is already in rawbits */
  368.             } else {
  369.                 return IR_NOT_CORRECT_DATA;
  370.             }
  371.         } else {            /* if even, ir-bit */
  372.             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) {
  373.                 return IR_NOT_CORRECT_DATA;
  374.             }
  375.         }
  376.     }
  377.    
  378.     proto->protocol=IR_PROTO_SHARP;
  379.     proto->timeout=IR_SHARP_TIMEOUT;
  380.     proto->data=rawbits;
  381.     return IR_OK;
  382. }
  383. #endif
  384.  
  385. /**
  386.  * Expand data from Sharp protocol
  387.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  388.  *
  389.  * @param buf
  390.  *      Pointer to buffer to store the expanded data
  391.  * @param len
  392.  *      Pointer to length of the data
  393.  * @param proto
  394.  *      Pointer to protocol information
  395.  * @return
  396.  *      IR_OK if data expanded successfully, one of several errormessages if not
  397.  */
  398. int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  399.     //TODO: Implement this function.
  400.     return IR_NOT_CORRECT_DATA;
  401. }
  402.  
  403.  
  404. #if (IR_PROTOCOLS_USE_NEC)
  405. /**
  406.  * Test data on NEC protocol
  407.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  408.  *
  409.  * @param buf
  410.  *      Pointer to buffer to where to data to parse is stored
  411.  * @param len
  412.  *      Length of the data
  413.  * @param proto
  414.  *      Pointer to protocol information
  415.  * @return
  416.  *      IR_OK if data parsed successfully, one of several errormessages if not
  417.  */
  418. int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  419.     /* parse buf[], max is len */
  420.  
  421.     /* check if we have correct amount of data */
  422.     if (len != 67) {
  423.         return IR_NOT_CORRECT_DATA;
  424.     }
  425.    
  426.     /* check startbit */
  427.     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) {
  428.         return IR_NOT_CORRECT_DATA;
  429.     }
  430.  
  431.     /* check pause after startbit */
  432.     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) {
  433.         return IR_NOT_CORRECT_DATA;
  434.     }
  435.  
  436.     uint32_t rawbits = 0;
  437.  
  438.     for (uint8_t i = 3; i < len; i++) {
  439.         if ((i&1) == 1) {       /* if odd, ir-pause */
  440.             /* check length of pause between bits */
  441.             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) {
  442.                 /* write a one */
  443.                 rawbits |= 1UL<<((i-3)>>1);
  444.             } 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) {
  445.                 /* do nothing, a zero is already in place */
  446.             } else {
  447.                 return IR_NOT_CORRECT_DATA;
  448.             }
  449.         } else {            /* if even, ir-bit */
  450.             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) {
  451.                 return IR_NOT_CORRECT_DATA;
  452.             }
  453.         }
  454.     }
  455.  
  456.     proto->protocol=IR_PROTO_NEC;
  457.     proto->timeout=IR_NEC_TIMEOUT;
  458.     proto->data=rawbits;   
  459.     return IR_OK;
  460. }
  461. #endif
  462.  
  463. /**
  464.  * Expand data from NEC protocol
  465.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  466.  *
  467.  * @param buf
  468.  *      Pointer to buffer to store the expanded data
  469.  * @param len
  470.  *      Pointer to length of the data
  471.  * @param proto
  472.  *      Pointer to protocol information
  473.  * @return
  474.  *      IR_OK if data expanded successfully, one of several errormessages if not
  475.  */
  476. int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  477.     /* Set up startbit */
  478.     buf[0] = IR_NEC_ST_BIT;
  479.    
  480.     if (proto->framecnt == 0) {
  481.         buf[1] = IR_NEC_ST_PAUSE;
  482.    
  483.         *len = 67;
  484.         for (uint8_t i = 0; i < 65; i++) {
  485.             if ((i&1) == 1) {       /* if odd, ir-pause */
  486.                 if ((proto->data>>(i>>1))&1) {
  487.                     buf[i+2] = IR_NEC_LOW_ONE;
  488.                 } else {
  489.                     buf[i+2] = IR_NEC_LOW_ZERO;
  490.                 }
  491.             } else {            /* if even, ir-bit */
  492.                 buf[i+2] = IR_NEC_HIGH;
  493.             }
  494.         }
  495.         proto->timeout=IR_NEC_TIMEOUT;
  496.     } else {
  497.         buf[1] = IR_NEC_ST_PAUSE/2;
  498.         buf[2] = IR_NEC_HIGH;
  499.         proto->timeout=IR_NEC_ST_TIMEOUT;
  500.         *len = 3;
  501.     }
  502.     proto->modfreq=IR_NEC_F_MOD;
  503.     proto->repeats=IR_NEC_REPS;
  504.     return IR_OK;
  505. }
  506.  
  507.  
  508. #if (IR_PROTOCOLS_USE_SAMSUNG)
  509. /**
  510.  * Test data on Samsung protocol
  511.  * Very much like NEC, different start bit/pause lengths etc.
  512.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  513.  *
  514.  * @param buf
  515.  *      Pointer to buffer to where to data to parse is stored
  516.  * @param len
  517.  *      Length of the data
  518.  * @param proto
  519.  *      Pointer to protocol information
  520.  * @return
  521.  *      IR_OK if data parsed successfully, one of several errormessages if not
  522.  */
  523. int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  524.     /* parse buf[], max is len */
  525.  
  526.     /* check if we have correct amount of data */
  527.     if (len != 67) {
  528.         return IR_NOT_CORRECT_DATA;
  529.     }
  530.    
  531.     /* check startbit */
  532.     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) {
  533.         return IR_NOT_CORRECT_DATA;
  534.     }
  535.  
  536.     /* check pause after startbit */
  537.     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) {
  538.         return IR_NOT_CORRECT_DATA;
  539.     }
  540.  
  541.     uint32_t rawbits = 0;
  542.    
  543.     for (uint8_t i = 3; i < len; i++) {
  544.         if ((i&1) == 1) {       /* if odd, ir-pause */
  545.             /* check length of pause between bits */
  546.             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) {
  547.                 /* write a one */
  548.                 rawbits |= 1UL<<((i-3)>>1);
  549.             } 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) {
  550.                 /* do nothing, a zero is already in rawbits */
  551.             } else {
  552.                 return IR_NOT_CORRECT_DATA;
  553.             }
  554.         } else {            /* if even, ir-bit */
  555.             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) {
  556.                 return IR_NOT_CORRECT_DATA;
  557.             }
  558.         }
  559.     }
  560.    
  561.     proto->protocol=IR_PROTO_SAMS;
  562.     proto->timeout=IR_SAMS_TIMEOUT;
  563.     proto->data=rawbits;   
  564.     return IR_OK;
  565. }
  566. #endif
  567.  
  568. /**
  569.  * Expand data from Samsung protocol
  570.  * Very much like NEC, different start bit/pause lengths etc.
  571.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  572.  *
  573.  * @param buf
  574.  *      Pointer to buffer to store the expanded data
  575.  * @param len
  576.  *      Pointer to length of the data
  577.  * @param proto
  578.  *      Pointer to protocol information
  579.  * @return
  580.  *      IR_OK if data expanded successfully, one of several errormessages if not
  581.  */
  582. int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  583.     /* Set up startbit */
  584.     buf[0] = IR_SAMS_ST_BIT;
  585.     buf[1] = IR_SAMS_ST_PAUSE;
  586.    
  587.     for (uint8_t i = 0; i < 65; i++) {
  588.         if ((i&1) == 1) {       /* if odd, ir-pause */
  589.             if ((proto->data>>(i>>1))&1) {
  590.                 buf[i+2] = IR_SAMS_LOW_ONE;
  591.             } else {
  592.                 buf[i+2] = IR_SAMS_LOW_ZERO;
  593.             }
  594.         } else {                /* if even, ir-bit */
  595.             buf[i+2] = IR_SAMS_HIGH;
  596.         }
  597.     }
  598.    
  599.     *len = 67;
  600.    
  601.     proto->modfreq=IR_SAMS_F_MOD;
  602.     proto->timeout=IR_SAMS_TIMEOUT;
  603.     proto->repeats=IR_SAMS_REPS;
  604.     return IR_OK;
  605. }
  606.  
  607. #if (IR_PROTOCOLS_USE_MARANTZ)
  608. /**
  609.  * Test data on Marantz protocol
  610.  * Reverse-Engineered by Noddan, very similar to RC-5.
  611.  * Not tested with odd adresses since I have no remote that sends them.
  612.  * Don't know what happens with the extra long bit in that case.
  613.  *
  614.  * @param buf
  615.  *      Pointer to buffer to where to data to parse is stored
  616.  * @param len
  617.  *      Length of the data
  618.  * @param proto
  619.  *      Pointer to protocol information
  620.  * @return
  621.  *      IR_OK if data parsed successfully, one of several errormessages if not
  622.  */
  623. int8_t parseMarantz(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  624.     uint8_t halfbitscnt = 1;
  625.     uint32_t rawbits = 0;
  626.    
  627.     for (uint8_t i = 0; i<len; i++) {
  628.         //halfbitscnt&1==1 in the middle of bits
  629.         //i&1==0 positive flank
  630.  
  631.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  632.             rawbits |= (uint32_t)1<<(19-(halfbitscnt>>1));
  633.         }
  634.        
  635.         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) {
  636.             halfbitscnt += 1;
  637.         } 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) {
  638.             halfbitscnt += 2;
  639.         } 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) {
  640.             halfbitscnt += 1; //It seems to work, not entirely sure of the purpose of this long zero though.
  641.         } else {
  642.             return IR_NOT_CORRECT_DATA;
  643.         }
  644.        
  645.     }
  646.    
  647.     proto->protocol=IR_PROTO_MARANTZ;
  648.     proto->timeout=IR_MARANTZ_TIMEOUT;
  649.     proto->data = rawbits&0x0001ffff;
  650.    
  651.     return IR_OK;
  652. }
  653. #endif
  654.  
  655. /**
  656.  * Expand data from Marantz. Written by Martin Nordin
  657.  *
  658.  * @param buf
  659.  *      Pointer to buffer to store the expanded data
  660.  * @param len
  661.  *      Pointer to length of the data
  662.  * @param proto
  663.  *      Pointer to protocol information
  664.  * @return
  665.  *      IR_OK if data expanded successfully, one of several errormessages if not
  666.  */
  667. int8_t expandMarantz(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  668.     uint8_t previousBit;
  669.     uint32_t tempdata;
  670.    
  671.     /* Set up startbits */
  672.     buf[0] = IR_MARANTZ_HALF_BIT;//first start bit
  673.     buf[1] = IR_MARANTZ_HALF_BIT;
  674.     buf[2] = IR_MARANTZ_HALF_BIT;//second start bit
  675.     //TODO: Toggle bit should be better, not hard-coded
  676.     buf[3] = IR_MARANTZ_HALF_BIT;
  677.     buf[4] = IR_MARANTZ_HALF_BIT;//toggle bit
  678.     *len=5;
  679.     previousBit = 1;
  680.    
  681.     tempdata = (uint32_t)(proto->data)<<14;
  682.        
  683.     for(uint8_t i = 0; i < 17; i++) {
  684.         tempdata = (uint32_t)tempdata<<1;
  685.  
  686.         if (((uint32_t)tempdata>>31)==1){
  687.             if (previousBit == 1){//11
  688.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  689.                 buf[*len+1] = IR_MARANTZ_HALF_BIT;
  690.                 *len = *len + 2;
  691.             } else {//01
  692.                 buf[*len-1] = IR_MARANTZ_BIT;
  693.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  694.                 *len = *len + 1;
  695.             }
  696.             previousBit = 1;
  697.         } else {
  698.             if (previousBit == 1){//10
  699.                 buf[*len-1] = IR_MARANTZ_BIT;
  700.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  701.                 *len = *len + 1;
  702.             } else {//00
  703.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  704.                 if (i==4){
  705.                     buf[*len+1] = IR_MARANTZ_HALF_BIT*5;
  706.                 } else {
  707.                     buf[*len+1] = IR_MARANTZ_HALF_BIT;
  708.                 }
  709.                
  710.                 *len = *len + 2;
  711.             }
  712.             previousBit = 0;
  713.         }
  714.     }
  715.     //make sure that we finish high by removing the last zero if needed
  716.     if (*len%2 == 0){
  717.         *len = *len - 1;
  718.     }
  719.  
  720.     proto->modfreq=IR_MARANTZ_F_MOD;
  721.     proto->timeout=IR_MARANTZ_TIMEOUT;
  722.     proto->repeats=IR_MARANTZ_REPS;
  723.     return IR_OK;
  724. }
  725.  
  726. #if (IR_PROTOCOLS_USE_PANASONIC)
  727. /**
  728.  * Test data on Panasonic protocol
  729.  *
  730.  * @param buf
  731.  *      Pointer to buffer to where to data to parse is stored
  732.  * @param len
  733.  *      Length of the data
  734.  * @param proto
  735.  *      Pointer to protocol information
  736.  * @return
  737.  *      IR_OK if data parsed successfully, one of several errormessages if not
  738.  */
  739. int8_t parsePanasonic(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  740.     /* parse buf[], max is len */
  741.  
  742.     /* check if we have correct amount of data */
  743.     if (len != 99) {
  744.         return IR_NOT_CORRECT_DATA;
  745.     }
  746.    
  747.     /* check startbit */
  748.     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) {
  749.         return IR_NOT_CORRECT_DATA;
  750.     }
  751.  
  752.     /* check pause after startbit */
  753.     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) {
  754.         return IR_NOT_CORRECT_DATA;
  755.     }
  756.  
  757.     uint32_t rawbits = 0;
  758.    
  759.     /* skip start bit, start bit pause and first 16 bits (32 values) */
  760.     for (uint8_t i = (3+16*2); i < len; i++) {
  761.         if ((i&1) == 1) {       /* if odd, ir-pause */
  762.             /* check length of pause between bits */
  763.             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) {
  764.                 /* write a one */
  765.                 rawbits |= 1UL<<((i-(3+16*2))>>1);
  766.             } 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) {
  767.                 /* do nothing, a zero is already in rawbits */
  768.             } else {
  769.                 return IR_NOT_CORRECT_DATA;
  770.             }
  771.         } else {            /* if even, ir-bit */
  772.             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) {
  773.                 return IR_NOT_CORRECT_DATA;
  774.             }
  775.         }
  776.     }
  777.    
  778.     proto->protocol=IR_PROTO_PANASONIC;
  779.     proto->timeout=IR_PANA_TIMEOUT;
  780.     proto->data=rawbits;   
  781.     return IR_OK;
  782. }
  783. #endif
  784.  
  785. /**
  786.  * Expand data from Panasonic protocol
  787.  *
  788.  * @param buf
  789.  *      Pointer to buffer to store the expanded data
  790.  * @param len
  791.  *      Pointer to length of the data
  792.  * @param proto
  793.  *      Pointer to protocol information
  794.  * @return
  795.  *      IR_OK if data expanded successfully, one of several errormessages if not
  796.  */
  797. int8_t expandPanasonic(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  798.     /* Set up startbit */
  799.     buf[0] = IR_PANA_ST_BIT;
  800.     buf[1] = IR_PANA_ST_PAUSE;
  801.    
  802.     /* add the first 16 static bits */
  803.     uint16_t staticBits = 0x2002;
  804.     for (uint8_t i = 0; i < 32; i++) {
  805.         if ((i&1) == 1) {       /* if odd, ir-pause */
  806.             if ((staticBits>>(i>>1))&1) {
  807.                 buf[i+2] = IR_PANA_LOW_ONE;
  808.             } else {
  809.                 buf[i+2] = IR_PANA_LOW_ZERO;
  810.             }
  811.         } else {                /* if even, ir-bit */
  812.             buf[i+2] = IR_PANA_HIGH;
  813.         }
  814.     }
  815.    
  816.     /* then add the value bits */
  817.     for (uint8_t i = 0; i < 65; i++) {
  818.         if ((i&1) == 1) {       /* if odd, ir-pause */
  819.             if ((proto->data>>(i>>1))&1) {
  820.                 buf[i+2+32] = IR_PANA_LOW_ONE;
  821.             } else {
  822.                 buf[i+2+32] = IR_PANA_LOW_ZERO;
  823.             }
  824.         } else {                /* if even, ir-bit */
  825.             buf[i+2+32] = IR_PANA_HIGH;
  826.         }
  827.     }
  828.    
  829.     *len = 99;
  830.    
  831.     proto->modfreq=IR_PANA_F_MOD;
  832.     proto->timeout=IR_PANA_TIMEOUT;
  833.     proto->repeats=IR_PANA_REPS;
  834.     return IR_OK;
  835. }
  836.  
  837. #if (IR_PROTOCOLS_USE_SKY)
  838. /**
  839.  * Test data on Sky protocol
  840.  *
  841.  *
  842.  * @param buf
  843.  *      Pointer to buffer to where to data to parse is stored
  844.  * @param len
  845.  *      Length of the data
  846.  * @param proto
  847.  *      Pointer to protocol information
  848.  * @return
  849.  *      IR_OK if data parsed successfully, one of several errormessages if not
  850.  */
  851. int8_t parseSky(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  852.     /* parse buf[], max is len */
  853.  
  854.     /* check startbit */
  855.     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) {
  856.         return IR_NOT_CORRECT_DATA;
  857.     }
  858.    
  859.     uint32_t rawbits=0;
  860.     uint8_t current=0;
  861.     uint8_t previous=0;
  862.     uint8_t cnt=0;
  863. #define SKYLONG 0
  864. #define SKYSHORT 1
  865.     for (uint8_t i = 1; i < len; i++)
  866.     {
  867.         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) {
  868.             current = SKYSHORT;
  869.         }
  870.         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) {
  871.             current = SKYLONG;
  872.         }
  873.         else {
  874.             return IR_NOT_CORRECT_DATA;
  875.         }
  876.        
  877.         /* if level is low */
  878.         if ((rawbits&1)==0) {
  879.             /* and there is a long pulse */
  880.             if (current == SKYLONG) {
  881.                 /* push a one */
  882.                 rawbits = rawbits<<1;
  883.                 rawbits |= 1;
  884.                 cnt = 0;
  885.             }
  886.             else if (cnt == 0) {
  887.                 cnt=1;
  888.                 /* push a zero */
  889.                 rawbits = rawbits<<1;
  890.                
  891.             }
  892.             else {
  893.                 cnt = 0;
  894.             }
  895.         }
  896.        
  897.         /* if level is high */
  898.         if ((rawbits&1)==1) {
  899.             /* and there is a long pulse */
  900.             if (current == SKYLONG) {
  901.                 /* push a zero */
  902.                 rawbits = rawbits<<1;
  903.                
  904.                 if (previous == SKYLONG) {
  905.                     cnt = 1;
  906.                 }
  907.                 else {
  908.                     cnt = 0;
  909.                 }
  910.             }
  911.             else if (cnt == 0) {
  912.                 cnt=1;
  913.                 /* push a one */
  914.                 rawbits = rawbits<<1;
  915.                 rawbits |= 1;
  916.             }
  917.             else {
  918.                 cnt = 0;
  919.             }
  920.         }
  921.        
  922.         previous=current;
  923.        
  924.     }
  925.    
  926.     proto->protocol = IR_PROTO_SKY;
  927.     proto->timeout = IR_SKY_TIMEOUT;
  928.     proto->data = rawbits;
  929.    
  930.     return IR_OK;
  931. }
  932. #endif
  933.  
  934. /**
  935.  * Expand data from Sky protocol
  936.  *
  937.  *
  938.  * @param buf
  939.  *      Pointer to buffer to store the expanded data
  940.  * @param len
  941.  *      Pointer to length of the data
  942.  * @param proto
  943.  *      Pointer to protocol information
  944.  * @return
  945.  *      IR_OK if data expanded successfully, one of several errormessages if not
  946.  */
  947. int8_t expandSky(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  948.     //TODO: Implement this function.
  949.     buf[0] = IR_SKY_ST_BIT;
  950.     buf[1] = IR_SKY_LONG;   //
  951.    
  952.    
  953.     return IR_NOT_CORRECT_DATA;
  954. }
  955.  
  956. #if (IR_PROTOCOLS_USE_NEXA2)
  957. /**
  958.  * Test data on NEXA protocol
  959.  * http://elektronikforumet.com/wiki/index.php?title=RF_Protokoll_-_Nexa_sj%C3%A4lvl%C3%A4rande
  960.  *
  961.  * @param buf
  962.  *      Pointer to buffer to where to data to parse is stored
  963.  * @param len
  964.  *      Length of the data
  965.  * @param proto
  966.  *      Pointer to protocol information
  967.  * @return
  968.  *      IR_OK if data parsed successfully, one of several errormessages if not
  969.  */
  970. int8_t parseNexa2(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  971.     /* parse buf[], max is len */
  972.  
  973.     /* check if we have correct amount of data */
  974.     if (len != 148 && len != 132) {
  975.         return IR_NOT_CORRECT_DATA;
  976.     }
  977.  
  978.     if (buf[0] < IR_NEXA2_START1 - IR_NEXA2_START1/IR_NEXA2_TOL_DIV && buf[0] > IR_NEXA2_START1 + IR_NEXA2_START1/IR_NEXA2_TOL_DIV) { //check start bit
  979.         return IR_NOT_CORRECT_DATA;
  980.     }
  981.     if (buf[1] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV && buf[1] > IR_NEXA2_HIGH + IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) { //check start bit
  982.         return IR_NOT_CORRECT_DATA;
  983.     }
  984.     if (buf[2] < IR_NEXA2_START2 - IR_NEXA2_START2/IR_NEXA2_TOL_DIV && buf[2] > IR_NEXA2_START2 + IR_NEXA2_START2/IR_NEXA2_TOL_DIV) { //check start bit
  985.         return IR_NOT_CORRECT_DATA;
  986.     }
  987.  
  988.     /* Incoming data could actually be longer than 32bits when a dimming command is received */
  989.     uint32_t rawbitsTemp = 0;
  990.     uint8_t bitCounter = 0;
  991.     for (uint8_t i = 3; i < len; i++) {
  992.         if ((i&1) == 0) {       /* if even, data */
  993.             /* check length of transmit pulse */
  994.             if (buf[i] > IR_NEXA2_LOW_ONE - IR_NEXA2_LOW_ONE/IR_NEXA2_TOL_DIV && buf[i] < IR_NEXA2_LOW_ONE + IR_NEXA2_LOW_ONE/IR_NEXA2_TOL_DIV) {
  995.                 /* write a one */
  996.                 rawbitsTemp |= (1UL)<<(bitCounter++);
  997.             } else if (buf[i] > IR_NEXA2_LOW_ZERO - IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV && buf[i] < IR_NEXA2_LOW_ZERO + IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV) {
  998.                 /* do nothing, a zero is already in rawbits */
  999.                 bitCounter++;
  1000.             } else {
  1001.                 return IR_NOT_CORRECT_DATA;
  1002.             }
  1003.             i+=2;   // skip every other bit, implement check here in the future
  1004.         } else {            /* if odd, no data */
  1005.             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) {
  1006.                 return IR_NOT_CORRECT_DATA;
  1007.             }
  1008.         }
  1009.     }
  1010.    
  1011. //gpio_set_pin(EXP_H);
  1012.    
  1013.     proto->protocol=IR_PROTO_NEXA2;
  1014.     proto->timeout=IR_NEXA2_TIMEOUT;
  1015.     proto->data=rawbitsTemp;
  1016.     return IR_OK;
  1017. }
  1018.  
  1019. #endif
  1020.  
  1021. /**
  1022.  * Expand data from Nexa2 protocol
  1023.  *
  1024.  *
  1025.  * @param buf
  1026.  *      Pointer to buffer to store the expanded data
  1027.  * @param len
  1028.  *      Pointer to length of the data
  1029.  * @param proto
  1030.  *      Pointer to protocol information
  1031.  * @return
  1032.  *      IR_OK if data expanded successfully, one of several errormessages if not
  1033.  */
  1034. int8_t expandNexa2(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  1035.     buf[0] = IR_NEXA2_START1;
  1036.     buf[1] = IR_NEXA2_HIGH;
  1037.     buf[2] = IR_NEXA2_START2;
  1038.    
  1039.     // TODO find out if dimmer value should be send, set different length, pad different
  1040.    
  1041.     return IR_NOT_CORRECT_DATA;
  1042. }
  1043.  
  1044.