LIRC libraries
LinuxInfraredRemoteControl
 All Classes Files Functions Variables Typedefs Enumerations Macros Modules 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 #ifdef HAVE_KERNEL_LIRC_H
26 #include <linux/lirc.h>
27 #else
28 #include "media/lirc.h"
29 #endif
30 
31 #include "lirc/lirc_log.h"
32 #include "lirc/transmit.h"
33 
34 static const logchannel_t logchannel = LOG_LIB;
35 
39 static struct sbuf {
40  lirc_t* data;
41 
42  lirc_t _data[WBUF_SIZE];
43  int wptr;
44  int too_long;
45  int is_biphase;
46  lirc_t pendingp;
47  lirc_t pendings;
48  lirc_t sum;
49 } send_buffer;
50 
51 
52 static void send_signals(lirc_t* signals, int n);
53 static int init_send_or_sim(struct ir_remote* remote, struct ir_ncode* code, int sim, int repeat_preset);
54 
55 /*
56  * sending stuff
57  */
58 
62 void send_buffer_init(void)
63 {
64  memset(&send_buffer, 0, sizeof(send_buffer));
65 }
66 
67 static void clear_send_buffer(void)
68 {
69  log_trace2("clearing transmit buffer");
70  send_buffer.wptr = 0;
71  send_buffer.too_long = 0;
72  send_buffer.is_biphase = 0;
73  send_buffer.pendingp = 0;
74  send_buffer.pendings = 0;
75  send_buffer.sum = 0;
76 }
77 
78 static void add_send_buffer(lirc_t data)
79 {
80  if (send_buffer.wptr < WBUF_SIZE) {
81  log_trace2("adding to transmit buffer: %u", data);
82  send_buffer.sum += data;
83  send_buffer._data[send_buffer.wptr] = data;
84  send_buffer.wptr++;
85  } else {
86  send_buffer.too_long = 1;
87  }
88 }
89 
90 static void send_pulse(lirc_t data)
91 {
92  if (send_buffer.pendingp > 0) {
93  send_buffer.pendingp += data;
94  } else {
95  if (send_buffer.pendings > 0) {
96  add_send_buffer(send_buffer.pendings);
97  send_buffer.pendings = 0;
98  }
99  send_buffer.pendingp = data;
100  }
101 }
102 
103 static void send_space(lirc_t data)
104 {
105  if (send_buffer.wptr == 0 && send_buffer.pendingp == 0) {
106  log_trace("first signal is a space!");
107  return;
108  }
109  if (send_buffer.pendings > 0) {
110  send_buffer.pendings += data;
111  } else {
112  if (send_buffer.pendingp > 0) {
113  add_send_buffer(send_buffer.pendingp);
114  send_buffer.pendingp = 0;
115  }
116  send_buffer.pendings = data;
117  }
118 }
119 
120 static int bad_send_buffer(void)
121 {
122  if (send_buffer.too_long != 0)
123  return 1;
124  if (send_buffer.wptr == WBUF_SIZE && send_buffer.pendingp > 0)
125  return 1;
126  return 0;
127 }
128 
129 static int check_send_buffer(void)
130 {
131  int i;
132 
133  if (send_buffer.wptr == 0) {
134  log_trace("nothing to send");
135  return 0;
136  }
137  for (i = 0; i < send_buffer.wptr; i++) {
138  if (send_buffer.data[i] == 0) {
139  if (i % 2) {
140  log_trace("invalid space: %d", i);
141  } else {
142  log_trace("invalid pulse: %d", i);
143  }
144  return 0;
145  }
146  }
147 
148  return 1;
149 }
150 
151 static void flush_send_buffer(void)
152 {
153  if (send_buffer.pendingp > 0) {
154  add_send_buffer(send_buffer.pendingp);
155  send_buffer.pendingp = 0;
156  }
157  if (send_buffer.pendings > 0) {
158  add_send_buffer(send_buffer.pendings);
159  send_buffer.pendings = 0;
160  }
161 }
162 
163 static void sync_send_buffer(void)
164 {
165  if (send_buffer.pendingp > 0) {
166  add_send_buffer(send_buffer.pendingp);
167  send_buffer.pendingp = 0;
168  }
169  if (send_buffer.wptr > 0 && send_buffer.wptr % 2 == 0)
170  send_buffer.wptr--;
171 }
172 
173 static void send_header(struct ir_remote* remote)
174 {
175  if (has_header(remote)) {
176  send_pulse(remote->phead);
177  send_space(remote->shead);
178  }
179 }
180 
181 static void send_foot(struct ir_remote* remote)
182 {
183  if (has_foot(remote)) {
184  send_space(remote->sfoot);
185  send_pulse(remote->pfoot);
186  }
187 }
188 
189 static void send_lead(struct ir_remote* remote)
190 {
191  if (remote->plead != 0)
192  send_pulse(remote->plead);
193 }
194 
195 static void send_trail(struct ir_remote* remote)
196 {
197  if (remote->ptrail != 0)
198  send_pulse(remote->ptrail);
199 }
200 
201 static void send_data(struct ir_remote* remote, ir_code data, int bits, int done)
202 {
203  int i;
204  int all_bits = bit_count(remote);
205  int toggle_bit_mask_bits = bits_set(remote->toggle_bit_mask);
206  ir_code mask;
207 
208  data = reverse(data, bits);
209  if (is_rcmm(remote)) {
210  mask = 1 << (all_bits - 1 - done);
211  if (bits % 2 || done % 2) {
212  log_error("invalid bit number.");
213  return;
214  }
215  for (i = 0; i < bits; i += 2, mask >>= 2) {
216  switch (data & 3) {
217  case 0:
218  send_pulse(remote->pzero);
219  send_space(remote->szero);
220  break;
221  /* 2 and 1 swapped due to reverse() */
222  case 2:
223  send_pulse(remote->pone);
224  send_space(remote->sone);
225  break;
226  case 1:
227  send_pulse(remote->ptwo);
228  send_space(remote->stwo);
229  break;
230  case 3:
231  send_pulse(remote->pthree);
232  send_space(remote->sthree);
233  break;
234  }
235  data = data >> 2;
236  }
237  return;
238  } else if (is_xmp(remote)) {
239  if (bits % 4 || done % 4) {
240  log_error("invalid bit number.");
241  return;
242  }
243  for (i = 0; i < bits; i += 4) {
244  ir_code nibble;
245 
246  nibble = reverse(data & 0xf, 4);
247  send_pulse(remote->pzero);
248  send_space(remote->szero + nibble * remote->sone);
249  data >>= 4;
250  }
251  return;
252  }
253 
254  mask = ((ir_code)1) << (all_bits - 1 - done);
255  for (i = 0; i < bits; i++, mask >>= 1) {
256  if (has_toggle_bit_mask(remote) && mask & remote->toggle_bit_mask) {
257  if (toggle_bit_mask_bits == 1) {
258  /* backwards compatibility */
259  data &= ~((ir_code)1);
260  if (remote->toggle_bit_mask_state & mask)
261  data |= (ir_code)1;
262  } else {
263  if (remote->toggle_bit_mask_state & mask)
264  data ^= (ir_code)1;
265  }
266  }
267  if (has_toggle_mask(remote) && mask & remote->toggle_mask && remote->toggle_mask_state % 2)
268  data ^= 1;
269  if (data & 1) {
270  if (is_biphase(remote)) {
271  if (mask & remote->rc6_mask) {
272  send_space(2 * remote->sone);
273  send_pulse(2 * remote->pone);
274  } else {
275  send_space(remote->sone);
276  send_pulse(remote->pone);
277  }
278  } else if (is_space_first(remote)) {
279  send_space(remote->sone);
280  send_pulse(remote->pone);
281  } else {
282  send_pulse(remote->pone);
283  send_space(remote->sone);
284  }
285  } else {
286  if (mask & remote->rc6_mask) {
287  send_pulse(2 * remote->pzero);
288  send_space(2 * remote->szero);
289  } else if (is_space_first(remote)) {
290  send_space(remote->szero);
291  send_pulse(remote->pzero);
292  } else {
293  send_pulse(remote->pzero);
294  send_space(remote->szero);
295  }
296  }
297  data = data >> 1;
298  }
299 }
300 
301 static void send_pre(struct ir_remote* remote)
302 {
303  if (has_pre(remote)) {
304  send_data(remote, remote->pre_data, remote->pre_data_bits, 0);
305  if (remote->pre_p > 0 && remote->pre_s > 0) {
306  send_pulse(remote->pre_p);
307  send_space(remote->pre_s);
308  }
309  }
310 }
311 
312 static void send_post(struct ir_remote* remote)
313 {
314  if (has_post(remote)) {
315  if (remote->post_p > 0 && remote->post_s > 0) {
316  send_pulse(remote->post_p);
317  send_space(remote->post_s);
318  }
319  send_data(remote, remote->post_data, remote->post_data_bits, remote->pre_data_bits + remote->bits);
320  }
321 }
322 
323 static void send_repeat(struct ir_remote* remote)
324 {
325  send_lead(remote);
326  send_pulse(remote->prepeat);
327  send_space(remote->srepeat);
328  send_trail(remote);
329 }
330 
331 static void send_code(struct ir_remote* remote, ir_code code, int repeat)
332 {
333  if (!repeat || !(remote->flags & NO_HEAD_REP))
334  send_header(remote);
335  send_lead(remote);
336  send_pre(remote);
337  send_data(remote, code, remote->bits, remote->pre_data_bits);
338  send_post(remote);
339  send_trail(remote);
340  if (!repeat || !(remote->flags & NO_FOOT_REP))
341  send_foot(remote);
342 
343  if (!repeat && remote->flags & NO_HEAD_REP && remote->flags & CONST_LENGTH)
344  send_buffer.sum -= remote->phead + remote->shead;
345 }
346 
347 static void send_signals(lirc_t* signals, int n)
348 {
349  int i;
350 
351  for (i = 0; i < n; i++)
352  add_send_buffer(signals[i]);
353 }
354 
355 int send_buffer_put(struct ir_remote* remote, struct ir_ncode* code)
356 {
357  return init_send_or_sim(remote, code, 0, 0);
358 }
359 
364 int init_sim(struct ir_remote* remote, struct ir_ncode* code, int repeat_preset)
365 {
366  return init_send_or_sim(remote, code, 1, repeat_preset);
367 }
374 {
375  return send_buffer.wptr;
376 }
377 
378 
379 const lirc_t* send_buffer_data(void)
380 {
381  return send_buffer.data;
382 }
383 
384 lirc_t send_buffer_sum(void)
385 {
386  return send_buffer.sum;
387 }
388 
389 static int init_send_or_sim(struct ir_remote* remote, struct ir_ncode* code, int sim, int repeat_preset)
390 {
391  int i, repeat = repeat_preset;
392 
393  if (is_grundig(remote) || is_goldstar(remote) || is_serial(remote) || is_bo(remote)) {
394  if (!sim)
395  log_error("sorry, can't send this protocol yet");
396  return 0;
397  }
398  clear_send_buffer();
399  if (strcmp(remote->name, "lirc") == 0) {
400  send_buffer.data[send_buffer.wptr] = LIRC_EOF | 1;
401  send_buffer.wptr += 1;
402  goto final_check;
403  }
404 
405  if (is_biphase(remote))
406  send_buffer.is_biphase = 1;
407  if (!sim) {
408  if (repeat_remote == NULL)
409  remote->repeat_countdown = remote->min_repeat;
410  else
411  repeat = 1;
412  }
413 
414 init_send_loop:
415  if (repeat && has_repeat(remote)) {
416  if (remote->flags & REPEAT_HEADER && has_header(remote))
417  send_header(remote);
418  send_repeat(remote);
419  } else {
420  if (!is_raw(remote)) {
421  ir_code next_code;
422 
423  if (sim || code->transmit_state == NULL)
424  next_code = code->code;
425  else
426  next_code = code->transmit_state->code;
427 
428  if (repeat && has_repeat_mask(remote))
429  next_code ^= remote->repeat_mask;
430 
431  send_code(remote, next_code, repeat);
432  if (!sim && has_toggle_mask(remote)) {
433  remote->toggle_mask_state++;
434  if (remote->toggle_mask_state == 4)
435  remote->toggle_mask_state = 2;
436  }
437  send_buffer.data = send_buffer._data;
438  } else {
439  if (code->signals == NULL) {
440  if (!sim)
441  log_error("no signals for raw send");
442  return 0;
443  }
444  if (send_buffer.wptr > 0) {
445  send_signals(code->signals, code->length);
446  } else {
447  send_buffer.data = code->signals;
448  send_buffer.wptr = code->length;
449  for (i = 0; i < code->length; i++)
450  send_buffer.sum += code->signals[i];
451  }
452  }
453  }
454  sync_send_buffer();
455  if (bad_send_buffer()) {
456  if (!sim)
457  log_error("buffer too small");
458  return 0;
459  }
460  if (sim)
461  goto final_check;
462 
463  if (has_repeat_gap(remote) && repeat && has_repeat(remote)) {
464  remote->min_remaining_gap = remote->repeat_gap;
465  remote->max_remaining_gap = remote->repeat_gap;
466  } else if (is_const(remote)) {
467  if (min_gap(remote) > send_buffer.sum) {
468  remote->min_remaining_gap = min_gap(remote) - send_buffer.sum;
469  remote->max_remaining_gap = max_gap(remote) - send_buffer.sum;
470  } else {
471  log_error("too short gap: %u", remote->gap);
472  remote->min_remaining_gap = min_gap(remote);
473  remote->max_remaining_gap = max_gap(remote);
474  return 0;
475  }
476  } else {
477  remote->min_remaining_gap = min_gap(remote);
478  remote->max_remaining_gap = max_gap(remote);
479  }
480  /* update transmit state */
481  if (code->next != NULL) {
482  if (code->transmit_state == NULL) {
483  code->transmit_state = code->next;
484  } else {
485  code->transmit_state = code->transmit_state->next;
486  if (is_xmp(remote) && code->transmit_state == NULL)
487  code->transmit_state = code->next;
488  }
489  }
490  if ((remote->repeat_countdown > 0 || code->transmit_state != NULL)
491  && remote->min_remaining_gap < LIRCD_EXACT_GAP_THRESHOLD) {
492  if (send_buffer.data != send_buffer._data) {
493  lirc_t* signals;
494  int n;
495 
496  log_trace("unrolling raw signal optimisation");
497  signals = send_buffer.data;
498  n = send_buffer.wptr;
499  send_buffer.data = send_buffer._data;
500  send_buffer.wptr = 0;
501 
502  send_signals(signals, n);
503  }
504  log_trace("concatenating low gap signals");
505  if (code->next == NULL || code->transmit_state == NULL)
506  remote->repeat_countdown--;
507  send_space(remote->min_remaining_gap);
508  flush_send_buffer();
509  send_buffer.sum = 0;
510 
511  repeat = 1;
512  goto init_send_loop;
513  }
514  log_trace2("transmit buffer ready");
515 
516 final_check:
517  if (!check_send_buffer()) {
518  if (!sim) {
519  log_error("invalid send buffer");
520  log_error("this remote configuration cannot be used to transmit");
521  }
522  return 0;
523  }
524  return 1;
525 }
lirc_t min_remaining_gap
remember gap for CONST_LENGTH remotes
One remote as represented in the configuration file.
int bits
bits (length of code)
const lirc_t * send_buffer_data(void)
Definition: transmit.c:379
#define NO_FOOT_REP
no foot for key repeats
ir_code post_data
data which the remote sends after actual keycode
lirc_t post_s
signal between keycode and post_code
lirc_t plead
leading pulse
ir_code repeat_mask
mask defines which bits are inverted for repeats
struct ir_code_node * next
Linked list of the subsequent ir_code's, after the first one.
const char * name
name of remote control
lirc_t * signals
(private)
#define LIRC_EOF
Bit manipulator in lirc_t, see lirc.h .
Definition: lirc_config.h:90
lirc_t sfoot
foot
lirc_t ptrail
trailing pulse
int pre_data_bits
length of pre_data
logchannel_t
Log channels used to filter messages.
Definition: lirc_log.h:53
#define log_trace2(fmt,...)
Log a trace2 message.
Definition: lirc_log.h:139
int post_data_bits
length of post_data
lirc_t sthree
3 (only used for RC-MM)
ir_code toggle_mask
Sharp (?) error detection scheme.
#define log_error(fmt,...)
Log an error message.
Definition: lirc_log.h:104
ir_code pre_data
data which the remote sends before actual keycode
lirc_t send_buffer_sum(void)
Definition: transmit.c:384
uint32_t gap
time between signals in usecs
#define log_trace(fmt,...)
Log a trace message.
Definition: lirc_log.h:129
lirc_t sone
1
void send_buffer_init(void)
Initializes the global sending buffer.
Definition: transmit.c:62
uint32_t repeat_gap
time between two repeat codes if different from gap
lirc_t shead
header
#define REPEAT_HEADER
header is also sent before repeat code
int send_buffer_put(struct ir_remote *remote, struct ir_ncode *code)
Initializes the global send buffer for transmitting the code in the second argument, residing in the remote in the first.
Definition: transmit.c:355
#define CONST_LENGTH
signal length+gap is always constant
#define NO_HEAD_REP
no header for key repeats
lirc_t pre_s
signal between pre_data and keycode
lirc_t szero
0
IR Command, corresponding to one (command defining) line of the configuration file.
lirc_t stwo
2 (only used for RC-MM)
int flags
flags
lirc_t srepeat
indicate repeating
struct ir_code_node * transmit_state
(private)
lirc_t max_remaining_gap
gap range
ir_code code
The first code of the command.
ir_code rc6_mask
RC-6 doubles signal length of some bits.
int send_buffer_length(void)
Do not document this function.
Definition: transmit.c:373
struct ir_remote * repeat_remote
Global pointer to the remote that contains the code currently repeating.
Definition: ir_remote.c:61
ir_code toggle_bit_mask
previously only one bit called toggle_bit
int min_repeat
code is repeated at least x times code sent once -> min_repeat=0
uint64_t ir_code
Denotes an internal coded representation for an IR transmission.
int length
(private)