This is a part of the Kinetiszer project.
hardware.c
- Committer:
- Clemo
- Date:
- 2014-10-28
- Revision:
- 1:8ae4ab73ca6a
- Parent:
- 0:cb80470434eb
File content as of revision 1:8ae4ab73ca6a:
#include "atmegatron.h" #include "lcd.h" #define LOCKOUT 3000 //time between ctrl stop moving and locking it out #define HOLDLENGTH 2000 //time required to hold function button for hold functions (e.g. patch save) //const uint16_t bg_select_store[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}; //values used to light single led of led array //const uint16_t bg_fill_store[16] = {1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; //values used to fill leds between 0-x of led array const uint16_t envADR_store[16] = {0,8,23,48,88,151,245,381,574,845,1217,1722,2399,3297,4476,6013}; //times used for attack, decay and release of envelopes const uchar envS_store[16] = {0,17,34,51,68,85,102,119,136,153,170,187,204,221,238,255}; //levels used for sustain of envelope1 (unipolar for amplitude) const signed char fenvS_store[16] = {0,8,17,25,34,42,51,59,68,76,85,93,102,110,119,127}; //levels used for sustain of envelope2 (bipolar for filter) const uint16_t speed_store[16] = {32767,16383,8191,6143,5460,4095,3071,2730,2047,1535,1023,767,511,383,255,127}; //values used for speeds of LFO and arpeggiator const uint16_t porta_store[16] = {0,5,14,27,46,77,123,195,306,477,740,1145,1768,2728,4207,6484}; //values for portamento speeds //lets and gets (not all letable or getable at pres) byte hard_func = 255; //current selected function. 255 to allow reset in Init_Hardware byte hard_val[16]; //current select value for each function. byte hard_ctrl[2][6]; //current value for each digital control [bank][control] boolean hard_shift[16]; //current value of shift for each function (red/green mode) //long lastval; //last value of value rotary encoder byte maxval = 15; //maximum value that is selectable on the value dial (normally 15 apart from user wave mode) boolean testbutdown = false; //test button (value encoder button) byte hard_curctrlbank = 0; //current value of ctrl bank (red/green mode of controls) byte hard_curctrl = 1; //current control being read. Only 1 control is read in each pass. read order: 0,1,0,2,0,3,0,4 etc, so cutoff is smooth as poss byte hard_nextctrl = 1; //sets next control to be read after cutoff. byte lastfuncbut = 0; //last value of function button input byte lastvalbut = 0; //last value of value button input byte lastbank = 0; //last value of ctrl bank button input byte lastctrl[6]; //last value read of each ctrl boolean movingctrl[6]; //is a ctrl moving (i.e. is user turning it) unsigned long stopmovingtick[6]; //tick when ctrl will lock out (to stop jitter) assuming user has stopped moving it unsigned long butstarttick = 0; //tick when button was pressed boolean finishedhold = false; //used by function button for function that require 2 sec hold (e.g. patch save) boolean MIDIchannelmode = false; void Hardware_Adjust_Value(byte func, byte val); void Hardware_Adjust_Shift(byte func, boolean val); boolean IsFuncFill(byte func); boolean IsShiftHold(byte func); void Hardware_Let_CtrlBank(byte value); void Hardware_Refresh_FuncBG(void); void Hardware_Refresh_ValBG(void); int Hardware_Ctrl_Update(byte shift, byte index, int value); // Here you can remap the rotary encoders in case you don't like // the way they are set up. //#define LEFT_HANDED // 0 <-> 1 // 2 <-> 7 // 3 <-> 6 // 4 <-> 5 uint8_t encoder_to_ctrl[8] = { #if defined LEFT_HANDED 0, // function encoder 1, // value encoder 2, // filter cut-off 7, // filter resonance 3, // filter envelope (red) / pitch envelope (green) 4, // filter lfo (red) / pitch lfo (green) 5, // amplitude lfo (red) / pulse width lfo (green) 6 // distortion (red) / phase lfo (green) #else 0, // function encoder 1, // value encoder 7, // filter cut-off 2, // filter resonance 6, // filter envelope (red) / pitch envelope (green) 5, // filter lfo (red) / pitch lfo (green) 4, // amplitude lfo (red) / pulse width lfo (green) 3 // distortion (red) / phase lfo (green) #endif // LEFT_HANDED }; #define ENCODER_FUNCTION encoder_to_ctrl[0] #define ENCODER_VALUE encoder_to_ctrl[1] //Hardware setup, only run once void Init_Hardware(void) { byte i; byte newctrl; //int ctrlread; memset(hard_shift,0,sizeof(hard_shift)); // Set everything to RED. Hardware_Let_Function(0); //initialise function dial to 0 //Hardware_LED_SetState(3,HIGH); //initialise value encoder LED to red //Hardware_LED_SetState(2,LOW); Hardware_BicolorLED_SetState(2,2,1); Hardware_Refresh_ValBG(); //refresh value dial LED array Hardware_Let_CtrlBank(0); //initialise ctrl bank to 0 (red mode) //READ FUNCTION ENCODER BUTTON to see if setting MIDI channel number newctrl = keyboard_get_pushbutton(ENCODER_FUNCTION,false); // If function button down, then MIDI channel mode. if (newctrl>0) { MIDIchannelmode = true; //initialise value encoder LED to yellow (woo) //Hardware_LED_SetState(3,HIGH); //Hardware_LED_SetState(2,HIGH); Hardware_BicolorLED_SetState(2,1,1); Hardware_Let_Value(FUNC_MEM,Memory_Channel_Read()); } for (i=0; i<=5; i++) { //ctrlread = analogRead(i); //initialise lastctrl array. use analogread, coz speed not important //newctrl = ctrlread >> 2; //all ctrls are stored as byte (0-255) not ints //lastctrl[i] = newctrl; lastctrl[i] = 128; // TODO: should get these values from EEPROM. } hard_curctrl = 0; } //*************POLL HARDWARE*********************** void Hardware_Poll(void) { int newval; int newfunc; int temp; //byte r; byte newbut, newfuncbut, i, newvalbut; //int newctrl; //byte diff; unsigned long butcurtick; //uint8_t low, high; uint8_t ctrl; // READ FUNCTION ENCODER newfunc = keyboard_get_rotary_encoder_value(ENCODER_FUNCTION); if (newfunc!=0) { // Grab display focus if needed. if (display_page_set(PAGE_FUNCTION)==0) { newfunc += hard_func; if (newfunc>15) newfunc = 0; else if (newfunc<0) newfunc = 15; Hardware_Let_Function(newfunc); } keyboard_set_rotary_encoder_value(ENCODER_FUNCTION,0); } /*newfunc = re3_value; if (newfunc>0) { if (hard_func==15) { // Increment function. Hardware_Let_Function(0); } else { Hardware_Let_Function(hard_func+1); } // Set encoder pulse number back to 0. re3_value = 0; } // Same as above but for anti-clockwise. else if (newfunc<0) { if (hard_func==0) { Hardware_Let_Function(15); } else { Hardware_Let_Function(hard_func-1); } // Set encoder pulse number back to 0. re3_value = 0; }*/ // READ VALUE ENCODER newval = keyboard_get_rotary_encoder_value(ENCODER_VALUE); if (newval!=0) { // Grab display focus if needed. if (display_page_set(PAGE_FUNCTION)==0) { // Has encoder moved at all? if (newval!=0) { if (testbutdown==true) { // If value encoder button is down, change test note pitch. //if (newval>lastval) if (newval>0) { MIDI_TestButtonInc(); } //if (newval<lastval) if (newval<0) { MIDI_TestButtonDec(); } //lastval = newval; } else { // Allow roll-over of all functions (forget about "fill" functions). newval += hard_val[hard_func]; if (newval>maxval) newval = 0; else if (newval<0) newval = maxval; Hardware_Let_Value(hard_func,newval); // Has encoder moved one click? /*if (newval>0) { // If not a fill function (fill functions are A,D,S,R & portamento) and value at max if (hard_val[hard_func]==maxval && IsFuncFill(hard_func)==false) { // Go back to 0. Hardware_Let_Value(hard_func,0); } // Otherwise increment value. else if (hard_val[hard_func]<maxval) { Hardware_Let_Value(hard_func,hard_val[hard_func]+1); } } else if (newval<0) { // Same as above but for anti-clockwise. if (hard_val[hard_func]==0 && IsFuncFill(hard_func)==false) { Hardware_Let_Value(hard_func,maxval); } else if (hard_val[hard_func]>0) { Hardware_Let_Value(hard_func,hard_val[hard_func]-1); } }*/ } } } keyboard_set_rotary_encoder_value(ENCODER_VALUE,0); } //READ CTRL BANK BUTTON (red/green mode) newbut = keyboard_get_pushbutton(BOARD_KEYBOARD_ISP,false); // Has a button just been pressed - do nothing on release if (lastbank!=newbut && newbut>0) { // Toggle ctrl bank. if (hard_curctrlbank==0) { Hardware_Let_CtrlBank(1); } else { Hardware_Let_CtrlBank(0); } // Set all ctrls to not moving, just in case last thing you did was move ctrl in other bank and not locked out. for (i=0; i<6; i++) { movingctrl[i] = false; stopmovingtick[i] = master_tick + LOCKOUT; } display_invalidate(); } // Store last state of button. lastbank = newbut; //READ FUNCTION ENCODER BUTTON newfuncbut = keyboard_get_pushbutton(ENCODER_FUNCTION,false); // Are we on a function that requires function button to be held (e.g. save patch)? if (IsShiftHold(hard_func)==true) { //********SAVE AND LOAD IS DONE HERE********** //button pressed down, go green and wait if (lastfuncbut==0 && newfuncbut>0) { butstarttick = master_tick; Hard_Let_Shift(hard_func, true); finishedhold = false; } //is button still held else if (lastfuncbut>0 && newfuncbut>0) { butcurtick = master_tick - butstarttick; // Has button been held down for longer than hold length? if (butcurtick>=HOLDLENGTH && finishedhold==false) { switch (hard_func) { case FUNC_WAVE: // then do userwave write Memory_UserWave_Write(hard_val[FUNC_WAVE]); break; case FUNC_AENVA: // then write patch to sysex MIDI_SYSEX_write_patch(); break; case FUNC_AENVR: // then start sysex mem dump Memory_SYSEX_write_mem(); break; case FUNC_MEM: if (MIDIchannelmode==true) { MIDI_Set_Channel(hard_val[hard_func]); } else { lcd_cursor(1,0); lcd_puts("Saving..."); SysTick_Delay(100); // then save patch Memory_Save(hard_val[hard_func]); } break; } // completed operation (to prevent refires) finishedhold = true; Hard_Let_Shift(hard_func, false); // make encoder flash Hardware_LED_StartFlash(0,7); } } // Has button been released... else if (newfuncbut==0 && Hard_Get_Shift(hard_func)==true) { butcurtick = master_tick - butstarttick; // and it's been held less time than hold length... if (butcurtick < HOLDLENGTH) { switch (hard_func) { case FUNC_WAVE: // ...then toggle user wave mode Memory_UserWave_Read(hard_val[FUNC_WAVE]); break; case FUNC_MEM: lcd_cursor(1,0); // then load patch if (Memory_Load(hard_val[hard_func])==true) { lcd_puts("Loading..."); } else { lcd_puts("Empty..."); } SysTick_Delay(100); for (i=0; i<6; i++) { // stop knob jitter from overriding loaded patch movingctrl[i] = false; } break; } } // Set shift back to false, LED red (red mode). Hard_Let_Shift(hard_func, false); } } else { // Button pressed, but not hold function. if (lastfuncbut!=newfuncbut && newfuncbut>0) { // ...then toggle shift (red/green mode) Hard_Let_Shift(hard_func, !Hard_Get_Shift(hard_func)); } } //store last button state lastfuncbut = newfuncbut; //READ VALUE ENCODER BUTTON newvalbut = keyboard_get_pushbutton(ENCODER_VALUE,false); //has button been pressed down if (lastvalbut==0 && newvalbut>0) { //midi test note on MIDI_TestButtonDown(); testbutdown = true; //reset encoder pulse, because different ranges for midi test note mode. keyboard_set_rotary_encoder_value(ENCODER_VALUE,0); //knob goes green -> cpv red //Hardware_BicolorLED_SetState(1,2,1); //Hardware_LED_SetState(2,HIGH); //Hardware_LED_SetState(3,LOW); } //has button been released if (newvalbut==0 && lastvalbut>0) { //midi test note off MIDI_TestButtonUp(); testbutdown = false; //reset encoder pulse again, to stop possible value dial jump keyboard_set_rotary_encoder_value(ENCODER_VALUE,0); //knob back to red -> cpv back to off //Hardware_BicolorLED_SetState(1,2,0); } //store last button state lastvalbut = newvalbut; // READ CTRL KNOBS ctrl = 0; // Skip Function & Value encoders. for (i=2; i<8; i++) { if (keyboard_get_pushbutton(encoder_to_ctrl[i],false)>0) { // Reset rotary encoder. Hardware_Ctrl_Update(hard_curctrlbank,ctrl,0); display_page_set(PAGE_CTRL); display_invalidate(); } temp = keyboard_get_rotary_encoder_value(encoder_to_ctrl[i]); temp *= keyboard_get_rotary_encoder_accelerator(encoder_to_ctrl[i]); if (temp!=0) { temp += Hardware_Get_Ctrl(hard_curctrlbank,ctrl); // Grab display focus if needed. if (display_page_set(PAGE_CTRL)==0) { // No page change, we can update the control. Hardware_Ctrl_Update(hard_curctrlbank,ctrl,temp); } keyboard_set_rotary_encoder_value(encoder_to_ctrl[i],0); } // Next control. ctrl += 1; } //firstly has enough time passed to lock ctrl (to prevent jitter in DA readings effecting value) /*if (master_tick >= stopmovingtick[hard_curctrl]) { movingctrl[hard_curctrl] = false; } //is reading from DA is ready if (bit_is_set(ADCSRA, ADSC)==false) { low = ADCL; high = ADCH; //new reading of ctrl newctrl = ((high << 8) | low) >> 2; //calculate difference between new reading and old if (newctrl > lastctrl[hard_curctrl]) { diff = newctrl-lastctrl[hard_curctrl]; } else { diff = lastctrl[hard_curctrl]-newctrl; } //if difference > x then ctrl is being moved. ctrl lockout sensitivity set here (default = 4) if (diff > 4) { movingctrl[hard_curctrl] = true; //ctrl is moving, so reset lockout time stopmovingtick[hard_curctrl] = master_tick + LOCKOUT; } if (movingctrl[hard_curctrl] == true) { Hardware_Let_Ctrl(hard_curctrlbank, hard_curctrl, newctrl); //pass new value to ctrl parameter lastctrl[hard_curctrl] = newctrl; //store last ctrl state } //increment current ctrl to read. order is: 0,1,0,2,0,3,0,4.. so filter cutoff ctrl is smooth if (hard_curctrl==0) { hard_curctrl = hard_nextctrl; hard_nextctrl++; if (hard_nextctrl>5) { hard_nextctrl = 1; } } else { hard_curctrl = 0; } //start DA conversion of next ctrl going ADMUX = (1 << 6) | (hard_curctrl & 0x07); sbi(ADCSRA, ADSC); }*/ //update LEDs that may be flashing //Hardware_LED_RefreshFlash(); } int Hardware_Ctrl_Update(byte shift, byte index, int value) { if (value<0) { //value = 255; value = 0; } else if (value>255) { //value = 0; value = 255; } Hardware_Let_Ctrl(shift,index,value); display_invalidate(); return value; } void Hardware_Let_Ctrl(byte shift, byte index, byte value) { switch (index) { case CTRL_FILT: //Filter Cutoff frequency (same in red and green mode) hard_ctrl[0][index] = value; hard_ctrl[1][index] = value; Filt_Let_Fc(value); break; case CTRL_Q: //Filter resonance (same in red and green mode) hard_ctrl[0][index] = value; hard_ctrl[1][index] = value; Filt_Let_Q(value); break; case CTRL_ENV: hard_ctrl[shift][index] = value; if (shift==0) { Filt_Let_FenvAmt(value); //Filter envelope amount } else { Pitch_Let_FenvAmt(value); //Pitch envelope amount } break; case CTRL_LFO: hard_ctrl[shift][index] = value; if (shift==0) { Filt_Let_LFOAmt(value); //Filter LFO amount } else { Pitch_Let_LFOAmt(value); //Pitch LFO amount } break; case CTRL_AMP: hard_ctrl[shift][index] = value; if (shift==0) { Amplitude_Let_LFOAmt(value); //Amplitude LFO amount } else { PWM_Let_LFOAmt(value>>3); //Pulse width modulation amount } break; case CTRL_FX: hard_ctrl[shift][index] = value; if (shift==0) { Distortion_Let_Amt(value>>5); //Distortion (takes values 0-7) } else { Flange_Let_LFOAmt(value>>3); //Phaser (takes values 0-31) } break; } } byte Hardware_Get_Ctrl(byte shift, byte index) { return hard_ctrl[shift][index]; } byte Hardware_Get_Ctrl_Shift(void) { return hard_curctrlbank; } //**************FUNCTION KNOB******************* //set current function void Hardware_Let_Function(byte newfunc) { if (newfunc!=hard_func) { //if new value is different to current hard_func = newfunc; display_invalidate(); //Hardware_Refresh_FuncBG(); //refresh function dial LED array //Hardware_Refresh_ValBG(); //refresh value dial LED array (to show val of new func) // Hardware_Refresh_ShiftLED(hard_func); //refresh shift (red/green) mode (to show shift mode of new func) if (hard_shift[FUNC_AENVS]==true && hard_func==FUNC_WAVE) { //set max value of value dial (normally 15) maxval = 5; } else { maxval = 15; } } } byte Hardware_Get_Function() { //get current function return hard_func; } void Hardware_Refresh_FuncBG(void) { //user_interface_print_function(hard_func,hard_shift[hard_func]); display_invalidate(); } //*************VALUE KNOB*********************** //set new value of function void Hardware_Let_Value(byte func, byte newval) { if (newval!=hard_val[func]) { //is new value different to current value hard_val[func] = newval; Hardware_Adjust_Value(func, hard_val[func]); //the meat of how the new value effects the sound if (func==hard_func) { Hardware_Refresh_ValBG(); //refresh the value dial LED array } } } void Hardware_Adjust_Value(byte func, byte val) { //the meat of how a new value effects the sound switch (func) { case FUNC_WAVE: if (hard_shift[FUNC_AENVS]==false){ //if not user wave mode Wave_Let_Table(val); //select waveform } break; case FUNC_FILT: Filt_Let_Type(val); //set filter type break; case FUNC_FENVA: Fenv_Let_A(envADR_store[val]); //set filter/pitch envelope attack time (stored in PROGMEM) break; case FUNC_FENVDR: Fenv_Let_DR(envADR_store[val]); //set filter/pitch envelope decay time break; case FUNC_FENVS: Fenv_Let_S(fenvS_store[val]); //set filter/pitch envelope sustain level break; case FUNC_AENVA: Aenv_Let_A(envADR_store[val]); //set amplitude envelope attack time break; case FUNC_AENVD: Aenv_Let_D(envADR_store[val]); //set amplitude envelope decay time break; case FUNC_AENVS: Aenv_Let_S(envS_store[val]); //set amplitude envelope sustain level break; case FUNC_AENVR: Aenv_Let_R(envADR_store[val]); //set amplitude envelope release time break; case FUNC_LFOTYPE: LFO_Let_Type(val); //select lfo waveform break; case FUNC_LFOSPEED: LFO_Let_Speed(speed_store[val]);//select lfo speed (stored in PROGMEM) break; #ifdef __HAS_ARPEGGIATOR__ case FUNC_ARPTYPE: //select arpeggiator pattern Arp_Let_Type(val); if (val==0) { // Make sure that both LEDs are on when the arpeggiator is switched off. if (Hardware_Get_Ctrl_Shift()==GREEN) { Hardware_BicolorLED_SetState(1,1,2); Hardware_BicolorLED_SetState(2,1,2); } else { Hardware_BicolorLED_SetState(1,2,1); Hardware_BicolorLED_SetState(2,2,1); } } break; case FUNC_ARPSPEED: Arp_Let_Speed(speed_store[val]); //set arpeggiator speed when free running MIDI_Let_ClockArpSpeed(speed_store[val]); //set arpeggiator speed when MIDI clock synced break; #endif // __HAS_ARPEGGIATOR__ case FUNC_PORTA: Pitch_Let_Porta(porta_store[val]); //set portamento time break; case FUNC_BITCRUSH: BitCrush_Let_Type(val); //set wave crusher setting break; case FUNC_MEM: //this is a hold function, so do nothing (patch save) break; } } void Hardware_Refresh_ValBG(void) { //user_interface_print_value(0,13,hard_val[hard_func],true); display_invalidate(); } byte Hardware_Get_Value(byte func) { return hard_val[func]; } void Hard_Let_Shift(byte func, boolean newshift) { if (newshift!=hard_shift[func]) { switch (func) { // Tie filter/pitch envelope shifts together (envelope invert mode). case FUNC_FENVA: case FUNC_FENVDR: case FUNC_FENVS: hard_shift[FUNC_FENVA] = newshift; hard_shift[FUNC_FENVDR] = newshift; hard_shift[FUNC_FENVS] = newshift; break; // Tie LFO shifts together (LFO invert mode). case FUNC_LFOTYPE: case FUNC_LFOSPEED: hard_shift[FUNC_LFOTYPE] = newshift; hard_shift[FUNC_LFOSPEED] = newshift; break; #ifdef __HAS_ARPEGGIATOR__ // Tie arpeggiator shifts together (arpeggiator ping pong mode). case FUNC_ARPTYPE: case FUNC_ARPSPEED: hard_shift[FUNC_ARPTYPE] = newshift; hard_shift[FUNC_ARPSPEED] = newshift; break; #endif // __HAS_ARPEGGIATOR__ default: hard_shift[func] = newshift; } // Meat of how shift affects sound. Hardware_Adjust_Shift(func, newshift); if (func==hard_func) { // Hardware_Refresh_ShiftLED(func); //refresh function knob LED colour Hardware_Refresh_FuncBG(); } // Update display. display_invalidate(); } } boolean Hard_Get_Shift(byte func) { return hard_shift[func]; } // Meat of how shift affects sound. void Hardware_Adjust_Shift(byte func, boolean val) { //byte i; switch (func) { case FUNC_WAVE: if (hard_shift[FUNC_AENVS]==false) { if (val==true) { Wave_Let_Bank(1); //set waveform bank } else { Wave_Let_Bank(0); } } break; case FUNC_FILT: Filt_Let_GainAdj(val); //set filter normalise mode break; case FUNC_FENVA: case FUNC_FENVDR: case FUNC_FENVS: Fenv_Let_Invert(!Fenv_Get_Invert()); //set filter/pitch envelope invert mode break; case FUNC_AENVA: //hold function, so do nothing here (SEE Hardware_Poll) break; case FUNC_AENVD: MIDI_Let_SYSEXRead(val); //set sysex read mode break; case FUNC_AENVS: Wave_Let_UserMode(val); //set user wave mode if (val==true && hard_val[FUNC_WAVE]>5) { Hardware_Let_Value(FUNC_WAVE,5); } break; case FUNC_AENVR: //hold function, so do nothing here (SEE Hardware_Poll) break; case FUNC_LFOTYPE: case FUNC_LFOSPEED: LFO_Let_Invert(val); //set LFO invert mode break; #ifdef __HAS_ARPEGGIATOR__ case FUNC_ARPTYPE: case FUNC_ARPSPEED: Arp_Let_PingPong(val); //set arpeggiator ping pong mode break; #endif // __HAS_ARPEGGIATOR__ case FUNC_PORTA: Pitch_Let_PropPorta(val); //set proportional portamento mode break; case FUNC_BITCRUSH: BitCrush_Let_PreFilt(val); //set wave crusher pre-filter mode // CPV: no break??? case FUNC_MEM: //hold function, so do nothing here (SEE Hardware_Poll) break; } } //*************CTRL BANK BUTTON*********************** //set ctrl bank (red/green mode) void Hardware_Let_CtrlBank(byte value) { hard_curctrlbank = value; //Hardware_Refresh_CtrlBankLED(); //refresh LED color Hardware_BicolorLED_SetState(1,hard_curctrlbank!=0?1:0,hard_curctrlbank==0?1:0); Hardware_BicolorLED_SetState(2,hard_curctrlbank!=0?1:0,hard_curctrlbank==0?1:0); /*if (hard_curctrlbank==0) { Hardware_BicolorLED_SetState(false,true); //Hardware_LED_SetState(2,false); //Hardware_LED_SetState(3,true); } else { Hardware_BicolorLED_SetState(true,false); //Hardware_LED_SetState(2,true); //Hardware_LED_SetState(3,false); }*/ } void Hardware_LED_SetState(byte LEDnum, byte LEDstate) { if (LEDnum==BOARD_LED2_GREEN) { // Board_LED_Set(BOARD_LED2_GREEN,LEDstate==HIGH?BOARD_LED_ON:BOARD_LED_OFF); } else if (LEDnum==BOARD_LED2_RED) { // Board_LED_Set(BOARD_LED2_RED,LEDstate==HIGH?BOARD_LED_ON:BOARD_LED_OFF); } else if (LEDnum==BOARD_LED3) { // MIDI LED. Board_LED_Set(BOARD_LED3,LEDstate); } } void Hardware_BicolorLED_SetState(uint8_t led, uint8_t green, uint8_t red) { if (led==1) { if (green<2) Board_LED_Set(BOARD_LED1_GREEN,green==1?BOARD_LED_ON:BOARD_LED_OFF); if (red<2) Board_LED_Set(BOARD_LED1_RED,red==1?BOARD_LED_ON:BOARD_LED_OFF); } else if (led==2) { if (green<2) Board_LED_Set(BOARD_LED2_GREEN,green==1?BOARD_LED_ON:BOARD_LED_OFF); if (red<2) Board_LED_Set(BOARD_LED2_RED,red==1?BOARD_LED_ON:BOARD_LED_OFF); } } void Hardware_LED_StartFlash(byte LEDnum, byte FlashTimes) { //SysTick_LED_Flash(LEDnum==0?BOARD_LED1_GREEN:BOARD_LED1_RED,10); if (LEDnum==4) { SysTick_LED_Flash(BOARD_LED3,10); } } /*boolean IsFuncFill(byte func) { //returns true for functions where value dial fills up switch (func) { case FUNC_WAVE: case FUNC_FILT: case FUNC_LFOTYPE: case FUNC_LFOSPEED: case FUNC_ARPTYPE: case FUNC_ARPSPEED: case FUNC_BITCRUSH: case FUNC_MEM: return false; break; default: return true; } }*/ boolean IsShiftHold(byte func) { //returns true for functions where encoder button should be held down switch (func) { case FUNC_WAVE: return hard_shift[FUNC_AENVS]; //break; case FUNC_AENVA: case FUNC_AENVR: case FUNC_MEM: return true; //break; default: return false; } }