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

MURMULATOR2

This commit is contained in:
Phil 2024-12-14 21:56:47 +00:00
parent 870ed781ca
commit e90ca6d9a8
6 changed files with 112 additions and 26 deletions

View File

@ -100,6 +100,10 @@ set(zxspectrum_ear_in_pio
${CMAKE_CURRENT_LIST_DIR}/zx_ear_in.pio
)
set(zxspectrum_pwm_pio
${CMAKE_CURRENT_LIST_DIR}/pwm.pio
)
add_subdirectory(hdmi)
add_subdirectory(picomputer)
add_subdirectory(vga)

View File

@ -1,13 +1,48 @@
#include "ZxSpectrumAudio.h"
#include "hardware/gpio.h"
#include "hardware/clocks.h"
#include "pico/printf.h"
#ifndef INITIAL_VOL
#define INITIAL_VOL 0x100
#endif
static uint32_t _vol = INITIAL_VOL;
#if !defined(PICO_HDMI_AUDIO) && !defined(PICO_AUDIO_I2S)
#if defined(PICO_PIO_PWM_AUDIO)
#include "pwm.pio.h"
static uint pwm_audio_sm = 0;
// Write `period` to the input shift register
void pio_pwm_set_period(PIO pio, uint sm, uint32_t period) {
pio_sm_set_enabled(pio, sm, false);
pio_sm_put_blocking(pio, sm, period);
pio_sm_exec(pio, sm, pio_encode_pull(false, false));
pio_sm_exec(pio, sm, pio_encode_out(pio_isr, 32));
pio_sm_set_enabled(pio, sm, true);
}
void init_pio_pwm_audio() {
gpio_init(SPK_PIN);
gpio_set_dir(SPK_PIN, GPIO_OUT);
uint offset = pio_add_program(PICO_AUDIO_PWM_PIO, &pwm_program);
printf("Loaded PWM PIO at %u\n", offset);
pwm_audio_sm = pio_claim_unused_sm(PICO_AUDIO_PWM_PIO, true);
printf("Chosen %d for PWM PIO State machine\n", pwm_audio_sm);
pwm_program_init(PICO_AUDIO_PWM_PIO, pwm_audio_sm, offset, SPK_PIN);
pio_sm_set_clkdiv(PICO_AUDIO_PWM_PIO, pwm_audio_sm, 2.0);
pio_pwm_set_period(PICO_AUDIO_PWM_PIO, pwm_audio_sm, 1024);
printf("Finish configuring PWM PIO\n");
}
// Write `level` to TX FIFO. State machine will copy this into X.
inline void pio_pwm_set_level(PIO pio, uint sm, uint32_t level) {
pio_sm_put_blocking(pio, sm, level);
}
#elif !defined(PICO_HDMI_AUDIO) && !defined(PICO_AUDIO_I2S)
#include "pico/time.h"
// PWM Audio stuff
#define ZX_AUDIO_BUF_SIZE_BITS 7
@ -249,8 +284,9 @@ bool __not_in_flash_func(zxSpectrumEarReady)() {
}
void zxSpectrumAudioInit() {
#if defined(PICO_AUDIO_I2S)
#if defined(PICO_PIO_PWM_AUDIO)
init_pio_pwm_audio();
#elif defined(PICO_AUDIO_I2S)
init_is2_audio();
#elif defined(PICO_HDMI_AUDIO)
init_hdmi_audio();
@ -280,15 +316,21 @@ void zxSpectrumAudioInit() {
}
void __not_in_flash_func(zxSpectrumAudioHandler)(uint32_t vA, uint32_t vB, uint32_t vC, int32_t s, uint32_t buzzer, bool mute) {
#if defined(PICO_HDMI_AUDIO) || defined(PICO_AUDIO_I2S)
#if defined(PICO_PIO_PWM_AUDIO)
const int32_t l = vA + vC + vB + s - (128*3);
const int32_t v = __mul_instruction(_vol, 60);
const int32_t lr = __mul_instruction(v, l) >> (8 + 6);
const int32_t k = lr + 512;
pio_pwm_set_level(PICO_AUDIO_PWM_PIO, pwm_audio_sm, k < 0 ? 0 : k > 1024 ? 1024 : k);
#elif defined(PICO_HDMI_AUDIO) || defined(PICO_AUDIO_I2S)
uint32_t ll, rr;
if (mute) {
ll = rr = 0;
}
else {
const uint32_t l = (vA << 1) + vB + s + 128;
const uint32_t r = (vC << 1) + vB + s + 128;
const uint32_t v = _vol << 4;
const int32_t l = (vA << 1) + vB + s - (128*3);
const int32_t r = (vC << 1) + vB + s - (128*3);
const int32_t v = __mul_instruction(_vol, 60);
ll = (__mul_instruction(v, l) >> 8) & 0xffff;
rr = (__mul_instruction(v, r) >> 8) & 0xffff;
}
@ -330,7 +372,10 @@ uint32_t zxSpectrumAudioGetVolume() { return _vol; }
void zxSpectrumAudioSetVolume(uint32_t vol) { _vol = vol; }
bool __not_in_flash_func(zxSpectrumAudioReady)() {
#if defined(PICO_HDMI_AUDIO)
#if defined(PICO_PIO_PWM_AUDIO)
return !pio_sm_is_tx_fifo_full(PICO_AUDIO_PWM_PIO, pwm_audio_sm);
// return !(PICO_AUDIO_PWM_PIO->fstat & (1u << (pwm_audio_sm + PIO_FSTAT_TXFULL_LSB)));
#elif defined(PICO_HDMI_AUDIO)
return get_write_size(&dvi0.audio_ring, true) > 0;
#elif defined(PICO_AUDIO_I2S)
return is2_audio_ready();

View File

@ -519,13 +519,13 @@ ZxSpectrumMenu::ZxSpectrumMenu(
};
onPaint([](PicoPen *pen) {
#ifdef MURMULATOR
pen->printAt(0, 0, false, "ZX Spectrum 48K/128K by fruit-bat on MURMULATOR");
#ifdef ZX_PLATFORM
pen->printAtF(0, 0, false, "ZX Spectrum 48K/128K by fruit-bat on %s", ZX_PLATFORM);
#else
pen->printAt(0, 0, false, "ZX Spectrum 48K/128K by fruit-bat");
#endif
pen->printAtF(0, 1, false, "on %s Pico Pi at %3.1fMhz", PICO_MCU, (float)clock_get_hz(clk_sys) / 1000000.0);
pen->printAtF(0, 2, false, "Menu System version %d.%d", ZX_VERSION_MAJOR, ZX_VERSION_MINOR);
pen->printAtF(0, 1, false, "Build: %s", __DATE__);
pen->printAtF(0, 2, false, "CPU: %s @%3.1fMhz", PICO_MCU, (float)clock_get_hz(clk_sys) / 1000000.0);
pen->printAt(0, SZ_FRAME_ROWS-1, false, "F1 to exit menu");
pen->printAt(SZ_FRAME_COLS-14, SZ_FRAME_ROWS-1, false, "ESC to go back");

View File

@ -417,8 +417,8 @@ set(zxspectrum_murmulator_hdmi_nespad_defines
)
set(murmulator_common_defines
ZX_PLATFORM="MURMULATOR"
# Set up the DVI output to match the MURMULATOR board
MURMULATOR
PICO_CORE1_STACK_SIZE=0x400
DVI_DEFAULT_SERIAL_CONFIG=pimoroni_demo_hdmi_cfg
DVI_VERTICAL_REPEAT=2
@ -552,8 +552,8 @@ set(zxspectrum_murmulator2_hdmi_nespad_defines
)
set(murmulator2_common_defines
ZX_PLATFORM="MURMULATOR2"
# Set up the DVI output to match the MURMULATOR board
MURMULATOR
DVI_CUSTOM_CONFIG
DVI_DEFAULT_SERIAL_CONFIG=murmulator2_hdmi_cfg
PICO_CORE1_STACK_SIZE=0x400
@ -572,23 +572,24 @@ set(murmulator2_common_defines
# Use the alternate volume map
AY8912_ALT_VOL_MAP
# Tape audio in
EAR_PIN=22
#EAR_PIN=22
# Enable the PS/2 keyboard
USE_PS2_KBD
PS2KBD_CLK2_DAT
)
set(murmulator2_pwm_audio_defines
# Speaker pin audio
# Speaker pin audio (@270MHz)
PICO_PWM_AUDIO_FREQ=45000
PICO_AUDIO_PWM_PIO=pio1
PICO_PIO_PWM_AUDIO
SPK_PIN=10
# Buzzer audio out
# BZR_PIN=10
# STEREO AY audio
AY8912_ABC_STEREO
# AY8912_ABC_STEREO
# Left chanel audio out
AY8912_A_PIN=9
# AY8912_A_PIN=9
# Right chanel audio out
AY8912_C_PIN=11
# AY8912_C_PIN=11
)
set (zxspectrum_murmulator2_i2saudio_defines
@ -631,6 +632,10 @@ foreach(target
${zxspectrum_audio_i2s_pio}
)
pico_generate_pio_header(${target}
${zxspectrum_pwm_pio}
)
# create map/bin/hex file etc.
pico_add_extra_outputs(${target})

32
src/pwm.pio Normal file
View File

@ -0,0 +1,32 @@
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;
; Side-set pin 0 is used for PWM output
.pio_version 0 // only requires PIO version 0
.program pwm
.side_set 1 opt
pull noblock side 0 ; Pull from FIFO to OSR if available, else copy X to OSR.
mov x, osr ; Copy most-recently-pulled value back to scratch X
mov y, isr ; ISR contains PWM period. Y used as counter.
countloop:
jmp x!=y noset ; Set pin high if X == Y, keep the two paths length matched
jmp skip side 1
noset:
nop ; Single dummy cycle to keep the two paths the same length
skip:
jmp y-- countloop ; Loop until Y hits 0, then pull a fresh PWM value from FIFO
% c-sdk {
static inline void pwm_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_gpio_init(pio, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
pio_sm_config c = pwm_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, pin);
pio_sm_init(pio, sm, offset, &c);
}
%}

View File

@ -255,7 +255,7 @@ target_compile_definitions(ZxSpectrumPicoMiteVGA_640x480x60Hz PRIVATE
# ZX MURMULATOR
#========================================================
set(ZX-MURMULATOR_VGA_defines
MURMULATOR
ZX_PLATFORM=MURMULATOR
# Configure the SPI sd card to use SPI0
SDCARD_PIN_SPI0_CS=5
SDCARD_PIN_SPI0_SCK=2
@ -348,7 +348,7 @@ target_compile_definitions(ZX-MURMULATOR_VGA_I2S_AUDIO_720x576x50Hz PRIVATE
# ZX MURMULATOR2
#========================================================
set(ZX-MURMULATOR2_VGA_defines
MURMULATOR
ZX_PLATFORM=MURMULATOR2
# Configure the SPI sd card to use SPI0
SDCARD_PIN_SPI0_CS=5
SDCARD_PIN_SPI0_SCK=6
@ -382,15 +382,15 @@ set(ZX-MURMULATOR2_VGA_defines
set(ZX-MURMULATOR2_VGA_PWM_Audio_defines
# Speaker pin audio
SPK_PIN=10
SPK_PIN=9
# Buzzer audio out
# BZR_PIN=10
# STEREO AY audio
AY8912_ABC_STEREO
# Left chanel audio out
AY8912_A_PIN=9
AY8912_A_PIN=11
# Right chanel audio out
AY8912_C_PIN=11
AY8912_C_PIN=10
)
set (ZX-MURMULATOR2_VGA_I2S_Audio_defines