Subversion Repositories HomeAutomation

Rev

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