Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
arnoz
Date:
Fri Oct 01 08:19:46 2021 +0000
Revision:
116:7a67265d7c19
Parent:
82:4f6209cb5c33
- Correct information regarding your last merge

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 77:0b96f6867312 1 // IR Receiver
mjr 77:0b96f6867312 2 //
mjr 77:0b96f6867312 3 #include "IRReceiver.h"
mjr 77:0b96f6867312 4 #include "IRTransmitter.h"
mjr 77:0b96f6867312 5 #include "IRProtocols.h"
mjr 77:0b96f6867312 6
mjr 77:0b96f6867312 7 // utility macro
mjr 77:0b96f6867312 8 #define countof(arr) (sizeof(arr)/sizeof((arr)[0]))
mjr 77:0b96f6867312 9
mjr 77:0b96f6867312 10 // Constructor
mjr 77:0b96f6867312 11 IRReceiver::IRReceiver(PinName rxpin, size_t rawBufCount) :
mjr 77:0b96f6867312 12 pin(rxpin),
mjr 77:0b96f6867312 13 rawbuf(rawBufCount)
mjr 77:0b96f6867312 14 {
mjr 77:0b96f6867312 15 // the TSOP384xx has an internal pull-up resistor, so we don't
mjr 77:0b96f6867312 16 // need one of our own
mjr 77:0b96f6867312 17 pin.mode(PullNone);
mjr 77:0b96f6867312 18
mjr 77:0b96f6867312 19 // make sure the protocol singletons are allocated
mjr 77:0b96f6867312 20 IRProtocol::allocProtocols();
mjr 77:0b96f6867312 21
mjr 77:0b96f6867312 22 // there's no transmitter connected yet
mjr 77:0b96f6867312 23 transmitter = 0;
mjr 77:0b96f6867312 24 }
mjr 77:0b96f6867312 25
mjr 77:0b96f6867312 26 // Destructor
mjr 77:0b96f6867312 27 IRReceiver::~IRReceiver() {
mjr 77:0b96f6867312 28 }
mjr 77:0b96f6867312 29
mjr 77:0b96f6867312 30 // Enable reception
mjr 77:0b96f6867312 31 void IRReceiver::enable()
mjr 77:0b96f6867312 32 {
mjr 77:0b96f6867312 33 // start the pulse timers
mjr 77:0b96f6867312 34 startPulse(pin.read() ? 0 : 1);
mjr 77:0b96f6867312 35
mjr 77:0b96f6867312 36 // set interrupt handlers for edges on the input pin
mjr 82:4f6209cb5c33 37 pin.fall(&IRReceiver::cbFall, this);
mjr 82:4f6209cb5c33 38 pin.rise(&IRReceiver::cbRise, this);
mjr 77:0b96f6867312 39 }
mjr 77:0b96f6867312 40
mjr 77:0b96f6867312 41 // Disable reception
mjr 77:0b96f6867312 42 void IRReceiver::disable()
mjr 77:0b96f6867312 43 {
mjr 77:0b96f6867312 44 // Shut down all of our asynchronous handlers: remove the pin level
mjr 77:0b96f6867312 45 // interrupts, stop the pulse timer, and cancel the maximum pulse
mjr 77:0b96f6867312 46 // length timeout.
mjr 77:0b96f6867312 47 pin.fall(0);
mjr 77:0b96f6867312 48 pin.rise(0);
mjr 77:0b96f6867312 49 pulseTimer.stop();
mjr 77:0b96f6867312 50 timeout.detach();
mjr 77:0b96f6867312 51 }
mjr 77:0b96f6867312 52
mjr 77:0b96f6867312 53 // Start a new pulse of the given type.
mjr 77:0b96f6867312 54 void IRReceiver::startPulse(bool newPulseState)
mjr 77:0b96f6867312 55 {
mjr 77:0b96f6867312 56 // set the new state
mjr 77:0b96f6867312 57 pulseState = newPulseState;
mjr 77:0b96f6867312 58
mjr 77:0b96f6867312 59 // reset the pulse timer
mjr 77:0b96f6867312 60 pulseTimer.reset();
mjr 77:0b96f6867312 61 pulseTimer.start();
mjr 77:0b96f6867312 62 pulseAtMax = false;
mjr 77:0b96f6867312 63
mjr 77:0b96f6867312 64 // cancel any prior pulse timeout
mjr 77:0b96f6867312 65 timeout.detach();
mjr 77:0b96f6867312 66
mjr 77:0b96f6867312 67 // Set a new pulse timeout for the maximum pulse length
mjr 77:0b96f6867312 68 timeout.attach_us(this, &IRReceiver::pulseTimeout, MAX_PULSE);
mjr 77:0b96f6867312 69 }
mjr 77:0b96f6867312 70
mjr 77:0b96f6867312 71 // End the current pulse
mjr 77:0b96f6867312 72 void IRReceiver::endPulse(bool lastPulseState)
mjr 77:0b96f6867312 73 {
mjr 77:0b96f6867312 74 // Add the pulse to the buffer. If the pulse already timed out,
mjr 77:0b96f6867312 75 // we already wrote it, so there's no need to write it again.
mjr 77:0b96f6867312 76 if (!pulseAtMax)
mjr 77:0b96f6867312 77 {
mjr 77:0b96f6867312 78 // get the time of the ending space
mjr 77:0b96f6867312 79 uint32_t t = pulseTimer.read_us();
mjr 77:0b96f6867312 80
mjr 77:0b96f6867312 81 // Scale by 2X to give us more range in a 16-bit int. Since we're
mjr 77:0b96f6867312 82 // also discarding the low bit (for the mark/space indicator below),
mjr 77:0b96f6867312 83 // round to the nearest 4us by adding 2us before dividing.
mjr 77:0b96f6867312 84 t += 2;
mjr 77:0b96f6867312 85 t >>= 1;
mjr 77:0b96f6867312 86
mjr 77:0b96f6867312 87 // limit the stored value to the uint16 maximum value
mjr 77:0b96f6867312 88 if (t > 65535)
mjr 77:0b96f6867312 89 t = 65535;
mjr 77:0b96f6867312 90
mjr 77:0b96f6867312 91 // set the low bit if it's a mark, clear it if it's a space
mjr 77:0b96f6867312 92 t &= ~0x0001;
mjr 77:0b96f6867312 93 t |= lastPulseState;
mjr 77:0b96f6867312 94
mjr 77:0b96f6867312 95 // add it to the buffer
mjr 77:0b96f6867312 96 rawbuf.write(uint16_t(t));
mjr 77:0b96f6867312 97 }
mjr 77:0b96f6867312 98 }
mjr 77:0b96f6867312 99
mjr 77:0b96f6867312 100 // Falling-edge interrupt. The sensors we work with use active-low
mjr 77:0b96f6867312 101 // outputs, so a high->low edge means that we're switching from a "space"
mjr 77:0b96f6867312 102 //(IR off) to a "mark" (IR on).
mjr 77:0b96f6867312 103 void IRReceiver::fall(void)
mjr 77:0b96f6867312 104 {
mjr 77:0b96f6867312 105 // If the transmitter is sending, ignore new ON pulses, so that we
mjr 77:0b96f6867312 106 // don't try to read our own transmissions.
mjr 77:0b96f6867312 107 if (transmitter != 0 && transmitter->isSending())
mjr 77:0b96f6867312 108 return;
mjr 77:0b96f6867312 109
mjr 77:0b96f6867312 110 // if we were in a space, end the space and start a mark
mjr 77:0b96f6867312 111 if (!pulseState)
mjr 77:0b96f6867312 112 {
mjr 77:0b96f6867312 113 endPulse(false);
mjr 77:0b96f6867312 114 startPulse(true);
mjr 77:0b96f6867312 115 }
mjr 77:0b96f6867312 116 }
mjr 77:0b96f6867312 117
mjr 77:0b96f6867312 118 // Rising-edge interrupt. A low->high edge means we're switching from
mjr 77:0b96f6867312 119 // a "mark" (IR on) to a "space" (IR off).
mjr 77:0b96f6867312 120 void IRReceiver::rise(void)
mjr 77:0b96f6867312 121 {
mjr 77:0b96f6867312 122 // if we were in a mark, end the mark and start a space
mjr 77:0b96f6867312 123 if (pulseState)
mjr 77:0b96f6867312 124 {
mjr 77:0b96f6867312 125 endPulse(true);
mjr 77:0b96f6867312 126 startPulse(false);
mjr 77:0b96f6867312 127 }
mjr 77:0b96f6867312 128 }
mjr 77:0b96f6867312 129
mjr 77:0b96f6867312 130 // Pulse timeout.
mjr 77:0b96f6867312 131 void IRReceiver::pulseTimeout(void)
mjr 77:0b96f6867312 132 {
mjr 77:0b96f6867312 133 // End the current pulse, even though it hasn't physically ended,
mjr 77:0b96f6867312 134 // so that the protocol processor can read it. Pulses longer than
mjr 77:0b96f6867312 135 // the maximum are all the same to the protocols, so we can process
mjr 77:0b96f6867312 136 // these as soon as we reach the timeout. However, don't start a
mjr 77:0b96f6867312 137 // new pulse yet; we'll wait to do that until we get an actual
mjr 77:0b96f6867312 138 // physical pulser.
mjr 77:0b96f6867312 139 endPulse(pulseState);
mjr 77:0b96f6867312 140
mjr 77:0b96f6867312 141 // note that we've reached the pulse timeout
mjr 77:0b96f6867312 142 pulseAtMax = true;
mjr 77:0b96f6867312 143 }
mjr 77:0b96f6867312 144
mjr 77:0b96f6867312 145 // Process the buffer contents
mjr 77:0b96f6867312 146 void IRReceiver::process()
mjr 77:0b96f6867312 147 {
mjr 77:0b96f6867312 148 // keep going until we run out of samples
mjr 77:0b96f6867312 149 uint16_t t;
mjr 77:0b96f6867312 150 while (rawbuf.read(t))
mjr 77:0b96f6867312 151 {
mjr 77:0b96f6867312 152 // Process it through the protocol handlers. Note that the low
mjr 77:0b96f6867312 153 // bit is the mark/space indicator, not a time bit, so pull it
mjr 77:0b96f6867312 154 // out as the 'mark' argument and mask it out of the time. And
mjr 77:0b96f6867312 155 // note that the value in the buffer is in 2us units, so multiply
mjr 77:0b96f6867312 156 // by 2 to get microseconds.
mjr 77:0b96f6867312 157 processProtocols((t & ~0x0001) << 1, t & 0x0001);
mjr 77:0b96f6867312 158 }
mjr 77:0b96f6867312 159 }
mjr 77:0b96f6867312 160
mjr 77:0b96f6867312 161 // Process one buffer pulse
mjr 77:0b96f6867312 162 bool IRReceiver::processOne(uint16_t &sample)
mjr 77:0b96f6867312 163 {
mjr 77:0b96f6867312 164 // try reading a sample
mjr 77:0b96f6867312 165 if (rawbuf.read(sample))
mjr 77:0b96f6867312 166 {
mjr 77:0b96f6867312 167 // Process it through the protocols - convert to microseconds
mjr 77:0b96f6867312 168 // by masking out the low bit and mulitplying by the 2us units
mjr 77:0b96f6867312 169 // we use in the sample buffer, and pull out the low bit as
mjr 77:0b96f6867312 170 // the mark/space type.
mjr 77:0b96f6867312 171 processProtocols((sample & ~0x0001) << 1, sample & 0x0001);
mjr 77:0b96f6867312 172
mjr 77:0b96f6867312 173 // got a sample
mjr 77:0b96f6867312 174 return true;
mjr 77:0b96f6867312 175 }
mjr 77:0b96f6867312 176
mjr 77:0b96f6867312 177 // no sample
mjr 77:0b96f6867312 178 return false;
mjr 77:0b96f6867312 179 }
mjr 77:0b96f6867312 180
mjr 77:0b96f6867312 181 // Process one buffer pulse
mjr 77:0b96f6867312 182 bool IRReceiver::processOne(uint32_t &t, bool &mark)
mjr 77:0b96f6867312 183 {
mjr 77:0b96f6867312 184 // try reading a sample
mjr 77:0b96f6867312 185 uint16_t sample;
mjr 77:0b96f6867312 186 if (rawbuf.read(sample))
mjr 77:0b96f6867312 187 {
mjr 77:0b96f6867312 188 // it's a mark if the low bit is set
mjr 77:0b96f6867312 189 mark = sample & 0x0001;
mjr 77:0b96f6867312 190
mjr 77:0b96f6867312 191 // remove the low bit, as it's not actually part of the time value,
mjr 77:0b96f6867312 192 // and multiply by 2 to get from the 2us units in the buffer to
mjr 77:0b96f6867312 193 // microseconds
mjr 77:0b96f6867312 194 t = (sample & ~0x0001) << 1;
mjr 77:0b96f6867312 195
mjr 77:0b96f6867312 196 // process it through the protocol handlers
mjr 77:0b96f6867312 197 processProtocols(t, mark);
mjr 77:0b96f6867312 198
mjr 77:0b96f6867312 199 // got a sample
mjr 77:0b96f6867312 200 return true;
mjr 77:0b96f6867312 201 }
mjr 77:0b96f6867312 202
mjr 77:0b96f6867312 203 // no sample
mjr 77:0b96f6867312 204 return false;
mjr 77:0b96f6867312 205 }
mjr 77:0b96f6867312 206
mjr 77:0b96f6867312 207 // Process a pulse through the protocol handlers
mjr 77:0b96f6867312 208 void IRReceiver::processProtocols(uint32_t t, bool mark)
mjr 77:0b96f6867312 209 {
mjr 77:0b96f6867312 210 // generate a call to each sender in the RX list
mjr 77:0b96f6867312 211 #define IR_PROTOCOL_RX(cls) IRProtocol::protocols->s_##cls.rxPulse(this, t, mark);
mjr 77:0b96f6867312 212 #include "IRProtocolList.h"
mjr 77:0b96f6867312 213 }