diff --git a/NuEVI/FilterOnePole.cpp b/NuEVI/FilterOnePole.cpp old mode 100644 new mode 100755 diff --git a/NuEVI/FilterOnePole.h b/NuEVI/FilterOnePole.h old mode 100644 new mode 100755 diff --git a/NuEVI/NuEVI.ino b/NuEVI/NuEVI.ino index c7a06fe..aa86838 100644 --- a/NuEVI/NuEVI.ino +++ b/NuEVI/NuEVI.ino @@ -90,6 +90,9 @@ unsigned short levelCC; // 0-127 unsigned short levelVal; // 0-127 unsigned short fingering; // 0-4 EWI,EWX,SAX,EVI,EVR unsigned short lpinky3; // 0-25 (OFF, -12 - MOD - +12) +unsigned short batteryType; // 0-2 ALK,NIM,LIP +unsigned short harmSetting; // 0-7 +unsigned short harmSelect; // 0-4 unsigned short vibSens = 2; // vibrato sensitivity unsigned short vibRetn = 2; // vibrato return speed @@ -128,6 +131,10 @@ int calOffsetRH[12] = {-88,-68,-31,13,4,120,121,-68,-85,-34,23,87}; int calOffsetLH[12] = {90,-13,-33,-93,-82,115,118,2,4,-40,-75,-94}; #endif +int battMeasured[50]; +int battAvg = 0; +byte battCheckPos = 0; + // the following variables are unsigned longs because the time, measured in // milliseconds, will quickly become a bigger number than can be stored in an int. @@ -194,6 +201,8 @@ byte extracIsOn=0; int oldextrac=0; int oldextrac2=0; +int harmonics = 0; + int pitchBend=8192; int oldpb=8192; int vibSignal=0; @@ -255,6 +264,12 @@ const byte saxFingerMatch[17][11] = {0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2}, // C# (-0 semis) }; +const int harmonicResult[5][7] = {{ 0, 7, 12, 16, 19, 22, 24 }, //HRM + { 0, 7, 12, 19, 24, 31, 36 }, //5TH + { 0, 12, 24, 36, 48, 60, 72 }, //OCT + { 0, -5, -12, -17, -24, -29, -36 }, //5DN + { 0, -12, -24, -36, -48, -60, -72 }}; //ODN + const int saxFingerResult[17] = {-14, -13, -12, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -3, -2, -1, 0}; byte saxFinger[11]; @@ -472,7 +487,7 @@ void setup() { showVersion(); - delay(1500); + delay(1400); } mainState = NOTE_OFF; // initialize main state machine @@ -486,6 +501,10 @@ void setup() { midiSendControlChange(levelCC, levelVal); } + for (int i=0; i<50; i++){ + battMeasured[i] = analogRead(vMeterPin); + delay(1); + } activeMIDIchannel = MIDIchannel; midiInitialize(MIDIchannel); @@ -941,6 +960,7 @@ void loop() { #else if (gateOpenEnable || gateOpen) doorKnobCheck(); #endif + battCheck(); if (((pinkySetting == LVL) || (pinkySetting == LVLP) || (pinkySetting == GLD)) && pinkyKey && (mainState == NOTE_OFF)){ // show LVL indication } else updateSensorLEDs(); @@ -1225,6 +1245,17 @@ void doorKnobCheck() { //*********************************************************** +void battCheck(){ + battMeasured[battCheckPos] = analogRead(vMeterPin); + battAvg = 0; + for (int i=0; i<50; i++){ + battAvg += battMeasured[i]; + } + battAvg /= 50; + battCheckPos++; + if (battCheckPos == 50) battCheckPos = 0; +} + void extraController() { bool CC2sw = false; bool CC1sw = false; @@ -1254,11 +1285,28 @@ void extraController() { CC2sw = false; CC1sw = true; } + } else if (pinkySetting == ECH){ + if (pinkyKey){ + //extra controller harmonics only + CC2sw = false; + CC1sw = false; + } else { + //send extra controller primary CC only + CC2sw = false; + CC1sw = true; + } } else { //send both primary CC and CC2 CC2sw = true; CC1sw = true; } + + if ((harmSetting && (pinkySetting != ECH)) || ((pinkySetting == ECH) && pinkyKey)){ + harmonics = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 0, harmSetting); + } else if ((pinkySetting == ECH) && !pinkyKey) { + harmonics = 0; + } + if ((extraCT || extraCT2) && (exSensor >= extracThrVal)) { // if we are enabled and over the threshold, send data if (!extracIsOn) { extracIsOn = 1; @@ -1544,7 +1592,7 @@ void readSwitches() { + (6-octaveR)*12; //Octave rollers, reversed } - int fingeredNoteRead = fingeredNoteUntransposed + transpose - 12 + qTransp; + int fingeredNoteRead = fingeredNoteUntransposed + transpose - 12 + qTransp + harmonicResult[harmSelect][harmonics]; //lip sensor harmonics if (pinkyKey) pitchlatch = fingeredNoteUntransposed; //use pitchlatch to make settings based on note fingered @@ -1603,7 +1651,7 @@ void readSwitches() { if (4 == trill3_interval) fingeredNoteUntransposed+=2; else fingeredNoteUntransposed+=4; } - int fingeredNoteRead = fingeredNoteUntransposed + (octave - 3) * 12 + transpose - 12 + qTransp; + int fingeredNoteRead = fingeredNoteUntransposed + (octave - 3) * 12 + transpose - 12 + qTransp + harmonicResult[harmSelect][harmonics]; //lip sensor harmonics pcCombo1 = (K1 && K5 && !K2 && !K3); pcCombo2 = (K2 && K6 && !K1 && !K3); diff --git a/NuEVI/adjustmenu.cpp b/NuEVI/adjustmenu.cpp old mode 100644 new mode 100755 diff --git a/NuEVI/config.h b/NuEVI/config.h index 7446711..cce0f9f 100644 --- a/NuEVI/config.h +++ b/NuEVI/config.h @@ -5,7 +5,7 @@ // Compile options, comment/uncomment to change -#define FIRMWARE_VERSION "1.4.5" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<< +#define FIRMWARE_VERSION "1.4.6" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<< #define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak) #define CCN_Port 5 // Controller number for portamento level @@ -38,6 +38,15 @@ #define MIN_LED_BRIGHTNESS 5 // lowest PWM value that still is visible #define BREATH_LED_BRIGHTNESS 500 // up to 4095, PWM #define PORTAM_LED_BRIGHTNESS 500 // up to 4095, PWM +#define EXTCON_LED_BRIGHTNESS 500 // up to 4095, PWM +#define SPCKEY_LED_BRIGHTNESS 500 // up to 4095, PWM + +#define ALK_BAT_FULL 2800 // about 4.6V +#define NMH_BAT_FULL 2350 // about 3.8V +#define LIP_BAT_FULL 2550 // about 4.2V +#define ALK_BAT_LOW 2300 // about 3.8V +#define NMH_BAT_LOW 2200 // about 3.6V +#define LIP_BAT_LOW 2250 // about 3.7V #endif diff --git a/NuEVI/globals.h b/NuEVI/globals.h index 4500802..de565cb 100644 --- a/NuEVI/globals.h +++ b/NuEVI/globals.h @@ -25,6 +25,7 @@ #define LVL 27 #define LVLP 28 #define GLD 29 +#define ECH 30 #define MOD 13 @@ -85,6 +86,9 @@ extern unsigned short levelCC; // 0-127 extern unsigned short levelVal; // 0-127 extern unsigned short fingering; // 0-4 EWI,EWX,SAX,EVI,EVR extern unsigned short lpinky3; // 0-25 (OFF, -12 - MOD - +12) +extern unsigned short batteryType; // 0-2 ALK,NIM,LIP +extern unsigned short harmSetting; // 0-7 +extern unsigned short harmSelect; // 0-4 extern uint16_t gateOpenEnable; extern uint16_t specialKeyEnable; extern byte rotatorOn; @@ -134,6 +138,8 @@ extern int vibZeroBite; extern int vibThrBite; extern int vibThrBiteLo; +extern int battAvg; + extern int breathLevel; extern byte portIsOn; extern int oldport; diff --git a/NuEVI/hardware.h b/NuEVI/hardware.h index a704660..e777da1 100644 --- a/NuEVI/hardware.h +++ b/NuEVI/hardware.h @@ -2,7 +2,7 @@ #define __HARDWARE_H #define REVB -#define NURAD +//#define NURAD #if defined(NURAD) //NuRAD <<<<<<<<<<<<<<<<<<<<<<< diff --git a/NuEVI/led.cpp b/NuEVI/led.cpp old mode 100644 new mode 100755 diff --git a/NuEVI/led.h b/NuEVI/led.h old mode 100644 new mode 100755 diff --git a/NuEVI/menu.cpp b/NuEVI/menu.cpp index f9f237e..33eb3e2 100644 --- a/NuEVI/menu.cpp +++ b/NuEVI/menu.cpp @@ -202,6 +202,31 @@ extern const MenuPage mainMenuPage; // Forward declaration. #define OLED_RESET 4 Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET); +int drawBatt(int x,int y){ + display.drawRect(x+1,y,3,3,WHITE); + display.drawRect(x,y+2,5,12,WHITE); + int bar=0; + int vMeterReading = battAvg; + switch (batteryType){ + case 0: + bar = constrain((10 *(vMeterReading - ALK_BAT_LOW)) / (ALK_BAT_FULL - ALK_BAT_LOW),0,10); + break; + case 1: + bar = constrain((10 * (vMeterReading - NMH_BAT_LOW)) / (NMH_BAT_FULL - NMH_BAT_LOW),0,10); + break; + case 2: + bar = constrain((10 *(vMeterReading - LIP_BAT_LOW)) / (LIP_BAT_FULL - LIP_BAT_LOW),0,10); + } + display.fillRect(x+1,y+13-bar,3,constrain(bar,0,10),WHITE); + return bar; +} + +void drawFlash(int x, int y){ + display.drawLine(x+5,y,x,y+6,WHITE); + display.drawLine(x,y+6,x+5,y+6,WHITE); + display.drawLine(x,y+12,x+5,y+6,WHITE); +} + void initDisplay() { // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) @@ -375,12 +400,23 @@ static void mainTitleGetStr(char* out) { char* splice1 = menuTitle + 13; char* splice2 = menuTitle + 17; - int vMeterReading = analogRead(vMeterPin); - memcpy(splice1, (vMeterReading > 3000) ? "USB" : "BAT", 3); - if (vMeterReading < 2294) { + int vMeterReading = battAvg; + memcpy(splice1, (vMeterReading > 3020) ? "USB" : "BAT", 3); + int vLowLimit; + switch (batteryType){ + case 0: + vLowLimit = ALK_BAT_LOW; + break; + case 1: + vLowLimit = NMH_BAT_LOW; + break; + case 2: + vLowLimit = LIP_BAT_LOW; + } + if (vMeterReading < vLowLimit) { //2300 alkaline, 2250 lipo, 2200 nimh memcpy(splice2, "LOW ", 4); } else { - int voltage = map(vMeterReading,0,3030,0,50); + int voltage = map(vMeterReading,2200,3060,36,50); splice2[0] = (voltage/10)+'0'; splice2[2] = (voltage%10)+'0'; } @@ -705,12 +741,28 @@ const MenuEntrySub wlChannelMenu = { , nullptr }; +// Battery type menu +const MenuEntrySub batteryTypeMenu = { + MenuType::ESub, "BAT TYPE", "BAT TYPE", &batteryType, 0, 2, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused, char* out, const char** __unused unit) { + const char* breathCCMenuLabels[] = { "ALK", "NMH", "LIP" }; + strncpy(out, breathCCMenuLabels[batteryType], 4); + }, + [](const MenuEntrySub & __unused sub){ + if (readSetting(BATTYPE_ADDR) != batteryType) { + writeSetting(BATTYPE_ADDR,batteryType); + } + } + , nullptr +}; + #if defined(NURAD) const MenuEntry* extrasMenuEntries[] = { (MenuEntry*)&legacyPBMenu, (MenuEntry*)&legacyBRMenu, (MenuEntry*)&specialKeyMenu, (MenuEntry*)&dacModeMenu, + (MenuEntry*)&batteryTypeMenu, (MenuEntry*)&fastBootMenu, (MenuEntry*)&wlPowerMenu, (MenuEntry*)&wlChannelMenu, @@ -724,6 +776,7 @@ const MenuEntry* extrasMenuEntries[] = { (MenuEntry*)&trill3Menu, (MenuEntry*)&bcasModeMenu, (MenuEntry*)&dacModeMenu, + (MenuEntry*)&batteryTypeMenu, (MenuEntry*)&fastBootMenu, (MenuEntry*)&wlPowerMenu, (MenuEntry*)&wlChannelMenu, @@ -786,7 +839,7 @@ const MenuPage mainMenuPage = { // Breath menu const MenuEntrySub breathCCMenu = { - MenuType::ESub, "BRTH CC1", "BRTH CC1", &breathCC, 0, 10, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "BRTH CC A", "BRTH CC A", &breathCC, 0, 10, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused, char* out, const char** __unused unit) { const char* breathCCMenuLabels[] = { "OFF", "MW", "BR", "VL", "EX", "MW+", "BR+", "VL+", "EX+", "CF", "UNO" }; @@ -802,7 +855,7 @@ const MenuEntrySub breathCCMenu = { }; const MenuEntrySub breathCC2Menu = { - MenuType::ESub, "BRTH CC2", "BRTH CC2", &breathCC2, 0, 127, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "BRTH CC B", "BRTH CC B", &breathCC2, 0, 127, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused, char* out, const char** __unused unit) { if(breathCC2) numToString(breathCC2, out); else strncpy(out, "OFF", 4); @@ -817,7 +870,7 @@ const MenuEntrySub breathCC2Menu = { }; const MenuEntrySub breathCC2RiseMenu = { - MenuType::ESub, "CC2 RISE", "CC2 RISE", &breathCC2Rise, 1, 10, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "CC B RISE", "CC B RISE", &breathCC2Rise, 1, 10, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused, char *out, const char** label) { numToString(breathCC2Rise, out); *label = "X"; @@ -940,7 +993,7 @@ const MenuEntrySub pitchBendMenu = { }; const MenuEntrySub extraMenu = { - MenuType::ESub, "EXTRA CTR", "EXTRA CTR", &extraCT, 0,4, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "EXCT CC A", "EXCT CC A", &extraCT, 0,4, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused,char* out, const char** __unused unit) { const char* extraMenuLabels[] = { "OFF", "MW", "FP", "CF", "SP" }; strncpy(out, extraMenuLabels[extraCT], 12); @@ -950,7 +1003,7 @@ const MenuEntrySub extraMenu = { }; const MenuEntrySub extraCC2Menu = { - MenuType::ESub, "EXCTR CC2", "EXCTR CC2", &extraCT2, 0, 127, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "EXCT CC B", "EXCT CC B", &extraCT2, 0, 127, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused, char* out, const char** __unused unit) { if(extraCT2) numToString(extraCT2, out); else strncpy(out, "OFF", 4); @@ -959,6 +1012,30 @@ const MenuEntrySub extraCC2Menu = { , nullptr }; +const MenuEntrySub harmonicsMenu = { + MenuType::ESub, "EXCT HARM", "HARM RANGE", &harmSetting, 0, 6, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused, char* out, const char** __unused unit) { + if(harmSetting) numToString(harmSetting, out); + else strncpy(out, "OFF", 4); + }, +[](const MenuEntrySub & __unused sub) { writeSetting(HARMSET_ADDR,harmSetting); } + , nullptr +}; + +const MenuEntrySub harmSelectMenu = { + MenuType::ESub, "HARM SEL", "SERIES", &harmSelect, 0, 4, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused, char* out, const char** __unused unit) { + const char* harmSelectMenuLabels[] = { "HMS", "5TH", "OCT", "5DN", "ODN" }; + strncpy(out, harmSelectMenuLabels[harmSelect], 4); + }, + [](const MenuEntrySub & __unused sub){ + if (readSetting(HARMSEL_ADDR) != harmSelect) { + writeSetting(HARMSEL_ADDR,harmSelect); + } + } + , nullptr +}; + const MenuEntryStateCh vibratoSubMenu = { MenuType::EStateChange, "VIBRATO", VIBRATO_MENU }; const MenuEntrySub deglitchMenu = { @@ -976,25 +1053,27 @@ const MenuEntrySub deglitchMenu = { #if defined(NURAD) const MenuEntrySub pinkyMenu = { - MenuType::ESub, "MOD KEY", "MOD KEY", &pinkySetting, 0, 29, MenuEntryFlags::ENone, + MenuType::ESub, "MOD KEY", "MOD KEY", &pinkySetting, 0, 30, MenuEntryFlags::ENone, [](SubMenuRef __unused,char* textBuffer, const char** __unused unit) { #else const MenuEntrySub pinkyMenu = { - MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 29, MenuEntryFlags::ENone, + MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 30, MenuEntryFlags::ENone, [](SubMenuRef __unused,char* textBuffer, const char** __unused unit) { #endif if (pinkySetting == PBD) strncpy(textBuffer, "PBD", 4); else if (pinkySetting == EC2) - strncpy(textBuffer, "EC2", 4); + strncpy(textBuffer, "ECB", 4); else if (pinkySetting == ECSW) strncpy(textBuffer, "ECS", 4); else if (pinkySetting == LVL) strncpy(textBuffer, "LVL", 4); else if (pinkySetting == LVLP) strncpy(textBuffer, "LVP", 4); - else if (pinkySetting == GLD) + else if (pinkySetting == GLD) strncpy(textBuffer, "GLD", 4); + else if (pinkySetting == ECH) + strncpy(textBuffer, "ECH", 4); else numToString(pinkySetting-12, textBuffer, true); }, @@ -1040,6 +1119,8 @@ const MenuEntry* controlMenuEntries[] = { (MenuEntry*)&portMenu, (MenuEntry*)&extraMenu, (MenuEntry*)&extraCC2Menu, + (MenuEntry*)&harmonicsMenu, + (MenuEntry*)&harmSelectMenu, (MenuEntry*)&vibratoSubMenu, (MenuEntry*)°litchMenu, (MenuEntry*)&pinkyMenu, @@ -1053,6 +1134,8 @@ const MenuEntry* controlMenuEntries[] = { (MenuEntry*)&portMenu, (MenuEntry*)&extraMenu, (MenuEntry*)&extraCC2Menu, + (MenuEntry*)&harmonicsMenu, + (MenuEntry*)&harmSelectMenu, (MenuEntry*)&vibratoSubMenu, (MenuEntry*)°litchMenu, (MenuEntry*)&pinkyMenu, @@ -1193,7 +1276,7 @@ const MenuPageCustom aboutMenuPage = { nullptr, EMenuPageCustom, static uint32_t timer = 0; if(stateFirstRun) { display.clearDisplay(); - timer = timeNow + 3000; + timer = timeNow + 3500; stateFirstRun = 0; display.setCursor(49,0); display.setTextColor(WHITE); @@ -1206,6 +1289,49 @@ const MenuPageCustom aboutMenuPage = { nullptr, EMenuPageCustom, display.setCursor(16,12); display.print("firmware v."); display.println(FIRMWARE_VERSION); + int vMeterReading = battAvg; + int voltage = map(vMeterReading,2200,3060,36,50); + display.setCursor(16,32); + if (vMeterReading > 3020){ + drawFlash(4,34); + display.print("USB power"); + display.setCursor(16,42); + display.print(voltage/10); + display.print("."); + display.print(voltage%10); + display.print("v"); + } else { + int bar = drawBatt(4,34); + if (0 == batteryType) { + display.println("Alkaline battery"); + display.setCursor(16,42); + display.print(bar); + display.print("0 % at "); + display.print(voltage/10); + display.print("."); + display.print(voltage%10); + display.print("v"); + } else if (1 == batteryType) { + display.println("NiMH battery"); + display.setCursor(16,42); + display.print(bar); + display.print("0 % at "); + display.print(voltage/10); + display.print("."); + display.print(voltage%10); + display.print("v"); + } else if (2 == batteryType) { + display.println("LiPo battery"); + display.setCursor(16,42); + display.print(bar); + display.print("0 % at "); + display.print(voltage/10); + display.print("."); + display.print(voltage%10); + display.print("v"); + } + } + return true; } else { @@ -1654,6 +1780,8 @@ static KeyState readInput(uint32_t timeNow) { return keys; } + + void menu() { unsigned long timeNow = millis(); diff --git a/NuEVI/menu.h b/NuEVI/menu.h old mode 100644 new mode 100755 diff --git a/NuEVI/midi.cpp b/NuEVI/midi.cpp old mode 100644 new mode 100755 diff --git a/NuEVI/midi.h b/NuEVI/midi.h old mode 100644 new mode 100755 diff --git a/NuEVI/name.c b/NuEVI/name.c old mode 100644 new mode 100755 diff --git a/NuEVI/numenu.cpp b/NuEVI/numenu.cpp old mode 100644 new mode 100755 diff --git a/NuEVI/numenu.h b/NuEVI/numenu.h old mode 100644 new mode 100755 diff --git a/NuEVI/settings.cpp b/NuEVI/settings.cpp index ca0184b..6c8aa74 100644 --- a/NuEVI/settings.cpp +++ b/NuEVI/settings.cpp @@ -114,6 +114,12 @@ void readEEPROM(const bool factoryReset) { writeSetting(FINGER_ADDR, FINGER_FACTORY); writeSetting(LPINKY3_ADDR, LPINKY3_FACTORY); } + + if(settingsVersion < 35) { + writeSetting(BATTYPE_ADDR, BATTYPE_FACTORY); + writeSetting(HARMSET_ADDR, HARMSET_FACTORY); + writeSetting(HARMSEL_ADDR, HARMSEL_FACTORY); + } writeSetting(VERSION_ADDR, EEPROM_VERSION); } @@ -143,7 +149,7 @@ void readEEPROM(const bool factoryReset) { curve = readSettingBounded(BREATHCURVE_ADDR, 0, 12, BREATHCURVE_FACTORY); velSmpDl = readSettingBounded(VEL_SMP_DL_ADDR, 0, 30, VEL_SMP_DL_FACTORY); velBias = readSettingBounded(VEL_BIAS_ADDR, 0, 9, VEL_BIAS_FACTORY); - pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 29, PINKY_KEY_FACTORY); + pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 30, PINKY_KEY_FACTORY); fastPatch[0] = readSettingBounded(FP1_ADDR, 0, 127, 0); fastPatch[1] = readSettingBounded(FP2_ADDR, 0, 127, 0); fastPatch[2] = readSettingBounded(FP3_ADDR, 0, 127, 0); @@ -174,6 +180,9 @@ void readEEPROM(const bool factoryReset) { levelVal = readSettingBounded(LEVEL_VAL_ADDR, 0, 127, LEVEL_VAL_FACTORY); fingering = readSettingBounded(FINGER_ADDR, 0, 4, FINGER_FACTORY); lpinky3 = readSettingBounded(LPINKY3_ADDR, 0, 25, LPINKY3_FACTORY); + batteryType = readSettingBounded(BATTYPE_ADDR, 0, 2, BATTYPE_FACTORY); + harmSetting = readSettingBounded(HARMSET_ADDR, 0, 6, HARMSET_FACTORY); + harmSelect = readSettingBounded(HARMSEL_ADDR, 0, 4, HARMSEL_FACTORY); //Flags stored in bit field fastBoot = (dipSwBits & (1<