Hexi_Acceleromagnetic_Synth: Michael Yarnell, Alec Pierce, 2017 The program turns an NXP Hexiwear, its development board, and a Click buzzer collectively into an 'acceleromagnetic' synthesizer. That is to say that the synthesizer is controlled primarily via the on-board accelerometer and magnetometer units.

Dependencies:   FXOS8700 Hexi_KW40Z NeatGUI PWM_6_Tone_Library

Revision:
0:bec3a12e79e7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Apr 18 16:06:38 2017 +0000
@@ -0,0 +1,242 @@
+/* Hexi_Acceleromagnetic_Synth
+    2017 Michael Yarnell, Alec Pierce
+    Class Project: ECE49500 SP17 (MEMS/NEMS/IoT/Wearables)
+    IUPUI - Purdue School of Engineering and Technology
+
+ The following program turns an NXP Hexiwear, its development board, and a Click
+  buzzer collectively into an 'acceleromagnetic' synthesizer. That is to say
+  that the synthsizer is controlled primarily via the onboard accelerometer and 
+  magnetometer units.
+ Once the appropriate initializations have been made, the program plays a short,
+  preprogrammed tune.  If, at any time, the left or right screen buttons are
+  pressed, they each emit unique "drumbeat" note sequences.  The accelerometer
+  and magnetometer are read.  The accelerometer x and y (pitch and roll, 
+  respectively) control note selection.  The magnetometer value RMS is
+  calculated, and if the magnetic field RMS is greater than 250uT, the 
+  instrument will emit corresponding notes.
+  
+ Adapted from examples:
+  "Hexi_Magneto-v2_Example" 
+    https://developer.mbed.org/teams/Hexiwear/code/Hexi_Magneto-v2_Example/
+  "Hexi_Accelero-v2_Example" 
+    https://developer.mbed.org/teams/Hexiwear/code/Hexi_Accelero-v2_Example/
+  "Hexi_Click_Buzzer-v2_Example" 
+    https://developer.mbed.org/teams/Hexiwear/code/Hexi_Click_Buzzer-v2_Example/
+  "Hexi_Bubble_Game" 
+    https://developer.mbed.org/teams/Hexiwear/code/Hexi_Bubble_Game/
+*/
+
+// TYPEDEFS
+typedef     signed char             int8_t;
+typedef     unsigned char           uint8_t;
+typedef     signed long long int    int64_t;
+typedef     unsigned long long int  uint64_t;
+
+// LIBRARIES
+//  Note that pwm_6_tone.h has been modified from the default library header.
+#include "mbed.h"
+#include <pwm_6_tone.h>
+#include "Hexi_KW40Z.h"
+#include "FXOS8700.h"
+#include "string.h"
+
+// PIN CONNECTIONS
+// Define the Buzzer Pinout (PWM Out)
+PwmOut Buzzer(PTA10);                               
+// Instantiate the Hexi KW40Z Driver (UART TX, UART RX)
+KW40Z kw40z_device(PTE24, PTE25);                   
+// Accelerometer and Magnetometer instantiation
+FXOS8700 mag(PTC11, PTC10);                         
+FXOS8700 accel(PTC11, PTC10);
+// Initialize Face LED
+DigitalOut led1(LED_GREEN);
+// Initialize Serial port
+//Serial pc(USBTX, USBRX);          // Include to debug modified sensor values
+                                    //  or enter a practice mode. 
+
+// VARIABLES
+float accel_data[3]; // Storage for the data from the sensor
+float mag_data[3];   // Storage for the data from the sensor
+float mag_rms=0.0;   // RMS value to be computed from sensor input
+
+    // From Bubble
+int xposg = 0;       // The roll position of the unit
+int yposg = 0;       // The pitch position of the unit
+
+    // New Variables
+        // Note is a floating-point value that bears a number to send to the
+        //  Tune function.
+float  Note = 0.0;
+        // This table holds the values determined to play the appropriate notes
+        //  as reverse-engineered from the values in 
+        //  "Hexi_Click_Buzzer-v2_Example" to widen range to nearly six octaves.
+float  C_1 = 1000000/Do1, Cs_1 = 1000000/Do1s, D_1 = 1000000/Re1, Ds_1 = 1000000/Re1s,
+       E_1 = 1000000/Mi1, F_1 = 1000000/Fa1, Fs_1 = 1000000/Fa1s, G_1 = 1000000/So1,
+       Gs_1 = 1000000/So1s, A_1 = 1000000/La1, As_1 = 1000000/La1s, B_1 = 1000000/Ti1,
+       
+       C_2 = 1000000/Do2, Cs_2 = 1000000/Do2s, D_2 = 1000000/Re2, Ds_2 = 1000000/Re2s,
+       E_2 = 1000000/Mi2, F_2 = 1000000/Fa2, Fs_2 = 1000000/Fa2s, G_2 = 1000000/So2,
+       Gs_2 = 1000000/So2s, A_2 = 1000000/La2, As_2 = 1000000/La2s, B_2 = 1000000/Ti2,
+       
+       C_3 = 1000000/Do3, Cs_3 = 1000000/Do3s, D_3 = 1000000/Re3, Ds_3 = 1000000/Re3s,
+       E_3 = 1000000/Mi3, F_3 = 1000000/Fa3, Fs_3 = 1000000/Fa3s, G_3 = 1000000/So3,
+       Gs_3 = 1000000/So3s, A_3 = 1000000/La3, As_3 = 1000000/La3s, B_3 = 1000000/Ti3,
+       
+       C_4 = 1000000/Do4, Cs_4 = 1000000/Do4s, D_4 = 1000000/Re4, Ds_4 = 1000000/Re4s,
+       E_4 = 1000000/Mi4, F_4 = 1000000/Fa4, Fs_4 = 1000000/Fa4s, G_4 = 1000000/So4,
+       Gs_4 = 1000000/So4s, A_4 = 1000000/La4, As_4 = 1000000/La4s, B_4 = 1000000/Ti4,
+       
+       C_5 = 1000000/Do5, Cs_5 = 1000000/Do5s, D_5 = 1000000/Re5, Ds_5 = 1000000/Re5s,
+       E_5 = 1000000/Mi5, F_5 = 1000000/Fa5, Fs_5 = 1000000/Fa5s, G_5 = 1000000/So5,
+       Gs_5 = 1000000/So5s, A_5 = 1000000/La5, As_5 = 1000000/La5s, B_5 = 1000000/Ti5,
+       
+       C_6 = 1000000/Do6, Cs_6 = 1000000/Do6s, D_6 = 1000000/Re6, Ds_6 = 1000000/Re6s,
+       E_6 = 1000000/Mi6, F_6 = 1000000/Fa6, Fs_6 = 1000000/Fa6s, G_6 = 1000000/So6,
+       Gs_6 = 1000000/So6s, A_6 = 1000000/La6, As_6 = 1000000/La6s, B_6 = 1000000/Ti6;
+
+//FUNCTIONS
+void ButtonLeft(void)
+{
+// "Beat" 1
+    Tune(Buzzer, C_5, 1); Tune(Buzzer, E_2, 1); 
+    Tune(Buzzer, C_5, 1); Tune(Buzzer, E_1, 1);
+}
+
+void ButtonRight(void)
+{
+// "Beat" 2
+    Tune(Buzzer, C_3, 1); Tune(Buzzer, E_2, 1); 
+    Tune(Buzzer, C_1, 1); Tune(Buzzer, E_1, 1);
+}
+
+int main()
+{
+// Instantiate Buttons   
+    kw40z_device.attach_buttonLeft(&ButtonLeft);
+    kw40z_device.attach_buttonRight(&ButtonRight);
+    
+// Configure Accelerometer, Magnetometer FXOS8700
+    accel.accel_config();
+    mag.mag_config();
+    
+// Startup tune tones
+    Tune(Buzzer, D_6,  2); wait_ms(5);   Tune(Buzzer, D_4,  2); wait_ms(5);
+    Tune(Buzzer, C_5,  2); wait_ms(5);   Tune(Buzzer, D_4,  4); wait_ms(5);        
+    Tune(Buzzer, D_2,  4); wait_ms(5);   Tune(Buzzer, Cs_1, 2); wait_ms(10);
+    Tune(Buzzer, C_1, 16); wait_ms(10);  Tune(Buzzer, C_2,  8); wait_ms(25);
+    Tune(Buzzer, C_3,  4); wait_ms(60);  Tune(Buzzer, C_4,  2); wait_ms(40);
+    Tune(Buzzer, C_5,  4); wait_ms(100);
+
+// This loop, modified from from the Bubble game example, locates the
+//  x/y accelerometer information (within boundaries) to determine
+//  the position of the user and thus the note to play.
+    while(1) {
+
+// Get accelerometer data
+        accel.acquire_accel_data_g(accel_data);
+        xposg=(accel_data[1] * (-20.0));
+        if (xposg >  30) xposg =  30;  // Notes: 12 per octave
+        if (xposg < -30) xposg = -30;
+        yposg=(accel_data[0] * (40.0));
+        if (yposg >  30) yposg =  30;  // Octaves: 6 available
+        if (yposg < -30) yposg = -30;
+
+// Find Note
+//  Program first attempts to find Octave from accelerometer y values.
+//  Then it further determines the and assigns the value of the note
+//  from the x value.
+
+        if (yposg > 29) {                  // Octave 1
+            if (xposg >  20) Note = C_1;  // C
+            if (xposg >  16) Note = Cs_1; // Cs
+            if (xposg >  12) Note = D_1;  // D
+            if (xposg >   8) Note = Ds_1; // Ds
+            if (xposg >   4) Note = E_1;  // E
+            if (xposg >=  0) Note = F_1;  // F
+            if (xposg >  -4) Note = Fs_1; // Fs
+            if (xposg >  -8) Note = G_1;  // G
+            if (xposg > -12) Note = Gs_1; // Gs
+            if (xposg > -16) Note = A_1;  // A
+            if (xposg > -20) Note = As_1; // As
+            else             Note = B_1;  // B
+        } else if (yposg > 15) {           // Octave 2
+            if (xposg >  20) Note = C_2;  // C
+            if (xposg >  16) Note = Cs_2; // Cs
+            if (xposg >  12) Note = D_2;  // D
+            if (xposg >   8) Note = Ds_2; // Ds
+            if (xposg >   4) Note = E_2;  // E
+            if (xposg >=  0) Note = F_2;  // F
+            if (xposg >  -4) Note = Fs_2; // Fs
+            if (xposg >  -8) Note = G_2;  // G
+            if (xposg > -12) Note = Gs_2; // Gs
+            if (xposg > -16) Note = A_2;  // A
+            if (xposg > -20) Note = As_2; // As
+            else             Note = B_2;  // B
+        } else if (yposg >= 0) {           // Octave 3
+            if (xposg >  20) Note = C_3;  // C
+            if (xposg >  16) Note = Cs_3; // Cs
+            if (xposg >  12) Note = D_3;  // D
+            if (xposg >   8) Note = Ds_3; // Ds
+            if (xposg >   4) Note = E_3;  // E
+            if (xposg >=  0) Note = F_3;  // F
+            if (xposg >  -4) Note = Fs_3; // Fs
+            if (xposg >  -8) Note = G_3;  // G
+            if (xposg > -12) Note = Gs_3; // Gs
+            if (xposg > -16) Note = A_3;  // A
+            if (xposg > -20) Note = As_3; // As
+            else             Note = B_3;  // B
+        } else if (yposg > -15) {          // Octave 4
+            if (xposg >  20) Note = C_4;  // C
+            if (xposg >  16) Note = Cs_4; // Cs
+            if (xposg >  12) Note = D_4;  // D
+            if (xposg >   8) Note = Ds_4; // Ds
+            if (xposg >   4) Note = E_4;  // E
+            if (xposg >=  0) Note = F_4;  // F
+            if (xposg >  -4) Note = Fs_4; // Fs
+            if (xposg >  -8) Note = G_4;  // G
+            if (xposg > -12) Note = Gs_4; // Gs
+            if (xposg > -16) Note = A_4;  // A
+            if (xposg > -20) Note = As_4; // As
+            else             Note = B_4;  // B
+        } else if (yposg > -29) {          // Octave 5
+            if (xposg >  20) Note = C_5;  // C
+            if (xposg >  16) Note = Cs_5; // Cs
+            if (xposg >  12) Note = D_5;  // D
+            if (xposg >   8) Note = Ds_5; // Ds
+            if (xposg >   4) Note = E_5;  // E
+            if (xposg >=  0) Note = F_5;  // F
+            if (xposg >  -4) Note = Fs_5; // Fs
+            if (xposg >  -8) Note = G_5;  // G
+            if (xposg > -12) Note = Gs_5; // Gs
+            if (xposg > -16) Note = A_5;  // A
+            if (xposg > -20) Note = As_5; // As
+            else             Note = B_5;  // B
+        } else {                           // Octave 6
+            if (xposg >  20) Note = C_6;  // C
+            if (xposg >  16) Note = Cs_6; // Cs
+            if (xposg >  12) Note = D_6;  // D
+            if (xposg >   8) Note = Ds_6; // Ds
+            if (xposg >   4) Note = E_6;  // E
+            if (xposg >=  0) Note = F_6;  // F
+            if (xposg >  -4) Note = Fs_6; // Fs
+            if (xposg >  -8) Note = G_6;  // G
+            if (xposg > -12) Note = Gs_6; // Gs
+            if (xposg > -16) Note = A_6;  // A
+            if (xposg > -20) Note = As_6; // As
+            else             Note = B_6;  // B
+        }
+
+// Get magnetometer data
+        mag.acquire_mag_data_uT(mag_data);
+// Find RMS values of this 3-axis reading
+        mag_rms = sqrt(((mag_data[0] * mag_data[0]) + (mag_data[1] * mag_data[1]) + (mag_data[2] * mag_data[2])) / 3);
+
+        //printf("\tX: %i \tY: %i \tMAGRMS: %i", xposg, yposg, mag_rms);
+        // Above line displays modified sensor results, useful for practice or
+        //  debugging.
+
+// If the magnetic field is strong enough, play a note.
+        if (mag_rms > 150) { 
+                Tune(Buzzer, Note, 2); }// Timing is out of 16ths
+    }
+}
\ No newline at end of file