diff --git a/components/retro-go/drivers/audio/buzzer.c b/components/retro-go/drivers/audio/buzzer.c index 164e4590..9627b88c 100644 --- a/components/retro-go/drivers/audio/buzzer.c +++ b/components/retro-go/drivers/audio/buzzer.c @@ -33,7 +33,7 @@ Note that there are some restrictions on how high the PWM frequency can be, and #include "rg_system.h" // include configuration from components/retro-go/targets/*/config.h -#ifdef RG_AUDIO_USE_BUZZER_PIN +#if RG_AUDIO_USE_BUZZER_PIN #include "rg_audio.h" #ifndef ESP_PLATFORM diff --git a/components/retro-go/drivers/audio/i2s.c b/components/retro-go/drivers/audio/i2s.c index 1b2f47f5..5f273e04 100644 --- a/components/retro-go/drivers/audio/i2s.c +++ b/components/retro-go/drivers/audio/i2s.c @@ -11,10 +11,21 @@ #include #include -#if RG_AUDIO_USE_INT_DAC -#include + +#ifdef RG_GPIO_SND_AMP_ENABLE_INVERT +#define MUTE_ENABLE 1 +#define MUTE_DISABLE 0 +#else +#define MUTE_ENABLE 0 +#define MUTE_DISABLE 1 #endif +// We can safely assume that no application will submit more than 640 audio frames per call to +// driver_submit (32000/50). Using a single large buffer risks blocking the call needlessly because +// some apps submit more than once per cycle or there could be occasional jitter (early submission). +#define DMA_BUFFER_COUNT 4 +#define DMA_BUFFER_LEN 180 + static struct { const char *last_error; int device; @@ -37,8 +48,8 @@ static bool driver_init(int device, int sample_rate) .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format = I2S_COMM_FORMAT_STAND_MSB, .intr_alloc_flags = 0, // ESP_INTR_FLAG_LEVEL1 - .dma_buf_count = 4, // Goal is to have ~800 samples over 2-8 buffers (3x270 or 5x180 are pretty good) - .dma_buf_len = 180, // The unit is stereo samples (4 bytes) (optimize for 533 usage) + .dma_buf_count = DMA_BUFFER_COUNT, + .dma_buf_len = DMA_BUFFER_LEN, }, 0, NULL); if (ret == ESP_OK) ret = i2s_set_dac_mode(RG_AUDIO_USE_INT_DAC); @@ -58,8 +69,8 @@ static bool driver_init(int device, int sample_rate) .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = 0, // ESP_INTR_FLAG_LEVEL1 - .dma_buf_count = 4, // Goal is to have ~800 samples over 2-8 buffers (3x270 or 5x180 are pretty good) - .dma_buf_len = 180, // The unit is stereo samples (4 bytes) (optimize for 533 usage) + .dma_buf_count = DMA_BUFFER_COUNT, + .dma_buf_len = DMA_BUFFER_LEN, #if CONFIG_IDF_TARGET_ESP32 .use_apll = true, // External DAC may care about accuracy #endif @@ -80,6 +91,11 @@ static bool driver_init(int device, int sample_rate) state.last_error = "This device does not support external DAC mode!"; #endif } + #ifdef RG_GPIO_SND_AMP_ENABLE + gpio_reset_pin(RG_GPIO_SND_AMP_ENABLE); + gpio_set_level(RG_GPIO_SND_AMP_ENABLE, MUTE_ENABLE); + gpio_set_direction(RG_GPIO_SND_AMP_ENABLE, GPIO_MODE_OUTPUT); + #endif return state.last_error == NULL; } @@ -94,11 +110,7 @@ static bool driver_deinit(void) if (state.device == 0) { #if RG_AUDIO_USE_INT_DAC - if (RG_AUDIO_USE_INT_DAC & I2S_DAC_CHANNEL_RIGHT_EN) - dac_output_disable(DAC_CHANNEL_1); - if (RG_AUDIO_USE_INT_DAC & I2S_DAC_CHANNEL_LEFT_EN) - dac_output_disable(DAC_CHANNEL_2); - dac_i2s_disable(); + i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); #endif } else if (state.device == 1) @@ -118,11 +130,9 @@ static bool driver_deinit(void) static bool driver_submit(const rg_audio_frame_t *frames, size_t count) { float volume = state.muted ? 0.f : (state.volume * 0.01f); - rg_audio_frame_t buffer[180]; - size_t written = 0; - size_t pos = 0; - bool use_internal_dac = state.device == 0; + rg_audio_frame_t buffer[DMA_BUFFER_LEN]; + size_t pos = 0; for (size_t i = 0; i < count; ++i) { @@ -131,15 +141,15 @@ static bool driver_submit(const rg_audio_frame_t *frames, size_t count) if (use_internal_dac) { - int sample = (left + right) >> 1; #if RG_AUDIO_USE_INT_DAC == 1 - left = sample + 0x8000; // the internal DAC expects unsigned data + left = ((left + right) >> 1) + 0x8000; // the internal DAC expects unsigned data right = 0; #elif RG_AUDIO_USE_INT_DAC == 2 - left = 0; - right = sample + 0x8000; // the internal DAC expects unsigned data + left = 0; + right = ((left + right) >> 1) + 0x8000; // the internal DAC expects unsigned data #elif RG_AUDIO_USE_INT_DAC == 3 // In two channel mode we use left and right as a differential mono output to increase resolution. + int sample = (left + right) >> 1; if (sample > 0x7F00) { left = 0x8000 + (sample - 0x7F00); @@ -168,6 +178,7 @@ static bool driver_submit(const rg_audio_frame_t *frames, size_t count) if (i == count - 1 || ++pos == RG_COUNT(buffer)) { + size_t written; if (i2s_write(I2S_NUM_0, (void *)buffer, pos * 4, &written, 1000) != ESP_OK) RG_LOGW("I2S Submission error! Written: %d/%d\n", written, pos * 4); pos = 0; @@ -179,16 +190,8 @@ static bool driver_submit(const rg_audio_frame_t *frames, size_t count) static bool driver_set_mute(bool mute) { i2s_zero_dma_buffer(I2S_NUM_0); - #if defined(RG_GPIO_SND_AMP_ENABLE) - gpio_set_direction(RG_GPIO_SND_AMP_ENABLE, GPIO_MODE_OUTPUT); - #if defined(RG_TARGET_BYTEBOI_REV1) - gpio_set_level(RG_GPIO_SND_AMP_ENABLE, mute); - #else - gpio_set_level(RG_GPIO_SND_AMP_ENABLE, !mute); - #endif - #elif defined(RG_TARGET_QTPY_GAMER) - rg_i2c_gpio_set_direction(AW_HEADPHONE_EN, 0); - rg_i2c_gpio_set_level(AW_HEADPHONE_EN, !mute); + #ifdef RG_GPIO_SND_AMP_ENABLE + gpio_set_level(RG_GPIO_SND_AMP_ENABLE, mute ? MUTE_ENABLE : MUTE_DISABLE); #endif state.muted = mute; return true; diff --git a/components/retro-go/targets/byteboi-rev1/config.h b/components/retro-go/targets/byteboi-rev1/config.h index 91c36569..ae43fb5b 100644 --- a/components/retro-go/targets/byteboi-rev1/config.h +++ b/components/retro-go/targets/byteboi-rev1/config.h @@ -102,3 +102,4 @@ // #define RG_GPIO_SND_I2S_WS GPIO_NUM_NC // #define RG_GPIO_SND_I2S_DATA GPIO_NUM_NC #define RG_GPIO_SND_AMP_ENABLE GPIO_NUM_13 +#define RG_GPIO_SND_AMP_ENABLE_INVERT // Uncomment if the mute = HIGH diff --git a/components/retro-go/targets/crokpocket/env.py b/components/retro-go/targets/crokpocket/env.py index 602e2bbf..e99d8611 100644 --- a/components/retro-go/targets/crokpocket/env.py +++ b/components/retro-go/targets/crokpocket/env.py @@ -6,4 +6,4 @@ IDF_TARGET = "esp32s3" # .fw file format, if supported by the device FW_FORMAT = "none" # Default apps to build when none is specified (comment to build all) -# DEFAULT_APPS = "launcher prboom-go" +DEFAULT_APPS = "launcher retro-core prboom-go gwenesis" diff --git a/components/retro-go/targets/retro-ruler-V1/env.py b/components/retro-go/targets/retro-ruler-V1/env.py index 3f93c2b8..c8ff5fa4 100644 --- a/components/retro-go/targets/retro-ruler-V1/env.py +++ b/components/retro-go/targets/retro-ruler-V1/env.py @@ -6,4 +6,4 @@ IDF_TARGET = "esp32" # .fw file format, if supported by the device FW_FORMAT = "none" # Default apps to build when none is specified (comment to build all) -# DEFAULT_APPS = "launcher prboom-go" +DEFAULT_APPS = "launcher retro-core prboom-go gwenesis"