
Signal Generator
Dependencies: IniManager RA8875 Watchdog mbed-rtos mbed
Fork of speaker_demo_Analog by
Revision 5:49dd0c647a40, committed 2017-01-16
- Comitter:
- WiredHome
- Date:
- Mon Jan 16 22:57:59 2017 +0000
- Parent:
- 4:10281ddb673d
- Child:
- 6:1f48212fbaf9
- Commit message:
- Stable commit before any major refactoring
Changed in this revision
--- a/SignalGenDAC.cpp Mon Jan 16 21:05:13 2017 +0000 +++ b/SignalGenDAC.cpp Mon Jan 16 22:57:59 2017 +0000 @@ -3,7 +3,7 @@ DigitalOut led(LED1); -#define PI 3.14159 +#define PI 3.14159 // for the sine-wave /// The linked list structure used to control the DMA transfer /// @@ -28,17 +28,6 @@ SignalGenDAC::SignalGenDAC(PinName _aout, float _minV, float _maxV) : minV(_minV), maxV(_maxV) { aout = new AnalogOut(_aout); -#if 1 - #include "mbed.h" - aout->write(0.25); - wait_ms(25); - aout->write(0.50); - wait_ms(25); - aout->write(0.75); - wait_ms(25); - aout->write(1.00); - wait_ms(25); -#endif } SignalGenDAC::~SignalGenDAC() { @@ -68,9 +57,8 @@ /* Load DMA Channel0 */ LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)DACsignal; LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_DAC->DACR; - LPC_GPDMACH0->DMACCLLI = (uint32_t)&llio; // Free Running - //LPC_GPDMACH0->DMACCLLI = 0; // One-Shot - + LPC_GPDMACH0->DMACCLLI = (uint32_t)&llio; + LPC_GPDMACH0->DMACCControl = numSamples // transfer size (0 - 11) = 64 | (0 << 12) // source burst size (12 - 14) = 1 | (0 << 15) // destination burst size (15 - 17) = 1 @@ -106,13 +94,20 @@ void SignalGenDAC::Stop(void) { printf("Stop()\r\n"); LPC_GPDMACH0->DMACCLLI = 0; + while (LPC_GPDMACH0->DMACCConfig & 1) + wait_ms(1); + aout->write(offset / maxV); isOn = false; led = 0; } -void SignalGenDAC::PrepareWaveform(SG_Mode mode, float frequency, float dutycycle, float voltage, float offset) { +void SignalGenDAC::PrepareWaveform(SG_Mode mode, float _frequency, float _dutycycle, float _voltage, float _offset) { int x, dcCount, firstQtr, lastQtr; + frequency = _frequency; + dutycycle = _dutycycle; + voltage = _voltage; + offset = _offset; float upp = rangelimit(offset + voltage/2, minV, maxV); float mid = rangelimit(offset, minV, maxV); float low = rangelimit(offset - voltage/2, minV, maxV); @@ -186,7 +181,9 @@ DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6); printf("%3d, %5.3f, %d\r\n", x, VoltSignal[x], DACsignal[x]); } - Start(false); + if (!isOn) { + aout->write(offset / maxV); + } } float SignalGenDAC::rangelimit(float value, float min, float max) {
--- a/SignalGenDAC.h Mon Jan 16 21:05:13 2017 +0000 +++ b/SignalGenDAC.h Mon Jan 16 22:57:59 2017 +0000 @@ -17,12 +17,15 @@ public: /// Constructor, which is used to define the hardware + /// + /// The default parameters are based on the mbed LPC1768 micro, which has + /// AnalogOut on p18 and uses a 3.3v supply for the A/D reference. /// /// @param[in] aout is the analog output pin /// @param[in] minV is based on the A/D low reference voltage (default 0.0) - /// @param[in] maxV is based on the A/D high reference voltage (default 3.0) + /// @param[in] maxV is based on the A/D high reference voltage (default 3.3) /// - SignalGenDAC(PinName aout, float minV = 0.0, float maxV = 3.0); + SignalGenDAC(PinName aout = p18, float minV = 0.0, float maxV = 3.3); /// Destructor /// @@ -59,6 +62,10 @@ private: bool isOn; // tracks whether the signal is on or off AnalogOut * aout; + float frequency; // signal parameters + float dutycycle; + float voltage; + float offset; float minV; // Based on the A/D hardware float maxV; // Based on the A/D hardware /// range limit a value.
--- a/SignalGenDisplay.cpp Mon Jan 16 21:05:13 2017 +0000 +++ b/SignalGenDisplay.cpp Mon Jan 16 22:57:59 2017 +0000 @@ -63,45 +63,45 @@ #define BTN_KEYP_Y 53 // Keypad top edge // Rectangular Zones -const rect_t UI_START_STOP = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X + 2 * BTN_W + BTN_S,BTN_KEYP_Y+BTN_H}; -const char * UI_StartLabels[3] = { "Start", "Stop", "Pulse" }; -const char StartStopKeys[] = { 'G', 'O', 'P' }; -const rect_t UI_DATA_ENTRY = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X + 2 * BTN_W + BTN_S,BTN_KEYP_Y+BTN_H}; -const rect_t UI_SCOPE_RECT = {4,5, 290,160}; +static const rect_t UI_START_STOP = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X+2*BTN_W+BTN_S,BTN_KEYP_Y+BTN_H}; +static const char * UI_StartLabels[3] = { "Start", "Stop", "Pulse" }; +static const char StartStopKeys[] = { 'G', 'O', 'P' }; +static const rect_t UI_DATA_ENTRY = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X+2*BTN_W+BTN_S,BTN_KEYP_Y+BTN_H-2}; +static const rect_t UI_SCOPE_RECT = {4,5, 290,160}; -const rect_t UI_WAVE_RECT = {4+SC_LEFT_MARGIN,5+SC_TOP_MARGIN, 290-SC_RIGHT_MARGIN,160-SC_BOT_MARGIN}; +static const rect_t UI_WAVE_RECT = {4+SC_LEFT_MARGIN,5+SC_TOP_MARGIN, 290-SC_RIGHT_MARGIN,160-SC_BOT_MARGIN}; -const rect_t Parameters[] = { +static const rect_t Parameters[] = { {4,170, 60,190}, // 'd'uty cycle {90,170, 186,190}, // 'f'requency {90,200, 186,220}, // 'p'eriod {230,170, 290,190}, // 'v'oltage {230,200, 290,220} // 'o'ffset }; -const int ParameterCount = sizeof(Parameters)/sizeof(Parameters[0]); -const char ParameterKeys[] = { 'd', 'f', 'p', 'v', 'o' }; +static const int ParameterCount = sizeof(Parameters)/sizeof(Parameters[0]); +static const char ParameterKeys[] = { 'd', 'f', 'p', 'v', 'o' }; -const rect_t UI_PROD_RECT = { 298,3, 479,51 }; -const rect_t NavToSettings = { 4,200, 60,220 }; +static const rect_t UI_PROD_RECT = { 298,3, 479,51 }; +static const rect_t NavToSettings = { 4,200, 60,220 }; // Mode Buttons -const rect_t ModeButtons[] = { +static const rect_t ModeButtons[] = { { BTN_MODE_X+0*(BTN_W+BTN_S),BTN_MODE_Y, BTN_MODE_X+0*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H }, { BTN_MODE_X+1*(BTN_W+BTN_S),BTN_MODE_Y, BTN_MODE_X+1*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H }, { BTN_MODE_X+2*(BTN_W+BTN_S),BTN_MODE_Y, BTN_MODE_X+2*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H }, { BTN_MODE_X+3*(BTN_W+BTN_S),BTN_MODE_Y, BTN_MODE_X+3*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H }, { BTN_MODE_X+4*(BTN_W+BTN_S),BTN_MODE_Y, BTN_MODE_X+4*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H }, }; -const int ModeCount = sizeof(ModeButtons)/sizeof(ModeButtons[0]); -SG_Mode UI_ModeList[] = { +static const int ModeCount = sizeof(ModeButtons)/sizeof(ModeButtons[0]); +static const SG_Mode UI_ModeList[] = { SG_SINE, SG_SQUARE, SG_TRIANGLE, SG_SAWTOOTH, SG_USER, }; -const char ModeKeys[] = { 'S','Q','T','W','U' }; -const char *ModeNames[] = { +static const char ModeKeys[] = { 'S','Q','T','W','U' }; +static const char *ModeNames[] = { "Sine", "Square", "Triangle", @@ -109,7 +109,7 @@ "User", }; -const rect_t UI_Keypad[] = { +static const rect_t UI_Keypad[] = { {BTN_KEYP_X+2*(BTN_W+BTN_S),BTN_KEYP_Y+0*(BTN_H+BTN_S), BTN_KEYP_X+2*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+0*(BTN_H+BTN_S)+BTN_H }, // backspace {BTN_KEYP_X+0*(BTN_W+BTN_S),BTN_KEYP_Y+1*(BTN_H+BTN_S), BTN_KEYP_X+0*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+1*(BTN_H+BTN_S)+BTN_H }, {BTN_KEYP_X+1*(BTN_W+BTN_S),BTN_KEYP_Y+1*(BTN_H+BTN_S), BTN_KEYP_X+1*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+1*(BTN_H+BTN_S)+BTN_H }, @@ -127,8 +127,8 @@ {BTN_KEYP_X+1*(BTN_W+BTN_S),BTN_KEYP_Y+5*(BTN_H+BTN_S), BTN_KEYP_X+1*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+5*(BTN_H+BTN_S)+BTN_H }, {BTN_KEYP_X+2*(BTN_W+BTN_S),BTN_KEYP_Y+5*(BTN_H+BTN_S), BTN_KEYP_X+2*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+5*(BTN_H+BTN_S)+BTN_H }, }; -const int KeypadCount = sizeof(UI_Keypad)/sizeof(UI_Keypad[0]); -const char UI_KeyLabels[] = { +static const int KeypadCount = sizeof(UI_Keypad)/sizeof(UI_Keypad[0]); +static const char UI_KeyLabels[] = { '\x1B', '7', '8', '9', '4', '5', '6', @@ -136,7 +136,7 @@ '0', '.', '-', '\x19', '\x18', '\xB6', }; -const char KeyPadKeys[] = { +static const char KeyPadKeys[] = { '\x08', '7', '8', '9', '4', '5', '6', @@ -169,31 +169,31 @@ // | +--------+ | // +---------------------------------------------------------------------------+ -const point_t suncenter = { 450,85 }; -const rect_t sunray[] = { +static const point_t suncenter = { 450,85 }; +static const rect_t sunray[] = { { 450-2, 85-25, 450+2, 85+25 }, { 450-25,85-2, 450+25,85+2 } }; -const rect_t sungraph = { 450-18,120+0, 450+18,265+0 }; -const rect_t inrgraph = { 450-16,120+2, 450+16,265-2 }; +static const rect_t sungraph = { 450-18,120+0, 450+18,265+0 }; +static const rect_t inrgraph = { 450-16,120+2, 450+16,265-2 }; -const rect_t SignalMode = +static const rect_t SignalMode = { 20,50, 20+140,70 }; -const char * SignalModeLabel = "Signal Mode"; +static const char * SignalModeLabel = "Signal Mode"; -const rect_t radio_Cycles[] = { +static const rect_t radio_Cycles[] = { { 40, 80, 40+120,100 }, { 40,110, 40+120,130 } }; -const int radio_CyclesCount = sizeof(radio_Cycles)/sizeof(radio_Cycles[0]); -const char * radio_CyclesLabels[] = { +static const int radio_CyclesCount = sizeof(radio_Cycles)/sizeof(radio_Cycles[0]); +static const char * PulseModeLabels[] = { "Continuous", "One-Shot" }; #define UI_CyclesColor Green #define UI_CyclesBackColor RGB(0,0,0) -// rect_t radio_Cycles[], radio_CyclesCount, char * radio_CyclesLabels[] +// rect_t radio_Cycles[], radio_CyclesCount, char * PulseModeLabels[] #define PI 3.1415 // Handy value @@ -363,9 +363,9 @@ ini.ReadString("Signal", "Offset", buf, sizeof(buf), "1.5"); offset = atof(buf); - ini.ReadString("Signal", "Pulse Mode", buf, sizeof(buf), radio_CyclesLabels[0]); + ini.ReadString("Signal", "Pulse Mode", buf, sizeof(buf), PulseModeLabels[0]); for (int i=0; i<radio_CyclesCount; i++) { - if (strcmp(radio_CyclesLabels[i], buf) == 0) { + if (strcmp(PulseModeLabels[i], buf) == 0) { pulseMode = i; break; } @@ -404,7 +404,7 @@ } } -// rect_t radio_Cycles[], radio_CyclesCount, char * radio_CyclesLabels[] +// rect_t radio_Cycles[], radio_CyclesCount, char * PulseModeLabels[] void SignalGenDisplay::ShowCyclesControl(void) { lcd->fillrect(SignalMode, UI_CyclesBackColor); @@ -417,7 +417,7 @@ lcd->foreground(UI_CyclesColor); lcd->background(UI_CyclesBackColor); lcd->SetTextCursor(radio_Cycles[x].p1.x+1,radio_Cycles[x].p1.y+1); - lcd->printf("%c %s", (pulseMode == x) ? '\x07' : '\x09', radio_CyclesLabels[x]); + lcd->printf("%c %s", (pulseMode == x) ? '\x07' : '\x09', PulseModeLabels[x]); } } @@ -499,7 +499,7 @@ printf(" Duty: %f\r\n", dutycycle); printf(" Volt: %f\r\n", voltage); printf(" Offs: %f\r\n", offset); - printf(" Puls: %d - %s\r\n", pulseMode, radio_CyclesLabels[pulseMode]); + printf(" Puls: %d - %s\r\n", pulseMode, PulseModeLabels[pulseMode]); } SignalGenDisplay::OM_Changes SignalGenDisplay::Poll(char c) { @@ -968,9 +968,10 @@ privDutyCycle = 50; } privDutyCycleX = privDutyCycle/100.0 * 1*w/2; + int cyclesToShow = (pulseMode) ? 1 : 2; switch (mode) { case SG_SINE: - for (int cycle=0; cycle<2; cycle++) { + for (int cycle=0; cycle<cyclesToShow; cycle++) { for (x=0; x<=privDutyCycleX; x++) { v = privOffset + privVoltage/2 * sin(x * 1 * PI / privDutyCycleX); v = rangelimit(v, SG_MIN_V, SG_MAX_V); @@ -986,7 +987,7 @@ } break; case SG_SQUARE: - for (int cycle=0; cycle<2; cycle++) { + for (int cycle=0; cycle<cyclesToShow; cycle++) { loc_t mid = r.p2.y - rangelimit(privOffset, SG_MIN_V, SG_MAX_V) / vRange * h; loc_t upp = r.p2.y - rangelimit(privOffset + privVoltage/2, SG_MIN_V, SG_MAX_V) / vRange * h; loc_t low = r.p2.y - rangelimit(privOffset - privVoltage/2, SG_MIN_V, SG_MAX_V) / vRange * h; @@ -998,7 +999,7 @@ } break; case SG_TRIANGLE: - for (int cycle=0; cycle<2; cycle++) { + for (int cycle=0; cycle<cyclesToShow; cycle++) { for (x=0; x<=privDutyCycleX; x++) { v = privVoltage * (float)x/privDutyCycleX; if (x < privDutyCycleX/2) @@ -1021,7 +1022,7 @@ } break; case SG_SAWTOOTH: - for (int cycle=0; cycle<2; cycle++) { + for (int cycle=0; cycle<cyclesToShow; cycle++) { for (x=0; x<=privDutyCycleX; x++) { v = privVoltage/2 * (float)x/privDutyCycleX - privVoltage/2 + privOffset; y = r.p2.y - rangelimit(v, SG_MIN_V, SG_MAX_V) / vRange * h; @@ -1045,6 +1046,11 @@ lcd->rect(r.p1.x+5*w/8, y0-a/4, r.p1.x+7*w/8, y0+a/4, color); break; } + if (cyclesToShow != 2) { + v = rangelimit(privOffset, SG_MIN_V, SG_MAX_V); + y = r.p2.y - 2 * a * v / vRange; + lcd->line(r.p1.x + w/2, y, r.p1.x+w,y, color); + } } void SignalGenDisplay::ClearScope(void) { @@ -1269,6 +1275,10 @@ Changes &= ~ OM_MODE; ini.WriteString("Signal", "Waveform", ModeNames[mode]); } + if (Changes & OM_PULSE) { + Changes &= ~ OM_PULSE; + ini.WriteString("Signal", "Pulse Mode", PulseModeLabels[pulseMode]); + } if (Changes & OM_FREQ) { Changes &= ~ OM_FREQ; snprintf(buf, sizeof(buf),"%5.3f", frequency);
--- a/SignalGenDisplay.h Mon Jan 16 21:05:13 2017 +0000 +++ b/SignalGenDisplay.h Mon Jan 16 22:57:59 2017 +0000 @@ -177,14 +177,15 @@ /// bitmask value, where zero or more bits are set. /// typedef enum { - OM_NONE = 0, ///< No change in operating mode - OM_MODE = 1, ///< Signal mode changed; Sine, Square, Triangle, Sawtooth, User - OM_FREQ = 2, ///< Change in the frequency - OM_PERI = 4, ///< Change in the period (effectively same as frequency) - OM_DUTY = 8, ///< Change in the duty cycle - OM_VOLT = 16, ///< Change in the peak to peak amplitude - OM_OFFS = 32, ///< Change in the offset voltage - OM_BACKL = 64, ///< Change in the backlight setting + OM_NONE = 0x0000, ///< No change in operating mode + OM_MODE = 0x0001, ///< Signal mode changed; Sine, Square, Triangle, Sawtooth, User + OM_PULSE = 0x0002, ///< Continuous v. Single-shot + OM_FREQ = 0x0004, ///< Change in the frequency + OM_PERI = 0x0008, ///< Change in the period (effectively same as frequency) + OM_DUTY = 0x0010, ///< Change in the duty cycle + OM_VOLT = 0x0020, ///< Change in the peak to peak amplitude + OM_OFFS = 0x0040, ///< Change in the offset voltage + OM_BACKL = 0x0080, ///< Change in the backlight setting } OM_Changes; /// Poll the Signal Generator UI for changes in operation. @@ -280,4 +281,4 @@ }; -#endif // SIGNALGENDISPLAY_H \ No newline at end of file +#endif // SIGNALGENVIEW_H \ No newline at end of file
--- a/main.cpp Mon Jan 16 21:05:13 2017 +0000 +++ b/main.cpp Mon Jan 16 22:57:59 2017 +0000 @@ -12,8 +12,7 @@ RawSerial pc(USBTX, USBRX); LocalFileSystem local("local"); -//AnalogOut aout(p18); -SignalGenDAC g_signal(p18); +SignalGenDAC g_signal; // defaults to LPC1768 mbed module (p18 and 3.3v) SignalGenDisplay ui(&lcd, &g_signal); Watchdog wd;