SAME70 SSC Read and Write fail

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Deer Atmel,

I try use SSC to communication with codec (NAU8822) in both way - read stream data from codec ADC, process it and send data to codec DAC. I have in mind figure 44-4 from datasheet SAM-E70-S70-V70-V71-Family-Data-Sheet-DS60001527D.pdf on page 1114 but i use ssc in I2S mode.

SAME70Q21A SSC work as slave, codec is master and delivery bitclock and frame signal (and ofc data).

First question in - how to fire receive start trigger if i have not connection beetwen RF and TF and beetwen RK and TK? I try use REG_SSC_RCMR_START_RECEIVE option. But i do not know it is proper way.

I think transmiter configuration is good, it can receive packet data from ethernet and send it to codec with perfect sound quality. Ofc i use xdmac and it work good.

For this communication i config two xdmac channels, 0 and 1, one read data from ssc_rhr and store it info RxAudioBuffer and second channel transmit data from memory TxAudioBuffer to ssc_thr. It seems to work good. 

But sound quality is terrible. I spent some time with osc-scope and look at this picture.

SAME70 SSC

 

Yellow - frame sync signal from codec.

Auzre - bitclock signal from codec.

Blue - data stream from codec.

Purple - signal from SSC to codec.

 

In purple timming i can see one additional high state - this state is near always present on ossc-scope. I think it is reason of sound is terrible quality. But i cant find source of werid add-state.

 

#define BITS_BY_SLOT	16
#define TOTAL_BUFFERS	4
#define MAX_DMA_SIZE	500

#define XDMA_SSC_TX_CH	0
#define XDMA_SSC_RX_CH	1

COMPILER_ALIGNED(8)
lld_view1 linklist_write[TOTAL_BUFFERS];
lld_view1 linklist_read[TOTAL_BUFFERS];

COMPILER_ALIGNED(8)
uint16_t TxAudioBuffer[TOTAL_BUFFERS][MAX_DMA_SIZE * (BITS_BY_SLOT/8)];
uint16_t RxAudioBuffer[TOTAL_BUFFERS][MAX_DMA_SIZE * (BITS_BY_SLOT/8)];

uint8_t volatile rcb = 1;
uint8_t volatile nrcb = 0;

uint8_t volatile tcb = 1;
uint8_t volatile ntcb = 0;

void XDMAC_Handler(void)
{
	uint32_t volatile xdmac_gis = xdmac_get_interrupt_status(XDMAC);
	UNUSED(xdmac_gis);

	xdmac_chan_0_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_SSC_TX_CH);
	if( xdmac_chan_0_status == 1){
		rcb++;
		if(rcb > TOTAL_BUFFERS){
			rcb = 1;
		};
	}else{
		if(xdmac_chan_0_status > 1){
			//LED_CLR;
		};
	};

	xdmac_chan_1_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_SSC_RX_CH);
	if( xdmac_chan_1_status == 1){
		tcb++;
		if(tcb > TOTAL_BUFFERS){
			tcb = 1;
		};
	}else{
		if(xdmac_chan_1_status > 1){
			LED_CLR;
		};
	};
};

// main
pmc_enable_periph_clk(ID_SSC);

pio_configure(PIOD, PIO_PERIPH_B, PIO_PD26, 0); // TD, per b, transmit data to codec
pio_configure(PIOB, PIO_PERIPH_D, PIO_PB1, 0);	// TK, per d, clock, from codec
pio_configure(PIOB, PIO_PERIPH_D, PIO_PB0, 0);	// TF, per d, frame sync

pio_configure(PIOA, PIO_PERIPH_C, PIO_PA10, 0);	// RD, per c, receive data from codec

ssc_reset(SSC);
ssc_i2s_set_transmitter(SSC, SSC_I2S_SLAVE_OUT, SSC_TCMR_CKS_TK, SSC_AUDIO_STERO, 16);
ssc_i2s_set_receiver(SSC, SSC_I2S_SLAVE_IN, SSC_RCMR_CKS_TK, SSC_AUDIO_STERO, 16);

/* but in reveiver actualy is, otherwise it is not work
rx_clk_option.ul_start_sel = SSC_RCMR_START_CONTINUOUS;
*/

ssc_disable_tx(SSC);
ssc_disable_rx(SSC);

pmc_enable_periph_clk(ID_XDMAC);
xdmac_channel_disable(XDMAC, XDMA_SSC_TX_CH);
xdmac_channel_disable(XDMAC, XDMA_SSC_RX_CH);

xdmac_ssc_tx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
							| XDMAC_CC_MBSIZE_SINGLE
							| XDMAC_CC_DSYNC_MEM2PER
							| XDMAC_CC_CSIZE_CHK_1
							| XDMAC_CC_DWIDTH_HALFWORD
							| XDMAC_CC_SWREQ_HWR_CONNECTED
							| XDMAC_CC_SIF_AHB_IF0
							| XDMAC_CC_DIF_AHB_IF1
							| XDMAC_CC_SAM_INCREMENTED_AM
							| XDMAC_CC_DAM_FIXED_AM
							| XDMAC_CC_PERID(XDMAC_CHANNEL_HWID_SSC_TX);

