Il y avait des problèmes dans la libraire...

Dependents:   X_NUCLEO_CCA02M1

Fork of ST_I2S by ST

Committer:
Wolfgang Betz
Date:
Fri Dec 23 12:27:30 2016 +0100
Revision:
13:fa1b24df9025
Parent:
10:1a612c2e4a85
Child:
16:04e1abb4cca3
My trial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 0:752e74bf5ef1 1 #ifndef MBED_I2S_H
Wolfgang Betz 0:752e74bf5ef1 2 #define MBED_I2S_H
Wolfgang Betz 0:752e74bf5ef1 3
Wolfgang Betz 0:752e74bf5ef1 4 #include "platform/platform.h"
Wolfgang Betz 0:752e74bf5ef1 5
Wolfgang Betz 0:752e74bf5ef1 6 #if DEVICE_I2S
Wolfgang Betz 0:752e74bf5ef1 7
Wolfgang Betz 0:752e74bf5ef1 8 #include "platform/PlatformMutex.h"
Wolfgang Betz 1:f90318e0923b 9 #include "hal/stm_i2s_api.h"
Wolfgang Betz 0:752e74bf5ef1 10 #include "platform/SingletonPtr.h"
Wolfgang Betz 0:752e74bf5ef1 11
Wolfgang Betz 0:752e74bf5ef1 12 #include "platform/CThunk.h"
Wolfgang Betz 1:f90318e0923b 13 #include "hal/stm_dma_api.h"
Wolfgang Betz 0:752e74bf5ef1 14 #include "platform/CircularBuffer.h"
Wolfgang Betz 0:752e74bf5ef1 15 #include "platform/FunctionPointer.h"
Wolfgang Betz 0:752e74bf5ef1 16 #include "platform/Transaction.h"
Wolfgang Betz 0:752e74bf5ef1 17
Wolfgang Betz 0:752e74bf5ef1 18 #include "events/EventQueue.h"
Wolfgang Betz 0:752e74bf5ef1 19
Wolfgang Betz 0:752e74bf5ef1 20 namespace mbed {
Wolfgang Betz 0:752e74bf5ef1 21
Wolfgang Betz 0:752e74bf5ef1 22 /** A I2S Master/Slave, used for communicating with I2S slave/master devices
Wolfgang Betz 0:752e74bf5ef1 23 *
Wolfgang Betz 0:752e74bf5ef1 24 * The default format is set to master transmission mode, one-shot (i.e. not circular)
Wolfgang Betz 0:752e74bf5ef1 25 * 16 data bits & 16 bits per frame, clock polarity 0,
Wolfgang Betz 0:752e74bf5ef1 26 * protocol PHILIPS, and a clock frequency of 44.1kHz
Wolfgang Betz 0:752e74bf5ef1 27 *
Wolfgang Betz 0:752e74bf5ef1 28 * TODO: "direct" PDM support
Wolfgang Betz 0:752e74bf5ef1 29 *
Wolfgang Betz 0:752e74bf5ef1 30 * Most I2S devices will also require Reset signals. These
Wolfgang Betz 0:752e74bf5ef1 31 * can be controlled using <DigitalOut> pins
Wolfgang Betz 0:752e74bf5ef1 32 *
Wolfgang Betz 0:752e74bf5ef1 33 * @Note Synchronization level: Thread safe
Wolfgang Betz 0:752e74bf5ef1 34 *
Wolfgang Betz 0:752e74bf5ef1 35 */
Wolfgang Betz 10:1a612c2e4a85 36 class I2S {
Wolfgang Betz 0:752e74bf5ef1 37
Wolfgang Betz 10:1a612c2e4a85 38 public:
Wolfgang Betz 10:1a612c2e4a85 39 /** Create a I2S master connected to the specified pins
Wolfgang Betz 10:1a612c2e4a85 40 *
Wolfgang Betz 10:1a612c2e4a85 41 * @param dpin I2S data input/output pin
Wolfgang Betz 10:1a612c2e4a85 42 * @param clk I2S clock output pin
Wolfgang Betz 10:1a612c2e4a85 43 * @param wsel I2S word select output pin (might be NC for PDM sources)
Wolfgang Betz 10:1a612c2e4a85 44 * @param fdpin I2S data input pin (for full-duplex operation, default = NC)
Wolfgang Betz 10:1a612c2e4a85 45 * @param mck I2S master clock output (additional pin when needed for some external audio devices, default = NC)
Wolfgang Betz 10:1a612c2e4a85 46 *
Wolfgang Betz 10:1a612c2e4a85 47 * @Note It is up to the application programmer to not generate at the same time two I2S instances with the
Wolfgang Betz 10:1a612c2e4a85 48 * same pin (NC excluded) for one of the parameters, otherwise the correct operation of this class cannot be
Wolfgang Betz 10:1a612c2e4a85 49 * guaranteed (e.g. things like SPI/I2S clock enabling and above all disabling might not work correctly)!
Wolfgang Betz 10:1a612c2e4a85 50 */
Wolfgang Betz 10:1a612c2e4a85 51 I2S(PinName dpin, PinName clk, PinName wsel, PinName fdpin = NC, PinName mck = NC);
Wolfgang Betz 0:752e74bf5ef1 52
Wolfgang Betz 10:1a612c2e4a85 53 /** Configure the data transmission format
Wolfgang Betz 10:1a612c2e4a85 54 *
Wolfgang Betz 10:1a612c2e4a85 55 * @param dbits Number of data bits per I2S frame (16, 24, or 32)
Wolfgang Betz 10:1a612c2e4a85 56 * @param fbits Number of bits per I2S frame (16 or 32)
Wolfgang Betz 10:1a612c2e4a85 57 * @param polarity Clock polarity (either 0/low or 1/high, default = 0)
Wolfgang Betz 10:1a612c2e4a85 58 * @return Zero if the usage was set, -1 if a transaction is on-going
Wolfgang Betz 10:1a612c2e4a85 59 */
Wolfgang Betz 10:1a612c2e4a85 60 int format(int dbits, int fbits, int polarity = 0);
Wolfgang Betz 0:752e74bf5ef1 61
Wolfgang Betz 10:1a612c2e4a85 62 /** Set the i2s audio frequency
Wolfgang Betz 10:1a612c2e4a85 63 *
Wolfgang Betz 10:1a612c2e4a85 64 * @param hz audio frequency in hz
Wolfgang Betz 10:1a612c2e4a85 65 * @return Zero if the usage was set, -1 if a transaction is on-going
Wolfgang Betz 10:1a612c2e4a85 66 */
Wolfgang Betz 10:1a612c2e4a85 67 int audio_frequency(unsigned int hz);
Wolfgang Betz 0:752e74bf5ef1 68
Wolfgang Betz 13:fa1b24df9025 69 /** Get the i2s audio frequency
Wolfgang Betz 13:fa1b24df9025 70 *
Wolfgang Betz 13:fa1b24df9025 71 * @return Currently set audio frequency
Wolfgang Betz 13:fa1b24df9025 72 */
Wolfgang Betz 13:fa1b24df9025 73 unsigned int get_audio_frequency(void) {
Wolfgang Betz 13:fa1b24df9025 74 return _hz;
Wolfgang Betz 13:fa1b24df9025 75 }
Wolfgang Betz 13:fa1b24df9025 76
Wolfgang Betz 10:1a612c2e4a85 77 /** Set the i2s bus protocol
Wolfgang Betz 10:1a612c2e4a85 78 *
Wolfgang Betz 10:1a612c2e4a85 79 * @param protocol I2S protocol to be used
Wolfgang Betz 10:1a612c2e4a85 80 * @return Zero if the usage was set, -1 if a transaction is on-going
Wolfgang Betz 10:1a612c2e4a85 81 */
Wolfgang Betz 10:1a612c2e4a85 82 int set_protocol(i2s_bitorder_t protocol);
Wolfgang Betz 0:752e74bf5ef1 83
Wolfgang Betz 10:1a612c2e4a85 84 /** Set the i2s mode
Wolfgang Betz 10:1a612c2e4a85 85 *
Wolfgang Betz 10:1a612c2e4a85 86 * @param mode I2S mode to be used
Wolfgang Betz 10:1a612c2e4a85 87 * @param circular I2S should read/write buffers continuously (in circular mode)
Wolfgang Betz 10:1a612c2e4a85 88 * @return Zero if the usage was set, -1 if a transaction is on-going
Wolfgang Betz 10:1a612c2e4a85 89 */
Wolfgang Betz 10:1a612c2e4a85 90 int set_mode(i2s_mode_t mode, bool circular);
Wolfgang Betz 0:752e74bf5ef1 91
Wolfgang Betz 10:1a612c2e4a85 92 /** Start non-blocking I2S transfer as configured with above methods
Wolfgang Betz 10:1a612c2e4a85 93 *
Wolfgang Betz 10:1a612c2e4a85 94 * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
Wolfgang Betz 10:1a612c2e4a85 95 * no transmission will be set up
Wolfgang Betz 10:1a612c2e4a85 96 * @param tx_length The length of TX buffer in bytes
Wolfgang Betz 10:1a612c2e4a85 97 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
Wolfgang Betz 10:1a612c2e4a85 98 * received data will be ignored
Wolfgang Betz 10:1a612c2e4a85 99 * @param rx_length The length of RX buffer in bytes
Wolfgang Betz 10:1a612c2e4a85 100 * @param callback The event callback function
Wolfgang Betz 10:1a612c2e4a85 101 * @param event The logical OR of events to notify. Look at i2s hal header file for I2S events.
Wolfgang Betz 10:1a612c2e4a85 102 * @return Zero if the transfer has started (or been queued), or
Wolfgang Betz 10:1a612c2e4a85 103 * -1 if I2S peripheral is busy (or out of resources)
Wolfgang Betz 10:1a612c2e4a85 104 */
Wolfgang Betz 10:1a612c2e4a85 105 template<typename Type>
Wolfgang Betz 10:1a612c2e4a85 106 int transfer(const Type *tx_buffer, int tx_length, Type *rx_buffer, int rx_length, const event_callback_t& callback, int event) {
Wolfgang Betz 10:1a612c2e4a85 107 int ret = 0;
Wolfgang Betz 0:752e74bf5ef1 108
Wolfgang Betz 10:1a612c2e4a85 109 lock();
Wolfgang Betz 10:1a612c2e4a85 110
Wolfgang Betz 10:1a612c2e4a85 111 if (i2s_active(&_i2s)
Wolfgang Betz 0:752e74bf5ef1 112 #if TRANSACTION_QUEUE_SIZE_I2S
Wolfgang Betz 10:1a612c2e4a85 113 || !_transaction_buffer.empty()
Wolfgang Betz 0:752e74bf5ef1 114 #endif
Wolfgang Betz 10:1a612c2e4a85 115 ) {
Wolfgang Betz 10:1a612c2e4a85 116 ret = queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
Wolfgang Betz 10:1a612c2e4a85 117 } else {
Wolfgang Betz 10:1a612c2e4a85 118 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
Wolfgang Betz 9:c4c2240e06d6 119 }
Wolfgang Betz 10:1a612c2e4a85 120
Wolfgang Betz 10:1a612c2e4a85 121 unlock();
Wolfgang Betz 10:1a612c2e4a85 122 return ret;
Wolfgang Betz 10:1a612c2e4a85 123 }
Wolfgang Betz 0:752e74bf5ef1 124
Wolfgang Betz 10:1a612c2e4a85 125 /** Acquire exclusive access to this I2S bus
Wolfgang Betz 10:1a612c2e4a85 126 */
Wolfgang Betz 10:1a612c2e4a85 127 virtual void lock(void);
Wolfgang Betz 0:752e74bf5ef1 128
Wolfgang Betz 10:1a612c2e4a85 129 /** Release exclusive access to this I2S bus
Wolfgang Betz 10:1a612c2e4a85 130 */
Wolfgang Betz 10:1a612c2e4a85 131 virtual void unlock(void);
Wolfgang Betz 0:752e74bf5ef1 132
Wolfgang Betz 10:1a612c2e4a85 133 /** Abort the on-going I2S transfer, and continue with transfer's in the queue if any.
Wolfgang Betz 10:1a612c2e4a85 134 */
Wolfgang Betz 10:1a612c2e4a85 135 void abort_transfer();
Wolfgang Betz 0:752e74bf5ef1 136
Wolfgang Betz 10:1a612c2e4a85 137 /** Clear the transaction buffer
Wolfgang Betz 10:1a612c2e4a85 138 */
Wolfgang Betz 10:1a612c2e4a85 139 void clear_transfer_buffer();
Wolfgang Betz 0:752e74bf5ef1 140
Wolfgang Betz 10:1a612c2e4a85 141 /** Clear the transaction buffer and abort on-going transfer.
Wolfgang Betz 10:1a612c2e4a85 142 */
Wolfgang Betz 10:1a612c2e4a85 143 void abort_all_transfers();
Wolfgang Betz 0:752e74bf5ef1 144
Wolfgang Betz 10:1a612c2e4a85 145 /** Get transfer status
Wolfgang Betz 10:1a612c2e4a85 146 *
Wolfgang Betz 10:1a612c2e4a85 147 * @return -1 if a transaction is on-going, zero otherwise
Wolfgang Betz 10:1a612c2e4a85 148 */
Wolfgang Betz 10:1a612c2e4a85 149 int get_transfer_status();
Wolfgang Betz 0:752e74bf5ef1 150
Wolfgang Betz 10:1a612c2e4a85 151 /** Get internal module id
Wolfgang Betz 10:1a612c2e4a85 152 *
Wolfgang Betz 10:1a612c2e4a85 153 * @return internal module id
Wolfgang Betz 10:1a612c2e4a85 154 */
Wolfgang Betz 10:1a612c2e4a85 155 unsigned int get_module();
Wolfgang Betz 0:752e74bf5ef1 156
Wolfgang Betz 10:1a612c2e4a85 157 /** Configure DMA priority for transfers
Wolfgang Betz 10:1a612c2e4a85 158 *
Wolfgang Betz 10:1a612c2e4a85 159 * @param prio The DMA priority to be used
Wolfgang Betz 10:1a612c2e4a85 160 * @return Zero if the usage was set, -1 if a transaction is on-going
Wolfgang Betz 10:1a612c2e4a85 161 */
Wolfgang Betz 10:1a612c2e4a85 162 int set_dma_priority(i2s_dma_prio_t prio);
Davide Aliprandi 4:21603d68bcf7 163
Wolfgang Betz 10:1a612c2e4a85 164 /** Harmonize the frequencies of the given I2S objects so that they are
Wolfgang Betz 10:1a612c2e4a85 165 * exact multiple one of the other. It can be useful whenever two I2S
Wolfgang Betz 10:1a612c2e4a85 166 * peripherals have to work together and no drift is allowed between them.
Wolfgang Betz 10:1a612c2e4a85 167 *
Wolfgang Betz 10:1a612c2e4a85 168 * @param dev_i2s_1 reference to the first I2S object.
Wolfgang Betz 10:1a612c2e4a85 169 * @param dev_i2s_2 reference to the second I2S object.
Wolfgang Betz 10:1a612c2e4a85 170 * @return Zero if the frequencies have been harmonized correctly, -1
Wolfgang Betz 10:1a612c2e4a85 171 * otherwise.
Wolfgang Betz 10:1a612c2e4a85 172 */
Wolfgang Betz 10:1a612c2e4a85 173 static int harmonize(I2S &dev_i2s_1, I2S &dev_i2s_2);
Wolfgang Betz 0:752e74bf5ef1 174
Wolfgang Betz 0:752e74bf5ef1 175
Wolfgang Betz 10:1a612c2e4a85 176 /** Bottom-half & transactions event queue for all I2S objects
Wolfgang Betz 10:1a612c2e4a85 177 * Must be used by application programmer to schedule/execute bottom-halves
Wolfgang Betz 10:1a612c2e4a85 178 * (i.e. transfer event callback functions) and automatically start queued
Wolfgang Betz 10:1a612c2e4a85 179 * transactions (i.e. transfers), e.g. by calling `events::EventQueue::dispatch_forever()`! */
Wolfgang Betz 10:1a612c2e4a85 180 static events::EventQueue i2s_bh_queue;
Wolfgang Betz 10:1a612c2e4a85 181
Wolfgang Betz 10:1a612c2e4a85 182 protected:
Wolfgang Betz 10:1a612c2e4a85 183 /** I2S TX DMA IRQ handler
Wolfgang Betz 10:1a612c2e4a85 184 *
Wolfgang Betz 10:1a612c2e4a85 185 */
Wolfgang Betz 10:1a612c2e4a85 186 void irq_handler_asynch_tx(void);
Wolfgang Betz 0:752e74bf5ef1 187
Wolfgang Betz 10:1a612c2e4a85 188 /** I2S RX DMA IRQ handler
Wolfgang Betz 10:1a612c2e4a85 189 *
Wolfgang Betz 10:1a612c2e4a85 190 */
Wolfgang Betz 10:1a612c2e4a85 191 void irq_handler_asynch_rx(void);
Wolfgang Betz 0:752e74bf5ef1 192
Wolfgang Betz 10:1a612c2e4a85 193 /** Add a transfer to the queue
Wolfgang Betz 10:1a612c2e4a85 194 * @param data Transaction data
Wolfgang Betz 10:1a612c2e4a85 195 * @return Zero if a transfer was added to the queue, or -1 if the queue is full
Wolfgang Betz 10:1a612c2e4a85 196 */
Wolfgang Betz 10:1a612c2e4a85 197 int queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length,
Wolfgang Betz 10:1a612c2e4a85 198 const event_callback_t& callback, int event);
Wolfgang Betz 10:1a612c2e4a85 199
Wolfgang Betz 10:1a612c2e4a85 200 /** Configures a callback, i2s peripheral and initiate a new transfer
Wolfgang Betz 10:1a612c2e4a85 201 *
Wolfgang Betz 10:1a612c2e4a85 202 * @param data Transaction data
Wolfgang Betz 10:1a612c2e4a85 203 */
Wolfgang Betz 10:1a612c2e4a85 204 void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length,
Wolfgang Betz 10:1a612c2e4a85 205 const event_callback_t& callback, int event);
Wolfgang Betz 0:752e74bf5ef1 206
Wolfgang Betz 10:1a612c2e4a85 207 class I2sBhHandler {
Wolfgang Betz 10:1a612c2e4a85 208 friend class I2S;
Wolfgang Betz 0:752e74bf5ef1 209
Wolfgang Betz 10:1a612c2e4a85 210 static void i2s_defer_function(const event_callback_t& bottom_half, int event) {
Wolfgang Betz 10:1a612c2e4a85 211 i2s_bh_queue.call(bottom_half, event);
Wolfgang Betz 10:1a612c2e4a85 212 }
Wolfgang Betz 0:752e74bf5ef1 213
Wolfgang Betz 10:1a612c2e4a85 214 static void i2s_defer_function(const Callback<void()>& bottom_half) {
Wolfgang Betz 10:1a612c2e4a85 215 i2s_bh_queue.call(bottom_half);
Wolfgang Betz 10:1a612c2e4a85 216 }
Wolfgang Betz 10:1a612c2e4a85 217 };
Wolfgang Betz 0:752e74bf5ef1 218
Wolfgang Betz 0:752e74bf5ef1 219 #if TRANSACTION_QUEUE_SIZE_I2S
Wolfgang Betz 10:1a612c2e4a85 220 /** Start a new transaction
Wolfgang Betz 10:1a612c2e4a85 221 *
Wolfgang Betz 10:1a612c2e4a85 222 * @param data Transaction data
Wolfgang Betz 10:1a612c2e4a85 223 */
Wolfgang Betz 10:1a612c2e4a85 224 void start_transaction(transaction_t *data);
Wolfgang Betz 0:752e74bf5ef1 225
Wolfgang Betz 10:1a612c2e4a85 226 /** Dequeue a transaction
Wolfgang Betz 10:1a612c2e4a85 227 *
Wolfgang Betz 10:1a612c2e4a85 228 */
Wolfgang Betz 10:1a612c2e4a85 229 void dequeue_transaction();
Wolfgang Betz 0:752e74bf5ef1 230
Wolfgang Betz 10:1a612c2e4a85 231 /* betzw - WAS : static */ CircularBuffer<Transaction<I2S>, TRANSACTION_QUEUE_SIZE_I2S> _transaction_buffer;
Wolfgang Betz 0:752e74bf5ef1 232 #endif // TRANSACTION_QUEUE_SIZE_I2S
Wolfgang Betz 0:752e74bf5ef1 233
Wolfgang Betz 10:1a612c2e4a85 234 public:
Wolfgang Betz 10:1a612c2e4a85 235 virtual ~I2S() {
Wolfgang Betz 10:1a612c2e4a85 236 /* betzw - TODO: cleanup has still to be revised completely! */
Wolfgang Betz 10:1a612c2e4a85 237 abort_all_transfers();
Wolfgang Betz 10:1a612c2e4a85 238 i2s_free(&_i2s);
Wolfgang Betz 10:1a612c2e4a85 239 }
Davide Aliprandi 4:21603d68bcf7 240
Wolfgang Betz 10:1a612c2e4a85 241 protected:
Wolfgang Betz 10:1a612c2e4a85 242 i2s_t _i2s;
Davide Aliprandi 4:21603d68bcf7 243
Wolfgang Betz 10:1a612c2e4a85 244 CThunk<I2S> _irq_tx;
Wolfgang Betz 10:1a612c2e4a85 245 CThunk<I2S> _irq_rx;
Wolfgang Betz 10:1a612c2e4a85 246 event_callback_t _callback;
Wolfgang Betz 10:1a612c2e4a85 247 i2s_dma_prio_t _priority; // DMA priority
Wolfgang Betz 0:752e74bf5ef1 248
Wolfgang Betz 10:1a612c2e4a85 249 void acquire(void);
Wolfgang Betz 0:752e74bf5ef1 250
Wolfgang Betz 10:1a612c2e4a85 251 static I2S *_owner;
Wolfgang Betz 10:1a612c2e4a85 252 static SingletonPtr<PlatformMutex> _mutex;
Wolfgang Betz 0:752e74bf5ef1 253
Wolfgang Betz 10:1a612c2e4a85 254 int _dbits;
Wolfgang Betz 10:1a612c2e4a85 255 int _fbits;
Wolfgang Betz 10:1a612c2e4a85 256 int _polarity;
Wolfgang Betz 10:1a612c2e4a85 257 i2s_bitorder_t _protocol;
Wolfgang Betz 10:1a612c2e4a85 258 i2s_mode_t _mode;
Wolfgang Betz 10:1a612c2e4a85 259 bool _circular;
Wolfgang Betz 10:1a612c2e4a85 260 unsigned int _hz;
Wolfgang Betz 10:1a612c2e4a85 261 };
Wolfgang Betz 0:752e74bf5ef1 262
Wolfgang Betz 0:752e74bf5ef1 263 } // namespace mbed
Wolfgang Betz 0:752e74bf5ef1 264
Wolfgang Betz 0:752e74bf5ef1 265 #endif
Wolfgang Betz 0:752e74bf5ef1 266
Wolfgang Betz 0:752e74bf5ef1 267 #endif