Waveform generator

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

main.cpp

Committer:
carsonbrown27
Date:
18 months ago
Revision:
0:7e122b3c7928

File content as of revision 0:7e122b3c7928:

#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();
            }
        }
    }
}