]> cloudbase.mooo.com Git - irmp.git/blob - irsnd.c
Version 1.5.0: added Siemens Gigaset protocol, added frame repeat for irsnd
[irmp.git] / irsnd.c
1 /*---------------------------------------------------------------------------------------------------------------------------------------------------
2 * @file irsnd.c
3 *
4 * Copyright (c) 2010 Frank Meyer - frank(at)fli4l.de
5 *
6 * $Id: irsnd.c,v 1.15 2010/06/02 13:18:03 fm Exp $
7 *
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 *---------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14
15 #ifdef unix // test/debug on linux/unix
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <inttypes.h>
21
22 #define DEBUG
23 #define F_CPU 8000000L
24
25 #else // not unix:
26
27 #ifdef WIN32 // test/debug on windows
28 #include <stdio.h>
29 #define F_CPU 8000000L
30 typedef unsigned char uint8_t;
31 typedef unsigned short uint16_t;
32 #define DEBUG
33
34 #else
35
36 #ifdef CODEVISION
37 #define COM2A0 6
38 #define WGM21 1
39 #define CS20 0
40 #else
41 #include <inttypes.h>
42 #include <avr/io.h>
43 #include <util/delay.h>
44 #include <avr/pgmspace.h>
45 #endif // CODEVISION
46
47 #endif // WIN32
48 #endif // unix
49
50 #include "irmp.h"
51 #include "irsndconfig.h"
52 #include "irsnd.h"
53
54 #define SIRCS_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME + 0.5)
55 #define SIRCS_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME + 0.5)
56 #define SIRCS_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME + 0.5)
57 #define SIRCS_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME + 0.5)
58 #define SIRCS_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME + 0.5)
59 #define SIRCS_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIRCS_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
60 #define SIRCS_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIRCS_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
61
62 #define NEC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME + 0.5)
63 #define NEC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME + 0.5)
64 #define NEC_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME + 0.5)
65 #define NEC_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME + 0.5)
66 #define NEC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME + 0.5)
67 #define NEC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME + 0.5)
68 #define NEC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
69
70 #define SAMSUNG_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME + 0.5)
71 #define SAMSUNG_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME + 0.5)
72 #define SAMSUNG_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME + 0.5)
73 #define SAMSUNG_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME + 0.5)
74 #define SAMSUNG_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME + 0.5)
75 #define SAMSUNG_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
76
77 #define SAMSUNG32_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG32_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
78 #define SAMSUNG32_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG32_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
79
80 #define MATSUSHITA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME + 0.5)
81 #define MATSUSHITA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME + 0.5)
82 #define MATSUSHITA_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME + 0.5)
83 #define MATSUSHITA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME + 0.5)
84 #define MATSUSHITA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME + 0.5)
85 #define MATSUSHITA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MATSUSHITA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
86
87 #define RECS80_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME + 0.5)
88 #define RECS80_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME + 0.5)
89 #define RECS80_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME + 0.5)
90 #define RECS80_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME + 0.5)
91 #define RECS80_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME + 0.5)
92 #define RECS80_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RECS80_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
93
94 #define RC5_START_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5)
95 #define RC5_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5)
96 #define RC5_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RC5_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
97
98 #define RC6_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME + 0.5)
99 #define RC6_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME + 0.5)
100 #define RC6_TOGGLE_BIT_LEN (uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME + 0.5)
101 #define RC6_BIT_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_TIME + 0.5)
102 #define RC6_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RC6_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
103
104 #define DENON_PULSE_LEN (uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME + 0.5)
105 #define DENON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME + 0.5)
106 #define DENON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME + 0.5)
107 #define DENON_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * DENON_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
108 #define DENON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * DENON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
109
110 #define RECS80EXT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME + 0.5)
111 #define RECS80EXT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME + 0.5)
112 #define RECS80EXT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME + 0.5)
113 #define RECS80EXT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME + 0.5)
114 #define RECS80EXT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME + 0.5)
115 #define RECS80EXT_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RECS80EXT_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
116
117 #define NUBERT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME + 0.5)
118 #define NUBERT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME + 0.5)
119 #define NUBERT_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME + 0.5)
120 #define NUBERT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME + 0.5)
121 #define NUBERT_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME + 0.5)
122 #define NUBERT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME + 0.5)
123 #define NUBERT_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NUBERT_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
124 #define NUBERT_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NUBERT_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
125
126 #define BANG_OLUFSEN_START_BIT1_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME + 0.5)
127 #define BANG_OLUFSEN_START_BIT1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME + 0.5)
128 #define BANG_OLUFSEN_START_BIT2_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME + 0.5)
129 #define BANG_OLUFSEN_START_BIT2_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME + 0.5)
130 #define BANG_OLUFSEN_START_BIT3_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME + 0.5)
131 #define BANG_OLUFSEN_START_BIT3_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME + 0.5)
132 #define BANG_OLUFSEN_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME + 0.5)
133 #define BANG_OLUFSEN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME + 0.5)
134 #define BANG_OLUFSEN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME + 0.5)
135 #define BANG_OLUFSEN_R_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME + 0.5)
136 #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME + 0.5)
137 #define BANG_OLUFSEN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
138
139 #define GRUNDIG_OR_NOKIA_PRE_PAUSE_LEN (uint8_t)(F_INTERRUPTS * GRUNDIG_OR_NOKIA_PRE_PAUSE_TIME + 0.5)
140 #define GRUNDIG_OR_NOKIA_BIT_LEN (uint8_t)(F_INTERRUPTS * GRUNDIG_OR_NOKIA_BIT_TIME + 0.5)
141 #define GRUNDIG_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * GRUNDIG_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
142 #define NOKIA_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NOKIA_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
143 #define GRUNDIG_OR_NOKIA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * GRUNDIG_OR_NOKIA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
144
145 #define SIEMENS_START_BIT_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_BIT_TIME + 0.5)
146 #define SIEMENS_BIT_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_BIT_TIME + 0.5)
147 #define SIEMENS_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIEMENS_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
148
149 #define IRSND_FREQ_32_KHZ (uint8_t) ((F_CPU / 32000 / 2) - 1)
150 #define IRSND_FREQ_36_KHZ (uint8_t) ((F_CPU / 36000 / 2) - 1)
151 #define IRSND_FREQ_38_KHZ (uint8_t) ((F_CPU / 38000 / 2) - 1)
152 #define IRSND_FREQ_40_KHZ (uint8_t) ((F_CPU / 40000 / 2) - 1)
153 #define IRSND_FREQ_56_KHZ (uint8_t) ((F_CPU / 56000 / 2) - 1)
154 #define IRSND_FREQ_455_KHZ (uint8_t) ((F_CPU / 455000 / 2) - 1)
155
156 static volatile uint8_t irsnd_busy;
157 static volatile uint8_t irsnd_protocol;
158 static volatile uint8_t irsnd_buffer[6];
159 static volatile uint8_t irsnd_repeat;
160 static volatile uint8_t irsnd_is_on = FALSE;
161
162 /*---------------------------------------------------------------------------------------------------------------------------------------------------
163 * Switch PWM on
164 * @details Switches PWM on with a narrow spike on all 3 channels -> leds glowing
165 *---------------------------------------------------------------------------------------------------------------------------------------------------
166 */
167 static void
168 irsnd_on (void)
169 {
170 if (! irsnd_is_on)
171 {
172 #ifndef DEBUG
173 #if defined (__AVR_ATmega32__)
174 TCCR2 |= (1<<COM20)|(1<<WGM21); // = 0x42: toggle OC2A on compare match, clear Timer 2 at compare match OCR2A
175 #else
176 TCCR2A |= (1<<COM2A0)|(1<<WGM21); // = 0x42: toggle OC2A on compare match, clear Timer 2 at compare match OCR2A
177 #endif // __AVR...
178 #endif // DEBUG
179 irsnd_is_on = TRUE;
180 }
181 }
182
183 /*---------------------------------------------------------------------------------------------------------------------------------------------------
184 * Switch PWM off
185 * @details Switches PWM off
186 *---------------------------------------------------------------------------------------------------------------------------------------------------
187 */
188 static void
189 irsnd_off (void)
190 {
191 if (irsnd_is_on)
192 {
193 #ifndef DEBUG
194 #if defined (__AVR_ATmega32__)
195 TCCR2 &= ~(1<<COM20); // normal port operation, OC2A disconnected.
196 #else
197 TCCR2A &= ~(1<<COM2A0); // normal port operation, OC2A disconnected.
198 #endif // __AVR...
199 IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low
200 #endif // DEBUG
201 irsnd_is_on = FALSE;
202 }
203 }
204
205 /*---------------------------------------------------------------------------------------------------------------------------------------------------
206 * Set PWM frequency
207 * @details sets pwm frequency
208 *---------------------------------------------------------------------------------------------------------------------------------------------------
209 */
210 static void
211 irsnd_set_freq (uint8_t freq)
212 {
213 #ifndef DEBUG
214 #if defined (__AVR_ATmega32__)
215 OCR2 = freq;
216 #else
217 OCR2A = freq;
218 #endif // __AVR...
219 #endif // DEBUG
220 }
221
222 /*---------------------------------------------------------------------------------------------------------------------------------------------------
223 * Initialize the PWM
224 * @details Configures 0CR0A, 0CR0B and 0CR2B as PWM channels
225 *---------------------------------------------------------------------------------------------------------------------------------------------------
226 */
227 void
228 irsnd_init (void)
229 {
230 #ifndef DEBUG
231 IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low
232 IRSND_DDR |= (1<<IRSND_BIT); // set IRSND_BIT to output
233
234 #if defined (__AVR_ATmega32__)
235 TCCR2 = (1<<WGM21); // CTC mode
236 TCCR2 |= (1<<CS20); // 0x01, start Timer 2, no prescaling
237 #else
238 TCCR2A = (1<<WGM21); // CTC mode
239 TCCR2B |= (1<<CS20); // 0x01, start Timer 2, no prescaling
240 #endif // __AVR...
241
242 irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency
243 #endif // DEBUG
244 }
245
246 uint8_t
247 irsnd_is_busy (void)
248 {
249 return irsnd_busy;
250 }
251
252 static uint16_t
253 bitsrevervse (uint16_t x, uint8_t len)
254 {
255 uint16_t xx = 0;
256
257 while(len)
258 {
259 xx <<= 1;
260 if (x & 1)
261 {
262 xx |= 1;
263 }
264 x >>= 1;
265 len--;
266 }
267 return xx;
268 }
269
270
271 uint8_t
272 irsnd_send_data (IRMP_DATA * irmp_data_p)
273 {
274 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
275 static uint8_t toggle_bit_recs80;
276 #endif
277 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
278 static uint8_t toggle_bit_recs80ext;
279 #endif
280 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
281 static uint8_t toggle_bit_rc5;
282 #endif
283 uint16_t address;
284 uint16_t command;
285
286 while (irsnd_busy)
287 {
288 ;
289 }
290
291 irsnd_protocol = irmp_data_p->protocol;
292 irsnd_repeat = irmp_data_p->flags;
293
294 switch (irsnd_protocol)
295 {
296 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
297 case IRMP_SIRCS_PROTOCOL:
298 {
299 command = bitsrevervse (irmp_data_p->command, SIRCS_MINIMUM_DATA_LEN);
300
301 irsnd_buffer[0] = (command & 0x0FF0) >> 4; // CCCCCCCC
302 irsnd_buffer[1] = (command & 0x000F) << 4; // CCCC0000
303 irsnd_busy = TRUE;
304 break;
305 }
306 #endif
307 #if IRSND_SUPPORT_NEC_PROTOCOL == 1
308 case IRMP_NEC_PROTOCOL:
309 case IRMP_APPLE_PROTOCOL:
310 {
311 address = bitsrevervse (irmp_data_p->address, NEC_ADDRESS_LEN);
312 command = bitsrevervse (irmp_data_p->command, NEC_COMMAND_LEN);
313
314 irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
315 irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
316 irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC
317
318 if (irsnd_protocol == IRMP_APPLE_PROTOCOL)
319 {
320 irsnd_protocol = IRMP_NEC_PROTOCOL; // APPLE protocol is NEC with fix bitmask instead of inverted command
321 irsnd_buffer[3] = 0x8B; // 10001011
322 }
323 else
324 {
325 irsnd_buffer[3] = ~((command & 0xFF00) >> 8); // cccccccc
326 }
327
328 irsnd_busy = TRUE;
329 break;
330 }
331 #endif
332 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
333 case IRMP_SAMSUNG_PROTOCOL:
334 {
335 address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN);
336 command = bitsrevervse (irmp_data_p->command, SAMSUNG_COMMAND_LEN);
337
338 irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
339 irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
340 irsnd_buffer[2] = (command & 0x00F0) | ((command & 0xF000) >> 12); // IIIICCCC
341 irsnd_buffer[3] = ((command & 0x0F00) >> 4) | ((~(command & 0xF000) >> 12) & 0x0F); // CCCCcccc
342 irsnd_buffer[4] = (~(command & 0x0F00) >> 4) & 0xF0; // cccc0000
343 irsnd_busy = TRUE;
344 break;
345 }
346 case IRMP_SAMSUNG32_PROTOCOL:
347 {
348 address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN);
349 command = bitsrevervse (irmp_data_p->command, SAMSUNG32_COMMAND_LEN);
350
351 irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
352 irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
353 irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC
354 irsnd_buffer[3] = (command & 0x00FF); // CCCCCCCC
355 irsnd_busy = TRUE;
356 break;
357 }
358 #endif
359 #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
360 case IRMP_MATSUSHITA_PROTOCOL:
361 {
362 address = bitsrevervse (irmp_data_p->address, MATSUSHITA_ADDRESS_LEN);
363 command = bitsrevervse (irmp_data_p->command, MATSUSHITA_COMMAND_LEN);
364
365 irsnd_buffer[0] = (command & 0x0FF0) >> 4; // CCCCCCCC
366 irsnd_buffer[1] = ((command & 0x000F) << 4) | ((address & 0x0F00) >> 8); // CCCCAAAA
367 irsnd_buffer[2] = (address & 0x00FF); // AAAAAAAA
368 irsnd_busy = TRUE;
369 break;
370 }
371 #endif
372 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
373 case IRMP_RECS80_PROTOCOL:
374 {
375 toggle_bit_recs80 = toggle_bit_recs80 ? 0x00 : 0x40;
376
377 irsnd_buffer[0] = 0x80 | toggle_bit_recs80 | ((irmp_data_p->address & 0x0007) << 3) |
378 ((irmp_data_p->command & 0x0038) >> 3); // STAAACCC
379 irsnd_buffer[1] = (irmp_data_p->command & 0x07) << 5; // CCC00000
380 irsnd_busy = TRUE;
381 break;
382 }
383 #endif
384 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
385 case IRMP_RECS80EXT_PROTOCOL:
386 {
387 toggle_bit_recs80ext = toggle_bit_recs80ext ? 0x00 : 0x40;
388
389 irsnd_buffer[0] = 0x80 | toggle_bit_recs80ext | ((irmp_data_p->address & 0x000F) << 2) |
390 ((irmp_data_p->command & 0x0030) >> 4); // STAAAACC
391 irsnd_buffer[1] = (irmp_data_p->command & 0x0F) << 4; // CCCC0000
392 irsnd_busy = TRUE;
393 break;
394 }
395 #endif
396 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
397 case IRMP_RC5_PROTOCOL:
398 {
399 toggle_bit_rc5 = toggle_bit_rc5 ? 0x00 : 0x40;
400
401 irsnd_buffer[0] = ((irmp_data_p->command & 0x40) ? 0x00 : 0x80) | toggle_bit_rc5 |
402 ((irmp_data_p->address & 0x001F) << 1) | ((irmp_data_p->command & 0x20) >> 5); // CTAAAAAC
403 irsnd_buffer[1] = (irmp_data_p->command & 0x1F) << 3; // CCCCC000
404 irsnd_busy = TRUE;
405 break;
406 }
407 #endif
408 #if IRSND_SUPPORT_DENON_PROTOCOL == 1
409 case IRMP_DENON_PROTOCOL:
410 {
411 irsnd_buffer[0] = ((irmp_data_p->address & 0x1F) << 3) | ((irmp_data_p->command & 0x0380) >> 7); // AAAAACCC (1st frame)
412 irsnd_buffer[1] = (irmp_data_p->command & 0x7F) << 1; // CCCCCCC
413 irsnd_buffer[2] = ((irmp_data_p->address & 0x1F) << 3) | (((~irmp_data_p->command) & 0x0380) >> 7); // AAAAACCC (2nd frame)
414 irsnd_buffer[3] = (~(irmp_data_p->command) & 0x7F) << 1; // CCCCCCC
415 irsnd_busy = TRUE;
416 break;
417 }
418 #endif
419 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
420 case IRMP_NUBERT_PROTOCOL:
421 {
422 irsnd_buffer[0] = irmp_data_p->command >> 2; // CCCCCCCC
423 irsnd_buffer[1] = (irmp_data_p->command & 0x0003) << 6; // CC000000
424 irsnd_busy = TRUE;
425 break;
426 }
427 #endif
428 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
429 case IRMP_BANG_OLUFSEN_PROTOCOL:
430 {
431 irsnd_buffer[0] = irmp_data_p->command >> 11; // SXSCCCCC
432 irsnd_buffer[1] = irmp_data_p->command >> 3; // CCCCCCCC
433 irsnd_buffer[2] = (irmp_data_p->command & 0x0007) << 5; // CCC00000
434 irsnd_busy = TRUE;
435 break;
436 }
437 #endif
438 #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
439 case IRMP_GRUNDIG_PROTOCOL:
440 {
441 command = bitsrevervse (irmp_data_p->command, GRUNDIG_COMMAND_LEN);
442
443 irsnd_buffer[0] = 0xFF; // S1111111 (1st frame)
444 irsnd_buffer[1] = 0xC0; // 11
445 irsnd_buffer[2] = 0x80 | (command >> 2); // SCCCCCCC (2nd frame)
446 irsnd_buffer[3] = (command << 6) & 0xC0; // CC
447
448 irsnd_busy = TRUE;
449 break;
450 }
451 #endif
452 #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
453 case IRMP_NOKIA_PROTOCOL:
454 {
455 address = bitsrevervse (irmp_data_p->address, NOKIA_ADDRESS_LEN);
456 command = bitsrevervse (irmp_data_p->command, NOKIA_COMMAND_LEN);
457
458 irsnd_buffer[0] = 0xBF; // S0111111 (1st + 3rd frame)
459 irsnd_buffer[1] = 0xFF; // 11111111
460 irsnd_buffer[2] = 0x80; // 1
461 irsnd_buffer[3] = 0x80 | command >> 1; // SCCCCCCC (2nd frame)
462 irsnd_buffer[4] = (command << 7) | (address >> 1); // CAAAAAAA
463 irsnd_buffer[5] = (address << 7); // A
464
465 irsnd_busy = TRUE;
466 break;
467 }
468 #endif
469 #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
470 case IRMP_SIEMENS_PROTOCOL:
471 {
472 irsnd_buffer[0] = ((irmp_data_p->address & 0x0FFF) >> 5); // SAAAAAAA
473 irsnd_buffer[1] = ((irmp_data_p->address & 0x1F) << 3) | ((irmp_data_p->command & 0x7F) >> 5); // AAAAA0CC
474 irsnd_buffer[2] = (irmp_data_p->command << 3); // CCCCC0
475 irsnd_busy = TRUE;
476 break;
477 }
478 #endif
479 default:
480 {
481 break;
482 }
483 }
484
485 return irsnd_busy;
486 }
487
488 /*---------------------------------------------------------------------------------------------------------------------------------------------------
489 * ISR routine
490 * @details ISR routine, called 10000 times per second
491 *---------------------------------------------------------------------------------------------------------------------------------------------------
492 */
493 uint8_t
494 irsnd_ISR (void)
495 {
496 static uint8_t current_bit = 0xFF;
497 static uint8_t pulse_counter;
498 static uint8_t pause_counter;
499 static uint8_t startbit_pulse_len;
500 static uint8_t startbit_pause_len;
501 static uint8_t pulse_1_len;
502 static uint8_t pause_1_len;
503 static uint8_t pulse_0_len;
504 static uint8_t pause_0_len;
505 static uint8_t has_stop_bit;
506 static uint8_t new_frame = TRUE;
507 static uint8_t complete_data_len;
508 static uint8_t n_auto_repetitions; // number of auto_repetitions
509 static uint8_t auto_repetition_counter; // auto_repetition counter
510 static uint16_t auto_repetition_pause_len; // pause before auto_repetition, uint16_t!
511 static uint16_t auto_repetition_pause_counter; // pause before auto_repetition, uint16_t!
512 static uint8_t n_repeat_frames; // number of repeat frames
513 static uint8_t repeat_counter; // repeat counter
514 static uint16_t repeat_frame_pause_len; // pause before repeat, uint16_t!
515 static uint16_t packet_repeat_pause_counter; // pause before repeat, uint16_t!
516 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
517 static uint8_t last_bit_value;
518 #endif
519 static uint8_t pulse_len = 0xFF;
520 static uint8_t pause_len = 0xFF;
521
522 if (irsnd_busy)
523 {
524 if (current_bit == 0xFF && new_frame) // start of transmission...
525 {
526 if (auto_repetition_counter > 0)
527 {
528 auto_repetition_pause_counter++;
529
530 if (auto_repetition_pause_counter >= auto_repetition_pause_len)
531 {
532 auto_repetition_pause_counter = 0;
533
534 if (irsnd_protocol == IRMP_DENON_PROTOCOL)
535 {
536 current_bit = 16;
537 complete_data_len = 2 * DENON_COMPLETE_DATA_LEN + 1;
538 }
539 else if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL) // n'th grundig info frame
540 {
541 current_bit = 15;
542 complete_data_len = 16 + GRUNDIG_COMPLETE_DATA_LEN;
543 }
544 else if (irsnd_protocol == IRMP_NOKIA_PROTOCOL) // n'th nokia info frame
545 {
546 if (auto_repetition_counter + 1 < n_auto_repetitions)
547 {
548 current_bit = 23;
549 complete_data_len = 24 + NOKIA_COMPLETE_DATA_LEN;
550 }
551 else // nokia stop frame
552 {
553 current_bit = 0xFF;
554 complete_data_len = NOKIA_COMPLETE_DATA_LEN;
555 }
556 }
557 }
558 else
559 {
560 #ifdef DEBUG
561 if (irsnd_is_on)
562 {
563 putchar ('0');
564 }
565 else
566 {
567 putchar ('1');
568 }
569 #endif
570 return irsnd_busy;
571 }
572 }
573 else if (repeat_counter > 0 && packet_repeat_pause_counter < repeat_frame_pause_len)
574 {
575 packet_repeat_pause_counter++;
576
577 #ifdef DEBUG
578 if (irsnd_is_on)
579 {
580 putchar ('0');
581 }
582 else
583 {
584 putchar ('1');
585 }
586 #endif
587 return irsnd_busy;
588 }
589 else
590 {
591 n_repeat_frames = irsnd_repeat;
592 packet_repeat_pause_counter = 0;
593 pulse_counter = 0;
594 pause_counter = 0;
595
596 switch (irsnd_protocol)
597 {
598 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
599 case IRMP_SIRCS_PROTOCOL:
600 {
601 startbit_pulse_len = SIRCS_START_BIT_PULSE_LEN;
602 startbit_pause_len = SIRCS_START_BIT_PAUSE_LEN;
603 pulse_1_len = SIRCS_1_PULSE_LEN;
604 pause_1_len = SIRCS_PAUSE_LEN;
605 pulse_0_len = SIRCS_0_PULSE_LEN;
606 pause_0_len = SIRCS_PAUSE_LEN;
607 has_stop_bit = SIRCS_STOP_BIT;
608 complete_data_len = SIRCS_MINIMUM_DATA_LEN;
609 n_auto_repetitions = (repeat_counter == 0) ? SIRCS_FRAMES : 1; // 3 frames auto repetition if first frame
610 auto_repetition_pause_len = SIRCS_AUTO_REPETITION_PAUSE_LEN; // 25ms pause
611 repeat_frame_pause_len = SIRCS_FRAME_REPEAT_PAUSE_LEN;
612 irsnd_set_freq (IRSND_FREQ_40_KHZ);
613 break;
614 }
615 #endif
616 #if IRSND_SUPPORT_NEC_PROTOCOL == 1
617 case IRMP_NEC_PROTOCOL:
618 {
619 startbit_pulse_len = NEC_START_BIT_PULSE_LEN;
620
621 if (repeat_counter > 0)
622 {
623 startbit_pause_len = NEC_REPEAT_START_BIT_PAUSE_LEN;
624 complete_data_len = 0;
625 }
626 else
627 {
628 startbit_pause_len = NEC_START_BIT_PAUSE_LEN;
629 complete_data_len = NEC_COMPLETE_DATA_LEN;
630 }
631
632 pulse_1_len = NEC_PULSE_LEN;
633 pause_1_len = NEC_1_PAUSE_LEN;
634 pulse_0_len = NEC_PULSE_LEN;
635 pause_0_len = NEC_0_PAUSE_LEN;
636 has_stop_bit = NEC_STOP_BIT;
637 n_auto_repetitions = 1; // 1 frame
638 auto_repetition_pause_len = 0;
639 repeat_frame_pause_len = NEC_FRAME_REPEAT_PAUSE_LEN;
640 irsnd_set_freq (IRSND_FREQ_38_KHZ);
641 break;
642 }
643 #endif
644 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
645 case IRMP_SAMSUNG_PROTOCOL:
646 {
647 startbit_pulse_len = SAMSUNG_START_BIT_PULSE_LEN;
648 startbit_pause_len = SAMSUNG_START_BIT_PAUSE_LEN;
649 pulse_1_len = SAMSUNG_PULSE_LEN;
650 pause_1_len = SAMSUNG_1_PAUSE_LEN;
651 pulse_0_len = SAMSUNG_PULSE_LEN;
652 pause_0_len = SAMSUNG_0_PAUSE_LEN;
653 has_stop_bit = SAMSUNG_STOP_BIT;
654 complete_data_len = SAMSUNG_COMPLETE_DATA_LEN;
655 n_auto_repetitions = 1; // 1 frame
656 auto_repetition_pause_len = 0;
657 repeat_frame_pause_len = SAMSUNG_FRAME_REPEAT_PAUSE_LEN;
658 irsnd_set_freq (IRSND_FREQ_38_KHZ);
659 break;
660 }
661
662 case IRMP_SAMSUNG32_PROTOCOL:
663 {
664 startbit_pulse_len = SAMSUNG_START_BIT_PULSE_LEN;
665 startbit_pause_len = SAMSUNG_START_BIT_PAUSE_LEN;
666 pulse_1_len = SAMSUNG_PULSE_LEN;
667 pause_1_len = SAMSUNG_1_PAUSE_LEN;
668 pulse_0_len = SAMSUNG_PULSE_LEN;
669 pause_0_len = SAMSUNG_0_PAUSE_LEN;
670 has_stop_bit = SAMSUNG_STOP_BIT;
671 complete_data_len = SAMSUNG32_COMPLETE_DATA_LEN;
672 n_auto_repetitions = SAMSUNG32_FRAMES; // 2 frames
673 auto_repetition_pause_len = SAMSUNG32_AUTO_REPETITION_PAUSE_LEN; // 47 ms pause
674 repeat_frame_pause_len = SAMSUNG32_FRAME_REPEAT_PAUSE_LEN;
675 irsnd_set_freq (IRSND_FREQ_38_KHZ);
676 break;
677 }
678 #endif
679 #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
680 case IRMP_MATSUSHITA_PROTOCOL:
681 {
682 startbit_pulse_len = MATSUSHITA_START_BIT_PULSE_LEN;
683 startbit_pause_len = MATSUSHITA_START_BIT_PAUSE_LEN;
684 pulse_1_len = MATSUSHITA_PULSE_LEN;
685 pause_1_len = MATSUSHITA_1_PAUSE_LEN;
686 pulse_0_len = MATSUSHITA_PULSE_LEN;
687 pause_0_len = MATSUSHITA_0_PAUSE_LEN;
688 has_stop_bit = MATSUSHITA_STOP_BIT;
689 complete_data_len = MATSUSHITA_COMPLETE_DATA_LEN;
690 n_auto_repetitions = 1; // 1 frame
691 auto_repetition_pause_len = 0;
692 repeat_frame_pause_len = MATSUSHITA_FRAME_REPEAT_PAUSE_LEN;
693 irsnd_set_freq (IRSND_FREQ_36_KHZ);
694 break;
695 }
696 #endif
697 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
698 case IRMP_RECS80_PROTOCOL:
699 {
700 startbit_pulse_len = RECS80_START_BIT_PULSE_LEN;
701 startbit_pause_len = RECS80_START_BIT_PAUSE_LEN;
702 pulse_1_len = RECS80_PULSE_LEN;
703 pause_1_len = RECS80_1_PAUSE_LEN;
704 pulse_0_len = RECS80_PULSE_LEN;
705 pause_0_len = RECS80_0_PAUSE_LEN;
706 has_stop_bit = RECS80_STOP_BIT;
707 complete_data_len = RECS80_COMPLETE_DATA_LEN;
708 n_auto_repetitions = 1; // 1 frame
709 auto_repetition_pause_len = 0;
710 repeat_frame_pause_len = RECS80_FRAME_REPEAT_PAUSE_LEN;
711 irsnd_set_freq (IRSND_FREQ_38_KHZ);
712 break;
713 }
714 #endif
715 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
716 case IRMP_RECS80EXT_PROTOCOL:
717 {
718 startbit_pulse_len = RECS80EXT_START_BIT_PULSE_LEN;
719 startbit_pause_len = RECS80EXT_START_BIT_PAUSE_LEN;
720 pulse_1_len = RECS80EXT_PULSE_LEN;
721 pause_1_len = RECS80EXT_1_PAUSE_LEN;
722 pulse_0_len = RECS80EXT_PULSE_LEN;
723 pause_0_len = RECS80EXT_0_PAUSE_LEN;
724 has_stop_bit = RECS80EXT_STOP_BIT;
725 complete_data_len = RECS80EXT_COMPLETE_DATA_LEN;
726 n_auto_repetitions = 1; // 1 frame
727 auto_repetition_pause_len = 0;
728 repeat_frame_pause_len = RECS80EXT_FRAME_REPEAT_PAUSE_LEN;
729 irsnd_set_freq (IRSND_FREQ_38_KHZ);
730 break;
731 }
732 #endif
733 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
734 case IRMP_RC5_PROTOCOL:
735 {
736 startbit_pulse_len = RC5_BIT_LEN;
737 startbit_pause_len = RC5_BIT_LEN;
738 pulse_len = RC5_BIT_LEN;
739 pause_len = RC5_BIT_LEN;
740 has_stop_bit = RC5_STOP_BIT;
741 complete_data_len = RC5_COMPLETE_DATA_LEN;
742 n_auto_repetitions = 1; // 1 frame
743 auto_repetition_pause_len = 0;
744 repeat_frame_pause_len = RC5_FRAME_REPEAT_PAUSE_LEN;
745 irsnd_set_freq (IRSND_FREQ_36_KHZ);
746 break;
747 }
748 #endif
749 #if IRSND_SUPPORT_DENON_PROTOCOL == 1
750 case IRMP_DENON_PROTOCOL:
751 {
752 startbit_pulse_len = 0x00;
753 startbit_pause_len = 0x00;
754 pulse_1_len = DENON_PULSE_LEN;
755 pause_1_len = DENON_1_PAUSE_LEN;
756 pulse_0_len = DENON_PULSE_LEN;
757 pause_0_len = DENON_0_PAUSE_LEN;
758 has_stop_bit = DENON_STOP_BIT;
759 complete_data_len = DENON_COMPLETE_DATA_LEN;
760 n_auto_repetitions = DENON_FRAMES; // 2 frames, 2nd with inverted command
761 auto_repetition_pause_len = DENON_AUTO_REPETITION_PAUSE_LEN; // 65 ms pause after 1st frame
762 repeat_frame_pause_len = DENON_FRAME_REPEAT_PAUSE_LEN;
763 irsnd_set_freq (IRSND_FREQ_32_KHZ);
764 break;
765 }
766 #endif
767 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
768 case IRMP_NUBERT_PROTOCOL:
769 {
770 startbit_pulse_len = NUBERT_START_BIT_PULSE_LEN;
771 startbit_pause_len = NUBERT_START_BIT_PAUSE_LEN;
772 pulse_1_len = NUBERT_1_PULSE_LEN;
773 pause_1_len = NUBERT_1_PAUSE_LEN;
774 pulse_0_len = NUBERT_0_PULSE_LEN;
775 pause_0_len = NUBERT_0_PAUSE_LEN;
776 has_stop_bit = NUBERT_STOP_BIT;
777 complete_data_len = NUBERT_COMPLETE_DATA_LEN;
778 n_auto_repetitions = NUBERT_FRAMES; // 2 frames
779 auto_repetition_pause_len = NUBERT_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause
780 repeat_frame_pause_len = NUBERT_FRAME_REPEAT_PAUSE_LEN;
781 irsnd_set_freq (IRSND_FREQ_36_KHZ);
782 break;
783 }
784 #endif
785 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
786 case IRMP_BANG_OLUFSEN_PROTOCOL:
787 {
788 startbit_pulse_len = BANG_OLUFSEN_START_BIT1_PULSE_LEN;
789 startbit_pause_len = BANG_OLUFSEN_START_BIT1_PAUSE_LEN;
790 pulse_1_len = BANG_OLUFSEN_PULSE_LEN;
791 pause_1_len = BANG_OLUFSEN_1_PAUSE_LEN;
792 pulse_0_len = BANG_OLUFSEN_PULSE_LEN;
793 pause_0_len = BANG_OLUFSEN_0_PAUSE_LEN;
794 has_stop_bit = BANG_OLUFSEN_STOP_BIT;
795 complete_data_len = BANG_OLUFSEN_COMPLETE_DATA_LEN;
796 n_auto_repetitions = 1; // 1 frame
797 auto_repetition_pause_len = 0;
798 repeat_frame_pause_len = BANG_OLUFSEN_FRAME_REPEAT_PAUSE_LEN;
799 last_bit_value = 0;
800 irsnd_set_freq (IRSND_FREQ_455_KHZ);
801 break;
802 }
803 #endif
804 #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
805 case IRMP_GRUNDIG_PROTOCOL:
806 {
807 startbit_pulse_len = GRUNDIG_OR_NOKIA_BIT_LEN;
808 startbit_pause_len = GRUNDIG_OR_NOKIA_PRE_PAUSE_LEN;
809 pulse_len = GRUNDIG_OR_NOKIA_BIT_LEN;
810 pause_len = GRUNDIG_OR_NOKIA_BIT_LEN;
811 has_stop_bit = GRUNDIG_OR_NOKIA_STOP_BIT;
812 complete_data_len = GRUNDIG_COMPLETE_DATA_LEN;
813 n_auto_repetitions = GRUNDIG_FRAMES; // 2 frames
814 auto_repetition_pause_len = GRUNDIG_AUTO_REPETITION_PAUSE_LEN; // 20m sec pause
815 repeat_frame_pause_len = GRUNDIG_OR_NOKIA_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause
816 irsnd_set_freq (IRSND_FREQ_38_KHZ);
817
818 break;
819 }
820 #endif
821 #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
822 case IRMP_NOKIA_PROTOCOL:
823 {
824 startbit_pulse_len = GRUNDIG_OR_NOKIA_BIT_LEN;
825 startbit_pause_len = GRUNDIG_OR_NOKIA_PRE_PAUSE_LEN;
826 pulse_len = GRUNDIG_OR_NOKIA_BIT_LEN;
827 pause_len = GRUNDIG_OR_NOKIA_BIT_LEN;
828 has_stop_bit = GRUNDIG_OR_NOKIA_STOP_BIT;
829 complete_data_len = NOKIA_COMPLETE_DATA_LEN;
830 n_auto_repetitions = NOKIA_FRAMES; // 2 frames
831 auto_repetition_pause_len = NOKIA_AUTO_REPETITION_PAUSE_LEN; // 20 msec pause
832 repeat_frame_pause_len = GRUNDIG_OR_NOKIA_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause
833 irsnd_set_freq (IRSND_FREQ_38_KHZ);
834 break;
835 }
836 #endif
837 #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
838 case IRMP_SIEMENS_PROTOCOL:
839 {
840 startbit_pulse_len = SIEMENS_BIT_LEN;
841 startbit_pause_len = SIEMENS_BIT_LEN;
842 pulse_len = SIEMENS_BIT_LEN;
843 pause_len = SIEMENS_BIT_LEN;
844 has_stop_bit = SIEMENS_STOP_BIT;
845 complete_data_len = SIEMENS_COMPLETE_DATA_LEN - 1;
846 n_auto_repetitions = 1; // 1 frame
847 auto_repetition_pause_len = 0;
848 repeat_frame_pause_len = SIEMENS_FRAME_REPEAT_PAUSE_LEN;
849 irsnd_set_freq (IRSND_FREQ_36_KHZ);
850 break;
851 }
852 #endif
853 default:
854 {
855 irsnd_busy = FALSE;
856 break;
857 }
858 }
859 }
860 }
861
862 if (irsnd_busy)
863 {
864 new_frame = FALSE;
865
866 switch (irsnd_protocol)
867 {
868 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
869 case IRMP_SIRCS_PROTOCOL:
870 #endif
871 #if IRSND_SUPPORT_NEC_PROTOCOL == 1
872 case IRMP_NEC_PROTOCOL:
873 #endif
874 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
875 case IRMP_SAMSUNG_PROTOCOL:
876 case IRMP_SAMSUNG32_PROTOCOL:
877 #endif
878 #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
879 case IRMP_MATSUSHITA_PROTOCOL:
880 #endif
881 #if IRSND_SUPPORT_RECS80_PROTOCOL == 1
882 case IRMP_RECS80_PROTOCOL:
883 #endif
884 #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
885 case IRMP_RECS80EXT_PROTOCOL:
886 #endif
887 #if IRSND_SUPPORT_DENON_PROTOCOL == 1
888 case IRMP_DENON_PROTOCOL:
889 #endif
890 #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
891 case IRMP_NUBERT_PROTOCOL:
892 #endif
893 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
894 case IRMP_BANG_OLUFSEN_PROTOCOL:
895 #endif
896
897
898 #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 || IRSND_SUPPORT_NEC_PROTOCOL == 1 || IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 || IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 || \
899 IRSND_SUPPORT_RECS80_PROTOCOL == 1 || IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 || IRSND_SUPPORT_DENON_PROTOCOL == 1 || IRSND_SUPPORT_NUBERT_PROTOCOL == 1 || \
900 IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
901 {
902 if (pulse_counter == 0)
903 {
904 if (current_bit == 0xFF) // send start bit
905 {
906 pulse_len = startbit_pulse_len;
907 pause_len = startbit_pause_len;
908 }
909 else if (current_bit < complete_data_len) // send n'th bit
910 {
911 #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
912 if (irsnd_protocol == IRMP_SAMSUNG_PROTOCOL)
913 {
914 if (current_bit < SAMSUNG_ADDRESS_LEN) // send address bits
915 {
916 pulse_len = SAMSUNG_PULSE_LEN;
917 pause_len = (irsnd_buffer[current_bit / 8] & (1<<(7-(current_bit % 8)))) ?
918 SAMSUNG_1_PAUSE_LEN : SAMSUNG_0_PAUSE_LEN;
919 }
920 else if (current_bit == SAMSUNG_ADDRESS_LEN) // send SYNC bit (16th bit)
921 {
922 pulse_len = SAMSUNG_PULSE_LEN;
923 pause_len = SAMSUNG_START_BIT_PAUSE_LEN;
924 }
925 else if (current_bit < SAMSUNG_COMPLETE_DATA_LEN) // send n'th bit
926 {
927 uint8_t cur_bit = current_bit - 1; // sync skipped, offset = -1 !
928
929 pulse_len = SAMSUNG_PULSE_LEN;
930 pause_len = (irsnd_buffer[cur_bit / 8] & (1<<(7-(cur_bit % 8)))) ?
931 SAMSUNG_1_PAUSE_LEN : SAMSUNG_0_PAUSE_LEN;
932 }
933 }
934 else
935 #endif
936
937 #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
938 if (irsnd_protocol == IRMP_BANG_OLUFSEN_PROTOCOL)
939 {
940 if (current_bit == 0) // send 2nd start bit
941 {
942 pulse_len = BANG_OLUFSEN_START_BIT2_PULSE_LEN;
943 pause_len = BANG_OLUFSEN_START_BIT2_PAUSE_LEN;
944 }
945 else if (current_bit == 1) // send 3rd start bit
946 {
947 pulse_len = BANG_OLUFSEN_START_BIT3_PULSE_LEN;
948 pause_len = BANG_OLUFSEN_START_BIT3_PAUSE_LEN;
949 }
950 else if (current_bit == 2) // send 4th start bit
951 {
952 pulse_len = BANG_OLUFSEN_START_BIT2_PULSE_LEN;
953 pause_len = BANG_OLUFSEN_START_BIT2_PAUSE_LEN;
954 }
955 else if (current_bit == 19) // send trailer bit
956 {
957 pulse_len = BANG_OLUFSEN_PULSE_LEN;
958 pause_len = BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN;
959 }
960 else if (current_bit < BANG_OLUFSEN_COMPLETE_DATA_LEN) // send n'th bit
961 {
962 uint8_t cur_bit_value = (irsnd_buffer[current_bit / 8] & (1<<(7-(current_bit % 8)))) ? 1 : 0;
963 pulse_len = BANG_OLUFSEN_PULSE_LEN;
964
965 if (cur_bit_value == last_bit_value)
966 {
967 pause_len = BANG_OLUFSEN_R_PAUSE_LEN;
968 }
969 else
970 {
971 pause_len = cur_bit_value ? BANG_OLUFSEN_1_PAUSE_LEN : BANG_OLUFSEN_0_PAUSE_LEN;
972 last_bit_value = cur_bit_value;
973 }
974 }
975 }
976 else
977 #endif
978 if (irsnd_buffer[current_bit / 8] & (1<<(7-(current_bit % 8))))
979 {
980 pulse_len = pulse_1_len;
981 pause_len = pause_1_len;
982 }
983 else
984 {
985 pulse_len = pulse_0_len;
986 pause_len = pause_0_len;
987 }
988 }
989 else if (has_stop_bit) // send stop bit
990 {
991 pulse_len = pulse_0_len;
992
993 if (auto_repetition_counter < n_auto_repetitions)
994 {
995 pause_len = pause_0_len;
996 }
997 else
998 {
999 pause_len = 255; // last frame: pause of 255
1000 }
1001 }
1002 }
1003
1004 if (pulse_counter < pulse_len)
1005 {
1006 if (pulse_counter == 0)
1007 {
1008 irsnd_on ();
1009 }
1010 pulse_counter++;
1011 }
1012 else if (pause_counter < pause_len)
1013 {
1014 if (pause_counter == 0)
1015 {
1016 irsnd_off ();
1017 }
1018 pause_counter++;
1019 }
1020 else
1021 {
1022 current_bit++;
1023
1024 if (current_bit >= complete_data_len + has_stop_bit)
1025 {
1026 current_bit = 0xFF;
1027 auto_repetition_counter++;
1028
1029 if (auto_repetition_counter == n_auto_repetitions)
1030 {
1031 irsnd_busy = FALSE;
1032 auto_repetition_counter = 0;
1033 }
1034 new_frame = TRUE;
1035 }
1036
1037 pulse_counter = 0;
1038 pause_counter = 0;
1039 }
1040 break;
1041 }
1042 #endif
1043
1044 #if IRSND_SUPPORT_RC5_PROTOCOL == 1
1045 case IRMP_RC5_PROTOCOL:
1046 #endif
1047 #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
1048 case IRMP_SIEMENS_PROTOCOL:
1049 #endif
1050 #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
1051 case IRMP_GRUNDIG_PROTOCOL:
1052 #endif
1053 #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
1054 case IRMP_NOKIA_PROTOCOL:
1055 #endif
1056
1057 #if IRSND_SUPPORT_RC5_PROTOCOL == 1 || IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 || IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
1058 {
1059 if (pulse_counter == pulse_len && pause_counter == pause_len)
1060 {
1061 current_bit++;
1062
1063 if (current_bit >= complete_data_len)
1064 {
1065 current_bit = 0xFF;
1066
1067 #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
1068 if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL || irsnd_protocol == IRMP_NOKIA_PROTOCOL)
1069 {
1070 auto_repetition_counter++;
1071
1072 if (repeat_counter > 0)
1073 { // set 117 msec pause time
1074 auto_repetition_pause_len = GRUNDIG_OR_NOKIA_FRAME_REPEAT_PAUSE_LEN;
1075 }
1076
1077 if (repeat_counter < n_repeat_frames) // tricky: repeat n info frames per auto repetition before sending last stop frame
1078 {
1079 n_auto_repetitions++; // increment number of auto repetitions
1080 repeat_counter++;
1081 }
1082 else if (auto_repetition_counter == n_auto_repetitions)
1083 {
1084 irsnd_busy = FALSE;
1085 auto_repetition_counter = 0;
1086 }
1087 }
1088 else
1089 #endif
1090 {
1091 irsnd_busy = FALSE;
1092 }
1093
1094 new_frame = TRUE;
1095 irsnd_off ();
1096 }
1097
1098 pulse_counter = 0;
1099 pause_counter = 0;
1100 }
1101
1102 if (! new_frame)
1103 {
1104 uint8_t first_pulse;
1105
1106 #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
1107 if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL || irsnd_protocol == IRMP_NOKIA_PROTOCOL)
1108 {
1109 if (current_bit == 0xFF || // start bit of start-frame
1110 (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL && current_bit == 15) || // start bit of info-frame (Grundig)
1111 (irsnd_protocol == IRMP_NOKIA_PROTOCOL && (current_bit == 23 || current_bit == 47))) // start bit of info- or stop-frame (Nokia)
1112 {
1113 pulse_len = startbit_pulse_len;
1114 pause_len = startbit_pause_len;
1115 first_pulse = TRUE;
1116 }
1117 else // send n'th bit
1118 {
1119 pulse_len = GRUNDIG_OR_NOKIA_BIT_LEN;
1120 pause_len = GRUNDIG_OR_NOKIA_BIT_LEN;
1121 first_pulse = (irsnd_buffer[current_bit / 8] & (1<<(7-(current_bit % 8)))) ? TRUE : FALSE;
1122 }
1123 }
1124 else // if (irsnd_protocol == IRMP_RC5_PROTOCOL || irsnd_protocol == IRMP_SIEMENS_PROTOCOL)
1125 #endif
1126 {
1127 if (current_bit == 0xFF) // 1 start bit
1128 {
1129 first_pulse = TRUE;
1130 }
1131 else // send n'th bit
1132 {
1133 first_pulse = (irsnd_buffer[current_bit / 8] & (1<<(7-(current_bit % 8)))) ? TRUE : FALSE;
1134 }
1135
1136 if (irsnd_protocol == IRMP_RC5_PROTOCOL)
1137 {
1138 first_pulse = first_pulse ? FALSE : TRUE;
1139 }
1140 }
1141
1142 if (first_pulse)
1143 {
1144 if (pulse_counter < pulse_len)
1145 {
1146 if (pulse_counter == 0)
1147 {
1148 irsnd_on ();
1149 }
1150 pulse_counter++;
1151 }
1152 else // if (pause_counter < pause_len)
1153 {
1154 if (pause_counter == 0)
1155 {
1156 irsnd_off ();
1157 }
1158 pause_counter++;
1159 }
1160 }
1161 else
1162 {
1163 if (pause_counter < pause_len)
1164 {
1165 if (pause_counter == 0)
1166 {
1167 irsnd_off ();
1168 }
1169 pause_counter++;
1170 }
1171 else // if (pulse_counter < pulse_len)
1172 {
1173 if (pulse_counter == 0)
1174 {
1175 irsnd_on ();
1176 }
1177 pulse_counter++;
1178 }
1179 }
1180 }
1181 break;
1182 }
1183 #endif // IRSND_SUPPORT_RC5_PROTOCOL == 1 || IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 || IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
1184
1185 default:
1186 {
1187 irsnd_busy = FALSE;
1188 break;
1189 }
1190 }
1191 }
1192
1193 if (! irsnd_busy)
1194 {
1195 if (repeat_counter < n_repeat_frames)
1196 {
1197 repeat_counter++;
1198 irsnd_busy = TRUE;
1199 }
1200 else
1201 {
1202 n_repeat_frames = 0;
1203 repeat_counter = 0;
1204 }
1205 }
1206 }
1207
1208 #ifdef DEBUG
1209 if (irsnd_is_on)
1210 {
1211 putchar ('0');
1212 }
1213 else
1214 {
1215 putchar ('1');
1216 }
1217 #endif
1218
1219 return irsnd_busy;
1220 }
1221
1222 #ifdef DEBUG
1223
1224 // main function - for unix/linux + windows only!
1225 // AVR: see main.c!
1226 // Compile it under linux with:
1227 // cc irsnd.c -o irsnd
1228 //
1229 // usage: ./irsnd protocol hex-address hex-command >filename
1230
1231 int
1232 main (int argc, char ** argv)
1233 {
1234 int idx;
1235 int protocol;
1236 int address;
1237 int command;
1238 IRMP_DATA irmp_data;
1239
1240 if (argc != 4 && argc != 5)
1241 {
1242 fprintf (stderr, "usage: %s protocol hex-address hex-command [repeat] > filename\n", argv[0]);
1243 return 1;
1244 }
1245
1246 if (sscanf (argv[1], "%d", &protocol) == 1 &&
1247 sscanf (argv[2], "%x", &address) == 1 &&
1248 sscanf (argv[3], "%x", &command) == 1)
1249 {
1250 irmp_data.protocol = protocol;
1251 irmp_data.address = address;
1252 irmp_data.command = command;
1253
1254 if (argc == 5)
1255 {
1256 irmp_data.flags = atoi (argv[4]);
1257 }
1258 else
1259 {
1260 irmp_data.flags = 0;
1261 }
1262
1263 irsnd_init ();
1264
1265 (void) irsnd_send_data (&irmp_data);
1266
1267 while (irsnd_busy)
1268 {
1269 irsnd_ISR ();
1270 }
1271 for (idx = 0; idx < 20; idx++)
1272 {
1273 irsnd_ISR ();
1274 }
1275
1276 putchar ('\n');
1277 }
1278 else
1279 {
1280 fprintf (stderr, "%s: wrong arguments\n", argv[0]);
1281 return 1;
1282 }
1283 return 0;
1284 }
1285
1286 #endif // DEBUG