xdmac_ssc_rx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
							| XDMAC_CC_MBSIZE_SINGLE
							| XDMAC_CC_DSYNC_PER2MEM
							| XDMAC_CC_CSIZE_CHK_1
							| XDMAC_CC_DWIDTH_HALFWORD
							| XDMAC_CC_SWREQ_HWR_CONNECTED
							| XDMAC_CC_SIF_AHB_IF1
							| XDMAC_CC_DIF_AHB_IF0
							| XDMAC_CC_SAM_FIXED_AM
							| XDMAC_CC_DAM_INCREMENTED_AM
							| XDMAC_CC_PERID(XDMAC_CHANNEL_HWID_SSC_RX);

xdmac_configure_transfer(XDMAC, XDMA_SSC_TX_CH, &xdmac_ssc_tx_cfg);
xdmac_configure_transfer(XDMAC, XDMA_SSC_RX_CH, &xdmac_ssc_rx_cfg);

for(uint32_t i = 0; i < TOTAL_BUFFERS; i++) {
	linklist_write[i].mbr_ubc =	XDMAC_UBC_NVIEW_NDV1 |
								XDMAC_UBC_NDE_FETCH_EN |
								XDMAC_UBC_NSEN_UPDATED |
								XDMAC_UBC_NDEN_UNCHANGED |
								XDMAC_CUBC_UBLEN(MAX_DMA_SIZE);

	linklist_write[i].mbr_sa = (uint32_t)(&TxAudioBuffer[i]);
	linklist_write[i].mbr_da  = (uint32_t)&(SSC->SSC_THR);

	if ( i == (TOTAL_BUFFERS - 1)) {
		linklist_write[i].mbr_nda = ((uint32_t)&linklist_write[0]);
	}else{
		linklist_write[i].mbr_nda = ((uint32_t)&linklist_write[i + 1]);
	};
};

for(uint32_t i = 0; i < TOTAL_BUFFERS; i++){
	linklist_read[i].mbr_ubc =	XDMAC_UBC_NVIEW_NDV1 |
								XDMAC_UBC_NDE_FETCH_EN |
								XDMAC_UBC_NSEN_UNCHANGED |
								XDMAC_UBC_NDEN_UPDATED |
								XDMAC_CUBC_UBLEN(MAX_DMA_SIZE);

	linklist_read[i].mbr_sa = (uint32_t)&(SSC->SSC_RHR);
	linklist_read[i].mbr_da = (uint32_t)(&RxAudioBuffer[i]);

	if( i == (TOTAL_BUFFERS - 1)){
		linklist_read[i].mbr_nda = ((uint32_t)&linklist_read[0]);
	}else{
		linklist_read[i].mbr_nda = ((uint32_t)&linklist_read[i + 1]);
	};
};

xdmac_channel_set_descriptor_addr(XDMAC, XDMA_SSC_TX_CH, (uint32_t)(&linklist_write[0]), 0);
xdmac_channel_set_descriptor_addr(XDMAC, XDMA_SSC_RX_CH, (uint32_t)(&linklist_read[0]), 0);

xdmac_channel_set_descriptor_control(XDMAC, XDMA_SSC_TX_CH, XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | XDMAC_CNDC_NDDUP_DST_PARAMS_UNCHANGED);
xdmac_channel_set_descriptor_control(XDMAC, XDMA_SSC_RX_CH, XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED);

xdmac_enable_interrupt(XDMAC, XDMA_SSC_TX_CH);
xdmac_enable_interrupt(XDMAC, XDMA_SSC_RX_CH);

xdmac_channel_enable_interrupt(XDMAC, XDMA_SSC_TX_CH, XDMAC_CIE_BIE | XDMAC_CIE_LIE | XDMAC_CIE_DIE | XDMAC_CIE_FIE | XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE);
xdmac_channel_enable_interrupt(XDMAC, XDMA_SSC_RX_CH, XDMAC_CIE_BIE | XDMAC_CIE_LIE | XDMAC_CIE_DIE | XDMAC_CIE_FIE | XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE);

xdmac_channel_software_flush_request(XDMAC, XDMA_SSC_TX_CH);
xdmac_channel_software_flush_request(XDMAC, XDMA_SSC_RX_CH);

ssc_enable_rx(SSC);
xdmac_channel_enable(XDMAC, XDMA_SSC_RX_CH);

ssc_enable_tx(SSC);
xdmac_channel_enable(XDMAC, XDMA_SSC_TX_CH);

irq_initialize_vectors();

irq_register_handler(XDMAC_IRQn, 1);

Enable_global_interrupt();

while(1){
		if(rcb != nrcb){
		if(tcb != ntcb){
			for(uint16_t volatile i=0; i<MAX_DMA_SIZE; i++){
				TxAudioBuffer[rcb][i] = RxAudioBuffer[tcb][i];
			};
		};

		nrcb = rcb;
		ntcb = tcb;
	};
};

 

Edit: can i please someone to move topic to proper forum? There is Cortex-M not ARM7 uC.

Last Edited: Tue. Mar 17, 2020 - 05:53 PM