void AudioOutputI2S2::isr(void) { int16_t *dest, *dc; audio_block_t *blockL, *blockR; uint32_t saddr, offsetL, offsetR; saddr = (uint32_t)(dma.TCD->SADDR); dma.clearInterrupt(); if (saddr < (uint32_t)i2s2_tx_buffer + sizeof(i2s2_tx_buffer) / 2) { // DMA is transmitting the first half of the buffer // so we must fill the second half dest = (int16_t *)&i2s2_tx_buffer[AUDIO_BLOCK_SAMPLES/2]; if (AudioOutputI2S2::update_responsibility) AudioStream::update_all(); } else { // DMA is transmitting the second half of the buffer // so we must fill the first half dest = (int16_t *)i2s2_tx_buffer; } blockL = AudioOutputI2S2::block_left_1st; blockR = AudioOutputI2S2::block_right_1st; offsetL = AudioOutputI2S2::block_left_offset; offsetR = AudioOutputI2S2::block_right_offset; if (blockL && blockR) { memcpy_tointerleaveLR(dest, blockL->data + offsetL, blockR->data + offsetR); offsetL += AUDIO_BLOCK_SAMPLES / 2; offsetR += AUDIO_BLOCK_SAMPLES / 2; } else if (blockL) { memcpy_tointerleaveL(dest, blockL->data + offsetL); offsetL += AUDIO_BLOCK_SAMPLES / 2; } else if (blockR) { memcpy_tointerleaveR(dest, blockR->data + offsetR); offsetR += AUDIO_BLOCK_SAMPLES / 2; } else { memset(dest,0,AUDIO_BLOCK_SAMPLES * 2); } #if IMXRT_CACHE_ENABLED >= 2 arm_dcache_flush_delete(dest, sizeof(i2s2_tx_buffer) / 2 ); #endif if (offsetL < AUDIO_BLOCK_SAMPLES) { AudioOutputI2S2::block_left_offset = offsetL; } else { AudioOutputI2S2::block_left_offset = 0; AudioStream::release(blockL); AudioOutputI2S2::block_left_1st = AudioOutputI2S2::block_left_2nd; AudioOutputI2S2::block_left_2nd = NULL; } if (offsetR < AUDIO_BLOCK_SAMPLES) { AudioOutputI2S2::block_right_offset = offsetR; } else { AudioOutputI2S2::block_right_offset = 0; AudioStream::release(blockR); AudioOutputI2S2::block_right_1st = AudioOutputI2S2::block_right_2nd; AudioOutputI2S2::block_right_2nd = NULL; } }
void AudioOutputI2S::isr(void) { #if defined(KINETISK) int16_t *dest; audio_block_t *blockL, *blockR; uint32_t saddr, offsetL, offsetR; saddr = (uint32_t)(dma.TCD->SADDR); dma.clearInterrupt(); if (saddr < (uint32_t)i2s_tx_buffer + sizeof(i2s_tx_buffer) / 2) { // DMA is transmitting the first half of the buffer // so we must fill the second half dest = (int16_t *)&i2s_tx_buffer[AUDIO_BLOCK_SAMPLES/2]; if (AudioOutputI2S::update_responsibility) AudioStream::update_all(); } else { // DMA is transmitting the second half of the buffer // so we must fill the first half dest = (int16_t *)i2s_tx_buffer; } blockL = AudioOutputI2S::block_left_1st; blockR = AudioOutputI2S::block_right_1st; offsetL = AudioOutputI2S::block_left_offset; offsetR = AudioOutputI2S::block_right_offset; if (blockL && blockR) { memcpy_tointerleaveLR(dest, blockL->data + offsetL, blockR->data + offsetR); offsetL += AUDIO_BLOCK_SAMPLES / 2; offsetR += AUDIO_BLOCK_SAMPLES / 2; } else if (blockL) { memcpy_tointerleaveL(dest, blockL->data + offsetL); offsetL += AUDIO_BLOCK_SAMPLES / 2; } else if (blockR) { memcpy_tointerleaveR(dest, blockR->data + offsetR); offsetR += AUDIO_BLOCK_SAMPLES / 2; } else { memset(dest,0,AUDIO_BLOCK_SAMPLES * 2); return; } if (offsetL < AUDIO_BLOCK_SAMPLES) { AudioOutputI2S::block_left_offset = offsetL; } else { AudioOutputI2S::block_left_offset = 0; AudioStream::release(blockL); AudioOutputI2S::block_left_1st = AudioOutputI2S::block_left_2nd; AudioOutputI2S::block_left_2nd = NULL; } if (offsetR < AUDIO_BLOCK_SAMPLES) { AudioOutputI2S::block_right_offset = offsetR; } else { AudioOutputI2S::block_right_offset = 0; AudioStream::release(blockR); AudioOutputI2S::block_right_1st = AudioOutputI2S::block_right_2nd; AudioOutputI2S::block_right_2nd = NULL; } #else const int16_t *src, *end; int16_t *dest; audio_block_t *block; uint32_t saddr, offset; saddr = (uint32_t)(dma.CFG->SAR); dma.clearInterrupt(); if (saddr < (uint32_t)i2s_tx_buffer + sizeof(i2s_tx_buffer) / 2) { // DMA is transmitting the first half of the buffer // so we must fill the second half dest = (int16_t *)&i2s_tx_buffer[AUDIO_BLOCK_SAMPLES/2]; end = (int16_t *)&i2s_tx_buffer[AUDIO_BLOCK_SAMPLES]; if (AudioOutputI2S::update_responsibility) AudioStream::update_all(); } else { // DMA is transmitting the second half of the buffer // so we must fill the first half dest = (int16_t *)i2s_tx_buffer; end = (int16_t *)&i2s_tx_buffer[AUDIO_BLOCK_SAMPLES/2]; } block = AudioOutputI2S::block_left_1st; if (block) { offset = AudioOutputI2S::block_left_offset; src = &block->data[offset]; do { *dest = *src++; dest += 2; } while (dest < end); offset += AUDIO_BLOCK_SAMPLES/2; if (offset < AUDIO_BLOCK_SAMPLES) { AudioOutputI2S::block_left_offset = offset; } else { AudioOutputI2S::block_left_offset = 0; AudioStream::release(block); AudioOutputI2S::block_left_1st = AudioOutputI2S::block_left_2nd; AudioOutputI2S::block_left_2nd = NULL; } } else { do { *dest = 0; dest += 2; } while (dest < end); } dest -= AUDIO_BLOCK_SAMPLES - 1; block = AudioOutputI2S::block_right_1st; if (block) { offset = AudioOutputI2S::block_right_offset; src = &block->data[offset]; do { *dest = *src++; dest += 2; } while (dest < end); offset += AUDIO_BLOCK_SAMPLES/2; if (offset < AUDIO_BLOCK_SAMPLES) { AudioOutputI2S::block_right_offset = offset; } else { AudioOutputI2S::block_right_offset = 0; AudioStream::release(block); AudioOutputI2S::block_right_1st = AudioOutputI2S::block_right_2nd; AudioOutputI2S::block_right_2nd = NULL; } } else { do { *dest = 0; dest += 2; } while (dest < end); } #endif }
void AudioOutputPT8211::isr(void) { int16_t *dest; audio_block_t *blockL, *blockR; uint32_t saddr, offsetL, offsetR; saddr = (uint32_t)(dma.TCD->SADDR); dma.clearInterrupt(); if (saddr < (uint32_t)i2s_tx_buffer + sizeof(i2s_tx_buffer) / 2) { // DMA is transmitting the first half of the buffer // so we must fill the second half #if defined(AUDIO_PT8211_OVERSAMPLING) dest = (int16_t *)&i2s_tx_buffer[(AUDIO_BLOCK_SAMPLES/2)*4]; #else dest = (int16_t *)&i2s_tx_buffer[AUDIO_BLOCK_SAMPLES/2]; #endif if (AudioOutputPT8211::update_responsibility) AudioStream::update_all(); } else { // DMA is transmitting the second half of the buffer // so we must fill the first half dest = (int16_t *)i2s_tx_buffer; } blockL = AudioOutputPT8211::block_left_1st; blockR = AudioOutputPT8211::block_right_1st; offsetL = AudioOutputPT8211::block_left_offset; offsetR = AudioOutputPT8211::block_right_offset; #if defined(AUDIO_PT8211_OVERSAMPLING) static int32_t oldL = 0; static int32_t oldR = 0; #endif if (blockL && blockR) { #if defined(AUDIO_PT8211_OVERSAMPLING) #if defined(AUDIO_PT8211_INTERPOLATION_LINEAR) for (int i=0; i< AUDIO_BLOCK_SAMPLES / 2; i++, offsetL++, offsetR++) { int32_t valL = blockL->data[offsetL]; int32_t valR = blockR->data[offsetR]; int32_t nL = (oldL+valL) >> 1; int32_t nR = (oldR+valR) >> 1; *(dest+0) = (oldL+nL) >> 1; *(dest+1) = (oldR+nR) >> 1; *(dest+2) = nL; *(dest+3) = nR; *(dest+4) = (nL+valL) >> 1; *(dest+5) = (nR+valR) >> 1; *(dest+6) = valL; *(dest+7) = valR; dest+=8; oldL = valL; oldR = valR; } #elif defined(AUDIO_PT8211_INTERPOLATION_CIC) for (int i=0; i< AUDIO_BLOCK_SAMPLES / 2; i++, offsetL++, offsetR++) { int32_t valL = blockL->data[offsetL]; int32_t valR = blockR->data[offsetR]; int32_t combL[3] = {0}; static int32_t combLOld[2] = {0}; int32_t combR[3] = {0}; static int32_t combROld[2] = {0}; combL[0] = valL - oldL; combR[0] = valR - oldR; combL[1] = combL[0] - combLOld[0]; combR[1] = combR[0] - combROld[0]; combL[2] = combL[1] - combLOld[1]; combR[2] = combR[1] - combROld[1]; // combL[2] now holds input val // combR[2] now holds input val oldL = valL; oldR = valR; combLOld[0] = combL[0]; combROld[0] = combR[0]; combLOld[1] = combL[1]; combROld[1] = combR[1]; for (int j = 0; j < 4; j++) { int32_t integrateL[3]; int32_t integrateR[3]; static int32_t integrateLOld[3] = {0}; static int32_t integrateROld[3] = {0}; integrateL[0] = ( (j==0) ? (combL[2]) : (0) ) + integrateLOld[0]; integrateR[0] = ( (j==0) ? (combR[2]) : (0) ) + integrateROld[0]; integrateL[1] = integrateL[0] + integrateLOld[1]; integrateR[1] = integrateR[0] + integrateROld[1]; integrateL[2] = integrateL[1] + integrateLOld[2]; integrateR[2] = integrateR[1] + integrateROld[2]; // integrateL[2] now holds j'th upsampled value // integrateR[2] now holds j'th upsampled value *(dest+j*2) = integrateL[2] >> 4; *(dest+j*2+1) = integrateR[2] >> 4; integrateLOld[0] = integrateL[0]; integrateROld[0] = integrateR[0]; integrateLOld[1] = integrateL[1]; integrateROld[1] = integrateR[1]; integrateLOld[2] = integrateL[2]; integrateROld[2] = integrateR[2]; } dest+=8; } #else #error no interpolation method defined for oversampling. #endif //defined(AUDIO_PT8211_INTERPOLATION_LINEAR) #else memcpy_tointerleaveLR(dest, blockL->data + offsetL, blockR->data + offsetR); offsetL += AUDIO_BLOCK_SAMPLES / 2; offsetR += AUDIO_BLOCK_SAMPLES / 2; #endif //defined(AUDIO_PT8211_OVERSAMPLING) } else if (blockL) {