Consolidate Tandy and CMS into PSG mode

This commit is contained in:
Ian Scott committed 2025-06-18 18:30:01 -06:00
1 parent 8c2eff61fa
commit 180e1db710
11 files changed
+155 -389

No files matched your search

+6 -8
View File
@@ -30,20 +30,18 @@ typedef enum {
GUS_MODE = 1,
ADLIB_MODE = 2,
MPU_MODE = 3,
TANDY_MODE = 4,
CMS_MODE = 5,
SB_MODE = 6,
USB_MODE = 7,
NE2000_MODE = 8
PSG_MODE = 4,
SB_MODE = 5,
USB_MODE = 6,
NE2000_MODE = 7
} card_mode_t;
static const char *modenames[9] = {
static const char *modenames[8] = {
"INVALID",
"GUS",
"ADLIB",
"MPU",
"TANDY",
"CMS",
"PSG",
"SB",
"USB",
"NE2000"
+14 -12
View File
@@ -37,7 +37,7 @@ static void usage(card_mode_t mode, bool print_all) {
printf("Usage:\n");
printf(" /? - show this message (/?? to show options for all modes)\n");
printf(" /flash fw.uf2 - program the PicoGUS with the firmware file fw.uf2\n");
printf(" /mode x - change card mode to x (gus, sb, mpu, tandy, cms, adlib, usb)\n");
printf(" /mode x - change card mode to x (gus, sb, mpu, psg, adlib, usb)\n");
printf(" /save - save settings to the card to persist on system boot\n");
printf(" /defaults - set all settings for all modes to defaults\n");
printf(" /wtvol x - set volume of WT header. 0-100, Default 100 (2.0 cards only)\n");
@@ -75,17 +75,17 @@ static void usage(card_mode_t mode, bool print_all) {
printf(" /cdload n - load image n in the list given by /cdlist. 0 to unload image\n");
printf(" /cdauto 1|0 - auto-advance loaded image when same USB drive is reinserted\n");
}
if (mode == TANDY_MODE || print_all) {
if (mode == PSG_MODE || print_all) {
// "...............................................................................\n"
printf("Tandy settings:\n");
printf(" /tandyport x - set the base port of the Tandy 3-voice. Default: 2C0\n");
}
if (mode == CMS_MODE || print_all) {
if (mode == PSG_MODE || print_all) {
// "...............................................................................\n"
printf("CMS settings:\n");
printf(" /cmsport x - set the base port of the CMS. Default: 220\n");
}
if (mode == USB_MODE || mode == CMS_MODE || mode == TANDY_MODE || mode == ADLIB_MODE || print_all) {
if (mode == USB_MODE || mode == PSG_MODE || mode == ADLIB_MODE || print_all) {
// "...............................................................................\n"
printf("Serial Mouse settings:\n");
printf(" /mousecom n - mouse COM port. Default: 0, Choices: 0 (disable), 1, 2, 3, 4\n");
@@ -785,7 +785,7 @@ int main(int argc, char* argv[]) {
// CD-ROM options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/cdport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_CDPORT); // Select Tandy port register
outp(CONTROL_PORT, MODE_CDPORT); // Select CD port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
} else if (stricmp(argv[i], "/cdlist") == 0) {
if (!print_cdimage_list()) {
@@ -820,8 +820,12 @@ int main(int argc, char* argv[]) {
if (mode_name[0]) {
if (strnicmp(mode_name, "TANDY", 5) == 0 || strnicmp(mode_name, "CMS", 3) == 0) {
// Backwards compatibility for old tandy and cms modes
strcpy(mode_name, "PSG");
}
int i;
for (i = 1; i < 8; ++i) {
for (i = 1; i < 7; ++i) {
if (strnicmp(modenames[i], mode_name, 7) == 0) {
fw_num = i;
break;
@@ -921,15 +925,13 @@ int main(int argc, char* argv[]) {
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("CD image auto-advance on USB reinsert %s\n", tmp_uint8 ? "enabled" : "disabled");
break;
case TANDY_MODE:
case PSG_MODE:
outp(CONTROL_PORT, MODE_TANDYPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in Tandy 3-voice mode on port %x\n", tmp_uint16);
break;
case CMS_MODE:
printf("Running in PSG mode (Tandy 3-voice on port %x, ", tmp_uint16);
outp(CONTROL_PORT, MODE_CMSPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in CMS/Game Blaster mode on port %x\n", tmp_uint16);
printf("CMS/Game Blaster on port %x)\n", tmp_uint16);
break;
case SB_MODE:
if (init_sb()) {
@@ -963,7 +965,7 @@ int main(int argc, char* argv[]) {
printf("Running in unknown mode (maybe upgrade pgusinit?)\n");
break;
}
if (mode == USB_MODE || mode == CMS_MODE || mode == TANDY_MODE || mode == ADLIB_MODE) {
if (mode == USB_MODE || mode == PSG_MODE || mode == ADLIB_MODE) {
outp(CONTROL_PORT, MODE_MOUSEPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Serial Mouse ");
+21 -49
View File
@@ -284,38 +284,21 @@ function(build_mpu TARGET_NAME MULTIFW)
endfunction()
################################################################################
# Build Tandy firmware
function(build_tandy TARGET_NAME MULTIFW)
# Build PSG firmware
function(build_psg TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-tandy")
pico_set_program_name(${TARGET_NAME} "picogus-psg")
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_TANDY=1
# SQUARE_FLOAT_OUTPUT=1
)
target_sources(${TARGET_NAME} PRIVATE
square/square.cpp
)
target_sources(${TARGET_NAME} PRIVATE tandyplay.cpp)
endfunction()
################################################################################
# Build CMS firmware
function(build_cms TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-cms")
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_CMS=1
)
target_sources(${TARGET_NAME} PRIVATE
square/square.cpp
)
target_sources(${TARGET_NAME} PRIVATE cmsplay.cpp)
target_sources(${TARGET_NAME} PRIVATE psgplay.cpp)
endfunction()
################################################################################
@@ -363,8 +346,7 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
"${CMAKE_BINARY_DIR}/pg-gus-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-adlib-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-mpu-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-tandy-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-cms-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-psg-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
COMMAND
@@ -378,22 +360,19 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
-DFW_2_LD="${CMAKE_BINARY_DIR}/pg-adlib-multifw.ld"
-DFW_3_BIN="${CMAKE_BINARY_DIR}/pg-mpu.bin"
-DFW_3_LD="${CMAKE_BINARY_DIR}/pg-mpu-multifw.ld"
-DFW_4_BIN="${CMAKE_BINARY_DIR}/pg-tandy.bin"
-DFW_4_LD="${CMAKE_BINARY_DIR}/pg-tandy-multifw.ld"
-DFW_5_BIN="${CMAKE_BINARY_DIR}/pg-cms.bin"
-DFW_5_LD="${CMAKE_BINARY_DIR}/pg-cms-multifw.ld"
-DFW_6_BIN="${CMAKE_BINARY_DIR}/pg-sb.bin"
-DFW_6_LD="${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
-DFW_7_BIN="${CMAKE_BINARY_DIR}/pg-usb.bin"
-DFW_7_LD="${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
-DFW_4_BIN="${CMAKE_BINARY_DIR}/pg-psg.bin"
-DFW_4_LD="${CMAKE_BINARY_DIR}/pg-psg-multifw.ld"
-DFW_5_BIN="${CMAKE_BINARY_DIR}/pg-sb.bin"
-DFW_5_LD="${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
-DFW_6_BIN="${CMAKE_BINARY_DIR}/pg-usb.bin"
-DFW_6_LD="${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
-P ${CMAKE_SOURCE_DIR}/multifw/generate_ld.cmake
DEPENDS
"${CMAKE_SOURCE_DIR}/multifw/firmware.ld.in"
pg-gus
pg-adlib
pg-mpu
pg-tandy
pg-cms
pg-psg
pg-sb
pg-usb
)
@@ -402,8 +381,7 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
"${CMAKE_BINARY_DIR}/pg-gus-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-adlib-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-mpu-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-tandy-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-cms-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-psg-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
)
@@ -417,12 +395,9 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
build_mpu(pg-mpu FALSE)
build_mpu(pg-mpu-multifw TRUE)
add_dependencies(pg-mpu-multifw pg-mpu generate_flash_firmware_h)
build_tandy(pg-tandy FALSE)
build_tandy(pg-tandy-multifw TRUE)
add_dependencies(pg-tandy-multifw pg-tandy generate_flash_firmware_h)
build_cms(pg-cms FALSE)
build_cms(pg-cms-multifw TRUE)
add_dependencies(pg-cms-multifw pg-cms generate_flash_firmware_h)
build_psg(pg-psg FALSE)
build_psg(pg-psg-multifw TRUE)
add_dependencies(pg-psg-multifw pg-psg generate_flash_firmware_h)
build_sb(pg-sb FALSE)
build_sb(pg-sb-multifw TRUE)
add_dependencies(pg-sb-multifw pg-sb generate_flash_firmware_h)
@@ -450,8 +425,8 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
endif()
add_custom_command(
OUTPUT picogus.uf2
DEPENDS bootloader UF2CREATE pg-gus-multifw pg-adlib-multifw pg-mpu-multifw pg-tandy-multifw pg-cms-multifw pg-sb-multifw pg-usb-multifw
COMMAND UF2CREATE bootloader.bin pg-gus-multifw.bin pg-adlib-multifw.bin pg-mpu-multifw.bin pg-tandy-multifw.bin pg-cms-multifw.bin pg-sb-multifw.bin pg-usb-multifw.bin picogus.uf2
DEPENDS bootloader UF2CREATE pg-gus-multifw pg-adlib-multifw pg-mpu-multifw pg-psg-multifw pg-sb-multifw pg-usb-multifw
COMMAND UF2CREATE bootloader.bin pg-gus-multifw.bin pg-adlib-multifw.bin pg-mpu-multifw.bin pg-psg-multifw.bin pg-sb-multifw.bin pg-usb-multifw.bin picogus.uf2
)
add_custom_target(picogus ALL DEPENDS picogus.uf2)
@@ -469,12 +444,9 @@ elseif(PROJECT_TYPE STREQUAL "ADLIB")
elseif(PROJECT_TYPE STREQUAL "MPU")
set(FW_TARGET pg-mpu)
build_mpu(pg-mpu FALSE)
elseif(PROJECT_TYPE STREQUAL "TANDY")
set(FW_TARGET pg-tandy)
build_tandy(pg-tandy FALSE)
elseif(PROJECT_TYPE STREQUAL "CMS")
set(FW_TARGET pg-cms)
build_cms(pg-cms FALSE)
elseif(PROJECT_TYPE STREQUAL "PSG")
set(FW_TARGET pg-psg)
build_psg(pg-psg FALSE)
elseif(PROJECT_TYPE STREQUAL "USB")
set(FW_TARGET pg-usb)
build_usb(pg-usb FALSE)
+1
View File
@@ -1,3 +1,4 @@
#pragma once
/*
* Command buffers for CMS and Tandy bus events
*/
-223
View File
@@ -1,223 +0,0 @@
/*
* Copyright (C) 2022-2024 Ian Scott
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#if PICO_ON_DEVICE
#include "hardware/clocks.h"
#include "hardware/structs/clocks.h"
#endif
#include "pico/stdlib.h"
#include "pico/audio_i2s.h"
#ifdef USB_STACK
#include "tusb.h"
#endif
#if defined(USB_MOUSE) || defined(SOUND_MPU)
#include "pico_pic.h"
#endif
#ifdef USB_MOUSE
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
#endif
#ifdef MAME_CMS
#include "saa1099/saa1099.h"
saa1099_device *saa0, *saa1;
#else
#include "square/square.h"
#endif
#include "cmd_buffers.h"
extern cms_buffer_t cms_buffer;
#ifdef SOUND_MPU
#include "flash_settings.h"
extern Settings settings;
#include "mpu401/export.h"
#endif
extern uint LED_PIN;
#if PICO_ON_DEVICE
#include "pico/binary_info.h"
bi_decl(bi_3pins_with_names(PICO_AUDIO_I2S_DATA_PIN, "I2S DIN", PICO_AUDIO_I2S_CLOCK_PIN_BASE, "I2S BCK", PICO_AUDIO_I2S_CLOCK_PIN_BASE+1, "I2S LRCK"));
#endif
#define SAMPLES_PER_BUFFER 4
struct audio_buffer_pool *init_audio() {
static audio_format_t audio_format = {
.sample_freq = 44100,
.format = AUDIO_BUFFER_FORMAT_PCM_S16,
.channel_count = 2,
};
static struct audio_buffer_format producer_format = {
.format = &audio_format,
.sample_stride = 4
};
struct audio_buffer_pool *producer_pool = audio_new_producer_pool(&producer_format, 2,
SAMPLES_PER_BUFFER); // todo correct size
bool __unused ok;
const struct audio_format *output_format;
struct audio_i2s_config config = {
.data_pin = PICO_AUDIO_I2S_DATA_PIN,
.clock_pin_base = PICO_AUDIO_I2S_CLOCK_PIN_BASE,
.dma_channel = 6,
.pio_sm = 3,
};
output_format = audio_i2s_setup(&audio_format, &config);
if (!output_format) {
panic("PicoAudio: Unable to open audio device.\n");
}
ok = audio_i2s_connect_extra(producer_pool, false, 0, 0, NULL);
assert(ok);
audio_i2s_set_enabled(true);
return producer_pool;
}
void play_cms() {
puts("starting core 1 CMS");
// flash_safe_execute_core_init();
#if defined(USB_MOUSE) || defined(SOUND_MPU)
// Init PIC on this core so it handles timers
PIC_Init();
puts("pic inited on core 1");
#endif
#ifdef USB_STACK
// Init TinyUSB for joystick support
tuh_init(BOARD_TUH_RHPORT);
#endif
#ifdef SOUND_MPU
MPU401_Init(settings.MPU.delaySysex, settings.MPU.fakeAllNotesOff);
#endif
#ifdef MAME_CMS
puts("Creating SAA1099 1");
saa0 = new saa1099_device(7159090);
puts("Creating SAA1099 2");
saa1 = new saa1099_device(7159090);
// saa0->device_start();
// saa1->device_start();
int16_t buf0[SAMPLES_PER_BUFFER * 2];
int16_t buf1[SAMPLES_PER_BUFFER * 2];
#else
cms_t cms;
#ifdef SQUARE_FLOAT_OUTPUT
float buf[SAMPLES_PER_BUFFER * 2];
#else
int32_t buf[SAMPLES_PER_BUFFER * 2];
#endif
#endif // MAME_CMS
struct audio_buffer_pool *ap = init_audio();
for (;;) {
// putchar('.');
bool notfirst = false;
while (cms_buffer.tail != cms_buffer.head) {
if (!notfirst) {
gpio_xor_mask(LED_PIN);
notfirst = true;
}
auto cmd = cms_buffer.cmds[cms_buffer.tail];
#ifdef MAME_CMS
// printf("%x ", cmd.addr & 0x3);
switch (cmd.addr & 0x3) {
case 0x0:
saa0->data_w(cmd.data);
break;
case 0x1:
saa0->control_w(cmd.data);
break;
case 0x2:
saa1->data_w(cmd.data);
break;
case 0x3:
saa1->control_w(cmd.data);
break;
}
#else // MAME_CMS
if (cmd.addr & 1) {
cms.write_addr(cmd.addr, cmd.data);
} else {
cms.write_data(cmd.addr, cmd.data);
}
#endif // MAME_CMS
++cms_buffer.tail;
}
struct audio_buffer *buffer = take_audio_buffer(ap, true);
int16_t *samples = (int16_t *) buffer->buffer->bytes;
#ifdef MAME_CMS
saa0->sound_stream_update(buf0, SAMPLES_PER_BUFFER);
saa1->sound_stream_update(buf1, SAMPLES_PER_BUFFER);
#else
memset(buf, 0, sizeof(buf));
// uint32_t cms_audio_begin = time_us_32();
#ifdef SQUARE_FLOAT_OUTPUT
cms.generator(0).generate_frames(buf, SAMPLES_PER_BUFFER, 1.0f);
cms.generator(1).generate_frames(buf, SAMPLES_PER_BUFFER, 1.0f);
#else
cms.generator(0).generate_frames(buf, SAMPLES_PER_BUFFER);
cms.generator(1).generate_frames(buf, SAMPLES_PER_BUFFER);
#endif // SQUARE_FLOAT_OUTPUT
#endif // MAME_CMS
for(uint32_t i = 0; i < SAMPLES_PER_BUFFER; ++i) {
#ifdef MAME_CMS
samples[i << 1] = ((int32_t)buf0[i << 1] + (int32_t)buf1[i << 1]) >> 1;
samples[(i << 1) + 1] = ((int32_t)buf0[(i << 1) + 1] + (int32_t)buf1[(i << 1) + 1]) >> 1;
#else
#ifdef SQUARE_FLOAT_OUTPUT
samples[i << 1] = (int32_t)(buf[i << 1] * 32768.0f) >> 1;
samples[(i << 1) + 1] = (int32_t)(buf[(i << 1) + 1] * 32768.0f) >> 1;
#else
samples[i << 1] = buf[i << 1] >> 1;
samples[(i << 1) + 1] = buf[(i << 1) + 1] >> 1;
#endif //SQUARE_FLOAT_OUTPUT
#endif // MAME_CMS
}
// uint32_t cms_audio_elapsed = time_us_32() - cms_audio_begin;
// printf("%u ", cms_audio_elapsed);
buffer->sample_count = buffer->max_sample_count;
give_audio_buffer(ap, buffer);
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
#endif
#ifdef USB_MOUSE
// mouse task
sermouse_core1_task();
// uart emulation task
uartemu_core1_task();
#endif
#ifdef SOUND_MPU
send_midi_bytes(4);
#endif
}
}
+1 -1
View File
@@ -9,7 +9,7 @@
#include <stdio.h>
static uint32_t sStart = 0;
static const uint32_t offset[NR_OF_FIRMWARES] = {FLASH_FIRMWARE1, FLASH_FIRMWARE2, FLASH_FIRMWARE3, FLASH_FIRMWARE4, FLASH_FIRMWARE5, FLASH_FIRMWARE6, FLASH_FIRMWARE7};
static const uint32_t offset[NR_OF_FIRMWARES] = {FLASH_FIRMWARE1, FLASH_FIRMWARE2, FLASH_FIRMWARE3, FLASH_FIRMWARE4, FLASH_FIRMWARE5, FLASH_FIRMWARE6};
uint8_t read_permMode(void)
{
+1 -2
View File
@@ -6,11 +6,10 @@
// Make sure the FLASH addresses match the .ld files!!!
// ld files for picogus firmwares/modes are based on memmap_copy_to_ram.ld as they run with set(PICO_COPY_TO_RAM 1)
#define NR_OF_FIRMWARES 7
#define NR_OF_FIRMWARES 6
#define FLASH_FIRMWARE1 ${FW_1_ORIGIN}
#define FLASH_FIRMWARE2 ${FW_2_ORIGIN}
#define FLASH_FIRMWARE3 ${FW_3_ORIGIN}
#define FLASH_FIRMWARE4 ${FW_4_ORIGIN}
#define FLASH_FIRMWARE5 ${FW_5_ORIGIN}
#define FLASH_FIRMWARE6 ${FW_6_ORIGIN}
#define FLASH_FIRMWARE7 ${FW_7_ORIGIN}
-2
View File
@@ -19,14 +19,12 @@ generate_ld_file(${FW_3_BIN} ${FW_3_LD})
generate_ld_file(${FW_4_BIN} ${FW_4_LD})
generate_ld_file(${FW_5_BIN} ${FW_5_LD})
generate_ld_file(${FW_6_BIN} ${FW_6_LD})
generate_ld_file(${FW_7_BIN} ${FW_7_LD})
list(GET FW_ORIGINS 0 FW_1_ORIGIN)
list(GET FW_ORIGINS 1 FW_2_ORIGIN)
list(GET FW_ORIGINS 2 FW_3_ORIGIN)
list(GET FW_ORIGINS 3 FW_4_ORIGIN)
list(GET FW_ORIGINS 4 FW_5_ORIGIN)
list(GET FW_ORIGINS 5 FW_6_ORIGIN)
list(GET FW_ORIGINS 6 FW_7_ORIGIN)
file(REMOVE ${FLASH_FIRMWARE_H})
configure_file(${FLASH_FIRMWARE_H_IN} ${FLASH_FIRMWARE_H})
+1 -1
View File
@@ -16,7 +16,7 @@ int main(int argc, char *argv[])
{
int total_size = 0;
static uint8_t flashbuffer[FLASH_SIZE];
uint32_t offset[INPUT_FILES] = {0, FLASH_FIRMWARE1, FLASH_FIRMWARE2, FLASH_FIRMWARE3, FLASH_FIRMWARE4, FLASH_FIRMWARE5, FLASH_FIRMWARE6, FLASH_FIRMWARE7};
uint32_t offset[INPUT_FILES] = {0, FLASH_FIRMWARE1, FLASH_FIRMWARE2, FLASH_FIRMWARE3, FLASH_FIRMWARE4, FLASH_FIRMWARE5, FLASH_FIRMWARE6};
struct uf2_block uf2;
FILE *f_input, *f_output;
+72 -76
View File
@@ -104,19 +104,16 @@ void play_mpu(void);
#endif
#endif
#ifdef SOUND_TANDY
#include "square/square.h"
void play_tandy(void);
#if SOUND_TANDY || SOUND_CMS
#include "cmd_buffers.h"
#include "square/square.h"
void play_psg(void);
#endif
#if SOUND_TANDY
tandy_buffer_t tandy_buffer = { {0}, 0, 0 };
#endif
#ifdef SOUND_CMS
void play_cms(void);
#if SOUND_CMS
static uint8_t cms_detect = 0xFF;
#include "cmd_buffers.h"
cms_buffer_t cms_buffer = { {0}, 0, 0 };
#endif
@@ -570,10 +567,8 @@ __force_inline uint8_t read_picogus_high(void) {
void processSettings(void) {
#if defined(SOUND_GUS)
settings.startupMode = GUS_MODE;
#elif defined(SOUND_TANDY)
settings.startupMode = TANDY_MODE;
#elif defined(SOUND_CMS)
settings.startupMode = CMS_MODE;
#elif (SOUND_TANDY || SOUND_CMS)
settings.startupMode = PSG_MODE;
#elif defined(SOUND_SB)
settings.startupMode = SB_MODE;
#elif defined(SOUND_OPL)
@@ -744,6 +739,47 @@ __force_inline void handle_iow(void) {
PG_NE2000_Write(port & 0x1f, iow_read & 0xFF);
} else // if follows down below
#endif
#ifdef SOUND_CMS
if ((port & 0x3f0) == settings.CMS.basePort) {
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
switch (port & 0xf) {
// SAA data/address ports
case 0x0:
case 0x1:
case 0x2:
case 0x3:
cms_buffer.cmds[cms_buffer.head++] = {
port,
(uint8_t)(iow_read & 0xFF)
};
break;
// CMS autodetect ports
case 0x6:
case 0x7:
cms_detect = iow_read & 0xFF;
break;
}
return;
} else
#endif // SOUND_CMS
#ifdef SOUND_MPU
if ((port & 0x3fe) == settings.MPU.basePort) {
switch (port & 0xf) {
case 0:
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
// printf("MPU IOW: port: %x value: %x\n", port, iow_read & 0xFF);
MPU401_WriteData(iow_read & 0xFF, true);
gpio_xor_mask(LED_PIN);
break;
case 1:
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
MPU401_WriteCommand(iow_read & 0xFF, true);
// printf("MPU IOW: port: %x value: %x\n", port, iow_read & 0xFF);
// __dsb();
break;
}
} else
#endif // SOUND_MPU
// PicoGUS control
if (port == CONTROL_PORT) {
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
@@ -767,46 +803,6 @@ __force_inline void handle_iow(void) {
if (control_active) {
write_picogus_high(iow_read & 0xFF);
}
} else {
#ifdef SOUND_CMS
switch (port - settings.CMS.basePort) {
// SAA data/address ports
case 0x0:
case 0x1:
case 0x2:
case 0x3:
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
cms_buffer.cmds[cms_buffer.head++] = {
port,
(uint8_t)(iow_read & 0xFF)
};
return;
break;
// CMS autodetect ports
case 0x6:
case 0x7:
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
cms_detect = iow_read & 0xFF;
return;
break;
}
#endif // SOUND_CMS
#ifdef SOUND_MPU
switch (port - settings.MPU.basePort) {
case 0:
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
// printf("MPU IOW: port: %x value: %x\n", port, iow_read & 0xFF);
MPU401_WriteData(iow_read & 0xFF, true);
gpio_xor_mask(LED_PIN);
break;
case 1:
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
MPU401_WriteCommand(iow_read & 0xFF, true);
// printf("MPU IOW: port: %x value: %x\n", port, iow_read & 0xFF);
// __dsb();
break;
}
#endif // SOUND_MPU
}
// Fallthrough if no match, or for slow write, reset PIO
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
@@ -905,6 +901,25 @@ __force_inline void handle_ior(void) {
return;
} else // if follows down below
#endif // USB_MOUSE
#if defined(SOUND_CMS)
if ((port & 0x3f0) == settings.CMS.basePort) {
switch (port & 0xf) {
// CMS autodetect ports
case 0x4:
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | 0x7F);
return;
case 0xa:
case 0xb:
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | cms_detect);
return;
default:
pio_sm_put(pio0, IOR_PIO_SM, IO_END);
return;
}
} else
#endif // SOUND_CMS
if (port == CONTROL_PORT) {
// Tell PIO to wait for data
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
@@ -917,20 +932,6 @@ __force_inline void handle_ior(void) {
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | read_picogus_high());
} else {
#if defined(SOUND_CMS)
switch (port - settings.CMS.basePort) {
// CMS autodetect ports
case 0x4:
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | 0x7F);
return;
case 0xa:
case 0xb:
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | cms_detect);
return;
}
#endif // SOUND_CMS
// Reset PIO
pio_sm_put(pio0, IOR_PIO_SM, IO_END);
}
@@ -1145,15 +1146,10 @@ int main()
#endif // MPU_ONLY
#endif // SOUND_MPU
#ifdef SOUND_TANDY
puts("Creating tandysound");
multicore_launch_core1(&play_tandy);
#endif // SOUND_TANDY
#ifdef SOUND_CMS
puts("Creating CMS");
multicore_launch_core1(&play_cms);
#endif // SOUND_CMS
#if (SOUND_TANDY || SOUND_CMS)
puts("Creating psgsound");
multicore_launch_core1(&play_psg);
#endif // (SOUND_TANDY || SOUND_CMS)
#ifdef NE2000
extern void PIC_ActivateIRQ(void);
+38 -15
View File
@@ -32,7 +32,13 @@
#include "square/square.h"
#include "cmd_buffers.h"
#if SOUND_TANDY
extern tandy_buffer_t tandy_buffer;
#endif
#if SOUND_CMS
extern cms_buffer_t cms_buffer;
#endif
extern uint LED_PIN;
@@ -98,8 +104,8 @@ struct audio_buffer_pool *init_audio() {
return producer_pool;
}
void play_tandy() {
puts("starting core 1 tandy");
void play_psg() {
puts("starting core 1 psg");
// flash_safe_execute_core_init();
#if defined(USB_MOUSE) || defined(SOUND_MPU)
@@ -116,15 +122,18 @@ void play_tandy() {
MPU401_Init(settings.MPU.delaySysex, settings.MPU.fakeAllNotesOff);
#endif
#if SOUND_TANDY
tandysound_t tandysound;
struct audio_buffer_pool *ap = init_audio();
#ifdef SQUARE_FLOAT_OUTPUT
float buf[SAMPLES_PER_BUFFER * 2];
#else
int32_t buf[SAMPLES_PER_BUFFER * 2];
#endif
#if SOUND_CMS
cms_t cms;
#endif
struct audio_buffer_pool *ap = init_audio();
int32_t buf[SAMPLES_PER_BUFFER * 2];
for (;;) {
bool notfirst = false;
#if SOUND_TANDY
while (tandy_buffer.tail != tandy_buffer.head) {
if (!notfirst) {
gpio_xor_mask(LED_PIN);
@@ -133,23 +142,37 @@ void play_tandy() {
tandysound.write_register(0, tandy_buffer.cmds[tandy_buffer.tail]);
++tandy_buffer.tail;
}
#endif // SOUND_TANDY
#if SOUND_CMS
while (cms_buffer.tail != cms_buffer.head) {
if (!notfirst) {
gpio_xor_mask(LED_PIN);
notfirst = true;
}
auto cmd = cms_buffer.cmds[cms_buffer.tail];
if (cmd.addr & 1) {
cms.write_addr(cmd.addr, cmd.data);
} else {
cms.write_data(cmd.addr, cmd.data);
}
++cms_buffer.tail;
}
#endif
memset(buf, 0, sizeof(buf));
struct audio_buffer *buffer = take_audio_buffer(ap, true);
int16_t *samples = (int16_t *) buffer->buffer->bytes;
#ifdef SQUARE_FLOAT_OUTPUT
tandysound.generator().generate_frames(buf, SAMPLES_PER_BUFFER, 1.0f);
#else
#if SOUND_TANDY
tandysound.generator().generate_frames(buf, SAMPLES_PER_BUFFER);
#endif
#if SOUND_CMS
cms.generator(0).generate_frames(buf, SAMPLES_PER_BUFFER);
cms.generator(1).generate_frames(buf, SAMPLES_PER_BUFFER);
#endif
for (int i = 0; i < SAMPLES_PER_BUFFER; ++i) {
#ifdef SQUARE_FLOAT_OUTPUT
samples[i << 1] = (int32_t)(buf[i << 1] * 32768.0f) >> 1;
samples[(i << 1) + 1] = (int32_t)(buf[(i << 1) + 1] * 32768.0f) >> 1;
#else
samples[i << 1] = buf[i << 1] >> 1;
samples[(i << 1) + 1] = buf[(i << 1) + 1] >> 1;
#endif
}
buffer->sample_count = SAMPLES_PER_BUFFER;