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