Hello, I am working with ADSP-SC835 (SOM + SOMCRR board) and CCES 3.0.2. I have a simple scheme where I receive external LRCLK and BCLK signals, working in TDM4 (multichannel) mode, where SPORT5A receives the input data on both data lines (D0 and D1) and SPORT5B sends the processed data on both lines (D0 and D1), working with 8 input and 8 output channels in total.
Both half SPORTs share the exact same configuration, receive the same LRCLK and BCLK signals, and my system works with 48kHz sampling frequency and a buffer size of 4 samples. (4 samples per channel, meaning LRCLK pulses ocurr after getting the set of 1 sample for all 4 channels, and I will process the data every 16 total samples per data line - 4 samples of 4 channels per data line)
I implemented the same code shown in I2S and TDM talkthrough examples for ADSP-SC835, working in descriptor list mode to have a continuos audio stream, in which I would expect my system to have a maximum latency of 8 samples: 4 samples to fill the Rx buffer, and 4 samples to perform my desired processing and send data to Tx SPORT. Given sampling frequency and buffer length, my avaiable processing time is 83us.
For reasons I can't understand, the Tx interruption is triggered 15us before the Rx interruption, and this is forcing me to complete my processing 15us before my available time, otherwisethe total delay of my system is forced to add an extra 4 samples delay to not corrupt the new Tx buffer being sent, turning my ideal 8 samples delay into 12.
The following tests didn't bring any improvement so far:
- using global SPORT grouping together Tx and Rx triggers a single interrupt, but the underlying buffer management for Tx/Rx remains the same, so I get corrupted data if my processing exceeds (83-15)us
- triggering manually Tx transaction in STOP mode after my processing is finished sends unaligned data without respecting LRCLK (frame sync), breaking the TDM channel locations. If the processing is too long (but still below 83us) I get underflow Tx errors in both data lines. Same results triggering interruption with XCNT than with PERIPH.
- using TRU to control Tx transaction one the processing is done, also outputs unaligned data which does not respect the frame sync
- this suggestion (Sync bit) is already enabled by default inside adi_sport_v1.c/adi_sport_DMATransfer()/adi_pdma_LoadConfiguration/COMMON_PDMA_CONFIG_PARAMETERS for STOP and AUTOBUFFER mode. If I set it manually with ENUM_DMA_CFG_SYNC in descriptor list mode I don't see any change on interruptions triggering time
- this suggestion also didn't bring any change
Next images summarizes the results I get:




