Signal Generator
Dependencies: IniManager RA8875 Watchdog mbed-rtos mbed
Fork of speaker_demo_Analog by
Diff: SignalGenDAC.cpp
- Revision:
- 2:8f71b71fce1b
- Child:
- 3:d22f3e52d06a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SignalGenDAC.cpp Sun Jan 15 03:11:22 2017 +0000 @@ -0,0 +1,118 @@ + +#include "SignalGenDAC.h" + +#define PI 3.14159 + +/// The linked list structure used to control the DMA transfer +/// +typedef struct { + uint32_t source; /// start of source area + uint32_t destination;/// start of destination area + uint32_t next; /// address of next strLLI in chain + uint32_t control; /// DMACCxControl register +} LinkListItem_t; + +/// The signal memory, which is DMA sent to the DAC to play the waveform +/// +float /*signed long*/ signal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0"))); + +/// The linked list item record, used by the DMA engine to decide how to play +/// +LinkListItem_t llio __attribute__ ((section("AHBSRAM0"))); + + +SignalGenDAC::SignalGenDAC(PinName _aout, float _minV, float _maxV) : + minV(_minV), maxV(_maxV) { + aout = new AnalogOut(_aout); +} + +SignalGenDAC::~SignalGenDAC() { +} + +void SignalGenDAC::Start(bool oneShot) { +} + +void SignalGenDAC::Stop(void) { +} + + +void SignalGenDAC::PrepareWaveform(SG_Mode mode, float frequency, float dutycycle, float voltage, float offset) { + int x, dcCount, firstQtr, lastQtr; + float upp = rangelimit(offset + voltage/2, minV, maxV); + float mid = rangelimit(offset, minV, maxV); + float low = rangelimit(offset - voltage/2, minV, maxV); + float v; + int numSamples = 32; // Ideally, compute this based on the frequency for good resolution + dcCount = dutycycle/100.0 * numSamples; + firstQtr = dcCount / 2; + lastQtr = dcCount + (numSamples - dcCount)/2; + + // Set the timebased based on the frequency + if (isOn) { + // stop the signal during the change + isOn = false; + } + switch (mode) { + case SG_SINE: + for (x=0; x<numSamples; x++) { + if (x < dcCount) { + v = offset + voltage/2 * sin(x * 1 * PI / dcCount); + v = rangelimit(v, minV, maxV); + } else { + v = offset - voltage/2 * sin((x - dcCount) * 1 * PI / (numSamples-dcCount)); + v = rangelimit(v, minV, maxV); + } + signal[x] = v; + } + break; + case SG_SQUARE: + for (x=0; x<numSamples; x++) { + if (x < dcCount) { + v = rangelimit(offset + voltage/2, minV, maxV); + } else { + v = rangelimit(offset - voltage/2, minV, maxV); + } + signal[x] = v; + } + break; + case SG_TRIANGLE: + for (x=0; x<numSamples; x++) { + if (x < firstQtr) { + v = (float)x/(firstQtr) * mid + mid; + } else if (x < dcCount) { + v = upp - (float)(x-firstQtr)/(dcCount - firstQtr) * mid; + } else if (x < lastQtr) { + v = mid - (float)(x-dcCount)/(lastQtr - dcCount) * mid; + } else { + v = (float)(x-lastQtr)/(numSamples - lastQtr) * mid; + } + signal[x] = v; + } + break; + case SG_SAWTOOTH: + for (x=0; x<numSamples; x++) { + if (x < dcCount) { + v = (float)x/dcCount * (upp - low)/2 + low; + } else { + v = (float)(x - dcCount)/(numSamples - dcCount) * (upp - low)/2 + (upp - low)/2; + } + signal[x] = v; + } + break; + case SG_USER: + break; + } + for (x=0; x<numSamples; x++) { + printf("%3d, %5.3f\r\n", x, signal[x]); + } +} + +float SignalGenDAC::rangelimit(float value, float min, float max) { + if (value < min) + return min; + else if (value > max) + return max; + else + return value; +} +