]> cloudbase.mooo.com Git - irmp.git/blobdiff - irsnd.c
Version 2.9.7: added port to to ESP8266 and TEENSY, added PANASONIC protocol, added...
[irmp.git] / irsnd.c
diff --git a/irsnd.c b/irsnd.c
index 8420675c2ae600beb3d92563bad22092c792f7e3..7fe263357e469c81c7ef05e2154eb7188dac7369 100644 (file)
--- a/irsnd.c
+++ b/irsnd.c
@@ -13,7 +13,7 @@
  * ATmega164, ATmega324, ATmega644,  ATmega644P, ATmega1284, ATmega1284P\r
  * ATmega88,  ATmega88P, ATmega168,  ATmega168P, ATmega328P\r
  *\r
- * $Id: irsnd.c,v 1.91 2015/09/20 10:51:37 fm Exp $\r
+ * $Id: irsnd.c,v 1.97 2015/11/18 08:27:50 fm Exp $\r
  *\r
  * This program is free software; you can redistribute it and/or modify\r
  * it under the terms of the GNU General Public License as published by\r
     //Nothing here to do here -> See irsndconfig.h\r
 #elif defined (ARM_STM32)  //STM32\r
     //Nothing here to do here -> See irsndconfig.h\r
+#elif defined (TEENSY_ARM_CORTEX_M4)                                // Teensy3\r
+#  if !digitalPinHasPWM(IRSND_PIN)\r
+#    error need pin with PWM output.\r
+#  endif\r
 #else\r
 #  if !defined (unix) && !defined (WIN32)\r
 #    error mikrocontroller not defined, please fill in definitions here.\r
 #define KASEIKYO_AUTO_REPETITION_PAUSE_LEN      (uint16_t)(F_INTERRUPTS * KASEIKYO_AUTO_REPETITION_PAUSE_TIME + 0.5)            // use uint16_t!\r
 #define KASEIKYO_FRAME_REPEAT_PAUSE_LEN         (uint16_t)(F_INTERRUPTS * KASEIKYO_FRAME_REPEAT_PAUSE_TIME + 0.5)               // use uint16_t!\r
 \r
+#define PANASONIC_START_BIT_PULSE_LEN            (uint8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME + 0.5)\r
+#define PANASONIC_START_BIT_PAUSE_LEN            (uint8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME + 0.5)\r
+#define PANASONIC_PULSE_LEN                      (uint8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME + 0.5)\r
+#define PANASONIC_1_PAUSE_LEN                    (uint8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME + 0.5)\r
+#define PANASONIC_0_PAUSE_LEN                    (uint8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME + 0.5)\r
+#define PANASONIC_AUTO_REPETITION_PAUSE_LEN      (uint16_t)(F_INTERRUPTS * PANASONIC_AUTO_REPETITION_PAUSE_TIME + 0.5)            // use uint16_t!\r
+#define PANASONIC_FRAME_REPEAT_PAUSE_LEN         (uint16_t)(F_INTERRUPTS * PANASONIC_FRAME_REPEAT_PAUSE_TIME + 0.5)               // use uint16_t!\r
+\r
 #define RECS80_START_BIT_PULSE_LEN              (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME + 0.5)\r
 #define RECS80_START_BIT_PAUSE_LEN              (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME + 0.5)\r
 #define RECS80_PULSE_LEN                        (uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME + 0.5)\r
 \r
 #define RC6_START_BIT_PULSE_LEN                 (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME + 0.5)\r
 #define RC6_START_BIT_PAUSE_LEN                 (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME + 0.5)\r
-#define RC6_TOGGLE_BIT_LEN                      (uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME + 0.5)\r
 #define RC6_BIT_LEN                             (uint8_t)(F_INTERRUPTS * RC6_BIT_TIME + 0.5)\r
+#define RC6_BIT_2_LEN                           (uint8_t)(F_INTERRUPTS * RC6_BIT_2_TIME + 0.5)\r
+#define RC6_BIT_3_LEN                           (uint8_t)(F_INTERRUPTS * RC6_BIT_3_TIME + 0.5)\r
 #define RC6_FRAME_REPEAT_PAUSE_LEN              (uint16_t)(F_INTERRUPTS * RC6_FRAME_REPEAT_PAUSE_TIME + 0.5)                    // use uint16_t!\r
 \r
 #define DENON_PULSE_LEN                         (uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME + 0.5)\r
 #define TELEFUNKEN_AUTO_REPETITION_PAUSE_LEN    (uint16_t)(F_INTERRUPTS * TELEFUNKEN_AUTO_REPETITION_PAUSE_TIME + 0.5)          // use uint16_t!\r
 #define TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN       (uint16_t)(F_INTERRUPTS * TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME + 0.5)             // use uint16_t!\r
 \r
