IRremote
MicroGirs.ino
Go to the documentation of this file.
1 
71 // Change the following two entries if desired
72 
76 #define INPUTPIN 5
77 
82 #define BAUDRATE 115200
83 
84 #include <IRremote.h>
85 #include <limits.h>
86 
90 #define RECEIVE
91 
95 #define TRANSMIT
96 
97 // (The sending pin is in general not configurable, see the documentation of IRremote.)
98 
103 #define EOLCHAR '\r'
104 
106 
110 #ifdef TRANSMIT
111 #ifdef RECEIVE
112 #define modulesSupported "base transmit receive"
113 #else // ! RECEIVE
114 #define modulesSupported "base transmit"
115 #endif
116 #else // !TRANSMIT
117 #ifdef RECEIVE
118 #define modulesSupported "base receive"
119 #else // ! RECETVE
120 #error At lease one of TRANSMIT and RECEIVE must be defined
121 #endif
122 #endif
123 
127 #define PROGNAME "MicroGirs"
128 
132 #define VERSION "2020-07-05"
133 
134 #define okString "OK"
135 #define errorString "ERROR"
136 #define timeoutString "."
137 
138 // For compatibility with IRremote, we deliberately use
139 // the platform dependent types.
140 // (Although it is a questionable idea ;-) )
144 typedef unsigned frequency_t; // max 65535, unless 32-bit
145 
149 typedef unsigned microseconds_t; // max 65535, unless 32-bit
150 
151 static const microseconds_t DUMMYENDING = 40000U;
152 static const frequency_t FREQUENCY_T_MAX = UINT16_MAX;
153 static const frequency_t MICROSECONDS_T_MAX = UINT16_MAX;
154 
155 #ifdef RECEIVE
156 
160 #endif
161 
162 #ifdef TRANSMIT
163 /*}
164  * Instance of the IRremote class.
165  */
167 #endif
168 
173 class Tokenizer {
174 private:
175  static const int invalidIndex = -1;
176 
177  int index; // signed since invalidIndex is possible
178  const String& payload;
179  void trim();
180 
181 public:
182  Tokenizer(const String &str);
183  virtual ~Tokenizer();
184 
185  String getToken();
186  String getRest();
187  String getLine();
188  long getInt();
191 
192  static const int invalid = INT_MAX;
193 };
194 
195 Tokenizer::Tokenizer(const String& str) : index(0), payload(str) {
196 }
197 
199 }
200 
202  String result = index == invalidIndex ? String("") : payload.substring(index);
203  index = invalidIndex;
204  return result;
205 }
206 
208  if (index == invalidIndex)
209  return String("");
210 
211  int i = payload.indexOf('\n', index);
212  String s = (i > 0) ? payload.substring(index, i) : payload.substring(index);
213  index = (i > 0) ? i+1 : invalidIndex;
214  return s;
215 }
216 
218  if (index < 0)
219  return String("");
220 
221  int i = payload.indexOf(' ', index);
222  String s = (i > 0) ? payload.substring(index, i) : payload.substring(index);
223  index = (i > 0) ? i : invalidIndex;
224  if (index != invalidIndex)
225  if (index != invalidIndex)
226  while (payload.charAt(index) == ' ')
227  index++;
228  return s;
229 }
230 
232  String token = getToken();
233  return token == "" ? (long) invalid : token.toInt();
234 }
235 
237  long t = getToken().toInt();
239 }
240 
242  long t = getToken().toInt();
243  return (frequency_t) ((t < FREQUENCY_T_MAX) ? t : FREQUENCY_T_MAX);
244 }
246 
247 #ifdef TRANSMIT
248 static inline unsigned hz2khz(frequency_t hz) {
249  return (hz + 500)/1000;
250 }
251 
269 static void sendRaw(const microseconds_t intro[], unsigned lengthIntro,
270  const microseconds_t repeat[], unsigned lengthRepeat,
271  const microseconds_t ending[], unsigned lengthEnding,
272  frequency_t frequency, unsigned times) {
273  if (lengthIntro > 0U)
274  irSend.sendRaw(intro, lengthIntro, hz2khz(frequency));
275  if (lengthRepeat > 0U)
276  for (unsigned i = 0U; i < times - (lengthIntro > 0U); i++)
277  irSend.sendRaw(repeat, lengthRepeat, hz2khz(frequency));
278  if (lengthEnding > 0U)
279  irSend.sendRaw(ending, lengthEnding, hz2khz(frequency));
280 }
281 #endif // TRANSMIT
282 
283 #ifdef RECEIVE
284 
288 static void receive(Stream& stream) {
289  irRecv.enableIRIn();
290  irRecv.resume(); // Receive the next value
291  decode_results results;
292 
293  while (!irRecv.decode(&results)) {
294  }
296 
297  dump(stream, &results);
298 }
299 
300 static void dump(Stream& stream, decode_results* results) {
301  unsigned int count = results->rawlen;
302  // If buffer gets full, count = RAW_BUFFER_LENGTH, which is odd,
303  // and IrScrutinizer does not like that.
304  count &= ~1;
305  for (unsigned int i = 1; i < count; i++) {
306  stream.write(i & 1 ? '+' : '-');
307  stream.print(results->rawbuf[i] * USECPERTICK, DEC);
308  stream.print(" ");
309  }
310  stream.print('-');
311  stream.println(DUMMYENDING);
312 }
313 #endif // RECEIVE
314 
318 void setup() {
319  Serial.begin(BAUDRATE);
320  while (!Serial)
321  ; // wait for serial port to connect.
322 
323  Serial.println(F(PROGNAME " " VERSION));
324  //Serial.setTimeout(SERIALTIMEOUT);
325 /*
326 #ifdef RECEIVE
327  // There is unfortunately no disableIRIn in IRremote.
328  // Therefore, turn it on, and leave it on.
329  // We _hope_ that it will not interfere with sending.
330  irRecv.enableIRIn();
331 #endif
332 */
333 }
334 
335 
336 static String readCommand(Stream& stream) {
337  while (stream.available() == 0) {
338  }
339 
340  String line = stream.readStringUntil(EOLCHAR);
341  line.trim();
342  return line;
343 }
344 
345 static void processCommand(const String& line, Stream& stream) {
346  Tokenizer tokenizer(line);
347  String cmd = tokenizer.getToken();
348 
349  // Decode the command in cmd
350  if (cmd.length() == 0) {
351  // empty command, do nothing
352  stream.println(F(okString));
353  return;
354  }
355 
356  switch (cmd[0]) {
357  case 'm':
358  stream.println(F(modulesSupported));
359  break;
360 
361 #ifdef RECEIVE
362  case 'r': // receive
363  //case 'a':
364  //case 'c':
365  receive(stream);
366  break;
367 #endif // RECEIVE
368 
369 #ifdef TRANSMIT
370  case 's': // send
371  {
372  // TODO: handle unparsable data gracefully
373  unsigned noSends = (unsigned) tokenizer.getInt();
374  frequency_t frequency = tokenizer.getFrequency();
375  unsigned introLength = (unsigned) tokenizer.getInt();
376  unsigned repeatLength = (unsigned) tokenizer.getInt();
377  unsigned endingLength = (unsigned) tokenizer.getInt();
378  microseconds_t intro[introLength];
379  microseconds_t repeat[repeatLength];
380  microseconds_t ending[endingLength];
381  for (unsigned i = 0; i < introLength; i++)
382  intro[i] = tokenizer.getMicroseconds();
383  for (unsigned i = 0; i < repeatLength; i++)
384  repeat[i] = tokenizer.getMicroseconds();
385  for (unsigned i = 0; i < endingLength; i++)
386  ending[i] = tokenizer.getMicroseconds();
387  sendRaw(intro, introLength, repeat, repeatLength, ending, endingLength, frequency, noSends);
388  stream.println(F(okString));
389  }
390  break;
391 #endif // TRANSMIT
392 
393  case 'v': // version
394  stream.println(F(PROGNAME " " VERSION));
395  break;
396  default:
397  stream.println(F(errorString));
398  }
399 }
400 
404 void loop() {
405  String line = readCommand(Serial);
406  processCommand(line, Serial);
407 }
loop
void loop()
Reads a command from the serial line and executes it-.
Definition: MicroGirs.ino:404
Tokenizer::getInt
long getInt()
Definition: MicroGirs.ino:231
Tokenizer::getLine
String getLine()
Definition: MicroGirs.ino:207
IRrecv::resume
void resume()
Called to re-enable IR reception.
Definition: irRecv.cpp:215
IRrecv::disableIRIn
void disableIRIn()
Disable IR reception.
Definition: irRecv.cpp:185
IRrecv::enableIRIn
void enableIRIn()
Enable IR reception.
Definition: irRecv.cpp:160
FREQUENCY_T_MAX
static const frequency_t FREQUENCY_T_MAX
Definition: MicroGirs.ino:152
IRrecv
Main class for receiving IR.
Definition: IRremote.h:193
decode_results
Results returned from the decoder.
Definition: IRremote.h:174
frequency_t
unsigned frequency_t
Type used for modulation frequency in Hz (not kHz).
Definition: MicroGirs.ino:144
Tokenizer
Our own tokenizer class.
Definition: MicroGirs.ino:173
decode_results::rawbuf
volatile unsigned int * rawbuf
Raw intervals in 50uS ticks.
Definition: IRremote.h:180
Tokenizer::~Tokenizer
virtual ~Tokenizer()
Definition: MicroGirs.ino:198
Tokenizer::Tokenizer
Tokenizer(const String &str)
Definition: MicroGirs.ino:195
IRsend
Main class for sending IR.
Definition: IRremote.h:333
microseconds_t
unsigned microseconds_t
Type used for durations in micro seconds.
Definition: MicroGirs.ino:149
hz2khz
static unsigned hz2khz(frequency_t hz)
Definition: MicroGirs.ino:248
EOLCHAR
#define EOLCHAR
Character that ends the command lines.
Definition: MicroGirs.ino:103
readCommand
static String readCommand(Stream &stream)
Definition: MicroGirs.ino:336
PROGNAME
#define PROGNAME
Name of program, as reported by the "version" command.
Definition: MicroGirs.ino:127
irRecv
IRrecv irRecv(INPUTPIN)
Instance of the IRremote class.
BAUDRATE
#define BAUDRATE
Baud rate for the serial/USB connection.
Definition: MicroGirs.ino:82
errorString
#define errorString
Definition: MicroGirs.ino:135
sendRaw
static void sendRaw(const microseconds_t intro[], unsigned lengthIntro, const microseconds_t repeat[], unsigned lengthRepeat, const microseconds_t ending[], unsigned lengthEnding, frequency_t frequency, unsigned times)
Transmits the IR signal given as argument.
Definition: MicroGirs.ino:269
INPUTPIN
#define INPUTPIN
Input Pin used by the receiver, can be arbitrary (almost...)
Definition: MicroGirs.ino:76
USECPERTICK
#define USECPERTICK
Definition: IRremoteBoardDefs.h:166
IRrecv::decode
int decode(decode_results *results)
Attempt to decode the recently receive IR signal.
Definition: irRecv.cpp:8
Tokenizer::invalid
static const int invalid
Definition: MicroGirs.ino:192
irSend
IRsend irSend
Definition: MicroGirs.ino:166
dump
static void dump(Stream &stream, decode_results *results)
Definition: MicroGirs.ino:300
okString
#define okString
Definition: MicroGirs.ino:134
modulesSupported
#define modulesSupported
The modules supported, as given by the "modules" command.
Definition: MicroGirs.ino:112
IRremote.h
Public API to the library.
MICROSECONDS_T_MAX
static const frequency_t MICROSECONDS_T_MAX
Definition: MicroGirs.ino:153
Tokenizer::getMicroseconds
microseconds_t getMicroseconds()
Definition: MicroGirs.ino:236
DUMMYENDING
static const microseconds_t DUMMYENDING
Definition: MicroGirs.ino:151
processCommand
static void processCommand(const String &line, Stream &stream)
Definition: MicroGirs.ino:345
Tokenizer::getFrequency
frequency_t getFrequency()
Definition: MicroGirs.ino:241
receive
static void receive(Stream &stream)
Reads a command from the stream given as argument.
Definition: MicroGirs.ino:288
Tokenizer::getRest
String getRest()
Definition: MicroGirs.ino:201
Tokenizer::getToken
String getToken()
Definition: MicroGirs.ino:217
VERSION
#define VERSION
Version of program, as reported by the "version" command.
Definition: MicroGirs.ino:132
setup
void setup()
Initialization.
Definition: MicroGirs.ino:318
decode_results::rawlen
unsigned int rawlen
Number of records in rawbuf.
Definition: IRremote.h:181
IRsend::sendRaw
void sendRaw(const unsigned int buf[], unsigned int len, unsigned int hz)
Definition: irSend.cpp:5