406 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			406 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /****************************************************************************
 | |||
|  |  * | |||
|  |  * Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. | |||
|  |  * | |||
|  |  * This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT | |||
|  |  * be copied by any method or incorporated into another program without | |||
|  |  * the express written consent of Aerospace C.Power. This Information or any portion | |||
|  |  * thereof remains the property of Aerospace C.Power. The Information contained herein | |||
|  |  * is believed to be accurate and Aerospace C.Power assumes no responsibility or | |||
|  |  * liability for its use in any way and conveys no license or title under | |||
|  |  * any patent or copyright and makes no representation or warranty that this | |||
|  |  * Information is free from patent or copyright infringement. | |||
|  |  * | |||
|  |  * ****************************************************************************/ | |||
|  | 
 | |||
|  |  /* os shim includes */ | |||
|  | #include "os_types.h"
 | |||
|  | #include "os_task.h"
 | |||
|  | #include "os_utils.h"
 | |||
|  | 
 | |||
|  | /* common includes */ | |||
|  | #include "iot_io.h"
 | |||
|  | #include "iot_bitops.h"
 | |||
|  | #include "iot_pkt.h"
 | |||
|  | #include "iot_ipc.h"
 | |||
|  | #include "iot_plc_lib.h"
 | |||
|  | #include "iot_dbglog_api.h"
 | |||
|  | #include "iot_config.h"
 | |||
|  | #include "iot_errno_api.h"
 | |||
|  | 
 | |||
|  | /* driver includes */ | |||
|  | #include "iot_clock.h"
 | |||
|  | #include "iot_uart.h"
 | |||
|  | #include "iot_led.h"
 | |||
|  | #include "iot_gpio_api.h"
 | |||
|  | 
 | |||
|  | /* cli includes */ | |||
|  | #include "iot_cli.h"
 | |||
|  | #include "iot_uart_h.h"
 | |||
|  | 
 | |||
|  | /* debug includes*/ | |||
|  | #include "dbg_io.h"
 | |||
|  | 
 | |||
|  | #include "gpio.h"
 | |||
|  | 
 | |||
|  | #include "hw_reg_api.h"
 | |||
|  | 
 | |||
|  | #include "gpio_mtx_reg.h"
 | |||
|  | #include "pin_rf.h"
 | |||
|  | #include "apb.h"
 | |||
|  | #include "gpio_mtx.h"
 | |||
|  | //#include "gpio_reg.h"
 | |||
|  | 
 | |||
|  | #include "i2s_reg.h"
 | |||
|  | #include "apb_dma.h"
 | |||
|  | #include "dma_hw.h"
 | |||
|  | #include "i2s.h"
 | |||
|  | #include "dma_i2s.h"
 | |||
|  | #include "iot_share_task.h"
 | |||
|  | 
 | |||
|  | #include "wav.h"
 | |||
|  | #include "d16.h"
 | |||
|  | #include "s16.h"
 | |||
|  | 
 | |||
|  | #define USE_SINE_TONE 0
 | |||
|  | char pcm_data[2]={0}; | |||
|  | extern int platform_init(); | |||
|  | 
 | |||
|  | #if USE_SINE_TONE
 | |||
|  | static short sine_table[48] = { | |||
|  |   0x0000, 0x10b4, 0x2120, 0x30fb, 0x3fff, 0x4dea, 0x5a81, 0x658b, | |||
|  |   0x6ed8, 0x763f, 0x7ba1, 0x7ee5, 0x7ffd, 0x7ee5, 0x7ba1, 0x76ef, | |||
|  |   0x6ed8, 0x658b, 0x5a81, 0x4dea, 0x3fff, 0x30fb, 0x2120, 0x10b4, | |||
|  |   0x0000, 0xef4c, 0xdee0, 0xcf06, 0xc002, 0xb216, 0xa57f, 0x9a75, | |||
|  |   0x9128, 0x89c1, 0x845f, 0x811b, 0x8002, 0x811b, 0x845f, 0x89c1, | |||
|  |   0x9128, 0x9a76, 0xa57f, 0xb216, 0xc002, 0xcf06, 0xdee0, 0xef4c | |||
|  | }; | |||
|  | 
 | |||
