From c4041799fc3c6e6cdcce6121ea2c121fd504a3b6 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 25 May 2021 15:01:42 +0200 Subject: Add sample playing prototype (not on UXN yet) --- src/common.h | 10 ++++-- src/main.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 8 deletions(-) diff --git a/src/common.h b/src/common.h index 5766565..048708b 100644 --- a/src/common.h +++ b/src/common.h @@ -14,6 +14,7 @@ WITH REGARD TO THIS SOFTWARE. #include "shorthand.h" +#define CPU_FREQUENCY (2 << 23) // // Memory sections. // @@ -585,10 +586,11 @@ int bios_div(int num, int denom); #define SOUND_ENABLE_NOISE_RIGHT (1 << 0xF) typedef enum { + SOUND_DSOUND = (0x0 << 0), SOUND_SQUARE1 = (0x1 << 0), SOUND_SQUARE2 = (0x1 << 1), - SOUND_WAVE = (0x1 << 2), - SOUND_NOISE = (0x1 << 3), + SOUND_WAVE = (0x1 << 2), + SOUND_NOISE = (0x1 << 3), } SoundChannel; u16 @@ -613,6 +615,10 @@ sound_volume(SoundChannel channels, u8 volume) { #define SOUND_DSOUND_TIMER_B (1 << 0xE) #define SOUND_DSOUND_RESET_B (1 << 0xF) +// Direct sound FIFO queues. +#define SOUND_FIFO_A ((u16*)(MEM_IO + 0xA0)) +#define SOUND_FIFO_B ((u16*)(MEM_IO + 0xA4)) + // Sound status bits. #define SOUND_ENABLE (1 << 0x7) diff --git a/src/main.c b/src/main.c index 7764278..0862ca5 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,7 @@ WITH REGARD TO THIS SOFTWARE. // // Config parameters. // + #ifndef TEXT_LAYER #define TEXT_LAYER ppu.fg #endif @@ -298,7 +299,8 @@ handle_input(Uxn *u) { } if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) { update_cursor(cursor_position - KEYBOARD_ROW_SIZE); - } else if (key_tap(KEY_DOWN) && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) { + } else if (key_tap(KEY_DOWN) + && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) { update_cursor(cursor_position + KEYBOARD_ROW_SIZE); } if (key_tap(KEY_B)) { @@ -342,6 +344,75 @@ static Uxn u; EWRAM_BSS static u8 umem[65536]; +#include "kick.c" + +typedef struct AudioChannel { + u32 *samples; + u32 n_samples; + u16 sampling_freq; + bool loop; + // TODO: u16 adsr; // attack, decay, sustain, release + // TODO: u8 pitch; // Bit 8 is the "loop" bit + // TODO: u8 volume; // VOL_LEFT | (VOL_RIGHT << 4) +} AudioChannel; + +typedef struct APU { + AudioChannel chan_0; + // u32 *samples_1; + // u32 *samples_2; + // u32 *samples_3; +} APU; + + +static APU apu = {0}; + +void +reset_sound(AudioChannel *chan) { + TIMER_CTRL_0 = 0; + TIMER_CTRL_1 = 0; + DMA_CTRL(1) = 0; + + // Set max volume, left-right sound, fifo reset and use timer 0 for + // DirectSound A. + SOUND_DSOUND_MASTER = SOUND_DSOUND_RATIO_A + | SOUND_DSOUND_LEFT_A + | SOUND_DSOUND_RIGHT_A + | SOUND_DSOUND_RESET_A; + + // Prepare DMA copy. + dma_transfer_copy(SOUND_FIFO_A, chan->samples, 1, 1, + DMA_CHUNK_32 | DMA_REFRESH | DMA_REPEAT | DMA_ENABLE); + + // Timer 1 used to stop playing samples. + u32 sample_duration = chan->n_samples; + TIMER_DATA_1 = 0xFFFF - sample_duration; + TIMER_CTRL_1 = TIMER_CTRL_IRQ + | TIMER_CTRL_ENABLE + | TIMER_CTRL_CASCADE; + + // Timer 0 used to stop sample playing. + TIMER_DATA_0 = 0xFFFF - CPU_FREQUENCY / chan->sampling_freq; + TIMER_CTRL_0 = TIMER_CTRL_ENABLE; +} + +void +irs_stop_sample(void) { + if (apu.chan_0.loop) { + reset_sound(&apu.chan_0); + } else { + TIMER_CTRL_0 = 0; + DMA_CTRL(1) = 0; + } +} + +void +init_sound(AudioChannel *chan) { + chan->samples = voiceraw; + chan->n_samples = LEN(voiceraw); + chan->sampling_freq = 44100; + chan->loop = true; +} + int main(void) { // Initialize filesystem. fs_init(); @@ -349,6 +420,7 @@ int main(void) { // Register interrupts. irq_init(); irs_set(IRQ_VBLANK, irs_stub); + irs_set(IRQ_TIMER_1, irs_stop_sample); // Initialize VM. memset(&u, 0, sizeof(u)); @@ -359,15 +431,39 @@ int main(void) { txt_init(1, TEXT_LAYER); txt_position(0,0); + txt_printf("VOICE LOADED: %lu\n", LEN(voiceraw)); + + // Enable sound. + SOUND_STATUS = SOUND_ENABLE; + + init_sound(&apu.chan_0); + reset_sound(&apu.chan_0); + // Main loop. - int frame_counter = 0; - evaluxn(&u, 0x0100); + // int frame_counter = 0; + // evaluxn(&u, 0x0100); + // u32 flip_cycles = 0; while(true) { bios_vblank_wait(); - handle_input(&u); - evaluxn(&u, mempeek16(devscreen->dat, 0)); + // profile_start(); + // handle_input(&u); + // u32 input_cycles = profile_stop(); + // profile_start(); + // evaluxn(&u, mempeek16(devscreen->dat, 0)); + // u32 eval_cycles = profile_stop(); + // txt_position(0, 8); + // txt_printf("INPUT: %lu \n", input_cycles); + // txt_printf("EVAL: %lu \n", eval_cycles); + // txt_printf("FLIP: %lu \n", flip_cycles); + // profile_start(); flipbuf(&ppu); - frame_counter++; + // flip_cycles = profile_stop(); + // frame_counter++; + poll_keys(); + if (key_tap(KEY_B)) { + txt_printf("TAP B\n"); + reset_sound(&apu.chan_0); + } } return 0; -- cgit v1.2.1