Waveform generator

Dependencies:   4DGL-uLCD-SE AFG_project PinDetect RPG mbed

Revision:
0:7e122b3c7928
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Dec 08 05:06:29 2022 +0000
@@ -0,0 +1,447 @@
+#include "mbed.h"
+#include "PinDetect.h"
+#include "uLCD_4DGL.h"
+#include "SongPlayer.h"
+#include "RPG.h"
+#include "MODDMA.h"
+#include "SignalGenDAC.h"
+#include "SignalGenDefs.h"
+#include <cstdlib>
+#include <string.h>
+
+//TO DO:
+//Serial Code (Generate Waveform from GUI)
+
+PinDetect pb_w(p5);
+PinDetect pb_v(p6);
+PinDetect pb_k(p7);
+InterruptIn rpg_a(p14,PullUp);
+InterruptIn rpg_b(p15,PullUp);
+PinDetect pb_rpg(p16);
+PwmOut red(p21); // R
+PwmOut blue(p22); // G
+PwmOut green(p23); // B
+uLCD_4DGL uLCD(p28,p27,p30);
+SongPlayer mySpeaker(p26);
+RPG rpg(p14, p15, p16);
+SignalGenDAC signal;
+Serial pc(USBTX, USBRX);
+
+float note[18]= {1568.0,1396.9,1244.5, 0.0};
+float duration[18]= {0.48,0.24,0.72, 0.0};
+volatile int waveform = 0;
+volatile int values = 1;
+volatile bool khz = true;
+volatile bool generated = false;
+volatile bool prepared = false; 
+volatile int places = 1;
+float scaling[6] = {0.001, 0.01, 0.1, 1, 10, 100};
+volatile float amplitude = 5;
+volatile float offset = 0;
+volatile float frequency = 10;
+volatile int duty_cycle = 50;
+volatile int direction = 0;
+volatile int value_count = 0;
+
+/*
+*** WAVEFORMS ***
+0: dc_offset (offset)
+1: sine (amplitude, offset, frequency)
+2: square (amplitude, offset, frequency)
+3: triangle (amplitude, offset, frequency)
+4: ramp (amplitude, offset, frequency)
+5: pulse (amplitude, offset, frequency, duty_cycle)
+
+*** VALUES ***
+0: amplitude (Default: 5, Resolution: 0.01, Range: -5 to 5)
+1: offset (Default: 0, Resolution: 0.01, Range: -5 to 5)
+2: frequency (Default: 10KHz, Resolution: 1, Range(Hz): 10 to 999, Range(KHz: 1 to 20)
+3: duty_cycle (Default: 50, Resolution: 1, Range: 0 to 100)
+
+*** UNITS ***
+false: Hz
+true: KHz
+
+*** PLACES ***
+0: Thousandths (frequency(KHz))
+1: Hundredths (amplitude, offset, frequency(KHz))
+2: Tenths (amplitude, offset, frequency(KHz))
+3: Ones (amplitude, offset, frequency(KHz), frequency(Hz), duty cycle)
+4: Tens (frequency(KHz), frequency(Hz), duty cycle)
+5: Hundreds (frequency(Hz))
+*/
+
+float map(float x, float in_min, float in_max, float out_min, float out_max) {
+    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+
+void updateLCD(void) {
+    value_count = 0;
+    uLCD.cls();
+    // Printing Offset
+    uLCD.locate(1,1);
+    if (values == 1) {
+        uLCD.color(GREEN);
+    } else {
+        uLCD.color(BLUE);
+    }
+    uLCD.printf("Offset: %3.2f", offset);
+    if (waveform != 0) {
+        // Printing Amplitude
+        uLCD.locate(1,0); 
+        if (values == 0) {
+            uLCD.color(GREEN);
+        } else {
+            uLCD.color(BLUE);
+        }
+        uLCD.printf("Amplitude: %3.2f", amplitude);
+        // Printing Frequency
+        uLCD.locate(1,2); 
+        if (values == 2) {
+            uLCD.color(GREEN);
+        } else {
+            uLCD.color(BLUE);
+        }
+        if (khz) {
+            uLCD.printf("Freq(KHz): %3.3f", frequency);
+        } else {
+            uLCD.printf("Freq(Hz): %3.3f", frequency);
+        }
+    }
+    if (waveform == 5) {
+        // Printing Duty Cycle
+        uLCD.locate(1,3);
+        if (values == 3) {
+            uLCD.color(GREEN);
+        } else {
+            uLCD.color(BLUE);
+        }
+        uLCD.printf("Duty Cycle: %3.0d", duty_cycle);
+    }
+    //Printing Places
+    uLCD.locate(1,5);
+    uLCD.color(BLUE);
+    uLCD.printf("Place: %3.3f", scaling[places]);
+    //Printing Waveform
+    uLCD.locate(1,6); 
+    uLCD.color(BLUE);
+    uLCD.printf("Waveform:");
+    uLCD.locate(1,7); 
+    uLCD.color(BLUE);
+    switch (waveform) {
+        case 0:
+            uLCD.printf("DC Offset\n");
+            break;
+        case 1:
+            uLCD.printf("Sine\n");
+            break;
+        case 2:
+            uLCD.printf("Square\n");
+            break;
+        case 3:
+            uLCD.printf("Triangle\n");
+            break;
+        case 4:
+            uLCD.printf("Ramp\n");
+            break;
+        case 5:
+            uLCD.printf("Pulse\n");
+            break;
+        default:
+            break;
+    }
+}
+
+void updateValue(void) {
+    float scale = scaling[places];
+    switch (values) {
+        case 0: // amplitude
+            amplitude += value_count * scale;
+            if (amplitude > 5.0) {
+                amplitude = 5.0;
+            } else if (amplitude < -5.0) {
+                amplitude = -5.0;
+            }
+            uLCD.locate(1,0); 
+            uLCD.color(GREEN);
+            uLCD.printf("Amplitude: %3.2f", amplitude);
+            break;
+        case 1: // offset
+            offset += value_count * scale;
+            if (offset > 5.0) {
+                offset = 5.0;
+            } else if (offset < -5.0) {
+                offset = -5.0;
+            }
+            uLCD.locate(1,1); 
+            uLCD.color(GREEN);
+            uLCD.printf("Offset: %3.2f", offset);
+            break;
+        case 2: // frequency
+            frequency += value_count * scale;
+            if (frequency > 999 && !khz) {
+                frequency = 999;
+            } else if (frequency < 10 && !khz) {
+                frequency = 10;
+            } else if (frequency > 20 && khz) {
+                frequency = 20;
+            } else if (frequency < 0 && khz) {
+                frequency = 0;
+            }
+            uLCD.locate(1,2); 
+            uLCD.color(GREEN);
+            if (khz) {
+                uLCD.printf("Freq(KHz): %3.3f", frequency);
+            } else {
+                uLCD.printf("Freq(Hz): %3.3f", frequency);
+            }
+            break;
+        case 3: // duty cycle
+            duty_cycle += value_count * scale;
+            if (duty_cycle > 100) {
+                duty_cycle = 100;
+            } else if (duty_cycle < 0) {
+                duty_cycle = 0;
+            }
+            uLCD.locate(1,3);
+            uLCD.color(GREEN);
+            uLCD.printf("Duty Cycle: %3.0d", duty_cycle);
+            break;
+        default:
+            break;
+    }
+    value_count = 0;
+}
+
+void changeWaveform(void) {
+    if (waveform < 5) {
+        waveform++;
+    } else {
+        waveform = 0;
+    }
+    if (waveform == 0) {
+        values = 1;
+        places = 1;
+    }
+    updateLCD();
+}
+
+void changeValues(void) {
+    switch (waveform) {
+        case 0: // dc_offset
+            break;
+        case 5: // pulse
+            if (values < 3) {
+                values++;
+            } else {
+                values = 0;
+            }
+            break;
+        default:
+            if (values < 2) {
+                values++;
+            } else {
+                values = 0;
+            }
+            break;
+    }
+    switch (values) {
+        case 0: // amplitude
+            places = 1;
+            break;
+        case 1: // offset
+            places = 1;
+            break;
+        case 2: // frequency
+            if (!khz) {
+                places = 3;
+            } else {
+                places = 0;
+            }
+            break;
+        case 3: // duty cycle
+            places = 3;
+            break;
+        default:
+            break;
+    }    
+    updateLCD();
+}
+
+void changePlaces(void) {
+    switch (values) {
+        case 0: // amplitude
+            if (places < 3) {
+                places++;
+            } else {
+                places = 1;
+            }
+            break;
+        case 1: // offset
+            if (places < 3) {
+                places++;
+            } else {
+                places = 1;
+            }
+            break;
+        case 2: // frequency
+            if (!khz && places < 5) {
+                places++;
+            } else if (!khz) {
+                khz = true;
+                places = 0;
+                frequency = 0;
+            } else if (khz && places < 4) {
+                places++;
+            } else if (khz) {
+                khz = false;
+                places = 3;
+                frequency = 0;
+            }
+            break;
+        case 3: // duty cycle
+            if (places < 4) {
+                places++;
+            } else {
+                places = 3;
+            }
+            break;
+        default:
+            break;
+    }
+    updateLCD();
+}
+
+void adjustValues(void) {
+    value_count += rpg.dir();
+}
+
+void generate(void)
+{
+    if (!generated && !prepared) {
+        uLCD.cls();
+        uLCD.locate(1,0);
+        uLCD.color(BLUE);
+        uLCD.printf("Waveform is being prepared");
+        float adjusted_frequency = frequency;
+        if (khz) {
+            adjusted_frequency *= 1000.0;
+        }
+        switch (waveform) {
+            case 0: // dc_offset
+                signal.PrepareWaveform(SG_SQUARE, 10000, 100, map(offset, -5, 5, 0, 3.3), 0);
+                break;
+            case 1: // sine
+                signal.PrepareWaveform(SG_SINE, adjusted_frequency, 50, map(amplitude, -5, 5, 0, 3.3), map(offset, -5, 5, 0, 3.3));
+                break;
+            case 2: // square
+                signal.PrepareWaveform(SG_SQUARE, adjusted_frequency, 50, map(amplitude, -5, 5, 0, 3.3), map(offset, -5, 5, 0, 3.3));
+                break;
+            case 3: // triangle
+                signal.PrepareWaveform(SG_TRIANGLE, adjusted_frequency, 50, map(amplitude, -5, 5, 0, 3.3), map(offset, -5, 5, 0, 3.3));
+                break;
+            case 4: // ramp
+                signal.PrepareWaveform(SG_SAWTOOTH, adjusted_frequency, 50, map(amplitude, -5, 5, 0, 3.3), map(offset, -5, 5, 0, 3.3));
+                break;
+            case 5: // pulse
+                signal.PrepareWaveform(SG_SQUARE, adjusted_frequency, duty_cycle, map(amplitude, -5, 5, 0, 3.3), map(offset, -5, 5, 0, 3.3));
+                break;
+            default:
+                break;
+        }
+        wait(1.0);
+        mySpeaker.PlaySong(note,duration);
+        red = 1.0;
+        green = 0.0;
+        blue = 1.0;
+        prepared = true;
+    } else if (!generated) {
+        uLCD.cls();
+        uLCD.locate(1,0);
+        uLCD.color(BLUE);
+        uLCD.printf("Waveform is being generated");
+        signal.Start();
+        red = 1.0;
+        green = 1.0;
+        blue = 0.0;
+        generated = true;
+    } else {
+        signal.Stop();
+        red = 0.0;
+        green = 1.0;
+        blue = 1.0;
+        updateLCD();
+        prepared = false;
+        generated = false;
+    }
+}
+
+int main() {
+    pb_w.mode(PullUp);
+    pb_v.mode(PullUp);
+    pb_k.mode(PullUp);
+    pb_rpg.mode(PullDown);
+    wait(.001);
+    pb_w.attach_deasserted(&changeWaveform);
+    pb_v.attach_deasserted(&changeValues);
+    pb_k.attach_deasserted(&changePlaces);
+    pb_rpg.attach_deasserted(&generate);
+    pb_w.setSampleFrequency();
+    pb_v.setSampleFrequency();
+    pb_k.setSampleFrequency();
+    pb_rpg.setSampleFrequency();
+    red = 0.0; // 1.0 is off, 0.0 on
+    green = 1.0;
+    blue = 1.0;
+    rpg_a.rise(&adjustValues);
+    rpg_a.fall(&adjustValues);
+    rpg_b.rise(&adjustValues);
+    rpg_b.fall(&adjustValues);
+    updateLCD();
+    while(1) {
+        if (!generated && !prepared && value_count != 0) {
+            updateValue();
+        }
+        if (pc.readable()) {
+            char str[100];
+            char* message = pc.gets(str, 100);
+            pc.printf(message);
+            if (prepared && !generated) {
+                pc.printf("generating");
+                generate();
+            } else if (prepared && generated) {
+                pc.printf("stopping");
+                generate();
+            } else {
+                uLCD.locate(1,8);
+                uLCD.color(GREEN);
+                uLCD.printf("%s", message);
+                char* token = strtok(message, ",");
+                char* waveformStr = token;
+                token = strtok(NULL, ",");
+                char* amplitudeStr = token;
+                token = strtok(NULL, ",");
+                char* offsetStr = token;
+                token = strtok(NULL, ",");
+                char* frequencyStr = token;
+                token = strtok(NULL, ",");
+                char* duty_cycleStr = token;
+                waveform = atoi(waveformStr);
+                amplitude = atof(amplitudeStr);
+                offset = atof(offsetStr);
+                frequency = atof(frequencyStr);
+                if (frequency >= 1000.0) {
+                    khz = true;
+                    frequency /= 1000.0;
+                } else {
+                    khz = false;
+                }
+                duty_cycle = atoi(duty_cycleStr);
+                updateLCD();
+                prepared = false;
+                generated = false;
+                generate();
+            }
+        }
+    }
+}