Subversion Repositories HomeAutomation

Rev

Rev 610 | Rev 732 | 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.     /* No protocol matched. */
  33.     proto->protocol = IR_PROTO_UNKNOWN;
  34.     return IR_NOT_CORRECT_DATA;
  35. }
  36.  
  37. int8_t parseHash(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  38.     //TODO: Transform the buffer in some clever way to a 32 bit word. */
  39.     proto->protocol = IR_PROTO_HASH;
  40.     proto->timeout = 200;
  41.     proto->data = 0;
  42.    
  43.     return 0;
  44. }
  45.  
  46. int8_t expandProtocol(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  47.     /* Call the expand function for the specified protocol. */
  48.     switch (proto->protocol) {
  49.     case IR_PROTO_SIRC:
  50.         return expandSIRC(buf, len, proto);
  51.     case IR_PROTO_RC5:
  52.         return expandRC5(buf, len, proto);
  53.     case IR_PROTO_SHARP:
  54.         return expandSharp(buf, len, proto);
  55.     case IR_PROTO_NEC:
  56.         return expandNEC(buf, len, proto);
  57.     case IR_PROTO_SAMS:
  58.         return expandSamsung(buf, len, proto);
  59.     }
  60.     /* Invalid protocol specified. */
  61.     return IR_NOT_CORRECT_DATA;
  62. }
  63.  
  64. #if (IR_PROTOCOLS_USE_SIRC)
  65. /**
  66.  * Test data on SIRC protocol, 12-bit version
  67.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  68.  *
  69.  * @param buf
  70.  *      Pointer to buffer to where to data to parse is stored
  71.  * @param len
  72.  *      Length of the data
  73.  * @param proto
  74.  *      Pointer to protocol information
  75.  * @return
  76.  *      IR_OK if data parsed successfully, one of several errormessages if not
  77.  */
  78. int8_t parseSIRC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  79.     /* parse buf[], max is len */
  80.  
  81.     /* check if we have correct amount of data */
  82.     if (len != 25) {
  83.         return IR_NOT_CORRECT_DATA;
  84.     }
  85.    
  86.     /* check startbit */
  87.     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) {
  88.         return IR_NOT_CORRECT_DATA;
  89.     }
  90.    
  91.     uint16_t rawbits=0;
  92.    
  93.     for (uint8_t i = 1; i < len; i++) {
  94.         if ((i&1) == 1) {       /* if odd, ir-pause */
  95.             /* check length of pause between bits */
  96.             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) {
  97.                 return IR_NOT_CORRECT_DATA;
  98.             }
  99.         } else {            /* if even, ir-bit */
  100.             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) {
  101.                 /* write a one */
  102.                 rawbits |= 1<<((i-2)>>1);
  103.             } 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) {
  104.                 /* do nothing, a zero is already in rawbits */
  105.             } else {
  106.                 return IR_NOT_CORRECT_DATA;
  107.             }
  108.         }
  109.     }
  110.    
  111.     proto->protocol = IR_PROTO_SIRC;
  112.     proto->timeout = IR_SIRC_TIMEOUT;
  113.     proto->data = rawbits;
  114.    
  115.     return IR_OK;
  116. }
  117. #endif
  118.  
  119. /**
  120.  * Expand data from SIRC protocol
  121.  * http://www.sbprojects.com/knowledge/ir/sirc.htm
  122.  *
  123.  * @param buf
  124.  *      Pointer to buffer to store the expanded data
  125.  * @param len
  126.  *      Pointer to length of the data
  127.  * @param proto
  128.  *      Pointer to protocol information
  129.  * @return
  130.  *      IR_OK if data expanded successfully, one of several errormessages if not
  131.  */
  132. int8_t expandSIRC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  133.     //TODO: Implement this function.
  134.     return IR_NOT_CORRECT_DATA;
  135. }
  136.  
  137.  
  138. #if (IR_PROTOCOLS_USE_RC5)
  139. /**
  140.  * Test data on RC5 protocol
  141.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  142.  *
  143.  * @param buf
  144.  *      Pointer to buffer to where to data to parse is stored
  145.  * @param len
  146.  *      Length of the data
  147.  * @param proto
  148.  *      Pointer to protocol information
  149.  * @return
  150.  *      IR_OK if data parsed successfully, one of several errormessages if not
  151.  */
  152. int8_t parseRC5(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  153.     uint8_t halfbitscnt = 1;
  154.     uint16_t rawbits = 0;
  155.    
  156.     for (uint8_t i = 0; i<len; i++) {
  157.         //halfbitscnt&1==1 in the middle of bits
  158.         //i&1==0 positive flank
  159.  
  160.         if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
  161.             rawbits |= (1<<(13-(halfbitscnt>>1)));
  162.         }
  163.        
  164.         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) {
  165.             halfbitscnt += 1;
  166.         } 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) {
  167.             halfbitscnt += 2;
  168.         } else {
  169.             return IR_NOT_CORRECT_DATA;
  170.         }
  171.        
  172.     }
  173.  
  174.     proto->protocol=IR_PROTO_RC5;
  175.     proto->timeout=IR_RC5_TIMEOUT;
  176.     //support RC5-extended keeping second startbit
  177.     //remove togglebit
  178.     proto->data = rawbits&0x37ff;
  179.  
  180.    
  181.     return IR_OK;
  182. }
  183. #endif
  184.  
  185. /**
  186.  * Expand data from RC5 protocol
  187.  * http://www.sbprojects.com/knowledge/ir/rc5.htm
  188.  *
  189.  * @param buf
  190.  *      Pointer to buffer to store the expanded data
  191.  * @param len
  192.  *      Pointer to length of the data
  193.  * @param proto
  194.  *      Pointer to protocol information
  195.  * @return
  196.  *      IR_OK if data expanded successfully, one of several errormessages if not
  197.  */
  198. int8_t expandRC5(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  199.     //TODO: Implement this function.
  200.     return IR_NOT_CORRECT_DATA;
  201. }
  202.  
  203.  
  204. #if (IR_PROTOCOLS_USE_SHARP)
  205. /**
  206.  * Test data on SHARP protocol
  207.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  208.  *
  209.  * @param buf
  210.  *      Pointer to buffer to where to data to parse is stored
  211.  * @param len
  212.  *      Length of the data
  213.  * @param proto
  214.  *      Pointer to protocol information
  215.  * @return
  216.  *      IR_OK if data parsed successfully, one of several errormessages if not
  217.  */
  218. int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  219.     /* parse buf[], max is len */
  220.  
  221.     /* check if we have correct amount of data */
  222.     if (len != 31) {
  223.         return IR_NOT_CORRECT_DATA;
  224.     }
  225.    
  226.     uint16_t rawbits=0;
  227.    
  228.     for (uint8_t i = 1; i < len; i++) {
  229.         if ((i&1) == 1) {       /* if odd, ir-pause */
  230.             /* check length of pause between bits */
  231.             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) {
  232.                 /* write a one */
  233.                 rawbits |= 1<<((i-1)>>1);
  234.             } 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) {
  235.                 /* do nothing, a zero is already in rawbits */
  236.             } else {
  237.                 return IR_NOT_CORRECT_DATA;
  238.             }
  239.         } else {            /* if even, ir-bit */
  240.             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) {
  241.                 return IR_NOT_CORRECT_DATA;
  242.             }
  243.         }
  244.     }
  245.    
  246.     proto->protocol=IR_PROTO_SHARP;
  247.     proto->timeout=IR_SHARP_TIMEOUT;
  248.     proto->data=rawbits;
  249.     return IR_OK;
  250. }
  251. #endif
  252.  
  253. /**
  254.  * Expand data from Sharp protocol
  255.  * http://www.sbprojects.com/knowledge/ir/sharp.htm
  256.  *
  257.  * @param buf
  258.  *      Pointer to buffer to store the expanded data
  259.  * @param len
  260.  *      Pointer to length of the data
  261.  * @param proto
  262.  *      Pointer to protocol information
  263.  * @return
  264.  *      IR_OK if data expanded successfully, one of several errormessages if not
  265.  */
  266. int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  267.     //TODO: Implement this function.
  268.     return IR_NOT_CORRECT_DATA;
  269. }
  270.  
  271.  
  272. #if (IR_PROTOCOLS_USE_NEC)
  273. /**
  274.  * Test data on NEC protocol
  275.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  276.  *
  277.  * @param buf
  278.  *      Pointer to buffer to where to data to parse is stored
  279.  * @param len
  280.  *      Length of the data
  281.  * @param proto
  282.  *      Pointer to protocol information
  283.  * @return
  284.  *      IR_OK if data parsed successfully, one of several errormessages if not
  285.  */
  286. int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  287.     /* parse buf[], max is len */
  288.  
  289.     /* check if we have correct amount of data */
  290.     if (len != 67) {
  291.         return IR_NOT_CORRECT_DATA;
  292.     }
  293.    
  294.     /* check startbit */
  295.     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) {
  296.         return IR_NOT_CORRECT_DATA;
  297.     }
  298.  
  299.     /* check pause after startbit */
  300.     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) {
  301.         return IR_NOT_CORRECT_DATA;
  302.     }
  303.  
  304.     uint32_t rawbits = 0;
  305.  
  306.     for (uint8_t i = 3; i < len; i++) {
  307.         if ((i&1) == 1) {       /* if odd, ir-pause */
  308.             /* check length of pause between bits */
  309.             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) {
  310.                 /* write a one */
  311.                 rawbits |= 1UL<<((i-3)>>1);
  312.             } 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) {
  313.                 /* do nothing, a zero is already in place */
  314.             } else {
  315.                 return IR_NOT_CORRECT_DATA;
  316.             }
  317.         } else {            /* if even, ir-bit */
  318.             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) {
  319.                 return IR_NOT_CORRECT_DATA;
  320.             }
  321.         }
  322.     }
  323.  
  324.     proto->protocol=IR_PROTO_NEC;
  325.     proto->timeout=IR_NEC_TIMEOUT;
  326.     proto->data=rawbits;   
  327.     return IR_OK;
  328. }
  329. #endif
  330.  
  331. /**
  332.  * Expand data from NEC protocol
  333.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  334.  *
  335.  * @param buf
  336.  *      Pointer to buffer to store the expanded data
  337.  * @param len
  338.  *      Pointer to length of the data
  339.  * @param proto
  340.  *      Pointer to protocol information
  341.  * @return
  342.  *      IR_OK if data expanded successfully, one of several errormessages if not
  343.  */
  344. int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  345.     /* Set up startbit */
  346.     buf[0] = IR_NEC_ST_BIT;
  347.    
  348.     if (proto->framecnt == 0) {
  349.         buf[1] = IR_NEC_ST_PAUSE;
  350.    
  351.         *len = 67;
  352.         for (uint8_t i = 0; i < 65; i++) {
  353.             if ((i&1) == 1) {       /* if odd, ir-pause */
  354.                 if ((proto->data>>(i>>1))&1) {
  355.                     buf[i+2] = IR_NEC_LOW_ONE;
  356.                 } else {
  357.                     buf[i+2] = IR_NEC_LOW_ZERO;
  358.                 }
  359.             } else {            /* if even, ir-bit */
  360.                 buf[i+2] = IR_NEC_HIGH;
  361.             }
  362.         }
  363.         proto->timeout=IR_NEC_TIMEOUT;
  364.     } else {
  365.         buf[1] = IR_NEC_ST_PAUSE/2;
  366.         buf[2] = IR_NEC_HIGH;
  367.         proto->timeout=IR_NEC_ST_TIMEOUT;
  368.         *len = 3;
  369.     }
  370.     proto->modfreq=(((F_CPU/2000)/IR_NEC_F_MOD) -1);
  371.     proto->repeats=IR_NEC_REPS;
  372.     return IR_OK;
  373. }
  374.  
  375.  
  376. #if (IR_PROTOCOLS_USE_SAMSUNG)
  377. /**
  378.  * Test data on Samsung protocol
  379.  * Very much like NEC, different start bit/pause lengths etc.
  380.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  381.  *
  382.  * @param buf
  383.  *      Pointer to buffer to where to data to parse is stored
  384.  * @param len
  385.  *      Length of the data
  386.  * @param proto
  387.  *      Pointer to protocol information
  388.  * @return
  389.  *      IR_OK if data parsed successfully, one of several errormessages if not
  390.  */
  391. int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
  392.     /* parse buf[], max is len */
  393.  
  394.     /* check if we have correct amount of data */
  395.     if (len != 67) {
  396.         return IR_NOT_CORRECT_DATA;
  397.     }
  398.    
  399.     /* check startbit */
  400.     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) {
  401.         return IR_NOT_CORRECT_DATA;
  402.     }
  403.  
  404.     /* check pause after startbit */
  405.     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) {
  406.         return IR_NOT_CORRECT_DATA;
  407.     }
  408.  
  409.     uint32_t rawbits = 0;
  410.    
  411.     for (uint8_t i = 3; i < len; i++) {
  412.         if ((i&1) == 1) {       /* if odd, ir-pause */
  413.             /* check length of pause between bits */
  414.             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) {
  415.                 /* write a one */
  416.                 rawbits |= 1UL<<((i-3)>>1);
  417.             } 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) {
  418.                 /* do nothing, a zero is already in rawbits */
  419.             } else {
  420.                 return IR_NOT_CORRECT_DATA;
  421.             }
  422.         } else {            /* if even, ir-bit */
  423.             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) {
  424.                 return IR_NOT_CORRECT_DATA;
  425.             }
  426.         }
  427.     }
  428.    
  429.     proto->protocol=IR_PROTO_SAMS;
  430.     proto->timeout=IR_SAMS_TIMEOUT;
  431.     proto->data=rawbits;   
  432.     return IR_OK;
  433. }
  434. #endif
  435.  
  436. /**
  437.  * Expand data from Samsung protocol
  438.  * Very much like NEC, different start bit/pause lengths etc.
  439.  * http://www.sbprojects.com/knowledge/ir/nec.htm
  440.  *
  441.  * @param buf
  442.  *      Pointer to buffer to store the expanded data
  443.  * @param len
  444.  *      Pointer to length of the data
  445.  * @param proto
  446.  *      Pointer to protocol information
  447.  * @return
  448.  *      IR_OK if data expanded successfully, one of several errormessages if not
  449.  */
  450. int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
  451.     /* Set up startbit */
  452.     buf[0] = IR_SAMS_ST_BIT;
  453.     buf[1] = IR_SAMS_ST_PAUSE;
  454.    
  455.     for (uint8_t i = 0; i < 65; i++) {
  456.         if ((i&1) == 1) {       /* if odd, ir-pause */
  457.             if ((proto->data>>(i>>1))&1) {
  458.                 buf[i+2] = IR_SAMS_LOW_ONE;
  459.             } else {
  460.                 buf[i+2] = IR_SAMS_LOW_ZERO;
  461.             }
  462.         } else {                /* if even, ir-bit */
  463.             buf[i+2] = IR_SAMS_HIGH;
  464.         }
  465.     }
  466.    
  467.     *len = 67;
  468.    
  469.     proto->modfreq=(((F_CPU/2000)/IR_SAMS_F_MOD) -1);
  470.     proto->timeout=IR_SAMS_TIMEOUT;
  471.     proto->repeats=IR_SAMS_REPS;
  472.     return IR_OK;
  473. }
  474.