Subversion Repositories HomeAutomation

Rev

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