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