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