Sound update

Dependencies:   4DGL-uLCD-SE Physac-MBED PinDetect SDFileSystem mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
jaybalar
Date:
Thu Dec 08 18:42:16 2022 +0000
Parent:
26:163d7ca8c42d
Child:
28:bccd14334bb9
Commit message:
Sound works

Changed in this revision

Speaker.h Show annotated file Show diff for this revision Revisions of this file
globals.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
tetris/tetris.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/Speaker.h	Thu Dec 08 02:12:14 2022 +0000
+++ b/Speaker.h	Thu Dec 08 18:42:16 2022 +0000
@@ -1,26 +1,52 @@
-//#ifndef __SPEAKER.H
-//#define __SPEAKER.H
-
-#include "mbed.h"
-// new class to play a note on Speaker based on PwmOut class
 class Speaker
 {
 public:
-    Speaker(PinName pin) : _pin(pin)
-    {
+    Speaker(PinName pin) : _pin(pin) {
 // _pin(pin) means pass pin to the Speaker Constructor
+// precompute 32 sample points on one sine wave cycle
+// used for continuous sine wave output later
+        for(int k=0; k<32; k++) {
+            Analog_out_data[k] = int (65536.0 * ((1.0 + sin((float(k)/32.0*6.28318530717959)))/2.0));
+            // scale the sine wave to 16-bits - as needed for AnalogOut write_u16 arg
+        }
+
     }
-// class method to play a note based on PwmOut class
-    void PlayNote(float frequency, float duration, float volume)
-    {
-        _pin.period(1.0/frequency);
-        _pin = volume/2.0;
+// class method to play a note based on AnalogOut class
+    void PlayNote(float frequency, float duration, float volume) {
+        // scale samples using current volume level arg
+        for(int k=0; k<32; k++) {
+            Analog_scaled_data[k] = Analog_out_data[k] * volume;
+        }
+        // reset to start of sample array
+        i=0;
+        // turn on timer interrupts to start sine wave output
+        Sample_Period.attach(this, &Speaker::Sample_timer_interrupt, 1.0/(frequency*32.0));
+        // play note for specified time
         wait(duration);
-        _pin = 0.0;
+        // turns off timer interrupts
+        Sample_Period.detach();
+        // sets output to mid range - analog zero
+        this->_pin.write_u16(32768);
+
     }
+private:
+// sets up specified pin for analog using AnalogOut class
+    AnalogOut _pin;
+    // set up a timer to be used for sample rate interrupts
+    Ticker Sample_Period;
 
-private:
-    PwmOut _pin;
+    //variables used by interrupt routine and PlayNote
+    volatile int i;
+    short unsigned Analog_out_data[32];
+    short unsigned Analog_scaled_data[32];
+
+// Interrupt routine
+// used to output next analog sample whenever a timer interrupt occurs
+    void Sample_timer_interrupt(void) {
+        // send next analog sample out to D to A
+        this->_pin.write_u16(Analog_scaled_data[i]);
+        // increment pointer and wrap around back to 0 at 32
+        i = (i+1) & 0x01F;
+    }
 };
 
-//#endif
\ No newline at end of file
--- a/globals.h	Thu Dec 08 02:12:14 2022 +0000
+++ b/globals.h	Thu Dec 08 18:42:16 2022 +0000
@@ -2,7 +2,7 @@
 #include "rtos.h"
 
 #include "wave_player.h"
-//#include "Speaker.h"
+#include "Speaker.h"
 #include "SDFileSystem.h"
 #include "uLCD_4DGL.h"
 #include "bluefruit_controller.h"
@@ -38,5 +38,5 @@
 extern PwmOut rGb;
 extern PwmOut rgB;
 
-//extern Speaker DACout;
+extern Speaker DACout;
 //extern wave_player waver;
--- a/main.cpp	Thu Dec 08 02:12:14 2022 +0000
+++ b/main.cpp	Thu Dec 08 18:42:16 2022 +0000
@@ -35,11 +35,10 @@
 PwmOut Rgb(p23);
 PwmOut rGb(p24);
 PwmOut rgB(p25);
-//Speaker DACout(p18);
+Speaker DACout(p18);
 //wave_player waver(&DACout);
 
 
-
 ////////////////////////////////
 // MAIN.CPP LOCAL DEFINITIONS //
 ////////////////////////////////
@@ -55,34 +54,253 @@
 //////////////////////
 // MAIN.CPP THREADS //
 //////////////////////
-/*
+
 void audioThread()
 {
     while (true) {
-        FILE *wave_file;
+        //FILE *wave_file;
         while (game1 == false && game2 == false) {
-            led2 = true;
+            DACout.PlayNote(369.99, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(466.16, 0.2, 1);
+            DACout.PlayNote(554.37, 0.2, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(466.16, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(369.99, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(293.66, 0.2, 1);
+            DACout.PlayNote(293.66, 0.2, 1);
+            DACout.PlayNote(293.66, 0.2, 1);
+            DACout.PlayNote(0, 0.8, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(277.18, 0.4, 1);
+            DACout.PlayNote(293.66, 0.2, 1);
+            DACout.PlayNote(369.99, 0.2, 1);
+            DACout.PlayNote(466.16, 0.2, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(554.37, 0.2, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(466.16, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(369.99, 0.4, 1);
+            DACout.PlayNote(659.25, 0.4, 1);
+            DACout.PlayNote(622.25, 0.4, 1);
+            DACout.PlayNote(587.33, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(0, 0.4, 1);
+            
+            
+            
+            DACout.PlayNote(392.00, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(554.37, 0.2, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(369.99, 0.2, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(554.37, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(329.00, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(523.25, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(329.00, 0.4, 1);
+            DACout.PlayNote(369.99, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(329.63, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(277.18, 0.2, 1);
+            DACout.PlayNote(277.18, 0.2, 1);
+            DACout.PlayNote(277.18, 0.2, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(277.18, 0.2, 1);
+            DACout.PlayNote(277.18, 0.2, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(277.18, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(0, 0.4, 1);
+            DACout.PlayNote(311.13, 0.4, 1);
+            if(game1 == true || game2 == true) break;
+            DACout.PlayNote(293.66, 0.4, 1);
+            //DACout.PlayNote(440.00, 0.3, 1);
+            
+            /*led2 = true;
             wave_file=fopen("/sd/MiiMenu.wav","r");
+            PRINTF("Opening");
             waver.play(wave_file);
             fclose(wave_file);
-            led2 = false;
+            led2 = false;*/
         }
         while (game1 == true && game2 == false) {
-            led2 = true;
+            DACout.PlayNote(659.25, 0.3, 1);
+            DACout.PlayNote(493.88, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+           if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(493.88, 0.3, 1);
+            DACout.PlayNote(440.00, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(440.00, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(659.25, 0.3, 1);
+            DACout.PlayNote(587.33, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(493.88, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(587.33, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(659.25, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(440.00, 0.3, 1);
+            DACout.PlayNote(440.00, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            
+            DACout.PlayNote(583.33, 0.3, 1);
+            DACout.PlayNote(698.46, 0.3, 1);
+            DACout.PlayNote(880.00, 0.3, 1);
+            DACout.PlayNote(783.99, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(698.46, 0.3, 1);
+            DACout.PlayNote(659.25, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(659.25, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.3, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(493.88, 0.3, 1);
+            DACout.PlayNote(493.88, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(587.33, 0.3, 1);
+            DACout.PlayNote(659.25, 0.3, 1);
+            DACout.PlayNote(523.35, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(440.00, 0.3, 1);
+            DACout.PlayNote(440.00, 0.3, 1);
+           /* led2 = true;
             wave_file=fopen("/sd/tetris.wav","r");
             waver.play(wave_file);
             fclose(wave_file);
-            led2 = false;
+            led2 = false;*/
         }
         while (game2 == true && game1 == false) {
-            led2 = true;
+            DACout.PlayNote(329.63, 0.6, 1);
+            DACout.PlayNote(349.23, 0.6, 1);
+            DACout.PlayNote(392.00, 0.15, 1);
+            DACout.PlayNote(523.25, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(493.88, 0.15, 1);
+            DACout.PlayNote(523.25, 0.15, 1);
+            DACout.PlayNote(392.00, 0.15, 1);
+            DACout.PlayNote(329.63, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(261.63, 0.15, 1);
+            DACout.PlayNote(293.66, 0.15, 1);
+            DACout.PlayNote(329.33, 0.15, 1);
+            DACout.PlayNote(293.66, 0.6, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(293.66, 1.2, 1);
+            DACout.PlayNote(329.63, 0.6, 1);
+            DACout.PlayNote(349.23, 0.3, 1);
+            DACout.PlayNote(329.63, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(349.23, 0.15, 1);
+            
+            
+            DACout.PlayNote(392.00, 0.15, 1);
+            DACout.PlayNote(523.25, 0.15, 1);           
+            DACout.PlayNote(587.33, 0.15, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.1, 1);
+            DACout.PlayNote(659.25, 0.1, 1);
+            DACout.PlayNote(698.46, 0.15, 1);
+            DACout.PlayNote(659.25, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.15, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(392.00, 0.15, 1);
+            DACout.PlayNote(440.00, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(440.00, 0.15, 1);
+            DACout.PlayNote(587.33, 0.15, 1);
+            DACout.PlayNote(587.33, 0.1, 1);
+            DACout.PlayNote(587.33, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.1, 1);
+            DACout.PlayNote(659.25, 0.1, 1);
+            DACout.PlayNote(698.46, 0.15, 1);
+            DACout.PlayNote(659.25, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.15, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(392.00, 0.3, 1);
+            DACout.PlayNote(392.00, 0.6, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(392.00, 0.15, 1);
+            DACout.PlayNote(587.33, 0.1, 1);
+            DACout.PlayNote(659.25, 0.1, 1);
+            DACout.PlayNote(698.46, 0.15, 1);
+            DACout.PlayNote(659.25, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.15, 1);
+            DACout.PlayNote(523.25, 0.3, 1);
+            DACout.PlayNote(783.99, 0.3, 1);
+            DACout.PlayNote(783.99, 0.6, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(783.99, 0.15, 1);
+            DACout.PlayNote(783.99, 0.1, 1);
+            DACout.PlayNote(880.00, 0.1, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(932.33, 0.15, 1);
+            DACout.PlayNote(880.00, 0.15, 1);           
+            DACout.PlayNote(783.99, 0.15, 1);
+            DACout.PlayNote(698.46, 0.6, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(830.61, 0.15, 1);
+            DACout.PlayNote(783.99, 0.15, 1);
+            DACout.PlayNote(698.46, 0.15, 1);
+            DACout.PlayNote(622.25, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(739.99, 0.15, 1);
+            DACout.PlayNote(698.46, 0.1, 1);
+            DACout.PlayNote(698.46, 0.15, 1);
+            DACout.PlayNote(622.25, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(554.37, 0.15, 1);
+            DACout.PlayNote(415.30, 0.15, 1);
+            DACout.PlayNote(349.23, 0.15, 1);
+            DACout.PlayNote(277.18, 0.15, 1);
+            DACout.PlayNote(311.13, 0.3, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(554.37, 0.3, 1);
+            DACout.PlayNote(587.33, 0.6, 1);
+            DACout.PlayNote(587.33, 0.6, 1);
+            DACout.PlayNote(587.33, 0.15, 1);
+            DACout.PlayNote(392.00, 0.15, 1);
+            if(game1 != true && game2 == false) break;
+            DACout.PlayNote(587.33, 0.3, 1);
+            DACout.PlayNote(783.99, 0.3, 1);
+            DACout.PlayNote(783.99, 0.6, 1);
+            DACout.PlayNote(783.99, 1.2, 1);
+            if(game1 != true && game2 == false) break;
+            /*led2 = true;
             wave_file=fopen("/sd/WiiPlayAirHockey.wav","r");
             waver.play(wave_file);
             fclose(wave_file);
-            led2 = false;
+            led2 = false;*/
         }
     }
-}*/
+}
 
 void ledThread()
 {
@@ -113,10 +331,18 @@
     // Launch four threads
     Thread thread1(tetrisGame, osPriorityHigh);
     Thread thread2(hockeyGame, osPriorityHigh);
-    //Thread thread3(audioThread, osPriorityLow);
+    Thread thread3(audioThread, osPriorityLow);
     Thread thread4(ledThread, osPriorityLow);
     
     // The main thread goes on to blink LEDs
+    //Speaker mySpeaker(p18);
+    // loops forever playing two notes on speaker using analog samples
+    //PRINTF("test");
+//    while(1) {
+//        //mySpeaker.PlayNote(969.0, 0.5, 1.0);
+////        mySpeaker.PlayNote(800.0, 0.5, 1.0);
+//        //PRINTF("loop");
+//    }
     while (true) {
         led1 = 1;
         Thread::wait(500);
@@ -143,7 +369,7 @@
         PRINTF("[MAIN] Thread stacks: %lu %lu %lu %lu\r\n",
             thread1.used_stack(),
             thread2.used_stack(),
-            //thread3.used_stack(),
+            thread3.used_stack(),
             thread4.used_stack());
         
         // Launch into the air hockey game
--- a/tetris/tetris.cpp	Thu Dec 08 02:12:14 2022 +0000
+++ b/tetris/tetris.cpp	Thu Dec 08 18:42:16 2022 +0000
@@ -87,7 +87,7 @@
     uLCD.color(WHITE);
     uLCD.locate(1,0);
     uLCD.printf("TETRIS");
-    wait(2);
+    Thread::wait(2000);
     
     uLCD.baudrate(3000000);
     
@@ -145,12 +145,12 @@
         
         if(isGameOver) 
         {
-            wait(1);
+            Thread::wait(1000);
             uLCD.cls();
             uLCD.text_width(2);
             uLCD.text_height(2);
             uLCD.printf("GAME OVER");
-            wait(2);
+            Thread::wait(2000);
             uLCD.cls();
             
             //isGameOver = false;
@@ -254,12 +254,12 @@
             
             case (5)://menu
             {
-                wait(1);
+                Thread::wait(1000);
                 uLCD.cls();
                 uLCD.text_width(2);
                 uLCD.text_height(2);
                 uLCD.printf("MENU");
-                wait(2);
+                Thread::wait(2000);
                 uLCD.cls();
                 
                 Thread::wait(1000); // FIX?
@@ -319,7 +319,7 @@
             }
             timer.reset();
         }
-            wait(0.1);
+            Thread::wait(100);
             
             //get a new random number for PWM
         //x = rand() / float(RAND_MAX);