I wanna show you my ESP8266 based Arduboy in a ps2 controller. Actually it is more a controller for my other projects where I can also play a few games.
Here is a link with more pictures and informations: thiniverse link
As already said the main chip is an ESP8266. I found a ESP8266 branch of arduboy but It was a bit different with an additional arduino Nano. So I forked the old arduboy(ONE) library and changed a few lines to make it run.
I am using a few librarys to get all this working:
PS2X_lib to read the controller buttons (there is a branch with ESP8266 support available)
SSD1306_OLED_ESP8266 to write to the 128x64 I2C oled
Brzo_i2c is used by the OLEDDisplay lib for 800MHz I2C speed
I also had to made some little changes in the SSD1306_OLED_ESP8266 lib, so sharing my arduboy fork alone wouldn´t really help anybody else. I know nothing about licences so I am not sure if I could share ported games with anybody else.
After playing Squario, which was the first and only arduboy game I ported, i realised that allmost every other game now uses Arduboy2. And by porting I mean adding about 10 lines of code, the rest happens inside the Arduboy lib. I tried to get the Arduboy2 lib running but had some problems with it and the games, there is a lot avr specific code in them.
Right now I am programming my own game based on the old Arduboy lib. I kind of like it more, because I want to use all those adafruit like draw funktions and stuff.
CPU Speed is not an issue if you have 32bit and 80MHz. I hope it will also run fast enough on those avr chips. Flash is more than enough available, so I compile it now and than for a lenoardo board to keep in mind how much there is left if I had a real arduboy.
I also ported the gamebuino library to this platform. The games are easier to port but I do not like the even smaller display resolution, so I got back to arduboy.
My experience was really good. After getting rid of all the avr pins, ports, assembler and timer stuff I just had to link the display library in. I learnd a lot and it was fun.
I do not own a ESP32 and I have not read a lot about it. It is way faster, I think with a chip like this you could easily control a color display with a lot more pixels.
I think my fork of arduboy2 should also work on a ESP32. The only little thing is I used everywhere these #ifdef ESP8266 lines. To compile it on a ESP32 you have to change those or #define ESP8266 in your code.
Here are some information about my Wemos d1 Mini ESP8266 build. The available pins are very limited, i used:
4 to SPI communicate with the ps2 controller and get the 6 buttons states.
2 to update the I2C display. (and get gyroscope chip data)
1 for a little speaker
1 ADC to measure the batttery voltage
2 Rx and Tx for debug (and bluetooth)
2 pins are free, I could have used them for ws2812 rgb leds
Some information about timings:
Updating the full display takes about 14ms. The display library is smart and remembers if you changed the whole area, if not it will only update the area where pixels changed and will be faster. But still this is the limiting faktor, everything else is done really fast.
I connected 6 buttons and the I2C oled display, no sound and no leds because there where not many pins left and I was too lazy. Those buttons worked and with some little changes many games should be possilbe to play.
On the second picture the following test code is running:
#include "Arduboy2.h"
#ifdef ESP8266
#define I2C_SDA D2
#define I2C_SCL D1
SSD1306Brzo oled(OLED_I2C_ADRESS, I2C_SDA, I2C_SCL);
#define MY_BUTTON_A D0
#define MY_BUTTON_B D4
#define MY_BUTTON_UP D6
#define MY_BUTTON_DOWN D7
#define MY_BUTTON_LEFT D5
#define MY_BUTTON_RIGHT D8
#endif
// Make an instance of arduboy used for many functions
Arduboy2 arduboy;
// some variables to count the frames pro seconde
uint8_t framesNow = 0;
uint8_t framesCurrent = 0;
uint8_t secondsNow = 0;
uint8_t secondsCurrent = -1;
// returns the frames displayed in the last second
uint8_t getFramesPerSecond() {
// get the current second
secondsNow = millis() / 1000;
if (secondsNow != secondsCurrent) {
// to reset only with every new second
secondsCurrent = secondsNow;
// save the last frames per second
framesCurrent = framesNow;
// reset the counter
framesNow = 0;
} else {
// count
framesNow++;
}
return framesCurrent;
}
#ifdef ESP8266
void getButtons() {
uint8_t buttons = 0;
if (digitalRead(MY_BUTTON_A))
buttons |= A_BUTTON;
if (digitalRead(MY_BUTTON_B))
buttons |= B_BUTTON;
if (digitalRead(MY_BUTTON_UP))
buttons |= UP_BUTTON;
if (digitalRead(MY_BUTTON_DOWN))
buttons |= DOWN_BUTTON;
if (digitalRead(MY_BUTTON_LEFT))
buttons |= LEFT_BUTTON;
if (digitalRead(MY_BUTTON_RIGHT))
buttons |= RIGHT_BUTTON;
arduboy.setExternalButtons(buttons);
}
#endif
void setup() {
#ifdef ESP8266
arduboy.setExternalButtonsHandler(getButtons);
// not sure if this is necessary
pinMode(MY_BUTTON_A, INPUT);
pinMode(MY_BUTTON_B, INPUT);
pinMode(MY_BUTTON_UP, INPUT);
pinMode(MY_BUTTON_DOWN, INPUT);
pinMode(MY_BUTTON_LEFT, INPUT);
pinMode(MY_BUTTON_RIGHT, INPUT);
#endif
arduboy.begin();
// set impossilbe high frame rate for max frames
arduboy.setFrameRate(1000);
}
void printPressedButtonAt(uint8_t yPos, String buttonName) {
arduboy.setCursor(20, yPos);
arduboy.print(buttonName + " Pressed");
}
void loop() {
if (!(arduboy.nextFrame()))
return;
// we clear our screen to black
arduboy.clear();
// need to change the screen because oled library updates only changed areas
if (arduboy.everyXFrames(2))
arduboy.fillScreen(WHITE);
arduboy.setCursor(0, 0);
arduboy.print(F("ESP8266 Test "));
arduboy.print(getFramesPerSecond());
// print buttons
if (arduboy.pressed(A_BUTTON))
printPressedButtonAt(9 * 1, "A");
if (arduboy.pressed(B_BUTTON))
printPressedButtonAt(9 * 2, "B");
if (arduboy.pressed(UP_BUTTON))
printPressedButtonAt(9 * 3, "UP");
if (arduboy.pressed(DOWN_BUTTON))
printPressedButtonAt(9 * 4, "DOWN");
if (arduboy.pressed(LEFT_BUTTON))
printPressedButtonAt(9 * 3, "LEFT");
if (arduboy.pressed(RIGHT_BUTTON))
printPressedButtonAt(9 * 4, "RIGHT");
arduboy.display();
}
The display says 64 frames, this is the maximum of frames pro second this built can do. Mostly because of the slow I2C bus, a arduboy.display() takes about 13ms. So games with 60 FPS could be a bit slow, because there is not much cpu time left for other things.
If this is compiled for the leonardo and put it in the emulator than round about 140 frames will be displayed.
It’s much work to do and one of the ideas is to implement web browser. It’s a first step to OTA (over the air) software update using WiFi without any wires, IDEs, compilers…
OLED is too small but i remember old times of mobile phones with small bw displays and WAP worked fine there. It’s also possible to attach 128х128 color TFT with much more space and colours…
Anyway looking around i found “Arduino PIP web browser” https://hackaday.io/project/3116-pip-arduino-web-browser
It’s seemed to me that it’s possible to port it to the ESP8266.
But having a display with 128x128 pixels wouldn´t help a lot if all the games only use half of the screen in black and white.
I was thinking about scaling the arduboy pixels, and with scaling factor two I mean to just use four pixels to display one arduboy pixel. Sadly the common and cheap
spi display resolutions are not ideal for scaling the arduboy screen.
I think it is absolutly crazy to use a color display with a high resolution to show arduboy stuff in two colors and a low resolution. But I already have one of those 240x320 pixels displays at home. Also I think the ESP would be powerfull enough and the spi fast enough to do this madness. So maybe I will try this soon.
I can´t help you with the wifi stuff, my knowledge about that is really small.
I have checked lot of colour displays IPS and TFT with esp8266.
The best to my mind is 1.44’’ TFT 128х128 and it ideally fits the form factor of the ESPboy device
and there is a special slot for OLED and this TFT on the final version of my psb…
i think the same way, meaning to software emulation the bw 128х64 OLED on the color TFT 128х128 in the ARDUBOY2 lib )
the idea is to keep compatibility of the new device with all previous bw games and apps and at the same time to bring new possibilities of 128х128 color tft
This is maybe the first homemade arduboy with an ili9341 touchscreen and an ESP32 chip.
You can see in the picture above, using only 128x64 pixels of those 320x240 pixels makes playing really ridiculous. So I scaled every arduboy pixel to a block of four display pixels. Doing this i am using 256128=32.768 of the 320240=76.800 pixels in total. Still far away from being optimal but okay for me.
The ili9341 SPI interface is really fast, but updating the screen with 60 FPS and more was challenging. The problem is there are now 4 times the pixels and every pixel has 16bit color instead of 1 bit of the oled screen. I had to use two big pixel buffers and some other tricks to be that fast.
It is hard to see in the shaky video, I scaled the pixels and played around with some color filters. And with color filter I mean replacing some black pixels that are next to many white pixels with a dark color and replacing some white pixels with a light color. Sometimes the picture gets a bit blurry but often I like the look with the new colors.
Here is a example Picture, first one is original, second with 2 greyscales and the third with yellow and magenta.