1 /*---------------------------------------------------------------------------------------------------------------------------------------------------
4 * Copyright (c) 2010 Frank Meyer - frank(at)fli4l.de
6 * $Id: irsnd.c,v 1.7 2010/04/14 13:21:39 fm Exp $
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *---------------------------------------------------------------------------------------------------------------------------------------------------
15 #ifdef unix // test/debug on linux/unix
23 #define F_CPU 8000000L
27 #ifdef WIN32 // test/debug on windows
29 #define F_CPU 8000000L
30 typedef unsigned char uint8_t;
31 typedef unsigned short uint16_t;
43 #include <util/delay.h>
44 #include <avr/pgmspace.h>
50 #include "irmpconfig.h"
54 /*---------------------------------------------------------------------------------------------------------------------------------------------------
55 * Change settings from 1 to 0 if you want to disable one or more encoders.
56 * This saves program space.
59 *---------------------------------------------------------------------------------------------------------------------------------------------------
61 #define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // flag: support SIRCS uses ~150 bytes
62 #define IRSND_SUPPORT_NEC_PROTOCOL 1 // flag: support NEC uses ~100 bytes
63 #define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // flag: support Samsung + Samsung32 uses ~300 bytes
64 #define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // flag: support Matsushita uses ~150 bytes
65 #define IRSND_SUPPORT_KASEIKYO_PROTOCOL 0 // flag: support Kaseikyo NOT SUPPORTED YET!
66 #define IRSND_SUPPORT_RECS80_PROTOCOL 1 // flag: support RECS80 uses ~100 bytes
67 #define IRSND_SUPPORT_RC5_PROTOCOL 1 // flag: support RC5 uses ~250 bytes
68 #define IRSND_SUPPORT_DENON_PROTOCOL 1 // flag: support DENON uses ~200 bytes
69 #define IRSND_SUPPORT_RC6_PROTOCOL 0 // flag: support RC6 NOT SUPPORTED YET!
70 #define IRSND_SUPPORT_RECS80EXT_PROTOCOL 1 // flag: support RECS80EXT uses ~100 bytes
71 #define IRSND_SUPPORT_NUBERT_PROTOCOL 1 // flag: support NUBERT uses ~100 bytes
72 #define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 1 // flag: support Bang&Olufsen uses ~250 bytes
75 /*---------------------------------------------------------------------------------------------------------------------------------------------------
76 * Change hardware pin here:
77 *---------------------------------------------------------------------------------------------------------------------------------------------------
79 #if defined (__AVR_ATmega32__) || defined (__AVR_ATmega644P__)
80 #define IRSND_PORT PORTD // port D
81 #define IRSND_DDR DDRD // ddr D
82 #define IRSND_BIT 7 // OC2A
84 #define IRSND_PORT PORTB // port B
85 #define IRSND_DDR DDRB // ddr B
86 #define IRSND_BIT 3 // OC2A
90 #define SIRCS_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME + 0.5)
91 #define SIRCS_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME + 0.5)
92 #define SIRCS_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME + 0.5)
93 #define SIRCS_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME + 0.5)
94 #define SIRCS_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME + 0.5)
95 #define SIRCS_REPETITION_LEN (uint16_t)(F_INTERRUPTS * SIRCS_REPETITION_TIME + 0.5) // use uint16_t!
97 #define NEC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME + 0.5)
98 #define NEC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME + 0.5)
99 #define NEC_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME + 0.5)
100 #define NEC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME + 0.5)
101 #define NEC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME + 0.5)
103 #define SAMSUNG_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME + 0.5)
104 #define SAMSUNG_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME + 0.5)
105 #define SAMSUNG_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME + 0.5)
106 #define SAMSUNG_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME + 0.5)
107 #define SAMSUNG_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME + 0.5)
109 #define MATSUSHITA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME + 0.5)
110 #define MATSUSHITA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME + 0.5)
111 #define MATSUSHITA_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME + 0.5)
112 #define MATSUSHITA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME + 0.5)
113 #define MATSUSHITA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME + 0.5)
115 #define RECS80_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME + 0.5)
116 #define RECS80_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME + 0.5)
117 #define RECS80_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME + 0.5)
118 #define RECS80_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME + 0.5)
119 #define RECS80_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME + 0.5)
121 #define RC5_START_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5)
122 #define RC5_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5)
124 #define RC6_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME + 0.5)
125 #define RC6_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME + 0.5)
126 #define RC6_TOGGLE_BIT_LEN (uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME + 0.5)
127 #define RC6_BIT_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_TIME + 0.5)
129 #define DENON_PULSE_LEN (uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME + 0.5)
130 #define DENON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME + 0.5)
131 #define DENON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME + 0.5)
132 #define DENON_REPETITION_LEN (uint16_t)(F_INTERRUPTS * DENON_REPETITION_TIME + 0.5) // use uint16_t!
134 #define RECS80EXT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME + 0.5)
135 #define RECS80EXT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME + 0.5)
136 #define RECS80EXT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME + 0.5)
137 #define RECS80EXT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME + 0.5)
138 #define RECS80EXT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME + 0.5)
140 #define NUBERT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME + 0.5)
141 #define NUBERT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME + 0.5)
142 #define NUBERT_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME + 0.5)
143 #define NUBERT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME + 0.5)
144 #define NUBERT_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME + 0.5)
145 #define NUBERT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME + 0.5)
146 #define NUBERT_REPETITION_LEN (uint16_t)(F_INTERRUPTS * NUBERT_REPETITION_TIME + 0.5) // use uint16_t!
148 #define BANG_OLUFSEN_START_BIT1_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME + 0.5)
149 #define BANG_OLUFSEN_START_BIT1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME + 0.5)
150 #define BANG_OLUFSEN_START_BIT2_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME + 0.5)
151 #define BANG_OLUFSEN_START_BIT2_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME + 0.5)
152 #define BANG_OLUFSEN_START_BIT3_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME + 0.5)
153 #define BANG_OLUFSEN_START_BIT3_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME + 0.5)
154 #define BANG_OLUFSEN_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME + 0.5)
155 #define BANG_OLUFSEN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME + 0.5)
156 #define BANG_OLUFSEN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME + 0.5)
157 #define BANG_OLUFSEN_R_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME + 0.5)
158 #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME + 0.5)
160 #define IRSND_FREQ_32_KHZ (uint8_t) ((F_CPU / 32000 / 2) - 1)
161 #define IRSND_FREQ_36_KHZ (uint8_t) ((F_CPU / 36000 / 2) - 1)
162 #define IRSND_FREQ_38_KHZ (uint8_t) ((F_CPU / 38000 / 2) - 1)
163 #define IRSND_FREQ_40_KHZ (uint8_t) ((F_CPU / 40000 / 2) - 1)
164 #define IRSND_FREQ_56_KHZ (uint8_t) ((F_CPU / 56000 / 2) - 1)
165 #define IRSND_FREQ_455_KHZ (uint8_t) ((F_CPU / 455000 / 2) - 1)
167 static volatile uint8_t irsnd_busy
;
168 static volatile uint8_t irsnd_protocol
;
169 static volatile uint8_t irsnd_buffer
[5];
170 static volatile uint8_t irsnd_is_on
= FALSE
;
172 /*---------------------------------------------------------------------------------------------------------------------------------------------------
174 * @details Switches PWM on with a narrow spike on all 3 channels -> leds glowing
175 *---------------------------------------------------------------------------------------------------------------------------------------------------
183 #if defined (__AVR_ATmega32__)
184 TCCR2
|= (1<<COM20
)|(1<<WGM21
); // = 0x42: toggle OC2A on compare match, clear Timer 2 at compare match OCR2A
186 TCCR2A
|= (1<<COM2A0
)|(1<<WGM21
); // = 0x42: toggle OC2A on compare match, clear Timer 2 at compare match OCR2A
193 /*---------------------------------------------------------------------------------------------------------------------------------------------------
195 * @details Switches PWM off
196 *---------------------------------------------------------------------------------------------------------------------------------------------------
204 #if defined (__AVR_ATmega32__)
205 TCCR2
&= ~(1<<COM20
); // normal port operation, OC2A disconnected.
207 TCCR2A
&= ~(1<<COM2A0
); // normal port operation, OC2A disconnected.
209 IRSND_PORT
&= ~(1<<IRSND_BIT
); // set IRSND_BIT to low
215 /*---------------------------------------------------------------------------------------------------------------------------------------------------
217 * @details sets pwm frequency
218 *---------------------------------------------------------------------------------------------------------------------------------------------------
221 irsnd_set_freq (uint8_t freq
)
224 #if defined (__AVR_ATmega32__)
232 /*---------------------------------------------------------------------------------------------------------------------------------------------------
234 * @details Configures 0CR0A, 0CR0B and 0CR2B as PWM channels
235 *---------------------------------------------------------------------------------------------------------------------------------------------------
241 IRSND_PORT
&= ~(1<<IRSND_BIT
); // set IRSND_BIT to low
242 IRSND_DDR
|= (1<<IRSND_BIT
); // set IRSND_BIT to output
244 #if defined (__AVR_ATmega32__)
245 TCCR2
= (1<<WGM21
); // CTC mode
246 TCCR2
|= (1<<CS20
); // 0x01, start Timer 2, no prescaling
248 TCCR2A
= (1<<WGM21
); // CTC mode
249 TCCR2B
|= (1<<CS20
); // 0x01, start Timer 2, no prescaling
252 irsnd_set_freq (IRSND_FREQ_36_KHZ
); // default frequency
263 bitsrevervse (uint16_t x
, uint8_t len
)
282 irsnd_send_data (IRMP_DATA
* irmp_data_p
)
284 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
285 static uint8_t toggle_bit_recs80
;
287 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
288 static uint8_t toggle_bit_recs80ext
;
290 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
291 static uint8_t toggle_bit_rc5
;
301 irsnd_protocol
= irmp_data_p
->protocol
;
303 switch (irsnd_protocol
)
305 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
306 case IRMP_SIRCS_PROTOCOL
:
308 command
= bitsrevervse (irmp_data_p
->command
, SIRCS_MINIMUM_DATA_LEN
);
310 irsnd_protocol
= irmp_data_p
->protocol
;
311 irsnd_buffer
[0] = (command
& 0x0FF0) >> 4; // CCCCCCCC
312 irsnd_buffer
[1] = (command
& 0x000F) << 4; // CCCC0000
317 #if IRSND_SUPPORT_NEC_PROTOCOL == 1
318 case IRMP_NEC_PROTOCOL
:
320 address
= bitsrevervse (irmp_data_p
->address
, NEC_ADDRESS_LEN
);
321 command
= bitsrevervse (irmp_data_p
->command
, NEC_COMMAND_LEN
);
323 irsnd_protocol
= irmp_data_p
->protocol
;
324 irsnd_buffer
[0] = (address
& 0xFF00) >> 8; // AAAAAAAA
325 irsnd_buffer
[1] = (address
& 0x00FF); // AAAAAAAA
326 irsnd_buffer
[2] = (command
& 0xFF00) >> 8; // CCCCCCCC
327 irsnd_buffer
[3] = ~((command
& 0xFF00) >> 8); // cccccccc
332 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
333 case IRMP_SAMSUNG_PROTOCOL
:
335 address
= bitsrevervse (irmp_data_p
->address
, SAMSUNG_ADDRESS_LEN
);
336 command
= bitsrevervse (irmp_data_p
->command
, SAMSUNG_COMMAND_LEN
);
338 irsnd_protocol
= irmp_data_p
->protocol
;
339 irsnd_buffer
[0] = (address
& 0xFF00) >> 8; // AAAAAAAA
340 irsnd_buffer
[1] = (address
& 0x00FF); // AAAAAAAA
341 irsnd_buffer
[2] = (command
& 0x00F0) | ((command
& 0xF000) >> 12); // IIIICCCC
342 irsnd_buffer
[3] = ((command
& 0x0F00) >> 4) | ((~(command
& 0xF000) >> 12) & 0x0F); // CCCCcccc
343 irsnd_buffer
[4] = (~(command
& 0x0F00) >> 4) & 0xF0; // cccc0000
347 case IRMP_SAMSUNG32_PROTOCOL
:
349 address
= bitsrevervse (irmp_data_p
->address
, SAMSUNG_ADDRESS_LEN
);
350 command
= bitsrevervse (irmp_data_p
->command
, SAMSUNG32_COMMAND_LEN
);
352 irsnd_protocol
= irmp_data_p
->protocol
;
353 irsnd_buffer
[0] = (address
& 0xFF00) >> 8; // AAAAAAAA
354 irsnd_buffer
[1] = (address
& 0x00FF); // AAAAAAAA
355 irsnd_buffer
[2] = (command
& 0xFF00) >> 8; // CCCCCCCC
356 irsnd_buffer
[3] = (command
& 0x00FF); // CCCCCCCC
361 #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
362 case IRMP_MATSUSHITA_PROTOCOL
:
364 address
= bitsrevervse (irmp_data_p
->address
, MATSUSHITA_ADDRESS_LEN
);
365 command
= bitsrevervse (irmp_data_p
->command
, MATSUSHITA_COMMAND_LEN
);
367 irsnd_protocol
= irmp_data_p
->protocol
;
368 irsnd_buffer
[0] = (command
& 0x0FF0) >> 4; // CCCCCCCC
369 irsnd_buffer
[1] = ((command
& 0x000F) << 4) | ((address
& 0x0F00) >> 8); // CCCCAAAA
370 irsnd_buffer
[2] = (address
& 0x00FF); // AAAAAAAA
375 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
376 case IRMP_RECS80_PROTOCOL
:
378 toggle_bit_recs80
= toggle_bit_recs80
? 0x00 : 0x40;
380 irsnd_protocol
= irmp_data_p
->protocol
;
381 irsnd_buffer
[0] = 0x80 | toggle_bit_recs80
| ((irmp_data_p
->address
& 0x0007) << 3) |
382 ((irmp_data_p
->command
& 0x0038) >> 3); // STAAACCC
383 irsnd_buffer
[1] = (irmp_data_p
->command
& 0x07) << 5; // CCC00000
388 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
389 case IRMP_RECS80EXT_PROTOCOL
:
391 toggle_bit_recs80ext
= toggle_bit_recs80ext
? 0x00 : 0x40;
393 irsnd_protocol
= irmp_data_p
->protocol
;
394 irsnd_buffer
[0] = 0x80 | toggle_bit_recs80ext
| ((irmp_data_p
->address
& 0x000F) << 2) |
395 ((irmp_data_p
->command
& 0x0030) >> 4); // STAAAACC
396 irsnd_buffer
[1] = (irmp_data_p
->command
& 0x0F) << 4; // CCCC0000
401 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
402 case IRMP_RC5_PROTOCOL
:
404 toggle_bit_rc5
= toggle_bit_rc5
? 0x00 : 0x40;
406 irsnd_protocol
= irmp_data_p
->protocol
;
407 irsnd_buffer
[0] = ((irmp_data_p
->command
& 0x40) ? 0x00 : 0x80) | toggle_bit_rc5
|
408 ((irmp_data_p
->address
& 0x001F) << 1) | ((irmp_data_p
->command
& 0x20) >> 5); // CTAAAAAC
409 irsnd_buffer
[1] = (irmp_data_p
->command
& 0x1F) << 3; // CCCCC000
414 #if IRSND_SUPPORT_DENON_PROTOCOL == 1
415 case IRMP_DENON_PROTOCOL
:
417 irsnd_protocol
= irmp_data_p
->protocol
;
418 irsnd_buffer
[0] = ((irmp_data_p
->address
& 0x1F) << 3) | ((irmp_data_p
->command
& 0x0380) >> 7); // AAAAACCC
419 irsnd_buffer
[1] = (irmp_data_p
->command
& 0x7F) << 1; // CCCCCCC0
420 irsnd_buffer
[2] = ((irmp_data_p
->address
& 0x1F) << 3) | (((~irmp_data_p
->command
) & 0x0380) >> 7); // AAAAACCC
421 irsnd_buffer
[3] = (~(irmp_data_p
->command
) & 0x7F) << 1; // CCCCCCC0
426 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
427 case IRMP_NUBERT_PROTOCOL
:
429 irsnd_protocol
= irmp_data_p
->protocol
;
430 irsnd_buffer
[0] = irmp_data_p
->command
>> 2; // CCCCCCCC
431 irsnd_buffer
[1] = (irmp_data_p
->command
& 0x0003) << 6; // CC000000
436 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
437 case IRMP_BANG_OLUFSEN_PROTOCOL
:
439 irsnd_protocol
= irmp_data_p
->protocol
;
440 irsnd_buffer
[0] = irmp_data_p
->command
>> 11; // SXSCCCCC
441 irsnd_buffer
[1] = irmp_data_p
->command
>> 3; // CCCCCCCC
442 irsnd_buffer
[2] = (irmp_data_p
->command
& 0x0007) << 5; // CCC00000
456 /*---------------------------------------------------------------------------------------------------------------------------------------------------
458 * @details ISR routine, called 10000 times per second
459 *---------------------------------------------------------------------------------------------------------------------------------------------------
464 static uint8_t current_bit
= 0xFF;
465 static uint8_t pulse_counter
;
466 static uint8_t pause_counter
;
467 static uint8_t startbit_pulse_len
;
468 static uint8_t startbit_pause_len
;
469 static uint8_t pulse_1_len
;
470 static uint8_t pause_1_len
;
471 static uint8_t pulse_0_len
;
472 static uint8_t pause_0_len
;
473 static uint8_t has_stop_bit
;
474 static uint8_t new_frame
= TRUE
;
475 static uint8_t complete_data_len
;
476 static uint8_t n_frames
; // number of repetitions
477 static uint8_t frame_counter
; // repetition counter
478 static uint16_t repetition_pause
; // pause before repetition, uint16_t!
479 static uint16_t repetition_pause_counter
; // pause before repetition, uint16_t!
480 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
481 static uint8_t last_bit_value
;
483 static uint8_t pulse_len
= 0xFF;
484 static uint8_t pause_len
= 0xFF;
488 if (current_bit
== 0xFF && new_frame
) // start of transmission...
490 if (frame_counter
> 0)
492 repetition_pause_counter
++;
494 if (repetition_pause_counter
>= repetition_pause
)
496 repetition_pause_counter
= 0;
498 if (irsnd_protocol
== IRMP_DENON_PROTOCOL
)
501 complete_data_len
= 2 * DENON_COMPLETE_DATA_LEN
+ 1;
524 switch (irsnd_protocol
)
526 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
527 case IRMP_SIRCS_PROTOCOL
:
529 startbit_pulse_len
= SIRCS_START_BIT_PULSE_LEN
;
530 startbit_pause_len
= SIRCS_START_BIT_PAUSE_LEN
;
531 pulse_1_len
= SIRCS_1_PULSE_LEN
;
532 pause_1_len
= SIRCS_PAUSE_LEN
;
533 pulse_0_len
= SIRCS_0_PULSE_LEN
;
534 pause_0_len
= SIRCS_PAUSE_LEN
;
535 has_stop_bit
= SIRCS_STOP_BIT
;
536 complete_data_len
= SIRCS_MINIMUM_DATA_LEN
;
537 n_frames
= SIRCS_REPETITION_CNT
;
538 repetition_pause
= SIRCS_REPETITION_LEN
; // 45 ms pause
539 irsnd_set_freq (IRSND_FREQ_40_KHZ
);
543 #if IRSND_SUPPORT_NEC_PROTOCOL == 1
544 case IRMP_NEC_PROTOCOL
:
546 startbit_pulse_len
= NEC_START_BIT_PULSE_LEN
;
547 startbit_pause_len
= NEC_START_BIT_PAUSE_LEN
;
548 pulse_1_len
= NEC_PULSE_LEN
;
549 pause_1_len
= NEC_1_PAUSE_LEN
;
550 pulse_0_len
= NEC_PULSE_LEN
;
551 pause_0_len
= NEC_0_PAUSE_LEN
;
552 has_stop_bit
= NEC_STOP_BIT
;
553 complete_data_len
= NEC_COMPLETE_DATA_LEN
;
555 irsnd_set_freq (IRSND_FREQ_38_KHZ
);
559 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
560 case IRMP_SAMSUNG_PROTOCOL
:
562 startbit_pulse_len
= SAMSUNG_START_BIT_PULSE_LEN
;
563 startbit_pause_len
= SAMSUNG_START_BIT_PAUSE_LEN
;
564 pulse_1_len
= SAMSUNG_PULSE_LEN
;
565 pause_1_len
= SAMSUNG_1_PAUSE_LEN
;
566 pulse_0_len
= SAMSUNG_PULSE_LEN
;
567 pause_0_len
= SAMSUNG_0_PAUSE_LEN
;
568 has_stop_bit
= SAMSUNG_STOP_BIT
;
569 complete_data_len
= SAMSUNG_COMPLETE_DATA_LEN
;
571 irsnd_set_freq (IRSND_FREQ_38_KHZ
);
575 case IRMP_SAMSUNG32_PROTOCOL
:
577 startbit_pulse_len
= SAMSUNG_START_BIT_PULSE_LEN
;
578 startbit_pause_len
= SAMSUNG_START_BIT_PAUSE_LEN
;
579 pulse_1_len
= SAMSUNG_PULSE_LEN
;
580 pause_1_len
= SAMSUNG_1_PAUSE_LEN
;
581 pulse_0_len
= SAMSUNG_PULSE_LEN
;
582 pause_0_len
= SAMSUNG_0_PAUSE_LEN
;
583 has_stop_bit
= SAMSUNG_STOP_BIT
;
584 complete_data_len
= SAMSUNG32_COMPLETE_DATA_LEN
;
586 irsnd_set_freq (IRSND_FREQ_38_KHZ
);
590 #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
591 case IRMP_MATSUSHITA_PROTOCOL
:
593 startbit_pulse_len
= MATSUSHITA_START_BIT_PULSE_LEN
;
594 startbit_pause_len
= MATSUSHITA_START_BIT_PAUSE_LEN
;
595 pulse_1_len
= MATSUSHITA_PULSE_LEN
;
596 pause_1_len
= MATSUSHITA_1_PAUSE_LEN
;
597 pulse_0_len
= MATSUSHITA_PULSE_LEN
;
598 pause_0_len
= MATSUSHITA_0_PAUSE_LEN
;
599 has_stop_bit
= MATSUSHITA_STOP_BIT
;
600 complete_data_len
= MATSUSHITA_COMPLETE_DATA_LEN
;
602 irsnd_set_freq (IRSND_FREQ_36_KHZ
);
606 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
607 case IRMP_RECS80_PROTOCOL
:
609 startbit_pulse_len
= RECS80_START_BIT_PULSE_LEN
;
610 startbit_pause_len
= RECS80_START_BIT_PAUSE_LEN
;
611 pulse_1_len
= RECS80_PULSE_LEN
;
612 pause_1_len
= RECS80_1_PAUSE_LEN
;
613 pulse_0_len
= RECS80_PULSE_LEN
;
614 pause_0_len
= RECS80_0_PAUSE_LEN
;
615 has_stop_bit
= RECS80_STOP_BIT
;
616 complete_data_len
= RECS80_COMPLETE_DATA_LEN
;
618 irsnd_set_freq (IRSND_FREQ_38_KHZ
);
622 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
623 case IRMP_RECS80EXT_PROTOCOL
:
625 startbit_pulse_len
= RECS80EXT_START_BIT_PULSE_LEN
;
626 startbit_pause_len
= RECS80EXT_START_BIT_PAUSE_LEN
;
627 pulse_1_len
= RECS80EXT_PULSE_LEN
;
628 pause_1_len
= RECS80EXT_1_PAUSE_LEN
;
629 pulse_0_len
= RECS80EXT_PULSE_LEN
;
630 pause_0_len
= RECS80EXT_0_PAUSE_LEN
;
631 has_stop_bit
= RECS80EXT_STOP_BIT
;
632 complete_data_len
= RECS80EXT_COMPLETE_DATA_LEN
;
634 irsnd_set_freq (IRSND_FREQ_38_KHZ
);
638 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
639 case IRMP_RC5_PROTOCOL
:
641 startbit_pulse_len
= RC5_BIT_LEN
;
642 startbit_pause_len
= RC5_BIT_LEN
;
643 pulse_1_len
= RC5_BIT_LEN
;
644 pause_1_len
= RC5_BIT_LEN
;
645 pulse_0_len
= RC5_BIT_LEN
;
646 pause_0_len
= RC5_BIT_LEN
;
647 has_stop_bit
= RC5_STOP_BIT
;
648 complete_data_len
= RC5_COMPLETE_DATA_LEN
;
650 irsnd_set_freq (IRSND_FREQ_36_KHZ
);
654 #if IRSND_SUPPORT_DENON_PROTOCOL == 1
655 case IRMP_DENON_PROTOCOL
:
657 startbit_pulse_len
= 0x00;
658 startbit_pause_len
= 0x00;
659 pulse_1_len
= DENON_PULSE_LEN
;
660 pause_1_len
= DENON_1_PAUSE_LEN
;
661 pulse_0_len
= DENON_PULSE_LEN
;
662 pause_0_len
= DENON_0_PAUSE_LEN
;
663 has_stop_bit
= DENON_STOP_BIT
;
664 complete_data_len
= DENON_COMPLETE_DATA_LEN
;
666 repetition_pause
= DENON_REPETITION_LEN
; // 65 ms pause after 1st frame (15 bits)
667 irsnd_set_freq (IRSND_FREQ_32_KHZ
);
671 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
672 case IRMP_NUBERT_PROTOCOL
:
674 startbit_pulse_len
= NUBERT_START_BIT_PULSE_LEN
;
675 startbit_pause_len
= NUBERT_START_BIT_PAUSE_LEN
;
676 pulse_1_len
= NUBERT_1_PULSE_LEN
;
677 pause_1_len
= NUBERT_1_PAUSE_LEN
;
678 pulse_0_len
= NUBERT_0_PULSE_LEN
;
679 pause_0_len
= NUBERT_0_PAUSE_LEN
;
680 has_stop_bit
= NUBERT_STOP_BIT
;
681 complete_data_len
= NUBERT_COMPLETE_DATA_LEN
;
683 repetition_pause
= NUBERT_REPETITION_LEN
; // 35 ms pause
684 irsnd_set_freq (IRSND_FREQ_36_KHZ
);
688 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
689 case IRMP_BANG_OLUFSEN_PROTOCOL
:
691 startbit_pulse_len
= BANG_OLUFSEN_START_BIT1_PULSE_LEN
;
692 startbit_pause_len
= BANG_OLUFSEN_START_BIT1_PAUSE_LEN
;
693 pulse_1_len
= BANG_OLUFSEN_PULSE_LEN
;
694 pause_1_len
= BANG_OLUFSEN_1_PAUSE_LEN
;
695 pulse_0_len
= BANG_OLUFSEN_PULSE_LEN
;
696 pause_0_len
= BANG_OLUFSEN_0_PAUSE_LEN
;
697 has_stop_bit
= BANG_OLUFSEN_STOP_BIT
;
698 complete_data_len
= BANG_OLUFSEN_COMPLETE_DATA_LEN
;
701 irsnd_set_freq (IRSND_FREQ_455_KHZ
);
717 switch (irsnd_protocol
)
719 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
720 case IRMP_SIRCS_PROTOCOL
:
722 #if IRSND_SUPPORT_NEC_PROTOCOL == 1
723 case IRMP_NEC_PROTOCOL
:
725 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
726 case IRMP_SAMSUNG_PROTOCOL
:
727 case IRMP_SAMSUNG32_PROTOCOL
:
729 #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
730 case IRMP_MATSUSHITA_PROTOCOL
:
732 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
733 case IRMP_RECS80_PROTOCOL
:
735 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
736 case IRMP_RECS80EXT_PROTOCOL
:
738 #if IRSND_SUPPORT_DENON_PROTOCOL == 1
739 case IRMP_DENON_PROTOCOL
:
741 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
742 case IRMP_NUBERT_PROTOCOL
:
744 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
745 case IRMP_BANG_OLUFSEN_PROTOCOL
:
748 if (pulse_counter
== 0)
750 if (current_bit
== 0xFF) // send start bit
752 pulse_len
= startbit_pulse_len
;
753 pause_len
= startbit_pause_len
;
755 else if (current_bit
< complete_data_len
) // send n'th bit
757 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
758 if (irsnd_protocol
== IRMP_SAMSUNG_PROTOCOL
)
760 if (current_bit
< SAMSUNG_ADDRESS_LEN
) // send address bits
762 pulse_len
= SAMSUNG_PULSE_LEN
;
763 pause_len
= (irsnd_buffer
[current_bit
/ 8] & (1<<(7-(current_bit
% 8)))) ?
764 SAMSUNG_1_PAUSE_LEN
: SAMSUNG_0_PAUSE_LEN
;
766 else if (current_bit
== SAMSUNG_ADDRESS_LEN
) // send SYNC bit (16th bit)
768 pulse_len
= SAMSUNG_PULSE_LEN
;
769 pause_len
= SAMSUNG_START_BIT_PAUSE_LEN
;
771 else if (current_bit
< SAMSUNG_COMPLETE_DATA_LEN
) // send n'th bit
773 uint8_t cur_bit
= current_bit
- 1; // sync skipped, offset = -1 !
775 pulse_len
= SAMSUNG_PULSE_LEN
;
776 pause_len
= (irsnd_buffer
[cur_bit
/ 8] & (1<<(7-(cur_bit
% 8)))) ?
777 SAMSUNG_1_PAUSE_LEN
: SAMSUNG_0_PAUSE_LEN
;
783 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
784 if (irsnd_protocol
== IRMP_BANG_OLUFSEN_PROTOCOL
)
786 if (current_bit
== 0) // send 2nd start bit
788 pulse_len
= BANG_OLUFSEN_START_BIT2_PULSE_LEN
;
789 pause_len
= BANG_OLUFSEN_START_BIT2_PAUSE_LEN
;
791 else if (current_bit
== 1) // send 3rd start bit
793 pulse_len
= BANG_OLUFSEN_START_BIT3_PULSE_LEN
;
794 pause_len
= BANG_OLUFSEN_START_BIT3_PAUSE_LEN
;
796 else if (current_bit
== 2) // send 4th start bit
798 pulse_len
= BANG_OLUFSEN_START_BIT2_PULSE_LEN
;
799 pause_len
= BANG_OLUFSEN_START_BIT2_PAUSE_LEN
;
801 else if (current_bit
== 19) // send trailer bit
803 pulse_len
= BANG_OLUFSEN_PULSE_LEN
;
804 pause_len
= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN
;
806 else if (current_bit
< BANG_OLUFSEN_COMPLETE_DATA_LEN
) // send n'th bit
808 uint8_t cur_bit_value
= (irsnd_buffer
[current_bit
/ 8] & (1<<(7-(current_bit
% 8)))) ? 1 : 0;
809 pulse_len
= BANG_OLUFSEN_PULSE_LEN
;
811 if (cur_bit_value
== last_bit_value
)
813 pause_len
= BANG_OLUFSEN_R_PAUSE_LEN
;
817 pause_len
= cur_bit_value
? BANG_OLUFSEN_1_PAUSE_LEN
: BANG_OLUFSEN_0_PAUSE_LEN
;
818 last_bit_value
= cur_bit_value
;
824 if (irsnd_buffer
[current_bit
/ 8] & (1<<(7-(current_bit
% 8))))
826 pulse_len
= pulse_1_len
;
827 pause_len
= pause_1_len
;
831 pulse_len
= pulse_0_len
;
832 pause_len
= pause_0_len
;
835 else if (has_stop_bit
) // send stop bit
837 pulse_len
= pulse_0_len
;
839 if (frame_counter
< n_frames
)
841 pause_len
= pause_0_len
;
845 pause_len
= 255; // last frame: pause of 255
850 if (pulse_counter
< pulse_len
)
852 if (pulse_counter
== 0)
858 else if (pause_counter
< pause_len
)
860 if (pause_counter
== 0)
870 if (current_bit
>= complete_data_len
+ has_stop_bit
)
875 if (frame_counter
== n_frames
)
888 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
889 case IRMP_RC5_PROTOCOL
:
892 uint8_t next_bit
= FALSE
;
894 if (current_bit
== 0xFF) // 1 start bit
898 else // send n'th bit
900 first_pulse
= (irsnd_buffer
[current_bit
/ 8] & (1<<(7-(current_bit
% 8)))) ? FALSE
: TRUE
;
905 if (pulse_counter
< RC5_BIT_LEN
)
907 if (pulse_counter
== 0)
913 else if (pause_counter
< RC5_BIT_LEN
)
915 if (pause_counter
== 0)
928 if (pause_counter
< RC5_BIT_LEN
)
930 if (pause_counter
== 0)
936 else if (pulse_counter
< RC5_BIT_LEN
)
938 if (pulse_counter
== 0)
954 if (current_bit
>= RC5_COMPLETE_DATA_LEN
)
967 #endif // IRSND_SUPPORT_RC5_PROTOCOL
993 // main function - for unix/linux + windows only!
995 // Compile it under linux with:
996 // cc irsnd.c -o irsnd
998 // usage: ./irsnd protocol hex-address hex-command >filename
1001 main (int argc
, char ** argv
)
1009 IRMP_DATA irmp_data
;
1013 fprintf (stderr
, "usage: %s protocol hex-address hex-command > filename\n", argv
[0]);
1017 if (sscanf (argv
[1], "%d", &protocol
) == 1 &&
1018 sscanf (argv
[2], "%x", &address
) == 1 &&
1019 sscanf (argv
[3], "%x", &command
) == 1)
1021 irmp_data
.protocol
= protocol
;
1022 irmp_data
.address
= address
;
1023 irmp_data
.command
= command
;
1027 for (cnt
= 0; cnt
< repeat
; cnt
++)
1029 (void) irsnd_send_data (&irmp_data
);
1031 for (idx
= 0; idx
< 3000; idx
++)
1041 fprintf (stderr
, "%s: wrong arguments\n", argv
[0]);