]> cloudbase.mooo.com Git - irmp.git/blobdiff - irmp.c
Version 1.3.0: added Grundig protocol, fixed auto repetition detection for SIRCS...
[irmp.git] / irmp.c
diff --git a/irmp.c b/irmp.c
index 470a2f91922afb83735e435835b49fd6d69e8267..7c1225f4e78f6b11d54b7ebb3c410622b1f4bb38 100644 (file)
--- a/irmp.c
+++ b/irmp.c
@@ -3,7 +3,7 @@
  *\r
  * Copyright (c) 2009-2010 Frank Meyer - frank(at)fli4l.de\r
  *\r
- * $Id: irmp.c,v 1.20 2010/04/19 13:42:17 fm Exp $\r
+ * $Id: irmp.c,v 1.24 2010/05/16 21:58:13 fm Exp $\r
  *\r
  * ATMEGA88 @ 8 MHz\r
  *\r
@@ -23,6 +23,7 @@
  * NUBERT     - Nubert Subwoofer System\r
  * B&O        - Bang & Olufsen\r
  * PANASONIC  - Panasonic (older, yet not implemented)\r
+ * Grundig    - Grundig\r
  *\r
  *---------------------------------------------------------------------------------------------------------------------------------------------------\r
  *\r
  *\r
  *---------------------------------------------------------------------------------------------------------------------------------------------------\r
  *\r
+ *   Grundig\r
+ *   -------\r
+ *\r
+ *   frame:  1 start packet + n info packets + 1 stop packet\r
+ *   packet: 1 pre bit + 1 start bit + 9 data bits + no stop bit\r
+ *   data of start packet:   9 x 1\r
+ *   data of info  packet:   9 command bits\r
+ *   data of stop  packet:   9 x 1\r
+ *\r
+ *   pre bit:              start bit           data "0":            data "1":\r
+ *   ------____________    ------______        ______------         ------______             \r
+ *   528us  2639us         528us  528us        528us  528us         528us  528us\r
+ *\r
+ *---------------------------------------------------------------------------------------------------------------------------------------------------\r
+ *\r
  *   PANASONIC (older protocol, yet not implemented, see also MATSUSHITA, timing very similar)\r
  *   -----------------------------------------------------------------------------------------\r
  *\r
@@ -459,12 +475,20 @@ typedef unsigned int16  uint16_t;
 #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN  ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)\r
 #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX  ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)\r
 \r
+#define GRUNDIG_START_BIT_LEN_MIN               ((uint8_t)(F_INTERRUPTS * GRUNDIG_BIT_TIME * MIN_TOLERANCE_20 + 0.5) - 1)\r
+#define GRUNDIG_START_BIT_LEN_MAX               ((uint8_t)(F_INTERRUPTS * GRUNDIG_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1)\r
+#define GRUNDIG_BIT_LEN_MIN                     ((uint8_t)(F_INTERRUPTS * GRUNDIG_BIT_TIME * MIN_TOLERANCE_20 + 0.5) - 1)\r
+#define GRUNDIG_BIT_LEN_MAX                     ((uint8_t)(F_INTERRUPTS * GRUNDIG_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1)\r
+#define GRUNDIG_PRE_PAUSE_LEN_MIN               ((uint8_t)(F_INTERRUPTS * GRUNDIG_PRE_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) + 1)\r
+#define GRUNDIG_PRE_PAUSE_LEN_MAX               ((uint8_t)(F_INTERRUPTS * GRUNDIG_PRE_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)\r
+\r
 #define AUTO_REPETITION_LEN                     (uint16_t)(F_INTERRUPTS * AUTO_REPETITION_TIME + 0.5)       // use uint16_t!\r
 \r
 #ifdef DEBUG\r
 #define DEBUG_PUTCHAR(a)                        { if (! silent) { putchar (a);          } }\r
 #define DEBUG_PRINTF(...)                       { if (! silent) { printf (__VA_ARGS__); } }\r
 static int silent;\r
+static int time_counter;\r
 #else\r
 #define DEBUG_PUTCHAR(a)\r
 #define DEBUG_PRINTF(...)\r
@@ -930,6 +954,30 @@ static PROGMEM IRMP_PARAMETER bang_olufsen_param =
 \r
 #endif\r
 \r
