From a9d2851688916986c6d7153675c394d5bd69abba Mon Sep 17 00:00:00 2001 From: Tobias Gunkel Date: Sat, 16 Aug 2025 11:50:13 +0200 Subject: [PATCH] use framebuffer --- src/{core.h => common.h} | 16 ++ src/gb.cpp | 6 + src/gb.h | 8 + src/input.cpp | 239 ++++++++++++++++++++++++++ src/input.h | 29 ++++ src/lcd_core.cpp | 110 +++++++----- src/main.cpp | 286 ++------------------------------ src/tft-espi-config/tft_setup.h | 10 +- 8 files changed, 385 insertions(+), 319 deletions(-) rename src/{core.h => common.h} (71%) create mode 100644 src/gb.cpp create mode 100644 src/gb.h create mode 100644 src/input.cpp create mode 100644 src/input.h diff --git a/src/core.h b/src/common.h similarity index 71% rename from src/core.h rename to src/common.h index 883b11d..c480368 100644 --- a/src/core.h +++ b/src/common.h @@ -2,6 +2,12 @@ #include +#include "gb.h" + +// display is rotated, so TFT_WIDTH/HEIGHT cannot be used +#define DISPLAY_WIDTH TFT_HEIGHT +#define DISPLAY_HEIGHT TFT_WIDTH + enum class ScalingMode { NORMAL = 0, STRETCH, @@ -11,6 +17,10 @@ enum class ScalingMode { extern volatile ScalingMode scalingMode; +extern struct gb_s gb; +extern palette_t palette; // Colour palette +extern uint_fast32_t frames; + /* Multicore command structure. */ union core_cmd { struct @@ -31,6 +41,12 @@ union core_cmd { uint32_t full; }; +void nextPalette(); + +void prevPalette(); + void lcd_draw_line(struct gb_s* gb, const uint8_t* pixels, const uint_fast8_t line); void core1_init(); + +void reset(); diff --git a/src/gb.cpp b/src/gb.cpp new file mode 100644 index 0000000..cae2caf --- /dev/null +++ b/src/gb.cpp @@ -0,0 +1,6 @@ +#include + +#include "peanut_gb_options.h" +#include "peanut_gb.h" + +#include "gbcolors.h" diff --git a/src/gb.h b/src/gb.h new file mode 100644 index 0000000..b1955d4 --- /dev/null +++ b/src/gb.h @@ -0,0 +1,8 @@ +#pragma once + +#define PEANUT_GB_HEADER_ONLY +#include "peanut_gb_options.h" +#include "peanut_gb.h" + +#define GBCOLOR_HEADER_ONLY +#include "gbcolors.h" diff --git a/src/input.cpp b/src/input.cpp new file mode 100644 index 0000000..9909976 --- /dev/null +++ b/src/input.cpp @@ -0,0 +1,239 @@ +#include "common.h" +#include "input.h" + +#include "gb.h" + +static struct +{ + unsigned a : 1; + unsigned b : 1; + unsigned select : 1; + unsigned start : 1; + unsigned right : 1; + unsigned left : 1; + unsigned up : 1; + unsigned down : 1; +} prev_joypad_bits; + +#ifndef USE_PAD_GPIO +static PCF8574 pcf8574(0x20, 16, 17); +#endif + + +#ifdef USE_PAD_GPIO +void initJoypad() { + gpio_set_function(GPIO_UP, GPIO_FUNC_SIO); + gpio_set_function(GPIO_DOWN, GPIO_FUNC_SIO); + gpio_set_function(GPIO_LEFT, GPIO_FUNC_SIO); + gpio_set_function(GPIO_RIGHT, GPIO_FUNC_SIO); + gpio_set_function(GPIO_A, GPIO_FUNC_SIO); + gpio_set_function(GPIO_B, GPIO_FUNC_SIO); + gpio_set_function(GPIO_SELECT, GPIO_FUNC_SIO); + gpio_set_function(GPIO_START, GPIO_FUNC_SIO); + + gpio_set_dir(GPIO_UP, false); + gpio_set_dir(GPIO_DOWN, false); + gpio_set_dir(GPIO_LEFT, false); + gpio_set_dir(GPIO_RIGHT, false); + gpio_set_dir(GPIO_A, false); + gpio_set_dir(GPIO_B, false); + gpio_set_dir(GPIO_SELECT, false); + gpio_set_dir(GPIO_START, false); + + gpio_pull_up(GPIO_UP); + gpio_pull_up(GPIO_DOWN); + gpio_pull_up(GPIO_LEFT); + gpio_pull_up(GPIO_RIGHT); + gpio_pull_up(GPIO_A); + gpio_pull_up(GPIO_B); + gpio_pull_up(GPIO_SELECT); + gpio_pull_up(GPIO_START); +} +#else +void initJoypad() { + for (int pin = 0; pin < 8; ++pin) { + pcf8574.pinMode(pin, INPUT_PULLUP); + } + + pcf8574.setLatency(5); + + if (pcf8574.begin()){ + Serial.println("PCF8574 initialized"); + }else{ + Serial.println("PCF8574 initialization failed"); + while (true) ; + } +} +#endif + +void handleSerial() { + static uint64_t start_time = time_us_64(); + + /* Serial monitor commands */ + int input = Serial.read(); + if (input <= 0) { + return; + } + + switch (input) { + case 'i': + gb.direct.interlace = !gb.direct.interlace; + break; + + case 'f': + gb.direct.frame_skip = !gb.direct.frame_skip; + break; + + case 'b': { + uint64_t end_time; + uint32_t diff; + uint32_t fps; + + end_time = time_us_64(); + diff = end_time - start_time; + fps = ((uint64_t)frames * 1000 * 1000) / diff; + Serial.printf("Frames: %u\n" + "Time: %lu us\n" + "FPS: %lu\n", + frames, diff, fps); + Serial.flush(); + frames = 0; + start_time = time_us_64(); + break; + } + + case '\n': + case '\r': { + gb.direct.joypad_bits.start = 0; + break; + } + + case '\b': { + gb.direct.joypad_bits.select = 0; + break; + } + + case '8': { + gb.direct.joypad_bits.up = 0; + break; + } + + case '2': { + gb.direct.joypad_bits.down = 0; + break; + } + + case '4': { + gb.direct.joypad_bits.left = 0; + break; + } + + case '6': { + gb.direct.joypad_bits.right = 0; + break; + } + + case 'z': + case 'w': { + gb.direct.joypad_bits.a = 0; + break; + } + + case 'x': { + gb.direct.joypad_bits.b = 0; + break; + } + + case 'q': + reset(); + + case 'p': + nextPalette(); + + default: + break; + } +} + +void handlePad() { + /* Update buttons state */ + prev_joypad_bits.up = gb.direct.joypad_bits.up; + prev_joypad_bits.down = gb.direct.joypad_bits.down; + prev_joypad_bits.left = gb.direct.joypad_bits.left; + prev_joypad_bits.right = gb.direct.joypad_bits.right; + prev_joypad_bits.a = gb.direct.joypad_bits.a; + prev_joypad_bits.b = gb.direct.joypad_bits.b; + prev_joypad_bits.select = gb.direct.joypad_bits.select; + prev_joypad_bits.start = gb.direct.joypad_bits.start; + +#ifdef USE_PAD_GPIO + gb.direct.joypad_bits.up = gpio_get(PIN_UP); + gb.direct.joypad_bits.down = gpio_get(PIN_DOWN); + gb.direct.joypad_bits.left = gpio_get(PIN_LEFT); + gb.direct.joypad_bits.right = gpio_get(PIN_RIGHT); + gb.direct.joypad_bits.a = gpio_get(PIN_A); + gb.direct.joypad_bits.b = gpio_get(PIN_B); + gb.direct.joypad_bits.select = gpio_get(PIN_SELECT); + gb.direct.joypad_bits.start = gpio_get(PIN_START); +#else + #if 0 + Serial.printf("pins:\n"); + for (int i = 0; i < 8; ++i) { + int in = pcf8574.digitalRead(i); + Serial.printf(" %d", in); + } + Serial.printf("\n"); + #endif + + gb.direct.joypad_bits.up = pcf8574.digitalRead(PIN_UP); + gb.direct.joypad_bits.down = pcf8574.digitalRead(PIN_DOWN); + gb.direct.joypad_bits.left = pcf8574.digitalRead(PIN_LEFT); + gb.direct.joypad_bits.right = pcf8574.digitalRead(PIN_RIGHT); + gb.direct.joypad_bits.a = pcf8574.digitalRead(PIN_A); + gb.direct.joypad_bits.b = pcf8574.digitalRead(PIN_B); + gb.direct.joypad_bits.select = pcf8574.digitalRead(PIN_SELECT); + gb.direct.joypad_bits.start = pcf8574.digitalRead(PIN_START); +#endif + + /* hotkeys (select + * combo)*/ + if (!gb.direct.joypad_bits.select) { +#if ENABLE_SOUND + if (!gb.direct.joypad_bits.up && prev_joypad_bits.up) { + /* select + up: increase sound volume */ + i2s_increase_volume(&i2s_config); + } + if (!gb.direct.joypad_bits.down && prev_joypad_bits.down) { + /* select + down: decrease sound volume */ + i2s_decrease_volume(&i2s_config); + } +#endif + if (!gb.direct.joypad_bits.right && prev_joypad_bits.right) { + /* select + right: select the next manual color palette */ + nextPalette(); + } + if (!gb.direct.joypad_bits.left && prev_joypad_bits.left) { + /* select + left: select the previous manual color palette */ + prevPalette(); + } + if (!gb.direct.joypad_bits.start && prev_joypad_bits.start) { + /* select + start: save ram and resets to the game selection menu */ +#if ENABLE_SDCARD + write_cart_ram_file(&gb); +#endif + reset(); + } + if (!gb.direct.joypad_bits.a && prev_joypad_bits.a) { + /* select + A: enable/disable frame-skip => fast-forward */ + gb.direct.frame_skip = !gb.direct.frame_skip; + Serial.printf("I gb.direct.frame_skip = %d\n", gb.direct.frame_skip); + } + if (!gb.direct.joypad_bits.b && prev_joypad_bits.b) { + /* select + B: change scaling mode */ + scalingMode = (ScalingMode)(((int) scalingMode + 1) % ((int) ScalingMode::COUNT)); + union core_cmd cmd; + cmd.cmd = CORE_CMD_IDLE_SET; + multicore_fifo_push_blocking(cmd.full); + Serial.printf("I Scaling mode: = %d\n", scalingMode); + } + } +} diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..c20af7e --- /dev/null +++ b/src/input.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +/* GPIO Connections. */ +#ifdef USE_PAD_GPIO +#define PIN_UP 2 +#define PIN_DOWN 3 +#define PIN_LEFT 4 +#define PIN_RIGHT 5 +#define PIN_A 6 +#define PIN_B 7 +#define PIN_SELECT 8 +#define PIN_START 9 +#else +#define PIN_UP 0 +#define PIN_DOWN 1 +#define PIN_LEFT 2 +#define PIN_RIGHT 3 +#define PIN_A 5 +#define PIN_B 4 +#define PIN_SELECT 6 +#define PIN_START 7 +#endif + +void initJoypad(); + +void handlePad(); +void handleSerial(); diff --git a/src/lcd_core.cpp b/src/lcd_core.cpp index b591a54..c7fafc9 100644 --- a/src/lcd_core.cpp +++ b/src/lcd_core.cpp @@ -1,23 +1,21 @@ #include -#define PEANUT_GB_HEADER_ONLY -#include "peanut_gb_options.h" -#include "peanut_gb.h" +#include "common.h" -// Note: must be included before core -#include "gbcolors.h" -#include "core.h" +#define USE_FRAMEBUFFER static TFT_eSPI tft = TFT_eSPI(); +#ifdef USE_FRAMEBUFFER +static TFT_eSprite framebuffer = TFT_eSprite(&tft); +#else +static TFT_eSPI& framebuffer = tft; +#endif static uint8_t scaledLineOffsetTable[LCD_HEIGHT]; // scaled to 240 lines /* Pixel data is stored in here. */ static uint8_t pixels_buffer[LCD_WIDTH]; -extern struct gb_s gb; -extern palette_t palette; // Colour palette - volatile ScalingMode scalingMode = ScalingMode::NORMAL; static int lcd_line_busy = 0; @@ -57,35 +55,54 @@ void lcd_draw_line(struct gb_s* gb, const uint8_t pixels[LCD_WIDTH], multicore_fifo_push_blocking(cmd.full); } -void lcd_write_pixels_normal(const uint16_t* pixels, uint8_t line, uint_fast16_t nmemb) { - const uint16_t colOffset = (tft.width() - nmemb) / 2; - const uint16_t lineOffset = (tft.height() - LCD_HEIGHT) / 2; - tft.setAddrWindow(colOffset, lineOffset + line, nmemb, 1); - tft.pushColors((uint16_t*) pixels, nmemb, true); +#ifdef USE_FRAMEBUFFER +void lcd_pushColors(size_t offset, const uint16_t* pixels, uint_fast16_t count) { + uint16_t* image = (uint16_t*) framebuffer.getPointer(); + memcpy(&image[offset], pixels, count * sizeof(uint16_t)); +} +#else +void lcd_pushColors(uint16_t colOffset, uint16_t lineOffset, const uint16_t* pixels, uint_fast16_t count) { + framebuffer.setAddrWindow(colOffset, lineOffset, count, 1); + tft.pushColors((uint16_t*) pixels, count, true); +} +#endif + +void lcd_write_pixels_normal(const uint16_t* pixels, uint8_t line, uint_fast16_t count) { + const uint16_t colOffset = (DISPLAY_WIDTH - count) / 2; + const uint16_t screenLineOffset = (DISPLAY_HEIGHT - LCD_HEIGHT) / 2; + const uint16_t lineOffset = screenLineOffset + line; + lcd_pushColors(lineOffset * DISPLAY_WIDTH + colOffset, pixels, count); } -void lcd_write_pixels_stretched(const uint16_t* pixels, uint8_t line, uint_fast16_t nmemb) { - static uint16_t doubledPixels[320]; +void lcd_write_pixels_stretched(const uint16_t* pixels, uint8_t line, uint_fast16_t count) { + static uint16_t doubledPixels[DISPLAY_WIDTH]; uint16_t pos = 0; - for (int col = 0; col < nmemb; ++col) { + for (int col = 0; col < count; ++col) { doubledPixels[pos++] = pixels[col]; doubledPixels[pos++] = pixels[col]; } const uint16_t stretchedWidth = pos; - uint8_t repeatedLines = IS_REPEATED(line); - tft.setAddrWindow(0, scaledLineOffsetTable[line], stretchedWidth, 1); - tft.pushColors((uint16_t*)doubledPixels, stretchedWidth, true); - if (repeatedLines) { - tft.setAddrWindow(0, scaledLineOffsetTable[line] + 1, stretchedWidth, 1); - tft.pushColors((uint16_t*)doubledPixels, stretchedWidth, true); + const uint8_t lineRepeated = IS_REPEATED(line); + const uint16_t lineOffset = scaledLineOffsetTable[line]; +#ifdef USE_FRAMEBUFFER + size_t offset = lineOffset * DISPLAY_WIDTH; + lcd_pushColors(offset, doubledPixels, stretchedWidth); + if (lineRepeated) { + lcd_pushColors(offset + DISPLAY_WIDTH, doubledPixels, stretchedWidth); } +#else + lcd_pushColors(0, lineOffset, doubledPixels, stretchedWidth); + if (lineRepeated) { + lcd_pushColors(0, lineOffset, doubledPixels, stretchedWidth); + } +#endif } -void lcd_write_pixels_stretched_keep_aspect(const uint16_t* pixels, uint8_t line, uint_fast16_t nmemb) { - static uint16_t doubledPixels[320]; +void lcd_write_pixels_stretched_keep_aspect(const uint16_t* pixels, uint8_t line, uint_fast16_t count) { + static uint16_t doubledPixels[DISPLAY_WIDTH]; uint16_t pos = 0; - for (int col = 0; col < nmemb; ++col) { + for (int col = 0; col < count; ++col) { doubledPixels[pos++] = pixels[col]; if (IS_REPEATED(col)) { doubledPixels[pos++] = pixels[col]; @@ -93,15 +110,22 @@ void lcd_write_pixels_stretched_keep_aspect(const uint16_t* pixels, uint8_t line } const uint16_t stretchedWidth = pos; - const uint16_t colOffset = (tft.width() - stretchedWidth) / 2; + const uint16_t colOffset = (DISPLAY_WIDTH - stretchedWidth) / 2; - uint8_t repeatedLines = IS_REPEATED(line); - tft.setAddrWindow(colOffset, scaledLineOffsetTable[line], stretchedWidth, 1); - tft.pushColors((uint16_t*)doubledPixels, stretchedWidth, true); - if (repeatedLines) { - tft.setAddrWindow(colOffset, scaledLineOffsetTable[line] + 1, stretchedWidth, 1); - tft.pushColors((uint16_t*)doubledPixels, stretchedWidth, true); + uint8_t lineRepeated = IS_REPEATED(line); + const uint16_t lineOffset = scaledLineOffsetTable[line]; +#ifdef USE_FRAMEBUFFER + size_t offset = lineOffset * DISPLAY_WIDTH + colOffset; + lcd_pushColors(offset, doubledPixels, stretchedWidth); + if (lineRepeated) { + lcd_pushColors(offset + DISPLAY_WIDTH, doubledPixels, stretchedWidth); } +#else + lcd_pushColors(colOffset, lineOffset, doubledPixels, stretchedWidth); + if (lineRepeated) { + lcd_pushColors(colOffset, lineOffset, doubledPixels, stretchedWidth); + } +#endif } void lcd_write_pixels(const uint16_t* pixels, uint8_t line, uint_fast16_t nmemb) { @@ -121,16 +145,16 @@ void lcd_write_pixels(const uint16_t* pixels, uint8_t line, uint_fast16_t nmemb) } void lcd_fill(uint16_t color) { +#ifdef USE_FRAMEBUFFER + framebuffer.fillSprite(color); +#else tft.fillScreen(color); -} - -void lcd_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color) { - tft.fillRect(0, 0, tft.width(), tft.height(), TFT_BLACK); +#endif } void lcd_text(char* s, uint8_t x, uint8_t y, uint16_t color, uint16_t bgcolor) { - tft.setTextColor(TFT_WHITE, TFT_BLACK); // TODO - tft.drawString(s, x, y); + framebuffer.setTextColor(TFT_WHITE, TFT_BLACK); // TODO + framebuffer.drawString(s, x, y); } void core1_lcd_draw_line(const uint_fast8_t line) { @@ -176,10 +200,12 @@ void core1_init() { lcd_init(); /* Clear LCD screen. */ - lcd_fill(0x0000); + lcd_fill(TFT_BLACK); - /* Set LCD window to DMG size. */ - lcd_fill_rect(31, 16, LCD_WIDTH, LCD_HEIGHT, 0x0000); +#ifdef USE_FRAMEBUFFER + framebuffer.setColorDepth(16); + framebuffer.createSprite(tft.width(), tft.height()); +#endif calcExtraLineTable(); diff --git a/src/main.cpp b/src/main.cpp index 8e2b461..05547fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,9 +13,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -// Peanut-GB emulator settings -#include "peanut_gb_options.h" -#include "peanut_gb.h" +#include "gb.h" /* C Headers */ #include @@ -25,40 +23,19 @@ /* RP2040 Headers */ #include -#include - /* Project headers */ #include "hedley.h" #include "minigb_apu.h" // #include "sdcard.h" -#include "core.h" +#include "common.h" #include "game_bin.h" #include "i2s.h" #define GBCOLOR_HEADER_ONLY #include "gbcolors.h" -/* GPIO Connections. */ -#ifdef USE_PAD_GPIO -#define PIN_UP 2 -#define PIN_DOWN 3 -#define PIN_LEFT 4 -#define PIN_RIGHT 5 -#define PIN_A 6 -#define PIN_B 7 -#define PIN_SELECT 8 -#define PIN_START 9 -#else -#define PIN_UP 0 -#define PIN_DOWN 1 -#define PIN_LEFT 2 -#define PIN_RIGHT 3 -#define PIN_A 5 -#define PIN_B 4 -#define PIN_SELECT 6 -#define PIN_START 7 -#endif +#include "input.h" #if ENABLE_SOUND /** @@ -84,22 +61,10 @@ static unsigned char rom_bank0[65536]; static uint8_t ram[32768]; static uint8_t manual_palette_selected = 0; -static PCF8574 pcf8574(0x20, 16, 17); - struct gb_s gb; palette_t palette; // Colour palette -static struct -{ - unsigned a : 1; - unsigned b : 1; - unsigned select : 1; - unsigned start : 1; - unsigned right : 1; - unsigned left : 1; - unsigned up : 1; - unsigned down : 1; -} prev_joypad_bits; +uint_fast32_t frames = 0; #define putstdio(x) write(1, x, strlen(x)) @@ -145,14 +110,12 @@ void gb_error(struct gb_s* gb, const enum gb_error_e gb_err, const uint16_t addr #endif } -void reset(); - void startEmulator() { #if ENABLE_LCD #if ENABLE_SDCARD /* ROM File selector */ lcd_init(); - lcd_fill(TFT_BLACK); // 0x0000); + tft.fillScreen(TFT_BLACK); rom_file_selector(); #endif #endif @@ -204,63 +167,18 @@ void reset() { watchdog_reboot(0,0,0); } -#ifdef USE_PAD_GPIO -void initJoypad() { - gpio_set_function(GPIO_UP, GPIO_FUNC_SIO); - gpio_set_function(GPIO_DOWN, GPIO_FUNC_SIO); - gpio_set_function(GPIO_LEFT, GPIO_FUNC_SIO); - gpio_set_function(GPIO_RIGHT, GPIO_FUNC_SIO); - gpio_set_function(GPIO_A, GPIO_FUNC_SIO); - gpio_set_function(GPIO_B, GPIO_FUNC_SIO); - gpio_set_function(GPIO_SELECT, GPIO_FUNC_SIO); - gpio_set_function(GPIO_START, GPIO_FUNC_SIO); +void overclock() { + const unsigned vco = 1596 * 1000 * 1000; /* 266MHz */ + const unsigned div1 = 6, div2 = 1; - gpio_set_dir(GPIO_UP, false); - gpio_set_dir(GPIO_DOWN, false); - gpio_set_dir(GPIO_LEFT, false); - gpio_set_dir(GPIO_RIGHT, false); - gpio_set_dir(GPIO_A, false); - gpio_set_dir(GPIO_B, false); - gpio_set_dir(GPIO_SELECT, false); - gpio_set_dir(GPIO_START, false); - - gpio_pull_up(GPIO_UP); - gpio_pull_up(GPIO_DOWN); - gpio_pull_up(GPIO_LEFT); - gpio_pull_up(GPIO_RIGHT); - gpio_pull_up(GPIO_A); - gpio_pull_up(GPIO_B); - gpio_pull_up(GPIO_SELECT); - gpio_pull_up(GPIO_START); + vreg_set_voltage(VREG_VOLTAGE_1_15); + sleep_ms(2); + set_sys_clock_pll(vco, div1, div2); + sleep_ms(2); } -#else -void initJoypad() { - for (int pin = 0; pin < 8; ++pin) { - pcf8574.pinMode(pin, INPUT_PULLUP); - } - pcf8574.setLatency(5); - - if (pcf8574.begin()){ - Serial.println("PCF8574 initialized"); - }else{ - Serial.println("PCF8574 initialization failed"); - while (true) ; - } -} -#endif - -void setup(void) { - /* Overclock. */ - { - const unsigned vco = 1596 * 1000 * 1000; /* 266MHz */ - const unsigned div1 = 6, div2 = 1; - - vreg_set_voltage(VREG_VOLTAGE_1_15); - sleep_ms(2); - set_sys_clock_pll(vco, div1, div2); - sleep_ms(2); - } +void setup() { + overclock(); /* Initialise USB serial connection for debugging. */ Serial.begin(115200); @@ -312,181 +230,7 @@ void prevPalette() { manual_assign_palette(palette, manual_palette_selected); } -void handleSerial(uint_fast32_t& frames) { - static uint64_t start_time = time_us_64(); - - /* Serial monitor commands */ - int input = Serial.read(); - if (input <= 0) { - return; - } - - switch (input) { - case 'i': - gb.direct.interlace = !gb.direct.interlace; - break; - - case 'f': - gb.direct.frame_skip = !gb.direct.frame_skip; - break; - - case 'b': { - uint64_t end_time; - uint32_t diff; - uint32_t fps; - - end_time = time_us_64(); - diff = end_time - start_time; - fps = ((uint64_t)frames * 1000 * 1000) / diff; - Serial.printf("Frames: %u\n" - "Time: %lu us\n" - "FPS: %lu\n", - frames, diff, fps); - Serial.flush(); - frames = 0; - start_time = time_us_64(); - break; - } - - case '\n': - case '\r': { - gb.direct.joypad_bits.start = 0; - break; - } - - case '\b': { - gb.direct.joypad_bits.select = 0; - break; - } - - case '8': { - gb.direct.joypad_bits.up = 0; - break; - } - - case '2': { - gb.direct.joypad_bits.down = 0; - break; - } - - case '4': { - gb.direct.joypad_bits.left = 0; - break; - } - - case '6': { - gb.direct.joypad_bits.right = 0; - break; - } - - case 'z': - case 'w': { - gb.direct.joypad_bits.a = 0; - break; - } - - case 'x': { - gb.direct.joypad_bits.b = 0; - break; - } - - case 'q': - reset(); - - case 'p': - nextPalette(); - - default: - break; - } -} - -void handlePad() { - /* Update buttons state */ - prev_joypad_bits.up = gb.direct.joypad_bits.up; - prev_joypad_bits.down = gb.direct.joypad_bits.down; - prev_joypad_bits.left = gb.direct.joypad_bits.left; - prev_joypad_bits.right = gb.direct.joypad_bits.right; - prev_joypad_bits.a = gb.direct.joypad_bits.a; - prev_joypad_bits.b = gb.direct.joypad_bits.b; - prev_joypad_bits.select = gb.direct.joypad_bits.select; - prev_joypad_bits.start = gb.direct.joypad_bits.start; - -#ifdef USE_PAD_GPIO - gb.direct.joypad_bits.up = gpio_get(PIN_UP); - gb.direct.joypad_bits.down = gpio_get(PIN_DOWN); - gb.direct.joypad_bits.left = gpio_get(PIN_LEFT); - gb.direct.joypad_bits.right = gpio_get(PIN_RIGHT); - gb.direct.joypad_bits.a = gpio_get(PIN_A); - gb.direct.joypad_bits.b = gpio_get(PIN_B); - gb.direct.joypad_bits.select = gpio_get(PIN_SELECT); - gb.direct.joypad_bits.start = gpio_get(PIN_START); -#else - #if 0 - Serial.printf("pins:\n"); - for (int i = 0; i < 8; ++i) { - int in = pcf8574.digitalRead(i); - Serial.printf(" %d", in); - } - Serial.printf("\n"); - #endif - - gb.direct.joypad_bits.up = pcf8574.digitalRead(PIN_UP); - gb.direct.joypad_bits.down = pcf8574.digitalRead(PIN_DOWN); - gb.direct.joypad_bits.left = pcf8574.digitalRead(PIN_LEFT); - gb.direct.joypad_bits.right = pcf8574.digitalRead(PIN_RIGHT); - gb.direct.joypad_bits.a = pcf8574.digitalRead(PIN_A); - gb.direct.joypad_bits.b = pcf8574.digitalRead(PIN_B); - gb.direct.joypad_bits.select = pcf8574.digitalRead(PIN_SELECT); - gb.direct.joypad_bits.start = pcf8574.digitalRead(PIN_START); -#endif - - /* hotkeys (select + * combo)*/ - if (!gb.direct.joypad_bits.select) { -#if ENABLE_SOUND - if (!gb.direct.joypad_bits.up && prev_joypad_bits.up) { - /* select + up: increase sound volume */ - i2s_increase_volume(&i2s_config); - } - if (!gb.direct.joypad_bits.down && prev_joypad_bits.down) { - /* select + down: decrease sound volume */ - i2s_decrease_volume(&i2s_config); - } -#endif - if (!gb.direct.joypad_bits.right && prev_joypad_bits.right) { - /* select + right: select the next manual color palette */ - nextPalette(); - } - if (!gb.direct.joypad_bits.left && prev_joypad_bits.left) { - /* select + left: select the previous manual color palette */ - prevPalette(); - } - if (!gb.direct.joypad_bits.start && prev_joypad_bits.start) { - /* select + start: save ram and resets to the game selection menu */ -#if ENABLE_SDCARD - write_cart_ram_file(&gb); -#endif - reset(); - } - if (!gb.direct.joypad_bits.a && prev_joypad_bits.a) { - /* select + A: enable/disable frame-skip => fast-forward */ - gb.direct.frame_skip = !gb.direct.frame_skip; - Serial.printf("I gb.direct.frame_skip = %d\n", gb.direct.frame_skip); - } - if (!gb.direct.joypad_bits.b && prev_joypad_bits.b) { - /* select + B: change scaling mode */ - scalingMode = (ScalingMode)(((int) scalingMode + 1) % ((int) ScalingMode::COUNT)); - union core_cmd cmd; - cmd.cmd = CORE_CMD_IDLE_SET; - multicore_fifo_push_blocking(cmd.full); - Serial.printf("I Scaling mode: = %d\n", scalingMode); - } - } -} - void loop() { - static uint_fast32_t frames = 0; - gb.gb_frame = 0; do { @@ -503,5 +247,5 @@ void loop() { #endif handlePad(); - handleSerial(frames); + handleSerial(); } diff --git a/src/tft-espi-config/tft_setup.h b/src/tft-espi-config/tft_setup.h index 43688c1..c9543e2 100644 --- a/src/tft-espi-config/tft_setup.h +++ b/src/tft-espi-config/tft_setup.h @@ -23,14 +23,12 @@ // Tell the library to use parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT #define TFT_PARALLEL_16_BIT // **** 16-bit parallel ONLY for RP2040 processor **** - -// Display type - only define if RPi display -//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI - -// Only define one driver, the other ones must be commented out +#define RP2040_PIO_CLK_DIV 4 // 60ns #define ILI9341_DRIVER // Generic driver for common displays //#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172 +//#define ST7735_DRIVER + #if 0 #define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display #define TFT_INVERSION_OFF @@ -66,7 +64,7 @@ #define TFT_D7 7 #define TFT_WR 19 // Write strobe for modified Raspberry Pi TFT only #define TFT_DC 20 // Data Command control pin -#define TFT_CS 21 // Chip select control pin D8 +//#define TFT_CS 21 // Chip select control pin D8 #define TFT_RST 22 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V