|  | static void sine_tone_fill( unsigned char *buf, int len) | |||
|  | { | |||
|  |     static int i = 0; | |||
|  |     short *p; | |||
|  | 
 | |||
|  |     IOT_ASSERT( len > 0); | |||
|  |     IOT_ASSERT( ( len & 3) == 0); | |||
|  | 
 | |||
|  |     p = ( short *)buf; | |||
|  |     while( len > 0) | |||
|  |     { | |||
|  |         p[0] = p[1] = sine_table[i]; | |||
|  |         p += 2; | |||
|  | 
 | |||
|  |         i = ( i + 1) % 48; | |||
|  |         len -= 4; | |||
|  |     } | |||
|  | } | |||
|  | #endif
 | |||
|  | 
 | |||
|  | #define BUF_SIZE 640
 | |||
|  | os_task_h test_init_handle; | |||
|  | #define MAX_BUF_LEN         3840
 | |||
|  | #define SAMPLE_RATE         600000
 | |||
|  | 
 | |||
|  | 
 | |||
|  | unsigned char buf[2][BUF_SIZE]; | |||
|  | desc_t descLs[2]; | |||
|  | 
 | |||
|  | desc_t *pdesc_pool; | |||
|  | 
 | |||
|  | void i2s_test_i2s_func(); | |||
|  | 
 | |||
