Subversion Repositories HomeAutomation

Rev

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