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.
27 * This libsigrokdecode incarnation of IRMP will always be used in the
28 * UNIX_OR_WINDOWS configuration. But libtool(1) breaks the upstream
29 * logic's platform detection. Check reliably available conditions here
30 * and provide expected symbols to the library, to reduce changes to the
42 * The remaining source code implements the PC library, which accepts
43 * sample data from API callers, and provides detector results as they
44 * become available after seeing input data.
46 * TODO items, known constraints
47 * - Counters in the IRMP core logic and the library wrapper are 32bit
48 * only. In the strictest sense they only need to cover the span of
49 * an IR frame. In the PC side library case they need to cover "a
50 * detection phase", which happens to be under calling applications'
51 * control. The library shall not mess with the core's internal state,
52 * and may even not be able to reliably tell whether detection of a
53 * frame started in the core. Fortunately the 32bit counters only roll
54 * over after some 2.5 days at the highest available sample rate. So
55 * this limitation is not a blocker.
56 * - The IRMP core keeps internal state in global variables. Which is
57 * appropriate for MCU configurations. For the PC library use case
58 * this constraint prevents concurrency, only a single data stream
59 * can get processed at any time. This limitation can get addressed
60 * later, making the flexible and featureful IRMP detection available
61 * in the first place is considered highly desirable, and is a great
62 * improvement in itself.
63 * - The detection of IR frames from buffered data is both limited and
64 * complicated at the same time. The routine re-uses the caller's
65 * buffer _and_ internal state across multiple calls. Thus windowed
66 * operation over a larger set of input data is not available. The
67 * API lacks a flag for failed detection, thus applications need to
68 * guess from always returned payload data.
69 * - Is it worth adding a "detection in progress" query to the API? Is
70 * the information available to the library wrapper, and reliable?
71 * Shall applications be able to "poll" the started, and completed
72 * state for streamed operation including periodic state resets which
73 * won't interfere with pending detection? (It's assumed that this
74 * is only required when feeding single values in individual calls is
75 * found to be rather expensive.
76 * - Some of the result data reflects the core's internal presentation
77 * while there is no declaration in the library's API. This violates
78 * API layers, and needs to get addressed properly.
79 * - The IRMP core logic (strictly speaking the specific details of
80 * preprocessor symbol arrangements in the current implementation)
81 * appears to assume either to run on an MCU and capture IR signals
82 * from hardware pins, falling back to AVR if no other platform got
83 * detected. Or assumes to run on a (desktop) PC, and automatically
84 * enables ANALYZE mode, which results in lots of stdio traffic that
85 * is undesirable for application code which uses the shared library
86 * for strict detection purposes but no further analysis or research.
87 * It's a pity that turning off ANALYZE switches to MCU mode, and that
88 * keeping ANALYZE enabled but silencing the output is rather messy
89 * and touches the innards of the core logic (the irmp.c source file
90 * and its dependency header files).
94 # define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
97 static uint32_t s_end_sample;
99 IRMP_DLLEXPORT uint32_t irmp_get_sample_rate(void)
104 IRMP_DLLEXPORT void irmp_reset_state(void)
110 * Provide the equivalent of 1s idle input signal level. Then
111 * drain any potentially accumulated result data. This clears
112 * the internal decoder state.
119 (void)irmp_get_data(&data);
122 s_startBitSample = 0;
127 * TODO This is not the most appropriate location to control the
128 * core logic's verbosity. But out of the public set of library
129 * routines this call is closest to some initialization routine.
130 * The query for compile time parameter values is optional, the
131 * state reset is not. Multiple verbosity setup activities in
132 * the same program lifetime won't harm. This HACK is clearly
133 * preferrable over more fiddling with core logic innards, or
134 * the introduction of yet another DLL routine.
140 IRMP_DLLEXPORT int irmp_add_one_sample(int sample)
144 IRMP_PIN = sample ? 0xff : 0x00;
145 ret = irmp_ISR() ? 1 : 0;
146 s_end_sample = s_curSample++;
150 IRMP_DLLEXPORT int irmp_get_result_data(struct irmp_result_data *data)
154 if (!irmp_get_data(&d))
157 data->address = d.address;
158 data->command = d.command;
159 data->protocol = d.protocol;
160 data->protocol_name = irmp_get_protocol_name(d.protocol);
161 data->flags = d.flags;
162 data->start_sample = s_startBitSample;
163 data->end_sample = s_end_sample;
167 #if WITH_IRMP_DETECT_BUFFER
168 IRMP_DLLEXPORT struct irmp_result_data irmp_detect_buffer(const uint8_t *buff, size_t len)
170 struct irmp_result_data ret;
172 memset(&ret, 0, sizeof(ret));
173 while (s_curSample < len) {
174 if (irmp_add_one_sample(buff[s_curSample])) {
175 irmp_get_result_data(&ret);
183 IRMP_DLLEXPORT const char *irmp_get_protocol_name(uint32_t protocol)
187 if (protocol >= ARRAY_SIZE(irmp_protocol_names))
189 name = irmp_protocol_names[protocol];