sync
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
CONFIG_NRFX_POWER=y
|
CONFIG_NRFX_POWER=y
|
||||||
|
CONFIG_BT=n
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
status-led = &led2;
|
status-led = &led2;
|
||||||
buzzer-button = &button0;
|
buzzer-button = &button0;
|
||||||
audio-i2s = &i2s0;
|
audio-i2s = &i2s0;
|
||||||
|
audio-amp-en = &audio_amp_en;
|
||||||
usb-uart = &cdc_acm_uart0;
|
usb-uart = &cdc_acm_uart0;
|
||||||
qspi-flash = &mx25r64;
|
qspi-flash = &mx25r64;
|
||||||
};
|
};
|
||||||
@@ -17,6 +18,14 @@
|
|||||||
zephyr,user {
|
zephyr,user {
|
||||||
usb-detect-gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
usb-detect-gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
amp {
|
||||||
|
compatible = "gpio-leds";
|
||||||
|
audio_amp_en: audio_amp_en {
|
||||||
|
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
|
||||||
|
label = "Amplifier Shudown Pin";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&usbd {
|
&usbd {
|
||||||
@@ -53,3 +62,16 @@
|
|||||||
pinctrl-1 = <&i2s0_sleep>;
|
pinctrl-1 = <&i2s0_sleep>;
|
||||||
pinctrl-names = "default", "sleep";
|
pinctrl-names = "default", "sleep";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// &uart0 { status = "disabled"; };
|
||||||
|
&i2c0 { status = "disabled"; };
|
||||||
|
&spi1 { status = "disabled"; };
|
||||||
|
&spi3 { status = "disabled"; };
|
||||||
|
&adc { status = "disabled"; };
|
||||||
|
&nfct { status = "disabled"; };
|
||||||
|
&temp { status = "disabled"; };
|
||||||
|
&pwm0 { status = "disabled"; };
|
||||||
|
&radio { status = "disabled"; };
|
||||||
|
&ieee802154 { status = "disabled"; };
|
||||||
|
&bt_hci_sdc { status = "disabled"; };
|
||||||
|
&cryptocell { status = "disabled"; };
|
||||||
@@ -42,5 +42,10 @@ CONFIG_NRFX_I2S=y
|
|||||||
|
|
||||||
# --- Random & HW Info (für Audio-File-Auswahl) ---
|
# --- Random & HW Info (für Audio-File-Auswahl) ---
|
||||||
CONFIG_HWINFO=y
|
CONFIG_HWINFO=y
|
||||||
CONFIG_ENTROPY_GENERATOR=y
|
|
||||||
CONFIG_CRC=y
|
CONFIG_CRC=y
|
||||||
|
|
||||||
|
# --- Unbenutze Features ---
|
||||||
|
CONFIG_ADC=n
|
||||||
|
CONFIG_I2C=n
|
||||||
|
CONFIG_SPI=n
|
||||||
|
CONFIG_PWM=n
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/drivers/i2s.h>
|
#include <zephyr/drivers/i2s.h>
|
||||||
#include <zephyr/pm/device.h>
|
#include <zephyr/pm/device.h>
|
||||||
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <audio.h>
|
#include <audio.h>
|
||||||
@@ -29,13 +30,42 @@ K_SEM_DEFINE(audio_ready_sem, 0, 1);
|
|||||||
#error "Audio I2S alias not defined in devicetree"
|
#error "Audio I2S alias not defined in devicetree"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_AMP_ENABLE_NODE DT_ALIAS(audio_amp_en)
|
||||||
|
#if !DT_NODE_EXISTS(AUDIO_AMP_ENABLE_NODE)
|
||||||
|
#error "Audio Amplifier Enable alias not defined in devicetree"
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct device *const i2s_dev = DEVICE_DT_GET(I2S_NODE);
|
static const struct device *const i2s_dev = DEVICE_DT_GET(I2S_NODE);
|
||||||
|
static const struct gpio_dt_spec amp_en_dev = GPIO_DT_SPEC_GET(AUDIO_AMP_ENABLE_NODE, gpios);
|
||||||
|
|
||||||
|
|
||||||
static volatile bool abort_playback = false;
|
static volatile bool abort_playback = false;
|
||||||
static char next_random_filename[64] = {0};
|
static char next_random_filename[64] = {0};
|
||||||
|
|
||||||
static uint32_t audio_file_count = 0;
|
static uint32_t audio_file_count = 0;
|
||||||
static char cached_404_path[] = "/lfs/sys/404";
|
static char cached_404_path[] = "/lfs/sys/404";
|
||||||
|
|
||||||
|
void i2s_suspend(void)
|
||||||
|
{
|
||||||
|
LOG_DBG("Suspending I2S interface for power saving");
|
||||||
|
i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP);
|
||||||
|
|
||||||
|
/* Nutzt jetzt die korrekte Spezifikation */
|
||||||
|
gpio_pin_set_dt(&_en_dev, 0);
|
||||||
|
|
||||||
|
pm_device_action_run(i2s_dev, PM_DEVICE_ACTION_SUSPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2s_resume(void)
|
||||||
|
{
|
||||||
|
LOG_DBG("Resuming I2S interface");
|
||||||
|
|
||||||
|
/* Zuerst Pin auf High, dann Hardware wecken */
|
||||||
|
gpio_pin_set_dt(&_en_dev, 1);
|
||||||
|
|
||||||
|
pm_device_action_run(i2s_dev, PM_DEVICE_ACTION_RESUME);
|
||||||
|
}
|
||||||
|
|
||||||
void audio_refresh_file_count(void)
|
void audio_refresh_file_count(void)
|
||||||
{
|
{
|
||||||
struct fs_dir_t dirp;
|
struct fs_dir_t dirp;
|
||||||
@@ -142,6 +172,7 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
|
|||||||
{
|
{
|
||||||
LOG_DBG("Audio thread started");
|
LOG_DBG("Audio thread started");
|
||||||
k_sem_take(&audio_ready_sem, K_FOREVER);
|
k_sem_take(&audio_ready_sem, K_FOREVER);
|
||||||
|
i2s_suspend();
|
||||||
|
|
||||||
/* Ersten zufälligen Dateinamen beim Booten vorab cachen */
|
/* Ersten zufälligen Dateinamen beim Booten vorab cachen */
|
||||||
get_random_file(next_random_filename, sizeof(next_random_filename));
|
get_random_file(next_random_filename, sizeof(next_random_filename));
|
||||||
@@ -152,9 +183,8 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
|
|||||||
{
|
{
|
||||||
if (k_msgq_get(&audio_play_msgq, &filename, K_FOREVER) == 0)
|
if (k_msgq_get(&audio_play_msgq, &filename, K_FOREVER) == 0)
|
||||||
{
|
{
|
||||||
fs_pm_flash_resume();
|
|
||||||
|
|
||||||
abort_playback = false;
|
abort_playback = false;
|
||||||
|
i2s_resume();
|
||||||
|
|
||||||
/* 2. Datei bestimmen (aus Cache oder synchron als Fallback) */
|
/* 2. Datei bestimmen (aus Cache oder synchron als Fallback) */
|
||||||
if (filename[0] == '\0')
|
if (filename[0] == '\0')
|
||||||
@@ -178,7 +208,7 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
|
|||||||
|
|
||||||
struct fs_file_t file;
|
struct fs_file_t file;
|
||||||
fs_file_t_init(&file);
|
fs_file_t_init(&file);
|
||||||
if (fs_open(&file, filename, FS_O_READ) < 0)
|
if (fs_pm_open(&file, filename, FS_O_READ) < 0)
|
||||||
{
|
{
|
||||||
LOG_ERR("Failed to open %s", filename);
|
LOG_ERR("Failed to open %s", filename);
|
||||||
continue;
|
continue;
|
||||||
@@ -284,10 +314,10 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_close(&file);
|
fs_pm_close(&file);
|
||||||
fs_pm_flash_suspend();
|
|
||||||
if (k_msgq_num_used_get(&audio_play_msgq) == 0)
|
if (k_msgq_num_used_get(&audio_play_msgq) == 0)
|
||||||
{
|
{
|
||||||
|
i2s_suspend();
|
||||||
io_status(false);
|
io_status(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,6 +355,19 @@ int audio_init(void)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (!gpio_is_ready_dt(&_en_dev)) {
|
||||||
|
LOG_DBG("Amplifier enable GPIO device not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_pin_configure_dt(&_en_dev, GPIO_OUTPUT_ACTIVE);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to configure amplifier enable GPIO: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_configure_dt(&_en_dev, 0);
|
||||||
|
|
||||||
audio_refresh_file_count();
|
audio_refresh_file_count();
|
||||||
LOG_INF("Audio initialized: %u bits, %u.%03u kHz", config.word_size, config.frame_clk_freq / 1000, config.frame_clk_freq % 1000);
|
LOG_INF("Audio initialized: %u bits, %u.%03u kHz", config.word_size, config.frame_clk_freq / 1000, config.frame_clk_freq % 1000);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -79,16 +79,19 @@ int fs_pm_flash_resume(void)
|
|||||||
|
|
||||||
int fs_pm_open(struct fs_file_t *file, const char *path, fs_mode_t mode)
|
int fs_pm_open(struct fs_file_t *file, const char *path, fs_mode_t mode)
|
||||||
{
|
{
|
||||||
|
LOG_DBG("PM Opening file '%s' with mode 0x%02x", path, mode);
|
||||||
|
fs_pm_flash_resume();
|
||||||
int rc = fs_open(file, path, mode);
|
int rc = fs_open(file, path, mode);
|
||||||
if (rc == 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
fs_pm_flash_resume();
|
fs_pm_flash_suspend();
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_pm_close(struct fs_file_t *file)
|
int fs_pm_close(struct fs_file_t *file)
|
||||||
{
|
{
|
||||||
|
LOG_DBG("PM Closing file");
|
||||||
int rc = fs_close(file);
|
int rc = fs_close(file);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
{
|
{
|
||||||
@@ -99,16 +102,19 @@ int fs_pm_close(struct fs_file_t *file)
|
|||||||
|
|
||||||
int fs_pm_opendir(struct fs_dir_t *dirp, const char *path)
|
int fs_pm_opendir(struct fs_dir_t *dirp, const char *path)
|
||||||
{
|
{
|
||||||
|
LOG_DBG("PM Opening directory '%s'", path);
|
||||||
|
fs_pm_flash_resume();
|
||||||
int rc = fs_opendir(dirp, path);
|
int rc = fs_opendir(dirp, path);
|
||||||
if (rc == 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
fs_pm_flash_resume();
|
fs_pm_flash_suspend();
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_pm_closedir(struct fs_dir_t *dirp)
|
int fs_pm_closedir(struct fs_dir_t *dirp)
|
||||||
{
|
{
|
||||||
|
LOG_DBG("PM Closing directory");
|
||||||
int rc = fs_closedir(dirp);
|
int rc = fs_closedir(dirp);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
{
|
{
|
||||||
@@ -116,3 +122,24 @@ int fs_pm_closedir(struct fs_dir_t *dirp)
|
|||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fs_pm_unlink(const char *path)
|
||||||
|
{
|
||||||
|
LOG_DBG("PM Unlinking file '%s'", path);
|
||||||
|
fs_pm_flash_resume();
|
||||||
|
int rc = fs_unlink(path);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
fs_pm_flash_suspend();
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_pm_statvfs(const char *path, struct fs_statvfs *stat)
|
||||||
|
{
|
||||||
|
LOG_DBG("PM Getting filesystem stats for '%s'", path);
|
||||||
|
fs_pm_flash_resume();
|
||||||
|
int rc = fs_statvfs(path, stat);
|
||||||
|
fs_pm_flash_suspend();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@@ -18,9 +18,54 @@ int fs_pm_flash_suspend(void);
|
|||||||
*/
|
*/
|
||||||
int fs_pm_flash_resume(void);
|
int fs_pm_flash_resume(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper around fs_open that handles power management for the flash
|
||||||
|
* Resumes the flash before opening and suspends it if opening fails
|
||||||
|
* @param file Pointer to fs_file_t structure to be initialized
|
||||||
|
* @param path Path to the file to open
|
||||||
|
* @param mode Open flags (e.g. FS_O_READ, FS_O_WRITE)
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
int fs_pm_open(struct fs_file_t *file, const char *path, fs_mode_t mode);
|
int fs_pm_open(struct fs_file_t *file, const char *path, fs_mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper around fs_close that handles power management for the flash
|
||||||
|
* Resumes the flash after closing and suspends it if closing fails
|
||||||
|
* @param file Pointer to fs_file_t structure to be closed
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
int fs_pm_close(struct fs_file_t *file);
|
int fs_pm_close(struct fs_file_t *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper around fs_opendir that handles power management for the flash
|
||||||
|
* Resumes the flash before opening and suspends it if opening fails
|
||||||
|
* @param dirp Pointer to fs_dir_t structure to be initialized
|
||||||
|
* @param path Path to the directory to open
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
int fs_pm_opendir(struct fs_dir_t *dirp, const char *path);
|
int fs_pm_opendir(struct fs_dir_t *dirp, const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper around fs_closedir that handles power management for the flash
|
||||||
|
* Resumes the flash after closing and suspends it if closing fails
|
||||||
|
* @param dirp Pointer to fs_dir_t structure to be closed
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
int fs_pm_closedir(struct fs_dir_t *dirp);
|
int fs_pm_closedir(struct fs_dir_t *dirp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unlinks (deletes) a file, ensuring the flash is active during the operation
|
||||||
|
* @param path Path to the file to unlink
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
|
int fs_pm_unlink(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper around fs_statvfs that handles power management for the flash
|
||||||
|
* Resumes the flash before getting stats and suspends it afterwards
|
||||||
|
* @param path Path to the filesystem to get stats for
|
||||||
|
* @param stat Pointer to fs_statvfs structure to be filled with stats
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
|
int fs_pm_statvfs(const char *path, struct fs_statvfs *stat);
|
||||||
#endif // FS_H
|
#endif // FS_H
|
||||||
@@ -66,7 +66,7 @@ int send_info()
|
|||||||
{
|
{
|
||||||
char info[112];
|
char info[112];
|
||||||
struct fs_statvfs stat;
|
struct fs_statvfs stat;
|
||||||
int rc = fs_statvfs("/lfs", &stat);
|
int rc = fs_pm_statvfs("/lfs", &stat);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
LOG_ERR("Failed to get filesystem stats: %d", rc);
|
LOG_ERR("Failed to get filesystem stats: %d", rc);
|
||||||
@@ -87,7 +87,7 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
|
|||||||
size_t accumulated = 0;
|
size_t accumulated = 0;
|
||||||
|
|
||||||
fs_file_t_init(&file);
|
fs_file_t_init(&file);
|
||||||
fs_unlink(filename);
|
fs_pm_unlink(filename);
|
||||||
LOG_DBG("Opening file '%s' for writing (expected size: %zd bytes, expected CRC32: 0x%08x)", filename, filesize, expected_crc32);
|
LOG_DBG("Opening file '%s' for writing (expected size: %zd bytes, expected CRC32: 0x%08x)", filename, filesize, expected_crc32);
|
||||||
rc = fs_pm_open(&file, filename, FS_O_CREATE | FS_O_WRITE);
|
rc = fs_pm_open(&file, filename, FS_O_CREATE | FS_O_WRITE);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user