Subversion Repositories HomeAutomation

Rev

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