+#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+\r
+static PROGMEM IRMP_PARAMETER grundig_param =\r
+{\r
+    IRMP_GRUNDIG_PROTOCOL,\r
+    GRUNDIG_BIT_LEN_MIN,\r
+    GRUNDIG_BIT_LEN_MAX,\r
+    GRUNDIG_BIT_LEN_MIN,\r
+    GRUNDIG_BIT_LEN_MAX,\r
+    1,                                // tricky: use this as stop bit length\r
+    1,\r
+    1,\r
+    1,\r
+    GRUNDIG_ADDRESS_OFFSET,\r
+    GRUNDIG_ADDRESS_OFFSET + GRUNDIG_ADDRESS_LEN,\r
+    GRUNDIG_COMMAND_OFFSET,\r
+    GRUNDIG_COMMAND_OFFSET + GRUNDIG_COMMAND_LEN,\r
+    GRUNDIG_COMPLETE_DATA_LEN,\r
+    GRUNDIG_STOP_BIT,\r
+    GRUNDIG_LSB\r
+};\r
+\r
+#endif\r
+\r
 static uint8_t                              irmp_bit;                                           // current bit position\r
 static IRMP_PARAMETER                       irmp_param;\r
 \r
@@ -1093,6 +1141,7 @@ irmp_ISR (void)
     static uint16_t   last_irmp_address = 0xFFFF;                               // save last irmp address to recognize key repetition\r
     static uint16_t   last_irmp_command = 0xFFFF;                               // save last irmp command to recognize key repetition\r
     static uint16_t   repetition_counter;                                       // SIRCS repeats frame 2-5 times with 45 ms pause\r
+    static uint8_t    repetition_frame_number;\r
 #if IRMP_SUPPORT_DENON_PROTOCOL == 1\r
     static uint16_t   last_irmp_denon_command;                                  // save last irmp command to recognize DENON frame repetition\r
 #endif\r
@@ -1107,6 +1156,10 @@ irmp_ISR (void)
 #endif\r
     uint8_t           irmp_input;                                               // input value\r
 \r
+#ifdef DEBUG\r
+    time_counter++;\r
+#endif\r
+\r
     irmp_input = input(IRMP_PIN);\r
 \r
     irmp_logIsr(irmp_input);                                                    // log ir signal, if IRMP_LOGGING defined\r
@@ -1344,6 +1397,20 @@ irmp_ISR (void)
                     else\r
 #endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1\r
 \r
