Subversion Repositories HomeAutomation

Rev

Rev 1874 | Rev 1904 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

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