K64F drum machine, with RAW WAV sample playback, and USB midi functionality
Dependencies: FATFileSystem N5110_mod SDFileSystem USBDevice mbed
Diff: main.h
- 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