2 * irmp-main-sharedlib.c
4 * Copyright (c) 2009-2019 Frank Meyer - frank(at)fli4l.de
5 * Copyright (c) 2009-2019 René Staffen - r.staffen(at)gmx.de
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
14 * Declare the library's public API first. Prove it's consistent and
15 * complete as a standalone header file.
17 #include "irmp-main-sharedlib.h"
23 * Include the IRMP core logic. This approach is required because of
24 * static variables which hold internal state. The core logic started
25 * as an MCU project where resources are severely constrained.
31 * The remaining source code implements the PC library, which accepts
32 * sample data from API callers, and provides detector results as they
33 * become available after seeing input data.
35 * TODO items, known constraints
36 * - Counters in the IRMP core logic and the library wrapper are 32bit
37 * only. In the strictest sense they only need to cover the span of
38 * an IR frame. In the PC side library case they need to cover "a
39 * detection phase", which happens to be under calling applications'
40 * control. The library shall not mess with the core's internal state,
41 * and may even not be able to reliably tell whether detection of a
42 * frame started in the core. Fortunately the 32bit counters only roll
43 * over after some 2.5 days at the highest available sample rate. So
44 * this limitation is not a blocker.
45 * - The IRMP core keeps internal state in global variables. Which is
46 * appropriate for MCU configurations. For the PC library use case
47 * this constraint prevents concurrency, only a single data stream
48 * can get processed at any time. This limitation can get addressed
49 * later, making the flexible and featureful IRMP detection available
50 * in the first place is considered highly desirable, and is a great
51 * improvement in itself.
52 * - The detection of IR frames from buffered data is both limited and
53 * complicated at the same time. The routine re-uses the caller's
54 * buffer _and_ internal state across multiple calls. Thus windowed
55 * operation over a larger set of input data is not available. The
56 * API lacks a flag for failed detection, thus applications need to
57 * guess from always returned payload data.
58 * - Is it worth adding a "detection in progress" query to the API? Is
59 * the information available to the library wrapper, and reliable?
60 * Shall applications be able to "poll" the started, and completed
61 * state for streamed operation including periodic state resets which
62 * won't interfere with pending detection? (It's assumed that this
63 * is only required when feeding single values in individual calls is
64 * found to be rather expensive.
65 * - Some of the result data reflects the core's internal presentation
66 * while there is no declaration in the library's API. This violates
67 * API layers, and needs to get addressed properly.
68 * - The IRMP core logic (strictly speaking the specific details of
69 * preprocessor symbol arrangements in the current implementation)
70 * appears to assume either to run on an MCU and capture IR signals
71 * from hardware pins, falling back to AVR if no other platform got
72 * detected. Or assumes to run on a (desktop) PC, and automatically
73 * enables ANALYZE mode, which results in lots of stdio traffic that
74 * is undesirable for application code which uses the shared library
75 * for strict detection purposes but no further analysis or research.
76 * It's a pity that turning off ANALYZE switches to MCU mode, and that
77 * keeping ANALYZE enabled but silencing the output is rather messy
78 * and touches the innards of the core logic (the irmp.c source file
79 * and its dependency header files).
83 # define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
86 static uint32_t s_end_sample;
88 IRMP_DLLEXPORT uint32_t irmp_get_sample_rate(void)
93 IRMP_DLLEXPORT void irmp_reset_state(void)
99 * Provide the equivalent of 1s idle input signal level. Then
100 * drain any potentially accumulated result data. This clears
101 * the internal decoder state.
108 (void)irmp_get_data(&data);
111 s_startBitSample = 0;
116 IRMP_DLLEXPORT int irmp_add_one_sample(int sample)
120 IRMP_PIN = sample ? 0xff : 0x00;
121 ret = irmp_ISR() ? 1 : 0;
122 s_end_sample = s_curSample++;
126 IRMP_DLLEXPORT int irmp_get_result_data(struct irmp_result_data *data)
130 if (!irmp_get_data(&d))
133 data->address = d.address;
134 data->command = d.command;
135 data->protocol = d.protocol;
136 data->protocol_name = irmp_get_protocol_name(d.protocol);
137 data->flags = d.flags;
138 data->start_sample = s_startBitSample;
139 data->end_sample = s_end_sample;
143 #if WITH_IRMP_DETECT_BUFFER
144 IRMP_DLLEXPORT struct irmp_result_data irmp_detect_buffer(const uint8_t *buff, size_t len)
146 struct irmp_result_data ret;
148 memset(&ret, 0, sizeof(ret));
149 while (s_curSample < len) {
150 if (irmp_add_one_sample(buff[s_curSample])) {
151 irmp_get_result_data(&ret);
159 IRMP_DLLEXPORT const char *irmp_get_protocol_name(uint32_t protocol)
163 if (protocol >= ARRAY_SIZE(irmp_protocol_names))
165 name = irmp_protocol_names[protocol];