NetBurner 3.5.6
PDF Version
sai.h
1
2/*NB_REVISION*/
3
4/*NB_COPYRIGHT*/
5
6#include <predef.h>
7#include <sim.h>
8#include <nbrtos.h>
9#include <edma.h>
10
11#define SAI_HW_COUNT 3
12#define SAI_TXBD_COUNT 4
13#define SAI_RXBD_COUNT 4
14
15// class SAI_I2S : private Ssc {
16//
17//
18// public:
19// inline void Reset() { SAI_CR = SAI_CR_SWRST; }
20// inline void EnableTx(bool enable) {
21// SAI_CR = (enable ? SAI_CR_TXEN : SAI_CR_TXDIS);
22// }
23// inline void EnableRx(bool enable) {
24// SAI_CR = (enable ? SAI_CR_RXEN : SAI_CR_RXDIS);
25// }
26// inline uint16_t SetClkDiv(uint16_t div) {
27// return SAI_CMR = div & SAI_CMR_DIV_Msk;
28// }
29//
30// static Ssc *get() { return reinterpret_cast<SAI_I2S*>(SAI); }
31// Ssc &GetRegisers() { return *this; }
32//
33// } __attribute__((packed));
34//
35// static_assert( sizeof (SAI_I2S == sizeof(Ssc) );
36//
37
38// doneInvalid < -1, channel error, buffer state unchanged
39// doneInvalid == -1, transfer error, buffer retired
40// doneInvalid == 0, Half transferred, second half still in progress
41// doneInvalid > 0, Buffer completely transferred
42typedef void (*SAI_BufferDoneFn_t)(void *buffer, int doneInvalid);
43/****************************************/
44/* SAI Configuration Enums */
45/****************************************/
49enum clkSrc_t
50{
51 CLK_SRC_MCK,
52 CLK_SRC_EXT,
53};
54
58enum clkCh_t
59{
60 CLK_CH_CH,
61 CLK_CH_RK,
62 CLK_CH_TK,
63};
64
65enum clkPol_t
66{
67 CLK_ACTIVE_HIGH,
68 CLK_ACTIVE_LOW,
69};
70
74enum frameSyncCh_t
75{
76 SYNC_CH_CH,
77 SYNC_CH_RX,
78 SYNC_CH_TX
79};
80
104enum startCond_t
105{
106 START_CONTINUOUS,
107 START_SYNC_RX_TX,
108 START_FRAME_LOW,
109 START_FRAME_HIGH,
110 START_FRAME_FALLING,
111 START_FRAME_RISING,
112 START_FRAME_LEVEL,
113 START_FRAME_EDGE,
114 START_CMP_0
115};
116
120enum clkGate_t
121{
122 CLK_GATE_CONTINUOUS,
123 CLK_GATE_FRAME_LOW,
124 CLK_GATE_FRAME_HIGH,
125};
126
130enum frameEdge_t
131{
132 FRAME_SYNC_RISING,
133 FRAME_SYNC_FALLING
134};
135
139enum clkOut_t
140{
141 CLK_OUT_INPUT,
143 CLK_OUT_CONTINUOUS,
144 CLK_OUT_TRANSFER
145};
146
150enum frameSyncOut_t
151{
152 FRAME_SYNC_INPUT,
154 FRAME_SYNC_NEGATIVE,
156 FRAME_SYNC_POSITIVE,
158};
159
163enum dataPacking_t
164{
165 BUFFER_WORD8,
166 BUFFER_WORD16_LEFT,
167 BUFFER_WORD16_RIGHT,
168// BUFFER_WORD24_LEFT, /**< Buffer Word is 24 bits, data is Left Justified */
169// BUFFER_WORD24_RIGHT,/**< Buffer Word is 24 bits, data is Right Justified */
170 BUFFER_WORD32_LEFT,
171 BUFFER_WORD32_RIGHT,
172};
173
177enum bitOrder_t
178{
179 LEAST_SIG_FIRST,
180 MOST_SIG_FIRST
181};
182
193enum bufferDepletionBehavior_t
194{
195 DEPLETED_PAUSE,
196 DEPLETED_REPEAT_LAST,
197};
198
202enum rxTxSync_t
203{
204 RXTX_ASYNC,
205 RXTX_SYNC_RX,
206 RXTX_SYNC_TX
207};
208
209/****************************************/
210/* SAI Configuration Struct */
211/****************************************/
212
256{
257 bool enable{false};
258 uint8_t startDly{1};
259 startCond_t startCond{START_FRAME_EDGE};
260 clkGate_t clkGate{CLK_GATE_CONTINUOUS};
261 clkOut_t clkOut{CLK_OUT_CONTINUOUS};
262 clkSrc_t clkSrc{CLK_SRC_MCK};
263 clkCh_t clkCh{CLK_CH_CH};
264 clkPol_t clkPol{CLK_ACTIVE_HIGH};
265
266 uint8_t syncLen{0};
267 frameEdge_t syncEdge{FRAME_SYNC_FALLING};
268 frameSyncOut_t syncOut{FRAME_SYNC_INPUT};
269 frameSyncCh_t syncCh{SYNC_CH_CH};
270 uint8_t wordsPerFrame{2};
271 dataPacking_t dataPacking{BUFFER_WORD32_RIGHT};
272 bool unifyDataStream{false};
273 bitOrder_t bitOrder{MOST_SIG_FIRST};
275 uint8_t bitsPerWord{24};
276 uint32_t wordMask{0};
277
278 bufferDepletionBehavior_t depletionBehavior{DEPLETED_PAUSE};
279};
280
295{
296 uint32_t txClkFreq{12288000};
297 uint32_t rxClkFreq{12288000};
298 rxTxSync_t rxTxSync{RXTX_ASYNC};
299// uint32_t mclkFreq{0};
300
301 I2S_Type *sai;
304};
305
346extern const SAI_cfg_t SAI_I2S_SLAVE_24_TXRX_RK;
347extern const SAI_cfg_t SAI_I2S_SLAVE_24_TXRX_TK;
348extern const SAI_cfg_t SAI_I2S_SLAVE_24_TXRX_TKRK;
349extern const SAI_cfg_t SAI_I2S_SLAVE_16_TXRX_RK;
350extern const SAI_cfg_t SAI_I2S_SLAVE_16_TXRX_TK;
351extern const SAI_cfg_t SAI_I2S_SLAVE_16_TXRX_TKRK;
352extern const SAI_cfg_t SAI_I2S_SLAVE_8_TXRX_RK;
353extern const SAI_cfg_t SAI_I2S_SLAVE_8_TXRX_TK;
354extern const SAI_cfg_t SAI_I2S_SLAVE_8_TXRX_TKRK;
355
356extern const SAI_cfg_t SAI_LJUST_SLAVE_24_TXRX_RK;
357extern const SAI_cfg_t SAI_LJUST_SLAVE_24_TXRX_TK;
358extern const SAI_cfg_t SAI_LJUST_SLAVE_24_TXRX_TKRK;
359extern const SAI_cfg_t SAI_LJUST_SLAVE_16_TXRX_RK;
360extern const SAI_cfg_t SAI_LJUST_SLAVE_16_TXRX_TK;
361extern const SAI_cfg_t SAI_LJUST_SLAVE_16_TXRX_TKRK;
362extern const SAI_cfg_t SAI_LJUST_SLAVE_8_TXRX_RK;
363extern const SAI_cfg_t SAI_LJUST_SLAVE_8_TXRX_TK;
364extern const SAI_cfg_t SAI_LJUST_SLAVE_8_TXRX_TKRK;
365
366/****************************************/
367/* SAI Driver Context Object */
368/****************************************/
369
377{
378 public:
379 enum ctxState_t
380 {
381 CTX_STATE_STOPPED,
382 CTX_STATE_INIT,
383 CTX_STATE_TX,
384 CTX_STATE_RX,
385 CTX_STATE_TXRX,
386 };
387private:
388 static DmaTcd sDmaTcd[SAI_HW_COUNT][SAI_TXBD_COUNT+SAI_RXBD_COUNT];
389 static SAICtx_t *sCtx[SAI_HW_COUNT];
390 static int sDmaIsr(void *ctx, DmaCh *dmaCh, bool haveError);
391 static void sIsr();
392
393 private:
394 I2S_Type *sai;
395 DmaCh *txDma;
396 uint32_t txBDFlag;
397 DmaCh *rxDma;
398 uint32_t rxBDFlag;
399
400 OS_SEM txSem;
401 OS_SEM rxSem;
402 SAI_BufferDoneFn_t txBufDone;
403 SAI_BufferDoneFn_t rxBufDone;
404 uint32_t txReadyCount;
405 uint32_t rxReadyCount;
406 uint32_t nTxIrq;
407 uint32_t nTxErr;
408 uint32_t nTxPost;
409 uint32_t nTxCall;
410 uint32_t nTxStart;
411 uint32_t nTxAdd;
412
413 uint32_t nRxIrq;
414 uint32_t nRxErr;
415 uint32_t nRxPost;
416 uint32_t nRxCall;
417 uint32_t nRxStart;
418 uint32_t nRxAdd;
419
420 uint8_t stickyTxErr;
421 uint8_t stickyRxErr;
422
423// uint8_t rxByteWidth;
424// uint8_t txByteWidth;
425
426 ctxState_t state;
427 void InitBDs();
428 void initHw_Pins(const SAI_cfg_t &cfg);
429 void initHw_SAI(const SAI_cfg_t &cfg);
430 void initHw_DMA(const SAI_cfg_t &cfg);
431
432 int validateClockSync(const SAI_cfg_t &cfg) const;
433 int validateCfg(const SAI_cfg_t &cfg) const;
434 int InitClocks(uint32_t *saiClk, uint32_t divRem);
435
436 DmaTcd &getFirstTxBD() const;
437 DmaTcd &getLastTxBD() const;
438 DmaTcd &getNextTxBD() const;
439
440 DmaTcd &getFirstRxBD() const;
441 DmaTcd &getLastRxBD() const;
442 DmaTcd &getNextRxBD() const;
443
444 DmaTcd &getFirstBD(const DmaCh *dma) const;
445 DmaTcd &getLastBD(const DmaCh *dma) const;
446 DmaTcd &getNextBD(const DmaCh *dma) const;
447
448 int queueBuffer(void *buffer, uint32_t bufferLen, bool waitIfNeeded, bool enableHalfNotify, DmaCh *dma);
449
450 int getIdx() const;
451
452 int DmaIsr(DmaCh *dma, bool haveError);
453 void Isr();
454
455 public:
462 int Init(const SAI_cfg_t &cfg);
466 void Shutdown();
467
468 inline int GetMaxTxBuffers() { return SAI_TXBD_COUNT; }
469 inline int GetMaxRxBuffers() { return SAI_RXBD_COUNT; }
470
482 inline ctxState_t getState() const { return state; }
483
499 int TransmitBuffer(void *buffer, uint32_t bufferLen, bool waitIfNeeded, bool enableHalfNotify= false);
500
514 int ReadyReceiveBuffer(void *buffer, uint32_t bufferLen, bool waitIfNeeded, bool enableHalfNotify = false);
515
519 void RegisterTxBufferCB(SAI_BufferDoneFn_t cb);
523 void RegisterRxBufferCB(SAI_BufferDoneFn_t cb);
524
525
526 inline void clrStickyTxError() { stickyTxErr = 0; }
527 inline void clrStickyRxError() { stickyRxErr = 0; }
528 inline uint8_t getStickyTxError() { return stickyTxErr; }
529 inline uint8_t getStickyRxError() { return stickyRxErr; }
530
531 void dump();
532};
533
534extern SAICtx_t sai;
535
536
Definition sai.h:377
void Shutdown()
Shuts down the SAI hardware and driver.
void RegisterRxBufferCB(SAI_BufferDoneFn_t cb)
Registers a callback for when a receive buffer is finished.
int getCurrentConfig(SAI_cfg_t &cfg)
Fills in the config object with the current active configuration.
ctxState_t getState() const
Returns the current driver state.
Definition sai.h:482
void RegisterTxBufferCB(SAI_BufferDoneFn_t cb)
Registers a callback for when a transmit buffer is finished.
int ReadyReceiveBuffer(void *buffer, uint32_t bufferLen, bool waitIfNeeded, bool enableHalfNotify=false)
Hands off a buffer to be written to by the SAI driver.
int Init(const SAI_cfg_t &cfg)
Initializes the SAI hardware and driver context.
int TransmitBuffer(void *buffer, uint32_t bufferLen, bool waitIfNeeded, bool enableHalfNotify=false)
Hands off a buffer to be transmitted by the SAI driver. The driver will add this buffer to the chain ...
NetBurner Real-Time Operating System (NBRTOS) API.
Semaphores are used to control access to shared resources or or to communicate between tasks in a mul...
Definition nbrtos.h:411
Configuration structure for the SAI driver. Passed to the initialize function to configure the hardwa...
Definition sai.h:295
SAI_rxtx_cfg_t rx
Definition sai.h:302
SAI_rxtx_cfg_t tx
Definition sai.h:303
Configuration structure for a given direction (rx or tx) of the SAI module. Passed to the initialize ...
Definition sai.h:256
bool lineIdleState
Definition sai.h:274
clkGate_t clkGate
Definition sai.h:260
bufferDepletionBehavior_t depletionBehavior
Definition sai.h:278
frameEdge_t syncEdge
Definition sai.h:267
bool enable
Definition sai.h:257
clkSrc_t clkSrc
Definition sai.h:262
uint8_t startDly
Definition sai.h:258
uint8_t wordsPerFrame
Definition sai.h:270
uint8_t bitsPerWord
Definition sai.h:275
frameSyncOut_t syncOut
Definition sai.h:268
bitOrder_t bitOrder
Definition sai.h:273
clkOut_t clkOut
Definition sai.h:261
startCond_t startCond
Definition sai.h:259
uint32_t wordMask
Definition sai.h:276
uint8_t syncLen
Definition sai.h:266