Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
IRRemote/IRReceiver.cpp
- Committer:
- arnoz
- Date:
- 2021-10-01
- Revision:
- 116:7a67265d7c19
- Parent:
- 82:4f6209cb5c33
File content as of revision 116:7a67265d7c19:
// IR Receiver // #include "IRReceiver.h" #include "IRTransmitter.h" #include "IRProtocols.h" // utility macro #define countof(arr) (sizeof(arr)/sizeof((arr)[0])) // Constructor IRReceiver::IRReceiver(PinName rxpin, size_t rawBufCount) : pin(rxpin), rawbuf(rawBufCount) { // the TSOP384xx has an internal pull-up resistor, so we don't // need one of our own pin.mode(PullNone); // make sure the protocol singletons are allocated IRProtocol::allocProtocols(); // there's no transmitter connected yet transmitter = 0; } // Destructor IRReceiver::~IRReceiver() { } // Enable reception void IRReceiver::enable() { // start the pulse timers startPulse(pin.read() ? 0 : 1); // set interrupt handlers for edges on the input pin pin.fall(&IRReceiver::cbFall, this); pin.rise(&IRReceiver::cbRise, this); } // Disable reception void IRReceiver::disable() { // Shut down all of our asynchronous handlers: remove the pin level // interrupts, stop the pulse timer, and cancel the maximum pulse // length timeout. pin.fall(0); pin.rise(0); pulseTimer.stop(); timeout.detach(); } // Start a new pulse of the given type. void IRReceiver::startPulse(bool newPulseState) { // set the new state pulseState = newPulseState; // reset the pulse timer pulseTimer.reset(); pulseTimer.start(); pulseAtMax = false; // cancel any prior pulse timeout timeout.detach(); // Set a new pulse timeout for the maximum pulse length timeout.attach_us(this, &IRReceiver::pulseTimeout, MAX_PULSE); } // End the current pulse void IRReceiver::endPulse(bool lastPulseState) { // Add the pulse to the buffer. If the pulse already timed out, // we already wrote it, so there's no need to write it again. if (!pulseAtMax) { // get the time of the ending space uint32_t t = pulseTimer.read_us(); // Scale by 2X to give us more range in a 16-bit int. Since we're // also discarding the low bit (for the mark/space indicator below), // round to the nearest 4us by adding 2us before dividing. t += 2; t >>= 1; // limit the stored value to the uint16 maximum value if (t > 65535) t = 65535; // set the low bit if it's a mark, clear it if it's a space t &= ~0x0001; t |= lastPulseState; // add it to the buffer rawbuf.write(uint16_t(t)); } } // Falling-edge interrupt. The sensors we work with use active-low // outputs, so a high->low edge means that we're switching from a "space" //(IR off) to a "mark" (IR on). void IRReceiver::fall(void) { // If the transmitter is sending, ignore new ON pulses, so that we // don't try to read our own transmissions. if (transmitter != 0 && transmitter->isSending()) return; // if we were in a space, end the space and start a mark if (!pulseState) { endPulse(false); startPulse(true); } } // Rising-edge interrupt. A low->high edge means we're switching from // a "mark" (IR on) to a "space" (IR off). void IRReceiver::rise(void) { // if we were in a mark, end the mark and start a space if (pulseState) { endPulse(true); startPulse(false); } } // Pulse timeout. void IRReceiver::pulseTimeout(void) { // End the current pulse, even though it hasn't physically ended, // so that the protocol processor can read it. Pulses longer than // the maximum are all the same to the protocols, so we can process // these as soon as we reach the timeout. However, don't start a // new pulse yet; we'll wait to do that until we get an actual // physical pulser. endPulse(pulseState); // note that we've reached the pulse timeout pulseAtMax = true; } // Process the buffer contents void IRReceiver::process() { // keep going until we run out of samples uint16_t t; while (rawbuf.read(t)) { // Process it through the protocol handlers. Note that the low // bit is the mark/space indicator, not a time bit, so pull it // out as the 'mark' argument and mask it out of the time. And // note that the value in the buffer is in 2us units, so multiply // by 2 to get microseconds. processProtocols((t & ~0x0001) << 1, t & 0x0001); } } // Process one buffer pulse bool IRReceiver::processOne(uint16_t &sample) { // try reading a sample if (rawbuf.read(sample)) { // Process it through the protocols - convert to microseconds // by masking out the low bit and mulitplying by the 2us units // we use in the sample buffer, and pull out the low bit as // the mark/space type. processProtocols((sample & ~0x0001) << 1, sample & 0x0001); // got a sample return true; } // no sample return false; } // Process one buffer pulse bool IRReceiver::processOne(uint32_t &t, bool &mark) { // try reading a sample uint16_t sample; if (rawbuf.read(sample)) { // it's a mark if the low bit is set mark = sample & 0x0001; // remove the low bit, as it's not actually part of the time value, // and multiply by 2 to get from the 2us units in the buffer to // microseconds t = (sample & ~0x0001) << 1; // process it through the protocol handlers processProtocols(t, mark); // got a sample return true; } // no sample return false; } // Process a pulse through the protocol handlers void IRReceiver::processProtocols(uint32_t t, bool mark) { // generate a call to each sender in the RX list #define IR_PROTOCOL_RX(cls) IRProtocol::protocols->s_##cls.rxPulse(this, t, mark); #include "IRProtocolList.h" }