diff --git a/examples/LinkIR_demo/src/main.cpp b/examples/LinkIR_demo/src/main.cpp index 03fa48c..3499b90 100644 --- a/examples/LinkIR_demo/src/main.cpp +++ b/examples/LinkIR_demo/src/main.cpp @@ -95,7 +95,7 @@ int main() { // u8 address, command; u16 pulses[3000] = {}; Common::log("Receiving..."); - if (linkIR->receive(pulses, 3000, 15000, 1000000)) { + if (linkIR->receive(pulses, 3000, 1000000)) { Common::log("Let's see"); Common::waitForKey(KEY_DOWN); std::string recv; diff --git a/lib/LinkIR.hpp b/lib/LinkIR.hpp index 2e40b9b..05df483 100644 --- a/lib/LinkIR.hpp +++ b/lib/LinkIR.hpp @@ -26,7 +26,7 @@ // // 0 = EOS // - 7) Receive 38kHz signals; // u16 pulses[2000]; -// linkIR->receive(pulses, 2000, 30000); +// linkIR->receive(pulses, 2000); // // out array, max entries, timeout (in microseconds) // - 8) Bitbang the LED manually: // linkIR->setLight(true); @@ -63,19 +63,22 @@ class LinkIR { using Direction = LinkGPIO::Direction; static constexpr int CYCLES_PER_MICROSECOND = 17; - static constexpr int TIMEOUT_MICROSECONDS = 2500; + static constexpr int DETECTION_TIMEOUT = 2500; static constexpr int DEMODULATION_38KHZ_PERIOD = 1000000 / 38000; static constexpr int DEMODULATION_WINDOW_FACTOR = 2; static constexpr int DEMODULATION_SAMPLE_WINDOW_CYCLES = DEMODULATION_38KHZ_PERIOD * DEMODULATION_WINDOW_FACTOR * CYCLES_PER_MICROSECOND; static constexpr int DEMODULATION_MIN_TRANSITIONS = 2; + static constexpr int NEC_TOLERANCE_PERCENTAGE = 15; static constexpr int NEC_TOTAL_PULSES = 68; static constexpr int NEC_LEADER_MARK = 9000; static constexpr int NEC_LEADER_SPACE = 4500; static constexpr int NEC_PULSE = 560; static constexpr int NEC_SPACE_1 = 1690; static constexpr int NEC_SPACE_0 = 560; + static constexpr int DEFAULT_RECEIVE_TIMEOUT = 15000; + static constexpr u32 NO_TIMEOUT = 0xFFFFFFFF; public: /** @@ -120,7 +123,7 @@ class LinkIR { linkGPIO.setSIInterrupts(true); setLight(true); - waitMicroseconds(TIMEOUT_MICROSECONDS); + waitMicroseconds(DETECTION_TIMEOUT); setLight(false); linkGPIO.setSIInterrupts(false); @@ -151,6 +154,25 @@ class LinkIR { send(pulses); } + /** + * Receives a signal and returns whether it's a NEC signal or not. If it is, + * the `address` and `command` will be filled. + * @param address The read 8-bit address, specifying the device. + * @param command The read 8-bit command, specifying the action. + * @param startTimeout Number of microseconds before the first *mark* to abort + * the reception. + */ + bool receiveNEC(u8& address, u8& command, u32 startTimeout = NO_TIMEOUT) { + if (!isEnabled) + return false; + + u16 pulses[NEC_TOTAL_PULSES]; + if (!receive(pulses, NEC_TOTAL_PULSES, startTimeout)) + return false; + + // TODO: IMPLEMENT + } + /** * Sends a generic IR signal, modulating at standard 38kHz. * @param pulses An array of u16 numbers describing the signal. Even indices @@ -168,15 +190,17 @@ class LinkIR { * Even indices are *marks* (IR on), odd indices are *spaces* (IR off), and * `0` ends the signal. * @param maxEntries Maximum capacity of the `pulses` array. - * @param timeout Number of microseconds inside a *space* after terminating - * the reception. It doesn't start to count until the first *mark*. * @param startTimeout Number of microseconds before the first *mark* to abort * the reception. + * @param signalTimeout Number of microseconds inside a *space* after + * terminating the reception. It doesn't start to count until the first + * *mark*. */ - bool receive(u16 pulses[], - u32 maxEntries, - u32 timeout, - u32 startTimeout = 0xFFFFFFFF); // defined in `LinkIR.cpp` + bool receive( + u16 pulses[], + u32 maxEntries, + u32 startTimeout = NO_TIMEOUT, + u32 signalTimeout = DEFAULT_RECEIVE_TIMEOUT); // defined in `LinkIR.cpp` /** * Turns the output IR LED ON/OFF through the `SO` pin (HIGH = ON). diff --git a/lib/iwram_code/LinkIR.cpp b/lib/iwram_code/LinkIR.cpp index 76ed41c..7ff9353 100644 --- a/lib/iwram_code/LinkIR.cpp +++ b/lib/iwram_code/LinkIR.cpp @@ -23,8 +23,8 @@ LINK_CODE_IWRAM void LinkIR::send(u16 pulses[]) { LINK_CODE_IWRAM bool LinkIR::receive(u16 pulses[], u32 maxEntries, - u32 timeout, - u32 startTimeout) { + u32 startTimeout, + u32 signalTimeout) { if (!isEnabled) return false; @@ -32,8 +32,8 @@ LINK_CODE_IWRAM bool LinkIR::receive(u16 pulses[], bool isMark = false; u32 pulseIndex = 0; - u32 lastTransitionTime = 0; u32 initialTime = 0; + u32 lastTransitionTime = 0; startCount(); initialTime = getCount(); @@ -75,12 +75,13 @@ LINK_CODE_IWRAM bool LinkIR::receive(u16 pulses[], isMark = isCarrierPresent; } - // if we've started and we're in a space, check for overall timeout + // if we've started and we're in a space, check for `signalTimeout` if (hasStarted && !isMark && - (getCount() - lastTransitionTime) / CYCLES_PER_MICROSECOND >= timeout) + (getCount() - lastTransitionTime) / CYCLES_PER_MICROSECOND >= + signalTimeout) break; - // if we haven't started and we've waited longer than startTimeout, then + // if we haven't started and we've waited longer than `startTimeout`, then // timeout too if (!hasStarted && (getCount() - initialTime) / CYCLES_PER_MICROSECOND >= startTimeout)