Subversion Repositories HomeAutomation

Rev

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