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:
parent
870ed781ca
commit
e90ca6d9a8
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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
32
src/pwm.pio
Normal 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);
|
||||
}
|
||||
%}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user