CoreS3 virtual buttons

  • Page 7 of the CoreS3 document "CoreS3 Development kit.pdf" contains the following information.
    Covering most of the from is the capacitive multitouch screen sensor with three dedicated touch zones available in code as buttons A, B and C.
    These are not clearly marked as zone A shares the same location and the left microphone,
    Zone B shares the same location as the camera and zone C shares the same location as the right microphone.
    However, there is no mention of CoreS3 in the comments on M5Unified's Button.ino.
    I actually tested Button.ino and it doesn't work.
    That's why I thought CoreS3 was not equipped with virtual buttons.

    But when I test the code below,

    #include <Arduino.h>
    #include <M5Unified.h>
    void setup() {
       auto cfg = M5.config();
    void loop() {
         auto t = M5.Touch.getDetail();
         auto p = t.isPressed();
         auto r = t.isReleased();
         auto h = t.isHolding();
         auto x = t.base_x;
         auto y = t.base_y;
         M5.Display.printf("x=%4d y=%4d PRH=%d %d %d",x,y,p,r,h);

    When you touch the Zone A area, x=80, y=2000 will be displayed.
    Pressed Released Holding is also displayed correctly. In other words, it seems that only button A is implemented.
    When I touch Zone B or C, it doesn't respond at all.

    What does this mean?
    Is there any official comment on this?

  • Hello @chama

    interesting. I've never studied that document before and assumed there are no virtual buttons for M5CoreS3. That said, it is relatively easy to add them, but in contrast to M5Core2 where the touch area actually goes a bit below the display I don't think that is true for M5CoreS3. So for the M5CoreS3 you have to touch the lower rim of the display.

    Using Unified's Button.ino example I've added below code block after the M5.update() statement to make BtnA, BtnB and BtnC work.

        auto ms = m5gfx::millis();
        if (M5.Touch.isEnabled()) {
        uint_fast8_t btn_bits = 0;
        int i = M5.Touch.getCount();
        while (--i >= 0) {
          auto raw = M5.Touch.getTouchPointRaw(i);
          if (raw.y >= 238) {
            auto det = M5.Touch.getDetail(i);
            if (det.state & m5::touch_state_t::touch) {
              if (M5.BtnA.isPressed()) { btn_bits |= 1 << 0; }
              if (M5.BtnB.isPressed()) { btn_bits |= 1 << 1; }
              if (M5.BtnC.isPressed()) { btn_bits |= 1 << 2; }
              if (btn_bits || !(det.state & m5::touch_state_t::mask_moving)) {
                btn_bits |= 1 << ((raw.x - 2) / 107);
        M5.BtnA.setRawState(ms, btn_bits & 1);
        M5.BtnB.setRawState(ms, btn_bits & 2);
        M5.BtnC.setRawState(ms, btn_bits & 4);

    Note: The basic idea for above code block is inspired by the M5Core2 implementation. See here.

    Edit: I just realized that github user tobozo suggested a similar fix before. See here.


  • Hello @felmue
    Thank you for reading my bad English.
    And the idea of touching the lower rim of the display is good.

    However, it is a mystery whether there is a built-in sensor only at the position of the microphone hole at the bottom left.

    The documentation I wrote in the first post can be found on this page ( ) under the link "CoreS3 User Guide".

    The direct link is here ( Development Kit-compressed (1).pdf ).


  • Sorry, that was a mistake I made on earlier available information. and seamed to work with my fat fingers. I have rechecked, corrected and updated the document and its in the process of being re uploaded.