Problem with getting a Mouse to work with a ESP32

Hi, I am currently trying to follow a video on youtube that uses a TTGO ESP-32-WROVER to connect to a library called the FabGL library that allows you to use a PS2 mouse, PS2 keyboard, and simulate Windows 3.0 OS all at the same time. I am using this exact OS simulation example that uses an emulator to simulate the Windows 3.0 OS to achieve what is done in the YouTube video but I am having a hard time getting the PS2 Mouse to work with the TTGO Esp32-Wrover board as was shown in the video. This is because when I try and connect the PS2 Mouse to pins 26 and 27 to the Esp32 board the mouse itself responds, however when I try and plug in the Monitor to the VGA connector on pins 18 (Green_0), 19 (Green_1), 22 (Red_1), 21 (Red_0), 5 (Blue_1), and 4 (Blue_0), the mouse pointer is not present on the screen as seen in this picture:

I have also used the proper 120 Ohm and 2k Ohm resistors that are connected to Power (3.3v) in the former diagram and pins 26 and 27 as seen in the first diagram, as well as using the connections in the latter diagram which was posted on the FabGl Documentation Website:

Here is the full schematic of what I have built using the previous diagrams on the FabGL Website mentioned above:

Here is some code to the FabGL example portion of the library that I am using currently and that the person in the video is using:

  Created by Fabrizio Di Vittorio ( - <>
  Copyright (c) 2019-2021 Fabrizio Di Vittorio.
  All rights reserved.
* Please contact if you need a commercial license.
* This library and related software is available under GPL v3.
  FabGL is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  FabGL is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with FabGL.  If not, see <>.

 /* Instructions:
    - to run this application you need an ESP32 with PSRAM installed and an SD-CARD slot (ie TTGO VGA32 v1.4 or FabGL Development Board with WROVER)
    - open this with Arduino and make sure PSRAM is DISABLED
    - partition scheme must be: Huge App
    - compile and upload the sketch

#pragma message "This sketch requires Tools->Partition Scheme = Huge APP"

#include <memory>

#include "esp32-hal-psram.h"
extern "C" {
#include "esp_spiram.h"
#include "esp_sntp.h"

#include <Preferences.h>
#include <WiFi.h>
#include <HTTPClient.h>

#include "fabgl.h"

#include "mconf.h"
#include "machine.h"

using std::unique_ptr;

using fabgl::StringList;
using fabgl::imin;
using fabgl::imax;

Preferences   preferences;
InputBox      ibox;
Machine     * machine;

// noinit! Used to maintain datetime between reboots
__NOINIT_ATTR static timeval savedTimeValue;

static bool wifiConnected = false;
static bool downloadOK    = false;

// try to connected using saved parameters
bool tryToConnect()
  bool connected = WiFi.status() == WL_CONNECTED;
  if (!connected) {
    char SSID[32] = "";
    char psw[32]  = "";
    if (preferences.getString("SSID", SSID, sizeof(SSID)) && preferences.getString("WiFiPsw", psw, sizeof(psw))) {
      ibox.progressBox("", "Abort", true, 200, [&](fabgl::ProgressForm * form) {
        WiFi.begin(SSID, psw);
        for (int i = 0; i < 32 && WiFi.status() != WL_CONNECTED; ++i) {
          if (!form->update(i * 100 / 32, "Connecting to %s...", SSID))
          if (i == 16)
        connected = (WiFi.status() == WL_CONNECTED);
      // show to user the connection state
      if (!connected) {
        ibox.message("", "WiFi Connection failed!");
  return connected;

bool checkWiFi()
  wifiConnected = tryToConnect();
  if (!wifiConnected) {

    // configure WiFi?
    if (ibox.message("WiFi Configuration", "Configure WiFi?", "No", "Yes") == InputResult::Enter) {

      // repeat until connected or until user cancels
      do {

        // yes, scan for networks showing a progress dialog box
        int networksCount = 0;
        ibox.progressBox("", nullptr, false, 200, [&](fabgl::ProgressForm * form) {
          form->update(0, "Scanning WiFi networks...");
          networksCount = WiFi.scanNetworks();

        // are there available WiFi?
        if (networksCount > 0) {

          // yes, show a selectable list
          StringList list;
          for (int i = 0; i < networksCount; ++i)
            list.appendFmt("%s (%d dBm)", WiFi.SSID(i).c_str(), WiFi.RSSI(i));
          int s ="WiFi Configuration", "Please select a WiFi network", &list);

          // user selected something?
          if (s > -1) {
            // yes, ask for WiFi password
            char psw[32] = "";
            if (ibox.textInput("WiFi Configuration", "Insert WiFi password", psw, 31, "Cancel", "OK", true) == InputResult::Enter) {
              // user pressed OK, connect to WiFi...
              preferences.putString("SSID", WiFi.SSID(s).c_str());
              preferences.putString("WiFiPsw", psw);
              wifiConnected = tryToConnect();
              // show to user the connection state
              if (wifiConnected)
                ibox.message("", "Connection succeeded!");
            } else
          } else
        } else {
          // there is no WiFi
          ibox.message("", "No WiFi network found!");

      } while (!wifiConnected);



  return wifiConnected;

// handle soft restart
void shutdownHandler()
  // save current datetime into Preferences
  gettimeofday(&savedTimeValue, nullptr);

void updateDateTime()
  // Set timezone
  setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);

  // get datetime from savedTimeValue? (noinit section)
  if (esp_reset_reason() == ESP_RST_SW) {
    // adjust time taking account elapsed time since ESP32 started
    savedTimeValue.tv_usec += (int) esp_timer_get_time();
    savedTimeValue.tv_sec  += savedTimeValue.tv_usec / 1000000;
    savedTimeValue.tv_usec %= 1000000;
    settimeofday(&savedTimeValue, nullptr);

  if (checkWiFi()) {

    // we need time right now
    ibox.progressBox("", nullptr, true, 200, [&](fabgl::ProgressForm * form) {
      sntp_setservername(0, (char*)"");
      for (int i = 0; i < 12 && sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED; ++i) {
        form->update(i * 100 / 12, "Getting date-time from SNTP...");
      ibox.message("", "Date and Time updated. Restarting...");

  } else {

    // set default time
    auto tm = (struct tm){ .tm_sec  = 0, .tm_min  = 0, .tm_hour = 8, .tm_mday = 14, .tm_mon  = 7, .tm_year = 84 };
    auto now = (timeval){ .tv_sec = mktime(&tm) };
    settimeofday(&now, nullptr);


// download specified filename from URL
bool downloadURL(char const * URL, FILE * file)
  downloadOK = false;

  char const * filename = strrchr(URL, '/') + 1;

  ibox.progressBox("", "Abort", true, 380, [&](fabgl::ProgressForm * form) {
    form->update(0, "Preparing to download %s", filename);
    HTTPClient http;
    int httpCode = http.GET();
    if (httpCode == HTTP_CODE_OK) {
      if (file) {
        int tlen = http.getSize();
        int len = tlen;
        auto buf = (uint8_t*) SOC_EXTRAM_DATA_LOW; // use PSRAM as buffer
        WiFiClient * stream = http.getStreamPtr();
        int dsize = 0;
        while (http.connected() && (len > 0 || len == -1)) {
          size_t size = stream->available();
          if (size) {
            int c = stream->readBytes(buf, size);
            auto wr = fwrite(buf, 1, c, file);
            if (wr != c) {
              dsize = 0;
              break;  // writing failure!
            dsize += c;
            if (len > 0)
              len -= c;
            if (!form->update((int64_t)dsize * 100 / tlen, "Downloading %s (%.2f / %.2f MB)", filename, (double)dsize / 1048576.0, tlen / 1048576.0))
        downloadOK = (len == 0 || (len == -1 && dsize > 0));

  return downloadOK;

// return filename if successfully downloaded or already exist
char const * getDisk(char const * url)
  FileBrowser fb(SD_MOUNT_PATH);

  char const * filename = nullptr;
  if (url) {
    if (strncmp("://", url + 4, 3) == 0) {
      // this is actually an URL
      filename = strrchr(url, '/') + 1;
      if (filename && !fb.exists(filename, false)) {
        // disk doesn't exist, try to download
        if (!checkWiFi())
          return nullptr;
        auto file = fb.openFile(filename, "wb");
        bool success = downloadURL(url, file);
        if (!success) {
          return nullptr;
    } else {
      // this is just a file
      if (fb.filePathExists(url))
        filename = url;
  return filename;

// user pressed SYSREQ (ALT + PRINTSCREEN)
void sysReqCallback()
  ibox.begin(VGA_640x480_60Hz, 500, 400, 4);

  int s ="", "Select a command", "Restart (Boot Menu);Continue;Mount Disk");
  switch (s) {

    // Restart
    case 0:

    // Mount Disk
    case 2:
      int s ="", "Select Drive", "Floppy A (fd0);Floppy B (fd1)");
      if (s > -1) {
        constexpr int MAXNAMELEN = 256;
        unique_ptr<char[]> dir(new char[MAXNAMELEN + 1] { '/', 'S', 'D', 0 } );
        unique_ptr<char[]> filename(new char[MAXNAMELEN + 1] { 0 } );
        if (machine->diskFilename(s))
          strcpy(filename.get(), machine->diskFilename(s));
        if (ibox.fileSelector("Select Disk Image", "Image Filename", dir.get(), MAXNAMELEN, filename.get(), MAXNAMELEN) == InputResult::Enter) {
          machine->setDriveImage(s, filename.get());

    // Continue

  PS2Controller::keyboard()->enableVirtualKeys(false, false); // don't use virtual keys

void setup()
  Serial.begin(115200); delay(500); printf("\n\n\nReset\n\n");// DEBUG ONLY

  delay(100); // experienced crashes without this delay!

  preferences.begin("PCEmulator", false);

  // uncomment to clear preferences

  ibox.begin(VGA_640x480_60Hz, 500, 400, 4);
  ibox.setBackgroundColor(RGB888(0, 0, 0));

  ibox.onPaint = [&](Canvas * canvas) { drawInfo(canvas); };

  // we need PSRAM for this app, but we will handle it manually, so please DO NOT enable PSRAM on your development env
  ibox.message("Warning!", "Please disable PSRAM to improve performance!");

  // note: we use just 2MB of PSRAM so the infamous PSRAM bug should not happen. But to avoid gcc compiler hack (-mfix-esp32-psram-cache-issue)
  // we enable PSRAM at runtime, otherwise the hack slows down CPU too much (PSRAM_HACK is no more required).
  if (esp_spiram_init() != ESP_OK)
    ibox.message("Error!", "This app requires a board with PSRAM!", nullptr, nullptr);


  if (!FileBrowser::mountSDCard(false, SD_MOUNT_PATH, 8))   // @TODO: reduce to 4?
    ibox.message("Error!", "This app requires a SD-CARD!", nullptr, nullptr);

  // uncomment to format SD!
  //FileBrowser::format(fabgl::DriveType::SDCard, 0);



  // machine configurations
  MachineConf mconf;

  // show a list of machine configurations

  int idx = preferences.getInt("dconf", 0);

  for (bool showDialog = true; showDialog; ) {


    StringList dconfs;
    for (auto conf = mconf.getFirstItem(); conf; conf = conf->next)
      dconfs.append(conf->desc);, true);

    ibox.setupButton(0, "Browse Files");
    ibox.setupButton(1, "Options", "Edit;New;Remove", 52);
    auto r ="Machine Configurations", "Please select a machine configuration", &dconfs, nullptr, "Run");

    idx = dconfs.getFirstSelected();

    switch (r) {
      case InputResult::ButtonExt0:
        // Browse Files
        ibox.folderBrowser("Browse Files", SD_MOUNT_PATH);
      case InputResult::ButtonExt1:
        // Options
        switch (ibox.selectedSubItem()) {
          // Edit
          case 0:
            editConfigDialog(&ibox, &mconf, idx);
          // New
          case 1:
            newConfigDialog(&ibox, &mconf, idx);
          // Remove
          case 2:
            delConfigDialog(&ibox, &mconf, idx);
      case InputResult::Enter:
        // Run
        showDialog = false;

    // next selection will not have timeout

  idx = imax(idx, 0);
  preferences.putInt("dconf", idx);

  // setup selected configuration
  auto conf = mconf.getItem(idx);

  char const * diskFilename[DISKCOUNT];
  downloadOK = true;
  for (int i = 0; i < DISKCOUNT && downloadOK; ++i)
    diskFilename[i] = getDisk(conf->disk[i]);

  if (!downloadOK || (!diskFilename[0] && !diskFilename[2])) {
    // unable to get boot disks
    ibox.message("Error!", "Unable to get system disks!");

  if (wifiConnected) {
    // disk downloaded from the Internet, need to reboot to fully disable wifi
    ibox.message("", "Disks downloaded. Restarting...");


  machine = new Machine;

  for (int i = 0; i < DISKCOUNT; ++i)
    machine->setDriveImage(i, diskFilename[i], conf->cylinders[i], conf->heads[i], conf->sectors[i]);


  printf("MALLOC_CAP_32BIT : %d bytes (largest %d bytes)\r\n", heap_caps_get_free_size(MALLOC_CAP_32BIT), heap_caps_get_largest_free_block(MALLOC_CAP_32BIT));
  printf("MALLOC_CAP_8BIT  : %d bytes (largest %d bytes)\r\n", heap_caps_get_free_size(MALLOC_CAP_8BIT), heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
  printf("MALLOC_CAP_DMA   : %d bytes (largest %d bytes)\r\n\n", heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_largest_free_block(MALLOC_CAP_DMA));



namespace fabgl {
  extern volatile uint64_t s_vgapalctrlcycles;
using fabgl::s_vgapalctrlcycles;

void loop()

  static uint32_t tcpu = 0, s1 = 0, count = 0;
  tcpu = machine->ticksCounter();
  s_vgapalctrlcycles = 0;
  s1 = fabgl::getCycleCount();
  printf("%d\tCPU: %d", count, machine->ticksCounter() - tcpu);
  printf("   Graph: %lld / %d   (%d%%)\n", s_vgapalctrlcycles, fabgl::getCycleCount() - s1, (int)((double)s_vgapalctrlcycles/240000000*100));



Here is the Esp32-Wrover T8 v.1.7 pinout that that I am also using in the schematic above in this project to get the PS2 Mouse to work:

Any help as to what I am doing wrong would be greatly appreciated, thank you very much!

Report to moderators noted.
I think you are having difficulty getting any help because what you are asking about is unusual. It might be that there is no one here familiar with what you are doing.

It helps if you provide all the information about your question on the forum here, not links off to somewhere else that people have to follow. That you have provided links might well have put off the person, if there is anyone, who could have helped you. No one can guarantee you an answer, but making it easy for people to find the information they need to help improves your chances. Have a read of the forum guide before making any changes to your question How to get the best out of this forum

Thank you very much, I will modify the question to give all of the information that I can possibly give, and I will modify the links into more useful information like code in code tags and pictures as well.

Is there anything else I could Improve with this question, I have fixed the links and replaced them with pictures and code. I have also put more information at the top of the post. Thank you again for your help!

Not that I can think of.

Good luck!

Thank you!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.