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