enum class ProgramMode
{
Run,
Settings,
Debug,
SelectingSensor,
SettingNumeral
};
#include "helper.h"
#include <BfButton.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <stdlib.h>
#define BUTTON_HOLD_DELAY 2500
#define BACKGROUND_COLOR 0XFFFF
#define TFT_DC 9
#define TFT_CS 53
#define NUMERAL_LAST 9
#define NUMERAL_FIRST 0
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
const int btnPin = 3;
const int DT = 4;
const int CLK = 2;
volatile int state = 0;
volatile bool flagCW = false;
volatile bool flagCCW = false;
volatile bool numberCW = false;
volatile bool numberCCW = false;
volatile ProgramMode currentProgramMode = ProgramMode::Run;
volatile bool settingSensor = false;
volatile int programCounter = 0;
volatile int prevSelectedMode = 0;
volatile int selectedSensor = 0;
volatile int prevSelectedSensor = 0;
volatile int selectedIndexNumber = 0;
volatile int selectedSensorIndex = 0;
volatile int previousSelectedIndex = 0;
volatile int numeralNumber = 0;
volatile int prevNumeralNumber = 0;
volatile bool renderedRunMode = false;
volatile bool renderedSettingsMode = false;
volatile bool renderedSelectingSensor = false;
#define MAX_SELECTED_SENSOR_NUM 3
#define MIN_SELECTED_SENSOR_NUM 0
BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, true, LOW);
int sensor1 = 111;
int sensor2 = 222;
int sensor3 = 333;
int sensor4 = 444;
void setupTFT() {
tft.begin();
tft.setRotation(1);
tft.fillScreen(0xFFFF);
tft.setTextColor(000000);
tft.setTextSize(3);
}
void fillBackground() {
tft.fillScreen(BACKGROUND_COLOR);
}
// typedef struct Rect CVRect;
void fillRect(Adafruit_ILI9341 tft, Rect rect, uint16_t color) {
tft.fillRect(rect.x0, rect.y0, rect.w, rect.h, color);
}
void drawUnderlineForSettingMode()
{
Rect rect = {0, 0, 104, 4};
drawUnderline(tft, rect, BACKGROUND_COLOR, prevSelectedSensor);
drawUnderline(tft, rect, 0x0, selectedSensor);
// switch (prevSelectedSensor) {
// case 0: case 2: rect.x0 = 50; break;
// case 1: case 3: rect.x0 = 180; break;
// }
// switch (prevSelectedSensor) {
// case 0: case 1: rect.y0 = 104; break;
// case 2: case 3: rect.y0 = 160; break;
// }
// fillRect(tft, rect, BACKGROUND_COLOR);
// switch (selectedSensor) {
// case 0: case 2: rect.x0 = 50; break;
// case 1: case 3: rect.x0 = 180; break;
// }
// switch (selectedSensor) {
// case 0: case 1: rect.y0 = 104; break;
// case 2: case 3: rect.y0 = 160; break;
// }
// fillRect(tft, rect, 0x0);
}
String StringFromRect(Rect rect) {
return "Rect: " + String(rect.x0) + " " + String(rect.y0) + " " + String(rect.w) + " " + String(rect.h);
}
void drawUnderline(Adafruit_ILI9341 tft, Rect rect, uint16_t color, uint16_t selectedIndex) {
Rect newRect = { rect.x0, rect.y0, rect.w, rect.h };
switch (selectedIndex) {
case 0: case 2: newRect.x0 = 50; break;
case 1: case 3: newRect.x0 = 180; break;
}
switch (selectedIndex) {
case 0: case 1: newRect.y0 = 104; break;
case 2: case 3: newRect.y0 = 160; break;
}
StringFromRect(newRect);
fillRect(tft, newRect, color);
}
void printSelectingSensor() {
fillBackground();
tft.setCursor(50, 30);
tft.println("Level" + String(selectedSensor + 1));
printSelectedLevelValue();
}
void printSelectedLevelValue() {
int value = 0;
switch (selectedSensor) {
case 0:
value = sensor1;
break;
case 1:
value = sensor2;
break;
case 2:
value = sensor3;
break;
case 3:
value = sensor4;
break;
default:
break;
}
tft.setCursor(140, 80);
tft.println(String(value));
drawUnderlineSelectedNumber();
}
void drawSelectedNumeral() {
int x = 0;
switch (selectedSensorIndex) {
case 0:
x = 140;
break;
case 1:
x = 160;
break;
case 2:
x = 176;
break;
default:
break;
}
char num = 48 + numeralNumber;
Serial.println(num);
Serial.println("selecting numeral");
tft.fillRect(x, 78, 18, 10, 0xFFFFFF);
tft.drawChar(x, 80, num, 0x0, 0xFFFFFF, 3);
}
void drawUnderlineSelectedNumber() {
switch (previousSelectedIndex) {
case 0:
tft.setCursor(140, 30);
tft.fillRect(140, 110, 20, 4, 0xFFFFFF);
break;
case 1:
tft.setCursor(170, 30);
tft.fillRect(155, 110, 20, 4, 0xFFFFFF);
break;
case 2:
tft.setCursor(200, 30);
tft.fillRect(170, 110, 20, 4, 0xFFFFFF);
break;
default:
break;
}
switch (selectedSensorIndex) {
case 0:
tft.setCursor(140, 30);
tft.fillRect(140, 110, 20, 4, 0x0);
break;
case 1:
tft.setCursor(170, 30);
tft.fillRect(155, 110, 20, 4, 0x0);
break;
case 2:
tft.setCursor(200, 30);
tft.fillRect(170, 110, 20, 4, 0x0);
break;
default:
break;
}
}
void updateSelectedLevelValue() {
}
void printSettingMode() {
fillBackground();
tft.setCursor(50, 30);
tft.println("Settings mode");
tft.setTextSize(2);
tft.setCursor(50, 80);
tft.println("Level 1");
tft.setCursor(180, 80);
tft.println("Level 2");
tft.setCursor(50, 140);
tft.println("Level 3");
tft.setCursor(180, 140);
tft.println("Level 4");
drawUnderlineForSettingMode();
tft.setTextSize(3);
}
void printCenterSettingsMode() {
fillBackground();
tft.setCursor(50,100);
tft.println("Settings mode");
}
void printRunMode() {
fillBackground();
tft.setCursor(80,100);
tft.println(utf8rus("В работе"));
}
void printDiagnosticMode() {
fillBackground();
tft.setTextColor(0x00);
tft.setCursor(30,100);
tft.println("Diagnostic mode");
}
void printWarning() {
fillBackground();
tft.setCursor(80,100);
tft.setTextColor(0xF800);
tft.println("WARNING!!!");
}
void changeDrawingState() {
switch (currentProgramMode) {
case ProgramMode::Run:
renderedSettingsMode = false;
renderedSelectingSensor = false;
break;
case ProgramMode::Settings:
renderedRunMode = false;
renderedSelectingSensor = false;
break;
case ProgramMode::SelectingSensor:
renderedRunMode = false;
renderedSettingsMode = false;
break;
case ProgramMode::SettingNumeral:
renderedRunMode = false;
renderedSettingsMode = false;
renderedSelectingSensor = false;
break;
}
}
void pressHandler(BfButton *btn, BfButton::press_pattern_t pattern) {
switch (pattern) {
case BfButton::SINGLE_PRESS:
if (currentProgramMode == ProgramMode::Run) {
ProgramMode selectedProgramMode = static_cast<ProgramMode>(programCounter);
if (selectedProgramMode == ProgramMode::Settings) {
Serial.println("Settings mode enabled");
currentProgramMode = selectedProgramMode;
programCounter = 1; // not sure
}
} else if (currentProgramMode == ProgramMode::Settings) {
Serial.println("Settings mode turned");
currentProgramMode = ProgramMode::SelectingSensor;
} else if (currentProgramMode == ProgramMode::SelectingSensor) {
currentProgramMode = ProgramMode::SettingNumeral;
numeralNumber = getActualNumber();
Serial.println("Actual number is " + String(numeralNumber));
Serial.println("Selecting sensor numeral enabled");
} else if (currentProgramMode == ProgramMode::SettingNumeral) {
chooseSensorAndChangeValue();
currentProgramMode = ProgramMode::SelectingSensor;
Serial.println("Setting Numeral enabled");
}
break;
case BfButton::DOUBLE_PRESS:
if (currentProgramMode == ProgramMode::SelectingSensor) {
Serial.println("Double push:: Selecting Sensor");
currentProgramMode = ProgramMode::Settings;
}
break;
case BfButton::LONG_PRESS:
if (currentProgramMode == ProgramMode::Settings) {
Serial.println("Exiting current mode");
currentProgramMode = ProgramMode::Run;
programCounter = 0;
settingSensor = false;
} else if (currentProgramMode == ProgramMode::SettingNumeral) {
Serial.println("long press setting numeral");
currentProgramMode = ProgramMode::SelectingSensor;
}
break;
}
changeDrawingState();
}
void changeValue(int *number, int value, int index) {
int first = *number / 100;
int second = *number / 10 % 10;
int last = *number % 10;
switch (index) {
case 0: first = value; break;
case 1: second = value; break;
case 2: last = value; break;
default: Serial.println("Not implemented yet"); break;
}
*number = first * 100 + second * 10 + last;
}
void chooseSensorAndChangeValue() {
int *sensorPointer;
switch (selectedSensor)
{
case 0: sensorPointer = &sensor1; break;
case 1: sensorPointer = &sensor2; break;
case 2: sensorPointer = &sensor3; break;
case 3: sensorPointer = &sensor4; break;
default: break;
}
changeValue(sensorPointer, numeralNumber, selectedSensorIndex);
}
void selectSensorNumeral() {
if (flagCW) {
selectedSensorIndex++;
flagCW = false;
}
if (flagCCW) {
selectedSensorIndex--;
flagCCW = false;
}
if (selectedSensorIndex > 2) {
selectedSensorIndex = 2;
}
if (selectedSensorIndex < 0) {
selectedSensorIndex = 0;
}
if (previousSelectedIndex != selectedSensorIndex) {
Serial.println("Sensor numeral is " + String(selectedSensorIndex));
drawUnderlineSelectedNumber();
}
previousSelectedIndex = selectedSensorIndex;
}
int getActualNumber() {
int value = 0;
switch (selectedSensor) {
case 0: value = sensor1; break;
case 1: value = sensor2; break;
case 2: value = sensor3; break;
case 3: value = sensor4; break;
default: break;
}
int numeral = 0;
switch (selectedSensorIndex) {
case 0: numeral = value / 100; break;
case 1: numeral = value / 100 % 10; break;
case 2: numeral = value % 10; break;
default: break;
}
return numeral;
}
void selectNumeral() {
if (flagCW) {
numeralNumber++;
flagCW = false;
}
if (flagCCW) {
numeralNumber--;
flagCCW = false;
}
if (numeralNumber > NUMERAL_LAST) {
numeralNumber = NUMERAL_LAST;
}
if (numeralNumber < NUMERAL_FIRST) {
numeralNumber = NUMERAL_FIRST;
}
if (prevNumeralNumber != numeralNumber) {
drawSelectedNumeral();
}
prevNumeralNumber = numeralNumber;
}
void drawSelectedMode() {
switch (programCounter) {
case 0:
printRunMode();
break;
case 1:
printCenterSettingsMode();
break;
case 2:
break;
default:
break;
}
}
void selectMode() {
if (flagCW) {
programCounter++;
flagCW = false;
}
if (flagCCW) {
programCounter--;
flagCCW = false;
}
if (programCounter > 2) {
programCounter = 2;
}
if (programCounter < 0) {
programCounter = 0;
}
if (prevSelectedMode != programCounter) {
Serial.println("Selected mode: " + String(programCounter));
drawSelectedMode();
}
prevSelectedMode = programCounter;
}
void selectSensor() {
if (flagCW) {
selectedSensor++;
flagCW = false;
}
if (flagCCW) {
selectedSensor--;
flagCCW = false;
}
if (selectedSensor > MAX_SELECTED_SENSOR_NUM) {
selectedSensor = MAX_SELECTED_SENSOR_NUM;
}
if (selectedSensor < MIN_SELECTED_SENSOR_NUM) {
selectedSensor = MIN_SELECTED_SENSOR_NUM;
}
if (prevSelectedSensor != selectedSensor) {
drawUnderlineForSettingMode();
}
prevSelectedSensor = selectedSensor;
}
void runMode() {
if (!renderedRunMode) {
printRunMode();
renderedRunMode = true;
}
selectMode();
}
void settingsMode() {
if (!renderedSettingsMode) {
printSettingMode();
renderedSettingsMode = true;
}
selectSensor();
}
void selectingSensor() {
if (!renderedSelectingSensor) {
printSelectingSensor();
renderedSelectingSensor = true;
}
selectSensorNumeral();
}
void readEncoderData() {
switch (currentProgramMode) {
case ProgramMode::Run:
runMode();
break;
case ProgramMode::Settings:
settingsMode();
break;
case ProgramMode::SelectingSensor:
selectingSensor();
break;
case ProgramMode::SettingNumeral:
selectNumeral();
break;
}
}
void handleRotation(const int clkPin, const int dtPin, int *state, bool *flagCW, bool *flagCCW) {
int pinAValue = digitalRead(clkPin);
int pinBValue = digitalRead(dtPin);
cli();
if (!pinAValue && pinBValue) {
*state = 1;
}
if (!pinAValue && !pinBValue) {
*state = -1;
}
if (pinAValue && *state != 0) {
if ((*state == 1 && !pinBValue) || (*state == -1 && pinBValue)) {
if (*state == 1) {
*flagCW = true; // clockwise rotation
}
if (*state == -1) {
*flagCCW = true; // counter clockwise rotation
}
*state = 0;
}
}
sei();
}
void handleFunction() {
handleRotation(CLK, DT, &state, &flagCW, &flagCCW);
}
void setup() {
Serial.begin(9600);
pinMode(CLK, INPUT_PULLUP);
pinMode(DT, INPUT_PULLUP);
attachInterrupt(0, handleFunction, CHANGE);
btn.onPress(pressHandler)
.onDoublePress(pressHandler)
.onPressFor(pressHandler, BUTTON_HOLD_DELAY);
setupTFT();
}
void loop() {
btn.read();
readEncoderData();
}