|  | void i2s_dma__handler(int vector, int status) | |||
|  | { | |||
|  |     desc_t *pdesc1, *pdesc2; | |||
|  | 
 | |||
|  |     // Recycle out descroptors
 | |||
|  |     if(status&DMA_INT_OUT_DONE) | |||
|  |     { | |||
|  |         pdesc1 = NULL; | |||
|  |         //i2s_tx_stop();
 | |||
|  |         if(pdesc1) | |||
|  |         { | |||
|  |             if(pdesc_pool) | |||
|  |             { | |||
|  |                 pdesc2 = pdesc_pool; | |||
|  |                 while(pdesc2->n_ptr) | |||
|  |                 { | |||
|  |                     pdesc2 = pdesc2->n_ptr; | |||
|  |                 } | |||
|  |                 pdesc2->n_ptr = pdesc1; | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 pdesc_pool = pdesc1; | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     // Send bytes that we recieved, and add Recycled descriptors on the list tail
 | |||
|  |     if(status&DMA_INT_IN_DONE) | |||
|  |     { | |||
|  |         buf[1][0x12] = 0xaa; | |||
|  |         DMA_MAKE_DESC(&descLs[1], buf[1], BUF_SIZE, 0, 0, 0, 0, DESC_OWNER_DMA); | |||
|  | 
 | |||
|  |         dma_hw_start_recieve(DMA_DEV_I2S, &descLs[1]); | |||
|  |         /*
 | |||
|  |         pdesc1 = NULL; | |||
|  |         if(pdesc1) | |||
|  |         { | |||
|  |             pdesc2 = pdesc1; | |||
|  |             while(pdesc2) | |||
|  |             { | |||
|  |                 DMA_MAKE_DESC(pdesc2, 0, BUF_SIZE, pdesc2->length, 0, 0, 0, DESC_OWNER_DMA); | |||
|  |                 pdesc2 = pdesc2->n_ptr; | |||
|  |             } | |||
|  |             dma_hw_start_send(DMA_DEV_I2S, pdesc1); | |||
|  |         } | |||
|  |         if(pdesc_pool) | |||
|  |         { | |||
|  |             pdesc1 = pdesc_pool; | |||
|  | 
 | |||
|  |             while(pdesc1) | |||
|  |             { | |||
|  |                 DMA_MAKE_DESC(pdesc1, 0, BUF_SIZE, 0, 0, 0, 0, DESC_OWNER_DMA); | |||
|  |                 pdesc1 = pdesc1->n_ptr; | |||
|  |             } | |||
|  |             dma_hw_start_recieve(DMA_DEV_I2S, pdesc1); | |||
|  |             pdesc_pool = NULL; | |||
|  |         } | |||
|  |         */ | |||
|  |     } | |||
|  | 
 | |||
|  |     if(status&DMA_INT_ERROR_DEFAULT) | |||
|  |     { | |||
|  |         // TODO: Error handle.
 | |||
|  |     } | |||
|  | 
 | |||
|  |     return ; | |||
|  | } | |||
|  | 
 | |||
|  | void i2s_dma_config(void) | |||
|  | { | |||
|  |     int cnt=0; | |||
|  | 
 | |||
|  |     dma_hw_open(DMA_DEV_I2S, (dma_int_handler)i2s_dma__handler, NULL); | |||
|  | 
 | |||
|  |     for(cnt=0; cnt<BUF_SIZE; ) | |||
|  |     { | |||
|  |         buf[0][cnt++] = 0xaa; | |||
|  |         buf[0][cnt++] = 0x55; | |||
|  |         buf[0][cnt++] = 0x80; | |||
|  |         buf[0][cnt++] = 0x00; | |||
|  |     } | |||
|  | #ifndef I2S_PDM_MODE_TEST
 | |||
|  |     DMA_MAKE_DESC(&descLs[0], &pcm_data[0], BUF_SIZE, BUF_SIZE, 0, 0, 0, DESC_OWNER_DMA); | |||
|  | #else
 | |||
|  |     DMA_MAKE_DESC(&descLs[0], &pcm_data[0], BUF_SIZE, BUF_SIZE, 0, 0, 0, DESC_OWNER_DMA); | |||
|  | #endif
 | |||
|  |     buf[1][0x12] = 0xaa; | |||
|  |     DMA_MAKE_DESC(&descLs[1], buf[1], BUF_SIZE, 0, 0, 0, 0, DESC_OWNER_DMA); | |||
|  | 
 | |||
|  |     dma_hw_start_recieve(DMA_DEV_I2S, &descLs[1]); | |||
|  |     //dma_hw_start_send(DMA_DEV_I2S, &descLs[0]);
 | |||
|  | } | |||
|  | 
 | |||
|  | uint16_t test_data[MAX_BUF_LEN/2] = {0}; | |||
|  | 
 | |||
|  | uint32_t g_recv_cnt = 0; | |||
|  | uint32_t g_send_cnt = 0; | |||
|  | uint32_t g_recv_total_cnt = 0; | |||
|  | uint32_t iot_dtest_dma_recv(unsigned char port, uint8_t *buf, uint32_t len) | |||
|  | { | |||
|  |     static uint32_t cnt=0; | |||
|  |     if((cnt++ % 1000) == 999) | |||
|  |     { | |||
|  |       int i; | |||
|  |       for (i=0;i<500;i++) | |||
|  |         iot_printf("%02x",buf[i]); | |||
|  |     } | |||
|  | 
 | |||
|  |     if(os_mem_cmp(&test_data[0], buf, len)) | |||
|  |     { | |||
|  | 
 | |||
|  |     }else{ | |||
|  |       g_recv_cnt++; | |||
|  |     } | |||
|  |     os_mem_set((uint8_t *)buf, 0, len); | |||
|  | 
 | |||
|  |     g_recv_total_cnt++; | |||
|  | 
 | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | uint32_t iot_dtest_dma_send(unsigned char port, uint8_t *buf, uint32_t len, uint8_t seq) | |||
|  | { | |||
|  |     static uint32_t cnt=0; | |||
|  | 
 | |||
|  |     if ((cnt++ % 1000) == 0) | |||
|  |     { | |||
|  |         g_recv_total_cnt=g_recv_cnt=0; | |||
|  |     } | |||
|  |     if(seq!=0) | |||
|  |     { | |||
|  |         iot_printf("iis dma hw process too FAST!WILL NOT SYNC!!!!!!!!! seq=%x \r\n",seq); | |||
|  |     } | |||
|  |     g_send_cnt++; | |||
|  | 
 | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | int rx_start=0; | |||
|  | 
 | |||
|  | #define BYTES_PER_SEC       ( SAMPLE_RATE * 4) // dual 16bit by default
 | |||
|  | void i2s_test_i2s_func() | |||
|  | { | |||
|  |     unsigned int t0, t; | |||
|  |     uint32_t tx_bytes; | |||
|  |     uint8_t ret; | |||
|  | 
 | |||
|  |     i2s_config_t i2s_cfg = {0}; | |||
|  |     i2s_cfg.clk = SAMPLE_RATE;  //in FPGA 16M i2s module clk, > 126K ws clk is valid
 | |||
|  |     i2s_cfg.type = I2S_TYPE_MSTR_TX;//I2S_TYPE_MSTR_TX;
 | |||
|  |     i2s_cfg.bit_mode = I2S_BITS_16BIT; | |||
|  |     i2s_cfg.msb_right = I2S_MSB_RIGHT_BIT0;//1
 | |||
|  |     i2s_cfg.port = I2S_0; | |||
|  | 
 | |||
|  |     i2s_cfg.tx_cfg.data_fmt = I2S_DATA_FMT_DUAL_BIT16; | |||
|  |     i2s_cfg.tx_cfg.chl_sel = I2S_CHL_SEL_DUAL; | |||
|  |     i2s_cfg.tx_cfg.msb_shift = I2S_SHIFT_PHILIPS_DIS; | |||
|  |     i2s_cfg.tx_cfg.tx_desc_num = 20; | |||
|  |     i2s_cfg.tx_cfg.send = iot_dtest_dma_send; | |||
|  | 
 | |||
|  |     i2s_config_t i2s_cfg_rx = {0}; | |||
|  |     i2s_cfg_rx.clk = SAMPLE_RATE;   //in FPGA 16M i2s module clk, > 126K ws clk is valid
 | |||
|  |     i2s_cfg_rx.type = I2S_TYPE_SLAV_RX; //I2S_TYPE_SLAV_RX;
 | |||
|  |     i2s_cfg_rx.bit_mode = I2S_BITS_16BIT; | |||
|  |     i2s_cfg_rx.msb_right = I2S_MSB_RIGHT_BIT0;//1
 | |||
|  |     i2s_cfg_rx.port = I2S_1; | |||
|  | 
 | |||
|  |     i2s_cfg_rx.rx_cfg.data_fmt = I2S_DATA_FMT_DUAL_BIT16; | |||
|  |     i2s_cfg_rx.rx_cfg.chl_sel = I2S_CHL_SEL_DUAL; | |||
|  |     i2s_cfg_rx.rx_cfg.msb_shift = I2S_SHIFT_PHILIPS_DIS; | |||
|  |     i2s_cfg_rx.rx_cfg.rx_eof_len = 0xffffffff; | |||
|  |     i2s_cfg_rx.rx_cfg.recv = iot_dtest_dma_recv; | |||
|  |     i2s_cfg_rx.rx_cfg.rx_desc_num=10; | |||
|  | #if 0  // MASTER TX   SLAVE RX
 | |||
|  |     i2s_cfg.type = I2S_TYPE_MSTR_TX; | |||
|  |     i2s_cfg_rx.type = I2S_TYPE_SLAV_RX; | |||
|  |     i2s_pin_sel_t pin_master = {11, 13, 15};  //LOOP BACK TEST: keep ws/bck/data line apart!! Or the signal will influent each other!
 | |||
|  |     i2s_pin_sel_t pin_slave = {12, 14, 16}; | |||
|  |     i2s_cfg.pin_master = &pin_master; | |||
|  |     i2s_cfg_rx.pin_slave = &pin_slave; | |||
|  | #else  //SLAVE TX    MASTER RX
 | |||
|  |     i2s_cfg.type = I2S_TYPE_SLAV_TX; | |||
|  |     i2s_cfg_rx.type = I2S_TYPE_MSTR_RX; | |||
|  |     i2s_pin_sel_t pin_slave = {11, 13, 15}; | |||
|  |     i2s_pin_sel_t pin_master = {12, 14, 16}; | |||
|  |     i2s_cfg.pin_slave = &pin_slave; | |||
|  |     i2s_cfg_rx.pin_master = &pin_master; | |||
|  | #endif
 | |||
|  | 
 | |||
|  |     iot_set_tx_sync_en(1); | |||
|  | 
 | |||
|  |     iot_i2s_module_init(&i2s_cfg); | |||
|  |     for(uint32_t i = 0; i < (MAX_BUF_LEN/2); i++) { | |||
|  |        test_data[i] = 0x5aa5; | |||
|  |        i++; | |||
|  |        test_data[i] = 0xa55a; | |||
|  |     } | |||
|  | 
 | |||
|  | #if USE_SINE_TONE
 | |||
|  |     sine_tone_fill( (unsigned char *)test_data, MAX_BUF_LEN); | |||
|  | #endif
 | |||
|  |     tx_bytes = 0; | |||
|  |     t0 = os_boot_time32(); | |||
|  |     while(1) | |||
|  |     { | |||
|  |         ret =  iot_i2s_push_pool(I2S_0, (char *)test_data, MAX_BUF_LEN); | |||
|  |         if (rx_start==0)  // this code just do loop back
 | |||
|  |         { | |||
|  |             iot_i2s_module_init(&i2s_cfg_rx); | |||
|  |             volatile uint32_t *reg = (volatile uint32_t *) 0x020000c0; | |||
|  |             *reg |= 0x3; | |||
|  |             rx_start=1; | |||
|  |         } | |||
|  |         if(ret == 0) | |||
|  |         { | |||
|  | #if USE_SINE_TONE
 | |||
|  |               sine_tone_fill( (unsigned char *)test_data, MAX_BUF_LEN); | |||
|  | #endif
 | |||
|  |               tx_bytes += MAX_BUF_LEN; | |||
|  |               if ( tx_bytes >= BYTES_PER_SEC) | |||
|  |               { | |||
|  |                   t = os_boot_time32(); | |||
|  |                   iot_printf("\r\n %u, cnt: %d,  rx_ok: %d, rx_tol: %d \n", ( unsigned int)( tx_bytes * 1000) / ( unsigned int)( t - t0), g_send_cnt, g_recv_cnt, g_recv_total_cnt); | |||
|  |                   t0 = t; | |||
|  |                   tx_bytes = 0; | |||
|  |               } | |||
|  |         } | |||
|  |         else{ | |||
|  |                 os_delay(2); | |||
|  |             } | |||
|  |     } | |||
|  | } | |||
|  | 
 | |||
|  | void i2s_test_task() | |||
|  | { | |||
|  |     dma_hw_init(NULL); | |||
|  |     i2s_test_i2s_func(); | |||
|  | } | |||
|  | 
 | |||
|  | void i2s_test_task_init() | |||
|  | { | |||
|  |    os_task_h handle; | |||
|  | 
 | |||
|  |    handle = os_create_task(i2s_test_task, NULL, 6); | |||
|  |    if(handle != NULL) { | |||
|  |        iot_printf("task create successfully...\n"); | |||
|  |    } | |||
|  | } | |||
|  | 
 | |||
|  | int32_t iot_task_init() | |||
|  | { | |||
|  |     test_init_handle = os_create_task(i2s_test_task, NULL, 9); | |||
|  |     if(test_init_handle != NULL) { | |||
|  |         iot_printf("i2s_test_task created successfully .. \r\n"); | |||
|  |     } | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | int32_t iot_task_start() | |||
|  | { | |||
|  |     os_start_kernel(); | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | static int32_t iot_platform_init() | |||
|  | { | |||
|  |     platform_init(); | |||
|  |     dbg_uart_init(); | |||
|  |     iot_share_task_init(); | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | int32_t iot_module_init(void) | |||
|  | { | |||
|  |     iot_platform_init(); | |||
|  |     iot_task_init(); | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | int32_t iot_module_start(void) | |||
|  | { | |||
|  |     int32_t res = 0; | |||
|  |     res = iot_task_start(); | |||
|  |     return res; | |||
|  | } | |||
|  | 
 | |||
|  | int main(void) | |||
|  | { | |||
|  |     iot_module_init(); | |||
|  |     iot_module_start(); | |||
|  |     return 0; | |||
|  | } |