Skip to content

Commit b076427

Browse files
committed
Mostly working bufferless SB with CD
1 parent 140fabb commit b076427

File tree

8 files changed

+250
-182
lines changed

8 files changed

+250
-182
lines changed

sw/CMakeLists.txt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,17 @@ endfunction()
5757

5858
# Global definitions across all targets
5959
add_compile_definitions(
60-
RP2_CLOCK_SPEED=366000
60+
# 370MHz is extremely closely evenly divisible by 44100Hz
61+
RP2_CLOCK_SPEED=370000
62+
SYS_CLK_HZ=370000000
63+
# Manually set up PLLs because of non-default REFDIV
64+
PLL_SYS_REFDIV=2
65+
PLL_SYS_VCO_FREQ_HZ=1110000000
66+
PLL_SYS_POSTDIV1=3
67+
PLL_SYS_POSTDIV2=1
68+
# Set voltage before main so no need to do so on the fly
69+
SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST=1
70+
SYS_CLK_VREG_VOLTAGE_MIN=VREG_VOLTAGE_1_25
6171
PICO_DEFAULT_UART=0
6272
PICO_DEFAULT_UART_TX_PIN=28
6373
PICO_DEFAULT_UART_RX_PIN=-1
@@ -77,6 +87,7 @@ function(config_target TARGET_NAME MULTIFW)
7787
PICO_AUDIO_I2S_DATA_PIN=16
7888
PICO_AUDIO_I2S_CLOCK_PIN_BASE=17
7989
PICO_AUDIO_I2S_PIO=1
90+
PICO_AUDIO_I2S_SM=3
8091
M62429_PIO=1
8192
)
8293

@@ -235,7 +246,7 @@ endfunction()
235246
# Build SB firmware
236247
function(build_sb TARGET_NAME MULTIFW)
237248
set(USB_JOYSTICK TRUE)
238-
set(SOUND_MPU TRUE)
249+
set(SOUND_MPU FALSE)
239250
set(SOUND_OPL TRUE)
240251
set(CDROM TRUE)
241252
config_target(${TARGET_NAME} ${MULTIFW})
@@ -245,11 +256,14 @@ function(build_sb TARGET_NAME MULTIFW)
245256
sbplay.cpp
246257
isa_dma.c
247258
audio_fifo.c
259+
audio_i2s_minimal.c
248260
)
249261
target_compile_definitions(${TARGET_NAME} PRIVATE
250262
SOUND_SB=1
251263
SOUND_DSP=1
252-
# SB_BUFFERLESS=1
264+
SB_BUFFERLESS=1
265+
SB_BUFFERLESS_NG=1
266+
USE_CD_AUDIO_FIFO=1
253267
)
254268
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa_dma.pio)
255269
endfunction()

