338 lines
9.7 KiB
C++
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)
|
|
{
|
|
} |