00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 #include "board.h"
00089
00090
00091
00092
00093 #define I2S_SLAVE_TX_SETTING ((SSC_TCMR_CKS_TK) | \
00094 (SSC_TCMR_CKO_NONE) | \
00095 (SSC_TCMR_START_TF_EDGE) | \
00096 (SSC_TCMR_STTDLY(1)) | \
00097 (SSC_TCMR_PERIOD(0)))
00098
00099 #define I2S_SLAVE_TX_FRM_SETTING ((SSC_TFMR_DATLEN(BITS_BY_SLOT - 1)) | \
00100 (SSC_TFMR_MSBF) | \
00101 (SSC_TFMR_DATNB(SLOT_BY_FRAME - 1)) | \
00102 (SSC_TFMR_FSOS_NONE))
00103
00104
00105 #define I2S_SLAVE_RX_SETTING ((SSC_RCMR_CKS_TK) | \
00106 (SSC_RCMR_CKO_NONE) | \
00107 (SSC_RCMR_CKI) | \
00108 (SSC_RCMR_START_RF_EDGE) | \
00109 (SSC_RCMR_STTDLY(1)) | \
00110 (SSC_RCMR_PERIOD(0)))
00111
00112 #define I2S_SLAVE_RX_FRM_SETTING ((SSC_RFMR_DATLEN(BITS_BY_SLOT - 1)) | \
00113 (SSC_RFMR_MSBF) | \
00114 (SSC_RFMR_DATNB(SLOT_BY_FRAME - 1)) | \
00115 (SSC_RFMR_FSOS_NONE))
00116
00117
00118
00119 #define SSC_MCK BOARD_MCK
00120
00121
00122 #define MAX_RECORD_SIZE 0xFFFFFFFF
00123
00124
00125 #define MAX_DMA_SIZE 0x1000
00126
00127
00128 #define TWI_CLOCK 400000
00129
00130
00131 #define SAMPLE_RATE (48000)
00132 #define SLOT_BY_FRAME (1)
00133 #define BITS_BY_SLOT (16)
00134
00135
00136 #define TOTAL_Buffers 4
00137 #define AUDIO_IF SSC
00138
00139
00140
00141
00142
00143
00144 static const Pin pinsSsc[] = {PIN_TWI_TWD0, PIN_TWI_TWCK0, PIN_SSC_TD,
00145 PIN_SSC_TK, PIN_SSC_TF, PIN_SSC_RD, PIN_SSC_RK, PIN_SSC_RF, PIN_PCK2};
00146
00147
00148 static sXdmad dmad;
00149
00150 static uint32_t sscDmaRxChannel;
00151
00152 static uint32_t sscDmaTxChannel;
00153
00154 static sXdmadCfg xdmadCfg;
00155
00156 COMPILER_ALIGNED(32) static LinkedListDescriporView1 dmaWriteLinkList[TOTAL_Buffers];
00157 COMPILER_ALIGNED(32) static LinkedListDescriporView1 dmaReadLinkList[TOTAL_Buffers];
00158
00159
00160 static Twid twid;
00161
00162 static uint16_t AudioBuffer[TOTAL_Buffers*MAX_DMA_SIZE * (BITS_BY_SLOT / 8)];
00163
00164 static uint8_t buf_flag = 1;
00165
00166 static bool cpu_flag = false;
00167
00168 static uint32_t AudioNextBuffer[TOTAL_Buffers] = {0};
00169
00170
00171
00172
00173
00174
00175
00176
00177 void XDMAC_Handler(void)
00178 {
00179 XDMAD_Handler(&dmad);
00180 }
00181
00182
00183
00184
00185 void TWIHS0_Handler(void)
00186 {
00187 TWID_Handler(&twid);
00188 }
00189
00190
00191
00192
00193 static void sscDmaRxClk(uint32_t Channel, void* pArg)
00194 {
00195
00196 Channel = Channel;
00197 pArg = pArg;
00198
00199 if (cpu_flag) {
00200 if (AudioNextBuffer[buf_flag] == 0)
00201 AudioNextBuffer[buf_flag] = (dmad.pXdmacs->XDMAC_CHID[sscDmaRxChannel].XDMAC_CNDA);
00202 else {
00203 TRACE_WARNING("DMA is faster than CPU-%d\n\r",buf_flag);
00204 AudioNextBuffer[buf_flag] = (dmad.pXdmacs->XDMAC_CHID[sscDmaRxChannel].XDMAC_CNDA);
00205 }
00206 }
00207
00208 buf_flag++;
00209 if (buf_flag == TOTAL_Buffers) {
00210 buf_flag = 0;
00211
00212 cpu_flag = true;
00213 }
00214 }
00215
00216
00217
00218
00219 static void Dma_configure(void)
00220 {
00221 sXdmad *pDmad = &dmad;
00222
00223
00224 XDMAD_Initialize( pDmad, 0);
00225
00226 NVIC_ClearPendingIRQ(XDMAC_IRQn);
00227 NVIC_EnableIRQ(XDMAC_IRQn);
00228
00229 sscDmaTxChannel = XDMAD_AllocateChannel(pDmad, XDMAD_TRANSFER_MEMORY, ID_SSC);
00230 sscDmaRxChannel = XDMAD_AllocateChannel(pDmad, ID_SSC, XDMAD_TRANSFER_MEMORY);
00231 if (sscDmaTxChannel == XDMAD_ALLOC_FAILED
00232 || sscDmaRxChannel == XDMAD_ALLOC_FAILED) {
00233 printf("xDMA channel allocation error\n\r");
00234 while (1);
00235 }
00236
00237 XDMAD_SetCallback( pDmad, sscDmaRxChannel, sscDmaRxClk, 0);
00238 XDMAD_PrepareChannel(pDmad, sscDmaTxChannel);
00239 XDMAD_PrepareChannel(pDmad, sscDmaRxChannel);
00240 }
00241
00242
00243
00244
00245
00246 static void PlayRecording(void)
00247 {
00248 uint16_t *src;
00249 uint8_t i;
00250 uint32_t xdmaCndc;
00251
00252 src = &AudioBuffer[0];
00253 for (i = 0; i < TOTAL_Buffers; i++) {
00254 dmaReadLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1
00255 | XDMA_UBC_NDE_FETCH_EN
00256 | XDMA_UBC_NSEN_UPDATED
00257 | XDMAC_CUBC_UBLEN(MAX_DMA_SIZE);
00258 dmaReadLinkList[i].mbr_sa = (uint32_t)&(AUDIO_IF->SSC_RHR);
00259 dmaReadLinkList[i].mbr_da = (uint32_t)(src);
00260 if (i == (TOTAL_Buffers - 1))
00261 dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[0];
00262 else
00263 dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[i + 1];
00264 src += MAX_DMA_SIZE;
00265 }
00266
00267 xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
00268 | XDMAC_CC_MBSIZE_SINGLE
00269 | XDMAC_CC_DSYNC_PER2MEM
00270 | XDMAC_CC_CSIZE_CHK_1
00271 | XDMAC_CC_DWIDTH_HALFWORD
00272 | XDMAC_CC_SIF_AHB_IF1
00273 | XDMAC_CC_DIF_AHB_IF1
00274 | XDMAC_CC_SAM_FIXED_AM
00275 | XDMAC_CC_DAM_INCREMENTED_AM
00276 | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_SSC, XDMAD_TRANSFER_RX));
00277 xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1
00278 | XDMAC_CNDC_NDE_DSCR_FETCH_EN
00279 | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00280 | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
00281
00282 SCB_CleanDCache_by_Addr((uint32_t *)dmaReadLinkList, sizeof(dmaReadLinkList));
00283
00284
00285 XDMAD_ConfigureTransfer( &dmad, sscDmaRxChannel, &xdmadCfg, xdmaCndc,
00286 (uint32_t)&dmaReadLinkList[0], XDMAC_CIE_BIE);
00287
00288
00289 src = &AudioBuffer[0];
00290 for (i = 0; i < TOTAL_Buffers; i++) {
00291 dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1
00292 | XDMA_UBC_NDE_FETCH_EN
00293 | XDMA_UBC_NSEN_UPDATED
00294 | XDMAC_CUBC_UBLEN(MAX_DMA_SIZE);
00295 dmaWriteLinkList[i].mbr_sa = (uint32_t)(src);
00296 dmaWriteLinkList[i].mbr_da = (uint32_t)&(AUDIO_IF->SSC_THR);
00297 if (i == (TOTAL_Buffers - 1))
00298 dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0];
00299 else
00300 dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i + 1];
00301 src += MAX_DMA_SIZE;
00302 }
00303
00304 xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
00305 | XDMAC_CC_MBSIZE_SINGLE
00306 | XDMAC_CC_DSYNC_MEM2PER
00307 | XDMAC_CC_CSIZE_CHK_1
00308 | XDMAC_CC_DWIDTH_HALFWORD
00309 | XDMAC_CC_SIF_AHB_IF1
00310 | XDMAC_CC_DIF_AHB_IF1
00311 | XDMAC_CC_SAM_INCREMENTED_AM
00312 | XDMAC_CC_DAM_FIXED_AM
00313 | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_SSC, XDMAD_TRANSFER_TX));
00314 xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1
00315 | XDMAC_CNDC_NDE_DSCR_FETCH_EN
00316 | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00317 | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
00318
00319 SCB_CleanDCache_by_Addr((uint32_t *)dmaWriteLinkList, sizeof(dmaWriteLinkList));
00320 XDMAD_ConfigureTransfer( &dmad, sscDmaTxChannel, &xdmadCfg, xdmaCndc,
00321 (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE);
00322
00323 SSC_EnableReceiver(AUDIO_IF);
00324 XDMAD_StartTransfer( &dmad, sscDmaRxChannel);
00325
00326
00327 Wait(300);
00328
00329 SSC_EnableTransmitter(AUDIO_IF);
00330 XDMAD_StartTransfer( &dmad, sscDmaTxChannel);
00331
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 int main( void )
00343 {
00344 uint16_t data = 0;
00345
00346 WDT_Disable(WDT);
00347
00348
00349 SCB_EnableICache();
00350 SCB_EnableDCache();
00351
00352
00353 printf("-- SSC DMA Audio Example %s --\n\r", SOFTPACK_VERSION);
00354 printf("-- %s\n\r", BOARD_NAME);
00355 printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__, COMPILER_NAME);
00356
00357
00358 printf( "Configure system tick to get 1ms tick period.\n\r" );
00359 if (TimeTick_Configure())
00360 printf("-F- Systick configuration error\n\r" );
00361
00362
00363 PIO_Configure(pinsSsc, PIO_LISTSIZE(pinsSsc));
00364
00365
00366 SSC_Configure(AUDIO_IF , 0 , SSC_MCK);
00367 SSC_ConfigureReceiver(AUDIO_IF,I2S_SLAVE_RX_SETTING,I2S_SLAVE_RX_FRM_SETTING);
00368 SSC_DisableReceiver(AUDIO_IF);
00369 SSC_ConfigureTransmitter(AUDIO_IF,I2S_SLAVE_TX_SETTING,I2S_SLAVE_TX_FRM_SETTING);
00370 SSC_DisableTransmitter(AUDIO_IF);
00371
00372
00373 Dma_configure();
00374
00375
00376 PMC_EnablePeripheral(ID_TWIHS0);
00377 TWI_ConfigureMaster(TWIHS0, TWI_CLOCK, BOARD_MCK);
00378 TWID_Initialize(&twid, TWIHS0);
00379
00380 NVIC_ClearPendingIRQ(TWIHS0_IRQn);
00381 NVIC_EnableIRQ(TWIHS0_IRQn);
00382
00383
00384 WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, 22, 0);
00385 data=WM8904_Read(&twid, WM8904_SLAVE_ADDRESS, 0);
00386 if (data != 0x8904) {
00387 printf("WM8904 not found!\n\r");
00388 while (1);
00389 }
00390
00391 WM8904_Init(&twid, WM8904_SLAVE_ADDRESS, PMC_MCKR_CSS_SLOW_CLK);
00392
00393
00394 PMC_ConfigurePCK2(PMC_MCKR_CSS_SLOW_CLK, PMC_MCKR_PRES_CLK_1);
00395 printf("Insert Line-in cable with PC Headphone output\n\r");
00396 PlayRecording();
00397
00398 while (1) {
00399 if (cpu_flag == true) {
00400 if (AudioNextBuffer[(buf_flag + (TOTAL_Buffers - 1)) %
00401 (TOTAL_Buffers)] != 0) {
00402
00403
00404 SCB_InvalidateDCache_by_Addr((uint32_t *)AudioNextBuffer[buf_flag - 1],
00405 MAX_DMA_SIZE * (BITS_BY_SLOT / 8));
00406
00407 AudioNextBuffer[(buf_flag + (TOTAL_Buffers - 1)) % (TOTAL_Buffers)] = 0;
00408 } else {
00409 TRACE_DEBUG("AudioNextBuffer[%d] is empty\n\r",
00410 (buf_flag+(TOTAL_Buffers - 1)) % (TOTAL_Buffers));
00411 }
00412 }
00413 }
00414 }