sw/audio_fifo.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/*
2+
* Copyright (C) 2025 Ian Scott
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program; if not, write to the Free Software Foundation, Inc.,
16+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17+
*/
118
/**
219
* audio_fifo.c - Implementation of shared FIFO functionality
320
*

sw/audio_fifo.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/*
2+
* Copyright (C) 2025 Ian Scott
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program; if not, write to the Free Software Foundation, Inc.,
16+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17+
*/
118
/**
219
* audio_fifo.h - Shared header for audio producer and consumer
320
*
@@ -49,6 +66,10 @@ bool fifo_add_sample(audio_fifo_t *fifo, audio_sample_t sample);
4966
bool fifo_add_samples(audio_fifo_t *fifo, const audio_sample_t *samples_buffer, uint32_t num_samples_to_add);
5067

5168
uint32_t fifo_take_samples(audio_fifo_t *fifo, uint32_t num_samples);
69+
70+
inline uint32_t fifo_free_space(audio_fifo_t *fifo) {
71+
return AUDIO_FIFO_SIZE - fifo->samples_in_fifo;
72+
}
5273
// Helper for consumer to get one sample, this is a more fundamental FIFO op
5374

5475
#ifdef __cplusplus

sw/audio_i2s_minimal.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2025 Ian Scott
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program; if not, write to the Free Software Foundation, Inc.,
16+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17+
*/
18+
#include <hardware/clocks.h>
19+
#include <audio_i2s.pio.h>
20+
#include "audio_i2s_minimal.h"
21+
22+
#define audio_pio __CONCAT(pio, PICO_AUDIO_I2S_PIO)
23+
#define GPIO_FUNC_PIOx __CONCAT(GPIO_FUNC_PIO, PICO_AUDIO_I2S_PIO)
24+
25+
void audio_i2s_minimal_setup(const audio_i2s_config_t *config, uint32_t sample_rate) {
26+
uint func = GPIO_FUNC_PIOx;
27+
gpio_set_function(config->data_pin, func);
28+
gpio_set_function(config->clock_pin_base, func);
29+
gpio_set_function(config->clock_pin_base + 1, func);
30+
31+
#if PICO_PIO_USE_GPIO_BASE
32+
if(config->data_pin >= 32 || config->clock_pin_base + 1 >= 32) {
33+
pio_set_gpio_base(audio_pio, 16);
34+
}
35+
#endif
36+
uint8_t sm = config->pio_sm;
37+
pio_sm_claim(audio_pio, sm);
38+
39+
const struct pio_program *program =
40+
#if PICO_AUDIO_I2S_CLOCK_PINS_SWAPPED
41+
&audio_i2s_swapped_program
42+
#else
43+
&audio_i2s_program
44+
#endif
45+
;
46+
uint offset = pio_add_program(audio_pio, program);
47+
48+
audio_i2s_program_init(audio_pio, sm, offset, config->data_pin, config->clock_pin_base);
49+
50+
uint32_t system_clock_frequency = clock_get_hz(clk_sys);
51+
uint32_t divider = system_clock_frequency * 4 / sample_rate; // avoid arithmetic overflow
52+
pio_sm_set_clkdiv_int_frac(audio_pio, sm, divider >> 8u, divider & 0xffu);
53+
pio_sm_set_enabled(audio_pio, sm, true);
54+
}

sw/audio_i2s_minimal.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2025 Ian Scott
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program; if not, write to the Free Software Foundation, Inc.,
16+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17+
*/
18+
#pragma once
19+
20+
#include <pico/audio_i2s.h>
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
/*
27+
* Alternative setup for pico_extras' audio_i2s library that does not set up DMA.
28+
* This allows for a minimal set up audio to be sent to the PIO sample by sample,
29+
* enabling a simpler interface with a sample clock IRQ, other buffering arrangement, etc.
30+
*/
31+
void audio_i2s_minimal_setup(const audio_i2s_config_t *config, uint32_t sample_rate);
32+
33+
#ifdef __cplusplus
34+
} // extern "C"
35+
#endif

sw/pico_pic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ void PIC_RemoveEvent(PIC_TimerEvent* event) {
5050
}
5151