And here are the source files for those tests:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/platform.h>
#include <sys/adi_core.h>
#include "adi_initialize.h"
#include <services/int/adi_int.h>
#include <services/spu/adi_spu.h>
#include <services/tmr/adi_tmr.h>
#include <services/tru/adi_tru.h>
#include <drivers/sport/adi_sport.h>
#include <drivers/twi/adi_twi.h>
#include "math.h"
#include <sru.h>
#include "board/definitions.h"
#include "board/uart0.h"
#include "board/logBackend.h"
#include "board/softSwitchesConfig.h"
#include "board/gpioDebug.h"
//
// SPU
//
// SPU handle
static ADI_SPU_HANDLE ghSpu;
// Memory required for the SPU operation
uint8_t SpuMemory[ADI_SPU_MEMORY_SIZE];
int spuInit(void)
{
if ( adi_spu_Init(0, SpuMemory, NULL, NULL, &ghSpu) != ADI_SPU_SUCCESS )
{
pr_error("Failed to initialize SPU service\n");
return ADI_FAIL;
}
/* Make SPORT_3A to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5A_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3A\n");
return ADI_FAIL;
}
/* Make SPORT_3B to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5B_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3B\n");
return ADI_FAIL;
}
return ADI_SUCCESS;
}
uint32_t adiPowerConfigInit(void);
//
// I2S and SPORT
//
#define I2S_CHANNELS 16
float32_t i2sInputs0[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sInputs1[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sOutputs0[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sOutputs1[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
// Input descriptors (from XMOS I2S outputs - DAC connectors)
ADI_PDMA_DESC_LIST inputDescriptor1Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST inputDescriptor2Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST outputDescriptor1Sport5B __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST outputDescriptor2Sport5B __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
// SPORTs memory
static uint8_t memorySport5A[ADI_SPORT_MEMORY_SIZE];
static uint8_t memorySport5B[ADI_SPORT_MEMORY_SIZE];
// SPORTs handles
static ADI_SPORT_HANDLE handleSport5A;
static ADI_SPORT_HANDLE handleSport5B;
bool inputDataReady[2] = {false, false};
int inputBufferAvailable = 1;
int outputBufferAvailable = 1;
// SPORTs callbacks
static void callbackSport5A(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_RX_BUFFER_PROCESSED )
{
gpioDebug1Set();
gpioDebug1Clear();
inputDataReady[0] = true;
if (inputBufferAvailable == 0)
inputBufferAvailable = 1;
else
inputBufferAvailable = 0;
}
else
{
gpioDebug1Set();
gpioDebug2Set();
gpioDebug2Clear();
gpioDebug1Clear();
}
}
static void callbackSport5B(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_TX_BUFFER_PROCESSED )
{
gpioDebug2Set();
gpioDebug2Clear();
if (outputBufferAvailable == 0)
outputBufferAvailable = 1;
else
outputBufferAvailable = 0;
}
else
{
gpioDebug2Set();
gpioDebug1Set();
gpioDebug1Clear();
gpioDebug2Clear();
}
}
// Prepare DMA descriptors for SPORTs
static void prepareRxDescriptors (void)
{
// Input descriptors (ping)
inputDescriptor1Sport5A.pStartAddr = (int *) &i2sInputs0[0][0];
inputDescriptor1Sport5A.pNxtDscp = &inputDescriptor2Sport5A;
inputDescriptor1Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor1Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor1Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor1Sport5A.YCount = 0;
inputDescriptor1Sport5A.YModify = 0;
// Input descriptors (pong)
inputDescriptor2Sport5A.pStartAddr = (int *) &i2sInputs1[0][0];
inputDescriptor2Sport5A.pNxtDscp = &inputDescriptor1Sport5A;
inputDescriptor2Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor2Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor2Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor2Sport5A.YCount = 0;
inputDescriptor2Sport5A.YModify = 0;
}
static void prepareTxDescriptors (void)
{
// Output descriptors (ping)
outputDescriptor1Sport5B.pStartAddr = (int *) &i2sOutputs0[0][0];
outputDescriptor1Sport5B.pNxtDscp = &outputDescriptor2Sport5B;
outputDescriptor1Sport5B.Config = ENUM_DMA_CFG_XCNT_INT;
outputDescriptor1Sport5B.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
outputDescriptor1Sport5B.XModify = sizeof(i2sOutputs0[0][0]);
outputDescriptor1Sport5B.YCount = 0;
outputDescriptor1Sport5B.YModify = 0;
// Output descriptors (pong)
outputDescriptor2Sport5B.pStartAddr = (int *) &i2sOutputs1[0][0];
outputDescriptor2Sport5B.pNxtDscp = &outputDescriptor1Sport5B;
outputDescriptor2Sport5B.Config = ENUM_DMA_CFG_XCNT_INT;
outputDescriptor2Sport5B.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
outputDescriptor2Sport5B.XModify = sizeof(i2sOutputs0[0][0]);
outputDescriptor2Sport5B.YCount = 0;
outputDescriptor2Sport5B.YModify = 0;
}
// Initialize SPORTs
static int sportInit()
{
ADI_SPORT_RESULT eResult;
// Open SPORTs
eResult = adi_sport_Open(SPORT_DEVICE_5A, ADI_HALF_SPORT_A, ADI_SPORT_DIR_RX, ADI_SPORT_MC_MODE, memorySport5A, ADI_SPORT_MEMORY_SIZE, &handleSport5A);
CHECK_RESULT(eResult);
eResult = adi_sport_Open(SPORT_DEVICE_5B, ADI_HALF_SPORT_B, ADI_SPORT_DIR_TX, ADI_SPORT_MC_MODE, memorySport5B, ADI_SPORT_MEMORY_SIZE, &handleSport5B);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5A
eResult = adi_sport_ConfigData(handleSport5A, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5A, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5A, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5A, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5A, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5B
eResult = adi_sport_ConfigData(handleSport5B, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5B, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5B, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5B, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5B, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Register callbacks
eResult = adi_sport_RegisterCallback(handleSport5A, callbackSport5A, NULL);
CHECK_RESULT(eResult);
eResult = adi_sport_RegisterCallback(handleSport5B, callbackSport5B, NULL);
CHECK_RESULT(eResult);
// Prepare descriptors
prepareRxDescriptors();
prepareTxDescriptors();
// Submit first descriptors
adi_sport_DMATransfer(handleSport5A, &inputDescriptor1Sport5A, 2, ADI_PDMA_DESCRIPTOR_LIST, ADI_SPORT_CHANNEL_PRIM_SEC);
adi_sport_DMATransfer(handleSport5B, &outputDescriptor1Sport5B, 2, ADI_PDMA_DESCRIPTOR_LIST, ADI_SPORT_CHANNEL_PRIM_SEC);
// Enable SPORTs
eResult = adi_sport_Enable(handleSport5A, true);
CHECK_RESULT(eResult);
eResult = adi_sport_Enable(handleSport5B, true);
CHECK_RESULT(eResult);
return eResult;
}
//
// SRU
//
void sruInit()
{
*pREG_PADS0_DAI0_IE=0xfffff;
*pREG_PADS0_DAI1_IE=0xfffff;
// Input clock
SRU2 ( DAI1_PB05_O, SPT5_ACLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5A clock */
SRU2 ( DAI1_PB05_O, SPT5_BCLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5B clock */
SRU2 ( LOW, DAI1_PBEN05_I );
// Input FS
SRU2 ( DAI1_PB04_O, SPT5_AFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5A FS */
SRU2 ( DAI1_PB04_O, SPT5_BFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5B FS */
//SRU2 ( LOW, DAI1_PBEN04_I );
// Routing for monitoring LRCLK through DAI1_PB02. TODO comment me and enable back line above (DAI1_PBEN04_I)
SRU2(DAI1_PB04_O, DAI1_PB02_I);
SRU2 ( LOW, DAI1_PBEN04_I );
SRU2 ( HIGH, DAI1_PBEN02_I );
// Input D0-3
SRU2 ( DAI1_PB06_O, SPT5_AD0_I ); /* DAC D0 -> DAI1_PB6 -> SPORT_5A D0 */
SRU2 ( LOW, DAI1_PBEN06_I );
SRU2 ( DAI1_PB07_O, SPT5_AD1_I ); /* DAC D1 -> DAI1_PB7 -> SPORT_5A D1 */
SRU2 ( LOW, DAI1_PBEN07_I );
// Output D0-3
SRU2 ( SPT5_BD0_O, DAI1_PB10_I ); /* SPORT_5B D0 -> DAI1_PB10 -> ADC D0 */
SRU2 ( HIGH, DAI1_PBEN10_I );
SRU2 ( SPT5_BD1_O, DAI1_PB11_I ); /* SPORT_5B D1 -> DAI1_PB11 -> ADC D1 */
SRU2 ( HIGH, DAI1_PBEN11_I );
}
//
// Main app
//
int main(int argc, char *argv[])
{
// Init SEC, pinmux and SRU
adi_initComponents();
// PWR (CLKs) config
adiPowerConfigInit();
// SPU initialization
uint32_t Result = spuInit();
if ( Result != ADI_SUCCESS )
{
return ADI_FAIL;
}
// Config soft switches for LED control
softSwitchesConfig();
// SRU configuration
sruInit();
// Init UART0 for debug print
int32_t uartInitRes = uartInit();
if ( uartInitRes != ADI_SUCCESS )
{
printf("ERROR in uartInit(): %i\n", uartInitRes);
return ADI_FAIL;
}
// GPIO debug initialization
gpioDebugConfig();
// SPORT initialization
Result = sportInit();
if ( Result != ADI_SUCCESS )
{
pr_error("SPORT initialization failed\n\r");
return ADI_FAIL;
}
while(1)
{
// Wait until data is ready from I2S ISR
while ( inputDataReady[0] == false ) asm("NOP");
inputDataReady[0] = false;
gpioDebug0Set();
// DSP processing
int wait = 75000;
while(wait--) asm("NOP");
// Copy processed input to output
float32_t* pI2sInput = (inputBufferAvailable == 0) ? &i2sInputs0[0][0] : &i2sInputs1[0][0];
float32_t* pI2sOutput = (outputBufferAvailable == 0) ? &i2sOutputs0[0][0] : &i2sOutputs1[0][0];
memcpy(pI2sOutput, pI2sInput, sizeof(i2sInputs0));
gpioDebug0Clear();
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/platform.h>
#include <sys/adi_core.h>
#include "adi_initialize.h"
#include <services/int/adi_int.h>
#include <services/spu/adi_spu.h>
#include <services/tmr/adi_tmr.h>
#include <services/tru/adi_tru.h>
#include <drivers/sport/adi_sport.h>
#include <drivers/twi/adi_twi.h>
#include "math.h"
#include <sru.h>
#include "board/definitions.h"
#include "board/uart0.h"
#include "board/logBackend.h"
#include "board/softSwitchesConfig.h"
#include "board/gpioDebug.h"
//
// SPU
//
// SPU handle
static ADI_SPU_HANDLE ghSpu;
// Memory required for the SPU operation
uint8_t SpuMemory[ADI_SPU_MEMORY_SIZE];
int spuInit(void)
{
if ( adi_spu_Init(0, SpuMemory, NULL, NULL, &ghSpu) != ADI_SPU_SUCCESS )
{
pr_error("Failed to initialize SPU service\n");
return ADI_FAIL;
}
/* Make SPORT_3A to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5A_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3A\n");
return ADI_FAIL;
}
/* Make SPORT_3B to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5B_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3B\n");
return ADI_FAIL;
}
return ADI_SUCCESS;
}
uint32_t adiPowerConfigInit(void);
//
// I2S and SPORT
//
#define I2S_CHANNELS 16
float32_t i2sInputs0[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sInputs1[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sOutput[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
// Input descriptors (from XMOS I2S outputs - DAC connectors)
ADI_PDMA_DESC_LIST inputDescriptor1Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST inputDescriptor2Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST outputDescriptor1Sport5B __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
// SPORTs memory
static uint8_t memorySport5A[ADI_SPORT_MEMORY_SIZE];
static uint8_t memorySport5B[ADI_SPORT_MEMORY_SIZE];
// SPORTs handles
static ADI_SPORT_HANDLE handleSport5A;
static ADI_SPORT_HANDLE handleSport5B;
bool inputDataReady[2] = {false, false};
int inputBufferAvailable = 1;
int outputBufferAvailable = 1;
// SPORTs callbacks
static void callbackSport5A(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_RX_BUFFER_PROCESSED )
{
gpioDebug1Set();
gpioDebug1Clear();
inputDataReady[0] = true;
if (inputBufferAvailable == 0)
inputBufferAvailable = 1;
else
inputBufferAvailable = 0;
}
else
{
gpioDebug1Set();
gpioDebug2Set();
gpioDebug2Clear();
gpioDebug1Clear();
}
}
static void callbackSport5B(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_TX_BUFFER_PROCESSED )
{
gpioDebug2Set();
gpioDebug2Clear();
}
else
{
gpioDebug2Set();
gpioDebug1Set();
gpioDebug1Clear();
gpioDebug2Clear();
}
}
// Prepare DMA descriptors for SPORTs
static void prepareRxDescriptors (void)
{
// Input descriptors (ping)
inputDescriptor1Sport5A.pStartAddr = (int *) &i2sInputs0[0][0];
inputDescriptor1Sport5A.pNxtDscp = &inputDescriptor2Sport5A;
inputDescriptor1Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor1Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor1Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor1Sport5A.YCount = 0;
inputDescriptor1Sport5A.YModify = 0;
// Input descriptors (pong)
inputDescriptor2Sport5A.pStartAddr = (int *) &i2sInputs1[0][0];
inputDescriptor2Sport5A.pNxtDscp = &inputDescriptor1Sport5A;
inputDescriptor2Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor2Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor2Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor2Sport5A.YCount = 0;
inputDescriptor2Sport5A.YModify = 0;
}
static void prepareTxDescriptors (void)
{
// Output descriptors (ping)
outputDescriptor1Sport5B.pStartAddr = (int *) &i2sOutput[0][0];
outputDescriptor1Sport5B.pNxtDscp = NULL;
outputDescriptor1Sport5B.Config = ENUM_DMA_CFG_XCNT_INT;
outputDescriptor1Sport5B.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
outputDescriptor1Sport5B.XModify = sizeof(i2sOutput[0][0]);
outputDescriptor1Sport5B.YCount = 0;
outputDescriptor1Sport5B.YModify = 0;
}
// Initialize SPORTs
static int sportInit()
{
ADI_SPORT_RESULT eResult;
// Open SPORTs
eResult = adi_sport_Open(SPORT_DEVICE_5A, ADI_HALF_SPORT_A, ADI_SPORT_DIR_RX, ADI_SPORT_MC_MODE, memorySport5A, ADI_SPORT_MEMORY_SIZE, &handleSport5A);
CHECK_RESULT(eResult);
eResult = adi_sport_Open(SPORT_DEVICE_5B, ADI_HALF_SPORT_B, ADI_SPORT_DIR_TX, ADI_SPORT_MC_MODE, memorySport5B, ADI_SPORT_MEMORY_SIZE, &handleSport5B);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5A
eResult = adi_sport_ConfigData(handleSport5A, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5A, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5A, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5A, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5A, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5B
eResult = adi_sport_ConfigData(handleSport5B, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5B, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5B, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5B, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5B, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Register callbacks
eResult = adi_sport_RegisterCallback(handleSport5A, callbackSport5A, NULL);
CHECK_RESULT(eResult);
eResult = adi_sport_RegisterCallback(handleSport5B, callbackSport5B, NULL);
CHECK_RESULT(eResult);
// Prepare descriptors
prepareRxDescriptors();
prepareTxDescriptors();
// Submit first descriptors
adi_sport_DMATransfer(handleSport5A, &inputDescriptor1Sport5A, 2, ADI_PDMA_DESCRIPTOR_LIST, ADI_SPORT_CHANNEL_PRIM_SEC);
adi_sport_DMATransfer(handleSport5B, &outputDescriptor1Sport5B, 1, ADI_PDMA_AUTOBUFFER_MODE, ADI_SPORT_CHANNEL_PRIM_SEC);
// Enable SPORTs
eResult = adi_sport_Enable(handleSport5A, true);
CHECK_RESULT(eResult);
eResult = adi_sport_Enable(handleSport5B, true);
CHECK_RESULT(eResult);
return eResult;
}
//
// SRU
//
void sruInit()
{
*pREG_PADS0_DAI0_IE=0xfffff;
*pREG_PADS0_DAI1_IE=0xfffff;
// Input clock
SRU2 ( DAI1_PB05_O, SPT5_ACLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5A clock */
SRU2 ( DAI1_PB05_O, SPT5_BCLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5B clock */
SRU2 ( LOW, DAI1_PBEN05_I );
// Input FS
SRU2 ( DAI1_PB04_O, SPT5_AFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5A FS */
SRU2 ( DAI1_PB04_O, SPT5_BFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5B FS */
//SRU2 ( LOW, DAI1_PBEN04_I );
// Routing for monitoring LRCLK through DAI1_PB02. TODO comment me and enable back line above (DAI1_PBEN04_I)
SRU2(DAI1_PB04_O, DAI1_PB02_I);
SRU2 ( LOW, DAI1_PBEN04_I );
SRU2 ( HIGH, DAI1_PBEN02_I );
// Input D0-3
SRU2 ( DAI1_PB06_O, SPT5_AD0_I ); /* DAC D0 -> DAI1_PB6 -> SPORT_5A D0 */
SRU2 ( LOW, DAI1_PBEN06_I );
SRU2 ( DAI1_PB07_O, SPT5_AD1_I ); /* DAC D1 -> DAI1_PB7 -> SPORT_5A D1 */
SRU2 ( LOW, DAI1_PBEN07_I );
// Output D0-3
SRU2 ( SPT5_BD0_O, DAI1_PB10_I ); /* SPORT_5B D0 -> DAI1_PB10 -> ADC D0 */
SRU2 ( HIGH, DAI1_PBEN10_I );
SRU2 ( SPT5_BD1_O, DAI1_PB11_I ); /* SPORT_5B D1 -> DAI1_PB11 -> ADC D1 */
SRU2 ( HIGH, DAI1_PBEN11_I );
}
//
// Main app
//
int main(int argc, char *argv[])
{
// Init SEC, pinmux and SRU
adi_initComponents();
// PWR (CLKs) config
adiPowerConfigInit();
// SPU initialization
uint32_t Result = spuInit();
if ( Result != ADI_SUCCESS )
{
return ADI_FAIL;
}
// Config soft switches for LED control
softSwitchesConfig();
// SRU configuration
sruInit();
// Init UART0 for debug print
int32_t uartInitRes = uartInit();
if ( uartInitRes != ADI_SUCCESS )
{
printf("ERROR in uartInit(): %i\n", uartInitRes);
return ADI_FAIL;
}
// GPIO debug initialization
gpioDebugConfig();
// SPORT initialization
Result = sportInit();
if ( Result != ADI_SUCCESS )
{
pr_error("SPORT initialization failed\n\r");
return ADI_FAIL;
}
while(1)
{
// Wait until data is ready from I2S ISR
while ( inputDataReady[0] == false ) asm("NOP");
inputDataReady[0] = false;
gpioDebug0Set();
// DSP processing
int wait = 75000;
while(wait--) asm("NOP");
// Copy processed input to output
float32_t* pI2sInput = (inputBufferAvailable == 0) ? &i2sInputs0[0][0] : &i2sInputs1[0][0];
memcpy(&i2sOutput[0][0], pI2sInput, sizeof(i2sInputs0));
gpioDebug0Clear();
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/platform.h>
#include <sys/adi_core.h>
#include "adi_initialize.h"
#include <services/int/adi_int.h>
#include <services/spu/adi_spu.h>
#include <services/tmr/adi_tmr.h>
#include <services/tru/adi_tru.h>
#include <drivers/sport/adi_sport.h>
#include <drivers/twi/adi_twi.h>
#include "math.h"
#include <sru.h>
#include "board/definitions.h"
#include "board/uart0.h"
#include "board/logBackend.h"
#include "board/softSwitchesConfig.h"
#include "board/gpioDebug.h"
//
// SPU
//
// SPU handle
static ADI_SPU_HANDLE ghSpu;
// Memory required for the SPU operation
uint8_t SpuMemory[ADI_SPU_MEMORY_SIZE];
int spuInit(void)
{
if ( adi_spu_Init(0, SpuMemory, NULL, NULL, &ghSpu) != ADI_SPU_SUCCESS )
{
pr_error("Failed to initialize SPU service\n");
return ADI_FAIL;
}
/* Make SPORT_3A to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5A_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3A\n");
return ADI_FAIL;
}
/* Make SPORT_3B to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5B_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3B\n");
return ADI_FAIL;
}
return ADI_SUCCESS;
}
uint32_t adiPowerConfigInit(void);
//
// I2S and SPORT
//
#define I2S_CHANNELS 16
float32_t i2sInputs0[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sInputs1[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sOutput[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
// Input descriptors (from XMOS I2S outputs - DAC connectors)
ADI_PDMA_DESC_LIST inputDescriptor1Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST inputDescriptor2Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST outputDescriptor1Sport5B __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
// SPORTs memory
static uint8_t memorySport5A[ADI_SPORT_MEMORY_SIZE];
static uint8_t memorySport5B[ADI_SPORT_MEMORY_SIZE];
// SPORTs handles
static ADI_SPORT_HANDLE handleSport5A;
static ADI_SPORT_HANDLE handleSport5B;
bool inputDataReady[2] = {false, false};
int inputBufferAvailable = 1;
int outputBufferAvailable = 1;
// SPORTs callbacks
static void callbackSport5A(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_RX_BUFFER_PROCESSED )
{
gpioDebug1Set();
gpioDebug1Clear();
inputDataReady[0] = true;
if (inputBufferAvailable == 0)
inputBufferAvailable = 1;
else
inputBufferAvailable = 0;
}
else
{
gpioDebug1Set();
gpioDebug2Set();
gpioDebug2Clear();
gpioDebug1Clear();
}
}
static void callbackSport5B(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_TX_BUFFER_PROCESSED )
{
gpioDebug2Set();
gpioDebug2Clear();
}
else
{
gpioDebug2Set();
gpioDebug1Set();
gpioDebug1Clear();
gpioDebug2Clear();
}
}
// Prepare DMA descriptors for SPORTs
static void prepareRxDescriptors (void)
{
// Input descriptors (ping)
inputDescriptor1Sport5A.pStartAddr = (int *) &i2sInputs0[0][0];
inputDescriptor1Sport5A.pNxtDscp = &inputDescriptor2Sport5A;
inputDescriptor1Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor1Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor1Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor1Sport5A.YCount = 0;
inputDescriptor1Sport5A.YModify = 0;
// Input descriptors (pong)
inputDescriptor2Sport5A.pStartAddr = (int *) &i2sInputs1[0][0];
inputDescriptor2Sport5A.pNxtDscp = &inputDescriptor1Sport5A;
inputDescriptor2Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor2Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor2Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor2Sport5A.YCount = 0;
inputDescriptor2Sport5A.YModify = 0;
}
static void prepareTxDescriptors (void)
{
// Output descriptors (ping)
outputDescriptor1Sport5B.pStartAddr = (int *) &i2sOutput[0][0];
outputDescriptor1Sport5B.pNxtDscp = NULL;
outputDescriptor1Sport5B.Config = ENUM_DMA_CFG_XCNT_INT | ENUM_DMA_CFG_TRGWAIT;;
outputDescriptor1Sport5B.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
outputDescriptor1Sport5B.XModify = sizeof(i2sOutput[0][0]);
outputDescriptor1Sport5B.YCount = 0;
outputDescriptor1Sport5B.YModify = 0;
}
// Initialize SPORTs
static int sportInit()
{
ADI_SPORT_RESULT eResult;
adi_tru_Init(true);
adi_tru_ConfigureSlave(TRGS_SPORT5_B_DMA, TRGM_SYS_SOFT0_MST);
// Open SPORTs
eResult = adi_sport_Open(SPORT_DEVICE_5A, ADI_HALF_SPORT_A, ADI_SPORT_DIR_RX, ADI_SPORT_MC_MODE, memorySport5A, ADI_SPORT_MEMORY_SIZE, &handleSport5A);
CHECK_RESULT(eResult);
eResult = adi_sport_Open(SPORT_DEVICE_5B, ADI_HALF_SPORT_B, ADI_SPORT_DIR_TX, ADI_SPORT_MC_MODE, memorySport5B, ADI_SPORT_MEMORY_SIZE, &handleSport5B);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5A
eResult = adi_sport_ConfigData(handleSport5A, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5A, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5A, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5A, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5A, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5B
eResult = adi_sport_ConfigData(handleSport5B, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5B, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5B, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5B, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5B, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Register callbacks
eResult = adi_sport_RegisterCallback(handleSport5A, callbackSport5A, NULL);
CHECK_RESULT(eResult);
eResult = adi_sport_RegisterCallback(handleSport5B, callbackSport5B, NULL);
CHECK_RESULT(eResult);
// Prepare descriptors
prepareRxDescriptors();
prepareTxDescriptors();
// Submit first descriptors
adi_sport_DMATransfer(handleSport5A, &inputDescriptor1Sport5A, 2, ADI_PDMA_DESCRIPTOR_LIST, ADI_SPORT_CHANNEL_PRIM_SEC);
adi_sport_DMATransfer(handleSport5B, &outputDescriptor1Sport5B, 1, ADI_PDMA_AUTOBUFFER_MODE, ADI_SPORT_CHANNEL_PRIM_SEC);
// Enable SPORTs
eResult = adi_sport_Enable(handleSport5A, true);
CHECK_RESULT(eResult);
eResult = adi_sport_Enable(handleSport5B, true);
CHECK_RESULT(eResult);
return eResult;
}
//
// SRU
//
void sruInit()
{
*pREG_PADS0_DAI0_IE=0xfffff;
*pREG_PADS0_DAI1_IE=0xfffff;
// Input clock
SRU2 ( DAI1_PB05_O, SPT5_ACLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5A clock */
SRU2 ( DAI1_PB05_O, SPT5_BCLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5B clock */
SRU2 ( LOW, DAI1_PBEN05_I );
// Input FS
SRU2 ( DAI1_PB04_O, SPT5_AFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5A FS */
SRU2 ( DAI1_PB04_O, SPT5_BFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5B FS */
//SRU2 ( LOW, DAI1_PBEN04_I );
// Routing for monitoring LRCLK through DAI1_PB02. TODO comment me and enable back line above (DAI1_PBEN04_I)
SRU2(DAI1_PB04_O, DAI1_PB02_I);
SRU2 ( LOW, DAI1_PBEN04_I );
SRU2 ( HIGH, DAI1_PBEN02_I );
// Input D0-3
SRU2 ( DAI1_PB06_O, SPT5_AD0_I ); /* DAC D0 -> DAI1_PB6 -> SPORT_5A D0 */
SRU2 ( LOW, DAI1_PBEN06_I );
SRU2 ( DAI1_PB07_O, SPT5_AD1_I ); /* DAC D1 -> DAI1_PB7 -> SPORT_5A D1 */
SRU2 ( LOW, DAI1_PBEN07_I );
// Output D0-3
SRU2 ( SPT5_BD0_O, DAI1_PB10_I ); /* SPORT_5B D0 -> DAI1_PB10 -> ADC D0 */
SRU2 ( HIGH, DAI1_PBEN10_I );
SRU2 ( SPT5_BD1_O, DAI1_PB11_I ); /* SPORT_5B D1 -> DAI1_PB11 -> ADC D1 */
SRU2 ( HIGH, DAI1_PBEN11_I );
}
//
// Main app
//
int main(int argc, char *argv[])
{
// Init SEC, pinmux and SRU
adi_initComponents();
// PWR (CLKs) config
adiPowerConfigInit();
// SPU initialization
uint32_t Result = spuInit();
if ( Result != ADI_SUCCESS )
{
return ADI_FAIL;
}
// Config soft switches for LED control
softSwitchesConfig();
// SRU configuration
sruInit();
// Init UART0 for debug print
int32_t uartInitRes = uartInit();
if ( uartInitRes != ADI_SUCCESS )
{
printf("ERROR in uartInit(): %i\n", uartInitRes);
return ADI_FAIL;
}
// GPIO debug initialization
gpioDebugConfig();
// SPORT initialization
Result = sportInit();
if ( Result != ADI_SUCCESS )
{
pr_error("SPORT initialization failed\n\r");
return ADI_FAIL;
}
while(1)
{
// Wait until data is ready from I2S ISR
while ( inputDataReady[0] == false ) asm("NOP");
inputDataReady[0] = false;
gpioDebug0Set();
// DSP processing
int wait = 60000;
while(wait--) asm("NOP");
// Copy processed input to output
float32_t* pI2sInput = (inputBufferAvailable == 0) ? &i2sInputs0[0][0] : &i2sInputs1[0][0];
memcpy(&i2sOutput[0][0], pI2sInput, sizeof(i2sInputs0));
adi_tru_RaiseTriggerMaster(TRGM_SYS_SOFT0_MST);
gpioDebug0Clear();
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/platform.h>
#include <sys/adi_core.h>
#include "adi_initialize.h"
#include <services/int/adi_int.h>
#include <services/spu/adi_spu.h>
#include <services/tmr/adi_tmr.h>
#include <services/tru/adi_tru.h>
#include <drivers/sport/adi_sport.h>
#include <drivers/twi/adi_twi.h>
#include "math.h"
#include <sru.h>
#include "board/definitions.h"
#include "board/uart0.h"
#include "board/logBackend.h"
#include "board/softSwitchesConfig.h"
#include "board/gpioDebug.h"
//
// SPU
//
// SPU handle
static ADI_SPU_HANDLE ghSpu;
// Memory required for the SPU operation
uint8_t SpuMemory[ADI_SPU_MEMORY_SIZE];
int spuInit(void)
{
if ( adi_spu_Init(0, SpuMemory, NULL, NULL, &ghSpu) != ADI_SPU_SUCCESS )
{
pr_error("Failed to initialize SPU service\n");
return ADI_FAIL;
}
/* Make SPORT_3A to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5A_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3A\n");
return ADI_FAIL;
}
/* Make SPORT_3B to generate secure transactions */
if ( adi_spu_EnableMasterSecure(ghSpu, SPORT_5B_SPU_ID, true) != ADI_SPU_SUCCESS )
{
pr_error("Failed to enable Master secure for SPORT3B\n");
return ADI_FAIL;
}
return ADI_SUCCESS;
}
uint32_t adiPowerConfigInit(void);
//
// I2S and SPORT
//
#define I2S_CHANNELS 16
float32_t i2sInputs0[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sInputs1[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
float32_t i2sOutput[I2S_CHANNELS][BUFFER_LEN] __attribute__ ( (section(".L1.data")) ) ADI_CACHE_ALIGN;
// Input descriptors (from XMOS I2S outputs - DAC connectors)
ADI_PDMA_DESC_LIST inputDescriptor1Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST inputDescriptor2Sport5A __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
ADI_PDMA_DESC_LIST outputDescriptor1Sport5B __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
// SPORTs memory
static uint8_t memorySport5A[ADI_SPORT_MEMORY_SIZE];
static uint8_t memorySport5B[ADI_SPORT_MEMORY_SIZE];
// SPORTs handles
static ADI_SPORT_HANDLE handleSport5A;
static ADI_SPORT_HANDLE handleSport5B;
bool inputDataReady[2] = {false, false};
int inputBufferAvailable = 1;
int outputBufferAvailable = 1;
// SPORTs callbacks
static void callbackSport5A(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_RX_BUFFER_PROCESSED )
{
gpioDebug1Set();
gpioDebug1Clear();
inputDataReady[0] = true;
if (inputBufferAvailable == 0)
inputBufferAvailable = 1;
else
inputBufferAvailable = 0;
}
else
{
gpioDebug1Set();
gpioDebug2Set();
gpioDebug2Clear();
gpioDebug1Clear();
}
}
static void callbackSport5B(void *pAppHandle, uint32_t nEvent, void *pArg)
{
if ( nEvent == ADI_SPORT_EVENT_TX_BUFFER_PROCESSED )
{
gpioDebug2Set();
gpioDebug2Clear();
}
else
{
gpioDebug2Set();
gpioDebug1Set();
gpioDebug1Clear();
gpioDebug2Clear();
}
}
// Prepare DMA descriptors for SPORTs
static void prepareRxDescriptors (void)
{
// Input descriptors (ping)
inputDescriptor1Sport5A.pStartAddr = (int *) &i2sInputs0[0][0];
inputDescriptor1Sport5A.pNxtDscp = &inputDescriptor2Sport5A;
inputDescriptor1Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor1Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor1Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor1Sport5A.YCount = 0;
inputDescriptor1Sport5A.YModify = 0;
// Input descriptors (pong)
inputDescriptor2Sport5A.pStartAddr = (int *) &i2sInputs1[0][0];
inputDescriptor2Sport5A.pNxtDscp = &inputDescriptor1Sport5A;
inputDescriptor2Sport5A.Config = ENUM_DMA_CFG_XCNT_INT;
inputDescriptor2Sport5A.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
inputDescriptor2Sport5A.XModify = sizeof(i2sInputs0[0][0]);
inputDescriptor2Sport5A.YCount = 0;
inputDescriptor2Sport5A.YModify = 0;
}
static void prepareTxDescriptors (void)
{
// Output descriptors (ping)
outputDescriptor1Sport5B.pStartAddr = (int *) &i2sOutput[0][0];
outputDescriptor1Sport5B.pNxtDscp = NULL;
outputDescriptor1Sport5B.Config = ENUM_DMA_CFG_XCNT_INT;
outputDescriptor1Sport5B.XCount = BUFFER_LEN * TDM_CHANNELS * SPORT_DATA_LINES;
outputDescriptor1Sport5B.XModify = sizeof(i2sOutput[0][0]);
outputDescriptor1Sport5B.YCount = 0;
outputDescriptor1Sport5B.YModify = 0;
}
// Initialize SPORTs
static int sportInit()
{
ADI_SPORT_RESULT eResult;
// Open SPORTs
eResult = adi_sport_Open(SPORT_DEVICE_5A, ADI_HALF_SPORT_A, ADI_SPORT_DIR_RX, ADI_SPORT_MC_MODE, memorySport5A, ADI_SPORT_MEMORY_SIZE, &handleSport5A);
CHECK_RESULT(eResult);
eResult = adi_sport_Open(SPORT_DEVICE_5B, ADI_HALF_SPORT_B, ADI_SPORT_DIR_TX, ADI_SPORT_MC_MODE, memorySport5B, ADI_SPORT_MEMORY_SIZE, &handleSport5B);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5A
eResult = adi_sport_ConfigData(handleSport5A, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5A, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5A, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5A, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5A, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Configure the data, clock, frame sync and MC of SPORT_5B
eResult = adi_sport_ConfigData(handleSport5B, ADI_SPORT_DTYPE_SIGN_FILL, BIT_DEPTH - 1, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigClock(handleSport5B, BIT_DEPTH, false, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigFrameSync(handleSport5B, ( TDM_CHANNELS * BIT_DEPTH ) - 1, true, false, false, true, false, false );
CHECK_RESULT(eResult);
eResult = adi_sport_ConfigMC(handleSport5B, 1, TDM_CHANNELS - 1, 0, false);
CHECK_RESULT(eResult);
eResult = adi_sport_SelectChannel(handleSport5B, 0, TDM_CHANNELS - 1);
CHECK_RESULT(eResult);
// Register callbacks
eResult = adi_sport_RegisterCallback(handleSport5A, callbackSport5A, NULL);
CHECK_RESULT(eResult);
eResult = adi_sport_RegisterCallback(handleSport5B, callbackSport5B, NULL);
CHECK_RESULT(eResult);
// Prepare descriptors
prepareRxDescriptors();
prepareTxDescriptors();
// Submit first descriptors
adi_sport_DMATransfer(handleSport5A, &inputDescriptor1Sport5A, 2, ADI_PDMA_DESCRIPTOR_LIST, ADI_SPORT_CHANNEL_PRIM_SEC);
adi_sport_DMATransfer(handleSport5B, &outputDescriptor1Sport5B, 1, ADI_PDMA_STOP_MODE, ADI_SPORT_CHANNEL_PRIM_SEC);
// Enable SPORTs
eResult = adi_sport_Enable(handleSport5A, true);
CHECK_RESULT(eResult);
eResult = adi_sport_Enable(handleSport5B, true);
CHECK_RESULT(eResult);
return eResult;
}
//
// SRU
//
void sruInit()
{
*pREG_PADS0_DAI0_IE=0xfffff;
*pREG_PADS0_DAI1_IE=0xfffff;
// Input clock
SRU2 ( DAI1_PB05_O, SPT5_ACLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5A clock */
SRU2 ( DAI1_PB05_O, SPT5_BCLK_I ); /* BCLK -> DAI1_PB5 -> SPORT_5B clock */
SRU2 ( LOW, DAI1_PBEN05_I );
// Input FS
SRU2 ( DAI1_PB04_O, SPT5_AFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5A FS */
SRU2 ( DAI1_PB04_O, SPT5_BFS_I ); /* LRCLK -> DAI1_PB4 -> SPORT_5B FS */
//SRU2 ( LOW, DAI1_PBEN04_I );
// Routing for monitoring LRCLK through DAI1_PB02. TODO comment me and enable back line above (DAI1_PBEN04_I)
SRU2(DAI1_PB04_O, DAI1_PB02_I);
SRU2 ( LOW, DAI1_PBEN04_I );
SRU2 ( HIGH, DAI1_PBEN02_I );
// Input D0-3
SRU2 ( DAI1_PB06_O, SPT5_AD0_I ); /* DAC D0 -> DAI1_PB6 -> SPORT_5A D0 */
SRU2 ( LOW, DAI1_PBEN06_I );
SRU2 ( DAI1_PB07_O, SPT5_AD1_I ); /* DAC D1 -> DAI1_PB7 -> SPORT_5A D1 */
SRU2 ( LOW, DAI1_PBEN07_I );
// Output D0-3
SRU2 ( SPT5_BD0_O, DAI1_PB10_I ); /* SPORT_5B D0 -> DAI1_PB10 -> ADC D0 */
SRU2 ( HIGH, DAI1_PBEN10_I );
SRU2 ( SPT5_BD1_O, DAI1_PB11_I ); /* SPORT_5B D1 -> DAI1_PB11 -> ADC D1 */
SRU2 ( HIGH, DAI1_PBEN11_I );
}
//
// Main app
//
int main(int argc, char *argv[])
{
// Init SEC, pinmux and SRU
adi_initComponents();
// PWR (CLKs) config
adiPowerConfigInit();
// SPU initialization
uint32_t Result = spuInit();
if ( Result != ADI_SUCCESS )
{
return ADI_FAIL;
}
// Config soft switches for LED control
softSwitchesConfig();
// SRU configuration
sruInit();
// Init UART0 for debug print
int32_t uartInitRes = uartInit();
if ( uartInitRes != ADI_SUCCESS )
{
printf("ERROR in uartInit(): %i\n", uartInitRes);
return ADI_FAIL;
}
// GPIO debug initialization
gpioDebugConfig();
// SPORT initialization
Result = sportInit();
if ( Result != ADI_SUCCESS )
{
pr_error("SPORT initialization failed\n\r");
return ADI_FAIL;
}
while(1)
{
// Wait until data is ready from I2S ISR
while ( inputDataReady[0] == false ) asm("NOP");
inputDataReady[0] = false;
gpioDebug0Set();
// DSP processing
int wait = 75000;
while(wait--) asm("NOP");
// Copy processed input to output
float32_t* pI2sInput = (inputBufferAvailable == 0) ? &i2sInputs0[0][0] : &i2sInputs1[0][0];
memcpy(&i2sOutput[0][0], pI2sInput, sizeof(i2sInputs0));
prepareTxDescriptors();
adi_sport_DMATransfer(handleSport5B, &outputDescriptor1Sport5B, 1, ADI_PDMA_STOP_MODE, ADI_SPORT_CHANNEL_PRIM_SEC);
gpioDebug0Clear();
}
}
Could you give any recomendation on how to properly align Tx and Rx interruptions (and buffers management in DMA operation) so that I can take an entire sampling cycle (4 samples in TDM4) to execute my required DSP processing? Without loosing a considerable part of the availale time just because of the current missalignment?
Thank you very much
