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