Subversion Repositories HomeAutomation

Rev

Rev 734 | Rev 922 | 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.     buf[0] = IR_SIRC_ST_BIT;
  140.     buf[1] = IR_SIRC_LOW;//start pulse finished
  141.    
  142.    
  143.    
  144.     return IR_NOT_CORRECT_DATA;
  145. }
  146.  
  147.  
  148. #if (IR_PROTOCOLS_USE_RC5)
  149. /**
  150.  * Test data on RC5 protocol
  151.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  152.  *
  153.  * @param buf
  154.  *      Pointer to buffer to where to data to parse is stored
  155.  * @param len
  156.  *      Length of the data
  157.  * @param proto
  158.  *      Pointer to protocol information
  159.  * @return
  160.  *      IR_OK if data parsed successfully, one of several errormessages if not
  161.  */
  162. int8_t parseRC5(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  163.     uint8_t halfbitscnt = 1;
  164.     uint16_t rawbits = 0;
  165.    
  166.     for (uint8_t i = 0; i<len; i++) {
  167.         //halfbitscnt&1==1 in the middle of bits
  168.         //i&1==0 positive flank
  169.  
  170.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  171.             rawbits |= (1<<(13-(halfbitscnt>>1)));
  172.         }
  173.        
  174.         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) {
  175.             halfbitscnt += 1;
  176.         } 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) {
  177.             halfbitscnt += 2;
  178.         } else {
  179.             return IR_NOT_CORRECT_DATA;
  180.         }
  181.        
  182.     }
  183.  
  184.     proto->protocol=IR_PROTO_RC5;
  185.     proto->timeout=IR_RC5_TIMEOUT;
  186.     //support RC5-extended keeping second startbit
  187.     //remove togglebit
  188.     proto->data = rawbits&0x37ff; //This seems to be wrong? Does not invert second start bit and keeps first start bit
  189.     //proto->data = (rawbits&0x07ff) | ((~rawbits)&0x0100);
  190.  
  191.    
  192.     return IR_OK;
  193. }
  194. #endif
  195.  
  196. /**
  197.  * Expand data from RC5 protocol
  198.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  199.  *
  200.  * @param buf
  201.  *      Pointer to buffer to store the expanded data
  202.  * @param len
  203.  *      Pointer to length of the data
  204.  * @param proto
  205.  *      Pointer to protocol information
  206.  * @return
  207.  *      IR_OK if data expanded successfully, one of several errormessages if not
  208.  */
  209. int8_t expandRC5(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  210.     uint8_t tempadress;
  211.     uint8_t tempcommand;
  212.     uint8_t previousBit;
  213.     uint16_t tempdata;
  214.    
  215.     /* Set up startbit */
  216.     buf[0] = 0; // no start-one
  217.     buf[1] = IR_RC5_HALF_BIT;
  218.     buf[2] = IR_RC5_HALF_BIT;//first start bit
  219.     buf[3] = IR_RC5_HALF_BIT;
  220.     buf[4] = IR_RC5_HALF_BIT;//second start bit
  221.  
  222. #define Toggle 0 //TODO: Fix toggle in some proper way
  223.     if (Toggle==0){
  224.         buf[5] = IR_RC5_HALF_BIT;
  225.         buf[6] = IR_RC5_HALF_BIT; //toggle bit (yes i know it should not be hardcoded)
  226.         *len = 7;
  227.         previousBit = 1;
  228.     } else {
  229.         buf[4] = IR_RC5_BIT;
  230.         buf[5] = IR_RC5_HALF_BIT;
  231.         *len = 6;
  232.         previousBit = 0;
  233.     }
  234.            
  235.     //let's start with the adress bits..
  236.     tempcommand = proto->data&(0b00111111);
  237.     tempadress = (proto->data>>8)&(0b00011111);
  238.     //TODO: This requires massive cleanup
  239.    
  240.     //tempdata = ((((uint16_t)(proto->data)&(0x3F)) + ((uint16_t)((proto->data>>8)&(0x1F))<<6)))<<5;
  241.    
  242.     tempdata = (uint16_t)tempcommand + ((uint16_t)tempadress<<6);
  243.     tempdata = tempdata<<5;
  244.    
  245.     /*
  246.     for(uint8_t ijag t = 0; i < 11; i++) {
  247.         tempdata = tempdata<<1;
  248.         //temptemp = tempadress&0xA0;
  249.         if (((tempdata&(0xA000))>>15)==1){
  250.             if (previousBit == 1){//11
  251.                 buf[*len] = IR_RC5_HALF_BIT;
  252.                 buf[*len+1] = IR_RC5_HALF_BIT;
  253.                 *len = *len + 2;
  254.             } else {//01
  255.                 buf[*len-1] = IR_RC5_BIT;
  256.                 buf[*len] = IR_RC5_HALF_BIT;
  257.                 *len = *len + 1;
  258.             }
  259.             previousBit = 1;
  260.         } else {//10
  261.             if (previousBit == 1){
  262.                 buf[*len-1] = IR_RC5_BIT;
  263.                 buf[*len] = IR_RC5_HALF_BIT;
  264.                 *len = *len + 1;
  265.             } else {//00
  266.                 buf[*len] = IR_RC5_HALF_BIT;
  267.                 buf[*len+1] = IR_RC5_HALF_BIT;
  268.                 *len = *len + 2;
  269.             }
  270.             previousBit = 0;
  271.         }
  272.     }
  273.     */
  274.    
  275.     tempadress = tempadress<<2;
  276.    
  277.     for(uint8_t i = 0; i < 5; i++) {
  278.         tempadress = tempadress<<1;
  279.         //temptemp = tempadress&0xA0;
  280.         if (((tempadress&(0xA0))>>7)==1){
  281.             if (previousBit == 1){//11
  282.                 buf[*len] = IR_RC5_HALF_BIT;
  283.                 buf[*len+1] = IR_RC5_HALF_BIT;
  284.                 *len = *len + 2;
  285.             } else {//01
  286.                 buf[*len-1] = IR_RC5_BIT;
  287.                 buf[*len] = IR_RC5_HALF_BIT;
  288.                 *len = *len + 1;
  289.             }
  290.             previousBit = 1;
  291.         } else {//10
  292.             if (previousBit == 1){
  293.                 buf[*len-1] = IR_RC5_BIT;
  294.                 buf[*len] = IR_RC5_HALF_BIT;
  295.                 *len = *len + 1;
  296.             } else {//00
  297.                 buf[*len] = IR_RC5_HALF_BIT;
  298.                 buf[*len+1] = IR_RC5_HALF_BIT;
  299.                 *len = *len + 2;
  300.             }
  301.             previousBit = 0;
  302.         }
  303.     }
  304.    
  305.    
  306.     tempcommand = tempcommand << 1;
  307.    
  308.     for(uint8_t i = 0; i < 6; i++) {
  309.         tempcommand = tempcommand<<1;
  310.         //temptemp = tempadress&0xA0;
  311.         if (((tempcommand&(0xA0))>>7)==1){
  312.             if (previousBit == 1){//11
  313.                 buf[*len] = IR_RC5_HALF_BIT;
  314.                 buf[*len+1] = IR_RC5_HALF_BIT;
  315.                 *len = *len + 2;
  316.             } else {//01
  317.                 buf[*len-1] = IR_RC5_BIT;
  318.                 buf[*len] = IR_RC5_HALF_BIT;
  319.                 *len = *len + 1;
  320.             }
  321.             previousBit = 1;
  322.         } else {//10
  323.             if (previousBit == 1){
  324.                 buf[*len-1] = IR_RC5_BIT;
  325.                 buf[*len] = IR_RC5_HALF_BIT;
  326.                 *len = *len + 1;
  327.             } else {//00
  328.                 buf[*len] = IR_RC5_HALF_BIT;
  329.                 buf[*len+1] = IR_RC5_HALF_BIT;
  330.                 *len = *len + 2;
  331.             }
  332.             previousBit = 0;
  333.         }
  334.     }
  335.  
  336.     proto->modfreq=(((F_CPU/2000)/IR_RC5_F_MOD) -1);
  337.     proto->timeout=IR_RC5_TIMEOUT;
  338.     proto->repeats=IR_RC5_REPS;
  339.     return IR_OK;
  340. }
  341.  
  342.  
  343. #if (IR_PROTOCOLS_USE_SHARP)
  344. /**
  345.  * Test data on SHARP protocol
  346.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  347.  *
  348.  * @param buf
  349.  *      Pointer to buffer to where to data to parse is stored
  350.  * @param len
  351.  *      Length of the data
  352.  * @param proto
  353.  *      Pointer to protocol information
  354.  * @return
  355.  *      IR_OK if data parsed successfully, one of several errormessages if not
  356.  */
  357. int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  358.     /* parse buf[], max is len */
  359.  
  360.     /* check if we have correct amount of data */
  361.     if (len != 31) {
  362.         return IR_NOT_CORRECT_DATA;
  363.     }
  364.    
  365.     uint16_t rawbits=0;
  366.    
  367.     for (uint8_t i = 1; i < len; i++) {
  368.         if ((i&1) == 1) {       /* if odd, ir-pause */
  369.             /* check length of pause between bits */
  370.             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) {
  371.                 /* write a one */
  372.                 rawbits |= 1<<((i-1)>>1);
  373.             } 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) {
  374.                 /* do nothing, a zero is already in rawbits */
  375.             } else {
  376.                 return IR_NOT_CORRECT_DATA;
  377.             }
  378.         } else {            /* if even, ir-bit */
  379.             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) {
  380.                 return IR_NOT_CORRECT_DATA;
  381.             }
  382.         }
  383.     }
  384.    
  385.     proto->protocol=IR_PROTO_SHARP;
  386.     proto->timeout=IR_SHARP_TIMEOUT;
  387.     proto->data=rawbits;
  388.     return IR_OK;
  389. }
  390. #endif
  391.  
  392. /**
  393.  * Expand data from Sharp protocol
  394.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  395.  *
  396.  * @param buf
  397.  *      Pointer to buffer to store the expanded data
  398.  * @param len
  399.  *      Pointer to length of the data
  400.  * @param proto
  401.  *      Pointer to protocol information
  402.  * @return
  403.  *      IR_OK if data expanded successfully, one of several errormessages if not
  404.  */
  405. int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  406.     //TODO: Implement this function.
  407.     return IR_NOT_CORRECT_DATA;
  408. }
  409.  
  410.  
  411. #if (IR_PROTOCOLS_USE_NEC)
  412. /**
  413.  * Test data on NEC protocol
  414.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  415.  *
  416.  * @param buf
  417.  *      Pointer to buffer to where to data to parse is stored
  418.  * @param len
  419.  *      Length of the data
  420.  * @param proto
  421.  *      Pointer to protocol information
  422.  * @return
  423.  *      IR_OK if data parsed successfully, one of several errormessages if not
  424.  */
  425. int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  426.     /* parse buf[], max is len */
  427.  
  428.     /* check if we have correct amount of data */
  429.     if (len != 67) {
  430.         return IR_NOT_CORRECT_DATA;
  431.     }
  432.    
  433.     /* check startbit */
  434.     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) {
  435.         return IR_NOT_CORRECT_DATA;
  436.     }
  437.  
  438.     /* check pause after startbit */
  439.     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) {
  440.         return IR_NOT_CORRECT_DATA;
  441.     }
  442.  
  443.     uint32_t rawbits = 0;
  444.  
  445.     for (uint8_t i = 3; i < len; i++) {
  446.         if ((i&1) == 1) {       /* if odd, ir-pause */
  447.             /* check length of pause between bits */
  448.             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) {
  449.                 /* write a one */
  450.                 rawbits |= 1UL<<((i-3)>>1);
  451.             } 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) {
  452.                 /* do nothing, a zero is already in place */
  453.             } else {
  454.                 return IR_NOT_CORRECT_DATA;
  455.             }
  456.         } else {            /* if even, ir-bit */
  457.             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) {
  458.                 return IR_NOT_CORRECT_DATA;
  459.             }
  460.         }
  461.     }
  462.  
  463.     proto->protocol=IR_PROTO_NEC;
  464.     proto->timeout=IR_NEC_TIMEOUT;
  465.     proto->data=rawbits;   
  466.     return IR_OK;
  467. }
  468. #endif
  469.  
  470. /**
  471.  * Expand data from NEC protocol
  472.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  473.  *
  474.  * @param buf
  475.  *      Pointer to buffer to store the expanded data
  476.  * @param len
  477.  *      Pointer to length of the data
  478.  * @param proto
  479.  *      Pointer to protocol information
  480.  * @return
  481.  *      IR_OK if data expanded successfully, one of several errormessages if not
  482.  */
  483. int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  484.     /* Set up startbit */
  485.     buf[0] = IR_NEC_ST_BIT;
  486.    
  487.     if (proto->framecnt == 0) {
  488.         buf[1] = IR_NEC_ST_PAUSE;
  489.    
  490.         *len = 67;
  491.         for (uint8_t i = 0; i < 65; i++) {
  492.             if ((i&1) == 1) {       /* if odd, ir-pause */
  493.                 if ((proto->data>>(i>>1))&1) {
  494.                     buf[i+2] = IR_NEC_LOW_ONE;
  495.                 } else {
  496.                     buf[i+2] = IR_NEC_LOW_ZERO;
  497.                 }
  498.             } else {            /* if even, ir-bit */
  499.                 buf[i+2] = IR_NEC_HIGH;
  500.             }
  501.         }
  502.         proto->timeout=IR_NEC_TIMEOUT;
  503.     } else {
  504.         buf[1] = IR_NEC_ST_PAUSE/2;
  505.         buf[2] = IR_NEC_HIGH;
  506.         proto->timeout=IR_NEC_ST_TIMEOUT;
  507.         *len = 3;
  508.     }
  509.     proto->modfreq=(((F_CPU/2000)/IR_NEC_F_MOD) -1);
  510.     proto->repeats=IR_NEC_REPS;
  511.     return IR_OK;
  512. }
  513.  
  514.  
  515. #if (IR_PROTOCOLS_USE_SAMSUNG)
  516. /**
  517.  * Test data on Samsung protocol
  518.  * Very much like NEC, different start bit/pause lengths etc.
  519.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  520.  *
  521.  * @param buf
  522.  *      Pointer to buffer to where to data to parse is stored
  523.  * @param len
  524.  *      Length of the data
  525.  * @param proto
  526.  *      Pointer to protocol information
  527.  * @return
  528.  *      IR_OK if data parsed successfully, one of several errormessages if not
  529.  */
  530. int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  531.     /* parse buf[], max is len */
  532.  
  533.     /* check if we have correct amount of data */
  534.     if (len != 67) {
  535.         return IR_NOT_CORRECT_DATA;
  536.     }
  537.    
  538.     /* check startbit */
  539.     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) {
  540.         return IR_NOT_CORRECT_DATA;
  541.     }
  542.  
  543.     /* check pause after startbit */
  544.     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) {
  545.         return IR_NOT_CORRECT_DATA;
  546.     }
  547.  
  548.     uint32_t rawbits = 0;
  549.    
  550.     for (uint8_t i = 3; i < len; i++) {
  551.         if ((i&1) == 1) {       /* if odd, ir-pause */
  552.             /* check length of pause between bits */
  553.             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) {
  554.                 /* write a one */
  555.                 rawbits |= 1UL<<((i-3)>>1);
  556.             } 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) {
  557.                 /* do nothing, a zero is already in rawbits */
  558.             } else {
  559.                 return IR_NOT_CORRECT_DATA;
  560.             }
  561.         } else {            /* if even, ir-bit */
  562.             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) {
  563.                 return IR_NOT_CORRECT_DATA;
  564.             }
  565.         }
  566.     }
  567.    
  568.     proto->protocol=IR_PROTO_SAMS;
  569.     proto->timeout=IR_SAMS_TIMEOUT;
  570.     proto->data=rawbits;   
  571.     return IR_OK;
  572. }
  573. #endif
  574.  
  575. /**
  576.  * Expand data from Samsung protocol
  577.  * Very much like NEC, different start bit/pause lengths etc.
  578.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  579.  *
  580.  * @param buf
  581.  *      Pointer to buffer to store the expanded data
  582.  * @param len
  583.  *      Pointer to length of the data
  584.  * @param proto
  585.  *      Pointer to protocol information
  586.  * @return
  587.  *      IR_OK if data expanded successfully, one of several errormessages if not
  588.  */
  589. int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  590.     /* Set up startbit */
  591.     buf[0] = IR_SAMS_ST_BIT;
  592.     buf[1] = IR_SAMS_ST_PAUSE;
  593.    
  594.     for (uint8_t i = 0; i < 65; i++) {
  595.         if ((i&1) == 1) {       /* if odd, ir-pause */
  596.             if ((proto->data>>(i>>1))&1) {
  597.                 buf[i+2] = IR_SAMS_LOW_ONE;
  598.             } else {
  599.                 buf[i+2] = IR_SAMS_LOW_ZERO;
  600.             }
  601.         } else {                /* if even, ir-bit */
  602.             buf[i+2] = IR_SAMS_HIGH;
  603.         }
  604.     }
  605.    
  606.     *len = 67;
  607.    
  608.     proto->modfreq=(((F_CPU/2000)/IR_SAMS_F_MOD) -1);
  609.     proto->timeout=IR_SAMS_TIMEOUT;
  610.     proto->repeats=IR_SAMS_REPS;
  611.     return IR_OK;
  612. }
  613.  
  614. #if (IR_PROTOCOLS_USE_MARANTZ)
  615. /**
  616.  * Test data on Marantz protocol
  617.  * Reverse-Engineered by Noddan, very similar to RC-5.
  618.  * Not tested with odd adresses since I have no remote that sends them.
  619.  * Don't know what happens with the extra long bit in that case.
  620.  *
  621.  * @param buf
  622.  *      Pointer to buffer to where to data to parse is stored
  623.  * @param len
  624.  *      Length of the data
  625.  * @param proto
  626.  *      Pointer to protocol information
  627.  * @return
  628.  *      IR_OK if data parsed successfully, one of several errormessages if not
  629.  */
  630. int8_t parseMarantz(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  631.     uint8_t halfbitscnt = 1;
  632.     uint32_t rawbits = 0;
  633.    
  634.     for (uint8_t i = 0; i<len; i++) {
  635.         //halfbitscnt&1==1 in the middle of bits
  636.         //i&1==0 positive flank
  637.  
  638.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  639.             rawbits |= (uint32_t)1<<(19-(halfbitscnt>>1));
  640.         }
  641.        
  642.         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) {
  643.             halfbitscnt += 1;
  644.         } 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) {
  645.             halfbitscnt += 2;
  646.         } 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) {
  647.             halfbitscnt += 1; //It seems to work, not entirely sure of the purpose of this long zero though.
  648.         } else {
  649.             return IR_NOT_CORRECT_DATA;
  650.         }
  651.        
  652.     }
  653.    
  654.     proto->protocol=IR_PROTO_MARANTZ;
  655.     proto->timeout=IR_MARANTZ_TIMEOUT;
  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_MARANTZ_HALF_BIT;//first start bit
  679.     buf[1] = IR_MARANTZ_HALF_BIT;
  680.     buf[2] = IR_MARANTZ_HALF_BIT;//second start bit
  681.     //TODO: Toggle bit should be better, not hard-coded
  682.     buf[3] = IR_MARANTZ_HALF_BIT;
  683.     buf[4] = IR_MARANTZ_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_MARANTZ_HALF_BIT;
  695.                 buf[*len+1] = IR_MARANTZ_HALF_BIT;
  696.                 *len = *len + 2;
  697.             } else {//01
  698.                 buf[*len-1] = IR_MARANTZ_BIT;
  699.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  700.                 *len = *len + 1;
  701.             }
  702.             previousBit = 1;
  703.         } else {
  704.             if (previousBit == 1){//10
  705.                 buf[*len-1] = IR_MARANTZ_BIT;
  706.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  707.                 *len = *len + 1;
  708.             } else {//00
  709.                 buf[*len] = IR_MARANTZ_HALF_BIT;
  710.                 if (i==4){
  711.                     buf[*len+1] = IR_MARANTZ_HALF_BIT*5;
  712.                 } else {
  713.                     buf[*len+1] = IR_MARANTZ_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_MARANTZ_F_MOD) -1);
  727.     proto->timeout=IR_MARANTZ_TIMEOUT;
  728.     proto->repeats=IR_MARANTZ_REPS;
  729.     return IR_OK;
  730. }
  731.  
  732.  
  733. #endif
  734.