1 /* $Id: transmit.c,v 5.31 2010/04/02 10:26:57 lirc Exp $ */
2
3 /****************************************************************************
4 ** transmit.c **************************************************************
5 ****************************************************************************
6 *
7 * functions that prepare IR codes for transmitting
8 *
9 * Copyright (C) 1999-2004 Christoph Bartelmus <lirc@bartelmus.de>
10 *
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16
17 /* if the gap is lower than this value, we will concatenate the
18 signals and send the signal chain at a single blow */
19 #define LIRCD_EXACT_GAP_THRESHOLD 10000
20
21 #include "lircd.h"
22 #include "transmit.h"
23
24 extern struct ir_remote *repeat_remote;
25 struct sbuf send_buffer;
26
27 static void send_signals(lirc_t * signals, int n);
28 static int init_send_or_sim(struct ir_remote *remote, struct ir_ncode *code, int sim, int repeat_preset);
29
set_bit(ir_code * code,int bit,int data)30 inline void set_bit(ir_code * code, int bit, int data)
31 {
32 (*code) &= ~((((ir_code) 1) << bit));
33 (*code) |= ((ir_code) (data ? 1 : 0) << bit);
34 }
35
36 /*
37 sending stuff
38 */
39
init_send_buffer(void)40 void init_send_buffer(void)
41 {
42 memset(&send_buffer, 0, sizeof(send_buffer));
43 }
44
clear_send_buffer(void)45 inline void clear_send_buffer(void)
46 {
47 LOGPRINTF(3, "clearing transmit buffer");
48 send_buffer.wptr = 0;
49 send_buffer.too_long = 0;
50 send_buffer.is_biphase = 0;
51 send_buffer.pendingp = 0;
52 send_buffer.pendings = 0;
53 send_buffer.sum = 0;
54 }
55
add_send_buffer(lirc_t data)56 inline void add_send_buffer(lirc_t data)
57 {
58 if (send_buffer.wptr < WBUF_SIZE) {
59 LOGPRINTF(3, "adding to transmit buffer: %u", data);
60 send_buffer.sum += data;
61 send_buffer._data[send_buffer.wptr] = data;
62 send_buffer.wptr++;
63 } else {
64 send_buffer.too_long = 1;
65 }
66 }
67
send_pulse(lirc_t data)68 inline void send_pulse(lirc_t data)
69 {
70 if (send_buffer.pendingp > 0) {
71 send_buffer.pendingp += data;
72 } else {
73 if (send_buffer.pendings > 0) {
74 add_send_buffer(send_buffer.pendings);
75 send_buffer.pendings = 0;
76 }
77 send_buffer.pendingp = data;
78 }
79 }
80
send_space(lirc_t data)81 inline void send_space(lirc_t data)
82 {
83 if (send_buffer.wptr == 0 && send_buffer.pendingp == 0) {
84 LOGPRINTF(1, "first signal is a space!");
85 return;
86 }
87 if (send_buffer.pendings > 0) {
88 send_buffer.pendings += data;
89 } else {
90 if (send_buffer.pendingp > 0) {
91 add_send_buffer(send_buffer.pendingp);
92 send_buffer.pendingp = 0;
93 }
94 send_buffer.pendings = data;
95 }
96 }
97
bad_send_buffer(void)98 static inline int bad_send_buffer(void)
99 {
100 if (send_buffer.too_long != 0)
101 return (1);
102 if (send_buffer.wptr == WBUF_SIZE && send_buffer.pendingp > 0) {
103 return (1);
104 }
105 return (0);
106 }
107
check_send_buffer(void)108 static int check_send_buffer(void)
109 {
110 int i;
111
112 if (send_buffer.wptr == 0) {
113 LOGPRINTF(1, "nothing to send");
114 return (0);
115 }
116 for (i = 0; i < send_buffer.wptr; i++) {
117 if (send_buffer.data[i] == 0) {
118 if (i % 2) {
119 LOGPRINTF(1, "invalid space: %d", i);
120 } else {
121 LOGPRINTF(1, "invalid pulse: %d", i);
122 }
123 return 0;
124 }
125 }
126
127 return 1;
128 }
129
flush_send_buffer(void)130 static inline void flush_send_buffer(void)
131 {
132 if (send_buffer.pendingp > 0) {
133 add_send_buffer(send_buffer.pendingp);
134 send_buffer.pendingp = 0;
135 }
136 if (send_buffer.pendings > 0) {
137 add_send_buffer(send_buffer.pendings);
138 send_buffer.pendings = 0;
139 }
140 }
141
sync_send_buffer(void)142 static inline void sync_send_buffer(void)
143 {
144 if (send_buffer.pendingp > 0) {
145 add_send_buffer(send_buffer.pendingp);
146 send_buffer.pendingp = 0;
147 }
148 if (send_buffer.wptr > 0 && send_buffer.wptr % 2 == 0)
149 send_buffer.wptr--;
150 }
151
send_header(struct ir_remote * remote)152 inline void send_header(struct ir_remote *remote)
153 {
154 if (has_header(remote)) {
155 send_pulse(remote->phead);
156 send_space(remote->shead);
157 }
158 }
159
send_foot(struct ir_remote * remote)160 inline void send_foot(struct ir_remote *remote)
161 {
162 if (has_foot(remote)) {
163 send_space(remote->sfoot);
164 send_pulse(remote->pfoot);
165 }
166 }
167
send_lead(struct ir_remote * remote)168 inline void send_lead(struct ir_remote *remote)
169 {
170 if (remote->plead != 0) {
171 send_pulse(remote->plead);
172 }
173 }
174
send_trail(struct ir_remote * remote)175 inline void send_trail(struct ir_remote *remote)
176 {
177 if (remote->ptrail != 0) {
178 send_pulse(remote->ptrail);
179 }
180 }
181
send_data(struct ir_remote * remote,ir_code data,int bits,int done)182 inline void send_data(struct ir_remote *remote, ir_code data, int bits, int done)
183 {
184 int i;
185 int all_bits = bit_count(remote);
186 int toggle_bit_mask_bits = bits_set(remote->toggle_bit_mask);
187 ir_code mask;
188
189 data = reverse(data, bits);
190 if (is_rcmm(remote)) {
191 mask = 1 << (all_bits - 1 - done);
192 if (bits % 2 || done % 2) {
193 logprintf(LOG_ERR, "invalid bit number.");
194 return;
195 }
196 for (i = 0; i < bits; i += 2, mask >>= 2) {
197 switch (data & 3) {
198 case 0:
199 send_pulse(remote->pzero);
200 send_space(remote->szero);
201 break;
202 /* 2 and 1 swapped due to reverse() */
203 case 2:
204 send_pulse(remote->pone);
205 send_space(remote->sone);
206 break;
207 case 1:
208 send_pulse(remote->ptwo);
209 send_space(remote->stwo);
210 break;
211 case 3:
212 send_pulse(remote->pthree);
213 send_space(remote->sthree);
214 break;
215 }
216 data = data >> 2;
217 }
218 return;
219 } else if (is_xmp(remote)) {
220 if (bits % 4 || done % 4) {
221 logprintf(LOG_ERR, "invalid bit number.");
222 return;
223 }
224 for (i = 0; i < bits; i += 4) {
225 ir_code nibble;
226
227 nibble = reverse(data & 0xf, 4);
228 send_pulse(remote->pzero);
229 send_space(remote->szero + nibble * remote->sone);
230 data >>= 4;
231 }
232 return;
233 }
234
235 mask = ((ir_code) 1) << (all_bits - 1 - done);
236 for (i = 0; i < bits; i++, mask >>= 1) {
237 if (has_toggle_bit_mask(remote) && mask & remote->toggle_bit_mask) {
238 if (toggle_bit_mask_bits == 1) {
239 /* backwards compatibility */
240 data &= ~((ir_code) 1);
241 if (remote->toggle_bit_mask_state & mask) {
242 data |= (ir_code) 1;
243 }
244 } else {
245 if (remote->toggle_bit_mask_state & mask) {
246 data ^= (ir_code) 1;
247 }
248 }
249 }
250 if (has_toggle_mask(remote) && mask & remote->toggle_mask && remote->toggle_mask_state % 2) {
251 data ^= 1;
252 }
253 if (data & 1) {
254 if (is_biphase(remote)) {
255
256 if (mask & remote->rc6_mask) {
257 send_space(2 * remote->sone);
258 send_pulse(2 * remote->pone);
259 } else {
260 send_space(remote->sone);
261 send_pulse(remote->pone);
262 }
263 } else if (is_space_first(remote)) {
264 send_space(remote->sone);
265 send_pulse(remote->pone);
266 } else {
267 send_pulse(remote->pone);
268 send_space(remote->sone);
269 }
270 } else {
271 if (mask & remote->rc6_mask) {
272 send_pulse(2 * remote->pzero);
273 send_space(2 * remote->szero);
274 } else if (is_space_first(remote)) {
275 send_space(remote->szero);
276 send_pulse(remote->pzero);
277 } else {
278 send_pulse(remote->pzero);
279 send_space(remote->szero);
280 }
281 }
282 data = data >> 1;
283 }
284 }
285
send_pre(struct ir_remote * remote)286 inline void send_pre(struct ir_remote *remote)
287 {
288 if (has_pre(remote)) {
289 send_data(remote, remote->pre_data, remote->pre_data_bits, 0);
290 if (remote->pre_p > 0 && remote->pre_s > 0) {
291 send_pulse(remote->pre_p);
292 send_space(remote->pre_s);
293 }
294 }
295 }
296
send_post(struct ir_remote * remote)297 inline void send_post(struct ir_remote *remote)
298 {
299 if (has_post(remote)) {
300 if (remote->post_p > 0 && remote->post_s > 0) {
301 send_pulse(remote->post_p);
302 send_space(remote->post_s);
303 }
304 send_data(remote, remote->post_data, remote->post_data_bits, remote->pre_data_bits + remote->bits);
305 }
306 }
307
send_repeat(struct ir_remote * remote)308 inline void send_repeat(struct ir_remote *remote)
309 {
310 send_lead(remote);
311 send_pulse(remote->prepeat);
312 send_space(remote->srepeat);
313 send_trail(remote);
314 }
315
send_code(struct ir_remote * remote,ir_code code,int repeat)316 inline void send_code(struct ir_remote *remote, ir_code code, int repeat)
317 {
318 if (!repeat || !(remote->flags & NO_HEAD_REP))
319 send_header(remote);
320 send_lead(remote);
321 send_pre(remote);
322 send_data(remote, code, remote->bits, remote->pre_data_bits);
323 send_post(remote);
324 send_trail(remote);
325 if (!repeat || !(remote->flags & NO_FOOT_REP))
326 send_foot(remote);
327
328 if (!repeat && remote->flags & NO_HEAD_REP && remote->flags & CONST_LENGTH) {
329 send_buffer.sum -= remote->phead + remote->shead;
330 }
331 }
332
send_signals(lirc_t * signals,int n)333 static void send_signals(lirc_t * signals, int n)
334 {
335 int i;
336
337 for (i = 0; i < n; i++) {
338 add_send_buffer(signals[i]);
339 }
340 }
341
init_send(struct ir_remote * remote,struct ir_ncode * code)342 int init_send(struct ir_remote *remote, struct ir_ncode *code)
343 {
344 return init_send_or_sim(remote, code, 0, 0);
345 }
346
init_sim(struct ir_remote * remote,struct ir_ncode * code,int repeat_preset)347 int init_sim(struct ir_remote *remote, struct ir_ncode *code, int repeat_preset)
348 {
349 return init_send_or_sim(remote, code, 1, repeat_preset);
350 }
351
init_send_or_sim(struct ir_remote * remote,struct ir_ncode * code,int sim,int repeat_preset)352 int init_send_or_sim(struct ir_remote *remote, struct ir_ncode *code, int sim, int repeat_preset)
353 {
354 int i, repeat = repeat_preset;
355
356 if (is_grundig(remote) || is_goldstar(remote) || is_serial(remote) || is_bo(remote)) {
357 if (!sim) {
358 logprintf(LOG_ERR, "sorry, can't send this protocol yet");
359 }
360 return (0);
361 }
362 clear_send_buffer();
363 if (is_biphase(remote)) {
364 send_buffer.is_biphase = 1;
365 }
366 if (!sim) {
367 if (repeat_remote == NULL) {
368 remote->repeat_countdown = remote->min_repeat;
369 } else {
370 repeat = 1;
371 }
372 }
373
374 init_send_loop:
375 if (repeat && has_repeat(remote)) {
376 if (remote->flags & REPEAT_HEADER && has_header(remote)) {
377 send_header(remote);
378 }
379 send_repeat(remote);
380 } else {
381 if (!is_raw(remote)) {
382 ir_code next_code;
383
384 if (sim || code->transmit_state == NULL) {
385 next_code = code->code;
386 } else {
387 next_code = code->transmit_state->code;
388 }
389 send_code(remote, next_code, repeat);
390 if (!sim && has_toggle_mask(remote)) {
391 remote->toggle_mask_state++;
392 if (remote->toggle_mask_state == 4) {
393 remote->toggle_mask_state = 2;
394 }
395 }
396 send_buffer.data = send_buffer._data;
397 } else {
398 if (code->signals == NULL) {
399 if (!sim) {
400 logprintf(LOG_ERR, "no signals for raw send");
401 }
402 return 0;
403 }
404 if (send_buffer.wptr > 0) {
405 send_signals(code->signals, code->length);
406 } else {
407 send_buffer.data = code->signals;
408 send_buffer.wptr = code->length;
409 for (i = 0; i < code->length; i++) {
410 send_buffer.sum += code->signals[i];
411 }
412 }
413 }
414 }
415 sync_send_buffer();
416 if (bad_send_buffer()) {
417 if (!sim)
418 logprintf(LOG_ERR, "buffer too small");
419 return (0);
420 }
421 if (sim)
422 goto final_check;
423
424 if (has_repeat_gap(remote) && repeat && has_repeat(remote)) {
425 remote->min_remaining_gap = remote->repeat_gap;
426 remote->max_remaining_gap = remote->repeat_gap;
427 } else if (is_const(remote)) {
428 if (min_gap(remote) > send_buffer.sum) {
429 remote->min_remaining_gap = min_gap(remote) - send_buffer.sum;
430 remote->max_remaining_gap = max_gap(remote) - send_buffer.sum;
431 } else {
432 logprintf(LOG_ERR, "too short gap: %u", remote->gap);
433 remote->min_remaining_gap = min_gap(remote);
434 remote->max_remaining_gap = max_gap(remote);
435 return (0);
436 }
437 } else {
438 remote->min_remaining_gap = min_gap(remote);
439 remote->max_remaining_gap = max_gap(remote);
440 }
441 /* update transmit state */
442 if (code->next != NULL) {
443 if (code->transmit_state == NULL) {
444 code->transmit_state = code->next;
445 } else {
446 code->transmit_state = code->transmit_state->next;
447 if (is_xmp(remote) && code->transmit_state == NULL) {
448 code->transmit_state = code->next;
449 }
450 }
451 }
452 if ((remote->repeat_countdown > 0 || code->transmit_state != NULL)
453 && remote->min_remaining_gap < LIRCD_EXACT_GAP_THRESHOLD) {
454 if (send_buffer.data != send_buffer._data) {
455 lirc_t *signals;
456 int n;
457
458 LOGPRINTF(1, "unrolling raw signal optimisation");
459 signals = send_buffer.data;
460 n = send_buffer.wptr;
461 send_buffer.data = send_buffer._data;
462 send_buffer.wptr = 0;
463
464 send_signals(signals, n);
465 }
466 LOGPRINTF(1, "concatenating low gap signals");
467 if (code->next == NULL || code->transmit_state == NULL) {
468 remote->repeat_countdown--;
469 }
470 send_space(remote->min_remaining_gap);
471 flush_send_buffer();
472 send_buffer.sum = 0;
473
474 repeat = 1;
475 goto init_send_loop;
476 }
477 LOGPRINTF(3, "transmit buffer ready");
478
479 final_check:
480 if (!check_send_buffer()) {
481 if (!sim) {
482 logprintf(LOG_ERR, "invalid send buffer");
483 logprintf(LOG_ERR, "this remote configuration cannot be used to transmit");
484 }
485 return 0;
486 }
487 return 1;
488 }
489