Sitelet https://github.com/angeldeejay/IRremoteESP8266/commit/8a1a0055f1c159c153206621c51ecbcce61ac0bc
Skip to content

Commit 8a1a005

Browse files
authored
Add RawToPronto.py tool & improve sendPronto() precision (crankyoldgit#1104)
Convert a `rawData` entry into simplistic Pronto code. Does not handle repeats etc. * Improve precision of `sendPronto()` by 10 times. - Produces more accurate lengths for large values. e.g. Multibracket protocol. - Due to the integer maths used, some precision was lost. The lose was quite noticeable on large values. Fixes crankyoldgit#1103
1 parent 4dae5c3 commit 8a1a005

5 files changed

Lines changed: 271 additions & 103 deletions

File tree

‎src/ir_Pronto.cpp‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void IRsend::sendPronto(uint16_t data[], uint16_t len, uint16_t repeat) {
6969
uint16_t seq_1_start = kProntoDataOffset;
7070
uint16_t seq_2_start = kProntoDataOffset + seq_1_len;
7171

72-
uint32_t periodic_time = calcUSecPeriod(hz, false);
72+
uint32_t periodic_time_x10 = calcUSecPeriod(hz / 10, false);
7373

7474
// Normal (1st sequence) case.
7575
// Is there a first (normal) sequence to send?
@@ -78,8 +78,8 @@ void IRsend::sendPronto(uint16_t data[], uint16_t len, uint16_t repeat) {
7878
if (seq_1_len + seq_1_start > len) return;
7979
// Send the contents of the 1st sequence.
8080
for (uint16_t i = seq_1_start; i < seq_1_start + seq_1_len; i += 2) {
81-
mark(data[i] * periodic_time);
82-
space(data[i + 1] * periodic_time);
81+
mark((data[i] * periodic_time_x10) / 10);
82+
space((data[i + 1] * periodic_time_x10) / 10);
8383
}
8484
} else {
8585
// There was no first sequence to send, it is implied that we have to send
@@ -96,8 +96,8 @@ void IRsend::sendPronto(uint16_t data[], uint16_t len, uint16_t repeat) {
9696
// Send the contents of the 2nd sequence.
9797
for (uint16_t r = 0; r < repeat; r++)
9898
for (uint16_t i = seq_2_start; i < seq_2_start + seq_2_len; i += 2) {
99-
mark(data[i] * periodic_time);
100-
space(data[i + 1] * periodic_time);
99+
mark((data[i] * periodic_time_x10) / 10);
100+
space((data[i + 1] * periodic_time_x10) / 10);
101101
}
102102
}
103103
}

‎test/ir_Pronto_test.cpp‎

Lines changed: 106 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ TEST(TestSendPronto, MoreDataThanNeededInNormal) {
5858
uint16_t pronto_test[8] = {0x0000, 0x0067, 0x0001, 0x0000,
5959
0x0001, 0x0002, 0x0003, 0x0004};
6060
irsend.sendPronto(pronto_test, 8);
61-
EXPECT_EQ("f40244d50m25s50",
61+
EXPECT_EQ("f40244d50m24s49",
6262
irsend.outputStr()); // Only send the data required.
6363
}
6464

@@ -71,7 +71,7 @@ TEST(TestSendPronto, MoreDataThanNeededInRepeat) {
7171
uint16_t pronto_test[8] = {0x0000, 0x0067, 0x0000, 0x0001,
7272
0x0001, 0x0002, 0x0003, 0x0004};
7373
irsend.sendPronto(pronto_test, 8);
74-
EXPECT_EQ("f40244d50m25s50",
74+
EXPECT_EQ("f40244d50m24s49",
7575
irsend.outputStr()); // Only send the data required.
7676
}
7777

@@ -84,10 +84,10 @@ TEST(TestSendPronto, MoreDataThanNeededInBoth) {
8484
uint16_t pronto_test[10] = {0x0000, 0x0067, 0x0001, 0x0001, 0x0001,
8585
0x0002, 0x0003, 0x0004, 0x5, 0x6};
8686
irsend.sendPronto(pronto_test, 10);
87-
EXPECT_EQ("f40244d50m25s50",
87+
EXPECT_EQ("f40244d50m24s49",
8888
irsend.outputStr()); // Only send the data required.
8989
irsend.sendPronto(pronto_test, 10, 1);
90-
EXPECT_EQ("f40244d50m25s50m75s100",
90+
EXPECT_EQ("f40244d50m24s49m74s99",
9191
irsend.outputStr()); // Only the data required.
9292
}
9393

@@ -139,18 +139,18 @@ TEST(TestSendPronto, NonRepeatingCode) {
139139
EXPECT_EQ(0x0, irsend.capture.command);
140140
EXPECT_EQ(
141141
"f40244d50"
142-
"m2400s600"
143-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
144-
"m600s600m600s600m600s600m600s27650"
145-
"m2400s600"
146-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
147-
"m600s600m600s600m600s600m600s27650"
148-
"m2400s600"
149-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
150-
"m600s600m600s600m600s600m600s27650"
151-
"m2400s600"
152-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
153-
"m600s600m600s600m600s600m600s600",
142+
"m2390s597"
143+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
144+
"m597s597m597s597m597s597m597s27539"
145+
"m2390s597"
146+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
147+
"m597s597m597s597m597s597m597s27539"
148+
"m2390s597"
149+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
150+
"m597s597m597s597m597s597m597s27539"
151+
"m2390s597"
152+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
153+
"m597s597m597s597m597s597m597s597",
154154
irsend.outputStr());
155155

156156
// Now try repeating it.
@@ -166,18 +166,18 @@ TEST(TestSendPronto, NonRepeatingCode) {
166166
EXPECT_EQ(0x0, irsend.capture.command);
167167
EXPECT_EQ(
168168
"f40244d50"
169-
"m2400s600"
170-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
171-
"m600s600m600s600m600s600m600s27650"
172-
"m2400s600"
173-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
174-
"m600s600m600s600m600s600m600s27650"
175-
"m2400s600"
176-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
177-
"m600s600m600s600m600s600m600s27650"
178-
"m2400s600"
179-
"m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600"
180-
"m600s600m600s600m600s600m600s600",
169+
"m2390s597"
170+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
171+
"m597s597m597s597m597s597m597s27539"
172+
"m2390s597"
173+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
174+
"m597s597m597s597m597s597m597s27539"
175+
"m2390s597"
176+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
177+
"m597s597m597s597m597s597m597s27539"
178+
"m2390s597"
179+
"m597s597m597s597m597s597m597s597m597s597m597s597m597s597m1195s597"
180+
"m597s597m597s597m597s597m597s597",
181181
irsend.outputStr());
182182
}
183183

@@ -208,10 +208,10 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) {
208208
EXPECT_EQ(0x24AE, irsend.capture.command);
209209
EXPECT_EQ(
210210
"f40244d50"
211-
"m2400s600"
212-
"m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600"
213-
"m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600"
214-
"m600s600m600s600m1200s600m600s25350",
211+
"m2390s597"
212+
"m597s597m1195s597m1195s597m1195s597m597s597m1195s597m597s597m597s597"
213+
"m1195s597m597s597m1195s597m1195s597m1195s597m597s597m597s597m1195s597"
214+
"m597s597m597s597m1195s597m597s25248",
215215
irsend.outputStr());
216216

217217
// Send the Pronto code with 2 repeats.
@@ -226,18 +226,18 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) {
226226
EXPECT_EQ(0x24AE, irsend.capture.command);
227227
EXPECT_EQ(
228228
"f40244d50"
229-
"m2400s600"
230-
"m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600"
231-
"m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600"
232-
"m600s600m600s600m1200s600m600s25350"
233-
"m2400s600"
234-
"m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600"
235-
"m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600"
236-
"m600s600m600s600m1200s600m600s25350"
237-
"m2400s600"
238-
"m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600"
239-
"m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600"
240-
"m600s600m600s600m1200s600m600s25350",
229+
"m2390s597"
230+
"m597s597m1195s597m1195s597m1195s597m597s597m1195s597m597s597m597s597"
231+
"m1195s597m597s597m1195s597m1195s597m1195s597m597s597m597s597m1195s597"
232+
"m597s597m597s597m1195s597m597s25248"
233+
"m2390s597"
234+
"m597s597m1195s597m1195s597m1195s597m597s597m1195s597m597s597m597s597"
235+
"m1195s597m597s597m1195s597m1195s597m1195s597m597s597m597s597m1195s597"
236+
"m597s597m597s597m1195s597m597s25248"
237+
"m2390s597"
238+
"m597s597m1195s597m1195s597m1195s597m597s597m1195s597m597s597m597s597"
239+
"m1195s597m597s597m1195s597m1195s597m1195s597m597s597m597s597m1195s597"
240+
"m597s597m597s597m1195s597m597s25248",
241241
irsend.outputStr());
242242
}
243243

@@ -274,14 +274,14 @@ TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) {
274274
EXPECT_EQ(0x1007C7D, irsend.capture.command);
275275
EXPECT_EQ(
276276
"f36682d50"
277-
"m3456s1701"
278-
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
279-
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
280-
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
281-
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
282-
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
283-
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s1296"
284-
"m432s73224",
277+
"m3494s1719"
278+
"m436s436m436s1310m436s436m436s436m436s436m436s436m436s436m436s436"
279+
"m436s436m436s436m436s436m436s436m436s436m436s1310m436s436m436s436"
280+
"m436s436m436s436m436s436m436s436m436s436m436s436m436s436m436s1310"
281+
"m436s436m436s436m436s436m436s436m436s436m436s436m436s436m436s436"
282+
"m436s436m436s1310m436s1310m436s1310m436s1310m436s1310m436s436m436s436"
283+
"m436s436m436s1310m436s1310m436s1310m436s1310m436s1310m436s436m436s1310"
284+
"m436s74037",
285285
irsend.outputStr());
286286
}
287287

@@ -315,12 +315,12 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) {
315315
EXPECT_EQ(0x8, irsend.capture.command);
316316
EXPECT_EQ(
317317
"f38028d50"
318-
"m8892s4446"
319-
"m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546"
320-
"m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664"
321-
"m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546"
322-
"m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664"
323-
"m546s39858",
318+
"m8994s4497"
319+
"m552s552m552s552m552s552m552s1683m552s1683m552s552m552s552m552s552"
320+
"m552s1683m552s1683m552s1683m552s552m552s552m552s1683m552s1683m552s1683"
321+
"m552s552m552s552m552s552m552s1683m552s552m552s552m552s552m552s552"
322+
"m552s1683m552s1683m552s1683m552s552m552s1683m552s1683m552s1683m552s1683"
323+
"m552s40317",
324324
irsend.outputStr());
325325

326326
// Send it again with a single repeat.
@@ -335,13 +335,13 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) {
335335
EXPECT_EQ(0x8, irsend.capture.command);
336336
EXPECT_EQ(
337337
"f38028d50"
338-
"m8892s4446"
339-
"m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546"
340-
"m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664"
341-
"m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546"
342-
"m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664"
343-
"m546s39858"
344-
"m8892s2210m546s95212",
338+
"m8994s4497"
339+
"m552s552m552s552m552s552m552s1683m552s1683m552s552m552s552m552s552"
340+
"m552s1683m552s1683m552s1683m552s552m552s552m552s1683m552s1683m552s1683"
341+
"m552s552m552s552m552s552m552s1683m552s552m552s552m552s552m552s552"
342+
"m552s1683m552s1683m552s1683m552s552m552s1683m552s1683m552s1683m552s1683"
343+
"m552s40317"
344+
"m8994s2235m552s96310",
345345
irsend.outputStr());
346346

347347
// Send it again with a two repeats.
@@ -356,14 +356,14 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) {
356356
EXPECT_EQ(0x8, irsend.capture.command);
357357
EXPECT_EQ(
358358
"f38028d50"
359-
"m8892s4446"
360-
"m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546"
361-
"m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664"
362-
"m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546"
363-
"m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664"
364-
"m546s39858"
365-
"m8892s2210m546s95212"
366-
"m8892s2210m546s95212",
359+
"m8994s4497"
360+
"m552s552m552s552m552s552m552s1683m552s1683m552s552m552s552m552s552"
361+
"m552s1683m552s1683m552s1683m552s552m552s552m552s1683m552s1683m552s1683"
362+
"m552s552m552s552m552s552m552s1683m552s552m552s552m552s552m552s552"
363+
"m552s1683m552s1683m552s1683m552s552m552s1683m552s1683m552s1683m552s1683"
364+
"m552s40317"
365+
"m8994s2235m552s96310"
366+
"m8994s2235m552s96310",
367367
irsend.outputStr());
368368
}
369369

@@ -391,3 +391,36 @@ TEST(TestSendPronto, Issue1034) {
391391
EXPECT_EQ(0xa3, irsend.capture.address);
392392
EXPECT_EQ(0x10, irsend.capture.command);
393393
}
394+
395+
// Tests for #1103
396+
TEST(TestSendPronto, Issue1103) {
397+
IRsendTest irsend(0);
398+
IRrecv irrecv(0);
399+
irsend.begin();
400+
// Based on raw data:
401+
// uint16_t rawData[7] = {20100, 20472, 15092, 30704, 20102, 20472, 15086};
402+
// and output from `raw_to_pronto_code.py --hz 38000`:
403+
// Pronto code = '0000 006D 0004 0000 02FB 0309 023D 048E 02FB 0309 023D 0ED8'
404+
uint16_t pronto_test[12] = {
405+
0x0000, 0x006D, 0x0004, 0x0000, 0x02FB, 0x0309, 0x023D, 0x048E,
406+
0x02FB, 0x0309, 0x023D, 0x0ED8};
407+
irsend.reset();
408+
irsend.sendPronto(pronto_test, 12);
409+
EXPECT_EQ(
410+
"f38028d50m20066s20435m15069s30665m20066s20435m15069s99940",
411+
irsend.outputStr());
412+
// Which pretty much matches the `rawData` above.
413+
414+
// Shorter test.
415+
// uint16_t rawData[4] = {20100, 20472, 15092, 30704};
416+
// and output from `raw_to_pronto_code.py --hz 38000`:
417+
// Pronto code = '0000 006D 0002 0000 02FB 0309 023D 048E'
418+
uint16_t pronto_test2[8] = {
419+
0x0000, 0x006D, 0x0002, 0x0000, 0x02FB, 0x0309, 0x023D, 0x048E};
420+
irsend.reset();
421+
irsend.sendPronto(pronto_test2, 8);
422+
EXPECT_EQ(
423+
"f38028d50m20066s20435m15069s30665",
424+
irsend.outputStr());
425+
// Which pretty much matches the `rawData` above.
426+
}

‎tools/auto_analyse_raw_data.py‎

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import sys
99

1010

11-
class RawIRMessage():
11+
class RawIRMessage(object):
1212
"""Basic analyse functions & structure for raw IR messages."""
1313

1414
# pylint: disable=too-many-instance-attributes
@@ -679,6 +679,34 @@ def generate_code(defines, code, bits_str, name="", output=sys.stdout):
679679
for line in code["recv64+"]:
680680
output.write("%s\n" % line)
681681

682+
def add_rawdata_args(parser):
683+
"""Add the arguments for feeding in the rawdata string(s)."""
684+
arg_group = parser.add_mutually_exclusive_group(required=True)
685+
arg_group.add_argument(
686+
"rawdata",
687+
help="A rawData line from IRrecvDumpV2. e.g. 'uint16_t rawbuf[37] = {"
688+
"7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, "
689+
"520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, "
690+
"494, 520, 520, 520, 494, 520, 494, 520, 494, 520, 494};'",
691+
nargs="?")
692+
arg_group.add_argument(
693+
"-f", "--file", help="Read in a rawData line from the file.")
694+
arg_group.add_argument(
695+
"--stdin",
696+
help="Read in a rawData line from STDIN.",
697+
action="store_true",
698+
default=False)
699+
700+
def get_rawdata(arg_options):
701+
"""Return the rawdata string(s) as per the options."""
702+
if arg_options.stdin:
703+
return sys.stdin.read()
704+
elif arg_options.file:
705+
with open(arg_options.file) as input_file:
706+
return input_file.read()
707+
else:
708+
return arg_options.rawdata
709+
682710

683711
def main():
684712
"""Parse the commandline arguments and call the method."""
@@ -699,16 +727,6 @@ def main():
699727
help="Name of the protocol/device to use in code generation. E.g. Onkyo",
700728
dest="name",
701729
default="")
702-
arg_group = arg_parser.add_mutually_exclusive_group(required=True)
703-
arg_group.add_argument(
704-
"rawdata",
705-
help="A rawData line from IRrecvDumpV2. e.g. 'uint16_t rawbuf[37] = {"
706-
"7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, "
707-
"520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, "
708-
"494, 520, 520, 520, 494, 520, 494, 520, 494, 520, 494};'",
709-
nargs="?")
710-
arg_group.add_argument(
711-
"-f", "--file", help="Read in a rawData line from the file.")
712730
arg_parser.add_argument(
713731
"-r",
714732
"--range",
@@ -717,22 +735,11 @@ def main():
717735
" it the same value.",
718736
dest="margin",
719737
default=200)
720-
arg_group.add_argument(
721-
"--stdin",
722-
help="Read in a rawData line from STDIN.",
723-
action="store_true",
724-
default=False)
738+
add_rawdata_args(arg_parser)
725739
arg_options = arg_parser.parse_args()
726740

727-
if arg_options.stdin:
728-
data = sys.stdin.read()
729-
elif arg_options.file:
730-
with open(arg_options.file) as input_file:
731-
data = input_file.read()
732-
else:
733-
data = arg_options.rawdata
734-
parse_and_report(data, arg_options.margin, arg_options.gen_code,
735-
arg_options.name)
741+
parse_and_report(get_rawdata(arg_options), arg_options.margin,
742+
arg_options.gen_code, arg_options.name)
736743

737744

738745
if __name__ == '__main__':

0 commit comments

Comments
 (0)