+#define BOSE_START_BIT_PULSE_LEN                (uint8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME + 0.5)\r
+#define BOSE_START_BIT_PAUSE_LEN                (uint8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME + 0.5)\r
+#define BOSE_PULSE_LEN                          (uint8_t)(F_INTERRUPTS * BOSE_PULSE_TIME + 0.5)\r
+#define BOSE_1_PAUSE_LEN                        (uint8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME + 0.5)\r
+#define BOSE_0_PAUSE_LEN                        (uint8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME + 0.5)\r
+#define BOSE_AUTO_REPETITION_PAUSE_LEN          (uint16_t)(F_INTERRUPTS * BOSE_AUTO_REPETITION_PAUSE_TIME + 0.5)              // use uint16_t!\r
+#define BOSE_FRAME_REPEAT_PAUSE_LEN             (uint16_t)(F_INTERRUPTS * BOSE_FRAME_REPEAT_PAUSE_TIME + 0.5)                 // use uint16_t!\r
+\r
 #define NUBERT_START_BIT_PULSE_LEN              (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME + 0.5)\r
 #define NUBERT_START_BIT_PAUSE_LEN              (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME + 0.5)\r
 #define NUBERT_1_PULSE_LEN                      (uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME + 0.5)\r
 #  define IRSND_FREQ_40_KHZ                     (IRSND_FREQ_TYPE) (40000)\r
 #  define IRSND_FREQ_56_KHZ                     (IRSND_FREQ_TYPE) (56000)\r
 #  define IRSND_FREQ_455_KHZ                    (IRSND_FREQ_TYPE) (455000)\r
+#elif defined (TEENSY_ARM_CORTEX_M4)            // TEENSY\r
+#  define IRSND_FREQ_TYPE                       float\r
+#  define IRSND_FREQ_30_KHZ                     (IRSND_FREQ_TYPE) (30000)\r
+#  define IRSND_FREQ_32_KHZ                     (IRSND_FREQ_TYPE) (32000)\r
+#  define IRSND_FREQ_36_KHZ                     (IRSND_FREQ_TYPE) (36000)\r
+#  define IRSND_FREQ_38_KHZ                     (IRSND_FREQ_TYPE) (38000)\r
+#  define IRSND_FREQ_40_KHZ                     (IRSND_FREQ_TYPE) (40000)\r
+#  define IRSND_FREQ_56_KHZ                     (IRSND_FREQ_TYPE) (56000)\r
+#  define IRSND_FREQ_455_KHZ                    (IRSND_FREQ_TYPE) (455000)\r
 #else                                           // AVR\r
 #  if F_CPU >= 16000000L\r
 #    define AVR_PRESCALER                       8\r
@@ -475,6 +505,9 @@ irsnd_on (void)
         TIM_CCxCmd(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_CCx_Enable);      // enable OC-output (is being disabled in TIM_SelectOCxM())\r
         TIM_Cmd(IRSND_TIMER, ENABLE);                   // enable counter\r
 \r
+#  elif defined (TEENSY_ARM_CORTEX_M4)                  // TEENSY\r
+        analogWrite(IRSND_PIN, 33 * 255 / 100);         // pwm 33%\r
+\r
 #  elif defined (__AVR_XMEGA__) \r
 #    if (IRSND_OCx == IRSND_XMEGA_OC0A)                                 // use OC0A\r
                 XMEGA_Timer.CTRLB |= (1<<TC0_CCAEN_bp);                 // Compare A \r
@@ -544,6 +577,9 @@ irsnd_off (void)
         TIM_CCxCmd(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_CCx_Enable);      // enable OC-output (is being disabled in TIM_SelectOCxM())\r
         TIM_SetCounter(IRSND_TIMER, 0);                 // reset counter value\r
 \r
+#  elif defined (TEENSY_ARM_CORTEX_M4)                  // TEENSY\r
+        analogWrite(IRSND_PIN, 0); // pwm off, LOW level\r
+\r
 #  elif defined (__AVR_XMEGA__)\r
 #    if (IRSND_OCx == IRSND_XMEGA_OC0A)                                                                                                 // use OC0A \r
         XMEGA_Timer.CTRLB &= ~(1<<TC0_CCAEN_bp);                                        // Compare A disconnected\r
