mirror of
https://github.com/thelsing/knx.git
synced 2025-10-12 11:15:54 +02:00
git-subtree-dir: examples/knx-cc1310/coresdk_cc13xx_cc26xx git-subtree-split: 0d78d3280357416a5c0388148cda13717c9ffaa5
1189 lines
46 KiB
C
1189 lines
46 KiB
C
/*
|
|
* Copyright (c) 2015-2019, Texas Instruments Incorporated
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of Texas Instruments Incorporated nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/*!****************************************************************************
|
|
* @file I2S.h
|
|
* @brief Inter-Integrated Circuit Sound (I2S) Bus Driver
|
|
*
|
|
* The I2S header file should be included in an application as follows:
|
|
* @code
|
|
* #include <ti/drivers/I2S.h>
|
|
* @endcode
|
|
*
|
|
* @anchor ti_drivers_I2S_Overview
|
|
* # Overview #
|
|
*
|
|
* The I2S driver facilitates the use of Inter-IC Sound (I2S), which is
|
|
* used to connect digital audio devices so that audio signals can be
|
|
* communicated between devices. The I2S driver simplifies reading and
|
|
* writing to any of the Multichannel Audio Serial Port (McASP) peripherals
|
|
* on the board with Receive and Transmit support. These include read and
|
|
* write characters on the McASP peripheral.
|
|
*
|
|
* I2S interfaces typically consist of 4 or 5 signals. The 5th signal is not
|
|
* systematically used.
|
|
* @li <b>Serial Clock (SCK)</b> also called Bit Clock (BCLK) or Multichannel
|
|
* Audio Frame Synchronization (McAFSX)
|
|
* @li <b>Word Select (WS)</b> also called Word Clock (WCLK), Left Right
|
|
* Clock (LRCLK) or Multichannel Audio Clock (McACLK)
|
|
* @li <b>Serial Data (SD0)</b> also called AD0, AD1, McAXR0, or possibly SDI
|
|
* @li <b>Serial Data (SD1)</b> also called AD1, ADI, McAXR1, or possibly SDI
|
|
* @li <b>Master Clock (MCLK)</b>
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Usage
|
|
* # Usage #
|
|
*
|
|
* <b>The I2S driver provides the following APIs:</b>
|
|
* @li I2S_init(): @copybrief I2S_init
|
|
* @li I2S_open(): @copybrief I2S_open
|
|
* @li I2S_Params_init(): @copybrief I2S_Params_init
|
|
* @li I2S_Transaction_init(): @copybrief I2S_Transaction_init
|
|
* @li I2S_setReadQueueHead(): @copybrief I2S_setReadQueueHead
|
|
* @li I2S_startClocks(): @copybrief I2S_startClocks
|
|
* @li I2S_startRead(): @copybrief I2S_startRead
|
|
* @li I2S_stopRead(): @copybrief I2S_stopRead
|
|
* @li I2S_stopClocks(): @copybrief I2S_stopClocks
|
|
* @li I2S_close(): @copybrief I2S_close
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Driver_Transactions
|
|
* ### Transactions #
|
|
*
|
|
* Data transfers are achieved through #I2S_Transaction structures. Application is
|
|
* responsible to maintain the transactions queues. The I2S driver completes the
|
|
* transactions one by one. When a transaction is over, the I2S driver takes in
|
|
* consideration the next transaction (if the next transaction is NULL, the I2S
|
|
* drivers signals this to the user).
|
|
* The I2S driver relies on the following fields of the #I2S_Transaction to
|
|
* complete it:
|
|
* - the buffer
|
|
* - the length of the buffer
|
|
* - a pointer on the next transaction to achieve (kept in a List_Elem structure)
|
|
* .
|
|
* The I2S driver provides the following elements (fields of the #I2S_Transaction):
|
|
* - the number of untransferred bytes: the driver is designed to avoid memory corruption and will
|
|
* not complete an incomplete transaction (meaning a transaction where the buffer size would not
|
|
* permit to send or receive a whole number of samples). In this case, the system considers the
|
|
* samples of the beginning of the buffer and read/write as much as possible samples and ignore the
|
|
* end of the buffer. The number of untransafered bytes is the number of bytes left at the end of
|
|
* the buffer)
|
|
* - the number of completions of the transaction. This value is basically incremented by one
|
|
* every time the transaction is completed.
|
|
* .
|
|
* Please note that these two fields are valid only when the transaction has been completed.
|
|
* Consult examples to get more details on the transaction usage.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Driver_ProvidingData
|
|
* ### Providing data to the I2S driver #
|
|
* Application is responsible to handle the queues of transactions.
|
|
* Application is also responsible to provide to the driver a pointer on
|
|
* the first transaction to consider (considering that all the following
|
|
* transactions are correctly queued).
|
|
* #I2S_setReadQueueHead() and #I2S_setWriteQueueHead() allow the user to
|
|
* set the first transaction to consider. These functions should be used only
|
|
* when no transaction is running on the considered interface.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Driver_StartStopClocks
|
|
* ### Start and stop clocks and transactions #
|
|
* Clocks can be started and stopped by the application.
|
|
* Read and write can be started and stopped independently.
|
|
* To start a transfer, clocks must be running.
|
|
* To stop the clocks no transfer must be running.
|
|
* Refer to the following functions for more details:
|
|
* @li I2S_startClocks() @li I2S_startRead() @li I2S_startWrite()
|
|
* @li I2S_stopRead() @li I2S_stopWrite() @li I2S_stopClocks()
|
|
*
|
|
* @note
|
|
* @li In #I2S_SLAVE mode, clocks must be started and stopped exactly like
|
|
* it is done in #I2S_MASTER mode.
|
|
* @li If the queue of transaction is not empty, the calls to #I2S_stopRead()
|
|
* and #I2S_stopWrite() are blocking and potentially long.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Examples
|
|
* ## Examples #
|
|
*
|
|
* @li @ref ti_drivers_I2S_Example_PlayAndStop "Play and Stop"
|
|
* @li @ref ti_drivers_I2S_Example_Streaming "Streaming"
|
|
* @li @ref ti_drivers_I2S_Example_RepeatMode "Repeat"
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Example_PlayAndStop
|
|
* ### Mode Play and Stop #
|
|
* The following example shows how to simultaneously receive and send out a given amount of data.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Example_PlayAndStop_Code
|
|
* @code
|
|
* static I2S_Handle i2sHandle;
|
|
* static I2S_Config i2sConfig;
|
|
*
|
|
* static uint16_t readBuf1[500]; // the data read will end up in this buffer
|
|
* static uint16_t readBuf2[500]; // the data read will end up in this buffer
|
|
* static uint16_t readBuf3[500]; // the data read will end up in this buffer
|
|
* static uint16_t writeBuf1[250] = {...some data...}; // this buffer will be sent out
|
|
* static uint16_t writeBuf2[250] = {...some data...}; // this buffer will be sent out
|
|
* static uint16_t writeBuf3[250] = {...some data...}; // this buffer will be sent out
|
|
*
|
|
* static I2S_Transaction i2sRead1;
|
|
* static I2S_Transaction i2sRead2;
|
|
* static I2S_Transaction i2sRead3;
|
|
* static I2S_Transaction i2sWrite1;
|
|
* static I2S_Transaction i2sWrite2;
|
|
* static I2S_Transaction i2sWrite3;
|
|
*
|
|
* List_List i2sReadList;
|
|
* List_List i2sWriteList;
|
|
*
|
|
* static volatile bool readStopped = (bool)true;
|
|
* static volatile bool writeStopped = (bool)true;
|
|
*
|
|
* static void writeCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* if(status & I2S_ALL_TRANSACTIONS_SUCCESS){
|
|
*
|
|
* //Note: You should normally avoid to use I2S_stopRead() / I2S_stopWrite() in the callback.
|
|
* //However, here we do not have any transaction left in the queue (cf. status' value) so
|
|
* //the call to I2S_stoWrite() will not block.
|
|
* //Moreover, by delaying I2S_stopWrite() the driver could raise an error (data underflow).
|
|
*
|
|
* I2S_stopWrite(i2sHandle);
|
|
* writeStopped = (bool)true;
|
|
* }
|
|
* }
|
|
*
|
|
* static void readCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* if(status & I2S_ALL_TRANSACTIONS_SUCCESS){
|
|
*
|
|
* //Note: You should normally avoid to use I2S_stopRead() / I2S_stopWrite() in the callback.
|
|
* //However, here we do not have any transaction left in the queue (cf. status' value) so
|
|
* //the call to I2S_stopRead() will not block.
|
|
* //Moreover, by delaying I2S_stopRead() the driver could raise an error (data overflow).
|
|
*
|
|
* I2S_stopRead(i2sHandle);
|
|
* readStopped = (bool)true;
|
|
* }
|
|
* }
|
|
*
|
|
* static void errCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
* I2S_stopRead(handle);
|
|
* I2S_stopWrite(handle);
|
|
* I2S_stopClocks(handle);
|
|
* I2S_close(handle);
|
|
* }
|
|
*
|
|
* void *modePlayAndStopThread(void *arg0)
|
|
* {
|
|
* I2S_Params i2sParams;
|
|
*
|
|
* I2S_init();
|
|
*
|
|
* // Initialize I2S opening parameters
|
|
* I2S_Params_init(&i2sParams);
|
|
* i2sParams.fixedBufferLength = 500; // fixedBufferLength is the greatest common
|
|
* // divisor of all the different buffers
|
|
* // (here buffers' size are 500 and 1000 bytes)
|
|
* i2sParams.writeCallback = writeCallbackFxn ;
|
|
* i2sParams.readCallback = readCallbackFxn ;
|
|
* i2sParams.errorCallback = errCallbackFxn;
|
|
*
|
|
* i2sHandle = I2S_open(Board_I2S0, &i2sParams);
|
|
*
|
|
* // Initialize the read-transactions
|
|
* I2S_Transaction_init(&i2sRead1);
|
|
* I2S_Transaction_init(&i2sRead2);
|
|
* I2S_Transaction_init(&i2sRead3);
|
|
* i2sRead1.bufPtr = readBuf1;
|
|
* i2sRead2.bufPtr = readBuf2;
|
|
* i2sRead3.bufPtr = readBuf3;
|
|
* i2sRead1.bufSize = sizeof(readBuf1);
|
|
* i2sRead2.bufSize = sizeof(readBuf2);
|
|
* i2sRead3.bufSize = sizeof(readBuf3);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead1);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead2);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead3);
|
|
*
|
|
* I2S_setReadQueueHead(i2sHandle, &i2sRead1);
|
|
*
|
|
* // Initialize the write-transactions
|
|
* I2S_Transaction_init(&i2sWrite1);
|
|
* I2S_Transaction_init(&i2sWrite2);
|
|
* I2S_Transaction_init(&i2sWrite3);
|
|
* i2sWrite1.bufPtr = writeBuf1;
|
|
* i2sWrite2.bufPtr = writeBuf2;
|
|
* i2sWrite3.bufPtr = writeBuf3;
|
|
* i2sWrite1.bufSize = sizeof(writeBuf1);
|
|
* i2sWrite2.bufSize = sizeof(writeBuf2);
|
|
* i2sWrite3.bufSize = sizeof(writeBuf3);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite1);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite2);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite3);
|
|
*
|
|
* I2S_setWriteQueueHead(i2sHandle, &i2sWrite1);
|
|
*
|
|
* I2S_startClocks(i2sHandle);
|
|
* I2S_startWrite(i2sHandle);
|
|
* I2S_startRead(i2sHandle);
|
|
*
|
|
* readStopped = (bool)false;
|
|
* writeStopped = (bool)false;
|
|
*
|
|
* while(1) {
|
|
*
|
|
* if(readStopped && writeStopped) {
|
|
* I2S_stopClocks(i2sHandle);
|
|
* I2S_close(i2sHandle);
|
|
* while(1);
|
|
* }
|
|
* }
|
|
* }
|
|
* @endcode
|
|
*
|
|
* \note If you desire to put only one transaction in the queue, fixedBufferLength must be inferior to half the length (in bytes) of the buffer to transfer.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Example_Streaming
|
|
* ### Writing Data in Continuous Streaming Mode #
|
|
* The following example shows how to read and write data in streaming mode.
|
|
* A dummy treatment of the data is also done.
|
|
* This example is not complete (semaphore and tasks creation are not shown)
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Example_Streaming_Code
|
|
* @code
|
|
* static I2S_Handle i2sHandle;
|
|
* static I2S_Config i2sConfig;
|
|
*
|
|
* // These buffers will successively be written, treated and sent out
|
|
* static uint16_t readBuf1[500];
|
|
* static uint16_t readBuf2[500];
|
|
* static uint16_t readBuf3[500];
|
|
* static uint16_t readBuf4[500];
|
|
* static uint16_t writeBuf1[500]={0};
|
|
* static uint16_t writeBuf2[500]={0};
|
|
* static uint16_t writeBuf3[500]={0};
|
|
* static uint16_t writeBuf4[500]={0};
|
|
*
|
|
* // These transactions will successively be part of the
|
|
* // i2sReadList, the treatmentList and the i2sWriteList
|
|
* static I2S_Transaction i2sRead1;
|
|
* static I2S_Transaction i2sRead2;
|
|
* static I2S_Transaction i2sRead3;
|
|
* static I2S_Transaction i2sRead4;
|
|
* static I2S_Transaction i2sWrite1;
|
|
* static I2S_Transaction i2sWrite2;
|
|
* static I2S_Transaction i2sWrite3;
|
|
* static I2S_Transaction i2sWrite4;
|
|
*
|
|
* List_List i2sReadList;
|
|
* List_List treatmentList;
|
|
* List_List i2sWriteList;
|
|
*
|
|
* static void writeCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* // We must remove the previous transaction (the current one is not over)
|
|
* I2S_Transaction *transactionFinished = (I2S_Transaction*)List_prev(&transactionPtr->queueElement);
|
|
*
|
|
* if(transactionFinished != NULL){
|
|
* // Remove the finished transaction from the write queue
|
|
* List_remove(&i2sWriteList, (List_Elem*)transactionFinished);
|
|
*
|
|
* // This transaction must now feed the read queue (we do not need anymore the data of this transaction)
|
|
* transactionFinished->queueElement.next = NULL;
|
|
* List_put(&i2sReadList, (List_Elem*)transactionFinished);
|
|
*
|
|
* // We need to queue a new transaction: let's take one in the treatment queue
|
|
* I2S_Transaction *newTransaction = (I2S_Transaction*)List_head(&treatmentList);
|
|
* if(newTransaction != NULL){
|
|
* List_remove(&treatmentList, (List_Elem*)newTransaction);
|
|
* newTransaction->queueElement.next = NULL;
|
|
* List_put(&i2sWriteList, (List_Elem*)newTransaction);
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* static void readCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* // We must remove the previous transaction (the current one is not over)
|
|
* I2S_Transaction *transactionFinished = (I2S_Transaction*)List_prev(&transactionPtr->queueElement);
|
|
*
|
|
* if(transactionFinished != NULL){
|
|
* // The finished transaction contains data that must be treated
|
|
* List_remove(&i2sReadList, (List_Elem*)transactionFinished);
|
|
* transactionFinished->queueElement.next = NULL;
|
|
* List_put(&treatmentList, (List_Elem*)transactionFinished);
|
|
*
|
|
* // Start the treatment of the data
|
|
* Semaphore_post(dataReadyForTreatment);
|
|
*
|
|
* // We do not need to queue transaction here: writeCallbackFxn takes care of this :)
|
|
* }
|
|
* }
|
|
*
|
|
* static void errCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* }
|
|
*
|
|
* void *myTreatmentThread(void *arg0){
|
|
*
|
|
* int k;
|
|
*
|
|
* while(1) {
|
|
* Semaphore_pend(dataReadyForTreatment, BIOS_WAIT_FOREVER);
|
|
*
|
|
* if(lastAchievedReadTransaction != NULL) {
|
|
*
|
|
* // Need a critical section to be sure to have corresponding bufPtr and bufSize
|
|
* uintptr_t key = HwiP_disable();
|
|
* uint16_t *buf = lastAchievedReadTransaction->bufPtr;
|
|
* uint16_t bufLength = lastAchievedReadTransaction->bufSize / sizeof(uint16_t);
|
|
* HwiP_restore(key);
|
|
*
|
|
* // My dummy data treatment...
|
|
* for(k=0; k<bufLength; k++) {buf[k] --;}
|
|
* for(k=0; k<bufLength; k++) {buf[k] ++;}
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* void *echoExampleThread(void *arg0)
|
|
* {
|
|
* I2S_Params i2sParams;
|
|
*
|
|
* I2S_init();
|
|
*
|
|
* // Initialize the treatmentList (this list is initially empty)
|
|
* List_clearList(&treatmentList);
|
|
*
|
|
* //Initialize I2S opening parameters
|
|
* I2S_Params_init(&i2sParams);
|
|
* i2sParams.fixedBufferLength = 1000;
|
|
* i2sParams.writeCallback = writeCallbackFxn ;
|
|
* i2sParams.readCallback = readCallbackFxn ;
|
|
* i2sParams.errorCallback = errCallbackFxn;
|
|
*
|
|
* i2sHandle = I2S_open(Board_I2S0, &i2sParams);
|
|
*
|
|
* // Initialize the read-transactions
|
|
* I2S_Transaction_init(&i2sRead1);
|
|
* I2S_Transaction_init(&i2sRead2);
|
|
* I2S_Transaction_init(&i2sRead3);
|
|
* I2S_Transaction_init(&i2sRead4);
|
|
* i2sRead1.bufPtr = readBuf1;
|
|
* i2sRead2.bufPtr = readBuf2;
|
|
* i2sRead3.bufPtr = readBuf3;
|
|
* i2sRead4.bufPtr = readBuf4;
|
|
* i2sRead1.bufSize = sizeof(readBuf1);
|
|
* i2sRead2.bufSize = sizeof(readBuf2);
|
|
* i2sRead3.bufSize = sizeof(readBuf3);
|
|
* i2sRead4.bufSize = sizeof(readBuf4);
|
|
* List_clearList(&i2sReadList);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead1);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead2);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead3);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead4);
|
|
*
|
|
* I2S_setReadQueueHead(i2sHandle, &i2sRead1);
|
|
*
|
|
* // Initialize the write-transactions
|
|
* I2S_Transaction_init(&i2sWrite1);
|
|
* I2S_Transaction_init(&i2sWrite2);
|
|
* I2S_Transaction_init(&i2sWrite3);
|
|
* I2S_Transaction_init(&i2sWrite4);
|
|
* i2sWrite1.bufPtr = writeBuf1;
|
|
* i2sWrite2.bufPtr = writeBuf2;
|
|
* i2sWrite3.bufPtr = writeBuf3;
|
|
* i2sWrite4.bufPtr = writeBuf4;
|
|
* i2sWrite1.bufSize = sizeof(writeBuf1);
|
|
* i2sWrite2.bufSize = sizeof(writeBuf2);
|
|
* i2sWrite3.bufSize = sizeof(writeBuf3);
|
|
* i2sWrite4.bufSize = sizeof(writeBuf4);
|
|
* List_clearList(&i2sWriteList);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite1);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite2);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite3);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite4);
|
|
*
|
|
* I2S_setWriteQueueHead(i2sHandle, &i2sWrite1);
|
|
*
|
|
* I2S_startClocks(i2sHandle);
|
|
* I2S_startWrite(i2sHandle);
|
|
* I2S_startRead(i2sHandle);
|
|
*
|
|
* while(1);
|
|
* }
|
|
* @endcode
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Example_RepeatMode
|
|
* ### Writing Data in repeat Mode #
|
|
* The following example shows how to read and write data in repeat mode.
|
|
* The same buffers are continuously written and send out while the driver is not stopped.
|
|
* Here, we decide to only stop sending out after an arbitrary number of sending.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Example_RepeatMode_Code
|
|
* @code
|
|
* static I2S_Handle i2sHandle;
|
|
* static I2S_Config i2sConfig;
|
|
* static I2SCC26XX_Object i2sObject;
|
|
*
|
|
* // This buffer will be continuously re-written
|
|
* static uint16_t readBuf[500];
|
|
* // This data will be continuously sent out
|
|
* static uint16_t writeBuf[500] = {...some cool data...};
|
|
*
|
|
* static I2S_Transaction i2sRead;
|
|
* static I2S_Transaction i2sWrite;
|
|
*
|
|
* List_List i2sReadList;
|
|
* List_List i2sWriteList;
|
|
*
|
|
* static volatile bool writeFinished = (bool)false;
|
|
* static void writeCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* // Nothing to do here: the buffer(s) are queued in a ring list, the transfers are
|
|
* // executed without any action from the application.
|
|
*
|
|
* // We must consider the previous transaction (ok, when you have only one transaction it's the same)
|
|
* I2S_Transaction *transactionFinished = (I2S_Transaction*)List_prev(&transactionPtr->queueElement);
|
|
*
|
|
* if(transactionFinished != NULL){
|
|
* // After an arbitrary number of completion of the transaction, we will stop writting
|
|
* if(transactionFinished->numberOfCompletions >= 10) {
|
|
*
|
|
* // Note: You should avoid to use I2S_stopRead() / I2S_stopWrite() in the callback,
|
|
* // especially if you do not want to stop both read and write transfers.
|
|
* // The execution of these functions is potentially blocking and can mess up the
|
|
* // other transfers.
|
|
*
|
|
* writeFinished = (bool)true;
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* static void readCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
* // Nothing to do here: the buffer(s) are queued in a ring list, the transfers are
|
|
* // executed without any action from the application.
|
|
* }
|
|
*
|
|
* static void errCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {
|
|
*
|
|
* }
|
|
*
|
|
* void *modeRepeat(void *arg0)
|
|
* {
|
|
* I2S_Params i2sParams;
|
|
*
|
|
* // Initialize I2S opening parameters
|
|
* I2S_Params_init(&i2sParams);
|
|
* i2sParams.fixedBufferLength = 1000; // No problem here: the driver consider
|
|
* // the list as an infinite list.
|
|
* i2sParams.writeCallback = writeCallbackFxn ;
|
|
* i2sParams.readCallback = readCallbackFxn ;
|
|
* i2sParams.errorCallback = errCallbackFxn;
|
|
*
|
|
* i2sHandle = I2S_open(0, &i2sParams);
|
|
*
|
|
* // Initialize the read-transactions
|
|
* I2S_Transaction_init(&i2sRead);
|
|
* i2sRead.bufPtr = readBuf;
|
|
* i2sRead.bufSize = sizeof(readBuf);
|
|
* List_put(&i2sReadList, (List_Elem*)&i2sRead);
|
|
* List_tail(&i2sReadList)->next = List_head(&i2sReadList);// Read buffers are queued in a ring-list
|
|
* List_head(&i2sReadList)->prev = List_tail(&i2sReadList);
|
|
*
|
|
* I2S_setReadQueueHead(i2sHandle, &i2sRead);
|
|
*
|
|
* // Initialize the write-transactions
|
|
* I2S_Transaction_init(&i2sWrite);
|
|
* i2sWrite.bufPtr = writeBuf;
|
|
* i2sWrite.bufSize = sizeof(writeBuf);
|
|
* List_put(&i2sWriteList, (List_Elem*)&i2sWrite);
|
|
* List_tail(&i2sWriteList)->next = List_head(&i2sWriteList); // Write buffers are queued in a ring-list
|
|
* List_head(&i2sWriteList)->prev = List_tail(&i2sWriteList);
|
|
*
|
|
* I2S_setWriteQueueHead(i2sHandle, &i2sWrite);
|
|
*
|
|
* I2S_startClocks(i2sHandle);
|
|
* I2S_startWrite(i2sHandle);
|
|
* I2S_startRead(i2sHandle);
|
|
*
|
|
* while(1){
|
|
*
|
|
* if(writeFinished){
|
|
* writeFinished = (bool)false;
|
|
* I2S_stopWrite(i2sHandle);
|
|
* }
|
|
* }
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @note In the case of circular lists, there is no problem to put only
|
|
* one buffer in the queue.
|
|
*
|
|
* <hr>
|
|
* @anchor ti_drivers_I2S_Configuration
|
|
* # Configuration
|
|
*
|
|
* Refer to the @ref driver_configuration "Driver's Configuration" section
|
|
* for driver configuration information.
|
|
* <hr>
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef ti_drivers_I2S__include
|
|
#define ti_drivers_I2S__include
|
|
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include <ti/drivers/utils/List.h>
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @defgroup I2S_STATUS Status Codes
|
|
* I2S_STATUS_* macros are general status codes used when user callback is called
|
|
* @{
|
|
* @ingroup I2S_CONTROL
|
|
*/
|
|
|
|
/*!
|
|
* @brief Successful status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_ALL_TRANSACTION_SUCCESS if ALL the queued transactions
|
|
* were executed successfully.
|
|
*/
|
|
#define I2S_ALL_TRANSACTIONS_SUCCESS (0x0001U)
|
|
|
|
/*!
|
|
* @brief Successful status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_TRANSACTION_SUCCESS if ONE queued transaction
|
|
* was executed successfully.
|
|
*/
|
|
#define I2S_TRANSACTION_SUCCESS (0x0002U)
|
|
|
|
/*!
|
|
* @brief Error status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_TIMEOUT_ERROR if I2S module lost the audio clock.
|
|
* If this error has been raised, I2S module must be reseted and restarted.
|
|
*/
|
|
#define I2S_TIMEOUT_ERROR (0x0100U)
|
|
|
|
/*!
|
|
* @brief Error status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_BUS_ERROR if I2S module faced problem with the DMA
|
|
* bus (DMA transfer not completed in time).
|
|
* If this error has been raised, I2S module must be reseted and restarted.
|
|
*/
|
|
#define I2S_BUS_ERROR (0x0200U)
|
|
|
|
/*!
|
|
* @brief Error status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_WS_ERROR if I2S module detect noise on the WS signal.
|
|
* If this error has been raised, I2S module must be reseted and restarted.
|
|
*/
|
|
#define I2S_WS_ERROR (0x0400U)
|
|
|
|
/*!
|
|
* @brief Error status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_PTR_READ_ERROR if I2S module ran out of data
|
|
* on the read interface (DMA pointer not loaded in time).
|
|
* If this error has been raised, I2S module must be reseted and restarted.
|
|
*/
|
|
#define I2S_PTR_READ_ERROR (0x0800U)
|
|
|
|
/*!
|
|
* @brief Error status code returned by I2S driver functions.
|
|
*
|
|
* I2S driver functions return I2S_PTR_WRITE_ERROR if I2S module ran out of data
|
|
* on the write interface (DMA pointer not loaded in time).
|
|
* If this error has been raised, I2S module must be reseted and restarted.
|
|
*/
|
|
#define I2S_PTR_WRITE_ERROR (0x1000U)
|
|
/** @}*/
|
|
|
|
/*!
|
|
* @brief A handle that is returned from a I2S_open() call.
|
|
*/
|
|
typedef struct I2S_Config_ *I2S_Handle;
|
|
|
|
/*!
|
|
* @brief I2S transaction descriptor.
|
|
*/
|
|
typedef struct I2S_Transaction_ {
|
|
/*! Used internally to link descriptors together */
|
|
List_Elem queueElement;
|
|
/*! Pointer to the buffer */
|
|
void *bufPtr;
|
|
/*! Size of the buffer. */
|
|
size_t bufSize;
|
|
/*! Internal use only. Number of bytes written to or read from the buffer. */
|
|
size_t bytesTransferred;
|
|
/*! Number of non-transfered bytes at transaction's end. */
|
|
size_t untransferredBytes;
|
|
/*! Parameter incremented each time the transaction is completed. */
|
|
uint16_t numberOfCompletions;
|
|
/*! Internal argument. Application must not modify this element. */
|
|
uintptr_t arg;
|
|
} I2S_Transaction;
|
|
|
|
/*!
|
|
* @brief The definition of a user-callback function used by the I2S driver
|
|
*
|
|
* @param I2S_Handle I2S_Handle
|
|
*
|
|
* @param status Status of the operation (possible values are :
|
|
* :I2S_STATUS_SUCCESS, :I2S_STATUS_ERROR,
|
|
* :I2S_STATUS_BUFFER_UNAVAILABLE, :I2S_STATUS_TIMEOUT)
|
|
*
|
|
* @param I2S_Transaction *transactionPtr: Pointer on the transaction just completed.
|
|
* For error calbacks, transactionPtr points on NULL.
|
|
*
|
|
*/
|
|
typedef void (*I2S_Callback)(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr);
|
|
|
|
/*!
|
|
* @brief The definition of a function used to set the I2S register
|
|
*
|
|
* @param uint32_t ui32Base: base address of the I2S module.
|
|
*
|
|
* @param uint32_t ui32NextPointer: pointer on an I2S buffer.
|
|
*
|
|
*/
|
|
typedef void (*I2S_RegUpdate)(uint32_t ui32Base, uint32_t ui32NextPointer);
|
|
|
|
/*!
|
|
* @brief I2S slot memory length setting
|
|
*
|
|
* The enum defines if the module uses a 16 bits or a 24 bits buffer in memory.
|
|
* This value has no influence on the number of bit transmitted.
|
|
*/
|
|
typedef enum I2S_MemoryLength_ {
|
|
|
|
I2S_MEMORY_LENGTH_8BITS = 8U, /*!< Buffer used is 8 bits length. Not available for CC26XX. */
|
|
I2S_MEMORY_LENGTH_16BITS = 16U, /*!< Buffer used is 16 bits length. */
|
|
I2S_MEMORY_LENGTH_24BITS = 24U, /*!< Buffer used is 24 bits length. */
|
|
I2S_MEMORY_LENGTH_32BITS = 32U /*!< Buffer used is 32 bits length. Not available for CC26XX. */
|
|
|
|
} I2S_MemoryLength;
|
|
|
|
/*!
|
|
* @brief I2S master / slave selection
|
|
*
|
|
* The enum defines if the module acts like a master (clocks are internally generated)
|
|
* or a slave (the clocks are externally generated).
|
|
*/
|
|
typedef enum I2S_Role_ {
|
|
|
|
I2S_SLAVE = 0, /*!< Module is a slave, clocks are externally generated. */
|
|
I2S_MASTER = 1 /*!< Module is a master, clocks are internally generated. */
|
|
|
|
} I2S_Role;
|
|
|
|
/*!
|
|
* @brief I2S sampling setting
|
|
*
|
|
* The enum defines if sampling is done on BLCK rising or falling edges.
|
|
*/
|
|
typedef enum I2S_SamplingEdge_ {
|
|
|
|
I2S_SAMPLING_EDGE_FALLING = 0, /*!< Sampling on falling edges. */
|
|
I2S_SAMPLING_EDGE_RISING = 1 /*!< Sampling on rising edges. */
|
|
|
|
} I2S_SamplingEdge;
|
|
|
|
/*!
|
|
* @brief I2S phase setting
|
|
*
|
|
* The enum defines if the I2S if set with single or dual phase.
|
|
*/
|
|
typedef enum I2S_PhaseType_ {
|
|
|
|
I2S_PHASE_TYPE_SINGLE = 0U, /*!< Single phase */
|
|
I2S_PHASE_TYPE_DUAL = 1U, /*!< Dual phase */
|
|
|
|
} I2S_PhaseType;
|
|
|
|
/*!
|
|
* @brief I2S data interface configuration
|
|
*
|
|
* The enum defines the different settings for the data interfaces (SD0 and SD1).
|
|
*/
|
|
typedef enum I2S_DataInterfaceUse_ {
|
|
|
|
I2S_SD0_DISABLED = 0x00U, /*!< SD0 is disabled */
|
|
I2S_SD0_INPUT = 0x01U, /*!< SD0 is an input */
|
|
I2S_SD0_OUTPUT = 0x02U, /*!< SD0 is an output */
|
|
I2S_SD1_DISABLED = 0x00U, /*!< SD1 is disabled */
|
|
I2S_SD1_INPUT = 0x10U, /*!< SD1 is an input */
|
|
I2S_SD1_OUTPUT = 0x20U /*!< SD1 is an output */
|
|
|
|
} I2S_DataInterfaceUse;
|
|
|
|
/*!
|
|
* @brief Channels used selection
|
|
*
|
|
* The enum defines different settings to activate the expected channels.
|
|
*/
|
|
typedef enum I2S_ChannelConfig_ {
|
|
|
|
I2S_CHANNELS_NONE = 0x00U, /*!< No channel activated */
|
|
I2S_CHANNELS_MONO = 0x01U, /*!< MONO: only channel one is activated */
|
|
I2S_CHANNELS_MONO_INV = 0x02U, /*!< MONO INVERERTED: only channel two is activated */
|
|
I2S_CHANNELS_STEREO = 0x03U, /*!< STEREO: channels one and two are activated */
|
|
I2S_1_CHANNEL = 0x01U, /*!< 1 channel is activated */
|
|
I2S_2_CHANNELS = 0x03U, /*!< 2 channels are activated */
|
|
I2S_3_CHANNELS = 0x07U, /*!< 3 channels are activated */
|
|
I2S_4_CHANNELS = 0x0FU, /*!< 4 channels are activated */
|
|
I2S_5_CHANNELS = 0x1FU, /*!< 5 channels are activated */
|
|
I2S_6_CHANNELS = 0x3FU, /*!< 6 channels are activated */
|
|
I2S_7_CHANNELS = 0x7FU, /*!< 7 channels are activated */
|
|
I2S_8_CHANNELS = 0xFFU, /*!< 8 channels are activated */
|
|
I2S_CHANNELS_ALL = 0xFFU /*!< All the eight channels are activated */
|
|
|
|
} I2S_ChannelConfig;
|
|
|
|
/*!
|
|
* @brief Basic I2S Parameters
|
|
*
|
|
* I2S parameters are used to with the I2S_open() call. Default values for
|
|
* these parameters are set using I2S_Params_init().
|
|
*
|
|
* @sa I2S_Params_init()
|
|
*/
|
|
typedef struct I2S_Params_ {
|
|
|
|
bool invertWS;
|
|
/*!< WS must be internally inverted when using I2S data format.
|
|
* false: The WS signal is not internally inverted.
|
|
* true: The WS signal is internally inverted. */
|
|
|
|
bool isMSBFirst;
|
|
/*!< Endianness selection. Not available on CC26XX.
|
|
* false: The samples are transmitted LSB first.
|
|
* true: The samples are transmitted MSB first. */
|
|
|
|
bool isDMAUnused;
|
|
/*!< Selection between DMA transmissions and CPU transmissions.
|
|
* false: Transmission are performed by DMA.
|
|
* true: Transmission are performed by CPU.
|
|
* Not available for CC26XX: all transmissions are performed by CPU. */
|
|
|
|
I2S_MemoryLength memorySlotLength;
|
|
/*!< Memory buffer used.
|
|
* #I2S_MEMORY_LENGTH_8BITS: Memory length is 8 bits (not available for CC26XX).
|
|
* #I2S_MEMORY_LENGTH_16BITS: Memory length is 16 bits.
|
|
* #I2S_MEMORY_LENGTH_24BITS: Memory length is 24 bits.
|
|
* #I2S_MEMORY_LENGTH_32BITS: Memory length is 32 bits (not available for CC26XX).*/
|
|
|
|
uint8_t beforeWordPadding;
|
|
/*!< Number of SCK periods between the first WS edge and the MSB of the first audio channel data transferred during the phase.*/
|
|
|
|
uint8_t afterWordPadding;
|
|
/*!< Number of SCK periods between the first WS edge and the MSB of the first audio channel data transferred during the phase.*/
|
|
|
|
uint8_t bitsPerWord;
|
|
/*!< Bits per sample (Word length): must be between 8 and 24 bits. */
|
|
|
|
I2S_Role moduleRole;
|
|
/*!< Select if the I2S module is a Slave or a Master.
|
|
* - #I2S_SLAVE: The device is a slave (clocks are generated externally).
|
|
* - #I2S_MASTER: The device is a master (clocks are generated internally). */
|
|
|
|
I2S_SamplingEdge samplingEdge;
|
|
/*!< Select edge sampling type.
|
|
* - #I2S_SAMPLING_EDGE_FALLING: Sampling on falling edges (for DSP data format).
|
|
* - #I2S_SAMPLING_EDGE_RISING: Sampling on rising edges (for I2S, LJF and RJF data formats). */
|
|
|
|
I2S_DataInterfaceUse SD0Use;
|
|
/*!< Select if SD0 is an input, an output or disabled.
|
|
* - #I2S_SD0_DISABLED: Disabled.
|
|
* - #I2S_SD0_INPUT: Input.
|
|
* - #I2S_SD0_OUTPUT: Output. */
|
|
|
|
I2S_DataInterfaceUse SD1Use;
|
|
/*!< Select if SD1 is an input, an output or disabled.
|
|
* - #I2S_SD1_DISABLED: Disabled.
|
|
* - #I2S_SD1_INPUT: Input.
|
|
* - #I2S_SD1_OUTPUT: Output. */
|
|
|
|
I2S_ChannelConfig SD0Channels;
|
|
/*!< This parameter is a bit mask indicating which channels are valid on SD0.
|
|
* If phase type is "dual", maximum channels number is two.
|
|
* Valid channels on SD1 and SD0 can be different.
|
|
* For dual phase mode:
|
|
* - #I2S_CHANNELS_NONE: No channel activated:
|
|
* read -> I2S does not receive anything (no buffer consumption)
|
|
* write -> I2S does not send anything (no buffer consumption)
|
|
* - #I2S_CHANNELS_MONO: Only channel 1 is activated:
|
|
* read -> I2S only reads channel 1
|
|
* write -> I2S transmits the data on channel 1 and duplicates it on channel 2
|
|
* - #I2S_CHANNELS_MONO_INV: Only channel 2 is activated:
|
|
* read -> I2S only reads channel 2
|
|
* write -> I2S transmits the data on channel 2 and duplicates it on the channel 1 of the next word
|
|
* - #I2S_CHANNELS_STEREO: STEREO:
|
|
* read -> I2S reads both channel 1 and channel 2
|
|
* write -> I2S transmits data both on channel 1 and channel 2
|
|
* .
|
|
* For single phase mode:
|
|
* - Various number of channels can be activated using: #I2S_1_CHANNEL, #I2S_2_CHANNELS, #I2S_3_CHANNELS, #I2S_4_CHANNELS,
|
|
* #I2S_5_CHANNELS, #I2S_6_CHANNELS, #I2S_7_CHANNELS, #I2S_8_CHANNELS.
|
|
* - #I2S_CHANNELS_ALL: The eight channels are activated */
|
|
|
|
I2S_ChannelConfig SD1Channels;
|
|
/*!< This parameter is a bit mask indicating which channels are valid on SD1.
|
|
* If phase type is "dual", maximum channels number is two.
|
|
* Valid channels on SD1 and SD0 can be different.
|
|
* For dual phase mode:
|
|
* - #I2S_CHANNELS_NONE: No channel activated:
|
|
* read -> I2S does not receive anything (no buffer consumption)
|
|
* write -> I2S does not send anything (no buffer consumption)
|
|
* - #I2S_CHANNELS_MONO: Only channel 1 is activated:
|
|
* read -> I2S only reads channel 1
|
|
* write -> I2S transmits the data on channel 1 and duplicates it on channel 2
|
|
* - #I2S_CHANNELS_MONO_INV: Only channel 2 is activated:
|
|
* read -> I2S only reads channel 2
|
|
* write -> I2S transmits the data on channel 2 and duplicates it on the channel 1 of the next word
|
|
* - #I2S_CHANNELS_STEREO: STEREO:
|
|
* read -> I2S reads both channel 1 and channel 2
|
|
* write -> I2S transmits data both on channel 1 and channel 2
|
|
* .
|
|
* For single phase mode:
|
|
* - Various number of channels can be activated using: #I2S_1_CHANNEL, #I2S_2_CHANNELS, #I2S_3_CHANNELS, #I2S_4_CHANNELS,
|
|
* #I2S_5_CHANNELS, #I2S_6_CHANNELS, #I2S_7_CHANNELS, #I2S_8_CHANNELS.
|
|
* - #I2S_CHANNELS_ALL: The eight channels are activated */
|
|
|
|
I2S_PhaseType phaseType;
|
|
/*!< Select phase type.
|
|
* - #I2S_PHASE_TYPE_SINGLE: Single phase (for DSP format): up to eight channels are usable.
|
|
* - #I2S_PHASE_TYPE_DUAL: Dual phase (for I2S, LJF and RJF data formats): up to two channels are usable.
|
|
* .
|
|
* This parameter must not be considered on CC32XX. This chip only allows dual phase formats.*/
|
|
|
|
uint16_t fixedBufferLength;
|
|
/*!< Number of consecutive bytes of the samples buffers. This field must be set to a value x different from 0.
|
|
* All the data buffers used (both for input and output) must contain N*x bytes (with N an integer verifying N>0). */
|
|
|
|
uint16_t startUpDelay;
|
|
/*!< Time (in number of WS cycles) to wait before the first transfer. */
|
|
|
|
uint16_t MCLKDivider;
|
|
/*!< Select the frequency divider for MCLK signal. Final value of MCLK is 48MHz/MCLKDivider. Value must be selected between 2 and 1024. */
|
|
|
|
uint32_t samplingFrequency;
|
|
/*!< I2S sampling frequency configuration in samples/second.
|
|
* SCK frequency limits:
|
|
*- For CC26XX, SCK frequency should be between 47 kHz and 4 MHz.
|
|
*- For CC32XX, SCK frequency should be between 57 Hz and 8 MHz. */
|
|
|
|
I2S_Callback readCallback;
|
|
/*!< Pointer to read callback. Cannot be NULL if a read interface is activated. */
|
|
|
|
I2S_Callback writeCallback;
|
|
/*!< Pointer to write callback. Cannot be NULL if a write interface is activated. */
|
|
|
|
I2S_Callback errorCallback;
|
|
/*!< Pointer to error callback. Cannot be NULL. */
|
|
|
|
void *custom;
|
|
/*!< Pointer to device specific custom params */
|
|
} I2S_Params;
|
|
|
|
/*!
|
|
* @brief Default I2S_Params structure
|
|
*
|
|
* @sa I2S_Params_init()
|
|
*/
|
|
extern const I2S_Params I2S_defaultParams;
|
|
|
|
/*! @brief I2S Global configuration
|
|
*
|
|
* The I2S_Config structure contains a set of pointers used to characterize
|
|
* the I2S driver implementation.
|
|
*
|
|
* This structure needs to be defined before calling I2S_init() and it must
|
|
* not be changed thereafter.
|
|
*
|
|
* @sa I2S_init()
|
|
*/
|
|
typedef struct I2S_Config_ {
|
|
/*! Pointer to a driver specific data object */
|
|
void *object;
|
|
|
|
/*! Pointer to a driver specific hardware attributes structure */
|
|
void const *hwAttrs;
|
|
} I2S_Config;
|
|
|
|
/*!
|
|
* @brief Function to close a given I2S peripheral specified by the I2S
|
|
* handle.
|
|
*
|
|
* @pre I2S_open() had to be called first.
|
|
*
|
|
* @param [in] handle An I2S_Handle returned from I2S_open
|
|
*
|
|
* @sa I2S_open()
|
|
*/
|
|
extern void I2S_close(I2S_Handle handle);
|
|
|
|
/*!
|
|
* @brief Function to initializes the I2S module
|
|
*
|
|
* @pre The I2S_config structure must exist and be persistent before this
|
|
* function can be called. This function must also be called before
|
|
* any other I2S driver APIs. This function call does not modify any
|
|
* peripheral registers.
|
|
*/
|
|
extern void I2S_init(void);
|
|
|
|
/*!
|
|
* @brief Function to initialize a given I2S peripheral specified by the
|
|
* particular index value. The parameter specifies which mode the I2S
|
|
* will operate.
|
|
*
|
|
* @pre I2S controller has been initialized
|
|
*
|
|
* @param [inout] index Logical peripheral number for the I2S indexed into
|
|
* the I2S_config table
|
|
*
|
|
* @param [in] params Pointer to an parameter block.
|
|
* All the fields in this structure are RO (read-only).
|
|
* Provide a NULL pointer cannot open the module.
|
|
*
|
|
* @return An I2S_Handle on success or a NULL on an error or if it has been
|
|
* opened already.
|
|
*
|
|
* @sa I2S_init()
|
|
* @sa I2S_close()
|
|
*/
|
|
extern I2S_Handle I2S_open(uint_least8_t index, I2S_Params *params);
|
|
|
|
/*!
|
|
* @brief Function to initialize the I2S_Params struct to its defaults
|
|
*
|
|
* @param [out] params An pointer to I2S_Params structure for
|
|
* initialization
|
|
*
|
|
* Defaults values are:
|
|
* @code
|
|
* params.samplingFrequency = 8000;
|
|
* params.isMemory24Bits = I2S_MEMORY_LENGTH_16BITS;
|
|
* params.isMaster = I2S_MASTER;
|
|
* params.invertWS = (bool)true;
|
|
* params.isMSBFirst = (bool)true;
|
|
* params.isDMAUnused = (bool)false;
|
|
* params.samplingEdge = I2S_SAMPLING_EDGE_RISING;
|
|
* params.beforeWordPadding = 0;
|
|
* params.bitsPerWord = 16;
|
|
* params.afterWordPadding = 0;
|
|
* params.fixedBufferLength = 1;
|
|
* params.SD0Use = I2S_SD0_OUTPUT;
|
|
* params.SD1Use = I2S_SD1_INPUT;
|
|
* params.SD0Channels = I2S_CHANNELS_STEREO;
|
|
* params.SD1Channels = I2S_CHANNELS_STEREO;
|
|
* params.phaseType = I2S_PHASE_TYPE_DUAL;
|
|
* params.startUpDelay = 0;
|
|
* params.MCLKDivider = 40;
|
|
* params.readCallback = NULL;
|
|
* params.writeCallback = NULL;
|
|
* params.errorCallback = NULL;
|
|
* params.custom = NULL;
|
|
* @endcode
|
|
*
|
|
* @param params Parameter structure to initialize
|
|
*/
|
|
extern void I2S_Params_init(I2S_Params *params);
|
|
|
|
/*!
|
|
* @brief Initialize an I2S_Transaction struct to known state.
|
|
*
|
|
* The I2S_Transaction struct is put in a known state. The application is
|
|
* still responsible for populating some of the fields.
|
|
* For example, the user is responsible to provide the buffer containing the
|
|
* data and the size of it.
|
|
* User provided buffer's size must matche with the I2S settings.
|
|
* If the buffer size is not adapted, the I2S module will truncate it.
|
|
* Authorized buffer sizes depend on the number of activated outputs, the number
|
|
* of channels activated, the memory slots length (16 or 24 bits), and the
|
|
* fixed-buffer-size eventually provided.
|
|
* Authorized buffer sizes are all the multiple values of the value of
|
|
* handle->object->memoryStepOut.
|
|
*
|
|
* @param [out] transaction Transaction struct to initialize.
|
|
*/
|
|
extern void I2S_Transaction_init(I2S_Transaction *transaction);
|
|
|
|
/*!
|
|
* @brief Function to set the first read-transaction to consider
|
|
*
|
|
* At the end of each transaction, I2S driver takes in consideration the next
|
|
* transaction. Application is responsible to handle the queue.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @param [in] transaction A pointer to an I2S_Transaction object. The bufPtr
|
|
* and bufSize fields must be set to a buffer and the
|
|
* size of the buffer before passing to this function.
|
|
*
|
|
* @return void
|
|
*
|
|
* @sa I2S_setWriteQueueHead()
|
|
*/
|
|
extern void I2S_setReadQueueHead(I2S_Handle handle, I2S_Transaction *transaction);
|
|
|
|
/*!
|
|
* @brief Function to set the first write-transaction to consider
|
|
*
|
|
* At the end of each transaction, I2S driver takes in consideration the next
|
|
* transaction. Application is responsible to handle the queue.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @param [in] transaction A pointer to an I2S_Transaction object. The bufPtr
|
|
* and bufSize fields must be set to a buffer and the
|
|
* size of the buffer before passing to this function.
|
|
*
|
|
* @return void
|
|
*
|
|
* @sa I2S_setReadQueueHead()
|
|
*/
|
|
extern void I2S_setWriteQueueHead(I2S_Handle handle, I2S_Transaction *transaction);
|
|
|
|
/*!
|
|
* @brief Start the WS, SCK and MCLK clocks.
|
|
*
|
|
* This function enable WS, SCK and MCLK (if activated) clocks. This is required before starting
|
|
* any reading or a writing transaction.
|
|
* This function is supposed to be executed both in slave and master mode.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @return void
|
|
*
|
|
* @sa I2S_stopClocks()
|
|
*/
|
|
extern void I2S_startClocks(I2S_Handle handle);
|
|
|
|
/*!
|
|
* @brief Stops the WS, SCK and MCLK clocks.
|
|
*
|
|
* This function disable WS, SCK and MCLK clocks.
|
|
* This function must be executed only if no transaction is in progress.
|
|
* This function is supposed to be executed both in slave and master mode.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @return void
|
|
*
|
|
* @sa I2S_stopRead()
|
|
* @sa I2S_stopWrite()
|
|
*/
|
|
extern void I2S_stopClocks(I2S_Handle handle);
|
|
|
|
/*!
|
|
* @brief Start read transactions.
|
|
*
|
|
* This function starts reception of the transactions stored in the read-queue.
|
|
* and returns immediately. At the end of the transaction(s) the readCallback
|
|
* provided is executed.
|
|
* Clocks must be running before calling this function.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @return void
|
|
*
|
|
* @sa I2S_stopRead()
|
|
*/
|
|
extern void I2S_startRead(I2S_Handle handle);
|
|
|
|
/*!
|
|
* @brief Start write transactions.
|
|
*
|
|
* This function starts transmission of the transactions stored in the write-queue
|
|
* and returns immediately. At the end of the transaction(s) the writeCallback
|
|
* provided is executed.
|
|
* Clocks must be running before calling this function.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @return void
|
|
*
|
|
* @sa I2S_startClocks
|
|
*/
|
|
extern void I2S_startWrite(I2S_Handle handle);
|
|
|
|
/*!
|
|
* @brief Stop read transactions.
|
|
*
|
|
* This function stops reception of the transactions stored in the read-queue.
|
|
* To avoid the apparition of errors, this function blocks while currently
|
|
* received sample is not completely done.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @return void
|
|
*/
|
|
extern void I2S_stopRead(I2S_Handle handle);
|
|
|
|
/*!
|
|
* @brief Stop write transactions.
|
|
*
|
|
* This function stops transmission of the transactions stored in the write-queue.
|
|
* To avoid the apparition of errors, this function blocks while currently
|
|
* transmitted sample is not completely done.
|
|
*
|
|
* @param [in] handle An I2S_Handle.
|
|
*
|
|
* @return void
|
|
*/
|
|
extern void I2S_stopWrite(I2S_Handle handle);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ti_drivers_I2S__include */
|