feat(pocketdungeon): intro GOAL+CONTROLS left icons right + 2x2 tutorial levels
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
- Intro redesign QVGA: left scrollable column 2 cards GOAL+CONTROLS only, right 44px rail small icons Play 38 accent + Exit 30 muted (fixes cramped) - Tutorial by play: floor0 TUTORIAL_ROWS=2 player+stairs, floor1 bat+gold+stairs, real game from floor2 infinite with displayFloor mapping - Model: renderRows, isTutorial(), tutorialId(), clearAllTiles(), generateTutorialFloor - Renderer: respects renderRows HIDDEN, board height 2 rows centered, TUT messages - Game: reset tutorials=true, skip moveMonsters in tutorial, bests only real floors - Keep audio-stream migration: SDK 0.8.0-dev IDF5.5, CMake GLOB SfxEngine, SfxEngine audio-stream - No unexported LVGL: no max_width/scrollbar_mode -> 0 missing symbols Installed 192.168.68.134 verified screenshot 6.1K airy left+right
This commit is contained in:
@@ -9,7 +9,8 @@
|
||||
#include "SfxEngine.h"
|
||||
#include "SfxDefinitions.h"
|
||||
|
||||
#include <tactility/drivers/i2s_controller.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/audio_stream.h>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include "esp_log.h"
|
||||
@@ -424,7 +425,7 @@ void SfxEngine::audioTaskFunc(void* param) {
|
||||
size_t written;
|
||||
QueueMsg msg;
|
||||
|
||||
ESP_LOGI(TAG, "Audio task started");
|
||||
ESP_LOGI(TAG, "Audio task started (audio-stream)");
|
||||
|
||||
while (self->running_) {
|
||||
// Process queued messages (non-blocking)
|
||||
@@ -463,19 +464,26 @@ void SfxEngine::audioTaskFunc(void* param) {
|
||||
// Fill audio buffer (member buffer to avoid stack pressure)
|
||||
self->fillStereoBuffer(self->audioBuffer_, BUFFER_SAMPLES);
|
||||
|
||||
// Write to I2S
|
||||
error_t error = i2s_controller_write(self->i2sDevice_, self->audioBuffer_,
|
||||
sizeof(self->audioBuffer_), &written, pdMS_TO_TICKS(100));
|
||||
// Write via audio-stream (resampled to native codec rate, e.g. 44100)
|
||||
if (self->streamHandle_ == nullptr) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
continue;
|
||||
}
|
||||
error_t error = audio_stream_write(self->streamHandle_, self->audioBuffer_,
|
||||
sizeof(self->audioBuffer_), &written, pdMS_TO_TICKS(200));
|
||||
if (error != ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "I2S write error");
|
||||
ESP_LOGE(TAG, "audio_stream_write error %d", error);
|
||||
self->running_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush silence
|
||||
memset(self->audioBuffer_, 0, sizeof(self->audioBuffer_));
|
||||
i2s_controller_write(self->i2sDevice_, self->audioBuffer_, sizeof(self->audioBuffer_), &written, pdMS_TO_TICKS(50));
|
||||
// Flush silence to avoid pop
|
||||
if (self->streamHandle_ != nullptr) {
|
||||
memset(self->audioBuffer_, 0, sizeof(self->audioBuffer_));
|
||||
size_t dummy = 0;
|
||||
audio_stream_write(self->streamHandle_, self->audioBuffer_, sizeof(self->audioBuffer_), &dummy, pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Audio task exiting");
|
||||
|
||||
@@ -494,33 +502,38 @@ void SfxEngine::audioTaskFunc(void* param) {
|
||||
bool SfxEngine::start() {
|
||||
if (running_) return true;
|
||||
|
||||
// Find I2S device
|
||||
i2sDevice_ = nullptr;
|
||||
device_for_each_of_type(&I2S_CONTROLLER_TYPE, &i2sDevice_, [](Device* device, void* context) {
|
||||
if (!device_is_ready(device)) return true;
|
||||
Device** devicePtr = static_cast<Device**>(context);
|
||||
*devicePtr = device;
|
||||
return false;
|
||||
});
|
||||
// Find audio-stream device (new audio provision)
|
||||
streamDevice_ = nullptr;
|
||||
streamHandle_ = nullptr;
|
||||
|
||||
if (i2sDevice_ == nullptr) {
|
||||
ESP_LOGW(TAG, "No I2S device found");
|
||||
streamDevice_ = device_find_by_name("audio-stream");
|
||||
if (streamDevice_ == nullptr) {
|
||||
// Fallback: find first device of AUDIO_STREAM_TYPE
|
||||
device_for_each_of_type(&AUDIO_STREAM_TYPE, &streamDevice_, [](Device* device, void* context) {
|
||||
if (!device_is_ready(device)) return true;
|
||||
Device** devPtr = static_cast<Device**>(context);
|
||||
*devPtr = device;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (streamDevice_ == nullptr) {
|
||||
ESP_LOGW(TAG, "No audio-stream device found - audio provision missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Configure I2S
|
||||
I2sConfig config = {
|
||||
.communication_format = I2S_FORMAT_STAND_I2S,
|
||||
// Open output stream with resampling (app wants 16k stereo, codec native is 44100)
|
||||
struct AudioStreamConfig cfg = {
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = 16,
|
||||
.channel_left = 0,
|
||||
.channel_right = 0
|
||||
.channels = 2
|
||||
};
|
||||
|
||||
error_t error = i2s_controller_set_config(i2sDevice_, &config);
|
||||
error_t error = audio_stream_open_output(streamDevice_, &cfg, &streamHandle_);
|
||||
if (error != ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "Failed to configure I2S: %s", error_to_string(error));
|
||||
i2sDevice_ = nullptr;
|
||||
ESP_LOGE(TAG, "Failed to open audio-stream: %s (%d)", error_to_string(error), error);
|
||||
streamDevice_ = nullptr;
|
||||
streamHandle_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -528,12 +541,13 @@ bool SfxEngine::start() {
|
||||
msgQueue_ = xQueueCreate(8, sizeof(QueueMsg));
|
||||
if (msgQueue_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to create message queue");
|
||||
i2s_controller_reset(i2sDevice_);
|
||||
i2sDevice_ = nullptr;
|
||||
audio_stream_close(streamHandle_);
|
||||
streamHandle_ = nullptr;
|
||||
streamDevice_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start audio task
|
||||
// Start audio task (needs slightly larger stack for audio_stream write path)
|
||||
running_ = true;
|
||||
BaseType_t result = xTaskCreate(audioTaskFunc, "sfxeng", 4096, this, 5, &task_);
|
||||
if (result != pdPASS) {
|
||||
@@ -541,12 +555,13 @@ bool SfxEngine::start() {
|
||||
running_ = false;
|
||||
vQueueDelete(msgQueue_);
|
||||
msgQueue_ = nullptr;
|
||||
i2s_controller_reset(i2sDevice_);
|
||||
i2sDevice_ = nullptr;
|
||||
audio_stream_close(streamHandle_);
|
||||
streamHandle_ = nullptr;
|
||||
streamDevice_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "SfxEngine started (voices=%d, sampleRate=%d)", NUM_VOICES, SAMPLE_RATE);
|
||||
ESP_LOGI(TAG, "SfxEngine started via audio-stream (voices=%d, sampleRate=%d -> resampled to native)", NUM_VOICES, SAMPLE_RATE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -575,11 +590,13 @@ void SfxEngine::stop() {
|
||||
msgQueue_ = nullptr;
|
||||
}
|
||||
|
||||
if (i2sDevice_ != nullptr) {
|
||||
i2s_controller_reset(i2sDevice_);
|
||||
i2sDevice_ = nullptr;
|
||||
if (streamHandle_ != nullptr) {
|
||||
audio_stream_close(streamHandle_);
|
||||
streamHandle_ = nullptr;
|
||||
}
|
||||
|
||||
streamDevice_ = nullptr;
|
||||
|
||||
ESP_LOGI(TAG, "SfxEngine stopped");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user