Subversion Repositories HomeAutomation

Rev

Rev 727 | 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 "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.     //TODO: Implement this function. Martin testar!
  211.     /* Set up startbit */
  212.     buf[0] = 0; // no start-one
  213.     buf[1] = IR_RC5_HALF_BIT;
  214.     buf[2] = IR_RC5_HALF_BIT;//first start bit
  215.     buf[3] = IR_RC5_HALF_BIT;
  216.     buf[4] = IR_RC5_HALF_BIT;//second start bit
  217.  
  218. #define Toggle 0 //TODO: Fix toggle in some proper way
  219.     if (Toggle==0){
  220.         buf[5] = IR_RC5_HALF_BIT;
  221.         buf[6] = IR_RC5_HALF_BIT; //toggle bit (yes i know it should not be hardcoded)
  222.         *len = 7;
  223.         previousBit = 1;
  224.     } else {
  225.         buf[4] = IR_RC5_BIT;
  226.         buf[5] = IR_RC5_HALF_BIT;
  227.         *len = 6;
  228.         previousBit = 0;
  229.     }
  230.            
  231.     //let's start with the adress bits..
  232.     tempcommand = proto->data&(0b00111111);
  233.     tempadress = (proto->data>>8)&(0b00011111);
  234.    
  235.    
  236.     //tempdata = ((((uint16_t)(proto->data)&(0x3F)) + ((uint16_t)((proto->data>>8)&(0x1F))<<6)))<<5;
  237.    
  238.     tempdata = (uint16_t)tempcommand + ((uint16_t)tempadress<<6);
  239.     tempdata = tempdata<<5;
  240.    
  241.     /*
  242.     for(uint8_t ijag t = 0; i < 11; i++) {
  243.         tempdata = tempdata<<1;
  244.         //temptemp = tempadress&0xA0;
  245.         if (((tempdata&(0xA000))>>15)==1){
  246.             if (previousBit == 1){//11
  247.                 buf[*len] = IR_RC5_HALF_BIT;
  248.                 buf[*len+1] = IR_RC5_HALF_BIT;
  249.                 *len = *len + 2;
  250.             } else {//01
  251.                 buf[*len-1] = IR_RC5_BIT;
  252.                 buf[*len] = IR_RC5_HALF_BIT;
  253.                 *len = *len + 1;
  254.             }
  255.             previousBit = 1;
  256.         } else {//10
  257.             if (previousBit == 1){
  258.                 buf[*len-1] = IR_RC5_BIT;
  259.                 buf[*len] = IR_RC5_HALF_BIT;
  260.                 *len = *len + 1;
  261.             } else {//00
  262.                 buf[*len] = IR_RC5_HALF_BIT;
  263.                 buf[*len+1] = IR_RC5_HALF_BIT;
  264.                 *len = *len + 2;
  265.             }
  266.             previousBit = 0;
  267.         }
  268.     }
  269.     */
  270.    
  271.     tempadress = tempadress<<2;
  272.    
  273.     for(uint8_t i = 0; i < 5; i++) {
  274.         tempadress = tempadress<<1;
  275.         //temptemp = tempadress&0xA0;
  276.         if (((tempadress&(0xA0))>>7)==1){
  277.             if (previousBit == 1){//11
  278.                 buf[*len] = IR_RC5_HALF_BIT;
  279.                 buf[*len+1] = IR_RC5_HALF_BIT;
  280.                 *len = *len + 2;
  281.             } else {//01
  282.                 buf[*len-1] = IR_RC5_BIT;
  283.                 buf[*len] = IR_RC5_HALF_BIT;
  284.                 *len = *len + 1;
  285.             }
  286.             previousBit = 1;
  287.         } else {//10
  288.             if (previousBit == 1){
  289.                 buf[*len-1] = IR_RC5_BIT;
  290.                 buf[*len] = IR_RC5_HALF_BIT;
  291.                 *len = *len + 1;
  292.             } else {//00
  293.                 buf[*len] = IR_RC5_HALF_BIT;
  294.                 buf[*len+1] = IR_RC5_HALF_BIT;
  295.                 *len = *len + 2;
  296.             }
  297.             previousBit = 0;
  298.         }
  299.     }
  300.    
  301.    
  302.     tempcommand = tempcommand << 1;
  303.    
  304.     for(uint8_t i = 0; i < 6; i++) {
  305.         tempcommand = tempcommand<<1;
  306.         //temptemp = tempadress&0xA0;
  307.         if (((tempcommand&(0xA0))>>7)==1){
  308.             if (previousBit == 1){//11
  309.                 buf[*len] = IR_RC5_HALF_BIT;
  310.                 buf[*len+1] = IR_RC5_HALF_BIT;
  311.                 *len = *len + 2;
  312.             } else {//01
  313.                 buf[*len-1] = IR_RC5_BIT;
  314.                 buf[*len] = IR_RC5_HALF_BIT;
  315.                 *len = *len + 1;
  316.             }
  317.             previousBit = 1;
  318.         } else {//10
  319.             if (previousBit == 1){
  320.                 buf[*len-1] = IR_RC5_BIT;
  321.                 buf[*len] = IR_RC5_HALF_BIT;
  322.                 *len = *len + 1;
  323.             } else {//00
  324.                 buf[*len] = IR_RC5_HALF_BIT;
  325.                 buf[*len+1] = IR_RC5_HALF_BIT;
  326.                 *len = *len + 2;
  327.             }
  328.             previousBit = 0;
  329.         }
  330.     }
  331.  
  332.     proto->modfreq=(((F_CPU/2000)/IR_RC5_F_MOD) -1);
  333.     proto->timeout=IR_RC5_TIMEOUT;
  334.     proto->repeats=IR_RC5_REPS;
  335.     return IR_OK;
  336. }
  337.  
  338.  
  339. #if (IR_PROTOCOLS_USE_SHARP)
  340. /**
  341.  * Test data on SHARP protocol
  342.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  343.  *
  344.  * @param buf
  345.  *      Pointer to buffer to where to data to parse is stored
  346.  * @param len
  347.  *      Length of the data
  348.  * @param proto
  349.  *      Pointer to protocol information
  350.  * @return
  351.  *      IR_OK if data parsed successfully, one of several errormessages if not
  352.  */
  353. int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  354.     /* parse buf[], max is len */
  355.  
  356.     /* check if we have correct amount of data */
  357.     if (len != 31) {
  358.         return IR_NOT_CORRECT_DATA;
  359.     }
  360.    
  361.     uint16_t rawbits=0;
  362.    
  363.     for (uint8_t i = 1; i < len; i++) {
  364.         if ((i&1) == 1) {       /* if odd, ir-pause */
  365.             /* check length of pause between bits */
  366.             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) {
  367.                 /* write a one */
  368.                 rawbits |= 1<<((i-1)>>1);
  369.             } 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) {
  370.                 /* do nothing, a zero is already in rawbits */
  371.             } else {
  372.                 return IR_NOT_CORRECT_DATA;
  373.             }
  374.         } else {            /* if even, ir-bit */
  375.             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) {
  376.                 return IR_NOT_CORRECT_DATA;
  377.             }
  378.         }
  379.     }
  380.    
  381.     proto->protocol=IR_PROTO_SHARP;
  382.     proto->timeout=IR_SHARP_TIMEOUT;
  383.     proto->data=rawbits;
  384.     return IR_OK;
  385. }
  386. #endif
  387.  
  388. /**
  389.  * Expand data from Sharp protocol
  390.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  391.  *
  392.  * @param buf
  393.  *      Pointer to buffer to store the expanded data
  394.  * @param len
  395.  *      Pointer to length of the data
  396.  * @param proto
  397.  *      Pointer to protocol information
  398.  * @return
  399.  *      IR_OK if data expanded successfully, one of several errormessages if not
  400.  */
  401. int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  402.     //TODO: Implement this function.
  403.     return IR_NOT_CORRECT_DATA;
  404. }
  405.  
  406.  
  407. #if (IR_PROTOCOLS_USE_NEC)
  408. /**
  409.  * Test data on NEC protocol
  410.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  411.  *
  412.  * @param buf
  413.  *      Pointer to buffer to where to data to parse is stored
  414.  * @param len
  415.  *      Length of the data
  416.  * @param proto
  417.  *      Pointer to protocol information
  418.  * @return
  419.  *      IR_OK if data parsed successfully, one of several errormessages if not
  420.  */
  421. int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  422.     /* parse buf[], max is len */
  423.  
  424.     /* check if we have correct amount of data */
  425.     if (len != 67) {
  426.         return IR_NOT_CORRECT_DATA;
  427.     }
  428.    
  429.     /* check startbit */
  430.     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) {
  431.         return IR_NOT_CORRECT_DATA;
  432.     }
  433.  
  434.     /* check pause after startbit */
  435.     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) {
  436.         return IR_NOT_CORRECT_DATA;
  437.     }
  438.  
  439.     uint32_t rawbits = 0;
  440.  
  441.     for (uint8_t i = 3; i < len; i++) {
  442.         if ((i&1) == 1) {       /* if odd, ir-pause */
  443.             /* check length of pause between bits */
  444.             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) {
  445.                 /* write a one */
  446.                 rawbits |= 1UL<<((i-3)>>1);
  447.             } 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) {
  448.                 /* do nothing, a zero is already in place */
  449.             } else {
  450.                 return IR_NOT_CORRECT_DATA;
  451.             }
  452.         } else {            /* if even, ir-bit */
  453.             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) {
  454.                 return IR_NOT_CORRECT_DATA;
  455.             }
  456.         }
  457.     }
  458.  
  459.     proto->protocol=IR_PROTO_NEC;
  460.     proto->timeout=IR_NEC_TIMEOUT;
  461.     proto->data=rawbits;   
  462.     return IR_OK;
  463. }
  464. #endif
  465.  
  466. /**
  467.  * Expand data from NEC protocol
  468.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  469.  *
  470.  * @param buf
  471.  *      Pointer to buffer to store the expanded data
  472.  * @param len
  473.  *      Pointer to length of the data
  474.  * @param proto
  475.  *      Pointer to protocol information
  476.  * @return
  477.  *      IR_OK if data expanded successfully, one of several errormessages if not
  478.  */
  479. int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  480.     /* Set up startbit */
  481.     buf[0] = IR_NEC_ST_BIT;
  482.    
  483.     if (proto->framecnt == 0) {
  484.         buf[1] = IR_NEC_ST_PAUSE;
  485.    
  486.         *len = 67;
  487.         for (uint8_t i = 0; i < 65; i++) {
  488.             if ((i&1) == 1) {       /* if odd, ir-pause */
  489.                 if ((proto->data>>(i>>1))&1) {
  490.                     buf[i+2] = IR_NEC_LOW_ONE;
  491.                 } else {
  492.                     buf[i+2] = IR_NEC_LOW_ZERO;
  493.                 }
  494.             } else {            /* if even, ir-bit */
  495.                 buf[i+2] = IR_NEC_HIGH;
  496.             }
  497.         }
  498.         proto->timeout=IR_NEC_TIMEOUT;
  499.     } else {
  500.         buf[1] = IR_NEC_ST_PAUSE/2;
  501.         buf[2] = IR_NEC_HIGH;
  502.         proto->timeout=IR_NEC_ST_TIMEOUT;
  503.         *len = 3;
  504.     }
  505.     proto->modfreq=(((F_CPU/2000)/IR_NEC_F_MOD) -1);
  506.     proto->repeats=IR_NEC_REPS;
  507.     return IR_OK;
  508. }
  509.  
  510.  
  511. #if (IR_PROTOCOLS_USE_SAMSUNG)
  512. /**
  513.  * Test data on Samsung protocol
  514.  * Very much like NEC, different start bit/pause lengths etc.
  515.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  516.  *
  517.  * @param buf
  518.  *      Pointer to buffer to where to data to parse is stored
  519.  * @param len
  520.  *      Length of the data
  521.  * @param proto
  522.  *      Pointer to protocol information
  523.  * @return
  524.  *      IR_OK if data parsed successfully, one of several errormessages if not
  525.  */
  526. int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  527.     /* parse buf[], max is len */
  528.  
  529.     /* check if we have correct amount of data */
  530.     if (len != 67) {
  531.         return IR_NOT_CORRECT_DATA;
  532.     }
  533.    
  534.     /* check startbit */
  535.     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) {
  536.         return IR_NOT_CORRECT_DATA;
  537.     }
  538.  
  539.     /* check pause after startbit */
  540.     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) {
  541.         return IR_NOT_CORRECT_DATA;
  542.     }
  543.  
  544.     uint32_t rawbits = 0;
  545.    
  546.     for (uint8_t i = 3; i < len; i++) {
  547.         if ((i&1) == 1) {       /* if odd, ir-pause */
  548.             /* check length of pause between bits */
  549.             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) {
  550.                 /* write a one */
  551.                 rawbits |= 1UL<<((i-3)>>1);
  552.             } 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) {
  553.                 /* do nothing, a zero is already in rawbits */
  554.             } else {
  555.                 return IR_NOT_CORRECT_DATA;
  556.             }
  557.         } else {            /* if even, ir-bit */
  558.             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) {
  559.                 return IR_NOT_CORRECT_DATA;
  560.             }
  561.         }
  562.     }
  563.    
  564.     proto->protocol=IR_PROTO_SAMS;
  565.     proto->timeout=IR_SAMS_TIMEOUT;
  566.     proto->data=rawbits;   
  567.     return IR_OK;
  568. }
  569. #endif
  570.  
  571. /**
  572.  * Expand data from Samsung protocol
  573.  * Very much like NEC, different start bit/pause lengths etc.
  574.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  575.  *
  576.  * @param buf
  577.  *      Pointer to buffer to store the expanded data
  578.  * @param len
  579.  *      Pointer to length of the data
  580.  * @param proto
  581.  *      Pointer to protocol information
  582.  * @return
  583.  *      IR_OK if data expanded successfully, one of several errormessages if not
  584.  */
  585. int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  586.     /* Set up startbit */
  587.     buf[0] = IR_SAMS_ST_BIT;
  588.     buf[1] = IR_SAMS_ST_PAUSE;
  589.    
  590.     for (uint8_t i = 0; i < 65; i++) {
  591.         if ((i&1) == 1) {       /* if odd, ir-pause */
  592.             if ((proto->data>>(i>>1))&1) {
  593.                 buf[i+2] = IR_SAMS_LOW_ONE;
  594.             } else {
  595.                 buf[i+2] = IR_SAMS_LOW_ZERO;
  596.             }
  597.         } else {                /* if even, ir-bit */
  598.             buf[i+2] = IR_SAMS_HIGH;
  599.         }
  600.     }
  601.    
  602.     *len = 67;
  603.    
  604.     proto->modfreq=(((F_CPU/2000)/IR_SAMS_F_MOD) -1);
  605.     proto->timeout=IR_SAMS_TIMEOUT;
  606.     proto->repeats=IR_SAMS_REPS;
  607.     return IR_OK;
  608. }
  609.  
  610. #if (IR_PROTOCOLS_USE_MARANTZ)
  611. /**
  612.  * Test data on Marantz protocol
  613.  * Reverse-Engineered by Noddan, very similar to RC-5.
  614.  * Not tested with odd adresses since I have no remote that sends them.
  615.  * Don't know what happens with the extra long bit in that case.
  616.  * TODO: Replace all the RC5 with Marantz :D
  617.  *
  618.  * @param buf
  619.  *      Pointer to buffer to where to data to parse is stored
  620.  * @param len
  621.  *      Length of the data
  622.  * @param proto
  623.  *      Pointer to protocol information
  624.  * @return
  625.  *      IR_OK if data parsed successfully, one of several errormessages if not
  626.  */
  627. int8_t parseMarantz(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  628.     uint8_t halfbitscnt = 1;
  629.     uint32_t rawbits = 0;
  630.    
  631.     for (uint8_t i = 0; i<len; i++) {
  632.         //halfbitscnt&1==1 in the middle of bits
  633.         //i&1==0 positive flank
  634.  
  635.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  636.             rawbits |= (uint32_t)1<<(19-(halfbitscnt>>1));
  637.         }
  638.        
  639.         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) {
  640.             halfbitscnt += 1;
  641.         } 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) {
  642.             halfbitscnt += 2;
  643.         } 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) {
  644.             halfbitscnt += 1; //It seems to work, not entirely sure of the purpose of this long zero though.
  645.         } else {
  646.             return IR_NOT_CORRECT_DATA;
  647.         }
  648.        
  649.     }
  650.    
  651.     //rawbits = (uint32_t)1<<17;
  652.     proto->protocol=IR_PROTO_MARANTZ;
  653.     proto->timeout=IR_RC5_TIMEOUT;
  654.     //support RC5-extended keeping second startbit
  655.     //remove togglebit
  656.     //proto->data = rawbits&0x37ff;
  657.     proto->data = rawbits&0x0001ffff;
  658.    
  659.     return IR_OK;
  660. }
  661.  
  662. /**
  663.  * Expand data from Marantz
  664.  *
  665.  * @param buf
  666.  *      Pointer to buffer to store the expanded data
  667.  * @param len
  668.  *      Pointer to length of the data
  669.  * @param proto
  670.  *      Pointer to protocol information
  671.  * @return
  672.  *      IR_OK if data expanded successfully, one of several errormessages if not
  673.  */
  674. int8_t expandMarantz(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  675.     uint8_t previousBit;
  676.     uint32_t tempdata;
  677.     uint32_t tempvariabel; //bra att ha eftersom jag inte har koll pŒ alla typecastingar
  678.    
  679.     //TODO: Implement this function. Martin testar!
  680.     /* Set up startbits */
  681.     buf[0] = IR_RC5_HALF_BIT;//first start bit
  682.     buf[1] = IR_RC5_HALF_BIT;
  683.     buf[2] = IR_RC5_HALF_BIT;//second start bit
  684.     //TODO: Toggle bit should be better, not hard-coded
  685.     buf[3] = IR_RC5_HALF_BIT;
  686.     buf[4] = IR_RC5_HALF_BIT;//toggle bit
  687.     *len=5;
  688.     previousBit = 1;
  689.    
  690.     tempdata = proto->data;
  691.    
  692.     tempdata = (uint32_t)tempdata<<14; //MSB at position 32.
  693.    
  694.     for(uint8_t ij = 0; ij < 17; ij++) {
  695.         tempdata = (uint32_t)tempdata<<1;
  696.         tempvariabel = (uint32_t)tempdata&(0x8000);
  697.         tempvariabel = (uint32_t)tempdata>>31;
  698.         if ((uint32_t)tempvariabel==1){
  699.             if (previousBit == 1){//11
  700.                 buf[*len] = IR_RC5_HALF_BIT;
  701.                 buf[*len+1] = IR_RC5_HALF_BIT;
  702.                 *len = *len + 2;
  703.             } else {//01
  704.                 buf[*len-1] = IR_RC5_BIT;
  705.                 buf[*len] = IR_RC5_HALF_BIT;
  706.                 *len = *len + 1;
  707.             }
  708.             previousBit = 1;
  709.         } else {
  710.             if (previousBit == 1){//10
  711.                 buf[*len-1] = IR_RC5_BIT;
  712.                 buf[*len] = IR_RC5_HALF_BIT;
  713.                 *len = *len + 1;
  714.             } else {//00
  715.                 buf[*len] = IR_RC5_HALF_BIT;
  716.                 if (ij==4){
  717.                     buf[*len+1] = IR_RC5_HALF_BIT*5;
  718.                 } else {
  719.                     buf[*len+1] = IR_RC5_HALF_BIT;
  720.                 }
  721.                
  722.                 *len = *len + 2;
  723.             }
  724.             previousBit = 0;
  725.         }
  726.     }
  727.     //make sure that we finish high by removing the last zero if needed
  728.     if (*len%2 == 0){
  729.         *len = *len - 1;
  730.     }
  731.  
  732.     proto->modfreq=(((F_CPU/2000)/IR_RC5_F_MOD) -1);
  733.     proto->timeout=IR_RC5_TIMEOUT;
  734.     proto->repeats=IR_RC5_REPS;
  735.     return IR_OK;
  736. }
  737.  
  738.  
  739. #endif
  740.