Provides a simple way to generate complex square wave signals on any available pin. In addition the SignalGenerator can generate a carrier wave which is useful when generating IR signals to control electronic devices like a TV etc. The signal generation can be carried out either synchronously or asynchronously. In the case of synchronous signal generation all interrupts can optionally be disabled to improve timing accuracy.
Diff: SignalGenerator.cpp
- Revision:
- 3:f30dcc6e8e70
- Parent:
- 2:b2a449bd787f
- Child:
- 4:64d2d834341b
--- a/SignalGenerator.cpp Fri Sep 12 05:20:08 2014 +0000 +++ b/SignalGenerator.cpp Sat Sep 13 21:40:16 2014 +0000 @@ -4,56 +4,9 @@ #include "mbed.h" #include "SignalGenerator.h" -int32_t SignalGenerator::_latency = -1; - SignalGenerator::SignalGenerator(PinName pin) : _pin(pin) { - if (_latency == -1) - { - Timer t; - - t.start(); - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - _pin = 0; - t.stop(); - int pinLatency = (t.read_us() + 0.5) / 10; - - t.reset(); - t.start(); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - wait_us(100); - t.stop(); - int waitLatency = (t.read_us() + 0.5) / 1000; - - t.reset(); - t.start(); - for (int i = 0; i < 20; i += 2) - { - wait_us(100); - } - t.stop(); - - int loopLatency = ((t.read_us() - (1000 + (10 * waitLatency))) + 0.5) / 10; - - _latency = pinLatency + waitLatency + loopLatency; - } + } void SignalGenerator::set(bool pinState) @@ -68,69 +21,81 @@ uint32_t lastStateHoldTime, int32_t carrierFrequency) { - uint32_t carrierHalfPeriod = 0; - if (timingBuffer == NULL || bufferCount == 0) { return; } + uint16_t lastTiming = bufferCount - 1; + + Timer transitionTimer; if (carrierFrequency > 0) - { - carrierHalfPeriod = (uint32_t)(500000 / carrierFrequency); + { + int timingIndex = 0; + bool pinState = initialState; + bool carrierState = true; + uint32_t carrierHalfPeriod = (500000 / carrierFrequency); + uint32_t compare = timingBuffer[timingIndex++]; + uint32_t carrierCompare = carrierHalfPeriod; - bool state = initialState; - for(uint16_t i = 0; i < bufferCount; i++) - { - int c = (int)(timingBuffer[i] / (carrierHalfPeriod + _latency)); - if (!state) - { - wait_us(timingBuffer[i]); + transitionTimer.start(); + while(true) + { + bool stateChange = false; + if (transitionTimer.read_us() >= compare) + { + pinState = !pinState; + stateChange = true; + if (timingIndex == lastTiming) break; + compare += timingBuffer[timingIndex++]; } - else + + if (transitionTimer.read_us() >= carrierCompare) { - for(int j = 0; j < c; j += 2) - { - _pin = 1; - wait_us(carrierHalfPeriod); - _pin = 0; - wait_us(carrierHalfPeriod); - } + carrierState = !carrierState; + carrierCompare += carrierHalfPeriod; + stateChange = true; } - state = !state; + + if (stateChange) _pin = pinState & carrierState ? 1 : 0; } - + if (lastStateHoldTime > 0) { - int c = (int)((double)lastStateHoldTime / carrierHalfPeriod); - if (!state) - { - wait_us(lastStateHoldTime); - } - else + compare += lastStateHoldTime; + while (transitionTimer.read_us() < compare) { - for(int j = 0; j < c; j += 2) + if (transitionTimer.read_us() >= carrierCompare) { - _pin = 1; - wait_us(carrierHalfPeriod); - _pin = 0; - wait_us(carrierHalfPeriod); - } + carrierState = !carrierState; + carrierCompare += carrierHalfPeriod; + _pin = pinState & carrierState ? 1 : 0; + } } - } + } } else - { - set(initialState); - for(uint16_t i = 0; i < bufferCount; ++i) - { - wait_us(timingBuffer[i]); - _pin = !_pin; + { + int timingIndex = 0; + uint32_t compare = timingBuffer[timingIndex++]; + transitionTimer.start(); + set(initialState); + while(true) + { + if (transitionTimer.read_us() >= compare) + { + _pin = !_pin; + if (timingIndex == lastTiming) break; + compare += timingBuffer[timingIndex++]; + } } - if (lastStateHoldTime > 0) { - wait_us(lastStateHoldTime); - } + compare += lastStateHoldTime; + while (transitionTimer.read_us() < compare) + { + ; + } + } } } \ No newline at end of file