Infrared4Arduino 1.2.3
Loading...
Searching...
No Matches
Pronto.cpp
Go to the documentation of this file.
1#include "Pronto.h"
2#include "IrSignal.h"
3#include "Board.h" // for HAS_FLASH_READ
4#include <string.h>
5
6inline uint16_t divRound(microseconds_t duration, microseconds_t timebase) {
7 return static_cast<uint16_t>((static_cast<uint32_t>(duration) + timebase / 2) / timebase);
8}
9
10IrSignal *Pronto::parse(const uint16_t *data, size_t size) {
11 microseconds_t timebase = (microsecondsInSeconds * data[1] + referenceFrequency/2) / referenceFrequency;
12 frequency_t frequency;
13 switch (data[0]) {
14 case learnedToken: // normal, "learned"
15 frequency = toFrequency(data[1]);
16 break;
17 case learnedNonModulatedToken: // non-demodulated, "learned"
18 frequency = 0U;
19 break;
20 default:
21 return nullptr;
22 }
23 size_t introPairs = data[2];
24 size_t repetitionPairs = data[3];
25 if (numbersInPreamble + 2*(introPairs + repetitionPairs) != size) // inconsistent sizes
26 return nullptr;
27
28 microseconds_t* intro = mkSequence(data + numbersInPreamble, introPairs, timebase);
29 microseconds_t* repeat = mkSequence(data + numbersInPreamble + 2*introPairs, repetitionPairs, timebase);
30
31 return new IrSignal(intro, 2*introPairs, repeat, 2*repetitionPairs, frequency);
32}
33
34IrSignal *Pronto::parse(const char *str) {
35 size_t len = strlen(str)/(digitsInProntoNumber + 1) + 1;
36 uint16_t* data = new uint16_t[len];
37 const char *p = str;
38 char *endptr[1];
39 for (unsigned int i = 0; i < len; i++) {
40 long x = strtol(p, endptr, 16);
41 if (x == 0 && i >= numbersInPreamble) {
42 // Alignment error?, bail immediately (often right result).
43 len = i;
44 break;
45 }
46 data[i] = x; // If input is conforming, there can be no overflow!
47 p = *endptr;
48 }
49 IrSignal *res = parse(data, len);
50 delete [] data;
51 return res;
52}
53
54#if HAS_FLASH_READ || defined(DOXYGEN)
56 size_t len = strlen_PF(STRCPY_PF_CAST(str));
57 char work[len + 1];
58 strncpy_PF(work, STRCPY_PF_CAST(str), len);
59 return parse(work);
60}
61
62IrSignal *Pronto::parse_PF(const char *str) {
63 return parse_PF(reinterpret_cast<uint_farptr_t>(str)); // to avoid infinite recursion
64};
65
66IrSignal *Pronto::parse(const __FlashStringHelper *str) {
67 return parse_PF(reinterpret_cast<uint_farptr_t>(str));
68}
69#endif
70
71microseconds_t* Pronto::mkSequence(const uint16_t* data, size_t noPairs, microseconds_t timebase) {
72 microseconds_t *durations = new microseconds_t[2*noPairs];
73 for (unsigned int i = 0; i < 2*noPairs; i++) {
74 uint32_t duration = static_cast<uint32_t>(data[i]) * timebase;
75 durations[i] = (duration <= MICROSECONDS_T_MAX) ? duration : MICROSECONDS_T_MAX;
76 }
77 return durations;
78}
79
80frequency_t Pronto::toFrequency(uint16_t code) {
81 return referenceFrequency / code;
82}
83
84uint16_t Pronto::toFrequencyCode(frequency_t frequency) {
85 return referenceFrequency / effectiveFrequency(frequency);
86}
87
88frequency_t Pronto::effectiveFrequency(frequency_t frequency) {
89 return frequency > 0 ? frequency : fallbackFrequency;
90}
91
92microseconds_t Pronto::toTimebase(frequency_t frequency) {
93 return microsecondsInSeconds / effectiveFrequency(frequency);
94}
95
96size_t Pronto::lengthHexString(size_t introLength, size_t repeatLength) {
97 return (digitsInProntoNumber + 1) * (numbersInPreamble + introLength + repeatLength);
98}
99
100char Pronto::hexDigit(unsigned int x) {
101 return x <= 9 ? ('0' + x) : ('A' + (x - 10));
102}
103
104void Pronto::appendChar(char *result, unsigned int& index, char ch) {
105 result[index] = ch;
106 index++;
107}
108
109void Pronto::appendDigit(char *result, unsigned int& index, unsigned int number) {
110 appendChar(result, index, hexDigit(number));
111}
112
113void Pronto::appendNumber(char *result, unsigned int& index, uint16_t number) {
114 for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
115 unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
116 appendDigit(result, index, (number >> shifts) & hexMask);
117 }
118 appendChar(result, index, ' ');
119}
120
121void Pronto::appendDuration(char *result, unsigned int& index, microseconds_t duration, microseconds_t timebase) {
122 appendNumber(result, index, divRound(duration, timebase));
123}
124
125void Pronto::appendSequence(char *result, unsigned int& index, const microseconds_t *data, size_t length, microseconds_t timebase) {
126 for (unsigned int i = 0; i < length; i++)
127 appendDuration(result, index, data[i], timebase);
128}
129
130void Pronto::appendSequence(char *result, unsigned int& index, const IrSequence& irSequence, microseconds_t timebase) {
131 appendSequence(result, index, irSequence.getDurations(), irSequence.getLength(), timebase);
132}
133
134char* Pronto::prelude(frequency_t frequency, size_t introLength, size_t repeatLength) {
135 char *result = new char[lengthHexString(introLength, repeatLength)];
136 unsigned int index = 0;
137 appendNumber(result, index, frequency > 0 ? learnedToken : learnedNonModulatedToken);
138 appendNumber(result, index, toFrequencyCode(frequency));
139 appendNumber(result, index, introLength / 2);
140 appendNumber(result, index, repeatLength / 2);
141 return result;
142}
143
144char* Pronto::toProntoHex(const microseconds_t* introData, size_t introLength, const microseconds_t* repeatData, size_t repeatLength, frequency_t frequency) {
145 char *result = prelude(frequency, introLength, repeatLength);
146 unsigned int index = numbersInPreamble * (digitsInProntoNumber + 1);
147 microseconds_t timebase = toTimebase(frequency);
148 appendSequence(result, index, introData, introLength, timebase);
149 appendSequence(result, index, repeatData, repeatLength, timebase);
150 result[index - 1] = '\0';
151 return result;
152}
153
154void Pronto::dump(Stream& stream, const microseconds_t* introData, size_t introLength, const microseconds_t* repeatData, size_t repeatLength, frequency_t frequency) {
155 dumpNumber(stream, frequency > 0 ? learnedToken : learnedNonModulatedToken);
156 stream.print(' ');
157 dumpNumber(stream, toFrequencyCode(frequency));
158 stream.print(' ');
159 dumpNumber(stream, introLength / 2);
160 stream.print(' ');
161 dumpNumber(stream, repeatLength / 2);
162 stream.print(' ');
163 microseconds_t timebase = toTimebase(frequency);
164 dumpSequence(stream, introData, introLength, timebase);
165 stream.print(' ');
166 dumpSequence(stream, repeatData, repeatLength, timebase);
167}
168
169void Pronto::dumpSequence(Stream& stream, const microseconds_t *data, size_t length, microseconds_t timebase) {
170 for (unsigned int i = 0; i < length; i++) {
171 dumpDuration(stream, data[i], timebase);
172 if (i < length - 1)
173 stream.print(' ');
174 }
175}
176
177void Pronto::dumpDuration(Stream& stream, microseconds_t duration, microseconds_t timebase) {
178 dumpNumber(stream, divRound(duration, timebase));
179}
180
181void Pronto::dumpNumber(Stream& stream, uint16_t number) {
182 for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
183 unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
184 dumpDigit(stream, (number >> shifts) & hexMask);
185 }
186}
187
188void Pronto::dumpDigit(Stream& stream, unsigned int number) {
189 stream.print(hexDigit(number));
190}
#define STRCPY_PF_CAST(x)
Definition: ATmega4809.h:39
void * uint_farptr_t
Definition: Board.h:288
static constexpr microseconds_t MICROSECONDS_T_MAX
Largest microseconds_t number possible.
Definition: InfraredTypes.h:18
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:31
uint16_t divRound(microseconds_t duration, microseconds_t timebase)
Definition: Pronto.cpp:6
This class consists of a vector of durations.
Definition: IrSequence.h:11
const microseconds_t * getDurations() const
Definition: IrSequence.h:73
size_t getLength() const
Returns the number of durations.
Definition: IrSequence.h:65
This class models an IR signal with intro-, repeat-, and ending sequences.
Definition: IrSignal.h:11
static constexpr unsigned int numbersInPreamble
Definition: Pronto.h:23
static char * toProntoHex(const IrSignal &irSignal)
Function for generating a Pronto Hex string from the argument.
Definition: Pronto.h:114
static IrSignal * parse(const uint16_t *data, size_t size)
Function for parsing its input data into an IrSignal.
Definition: Pronto.cpp:10
static void dump(Stream &stream, const IrSignal &irSignal)
Function for printing data as Pronto Hex string on the stream given as argument.
Definition: Pronto.h:159
static constexpr unsigned int digitsInProntoNumber
Definition: Pronto.h:22
static IrSignal * parse_PF(const uint_farptr_t str)
Function for parsing its input data into an IrSignal.
Definition: Pronto.cpp:55