diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c3add4..e69142b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -51,6 +51,9 @@ set(zxspectrum_common_src ${CMAKE_CURRENT_LIST_DIR}/ZxSpectrumMenu.cpp ${CMAKE_CURRENT_LIST_DIR}/ZxSpectrumFatSpiExists.cpp ${CMAKE_CURRENT_LIST_DIR}/PicoOnScreenKeyboard.cpp + ${CMAKE_CURRENT_LIST_DIR}/ZxSpectrumPort.cpp + ${CMAKE_CURRENT_LIST_DIR}/PicoMitePort.cpp + ${CMAKE_CURRENT_LIST_DIR}/WavesharePiZeroPort.cpp ) set(zxspectrum_rgb332_src @@ -88,6 +91,7 @@ set(zxspectrum_common_libs hardware_dma hardware_flash # Needed for flash settings (not currently working) hardware_sync # Needed for flash settings (not currently working) + hardware_adc Zeta Z80 ) diff --git a/src/PicoMitePort.cpp b/src/PicoMitePort.cpp new file mode 100644 index 0000000..e15776b --- /dev/null +++ b/src/PicoMitePort.cpp @@ -0,0 +1,32 @@ +#include "PicoMitePort.h" +#include "hardware/adc.h" + +// Output pins on GP10, GP11, GP12, GP13 +static const uint8_t POUT_PINS[] = {10, 11, 12, 13}; + +void PicoMitePort::init() { + adc_init(); + + // Make sure GPIO is high-impedance, no pullups etc + adc_gpio_init(26); + + // Select ADC input 2 (GP28) + adc_select_input(2); + + for(size_t i = 0; i < sizeof(POUT_PINS); ++i) { + gpio_init(POUT_PINS[i]); + gpio_set_dir(POUT_PINS[i], GPIO_OUT); + } +} + +uint8_t __not_in_flash_func(PicoMitePort::read)() { + uint16_t result = adc_read(); // Read 12 bit ADC + return (result >> 4) & 0xff; +} + +void __not_in_flash_func(PicoMitePort::write)(uint8_t data) { + for(size_t i = 0; i < sizeof(POUT_PINS); ++i) { + gpio_put(POUT_PINS[i], (data & 1) == 1); + data >>= 1; + } +} diff --git a/src/PicoMitePort.h b/src/PicoMitePort.h new file mode 100644 index 0000000..cee546b --- /dev/null +++ b/src/PicoMitePort.h @@ -0,0 +1,10 @@ +#pragma once + +#include "ZxSpectrumPort.h" + +class PicoMitePort : public ZxSpectrumPort { +public: + uint8_t read(); + void write(uint8_t data); + void init(); +}; diff --git a/src/RealPort.h b/src/RealPort.h new file mode 100644 index 0000000..d148da8 --- /dev/null +++ b/src/RealPort.h @@ -0,0 +1,17 @@ +#pragma once + +#if defined(PICO_MITE_PORT) +#include "PicoMitePort.h" +static PicoMitePort picoMitePort; +#define ZX_SPECTRUM_REAL_PORT &picoMitePort +#define ZX_SPECTRUM_REAL_PORT_INIT picoMitePort.init(); +#elif defined(WAVESHARE_PI_ZERO_PORT) +#include "WavesharePiZeroPort.h" +static WavesharePiZeroPort wavesharePiZeroPort; +#define ZX_SPECTRUM_REAL_PORT &wavesharePiZeroPort +#define ZX_SPECTRUM_REAL_PORT_INIT wavesharePiZeroPort.init(); +#else +#define ZX_SPECTRUM_REAL_PORT 0 +#define ZX_SPECTRUM_REAL_PORT_INIT +#endif + diff --git a/src/WavesharePiZeroPort.cpp b/src/WavesharePiZeroPort.cpp new file mode 100644 index 0000000..aa39151 --- /dev/null +++ b/src/WavesharePiZeroPort.cpp @@ -0,0 +1,37 @@ +#include "WavesharePiZeroPort.h" + +// Output pins on GP9, GP10, GP11, GP12 +static const uint8_t POUT_PINS[] = {9, 10, 11, 12}; + +// Input pins on GP13, GP14, GP15 +static const uint8_t PIN_PINS[] = {13, 14, 15}; + +void WavesharePiZeroPort::init() { + for(size_t i = 0; i < sizeof(POUT_PINS); ++i) { + const uint8_t pin = POUT_PINS[i]; + gpio_init(pin); + gpio_set_dir(pin, GPIO_OUT); + } + for(size_t i = 0; i < sizeof(PIN_PINS); ++i) { + const uint8_t pin = PIN_PINS[i]; + gpio_init(pin); + gpio_set_dir(pin, GPIO_IN); + gpio_set_pulls(pin, true, false); + } +} + +uint8_t __not_in_flash_func(WavesharePiZeroPort::read)() { + uint32_t data = 0; + for(size_t i = 0; i < sizeof(PIN_PINS); ++i) { + data |= gpio_get(PIN_PINS[sizeof(PIN_PINS) - i - 1]) ? 1 : 0; + data <<= 1; + } + return (uint8_t)data; +} + +void __not_in_flash_func(WavesharePiZeroPort::write)(uint8_t data) { + for(size_t i = 0; i < sizeof(POUT_PINS); ++i) { + gpio_put(POUT_PINS[i], (data & 1) == 1); + data >>= 1; + } +} diff --git a/src/WavesharePiZeroPort.h b/src/WavesharePiZeroPort.h new file mode 100644 index 0000000..a337208 --- /dev/null +++ b/src/WavesharePiZeroPort.h @@ -0,0 +1,10 @@ +#pragma once + +#include "ZxSpectrumPort.h" + +class WavesharePiZeroPort : public ZxSpectrumPort { +public: + uint8_t read(); + void write(uint8_t data); + void init(); +}; diff --git a/src/ZxSpectrum.cpp b/src/ZxSpectrum.cpp index 6d5205c..aa9d59c 100644 --- a/src/ZxSpectrum.cpp +++ b/src/ZxSpectrum.cpp @@ -14,13 +14,15 @@ ZxSpectrum::ZxSpectrum( ZxSpectrumKeyboard *keyboard1, ZxSpectrumKeyboard *keyboard2, ZxSpectrumJoystick *joystick, - ZxSpectrumMouse *mouse + ZxSpectrumMouse *mouse, + ZxSpectrumPort *parallelPort ) : _moderate(9), _keyboard1(keyboard1), _keyboard2(keyboard2), _joystick(joystick), _mouse(mouse), + _parallelPort(parallelPort), _borderColour(7), _port254(0), _ear(false), diff --git a/src/ZxSpectrum.h b/src/ZxSpectrum.h index 2abda9e..b7475f4 100644 --- a/src/ZxSpectrum.h +++ b/src/ZxSpectrum.h @@ -14,6 +14,7 @@ #include "hardware/pwm.h" #include "ZxSpectrumAudio.h" #include "ZxSpectrumMouse.h" +#include "ZxSpectrumPort.h" // #define DEBUG_SPEC #ifdef DEBUG_SPEC @@ -43,6 +44,7 @@ class ZxSpectrum { ZxSpectrumKeyboard *_keyboard2; ZxSpectrumJoystick *_joystick; ZxSpectrumMouse *_mouse; + ZxSpectrumPort *_parallelPort; uint8_t _borderColour; uint8_t _port254; uint8_t _portMem; @@ -137,6 +139,10 @@ class ZxSpectrum { return _mouse->buttons(); } + if (address == 0x0FFF && _parallelPort) { + return _parallelPort->read(); + } + return 0xFF; } @@ -156,7 +162,7 @@ inline void writeIO(uint16_t address, uint8_t value) return; } //BFFD - if (!(address & 0x8002) && _type != ZxSpectrum48k) + if (!(address & 0x8002) && (_type != ZxSpectrum48k)) { if ((_portMem & 0x20) == 0) { _fc += ((_portMem ^ value) >> 3) & 1; @@ -165,7 +171,11 @@ inline void writeIO(uint16_t address, uint8_t value) setPageaddr(0, (uint8_t*)((value & 0x10) ? zx_128k_rom_2 : zx_128k_rom_1)); } return; - }; + }; + + if (address == 0x0FFF && _parallelPort) { + _parallelPort->write(value); + } } else { @@ -243,7 +253,8 @@ inline void writeIO(uint16_t address, uint8_t value) ZxSpectrumKeyboard *keyboard1, ZxSpectrumKeyboard *keyboard2, ZxSpectrumJoystick *joystick, - ZxSpectrumMouse *mouse + ZxSpectrumMouse *mouse, + ZxSpectrumPort *parallelPort ); inline uint8_t* screenPtr() { return (unsigned char*)&_RAM[(_portMem & 8) ? 7 : 5]; } inline uint8_t* memPtr(uint32_t i) { return (unsigned char*)&_RAM[i]; } diff --git a/src/ZxSpectrumPort.cpp b/src/ZxSpectrumPort.cpp new file mode 100644 index 0000000..34e41c7 --- /dev/null +++ b/src/ZxSpectrumPort.cpp @@ -0,0 +1,2 @@ +#include "ZxSpectrumPort.h" + diff --git a/src/ZxSpectrumPort.h b/src/ZxSpectrumPort.h new file mode 100644 index 0000000..c15ed44 --- /dev/null +++ b/src/ZxSpectrumPort.h @@ -0,0 +1,9 @@ +#pragma once +#include + +class ZxSpectrumPort { +public: + virtual uint8_t __not_in_flash_func(read)() = 0; + virtual void __not_in_flash_func(write)(uint8_t data) = 0; + virtual void init(); +}; diff --git a/src/hdmi/CMakeLists.txt b/src/hdmi/CMakeLists.txt index b07764a..c1ef234 100644 --- a/src/hdmi/CMakeLists.txt +++ b/src/hdmi/CMakeLists.txt @@ -355,6 +355,7 @@ foreach(target add_executable(${target} ${zxspectrum_common_src} ${zxspectrum_hdmi_src} + main.cpp ) target_link_libraries(${target} @@ -386,6 +387,8 @@ set (ZxSpectrumPiZero_defines SDCARD_PIN_SPI0_MISO=20 # HDMI audio PICO_HDMI_AUDIO + # Add a real IO port + WAVESHARE_PI_ZERO_PORT ) target_compile_definitions(ZxSpectrumPiZero_640x480x60Hz PRIVATE diff --git a/src/hdmi/main.cpp b/src/hdmi/main.cpp index a322f12..405ecc6 100644 --- a/src/hdmi/main.cpp +++ b/src/hdmi/main.cpp @@ -56,6 +56,7 @@ extern "C" { #include "ZxSpectrumAudio.h" #include "ZxSpectrumFileSettings.h" #include "ZxSpectrumDisplay.h" +#include "RealPort.h" #define UART_ID uart0 #define BAUD_RATE 115200 @@ -109,7 +110,8 @@ static ZxSpectrum zxSpectrum( &keyboard1, &keyboard2, &joystick, - &mouse + &mouse, + ZX_SPECTRUM_REAL_PORT ); static ZxSpectrumFileSettings zxSpectrumSettings( &sdCard0, @@ -379,6 +381,7 @@ int main() { #ifdef USE_PS2_KBD ps2kbd.init_gpio(); #endif + ZX_SPECTRUM_REAL_PORT_INIT gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); diff --git a/src/picomputer/picomputer_st7789/main.cpp b/src/picomputer/picomputer_st7789/main.cpp index 99706e0..9668ff2 100644 --- a/src/picomputer/picomputer_st7789/main.cpp +++ b/src/picomputer/picomputer_st7789/main.cpp @@ -88,7 +88,8 @@ static ZxSpectrum zxSpectrum( &keyboard1, &keyboard2, &dualJoystick, - &mouse + &mouse, + 0 ); static ZxSpectrumFileSettings zxSpectrumSettings( &sdCard0, diff --git a/src/picomputer/picomputer_vga/main.cpp b/src/picomputer/picomputer_vga/main.cpp index daa26cb..d431d65 100644 --- a/src/picomputer/picomputer_vga/main.cpp +++ b/src/picomputer/picomputer_vga/main.cpp @@ -76,7 +76,8 @@ static ZxSpectrum zxSpectrum( &keyboard1, &keyboard2, &dualJoystick, - &mouse + &mouse, + 0 ); static ZxSpectrumFileSettings zxSpectrumSettings( &sdCard0, diff --git a/src/picomputer/picomputer_vga_zx/main.cpp b/src/picomputer/picomputer_vga_zx/main.cpp index 970e335..96fe821 100644 --- a/src/picomputer/picomputer_vga_zx/main.cpp +++ b/src/picomputer/picomputer_vga_zx/main.cpp @@ -74,7 +74,8 @@ static ZxSpectrum zxSpectrum( &keyboard1, &keyboard2, &dualJoystick, - &mouse + &mouse, + 0 ); static ZxSpectrumFileSettings zxSpectrumSettings( &sdCard0, diff --git a/src/picovga/main.cpp b/src/picovga/main.cpp index 6fbad96..cc4c60c 100644 --- a/src/picovga/main.cpp +++ b/src/picovga/main.cpp @@ -66,7 +66,8 @@ static ZxSpectrum zxSpectrum( &keyboard1, 0, &joystick, - &mouse + &mouse, + 0 ); static ZxSpectrumFileSettings zxSpectrumSettings( &sdCard0, diff --git a/src/vga/CMakeLists.txt b/src/vga/CMakeLists.txt index 265ff06..bbe999a 100644 --- a/src/vga/CMakeLists.txt +++ b/src/vga/CMakeLists.txt @@ -183,6 +183,8 @@ set(ZxSpectrumPicoMiteVGA_defines USE_MRMLTR_PS2_KBD # Use stdio USE_STDIO + # Add some real IO + PICO_MITE_PORT ) foreach(target @@ -212,6 +214,7 @@ foreach(target tinyusb_board hardware_pio hardware_pwm + hardware_adc ) pico_generate_pio_header(${target} diff --git a/src/vga/main.cpp b/src/vga/main.cpp index 957afa5..60f64ea 100644 --- a/src/vga/main.cpp +++ b/src/vga/main.cpp @@ -43,6 +43,7 @@ #include "ZxScanlineVgaRenderLoop.h" #include "ZxSpectrumNespadJoystick.h" #include "hid_app.h" +#include "RealPort.h" #define VREG_VSEL VREG_VOLTAGE_1_20 @@ -78,7 +79,8 @@ static ZxSpectrum zxSpectrum( &keyboard1, 0, &joystick, - &mouse + &mouse, + ZX_SPECTRUM_REAL_PORT ); static ZxSpectrumFileSettings zxSpectrumSettings( &sdCard0, @@ -313,7 +315,8 @@ int main(){ #ifdef USE_PS2_KBD ps2kbd.init_gpio(); // pio1, SM ? #endif - + ZX_SPECTRUM_REAL_PORT_INIT + // Configure the GPIO pins for audio zxSpectrumAudioInit(); // pio1, ear SM ?, I2S SM ?