Best way to create countup timer?

I am trying to create a simple countup timer with 1/10s resolution, that is activated on a GPIO input, and displayed on a SSD1306 OLED display.

Basically:
GPIO goes high, OLED switches to “timer” page, and displays a timer counting up: “XX.X s”
GPIO goes low, timer stops counting, and switches back to default display page after 30s

I came across this post which seemed to indicate that the lambda code was looped based on the update_interval. Using this information, I tried this code:

display:
  - platform: ssd1306_i2c
    id: my_display
    model: "SSD1306 128x64"
    update_interval: 0.1s
    pages:
      - id: page2
        lambda: |-
          // Print timer
          static float t = 0.0;
          if (id(pump_state).state) {
            it.printf(0, 46, id(font2a), TextAlign::BASELINE_LEFT, "%4.1f s", t);
            t+= 0.1;
          } else {
            it.printf(0, 46, id(font2a), TextAlign::BASELINE_LEFT, "%4.1f s", t);
          }

which seems to run okay, but the timing is not accurate and seems to be running slower than intended, unless I drastically increase the i2c frequency.

Am I missing something, or is there a completely different/better way to do this?

One tenth of a second is a fairly quick update rate for a platform that is interrupt based - especially if you are doing other things on your ESP.

Also update_interval: is not a timer - so I would not expect an accurate time count. I would expect it to be slow - depending on how busy the ESP is.

The ESPhome Time component has a minimum interrupt interval of 1 second, so that is not going to be much use for you either. If you wanted to count down in seconds then do an on_time: with seconds: /1, then do a component_update: of the display.

If I was going to do a timer with this sort of resolution I would probably just write a C++ program with some API or MQTT hooks to do the control.