Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FATFileSystem N5110_mod SDFileSystem USBDevice mbed
Revision 0:02a88f05d461, committed 2016-05-09
- Comitter:
- el14pjgn
- Date:
- Mon May 09 14:20:16 2016 +0000
- Commit message:
- K64F drum machine, with sample playback and USB midi functionality
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Mon May 09 14:20:16 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/FATFileSystem/#e960e2b81a3c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/N5110_mod.lib Mon May 09 14:20:16 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/ELEC2645-201516/code/N5110_mod/#d2140be00144
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Mon May 09 14:20:16 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/SDFileSystem/#7b35d1709458
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice.lib Mon May 09 14:20:16 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/USBDevice/#01321bd6ff89
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon May 09 14:20:16 2016 +0000
@@ -0,0 +1,706 @@
+# include "main.h"
+int main()
+{
+ init(); /// calls initialisation routine
+ while(1) {
+ if(USB_mode == 2) { /// prints display output for speaker mode
+ lcd.clear();
+ lcd.printString("USB audio",0,2);
+ lcd.printString("to exit,",0,3);
+ lcd.printString("press back",0,4);
+ }
+ while(USB_mode == 2) { ///loop for while within speaker mode
+ audio->read((uint8_t *)USBaudio_buffer); ///reads audio stream
+ USBaudio_packet_available = true; ///sets flag to indicate presence of data
+ if(buttons.back) { ///withdraw from speaker mode
+ USB_mode = 3; ///set USB mode to none
+ audio_tkr.detach(); ///detatch audio ticker
+ LED_scan_tkr.attach(&LED_scan_ISR,0.005); ///re-attach tickers
+ Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo);
+ buttons.back = 0; ///re-set back button flag
+ USB_init(); ///re-initialise USB
+ lcd.clear(); ///set display to normal
+ LCD_printMain();
+ }
+ }
+ check_flags(); ///check for button presses
+ sleep(); ///return to sleep mode, to save power
+ }
+}
+
+/* General functions */
+
+void init()
+{
+ LCD_init();
+ USB_init();
+ Button_init();
+ LED_init();
+ IO_init();
+ tempo_init();
+ Sequence_init();
+}
+
+void IO_init()
+{
+ for (int i = 0; i < 7; i++) {
+ trigOut[i]->write(1); /// test trigger outputs
+ wait(0.1);
+ trigOut[i]->write(0);
+ }
+}
+
+int bool_to_int(bool *array, int shifter)
+{
+ switch(shifter) {
+ case 0: /// 1:1 mapping
+ return array[15]+(array[14]*0x2)+(array[13]*0x4)+(array[12]*0x8)+(array[11]*0x10)+(array[10]*0x20)+(array[9]*0x40)+(array[8]*0x80)+(array[7]*0x100)+(array[6]*0x200)+(array[5]*0x400)+(array[4]*0x800)+(array[3]*0x1000)+(array[2]*0x2000)+(array[1]*0x4000)+(array[0]*0x8000);
+ case 1 : /// even mapping
+ return (array[7]*0x2)+(array[6]*0x8)+(array[5]*0x20)+(array[4]*0x80)+(array[3]*0x200)+(array[2]*0x800)+(array[1]*0x2000)+(array[0]*0x8000);
+ case 2: /// odd mapping
+ return array[7]+(array[6]*0x4)+(array[5]*0x10)+(array[4]*0x40)+(array[3]*0x100)+(array[2]*0x400)+(array[1]*0x1000)+(array[0]*0x4000);
+ }
+ return;
+}
+
+void selector(bool *flag, int *variable)
+{
+ for(int i=0; i<8; i++) { /// scans through input button values
+ if(buttons.steps[i]) { /// sets value if button is pressed
+ *variable = i;
+ buttons.steps[i] = 0;
+ *flag = 0;
+ lcd.clear(); ///set display to normal
+ LCD_printMain();
+ }
+ }
+}
+
+void check_flags()
+{
+ if(Seq_flag) Sequence_increment(); /// increments sequencer if flag is set
+ if(decay_flag) {
+ for(int i = 0; i<8; i++) { /// clears midi messages if decay flag is set
+ if(USB_mode == 0) midi->write(MIDIMessage::NoteOff(Seq_array[Seq_current_seq].structure.MIDI_note[i]));
+ }
+ for(int i = 0; i<7; i++) { /// clears trigger outputs if decay flag is set
+ trigOut[i]->write(0);
+ }
+ decay_tkr.detach(); /// detatches decay ticker
+ decay_flag = 0; /// clears decay flag
+ }
+ if(ButtonFlag_press) { /// run if any input buttons are pressed
+ /// prints button values over serial if available, for debugging
+ if(USB_mode == 1) pc->printf("step_0:%d step_1:%d step_2:%d step_3:%d step_4:%d step_5:%d step_6:%d step_7:%d \n",buttons.steps[0],buttons.steps[1],buttons.steps[2],buttons.steps[3],buttons.steps[4],buttons.steps[5],buttons.steps[6],buttons.steps[7]);
+ if(USB_mode == 1) pc->printf("start:%d skip:%d edit:%d pattern:%d inst:%d save:%d shift:%d load:%d back:%d down:%d enter:%d up:%d \n",buttons.start,buttons.skip,buttons.edit,buttons.pattern,buttons.inst,buttons.save,buttons.shift,buttons.load,buttons.back,buttons.down,buttons.enter,buttons.up);
+ if(buttons.shift) shift_LED = !shift_LED; /// toggles shift LED
+ buttons.shift = 0; /// clears shift button flag
+ //if(buttons.up) buttons.up = 0; /// clears unused button flags
+ //if(buttons.down) buttons.down = 0;
+ if(buttons.back) buttons.back = 0;
+ if(buttons.inst) {
+ pattern_flag = 0;
+ inst_flag = !inst_flag; /// toggles instrument selection, and updates LCD & serial
+ if(inst_flag) {
+ if(USB_mode == 1) pc->printf("instrument_select\n");
+ lcd.printString("select inst.",0,5);
+ } else {
+ lcd.clear();
+ LCD_printMain();
+ }
+ buttons.inst = 0;
+ }
+ if(buttons.pattern) { /// toggles pattern selection, and updates LCD & serial
+ inst_flag = 0;
+ pattern_flag = !pattern_flag;
+ if(pattern_flag) {
+ if(USB_mode == 1) pc->printf("pattern_select\n");
+ lcd.printString("select patrn.",0,5);
+ } else {
+ lcd.clear();
+ LCD_printMain();
+ }
+ buttons.pattern = 0;
+ }
+ if(inst_flag) selector(&inst_flag,&Seq_current_inst); /// selects current instrument if inst_flag is set
+ else if(pattern_flag) selector(&pattern_flag,&Seq_current_seq); /// selects current pattern if pattern_flag is set
+ else Sequence_write(); /// otherwise, updates sequence data
+ LED_write((Seq_array[Seq_current_seq].structure.gate[Seq_current_inst])|(0x8000>>Seq_current_step)); ///writes sequence data & position indicator to matrix
+ if(buttons.skip) {
+ if(skip_flag == 0) {
+ if(USB_mode == 1) pc->printf("skip...\n");
+ Seq_prev_inst = Seq_current_inst; /// stores current instrument, in order to return once skip setting is complete
+ Seq_current_inst = 8; /// sets sequencer channel to skip channel
+ } else {
+ if(USB_mode == 1) pc->printf("Done skip\n");
+ Seq_current_inst = Seq_prev_inst; /// returns to previous instrument
+ }
+ buttons.skip = 0;
+ skip_flag = !skip_flag;
+ LED_write((Seq_array[Seq_current_seq].structure.gate[Seq_current_inst])|(0x8000>>Seq_current_step)); ///updates LED output
+ lcd.clear(); ///re-draws display
+ LCD_printMain();
+ }
+ if(buttons.start) { ///toggles sequencer ticker
+ running? Sequence_increment_tkr.detach() : Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo);
+ lcd.printString(running? "Paused":" ",0,2);
+ running = !running;
+ if(running) Sequence_increment_ISR();
+ buttons.start = 0;
+ }
+ if(buttons.enter) { ///draws main menu
+ buttons.enter = 0;
+ mainMenu_draw();
+ }
+ if(buttons.edit) { ///draws edit menu
+ buttons.edit = 0;
+ if(skip_flag == 0) editMenu_draw();
+ }
+ if(buttons.load) { ///loads sequence from SD card
+ load();
+ buttons.load = 0;
+ }
+ if(buttons.save) { ///saves sequence to SD card
+ save();
+ buttons.save = 0;
+ }
+ ButtonFlag_press = 0; ///clears button press flag
+ }
+ if(tempo_flag) { ///runs tempo_set routine if button is pressed
+ tempo_set();
+ tempo_flag = 0;
+ }
+}
+void null() {} /// no function
+
+void USB_init() /// initialises USB mode, dependent on USB_mode value
+{
+ switch (USB_mode) {
+ case 0:
+ if(pc!=0) pc->disconnect(); /// disconnects serial, if connected
+ if(audio!=0) audio->disconnect(); /// disconnects audio, if connected
+ midi = new USBMIDI; /// connects midi
+ break;
+ case 1:
+ if(midi!=0) midi->disconnect(); /// disconnects midi, if connected
+ if(audio!=0) audio->disconnect(); /// disconnects audio, if connected
+ pc = new USBSerial; /// connects serial
+ break;
+ case 2:
+ if(pc!=0) pc->disconnect(); /// disconnects serial, if connected
+ if(midi!=0) midi->disconnect(); /// disconnects midi, if connected
+ audio = new USBAudio; /// connects audio
+ Sequence_increment_tkr.detach(); /// detatches all tickers, to maximise efficiency
+ LED_scan_tkr.detach();
+ audio_tkr.attach_us(audio_tkr_ISR, 1000000.0/(float)48000);
+ break;
+ case 3:
+ if(pc!=0) pc->disconnect(); /// disconnects serial, if connected
+ if(midi!=0) midi->disconnect(); /// disconnects midi, if connected
+ break;
+ }
+}
+void decay_ISR() /// sets decay flag if called by decay ticker
+{
+ decay_flag = 1;
+}
+
+/* Button functions */
+void Button_init() /// initialises button matrix
+{
+ Button_scan_tkr.attach(&Button_scan_ISR,0.02); ///attaches button ticker
+ ButtonIn_A.fall(&ButtonIn_A_ISR); ///connects button to ISR
+ ButtonIn_A.mode(PullUp); ///sets pullup
+ ButtonIn_B.fall(&ButtonIn_B_ISR);
+ ButtonIn_B.mode(PullUp);
+ ButtonIn_C.fall(&ButtonIn_C_ISR);
+ ButtonIn_C.mode(PullUp);
+ ButtonIn_D.fall(&ButtonIn_D_ISR);
+ ButtonIn_D.mode(PullUp);
+ ButtonIn_E.fall(&ButtonIn_E_ISR);
+ ButtonIn_E.mode(PullUp);
+}
+void Button_scan_ISR()
+{
+ if(ButtonFlag_zero == 0) ButtonFlag_cols[ButtonOut_pos] = 0; /// updates repeat flags
+ ButtonFlag_zero = 0;
+ ButtonOut_pos++; /// increments button scan position
+ if(ButtonOut_pos>3) ButtonOut_pos = 0; /// limits scan range
+ ButtonOut = ButtonOut_val[ButtonOut_pos]; /// writes to output
+}
+void ButtonIn_A_ISR()
+{
+ Button_update(0); /// updates button flags
+}
+void ButtonIn_B_ISR()
+{
+ Button_update(1); /// updates button flags
+}
+void ButtonIn_C_ISR()
+{
+ Button_update(2); /// updates button flags
+}
+void ButtonIn_D_ISR()
+{
+ Button_update(3); /// updates button flags
+}
+void ButtonIn_E_ISR()
+{
+ Button_update(4); /// updates button flags
+}
+void Button_update(int row)
+{
+ ButtonFlag_zero = 1; /// sets button flags
+ ButtonFlag_press = 1;
+ if(ButtonFlag_cols[ButtonOut_pos] == 0) {
+ *(keyMap_point[row][ButtonOut_pos]) = 1; ///sets flag pointed to by position within matrix
+ ButtonFlag_cols[ButtonOut_pos] = 1;
+ }
+}
+
+/* LED functions */
+void LED_init() ///initialises LEDs
+{
+ LED_scan_tkr.attach(&LED_scan_ISR,0.005); ///Setup matrix scan ticker
+ int LED_test[] { ///output values for test
+ 0x0,0x180,0x3c0,0x7e0,0xff0,0x1ff8,0x3ffc,0x7ffe,0xFFFF,~0x180,~0x3c0,~0x7e0,~0xff0,~0x1ff8,~0x3ffc,~0x7ffe,0x0
+ };
+ for(int j=0; j!=17; j++) { ///scan through output test values
+ LED_write(LED_test[j]);
+ wait(0.04);
+ }
+ shift_LED = 0; /// clear shift LED
+}
+void LED_scan_ISR() ///Scan ISR
+{
+ LED_bus = LED_buffer[LED_pos]; ///Sends buffer value to bus output
+ LED_pos++; ///Increment scan position
+ if(LED_pos==4) LED_pos = 0; ///limit range
+}
+void LED_write(uint16_t value) ///Matrix refresh routine
+{
+ uint8_t LED_scan_row = 0x1;
+ uint16_t LED_loadBuffer = ((value<<4) | (value>>(16-4))); ///initialise LED_loadBuffer
+ for(int i=0; i<4; i++) { ///Run loop 4 times
+ LED_buffer[i] = (~LED_loadBuffer)&0xF0|(LED_scan_row)&0xf; ///write LED_loadBuffer nibble to FSM
+ LED_scan_row=((LED_scan_row>>1) | (LED_scan_row<<(4-1))); ///Rotate row
+ LED_loadBuffer=((LED_loadBuffer<<4) | (LED_loadBuffer>>(16-4))); ///rotate LED_loadBuffer
+ };
+}
+
+/* LCD functions */
+void LCD_init() /// initialise LCD
+{
+ lcd.init();
+ LCD_set();
+ lcd.refresh();
+ lcd.printString("Drumulator",1,1); /// display bootscreen
+ lcd.printString("Ver 2.5PI",25,3);
+ wait(1);
+ lcd.clear();
+ LCD_printMain();
+}
+void LCD_set()
+{
+ lcd.setPwmFreq(PWM_freq); /// set PWM frequency (new function added to library)
+ lcd.setBrightness(brightness); /// set brightness (new function added to library)
+}
+void LCD_printMain()
+{
+ lcd.drawRect(0,0,84,16,2); /// clear upper section of the screen
+ char buffer[14]; /// set up buffer for variable printing
+ int length = sprintf(buffer,"%d bpm",int(tempo)); /// print tempo
+ if (length <= 14) {
+ lcd.printString(buffer,0,0);
+ }
+ length = sprintf(buffer,"Seq_%d",int(Seq_current_seq)); /// print sequence position
+ if (length <= 14) {
+ lcd.printString(buffer,55,0);
+ }
+ lcd.printString(inst_names[Seq_current_inst],55,1); /// print current instrument
+ length = sprintf(buffer,"Stp %d",(Seq_current_step/2)+1); /// print current step
+ if (length <= 14) {
+ lcd.printString(buffer,0,1);
+ }
+}
+
+/* Sequencer functions */
+void Sequence_init() /// initialise sequencer
+{
+ Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo);
+}
+void Sequence_increment_ISR() ///Increment sequencer position
+{
+ Seq_current_step++;
+ Seq_flag = 1;
+}
+void Sequence_increment() /// output sequence data
+{
+ if(Seq_current_step>15) Seq_current_step = 0;
+ LED_write((Seq_array[Seq_current_seq].structure.gate[Seq_current_inst])|(0x8000>>Seq_current_step)); /// update LED matrix
+ while((Seq_array[Seq_current_seq].structure.gate[8]&(0x8000>>(Seq_current_step==15? 0 : Seq_current_step+1)) )!=0) {
+ Seq_current_step++;
+ if(Seq_current_step>15) Seq_current_step = 0;
+ }
+ for(int i = 0; i<8; i++) {
+ if((Seq_array[Seq_current_seq].structure.gate[i]&(0x8000>>Seq_current_step) )!=0) {
+ switch (Seq_array[Seq_current_seq].structure.Output_type[i]) { /// update outputs
+ case 0: /// midi output
+ if(USB_mode == 0) midi->write(MIDIMessage::NoteOn(int(Seq_array[Seq_current_seq].structure.MIDI_note[i])));
+ decay_tkr.attach(&decay_ISR,0.1);
+ break;
+ case 1: /// audio output
+ audio_pos[i] = 0;
+ audio_flag[i] = 1;
+ if(USB_mode == 1) pc->printf("audio_flag %d = %d\n",i,audio_flag[i]);
+ break;
+ case 2: /// trigger output
+ trigOut[int(Seq_array[Seq_current_seq].structure.Trig_chan[i])]->write(1);
+ decay_tkr.attach(&decay_ISR,0.1);
+ break;
+ case 3: /// no output
+ break;
+ };
+ }
+ }
+ char buffer[14];
+ int length = sprintf(buffer,"Stp %d",(Seq_current_step/2)+1); /// update step position display
+ if (length <= 14) {
+ lcd.printString(buffer,0,1);
+ }
+ if(tempo_update_flag) { /// set tempo
+ Sequence_increment_tkr.detach(); ///detach increment ticker
+ Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo);
+ tempo_update_flag = 0;
+ }
+ Seq_flag = 0;
+}
+void Sequence_write() /// write button value to gate channel
+{
+ Seq_array[Seq_current_seq].structure.gate[Seq_current_inst] = Seq_array[Seq_current_seq].structure.gate[Seq_current_inst]^bool_to_int(buttons.steps,(shift_LED+1));
+ for(int i = 0; i!=8; i++) {
+ buttons.steps[i] = 0;
+ }
+}
+
+/* Tap tempo functions */
+void tempo_init() /// initialise tap tempo
+{
+ tempo_tapIn.rise(&tempo_ISR); /// attach tap input to ISR
+ tempo_time.start(); /// start timer
+}
+void tempo_ISR() //Tap tempo ISR
+{
+ tempo_flag = 1;
+}
+void tempo_set()
+{
+ if(USB_mode == 1) pc->printf("tapped...");
+ if(tempo_time.read()>(8*(tempo_timerState+1))) tempo_timerState = 0;
+ switch(tempo_timerState) {
+ case 0: ///First press (timer start)
+ if(tempo_time.read()>DEBOUNCE) { /// to prevent false triggers
+ if(USB_mode == 1) pc->printf("first tap\n");
+ tempo_time.stop(); /// reset and restart timer
+ tempo_time.reset();
+ tempo_time.start();
+ tempo_timerState++; /// Increment state variable
+ if(USB_mode == 1) pc->printf("tap tempo started!\n");
+ lcd.printString("Set tempo.",0,5);
+ }
+ break;
+ case 1: ///Second press (count)
+ if(tempo_time.read()>DEBOUNCE) { /// to prevent false triggers
+ tempo_timerState++; ///Increment state variable
+ if(USB_mode == 1) pc->printf("second tap\n");
+ tempo_debounce = tempo_time.read();
+ lcd.printString(".",59,5);
+ }
+ break;
+ case 2: ///Third press (count)
+ if((tempo_time.read()-tempo_debounce)>DEBOUNCE) { /// to prevent false triggers
+ tempo_timerState++; ///Increment state variable
+ if(USB_mode == 1) pc->printf("third tap\n");
+ tempo_debounce = tempo_time.read();
+ lcd.printString(".",64,5);
+ }
+ break;
+ case 3: ///Fourth press (Stop timer & set tempo)
+ if((tempo_time.read()-tempo_debounce)>DEBOUNCE) { /// to prevent false triggers
+ tempo_time.stop(); ///Stop timer
+ if(USB_mode == 1) pc->printf("timer stopped...");
+ tempo = (180/tempo_time.read());
+ tempo_update(); /// update tempo
+ Seq_current_step = 15;
+ LCD_printMain();
+ if(USB_mode == 1) pc->printf("tempo updated!\n");
+ tempo_time.reset();
+ tempo_time.start(); ///reset tempo timer
+ tempo_timerState = 0; ///Reset state variable
+ tempo_debounce = 0;
+ lcd.clear();
+ LCD_printMain();
+ }
+ }
+}
+void tempo_update() /// set update flag
+{
+ if(USB_mode == 1) pc->printf("tempo set...");
+ tempo_update_flag = 1;
+}
+
+/* Menu functions */
+void mainMenu_draw()
+{
+ switch(drawMenu(mainMenu)) { /// draw main menu
+ case 0:
+ drawVariable("Tempo",&tempo,5,500,1,&tempo_update); ///set tempo
+ break;
+ case 1:
+ switch(drawMenu(displayMenu)) { /// draw display menu
+ case 0:
+ drawVariable("Brightness", &brightness,0.05,1,0,&LCD_set); /// set brightness
+ break;
+ case 1:
+ drawVariable("PWM frequency", &PWM_freq,10,600,0,&LCD_set); /// set PWM frequency
+ break;
+ case 2:
+ inverse=!inverse; /// toggle screen inversion
+ if(inverse) {
+ lcd.inverseMode(); /// inverted display
+ } else {
+ lcd.normalMode(); /// normal display
+ }
+ lcd.clear(); /// reset display
+ LCD_printMain();
+ break;
+ case 3:
+ mainMenu_draw(); /// return to main menu when back button is pressed
+ };
+ break;
+ case 2:
+ USB_mode = drawMenu(usbMenu); /// select USB mode
+ USB_init();
+ break;
+ case 3:
+ break;
+ }
+ lcd.clear(); /// reset display
+ LCD_printMain();
+}
+void editMenu_draw()
+{
+ switch (drawMenu(editMenu)) { /// draw editmenu
+ case 0: /// set output type
+ Seq_array[Seq_current_seq].structure.Output_type[Seq_current_inst] = drawMenu(outputMenu);
+ break;
+ case 1: /// set note value
+ drawVariable("Note Value",&Seq_array[Seq_current_seq].structure.MIDI_note[Seq_current_inst],1,127,0,&null);
+ break;
+ case 2: /// set trigger channel
+ drawVariable("trig chan",&Seq_array[Seq_current_seq].structure.Trig_chan[Seq_current_inst],1,6,0,&null);
+ break;
+ case 3:
+ Audio_init(); /// call wave file load procedure
+ break;
+ case 4:
+ break;
+ }
+ lcd.clear(); /// reset screen
+ LCD_printMain();
+}
+int drawMenu(const char* array[]) ///draws single level menu on screen
+{
+ int size=0;
+ int pos_s=0;
+ bool data=true;
+ int menuPos=0;
+ while(data==true) { /// checks size of array
+ size++;
+ if(array[pos_s]==0) {
+ size--;
+ data = false;
+ }
+ pos_s++;
+ }
+ lcd.clear(); /// reset display
+ LCD_printMain();
+ for (int pos=0; pos<size; pos++) { ///loops through menu entries
+ lcd.printString(array[pos],0,pos+2); ///plots menu entries
+ }
+ while(1) { /// scans input flags
+ if(buttons.up) {
+ lcd.printString(" ",79,menuPos+2); /// clears menu indicator
+ (menuPos==0)? menuPos = size-1 : menuPos--; /// increments menu position
+ if(USB_mode == 1) pc->printf("menuPos %d\n",menuPos);
+ buttons.up = 0;
+ }
+ if(buttons.down) {
+ lcd.printString(" ",79,menuPos+2); /// clears menu indicator
+ (menuPos==size-1)? menuPos = 0 : menuPos++; /// decrements menu position
+ if(USB_mode == 1) pc->printf("menuPos %d\n",menuPos);
+ buttons.down = 0;
+ }
+ lcd.printString("<",79,menuPos+2); /// draw menu indicator
+ if(buttons.enter|buttons.back) { /// return
+ buttons.enter = 0;
+ buttons.back = 0;
+ lcd.clear();
+ LCD_printMain();
+ return menuPos;
+ }
+ check_flags();
+ sleep(); /// sleeps until output
+ }
+}
+
+void drawVariable(const char* variableName,float *variable, float step_size, float max, float min, void (*function)())
+{
+ char numberbuffer[14];
+ lcd.clear();
+ LCD_printMain();
+ while(1) {
+ lcd.printString(variableName,0,3); /// print variable name
+ if(buttons.up) { /// increment variable
+ *variable=*variable+step_size;
+ buttons.up = 0;
+ }
+ if(buttons.down) { /// decrement variable
+ *variable=*variable-step_size;
+ buttons.down = 0;
+ }
+ if (*variable>max) *variable = max; /// limit range
+ if (*variable<min) *variable = min;
+ int length = sprintf(numberbuffer,((*variable<0.1)&&(*variable>-0.1))? ((*variable<0)?"-%d.0%d":"%d.0%d"):((*variable<0)?"-%d.%d":"%d.%d"),abs(int(*variable)),abs(int(*variable*100-(int(*variable)*100))));
+ if (length <= 14) { /// print variable
+ lcd.printString(" ",0,4);
+ lcd.printString(numberbuffer,2,4);
+ }
+ if(buttons.enter|buttons.back) { /// return
+ buttons.enter = 0;
+ buttons.back = 0;
+ lcd.clear();
+ LCD_printMain();
+ return;
+ }
+ (*function)();
+ check_flags();
+ sleep();
+ }
+}
+
+/* File Functions */
+
+void save()
+{
+ lcd.clear(); /// reset display
+ LCD_printMain();
+ lcd.printString("saving...",0,5);
+ if(USB_mode == 1) pc->printf("saving sequence...\n");
+ Seq_array[Seq_current_seq].sequence = new char [sizeof(Seq_array[Seq_current_seq].structure)];
+ std::ofstream outfile ("/sd/sequence.mdrum",std::ofstream::binary); /// create file stream
+ outfile.seekp(0); /// set file position to zero
+ if(USB_mode == 1) pc->printf("sequence = %d\n",Seq_array[Seq_current_seq].sequence); /// output file data for debugging
+ outfile.write(Seq_array[Seq_current_seq].sequence,sizeof(Seq_array[Seq_current_seq].sequence)); /// write data to filestream
+ outfile.close(); /// close file
+ if(USB_mode == 1) pc->printf("file closed\n");
+ lcd.clear(); /// reset display
+ LCD_printMain();
+ buttons.save = 0;
+}
+
+void load()
+{
+ lcd.clear(); /// reset display
+ LCD_printMain();
+ lcd.printString("loading...",0,5);
+ if(USB_mode == 1) pc->printf("saving sequence...\n");
+ Seq_array[Seq_current_seq].sequence = new char [sizeof(Seq_array[Seq_current_seq].structure)];
+ std::ifstream infile ("/sd/sequence.mdrum",std::ifstream::binary); /// setup filestream
+ infile.seekg(0); /// set to start of file
+ infile.read(Seq_array[Seq_current_seq].sequence,sizeof(Seq_array[Seq_current_seq].sequence)); /// read file
+ infile.close(); /// close file
+ if(USB_mode == 1) pc->printf("file closed\n");
+ lcd.clear(); /// reset display
+ LCD_printMain();
+ buttons.load = 0;
+}
+
+/* USB audio functions */
+void audio_tkr_ISR() /// ticker to update USB audio output
+{
+ float speaker_value; /// speaker value
+ if (USBaudio_packet_available) { /// checks if packet is available
+ speaker_value = (float)(USBaudio_buffer[USBaudio_index_buffer]); /// converts value to float
+ speaker_value = speaker_value + 32768.0; /// ofsets speaker value
+ speaker_value *= audio->getVolume(); /// adjusts output level
+ USBaudio_index_buffer++; /// increment buffer position
+ if (USBaudio_index_buffer == 96/2) { /// checks if buffer is empty
+ USBaudio_index_buffer = 0;
+ USBaudio_packet_available = false;
+ }
+ } else {
+ speaker_value = audio_prev_val; /// sets speaker value to previous available value
+ }
+ audio_prev_val = speaker_value;
+ SOUND_OUT_1.write_u16((uint16_t)speaker_value); /// writes speaker value to analog output
+}
+
+/* audio functions */
+void Audio_init()
+{
+ if(USB_mode == 1) pc->printf("Initialising Audio file\n");
+ audio_tkr.detach();
+ lcd.clear();
+ LCD_printMain();
+ lcd.printString("loading WAVs...",0,5);
+ std::ifstream is (audioFile_map[Seq_current_inst], std::ifstream::binary);
+ if(is) { /// checks if file is present
+ if(USB_mode == 1) pc->printf("loading %s\n",audioFile_map[Seq_current_inst]);
+ is.seekg (0, is.end);
+ audio_length[Seq_current_inst] = is.tellg(); /// finds length of file
+ audio_buffer[Seq_current_inst] = new char [(audio_length[Seq_current_inst])]; /// sets buffer size
+ if(USB_mode == 1) pc->printf("length %d\n",audio_length[Seq_current_inst]);
+ is.seekg (0, is.beg);
+ is.read (audio_buffer[Seq_current_inst],audio_length[Seq_current_inst]); /// loads file into buffer
+ is.close(); /// closes file
+ }
+ if(USB_mode == 1) pc->printf("WAVs loaded\n");
+ lcd.clear();
+ LCD_printMain();
+ if(USB_mode == 1){
+ for(int i=0;i<audio_length[Seq_current_inst];i++)
+ {
+ pc->printf("%d",audio_buffer[Seq_current_inst][i]);
+ }
+ }
+ for(int i=0;i<audio_length[Seq_current_inst];i++)
+ {
+ SOUND_OUT_1 = float(int(audio_buffer[Seq_current_inst][i]))/255;
+ wait(0.00002267573);
+ }
+ audio_tkr.attach(Audio_ISR,0.00002267573);/// attaches audio update ticker
+}
+void Audio_ISR(){
+ /*if(audio_pos[Seq_current_inst]<audio_length[Seq_current_inst]){
+ SOUND_OUT_1 = float(int(audio_buffer[Seq_current_inst][audio_pos[Seq_current_inst]]))/1800;
+ audio_pos[Seq_current_inst]++;
+ }else{
+ audio_pos[Seq_current_inst] = 0;
+ }*/
+ float speaker_value; /// speaker value
+ for(int i = 0; i<8; i++){
+ if(audio_flag[i]==1) audio_pos[i]++;
+ if(audio_pos[i]>=audio_length[i]){
+ audio_pos[i] = 0;
+ audio_flag[i] = 0;
+ }
+ }
+ speaker_value = float(int(audio_buffer[0][audio_pos[0]])+int(audio_buffer[1][audio_pos[1]])+int(audio_buffer[2][audio_pos[2]])+int(audio_buffer[3][audio_pos[3]])+int(audio_buffer[4][audio_pos[4]])+int(audio_buffer[5][audio_pos[5]])+int(audio_buffer[6][audio_pos[6]])+int(audio_buffer[7][audio_pos[7]]))/1800;
+ if(speaker_value==0){
+ speaker_value = audio_prev_val;
+ }else{
+ SOUND_OUT_1 = speaker_value;
+ audio_prev_val = speaker_value;
+ }
+}
\ No newline at end of file
--- /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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon May 09 14:20:16 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/aae6fcc7d9bb \ No newline at end of file