I2S control
Requirements
None
Description
This example shows how to run GVSOC with a telnet proxy opened, and how to connect a python script to it to control the behavior of the I2S testbench dynamically.
Code
#!/usr/bin/env python3
import os
import argparse
import gv.gvsoc_control as gvsoc
import time
#time.sleep(3)
script_path = os.path.dirname(__file__)
parser = argparse.ArgumentParser(description='Control GVSOC')
parser.add_argument("--host", dest="host", default="localhost", help="Specify host name")
parser.add_argument("--port", dest="port", default=30000, type=int, help="Specify host port")
args = parser.parse_args()
for i in range(0,10):
try:
gv = gvsoc.Proxy(args.host, args.port)
except ConnectionRefusedError:
print("waiting for socket to open...retry #"+str(i)+"...")
time.sleep(1)
continue
break
testbench = gvsoc.Testbench(gv)
# Open SAI 0 interface
i2s_0 = testbench.i2s_get(0)
i2s_0.open(sampling_freq=44100, word_size=16, nb_slots=1, is_ext_clk=True, is_ext_ws=True)
# Setup slot 0 RX with input wav file
i2s_0.slot_open(slot=0, is_rx=True, word_size=16, is_msb=True, sign_extend=False, left_align=False)
i2s_0.slot_rx_file_reader(slot=0, filetype="wav", filepath=script_path+'/sound_0.wav')
# Setup slot 0 TX with output wav file. The test will open it with a loopback to redirect sdi to sdo
i2s_0.slot_open(slot=0, is_rx=False, word_size=16, is_msb=True, sign_extend=False, left_align=False)
i2s_0.slot_tx_file_dumper(slot=0, filetype="wav", filepath=script_path+'/sound_out.wav')
# Start the clock
i2s_0.clk_start()
# Run for 1 s
gv.run(3000000000000)
# Stop the clock and the RX slot
i2s_0.slot_stop(slot=0, stop_rx=True, stop_tx=False)
i2s_0.clk_stop()
# Run for 10 ms
gv.run(10000000000)
# Now continue with a different file
i2s_0.slot_rx_file_reader(slot=0, filetype="wav", filepath=script_path+'/sound_1.wav')
i2s_0.clk_start()
# Run for 1 s
gv.run(1000000000000)
# Stop everything and quit
i2s_0.clk_stop()
i2s_0.slot_close(slot=0)
i2s_0.close()
gv.quit()
gv.close()
/*
* Copyright (C) 2021 GreenWaves Technologies
* All rights reserved.
*
* This software may be modified and distributed under the terms
* of the BSD license. See the LICENSE file for details.
*
*/
#include "pmsis.h"
#include "stdio.h"
#define NB_ELEM 32
#define BUFFER_SIZE (NB_ELEM * 2)
static int16_t *buffers[2];
int main(void)
{
pi_device_t i2s;
// We will will samples from slot 0 in memory and also redirect them to TX with the bypass
// Open I2S for 44100, 16 bits, 1 slot
struct pi_i2s_conf i2s_conf;
pi_i2s_conf_init(&i2s_conf);
i2s_conf.itf = 0;
i2s_conf.mode = PI_I2S_MODE_I2S;
i2s_conf.slot_width = 16;
i2s_conf.channels = 1;
i2s_conf.options = PI_I2S_OPT_EXT_CLK | PI_I2S_OPT_EXT_WS;
pi_open_from_conf(&i2s, &i2s_conf);
if (pi_i2s_open(&i2s))
return -1;
// Open slot 0 RX
struct pi_i2s_channel_conf channel_conf;
pi_i2s_channel_conf_init(&channel_conf);
channel_conf.options = PI_I2S_OPT_PINGPONG | PI_I2S_OPT_IS_RX | PI_I2S_OPT_ENABLED;
buffers[0] = pi_l2_malloc(BUFFER_SIZE);
buffers[1] = pi_l2_malloc(BUFFER_SIZE);
if (buffers[0] == NULL || buffers[1] == NULL)
{
return -1;
}
channel_conf.pingpong_buffers[0] = buffers[0];
channel_conf.pingpong_buffers[1] = buffers[1];
channel_conf.block_size = BUFFER_SIZE;
channel_conf.word_size = 16;
channel_conf.format = PI_I2S_CH_FMT_DATA_ORDER_MSB;
// Open slot 0 TX in bypass mode
if (pi_i2s_channel_conf_set(&i2s, 0, &channel_conf))
return -1;
pi_i2s_channel_conf_init(&channel_conf);
channel_conf.options = PI_I2S_OPT_IS_TX | PI_I2S_OPT_ENABLED | PI_I2S_OPT_LOOPBACK;
if (pi_i2s_channel_conf_set(&i2s, 0, &channel_conf))
return -1;
if (pi_i2s_ioctl(&i2s, PI_I2S_IOCTL_START, NULL))
return -1;
// Print the first buffer of samples
void *read_buffer;
unsigned int size;
pi_i2s_channel_read(&i2s, 0, &read_buffer, &size);
for (int i=0; i<NB_ELEM; i++)
{
printf("Sample %d: %d\n", i, buffers[0][i]);
}
// Then do nothing and let the bypass propagate samples to TX
while(1)
{
pi_time_wait_us(5000000);
}
return 0;
}