Waveform generator
Dependencies: 4DGL-uLCD-SE AFG_project PinDetect RPG mbed
Revision 0:7e122b3c7928, committed 23 months ago
- Comitter:
- carsonbrown27
- Date:
- Thu Dec 08 05:06:29 2022 +0000
- Commit message:
- Final Version
Changed in this revision
diff -r 000000000000 -r 7e122b3c7928 4DGL-uLCD-SE.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4DGL-uLCD-SE.lib Thu Dec 08 05:06:29 2022 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
diff -r 000000000000 -r 7e122b3c7928 AFG_project.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AFG_project.lib Thu Dec 08 05:06:29 2022 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/carsonbrown27/code/AFG_project/#2fa202e02c48
diff -r 000000000000 -r 7e122b3c7928 PinDetect.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PinDetect.lib Thu Dec 08 05:06:29 2022 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/AjK/code/PinDetect/#cb3afc45028b
diff -r 000000000000 -r 7e122b3c7928 RPG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RPG.lib Thu Dec 08 05:06:29 2022 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/canderson199/code/RPG/#0b389c2c21b5
diff -r 000000000000 -r 7e122b3c7928 SongPlayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SongPlayer.h Thu Dec 08 05:06:29 2022 +0000 @@ -0,0 +1,41 @@ +#include "mbed.h" +// new class to play a note on Speaker based on PwmOut class +class SongPlayer +{ +public: + SongPlayer(PinName pin) : _pin(pin) { +// _pin(pin) means pass pin to the constructor + } +// class method to play a note based on PwmOut class + void PlaySong(float frequency[], float duration[], float volume=1.0) { + vol = volume; + notecount = 0; + _pin.period(1.0/frequency[notecount]); + _pin = volume/2.0; + noteduration.attach(this,&SongPlayer::nextnote, duration[notecount]); + // setup timer to interrupt for next note to play + frequencyptr = frequency; + durationptr = duration; + //returns after first note starts to play + } + void nextnote(); +private: + Timeout noteduration; + PwmOut _pin; + int notecount; + float vol; + float * frequencyptr; + float * durationptr; +}; +//Interrupt Routine to play next note +void SongPlayer::nextnote() +{ + _pin = 0.0; + notecount++; //setup next note in song + if (durationptr[notecount]!=0.0) { + _pin.period(1.0/frequencyptr[notecount]); + noteduration.attach(this,&SongPlayer::nextnote, durationptr[notecount]); + _pin = vol/2.0; + } else + _pin = 0.0; //turn off on last note +} \ No newline at end of file
diff -r 000000000000 -r 7e122b3c7928 main.cpp --- /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(); + } + } + } +}
diff -r 000000000000 -r 7e122b3c7928 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Dec 08 05:06:29 2022 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file