guidance : how to implement a simple low latency protocol? #1658
-
hello, Thank you for your answer! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Yes. See: https://github.com/crankyoldgit/IRremoteESP8266/wiki/Adding-support-for-a-new-IR-protocol
Sending it every 50ms will be a significant issue with the default configuration. Lines 39 to 49 in fae62c8 & IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino Lines 54 to 88 in fae62c8 You can specify that time in when you create the capture object. e.g. IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino Lines 120 to 121 in fae62c8 also see the documentation: https://crankyoldgit.github.io/IRremoteESP8266/doxygen/html/classIRrecv.html#a8fe4d26ef1f863db1db9994fed5fc209 For a message sent every As you want "low latency", a timeout of To lower the processing/decoding time, I'd recommend disabling every protocol other than your own new one. That will cut down on time lost to processing and lower your latency (and code/memory usage too). Tweaking your "protocol" a little by making the end "mark" the same as the bit mark, and the header space larger than the bit space, so I can use the automated tools. e.g.
Using // Copyright 2020 David Conran (crankyoldgit)
/// @file
/// @brief Support for MarioKarton protocol
// Supports:
// Brand: MarioKarton, Model: TODO add device and remote
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
// WARNING: This probably isn't directly usable. It's a guide only.
// See https://github.com/crankyoldgit/IRremoteESP8266/wiki/Adding-support-for-a-new-IR-protocol
// for details of how to include this in the library.
const uint16_t kMarioKartonHdrMark = 2500;
const uint16_t kMarioKartonBitMark = 650;
const uint16_t kMarioKartonHdrSpace = 2000;
const uint16_t kMarioKartonOneSpace = 1650;
const uint16_t kMarioKartonZeroSpace = 550;
const uint16_t kMarioKartonFreq = 38000; // Hz. (Guessing the most common frequency.)
const uint16_t kMarioKartonBits = 2; // Move to IRremoteESP8266.h
const uint16_t kMarioKartonOverhead = 3;
#if SEND_MARIOKARTON
// Function should be safe up to 64 bits.
/// Send a MarioKarton formatted message.
/// Status: ALPHA / Untested.
/// @param[in] data containing the IR command.
/// @param[in] nbits Nr. of bits to send. usually kMarioKartonBits
/// @param[in] repeat Nr. of times the message is to be repeated.
void IRsend::sendMarioKarton(const uint64_t data, const uint16_t nbits, const uint16_t repeat) {
enableIROut(kMarioKartonFreq);
for (uint16_t r = 0; r <= repeat; r++) {
uint64_t send_data = data;
// Header
mark(kMarioKartonHdrMark);
space(kMarioKartonHdrSpace);
// Data Section #1
// e.g. data = 0x1, nbits = 2
sendData(kMarioKartonBitMark, kMarioKartonOneSpace, kMarioKartonBitMark, kMarioKartonZeroSpace, send_data, 2, true);
send_data >>= 2;
// Footer
mark(kMarioKartonBitMark);
space(kDefaultMessageGap); // A 100% made up guess of the gap between messages.
}
}
#endif // SEND_MARIOKARTON
#if DECODE_MARIOKARTON
// Function should be safe up to 64 bits.
/// Decode the supplied MarioKarton message.
/// Status: ALPHA / Untested.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeMarioKarton(decode_results *results, uint16_t offset, const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * nbits + kMarioKartonOverhead - offset)
return false; // Too short a message to match.
if (strict && nbits != kMarioKartonBits)
return false;
uint64_t data = 0;
match_result_t data_result;
// Header
if (!matchMark(results->rawbuf[offset++], kMarioKartonHdrMark))
return false;
if (!matchSpace(results->rawbuf[offset++], kMarioKartonHdrSpace))
return false;
// Data Section #1
// e.g. data_result.data = 0x1, nbits = 2
data_result = matchData(&(results->rawbuf[offset]), 2,
kMarioKartonBitMark, kMarioKartonOneSpace,
kMarioKartonBitMark, kMarioKartonZeroSpace);
offset += data_result.used;
if (data_result.success == false) return false; // Fail
data <<= 2; // Make room for the new bits of data.
data |= data_result.data;
// Footer
if (!matchMark(results->rawbuf[offset++], kMarioKartonBitMark))
return false;
// Success
results->decode_type = decode_type_t::MARIOKARTON;
results->bits = nbits;
results->value = data;
results->command = 0;
results->address = 0;
return true;
}
#endif // DECODE_MARIOKARTON You can obviously tweak-back the modified values in the generated code to match what your actual values are. const uint16_t kMarioKartonGap = 41000; // uSeconds
...
space(kMarioKartonGap); But you don't need sending code really, as you have that sorted. Once you have the capture code working, you can probably trim it down to: /// Decode the supplied MarioKarton message.
/// Status: ALPHA / Untested.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeMarioKarton(decode_results *results, uint16_t offset, const uint16_t nbits, const bool strict) {
if (strict && nbits != kMarioKartonBits)
return false; // We expect MarioKarton to be a certain sized message.
uint64_t data = 0;
// Match Header + Data + Footer
if (!matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, nbits,
kMarioKartonHdrMark, kMarioKartonHdrSpace,
kMarioKartonBitMark, kMarioKartonOneSpace,
kMarioKartonMark, kMarioKartonSpace,
kMarioKartonBitMark, kMarioKartonGap, true)) return false;
// Success
results->decode_type = decode_type_t::MARIOKARTON;
results->bits = nbits;
results->value = data;
results->command = 0;
results->address = 0;
return true;
} Docs on Hope that helps you. |
Beta Was this translation helpful? Give feedback.
Yes. See: https://github.com/crankyoldgit/IRremoteESP8266/wiki/Adding-support-for-a-new-IR-protocol
Sending it every 50ms will be a significant issue with the default configuration.
You will need to lower how long the library waits for a there to be no more incoming IR signal. That's how the library determines when a message is finished.
See:
IRremoteESP8266/src/IRrecv.h
Lines 39 to 49 in fae62c8