1
0
mirror of https://github.com/fruit-bat/pico-zxspectrum.git synced 2025-04-19 00:04:01 +03:00

prepare for Pimoroni Pico VGA

This commit is contained in:
Phil 2022-09-21 18:48:44 +01:00
parent 8f121f794f
commit 695df72279
7 changed files with 611 additions and 16 deletions

287
src/ZxSpectrumEmu.cpp Normal file
View File

@ -0,0 +1,287 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "hardware/vreg.h"
#include "hardware/pwm.h"
#include "vga.h"
#include "ZxSpectrumPrepareRgbScanline.h"
// #include "pzx_keyscan.h"
#include "PicoCharRendererVga.h"
#include "PicoWinHidKeyboard.h"
#include "PicoDisplay.h"
#include "PicoPen.h"
#include "PicoTextField.h"
#include "PicoWinHidKeyboard.h"
#include "ZxSpectrumFatSpiKiosk.h"
#include "ZxSpectrum.h"
#include "ZxSpectrumHidKeyboard.h"
#include "ZxSpectrumDualJoystick.h"
#include "ZxSpectrumHidJoystick.h"
// #include "ZxSpectrumPicomputerJoystick.h"
#include "bsp/board.h"
#include "tusb.h"
#include <pico/printf.h>
#include "SdCardFatFsSpi.h"
#include "QuickSave.h"
#include "ZxSpectrumFatFsSpiFileLoop.h"
#include "PicoWinHidKeyboard.h"
#include "PicoDisplay.h"
#include "ZxSpectrumMenu.h"
#include "ZxSpectrumAudio.h"
#include "ZxSpectrumEmuVga.h"
#define VREG_VSEL VREG_VOLTAGE_1_10
struct semaphore ;
static const sVmode* vmode = NULL;
uint8_t* screenPtr;
uint8_t* attrPtr;
static bool showMenu = true;
static bool toggleMenu = false;
static volatile uint _frames = 0;
std::function<void()> _scanline_extra;
std::function<void()> _frame_extra;
void __not_in_flash_func(core1_main)() {
sem_acquire_blocking(&core1_start_sme);
printf("Core 1 running...\n");
// TODO fetch the resolution from the mode ?
VgaInit(vmode,640,480);
while (1) {
VgaLineBuf *linebuf = get_vga_line();
uint32_t* buf = (uint32_t*)&(linebuf->line);
uint32_t y = linebuf->row;
if (showMenu) {
pcw_prepare_vga332_scanline_80(
buf,
y,
linebuf->frame);
}
else {
zx_prepare_rgb_scanline(
buf,
y,
linebuf->frame,
screenPtr,
attrPtr,
zxSpectrum.borderColour()
);
}
_scanline_extra();
// pzx_keyscan_row();
if (y == 239) { // TODO use a const / get from vmode
// TODO Tidy this mechanism up
screenPtr = zxSpectrum.screenPtr();
attrPtr = screenPtr + (32 * 24 * 8);
if (toggleMenu) {
showMenu = !showMenu;
toggleMenu = false;
_frame_extra();
// picomputerJoystick.enabled(!showMenu);
}
_frames = linebuf->frame;
}
}
__builtin_unreachable();
}
void __not_in_flash_func(main_loop)(std::function<void()> main_loop_extra){
unsigned int lastInterruptFrame = _frames;
//Main Loop
uint frames = 0;
while(1){
tuh_task();
main_loop_extra();
// hid_keyboard_report_t const *curr;
// hid_keyboard_report_t const *prev;
// pzx_keyscan_get_hid_reports(&curr, &prev);
// process_picomputer_kbd_report(curr, prev);
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
}
}
else if (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}
}
}
int main_vga(
ZxSpectrum *pzxSpectrum,
PicoDisplay *ppicoDisplay,
std::function<void()> post_init,
std::function<void()> main_loop_extra,
std::function<void()> scanline_extra,
std::function<void()> frame_extra,
){
_scanline_extra = scanline_extra
_frame_extra = frame_extra;
vreg_set_voltage(VREG_VSEL);
sleep_ms(10);
vmode = Video(DEV_VGA, RES_HVGA);
sleep_ms(100);
// Initialise I/O
stdio_init_all();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
tusb_init();
// Configure the GPIO pins for audio
zxSpectrumAudioInit();
screenPtr = zxSpectrum.screenPtr();
attrPtr = screenPtr + (32 * 24 * 8);
// keyboard1.setZxSpectrum(&zxSpectrum);
// keyboard2.setZxSpectrum(&zxSpectrum);
// Initialise the menu renderer
pcw_init_renderer();
// // Initialise the keyboard scan
// pzx_keyscan_init();
// Initialise anything else
post_init();
sleep_ms(10);
sem_init(&core1_start_sme, 0, 1);
multicore_launch_core1(core1_main);
picoRootWin.showMessage([=](PicoPen *pen) {
pen->printAtF(3, 1, false, "Reading from SD card...");
});
picoDisplay.refresh();
sem_release(&core1_start_sme);
if (sdCard0.mount()) {
// Set up the quick load loops
zxSpectrumSnaps.reload();
zxSpectrumTapes.reload();
// Load quick save slot 1 if present
if (quickSave.used(0)) {
quickSave.load(&zxSpectrum, 0);
}
// See if the board is in kiosk mode
bool isKiosk = zxSpectrumKisok.isKiosk();
keyboard1.setKiosk(isKiosk);
keyboard2.setKiosk(isKiosk);
}
showMenu = false;
picoRootWin.removeMessage();
}
class ZxSpectrumEmu {
ZxSpectrum *_zxSpectrum,
PicoDisplay *_picoDisplay,
unsigned int _frames;
public:
void __not_in_flash_func(main_loop)(
ZxSpectrum *pzxSpectrum,
PicoDisplay *ppicoDisplay,
std::function<void()> *poll
){
unsigned int lastInterruptFrame = _frames;
//Main Loop
uint frames = 0, c = 0;
while(1){
poll[c++ & 1]();
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
pzxSpectrum->interrupt();
}
pzxSpectrum->step();
}
}
else if (frames != _frames) {
frames = _frames;
ppicoDisplay->refresh();
}
}
__builtin_unreachable();
}
};
void __not_in_flash_func(main_loop)(
ZxSpectrum *pzxSpectrum,
PicoDisplay *ppicoDisplay,
std::function<void()> *poll
){
unsigned int lastInterruptFrame = _frames;
//Main Loop
uint frames = 0, c = 0;
while(1){
poll[c++ & 1]();
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
pzxSpectrum->interrupt();
}
pzxSpectrum->step();
}
}
else if (frames != _frames) {
frames = _frames;
ppicoDisplay->refresh();
}
}
__builtin_unreachable();
}

