*\r
* Supported mikrocontrollers:\r
*\r
+ * ATtiny87, ATtiny167\r
* ATtiny45, ATtiny85\r
* ATtiny84\r
* ATmega8, ATmega16, ATmega32\r
* ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284\r
* ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P\r
*\r
- * $Id: irsnd.c,v 1.55 2012/05/24 06:55:11 fm Exp $\r
+ * $Id: irsnd.c,v 1.64 2012/12/06 08:49:33 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
\r
#include "irsnd.h"\r
\r
+#ifndef F_CPU\r
+# error F_CPU unkown\r
+#endif\r
+\r
/*---------------------------------------------------------------------------------------------------------------------------------------------------\r
* ATtiny pin definition of OC0A / OC0B\r
* ATmega pin definition of OC2 / OC2A / OC2B / OC0 / OC0A / OC0B\r
*/\r
#if defined (__AVR_ATtiny84__) // ATtiny84 uses OC0A = PB2 or OC0B = PA7\r
# if IRSND_OCx == IRSND_OC0A // OC0A\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 2 // OC0A\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 2\r
# elif IRSND_OCx == IRSND_OC0B // OC0B\r
-# define IRSND_PORT PORTA // port A\r
-# define IRSND_DDR DDRA // ddr A\r
-# define IRSND_BIT 7 // OC0B\r
+# define IRSND_PORT_LETTER A\r
+# define IRSND_BIT_NUMBER 7\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h\r
# endif // IRSND_OCx\r
#elif defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) // ATtiny45/85 uses OC0A = PB0 or OC0B = PB1\r
# if IRSND_OCx == IRSND_OC0A // OC0A\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 0 // OC0A\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 0\r
# elif IRSND_OCx == IRSND_OC0B // OC0B\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 1 // OC0B\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 1\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h\r
# endif // IRSND_OCx\r
+#elif defined (__AVR_ATtiny87__) || defined (__AVR_ATtiny167__) // ATtiny87/167 uses OC0A = PA2\r
+# if IRSND_OCx == IRSND_OC0A // OC0A\r
+# define IRSND_PORT_LETTER A\r
+# define IRSND_BIT_NUMBER 2\r
+# else\r
+# error Wrong value for IRSND_OCx, choose IRSND_OC0A in irsndconfig.h\r
+# endif // IRSND_OCx\r
#elif defined (__AVR_ATmega8__) // ATmega8 uses only OC2 = PB3\r
# if IRSND_OCx == IRSND_OC2 // OC0A\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 3 // OC0A\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 3\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC2 in irsndconfig.h\r
# endif // IRSND_OCx\r
#elif defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) // ATmega16|32 uses OC2 = PD7\r
# if IRSND_OCx == IRSND_OC2 // OC2\r
-# define IRSND_PORT PORTD // port D\r
-# define IRSND_DDR DDRD // ddr D\r
-# define IRSND_BIT 7 // OC2\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 7\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC2 in irsndconfig.h\r
# endif // IRSND_OCx\r
#elif defined (__AVR_ATmega162__) // ATmega162 uses OC2 = PB1 or OC0 = PB0\r
# if IRSND_OCx == IRSND_OC2 // OC2\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 1 // OC2\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 1\r
# elif IRSND_OCx == IRSND_OC0 // OC0\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 0 // OC0\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 0\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC2 or IRSND_OC0 in irsndconfig.h\r
# endif // IRSND_OCx\r
|| defined (__AVR_ATmega1284__) \\r
|| defined (__AVR_ATmega1284P__) // ATmega164|324|644|644P|1284 uses OC2A = PD7 or OC2B = PD6 or OC0A = PB3 or OC0B = PB4\r
# if IRSND_OCx == IRSND_OC2A // OC2A\r
-# define IRSND_PORT PORTD // port D\r
-# define IRSND_DDR DDRD // ddr D\r
-# define IRSND_BIT 7 // OC2A\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 7\r
# elif IRSND_OCx == IRSND_OC2B // OC2B\r
-# define IRSND_PORT PORTD // port D\r
-# define IRSND_DDR DDRD // ddr D\r
-# define IRSND_BIT 6 // OC2B\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 6\r
# elif IRSND_OCx == IRSND_OC0A // OC0A\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 3 // OC0A\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 3\r
# elif IRSND_OCx == IRSND_OC0B // OC0B\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 4 // OC0B\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 4\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC2A, IRSND_OC2B, IRSND_OC0A, or IRSND_OC0B in irsndconfig.h\r
# endif // IRSND_OCx\r
|| defined (__AVR_ATmega168P__) \\r
|| defined (__AVR_ATmega328P__) // ATmega48|88|168|168|328 uses OC2A = PB3 or OC2B = PD3 or OC0A = PD6 or OC0B = PD5\r
# if IRSND_OCx == IRSND_OC2A // OC2A\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 3 // OC2A\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 3\r
# elif IRSND_OCx == IRSND_OC2B // OC2B\r
-# define IRSND_PORT PORTD // port D\r
-# define IRSND_DDR DDRD // ddr D\r
-# define IRSND_BIT 3 // OC2B\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 3\r
# elif IRSND_OCx == IRSND_OC0A // OC0A\r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 6 // OC0A\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 6\r
# elif IRSND_OCx == IRSND_OC0B // OC0B\r
-# define IRSND_PORT PORTD // port D\r
-# define IRSND_DDR DDRD // ddr D\r
-# define IRSND_BIT 5 // OC0B\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 5\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC2A, IRSND_OC2B, IRSND_OC0A, or IRSND_OC0B in irsndconfig.h\r
# endif // IRSND_OCx\r
-#elif defined (__AVR_ATmega8515__) \r
+#elif defined (__AVR_ATmega8515__) // ATmega8515 uses OC0 = PB0 or OC1A = PD5 or OC1B = PE2\r
# if IRSND_OCx == IRSND_OC0 \r
-# define IRSND_PORT PORTB // port B\r
-# define IRSND_DDR DDRB // ddr B\r
-# define IRSND_BIT 0 // OC0\r
+# define IRSND_PORT_LETTER B\r
+# define IRSND_BIT_NUMBER 0\r
# elif IRSND_OCx == IRSND_OC1A \r
-# define IRSND_PORT PORTD // port D\r
-# define IRSND_DDR DDRD // ddr D\r
-# define IRSND_BIT 5 // OC1A\r
+# define IRSND_PORT_LETTER D\r
+# define IRSND_BIT_NUMBER 5\r
# elif IRSND_OCx == IRSND_OC1B \r
-# define IRSND_PORT PORTE // port E\r
-# define IRSND_DDR DDRE // ddr E\r
-# define IRSND_BIT 2 // OC1E\r
+# define IRSND_PORT_LETTER E\r
+# define IRSND_BIT_NUMBER 2\r
# else\r
# error Wrong value for IRSND_OCx, choose IRSND_OC0, IRSND_OC1A, or IRSND_OC1B in irsndconfig.h\r
# endif // IRSND_OCx\r
# endif // unix, WIN32\r
#endif // __AVR...\r
\r
+#if defined(ATMEL_AVR)\r
+# define _CONCAT(a,b) a##b\r
+# define CONCAT(a,b) _CONCAT(a,b)\r
+# define IRSND_PORT CONCAT(PORT, IRSND_PORT_LETTER)\r
+# define IRSND_DDR CONCAT(DDR, IRSND_PORT_LETTER)\r
+# define IRSND_BIT IRSND_BIT_NUMBER\r
+#endif\r
+\r
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1\r
typedef uint16_t IRSND_PAUSE_LEN;\r
#else\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
+# else\r
+# define AVR_PRESCALER 1\r
+# endif\r
# define IRSND_FREQ_TYPE uint8_t\r
-# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 30000 / 2) - 1)\r
-# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 32000 / 2) - 1)\r
-# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 36000 / 2) - 1)\r
-# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 38000 / 2) - 1)\r
-# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 40000 / 2) - 1)\r
-# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 56000 / 2) - 1)\r
-# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 455000 / 2) - 1)\r
+# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 30000 / AVR_PRESCALER / 2) - 1)\r
+# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 32000 / AVR_PRESCALER / 2) - 1)\r
+# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 36000 / AVR_PRESCALER / 2) - 1)\r
+# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 38000 / AVR_PRESCALER / 2) - 1)\r
+# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 40000 / AVR_PRESCALER / 2) - 1)\r
+# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 56000 / AVR_PRESCALER / 2) - 1)\r
+# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 455000 / AVR_PRESCALER / 2) - 1)\r
#endif\r
\r
#define FDC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME + 0.5)\r
\r
/*---------------------------------------------------------------------------------------------------------------------------------------------------\r
* Switch PWM on\r
- * @details Switches PWM on with a narrow spike on all 3 channels -> leds glowing\r
*---------------------------------------------------------------------------------------------------------------------------------------------------\r
*/\r
static void\r
# if defined(PIC_C18) // PIC C18\r
IRSND_PIN = 0; // output mode -> enable PWM outout pin (0=PWM on, 1=PWM off)\r
# elif defined (ARM_STM32) // STM32\r
- IRSND_TIMER->CCER |= (uint16_t)TIM_CCER_CC1E;\r
- TIM_Cmd(IRSND_TIMER, ENABLE); // TIMx enable counter\r
+ TIM_SelectOCxM(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_OCMode_PWM1); // enable PWM as OC-mode\r
+ 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
# else // AVR\r
# if IRSND_OCx == IRSND_OC2 // use OC2\r
TCCR2 |= (1<<COM20)|(1<<WGM21); // toggle OC2 on compare match, clear Timer 2 at compare match OCR2\r
# if defined(PIC_C18) // PIC C18\r
IRSND_PIN = 1; //input mode -> disbale PWM output pin (0=PWM on, 1=PWM off)\r
# elif defined (ARM_STM32) // STM32\r
- IRSND_TIMER->CCER &= (uint16_t)(~(uint16_t)TIM_CCER_CC1E);\r
- TIM_Cmd(IRSND_TIMER, DISABLE); // TIMx enable counter\r
+ TIM_Cmd(IRSND_TIMER, DISABLE); // disable counter\r
+ TIM_SelectOCxM(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_ForcedAction_InActive); // force output inactive\r
+ 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
# else //AVR\r
\r
# if IRSND_OCx == IRSND_OC2 // use OC2\r
freq = TimeBaseFreq/freq;\r
\r
/* Set frequency */\r
- TIM_SetAutoreload(IRSND_TIMER, freq);\r
+ TIM_SetAutoreload(IRSND_TIMER, freq - 1);\r
/* Set duty cycle */\r
TIM_SetCompare1(IRSND_TIMER, (freq + 1) / 2);\r
# else // AVR\r
# endif\r
\r
/* Time base configuration */\r
- TIM_TimeBaseStructure.TIM_Period = 0; // will be initialized later\r
+ TIM_TimeBaseStructure.TIM_Period = -1; // set dummy value (don't set to 0), will be initialized later\r
TIM_TimeBaseStructure.TIM_Prescaler = 0;\r
TIM_TimeBaseStructure.TIM_ClockDivision = 0;\r
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;\r
/* PWM1 Mode configuration */\r
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;\r
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;\r
- TIM_OCInitStructure.TIM_Pulse = 0; // will be initialized later\r
+ TIM_OCInitStructure.TIM_Pulse = 0; // will be initialized later\r
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;\r
TIM_OC1Init(IRSND_TIMER, &TIM_OCInitStructure);\r
\r
/* Preload configuration */\r
- TIM_OC1PreloadConfig(IRSND_TIMER, TIM_OCPreload_Enable);\r
TIM_ARRPreloadConfig(IRSND_TIMER, ENABLE);\r
+ TIM_OC1PreloadConfig(IRSND_TIMER, TIM_OCPreload_Enable);\r
\r
- irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency\r
+ irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency\r
# else // AVR\r
IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low\r
IRSND_DDR |= (1<<IRSND_BIT); // set IRSND_BIT to output\r
\r
# if IRSND_OCx == IRSND_OC2 // use OC2\r
TCCR2 = (1<<WGM21); // CTC mode\r
- TCCR2 |= (1<<CS20); // 0x01, start Timer 2, no prescaling\r
+# if AVR_PRESCALER == 8\r
+ TCCR2 |= (1<<CS21); // start Timer 2, prescaler = 8\r
+# else\r
+ TCCR2 |= (1<<CS20); // start Timer 2, prescaler = 1\r
+# endif\r
# elif IRSND_OCx == IRSND_OC2A || IRSND_OCx == IRSND_OC2B // use OC2A or OC2B\r
TCCR2A = (1<<WGM21); // CTC mode\r
- TCCR2B |= (1<<CS20); // 0x01, start Timer 2, no prescaling\r
+# if AVR_PRESCALER == 8\r
+ TCCR2B = (1<<CS21); // start Timer 2, prescaler = 8\r
+# else\r
+ TCCR2B = (1<<CS20); // start Timer 2, prescaler = 1\r
+# endif\r
# elif IRSND_OCx == IRSND_OC0 // use OC0\r
TCCR0 = (1<<WGM01); // CTC mode\r
- TCCR0 |= (1<<CS00); // 0x01, start Timer 0, no prescaling\r
+# if AVR_PRESCALER == 8\r
+ TCCR0 |= (1<<CS01); // start Timer 0, prescaler = 8\r
+# else\r
+ TCCR0 |= (1<<CS00); // start Timer 0, prescaler = 1\r
+# endif\r
# elif IRSND_OCx == IRSND_OC0A || IRSND_OCx == IRSND_OC0B // use OC0A or OC0B\r
TCCR0A = (1<<WGM01); // CTC mode\r
- TCCR0B |= (1<<CS00); // 0x01, start Timer 0, no prescaling\r
+# if AVR_PRESCALER == 8\r
+ TCCR0B = (1<<CS01); // start Timer 0, prescaler = 8\r
+# else\r
+ TCCR0B = (1<<CS00); // start Timer 0, prescaler = 1\r
+# endif\r
# else\r
# error wrong value of IRSND_OCx\r
# endif\r
#if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1\r
case IRMP_KASEIKYO_PROTOCOL:\r
{\r
- uint8_t xor;\r
+ uint8_t xor_value;\r
uint16_t genre2;\r
\r
address = bitsrevervse (irmp_data_p->address, KASEIKYO_ADDRESS_LEN);\r
command = bitsrevervse (irmp_data_p->command, KASEIKYO_COMMAND_LEN + 4);\r
genre2 = bitsrevervse ((irmp_data_p->flags & ~IRSND_REPETITION_MASK) >> 4, 4);\r
\r
- xor = ((address & 0x000F) ^ ((address & 0x00F0) >> 4) ^ ((address & 0x0F00) >> 8) ^ ((address & 0xF000) >> 12)) & 0x0F;\r
+ xor_value = ((address & 0x000F) ^ ((address & 0x00F0) >> 4) ^ ((address & 0x0F00) >> 8) ^ ((address & 0xF000) >> 12)) & 0x0F;\r
\r
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA\r
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA\r
- irsnd_buffer[2] = xor << 4 | (command & 0x000F); // XXXXCCCC\r
+ irsnd_buffer[2] = xor_value << 4 | (command & 0x000F); // XXXXCCCC\r
irsnd_buffer[3] = (genre2 << 4) | (command & 0xF000) >> 12; // ggggCCCC\r
irsnd_buffer[4] = (command & 0x0FF0) >> 4; // CCCCCCCC\r
\r
- xor = irsnd_buffer[2] ^ irsnd_buffer[3] ^ irsnd_buffer[4];\r
+ xor_value = irsnd_buffer[2] ^ irsnd_buffer[3] ^ irsnd_buffer[4];\r
\r
- irsnd_buffer[5] = xor;\r
+ irsnd_buffer[5] = xor_value;\r
irsnd_busy = TRUE;\r
break;\r
}\r
case IRMP_NIKON_PROTOCOL:\r
{\r
startbit_pulse_len = NIKON_START_BIT_PULSE_LEN;\r
- startbit_pause_len = 271 - 1; // NIKON_START_BIT_PAUSE_LEN;\r
+ startbit_pause_len = NIKON_START_BIT_PAUSE_LEN;\r
complete_data_len = NIKON_COMPLETE_DATA_LEN;\r
pulse_1_len = NIKON_PULSE_LEN;\r
pause_1_len = NIKON_1_PAUSE_LEN - 1;\r
}\r
else\r
{\r
+ // printf ("current_bit: %d %d < %d %d < %d\n", current_bit, pause_counter, pause_len, pulse_counter, pulse_len);\r
+\r
if (pause_counter < pause_len)\r
{\r
if (pause_counter == 0)\r
}\r
\r
putchar ('\n');\r
+\r
+#if 1 // enable here to send twice\r
+ (void) irsnd_send_data (&irmp_data, TRUE);\r
+\r
+ while (irsnd_busy)\r
+ {\r
+ irsnd_ISR ();\r
+ }\r
+\r
+ putchar ('\n');\r
+#endif\r
}\r
else\r
{\r