Konubinix' opinionated web of thoughts

Use My T-Watch-S3 for Gtd

Fleeting

TODO

  • look at zephyr

what the watch is for

subject
a spoken thought reaches my gtd inbox, and the phone rings the watch.
  • why: it’s my gtd tool to remember doing things.
scope
the note stops where the sound reaches the phone.
goal
the watch runs a FOSS OS that talks to my android phone.
  • why: I already have a python runtime on android, so I owe nothing to the annoying standards, like the ones gadgetbridge wants.
    • freedom: I can do whatever I want.

the stories

story
when I wake up, I start the watch, it connects to my phone, I think about something to be done and speak it into the watch, and it lands in my gtd inbox via the phone.
story
later in the day, I check the hour.
story
later, I get a recall; it comes from my phone and rings in the watch.
story
later, I go for a walk and start recording my gnss location, to get the track afterwards.
more
others will come, and these four are a good start.
rank
the hour and the track can drop when they cost me the other two.

which OS to run on the watch

survey
I look at what already exists before deciding.
decision
an existing OS, or my own.
prior
my previous attempt at aggregating my ESP work is my micro python distribution.
  • use: if I implement my own stuff, it is a thing to extend and reuse.

the hardware it has to fit

caveat
this board is known to me only from a vendor announcement as reported, neither a datasheet nor a measurement of my own1.
board
a t-watch-s3 plus.
screen
1.54 inch, 240x240, capacitive touch.
cell
940mAh.
voice
a built-in pdm microphone.
audio
a MAX98357A class D audio amplifier.
place
a MIA-M10Q multi-GNSS receiver.

the constraints

constraint
it is easy to maintain.
constraint
micropython, by a wide preference.
constraint
it is compatible with the hardware, screen included.
  • why: micropython that displays nothing on the screen would be stupid.
constraint
the battery is spared hardcore.
  • goal: one week on a charge.
    • doubt: I know I won’t reach it.
    • dream: for now, let me dream.
constraint
an existing project is a plus.
constraint
writing my own stuff does not bother me.

what already exists

measure
each project is read against my stories and my constraints, not against its own goals.
  • feel: how easy it is to maintain is not read off anything — that will be a subjective feeling when I try them.
means
freedom here is being free to adapt the tool to whatever strange use I want, without fighting a project too specific for it.
  • example: infinitime is awesome, but changing the way a notification appears is long work and long discussions with its team.
caveat
every cell is read off what a project publishes — a doc page, a config, a repo, somebody in a thread — and nothing here was run on my board.
  • power: the battery column holds what a project offers for sleeping, never a measured draw.
marker
« not said » is the project not saying, and never a « no ».
variant
the vendor names the s3 and the s3 plus apart2, the plus being the one that gets the gnss receiver and the 940mAh cell1.
  • gap: a project shipping an s3 target has not been shown to reach what this board adds.
  • transfer: an s3 config reaches the plus where the parts coincide — the amplifier by name, and the microphone by both being pdm1, 3.
project freedom micropython hardware voice audio talks to my phone battery gnss
plain micropython4 total yes power and screen exist, s3 not through machine.I2S i2s transmit ble central and peripheral lightsleep and deepsleep not said
circuitpython5 my code on its runtime no, circuitpython official board, s3 only yes on latest, no on stable amp pins named native ble on s3 light and deep sleep not said
lilygolib2 its c api no, c the vendor’s own, s3 and plus record wav to a buffer play wav example ble not wrapped light sleep, five wake examples gps examples
esphome3 its yaml components no, yaml listed as features, s3 mic yaml, voice assistant media player yaml not said deep sleep not said
meshtastic6 its protocol and purpose no, c++ supported, s3 only codec2, sent to the mesh codec2, sent to the mesh its own protobuf api light sleep, lora on, ble off gps in light sleep
cost
speaking into the watch under micropython means carrying a patched firmware, machine.I2S having no pdm and the pull request that adds it being open since 20244.
tension
the light sleep that spares the battery turns the radio off, and the recall arrives over it2, 6.

