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.

Committer:
taylorza
Date:
Sat Sep 13 21:40:16 2014 +0000
Revision:
3:f30dcc6e8e70
Parent:
2:b2a449bd787f
Child:
4:64d2d834341b
Improved timing accuracy and consistency. Removed need to explicitly calculate operation latencies.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
taylorza 1:4a1bcc41c473 1 ///////////////////////////////////////////////////////////////////////////////
taylorza 1:4a1bcc41c473 2 // Signal Generator
taylorza 1:4a1bcc41c473 3 // Author: Chris Taylor (taylorza)
taylorza 0:b7c65c0d82d3 4 #include "mbed.h"
taylorza 0:b7c65c0d82d3 5 #include "SignalGenerator.h"
taylorza 0:b7c65c0d82d3 6
taylorza 0:b7c65c0d82d3 7 SignalGenerator::SignalGenerator(PinName pin) : _pin(pin)
taylorza 0:b7c65c0d82d3 8 {
taylorza 3:f30dcc6e8e70 9
taylorza 0:b7c65c0d82d3 10 }
taylorza 0:b7c65c0d82d3 11
taylorza 0:b7c65c0d82d3 12 void SignalGenerator::set(bool pinState)
taylorza 0:b7c65c0d82d3 13 {
taylorza 0:b7c65c0d82d3 14 _pin = pinState ? 1 : 0;
taylorza 0:b7c65c0d82d3 15 }
taylorza 0:b7c65c0d82d3 16
taylorza 1:4a1bcc41c473 17 void SignalGenerator::set(
taylorza 1:4a1bcc41c473 18 bool initialState,
taylorza 1:4a1bcc41c473 19 uint32_t timingBuffer[],
taylorza 1:4a1bcc41c473 20 uint16_t bufferCount,
taylorza 1:4a1bcc41c473 21 uint32_t lastStateHoldTime,
taylorza 2:b2a449bd787f 22 int32_t carrierFrequency)
taylorza 0:b7c65c0d82d3 23 {
taylorza 2:b2a449bd787f 24 if (timingBuffer == NULL || bufferCount == 0)
taylorza 2:b2a449bd787f 25 {
taylorza 2:b2a449bd787f 26 return;
taylorza 2:b2a449bd787f 27 }
taylorza 0:b7c65c0d82d3 28
taylorza 3:f30dcc6e8e70 29 uint16_t lastTiming = bufferCount - 1;
taylorza 3:f30dcc6e8e70 30
taylorza 3:f30dcc6e8e70 31 Timer transitionTimer;
taylorza 0:b7c65c0d82d3 32 if (carrierFrequency > 0)
taylorza 3:f30dcc6e8e70 33 {
taylorza 3:f30dcc6e8e70 34 int timingIndex = 0;
taylorza 3:f30dcc6e8e70 35 bool pinState = initialState;
taylorza 3:f30dcc6e8e70 36 bool carrierState = true;
taylorza 3:f30dcc6e8e70 37 uint32_t carrierHalfPeriod = (500000 / carrierFrequency);
taylorza 3:f30dcc6e8e70 38 uint32_t compare = timingBuffer[timingIndex++];
taylorza 3:f30dcc6e8e70 39 uint32_t carrierCompare = carrierHalfPeriod;
taylorza 0:b7c65c0d82d3 40
taylorza 3:f30dcc6e8e70 41 transitionTimer.start();
taylorza 3:f30dcc6e8e70 42 while(true)
taylorza 3:f30dcc6e8e70 43 {
taylorza 3:f30dcc6e8e70 44 bool stateChange = false;
taylorza 3:f30dcc6e8e70 45 if (transitionTimer.read_us() >= compare)
taylorza 3:f30dcc6e8e70 46 {
taylorza 3:f30dcc6e8e70 47 pinState = !pinState;
taylorza 3:f30dcc6e8e70 48 stateChange = true;
taylorza 3:f30dcc6e8e70 49 if (timingIndex == lastTiming) break;
taylorza 3:f30dcc6e8e70 50 compare += timingBuffer[timingIndex++];
taylorza 0:b7c65c0d82d3 51 }
taylorza 3:f30dcc6e8e70 52
taylorza 3:f30dcc6e8e70 53 if (transitionTimer.read_us() >= carrierCompare)
taylorza 0:b7c65c0d82d3 54 {
taylorza 3:f30dcc6e8e70 55 carrierState = !carrierState;
taylorza 3:f30dcc6e8e70 56 carrierCompare += carrierHalfPeriod;
taylorza 3:f30dcc6e8e70 57 stateChange = true;
taylorza 0:b7c65c0d82d3 58 }
taylorza 3:f30dcc6e8e70 59
taylorza 3:f30dcc6e8e70 60 if (stateChange) _pin = pinState & carrierState ? 1 : 0;
taylorza 0:b7c65c0d82d3 61 }
taylorza 3:f30dcc6e8e70 62
taylorza 0:b7c65c0d82d3 63 if (lastStateHoldTime > 0)
taylorza 0:b7c65c0d82d3 64 {
taylorza 3:f30dcc6e8e70 65 compare += lastStateHoldTime;
taylorza 3:f30dcc6e8e70 66 while (transitionTimer.read_us() < compare)
taylorza 0:b7c65c0d82d3 67 {
taylorza 3:f30dcc6e8e70 68 if (transitionTimer.read_us() >= carrierCompare)
taylorza 0:b7c65c0d82d3 69 {
taylorza 3:f30dcc6e8e70 70 carrierState = !carrierState;
taylorza 3:f30dcc6e8e70 71 carrierCompare += carrierHalfPeriod;
taylorza 3:f30dcc6e8e70 72 _pin = pinState & carrierState ? 1 : 0;
taylorza 3:f30dcc6e8e70 73 }
taylorza 0:b7c65c0d82d3 74 }
taylorza 3:f30dcc6e8e70 75 }
taylorza 0:b7c65c0d82d3 76 }
taylorza 0:b7c65c0d82d3 77 else
taylorza 3:f30dcc6e8e70 78 {
taylorza 3:f30dcc6e8e70 79 int timingIndex = 0;
taylorza 3:f30dcc6e8e70 80 uint32_t compare = timingBuffer[timingIndex++];
taylorza 3:f30dcc6e8e70 81 transitionTimer.start();
taylorza 3:f30dcc6e8e70 82 set(initialState);
taylorza 3:f30dcc6e8e70 83 while(true)
taylorza 3:f30dcc6e8e70 84 {
taylorza 3:f30dcc6e8e70 85 if (transitionTimer.read_us() >= compare)
taylorza 3:f30dcc6e8e70 86 {
taylorza 3:f30dcc6e8e70 87 _pin = !_pin;
taylorza 3:f30dcc6e8e70 88 if (timingIndex == lastTiming) break;
taylorza 3:f30dcc6e8e70 89 compare += timingBuffer[timingIndex++];
taylorza 3:f30dcc6e8e70 90 }
taylorza 0:b7c65c0d82d3 91 }
taylorza 0:b7c65c0d82d3 92 if (lastStateHoldTime > 0)
taylorza 0:b7c65c0d82d3 93 {
taylorza 3:f30dcc6e8e70 94 compare += lastStateHoldTime;
taylorza 3:f30dcc6e8e70 95 while (transitionTimer.read_us() < compare)
taylorza 3:f30dcc6e8e70 96 {
taylorza 3:f30dcc6e8e70 97 ;
taylorza 3:f30dcc6e8e70 98 }
taylorza 3:f30dcc6e8e70 99 }
taylorza 0:b7c65c0d82d3 100 }
taylorza 2:b2a449bd787f 101 }