OOKwiz
on/off-keying for ESP32 and a variety of supported radio modules
RawTimings.cpp
Go to the documentation of this file.
1 #include "RawTimings.h"
2 #include "Pulsetrain.h"
3 #include "serial_output.h"
4 #include "Settings.h"
5 
6 
7 /// @brief Static method to see if String might be a representation of RawTimings. No guarantees until you try to convert it, but silent.
8 /// @param str String that we are curious about
9 /// @return `true` if it might be a RawTimings String, `false` if not.
10 /**
11  * Static, so not called on any particular RawTimings instance but instead like:
12  * ```cpp
13  * if (RawTimings::maybe(someString)) {
14  * ....
15  * }
16  * ```
17 */
18 
19 bool RawTimings::maybe(String str) {
20  int comma = 0;
21  for (int n = 0; n < str.length(); n++) {
22  if (!isDigit(str.charAt(n)) && str.charAt(n) != ',') {
23  return false;
24  }
25  if (str.charAt(n) == ',') {
26  comma++;
27  }
28  }
29  if (comma > 15) {
30  DEBUG("RawTimings::maybe() returns true.\n");
31  return true;
32  }
33  return false;
34 }
35 
36 /// @brief If you try to evaluate the instance as a bool, for instance in `if (myRawTimings) ...`, it will be `true` if there's intervals stored.
37 IRAM_ATTR RawTimings::operator bool() {
38  return (intervals.size() > 0);
39 }
40 
41 /// @brief empty out the stored intervals
42 void IRAM_ATTR RawTimings::zap() {
43  intervals.clear();
44 }
45 
46 /// @brief Get the String representation, which is a comma-separated list of intervals
47 /// @return the String representation
48 String RawTimings::toString() {
49  String res = "";
50  for (int count = 0; count < intervals.size(); count++) {
51  res += intervals[count];
52  if (count != intervals.size() - 1) {
53  res += ",";
54  }
55  }
56  return res;
57 }
58 
59 /// @brief Read a String representation, which is a comma-separated list of intervals, and store in this instance
60 /// @return `true` if it worked, `false` (with error message) if it didn't.
61 bool RawTimings::fromString(const String &in) {
62  bool error = false;
63  intervals.clear();
64  int pos = 0;
65  int nextSemicolon = in.indexOf(",", pos);
66  do {
67  int value = in.substring(pos, nextSemicolon).toInt();
68  if (value == 0) {
69  error = true;
70  break;
71  }
72  intervals.push_back(value);
73  pos = nextSemicolon + 1;
74  nextSemicolon = in.indexOf(",", pos);
75  } while (nextSemicolon != -1);
76  int value = in.substring(pos).toInt();
77  if (value == 0 || error) {
78  ERROR("Conversion to RawTimings failed at position %i in String '%s'\n", pos, in.c_str());
79  return false;
80  }
81  intervals.push_back(value);
82  return true;
83 }
84 
85 /// @brief Convert Pulsetrain into RawTimings. Loses stats about bins as well as information about repeats.
86 /// @param train the Pulsetrain you want to convert from
87 /// @return Always `true`
88 bool RawTimings::fromPulsetrain(Pulsetrain &train) {
89  for (int transition : train.transitions) {
90  intervals.push_back(train.bins[transition].average);
91  }
92  return true;
93 }
94 
95 /// @brief RawTimings to Pulsetrain
96 /// @return Pulsetrain instance
97 Pulsetrain RawTimings::toPulsetrain() {
98  Pulsetrain res;
99  res.fromRawTimings(*this);
100  return res;
101 }
102 
103 /// @brief Returns the viasualizer (the blocky time-graph) for the pulses in this RawTimings instance
104 /// @param base µs per (half-character) block. Every interval gets at least one block so all pulses are guaranteed visible
105 /// @return visualizer String
106 String RawTimings::visualizer(int base) {
107  if (base == 0) {
108  return "";
109  }
110  String ones_and_zeroes;
111  String curstate;
112  for (int n = 0; n < intervals.size(); n++) {
113  curstate = (n % 2 == 0) ? "1" : "0";
114  for (int m = 0; m < max((intervals[n] + (base / 2)) / base, 1); m++) {
115  ones_and_zeroes += curstate;
116  }
117  }
118  ones_and_zeroes += "0";
119  String output;
120  for (int n = 0; n < ones_and_zeroes.length(); n += 2) {
121  String chunk = ones_and_zeroes.substring(n, n + 2);
122  if (chunk == "11") {
123  output += "▀";
124  } else if (chunk == "00") {
125  output += " ";
126  } else if (chunk == "01") {
127  output += "▝";
128  } else if (chunk == "10") {
129  output += "▘";
130  }
131  }
132  return output;
133 }
134 
135 /// @brief The visualizer like above, with base taken from `visualizer_pixel` setting.
136 /// @return visualizer String
137 String RawTimings::visualizer() {
138  int visualizer_pixel;
139  SETTING_WITH_DEFAULT(visualizer_pixel, 200);
140  return visualizer(visualizer_pixel);
141 }