K64F drum machine, with RAW WAV sample playback, and USB midi functionality

Dependencies:   FATFileSystem N5110_mod SDFileSystem USBDevice mbed

Revision:
0:02a88f05d461
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Mon May 09 14:20:16 2016 +0000
@@ -0,0 +1,604 @@
+/**
+@file main.h
+@brief Header file containing functions prototypes, defines, and global variables
+@brief K64F drum machine project, for ELEC2645
+@author Peter J.G. Nye
+@date May 2016
+*/
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#define     DEBOUNCE   0.2 /*!<  Debounce time for tap tempo */
+
+#include    "mbed.h"
+#include    "N5110.h"
+#include    "USBMIDI.h"
+#include    "USBSerial.h"
+#include    "USBAudio.h"
+#include    "SDFileSystem.h"
+#include    <fstream>
+
+/** @defgroup group1 Button matrix
+ *  used for the scanning of the UI buttons
+ *  @{
+ */
+
+
+/** # IO & interrupts */
+
+/** @brief Output bus used for scanning button matrix */
+BusOut      ButtonOut(PTE26,PTE25,PTD3,PTC8);
+
+/** @brief  interrupt pins connected to button matrix outputs */
+InterruptIn ButtonIn_A(PTB11);
+InterruptIn ButtonIn_B(PTB3);
+InterruptIn ButtonIn_C(PTB2);
+InterruptIn ButtonIn_D(PTB10);
+InterruptIn ButtonIn_E(PTB20);
+
+/** @brief ticker to rotate ButtonOut bus */
+Ticker      Button_scan_tkr;
+
+/** # Flags, maps & variables */
+
+/** @brief generates boolean flags for the matrix buttons */
+struct      buttons_struct {
+    bool    steps[8];
+    bool    start;
+    bool    skip;
+    bool    edit;
+    bool    pattern;
+    bool    inst;
+    bool    save;
+    bool    shift;
+    bool    load;
+    bool    back;
+    bool    down;
+    bool    enter;
+    bool    up;
+};
+buttons_struct buttons;
+
+/**
+@namespace keyMap
+@brief indicates name of button pressed
+@brief used for serial debugging
+*/
+char        *keyMap[][4] {
+    {"Step 7",  "Step 6",   "Step 5",   "Step 4"    },
+    {"Step 3",  "Step 2",   "Step 1",   "Step 0"    },
+    {"Load",    "save",     "Edit",     "Instrument"},
+    {"Pattern", "Skip",     "Shift",    "Start",    },
+    {"Back",    "Enter",    "Down",     "Up"        }
+};
+
+/** @brief used to map the button presses on to the boolean flags */
+bool        *keyMap_point[][4] {
+    {&buttons.steps[7], &buttons.steps[6],  &buttons.steps[5],  &buttons.steps[4] },
+    {&buttons.steps[3], &buttons.steps[2],  &buttons.steps[1],  &buttons.steps[0] },
+    {&buttons.load,     &buttons.save,      &buttons.edit,      &buttons.inst     },
+    {&buttons.pattern,  &buttons.skip,      &buttons.shift,     &buttons.start    },
+    {&buttons.back,     &buttons.enter,     &buttons.down,      &buttons.up       }
+};
+
+/**
+@namespace ButtonOut_val
+@brief Used to set the value of the ButtonOut bus
+@brief When scanned through, sets a different value low each cycle
+*/
+uint8_t     ButtonOut_val[]= {
+    0xE,
+    0xD,
+    0xB,
+    0x7
+};
+
+/**
+@namespace ButtonOut_pos
+@brief stores the current position of the ButtonOut scan, in order to select the correct value for the output from the ButtonOut_val array
+@brief increments upwards from 0 to 3, and then resets
+*/
+uint8_t     ButtonOut_pos = 0;
+
+/** @brief used to indicate if any button has been pressed */
+bool        ButtonFlag_zero = 0;
+
+/** @brief used to indicate if the input on the column during the last scan was equal to zero */
+bool        ButtonFlag_cols[4] = {0,0,0,0};
+bool        ButtonFlag_press = 0;
+
+/** # Functions */
+
+/**
+@namespace Button_init
+@brief function used to initialise the button matrix
+*/
+void        Button_init();
+
+/**
+@namespace Button_scan_ISR
+@brief function called by Button_scan_tkr
+@brief rotates the output of ButtonOut
+*/
+void        Button_scan_ISR();
+
+/**
+@namespace Button_update
+@brief Used to update the boolean flags within Buttons_struct
+@brief called by ButtonIn_*_ISR
+@param row - Used to indicate which ButtonIn interrupt it was called by
+*/
+void        Button_update(int row);
+
+/** @brief interrupt subroutines for ButtonIn_* input */
+void        ButtonIn_A_ISR();
+void        ButtonIn_B_ISR();
+void        ButtonIn_C_ISR();
+void        ButtonIn_D_ISR();
+void        ButtonIn_E_ISR();
+
+/** @} */ // end of group1
+
+/** @defgroup group2 LED matrix
+ *  Variables and functions used to adress the step LEDs
+ *  @{
+ */
+
+/** # IO & interrupts */
+
+/** @brief bus used to adress the LED matrix */
+BusOut      LED_bus(PTC0,PTC9,PTC5,PTC7 , PTC2,PTA2,PTB23,PTA1);
+
+/** @brief ticker used to scan through the LED matrix values */
+Ticker      LED_scan_tkr;
+
+/**
+@namespace shift_LED
+@brief LED above the shift button on the PCB
+@brief not connected to the LED matrix
+*/
+DigitalOut  shift_LED(PTE24);
+
+/** # Flags, maps & variables */
+
+/**
+@namespace LED_buffer
+@brief array used to store the requred ouput values for LED_bus
+@brief used to reduce the amount of functions to be run within the LED_scan_ISR
+*/
+int         LED_buffer[4] = {0x7,0xB,0xD,0xE};
+
+//uint16_t    LED_loadBuffer = 0;
+
+/**
+@namespace LED_pos
+@brief stores the current position of the LED_bus scan, in order to select the correct value for the output from the LED_buffer array
+@brief increments upwards from 0 to 3, and then resets
+*/
+int         LED_pos = 0;
+
+/** @brief */
+//uint8_t     LED_scan_row = 0x1;
+
+/** # LED functions */
+
+/** @brief ISR for LED matrix scan */
+void        LED_scan_ISR();
+
+/**
+@namespace LED_write
+@brief updates the values within LED_buffer to those required for the current output
+@param value - data to be written to the LED matrix
+*/
+void        LED_write(uint16_t value);                                                                          //Loads buffer
+void        LED_init();
+
+/** @} */ // end of group2
+
+/** @defgroup group3 LCD
+ *  Variables and functions used to adress the nokia 5110 LCD
+ *  @{
+ */
+
+/** # IO */
+
+/** @brief defines LCD pins */
+N5110       lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3);
+
+/** # LCD variables */
+
+/** @brief current backlight brightness */
+float       brightness = 0.32;
+
+/** @brief current backlight PWM frequency */
+float       PWM_freq = 50;
+
+/** @brief boolean to keep track of screen colour inversion */
+bool        inverse = false;
+
+/** # LCD functions */
+
+/** @brief function to initialise screen */
+void        LCD_init();
+
+/** @brief function to set brightness and PWM frequency values */
+void        LCD_set();
+/** @brief function to print main screen to display */
+void        LCD_printMain();
+
+/** @} */ // end of group3
+
+/** @defgroup group4 Sequencing
+ *  Variables and functions used to adress the step sequencer
+ *  @{
+ */
+
+/** # Sequence data */
+
+/** @brief channel names (to be displayed to LCD) */
+char        *inst_names[]= {
+    "Kick",
+    "Snare",
+    "Crash",
+    "HH Cl",
+    "HH Op",
+    "Clap",
+    "Ride",
+    "Cowbl",
+    "Skip"
+};
+
+/**
+@namespace Sequence_struct
+@brief generates the variables requred for a sequence
+@brief Output_type indicates the type of output set for each channel
+@brief Midi_note indicates the note ouput via midi for each channel
+@brief Trig_chan indicates the hardware trigger output for each channel
+@brief gate contains the sequence data for each channel
+@brief final channel of the gate array contains step skip points
+@brief the data for each part of these arrays had to be set individually, due to limitations of the MBed IDE
+*/
+union       Sequence_struct {
+    struct  structure {
+        char        Output_type[8];
+        float       MIDI_note[8];
+        float       Trig_chan[8];
+        uint16_t    gate[9];
+    } structure;
+    char*   sequence;
+    Sequence_struct::Sequence_struct() {
+            structure.Output_type[0] = 0;
+            structure.Output_type[1] = 0;
+            structure.Output_type[2] = 0;
+            structure.Output_type[3] = 0;
+            structure.Output_type[4] = 0;
+            structure.Output_type[5] = 0;
+            structure.Output_type[6] = 0;
+            structure.Output_type[7] = 0;
+            structure.MIDI_note[0] = 36;
+            structure.MIDI_note[1] = 38;
+            structure.MIDI_note[2] = 49;
+            structure.MIDI_note[3] = 42;
+            structure.MIDI_note[4] = 56;
+            structure.MIDI_note[5] = 39;
+            structure.MIDI_note[6] = 37;
+            structure.MIDI_note[7] = 51;
+            structure.Trig_chan[0] = 0;
+            structure.Trig_chan[1] = 1;
+            structure.Trig_chan[2] = 2;
+            structure.Trig_chan[3] = 3;
+            structure.Trig_chan[4] = 3;
+            structure.Trig_chan[5] = 4;
+            structure.Trig_chan[6] = 5;
+            structure.Trig_chan[7] = 6;
+    };
+} Seq_array[8];
+
+/** # Sequence IO & interrupts */
+
+/** @brief ticker to increment sequence position */
+Ticker      Sequence_increment_tkr;
+
+/** # flags & variables */
+
+/** @brief currently selected instrument channel */
+int         Seq_current_inst = 0;
+/** @brief currently selected sequence */
+int         Seq_current_seq = 0;
+/** @brief previously selected instrument channel (used when skip button is pressed) */
+int         Seq_prev_inst = 0;
+/** @brief current sequence step */
+int         Seq_current_step = 15;
+/** @brief flag to indicate step increment */
+volatile int Seq_flag = 0;
+/** @brief current tempo value */
+float       tempo = 60;
+/** @brief flag to indicate if the sequence is currently running */
+bool        running = 1;
+/** @brief indicates whether system is waiting for instrument channel selection */
+bool        inst_flag = 0;
+/** @brief indicates whether system is waiting for sequence pattern selection */
+bool        pattern_flag = 0;
+/** @brief indicates whether in skip setup mode */
+bool        skip_flag = 0;
+
+/** # Sequence functions */
+
+/** @brief initialises sequencer */
+void        Sequence_init();
+
+/** @brief writes input data to sequence gate */
+void        Sequence_write();
+/** @brief interrupt call for sequence increment */
+void        Sequence_increment_ISR();
+/** @brief increments sequencer */
+void        Sequence_increment();
+
+/** @} */ // end of group4
+
+/** @defgroup group5 Tap tempo
+ *  Variables and functions used to control the tap-tempo
+ *  @{
+ */
+
+/** # IO & interrupts */
+
+/** @brief timer to keep track of time between button presses */
+Timer       tempo_time;
+/** @brief interrupt for tap tempo button */
+InterruptIn tempo_tapIn(PTB9);
+
+/** # flags & variables */
+
+/** @brief set when tap tempo button is pressed */
+volatile int tempo_flag;
+/** @brief indicates how many times tap tempo button has been pressed */
+int         tempo_timerState;
+/** @brief keeps track of button bounces */
+float       tempo_debounce = 0;
+/** @brief indicates that tempo has been changed */
+volatile int tempo_update_flag = 0;
+
+/** # functions */
+
+/** @brief initialises tap tempo */
+void        tempo_init();
+/** @brief interrupt called by tap tempo input */
+void        tempo_ISR();
+/** @brief tempo set routine */
+void        tempo_set();
+/** @brief Indicates tempo to be updated (used when tempo is set via menu) */
+void        tempo_update();
+
+/** @} */ // end of group5
+
+/** @defgroup group6 Audio output
+ *  Variables and functions used in the playback of wav files (not currently functional)
+ *  @{
+ */
+
+/** # flags & variables */
+
+/** @brief buffer to contain audio file data */
+char *      audio_buffer[8];
+
+/** @brief map to indicate positions of RAW WAV files on SD card */
+char*       audioFile_map[8] {
+    "/sd/samples/808/Bass.wav",
+    "/sd/samples/808/Snare.wav",
+    "/sd/samples/808/Crash.wav",
+    "/sd/samples/808/HiHat_closed.wav",
+    "/sd/samples/808/HiHat_open.wav",
+    "/sd/samples/808/Clap.wav",
+    "/sd/samples/808/Ride.wav",
+    "/sd/samples/808/CowBell.wav"
+};
+/** @brief indicates whether file is currently playing */
+bool        audio_flag[8]   {0,0,0,0,0,0,0,0};
+/** @brief indicates file length */
+int         audio_length[8] {0,0,0,0,0,0,0,0};
+/** @brief indicates current position within file */
+int         audio_pos[8]    {0,0,0,0,0,0,0,0};
+
+/** # functions */
+/** @brief loads file data into buffers */
+void        Audio_init();
+/** @brief updates speaker output */
+void        Audio_ISR();
+
+/** @} */ // end of group6
+
+/** @defgroup group7 USB
+ *  Variables and functions used to control the USB interfacing
+ *  @{
+ */
+
+/** # flags & variables */
+/** @brief keeps track of current USB mode (0 = midi, 1 = serial, 2 = speaker, 3 = none) */
+int         USB_mode = 3;
+/** @brief indicates whether the output needs clearing */
+volatile int decay_flag = 0;
+
+/** # IO & interrupts */
+
+/** @brief pointer to midi function */
+USBMIDI     *midi = 0;
+/** @brief pointer to serial function */
+USBSerial   *pc = 0;
+/** @brief pointer to audio function */
+USBAudio    *audio = 0;
+/** @brief ticker for note decay */
+Ticker      decay_tkr;
+
+
+/** # functions */
+
+/** @brief initialises USB */
+void        USB_init();
+/** @brief called by decay ticker */
+void        decay_ISR();
+
+/** @} */ // end of group7
+
+/** @defgroup group8 USB audio
+ *  Variables and functions used to act as a USB soundcard
+ *  (heavily based on existing code, [see here](https://developer.mbed.org/users/samux/code/USBAUDIO_speaker/))
+ *  @{
+ */
+
+/** # flags & variables */
+
+/** @brief ticker for audio output */
+Ticker      audio_tkr;
+/** @brief buffer to contain incoming audio packets */
+int16_t     USBaudio_buffer[96/2];
+/** @brief indicates availability of audio data */
+volatile bool USBaudio_packet_available = false;
+/** @brief indicates current position within USBaudio_buffer */
+int         USBaudio_index_buffer = 0;
+/** @brief maintains previous speaker value until more data is available */
+uint16_t    audio_prev_val = 0;
+
+/** # USB audio functions */
+/** @brief ISR for audio ouput */
+void        audio_tkr_ISR();
+
+/** @} */ // end of group8
+
+/** @defgroup group9 Menu system
+ *  Variables and functions used to control menus
+ *  based on menu system from first-year project
+ *  @{
+ */
+
+/** # Menu maps */
+
+/** @brief map for Main menu */
+const char  *mainMenu[]= {
+    "Tempo",
+    "Display",
+    "USB mode",0
+};
+/** @brief map for display submenu */
+const char  *displayMenu[]= {
+    "Brightness",
+    "PWM frequency",
+    "Invert",0
+};
+/** @brief map for USB mode submenu */
+const char  *usbMenu[]= {
+    "MIDI",
+    "Serial",
+    "Speaker",
+    "None",0
+};
+/** @brief map for output mode submenu */
+const char  *outputMenu[] = {
+    "Midi",
+    "WAV",
+    "Trigger",
+    "Muted",0
+};
+/** @brief map for edit menu */
+const char  *editMenu[] = {
+    "Output type",
+    "Midi Note",
+    "Trig chan",
+    "WAV load",0
+};
+
+/** # functions */
+
+/** @brief function to control main menu navigation */
+void        mainMenu_draw();
+/** @brief function to control edit menu navigation */
+void        editMenu_draw();
+/**
+@namespace drawMenu
+@brief draws menu to LCD, and returns selected value
+@param array[] - menu map to be drawn
+ */
+int         drawMenu(const char* array[]);
+/**
+@namespace drawVariable
+@brief draws variable to LCD
+@param variableName - name of variable being edited
+@param variable  - pointer to variable being edited
+@param step_size - amount to increment variable per buttonpress
+@param max - maximum value of variable
+@param min - minimum value of variable
+@param function - function to be called to update variables
+ */
+void        drawVariable(const char* variableName,float *variable, float step_size, float max, float min, void (*function)());
+
+/** @} */ // end of group9
+
+/** @defgroup group10 Filesystem
+ *  Variables and functions used to control file management
+ *  (only partially functional)
+ *  @{
+ */
+/** # IO */
+
+/** @brief IO for SD card interfacting */
+SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); //SD card
+
+/** # Functions */
+
+/** @brief loads current sequence data from SD card */
+void        load();
+/** @brief saves current sequence data to SD card */
+void        save();
+
+/** @} */ // end of group10
+
+/** @defgroup group11 general
+ *  General purpose variables and functions
+ *  @{
+ */
+
+/** # IO */
+
+/** @brief speaker output */
+AnalogOut   SOUND_OUT_1(DAC0_OUT);
+/** @brief trigger channels */
+DigitalOut  *trigOut[7] {
+    new     DigitalOut(PTC10),
+    new     DigitalOut(PTC11),
+    new     DigitalOut(PTC1),
+    new     DigitalOut(PTC19),
+    new     DigitalOut(PTC18),
+    new     DigitalOut(PTC17),
+    new     DigitalOut(PTC16)
+};
+
+/** # functions */
+
+/** @brief initialises system */
+void        init();
+/** @brief initialises general IO*/
+void        IO_init();
+/**
+@namespace bool_to_int
+@brief converts boolean array to integer
+@param array - boolean input
+@param shifter - integer output
+ */
+int         bool_to_int(bool *array, int shifter);
+/**
+@namespace selector
+@brief selects value between 0 and 7 based on step button press
+@param flag - flag to reset after selection is made
+@param shifter - variable to be changed
+ */
+void        selector(bool *flag, int *variable);
+
+/** @brief checks interrupt flags */
+void        check_flags();
+/** @brief null function; used to pad drawVariable when no repeated function call is needed
+void        null();
+
+/** @} */ // end of group11
+
+#endif