LIRC libraries
LinuxInfraredRemoteControl
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Groups Pages
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 }
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 }
lirc_t min_remaining_gap
const lirc_t * send_buffer_data(void)
Definition: transmit.c:372
#define NO_FOOT_REP
ir_code post_data
ir_code repeat_mask
struct ir_code_node * next
const char * name
lirc_t * signals
#define LIRC_EOF
Definition: lirc_config.h:104
__u64 ir_code
ir_code toggle_mask
ir_code pre_data
lirc_t send_buffer_sum(void)
Definition: transmit.c:377
void send_buffer_init(void)
Definition: transmit.c:55
#define REPEAT_HEADER
int send_buffer_put(struct ir_remote *remote, struct ir_ncode *code)
Definition: transmit.c:348
__u32 repeat_gap
#define CONST_LENGTH
#define NO_HEAD_REP
#define LOGPRINTF(level, fmt, args...)
Definition: lirc_log.h:75
lirc_t srepeat
struct ir_code_node * transmit_state
lirc_t max_remaining_gap
ir_code code
ir_code rc6_mask
int send_buffer_length(void)
Definition: transmit.c:366
struct ir_remote * repeat_remote
Definition: ir_remote.c:53
ir_code toggle_bit_mask