Code:
//
// Scaled down version of Teensy MIDI (12-note / 3-voice) TFT-Controlled Polyphonic Synthesizer - version 1.7 dated 20210205-1835
//
// - written by Mark J Culross (KD5RXT)
//
// - can read MIDI data & controls/commands from any of three sources:
// 1) traditional (serial) MIDI thru the MIDI DIN plugs/cables
// 1) USB MIDI (play MIDI files from PC thru this MIDI device)
// 3) connect a USB MIDI device (keyboard) the the USB Host of this device
//
// - plays the indicated note(s) in three voices, with the specified audio characteristics
//
// - appears as MIDI device "Teensy-MIDI-12-PolySynth"
//
// See documentation on MIDI callbacks here:
// https://github.com/FortySevenEffects/arduino_midi_library/wiki/Using-Callbacks
//
//
// Arduino IDE Configuration:
// Tools/Board: "Teensy 4.0"
// Tools/USB Type: "Serial"
// Tools/CPU Speed: "600MHz"
// Tools/Optimize: "Smallest Code"
// Tools/Keyboard Layout: "US English"
// Tools/Port: "COMx Serial (Teensy 4.0)"
//
String VERSION1 = "Teensy-MIDI-TFT-PolySynth";
String VERSION2 = "version 1.7 dated 02/05/2021 @1835";
String VERSION3 = "designed & written by Mark J Culross (KD5RXT)";
#define DEBUG_EEPROM_READ // uncomment to show specifics of EEPROM reads
#define DEBUG_EEPROM_WRITE // uncomment to show specifics of EEPROM writes
//#define DISABLE_EEPROM_READ_SETTINGS // uncomment to prevent reading settings from EEPROM
//#define DISABLE_EEPROM_WRITE_SETTINGS // uncomment to prevent writing settings to EEPROM
#include <ILI9341_t3n.h>
#include <XPT2046_Touchscreen.h>
#include <EEPROM.h>
// This is calibration data for mapping the raw touch data to the screen coordinates (for my particular PJRC ILI9341 TFT display)
const int TS_MINX = 200;
const int TS_MINY = 250;
const int TS_MAXX = 3750;
const int TS_MAXY = 3900;
// when used w/ Audio Adapter, must use an alternate CS pin for the display
const int TFT_CHIP_SELECT = 14;
const int TFT_DATA_COMMAND = 9;
ILI9341_t3n tft = ILI9341_t3n(TFT_CHIP_SELECT, TFT_DATA_COMMAND);
// create TFT framebuffer
DMAMEM uint16_t framebuf[320 * 240];
// when used w/ Audio Adapter, must use an alternate CS pin for the touchscreen
#define TS_CS_PIN 5
XPT2046_Touchscreen ts(TS_CS_PIN, 255);
//
// The following pins are used in this project:
//
// PIN D1 = (not used)
// PIN D2 = (not used)
// PIN D3 = (not used)
// PIN D4 = (not used)
// PIN D5 = TouchScreen chip select (alternate when used w/ audio adapter)
// PIN D6 = Audio adapter memory chip select
// PIN D7 = Audio adapter data in
// PIN D8 = Audio adapter data out
// PIN D9 = TFT/TS data/command select
// PIN D10 = Audio adapter SD card chip select
// PIN D11 = SPI MOSI (data in)
// PIN D12 = SPI MISO (data out)
// PIN D13 = SPI serial clock + on-board LED
// PIN A0 = (D14) TFT chip select (alternate when used w/ audio adapter)
// PIN A1 = Volume pot on audio adapter
// PIN A2 = (not used)
// PIN A3 = (not used)
// PIN A4 = (D18) Audio adapter SDA (I2C control data)
// PIN A5 = (D19) Audio adapter SCL (I2C control clock)
// onboard LED on pin 13
#define LED_PIN 13
// keep track of how often to repaint the display
#define SCREEN_UPDATE_MILLIS 125
unsigned long screen_update_time = millis();
// keep track of when the screen needs to be updated
bool screen_update_required = false;
// manage accumulating variable changes to reduce EEPROM writes
#define SAVE_DELAY_MILLIS 5000
unsigned long save_delay_millis = 0;
bool save_needed = false;
// custom ILI9341 TFT colors (5-bit RED, 6-bit GREEN, 5-bit BLUE)
#define ILI9341_SHADOWGREY 0x8414 // SHADOWGREY: 0x8414 = 10000 100000 10100 LIGHTGREY: 0xC618 = 11000 110000 11000
typedef enum
{
CONFIG_MODE_MAIN=0,
} CONFIG_MODE;
CONFIG_MODE config_mode = CONFIG_MODE_MAIN;
boolean previously_touched = false;
boolean touch_triggered = false;
// global touchscreen coordinates (in pixels) where touched
int BtnX, BtnY;
int previousBtnX = -1, previousBtnY = -1;
struct BUTTON_TYPE
{
unsigned int xCenterLoc;
unsigned int yCenterLoc;
unsigned int xSize;
unsigned int ySize;
String* textPtr;
uint16_t textColor;
uint16_t buttonColor;
uint16_t borderColor;
bool activated;
};
// MAIN BUTTONS
String mainVolumeButtonText = "VOL";
BUTTON_TYPE mainVolumeButton = { 16, 88, 28, 15, &mainVolumeButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainLevelAButtonText = "LvlA";
BUTTON_TYPE mainLevelAButton = { 53, 88, 28, 15, &mainLevelAButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainLevelBButtonText = "LvlB";
BUTTON_TYPE mainLevelBButton = { 90, 88, 28, 15, &mainLevelBButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainLevelCButtonText = "LvlC";
BUTTON_TYPE mainLevelCButton = {127, 88, 28, 15, &mainLevelCButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainTuningButtonText = "TUNE";
BUTTON_TYPE mainTuningButton = {189, 88, 28, 15, &mainTuningButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainTuningAButtonText = "TunA";
BUTTON_TYPE mainTuningAButton = {226, 88, 28, 15, &mainTuningAButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainTuningBButtonText = "TunB";
BUTTON_TYPE mainTuningBButton = {263, 88, 28, 15, &mainTuningBButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
String mainTuningCButtonText = "TunC";
BUTTON_TYPE mainTuningCButton = {300, 88, 28, 15, &mainTuningCButtonText, ILI9341_GREEN, ILI9341_BLACK, ILI9341_RED, true };
typedef enum
{
SLIDER_MODE_HORIZONTAL=0, SLIDER_MODE_VERTICAL
} SLIDER_MODE;
struct SLIDER_TYPE
{
unsigned int xCenterLoc;
unsigned int yCenterLoc;
unsigned int xSize;
unsigned int ySize;
float value;
unsigned int placesBeforeTheDecimal;
unsigned int placesAfterTheDecimal;
bool showPlusMinusSign;
float minValue; // for HORIZONTAL = all the way to the left, for VERTICAL, all the way up
float maxValue; // for HORIZONTAL = all the way to the right, for VERTICAL, all the way down
unsigned int xValueCenterLoc;
unsigned int yValueCenterLoc;
uint16_t valueColor;
uint16_t backgroundColor;
uint16_t borderColor;
uint16_t scaleColor;
uint16_t handleColor;
uint16_t handleBorderColor;
uint16_t backgroundColorDisabled;
uint16_t borderColorDisabled;
uint16_t scaleColorDisabled;
uint16_t handleColorDisabled;
uint16_t handleBorderColorDisabled;
bool activated;
SLIDER_MODE orientation;
};
SLIDER_TYPE mainVolumeSlider = { 16, 172, 15, 116, 1.00, 1, 1, true, 0.0, 1.0, 16, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainLevelASlider = { 53, 172, 15, 116, 0.75, 1, 1, true, 0.0, 1.0, 53, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainLevelBSlider = { 90, 172, 15, 116, 0.75, 1, 1, true, 0.0, 1.0, 90, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainLevelCSlider = { 127, 172, 15, 116, 0.75, 1, 1, true, 0.0, 1.0, 127, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainTuningSlider = { 189, 172, 15, 116, 0.00, 1, 1, true, -0.5, 0.5, 189, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainTuningASlider = { 226, 172, 15, 116, 0.00, 1, 1, true, -0.5, 0.5, 226, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainTuningBSlider = { 263, 172, 15, 116, 0.00, 1, 1, true, -0.5, 0.5, 263, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
SLIDER_TYPE mainTuningCSlider = { 300, 172, 15, 116, 0.00, 1, 1, true, -1.0, 1.0, 300, 101, ILI9341_WHITE, ILI9341_SHADOWGREY, ILI9341_GREEN, ILI9341_BLACK, ILI9341_GREEN, ILI9341_BLACK, ILI9341_BLACK, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_SHADOWGREY, ILI9341_BLACK, true, SLIDER_MODE_VERTICAL };
const char EEPROM_HEADER[] = "T12PS";
typedef enum
{
EEPROM_INDEX_HEADER_0=0, EEPROM_INDEX_HEADER_1, EEPROM_INDEX_HEADER_2, EEPROM_INDEX_HEADER_3, EEPROM_INDEX_HEADER_4,
EEPROM_INDEX_MAIN_VOLUME, EEPROM_INDEX_MAIN_LEVEL_A, EEPROM_INDEX_MAIN_LEVEL_B, EEPROM_INDEX_MAIN_LEVEL_C,
EEPROM_INDEX_MAIN_TUNING, EEPROM_INDEX_MAIN_TUNING_A, EEPROM_INDEX_MAIN_TUNING_B, EEPROM_INDEX_MAIN_TUNING_C,
EEPROM_INDEX_CHECKSUM, EEPROM_INDEX_INV_CHECKSUM
} EEPROM_INDEX;
// function headers
void centerDrawText(String text, unsigned int xCenterLoc, unsigned int yCenterLoc, uint16_t textColor, uint16_t textBackground);
bool checkButton(BUTTON_TYPE thisButton);
bool checkSlider(SLIDER_TYPE* thisSlider);
void drawButton(BUTTON_TYPE thisButton);
void drawScreen(void);
void drawSlider(SLIDER_TYPE thisSlider);
void loop();
void readSettings(void);
void saveSettings(void);
void setup();
void showIndex(int index);
// draw text, centered around xLoc & yLoc
void centerDrawText(String text, unsigned int xCenterLoc, unsigned int yCenterLoc, uint16_t textColor, uint16_t textBackground)
{
unsigned int xOffset = (text.length() / 2) * 6;
unsigned int yOffset = 3;
if (text.length() % 2)
{
xOffset += 3;
}
tft.setTextColor(textColor, textBackground);
tft.setTextSize(1);
tft.setCursor(xCenterLoc - xOffset, yCenterLoc - yOffset);
tft.print(text);
} // centerDrawText
// check if a button was pressed
bool checkButton(BUTTON_TYPE thisButton)
{
bool retVal = false;
// if touched most recently in thisButton
if ((BtnX >= (int)(thisButton.xCenterLoc - (thisButton.xSize / 2))) &&
(BtnX <= (int)(thisButton.xCenterLoc + (thisButton.xSize / 2))) &&
(BtnY >= (int)(thisButton.yCenterLoc - (thisButton.ySize / 2))) &&
(BtnY <= (int)(thisButton.yCenterLoc + (thisButton.ySize / 2))))
{
retVal = true;
}
return(retVal);
} // checkButton()
// check if a slider has changed
bool checkSlider(SLIDER_TYPE* thisSlider)
{
bool retVal = false;
float newValue = 0.0;
// if thisSlider is active & touched most recently in thisSlider
if ((thisSlider->activated) &&
(BtnX >= (int)(thisSlider->xCenterLoc - (thisSlider->xSize / 2))) &&
(BtnX <= (int)(thisSlider->xCenterLoc + (thisSlider->xSize / 2))) &&
(BtnY >= (int)(thisSlider->yCenterLoc - (thisSlider->ySize / 2))) &&
(BtnY <= (int)(thisSlider->yCenterLoc + (thisSlider->ySize / 2))))
{
if (thisSlider->orientation == SLIDER_MODE_HORIZONTAL)
{
newValue = (float)map((float)BtnX, (float)(thisSlider->xCenterLoc - (thisSlider->xSize / 2)), (float)(thisSlider->xCenterLoc + (thisSlider->xSize / 2)), thisSlider->maxValue, thisSlider->minValue);
} else {
newValue = (float)map((float)BtnY, (float)(thisSlider->yCenterLoc - (thisSlider->ySize / 2)), (float)(thisSlider->yCenterLoc + (thisSlider->ySize / 2)), thisSlider->maxValue, thisSlider->minValue);
}
if (newValue != thisSlider->value)
{
thisSlider->value = newValue;
drawSlider(*thisSlider);
retVal = true;
}
}
return(retVal);
} // checkSlider()
// draw a button
void drawButton(BUTTON_TYPE thisButton)
{
if (thisButton.activated)
{
tft.fillRect(thisButton.xCenterLoc - (thisButton.xSize / 2) + 1, thisButton.yCenterLoc - (thisButton.ySize / 2) + 1, thisButton.xSize - 2, thisButton.ySize - 2, thisButton.buttonColor);
tft.drawRect(thisButton.xCenterLoc - (thisButton.xSize / 2), thisButton.yCenterLoc - (thisButton.ySize / 2), thisButton.xSize, thisButton.ySize, thisButton.borderColor);
centerDrawText(*(thisButton.textPtr), thisButton.xCenterLoc, thisButton.yCenterLoc, thisButton.textColor, thisButton.buttonColor);
} else {
tft.fillRect(thisButton.xCenterLoc - (thisButton.xSize / 2) + 1, thisButton.yCenterLoc - (thisButton.ySize / 2) + 1, thisButton.xSize - 2, thisButton.ySize - 2, thisButton.borderColor);
tft.drawRect(thisButton.xCenterLoc - (thisButton.xSize / 2), thisButton.yCenterLoc - (thisButton.ySize / 2), thisButton.xSize, thisButton.ySize, thisButton.buttonColor);
centerDrawText(*(thisButton.textPtr), thisButton.xCenterLoc, thisButton.yCenterLoc, thisButton.textColor, thisButton.borderColor);
}
} // drawButton()
// update the screen based upon the current mode
void drawScreen(void)
{
// clear the unique portion of the display screen
tft.fillRect(0, 80, 320, 160, ILI9341_BLACK);
// update screen using the current config mode
switch(config_mode)
{
case CONFIG_MODE_MAIN:
{
tft.setTextSize(1);
tft.setTextColor(ILI9341_WHITE);
drawSlider(mainVolumeSlider);
drawButton(mainVolumeButton);
drawSlider(mainTuningSlider);
drawButton(mainTuningButton);
drawSlider(mainLevelASlider);
drawButton(mainLevelAButton);
drawSlider(mainTuningASlider);
drawButton(mainTuningAButton);
drawSlider(mainLevelBSlider);
drawButton(mainLevelBButton);
drawSlider(mainTuningBSlider);
drawButton(mainTuningBButton);
drawSlider(mainLevelCSlider);
drawButton(mainLevelCButton);
drawSlider(mainTuningCSlider);
drawButton(mainTuningCButton);
}
break;
}
} // drawScreen()
// draw a slider
void drawSlider(SLIDER_TYPE thisSlider)
{
int characterCount = 0;
String outString = "";
if (thisSlider.orientation == SLIDER_MODE_HORIZONTAL)
{
if (thisSlider.activated)
{
// clear the entire slider
tft.fillRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 7, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 2, thisSlider.xSize + 15, thisSlider.ySize + 4, thisSlider.backgroundColor);
// draw the slider outline
tft.drawRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 7, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 2, thisSlider.xSize + 15, thisSlider.ySize + 4, thisSlider.borderColor);
// draw the slider handle
tft.fillCircle((int)map(thisSlider.value, thisSlider.minValue, thisSlider.maxValue, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.xCenterLoc + (thisSlider.xSize / 2)), (int)thisSlider.yCenterLoc, 6, thisSlider.handleColor);
tft.drawCircle((int)map(thisSlider.value, thisSlider.minValue, thisSlider.maxValue, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.xCenterLoc + (thisSlider.xSize / 2)), (int)thisSlider.yCenterLoc, 6, thisSlider.handleBorderColor);
tft.drawCircle((int)map(thisSlider.value, thisSlider.minValue, thisSlider.maxValue, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.xCenterLoc + (thisSlider.xSize / 2)), (int)thisSlider.yCenterLoc, 7, thisSlider.handleBorderColor);
// draw the slider lines
tft.drawLine(thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.yCenterLoc, thisSlider.xCenterLoc + (thisSlider.xSize / 2), thisSlider.yCenterLoc, thisSlider.scaleColor);
tft.drawLine(thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.yCenterLoc - 3, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.yCenterLoc + 3, thisSlider.scaleColor); // left end
tft.drawLine(thisSlider.xCenterLoc + (thisSlider.xSize / 2), thisSlider.yCenterLoc - 3, thisSlider.xCenterLoc + (thisSlider.xSize / 2), thisSlider.yCenterLoc + 3, thisSlider.scaleColor); // right end
tft.drawLine(thisSlider.xCenterLoc, thisSlider.yCenterLoc - 2, thisSlider.xCenterLoc, thisSlider.yCenterLoc + 2, thisSlider.scaleColor); // center
} else {
// clear the entire slider
tft.fillRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 7, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 2, thisSlider.xSize + 15, thisSlider.ySize + 4, thisSlider.backgroundColorDisabled);
// draw the slider outline
tft.drawRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 7, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 2, thisSlider.xSize + 15, thisSlider.ySize + 4, thisSlider.borderColorDisabled);
// draw the slider handle
tft.fillCircle((int)map(thisSlider.value, thisSlider.minValue, thisSlider.maxValue, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.xCenterLoc + (thisSlider.xSize / 2)), (int)thisSlider.yCenterLoc, 6, thisSlider.handleColorDisabled);
tft.drawCircle((int)map(thisSlider.value, thisSlider.minValue, thisSlider.maxValue, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.xCenterLoc + (thisSlider.xSize / 2)), (int)thisSlider.yCenterLoc, 6, thisSlider.handleBorderColorDisabled);
tft.drawCircle((int)map(thisSlider.value, thisSlider.minValue, thisSlider.maxValue, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.xCenterLoc + (thisSlider.xSize / 2)), (int)thisSlider.yCenterLoc, 7, thisSlider.handleBorderColorDisabled);
// draw the slider lines
tft.drawLine(thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.yCenterLoc, thisSlider.xCenterLoc + (thisSlider.xSize / 2), thisSlider.yCenterLoc, thisSlider.scaleColorDisabled);
tft.drawLine(thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.yCenterLoc - 3, thisSlider.xCenterLoc - (thisSlider.xSize / 2), thisSlider.yCenterLoc + 3, thisSlider.scaleColorDisabled); // left end
tft.drawLine(thisSlider.xCenterLoc + (thisSlider.xSize / 2), thisSlider.yCenterLoc - 3, thisSlider.xCenterLoc + (thisSlider.xSize / 2), thisSlider.yCenterLoc + 3, thisSlider.scaleColorDisabled); // right end
tft.drawLine(thisSlider.xCenterLoc, thisSlider.yCenterLoc - 2, thisSlider.xCenterLoc, thisSlider.yCenterLoc + 2, thisSlider.scaleColorDisabled); // center
}
} else {
if (thisSlider.activated)
{
// clear the entire slider
tft.fillRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 7, thisSlider.xSize + 6, thisSlider.ySize + 15, thisSlider.backgroundColor);
// draw the slider outline
tft.drawRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 7, thisSlider.xSize + 6, thisSlider.ySize + 15, thisSlider.borderColor);
// draw the slider handle
tft.fillCircle(thisSlider.xCenterLoc, (int)map(thisSlider.value, thisSlider.maxValue, thisSlider.minValue, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.yCenterLoc + (thisSlider.ySize / 2)), 6, thisSlider.handleColor);
tft.drawCircle(thisSlider.xCenterLoc, (int)map(thisSlider.value, thisSlider.maxValue, thisSlider.minValue, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.yCenterLoc + (thisSlider.ySize / 2)), 6, thisSlider.handleBorderColor);
tft.drawCircle(thisSlider.xCenterLoc, (int)map(thisSlider.value, thisSlider.maxValue, thisSlider.minValue, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.yCenterLoc + (thisSlider.ySize / 2)), 7, thisSlider.handleBorderColor);
// draw the slider lines
tft.drawLine(thisSlider.xCenterLoc, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.xCenterLoc, thisSlider.yCenterLoc + (thisSlider.ySize / 2), thisSlider.scaleColor);
tft.drawLine(thisSlider.xCenterLoc - 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.xCenterLoc + 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.scaleColor); // top end
tft.drawLine(thisSlider.xCenterLoc - 3, thisSlider.yCenterLoc + (thisSlider.ySize / 2), thisSlider.xCenterLoc + 3, thisSlider.yCenterLoc + (thisSlider.ySize / 2), thisSlider.scaleColor); // bottom end
tft.drawLine(thisSlider.xCenterLoc - 2, thisSlider.yCenterLoc, thisSlider.xCenterLoc + 2, thisSlider.yCenterLoc, thisSlider.scaleColor); // center
} else {
// clear the entire slider
tft.fillRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 7, thisSlider.xSize + 6, thisSlider.ySize + 15, thisSlider.backgroundColorDisabled);
// draw the slider outline
tft.drawRect(thisSlider.xCenterLoc - (thisSlider.xSize / 2) - 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2) - 7, thisSlider.xSize + 6, thisSlider.ySize + 15, thisSlider.borderColorDisabled);
// draw the slider handle
tft.fillCircle(thisSlider.xCenterLoc, (int)map(thisSlider.value, thisSlider.maxValue, thisSlider.minValue, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.yCenterLoc + (thisSlider.ySize / 2)), 6, thisSlider.handleColorDisabled);
tft.drawCircle(thisSlider.xCenterLoc, (int)map(thisSlider.value, thisSlider.maxValue, thisSlider.minValue, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.yCenterLoc + (thisSlider.ySize / 2)), 6, thisSlider.handleBorderColorDisabled);
tft.drawCircle(thisSlider.xCenterLoc, (int)map(thisSlider.value, thisSlider.maxValue, thisSlider.minValue, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.yCenterLoc + (thisSlider.ySize / 2)), 7, thisSlider.handleBorderColorDisabled);
// draw the slider lines
tft.drawLine(thisSlider.xCenterLoc, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.xCenterLoc, thisSlider.yCenterLoc + (thisSlider.ySize / 2), thisSlider.scaleColorDisabled);
tft.drawLine(thisSlider.xCenterLoc - 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.xCenterLoc + 3, thisSlider.yCenterLoc - (thisSlider.ySize / 2), thisSlider.scaleColorDisabled); // top end
tft.drawLine(thisSlider.xCenterLoc - 3, thisSlider.yCenterLoc + (thisSlider.ySize / 2), thisSlider.xCenterLoc + 3, thisSlider.yCenterLoc + (thisSlider.ySize / 2), thisSlider.scaleColorDisabled); // bottom end
tft.drawLine(thisSlider.xCenterLoc - 2, thisSlider.yCenterLoc, thisSlider.xCenterLoc + 2, thisSlider.yCenterLoc, thisSlider.scaleColorDisabled); // center
}
}
characterCount = thisSlider.placesBeforeTheDecimal + thisSlider.placesAfterTheDecimal;
if (thisSlider.placesAfterTheDecimal != 0)
{
// add one character for the decimal point
characterCount++;
}
if (thisSlider.showPlusMinusSign)
{
// add one for the +/- sign
characterCount++;
if (thisSlider.value >= 0.0)
{
outString = outString + "+";
} else {
outString = outString + "-";
}
}
switch (thisSlider.placesBeforeTheDecimal)
{
case 5:
{
if (thisSlider.value < 10000.0)
{
characterCount--;
} else {
outString = outString + (char)(((int)(abs(thisSlider.value)) / 10000) + 0x30);
}
}
// no break, so fall-thru
case 4:
{
if (thisSlider.value < 1000)
{
characterCount--;
} else {
outString = outString + (char)((((int)(abs(thisSlider.value)) % 10000) / 1000) + 0x30);
}
}
// no break, so fall-thru
case 3:
{
if (thisSlider.value < 100)
{
characterCount--;
} else {
outString = outString + (char)((((int)(abs(thisSlider.value)) % 1000) / 100) + 0x30);
}
}
// no break, so fall-thru
case 2:
{
if (thisSlider.value < 10)
{
characterCount--;
} else {
outString = outString + (char)((((int)(abs(thisSlider.value)) % 100) / 10) + 0x30);
}
}
// no break, so fall-thru
}
outString = outString + (char)(((int)(abs(thisSlider.value)) % 10) + 0x30);
if (thisSlider.placesAfterTheDecimal != 0)
{
outString = outString + ".";
}
switch (thisSlider.placesAfterTheDecimal)
{
case 1:
{
outString = outString + (char)(((int)((abs(thisSlider.value) * 10.0)) % 10) + 0x30);
}
break;
case 2:
{
outString = outString + (char)(((int)((abs(thisSlider.value) * 10.0)) % 10) + 0x30);
outString = outString + (char)(((int)((abs(thisSlider.value) * 100.0)) % 10) + 0x30);
}
break;
}
tft.fillRect(thisSlider.xValueCenterLoc - ((thisSlider.placesBeforeTheDecimal + thisSlider.placesAfterTheDecimal + 2) * 3), thisSlider.yValueCenterLoc - 4, (thisSlider.placesBeforeTheDecimal + thisSlider.placesAfterTheDecimal + 2) * 6, 8, ILI9341_BLACK);
centerDrawText(outString, thisSlider.xValueCenterLoc + 1, thisSlider.yValueCenterLoc, thisSlider.valueColor, ILI9341_BLACK);
} // drawSlider()
// main loop
void loop()
{
bool screen_change = false;
// if the touchscreen is being touched anywhere
if (processTouchscreen())
{
switch(config_mode)
{
case CONFIG_MODE_MAIN:
{
if (checkSlider(&mainVolumeSlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainTuningSlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainLevelASlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainTuningASlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainLevelBSlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainTuningBSlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainLevelCSlider))
{
screen_update_required = true;
save_needed = true;
}
if (checkSlider(&mainTuningCSlider))
{
screen_update_required = true;
save_needed = true;
}
}
break;
}
} else {
// if the touchscreen was touched, but is no longer being touched
if (touch_triggered)
{
touch_triggered = false;
switch(config_mode)
{
case CONFIG_MODE_MAIN:
{
if (checkButton(mainTuningButton))
{
mainTuningSlider.value = 0.0;
drawSlider(mainTuningSlider);
screen_update_required = true;
save_needed = true;
}
if (checkButton(mainTuningAButton))
{
mainTuningASlider.value = 0.0;
drawSlider(mainTuningASlider);
screen_update_required = true;
save_needed = true;
}
if (checkButton(mainTuningBButton))
{
mainTuningBSlider.value = 0.0;
drawSlider(mainTuningBSlider);
screen_update_required = true;
save_needed = true;
}
if (checkButton(mainTuningCButton))
{
mainTuningCSlider.value = 0.0;
drawSlider(mainTuningCSlider);
screen_update_required = true;
save_needed = true;
}
}
break;
}
if (screen_change)
{
drawScreen();
screen_change = false;
screen_update_required = true;
}
BtnX = BtnY = -1;
}
}
// see if a save has been requested
if (save_needed == true)
{
save_needed = false;
// initialize the save accumulator delay timer
save_delay_millis = millis();
} else {
// if a delay is in progress & the dealy timer period is exceeded
if ((save_delay_millis > 0) && ((millis() - save_delay_millis) > SAVE_DELAY_MILLIS))
{
// reset the save accumulator delay timer
save_delay_millis = 0;
// actually save everything to EEPROM
saveSettings();
}
}
if ((screen_update_required) && (millis() > screen_update_time))
{
screen_update_time = millis() + SCREEN_UPDATE_MILLIS;
screen_update_required = false;
tft.updateScreen();
}
} // loop()
// process any touchscreen activity
bool processTouchscreen(void)
{
int i = 5;
TS_Point p = ts.getPoint();
if ((!ts.touched()) && (previously_touched))
{
touch_triggered = true;
}
if (ts.touched())
{
// Scale from raw to tft values to expected width & height using the calibration #'s
BtnX = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
BtnY = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
// see if we can't settle the touchpoint a little
while ((BtnX != previousBtnX) && (BtnY != previousBtnY) && (--i > 0))
{
previousBtnX = BtnX;
previousBtnY = BtnY;
// Scale from raw to tft values to expected width & height using the calibration #'s
BtnX = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
BtnY = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
}
previously_touched = true;
} else {
previously_touched = false;
}
return (ts.touched()); // whether the touchscreen is being touched or not
} // processTouchscreen()
// read the current settings from EEPROM
void readSettings(void)
{
byte eeprom_value, xor_value, inv_xor_value;
byte xor_result = 0x4D; // start with a non-zero value
bool header_is_good = true;
#ifdef DEBUG_EEPROM_READ
Serial.println("");
Serial.println("Attempting to read saved settings from EEPROM");
#endif
for (int eeprom_index = (int)(EEPROM_INDEX_HEADER_0); eeprom_index <= (int)(EEPROM_INDEX_INV_CHECKSUM); eeprom_index++)
{
EEPROM.get(eeprom_index, eeprom_value);
if (eeprom_index < EEPROM_INDEX_CHECKSUM)
{
xor_result = xor_result ^ eeprom_value;
}
#ifdef DEBUG_EEPROM_READ
Serial.print("(READ ");
showIndex(eeprom_index);
Serial.print(": ");
showIndex(eeprom_value);
Serial.println(")");
#endif
if (eeprom_index <= EEPROM_INDEX_HEADER_4)
{
if (eeprom_value != EEPROM_HEADER[eeprom_index])
{
header_is_good = false;
}
}
}
// read the checksum & inverse checksum
EEPROM.get(EEPROM_INDEX_CHECKSUM, xor_value);
EEPROM.get(EEPROM_INDEX_INV_CHECKSUM, inv_xor_value);
// if the checksums match & the header values match, then we seem to have valid settings in EEPROM, so read all of the settings
if ((xor_value == xor_result) &&
(inv_xor_value == (byte)~xor_result) &&
(header_is_good))
{
#ifdef DEBUG_EEPROM_READ
Serial.println("Valid settings found in EEPROM");
Serial.println("");
#endif
#ifndef DISABLE_EEPROM_READ_SETTINGS
for (int eeprom_index = (int)(EEPROM_INDEX_HEADER_0); eeprom_index <= (int)(EEPROM_INDEX_INV_CHECKSUM); eeprom_index++)
{
EEPROM.get(eeprom_index, eeprom_value);
#ifdef DEBUG_EEPROM_READ
Serial.print("(READ ");
showIndex(eeprom_index);
Serial.print(": ");
showIndex(eeprom_value);
#endif
switch(eeprom_index)
{
case EEPROM_INDEX_HEADER_0:
case EEPROM_INDEX_HEADER_1:
case EEPROM_INDEX_HEADER_2:
case EEPROM_INDEX_HEADER_3:
case EEPROM_INDEX_HEADER_4:
{
#ifdef DEBUG_EEPROM_READ
Serial.print(") Header[");
Serial.print(eeprom_index);
Serial.print("] = ");
Serial.println((char)eeprom_value);
#endif
}
break;
case EEPROM_INDEX_MAIN_VOLUME:
{
mainVolumeSlider.value = map((float)eeprom_value, 0.0, 255.0, mainVolumeSlider.minValue, mainVolumeSlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Volume Slider = ");
Serial.println(mainVolumeSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_LEVEL_A:
{
mainLevelASlider.value = map((float)eeprom_value, 0.0, 255.0, mainLevelASlider.minValue, mainLevelASlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Level A Slider = ");
Serial.println(mainLevelASlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_LEVEL_B:
{
mainLevelBSlider.value = map((float)eeprom_value, 0.0, 255.0, mainLevelBSlider.minValue, mainLevelBSlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Level B Slider = ");
Serial.println(mainLevelBSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_LEVEL_C:
{
mainLevelCSlider.value = map((float)eeprom_value, 0.0, 255.0, mainLevelCSlider.minValue, mainLevelCSlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Level C Slider = ");
Serial.println(mainLevelCSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING:
{
mainTuningSlider.value = map((float)eeprom_value, 0.0, 255.0, mainTuningSlider.minValue, mainTuningSlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Tuning Slider = ");
Serial.println(mainTuningSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING_A:
{
mainTuningASlider.value = map((float)eeprom_value, 0.0, 255.0, mainTuningASlider.minValue, mainTuningASlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Tuning A Slider = ");
Serial.println(mainTuningASlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING_B:
{
mainTuningBSlider.value = map((float)eeprom_value, 0.0, 255.0, mainTuningBSlider.minValue, mainTuningBSlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Tuning B Slider = ");
Serial.println(mainTuningBSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING_C:
{
mainTuningCSlider.value = map((float)eeprom_value, 0.0, 255.0, mainTuningCSlider.minValue, mainTuningCSlider.maxValue);
#ifdef DEBUG_EEPROM_READ
Serial.print(") Main Tuning C Slider = ");
Serial.println(mainTuningCSlider.value);
#endif
}
break;
case EEPROM_INDEX_CHECKSUM:
{
eeprom_value = (char)(xor_result);
#ifdef DEBUG_EEPROM_WRITE
Serial.print(") Calculated CHECKSUM = ");
showIndex(xor_result);
Serial.println("");
#endif
}
break;
case EEPROM_INDEX_INV_CHECKSUM:
{
eeprom_value = (char)(~xor_result);
#ifdef DEBUG_EEPROM_WRITE
Serial.print(") Calculated INVERSE CHECKSUM = ");
showIndex((byte)~xor_result);
Serial.println("");
#endif
}
break;
default:
{
#ifdef DEBUG_EEPROM_READ
Serial.println(")");
#endif
}
break;
}
}
#endif
} else {
#ifdef DEBUG_EEPROM_READ
Serial.println("Invalid settings found in EEPROM");
Serial.println("");
Serial.print("(READ ");
showIndex(EEPROM_INDEX_CHECKSUM);
Serial.print (") xor_value = ");
Serial.println(xor_value);
Serial.print("(CALC) xor_result = ");
Serial.println(xor_result);
Serial.print("(READ ");
showIndex(EEPROM_INDEX_INV_CHECKSUM);
Serial.print (") inv_xor_value = ");
Serial.println(inv_xor_value);
Serial.print("(CALC) inv_xor_result = ");
Serial.println((byte)~xor_result);
#endif
saveSettings();
}
} // readSettings()
// save the current settings to EEPROM
void saveSettings(void)
{
byte xor_result = 0x4D; // start with a non-zero value
char eeprom_value;
#ifdef DEBUG_EEPROM_WRITE
Serial.println("");
Serial.println("Saving settings to EEPROM");
Serial.println("");
#endif
for (byte eeprom_index = (byte)(EEPROM_INDEX_HEADER_0); eeprom_index <= (byte)(EEPROM_INDEX_INV_CHECKSUM); eeprom_index++)
{
#ifdef DEBUG_EEPROM_WRITE
Serial.print("(WRITE ");
showIndex(eeprom_index);
Serial.print(": ");
#endif
switch(eeprom_index)
{
case EEPROM_INDEX_HEADER_0:
case EEPROM_INDEX_HEADER_1:
case EEPROM_INDEX_HEADER_2:
case EEPROM_INDEX_HEADER_3:
case EEPROM_INDEX_HEADER_4:
{
eeprom_value = EEPROM_HEADER[eeprom_index];
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Header[");
Serial.print(eeprom_index);
Serial.print("] = ");
Serial.println(eeprom_value);
#endif
}
break;
case EEPROM_INDEX_MAIN_VOLUME:
{
eeprom_value = (char)map(mainVolumeSlider.value, mainVolumeSlider.minValue, mainVolumeSlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Volume Slider = ");
Serial.println(mainVolumeSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_LEVEL_A:
{
eeprom_value = (char)map(mainLevelASlider.value, mainLevelASlider.minValue, mainLevelASlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Level A Slider = ");
Serial.println(mainLevelASlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_LEVEL_B:
{
eeprom_value = (char)map(mainLevelBSlider.value, mainLevelBSlider.minValue, mainLevelBSlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Level B Slider = ");
Serial.println(mainLevelBSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_LEVEL_C:
{
eeprom_value = (char)map(mainLevelCSlider.value, mainLevelCSlider.minValue, mainLevelCSlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Level C Slider = ");
Serial.println(mainLevelCSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING:
{
eeprom_value = (char)map(mainTuningSlider.value, mainTuningSlider.minValue, mainTuningSlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Tuning Slider = ");
Serial.println(mainTuningSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING_A:
{
eeprom_value = (char)map(mainTuningASlider.value, mainTuningASlider.minValue, mainTuningASlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Tuning A Slider = ");
Serial.println(mainTuningASlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING_B:
{
eeprom_value = (char)map(mainTuningBSlider.value, mainTuningBSlider.minValue, mainTuningBSlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Tuning B Slider = ");
Serial.println(mainTuningBSlider.value);
#endif
}
break;
case EEPROM_INDEX_MAIN_TUNING_C:
{
eeprom_value = (char)map(mainTuningCSlider.value, mainTuningCSlider.minValue, mainTuningCSlider.maxValue, 0, 255);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Main Tuning C Slider = ");
Serial.println(mainTuningCSlider.value);
#endif
}
break;
case EEPROM_INDEX_CHECKSUM:
{
eeprom_value = (char)(xor_result);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Calculated CHECKSUM = ");
showIndex(xor_result);
Serial.println("");
#endif
}
break;
case EEPROM_INDEX_INV_CHECKSUM:
{
eeprom_value = (char)(~xor_result);
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.print(") Calculated INVERSE CHECKSUM = ");
showIndex((byte)~xor_result);
Serial.println("");
#endif
}
break;
default:
{
eeprom_value = eeprom_index;
#ifdef DEBUG_EEPROM_WRITE
showIndex(eeprom_value);
Serial.println(")");
#endif
}
break;
}
#ifndef DISABLE_EEPROM_WRITE_SETTINGS
EEPROM.update(eeprom_index, (byte)(eeprom_value));
#endif
if (eeprom_index < EEPROM_INDEX_CHECKSUM)
{
xor_result = (byte)(xor_result ^ eeprom_value);
}
}
} // saveSettings()
// one-time setup
void setup()
{
bool foundBegin = false;
bool foundEnd = false;
int indexCount = 0;
Serial.begin(57600);
while (!Serial && (millis() <= 1000));
Serial.println("=============================================");
Serial.print(" ");
Serial.println(VERSION1);
Serial.print(" ");
Serial.println(VERSION2);
Serial.println(VERSION3);
Serial.println("=============================================");
Serial.println("");
Serial.println("");
delay(500);
tft.begin();
tft.setRotation(1);
tft.setFrameBuffer(framebuf);
tft.useFrameBuffer(true);
delay(100);
ts.begin();
ts.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
centerDrawText(VERSION1, 160, 100, ILI9341_GREEN, ILI9341_BLACK);
centerDrawText(VERSION2, 160, 120, ILI9341_YELLOW, ILI9341_BLACK);
centerDrawText(VERSION3, 160, 140, ILI9341_RED, ILI9341_BLACK);
tft.updateScreen();
delay(3000);
tft.fillScreen(ILI9341_BLACK);
centerDrawText('v', 280, 4, ILI9341_YELLOW, ILI9341_BLACK);
for(unsigned int i = 0; i < sizeof(VERSION2); i++)
{
if (!foundBegin)
{
if (VERSION2[i] == ' ')
{
foundBegin = true;
}
} else {
if (!foundEnd)
{
if (VERSION2[i] == ' ')
{
foundEnd = true;
} else {
centerDrawText((char)VERSION2[i], 280 + (6 * ++indexCount), 4, ILI9341_YELLOW, ILI9341_BLACK);
}
}
}
}
centerDrawText(VERSION1, 160, 4, ILI9341_GREEN, ILI9341_BLACK);
drawScreen();
tft.updateScreen();
// try to read the settings from EEPROM
readSettings();
drawScreen();
tft.updateScreen();
} // setup()
// show index of EEPROM reads/writes
void showIndex(int index)
{
if (index < 100)
{
Serial.print("0");
} else {
Serial.print((char)((index / 100) + 0x30));
}
if (index < 10)
{
Serial.print("0");
} else {
Serial.print((char)(((index / 10) % 10) + 0x30));
}
Serial.print((char)((index % 10) + 0x30));
} // showIndex()
// EOF placeholder