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.
SignalGenerator.cpp
- Committer:
- taylorza
- Date:
- 2014-09-12
- Revision:
- 2:b2a449bd787f
- Parent:
- 1:4a1bcc41c473
- Child:
- 3:f30dcc6e8e70
File content as of revision 2:b2a449bd787f:
/////////////////////////////////////////////////////////////////////////////// // Signal Generator // Author: Chris Taylor (taylorza) #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) { _pin = pinState ? 1 : 0; } void SignalGenerator::set( bool initialState, uint32_t timingBuffer[], uint16_t bufferCount, uint32_t lastStateHoldTime, int32_t carrierFrequency) { uint32_t carrierHalfPeriod = 0; if (timingBuffer == NULL || bufferCount == 0) { return; } if (carrierFrequency > 0) { carrierHalfPeriod = (uint32_t)(500000 / carrierFrequency); bool state = initialState; for(uint16_t i = 0; i < bufferCount; i++) { int c = (int)(timingBuffer[i] / (carrierHalfPeriod + _latency)); if (!state) { wait_us(timingBuffer[i]); } else { for(int j = 0; j < c; j += 2) { _pin = 1; wait_us(carrierHalfPeriod); _pin = 0; wait_us(carrierHalfPeriod); } } state = !state; } if (lastStateHoldTime > 0) { int c = (int)((double)lastStateHoldTime / carrierHalfPeriod); if (!state) { wait_us(lastStateHoldTime); } else { for(int j = 0; j < c; j += 2) { _pin = 1; wait_us(carrierHalfPeriod); _pin = 0; wait_us(carrierHalfPeriod); } } } } else { set(initialState); for(uint16_t i = 0; i < bufferCount; ++i) { wait_us(timingBuffer[i]); _pin = !_pin; } if (lastStateHoldTime > 0) { wait_us(lastStateHoldTime); } } }