Infrared4Arduino
Pronto.cpp
Go to the documentation of this file.
1 //#ifdef ARDUINO_ARCH_AVR
2 
3 #include "Pronto.h"
4 #include "IrSignal.h"
5 #include <string.h>
6 
7 IrSignal *Pronto::parse(const uint16_t *data, size_t size) {
8  double timebase = prontoFreqConst * data[1];
9  frequency_t frequency;
10  switch (data[0]) {
11  case learnedToken: // normal, "learned"
12  frequency = toFrequency(data[1]);
13  break;
14  case learnedNonModulatedToken: // non-demodulated, "learned"
15  frequency = (frequency_t) 0;
16  break;
17  default:
18  return NULL;
19  }
20  size_t introPairs = data[2];
21  size_t repetitionPairs = data[3];
22  if (numbersInPreamble + 2*(introPairs + repetitionPairs) != size) // inconsistent sizes
23  return NULL;
24 
25  IrSequence *intro = mkSequence(data + numbersInPreamble, introPairs, timebase);
26  IrSequence *repeat = mkSequence(data + numbersInPreamble + 2*introPairs, repetitionPairs, timebase);
27  IrSequence *ending = new IrSequence();
28 
29  IrSignal *code = new IrSignal(*intro, *repeat, *ending, frequency, true);
30 
31  delete intro;
32  delete repeat;
33  delete ending;
34 
35  return code;
36 }
37 
38 IrSignal *Pronto::parse(const char *str) {
39  size_t len = strlen(str)/(digitsInProntoNumber + 1) + 1;
40  uint16_t data[len];
41  unsigned int index = 0;
42  const char *p = str;
43  char *endptr[1] = { NULL };
44  while (*p) {
45  long x = strtol(p, endptr, 16);
46  data[index++] = (uint16_t) x; // If input is conforming, there can be no overflow!
47  p = *endptr;
48  }
49  return parse(data, index);
50 }
51 
52 #if defined(ARDUINO) & defined(ARDUINO_ARCH_AVR)
53 
54 IrSignal *Pronto::parse(const __FlashStringHelper *str) {
55  size_t length = strlen_PF((uint_farptr_t)str);
56  char copy[length + 1]; // can be made more memory efficient.
57  strcpy_PF(copy, (uint_farptr_t)str);
58  return parse(copy);
59 }
60 #endif
61 
62 IrSequence *Pronto::mkSequence(const uint16_t* data, size_t noPairs, double timebase) {
63  microseconds_t *durations = new microseconds_t[2*noPairs];
64  for (unsigned int i = 0; i < 2*noPairs; i++) {
65  uint32_t duration = (uint32_t) (data[i] * timebase);
66  durations[i] = (microseconds_t)((duration <= MICROSECONDS_T_MAX) ? duration : MICROSECONDS_T_MAX);
67  }
68  return new IrSequence(durations, 2*noPairs, false);
69 }
70 
71 frequency_t Pronto::toFrequency(prontoInt code) {
72  return (frequency_t) (prontoConst / code);
73 }
74 
75 Pronto::prontoInt Pronto::toFrequencyCode(frequency_t frequency) {
76  return (prontoInt) (prontoConst / frequency);
77 }
78 
79 size_t Pronto::lengthHexString(size_t introLength, size_t repeatLength) {
80  return (digitsInProntoNumber + 1) * (numbersInPreamble + introLength + repeatLength);
81 }
82 
83 char Pronto::hexDigit(unsigned int x) {
84  return (char) (x <= 9 ? ('0' + x) : ('A' + (x - 10)));
85 }
86 
87 unsigned int Pronto::appendChar(char *result, unsigned int index, char ch) {
88  result[index] = ch;
89  index++;
90  return index;
91 }
92 
93 unsigned int Pronto::appendDigit(char *result, unsigned int index, unsigned int number) {
94  return appendChar(result, index, hexDigit(number)); //(number >> shifts) & 0xF);
95 }
96 
97 unsigned int Pronto::appendNumber(char *result, unsigned int index, prontoInt number) {
98  for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
99  unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
100  index = appendDigit(result, index, (number >> shifts) & hexMask);
101  }
102  return appendChar(result, index, ' ');
103 }
104 
105 unsigned int Pronto::appendDuration(char *result, unsigned int index, microseconds_t duration, frequency_t frequency) {
106  return appendNumber(result, index, (unsigned int)(1E-6 * duration * frequency + 0.5));
107 }
108 
109 unsigned int Pronto::appendSequence(char *result, unsigned int index, const microseconds_t *data, size_t length, frequency_t frequency) {
110  frequency_t effectiveFrequency = frequency > 0 ? frequency : fallbackFrequency;
111  for (unsigned int i = 0; i < length; i++)
112  index = appendDuration(result, index, data[i], effectiveFrequency);
113  return index;
114 }
115 
116 unsigned int Pronto::appendSequence(char *result, unsigned int index, const IrSequence& irSequence, frequency_t frequency) {
117  return appendSequence(result, index, irSequence.getDurations(), irSequence.getLength(), frequency);
118 }
119 
120 char* Pronto::setup(frequency_t frequency, size_t introLength, size_t repeatLength) {
121  char *result = new char[lengthHexString(introLength, repeatLength)];
122  unsigned int index = 0;
123  index = appendNumber(result, index, frequency > 0 ? learnedToken : learnedNonModulatedToken);
124  index = appendNumber(result, index, toFrequencyCode(frequency));
125  index = appendNumber(result, index, introLength / 2);
126  index = appendNumber(result, index, repeatLength / 2);
127  return result;
128 }
129 
130 char* Pronto::toProntoHex(const microseconds_t* data, size_t length, frequency_t frequency) {
131  char *result = setup(frequency, length, 0);
132  unsigned int index = charsInPreamble;
133  index = appendSequence(result, index, data, length, frequency);
134  appendChar(result, index - 1, '\0');
135  return result;
136 }
137 
138 char* Pronto::toProntoHex(const IrSequence& irSequence, frequency_t frequency) {
139  return toProntoHex(irSequence.getDurations(), irSequence.getLength(), frequency);
140 }
141 
142 char* Pronto::toProntoHex(const IrSignal& irSignal) {
143  char *result = setup(irSignal.getFrequency(), irSignal.getIntro().getLength(), irSignal.getRepeat().getLength());
144  unsigned int index = charsInPreamble;
145  index = appendSequence(result, index, irSignal.getIntro(), irSignal.getFrequency());
146  index = appendSequence(result, index, irSignal.getRepeat(), irSignal.getFrequency());
147  appendChar(result, index - 1, '\0');
148  return result;
149 }
uint16_t microseconds_t
Type for durations in micro seconds.
Definition: InfraredTypes.h:15
uint32_t frequency_t
Type for modulation frequency in Hz.
Definition: InfraredTypes.h:32
#define MICROSECONDS_T_MAX
Largest microseconds_t number possible.
Definition: InfraredTypes.h:18
const microseconds_t * getDurations() const
Definition: IrSequence.h:56
frequency_t getFrequency() const
Definition: IrSignal.h:51
const IrSequence & getIntro() const
Definition: IrSignal.h:63
This class models an IR signal with intro-, repeat-, and ending sequences.
Definition: IrSignal.h:10
size_t getLength() const
Returns the length of the data.
Definition: IrSequence.h:48
static IrSignal * parse(const uint16_t *data, size_t size)
Function for parsing its input data into an IrSignal.
Definition: Pronto.cpp:7
const IrSequence & getRepeat() const
Definition: IrSignal.h:59
This class consists of a vector of durations.
Definition: IrSequence.h:11
static char * toProntoHex(const IrSignal &irSignal)
Function for generating a Pronto Hex string from the argument.
Definition: Pronto.cpp:142