Subversion Repositories HomeAutomation

Rev

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