LIRC libraries LinuxInfraredRemoteControl

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

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