+#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+                    if (irmp_pulse_time >= GRUNDIG_START_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_START_BIT_LEN_MAX &&\r
+                        irmp_pause_time >= GRUNDIG_PRE_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG_PRE_PAUSE_LEN_MAX)\r
+                    {                                                           // it's GRUNDIG\r
+                        DEBUG_PRINTF ("protocol = GRUNDIG, pre bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",\r
+                                        GRUNDIG_START_BIT_LEN_MIN, GRUNDIG_START_BIT_LEN_MAX,\r
+                                        GRUNDIG_PRE_PAUSE_LEN_MIN, GRUNDIG_PRE_PAUSE_LEN_MAX);\r
+                        irmp_param_p = (IRMP_PARAMETER *) &grundig_param;\r
+                        last_pause = irmp_pause_time;\r
+                        last_value  = 1;\r
+                    }\r
+                    else\r
+#endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+\r
                     {\r
                         DEBUG_PRINTF ("protocol = UNKNOWN\n");\r
                         irmp_start_bit_detected = 0;                            // wait for another start bit...\r
@@ -1386,14 +1453,14 @@ irmp_ISR (void)
                     {\r
                         if (irmp_pause_time > RC5_START_BIT_LEN_MAX && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX)\r
                         {\r
-                          DEBUG_PRINTF ("[bit %2d: pulse = %3d, pause = %3d] ", irmp_bit, irmp_pulse_time, irmp_pause_time);\r
+                          DEBUG_PRINTF ("%8d [bit %2d: pulse = %3d, pause = %3d] ", time_counter, irmp_bit, irmp_pulse_time, irmp_pause_time);\r
                           DEBUG_PUTCHAR ('1');\r
                           DEBUG_PUTCHAR ('\n');\r
                           irmp_store_bit (1);\r
                         }\r
                         else if (! last_value)\r
                         {\r
-                          DEBUG_PRINTF ("[bit %2d: pulse = %3d, pause = %3d] ", irmp_bit, irmp_pulse_time, irmp_pause_time);\r
+                          DEBUG_PRINTF ("%8d [bit %2d: pulse = %3d, pause = %3d] ", time_counter, irmp_bit, irmp_pulse_time, irmp_pause_time);\r
                           DEBUG_PUTCHAR ('0');\r
                           DEBUG_PUTCHAR ('\n');\r
                           irmp_store_bit (0);\r
@@ -1402,10 +1469,31 @@ irmp_ISR (void)
                     else\r
 #endif // IRMP_SUPPORT_RC5_PROTOCOL == 1\r
 \r
+#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+                    if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL)\r
+                    {\r
+                        if (irmp_pause_time > GRUNDIG_START_BIT_LEN_MAX && irmp_pause_time <= 2 * GRUNDIG_START_BIT_LEN_MAX)\r
+                        {\r
+                          DEBUG_PRINTF ("%8d [bit %2d: pulse = %3d, pause = %3d] ", time_counter, irmp_bit, irmp_pulse_time, irmp_pause_time);\r
+                          DEBUG_PUTCHAR ('0');\r
+                          DEBUG_PUTCHAR ('\n');\r
+                          irmp_store_bit (0);\r
+                        }\r
+                        else if (! last_value)\r
+                        {\r
+                          DEBUG_PRINTF ("%8d [bit %2d: pulse = %3d, pause = %3d] ", time_counter, irmp_bit, irmp_pulse_time, irmp_pause_time);\r
+                          DEBUG_PUTCHAR ('1');\r
+                          DEBUG_PUTCHAR ('\n');\r
+                          irmp_store_bit (1);\r
+                        }\r
+                    }\r
+                    else\r
+#endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+\r
 #if IRMP_SUPPORT_DENON_PROTOCOL == 1\r
                     if (irmp_param.protocol == IRMP_DENON_PROTOCOL)\r
                     {\r
-                        DEBUG_PRINTF ("[bit %2d: pulse = %3d, pause = %3d] ", irmp_bit, irmp_pulse_time, irmp_pause_time);\r
+                        DEBUG_PRINTF ("%8d [bit %2d: pulse = %3d, pause = %3d] ", time_counter, irmp_bit, irmp_pulse_time, irmp_pause_time);\r
 \r
                         if (irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX)\r
                         {                                                       // pause timings correct for "1"?\r
@@ -1487,6 +1575,15 @@ irmp_ISR (void)
                             irmp_param.stop_bit = TRUE;                         // set flag\r
                         }\r
                         else\r
+#endif\r
+#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+                        if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL &&\r
+                            irmp_pause_time > 2 * GRUNDIG_BIT_LEN_MAX && irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN - 2 && !irmp_param.stop_bit)\r
+                        {                                                       // special rc5 decoder\r
+                            got_light = TRUE;                                   // this is a lie, but generates a stop bit ;-)\r
+                            irmp_param.stop_bit = TRUE;                         // set flag\r
+                        }\r
+                        else\r
 #endif\r
                         if (irmp_pause_time > IRMP_TIMEOUT_LEN)                 // timeout?\r
                         {                                                       // yes...\r
@@ -1512,7 +1609,7 @@ irmp_ISR (void)
 \r
                 if (got_light)\r
                 {\r
-                    DEBUG_PRINTF ("[bit %2d: pulse = %3d, pause = %3d] ", irmp_bit, irmp_pulse_time, irmp_pause_time);\r
+                    DEBUG_PRINTF ("%8d [bit %2d: pulse = %3d, pause = %3d] ", time_counter, irmp_bit, irmp_pulse_time, irmp_pause_time);\r
 \r
 #if IRMP_SUPPORT_RC5_PROTOCOL == 1\r
                     if (irmp_param.protocol == IRMP_RC5_PROTOCOL)               // special rc5 decoder\r
@@ -1552,6 +1649,44 @@ irmp_ISR (void)
                     else\r
 #endif\r
 \r
+#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+                    if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL)               // special Grundig decoder\r
+                    {\r
+                        if (irmp_pulse_time > GRUNDIG_BIT_LEN_MAX && irmp_pulse_time <= 2 * GRUNDIG_BIT_LEN_MAX)\r
+                        {\r
+                            DEBUG_PUTCHAR ('0');\r
+                            irmp_store_bit (0);\r
+                            DEBUG_PUTCHAR ('1');\r
+                            DEBUG_PUTCHAR ('\n');\r
+                            irmp_store_bit (1);\r
+                            last_value = 1;\r
+                        }\r
+\r
+                        else // if (irmp_pulse_time >= GRUNDIG_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_BIT_LEN_MAX)\r
+                        {\r
+                            uint8_t grundig_value;\r
+\r
+                            if (last_pause > GRUNDIG_BIT_LEN_MAX && last_pause <= 2 * GRUNDIG_BIT_LEN_MAX)\r
+                            {\r
+                                grundig_value = last_value ? 0 : 1;\r
+                                last_value  = grundig_value;\r
+                            }\r
+                            else\r
+                            {\r
+                                grundig_value = last_value;\r
+                            }\r
+\r
+                            DEBUG_PUTCHAR (grundig_value + '0');\r
+                            DEBUG_PUTCHAR ('\n');\r
+                            irmp_store_bit (grundig_value);\r
+                        }\r
+\r
+                        last_pause = irmp_pause_time;\r
+                        wait_for_space = 0;\r
+                    }\r
+                    else\r
+#endif\r
+\r
 #if IRMP_SUPPORT_RC6_PROTOCOL == 1\r
                     if (irmp_param.protocol == IRMP_RC6_PROTOCOL)               // special rc6 decoder\r
                     {\r
@@ -1781,17 +1916,48 @@ irmp_ISR (void)
 \r
             if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 0)    // enough bits received?\r
             {\r
-                // if SIRCS/SAMSUNG32 protocol and the code will be repeated within 50 ms, we will ignore it.\r
-                if ((irmp_param.protocol == IRMP_SIRCS_PROTOCOL ||\r
-                     irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL ||\r
-                     irmp_param.protocol == IRMP_NUBERT_PROTOCOL) &&\r
-                    last_irmp_command == irmp_tmp_command && repetition_counter < AUTO_REPETITION_LEN)\r
+                if (last_irmp_command == irmp_tmp_command && repetition_counter < AUTO_REPETITION_LEN)\r
+                {\r
+                    repetition_frame_number++;\r
+                }\r
+                else\r
                 {\r
-                    DEBUG_PRINTF ("code skipped, recognized SIRCS, SAMSUNG32 or NUBERT repetition, counter = %d, auto repetition len = %d\n",\r
-                                    repetition_counter, AUTO_REPETITION_LEN);\r
+                    repetition_frame_number = 0;\r
+                }\r
+\r
+#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1\r
+                // if SIRCS protocol and the code will be repeated within 50 ms, we will ignore 2nd and 3rd repetition frame\r
+                if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && (repetition_frame_number == 1 || repetition_frame_number == 2))\r
+                {\r
+                    DEBUG_PRINTF ("code skipped: SIRCS auto repetition frame #%d, counter = %d, auto repetition len = %d\n",\r
+                                    repetition_frame_number + 1, repetition_counter, AUTO_REPETITION_LEN);\r
+                    repetition_counter = 0;\r
+                }\r
+                else\r
+#endif\r
+\r
+#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1\r
+                // if SAMSUNG32 protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame\r
+                if (irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL && (repetition_frame_number & 0x01))\r
+                {\r
+                    DEBUG_PRINTF ("code skipped: SAMSUNG32 auto repetition frame #%d, counter = %d, auto repetition len = %d\n",\r
+                                    repetition_frame_number + 1, repetition_counter, AUTO_REPETITION_LEN);\r
+                    repetition_counter = 0;\r
+                }\r
+                else\r
+#endif\r
+\r
+#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1\r
+                // if NUBERT protocol and the code will be repeated within 50 ms, we will ignore it.\r
+                if (irmp_param.protocol == IRMP_NUBERT_PROTOCOL && (repetition_frame_number & 0x01))\r
+                {\r
+                    DEBUG_PRINTF ("code skipped: NUBERT auto repetition frame #%d, counter = %d, auto repetition len = %d\n",\r
+                                    repetition_frame_number + 1, repetition_counter, AUTO_REPETITION_LEN);\r
                     repetition_counter = 0;\r
                 }\r
                 else\r
+#endif\r
+\r
                 {\r
                     DEBUG_PRINTF ("code detected, length = %d\n", irmp_bit);\r
                     irmp_ir_detected = TRUE;\r
@@ -1816,6 +1982,16 @@ irmp_ISR (void)
                     }\r
                     else\r
 #endif // IRMP_SUPPORT_DENON_PROTOCOL\r
+\r
+#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1\r
+                    if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && irmp_tmp_command == 0x01ff)     // only start frame?\r
+                    {\r
+                        DEBUG_PRINTF ("Detected start frame, ignoring it\n");\r
+                        irmp_ir_detected = FALSE;\r
+                        // last_irmp_grundig_command = irmp_tmp_command;\r
+                    }\r
+                    else\r
+#endif // IRMP_SUPPORT_DENON_PROTOCOL\r
                     {\r
 #if IRMP_SUPPORT_NEC_PROTOCOL == 1\r
                         if (irmp_param.protocol == IRMP_NEC_PROTOCOL && irmp_bit == 0)  // repetition frame\r
@@ -1912,6 +2088,8 @@ print_timings (void)
             BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX);\r
     printf ("BANG_OLUFSEN   4               %3d - %3d           %3d - %3d\n",\r
             BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX);\r
+    printf ("GRUNDIG        1               %3d - %3d           %3d - %3d\n",\r
+            GRUNDIG_START_BIT_LEN_MIN, GRUNDIG_START_BIT_LEN_MAX, GRUNDIG_PRE_PAUSE_LEN_MIN, GRUNDIG_PRE_PAUSE_LEN_MAX);\r
 }\r
 \r
 int\r