Code Generated by AI for Weigh Station

#include <Arduino_GFX_Library.h>
#include <XPT2046_Touchscreen.h>
#include <SPI.h>

#define TFT_BL   21
#define TFT_DC    2
#define TFT_CS   15
#define TFT_SCLK 14
#define TFT_MOSI 13
#define TFT_MISO 12
#define TFT_RST  -1

#define TOUCH_CS   33
#define TOUCH_IRQ  36
#define TOUCH_MOSI 32
#define TOUCH_MISO 39
#define TOUCH_SCLK 25

#define SCREEN_W 320
#define SCREEN_H 240

#define BG_COLOR 0x000F
#define WHITE    0xFFFF
#define GREEN    0x07E0
#define RED      0xF800
#define BLACK    0x0000

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK, TFT_MOSI, TFT_MISO);
Arduino_GFX *tft = new Arduino_ILI9341(bus, TFT_RST, 1, false);

SPIClass touchSPI(VSPI);
XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ);

struct Car {
  int x, y, w, h;
  const char* label;
  const char* series;
  long maxWeight;
};

Car cars[6] = {
  {20,  50, 120, 40, "Boxcar",   "3000 - 3749",        72300},
  {180, 50, 120, 40, "Gondola",  "5500 - 5699",        82500},
  {20, 100, 120, 40, "Flat Car", "6500 - 6544",        80000},
  {180,100, 120, 40, "Tank Car", "UTLX 11000 - 11058", 65000},
  {20, 150, 120, 40, "S Reefer", "32 - 81",            62000},
  {180,150, 120, 40, "L Reefer", "150 - 169",          84000}
};

bool detailScreen = false;
int currentCarIndex = -1;
long currentWeight = 0;
bool overweight = false;

void drawCentreString(const char* text, int cx, int y, int size) {
  tft->setTextSize(size);

  int textW = strlen(text) * 6 * size;
  int x = cx - textW / 2;

  tft->setCursor(x, y);
  tft->print(text);
}

String formatWeight(long value) {
  String s = String(value);
  String out = "";
  int count = 0;

  for (int i = s.length() - 1; i >= 0; i--) {
    out = s[i] + out;
    count++;

    if (count == 3 && i > 0) {
      out = "," + out;
      count = 0;
    }
  }

  return out + " lbs";
}

void generateWeight(int i) {

  long maxW = cars[i].maxWeight;

  overweight = (random(100) < 5);

  if (overweight) {
    currentWeight = random(maxW + 1, maxW + (maxW / 10));
  }
  else {
    currentWeight = random(maxW * 80 / 100, maxW + 1);
  }
}

void drawMainScreen() {

  tft->fillScreen(BG_COLOR);

  tft->setTextColor(WHITE);

  drawCentreString("Scale Track", SCREEN_W / 2, 10, 3);

  for (int i = 0; i < 6; i++) {

    tft->drawRoundRect(
      cars[i].x,
      cars[i].y,
      cars[i].w,
      cars[i].h,
      8,
      WHITE
    );

    drawCentreString(
      cars[i].label,
      cars[i].x + cars[i].w / 2,
      cars[i].y + 12,
      2
    );
  }
}

void drawDetailScreen() {

  Car c = cars[currentCarIndex];

  tft->fillScreen(BG_COLOR);

  tft->setTextColor(WHITE);

  tft->fillTriangle(
    10, 25,
    35, 10,
    35, 40,
    WHITE
  );

  drawCentreString(c.label, SCREEN_W / 2, 20, 3);

  String weightText = formatWeight(currentWeight);

  if (overweight) {

    tft->setTextColor(RED);

    drawCentreString(
      "OVERWEIGHT",
      SCREEN_W / 2,
      135,
      2
    );
  }
  else {

    tft->setTextColor(WHITE);

    tft->drawRoundRect(
      35,
      80,
      250,
      55,
      8,
      GREEN
    );
  }

  drawCentreString(
    weightText.c_str(),
    SCREEN_W / 2,
    93,
    3
  );

  tft->setTextColor(WHITE);
  tft->setTextSize(2);

  tft->setCursor(25, 175);
  tft->print("Series: ");
  tft->print(c.series);

  tft->setCursor(25, 205);
  tft->print("Max Weight: ");
  tft->print(formatWeight(c.maxWeight));
}

bool touchedIn(
  int x,
  int y,
  int w,
  int h,
  int tx,
  int ty
) {

  return (
    tx >= x &&
    tx <= x + w &&
    ty >= y &&
    ty <= y + h
  );
}

void getTouchXY(int &x, int &y) {

  TS_Point p = ts.getPoint();

  x = map(p.x, 200, 3900, 0, SCREEN_W);
  y = map(p.y, 200, 3900, 0, SCREEN_H);

  x = constrain(x, 0, SCREEN_W);
  y = constrain(y, 0, SCREEN_H);
}

void setup() {

  Serial.begin(115200);
  delay(500);

  randomSeed(analogRead(34));

  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);

  tft->begin();
  tft->setRotation(1);

  touchSPI.begin(
    TOUCH_SCLK,
    TOUCH_MISO,
    TOUCH_MOSI,
    TOUCH_CS
  );

  ts.begin(touchSPI);
  ts.setRotation(1);

  drawMainScreen();
}

void loop() {

  if (ts.touched()) {

    int tx, ty;

    getTouchXY(tx, ty);

    if (!detailScreen) {

      for (int i = 0; i < 6; i++) {

        if (touchedIn(
              cars[i].x,
              cars[i].y,
              cars[i].w,
              cars[i].h,
              tx,
              ty
            )) {

          currentCarIndex = i;

          generateWeight(i);

          detailScreen = true;

          drawDetailScreen();

          delay(300);

          break;
        }
      }
    }

    else {

      if (touchedIn(0, 0, 60, 55, tx, ty)) {

        detailScreen = false;

        drawMainScreen();

        delay(300);
      }
    }
  }

  delay(10);
}