Xiao Clock — Xiao Esp32S3 Sense simulation

An interactive Xiao Esp32S3 Sense circuit simulation you can run free in your browser on Velxio, by tareq-neoaz.

Components

Sketch code

#include <M5GFX.h>
#include <lgfx/v1/panel/Panel_GC9A01.hpp>
#include <Wire.h>
#include <SPI.h>

static const int PIN_CS = 2, PIN_DC = 4, PIN_BL = 43;
static const int PIN_SCK = 7, PIN_MISO = 8, PIN_MOSI = 9;

class RoundDisplay : public lgfx::LGFX_Device {
  lgfx::Panel_GC9A01 _gc9a01;
  lgfx::Bus_SPI _spi;
 public:
  RoundDisplay() {
    {
      auto cfg = _spi.config();
      cfg.spi_host = SPI2_HOST;
      cfg.spi_mode = 0;
      cfg.freq_write = 40000000;
      cfg.pin_sclk = PIN_SCK;
      cfg.pin_mosi = PIN_MOSI;
      cfg.pin_miso = PIN_MISO;
      cfg.pin_dc = PIN_DC;
      _spi.config(cfg);
      _gc9a01.setBus(&_spi);
    }
    {
      auto cfg = _gc9a01.config();
      cfg.pin_cs = PIN_CS;
      cfg.pin_rst = -1;
      cfg.panel_width = 240;
      cfg.panel_height = 240;
      cfg.invert = true;
      _gc9a01.config(cfg);
    }
    setPanel(&_gc9a01);
  }
};

static RoundDisplay tft;
#define TFT_BL PIN_BL

static const int CX = 120, CY = 120;
static const int R = 116;

// PCF8563 RTC setup
static const uint8_t RTC_ADDR = 0x51;
static uint8_t bcd2dec(uint8_t b) { return (b >> 4) * 10 + (b & 0x0f); }
static uint8_t dec2bcd(uint8_t d) { return ((d / 10) << 4) | (d % 10); }

static void rtcSet(uint8_t h, uint8_t m, uint8_t s) {
  Wire.beginTransmission(RTC_ADDR);
  Wire.write(0x02);
  Wire.write(dec2bcd(s));
  Wire.write(dec2bcd(m));
  Wire.write(dec2bcd(h));
  Wire.endTransmission();
}

static bool rtcRead(uint8_t &h, uint8_t &m, uint8_t &s) {
  Wire.beginTransmission(RTC_ADDR);
  Wire.write(0x02);
  if (Wire.endTransmission() != 0) return false;
  if (Wire.requestFrom((int)RTC_ADDR, 3) != 3) return false;
  uint8_t rs = Wire.read(), rm = Wire.read(), rh = Wire.read();
  s = bcd2dec(rs & 0x7f);
  m = bcd2dec(rm & 0x7f);
  h = bcd2dec(rh & 0x3f);
  return true;
}

// --- AESTHETIC UI ---
static void drawFace() {
  tft.fillScreen(TFT_BLACK);
  
  // Outer rings
  tft.drawCircle(CX, CY, R, 0x4208);        // Dark grey outer
  tft.drawCircle(CX, CY, R - 2, TFT_WHITE); // White inner

  // 60 tick marks
  for (int i = 0; i < 60; i++) {
    float a = i * 6 * DEG_TO_RAD - HALF_PI;
    bool hour = (i % 5) == 0;
    bool quarter = (i % 15) == 0;
    int len = quarter ? 15 : (hour ? 10 : 4);
    
    // Cyberpunk colors
    uint16_t col = quarter ? TFT_CYAN : (hour ? TFT_WHITE : 0x4208);
    
    int r0 = R - 8, r1 = R - 8 - len;
    tft.drawLine(CX + cos(a) * r0, CY + sin(a) * r0,
                 CX + cos(a) * r1, CY + sin(a) * r1, col);
  }

  // Cool inner ring
  tft.drawCircle(CX, CY, R - 30, 0x2104); 
}

static void hand(float deg, int len, int thick, uint16_t colour) {
  float a = deg * DEG_TO_RAD - HALF_PI;
  int x = CX + cos(a) * len;
  int y = CY + sin(a) * len;
  for (int o = -thick / 2; o <= thick / 2; o++) {
    tft.drawLine(CX + o, CY, x + o, y, colour);
    tft.drawLine(CX, CY + o, x, y + o, colour);
  }
}

static uint8_t lastS = 255;
static uint8_t lastM = 255;
static uint8_t lastH = 255;

void setup() {
  pinMode(44, INPUT_PULLUP)

More projects by tareq-neoaz