-
Notifications
You must be signed in to change notification settings - Fork 838
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tool to convert protocol & code to raw timing info. (#1708)
* Add tool to convert protocol & code to raw timing info. Usage: tools/code_to_raw --protocol PROTOCOL_NAME --code <hexidecimal> [--bits 1-424] [--timinginfo] e.g. ``` # Convert an A/C code to rawData[] & Timinginfo tool/code_to_raw --protocol KELVINATOR --code 0x190B8050000000E0190B8070000010F0 --timinginfo # Convert a Samsung TV code to rawData[]. tools/code_to_raw --protocol SAMSUNG --code 0xE0E09966 # Convert a Sony 12 bit message to rawData[]. tools/code_to_raw --protocol Sony --code 0xf50 --bits 12 ``` * Add some tests for `code_to_raw`. * Update tools Makefile to be more dynamic For #1707 For #1703 Co-authored-by: Christian Nilsson <nikize@gmail.com>
- Loading branch information
1 parent
e53505d
commit 705c8c4
Showing
4 changed files
with
223 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ tools/*.o | |
tools/*.a | ||
tools/gc_decode | ||
tools/mode2_decode | ||
tools/code_to_raw | ||
|
||
.pioenvs | ||
.piolibdeps | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// Quick and dirty tool to convert a protocol's (hex) codes to raw timings. | ||
// Copyright 2021 David Conran | ||
|
||
#include <errno.h> | ||
#include <inttypes.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <string> | ||
#include "IRac.h" | ||
#include "IRsend.h" | ||
#include "IRsend_test.h" | ||
#include "IRutils.h" | ||
|
||
|
||
void usage_error(char *name) { | ||
std::cerr << "Usage: " << name | ||
<< " --protocol PROTOCOL_NAME" | ||
<< " --code <hexidecimal>" | ||
<< " [--bits 1-" << kStateSizeMax * 8 << "]" | ||
<< " [--timinginfo]" | ||
<< std::endl; | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
int argv_offset = 1; | ||
int repeats = 0; | ||
uint64_t code = 0; | ||
uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. | ||
decode_type_t input_type = decode_type_t::UNKNOWN; | ||
bool timinginfo = false; | ||
|
||
// Check the invocation/calling usage. | ||
if (argc < 5 || argc > 8) { | ||
usage_error(argv[0]); | ||
return 1; | ||
} | ||
|
||
if (strncmp("--protocol", argv[argv_offset], 11) == 0) { | ||
argv_offset++; | ||
input_type = strToDecodeType(argv[argv_offset]); | ||
switch (input_type) { | ||
// Unsupported types | ||
case decode_type_t::UNUSED: | ||
case decode_type_t::UNKNOWN: | ||
case decode_type_t::GLOBALCACHE: | ||
case decode_type_t::PRONTO: | ||
case decode_type_t::RAW: | ||
std::cerr << "The protocol specified is not supported by this program." | ||
<< std::endl; | ||
return 1; | ||
default: | ||
break; | ||
} | ||
argv_offset++; | ||
} | ||
|
||
uint16_t nbits = IRsend::defaultBits(input_type); | ||
uint16_t stateSize = nbits / 8; | ||
if (strncmp("--code", argv[argv_offset], 7) == 0) { | ||
argv_offset++; | ||
String hexstr = String(argv[argv_offset]); | ||
uint64_t strOffset = 0; | ||
if (hexstr.rfind("0x", 0) || hexstr.rfind("0X", 0)) strOffset = 2; | ||
|
||
// Calculate how many hexadecimal characters there are. | ||
uint64_t hexstrlength = hexstr.length() - strOffset; | ||
|
||
// Ptr to the least significant byte of the resulting state for this | ||
// protocol. | ||
uint8_t *statePtr = &state[stateSize - 1]; | ||
|
||
// Convert the string into a state array of the correct length. | ||
for (uint16_t i = 0; i < hexstrlength; i++) { | ||
// Grab the next least sigificant hexadecimal digit from the string. | ||
uint8_t c = tolower(hexstr[hexstrlength + strOffset - i - 1]); | ||
if (isxdigit(c)) { | ||
if (isdigit(c)) | ||
c -= '0'; | ||
else | ||
c = c - 'a' + 10; | ||
} else { | ||
std::cerr << "Code " << argv[argv_offset] | ||
<< " contains non-hexidecimal characters." << std::endl; | ||
return 3; | ||
} | ||
if (i % 2 == 1) { // Odd: Upper half of the byte. | ||
*statePtr += (c << 4); | ||
statePtr--; // Advance up to the next least significant byte of state. | ||
} else { // Even: Lower half of the byte. | ||
*statePtr = c; | ||
} | ||
} | ||
if (!hasACState(input_type)) | ||
code = std::stoull(argv[argv_offset], nullptr, 16); | ||
argv_offset++; | ||
} | ||
|
||
if (argc - argv_offset > 0 && strncmp("--bits", argv[argv_offset], 7) == 0) { | ||
argv_offset++; | ||
nbits = std::stoul(argv[argv_offset], nullptr, 10); | ||
if (nbits == 0 && (nbits <= kStateSizeMax * 8)) { | ||
std::cerr << "Nr. of bits " << argv[argv_offset] | ||
<< " is invalid." << std::endl; | ||
return 1; | ||
} | ||
stateSize = nbits / 8; | ||
argv_offset++; | ||
} | ||
|
||
if (argc - argv_offset > 0 && | ||
strncmp("--timinginfo", argv[argv_offset], 13) == 0) { | ||
argv_offset++; | ||
timinginfo = true; | ||
} | ||
|
||
if (argc - argv_offset != 0) { | ||
usage_error(argv[0]); | ||
return 1; | ||
} | ||
|
||
IRsendTest irsend(kGpioUnused); | ||
IRrecv irrecv(kGpioUnused); | ||
irsend.begin(); | ||
irsend.reset(); | ||
|
||
if (hasACState(input_type)) // Is it larger than 64 bits? | ||
irsend.send(input_type, state, stateSize); | ||
else | ||
irsend.send(input_type, code, nbits, repeats); | ||
|
||
irsend.makeDecodeResult(); | ||
irrecv.decode(&irsend.capture); | ||
|
||
std::cout << "Code type: " << irsend.capture.decode_type << " (" | ||
<< typeToString(irsend.capture.decode_type) << ")" << std::endl | ||
<< "Code bits: " << irsend.capture.bits << std::endl; | ||
if (hasACState(irsend.capture.decode_type)) { | ||
String description = IRAcUtils::resultAcToString(&irsend.capture); | ||
if (description.length()) { | ||
std::cout << "Description: " << description.c_str() << std::endl; | ||
} | ||
} | ||
|
||
std::cout << std::endl << resultToSourceCode(&irsend.capture) << std::endl; | ||
if (timinginfo) std::cout << resultToTimingInfo(&irsend.capture); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#! /bin/bash | ||
CODE_TO_RAW=./code_to_raw | ||
if [[ ! -x ${CODE_TO_RAW} ]]; then | ||
echo "'raw_to_code' failed to compile and produce an executable." | ||
exit 1 | ||
fi | ||
|
||
function unittest_success() | ||
{ | ||
COMMAND=$1 | ||
EXPECTED="$2" | ||
echo -n "Testing: \"${COMMAND}\" ..." | ||
OUTPUT="$(${COMMAND})" | ||
STATUS=$? | ||
FAILURE="" | ||
if [[ ${STATUS} -ne 0 ]]; then | ||
FAILURE="Non-Zero Exit status: ${STATUS}. " | ||
fi | ||
if [[ "${OUTPUT}" != "${EXPECTED}" ]]; then | ||
FAILURE="${FAILURE} Unexpected Output: \"${OUTPUT}\" != \"${EXPECTED}\"" | ||
fi | ||
if [[ -z ${FAILURE} ]]; then | ||
echo " ok!" | ||
return 0 | ||
else | ||
echo | ||
echo "FAILED: ${FAILURE}" | ||
return 1 | ||
fi | ||
} | ||
|
||
read -r -d '' OUT << EOM | ||
Code type: 4 (SONY) | ||
Code bits: 12 | ||
uint16_t rawData[78] = {2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600, 2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600, 2400, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 600, 600, 600, 600, 600, 24600 }; // SONY F50 | ||
uint32_t address = 0x1; | ||
uint32_t command = 0x2F; | ||
uint64_t data = 0xF50; | ||
EOM | ||
|
||
unittest_success "${CODE_TO_RAW} --protocol Sony --code 0xf50 --bits 12" "${OUT}" | ||
|
||
read -r -d '' OUT << EOM | ||
Code type: 7 (SAMSUNG) | ||
Code bits: 32 | ||
uint16_t rawData[68] = {4480, 4480, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 560, 560, 47040 }; // SAMSUNG E0E09966 | ||
uint32_t address = 0x7; | ||
uint32_t command = 0x99; | ||
uint64_t data = 0xE0E09966; | ||
EOM | ||
|
||
unittest_success "${CODE_TO_RAW} --protocol SAMSUNG --code 0xE0E09966" "${OUT}" | ||
|
||
read -r -d '' OUT << xEOMx | ||
Code type: 18 (KELVINATOR) | ||
Code bits: 128 | ||
Description: Power: On, Mode: 1 (Cool), Temp: 27C, Fan: 1 (Low), Turbo: Off, Quiet: Off, XFan: On, Ion: Off, Light: Off, Swing(H): Off, Swing(V): Off | ||
uint16_t rawData[280] = {9010, 4504, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 19974, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 39950, 9010, 4504, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 19974, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 510, 680, 1530, 680, 1530, 680, 1530, 680, 1530, 680, 39950 }; // KELVINATOR | ||
uint8_t state[16] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xF0}; | ||
xEOMx | ||
|
||
unittest_success "${CODE_TO_RAW} --protocol KELVINATOR --code 0x190B8050000000E0190B8070000010F0" "${OUT}" |