From 0aea1d0db279825c898dd33ad19e4dd5531ba23c Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 1 Mar 2024 19:38:47 +0800 Subject: [PATCH] example/aica_gdrom: initial aica_gdrom currently copies from system ram to AICA ram, 128 bytes at a time, synchronized with the AICA sample timer. --- example/aica.cpp | 2 +- example/aica_gdrom.cpp | 103 +++++++++++++++++++++++----------- example/arm/Makefile | 3 + example/arm/channel.cpp | 31 ++++++---- example/arm/main.lds | 11 +++- example/arm/sh4_interrupt.cpp | 92 ++++++++++++++++++++++++++++++ example/example.mk | 11 +++- 7 files changed, 207 insertions(+), 46 deletions(-) create mode 100644 example/arm/sh4_interrupt.cpp diff --git a/example/aica.cpp b/example/aica.cpp index 9cf9164..f89a81b 100644 --- a/example/aica.cpp +++ b/example/aica.cpp @@ -14,7 +14,7 @@ void wait() void wait_read() { - uint32_t ffst = ~0; + uint32_t ffst = system.FFST; while ( ffst::holly_cpu_if_block_internal_write_buffer(ffst) | ffst::holly_g2_if_block_internal_write_buffer(ffst) | ffst::aica_internal_write_buffer(ffst)) { diff --git a/example/aica_gdrom.cpp b/example/aica_gdrom.cpp index 4851143..3251480 100644 --- a/example/aica_gdrom.cpp +++ b/example/aica_gdrom.cpp @@ -1,20 +1,25 @@ #include "memorymap.hpp" -#include "aica/aica.hpp" #include "sh7091/serial.hpp" #include "systembus.hpp" #include "systembus_bits.hpp" +#include "aica/aica.hpp" -extern void * _binary_start __asm("_binary_example_arm_channel_bin_start"); -extern void * _binary_size __asm("_binary_example_arm_channel_bin_size"); +extern void * _audio_pcm_start __asm("_binary_audio_pcm_start"); -void wait() +extern void * _binary_start __asm("_binary_example_arm_sh4_interrupt_bin_start"); +extern void * _binary_size __asm("_binary_example_arm_sh4_interrupt_bin_size"); + +constexpr uint32_t mcipd__sh4_interrupt = (1 << 5); +constexpr uint32_t scipd__arm_interrupt = (1 << 5); + +void aica_wait_write() { while (ffst::aica_internal_write_buffer(system.FFST)); } -void wait_read() +void aica_wait_read() { - uint32_t ffst = ~0; + uint32_t ffst = system.FFST; while ( ffst::holly_cpu_if_block_internal_write_buffer(ffst) | ffst::holly_g2_if_block_internal_write_buffer(ffst) | ffst::aica_internal_write_buffer(ffst)) { @@ -22,41 +27,73 @@ void wait_read() }; } -void main() +void fill_chunk(volatile uint32_t * chunk, const uint32_t segment_index) +{ + const uint32_t * audio_pcm = reinterpret_cast(&_audio_pcm_start); + const uint32_t * segment = &audio_pcm[(segment_index * 128 * 2) / 4]; + + for (int i = 0; i < (128 * 2) / 4; i++) { + if (i % 8 == 0) aica_wait_write(); + chunk[i] = segment[i]; + } +} + +static volatile uint32_t (* chunk)[2][(128 * 2) / 4]; + +void aica_init(uint32_t& chunk_index, uint32_t& segment_index) { const uint32_t * binary = reinterpret_cast(&_binary_start); const uint32_t binary_size = reinterpret_cast(&_binary_size); - wait(); aica.common.reg_2c00 = 1; - wait(); aica.common.reg_2880 = 0; + aica_wait_write(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1); + aica_wait_write(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0); for (uint32_t i = 0; i < binary_size / 4; i++) { // copy - aica_wave_memory[i] = binary[i]; - if (i % 8 == 7) wait(); - } - wait(); aica.common.reg_2c00 = 0; - - serial::integer(aica_wave_memory[0]); - - wait(); aica.common.MSLC(0); - serial::string("mrwinh: "); - wait_read(); - serial::integer(aica.common.MRWINH()); - while (1) { - wait_read(); - serial::string("sgc: "); - serial::integer(aica.common.SGC(), ' '); - serial::string("; ca: "); - serial::integer(aica.common.CA(), ' '); - serial::string("; eg: "); - serial::integer(aica.common.EG(), ' '); - serial::string("; lp: "); - serial::integer(aica.common.LP(), ' '); - serial::character('\n'); - for (int i = 0; i < 10000000; i++) { - asm volatile ("nop"); + while (aica_wave_memory[i] != binary[i]) { + aica_wait_write(); + aica_wave_memory[i] = binary[i]; } } + chunk = reinterpret_cast(&aica_wave_memory[0x001ff000 / 4]); + + serial::integer(reinterpret_cast(&(*chunk)[0][0])); + serial::integer(reinterpret_cast(&(*chunk)[1][0])); + + fill_chunk(&(*chunk)[chunk_index][0], segment_index); + chunk_index = (chunk_index + 1) % 2; + segment_index += 1; + + aica_wait_write(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(0); +} + +void aica_step(uint32_t& chunk_index, uint32_t& segment_index) +{ + aica_wait_read(); + { // wait for interrupt from arm + while ((aica_sound.common.MCIPD() & mcipd__sh4_interrupt) == 0) { aica_wait_read(); }; + aica_wait_write(); aica_sound.common.mcire = mcipd__sh4_interrupt; + } + + { // fill the requested chunk + fill_chunk(&(*chunk)[chunk_index][0], segment_index); + + chunk_index = (chunk_index + 1) % 2; + segment_index += 1; + if (segment_index >= 3440) segment_index = 0; + } +} + +void main() +{ + uint32_t chunk_index = 0; + uint32_t segment_index = 0; + + aica_init(chunk_index, segment_index); + + while (1) { + aica_step(chunk_index, segment_index); + } + while (1); } diff --git a/example/arm/Makefile b/example/arm/Makefile index 9591d55..8523927 100644 --- a/example/arm/Makefile +++ b/example/arm/Makefile @@ -21,6 +21,9 @@ include base.mk channel.elf: LDSCRIPT = main.lds channel.elf: start.o channel.o audio.pcm.o +sh4_interrupt.elf: LDSCRIPT = main.lds +sh4_interrupt.elf: start.o sh4_interrupt.o + clean: find -P \ -regextype posix-egrep \ diff --git a/example/arm/channel.cpp b/example/arm/channel.cpp index 5c245a3..6d7bc69 100644 --- a/example/arm/channel.cpp +++ b/example/arm/channel.cpp @@ -22,7 +22,6 @@ void main() aica_sound.channel[0].KYONB(1); aica_sound.channel[0].LPCTL(1); aica_sound.channel[0].PCMS(0); - aica_sound.channel[0].SA(sine_addr); aica_sound.channel[0].LSA(0); aica_sound.channel[0].LEA(128); aica_sound.channel[0].D2R(0x0); @@ -39,26 +38,38 @@ void main() aica_sound.channel[0].TL(0); aica_sound.channel[0].LPOFF(1); - aica_sound.common.MVOL(0xf); + aica_sound.common.mono_mem8mb_dac18b_ver_mvol = + aica::mono_mem8mb_dac18b_ver_mvol::MONO(0) // enable panpots + | aica::mono_mem8mb_dac18b_ver_mvol::MEM8MB(0) // 16Mbit SDRAM + | aica::mono_mem8mb_dac18b_ver_mvol::DAC18B(0) // 16-bit DAC + | aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xf) // 15/15 volume + ; uint32_t segment = 0; - aica_sound.common.TACTL(7); // increment once every 128 samples - aica_sound.common.TIMA(255); - aica_sound.channel[0].KYONEX(1); dram[0] = 0x11223344; dram[1] = sine_addr; constexpr uint32_t timer_a_interrupt = (1 << 6); aica_sound.common.scire = timer_a_interrupt; + uint32_t next_sa = sine_addr; + bool started = 0; + while (1) { - if (aica_sound.common.SCIPD() & timer_a_interrupt) { + if (!started || (aica_sound.common.SCIPD() & timer_a_interrupt)) { + aica_sound.channel[0].SA(next_sa); + aica_sound.common.tactl_tima = + aica::tactl_tima::TACTL(0) // increment once every 128 samples + | aica::tactl_tima::TIMA(256 - 128) // interrupt after 128 counts + ; + + if (!started) { aica_sound.channel[0].KYONEX(1); started = 1; } + aica_sound.common.scire = timer_a_interrupt; - aica_sound.common.TIMA(255); + dram[1] = next_sa; + segment += 1; if (segment >= 3440) segment = 0; - uint32_t sa = sine_addr + (128 * 2) * segment; - dram[1] = sa; - aica_sound.channel[0].SA(sa); + next_sa = sine_addr + (128 * 2) * segment; } } } diff --git a/example/arm/main.lds b/example/arm/main.lds index b825663..a08ac95 100644 --- a/example/arm/main.lds +++ b/example/arm/main.lds @@ -1,7 +1,8 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") MEMORY { - ram : ORIGIN = 0x00000000, LENGTH = 0x200000 + ram : ORIGIN = 0x00000000, LENGTH = 0x1ff000 + buffers : ORIGIN = 0x001ff000, LENGTH = 0x1000 } SECTIONS { @@ -40,6 +41,14 @@ SECTIONS *(COMMON) } > ram + . = ORIGIN(buffers); + + .buffers ALIGN(4) (NOLOAD) : SUBALIGN(4) + { + *(.buffers) + *(.buffers.*) + } > buffers + INCLUDE "../../debug.lds" INCLUDE "arm.lds" } diff --git a/example/arm/sh4_interrupt.cpp b/example/arm/sh4_interrupt.cpp new file mode 100644 index 0000000..78b38fc --- /dev/null +++ b/example/arm/sh4_interrupt.cpp @@ -0,0 +1,92 @@ +#include "aica/aica.hpp" + +extern volatile uint32_t dram[0x200000] __asm("dram"); + +__attribute__((section(".buffers.chunk"))) +static uint32_t chunk[2][(128 * 2) / 4]; + +void request_chunk() +{ + constexpr uint32_t mcipd__sh4_interrupt = (1 << 5); + aica_sound.common.mcipd = mcipd__sh4_interrupt; +} + +void wait_sh4_response() +{ + constexpr uint32_t scipd__arm_interrupt = (1 << 5); + while ((aica_sound.common.SCIPD() & scipd__arm_interrupt) == 0) { + } + aica_sound.common.scire = scipd__arm_interrupt; +} + +extern "C" +void main() +{ + volatile uint32_t * slot = reinterpret_cast(0x00800000); + for (uint32_t i = 0; i < (sizeof (struct aica_channel)) * 64 / 4; i++) { + slot[i] = 0; + } + + volatile uint32_t * dsp = reinterpret_cast(0x00803000); + for (int i = 0; i < 0xb00 / 4; i++) { + dsp[i] = 0; + } + + aica_sound.channel[0].KYONB(1); + aica_sound.channel[0].LPCTL(1); + aica_sound.channel[0].PCMS(0); + aica_sound.channel[0].LSA(0); + aica_sound.channel[0].LEA(128); + aica_sound.channel[0].D2R(0x0); + aica_sound.channel[0].D1R(0x0); + aica_sound.channel[0].RR(0x0); + aica_sound.channel[0].AR(0x1f); + + aica_sound.channel[0].OCT(0); + aica_sound.channel[0].FNS(0); + aica_sound.channel[0].DISDL(0xf); + aica_sound.channel[0].DIPAN(0x0); + + aica_sound.channel[0].Q(0b00100); + aica_sound.channel[0].TL(0); + aica_sound.channel[0].LPOFF(1); + + aica_sound.common.mono_mem8mb_dac18b_ver_mvol = + aica::mono_mem8mb_dac18b_ver_mvol::MONO(0) // enable panpots + | aica::mono_mem8mb_dac18b_ver_mvol::MEM8MB(0) // 16Mbit SDRAM + | aica::mono_mem8mb_dac18b_ver_mvol::DAC18B(0) // 16-bit DAC + | aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xf) // 15/15 volume + ; + + constexpr uint32_t tactl = 0; // increment once every 1 samples + constexpr uint32_t tima = 256 - 128; // interrupt after 1 count + + dram[0] = reinterpret_cast(&chunk[0][0]); + dram[1] = reinterpret_cast(&chunk[1][0]); + + uint32_t next_chunk = 0; + aica_sound.channel[0].SA(reinterpret_cast(&chunk[next_chunk][0])); + aica_sound.channel[0].KYONEX(1); + next_chunk = (next_chunk + 1) % 2; + request_chunk(); + + constexpr uint32_t timer_a_interrupt = (1 << 6); + aica_sound.common.tactl_tima = aica::tactl_tima::TACTL(tactl) + | aica::tactl_tima::TIMA(tima); + aica_sound.common.scire = timer_a_interrupt; + + uint32_t index = 0; + while (1) { + if (aica_sound.common.SCIPD() & timer_a_interrupt) { + aica_sound.channel[0].SA(reinterpret_cast(&chunk[next_chunk][0])); + aica_sound.common.tactl_tima = aica::tactl_tima::TACTL(tactl) + | aica::tactl_tima::TIMA(tima); + + aica_sound.common.scire = timer_a_interrupt; + + next_chunk = (next_chunk + 1) % 2; + request_chunk(); + //dram[0] = (0xEE << 24) | index++; + } + } +} diff --git a/example/example.mk b/example/example.mk index a9072e9..b75b192 100644 --- a/example/example.mk +++ b/example/example.mk @@ -368,7 +368,16 @@ example/gdrom_iso9660.elf: $(START_OBJ) $(GDROM_ISO9660_OBJ) AICA_OBJ = \ example/aica.o \ sh7091/serial.o \ - example/arm/channel.bin.o \ + example/arm/channel.bin.o example/aica.elf: LDSCRIPT = $(LIB)/alt.lds example/aica.elf: $(START_OBJ) $(AICA_OBJ) + +AICA_GDROM_OBJ = \ + example/aica_gdrom.o \ + sh7091/serial.o \ + example/arm/sh4_interrupt.bin.o \ + audio.pcm.o + +example/aica_gdrom.elf: LDSCRIPT = $(LIB)/alt.lds +example/aica_gdrom.elf: $(START_OBJ) $(AICA_GDROM_OBJ)