//***************************************************************************** // //! Handles the I2S sound interrupt. //! //! This function services the I2S interrupt and ensures that DMA buffers are //! correctly handled to ensure smooth flow of audio data to the DAC. //! //! \return None. // //***************************************************************************** void SoundIntHandler(void) { unsigned long ulStatus; unsigned long *pulTemp; // // Get the interrupt status and clear any pending interrupts. // ulStatus = I2SIntStatus(I2S0_BASE, 1); // // Clear out any interrupts. // I2SIntClear(I2S0_BASE, ulStatus); // // Handle the TX channel interrupt // if(HWREGBITW(&g_ulDMAFlags, FLAG_TX_PENDING)) { // // If the TX DMA is done, then call the callback if present. // if(ROM_uDMAChannelModeGet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT) == UDMA_MODE_STOP) { // // Save a temp pointer so that the current pointer can be set to // zero before calling the callback. // pulTemp = (unsigned long *)g_sBuffers[0].pulData; // // If at the mid point then refill the first half of the buffer. // if((g_sBuffers[0].pfnBufferCallback) && (g_sBuffers[0].pulData != 0)) { g_sBuffers[0].pulData = 0; g_sBuffers[0].pfnBufferCallback(pulTemp, BUFFER_EVENT_FREE); } } // // If the TX DMA is done, then call the callback if present. // if(ROM_uDMAChannelModeGet(UDMA_CHANNEL_I2S0TX | UDMA_ALT_SELECT) == UDMA_MODE_STOP) { // // Save a temp pointer so that the current pointer can be set to // zero before calling the callback. // pulTemp = (unsigned long *)g_sBuffers[1].pulData; // // If at the mid point then refill the first half of the buffer. // if((g_sBuffers[1].pfnBufferCallback) && (g_sBuffers[1].pulData != 0)) { g_sBuffers[1].pulData = 0; g_sBuffers[1].pfnBufferCallback(pulTemp, BUFFER_EVENT_FREE); } } // // If no more buffers are pending then clear the flag. // if((g_sBuffers[0].pulData == 0) && (g_sBuffers[1].pulData == 0)) { HWREGBITW(&g_ulDMAFlags, FLAG_TX_PENDING) = 0; } } }
//***************************************************************************** // //! Handles the I2S sound interrupt. //! //! This function services the I2S interrupt and will call the callback function //! provided with the buffer that was given to the SoundBufferPlay() or //! SoundBufferRead() functions to handle emptying or filling the buffers and //! starting up DMA transfers again. It is solely the responsibility of the //! callback functions to continuing sending or receiving data to or from the //! audio codec. //! //! \return None. // //***************************************************************************** void SoundIntHandler(void) { unsigned long ulStatus; unsigned long *pulTemp; // // Get the interrupt status and clear any pending interrupts. // ulStatus = I2SIntStatus(I2S0_BASE, 1); // // Clear out any interrupts. // I2SIntClear(I2S0_BASE, ulStatus); // // Handle the RX channel interrupt // if(HWREGBITW(&g_ulDMAFlags, FLAG_RX_PENDING)) { // // If the RX DMA is done, then start another one using the same // RX buffer. This keeps the RX running continuously. // if(uDMAChannelModeGet(UDMA_CHANNEL_I2S0RX | UDMA_PRI_SELECT) == UDMA_MODE_STOP) { // // Save a temp pointer so that the current pointer can be set to // zero before calling the callback. // pulTemp = g_sInBuffers[0].pulData; // // If at the mid point the refill the first half of the buffer. // if(g_sInBuffers[0].pfnBufferCallback) { g_sInBuffers[0].pulData = 0; g_sInBuffers[0].pfnBufferCallback(pulTemp, BUFFER_EVENT_FULL); } } else if(uDMAChannelModeGet(UDMA_CHANNEL_I2S0RX | UDMA_ALT_SELECT) == UDMA_MODE_STOP) { // // Save a temp pointer so that the current pointer can be set to // zero before calling the callback. // pulTemp = g_sInBuffers[1].pulData; // // If at the mid point the refill the first half of the buffer. // if(g_sInBuffers[1].pfnBufferCallback) { g_sInBuffers[1].pulData = 0; g_sInBuffers[1].pfnBufferCallback(pulTemp, BUFFER_EVENT_FULL); } } // // If there are no more scheduled buffers then there are no more // pending DMA transfers. // if((g_sInBuffers[0].pulData == 0) && (g_sInBuffers[1].pulData == 0)) { HWREGBITW(&g_ulDMAFlags, FLAG_RX_PENDING) = 0; } } // // Handle the TX channel interrupt // if(HWREGBITW(&g_ulDMAFlags, FLAG_TX_PENDING)) { // // If the TX DMA is done, then call the callback if present. // if(uDMAChannelModeGet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT) == UDMA_MODE_STOP) { // // Save a temp pointer so that the current pointer can be set to // zero before calling the callback. // pulTemp = g_sOutBuffers[0].pulData; // // If at the mid point then refill the first half of the buffer. // if((g_sOutBuffers[0].pfnBufferCallback) && (g_sOutBuffers[0].pulData != 0)) { g_sOutBuffers[0].pulData = 0; g_sOutBuffers[0].pfnBufferCallback(pulTemp, BUFFER_EVENT_FREE); } } // // If the TX DMA is done, then call the callback if present. // if(uDMAChannelModeGet(UDMA_CHANNEL_I2S0TX | UDMA_ALT_SELECT) == UDMA_MODE_STOP) { // // Save a temporary pointer so that the current pointer can be set // to zero before calling the callback. // pulTemp = g_sOutBuffers[1].pulData; // // If at the mid point then refill the first half of the buffer. // if((g_sOutBuffers[1].pfnBufferCallback) && (g_sOutBuffers[1].pulData != 0)) { g_sOutBuffers[1].pulData = 0; g_sOutBuffers[1].pfnBufferCallback(pulTemp, BUFFER_EVENT_FREE); } } // // If no more buffers are pending then clear the flag. // if((g_sOutBuffers[0].pulData == 0) && (g_sOutBuffers[1].pulData == 0)) { HWREGBITW(&g_ulDMAFlags, FLAG_TX_PENDING) = 0; } } }