2
src/ZxSpectrumEmu.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once

310
src/ZxSpectrumEmuVga.cpp Normal file
View File

@ -0,0 +1,310 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "hardware/vreg.h"
#include "hardware/pwm.h"
#include "vga.h"
#include "ZxSpectrumPrepareRgbScanline.h"
// #include "pzx_keyscan.h"
#include "PicoCharRendererVga.h"
#include "PicoWinHidKeyboard.h"
#include "PicoDisplay.h"
#include "PicoPen.h"
#include "PicoTextField.h"
#include "PicoWinHidKeyboard.h"
#include "ZxSpectrumFatSpiKiosk.h"
#include "ZxSpectrum.h"
#include "ZxSpectrumHidKeyboard.h"
#include "ZxSpectrumDualJoystick.h"
#include "ZxSpectrumHidJoystick.h"
// #include "ZxSpectrumPicomputerJoystick.h"
#include "bsp/board.h"
#include "tusb.h"
#include <pico/printf.h>
#include "SdCardFatFsSpi.h"
#include "QuickSave.h"
#include "ZxSpectrumFatFsSpiFileLoop.h"
#include "PicoWinHidKeyboard.h"
#include "PicoDisplay.h"
#include "ZxSpectrumMenu.h"
#include "ZxSpectrumAudio.h"
#include "ZxSpectrumEmuVga.h"
#define VREG_VSEL VREG_VOLTAGE_1_10
struct semaphore ;
static const sVmode* vmode = NULL;
uint8_t* screenPtr;
uint8_t* attrPtr;
static SdCardFatFsSpi sdCard0(0);
// ZX Spectrum emulator
static ZxSpectrumFatFsSpiFileLoop zxSpectrumSnaps(
&sdCard0,
"zxspectrum/snapshots"
);
static ZxSpectrumFatFsSpiFileLoop zxSpectrumTapes(
&sdCard0,
"zxspectrum/tapes"
);
static QuickSave quickSave(
&sdCard0,
"zxspectrum/quicksaves"
);
static ZxSpectrumHidJoystick hidJoystick;
// static ZxSpectrumPicomputerJoystick picomputerJoystick;
//static ZxSpectrumDualJoystick dualJoystick(
// &hidJoystick,
// &picomputerJoystick
//);
static ZxSpectrumFatSpiKiosk zxSpectrumKisok(
&sdCard0,
"zxspectrum"
);
static ZxSpectrumHidKeyboard keyboard1(
&zxSpectrumSnaps,
&zxSpectrumTapes,
&quickSave,
&dualJoystick
);
static ZxSpectrumHidKeyboard keyboard2(
&zxSpectrumSnaps,
&zxSpectrumTapes,
&quickSave,
&picomputerJoystick
);
static ZxSpectrum zxSpectrum(
&keyboard1,
&keyboard2,
&dualJoystick
);
static ZxSpectrumMenu picoRootWin(
&sdCard0,
&zxSpectrum,
&quickSave
);
static PicoDisplay picoDisplay(
pcw_screen(),
&picoRootWin
);
static PicoWinHidKeyboard picoWinHidKeyboard(
&picoDisplay
);
static bool showMenu = true;
static bool toggleMenu = false;
static volatile uint _frames = 0;
extern "C" void __not_in_flash_func(process_kbd_mount)(uint8_t dev_addr, uint8_t instance) {
keyboard1.mount();
}
extern "C" void __not_in_flash_func(process_kbd_unmount)(uint8_t dev_addr, uint8_t instance) {
keyboard1.unmount();
}
extern "C" void __not_in_flash_func(process_kbd_report)(hid_keyboard_report_t const *report, hid_keyboard_report_t const *prev_report) {
int r;
if (showMenu) {
r = picoWinHidKeyboard.processHidReport(report, prev_report);
}
else {
r = keyboard1.processHidReport(report, prev_report);
}
if (r == 1) {
toggleMenu = true;
picoRootWin.repaint();
}
}
/*
void __not_in_flash_func(process_picomputer_kbd_report)(hid_keyboard_report_t const *report, hid_keyboard_report_t const *prev_report) {
int r;
if (showMenu) {
r = picoWinHidKeyboard.processHidReport(report, prev_report);
}
else {
r = keyboard2.processHidReport(report, prev_report);
}
if (r == 1) {
toggleMenu = true;
picoRootWin.repaint();
}
}
*/
std::function<void()> _scanline_extra;
std::function<void()> _frame_extra;
void __not_in_flash_func(core1_main)() {
sem_acquire_blocking(&core1_start_sme);
printf("Core 1 running...\n");
// TODO fetch the resolution from the mode ?
VgaInit(vmode,640,480);
while (1) {
VgaLineBuf *linebuf = get_vga_line();
uint32_t* buf = (uint32_t*)&(linebuf->line);
uint32_t y = linebuf->row;
if (showMenu) {
pcw_prepare_vga332_scanline_80(
buf,
y,
linebuf->frame);
}
else {
zx_prepare_rgb_scanline(
buf,
y,
linebuf->frame,
screenPtr,
attrPtr,
zxSpectrum.borderColour()
);
}
_scanline_extra();
// pzx_keyscan_row();
if (y == 239) { // TODO use a const / get from vmode
// TODO Tidy this mechanism up
screenPtr = zxSpectrum.screenPtr();
attrPtr = screenPtr + (32 * 24 * 8);
if (toggleMenu) {
showMenu = !showMenu;
toggleMenu = false;
_frame_extra();
// picomputerJoystick.enabled(!showMenu);
}
_frames = linebuf->frame;
}
}
__builtin_unreachable();
}
void __not_in_flash_func(main_loop)(std::function<void()> main_loop_extra){
unsigned int lastInterruptFrame = _frames;
//Main Loop
uint frames = 0;
while(1){
tuh_task();
main_loop_extra();
// hid_keyboard_report_t const *curr;
// hid_keyboard_report_t const *prev;
// pzx_keyscan_get_hid_reports(&curr, &prev);
// process_picomputer_kbd_report(curr, prev);
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
}
}
else if (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}
}
}
int main_vga(
std::function<void()> post_init,
std::function<void()> main_loop_extra,
std::function<void()> scanline_extra,
std::function<void()> frame_extra,
){
_scanline_extra = scanline_extra
_frame_extra = frame_extra;
vreg_set_voltage(VREG_VSEL);
sleep_ms(10);
vmode = Video(DEV_VGA, RES_HVGA);
sleep_ms(100);
// Initialise I/O
stdio_init_all();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
tusb_init();
// Configure the GPIO pins for audio
zxSpectrumAudioInit();
screenPtr = zxSpectrum.screenPtr();
attrPtr = screenPtr + (32 * 24 * 8);
keyboard1.setZxSpectrum(&zxSpectrum);
keyboard2.setZxSpectrum(&zxSpectrum);
// Initialise the menu renderer
pcw_init_renderer();
// // Initialise the keyboard scan
// pzx_keyscan_init();
// Initialise anything else
post_init();
sleep_ms(10);
sem_init(&core1_start_sme, 0, 1);
multicore_launch_core1(core1_main);
picoRootWin.showMessage([=](PicoPen *pen) {
pen->printAtF(3, 1, false, "Reading from SD card...");
});
picoDisplay.refresh();
sem_release(&core1_start_sme);
if (sdCard0.mount()) {
// Set up the quick load loops
zxSpectrumSnaps.reload();
zxSpectrumTapes.reload();
// Load quick save slot 1 if present
if (quickSave.used(0)) {
quickSave.load(&zxSpectrum, 0);
}
// See if the board is in kiosk mode
bool isKiosk = zxSpectrumKisok.isKiosk();
keyboard1.setKiosk(isKiosk);
keyboard2.setKiosk(isKiosk);
}
showMenu = false;
picoRootWin.removeMessage();
main_loop(main_loop_extra);
}
ZxSpectrumHidKeyboard *get_keyboard2() {
return &keyboard2;
}

