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:
Fri Sep 12 05:20:08 2014 +0000
Revision:
2:b2a449bd787f
Parent:
1:4a1bcc41c473
Child:
3:f30dcc6e8e70
Improved accuracy of the carrier wave

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 2:b2a449bd787f 7 int32_t SignalGenerator::_latency = -1;
taylorza 2:b2a449bd787f 8
taylorza 0:b7c65c0d82d3 9 SignalGenerator::SignalGenerator(PinName pin) : _pin(pin)
taylorza 0:b7c65c0d82d3 10 {
taylorza 2:b2a449bd787f 11 if (_latency == -1)
taylorza 2:b2a449bd787f 12 {
taylorza 2:b2a449bd787f 13 Timer t;
taylorza 2:b2a449bd787f 14
taylorza 2:b2a449bd787f 15 t.start();
taylorza 2:b2a449bd787f 16 _pin = 0;
taylorza 2:b2a449bd787f 17 _pin = 0;
taylorza 2:b2a449bd787f 18 _pin = 0;
taylorza 2:b2a449bd787f 19 _pin = 0;
taylorza 2:b2a449bd787f 20 _pin = 0;
taylorza 2:b2a449bd787f 21 _pin = 0;
taylorza 2:b2a449bd787f 22 _pin = 0;
taylorza 2:b2a449bd787f 23 _pin = 0;
taylorza 2:b2a449bd787f 24 _pin = 0;
taylorza 2:b2a449bd787f 25 _pin = 0;
taylorza 2:b2a449bd787f 26 t.stop();
taylorza 2:b2a449bd787f 27 int pinLatency = (t.read_us() + 0.5) / 10;
taylorza 2:b2a449bd787f 28
taylorza 2:b2a449bd787f 29 t.reset();
taylorza 2:b2a449bd787f 30 t.start();
taylorza 2:b2a449bd787f 31 wait_us(100);
taylorza 2:b2a449bd787f 32 wait_us(100);
taylorza 2:b2a449bd787f 33 wait_us(100);
taylorza 2:b2a449bd787f 34 wait_us(100);
taylorza 2:b2a449bd787f 35 wait_us(100);
taylorza 2:b2a449bd787f 36 wait_us(100);
taylorza 2:b2a449bd787f 37 wait_us(100);
taylorza 2:b2a449bd787f 38 wait_us(100);
taylorza 2:b2a449bd787f 39 wait_us(100);
taylorza 2:b2a449bd787f 40 wait_us(100);
taylorza 2:b2a449bd787f 41 wait_us(100);
taylorza 2:b2a449bd787f 42 t.stop();
taylorza 2:b2a449bd787f 43 int waitLatency = (t.read_us() + 0.5) / 1000;
taylorza 2:b2a449bd787f 44
taylorza 2:b2a449bd787f 45 t.reset();
taylorza 2:b2a449bd787f 46 t.start();
taylorza 2:b2a449bd787f 47 for (int i = 0; i < 20; i += 2)
taylorza 2:b2a449bd787f 48 {
taylorza 2:b2a449bd787f 49 wait_us(100);
taylorza 2:b2a449bd787f 50 }
taylorza 2:b2a449bd787f 51 t.stop();
taylorza 2:b2a449bd787f 52
taylorza 2:b2a449bd787f 53 int loopLatency = ((t.read_us() - (1000 + (10 * waitLatency))) + 0.5) / 10;
taylorza 2:b2a449bd787f 54
taylorza 2:b2a449bd787f 55 _latency = pinLatency + waitLatency + loopLatency;
taylorza 2:b2a449bd787f 56 }
taylorza 0:b7c65c0d82d3 57 }
taylorza 0:b7c65c0d82d3 58
taylorza 0:b7c65c0d82d3 59 void SignalGenerator::set(bool pinState)
taylorza 0:b7c65c0d82d3 60 {
taylorza 0:b7c65c0d82d3 61 _pin = pinState ? 1 : 0;
taylorza 0:b7c65c0d82d3 62 }
taylorza 0:b7c65c0d82d3 63
taylorza 1:4a1bcc41c473 64 void SignalGenerator::set(
taylorza 1:4a1bcc41c473 65 bool initialState,
taylorza 1:4a1bcc41c473 66 uint32_t timingBuffer[],
taylorza 1:4a1bcc41c473 67 uint16_t bufferCount,
taylorza 1:4a1bcc41c473 68 uint32_t lastStateHoldTime,
taylorza 2:b2a449bd787f 69 int32_t carrierFrequency)
taylorza 0:b7c65c0d82d3 70 {
taylorza 0:b7c65c0d82d3 71 uint32_t carrierHalfPeriod = 0;
taylorza 2:b2a449bd787f 72
taylorza 2:b2a449bd787f 73 if (timingBuffer == NULL || bufferCount == 0)
taylorza 2:b2a449bd787f 74 {
taylorza 2:b2a449bd787f 75 return;
taylorza 2:b2a449bd787f 76 }
taylorza 0:b7c65c0d82d3 77
taylorza 0:b7c65c0d82d3 78 if (carrierFrequency > 0)
taylorza 0:b7c65c0d82d3 79 {
taylorza 0:b7c65c0d82d3 80 carrierHalfPeriod = (uint32_t)(500000 / carrierFrequency);
taylorza 0:b7c65c0d82d3 81
taylorza 0:b7c65c0d82d3 82 bool state = initialState;
taylorza 0:b7c65c0d82d3 83 for(uint16_t i = 0; i < bufferCount; i++)
taylorza 0:b7c65c0d82d3 84 {
taylorza 2:b2a449bd787f 85 int c = (int)(timingBuffer[i] / (carrierHalfPeriod + _latency));
taylorza 0:b7c65c0d82d3 86 if (!state)
taylorza 0:b7c65c0d82d3 87 {
taylorza 0:b7c65c0d82d3 88 wait_us(timingBuffer[i]);
taylorza 0:b7c65c0d82d3 89 }
taylorza 0:b7c65c0d82d3 90 else
taylorza 0:b7c65c0d82d3 91 {
taylorza 0:b7c65c0d82d3 92 for(int j = 0; j < c; j += 2)
taylorza 0:b7c65c0d82d3 93 {
taylorza 0:b7c65c0d82d3 94 _pin = 1;
taylorza 0:b7c65c0d82d3 95 wait_us(carrierHalfPeriod);
taylorza 0:b7c65c0d82d3 96 _pin = 0;
taylorza 0:b7c65c0d82d3 97 wait_us(carrierHalfPeriod);
taylorza 0:b7c65c0d82d3 98 }
taylorza 0:b7c65c0d82d3 99 }
taylorza 0:b7c65c0d82d3 100 state = !state;
taylorza 0:b7c65c0d82d3 101 }
taylorza 0:b7c65c0d82d3 102
taylorza 0:b7c65c0d82d3 103 if (lastStateHoldTime > 0)
taylorza 0:b7c65c0d82d3 104 {
taylorza 0:b7c65c0d82d3 105 int c = (int)((double)lastStateHoldTime / carrierHalfPeriod);
taylorza 0:b7c65c0d82d3 106 if (!state)
taylorza 0:b7c65c0d82d3 107 {
taylorza 0:b7c65c0d82d3 108 wait_us(lastStateHoldTime);
taylorza 0:b7c65c0d82d3 109 }
taylorza 0:b7c65c0d82d3 110 else
taylorza 0:b7c65c0d82d3 111 {
taylorza 0:b7c65c0d82d3 112 for(int j = 0; j < c; j += 2)
taylorza 0:b7c65c0d82d3 113 {
taylorza 0:b7c65c0d82d3 114 _pin = 1;
taylorza 0:b7c65c0d82d3 115 wait_us(carrierHalfPeriod);
taylorza 0:b7c65c0d82d3 116 _pin = 0;
taylorza 0:b7c65c0d82d3 117 wait_us(carrierHalfPeriod);
taylorza 0:b7c65c0d82d3 118 }
taylorza 0:b7c65c0d82d3 119 }
taylorza 0:b7c65c0d82d3 120 }
taylorza 0:b7c65c0d82d3 121 }
taylorza 0:b7c65c0d82d3 122 else
taylorza 0:b7c65c0d82d3 123 {
taylorza 0:b7c65c0d82d3 124 set(initialState);
taylorza 0:b7c65c0d82d3 125 for(uint16_t i = 0; i < bufferCount; ++i)
taylorza 0:b7c65c0d82d3 126 {
taylorza 0:b7c65c0d82d3 127 wait_us(timingBuffer[i]);
taylorza 0:b7c65c0d82d3 128 _pin = !_pin;
taylorza 0:b7c65c0d82d3 129 }
taylorza 0:b7c65c0d82d3 130
taylorza 0:b7c65c0d82d3 131 if (lastStateHoldTime > 0)
taylorza 0:b7c65c0d82d3 132 {
taylorza 0:b7c65c0d82d3 133 wait_us(lastStateHoldTime);
taylorza 0:b7c65c0d82d3 134 }
taylorza 0:b7c65c0d82d3 135 }
taylorza 2:b2a449bd787f 136 }