5252
void PIC_Init() {
53-
alarm_pool = alarm_pool_create(2, PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
54-
irq_set_priority(TIMER_IRQ_2, PICO_HIGHEST_IRQ_PRIORITY);
53+
alarm_pool = alarm_pool_create_with_unused_hardware_alarm(PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
54+
irq_set_priority(hardware_alarm_get_irq_num(alarm_pool_timer_alarm_num(alarm_pool)), PICO_HIGHEST_IRQ_PRIORITY);
5555
}

sw/picogus.cpp

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void play_adlib(void);
7171
extern "C" int OPL_Pico_Init(unsigned int);
7272
extern "C" unsigned int OPL_Pico_PortRead(opl_port_t);
7373
#include "cmd_buffers.h"
74-
cms_buffer_t opl_buffer = { {0}, 0, 0 };
74+
cms_buffer_t opl_cmd_buffer = { {0}, 0, 0 };
7575
#endif
7676

7777
#ifdef CDROM
@@ -664,13 +664,13 @@ __force_inline void handle_iow(void) {
664664
// Fast write
665665
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
666666
// pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
667-
opl_buffer.cmds[opl_buffer.head].addr = (uint16_t)(iow_read & 0xFF);
667+
opl_cmd_buffer.cmds[opl_cmd_buffer.head].addr = (uint16_t)(iow_read & 0xFF);
668668
// Fast write - return early as we've already written 0x0u to the PIO
669669
return;
670670
break;
671671
case 0x9:
672672
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
673-
opl_buffer.cmds[opl_buffer.head++].data = (uint8_t)(iow_read & 0xFF);
673+
opl_cmd_buffer.cmds[opl_cmd_buffer.head++].data = (uint8_t)(iow_read & 0xFF);
674674
break;
675675
// DSP ports
676676
default:
@@ -694,15 +694,15 @@ __force_inline void handle_iow(void) {
694694
if ((port & 1) == 0) {
695695
// Fast write
696696
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
697-
opl_buffer.cmds[opl_buffer.head].addr = (uint16_t)(iow_read & 0xFF);
697+
opl_cmd_buffer.cmds[opl_cmd_buffer.head].addr = (uint16_t)(iow_read & 0xFF);
698698
// Fast write - return early as we've already written 0x0u to the PIO
699699
return;
700700
} else {
701701
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
702702
if (settings.SB.oplSpeedSensitive) {
703703
busy_wait_us(1); // busy wait for speed sensitive games
704704
}
705-
opl_buffer.cmds[opl_buffer.head++].data = (uint8_t)(iow_read & 0xFF);
705+
opl_cmd_buffer.cmds[opl_cmd_buffer.head++].data = (uint8_t)(iow_read & 0xFF);
706706
}
707707
} else // if follows down below
708708
#endif // SOUND_OPL
@@ -841,7 +841,7 @@ __force_inline void handle_ior(void) {
841841
switch (port - settings.SB.basePort) {
842842
case 0x8:
843843
// wait for OPL buffer to process
844-
while (opl_buffer.tail != opl_buffer.head) {
844+
while (opl_cmd_buffer.tail != opl_cmd_buffer.head) {
845845
tight_loop_contents();
846846
}
847847
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | OPL_Pico_PortRead(OPL_REGISTER_PORT));
@@ -867,7 +867,7 @@ __force_inline void handle_ior(void) {
867867
// Tell PIO to wait for data
868868
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
869869
// wait for OPL buffer to process
870-
while (opl_buffer.tail != opl_buffer.head) {
870+
while (opl_cmd_buffer.tail != opl_cmd_buffer.head) {
871871
tight_loop_contents();
872872
}
873873
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | OPL_Pico_PortRead(OPL_REGISTER_PORT));
@@ -988,6 +988,7 @@ __force_inline bool ior_has_data() {
988988
#include "hardware/structs/xip_ctrl.h"
989989
int main()
990990
{
991+
busy_wait_ms(250);
991992
#ifdef ASYNC_UART
992993
stdio_async_uart_init_full(UART_ID, BAUD_RATE, UART_TX_PIN, UART_RX_PIN);
993994
#else
@@ -1041,31 +1042,6 @@ int main()
10411042
BOARD_TYPE = PICOGUS_2;
10421043
}
10431044
gpio_set_mask(LED_PIN);
1044-
printf("Waiting for board to stabilize... ");
1045-
busy_wait_ms(250);
1046-
// Overclock!
1047-
printf("Overclocking... ");
1048-
vreg_set_voltage(VREG_VOLTAGE_1_25);
1049-
// vreg_set_voltage(VREG_VOLTAGE_1_15);
1050-
busy_wait_ms(250);
1051-
set_sys_clock_khz(rp2_clock, true);
1052-
busy_wait_ms(250);
1053-
gpio_xor_mask(LED_PIN);
1054-
#ifdef ASYNC_UART
1055-
uart_init(UART_ID, 0);
1056-
#else
1057-
stdio_init_all();
1058-
#endif
1059-
puts("Done. Continuing!");
1060-
1061-
// Set clk_peri to use the XOSC
1062-
// clock_configure(clk_peri,
1063-
// 0,
1064-
// CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_XOSC_CLKSRC,
1065-
// 12 * MHZ,
1066-
// 12 * MHZ);
1067-
// clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
1068-
// 12 * MHZ, 12 * MHZ);
10691045

10701046
if (BOARD_TYPE == PICOGUS_2) {
10711047
// Create new interface to M62429 digital volume control

0 commit comments

Comments
 (0)