the android companion

need
something on the phone receives what I said, and sends the recall.
decision
an existing app, or my own.

the test harness

need
the stories above get run, as far as the note goes.
open
how they run at all, the watch being hardware and the companion a phone.

the code

need
whichever of the watch and the companion turns out to be mine.

  1. « Display – 1.54-inch 16-bit full color TFT LCD display with 240×240 resolution, capacitive touch; ST7789V SPI controller », « Battery – 940mAh LiPo », « Built-in PDM microphone, MAX98357A Class D audio amplifier », « MIA-M10Q GPS module featuring a multi-GNSS engine with support for BeiDou, Galileo, GLONASS, and QZSS », and the plus « gets GPS and 940mAh battery » — CNX Software on the T-Watch S3 Plus↩︎ ↩︎ ↩︎

  2. « T-Watch Ultra & T-LoRa-Pager & T-Watch-S3 & T-Watch-S3-Plus », language « C », licence « MIT » — LilyGoLib. examples/peripheral holds « RecordWAV », « playWAV », « SimpleTone », « GPSFactory », « GPSFullExample » and « RTC_AlarmByUnits »; examples/sleep holds « LightSleep » with « WakeUpFromTimer », « WakeUpFromTouchPanel », « WakeUpFromSensor », « WakeUpFromPowerButton » and « WakeUpFromBootButton »; examples/ble holds « BLEKeyboard » and « BLEMouse » — the library’s examples. In RecordWAV.ino, « uint8_t *wav_buffer; », « size_t wav_size; » and « wav_buffer = instance.mic.recordWAV(5, &wav_size); », played by « instance.player.playWAV(wav_buffer, wav_size); »; in BLEKeyboard.ino, « #include <BleKeyboard.h> » with « BleKeyboard bleKeyboard(USB_PRODUCT); » beside the library’s own « instance.begin(); ». The board class declares « GPS gps; », « PDM mic; » under « #ifdef USING_PDM_MICROPHONE », « Player player; », « bool initMicrophone(); », « bool initGPS(); » and « bool _is_watch_plus; », with « Rewrite battery parameters , Determining if it’s a T-Watch Plus by checking if GPS is present. » and « Light sleep will turn off Haptic, GPS, Speaker , WiFi , Bluetooth . » — LilyGoWatchS3.h. Its src/ holds « PDM.h », « GPS.h », « LilyGoWatchS3.h », « LilyGoWatchUltra.h », « LilyGoPowerManage.h », « LilyGoKeyboard.h », « LilyGoDispInterface.h », « LV_Helper.h », « _wav_header.h », « bsp_codec » and « bsp_lcd », and no BLE source — its sources↩︎ ↩︎ ↩︎

  3. under « Features », « (SPM1423HM4H-B PDM) » with « platform: i2s_audio » and « pdm: true », « (MAX98357A) with R0805 speaker » with « media_player: » and « dac_type: external », « ST7789V 240x240 220ppi 16-bit, 1.54" IPS LCD over SPI », « FT6336 Capacitative touch » and « AXP2101 Highly Integrated Power Management Unit », and « - [x] `voice_assistant` enabled » under the microphone and speaker yaml, for the s3 — velijv’s T-Watch S3 configuration for ESPHome. « automatically enter a deep sleep mode on the ESP8266/ESP32/BK72xx/nRF52 after a certain amount of time », in which « the node will not do any work and not respond to any network traffic, even Over The Air updates » — the deep sleep component↩︎ ↩︎

  4. « Availability: ESP32, MIMXRT, RP2, STM32 » and « receive or transmit » — machine.I2S, where the port named covers this chip, « ESP32_GENERIC_S3 » being a board of the esp32 port. « The PDM protocol is not supported by MicroPython. It is not possible to use the machine.I2S class with a PDM microphone. » — miketeachman, in micropython discussion 16048. « ports/esp32: Add PDM RX feature to I2S. », open and unmerged since 2024 — pull request 14176, where « extmod/machine_i2s needs I2S to be in RX mode to be able to be read from. since PDM_RX is a new mode, it needed some modifications » — micropython discussion 14160. The patch’s downstream fate: emfcamp’s badge-2024 firmware merged it as a forked patch — « This patch adds support for I2S PDM to micropython, as implemented by this (unmerged) 2024 PR to micropython: … pull/14176 » and « appears to have gotten stuck in API bikeshedding hell » — confirming the note’s « patched firmware » claim, author joenash, merged 2026-06-27 — emfcamp pull request 352. « Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, Broadcaster, and Observer roles, as well as GATT Server and Client and L2CAP connection-oriented-channels. » and « currently only supported when using the NimBLE stack on ESP32, STM32 and Unix » — the bluetooth module. « Setup the AX2101 power manager chip in order to give current to the different subsystems, enable the TFT display backlight, setup charging, and so forth » and « a MicroPython ST7789 display driver that was already available here », for the s3 — t-watch-s3-micropython. « machine.lightsleep([time_ms]) » and « machine.deepsleep([time_ms]) », « Stops execution in an attempt to enter a low power state. », lightsleep giving « full RAM and state retention. Upon wake execution is resumed from the point where the sleep was requested » against deepsleep which « may not retain RAM or any other state » — the machine module↩︎ ↩︎

  5. « T-Watch S3 by LILYGO », and « CircuitPython 10.2.1 » given as « the latest stable release of CircuitPython that will work with the T-Watch S3 » — the circuitpython board page; the boards of the espressif port are « lilygo_twatch_s3 » and « lilygo_twatch_2020_v3 », with no plus among them. On PDMIn, « On Espressif, only available on ESP32, ESP32-S3, and ESP32-P4. » in audiobusio, latest against « Not available on Espressif. » in audiobusio, stable. « _bleio uses native BLE capability on boards that support it, including Nordic nRF, Espressif (except ESP32-S2 and ESP32-P4), and SiLabs. » — _bleio. « / MIC » with « MIC_DATA » and « MIC_SCLK », and « / MAX98357A SPK » with « I2S_BCK », « I2S_WS » and « I2S_DOUT » — the board’s pins; « CIRCUITPY_ESP_FLASH_SIZE = 16MB » with frozen drivers « Adafruit_CircuitPython_FocalTouch », « Adafruit_CircuitPython_DRV2605 », « Adafruit_CircuitPython_PCF8563 », « CircuitPython_AXP2101 » and « CircuitPython_BMA423 », LoRa left commented « To be added in the future » — the board’s makefile. « Light sleep keeps sufficient state so the program can resume after sleeping. » and « Deep sleep shuts down power to nearly all of the microcontroller including the CPU and RAM. » — the alarm module↩︎

  6. « The official firmware for Meshtastic, an open-source, off-grid mesh communication system. », language « C++ », licence « GPL-3.0 », and the merged pull request « T-Watch S3 Support »; the esp32s3 variants include « t-watch-s3 » and « t-watch-ultra », with no plus among them — the meshtastic firmware. « 1.54 inch ST7789V TFT LCD (Resolution: 240 x 240) » — the Meshtastic T-Watch page. « The Device API is designed to have only a simple stream of ToRadio and FromRadio packets and all polymorphism comes from the flexible set of Google Protocol Buffers. » and « almost identical when it is deployed over BLE, Serial/USB, or TCP (our three currently supported transports for connecting to phone/PC) » — the Meshtastic client API. « codec2.h » and « driver/i2s.h » included, with « PTT_PIN », « CODEC2_700 » and « void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); » — the audio module. « When activated, this feature disables Bluetooth, Serial, WiFi, and the device’s screen to conserve power. » and « In light sleep the CPU is suspended, LoRa radio is on, BLE is off and GPS is on » — the power configuration↩︎ ↩︎