Subversion Repositories HomeAutomation

Rev

Rev 617 | Rev 733 | 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
  7.  *  
  8.  */
  9.  
  10. #include <bios.h> //FIXME: Ta bort mig, jag finns bara fšr debug av noddans RC6
  11.  
  12. #include "protocols.h"
  13.  
  14. int8_t parseProtocol(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  15.     proto->protocol=IR_PROTO_UNKNOWN;
  16.     proto->data=0;
  17.     proto->timeout=100;
  18.     /* Try all protocols in order. */
  19. #if (IR_PROTOCOLS_USE_SIRC)
  20.     if (parseSIRC(buf, len, proto)==IR_OK) return IR_OK;
  21. #endif
  22. #if (IR_PROTOCOLS_USE_RC5)
  23.     if (parseRC5(buf, len, proto)==IR_OK) return IR_OK;
  24. #endif
  25. #if (IR_PROTOCOLS_USE_SHARP)
  26.     if (parseSharp(buf, len, proto)==IR_OK) return IR_OK;
  27. #endif
  28. #if (IR_PROTOCOLS_USE_NEC)
  29.     if (parseNEC(buf, len, proto)==IR_OK) return IR_OK;
  30. #endif
  31. #if (IR_PROTOCOLS_USE_SAMSUNG)
  32.     if (parseSamsung(buf, len, proto)==IR_OK) return IR_OK;
  33. #endif
  34.     /* No protocol matched. */
  35.     proto->protocol = IR_PROTO_UNKNOWN;
  36.     return IR_NOT_CORRECT_DATA;
  37. }
  38.  
  39. int8_t parseHash(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  40.     //TODO: Transform the buffer in some clever way to a 32 bit word. */
  41.     proto->protocol = IR_PROTO_HASH;
  42.     proto->timeout = 200;
  43.     proto->data = 0;
  44.    
  45.     return 0;
  46. }
  47.  
  48. int8_t expandProtocol(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  49.     /* Call the expand function for the specified protocol. */
  50.     switch (proto->protocol) {
  51.     case IR_PROTO_SIRC:
  52.         return expandSIRC(buf, len, proto);
  53.     case IR_PROTO_RC5:
  54.         return expandRC5(buf, len, proto);
  55.     case IR_PROTO_SHARP:
  56.         return expandSharp(buf, len, proto);
  57.     case IR_PROTO_NEC:
  58.         return expandNEC(buf, len, proto);
  59.     case IR_PROTO_SAMS:
  60.         return expandSamsung(buf, len, proto);
  61.     }
  62.     /* Invalid protocol specified. */
  63.     return IR_NOT_CORRECT_DATA;
  64. }
  65.  
  66. #if (IR_PROTOCOLS_USE_SIRC)
  67. /**
  68.  * Test data on SIRC protocol, 12-bit version
  69.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  70.  *
  71.  * @param buf
  72.  *      Pointer to buffer to where to data to parse is stored
  73.  * @param len
  74.  *      Length of the data
  75.  * @param proto
  76.  *      Pointer to protocol information
  77.  * @return
  78.  *      IR_OK if data parsed successfully, one of several errormessages if not
  79.  */
  80. int8_t parseSIRC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  81.     /* parse buf[], max is len */
  82.  
  83.     /* check if we have correct amount of data */
  84.     if (len != 25) {
  85.         return IR_NOT_CORRECT_DATA;
  86.     }
  87.    
  88.     /* check startbit */
  89.     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) {
  90.         return IR_NOT_CORRECT_DATA;
  91.     }
  92.    
  93.     uint16_t rawbits=0;
  94.    
  95.     for (uint8_t i = 1; i < len; i++) {
  96.         if ((i&1) == 1) {       /* if odd, ir-pause */
  97.             /* check length of pause between bits */
  98.             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) {
  99.                 return IR_NOT_CORRECT_DATA;
  100.             }
  101.         } else {            /* if even, ir-bit */
  102.             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) {
  103.                 /* write a one */
  104.                 rawbits |= 1<<((i-2)>>1);
  105.             } 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) {
  106.                 /* do nothing, a zero is already in rawbits */
  107.             } else {
  108.                 return IR_NOT_CORRECT_DATA;
  109.             }
  110.         }
  111.     }
  112.    
  113.     proto->protocol = IR_PROTO_SIRC;
  114.     proto->timeout = IR_SIRC_TIMEOUT;
  115.     proto->data = rawbits;
  116.    
  117.     return IR_OK;
  118. }
  119. #endif
  120.  
  121. /**
  122.  * Expand data from SIRC protocol
  123.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  124.  *
  125.  * @param buf
  126.  *      Pointer to buffer to store the expanded data
  127.  * @param len
  128.  *      Pointer to length of the data
  129.  * @param proto
  130.  *      Pointer to protocol information
  131.  * @return
  132.  *      IR_OK if data expanded successfully, one of several errormessages if not
  133.  */
  134. int8_t expandSIRC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  135.     //TODO: Implement this function.
  136.     return IR_NOT_CORRECT_DATA;
  137. }
  138.  
  139.  
  140. #if (IR_PROTOCOLS_USE_RC5)
  141. /**
  142.  * Test data on RC5 protocol
  143.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  144.  *
  145.  * @param buf
  146.  *      Pointer to buffer to where to data to parse is stored
  147.  * @param len
  148.  *      Length of the data
  149.  * @param proto
  150.  *      Pointer to protocol information
  151.  * @return
  152.  *      IR_OK if data parsed successfully, one of several errormessages if not
  153.  */
  154. int8_t parseRC5(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  155.     uint8_t halfbitscnt = 1;
  156.     uint16_t rawbits = 0;
  157.    
  158.     for (uint8_t i = 0; i<len; i++) {
  159.         //halfbitscnt&1==1 in the middle of bits
  160.         //i&1==0 positive flank
  161.  
  162.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  163.             rawbits |= (1<<(13-(halfbitscnt>>1)));
  164.         }
  165.        
  166.         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) {
  167.             halfbitscnt += 1;
  168.         } 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) {
  169.             halfbitscnt += 2;
  170.         } else {
  171.             return IR_NOT_CORRECT_DATA;
  172.         }
  173.        
  174.     }
  175.  
  176.     proto->protocol=IR_PROTO_RC5;
  177.     proto->timeout=IR_RC5_TIMEOUT;
  178.     //support RC5-extended keeping second startbit
  179.     //remove togglebit
  180.     proto->data = rawbits&0x37ff;
  181.  
  182.    
  183.     return IR_OK;
  184. }
  185. #endif
  186.  
  187. /**
  188.  * Expand data from RC5 protocol
  189.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  190.  *
  191.  * @param buf
  192.  *      Pointer to buffer to store the expanded data
  193.  * @param len
  194.  *      Pointer to length of the data
  195.  * @param proto
  196.  *      Pointer to protocol information
  197.  * @return
  198.  *      IR_OK if data expanded successfully, one of several errormessages if not
  199.  */
  200. int8_t expandRC5(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  201.     uint8_t tempadress;
  202.     uint8_t tempcommand;
  203.     uint8_t previousBit;
  204.    
  205.     //TODO: Implement this function. Martin testar!
  206.     /* Set up startbit */
  207.     buf[0] = 0; // no start-one
  208.     buf[1] = IR_RC5_HALF_BIT;
  209.     buf[2] = IR_RC5_HALF_BIT;//first start bit
  210.     buf[3] = IR_RC5_HALF_BIT;
  211.     buf[4] = IR_RC5_HALF_BIT;//second start bit
  212.  
  213. #define Toggle 0 //TODO: Fix toggle in some proper way
  214.     if (Toggle==0){
  215.         buf[5] = IR_RC5_HALF_BIT;
  216.         buf[6] = IR_RC5_HALF_BIT; //toggle bit (yes i know it should not be hardcoded)
  217.         *len = 7;
  218.     } else {
  219.         buf[4] = IR_RC5_BIT;
  220.         buf[5] = IR_RC5_HALF_BIT;
  221.         *len = 6;
  222.     }
  223.        
  224.    
  225.     previousBit = 1;
  226.    
  227.     //let's start with the adress bits..
  228.     tempadress = (proto->data>>8)&(0b00011111);
  229.     tempcommand = proto->data&(0b00111111);
  230.    
  231.  
  232.     Can_Message_t txMsg;
  233.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
  234.     txMsg.DataLength = 5;
  235.     txMsg.RemoteFlag = 0;
  236.     txMsg.ExtendedFlag = 1;
  237.     txMsg.Data.words[0] = tempadress;
  238.     //txMsg.Data.words[1] = tempcommand;
  239.     //txMsg.Data.words[2] = *len+3;
  240.     //BIOS_CanSend(&txMsg);
  241.    
  242.     tempadress = tempadress<<2;
  243.    
  244.     for(uint8_t i = 0; i < 5; i++) {
  245.         tempadress = tempadress<<1;
  246.         //temptemp = tempadress&0xA0;
  247.         if (((tempadress&(0xA0))>>7)==1){
  248.             if (previousBit == 1){//11
  249.                 buf[*len] = IR_RC5_HALF_BIT;
  250.                 buf[*len+1] = IR_RC5_HALF_BIT;
  251.                 *len = *len + 2;
  252.             } else {//01
  253.                 buf[*len-1] = IR_RC5_BIT;
  254.                 buf[*len] = IR_RC5_HALF_BIT;
  255.                 *len = *len + 1;
  256.             }
  257.             previousBit = 1;
  258.         } else {//10
  259.             if (previousBit == 1){
  260.                 buf[*len-1] = IR_RC5_BIT;
  261.                 buf[*len] = IR_RC5_HALF_BIT;
  262.                 *len = *len + 1;
  263.             } else {//00
  264.                 buf[*len] = IR_RC5_HALF_BIT;
  265.                 buf[*len+1] = IR_RC5_HALF_BIT;
  266.                 *len = *len + 2;
  267.             }
  268.             previousBit = 0;
  269.         }
  270.     }
  271.    
  272.     txMsg.DataLength = 6;
  273.    
  274.     tempcommand = tempcommand << 1;
  275.    
  276.     for(uint8_t i = 0; i < 6; i++) {
  277.         tempcommand = tempcommand<<1;
  278.         //temptemp = tempadress&0xA0;
  279.         if (((tempcommand&(0xA0))>>7)==1){
  280.             if (previousBit == 1){//11
  281.                 buf[*len] = IR_RC5_HALF_BIT;
  282.                 buf[*len+1] = IR_RC5_HALF_BIT;
  283.                 *len = *len + 2;
  284.             } else {//01
  285.                 buf[*len-1] = IR_RC5_BIT;
  286.                 buf[*len] = IR_RC5_HALF_BIT;
  287.                 *len = *len + 1;
  288.             }
  289.             previousBit = 1;
  290.         } else {//10
  291.             if (previousBit == 1){
  292.                 buf[*len-1] = IR_RC5_BIT;
  293.                 buf[*len] = IR_RC5_HALF_BIT;
  294.                 *len = *len + 1;
  295.             } else {//00
  296.                 buf[*len] = IR_RC5_HALF_BIT;
  297.                 buf[*len+1] = IR_RC5_HALF_BIT;
  298.                 *len = *len + 2;
  299.             }
  300.             previousBit = 0;
  301.         }
  302.     }
  303.  
  304.     /*
  305.     //time for the command then!
  306.     for(uint8_t i = 0; i < 6; i++) {
  307.         tempcommand = tempcommand << 1;
  308.         if (((tempcommand&0xA0)>>7)==1){
  309.             buf[*len] = 3; //zero at the start
  310.             buf[*len+1] = IR_RC5_HALF_BIT; //keep it low
  311.             buf[*len+2] = IR_RC5_HALF_BIT; //and then, make it high
  312.             buf[*len+3] = 3; //and then we waste another cycle low to get in sync
  313.             *len = *len + 4;
  314.         } else {
  315.             buf[*len] = IR_RC5_HALF_BIT;
  316.             buf[*len+1] = IR_RC5_HALF_BIT;
  317.             *len = *len + 2;
  318.         }
  319.        
  320.     }  
  321.     */
  322.     proto->modfreq=(((F_CPU/2000)/IR_RC5_F_MOD) -1);
  323.     proto->timeout=IR_RC5_TIMEOUT;
  324.     proto->repeats=IR_RC5_REPS;
  325.     return IR_OK;
  326.     //return IR_NOT_CORRECT_DATA;
  327. }
  328.  
  329.  
  330. #if (IR_PROTOCOLS_USE_SHARP)
  331. /**
  332.  * Test data on SHARP protocol
  333.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  334.  *
  335.  * @param buf
  336.  *      Pointer to buffer to where to data to parse is stored
  337.  * @param len
  338.  *      Length of the data
  339.  * @param proto
  340.  *      Pointer to protocol information
  341.  * @return
  342.  *      IR_OK if data parsed successfully, one of several errormessages if not
  343.  */
  344. int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  345.     /* parse buf[], max is len */
  346.  
  347.     /* check if we have correct amount of data */
  348.     if (len != 31) {
  349.         return IR_NOT_CORRECT_DATA;
  350.     }
  351.    
  352.     uint16_t rawbits=0;
  353.    
  354.     for (uint8_t i = 1; i < len; i++) {
  355.         if ((i&1) == 1) {       /* if odd, ir-pause */
  356.             /* check length of pause between bits */
  357.             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) {
  358.                 /* write a one */
  359.                 rawbits |= 1<<((i-1)>>1);
  360.             } 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) {
  361.                 /* do nothing, a zero is already in rawbits */
  362.             } else {
  363.                 return IR_NOT_CORRECT_DATA;
  364.             }
  365.         } else {            /* if even, ir-bit */
  366.             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) {
  367.                 return IR_NOT_CORRECT_DATA;
  368.             }
  369.         }
  370.     }
  371.    
  372.     proto->protocol=IR_PROTO_SHARP;
  373.     proto->timeout=IR_SHARP_TIMEOUT;
  374.     proto->data=rawbits;
  375.     return IR_OK;
  376. }
  377. #endif
  378.  
  379. /**
  380.  * Expand data from Sharp protocol
  381.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  382.  *
  383.  * @param buf
  384.  *      Pointer to buffer to store the expanded data
  385.  * @param len
  386.  *      Pointer to length of the data
  387.  * @param proto
  388.  *      Pointer to protocol information
  389.  * @return
  390.  *      IR_OK if data expanded successfully, one of several errormessages if not
  391.  */
  392. int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  393.     //TODO: Implement this function.
  394.     return IR_NOT_CORRECT_DATA;
  395. }
  396.  
  397.  
  398. #if (IR_PROTOCOLS_USE_NEC)
  399. /**
  400.  * Test data on NEC protocol
  401.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  402.  *
  403.  * @param buf
  404.  *      Pointer to buffer to where to data to parse is stored
  405.  * @param len
  406.  *      Length of the data
  407.  * @param proto
  408.  *      Pointer to protocol information
  409.  * @return
  410.  *      IR_OK if data parsed successfully, one of several errormessages if not
  411.  */
  412. int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  413.     /* parse buf[], max is len */
  414.  
  415.     /* check if we have correct amount of data */
  416.     if (len != 67) {
  417.         return IR_NOT_CORRECT_DATA;
  418.     }
  419.    
  420.     /* check startbit */
  421.     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) {
  422.         return IR_NOT_CORRECT_DATA;
  423.     }
  424.  
  425.     /* check pause after startbit */
  426.     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) {
  427.         return IR_NOT_CORRECT_DATA;
  428.     }
  429.  
  430.     uint32_t rawbits = 0;
  431.  
  432.     for (uint8_t i = 3; i < len; i++) {
  433.         if ((i&1) == 1) {       /* if odd, ir-pause */
  434.             /* check length of pause between bits */
  435.             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) {
  436.                 /* write a one */
  437.                 rawbits |= 1UL<<((i-3)>>1);
  438.             } 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) {
  439.                 /* do nothing, a zero is already in place */
  440.             } else {
  441.                 return IR_NOT_CORRECT_DATA;
  442.             }
  443.         } else {            /* if even, ir-bit */
  444.             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) {
  445.                 return IR_NOT_CORRECT_DATA;
  446.             }
  447.         }
  448.     }
  449.  
  450.     proto->protocol=IR_PROTO_NEC;
  451.     proto->timeout=IR_NEC_TIMEOUT;
  452.     proto->data=rawbits;   
  453.     return IR_OK;
  454. }
  455. #endif
  456.  
  457. /**
  458.  * Expand data from NEC protocol
  459.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  460.  *
  461.  * @param buf
  462.  *      Pointer to buffer to store the expanded data
  463.  * @param len
  464.  *      Pointer to length of the data
  465.  * @param proto
  466.  *      Pointer to protocol information
  467.  * @return
  468.  *      IR_OK if data expanded successfully, one of several errormessages if not
  469.  */
  470. int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  471.     /* Set up startbit */
  472.     buf[0] = IR_NEC_ST_BIT;
  473.    
  474.     if (proto->framecnt == 0) {
  475.         buf[1] = IR_NEC_ST_PAUSE;
  476.    
  477.         *len = 67;
  478.         for (uint8_t i = 0; i < 65; i++) {
  479.             if ((i&1) == 1) {       /* if odd, ir-pause */
  480.                 if ((proto->data>>(i>>1))&1) {
  481.                     buf[i+2] = IR_NEC_LOW_ONE;
  482.                 } else {
  483.                     buf[i+2] = IR_NEC_LOW_ZERO;
  484.                 }
  485.             } else {            /* if even, ir-bit */
  486.                 buf[i+2] = IR_NEC_HIGH;
  487.             }
  488.         }
  489.         proto->timeout=IR_NEC_TIMEOUT;
  490.     } else {
  491.         buf[1] = IR_NEC_ST_PAUSE/2;
  492.         buf[2] = IR_NEC_HIGH;
  493.         proto->timeout=IR_NEC_ST_TIMEOUT;
  494.         *len = 3;
  495.     }
  496.     proto->modfreq=(((F_CPU/2000)/IR_NEC_F_MOD) -1);
  497.     proto->repeats=IR_NEC_REPS;
  498.     return IR_OK;
  499. }
  500.  
  501.  
  502. #if (IR_PROTOCOLS_USE_SAMSUNG)
  503. /**
  504.  * Test data on Samsung protocol
  505.  * Very much like NEC, different start bit/pause lengths etc.
  506.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  507.  *
  508.  * @param buf
  509.  *      Pointer to buffer to where to data to parse is stored
  510.  * @param len
  511.  *      Length of the data
  512.  * @param proto
  513.  *      Pointer to protocol information
  514.  * @return
  515.  *      IR_OK if data parsed successfully, one of several errormessages if not
  516.  */
  517. int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  518.     /* parse buf[], max is len */
  519.  
  520.     /* check if we have correct amount of data */
  521.     if (len != 67) {
  522.         return IR_NOT_CORRECT_DATA;
  523.     }
  524.    
  525.     /* check startbit */
  526.     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) {
  527.         return IR_NOT_CORRECT_DATA;
  528.     }
  529.  
  530.     /* check pause after startbit */
  531.     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) {
  532.         return IR_NOT_CORRECT_DATA;
  533.     }
  534.  
  535.     uint32_t rawbits = 0;
  536.    
  537.     for (uint8_t i = 3; i < len; i++) {
  538.         if ((i&1) == 1) {       /* if odd, ir-pause */
  539.             /* check length of pause between bits */
  540.             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) {
  541.                 /* write a one */
  542.                 rawbits |= 1UL<<((i-3)>>1);
  543.             } 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) {
  544.                 /* do nothing, a zero is already in rawbits */
  545.             } else {
  546.                 return IR_NOT_CORRECT_DATA;
  547.             }
  548.         } else {            /* if even, ir-bit */
  549.             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) {
  550.                 return IR_NOT_CORRECT_DATA;
  551.             }
  552.         }
  553.     }
  554.    
  555.     proto->protocol=IR_PROTO_SAMS;
  556.     proto->timeout=IR_SAMS_TIMEOUT;
  557.     proto->data=rawbits;   
  558.     return IR_OK;
  559. }
  560. #endif
  561.  
  562. /**
  563.  * Expand data from Samsung protocol
  564.  * Very much like NEC, different start bit/pause lengths etc.
  565.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  566.  *
  567.  * @param buf
  568.  *      Pointer to buffer to store the expanded data
  569.  * @param len
  570.  *      Pointer to length of the data
  571.  * @param proto
  572.  *      Pointer to protocol information
  573.  * @return
  574.  *      IR_OK if data expanded successfully, one of several errormessages if not
  575.  */
  576. int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  577.     /* Set up startbit */
  578.     buf[0] = IR_SAMS_ST_BIT;
  579.     buf[1] = IR_SAMS_ST_PAUSE;
  580.    
  581.     for (uint8_t i = 0; i < 65; i++) {
  582.         if ((i&1) == 1) {       /* if odd, ir-pause */
  583.             if ((proto->data>>(i>>1))&1) {
  584.                 buf[i+2] = IR_SAMS_LOW_ONE;
  585.             } else {
  586.                 buf[i+2] = IR_SAMS_LOW_ZERO;
  587.             }
  588.         } else {                /* if even, ir-bit */
  589.             buf[i+2] = IR_SAMS_HIGH;
  590.         }
  591.     }
  592.    
  593.     *len = 67;
  594.    
  595.     proto->modfreq=(((F_CPU/2000)/IR_SAMS_F_MOD) -1);
  596.     proto->timeout=IR_SAMS_TIMEOUT;
  597.     proto->repeats=IR_SAMS_REPS;
  598.     return IR_OK;
  599. }
  600.