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()
|
||||
{
|
||||
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)) {
|
||||
|
@ -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<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_size = reinterpret_cast<uint32_t>(&_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<uint32_t>(aica_wave_memory[0]);
|
||||
|
||||
wait(); aica.common.MSLC(0);
|
||||
serial::string("mrwinh: ");
|
||||
wait_read();
|
||||
serial::integer<uint8_t>(aica.common.MRWINH());
|
||||
while (1) {
|
||||
wait_read();
|
||||
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 (aica_wave_memory[i] != binary[i]) {
|
||||
aica_wait_write();
|
||||
aica_wave_memory[i] = binary[i];
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
while (1) {
|
||||
aica_step(chunk_index, segment_index);
|
||||
}
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
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 = \
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user