K64F drum machine, with RAW WAV sample playback, and USB midi functionality
Dependencies: FATFileSystem N5110_mod SDFileSystem USBDevice mbed
main.h
- Committer:
- el14pjgn
- Date:
- 2016-05-09
- Revision:
- 0:02a88f05d461
File content as of revision 0:02a88f05d461:
/** @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