/* 4. Main cycle: Чтение микрофона (SGTL5000) + Вывод синуса (WM8960/TFA) */
while (streaming) {
void *rx_block = NULL;
void *tx_block = NULL;
size_t rx_size;
int ret;
/* === ЧАСТЬ 1: РАБОТА С МИКРОФОНОМ (SGTL5000) === */
/* Читаем блок данных от микрофона (16 кГц, 16 бит, стерео) */
ret = i2s_read(i2s_dev_rx, &rx_block, &rx_size);
if (ret < 0) {
printk("i2s_read (микрофон) failed: %d\n", ret);
break;
}
/* Проверяем валидность данных с микрофона в консоли (опционально) */
#if 0
int16_t *mas = (int16_t *)rx_block;
for (size_t i = 0; i < rx_size / sizeof(int16_t); i++) {
if (mas[i] != 0) {
printk("Mic data[%d] = 0x%X\n", i, mas[i]);
break; // Печатаем только первое ненулевое значение для лога
}
}
#endif
/* ОСВОБОЖДАЕМ БУФЕР МИКРОФОНА.
Это критически важно, чтобы не было ошибки i2s_read: -5! */
k_mem_slab_free(&mem_slab_rx, rx_block);
/* === ЧАСТЬ 2: РАБОТА С PLAYBACK (WM8960 / TFA) === */
/* Выделяем чистый блок памяти из пула передатчика */
ret = k_mem_slab_alloc(&mem_slab_tx, &tx_block, K_NO_WAIT);
if (ret < 0) {
printk("Не удалось выделить TX блок для синуса: %d\n", ret);
break;
}
/* Копируем кусок статического синуса в выделенный блок памяти.
Размер копируемых данных должен быть равен BLOCK_SIZE_TX */
static uint32_t sine_offset = 0;
// Защита на случай, если размер блока больше, чем весь массив синуса
uint32_t bytes_to_copy = BLOCK_SIZE_TX;
if (bytes_to_copy > __16kHz16bit_stereo_sine_pcm_len) {
bytes_to_copy = __16kHz16bit_stereo_sine_pcm_len;
}
// Копируем данные из синусоидального массива циклом по кругу
uint8_t *sine_source = (uint8_t *)__16kHz16bit_stereo_sine_pcm + sine_offset;
memcpy(tx_block, sine_source, bytes_to_copy);
// Сдвигаем указатель для следующей итерации цикла
sine_offset += bytes_to_copy;
if (sine_offset + BLOCK_SIZE_TX > __16kHz16bit_stereo_sine_pcm_len) {
sine_offset = 0; // Начинаем синусоиду сначала
}
/* Отправляем блок с синусом в динамики/наушники.
Функция i2s_write сама освободит tx_block, когда DMA отправит его в шину */
ret = i2s_write(i2s_dev_tx, tx_block, BLOCK_SIZE_TX);
if (ret < 0) {
printk("i2s_write (синус) failed: %d\n", ret);
k_mem_slab_free(&mem_slab_tx, tx_block); // Освобождаем при ошибке
break;
}
}