/** audio tx isr (to be called from dispatcher) * - get chunk from tx queue * - if valid, release old pending chunk to buffer pool * - configure DMA * - if not valid, configure DMA to replay same chunk again * Parameters: * @param pThis pointer to own object * * @return None */ void audioTx_isr(void *pThisArg) { // create local casted pThis to avoid casting on every single access audioTx_t *pThis = (audioTx_t*) pThisArg; chunk_t *pchunk = NULL; // validate that TX DMA IRQ was triggered if ( *pDMA4_IRQ_STATUS & 0x1 ) { //printf("[TXISR]\n"); /* We need to remove the data from the queue and create space for more data * (The data was read previously by the DMA) 1. First, attempt to get the new chunk, and check if it's available: */ if (PASS == queue_get(&pThis->queue, (void **)&pchunk) ) { /* 2. If so, release old chunk on success back to buffer pool */ bufferPool_release(pThis->pBuffP, pThis->pPending); /* 3. Register the new chunk as pending */ pThis->pPending = pchunk; } else { //printf("[Audio TX]: TX Queue Empty! \r\n"); } *pDMA4_IRQ_STATUS |= DMA_DONE; // Clear the interrupt // config DMA either with new chunk (if there was one), or with old chunk on empty Q audioTx_dmaConfig(pThis->pPending); } }
/** audio tx put * copies filled pChunk into the TX queue for transmission * if queue is full, then chunk is dropped * Parameters: * @param pThis pointer to own object * * @return Zero on success. * Negative value on failure. */ int audioTx_put(audioTx_t *pThis, chunk_t *pChunk) { chunk_t *pchunk_temp = NULL; if ( NULL == pThis || NULL == pChunk ) { //printf("[Audio TX]: Failed to put \r\n"); return FAIL; } // block if queue is full //while(queue_is_full(&pThis->queue)) { if(queue_is_full(&pThis->queue)) { //printf("[Audio TX]: Queue Full \r\n"); return FAIL; //powerMode_change(PWR_ACTIVE); //asm("idle;"); } //powerMode_change(PWR_FULL_ON); // get free chunk from pool if ( PASS == bufferPool_acquire(pThis->pBuffP, &pchunk_temp) ) { // copy chunk into free buffer for queue chunk_copy(pChunk, pchunk_temp); /* If DMA not running ? */ if ( 0 == pThis->running ) { /* directly put chunk to DMA transfer & enable */ pThis->running = 1; pThis->pPending = pchunk_temp; audioTx_dmaConfig(pThis->pPending); ENABLE_SPORT0_TX(); } else { /* DMA already running add chunk to queue */ if ( PASS != queue_put(&pThis->queue, pchunk_temp) ) { // return chunk to pool if queue is full, effectively dropping the chunk bufferPool_release(pThis->pBuffP, pchunk_temp); return FAIL; } else { return PASS; } } } else { // drop if we don't get free space //printf("[Audio TX]: failed to get buffer \r\n"); return FAIL; } return FAIL; }
int uartRx_getChunk(uartRx_t *pThis, chunk_t *pChunk) { chunk_t *chunk_rx; queue_get(&pThis->queue, (void**)&chunk_rx); unsigned int count; unsigned int len = chunk_rx->bytesUsed; // copy manuall since memcpy does not work currently for (count = 0; len > count; count++) { pChunk->u08_buff[count] = chunk_rx->u08_buff[count]; } // update length of actual copied data pChunk->bytesUsed = chunk_rx->bytesUsed; if ( FAIL == bufferPool_release(pThis->pBuffP, chunk_rx) ) { return FAIL; } return PASS; }