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@3:f30dcc6e8e70, 2014-09-13 (annotated)
- 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?
User | Revision | Line number | New 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 | } |