Subversion Repositories HomeAutomation

Rev

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