@@ -627,10 +663,10 @@ irsnd_set_freq (IRSND_FREQ_TYPE freq)
 #    endif\r
         PWMoff();\r
 #  elif defined (ARM_STM32)                                                                 // STM32\r
-         static uint32_t      TimeBaseFreq = 0;\r
+        static uint32_t      TimeBaseFreq = 0;\r
 \r
-         if (TimeBaseFreq == 0)\r
-         {\r
+        if (TimeBaseFreq == 0)\r
+        {\r
             RCC_ClocksTypeDef        RCC_ClocksStructure;\r
             /* Get system clocks and store timer clock in variable */\r
             RCC_GetClocksFreq(&RCC_ClocksStructure);\r
@@ -653,14 +689,19 @@ irsnd_set_freq (IRSND_FREQ_TYPE freq)
                TimeBaseFreq = RCC_ClocksStructure.PCLK2_Frequency * 2;\r
             }\r
 #    endif\r
-         }\r
+        }\r
+\r
+        freq = TimeBaseFreq/freq;\r
 \r
-         freq = TimeBaseFreq/freq;\r
+        /* Set frequency */\r
+        TIM_SetAutoreload(IRSND_TIMER, freq - 1);\r
+        /* Set duty cycle */\r
+        TIM_SetCompare1(IRSND_TIMER, (freq + 1) / 2);\r
 \r
-         /* Set frequency */\r
-         TIM_SetAutoreload(IRSND_TIMER, freq - 1);\r
-         /* Set duty cycle */\r
-         TIM_SetCompare1(IRSND_TIMER, (freq + 1) / 2);\r
+#  elif defined (TEENSY_ARM_CORTEX_M4)\r
+        analogWriteResolution(8);  // 8 bit\r
+        analogWriteFrequency(IRSND_PIN, freq);\r
+        analogWrite(IRSND_PIN, 0); // pwm off, LOW level\r
 \r
 #  elif defined (__AVR_XMEGA__)\r
         XMEGA_Timer.CCA = freq;\r
@@ -760,7 +801,13 @@ irsnd_init (void)
 \r
         irsnd_set_freq (IRSND_FREQ_36_KHZ);                                         // set default frequency\r
 \r
-# elif defined (__AVR_XMEGA__)\r
+#  elif defined (TEENSY_ARM_CORTEX_M4)\r
+        if (!digitalPinHasPWM(IRSND_PIN))\r
+        {\r
+            return;\r
+        }\r
+\r
+#  elif defined (__AVR_XMEGA__)\r
         IRSND_PORT &= ~(1<<IRSND_BIT);                                              // set IRSND_BIT to low\r
         IRSND_DDR |= (1<<IRSND_BIT);                                                // set IRSND_BIT to output\r
 \r
@@ -1091,6 +1138,24 @@ irsnd_send_data (IRMP_DATA * irmp_data_p, uint8_t do_wait)
             break;\r
         }\r
 #endif\r
+#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1\r
+        case IRMP_PANASONIC_PROTOCOL:\r
+        {\r
+            address = bitsrevervse (irmp_data_p->address, PANASONIC_ADDRESS_LEN);\r
+            command = bitsrevervse (irmp_data_p->command, PANASONIC_COMMAND_LEN);\r
+\r
+            irsnd_buffer[0] = 0x40;                                                                             // 01000000\r
+            irsnd_buffer[1] = 0x04;                                                                             // 00000100\r
+            irsnd_buffer[2] = 0x01;                                                                             // 00000001\r
+            irsnd_buffer[3] = (address & 0xFF00) >> 8;                                                          // AAAAAAAA\r
+            irsnd_buffer[4] = (address & 0x00FF);                                                               // AAAAAAAA\r
+            irsnd_buffer[5] = (command & 0xFF00) >> 8;                                                          // CCCCCCCC\r
+            irsnd_buffer[6] = (command & 0x00FF);                                                               // CCCCCCCC\r
+\r
+            irsnd_busy      = TRUE;\r
+            break;\r
+        }\r
+#endif\r
 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1\r
         case IRMP_RECS80_PROTOCOL:\r
         {\r
@@ -1175,6 +1240,17 @@ irsnd_send_data (IRMP_DATA * irmp_data_p, uint8_t do_wait)
             break;\r
         }\r
 #endif\r
