Files
reflowplate/reflow_plate_fw/src/lcd.cpp

338 lines
9.7 KiB
C++

#include "lcd.h"
#include "thermo.h"
#include "controlloop.h"
#include "button.h"
#include <TFT_eSPI.h> // Include the graphics library
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
TFT_eSprite looptime_spr = TFT_eSprite(&tft);
//chart data
TFT_eSprite chartXaxis_spr = TFT_eSprite(&tft);
TFT_eSprite chartYaxis_spr = TFT_eSprite(&tft);
TFT_eSprite chartArea_spr = TFT_eSprite(&tft);
TFT_eSprite reflowstate_spr = TFT_eSprite(&tft);
TFT_eSprite output_spr = TFT_eSprite(&tft);
//buttons
String buttonNames[] = {"START", "STOP", "SET"};
char buttonlabels[BUTTONS_N][10] = {"", "", ""};
TFT_eSPI_Button key[BUTTONS_N];
uint16_t calData[5] = {549, 3080, 343, 3159, 4};
uint32_t lastButtonTime = 0;
void updateTemperature(void)
{
//draw actualTemperature
chartArea_spr.fillRoundRect(TEMP_X, 0, 60-TEMP_R, TEMP_H, TEMP_R, TEMP_BG_COLOR);
chartArea_spr.drawString("A:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4);
chartArea_spr.drawString("T:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4 * 3);
chartArea_spr.drawNumber(getTemperature(), TEMP_X + TEMP_VALUE_X, TEMP_H / 4);
if (getReflowStatus() == REFLOW_STATUS_OFF)
{
chartArea_spr.drawString("--", TEMP_X + TEMP_VALUE_X, TEMP_H / 4 * 3);
}
else
{
chartArea_spr.drawNumber(getReflowTargetTemp(), TEMP_X + TEMP_VALUE_X, TEMP_H / 4 * 3);
}
}
uint32_t calcTemp(double temp)
{
//map(long x, long in_min, long in_max, long out_min, long out_max)
return CHART_H - map(temp, CHART_TEMP_MIN, CHART_TEMP_MAX, CHART_Y_AXIS_OFFSET, CHART_H) + CHART_X_AXIS_OFFSET;
}
uint32_t calcTime(uint32_t timeMs)
{
return map((timeMs / 1000), 0, CHART_TIME_MAX, 0, CHART_W - CHART_Y_AXIS_OFFSET);
}
void updateTargetChart(void)
{
chartArea_spr.fillSprite(CHART_BG_COLOR);
//draw preheat
uint32_t stepTimeStart = 0;
uint32_t stepTimeStop = calcTime(PREHEAT_PERIOD);
chartArea_spr.drawLine(stepTimeStart,
CHART_H - CHART_X_AXIS_OFFSET,
stepTimeStop,
calcTemp(TEMPERATURE_SOAK_MIN),
CHART_TARGET_COLOR);
//draw soak
stepTimeStart = stepTimeStop;
stepTimeStop += calcTime(SOAK_MICRO_PERIOD * (((TEMPERATURE_SOAK_MAX - TEMPERATURE_SOAK_MIN) / SOAK_TEMPERATURE_STEP) - 1));
chartArea_spr.drawLine(stepTimeStart,
calcTemp(TEMPERATURE_SOAK_MIN),
stepTimeStop,
calcTemp(TEMPERATURE_SOAK_MAX),
CHART_TARGET_COLOR);
//draw reflow
stepTimeStart = stepTimeStop;
stepTimeStop += calcTime(REFLOW_PERIOD);
chartArea_spr.drawLine(stepTimeStart,
calcTemp(TEMPERATURE_SOAK_MAX),
stepTimeStop,
calcTemp(TEMPERATURE_REFLOW_MAX),
CHART_TARGET_COLOR);
//draw cool
stepTimeStart = stepTimeStop;
stepTimeStop += calcTime(COOLDOWN_PERIOD);
chartArea_spr.drawLine(stepTimeStart,
calcTemp(TEMPERATURE_REFLOW_MAX),
stepTimeStop,
calcTemp(TEMPERATURE_ROOM),
CHART_TARGET_COLOR);
updateTemperature();
chartArea_spr.pushSprite(CHART_X + CHART_Y_AXIS_OFFSET, CHART_Y);
}
void prepTargetChart(void)
{
chartArea_spr.createSprite(CHART_W - CHART_Y_AXIS_OFFSET, CHART_H - CHART_X_AXIS_OFFSET);
chartArea_spr.setTextFont(TEMP_FONT);
chartArea_spr.setTextColor(TEMP_F_COLOR);
chartArea_spr.setTextDatum(CL_DATUM);
updateTargetChart();
}
void updateReflowState(void)
{
reflowstate_spr.fillRoundRect(STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, STATE_BG_COLOR);
reflowstate_spr.fillRoundRect(STATE_W / 2 + STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, STATE_BG_COLOR);
reflowstate_spr.drawString(getReflowState_str(), STATE_W / 4, STATE_H / 2);
reflowstate_spr.drawString(getReflowStatus_str(), STATE_W / 4 * 3, STATE_H / 2);
reflowstate_spr.pushSprite(STATE_X, STATE_Y);
}
void prepReflowstate(void)
{
reflowstate_spr.createSprite(STATE_W, STATE_H);
reflowstate_spr.setTextFont(STATE_FONT);
reflowstate_spr.setTextColor(STATE_F_COLOR);
reflowstate_spr.setTextDatum(MC_DATUM);
updateReflowState();
}
void updateOutput(void)
{
output_spr.fillSprite(OUTPUT_BG);
if (getOutputState())
{
output_spr.fillCircle(OUTPUT_W / 2, OUTPUT_H / 2, OUTPUT_R, OUTPUT_ON_COLOR);
}
else
{
output_spr.drawCircle(OUTPUT_W / 2, OUTPUT_H / 2, OUTPUT_R, OUTPUT_OFF_COLOR);
}
output_spr.pushSprite(OUTPUT_X, OUTPUT_Y);
}
void prepOutput(void)
{
output_spr.createSprite(OUTPUT_W, OUTPUT_H);
updateOutput();
}
void prepChart(void)
{
chartXaxis_spr.createSprite(CHART_W, CHART_X_AXIS_OFFSET);
chartYaxis_spr.createSprite(CHART_Y_AXIS_OFFSET, CHART_H);
//draw X-axis
chartXaxis_spr.drawLine(0, 0, CHART_W, 0, CHART_LINE_COLOR);
//draw Y-axis
chartYaxis_spr.drawLine(CHART_Y_AXIS_OFFSET - 1, 0, CHART_Y_AXIS_OFFSET - 1, CHART_H, CHART_LINE_COLOR);
//draw Y axis labels
uint16_t tickIndex = (CHART_H - CHART_X_AXIS_OFFSET) / CHART_Y_TICKS;
chartXaxis_spr.setTextColor(CHART_TEXT_COLOR);
chartYaxis_spr.setTextColor(CHART_TEXT_COLOR);
for (int i = 0; i < CHART_Y_TICKS; i++)
{
//tick value
uint16_t y_tick_step = CHART_TEMP_MAX - ((CHART_TEMP_MAX - CHART_TEMP_MIN) / CHART_Y_TICKS * i + 1) + CHART_TEMP_MIN;
chartYaxis_spr.drawLine(CHART_Y_AXIS_OFFSET - 8, tickIndex * (i + 1), CHART_Y_AXIS_OFFSET, tickIndex * (i + 1), CHART_LINE_COLOR);
chartYaxis_spr.setTextDatum(BR_DATUM);
chartYaxis_spr.drawString(String(y_tick_step), CHART_Y_AXIS_OFFSET - 3, tickIndex * (i + 1), CHART_FONT);
}
//draw X axis labels
tickIndex = (CHART_W - CHART_Y_AXIS_OFFSET) / CHART_X_TICKS;
for (int i = 0; i < CHART_X_TICKS + 1; i++)
{
uint16_t x_tick_step = (CHART_TIME_MAX / CHART_X_TICKS * (i));
chartXaxis_spr.drawLine(tickIndex * i + CHART_Y_AXIS_OFFSET - 1, 0, tickIndex * i + CHART_Y_AXIS_OFFSET - 1, 8, CHART_LINE_COLOR);
chartXaxis_spr.setTextDatum(TR_DATUM);
chartXaxis_spr.drawString(String(x_tick_step), tickIndex * i + CHART_Y_AXIS_OFFSET - 1, 3, CHART_FONT);
}
chartXaxis_spr.pushSprite(CHART_X, CHART_Y + CHART_H - CHART_X_AXIS_OFFSET);
chartYaxis_spr.pushSprite(CHART_X, CHART_Y);
}
void prepStatus(void)
{
looptime_spr.createSprite(20, tft.fontHeight(1) + 1);
}
void updateStatus(void)
{
looptime_spr.fillSprite(TFT_BLACK);
looptime_spr.setTextDatum(MC_DATUM);
looptime_spr.drawNumber(getLooptime(), looptime_spr.width() / 2, looptime_spr.height() / 2, 1);
looptime_spr.pushSprite(1, 1);
}
void prepButtons(void)
{
const uint32_t button_width = tft.width() / BUTTONS_N;
for (int i = 0; i < BUTTONS_N; i++)
{
key[i].initButtonUL(&tft,
(button_width * i) + BUTTON_PADDING,
tft.height() - BUTTON_H,
button_width - (BUTTON_PADDING * 2),
BUTTON_H,
TFT_BLUE, // Outline
TFT_SKYBLUE, // Fill
TFT_BLACK, // Text
buttonlabels[i], // 10 Byte Label
KEY_TEXTSIZE);
key[i].setLabelDatum(0, 2, MC_DATUM);
key[i].drawButton(false, buttonNames[i]);
}
}
void touch_calibrate()
{
uint16_t calData[5];
uint8_t calDataOK = 0;
// Calibrate
tft.fillScreen(TFT_BLACK);
tft.setCursor(20, 0);
tft.setTextFont(2);
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("Touch corners as indicated");
tft.setTextFont(1);
tft.println();
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
// Use this calibration code in setup():");
// uint16_t calData[5] = { 0,0,0,0,0 };
// tft.setTouch(calData);
//String calDatastr = "";
for (uint8_t i = 0; i < 5; i++)
{
tft.printf("%d,", calData[i]);
}
while (1)
;
}
void updateGUIButtons(void)
{
uint32_t timeNow = millis();
if (timeNow - lastButtonTime > BUTTON_INTERVAL)
{
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
bool pressed = tft.getTouch(&t_x, &t_y);
for (uint8_t b = 0; b < BUTTONS_N; b++)
{
if (pressed && key[b].contains(t_x, t_y))
{
//Serial.println("key pressed");
key[b].press(true); // tell the button it is pressed
setButton(b, true);
}
else
{
//Serial.println("key released");
key[b].press(false); // tell the button it is NOT pressed
setButton(b, false);
}
}
// Check if any key has changed state
for (uint8_t b = 0; b < BUTTONS_N; b++)
{
// If button was just pressed, redraw inverted button
if (key[b].justPressed())
{
key[b].drawButton(true, buttonNames[b]);
}
// If button was just released, redraw normal color button
if (key[b].justReleased())
{
key[b].drawButton(false, buttonNames[b]);
}
}
lastButtonTime = timeNow;
}
}
// -------------------------------------------------------------------------
// Setup
// -------------------------------------------------------------------------
void initLCD(void)
{
tft.init();
tft.setRotation(2);
tft.setTextFont(2);
tft.fillScreen(TFT_BLACK);
tft.invertDisplay(false);
//touch_calibrate();
tft.setTouch(calData);
prepStatus();
prepButtons();
prepChart();
prepReflowstate();
prepTargetChart();
prepOutput();
}
// -------------------------------------------------------------------------
// Main loop
// -------------------------------------------------------------------------
uint32_t lastLCDupdate = 0;
void handleLCD()
{
updateStatus();
uint32_t timeNow = millis();
if (timeNow - lastLCDupdate > LCD_INTERVAL)
{
updateGUIButtons();
updateReflowState();
updateTargetChart();
updateOutput();
lastLCDupdate = timeNow;
}
}
void loopScreen(void)
{
}