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.
This commit is contained in:
parent
73a685face
commit
0aea1d0db2
@ -14,7 +14,7 @@ void wait()
|
|||||||
|
|
||||||
void wait_read()
|
void wait_read()
|
||||||
{
|
{
|
||||||
uint32_t ffst = ~0;
|
uint32_t ffst = system.FFST;
|
||||||
while ( ffst::holly_cpu_if_block_internal_write_buffer(ffst)
|
while ( ffst::holly_cpu_if_block_internal_write_buffer(ffst)
|
||||||
| ffst::holly_g2_if_block_internal_write_buffer(ffst)
|
| ffst::holly_g2_if_block_internal_write_buffer(ffst)
|
||||||
| ffst::aica_internal_write_buffer(ffst)) {
|
| ffst::aica_internal_write_buffer(ffst)) {
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
#include "memorymap.hpp"
|
#include "memorymap.hpp"
|
||||||
#include "aica/aica.hpp"
|
|
||||||
#include "sh7091/serial.hpp"
|
#include "sh7091/serial.hpp"
|
||||||
#include "systembus.hpp"
|
#include "systembus.hpp"
|
||||||
#include "systembus_bits.hpp"
|
#include "systembus_bits.hpp"
|
||||||
|
#include "aica/aica.hpp"
|
||||||
|
|
||||||
extern void * _binary_start __asm("_binary_example_arm_channel_bin_start");
|
extern void * _audio_pcm_start __asm("_binary_audio_pcm_start");
|
||||||
extern void * _binary_size __asm("_binary_example_arm_channel_bin_size");
|
|
||||||
|
|
||||||
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));
|
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)
|
while ( ffst::holly_cpu_if_block_internal_write_buffer(ffst)
|
||||||
| ffst::holly_g2_if_block_internal_write_buffer(ffst)
|
| ffst::holly_g2_if_block_internal_write_buffer(ffst)
|
||||||
| ffst::aica_internal_write_buffer(ffst)) {
|
| ffst::aica_internal_write_buffer(ffst)) {
|
||||||
@ -22,40 +27,72 @@ void wait_read()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void fill_chunk(volatile uint32_t * chunk, const uint32_t segment_index)
|
||||||
|
{
|
||||||
|
const uint32_t * audio_pcm = reinterpret_cast<const uint32_t *>(&_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<uint32_t *>(&_binary_start);
|
const uint32_t * binary = reinterpret_cast<uint32_t *>(&_binary_start);
|
||||||
const uint32_t binary_size = reinterpret_cast<uint32_t>(&_binary_size);
|
const uint32_t binary_size = reinterpret_cast<uint32_t>(&_binary_size);
|
||||||
|
|
||||||
wait(); aica.common.reg_2c00 = 1;
|
aica_wait_write(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1);
|
||||||
wait(); aica.common.reg_2880 = 0;
|
aica_wait_write(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0);
|
||||||
for (uint32_t i = 0; i < binary_size / 4; i++) {
|
for (uint32_t i = 0; i < binary_size / 4; i++) {
|
||||||
// copy
|
// copy
|
||||||
|
while (aica_wave_memory[i] != binary[i]) {
|
||||||
|
aica_wait_write();
|
||||||
aica_wave_memory[i] = binary[i];
|
aica_wave_memory[i] = binary[i];
|
||||||
if (i % 8 == 7) wait();
|
|
||||||
}
|
}
|
||||||
wait(); aica.common.reg_2c00 = 0;
|
}
|
||||||
|
|
||||||
serial::integer<uint32_t>(aica_wave_memory[0]);
|
chunk = reinterpret_cast<decltype (chunk)>(&aica_wave_memory[0x001ff000 / 4]);
|
||||||
|
|
||||||
|
serial::integer<uint32_t>(reinterpret_cast<uint32_t>(&(*chunk)[0][0]));
|
||||||
|
serial::integer<uint32_t>(reinterpret_cast<uint32_t>(&(*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);
|
||||||
|
|
||||||
wait(); aica.common.MSLC(0);
|
|
||||||
serial::string("mrwinh: ");
|
|
||||||
wait_read();
|
|
||||||
serial::integer<uint8_t>(aica.common.MRWINH());
|
|
||||||
while (1) {
|
while (1) {
|
||||||
wait_read();
|
aica_step(chunk_index, segment_index);
|
||||||
serial::string("sgc: ");
|
|
||||||
serial::integer<uint8_t>(aica.common.SGC(), ' ');
|
|
||||||
serial::string("; ca: ");
|
|
||||||
serial::integer<uint8_t>(aica.common.CA(), ' ');
|
|
||||||
serial::string("; eg: ");
|
|
||||||
serial::integer<uint8_t>(aica.common.EG(), ' ');
|
|
||||||
serial::string("; lp: ");
|
|
||||||
serial::integer<uint8_t>(aica.common.LP(), ' ');
|
|
||||||
serial::character('\n');
|
|
||||||
for (int i = 0; i < 10000000; i++) {
|
|
||||||
asm volatile ("nop");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1);
|
while (1);
|
||||||
|
@ -21,6 +21,9 @@ include base.mk
|
|||||||
channel.elf: LDSCRIPT = main.lds
|
channel.elf: LDSCRIPT = main.lds
|
||||||
channel.elf: start.o channel.o audio.pcm.o
|
channel.elf: start.o channel.o audio.pcm.o
|
||||||
|
|
||||||
|
sh4_interrupt.elf: LDSCRIPT = main.lds
|
||||||
|
sh4_interrupt.elf: start.o sh4_interrupt.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find -P \
|
find -P \
|
||||||
-regextype posix-egrep \
|
-regextype posix-egrep \
|
||||||
|
@ -22,7 +22,6 @@ void main()
|
|||||||
aica_sound.channel[0].KYONB(1);
|
aica_sound.channel[0].KYONB(1);
|
||||||
aica_sound.channel[0].LPCTL(1);
|
aica_sound.channel[0].LPCTL(1);
|
||||||
aica_sound.channel[0].PCMS(0);
|
aica_sound.channel[0].PCMS(0);
|
||||||
aica_sound.channel[0].SA(sine_addr);
|
|
||||||
aica_sound.channel[0].LSA(0);
|
aica_sound.channel[0].LSA(0);
|
||||||
aica_sound.channel[0].LEA(128);
|
aica_sound.channel[0].LEA(128);
|
||||||
aica_sound.channel[0].D2R(0x0);
|
aica_sound.channel[0].D2R(0x0);
|
||||||
@ -39,26 +38,38 @@ void main()
|
|||||||
aica_sound.channel[0].TL(0);
|
aica_sound.channel[0].TL(0);
|
||||||
aica_sound.channel[0].LPOFF(1);
|
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;
|
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[0] = 0x11223344;
|
||||||
dram[1] = sine_addr;
|
dram[1] = sine_addr;
|
||||||
constexpr uint32_t timer_a_interrupt = (1 << 6);
|
constexpr uint32_t timer_a_interrupt = (1 << 6);
|
||||||
aica_sound.common.scire = timer_a_interrupt;
|
aica_sound.common.scire = timer_a_interrupt;
|
||||||
|
uint32_t next_sa = sine_addr;
|
||||||
|
bool started = 0;
|
||||||
|
|
||||||
while (1) {
|
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.scire = timer_a_interrupt;
|
||||||
aica_sound.common.TIMA(255);
|
dram[1] = next_sa;
|
||||||
|
|
||||||
segment += 1;
|
segment += 1;
|
||||||
if (segment >= 3440) segment = 0;
|
if (segment >= 3440) segment = 0;
|
||||||
uint32_t sa = sine_addr + (128 * 2) * segment;
|
next_sa = sine_addr + (128 * 2) * segment;
|
||||||
dram[1] = sa;
|
|
||||||
aica_sound.channel[0].SA(sa);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
ram : ORIGIN = 0x00000000, LENGTH = 0x200000
|
ram : ORIGIN = 0x00000000, LENGTH = 0x1ff000
|
||||||
|
buffers : ORIGIN = 0x001ff000, LENGTH = 0x1000
|
||||||
}
|
}
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
@ -40,6 +41,14 @@ SECTIONS
|
|||||||
*(COMMON)
|
*(COMMON)
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
. = ORIGIN(buffers);
|
||||||
|
|
||||||
|
.buffers ALIGN(4) (NOLOAD) : SUBALIGN(4)
|
||||||
|
{
|
||||||
|
*(.buffers)
|
||||||
|
*(.buffers.*)
|
||||||
|
} > buffers
|
||||||
|
|
||||||
INCLUDE "../../debug.lds"
|
INCLUDE "../../debug.lds"
|
||||||
INCLUDE "arm.lds"
|
INCLUDE "arm.lds"
|
||||||
}
|
}
|
||||||
|
92
example/arm/sh4_interrupt.cpp
Normal file
92
example/arm/sh4_interrupt.cpp
Normal file
@ -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<volatile uint32_t*>(0x00800000);
|
||||||
|
for (uint32_t i = 0; i < (sizeof (struct aica_channel)) * 64 / 4; i++) {
|
||||||
|
slot[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile uint32_t * dsp = reinterpret_cast<volatile uint32_t*>(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<uint32_t>(&chunk[0][0]);
|
||||||
|
dram[1] = reinterpret_cast<uint32_t>(&chunk[1][0]);
|
||||||
|
|
||||||
|
uint32_t next_chunk = 0;
|
||||||
|
aica_sound.channel[0].SA(reinterpret_cast<const uint32_t>(&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<const uint32_t>(&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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -368,7 +368,16 @@ example/gdrom_iso9660.elf: $(START_OBJ) $(GDROM_ISO9660_OBJ)
|
|||||||
AICA_OBJ = \
|
AICA_OBJ = \
|
||||||
example/aica.o \
|
example/aica.o \
|
||||||
sh7091/serial.o \
|
sh7091/serial.o \
|
||||||
example/arm/channel.bin.o \
|
example/arm/channel.bin.o
|
||||||
|
|
||||||
example/aica.elf: LDSCRIPT = $(LIB)/alt.lds
|
example/aica.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||||
example/aica.elf: $(START_OBJ) $(AICA_OBJ)
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user