Signal Generator
Dependencies: IniManager RA8875 Watchdog mbed-rtos mbed
Fork of speaker_demo_Analog by
SignalGenDAC.cpp
- Committer:
- WiredHome
- Date:
- 2017-01-15
- Revision:
- 2:8f71b71fce1b
- Child:
- 3:d22f3e52d06a
File content as of revision 2:8f71b71fce1b:
#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; }