15 if (str.indexOf(
"(") != -1) {
16 DEBUG(
"Meaning::maybe() returns true.\n");
24 return (elements.size() > 0);
41 repeats = train.repeats;
44 typedef struct prevalence_t {
48 prevalence_t prevalence[train.bins.size()];
49 for (
int n = 0; n < train.bins.size(); n++) {
50 prevalence[n].bin = n;
51 prevalence[n].count = train.bins[n].count;
55 for (
int i = 0; i < train.bins.size(); i++) {
56 for (
int j = 0; j < train.bins.size() - i - 1; j++) {
57 if (prevalence[j].count < prevalence[j + 1].count) {
59 prevalence[j] = prevalence[j + 1];
60 prevalence[j + 1] = temp;
65 bool likely_PWM =
false;
67 train.bins.size() >= 2 &&
68 abs(prevalence[0].count - prevalence[1].count) <= 2
72 DEBUG(
"likely_PWM set.\n", likely_PWM);
76 bool likely_PPM =
false;
78 train.bins.size() >= 3 &&
79 prevalence[0].count - (prevalence[1].count + prevalence[2].count) >= -2 &&
80 prevalence[0].count - (prevalence[1].count + prevalence[2].count) <= 4
84 DEBUG(
"likely_PPM set.\n", likely_PPM);
87 if (!likely_PWM && !likely_PPM) {
88 DEBUG(
"Could not parse Pulsetrain, no likely modulation found.\n");
92 bool something_decoded =
false;
93 for (
int n = 0; n < train.transitions.size(); n++) {
96 r =
parsePWM(train
, n
, train.transitions.size() - 1
, prevalence[0].bin
, prevalence[1].bin
);
97 }
else if (likely_PPM) {
98 r =
parsePPM(train
, n
, train.transitions.size() - 1
, prevalence[1].bin
, prevalence[2].bin
, prevalence[0].bin
);
104 something_decoded =
true;
109 if (!addPulse(train.bins[train.transitions[n]].average)) {
113 if (!addGap(train.bins[train.transitions[n]].average)) {
118 if (!something_decoded) {
122 if (train.repeats > 1) {
125 return (elements.size() > 0);
136 DEBUG (
"Entered parsePWM with from: %i, to: %i space: %i, mark: %i\n", from, to, space, mark);
138 int transitions_parsed = 0;
140 for (
int n = from; n <= to; n += 2) {
141 int current = train.transitions[n];
142 int next = train.transitions[n + 1];
143 if (current == space && next == mark) {
145 tools::shiftInBit(tmp_data, num_bits, 0);
146 transitions_parsed += 2;
147 }
else if (current == mark && next == space) {
149 tools::shiftInBit(tmp_data, num_bits, 1);
150 transitions_parsed += 2;
155 if (num_bits % 4 != 0) {
160 new_element.data_len = num_bits;
161 int len_in_bytes = (num_bits + 7) / 8;
163 for (
int n = 0; n < len_in_bytes; n++) {
164 new_element.data.insert(new_element.data.begin(), tmp_data[n]);
167 new_element.time1 = train.bins[space].average;
168 new_element.time2 = train.bins[mark].average;
169 elements.push_back(new_element);
170 return transitions_parsed;
185 DEBUG (
"Entered parsePPM with from: %i, to: %i space: %i, mark: %i, filler: %i\n", from, to, space, mark, filler);
187 int transitions_parsed = 0;
190 for (
int n = from; n <= to; n++) {
191 int current = train.transitions[n];
192 if (current == space && previous == filler) {
194 tools::shiftInBit(tmp_data, num_bits, 0);
195 transitions_parsed++;
196 }
else if (current == mark && previous == filler) {
198 tools::shiftInBit(tmp_data, num_bits, 1);
199 transitions_parsed++;
200 }
else if (current == filler) {
201 if (previous == filler) {
204 transitions_parsed++;
210 if (num_bits % 4 != 0) {
215 new_element.data_len = num_bits;
216 int len_in_bytes = (num_bits + 7) / 8;
218 for (
int n = 0; n < len_in_bytes; n++) {
219 new_element.data.insert(new_element.data.begin(), tmp_data[n]);
222 new_element.time1 = train.bins[space].average;
223 new_element.time2 = train.bins[mark].average;
224 new_element.time3 = train.bins[filler].average;
225 elements.push_back(new_element);
226 return transitions_parsed;
244 for (
const auto& element : elements) {
245 switch (element.type) {
253 snprintf_append(res, 60,
"pwm(timing %i/%i, %i bits 0x", element.time1, element.time2, element.data_len);
254 for (
int m = 0; m < (element.data_len + 7) / 8; m++) {
260 snprintf_append(res, 60,
"ppm(timing %i/%i/%i, %i bits 0x", element.time1, element.time2, element.time3, element.data_len);
261 for (
int m = 0; m < (element.data_len + 7) / 8; m++) {
269 res = res.substring(0, res.length() - 3);
271 snprintf_append(res, 40,
" Repeated %i times with %i µs gap.", repeats, gap);
274 res = res +
" (SUSPECTED INCOMPLETE)";
284 int rptd = in.indexOf(
"repeated");
286 String str_repeats = in.substring(rptd);
287 repeats = tools::nthNumberFrom(str_repeats, 0);
288 gap = tools::nthNumberFrom(str_repeats, 1);
289 in = in.substring(0, rptd);
290 if (repeats == 0
or gap == 0) {
291 ERROR(
"ERROR: cannot convert String to Meaning: invalid values for repeats or gap.\n");
298 int plus = in.indexOf(
"+");
300 work = in.substring(0, plus);
301 in = in.substring(plus + 1);
307 int open_bracket = work.indexOf(
"(");
308 int closing_bracket = work.indexOf(
")");
309 if (open_bracket == -1 || closing_bracket == -1) {
310 ERROR(
"ERROR: cannot convert String to Meaning: incorrect element '%s'.\n", work);
313 if (work.startsWith(
"pulse")) {
314 int num = tools::nthNumberFrom(work, 0);
316 ERROR(
"ERROR: cannot convert String to Meaning: no length found in '%s'.\n", work);
321 if (work.startsWith(
"gap")) {
322 int num = tools::nthNumberFrom(work, 0);
324 ERROR(
"ERROR: cannot convert String to Meaning: no length found in '%s'.\n", work);
329 if (work.startsWith(
"ppm")) {
330 int time1 = tools::nthNumberFrom(work, 0);
331 int time2 = tools::nthNumberFrom(work, 1);
332 int time3 = tools::nthNumberFrom(work, 2);
333 int bits = tools::nthNumberFrom(work, 3);
334 int check_zero = tools::nthNumberFrom(work, 4);
335 if (time1 < 1 || time2 < 1 || time3 < 1 || check_zero != 0) {
336 ERROR(
"ERROR: cannot convert String to Meaning: '%s' malformed.\n", work);
339 int data_start = work.indexOf(
"0x");
340 int data_end = work.indexOf(
")");
341 if (data_start == -1 || data_end < data_start) {
342 ERROR(
"ERROR: cannot convert String to Meaning: '%s' malformed.\n", work);
345 String hex_data = work.substring(data_start + 2, data_end);
346 int bytes_expected = (bits + 7) / 8;
347 if (hex_data.length() != bytes_expected * 2) {
348 ERROR(
"ERROR: cannot convert String to Meaning: %i bits means %i data bytes in hex expected.\n", bits, bytes_expected);
351 uint8_t tmp_data[bytes_expected];
352 for (
int n = 0; n < bytes_expected; n++) {
353 tmp_data[n] = strtoul(hex_data.substring(n * 2, (n * 2) + 2).c_str(),
nullptr, 16);
355 addPPM(time1, time2, time3, bits, tmp_data);
357 if (work.startsWith(
"pwm")) {
358 int time1 = tools::nthNumberFrom(work, 0);
359 int time2 = tools::nthNumberFrom(work, 1);
360 int bits = tools::nthNumberFrom(work, 2);
361 int check_zero = tools::nthNumberFrom(work, 3);
362 if (time1 < 1 || time2 < 1 || check_zero != 0) {
363 ERROR(
"ERROR: cannot convert String to Meaning: '%s' malformed.\n", work);
366 int data_start = work.indexOf(
"0x");
367 int data_end = work.indexOf(
")");
368 if (data_start == -1 || data_end < data_start) {
369 ERROR(
"ERROR: cannot convert String to Meaning: '%s' malformed.\n", work);
372 String hex_data = work.substring(data_start + 2, data_end);
373 tools::trim(hex_data);
374 int bytes_expected = (bits + 7) / 8;
375 if (hex_data.length() != bytes_expected * 2) {
376 ERROR(
"ERROR: cannot convert String to Meaning: %i bits means %i data bytes in hex expected.\n", bits, bytes_expected);
379 uint8_t tmp_data[bytes_expected];
380 for (
int n = 0; n < bytes_expected; n++) {
381 tmp_data[n] = strtoul(hex_data.substring(n * 2, (n * 2) + 2).c_str(),
nullptr, 16);
383 addPWM(time1, time2, bits, tmp_data);
395 new_element.time1 = pulse_time;
396 elements.push_back(new_element);
406 new_element.time1 = gap_time;
407 elements.push_back(new_element);
418 bool Meaning::
addPPM(
int space,
int mark,
int filler,
int bits, uint8_t* tmp_data) {
420 int len_in_bytes = (bits + 7) / 8;
421 new_element.data_len = bits;
422 for (
int n = 0; n < len_in_bytes; n++) {
423 new_element.data.push_back(tmp_data[n]);
426 new_element.time1 = space;
427 new_element.time2 = mark;
428 new_element.time3 = filler;
429 elements.push_back(new_element);
441 int len_in_bytes = (bits + 7) / 8;
442 new_element.data_len = bits;
443 for (
int n = 0; n < len_in_bytes; n++) {
444 new_element.data.push_back(tmp_data[n]);
447 new_element.time1 = space;
448 new_element.time2 = mark;
449 elements.push_back(new_element);