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

Try Pimoroni fatfs

This commit is contained in:
Phil 2022-07-22 20:40:15 +01:00
parent 620d694802
commit 7f61c87e61
22 changed files with 1636 additions and 65 deletions

View File

@ -23,9 +23,13 @@ include_directories(
add_subdirectory(${PICO_FOLDER}/PicoDVI/software/libdvi "${CMAKE_CURRENT_BINARY_DIR}/libdvi")
add_subdirectory(${PICO_FOLDER}/PicoDVI/software/libsprite "${CMAKE_CURRENT_BINARY_DIR}/libsprite")
add_subdirectory(${PICO_FOLDER}/pico-vga-332/ "${CMAKE_CURRENT_BINARY_DIR}/pico-vga-332")
add_subdirectory(${PICO_FOLDER}/no-OS-FatFS-SD-SPI-RPi-Pico/FatFs_SPI "${CMAKE_CURRENT_BINARY_DIR}/FatFs_SPI")
add_subdirectory(${PICO_FOLDER}/pico-dvi-menu "${CMAKE_CURRENT_BINARY_DIR}/pico-dvi-menu")
add_subdirectory(${PICO_FOLDER}/pico-emu-utils "${CMAKE_CURRENT_BINARY_DIR}/pico-emu-utils")
add_subdirectory(${PICO_FOLDER}/pimoroni-pico/drivers/fatfs "${CMAKE_CURRENT_BINARY_DIR}/pimoroni-pico/drivers/fatfs")
add_subdirectory(${PICO_FOLDER}/pimoroni-pico/drivers/sdcard "${CMAKE_CURRENT_BINARY_DIR}/pimoroni-pico/drivers/sdcard")
include_directories(${PICO_FOLDER}/pimoroni-pico/drivers/fatfs)
include_directories(${PICO_FOLDER}/pimoroni-pico/drivers/sdcard)
add_subdirectory(src "${CMAKE_CURRENT_BINARY_DIR}/bin")

View File

@ -25,14 +25,20 @@ Uses [Wren's Amazing PicoDVI](https://github.com/Wren6991/PicoDVI) and [CarlK's
* [RetroVGA](https://hackaday.io/project/183398-retrovga-raspbery-pico-multi-retro-computer)
* PicomputerMax
* PicomputerZX
* Pimoroni Pico DV Demo Base
<img src="docs/breadboard.png" width="200"/><a href="https://hackaday.io/project/183398-retrovga-raspbery-pico-multi-retro-computer">
<img src="docs/retrovga.png" width="200"/><img src="docs/picomputermax.png" width="200"/><img src="docs/picomputerzx.png" width="200"/>
<img src="docs/breadboard.png" width="200"/>
<a href="https://hackaday.io/project/183398-retrovga-raspbery-pico-multi-retro-computer"><img src="docs/retrovga.png" width="200"/></a>
<a href="https://hackaday.io/project/183398-retrovga-raspbery-pico-multi-retro-computer"><img src="docs/picomputermax.png" width="200"/></a>
<a href="https://hackaday.io/project/183398-retrovga-raspbery-pico-multi-retro-computer"><img src="docs/picomputerzx.png" width="200"/></a>
<a href="https://shop.pimoroni.com/products/pimoroni-pico-dv-demo-base"><img src="docs/P1040672_192x192.webp" /></a>
</a>
## Updates
* 23/07/22 - Added target for Pico DV board
* 23/07/22 - Moved to Pimoroni FATFS to support Pimoroni Pico DV board
* 10/07/22 - Added basic support for PS/2 keyboards
* 27/06/22 - Added support for RGB222 and RGBY1111 over VGA
* 22/06/22 - Even better sound with 4 pin audio output (HDMI version only)
@ -379,4 +385,5 @@ tio -m ODELBS /dev/ttyUSB0
[ST7789 LCD driver reference](docs/ST7789_Datasheet.pdf)<br/>
[RGB for 128k ZX Spectrum](docs/128_rgb.pdf)<br/>
[PS/2 vs HID keyboard codes](docs/ps2-hid.pdf)<br/>
[PCM 5100A DAC](PCM510xA.pdf)<br/>
[RP2040 Datasheet](https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf)</br>

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
docs/P1040672_192x192.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/PCM510xA.pdf Normal file

Binary file not shown.

View File

@ -32,10 +32,13 @@ set(zxspectrum_common_libs
pico_stdlib
pico_multicore
pico_util
FatFs_SPI
pico_emu_utils
sdcard
fatfs
hardware_dma
)
add_subdirectory(breadboard_hdmi)
add_subdirectory(picomputer)
add_subdirectory(pico_dv)

View File

@ -169,7 +169,7 @@ public:
ZxSpectrumType type() { return _type; }
inline void step()
{
const int c = _Z80.step() + _Z80.step();
const int c = _Z80.step();
const uint32_t tu32 = time_us_32() << 5;
const uint32_t tud = tu32 - _tu32;
_tu32 = tu32;

View File

@ -1,6 +1,7 @@
#include "ZxSpectrumAudio.h"
static void init_pwm_pin(uint32_t pin) {
#ifndef AUDIO_I2S
static void init_pwm_pin(uint32_t pin) {
gpio_set_function(pin, GPIO_FUNC_PWM);
const int audio_pin_slice = pwm_gpio_to_slice_num(pin);
pwm_config config = pwm_get_default_config();
@ -8,8 +9,12 @@ static void init_pwm_pin(uint32_t pin) {
pwm_config_set_wrap(&config, PWM_WRAP);
pwm_init(audio_pin_slice, &config, true);
}
#endif
void zxSpectrumAudioInit() {
#ifdef AUDIO_I2S
init_is2_audio();
#else
#ifdef BZR_PIN
gpio_init(BZR_PIN);
gpio_set_dir(BZR_PIN, GPIO_OUT);
@ -26,4 +31,5 @@ void zxSpectrumAudioInit() {
#ifdef AY8912_C_PIN
init_pwm_pin(AY8912_C_PIN);
#endif
#endif
}

View File

@ -3,7 +3,8 @@
#include "ZxSpectrum.h"
#include "hardware/gpio.h"
#include "hardware/pwm.h"
//
// AUDIO_I2S I2S audio
//
// SPK_PIN combined audio from AY-3-8912 and buzzer
//
@ -18,36 +19,49 @@
//
// See CMakeLists.txt files for configurations
//
#ifdef BZR_PIN
#ifdef AY8912_A_PIN
#define PWM_WRAP (255)
#else
#define PWM_WRAP (255 + 255 + 255)
#endif
#ifdef AUDIO_I2S
#include "pico_dv/audio_i2s.h"
#else
#define PWM_WRAP (255 + 255 + 255 + 255)
#ifdef BZR_PIN
#ifdef AY8912_A_PIN
#define PWM_WRAP (255)
#else
#define PWM_WRAP (255 + 255 + 255)
#endif
#else
#define PWM_WRAP (255 + 255 + 255 + 255)
#endif
#endif
void zxSpectrumAudioInit();
inline void zxSpectrumAudioToGpio(ZxSpectrum& zxSpectrum) {
#ifdef BZR_PIN
gpio_put(BZR_PIN, zxSpectrum.getBuzzer());
#ifdef SPK_PIN
const uint32_t l = zxSpectrum.getAnalogueAudio();
pwm_set_gpio_level(SPK_PIN, l);
#ifdef AUDIO_I2S
if (is2_audio_ready()) {
uint32_t vA, vB, vC;
zxSpectrum.vol(vA, vB, vC);
uint32_t s = zxSpectrum.getBuzzer() ? 255 : 0;
uint32_t l = ((((vA << 1) + vB + s) << 4) - ((255 + 255 + 255 + 255) << (4 - 1))) & 0xffff;
uint32_t r = ((((vC << 1) + vB + s) << 4) - ((255 + 255 + 255 + 255) << (4 - 1))) & 0xffff;
is2_audio_put((l << 16) | r);
}
#else
uint32_t vA, vB, vC;
zxSpectrum.vol(vA, vB, vC);
pwm_set_gpio_level(AY8912_A_PIN, vA);
pwm_set_gpio_level(AY8912_B_PIN, vB);
pwm_set_gpio_level(AY8912_C_PIN, vC);
#endif
#else
const uint32_t l = zxSpectrum.getSpeaker();
pwm_set_gpio_level(SPK_PIN, l);
#ifdef BZR_PIN
gpio_put(BZR_PIN, zxSpectrum.getBuzzer());
#ifdef SPK_PIN
const uint32_t l = zxSpectrum.getAnalogueAudio();
pwm_set_gpio_level(SPK_PIN, l);
#else
uint32_t vA, vB, vC;
zxSpectrum.vol(vA, vB, vC);
pwm_set_gpio_level(AY8912_A_PIN, vA);
pwm_set_gpio_level(AY8912_B_PIN, vB);
pwm_set_gpio_level(AY8912_C_PIN, vC);
#endif
#else
const uint32_t l = zxSpectrum.getSpeaker();
pwm_set_gpio_level(SPK_PIN, l);
#endif
#endif
}

View File

@ -2,7 +2,6 @@ set(zxspectrum_hdmi_src
main.cpp
tmds_encode_zxspectrum.S
tmds_encode_zxspectrum.h
hw_config.c
)
add_executable(ZxSpectrumBreadboardHdmi1PinAudio

View File

@ -250,15 +250,17 @@ void __not_in_flash_func(main_loop)() {
while (1) {
tuh_task();
ps2kbd.tick();
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
}
if (showMenu && frames != _frames) {
else (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}

View File

@ -0,0 +1,60 @@
set(zxspectrum_hdmi_src
main.cpp
tmds_encode_zxspectrum.S
tmds_encode_zxspectrum.h
audio_i2s.cpp
)
add_executable(ZxSpectrumPicoDv
${zxspectrum_common_src}
${zxspectrum_hdmi_src}
)
pico_generate_pio_header(ZxSpectrumPicoDv
${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pio
)
target_compile_definitions(ZxSpectrumPicoDv PRIVATE
DVI_DEFAULT_SERIAL_CONFIG=pimoroni_demo_hdmi_cfg
DVI_VERTICAL_REPEAT=2
DVI_N_TMDS_BUFFERS=3
DVI_1BPP_BIT_REVERSE=1
PCS_COLS=80
PCS_ROWS=30
FF_USE_FIND=1
SDCARD_PIO=pio1
SDCARD_PIO_SM=1
SDCARD_PIN_SPI0_CS=22
SDCARD_PIN_SPI0_SCK=5
SDCARD_PIN_SPI0_MOSI=18
SDCARD_PIN_SPI0_MISO=19
AUDIO_I2S=1
# # compile time configuration of I2S
# PICO_AUDIO_I2S_MONO_INPUT=1
# #define for our example code
# USE_AUDIO_I2S=1
# PICO_AUDIO_I2S_DMA_IRQ=1
# PICO_AUDIO_I2S_PIO=1
# PICO_AUDIO_I2S_DATA=26
# PICO_AUDIO_I2S_BCLK=27
)
set(zxspectrum_hdmi_libs
libdvi
tinyusb_host
tinyusb_board
pico_emu_utils
pico_dvi_menu
# pico_audio_i2s
)
target_link_libraries(ZxSpectrumPicoDv
${zxspectrum_common_libs}
${zxspectrum_hdmi_libs}
)
# create map/bin/hex file etc.
pico_add_extra_outputs(ZxSpectrumPicoDv)

40
src/pico_dv/audio_i2s.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <stdio.h>
#include "audio_i2s.pio.h"
#include "hardware/pio.h"
#include "hardware/gpio.h"
#include "hardware/dma.h"
#include "hardware/irq.h"
#include "hardware/clocks.h"
#include "audio_i2s.h"
#include "audio_i2s.pio.h"
static void update_pio_frequency(uint32_t sample_freq, PIO audio_pio, uint pio_sm) {
uint32_t system_clock_frequency = clock_get_hz(clk_sys);
assert(system_clock_frequency < 0x40000000);
uint32_t divider = system_clock_frequency * 4 / sample_freq; // avoid arithmetic overflow
assert(divider < 0x1000000);
pio_sm_set_clkdiv_int_frac(audio_pio, pio_sm, divider >> 8u, divider & 0xffu);
}
void init_is2_audio() {
PIO pio = pio1;
uint sm = 2;
uint data_pin = 26;
uint clock_pin_base = 27;
gpio_set_function(data_pin, GPIO_FUNC_PIO1);
gpio_set_function(clock_pin_base, GPIO_FUNC_PIO1);
gpio_set_function(clock_pin_base + 1, GPIO_FUNC_PIO1);
// get a state machine
// sm = pio_claim_unused_sm(pio, true);
uint offset = pio_add_program(pio, &audio_i2s_program);
audio_i2s_program_init(pio, sm, offset, data_pin, clock_pin_base);
update_pio_frequency(96000, pio, sm);
pio_sm_set_enabled(pio, sm, true);
}

16
src/pico_dv/audio_i2s.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "hardware/pio.h"
void init_is2_audio();
inline bool is2_audio_ready() {
PIO pio = pio1;
uint sm = 2;
return !pio_sm_is_tx_fifo_full(pio, sm);
}
inline void is2_audio_put(uint32_t x) {
PIO pio = pio1;
uint sm = 2;
*(volatile uint32_t*)&pio->txf[sm] = x;
}

63
src/pico_dv/audio_i2s.pio Normal file
View File

@ -0,0 +1,63 @@
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;
; Transmit a mono or stereo I2S audio stream as stereo
; This is 16 bits per sample; can be altered by modifying the "set" params,
; or made programmable by replacing "set x" with "mov x, y" and using Y as a config register.
;
; Autopull must be enabled, with threshold set to 32.
; Since I2S is MSB-first, shift direction should be to left.
; Hence the format of the FIFO word is:
;
; | 31 : 16 | 15 : 0 |
; | sample ws=0 | sample ws=1 |
;
; Data is output at 1 bit per clock. Use clock divider to adjust frequency.
; Fractional divider will probably be needed to get correct bit clock period,
; but for common syslck freqs this should still give a constant word select period.
;
; One output pin is used for the data output.
; Two side-set pins are used. Bit 0 is clock, bit 1 is word select.
; Send 16 bit words to the PIO for mono, 32 bit words for stereo
.program audio_i2s
.side_set 2
; /--- LRCLK
; |/-- BCLK
bitloop1: ; ||
out pins, 1 side 0b10
jmp x-- bitloop1 side 0b11
out pins, 1 side 0b00
set x, 14 side 0b01
bitloop0:
out pins, 1 side 0b00
jmp x-- bitloop0 side 0b01
out pins, 1 side 0b10
public entry_point:
set x, 14 side 0b11
% c-sdk {
static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base) {
pio_sm_config sm_config = audio_i2s_program_get_default_config(offset);
sm_config_set_out_pins(&sm_config, data_pin, 1);
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
sm_config_set_out_shift(&sm_config, false, true, 32);
pio_sm_init(pio, sm, offset, &sm_config);
uint pin_mask = (1u << data_pin) | (3u << clock_pin_base);
pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
pio_sm_set_pins(pio, sm, 0); // clear pins
pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point));
}
%}

334
src/pico_dv/main.cpp Normal file
View File

@ -0,0 +1,334 @@
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "hardware/clocks.h"
#include "hardware/irq.h"
#include "hardware/sync.h"
#include "hardware/gpio.h"
#include "hardware/vreg.h"
#include "hardware/structs/bus_ctrl.h"
#include "hardware/structs/ssi.h"
#include "hardware/dma.h"
#include "hardware/uart.h"
#include "pico/sem.h"
#include "hardware/pwm.h"
extern "C" {
#include "dvi.h"
#include "dvi_serialiser.h"
#include "common_dvi_pin_configs.h"
#include "tmds_encode_zxspectrum.h"
}
#include "ZxSpectrumFatSpiKiosk.h"
#include "ZxSpectrum.h"
#include "ZxSpectrumHidKeyboard.h"
#include "ZxSpectrumHidJoystick.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 "PicoCharRenderer.h"
#include "ZxSpectrumMenu.h"
#include "ZxSpectrumAudio.h"
#define UART_ID uart0
#define BAUD_RATE 115200
// We are using pins 0 and 1, but see the GPIO function select table in the
// datasheet for information on which other pins can be used.
#define UART_TX_PIN 0
#define UART_RX_PIN 1
// DVDD 1.2V (1.1V seems ok too)
#define FRAME_HEIGHT 240
#define VREG_VSEL VREG_VOLTAGE_1_20
#define DVI_TIMING dvi_timing_640x480p_60hz
#define LED_PIN 25
struct dvi_inst dvi0;
struct semaphore dvi_start_sem;
static SdCardFatFsSpi sdCard0(0);
// ZX Spectrum emulator
static ZxSpectrumFatSpiKiosk zxSpectrumKisok(
&sdCard0,
"zxspectrum"
);
static ZxSpectrumFatFsSpiFileLoop zxSpectrumSnaps(
&sdCard0,
"zxspectrum/snapshots"
);
static ZxSpectrumFatFsSpiFileLoop zxSpectrumTapes(
&sdCard0,
"zxspectrum/tapes"
);
static QuickSave quickSave(
&sdCard0,
"zxspectrum/quicksaves"
);
static ZxSpectrumHidJoystick joystick;
static ZxSpectrumHidKeyboard keyboard(
&zxSpectrumSnaps,
&zxSpectrumTapes,
&quickSave,
&joystick
);
static ZxSpectrum zxSpectrum(
&keyboard,
0,
&joystick
);
static ZxSpectrumMenu picoRootWin(
&sdCard0,
&zxSpectrum,
&quickSave
);
static PicoDisplay picoDisplay(
pcw_screen(),
&picoRootWin
);
static PicoWinHidKeyboard picoWinHidKeyboard(
&picoDisplay
);
static bool showMenu = true;
static bool toggleMenu = false;
void print(hid_keyboard_report_t const *report) {
printf("HID key report modifiers %2.2X report ", report->modifier);
for(int i = 0; i < 6; ++i) printf("%2.2X", report->keycode[i]);
printf("\n");
}
extern "C" void __not_in_flash_func(process_kbd_mount)(uint8_t dev_addr, uint8_t instance) {
keyboard.mount();
}
extern "C" void __not_in_flash_func(process_kbd_unmount)(uint8_t dev_addr, uint8_t instance) {
keyboard.unmount();
}
extern "C" void __not_in_flash_func(process_kbd_report)(hid_keyboard_report_t const *report, hid_keyboard_report_t const *prev_report) {
#if 0
// Some help debugging keyboard input/drivers
printf("PREV ");print(prev_report);
printf("CURR ");print(report);
#endif
int r;
if (showMenu) {
r = picoWinHidKeyboard.processHidReport(report, prev_report);
}
else {
r = keyboard.processHidReport(report, prev_report);
}
if (r == 1) toggleMenu = true;
}
unsigned char* screenPtr;
unsigned char* attrPtr;
static volatile uint _frames = 0;
// Screen handler
//
// 256×192 Pixels
// 32x24 Charaters
//
// 240-192 = 48 => 24 border rows top and bottom
// 320-256 = 64 => 64 border pixels left and right
//
static inline void prepare_scanline(const uint y, uint f) {
const uint8_t borderColor = zxSpectrum.borderColour();
uint32_t *tmdsbuf;
queue_remove_blocking(&dvi0.q_tmds_free, &tmdsbuf);
uint32_t *p = tmdsbuf;
const uint v = y - 24;
const uint8_t *s = screenPtr + ((v & 0x7) << 8) + ((v & 0x38) << 2) + ((v & 0xc0) << 5);
const uint8_t *a = attrPtr+((v>>3)<<5);
const int m = (f >> 5) & 1 ? 0xff : 0x7f;
if (y < 24 || y >= (24+192)) {
for (int plane = 0; plane < 3; ++plane) {
p = tmds_encode_border(
40, // r0 is width in characters
plane, // r1 is colour channel
p, // r2 is output TMDS buffer
borderColor // r3 is the colour attribute
);
}
}
else {
for (int plane = 0; plane < 3; ++plane) {
p = tmds_encode_border(
4, // r0 is width in characters
plane, // r1 is colour channel
p, // r2 is output TMDS buffer
borderColor // r3 is the colour attribute
);
p = tmds_encode_screen(
(const uint8_t*)s,
a,
p,
m,
plane
);
p = tmds_encode_border(
4, // r0 is width in characters
plane, // r1 is colour channel
p, // r2 is output TMDS buffer
borderColor // r3 is the colour attribute
);
}
}
queue_add_blocking(&dvi0.q_tmds_valid, &tmdsbuf);
}
void __not_in_flash_func(core1_scanline_callback)() {
static uint y = 1;
static uint ys = 0;
if (showMenu) {
uint rs = pcw_prepare_scanline_80(&dvi0, y++, ys, _frames);
if (0 == (y & 7)) {
ys += rs;
}
}
else {
prepare_scanline(y++, _frames);
}
if (y == FRAME_HEIGHT) {
_frames++;
y = 0;
ys = 0;
// TODO Tidy this mechanism up
screenPtr = zxSpectrum.screenPtr();
attrPtr = screenPtr + (32 * 24 * 8);
if (toggleMenu) {
showMenu = !showMenu;
toggleMenu = false;
}
}
}
void __not_in_flash_func(core1_main)() {
dvi_register_irqs_this_core(&dvi0, DMA_IRQ_1);
sem_acquire_blocking(&dvi_start_sem);
dvi_start(&dvi0);
// The text display is completely IRQ driven (takes up around 30% of cycles @
// VGA). We could do something useful, or we could just take a nice nap
while (1)
__wfi();
__builtin_unreachable();
}
void __not_in_flash_func(main_loop)() {
unsigned int lastInterruptFrame = _frames;
uint frames = 0;
while (1) {
tuh_task();
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
}
else if (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}
}
}
int main() {
vreg_set_voltage(VREG_VSEL);
sleep_ms(10);
#ifdef RUN_FROM_CRYSTAL
set_sys_clock_khz(12000, true);
#else
// Run system at TMDS bit clock
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
#endif
setup_default_uart();
tusb_init();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
// Configure the GPIO pins for audio
zxSpectrumAudioInit();
screenPtr = zxSpectrum.screenPtr();
attrPtr = screenPtr + (32 * 24 * 8);
keyboard.setZxSpectrum(&zxSpectrum);
// Initialise the menu renderer
pcw_init_renderer();
printf("Configuring DVI\n");
dvi0.timing = &DVI_TIMING;
dvi0.ser_cfg = DVI_DEFAULT_SERIAL_CONFIG;
dvi0.scanline_callback = core1_scanline_callback;
dvi_init(&dvi0, next_striped_spin_lock_num(), next_striped_spin_lock_num());
printf("Prepare first scanline\n");
prepare_scanline(0, 0);
printf("Core 1 start\n");
sem_init(&dvi_start_sem, 0, 1);
hw_set_bits(&bus_ctrl_hw->priority, BUSCTRL_BUS_PRIORITY_PROC1_BITS);
multicore_launch_core1(core1_main);
picoRootWin.showMessage([=](PicoPen *pen) {
pen->printAtF(3, 1, false, "Reading from SD card...");
});
picoDisplay.refresh();
sem_release(&dvi_start_sem);
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);
}
bool isKiosk = zxSpectrumKisok.isKiosk();
keyboard.setKiosk(isKiosk);
}
showMenu = false;
picoRootWin.removeMessage();
main_loop();
__builtin_unreachable();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
#ifndef _TMDS_ENCODE_ZXSPECTRUM_H
#define _TMDS_ENCODE_ZXSPECTRUM_H
#include "pico/types.h"
uint32_t * __not_in_flash_func(tmds_encode_screen)(
const uint8_t *screenRowPtr,
const uint8_t *attributeRowPtr,
uint32_t *tmdsbuf,
uint32_t flash,
uint32_t plane
);
uint32_t *__not_in_flash_func(tmds_encode_border)(
uint32_t nchars, // r0 is width in characters
uint32_t plane, // r1 is colour channel
uint32_t *tmdsbuf, // r2 is output TMDS buffer
uint32_t attr // r3 is the colour attribute
);
#endif

View File

@ -4,7 +4,6 @@ set(picomputer_common_src
${CMAKE_CURRENT_LIST_DIR}/pzx_keyscan.cpp
${CMAKE_CURRENT_LIST_DIR}/pzx_keyscan.h
${CMAKE_CURRENT_LIST_DIR}/ZxSpectrumPicomputerJoystick.cpp
${CMAKE_CURRENT_LIST_DIR}/hw_config.c
)
add_subdirectory(picomputer_vga)

View File

@ -207,17 +207,17 @@ void __not_in_flash_func(main_loop)() {
pzx_keyscan_get_hid_reports(&curr, &prev);
process_picomputer_kbd_report(curr, prev);
}
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
if (showMenu && frames != _frames) {
else (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}

View File

@ -200,16 +200,17 @@ void __not_in_flash_func(main_loop)(){
pzx_keyscan_get_hid_reports(&curr, &prev);
process_picomputer_kbd_report(curr, prev);
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
if (showMenu && frames != _frames) {
else (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}

View File

@ -200,16 +200,17 @@ void __not_in_flash_func(main_loop)(){
pzx_keyscan_get_hid_reports(&curr, &prev);
process_picomputer_kbd_report(curr, prev);
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
if (!showMenu) {
for (int i = 1; i < 100; ++i) {
if (lastInterruptFrame != _frames) {
lastInterruptFrame = _frames;
zxSpectrum.interrupt();
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
zxSpectrum.step();
zxSpectrumAudioToGpio(zxSpectrum);
}
if (showMenu && frames != _frames) {
else (frames != _frames) {
frames = _frames;
picoDisplay.refresh();
}