5
src/ZxSpectrumEmuVga.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
int main_vga(std::function<void()> post_init);
//ZxSpectrumHidKeyboard *get_keyboard2();

View File

@ -4,6 +4,10 @@ add_executable(ZxSpectrumPicoVga
main.cpp
)
pico_generate_pio_header(ZxSpectrumPicoVga
${zxspectrum_audio_i2s_pio}
)
target_compile_definitions(ZxSpectrumPicoVga PRIVATE
# Tell FATFS we want to find files
FF_USE_FIND=1
@ -17,13 +21,6 @@ target_compile_definitions(ZxSpectrumPicoVga PRIVATE
# Set up the menu 80 columns and 30 rows
PCS_COLS=80
PCS_ROWS=30
# Configure the SPI sd card to use SPI0
SDCARD_PIN_SPI0_CS=5
SDCARD_PIN_SPI0_SCK=2
SDCARD_PIN_SPI0_MOSI=3
SDCARD_PIN_SPI0_MISO=4
DEBUG_FAT_SPI
# VGA 16
# TODO
@ -40,8 +37,7 @@ target_compile_definitions(ZxSpectrumPicoVga PRIVATE
target_link_libraries(ZxSpectrumPicoVga
${zxspectrum_common_libs}
pico_emu_utils
pico_vga_menu
pico_vga_332
pico_vga16_menu
tinyusb_host
tinyusb_board
hardware_pio

View File

@ -8,11 +8,9 @@
#endif
// TODO need a 16bit version
// #include "vga.h"
// TODO need a 16bit version
// #include "ZxSpectrumPrepareRgbScanline.h"
// TODO need a 16 bit version
//#include "PicoCharRendererVga.h"
#include "ZxSpectrumPrepareRgb16Scanline.h"
#include "PicoCharRendererVga16.h"
#include "PicoWinHidKeyboard.h"
#include "PicoDisplay.h"
#include "PicoPen.h"
@ -43,7 +41,6 @@
#define VREG_VSEL VREG_VOLTAGE_1_10
struct semaphore dvi_start_sem;
static const sVmode* vmode = NULL;
static SdCardFatFsSpi sdCard0(0);

View File

@ -9,8 +9,6 @@ set(picomputer_vga_defines
SDCARD_PIN_SPI0_SCK=2
SDCARD_PIN_SPI0_MOSI=3
SDCARD_PIN_SPI0_MISO=4
DEBUG_FAT_SPI
)
add_executable(ZxSpectrum4PinAudioVga1111Ps2