An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.
Dependencies: mbed FastIO FastPWM USBDevice
Fork of Pinscape_Controller by
IRReceiver.cpp
00001 // IR Receiver 00002 // 00003 #include "IRReceiver.h" 00004 #include "IRTransmitter.h" 00005 #include "IRProtocols.h" 00006 00007 // utility macro 00008 #define countof(arr) (sizeof(arr)/sizeof((arr)[0])) 00009 00010 // Constructor 00011 IRReceiver::IRReceiver(PinName rxpin, size_t rawBufCount) : 00012 pin(rxpin), 00013 rawbuf(rawBufCount) 00014 { 00015 // the TSOP384xx has an internal pull-up resistor, so we don't 00016 // need one of our own 00017 pin.mode(PullNone); 00018 00019 // make sure the protocol singletons are allocated 00020 IRProtocol::allocProtocols(); 00021 00022 // there's no transmitter connected yet 00023 transmitter = 0; 00024 } 00025 00026 // Destructor 00027 IRReceiver::~IRReceiver() { 00028 } 00029 00030 // Enable reception 00031 void IRReceiver::enable() 00032 { 00033 // start the pulse timers 00034 startPulse(pin.read() ? 0 : 1); 00035 00036 // set interrupt handlers for edges on the input pin 00037 pin.fall(&IRReceiver::cbFall, this); 00038 pin.rise(&IRReceiver::cbRise, this); 00039 } 00040 00041 // Disable reception 00042 void IRReceiver::disable() 00043 { 00044 // Shut down all of our asynchronous handlers: remove the pin level 00045 // interrupts, stop the pulse timer, and cancel the maximum pulse 00046 // length timeout. 00047 pin.fall(0); 00048 pin.rise(0); 00049 pulseTimer.stop(); 00050 timeout.detach(); 00051 } 00052 00053 // Start a new pulse of the given type. 00054 void IRReceiver::startPulse(bool newPulseState) 00055 { 00056 // set the new state 00057 pulseState = newPulseState; 00058 00059 // reset the pulse timer 00060 pulseTimer.reset(); 00061 pulseTimer.start(); 00062 pulseAtMax = false; 00063 00064 // cancel any prior pulse timeout 00065 timeout.detach(); 00066 00067 // Set a new pulse timeout for the maximum pulse length 00068 timeout.attach_us(this, &IRReceiver::pulseTimeout, MAX_PULSE); 00069 } 00070 00071 // End the current pulse 00072 void IRReceiver::endPulse(bool lastPulseState) 00073 { 00074 // Add the pulse to the buffer. If the pulse already timed out, 00075 // we already wrote it, so there's no need to write it again. 00076 if (!pulseAtMax) 00077 { 00078 // get the time of the ending space 00079 uint32_t t = pulseTimer.read_us(); 00080 00081 // Scale by 2X to give us more range in a 16-bit int. Since we're 00082 // also discarding the low bit (for the mark/space indicator below), 00083 // round to the nearest 4us by adding 2us before dividing. 00084 t += 2; 00085 t >>= 1; 00086 00087 // limit the stored value to the uint16 maximum value 00088 if (t > 65535) 00089 t = 65535; 00090 00091 // set the low bit if it's a mark, clear it if it's a space 00092 t &= ~0x0001; 00093 t |= lastPulseState; 00094 00095 // add it to the buffer 00096 rawbuf.write(uint16_t(t)); 00097 } 00098 } 00099 00100 // Falling-edge interrupt. The sensors we work with use active-low 00101 // outputs, so a high->low edge means that we're switching from a "space" 00102 //(IR off) to a "mark" (IR on). 00103 void IRReceiver::fall(void) 00104 { 00105 // If the transmitter is sending, ignore new ON pulses, so that we 00106 // don't try to read our own transmissions. 00107 if (transmitter != 0 && transmitter->isSending()) 00108 return; 00109 00110 // if we were in a space, end the space and start a mark 00111 if (!pulseState) 00112 { 00113 endPulse(false); 00114 startPulse(true); 00115 } 00116 } 00117 00118 // Rising-edge interrupt. A low->high edge means we're switching from 00119 // a "mark" (IR on) to a "space" (IR off). 00120 void IRReceiver::rise(void) 00121 { 00122 // if we were in a mark, end the mark and start a space 00123 if (pulseState) 00124 { 00125 endPulse(true); 00126 startPulse(false); 00127 } 00128 } 00129 00130 // Pulse timeout. 00131 void IRReceiver::pulseTimeout(void) 00132 { 00133 // End the current pulse, even though it hasn't physically ended, 00134 // so that the protocol processor can read it. Pulses longer than 00135 // the maximum are all the same to the protocols, so we can process 00136 // these as soon as we reach the timeout. However, don't start a 00137 // new pulse yet; we'll wait to do that until we get an actual 00138 // physical pulser. 00139 endPulse(pulseState); 00140 00141 // note that we've reached the pulse timeout 00142 pulseAtMax = true; 00143 } 00144 00145 // Process the buffer contents 00146 void IRReceiver::process() 00147 { 00148 // keep going until we run out of samples 00149 uint16_t t; 00150 while (rawbuf.read(t)) 00151 { 00152 // Process it through the protocol handlers. Note that the low 00153 // bit is the mark/space indicator, not a time bit, so pull it 00154 // out as the 'mark' argument and mask it out of the time. And 00155 // note that the value in the buffer is in 2us units, so multiply 00156 // by 2 to get microseconds. 00157 processProtocols((t & ~0x0001) << 1, t & 0x0001); 00158 } 00159 } 00160 00161 // Process one buffer pulse 00162 bool IRReceiver::processOne(uint16_t &sample) 00163 { 00164 // try reading a sample 00165 if (rawbuf.read(sample)) 00166 { 00167 // Process it through the protocols - convert to microseconds 00168 // by masking out the low bit and mulitplying by the 2us units 00169 // we use in the sample buffer, and pull out the low bit as 00170 // the mark/space type. 00171 processProtocols((sample & ~0x0001) << 1, sample & 0x0001); 00172 00173 // got a sample 00174 return true; 00175 } 00176 00177 // no sample 00178 return false; 00179 } 00180 00181 // Process one buffer pulse 00182 bool IRReceiver::processOne(uint32_t &t, bool &mark) 00183 { 00184 // try reading a sample 00185 uint16_t sample; 00186 if (rawbuf.read(sample)) 00187 { 00188 // it's a mark if the low bit is set 00189 mark = sample & 0x0001; 00190 00191 // remove the low bit, as it's not actually part of the time value, 00192 // and multiply by 2 to get from the 2us units in the buffer to 00193 // microseconds 00194 t = (sample & ~0x0001) << 1; 00195 00196 // process it through the protocol handlers 00197 processProtocols(t, mark); 00198 00199 // got a sample 00200 return true; 00201 } 00202 00203 // no sample 00204 return false; 00205 } 00206 00207 // Process a pulse through the protocol handlers 00208 void IRReceiver::processProtocols(uint32_t t, bool mark) 00209 { 00210 // generate a call to each sender in the RX list 00211 #define IR_PROTOCOL_RX(cls) IRProtocol::protocols->s_##cls.rxPulse(this, t, mark); 00212 #include "IRProtocolList.h" 00213 }
Generated on Wed Jul 13 2022 03:30:10 by 1.7.2