Загрузка данных


	/* 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;
		}
	}