+#if IRSND_SUPPORT_BOSE_PROTOCOL == 1\r
+        case IRMP_BOSE_PROTOCOL:\r
+        {\r
+            command = bitsrevervse (irmp_data_p->command, BOSE_COMMAND_LEN);\r
+\r
+            irsnd_buffer[0] = (command & 0xFF00) >> 8;                                                                      // CCCCCCCC\r
+            irsnd_buffer[1] = ~((command & 0xFF00) >> 8);                                                                   // cccccccc\r
+            irsnd_busy      = TRUE;\r
+            break;\r
+        }\r
+#endif\r
 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1\r
         case IRMP_NUBERT_PROTOCOL:\r
         {\r
@@ -1489,13 +1565,6 @@ irsnd_ISR (void)
             {\r
                 auto_repetition_pause_counter++;\r
 \r
-#if IRSND_SUPPORT_DENON_PROTOCOL == 1\r
-                if (repeat_frame_pause_len > 0)                                     // frame repeat distance counts from beginning of 1st frame!\r
-                {\r
-                    repeat_frame_pause_len--;\r
-                }\r
-#endif\r
-\r
                 if (auto_repetition_pause_counter >= auto_repetition_pause_len)\r
                 {\r
                     auto_repetition_pause_counter = 0;\r
@@ -1803,6 +1872,24 @@ irsnd_ISR (void)
                         break;\r
                     }\r
 #endif\r
+#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1\r
+                    case IRMP_PANASONIC_PROTOCOL:\r
+                    {\r
+                        startbit_pulse_len          = PANASONIC_START_BIT_PULSE_LEN;\r
+                        startbit_pause_len          = PANASONIC_START_BIT_PAUSE_LEN - 1;\r
+                        pulse_1_len                 = PANASONIC_PULSE_LEN;\r
+                        pause_1_len                 = PANASONIC_1_PAUSE_LEN - 1;\r
+                        pulse_0_len                 = PANASONIC_PULSE_LEN;\r
+                        pause_0_len                 = PANASONIC_0_PAUSE_LEN - 1;\r
+                        has_stop_bit                = PANASONIC_STOP_BIT;\r
+                        complete_data_len           = PANASONIC_COMPLETE_DATA_LEN;\r
+                        n_auto_repetitions          = PANASONIC_FRAMES;                             // 1 frame\r
+                        auto_repetition_pause_len   = PANASONIC_AUTO_REPETITION_PAUSE_LEN;          // 40 ms pause\r
+                        repeat_frame_pause_len      = PANASONIC_FRAME_REPEAT_PAUSE_LEN;\r
+                        irsnd_set_freq (IRSND_FREQ_38_KHZ);\r
+                        break;\r
+                    }\r
+#endif\r
 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1\r
                     case IRMP_RECS80_PROTOCOL:\r
                     {\r
@@ -1936,11 +2023,29 @@ irsnd_ISR (void)
                         complete_data_len           = THOMSON_COMPLETE_DATA_LEN;\r
                         n_auto_repetitions          = THOMSON_FRAMES;                               // only 1 frame\r
                         auto_repetition_pause_len   = THOMSON_AUTO_REPETITION_PAUSE_LEN;\r
-                        repeat_frame_pause_len      = DENON_FRAME_REPEAT_PAUSE_LEN;\r
+                        repeat_frame_pause_len      = THOMSON_FRAME_REPEAT_PAUSE_LEN;\r
                         irsnd_set_freq (IRSND_FREQ_38_KHZ);\r
                         break;\r
                     }\r
 #endif\r
+#if IRSND_SUPPORT_BOSE_PROTOCOL == 1\r
+                    case IRMP_BOSE_PROTOCOL:\r
+                    {\r
+                        startbit_pulse_len          = BOSE_START_BIT_PULSE_LEN;\r
+                        startbit_pause_len          = BOSE_START_BIT_PAUSE_LEN - 1;\r
+                        pulse_1_len                 = BOSE_PULSE_LEN;\r
+                        pause_1_len                 = BOSE_1_PAUSE_LEN - 1;\r
+                        pulse_0_len                 = BOSE_PULSE_LEN;\r
+                        pause_0_len                 = BOSE_0_PAUSE_LEN - 1;\r
+                        has_stop_bit                = BOSE_STOP_BIT;\r
+                        complete_data_len           = BOSE_COMPLETE_DATA_LEN;\r
+                        n_auto_repetitions          = BOSE_FRAMES;                                // 1 frame\r
+                        auto_repetition_pause_len   = BOSE_AUTO_REPETITION_PAUSE_LEN;             // 40 ms pause\r
+                        repeat_frame_pause_len      = BOSE_FRAME_REPEAT_PAUSE_LEN;\r
+                        irsnd_set_freq (IRSND_FREQ_36_KHZ);\r
+                        break;\r
+                    }\r
+#endif\r
 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1\r
                     case IRMP_NUBERT_PROTOCOL:\r
                     {\r
@@ -2305,6 +2410,9 @@ irsnd_ISR (void)
 #if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1\r
                 case IRMP_KASEIKYO_PROTOCOL:\r
 #endif\r
+#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1\r
+                case IRMP_PANASONIC_PROTOCOL:\r
+#endif\r
 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1\r
                 case IRMP_RECS80_PROTOCOL:\r
 #endif\r
@@ -2317,6 +2425,9 @@ irsnd_ISR (void)
 #if IRSND_SUPPORT_DENON_PROTOCOL == 1\r
                 case IRMP_DENON_PROTOCOL:\r
 #endif\r
+#if IRSND_SUPPORT_BOSE_PROTOCOL == 1\r
+                case IRMP_BOSE_PROTOCOL:\r
+#endif\r
 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1\r
                 case IRMP_NUBERT_PROTOCOL:\r
 #endif\r
@@ -2363,23 +2474,8 @@ irsnd_ISR (void)
     IRSND_SUPPORT_NUBERT_PROTOCOL == 1 || IRSND_SUPPORT_FAN_PROTOCOL == 1 || IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 || IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 || \\r
     IRSND_SUPPORT_FDC_PROTOCOL == 1 || IRSND_SUPPORT_RCCAR_PROTOCOL == 1 || IRSND_SUPPORT_JVC_PROTOCOL == 1 || IRSND_SUPPORT_NIKON_PROTOCOL == 1 || \\r
     IRSND_SUPPORT_LEGO_PROTOCOL == 1 || IRSND_SUPPORT_THOMSON_PROTOCOL == 1 || IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 || IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 || \\r
-    IRSND_SUPPORT_PENTAX_PROTOCOL == 1 || IRSND_SUPPORT_ACP24_PROTOCOL == 1\r
+    IRSND_SUPPORT_PENTAX_PROTOCOL == 1 || IRSND_SUPPORT_ACP24_PROTOCOL == 1 || IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 || IRSND_SUPPORT_BOSE_PROTOCOL == 1\r
                 {\r
-#if IRSND_SUPPORT_DENON_PROTOCOL == 1\r
-                    if (irsnd_protocol == IRMP_DENON_PROTOCOL)\r
-                    {\r
-                        if (auto_repetition_pause_len > 0)                                          // 2nd frame distance counts from beginning of 1st frame!\r
-                        {\r
-                            auto_repetition_pause_len--;\r
-                        }\r
-\r
-                        if (repeat_frame_pause_len > 0)                                             // frame repeat distance counts from beginning of 1st frame!\r
-                        {\r
-                            repeat_frame_pause_len--;\r
-                        }\r
-                    }\r
-#endif\r
-\r
                     if (pulse_counter == 0)\r
                     {\r
                         if (current_bit == 0xFF)                                                    // send start bit\r
@@ -2691,20 +2787,20 @@ irsnd_ISR (void)
                                     {\r
                                         if (current_bit == 4)                                           // toggle bit (double len)\r
                                         {\r
-                                            pulse_len = 2 * RC6_BIT_LEN;\r
-                                            pause_len = 2 * RC6_BIT_LEN;\r
+                                            pulse_len = RC6_BIT_2_LEN;                                  // = 2 * RC_BIT_LEN\r
+                                            pause_len = RC6_BIT_2_LEN;                                  // = 2 * RC_BIT_LEN\r
                                         }\r
                                     }\r
                                     else // if (irsnd_protocol == IRMP_RC6A_PROTOCOL)\r
                                     {\r
                                         if (current_bit == 4)                                           // toggle bit (double len)\r
                                         {\r
-                                            pulse_len = 2 * RC6_BIT_LEN + RC6_BIT_LEN;                  // hack!\r
-                                            pause_len = 2 * RC6_BIT_LEN;\r
+                                            pulse_len = RC6_BIT_3_LEN;                                  // = 3 * RC6_BIT_LEN\r
+                                            pause_len = RC6_BIT_2_LEN;                                  // = 2 * RC6_BIT_LEN\r
                                         }\r
                                         else if (current_bit == 5)                                      // toggle bit (double len)\r
                                         {\r
-                                            pause_len = 2 * RC6_BIT_LEN;\r
+                                            pause_len = RC6_BIT_2_LEN;                                  // = 2 * RC6_BIT_LEN\r
                                         }\r
                                     }\r
                                 }\r