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