sdk-hwV1.3/lichee/xr806/appos/project/example/i2s/main.c

248 lines
6.3 KiB
C
Executable File

/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "kernel/os/os.h"
#include "driver/chip/hal_snd_card.h"
#include "audio/pcm/audio_pcm.h"
#include "audio/manager/audio_manager.h"
#include "common/framework/platform_init.h"
//I2S Test config
#define I2S_TEST_SND_CARD SND_CARD_3
#define I2S_TEST_LOOP_BACK_EN 1
#define I2S_TEST_SAMPLE_RATE 16000 //[8000,16000,32000, 12000,24000,48000, 11025,22050,44100]
#define I2S_TEST_CHANNEL_NUMS 2 //[1,2]
#define I2S_TEST_RESOLUTION 32 //[8,12,16,20,24,28,32]
unsigned int tx_data_32bit[32] = {
0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678,
0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678,
0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678,
0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678,
};
static int i2s_open_example(uint8_t direction, uint32_t samplerate, uint8_t channels, uint8_t resolution)
{
uint32_t cmd_param[3];
if (direction != 0 && direction != 1) {
printf("Invalid direction %d\n", direction);
return HAL_INVALID;
}
if (channels < 1 || channels > 2) {
printf("Invalid channels %d\n", channels);
return HAL_INVALID;
}
switch (samplerate) {
case 8000:
case 16000:
case 32000:
case 12000:
case 24000:
case 48000:
case 11025:
case 22050:
case 44100:
break;
default:
printf("Invalid sample rate %u\n", samplerate);
return HAL_INVALID;
}
switch (resolution) {
case 8:
resolution = PCM_FORMAT_S8;
break;
case 12:
resolution = PCM_FORMAT_S12_LE;
break;
case 16:
resolution = PCM_FORMAT_S16_LE;
break;
case 20:
resolution = PCM_FORMAT_S20_LE;
break;
case 24:
resolution = PCM_FORMAT_S24_LE;
break;
case 28:
resolution = PCM_FORMAT_S28_LE;
break;
case 32:
resolution = PCM_FORMAT_S32_LE;
break;
default:
printf("Invalid resolution %d\n", resolution);
return HAL_INVALID;
}
struct pcm_config pcm_cfg;
pcm_cfg.rate = samplerate;
pcm_cfg.channels = channels;
pcm_cfg.format = resolution;
pcm_cfg.period_count = 1;
pcm_cfg.period_size = sizeof(tx_data_32bit)/(pcm_format_to_bits(pcm_cfg.format)/8*channels)/pcm_cfg.period_count;
cmd_param[0] = !!I2S_TEST_LOOP_BACK_EN<<24 | 0x0<<16 | 0x20<<8 | 0x2;
cmd_param[1] = (channels+1)/2*32;
cmd_param[2] = samplerate%1000 ? 22579200 : 24576000;
audio_maneger_ioctl(I2S_TEST_SND_CARD, PLATFORM_IOCTL_HW_CONFIG, cmd_param, 3);
cmd_param[0] = 256<<16 | 256;
audio_maneger_ioctl(I2S_TEST_SND_CARD, PLATFORM_IOCTL_SW_CONFIG, cmd_param, 1);
if (snd_pcm_open(I2S_TEST_SND_CARD, (Audio_Stream_Dir)direction, &pcm_cfg)) {
printf("snd pcm open Fail..\n");
return HAL_ERROR;
}
return HAL_OK;
}
static int i2s_close_example(uint8_t direction)
{
if (direction != 0 && direction != 1) {
printf("Invalid direction %d\n", direction);
return HAL_INVALID;
}
if (snd_pcm_close(I2S_TEST_SND_CARD, (Audio_Stream_Dir)direction)) {
printf("Snd pcm close Fail..\n");
return HAL_ERROR;
}
return HAL_OK;
}
static int i2s_pcm_write_example(uint8_t *buffer, uint32_t size)
{
uint8_t *buf;
uint32_t i;
if (!buffer || !size) {
printf("Invalid write buf|size params error!\n");
return HAL_INVALID;
}
buf = (uint8_t *)malloc(size);
if (buf == NULL) {
printf("Malloc I2S write buffer Fail\n");
return HAL_ERROR;
}
memcpy(buf, buffer, size);
if (snd_pcm_write(I2S_TEST_SND_CARD, buf, size) != size) {
free(buf);
printf("I2S write error!\n");
return HAL_ERROR;
}
printf("\nwrite buf:\n");
for (i = 0; i < size; i++) {
printf("0x%02x ", buf[i]);
}
printf("\n\n");
free(buf);
return HAL_OK;
}
static int i2s_pcm_read_example(uint32_t size)
{
uint8_t *buf;
uint32_t i;
if (!size) {
printf("Invalid read size params error!\n");
return HAL_INVALID;
}
buf = (uint8_t *)malloc(size);
if (buf == NULL) {
printf("Malloc I2S read buffer Fail\n");
return HAL_ERROR;
}
memset(buf, 0, size);
if (snd_pcm_read(I2S_TEST_SND_CARD, buf, size) != size) {
free(buf);
printf("I2S read error!\n");
return HAL_ERROR;
}
printf("\nread buf:\n");
for (i = 0; i < size; i++)
printf("0x%02x ", buf[i]);
printf("\n\n");
free(buf);
return HAL_OK;
}
static void i2s_test_example(void)
{
i2s_open_example(0, I2S_TEST_SAMPLE_RATE, I2S_TEST_CHANNEL_NUMS, I2S_TEST_RESOLUTION);
i2s_open_example(1, I2S_TEST_SAMPLE_RATE, I2S_TEST_CHANNEL_NUMS, I2S_TEST_RESOLUTION);
i2s_pcm_write_example((uint8_t *)&tx_data_32bit, sizeof(tx_data_32bit));
i2s_pcm_read_example(sizeof(tx_data_32bit));
i2s_close_example(0);
i2s_close_example(1);
}
int main(void)
{
platform_init();
printf("\n\n/*** i2s demo start ***/\n");
i2s_test_example();
printf("\n\n/*** i2c demo end ***/\n");
}