Quentin Roche / ST_I2S

Dependents:   X_NUCLEO_CCA02M1

Fork of ST_I2S by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2S.cpp Source File

I2S.cpp

00001 #include "drivers/I2S.h"
00002 #include "platform/mbed_critical.h"
00003 #include "platform/mbed_assert.h"
00004 
00005 #if DEVICE_I2S
00006 
00007 I2S* I2S::_owner = NULL;
00008 SingletonPtr<PlatformMutex> I2S::_mutex; // intentional class level lock!
00009 
00010 events::EventQueue I2S::i2s_bh_queue;
00011 
00012 void I2S::lock() {
00013 #if defined(NDEBUG) || !defined(MBED_CONF_RTOS_PRESENT)
00014     _mutex->lock(); // intentional class level lock!
00015 #else
00016     osStatus ret = _mutex->lock(); // intentional class level lock!
00017     MBED_ASSERT(ret == osOK);
00018 #endif
00019 }
00020 
00021 void I2S::unlock() {
00022 #if defined(NDEBUG) || !defined(MBED_CONF_RTOS_PRESENT)
00023     _mutex->unlock(); // intentional class level lock!
00024 #else
00025     osStatus ret = _mutex->unlock(); // intentional class level lock!
00026     MBED_ASSERT(ret == osOK);
00027 #endif
00028 }
00029 
00030 I2S::I2S(PinName dpin, PinName clk, PinName wsel, PinName fdpin, PinName mck) :
00031     _i2s(),
00032     _irq_tx(this), _irq_rx(this),
00033     _priority(MEDIUM),
00034     _dbits(16),
00035     _fbits(16),
00036     _polarity(0),
00037     _protocol(PHILIPS),
00038     _mode(MASTER_TX),
00039     _circular(false),
00040     _hz(44100) {
00041     lock();
00042     /* Init instance */
00043     i2s_init(&_i2s, dpin, clk, wsel, fdpin, mck, _mode);
00044     acquire();
00045     unlock();
00046 }
00047 
00048 int I2S::format(int dbits, int fbits, int polarity) {
00049     lock();
00050     if (i2s_active(&_i2s)) {
00051     unlock();
00052     return -1;
00053     }
00054     _dbits = dbits;
00055     _fbits = fbits;
00056     _polarity = polarity;
00057     I2S::_owner = NULL; // Not that elegant, but works. rmeyer
00058     acquire();
00059     unlock();
00060     return 0;
00061 }
00062 
00063 int I2S::audio_frequency(unsigned int hz) {
00064     lock();
00065     if (i2s_active(&_i2s)) {
00066     unlock();
00067     return -1;
00068     }
00069     _hz = hz;
00070     I2S::_owner = NULL; // Not that elegant, but works. rmeyer
00071     acquire();
00072     unlock();
00073     return 0;
00074 }
00075 
00076 int I2S::protocol(i2s_bitorder_t protocol) {
00077     lock();
00078     if (i2s_active(&_i2s)) {
00079     unlock();
00080     return -1;
00081     }
00082     _protocol = protocol;
00083     I2S::_owner = NULL; // Not that elegant, but works. rmeyer
00084     acquire();
00085     unlock();
00086     return 0;
00087 }
00088 
00089 int I2S::mode(i2s_mode_t mode, bool circular) {
00090     lock();
00091     if (i2s_active(&_i2s)) {
00092     unlock();
00093     return -1;
00094     }
00095     _mode = mode;
00096     _circular = circular;
00097     I2S::_owner = NULL; // Not that elegant, but works. rmeyer
00098     acquire();
00099     unlock();
00100     return 0;
00101 }
00102 
00103 int I2S::harmonize(I2S &dev_i2s_1, I2S &dev_i2s_2) {
00104     dev_i2s_1.lock();
00105     if (i2s_active(&dev_i2s_1._i2s)) {
00106     dev_i2s_1.unlock();
00107     return -1;
00108     }
00109 
00110     dev_i2s_2.lock();
00111     if (i2s_active(&dev_i2s_2._i2s)) {
00112     dev_i2s_2.unlock();
00113     dev_i2s_1.unlock();
00114     return -1;
00115     }
00116 
00117     uint32_t hz1 = dev_i2s_1._hz;
00118     uint32_t hz2 = dev_i2s_2._hz;
00119     int8_t ret = i2s_harmonize(&dev_i2s_1._i2s, &hz1, &dev_i2s_2._i2s, &hz2);
00120 
00121     if(ret == 0) {
00122     dev_i2s_1.audio_frequency(hz1);
00123     dev_i2s_2.audio_frequency(hz2);
00124     }
00125 
00126     dev_i2s_2.unlock();
00127     dev_i2s_1.unlock();
00128 
00129     return ret;
00130 }
00131 
00132 void I2S::abort_transfer()
00133 {
00134     lock();
00135     i2s_abort_asynch(&_i2s);
00136 #if TRANSACTION_QUEUE_SIZE_I2S
00137     dequeue_transaction();
00138 #endif
00139     unlock();
00140 }
00141 
00142 
00143 void I2S::clear_transfer_buffer()
00144 {
00145 #if TRANSACTION_QUEUE_SIZE_I2S
00146     lock();
00147     _transaction_buffer.reset();
00148     unlock();
00149 #endif
00150 }
00151 
00152 void I2S::abort_all_transfers()
00153 {
00154     lock();
00155     clear_transfer_buffer();
00156     abort_transfer();
00157     unlock();
00158 }
00159 
00160 int I2S::get_transfer_status()
00161 {
00162     lock();
00163     if (i2s_active(&_i2s)) {
00164     unlock();
00165     return -1;
00166     }
00167     unlock();
00168     return  0;
00169 }
00170 
00171 unsigned int I2S::get_module()
00172 {
00173     return i2s_get_module(&_i2s);
00174 }
00175 
00176 int I2S::dma_priority(i2s_dma_prio_t prio)
00177 {
00178     lock();
00179     if (i2s_active(&_i2s)) {
00180     unlock();
00181     return -1;
00182     }
00183     _priority = prio;
00184     unlock();
00185     return  0;
00186 }
00187 
00188 int I2S::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, const mbed::event_callback_t& callback, int event)
00189 { // NOTE: MUST be called with lock held!
00190 #if TRANSACTION_QUEUE_SIZE_I2S
00191     mbed::transaction_t t;
00192 
00193     t.tx_buffer = const_cast<void *>(tx_buffer);
00194     t.tx_length = tx_length;
00195     t.rx_buffer = rx_buffer;
00196     t.rx_length = rx_length;
00197     t.event = event;
00198     t.callback = callback;
00199     t.width = 16;
00200     mbed::Transaction<I2S> transaction(this, t);
00201     core_util_critical_section_enter();
00202     if (_transaction_buffer.full()) {
00203     core_util_critical_section_enter();
00204     return -1; // the buffer is full
00205     } else {
00206     _transaction_buffer.push(transaction);
00207     core_util_critical_section_exit();
00208     return 0;
00209     }
00210 #else
00211     return -1;
00212 #endif
00213 }
00214 
00215 
00216 // ignore the fact that there are multiple physical i2s's, and always update if it wasn't us last
00217 void I2S::acquire() { // NOTE: MUST be called with lock held!
00218     if (_owner != this) {
00219     i2s_format(&_i2s, _dbits, _fbits, _polarity);
00220     i2s_audio_frequency(&_i2s, _hz);
00221     i2s_set_protocol(&_i2s, _protocol);
00222     i2s_set_mode(&_i2s, _mode);
00223     _owner = this;
00224     }
00225 }
00226 
00227 void I2S::start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, 
00228              const mbed::event_callback_t& callback, int event)
00229 { // NOTE: MUST be called with lock held!
00230     acquire();
00231     _callback = callback;
00232     _irq_tx.callback(&I2S::irq_handler_asynch_tx);
00233     _irq_rx.callback(&I2S::irq_handler_asynch_rx);
00234     i2s_transfer(&_i2s,
00235          const_cast<void *>(tx_buffer), tx_length, rx_buffer, rx_length,
00236          _circular, _priority,
00237          _irq_tx.entry(), _irq_rx.entry(),
00238          event);
00239 }
00240 
00241 #if TRANSACTION_QUEUE_SIZE_I2S
00242 
00243 void I2S::start_transaction(mbed::transaction_t *data)
00244 { // NOTE: MUST be called with lock held!
00245     start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->callback, data->event);
00246 }
00247 
00248 void I2S::dequeue_transaction()
00249 {
00250     lock();
00251     if (!i2s_active(&_i2s)) {
00252     mbed::Transaction<I2S> t;
00253     if (_transaction_buffer.pop(t)) {
00254         I2S* obj = t.get_object();
00255         mbed::transaction_t* data = t.get_transaction();
00256         MBED_ASSERT(obj == this);
00257         obj->start_transaction(data);
00258     }
00259     }
00260     unlock();
00261 }
00262 
00263 #endif
00264 
00265 void I2S::irq_handler_asynch_rx(void)
00266 {
00267     int event = i2s_irq_handler_asynch(&_i2s, I2S_RX_EVENT);
00268     if (_callback && (event & I2S_EVENT_ALL)) {
00269     I2sBhHandler::i2s_defer_function(_callback, event & I2S_EVENT_ALL);
00270     }
00271 #if TRANSACTION_QUEUE_SIZE_I2S
00272     if (event & I2S_EVENT_INTERNAL_TRANSFER_COMPLETE) {
00273     I2sBhHandler::i2s_defer_function(mbed::Callback<void()>(this, &I2S::dequeue_transaction));
00274     }
00275 #endif
00276 }
00277 
00278 void I2S::irq_handler_asynch_tx(void)
00279 {
00280     int event = i2s_irq_handler_asynch(&_i2s, I2S_TX_EVENT);
00281     if (_callback && (event & I2S_EVENT_ALL)) {
00282     I2sBhHandler::i2s_defer_function(_callback, event & I2S_EVENT_ALL);
00283     }
00284 #if TRANSACTION_QUEUE_SIZE_I2S
00285     if (event & I2S_EVENT_INTERNAL_TRANSFER_COMPLETE) {
00286     I2sBhHandler::i2s_defer_function(mbed::Callback<void()>(this, &I2S::dequeue_transaction));
00287     }
00288 #endif
00289 }
00290 
00291 #endif // DEVICE_I2S