K64F drum machine, with RAW WAV sample playback, and USB midi functionality
Dependencies: FATFileSystem N5110_mod SDFileSystem USBDevice mbed
main.cpp@0:02a88f05d461, 2016-05-09 (annotated)
- Committer:
- el14pjgn
- Date:
- Mon May 09 14:20:16 2016 +0000
- Revision:
- 0:02a88f05d461
K64F drum machine, with sample playback and USB midi functionality
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
el14pjgn | 0:02a88f05d461 | 1 | # include "main.h" |
el14pjgn | 0:02a88f05d461 | 2 | int main() |
el14pjgn | 0:02a88f05d461 | 3 | { |
el14pjgn | 0:02a88f05d461 | 4 | init(); /// calls initialisation routine |
el14pjgn | 0:02a88f05d461 | 5 | while(1) { |
el14pjgn | 0:02a88f05d461 | 6 | if(USB_mode == 2) { /// prints display output for speaker mode |
el14pjgn | 0:02a88f05d461 | 7 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 8 | lcd.printString("USB audio",0,2); |
el14pjgn | 0:02a88f05d461 | 9 | lcd.printString("to exit,",0,3); |
el14pjgn | 0:02a88f05d461 | 10 | lcd.printString("press back",0,4); |
el14pjgn | 0:02a88f05d461 | 11 | } |
el14pjgn | 0:02a88f05d461 | 12 | while(USB_mode == 2) { ///loop for while within speaker mode |
el14pjgn | 0:02a88f05d461 | 13 | audio->read((uint8_t *)USBaudio_buffer); ///reads audio stream |
el14pjgn | 0:02a88f05d461 | 14 | USBaudio_packet_available = true; ///sets flag to indicate presence of data |
el14pjgn | 0:02a88f05d461 | 15 | if(buttons.back) { ///withdraw from speaker mode |
el14pjgn | 0:02a88f05d461 | 16 | USB_mode = 3; ///set USB mode to none |
el14pjgn | 0:02a88f05d461 | 17 | audio_tkr.detach(); ///detatch audio ticker |
el14pjgn | 0:02a88f05d461 | 18 | LED_scan_tkr.attach(&LED_scan_ISR,0.005); ///re-attach tickers |
el14pjgn | 0:02a88f05d461 | 19 | Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo); |
el14pjgn | 0:02a88f05d461 | 20 | buttons.back = 0; ///re-set back button flag |
el14pjgn | 0:02a88f05d461 | 21 | USB_init(); ///re-initialise USB |
el14pjgn | 0:02a88f05d461 | 22 | lcd.clear(); ///set display to normal |
el14pjgn | 0:02a88f05d461 | 23 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 24 | } |
el14pjgn | 0:02a88f05d461 | 25 | } |
el14pjgn | 0:02a88f05d461 | 26 | check_flags(); ///check for button presses |
el14pjgn | 0:02a88f05d461 | 27 | sleep(); ///return to sleep mode, to save power |
el14pjgn | 0:02a88f05d461 | 28 | } |
el14pjgn | 0:02a88f05d461 | 29 | } |
el14pjgn | 0:02a88f05d461 | 30 | |
el14pjgn | 0:02a88f05d461 | 31 | /* General functions */ |
el14pjgn | 0:02a88f05d461 | 32 | |
el14pjgn | 0:02a88f05d461 | 33 | void init() |
el14pjgn | 0:02a88f05d461 | 34 | { |
el14pjgn | 0:02a88f05d461 | 35 | LCD_init(); |
el14pjgn | 0:02a88f05d461 | 36 | USB_init(); |
el14pjgn | 0:02a88f05d461 | 37 | Button_init(); |
el14pjgn | 0:02a88f05d461 | 38 | LED_init(); |
el14pjgn | 0:02a88f05d461 | 39 | IO_init(); |
el14pjgn | 0:02a88f05d461 | 40 | tempo_init(); |
el14pjgn | 0:02a88f05d461 | 41 | Sequence_init(); |
el14pjgn | 0:02a88f05d461 | 42 | } |
el14pjgn | 0:02a88f05d461 | 43 | |
el14pjgn | 0:02a88f05d461 | 44 | void IO_init() |
el14pjgn | 0:02a88f05d461 | 45 | { |
el14pjgn | 0:02a88f05d461 | 46 | for (int i = 0; i < 7; i++) { |
el14pjgn | 0:02a88f05d461 | 47 | trigOut[i]->write(1); /// test trigger outputs |
el14pjgn | 0:02a88f05d461 | 48 | wait(0.1); |
el14pjgn | 0:02a88f05d461 | 49 | trigOut[i]->write(0); |
el14pjgn | 0:02a88f05d461 | 50 | } |
el14pjgn | 0:02a88f05d461 | 51 | } |
el14pjgn | 0:02a88f05d461 | 52 | |
el14pjgn | 0:02a88f05d461 | 53 | int bool_to_int(bool *array, int shifter) |
el14pjgn | 0:02a88f05d461 | 54 | { |
el14pjgn | 0:02a88f05d461 | 55 | switch(shifter) { |
el14pjgn | 0:02a88f05d461 | 56 | case 0: /// 1:1 mapping |
el14pjgn | 0:02a88f05d461 | 57 | 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); |
el14pjgn | 0:02a88f05d461 | 58 | case 1 : /// even mapping |
el14pjgn | 0:02a88f05d461 | 59 | 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); |
el14pjgn | 0:02a88f05d461 | 60 | case 2: /// odd mapping |
el14pjgn | 0:02a88f05d461 | 61 | return array[7]+(array[6]*0x4)+(array[5]*0x10)+(array[4]*0x40)+(array[3]*0x100)+(array[2]*0x400)+(array[1]*0x1000)+(array[0]*0x4000); |
el14pjgn | 0:02a88f05d461 | 62 | } |
el14pjgn | 0:02a88f05d461 | 63 | return; |
el14pjgn | 0:02a88f05d461 | 64 | } |
el14pjgn | 0:02a88f05d461 | 65 | |
el14pjgn | 0:02a88f05d461 | 66 | void selector(bool *flag, int *variable) |
el14pjgn | 0:02a88f05d461 | 67 | { |
el14pjgn | 0:02a88f05d461 | 68 | for(int i=0; i<8; i++) { /// scans through input button values |
el14pjgn | 0:02a88f05d461 | 69 | if(buttons.steps[i]) { /// sets value if button is pressed |
el14pjgn | 0:02a88f05d461 | 70 | *variable = i; |
el14pjgn | 0:02a88f05d461 | 71 | buttons.steps[i] = 0; |
el14pjgn | 0:02a88f05d461 | 72 | *flag = 0; |
el14pjgn | 0:02a88f05d461 | 73 | lcd.clear(); ///set display to normal |
el14pjgn | 0:02a88f05d461 | 74 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 75 | } |
el14pjgn | 0:02a88f05d461 | 76 | } |
el14pjgn | 0:02a88f05d461 | 77 | } |
el14pjgn | 0:02a88f05d461 | 78 | |
el14pjgn | 0:02a88f05d461 | 79 | void check_flags() |
el14pjgn | 0:02a88f05d461 | 80 | { |
el14pjgn | 0:02a88f05d461 | 81 | if(Seq_flag) Sequence_increment(); /// increments sequencer if flag is set |
el14pjgn | 0:02a88f05d461 | 82 | if(decay_flag) { |
el14pjgn | 0:02a88f05d461 | 83 | for(int i = 0; i<8; i++) { /// clears midi messages if decay flag is set |
el14pjgn | 0:02a88f05d461 | 84 | if(USB_mode == 0) midi->write(MIDIMessage::NoteOff(Seq_array[Seq_current_seq].structure.MIDI_note[i])); |
el14pjgn | 0:02a88f05d461 | 85 | } |
el14pjgn | 0:02a88f05d461 | 86 | for(int i = 0; i<7; i++) { /// clears trigger outputs if decay flag is set |
el14pjgn | 0:02a88f05d461 | 87 | trigOut[i]->write(0); |
el14pjgn | 0:02a88f05d461 | 88 | } |
el14pjgn | 0:02a88f05d461 | 89 | decay_tkr.detach(); /// detatches decay ticker |
el14pjgn | 0:02a88f05d461 | 90 | decay_flag = 0; /// clears decay flag |
el14pjgn | 0:02a88f05d461 | 91 | } |
el14pjgn | 0:02a88f05d461 | 92 | if(ButtonFlag_press) { /// run if any input buttons are pressed |
el14pjgn | 0:02a88f05d461 | 93 | /// prints button values over serial if available, for debugging |
el14pjgn | 0:02a88f05d461 | 94 | 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]); |
el14pjgn | 0:02a88f05d461 | 95 | 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); |
el14pjgn | 0:02a88f05d461 | 96 | if(buttons.shift) shift_LED = !shift_LED; /// toggles shift LED |
el14pjgn | 0:02a88f05d461 | 97 | buttons.shift = 0; /// clears shift button flag |
el14pjgn | 0:02a88f05d461 | 98 | //if(buttons.up) buttons.up = 0; /// clears unused button flags |
el14pjgn | 0:02a88f05d461 | 99 | //if(buttons.down) buttons.down = 0; |
el14pjgn | 0:02a88f05d461 | 100 | if(buttons.back) buttons.back = 0; |
el14pjgn | 0:02a88f05d461 | 101 | if(buttons.inst) { |
el14pjgn | 0:02a88f05d461 | 102 | pattern_flag = 0; |
el14pjgn | 0:02a88f05d461 | 103 | inst_flag = !inst_flag; /// toggles instrument selection, and updates LCD & serial |
el14pjgn | 0:02a88f05d461 | 104 | if(inst_flag) { |
el14pjgn | 0:02a88f05d461 | 105 | if(USB_mode == 1) pc->printf("instrument_select\n"); |
el14pjgn | 0:02a88f05d461 | 106 | lcd.printString("select inst.",0,5); |
el14pjgn | 0:02a88f05d461 | 107 | } else { |
el14pjgn | 0:02a88f05d461 | 108 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 109 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 110 | } |
el14pjgn | 0:02a88f05d461 | 111 | buttons.inst = 0; |
el14pjgn | 0:02a88f05d461 | 112 | } |
el14pjgn | 0:02a88f05d461 | 113 | if(buttons.pattern) { /// toggles pattern selection, and updates LCD & serial |
el14pjgn | 0:02a88f05d461 | 114 | inst_flag = 0; |
el14pjgn | 0:02a88f05d461 | 115 | pattern_flag = !pattern_flag; |
el14pjgn | 0:02a88f05d461 | 116 | if(pattern_flag) { |
el14pjgn | 0:02a88f05d461 | 117 | if(USB_mode == 1) pc->printf("pattern_select\n"); |
el14pjgn | 0:02a88f05d461 | 118 | lcd.printString("select patrn.",0,5); |
el14pjgn | 0:02a88f05d461 | 119 | } else { |
el14pjgn | 0:02a88f05d461 | 120 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 121 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 122 | } |
el14pjgn | 0:02a88f05d461 | 123 | buttons.pattern = 0; |
el14pjgn | 0:02a88f05d461 | 124 | } |
el14pjgn | 0:02a88f05d461 | 125 | if(inst_flag) selector(&inst_flag,&Seq_current_inst); /// selects current instrument if inst_flag is set |
el14pjgn | 0:02a88f05d461 | 126 | else if(pattern_flag) selector(&pattern_flag,&Seq_current_seq); /// selects current pattern if pattern_flag is set |
el14pjgn | 0:02a88f05d461 | 127 | else Sequence_write(); /// otherwise, updates sequence data |
el14pjgn | 0:02a88f05d461 | 128 | LED_write((Seq_array[Seq_current_seq].structure.gate[Seq_current_inst])|(0x8000>>Seq_current_step)); ///writes sequence data & position indicator to matrix |
el14pjgn | 0:02a88f05d461 | 129 | if(buttons.skip) { |
el14pjgn | 0:02a88f05d461 | 130 | if(skip_flag == 0) { |
el14pjgn | 0:02a88f05d461 | 131 | if(USB_mode == 1) pc->printf("skip...\n"); |
el14pjgn | 0:02a88f05d461 | 132 | Seq_prev_inst = Seq_current_inst; /// stores current instrument, in order to return once skip setting is complete |
el14pjgn | 0:02a88f05d461 | 133 | Seq_current_inst = 8; /// sets sequencer channel to skip channel |
el14pjgn | 0:02a88f05d461 | 134 | } else { |
el14pjgn | 0:02a88f05d461 | 135 | if(USB_mode == 1) pc->printf("Done skip\n"); |
el14pjgn | 0:02a88f05d461 | 136 | Seq_current_inst = Seq_prev_inst; /// returns to previous instrument |
el14pjgn | 0:02a88f05d461 | 137 | } |
el14pjgn | 0:02a88f05d461 | 138 | buttons.skip = 0; |
el14pjgn | 0:02a88f05d461 | 139 | skip_flag = !skip_flag; |
el14pjgn | 0:02a88f05d461 | 140 | LED_write((Seq_array[Seq_current_seq].structure.gate[Seq_current_inst])|(0x8000>>Seq_current_step)); ///updates LED output |
el14pjgn | 0:02a88f05d461 | 141 | lcd.clear(); ///re-draws display |
el14pjgn | 0:02a88f05d461 | 142 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 143 | } |
el14pjgn | 0:02a88f05d461 | 144 | if(buttons.start) { ///toggles sequencer ticker |
el14pjgn | 0:02a88f05d461 | 145 | running? Sequence_increment_tkr.detach() : Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo); |
el14pjgn | 0:02a88f05d461 | 146 | lcd.printString(running? "Paused":" ",0,2); |
el14pjgn | 0:02a88f05d461 | 147 | running = !running; |
el14pjgn | 0:02a88f05d461 | 148 | if(running) Sequence_increment_ISR(); |
el14pjgn | 0:02a88f05d461 | 149 | buttons.start = 0; |
el14pjgn | 0:02a88f05d461 | 150 | } |
el14pjgn | 0:02a88f05d461 | 151 | if(buttons.enter) { ///draws main menu |
el14pjgn | 0:02a88f05d461 | 152 | buttons.enter = 0; |
el14pjgn | 0:02a88f05d461 | 153 | mainMenu_draw(); |
el14pjgn | 0:02a88f05d461 | 154 | } |
el14pjgn | 0:02a88f05d461 | 155 | if(buttons.edit) { ///draws edit menu |
el14pjgn | 0:02a88f05d461 | 156 | buttons.edit = 0; |
el14pjgn | 0:02a88f05d461 | 157 | if(skip_flag == 0) editMenu_draw(); |
el14pjgn | 0:02a88f05d461 | 158 | } |
el14pjgn | 0:02a88f05d461 | 159 | if(buttons.load) { ///loads sequence from SD card |
el14pjgn | 0:02a88f05d461 | 160 | load(); |
el14pjgn | 0:02a88f05d461 | 161 | buttons.load = 0; |
el14pjgn | 0:02a88f05d461 | 162 | } |
el14pjgn | 0:02a88f05d461 | 163 | if(buttons.save) { ///saves sequence to SD card |
el14pjgn | 0:02a88f05d461 | 164 | save(); |
el14pjgn | 0:02a88f05d461 | 165 | buttons.save = 0; |
el14pjgn | 0:02a88f05d461 | 166 | } |
el14pjgn | 0:02a88f05d461 | 167 | ButtonFlag_press = 0; ///clears button press flag |
el14pjgn | 0:02a88f05d461 | 168 | } |
el14pjgn | 0:02a88f05d461 | 169 | if(tempo_flag) { ///runs tempo_set routine if button is pressed |
el14pjgn | 0:02a88f05d461 | 170 | tempo_set(); |
el14pjgn | 0:02a88f05d461 | 171 | tempo_flag = 0; |
el14pjgn | 0:02a88f05d461 | 172 | } |
el14pjgn | 0:02a88f05d461 | 173 | } |
el14pjgn | 0:02a88f05d461 | 174 | void null() {} /// no function |
el14pjgn | 0:02a88f05d461 | 175 | |
el14pjgn | 0:02a88f05d461 | 176 | void USB_init() /// initialises USB mode, dependent on USB_mode value |
el14pjgn | 0:02a88f05d461 | 177 | { |
el14pjgn | 0:02a88f05d461 | 178 | switch (USB_mode) { |
el14pjgn | 0:02a88f05d461 | 179 | case 0: |
el14pjgn | 0:02a88f05d461 | 180 | if(pc!=0) pc->disconnect(); /// disconnects serial, if connected |
el14pjgn | 0:02a88f05d461 | 181 | if(audio!=0) audio->disconnect(); /// disconnects audio, if connected |
el14pjgn | 0:02a88f05d461 | 182 | midi = new USBMIDI; /// connects midi |
el14pjgn | 0:02a88f05d461 | 183 | break; |
el14pjgn | 0:02a88f05d461 | 184 | case 1: |
el14pjgn | 0:02a88f05d461 | 185 | if(midi!=0) midi->disconnect(); /// disconnects midi, if connected |
el14pjgn | 0:02a88f05d461 | 186 | if(audio!=0) audio->disconnect(); /// disconnects audio, if connected |
el14pjgn | 0:02a88f05d461 | 187 | pc = new USBSerial; /// connects serial |
el14pjgn | 0:02a88f05d461 | 188 | break; |
el14pjgn | 0:02a88f05d461 | 189 | case 2: |
el14pjgn | 0:02a88f05d461 | 190 | if(pc!=0) pc->disconnect(); /// disconnects serial, if connected |
el14pjgn | 0:02a88f05d461 | 191 | if(midi!=0) midi->disconnect(); /// disconnects midi, if connected |
el14pjgn | 0:02a88f05d461 | 192 | audio = new USBAudio; /// connects audio |
el14pjgn | 0:02a88f05d461 | 193 | Sequence_increment_tkr.detach(); /// detatches all tickers, to maximise efficiency |
el14pjgn | 0:02a88f05d461 | 194 | LED_scan_tkr.detach(); |
el14pjgn | 0:02a88f05d461 | 195 | audio_tkr.attach_us(audio_tkr_ISR, 1000000.0/(float)48000); |
el14pjgn | 0:02a88f05d461 | 196 | break; |
el14pjgn | 0:02a88f05d461 | 197 | case 3: |
el14pjgn | 0:02a88f05d461 | 198 | if(pc!=0) pc->disconnect(); /// disconnects serial, if connected |
el14pjgn | 0:02a88f05d461 | 199 | if(midi!=0) midi->disconnect(); /// disconnects midi, if connected |
el14pjgn | 0:02a88f05d461 | 200 | break; |
el14pjgn | 0:02a88f05d461 | 201 | } |
el14pjgn | 0:02a88f05d461 | 202 | } |
el14pjgn | 0:02a88f05d461 | 203 | void decay_ISR() /// sets decay flag if called by decay ticker |
el14pjgn | 0:02a88f05d461 | 204 | { |
el14pjgn | 0:02a88f05d461 | 205 | decay_flag = 1; |
el14pjgn | 0:02a88f05d461 | 206 | } |
el14pjgn | 0:02a88f05d461 | 207 | |
el14pjgn | 0:02a88f05d461 | 208 | /* Button functions */ |
el14pjgn | 0:02a88f05d461 | 209 | void Button_init() /// initialises button matrix |
el14pjgn | 0:02a88f05d461 | 210 | { |
el14pjgn | 0:02a88f05d461 | 211 | Button_scan_tkr.attach(&Button_scan_ISR,0.02); ///attaches button ticker |
el14pjgn | 0:02a88f05d461 | 212 | ButtonIn_A.fall(&ButtonIn_A_ISR); ///connects button to ISR |
el14pjgn | 0:02a88f05d461 | 213 | ButtonIn_A.mode(PullUp); ///sets pullup |
el14pjgn | 0:02a88f05d461 | 214 | ButtonIn_B.fall(&ButtonIn_B_ISR); |
el14pjgn | 0:02a88f05d461 | 215 | ButtonIn_B.mode(PullUp); |
el14pjgn | 0:02a88f05d461 | 216 | ButtonIn_C.fall(&ButtonIn_C_ISR); |
el14pjgn | 0:02a88f05d461 | 217 | ButtonIn_C.mode(PullUp); |
el14pjgn | 0:02a88f05d461 | 218 | ButtonIn_D.fall(&ButtonIn_D_ISR); |
el14pjgn | 0:02a88f05d461 | 219 | ButtonIn_D.mode(PullUp); |
el14pjgn | 0:02a88f05d461 | 220 | ButtonIn_E.fall(&ButtonIn_E_ISR); |
el14pjgn | 0:02a88f05d461 | 221 | ButtonIn_E.mode(PullUp); |
el14pjgn | 0:02a88f05d461 | 222 | } |
el14pjgn | 0:02a88f05d461 | 223 | void Button_scan_ISR() |
el14pjgn | 0:02a88f05d461 | 224 | { |
el14pjgn | 0:02a88f05d461 | 225 | if(ButtonFlag_zero == 0) ButtonFlag_cols[ButtonOut_pos] = 0; /// updates repeat flags |
el14pjgn | 0:02a88f05d461 | 226 | ButtonFlag_zero = 0; |
el14pjgn | 0:02a88f05d461 | 227 | ButtonOut_pos++; /// increments button scan position |
el14pjgn | 0:02a88f05d461 | 228 | if(ButtonOut_pos>3) ButtonOut_pos = 0; /// limits scan range |
el14pjgn | 0:02a88f05d461 | 229 | ButtonOut = ButtonOut_val[ButtonOut_pos]; /// writes to output |
el14pjgn | 0:02a88f05d461 | 230 | } |
el14pjgn | 0:02a88f05d461 | 231 | void ButtonIn_A_ISR() |
el14pjgn | 0:02a88f05d461 | 232 | { |
el14pjgn | 0:02a88f05d461 | 233 | Button_update(0); /// updates button flags |
el14pjgn | 0:02a88f05d461 | 234 | } |
el14pjgn | 0:02a88f05d461 | 235 | void ButtonIn_B_ISR() |
el14pjgn | 0:02a88f05d461 | 236 | { |
el14pjgn | 0:02a88f05d461 | 237 | Button_update(1); /// updates button flags |
el14pjgn | 0:02a88f05d461 | 238 | } |
el14pjgn | 0:02a88f05d461 | 239 | void ButtonIn_C_ISR() |
el14pjgn | 0:02a88f05d461 | 240 | { |
el14pjgn | 0:02a88f05d461 | 241 | Button_update(2); /// updates button flags |
el14pjgn | 0:02a88f05d461 | 242 | } |
el14pjgn | 0:02a88f05d461 | 243 | void ButtonIn_D_ISR() |
el14pjgn | 0:02a88f05d461 | 244 | { |
el14pjgn | 0:02a88f05d461 | 245 | Button_update(3); /// updates button flags |
el14pjgn | 0:02a88f05d461 | 246 | } |
el14pjgn | 0:02a88f05d461 | 247 | void ButtonIn_E_ISR() |
el14pjgn | 0:02a88f05d461 | 248 | { |
el14pjgn | 0:02a88f05d461 | 249 | Button_update(4); /// updates button flags |
el14pjgn | 0:02a88f05d461 | 250 | } |
el14pjgn | 0:02a88f05d461 | 251 | void Button_update(int row) |
el14pjgn | 0:02a88f05d461 | 252 | { |
el14pjgn | 0:02a88f05d461 | 253 | ButtonFlag_zero = 1; /// sets button flags |
el14pjgn | 0:02a88f05d461 | 254 | ButtonFlag_press = 1; |
el14pjgn | 0:02a88f05d461 | 255 | if(ButtonFlag_cols[ButtonOut_pos] == 0) { |
el14pjgn | 0:02a88f05d461 | 256 | *(keyMap_point[row][ButtonOut_pos]) = 1; ///sets flag pointed to by position within matrix |
el14pjgn | 0:02a88f05d461 | 257 | ButtonFlag_cols[ButtonOut_pos] = 1; |
el14pjgn | 0:02a88f05d461 | 258 | } |
el14pjgn | 0:02a88f05d461 | 259 | } |
el14pjgn | 0:02a88f05d461 | 260 | |
el14pjgn | 0:02a88f05d461 | 261 | /* LED functions */ |
el14pjgn | 0:02a88f05d461 | 262 | void LED_init() ///initialises LEDs |
el14pjgn | 0:02a88f05d461 | 263 | { |
el14pjgn | 0:02a88f05d461 | 264 | LED_scan_tkr.attach(&LED_scan_ISR,0.005); ///Setup matrix scan ticker |
el14pjgn | 0:02a88f05d461 | 265 | int LED_test[] { ///output values for test |
el14pjgn | 0:02a88f05d461 | 266 | 0x0,0x180,0x3c0,0x7e0,0xff0,0x1ff8,0x3ffc,0x7ffe,0xFFFF,~0x180,~0x3c0,~0x7e0,~0xff0,~0x1ff8,~0x3ffc,~0x7ffe,0x0 |
el14pjgn | 0:02a88f05d461 | 267 | }; |
el14pjgn | 0:02a88f05d461 | 268 | for(int j=0; j!=17; j++) { ///scan through output test values |
el14pjgn | 0:02a88f05d461 | 269 | LED_write(LED_test[j]); |
el14pjgn | 0:02a88f05d461 | 270 | wait(0.04); |
el14pjgn | 0:02a88f05d461 | 271 | } |
el14pjgn | 0:02a88f05d461 | 272 | shift_LED = 0; /// clear shift LED |
el14pjgn | 0:02a88f05d461 | 273 | } |
el14pjgn | 0:02a88f05d461 | 274 | void LED_scan_ISR() ///Scan ISR |
el14pjgn | 0:02a88f05d461 | 275 | { |
el14pjgn | 0:02a88f05d461 | 276 | LED_bus = LED_buffer[LED_pos]; ///Sends buffer value to bus output |
el14pjgn | 0:02a88f05d461 | 277 | LED_pos++; ///Increment scan position |
el14pjgn | 0:02a88f05d461 | 278 | if(LED_pos==4) LED_pos = 0; ///limit range |
el14pjgn | 0:02a88f05d461 | 279 | } |
el14pjgn | 0:02a88f05d461 | 280 | void LED_write(uint16_t value) ///Matrix refresh routine |
el14pjgn | 0:02a88f05d461 | 281 | { |
el14pjgn | 0:02a88f05d461 | 282 | uint8_t LED_scan_row = 0x1; |
el14pjgn | 0:02a88f05d461 | 283 | uint16_t LED_loadBuffer = ((value<<4) | (value>>(16-4))); ///initialise LED_loadBuffer |
el14pjgn | 0:02a88f05d461 | 284 | for(int i=0; i<4; i++) { ///Run loop 4 times |
el14pjgn | 0:02a88f05d461 | 285 | LED_buffer[i] = (~LED_loadBuffer)&0xF0|(LED_scan_row)&0xf; ///write LED_loadBuffer nibble to FSM |
el14pjgn | 0:02a88f05d461 | 286 | LED_scan_row=((LED_scan_row>>1) | (LED_scan_row<<(4-1))); ///Rotate row |
el14pjgn | 0:02a88f05d461 | 287 | LED_loadBuffer=((LED_loadBuffer<<4) | (LED_loadBuffer>>(16-4))); ///rotate LED_loadBuffer |
el14pjgn | 0:02a88f05d461 | 288 | }; |
el14pjgn | 0:02a88f05d461 | 289 | } |
el14pjgn | 0:02a88f05d461 | 290 | |
el14pjgn | 0:02a88f05d461 | 291 | /* LCD functions */ |
el14pjgn | 0:02a88f05d461 | 292 | void LCD_init() /// initialise LCD |
el14pjgn | 0:02a88f05d461 | 293 | { |
el14pjgn | 0:02a88f05d461 | 294 | lcd.init(); |
el14pjgn | 0:02a88f05d461 | 295 | LCD_set(); |
el14pjgn | 0:02a88f05d461 | 296 | lcd.refresh(); |
el14pjgn | 0:02a88f05d461 | 297 | lcd.printString("Drumulator",1,1); /// display bootscreen |
el14pjgn | 0:02a88f05d461 | 298 | lcd.printString("Ver 2.5PI",25,3); |
el14pjgn | 0:02a88f05d461 | 299 | wait(1); |
el14pjgn | 0:02a88f05d461 | 300 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 301 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 302 | } |
el14pjgn | 0:02a88f05d461 | 303 | void LCD_set() |
el14pjgn | 0:02a88f05d461 | 304 | { |
el14pjgn | 0:02a88f05d461 | 305 | lcd.setPwmFreq(PWM_freq); /// set PWM frequency (new function added to library) |
el14pjgn | 0:02a88f05d461 | 306 | lcd.setBrightness(brightness); /// set brightness (new function added to library) |
el14pjgn | 0:02a88f05d461 | 307 | } |
el14pjgn | 0:02a88f05d461 | 308 | void LCD_printMain() |
el14pjgn | 0:02a88f05d461 | 309 | { |
el14pjgn | 0:02a88f05d461 | 310 | lcd.drawRect(0,0,84,16,2); /// clear upper section of the screen |
el14pjgn | 0:02a88f05d461 | 311 | char buffer[14]; /// set up buffer for variable printing |
el14pjgn | 0:02a88f05d461 | 312 | int length = sprintf(buffer,"%d bpm",int(tempo)); /// print tempo |
el14pjgn | 0:02a88f05d461 | 313 | if (length <= 14) { |
el14pjgn | 0:02a88f05d461 | 314 | lcd.printString(buffer,0,0); |
el14pjgn | 0:02a88f05d461 | 315 | } |
el14pjgn | 0:02a88f05d461 | 316 | length = sprintf(buffer,"Seq_%d",int(Seq_current_seq)); /// print sequence position |
el14pjgn | 0:02a88f05d461 | 317 | if (length <= 14) { |
el14pjgn | 0:02a88f05d461 | 318 | lcd.printString(buffer,55,0); |
el14pjgn | 0:02a88f05d461 | 319 | } |
el14pjgn | 0:02a88f05d461 | 320 | lcd.printString(inst_names[Seq_current_inst],55,1); /// print current instrument |
el14pjgn | 0:02a88f05d461 | 321 | length = sprintf(buffer,"Stp %d",(Seq_current_step/2)+1); /// print current step |
el14pjgn | 0:02a88f05d461 | 322 | if (length <= 14) { |
el14pjgn | 0:02a88f05d461 | 323 | lcd.printString(buffer,0,1); |
el14pjgn | 0:02a88f05d461 | 324 | } |
el14pjgn | 0:02a88f05d461 | 325 | } |
el14pjgn | 0:02a88f05d461 | 326 | |
el14pjgn | 0:02a88f05d461 | 327 | /* Sequencer functions */ |
el14pjgn | 0:02a88f05d461 | 328 | void Sequence_init() /// initialise sequencer |
el14pjgn | 0:02a88f05d461 | 329 | { |
el14pjgn | 0:02a88f05d461 | 330 | Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo); |
el14pjgn | 0:02a88f05d461 | 331 | } |
el14pjgn | 0:02a88f05d461 | 332 | void Sequence_increment_ISR() ///Increment sequencer position |
el14pjgn | 0:02a88f05d461 | 333 | { |
el14pjgn | 0:02a88f05d461 | 334 | Seq_current_step++; |
el14pjgn | 0:02a88f05d461 | 335 | Seq_flag = 1; |
el14pjgn | 0:02a88f05d461 | 336 | } |
el14pjgn | 0:02a88f05d461 | 337 | void Sequence_increment() /// output sequence data |
el14pjgn | 0:02a88f05d461 | 338 | { |
el14pjgn | 0:02a88f05d461 | 339 | if(Seq_current_step>15) Seq_current_step = 0; |
el14pjgn | 0:02a88f05d461 | 340 | LED_write((Seq_array[Seq_current_seq].structure.gate[Seq_current_inst])|(0x8000>>Seq_current_step)); /// update LED matrix |
el14pjgn | 0:02a88f05d461 | 341 | while((Seq_array[Seq_current_seq].structure.gate[8]&(0x8000>>(Seq_current_step==15? 0 : Seq_current_step+1)) )!=0) { |
el14pjgn | 0:02a88f05d461 | 342 | Seq_current_step++; |
el14pjgn | 0:02a88f05d461 | 343 | if(Seq_current_step>15) Seq_current_step = 0; |
el14pjgn | 0:02a88f05d461 | 344 | } |
el14pjgn | 0:02a88f05d461 | 345 | for(int i = 0; i<8; i++) { |
el14pjgn | 0:02a88f05d461 | 346 | if((Seq_array[Seq_current_seq].structure.gate[i]&(0x8000>>Seq_current_step) )!=0) { |
el14pjgn | 0:02a88f05d461 | 347 | switch (Seq_array[Seq_current_seq].structure.Output_type[i]) { /// update outputs |
el14pjgn | 0:02a88f05d461 | 348 | case 0: /// midi output |
el14pjgn | 0:02a88f05d461 | 349 | if(USB_mode == 0) midi->write(MIDIMessage::NoteOn(int(Seq_array[Seq_current_seq].structure.MIDI_note[i]))); |
el14pjgn | 0:02a88f05d461 | 350 | decay_tkr.attach(&decay_ISR,0.1); |
el14pjgn | 0:02a88f05d461 | 351 | break; |
el14pjgn | 0:02a88f05d461 | 352 | case 1: /// audio output |
el14pjgn | 0:02a88f05d461 | 353 | audio_pos[i] = 0; |
el14pjgn | 0:02a88f05d461 | 354 | audio_flag[i] = 1; |
el14pjgn | 0:02a88f05d461 | 355 | if(USB_mode == 1) pc->printf("audio_flag %d = %d\n",i,audio_flag[i]); |
el14pjgn | 0:02a88f05d461 | 356 | break; |
el14pjgn | 0:02a88f05d461 | 357 | case 2: /// trigger output |
el14pjgn | 0:02a88f05d461 | 358 | trigOut[int(Seq_array[Seq_current_seq].structure.Trig_chan[i])]->write(1); |
el14pjgn | 0:02a88f05d461 | 359 | decay_tkr.attach(&decay_ISR,0.1); |
el14pjgn | 0:02a88f05d461 | 360 | break; |
el14pjgn | 0:02a88f05d461 | 361 | case 3: /// no output |
el14pjgn | 0:02a88f05d461 | 362 | break; |
el14pjgn | 0:02a88f05d461 | 363 | }; |
el14pjgn | 0:02a88f05d461 | 364 | } |
el14pjgn | 0:02a88f05d461 | 365 | } |
el14pjgn | 0:02a88f05d461 | 366 | char buffer[14]; |
el14pjgn | 0:02a88f05d461 | 367 | int length = sprintf(buffer,"Stp %d",(Seq_current_step/2)+1); /// update step position display |
el14pjgn | 0:02a88f05d461 | 368 | if (length <= 14) { |
el14pjgn | 0:02a88f05d461 | 369 | lcd.printString(buffer,0,1); |
el14pjgn | 0:02a88f05d461 | 370 | } |
el14pjgn | 0:02a88f05d461 | 371 | if(tempo_update_flag) { /// set tempo |
el14pjgn | 0:02a88f05d461 | 372 | Sequence_increment_tkr.detach(); ///detach increment ticker |
el14pjgn | 0:02a88f05d461 | 373 | Sequence_increment_tkr.attach(&Sequence_increment_ISR,30/tempo); |
el14pjgn | 0:02a88f05d461 | 374 | tempo_update_flag = 0; |
el14pjgn | 0:02a88f05d461 | 375 | } |
el14pjgn | 0:02a88f05d461 | 376 | Seq_flag = 0; |
el14pjgn | 0:02a88f05d461 | 377 | } |
el14pjgn | 0:02a88f05d461 | 378 | void Sequence_write() /// write button value to gate channel |
el14pjgn | 0:02a88f05d461 | 379 | { |
el14pjgn | 0:02a88f05d461 | 380 | 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)); |
el14pjgn | 0:02a88f05d461 | 381 | for(int i = 0; i!=8; i++) { |
el14pjgn | 0:02a88f05d461 | 382 | buttons.steps[i] = 0; |
el14pjgn | 0:02a88f05d461 | 383 | } |
el14pjgn | 0:02a88f05d461 | 384 | } |
el14pjgn | 0:02a88f05d461 | 385 | |
el14pjgn | 0:02a88f05d461 | 386 | /* Tap tempo functions */ |
el14pjgn | 0:02a88f05d461 | 387 | void tempo_init() /// initialise tap tempo |
el14pjgn | 0:02a88f05d461 | 388 | { |
el14pjgn | 0:02a88f05d461 | 389 | tempo_tapIn.rise(&tempo_ISR); /// attach tap input to ISR |
el14pjgn | 0:02a88f05d461 | 390 | tempo_time.start(); /// start timer |
el14pjgn | 0:02a88f05d461 | 391 | } |
el14pjgn | 0:02a88f05d461 | 392 | void tempo_ISR() //Tap tempo ISR |
el14pjgn | 0:02a88f05d461 | 393 | { |
el14pjgn | 0:02a88f05d461 | 394 | tempo_flag = 1; |
el14pjgn | 0:02a88f05d461 | 395 | } |
el14pjgn | 0:02a88f05d461 | 396 | void tempo_set() |
el14pjgn | 0:02a88f05d461 | 397 | { |
el14pjgn | 0:02a88f05d461 | 398 | if(USB_mode == 1) pc->printf("tapped..."); |
el14pjgn | 0:02a88f05d461 | 399 | if(tempo_time.read()>(8*(tempo_timerState+1))) tempo_timerState = 0; |
el14pjgn | 0:02a88f05d461 | 400 | switch(tempo_timerState) { |
el14pjgn | 0:02a88f05d461 | 401 | case 0: ///First press (timer start) |
el14pjgn | 0:02a88f05d461 | 402 | if(tempo_time.read()>DEBOUNCE) { /// to prevent false triggers |
el14pjgn | 0:02a88f05d461 | 403 | if(USB_mode == 1) pc->printf("first tap\n"); |
el14pjgn | 0:02a88f05d461 | 404 | tempo_time.stop(); /// reset and restart timer |
el14pjgn | 0:02a88f05d461 | 405 | tempo_time.reset(); |
el14pjgn | 0:02a88f05d461 | 406 | tempo_time.start(); |
el14pjgn | 0:02a88f05d461 | 407 | tempo_timerState++; /// Increment state variable |
el14pjgn | 0:02a88f05d461 | 408 | if(USB_mode == 1) pc->printf("tap tempo started!\n"); |
el14pjgn | 0:02a88f05d461 | 409 | lcd.printString("Set tempo.",0,5); |
el14pjgn | 0:02a88f05d461 | 410 | } |
el14pjgn | 0:02a88f05d461 | 411 | break; |
el14pjgn | 0:02a88f05d461 | 412 | case 1: ///Second press (count) |
el14pjgn | 0:02a88f05d461 | 413 | if(tempo_time.read()>DEBOUNCE) { /// to prevent false triggers |
el14pjgn | 0:02a88f05d461 | 414 | tempo_timerState++; ///Increment state variable |
el14pjgn | 0:02a88f05d461 | 415 | if(USB_mode == 1) pc->printf("second tap\n"); |
el14pjgn | 0:02a88f05d461 | 416 | tempo_debounce = tempo_time.read(); |
el14pjgn | 0:02a88f05d461 | 417 | lcd.printString(".",59,5); |
el14pjgn | 0:02a88f05d461 | 418 | } |
el14pjgn | 0:02a88f05d461 | 419 | break; |
el14pjgn | 0:02a88f05d461 | 420 | case 2: ///Third press (count) |
el14pjgn | 0:02a88f05d461 | 421 | if((tempo_time.read()-tempo_debounce)>DEBOUNCE) { /// to prevent false triggers |
el14pjgn | 0:02a88f05d461 | 422 | tempo_timerState++; ///Increment state variable |
el14pjgn | 0:02a88f05d461 | 423 | if(USB_mode == 1) pc->printf("third tap\n"); |
el14pjgn | 0:02a88f05d461 | 424 | tempo_debounce = tempo_time.read(); |
el14pjgn | 0:02a88f05d461 | 425 | lcd.printString(".",64,5); |
el14pjgn | 0:02a88f05d461 | 426 | } |
el14pjgn | 0:02a88f05d461 | 427 | break; |
el14pjgn | 0:02a88f05d461 | 428 | case 3: ///Fourth press (Stop timer & set tempo) |
el14pjgn | 0:02a88f05d461 | 429 | if((tempo_time.read()-tempo_debounce)>DEBOUNCE) { /// to prevent false triggers |
el14pjgn | 0:02a88f05d461 | 430 | tempo_time.stop(); ///Stop timer |
el14pjgn | 0:02a88f05d461 | 431 | if(USB_mode == 1) pc->printf("timer stopped..."); |
el14pjgn | 0:02a88f05d461 | 432 | tempo = (180/tempo_time.read()); |
el14pjgn | 0:02a88f05d461 | 433 | tempo_update(); /// update tempo |
el14pjgn | 0:02a88f05d461 | 434 | Seq_current_step = 15; |
el14pjgn | 0:02a88f05d461 | 435 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 436 | if(USB_mode == 1) pc->printf("tempo updated!\n"); |
el14pjgn | 0:02a88f05d461 | 437 | tempo_time.reset(); |
el14pjgn | 0:02a88f05d461 | 438 | tempo_time.start(); ///reset tempo timer |
el14pjgn | 0:02a88f05d461 | 439 | tempo_timerState = 0; ///Reset state variable |
el14pjgn | 0:02a88f05d461 | 440 | tempo_debounce = 0; |
el14pjgn | 0:02a88f05d461 | 441 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 442 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 443 | } |
el14pjgn | 0:02a88f05d461 | 444 | } |
el14pjgn | 0:02a88f05d461 | 445 | } |
el14pjgn | 0:02a88f05d461 | 446 | void tempo_update() /// set update flag |
el14pjgn | 0:02a88f05d461 | 447 | { |
el14pjgn | 0:02a88f05d461 | 448 | if(USB_mode == 1) pc->printf("tempo set..."); |
el14pjgn | 0:02a88f05d461 | 449 | tempo_update_flag = 1; |
el14pjgn | 0:02a88f05d461 | 450 | } |
el14pjgn | 0:02a88f05d461 | 451 | |
el14pjgn | 0:02a88f05d461 | 452 | /* Menu functions */ |
el14pjgn | 0:02a88f05d461 | 453 | void mainMenu_draw() |
el14pjgn | 0:02a88f05d461 | 454 | { |
el14pjgn | 0:02a88f05d461 | 455 | switch(drawMenu(mainMenu)) { /// draw main menu |
el14pjgn | 0:02a88f05d461 | 456 | case 0: |
el14pjgn | 0:02a88f05d461 | 457 | drawVariable("Tempo",&tempo,5,500,1,&tempo_update); ///set tempo |
el14pjgn | 0:02a88f05d461 | 458 | break; |
el14pjgn | 0:02a88f05d461 | 459 | case 1: |
el14pjgn | 0:02a88f05d461 | 460 | switch(drawMenu(displayMenu)) { /// draw display menu |
el14pjgn | 0:02a88f05d461 | 461 | case 0: |
el14pjgn | 0:02a88f05d461 | 462 | drawVariable("Brightness", &brightness,0.05,1,0,&LCD_set); /// set brightness |
el14pjgn | 0:02a88f05d461 | 463 | break; |
el14pjgn | 0:02a88f05d461 | 464 | case 1: |
el14pjgn | 0:02a88f05d461 | 465 | drawVariable("PWM frequency", &PWM_freq,10,600,0,&LCD_set); /// set PWM frequency |
el14pjgn | 0:02a88f05d461 | 466 | break; |
el14pjgn | 0:02a88f05d461 | 467 | case 2: |
el14pjgn | 0:02a88f05d461 | 468 | inverse=!inverse; /// toggle screen inversion |
el14pjgn | 0:02a88f05d461 | 469 | if(inverse) { |
el14pjgn | 0:02a88f05d461 | 470 | lcd.inverseMode(); /// inverted display |
el14pjgn | 0:02a88f05d461 | 471 | } else { |
el14pjgn | 0:02a88f05d461 | 472 | lcd.normalMode(); /// normal display |
el14pjgn | 0:02a88f05d461 | 473 | } |
el14pjgn | 0:02a88f05d461 | 474 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 475 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 476 | break; |
el14pjgn | 0:02a88f05d461 | 477 | case 3: |
el14pjgn | 0:02a88f05d461 | 478 | mainMenu_draw(); /// return to main menu when back button is pressed |
el14pjgn | 0:02a88f05d461 | 479 | }; |
el14pjgn | 0:02a88f05d461 | 480 | break; |
el14pjgn | 0:02a88f05d461 | 481 | case 2: |
el14pjgn | 0:02a88f05d461 | 482 | USB_mode = drawMenu(usbMenu); /// select USB mode |
el14pjgn | 0:02a88f05d461 | 483 | USB_init(); |
el14pjgn | 0:02a88f05d461 | 484 | break; |
el14pjgn | 0:02a88f05d461 | 485 | case 3: |
el14pjgn | 0:02a88f05d461 | 486 | break; |
el14pjgn | 0:02a88f05d461 | 487 | } |
el14pjgn | 0:02a88f05d461 | 488 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 489 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 490 | } |
el14pjgn | 0:02a88f05d461 | 491 | void editMenu_draw() |
el14pjgn | 0:02a88f05d461 | 492 | { |
el14pjgn | 0:02a88f05d461 | 493 | switch (drawMenu(editMenu)) { /// draw editmenu |
el14pjgn | 0:02a88f05d461 | 494 | case 0: /// set output type |
el14pjgn | 0:02a88f05d461 | 495 | Seq_array[Seq_current_seq].structure.Output_type[Seq_current_inst] = drawMenu(outputMenu); |
el14pjgn | 0:02a88f05d461 | 496 | break; |
el14pjgn | 0:02a88f05d461 | 497 | case 1: /// set note value |
el14pjgn | 0:02a88f05d461 | 498 | drawVariable("Note Value",&Seq_array[Seq_current_seq].structure.MIDI_note[Seq_current_inst],1,127,0,&null); |
el14pjgn | 0:02a88f05d461 | 499 | break; |
el14pjgn | 0:02a88f05d461 | 500 | case 2: /// set trigger channel |
el14pjgn | 0:02a88f05d461 | 501 | drawVariable("trig chan",&Seq_array[Seq_current_seq].structure.Trig_chan[Seq_current_inst],1,6,0,&null); |
el14pjgn | 0:02a88f05d461 | 502 | break; |
el14pjgn | 0:02a88f05d461 | 503 | case 3: |
el14pjgn | 0:02a88f05d461 | 504 | Audio_init(); /// call wave file load procedure |
el14pjgn | 0:02a88f05d461 | 505 | break; |
el14pjgn | 0:02a88f05d461 | 506 | case 4: |
el14pjgn | 0:02a88f05d461 | 507 | break; |
el14pjgn | 0:02a88f05d461 | 508 | } |
el14pjgn | 0:02a88f05d461 | 509 | lcd.clear(); /// reset screen |
el14pjgn | 0:02a88f05d461 | 510 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 511 | } |
el14pjgn | 0:02a88f05d461 | 512 | int drawMenu(const char* array[]) ///draws single level menu on screen |
el14pjgn | 0:02a88f05d461 | 513 | { |
el14pjgn | 0:02a88f05d461 | 514 | int size=0; |
el14pjgn | 0:02a88f05d461 | 515 | int pos_s=0; |
el14pjgn | 0:02a88f05d461 | 516 | bool data=true; |
el14pjgn | 0:02a88f05d461 | 517 | int menuPos=0; |
el14pjgn | 0:02a88f05d461 | 518 | while(data==true) { /// checks size of array |
el14pjgn | 0:02a88f05d461 | 519 | size++; |
el14pjgn | 0:02a88f05d461 | 520 | if(array[pos_s]==0) { |
el14pjgn | 0:02a88f05d461 | 521 | size--; |
el14pjgn | 0:02a88f05d461 | 522 | data = false; |
el14pjgn | 0:02a88f05d461 | 523 | } |
el14pjgn | 0:02a88f05d461 | 524 | pos_s++; |
el14pjgn | 0:02a88f05d461 | 525 | } |
el14pjgn | 0:02a88f05d461 | 526 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 527 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 528 | for (int pos=0; pos<size; pos++) { ///loops through menu entries |
el14pjgn | 0:02a88f05d461 | 529 | lcd.printString(array[pos],0,pos+2); ///plots menu entries |
el14pjgn | 0:02a88f05d461 | 530 | } |
el14pjgn | 0:02a88f05d461 | 531 | while(1) { /// scans input flags |
el14pjgn | 0:02a88f05d461 | 532 | if(buttons.up) { |
el14pjgn | 0:02a88f05d461 | 533 | lcd.printString(" ",79,menuPos+2); /// clears menu indicator |
el14pjgn | 0:02a88f05d461 | 534 | (menuPos==0)? menuPos = size-1 : menuPos--; /// increments menu position |
el14pjgn | 0:02a88f05d461 | 535 | if(USB_mode == 1) pc->printf("menuPos %d\n",menuPos); |
el14pjgn | 0:02a88f05d461 | 536 | buttons.up = 0; |
el14pjgn | 0:02a88f05d461 | 537 | } |
el14pjgn | 0:02a88f05d461 | 538 | if(buttons.down) { |
el14pjgn | 0:02a88f05d461 | 539 | lcd.printString(" ",79,menuPos+2); /// clears menu indicator |
el14pjgn | 0:02a88f05d461 | 540 | (menuPos==size-1)? menuPos = 0 : menuPos++; /// decrements menu position |
el14pjgn | 0:02a88f05d461 | 541 | if(USB_mode == 1) pc->printf("menuPos %d\n",menuPos); |
el14pjgn | 0:02a88f05d461 | 542 | buttons.down = 0; |
el14pjgn | 0:02a88f05d461 | 543 | } |
el14pjgn | 0:02a88f05d461 | 544 | lcd.printString("<",79,menuPos+2); /// draw menu indicator |
el14pjgn | 0:02a88f05d461 | 545 | if(buttons.enter|buttons.back) { /// return |
el14pjgn | 0:02a88f05d461 | 546 | buttons.enter = 0; |
el14pjgn | 0:02a88f05d461 | 547 | buttons.back = 0; |
el14pjgn | 0:02a88f05d461 | 548 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 549 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 550 | return menuPos; |
el14pjgn | 0:02a88f05d461 | 551 | } |
el14pjgn | 0:02a88f05d461 | 552 | check_flags(); |
el14pjgn | 0:02a88f05d461 | 553 | sleep(); /// sleeps until output |
el14pjgn | 0:02a88f05d461 | 554 | } |
el14pjgn | 0:02a88f05d461 | 555 | } |
el14pjgn | 0:02a88f05d461 | 556 | |
el14pjgn | 0:02a88f05d461 | 557 | void drawVariable(const char* variableName,float *variable, float step_size, float max, float min, void (*function)()) |
el14pjgn | 0:02a88f05d461 | 558 | { |
el14pjgn | 0:02a88f05d461 | 559 | char numberbuffer[14]; |
el14pjgn | 0:02a88f05d461 | 560 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 561 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 562 | while(1) { |
el14pjgn | 0:02a88f05d461 | 563 | lcd.printString(variableName,0,3); /// print variable name |
el14pjgn | 0:02a88f05d461 | 564 | if(buttons.up) { /// increment variable |
el14pjgn | 0:02a88f05d461 | 565 | *variable=*variable+step_size; |
el14pjgn | 0:02a88f05d461 | 566 | buttons.up = 0; |
el14pjgn | 0:02a88f05d461 | 567 | } |
el14pjgn | 0:02a88f05d461 | 568 | if(buttons.down) { /// decrement variable |
el14pjgn | 0:02a88f05d461 | 569 | *variable=*variable-step_size; |
el14pjgn | 0:02a88f05d461 | 570 | buttons.down = 0; |
el14pjgn | 0:02a88f05d461 | 571 | } |
el14pjgn | 0:02a88f05d461 | 572 | if (*variable>max) *variable = max; /// limit range |
el14pjgn | 0:02a88f05d461 | 573 | if (*variable<min) *variable = min; |
el14pjgn | 0:02a88f05d461 | 574 | 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)))); |
el14pjgn | 0:02a88f05d461 | 575 | if (length <= 14) { /// print variable |
el14pjgn | 0:02a88f05d461 | 576 | lcd.printString(" ",0,4); |
el14pjgn | 0:02a88f05d461 | 577 | lcd.printString(numberbuffer,2,4); |
el14pjgn | 0:02a88f05d461 | 578 | } |
el14pjgn | 0:02a88f05d461 | 579 | if(buttons.enter|buttons.back) { /// return |
el14pjgn | 0:02a88f05d461 | 580 | buttons.enter = 0; |
el14pjgn | 0:02a88f05d461 | 581 | buttons.back = 0; |
el14pjgn | 0:02a88f05d461 | 582 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 583 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 584 | return; |
el14pjgn | 0:02a88f05d461 | 585 | } |
el14pjgn | 0:02a88f05d461 | 586 | (*function)(); |
el14pjgn | 0:02a88f05d461 | 587 | check_flags(); |
el14pjgn | 0:02a88f05d461 | 588 | sleep(); |
el14pjgn | 0:02a88f05d461 | 589 | } |
el14pjgn | 0:02a88f05d461 | 590 | } |
el14pjgn | 0:02a88f05d461 | 591 | |
el14pjgn | 0:02a88f05d461 | 592 | /* File Functions */ |
el14pjgn | 0:02a88f05d461 | 593 | |
el14pjgn | 0:02a88f05d461 | 594 | void save() |
el14pjgn | 0:02a88f05d461 | 595 | { |
el14pjgn | 0:02a88f05d461 | 596 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 597 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 598 | lcd.printString("saving...",0,5); |
el14pjgn | 0:02a88f05d461 | 599 | if(USB_mode == 1) pc->printf("saving sequence...\n"); |
el14pjgn | 0:02a88f05d461 | 600 | Seq_array[Seq_current_seq].sequence = new char [sizeof(Seq_array[Seq_current_seq].structure)]; |
el14pjgn | 0:02a88f05d461 | 601 | std::ofstream outfile ("/sd/sequence.mdrum",std::ofstream::binary); /// create file stream |
el14pjgn | 0:02a88f05d461 | 602 | outfile.seekp(0); /// set file position to zero |
el14pjgn | 0:02a88f05d461 | 603 | if(USB_mode == 1) pc->printf("sequence = %d\n",Seq_array[Seq_current_seq].sequence); /// output file data for debugging |
el14pjgn | 0:02a88f05d461 | 604 | outfile.write(Seq_array[Seq_current_seq].sequence,sizeof(Seq_array[Seq_current_seq].sequence)); /// write data to filestream |
el14pjgn | 0:02a88f05d461 | 605 | outfile.close(); /// close file |
el14pjgn | 0:02a88f05d461 | 606 | if(USB_mode == 1) pc->printf("file closed\n"); |
el14pjgn | 0:02a88f05d461 | 607 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 608 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 609 | buttons.save = 0; |
el14pjgn | 0:02a88f05d461 | 610 | } |
el14pjgn | 0:02a88f05d461 | 611 | |
el14pjgn | 0:02a88f05d461 | 612 | void load() |
el14pjgn | 0:02a88f05d461 | 613 | { |
el14pjgn | 0:02a88f05d461 | 614 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 615 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 616 | lcd.printString("loading...",0,5); |
el14pjgn | 0:02a88f05d461 | 617 | if(USB_mode == 1) pc->printf("saving sequence...\n"); |
el14pjgn | 0:02a88f05d461 | 618 | Seq_array[Seq_current_seq].sequence = new char [sizeof(Seq_array[Seq_current_seq].structure)]; |
el14pjgn | 0:02a88f05d461 | 619 | std::ifstream infile ("/sd/sequence.mdrum",std::ifstream::binary); /// setup filestream |
el14pjgn | 0:02a88f05d461 | 620 | infile.seekg(0); /// set to start of file |
el14pjgn | 0:02a88f05d461 | 621 | infile.read(Seq_array[Seq_current_seq].sequence,sizeof(Seq_array[Seq_current_seq].sequence)); /// read file |
el14pjgn | 0:02a88f05d461 | 622 | infile.close(); /// close file |
el14pjgn | 0:02a88f05d461 | 623 | if(USB_mode == 1) pc->printf("file closed\n"); |
el14pjgn | 0:02a88f05d461 | 624 | lcd.clear(); /// reset display |
el14pjgn | 0:02a88f05d461 | 625 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 626 | buttons.load = 0; |
el14pjgn | 0:02a88f05d461 | 627 | } |
el14pjgn | 0:02a88f05d461 | 628 | |
el14pjgn | 0:02a88f05d461 | 629 | /* USB audio functions */ |
el14pjgn | 0:02a88f05d461 | 630 | void audio_tkr_ISR() /// ticker to update USB audio output |
el14pjgn | 0:02a88f05d461 | 631 | { |
el14pjgn | 0:02a88f05d461 | 632 | float speaker_value; /// speaker value |
el14pjgn | 0:02a88f05d461 | 633 | if (USBaudio_packet_available) { /// checks if packet is available |
el14pjgn | 0:02a88f05d461 | 634 | speaker_value = (float)(USBaudio_buffer[USBaudio_index_buffer]); /// converts value to float |
el14pjgn | 0:02a88f05d461 | 635 | speaker_value = speaker_value + 32768.0; /// ofsets speaker value |
el14pjgn | 0:02a88f05d461 | 636 | speaker_value *= audio->getVolume(); /// adjusts output level |
el14pjgn | 0:02a88f05d461 | 637 | USBaudio_index_buffer++; /// increment buffer position |
el14pjgn | 0:02a88f05d461 | 638 | if (USBaudio_index_buffer == 96/2) { /// checks if buffer is empty |
el14pjgn | 0:02a88f05d461 | 639 | USBaudio_index_buffer = 0; |
el14pjgn | 0:02a88f05d461 | 640 | USBaudio_packet_available = false; |
el14pjgn | 0:02a88f05d461 | 641 | } |
el14pjgn | 0:02a88f05d461 | 642 | } else { |
el14pjgn | 0:02a88f05d461 | 643 | speaker_value = audio_prev_val; /// sets speaker value to previous available value |
el14pjgn | 0:02a88f05d461 | 644 | } |
el14pjgn | 0:02a88f05d461 | 645 | audio_prev_val = speaker_value; |
el14pjgn | 0:02a88f05d461 | 646 | SOUND_OUT_1.write_u16((uint16_t)speaker_value); /// writes speaker value to analog output |
el14pjgn | 0:02a88f05d461 | 647 | } |
el14pjgn | 0:02a88f05d461 | 648 | |
el14pjgn | 0:02a88f05d461 | 649 | /* audio functions */ |
el14pjgn | 0:02a88f05d461 | 650 | void Audio_init() |
el14pjgn | 0:02a88f05d461 | 651 | { |
el14pjgn | 0:02a88f05d461 | 652 | if(USB_mode == 1) pc->printf("Initialising Audio file\n"); |
el14pjgn | 0:02a88f05d461 | 653 | audio_tkr.detach(); |
el14pjgn | 0:02a88f05d461 | 654 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 655 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 656 | lcd.printString("loading WAVs...",0,5); |
el14pjgn | 0:02a88f05d461 | 657 | std::ifstream is (audioFile_map[Seq_current_inst], std::ifstream::binary); |
el14pjgn | 0:02a88f05d461 | 658 | if(is) { /// checks if file is present |
el14pjgn | 0:02a88f05d461 | 659 | if(USB_mode == 1) pc->printf("loading %s\n",audioFile_map[Seq_current_inst]); |
el14pjgn | 0:02a88f05d461 | 660 | is.seekg (0, is.end); |
el14pjgn | 0:02a88f05d461 | 661 | audio_length[Seq_current_inst] = is.tellg(); /// finds length of file |
el14pjgn | 0:02a88f05d461 | 662 | audio_buffer[Seq_current_inst] = new char [(audio_length[Seq_current_inst])]; /// sets buffer size |
el14pjgn | 0:02a88f05d461 | 663 | if(USB_mode == 1) pc->printf("length %d\n",audio_length[Seq_current_inst]); |
el14pjgn | 0:02a88f05d461 | 664 | is.seekg (0, is.beg); |
el14pjgn | 0:02a88f05d461 | 665 | is.read (audio_buffer[Seq_current_inst],audio_length[Seq_current_inst]); /// loads file into buffer |
el14pjgn | 0:02a88f05d461 | 666 | is.close(); /// closes file |
el14pjgn | 0:02a88f05d461 | 667 | } |
el14pjgn | 0:02a88f05d461 | 668 | if(USB_mode == 1) pc->printf("WAVs loaded\n"); |
el14pjgn | 0:02a88f05d461 | 669 | lcd.clear(); |
el14pjgn | 0:02a88f05d461 | 670 | LCD_printMain(); |
el14pjgn | 0:02a88f05d461 | 671 | if(USB_mode == 1){ |
el14pjgn | 0:02a88f05d461 | 672 | for(int i=0;i<audio_length[Seq_current_inst];i++) |
el14pjgn | 0:02a88f05d461 | 673 | { |
el14pjgn | 0:02a88f05d461 | 674 | pc->printf("%d",audio_buffer[Seq_current_inst][i]); |
el14pjgn | 0:02a88f05d461 | 675 | } |
el14pjgn | 0:02a88f05d461 | 676 | } |
el14pjgn | 0:02a88f05d461 | 677 | for(int i=0;i<audio_length[Seq_current_inst];i++) |
el14pjgn | 0:02a88f05d461 | 678 | { |
el14pjgn | 0:02a88f05d461 | 679 | SOUND_OUT_1 = float(int(audio_buffer[Seq_current_inst][i]))/255; |
el14pjgn | 0:02a88f05d461 | 680 | wait(0.00002267573); |
el14pjgn | 0:02a88f05d461 | 681 | } |
el14pjgn | 0:02a88f05d461 | 682 | audio_tkr.attach(Audio_ISR,0.00002267573);/// attaches audio update ticker |
el14pjgn | 0:02a88f05d461 | 683 | } |
el14pjgn | 0:02a88f05d461 | 684 | void Audio_ISR(){ |
el14pjgn | 0:02a88f05d461 | 685 | /*if(audio_pos[Seq_current_inst]<audio_length[Seq_current_inst]){ |
el14pjgn | 0:02a88f05d461 | 686 | SOUND_OUT_1 = float(int(audio_buffer[Seq_current_inst][audio_pos[Seq_current_inst]]))/1800; |
el14pjgn | 0:02a88f05d461 | 687 | audio_pos[Seq_current_inst]++; |
el14pjgn | 0:02a88f05d461 | 688 | }else{ |
el14pjgn | 0:02a88f05d461 | 689 | audio_pos[Seq_current_inst] = 0; |
el14pjgn | 0:02a88f05d461 | 690 | }*/ |
el14pjgn | 0:02a88f05d461 | 691 | float speaker_value; /// speaker value |
el14pjgn | 0:02a88f05d461 | 692 | for(int i = 0; i<8; i++){ |
el14pjgn | 0:02a88f05d461 | 693 | if(audio_flag[i]==1) audio_pos[i]++; |
el14pjgn | 0:02a88f05d461 | 694 | if(audio_pos[i]>=audio_length[i]){ |
el14pjgn | 0:02a88f05d461 | 695 | audio_pos[i] = 0; |
el14pjgn | 0:02a88f05d461 | 696 | audio_flag[i] = 0; |
el14pjgn | 0:02a88f05d461 | 697 | } |
el14pjgn | 0:02a88f05d461 | 698 | } |
el14pjgn | 0:02a88f05d461 | 699 | 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; |
el14pjgn | 0:02a88f05d461 | 700 | if(speaker_value==0){ |
el14pjgn | 0:02a88f05d461 | 701 | speaker_value = audio_prev_val; |
el14pjgn | 0:02a88f05d461 | 702 | }else{ |
el14pjgn | 0:02a88f05d461 | 703 | SOUND_OUT_1 = speaker_value; |
el14pjgn | 0:02a88f05d461 | 704 | audio_prev_val = speaker_value; |
el14pjgn | 0:02a88f05d461 | 705 | } |
el14pjgn | 0:02a88f05d461 | 706 | } |