Skip to content

Commit 1d971d9

Browse files
pesinttamchehab
authored andcommitted
[media] rc: rc-ir-raw: Add Manchester encoder (phase encoder) helper
Adding a simple Manchester encoder to rc-core. Manchester coding is used by at least RC-5 and RC-6 protocols and their variants. Signed-off-by: Antti Seppälä <a.seppala@gmail.com> Signed-off-by: James Hogan <james@albanarts.com> Cc: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
1 parent 9869da5 commit 1d971d9

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

drivers/media/rc/rc-core-priv.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,39 @@ static inline bool is_timing_event(struct ir_raw_event ev)
152152
#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
153153
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
154154

155+
/* functions for IR encoders */
156+
157+
static inline void init_ir_raw_event_duration(struct ir_raw_event *ev,
158+
unsigned int pulse,
159+
u32 duration)
160+
{
161+
init_ir_raw_event(ev);
162+
ev->duration = duration;
163+
ev->pulse = pulse;
164+
}
165+
166+
/**
167+
* struct ir_raw_timings_manchester - Manchester coding timings
168+
* @leader: duration of leader pulse (if any) 0 if continuing
169+
* existing signal (see @pulse_space_start)
170+
* @pulse_space_start: 1 for starting with pulse (0 for starting with space)
171+
* @clock: duration of each pulse/space in ns
172+
* @invert: if set clock logic is inverted
173+
* (0 = space + pulse, 1 = pulse + space)
174+
* @trailer_space: duration of trailer space in ns
175+
*/
176+
struct ir_raw_timings_manchester {
177+
unsigned int leader;
178+
unsigned int pulse_space_start:1;
179+
unsigned int clock;
180+
unsigned int invert:1;
181+
unsigned int trailer_space;
182+
};
183+
184+
int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
185+
const struct ir_raw_timings_manchester *timings,
186+
unsigned int n, unsigned int data);
187+
155188
/*
156189
* Routines from rc-raw.c to be used internally and by decoders
157190
*/

drivers/media/rc/rc-ir-raw.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,91 @@ static int change_protocol(struct rc_dev *dev, u64 *rc_type)
246246
return 0;
247247
}
248248

249+
/**
250+
* ir_raw_gen_manchester() - Encode data with Manchester (bi-phase) modulation.
251+
* @ev: Pointer to pointer to next free event. *@ev is incremented for
252+
* each raw event filled.
253+
* @max: Maximum number of raw events to fill.
254+
* @timings: Manchester modulation timings.
255+
* @n: Number of bits of data.
256+
* @data: Data bits to encode.
257+
*
258+
* Encodes the @n least significant bits of @data using Manchester (bi-phase)
259+
* modulation with the timing characteristics described by @timings, writing up
260+
* to @max raw IR events using the *@ev pointer.
261+
*
262+
* Returns: 0 on success.
263+
* -ENOBUFS if there isn't enough space in the array to fit the
264+
* full encoded data. In this case all @max events will have been
265+
* written.
266+
*/
267+
int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
268+
const struct ir_raw_timings_manchester *timings,
269+
unsigned int n, unsigned int data)
270+
{
271+
bool need_pulse;
272+
unsigned int i;
273+
int ret = -ENOBUFS;
274+
275+
i = 1 << (n - 1);
276+
277+
if (timings->leader) {
278+
if (!max--)
279+
return ret;
280+
if (timings->pulse_space_start) {
281+
init_ir_raw_event_duration((*ev)++, 1, timings->leader);
282+
283+
if (!max--)
284+
return ret;
285+
init_ir_raw_event_duration((*ev), 0, timings->leader);
286+
} else {
287+
init_ir_raw_event_duration((*ev), 1, timings->leader);
288+
}
289+
i >>= 1;
290+
} else {
291+
/* continue existing signal */
292+
--(*ev);
293+
}
294+
/* from here on *ev will point to the last event rather than the next */
295+
296+
while (n && i > 0) {
297+
need_pulse = !(data & i);
298+
if (timings->invert)
299+
need_pulse = !need_pulse;
300+
if (need_pulse == !!(*ev)->pulse) {
301+
(*ev)->duration += timings->clock;
302+
} else {
303+
if (!max--)
304+
goto nobufs;
305+
init_ir_raw_event_duration(++(*ev), need_pulse,
306+
timings->clock);
307+
}
308+
309+
if (!max--)
310+
goto nobufs;
311+
init_ir_raw_event_duration(++(*ev), !need_pulse,
312+
timings->clock);
313+
i >>= 1;
314+
}
315+
316+
if (timings->trailer_space) {
317+
if (!(*ev)->pulse)
318+
(*ev)->duration += timings->trailer_space;
319+
else if (!max--)
320+
goto nobufs;
321+
else
322+
init_ir_raw_event_duration(++(*ev), 0,
323+
timings->trailer_space);
324+
}
325+
326+
ret = 0;
327+
nobufs:
328+
/* point to the next event rather than last event before returning */
329+
++(*ev);
330+
return ret;
331+
}
332+
EXPORT_SYMBOL(ir_raw_gen_manchester);
333+
249334
/**
250335
* ir_raw_encode_scancode() - Encode a scancode as raw events
251336
*

0 commit comments

Comments
 (0)