Lancaster University's (short term!) clone of mbed-src for micro:bit. This is a copy of the github branch https://github.com/lancaster-university/mbed-classic
Fork of mbed-src by
common/SPI.cpp
- Committer:
- LancasterUniversity
- Date:
- 2016-07-13
- Revision:
- 641:be9b2017785a
- Parent:
- 563:536c9fb088a0
File content as of revision 641:be9b2017785a:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "SPI.h" #if DEVICE_SPI namespace mbed { #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer; #endif SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : _spi(), #if DEVICE_SPI_ASYNCH _irq(this), _usage(DMA_USAGE_NEVER), #endif _bits(8), _mode(0), _hz(1000000) { spi_init(&_spi, mosi, miso, sclk, ssel); spi_format(&_spi, _bits, _mode, 0); spi_frequency(&_spi, _hz); } void SPI::format(int bits, int mode) { _bits = bits; _mode = mode; SPI::_owner = NULL; // Not that elegant, but works. rmeyer aquire(); } void SPI::frequency(int hz) { _hz = hz; SPI::_owner = NULL; // Not that elegant, but works. rmeyer aquire(); } SPI* SPI::_owner = NULL; // ignore the fact there are multiple physical spis, and always update if it wasnt us last void SPI::aquire() { if (_owner != this) { spi_format(&_spi, _bits, _mode, 0); spi_frequency(&_spi, _hz); _owner = this; } } int SPI::write(int value) { aquire(); return spi_master_write(&_spi, value); } #if DEVICE_SPI_ASYNCH int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event) { if (spi_active(&_spi)) { return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); } start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); return 0; } void SPI::abort_transfer() { spi_abort_asynch(&_spi); #if TRANSACTION_QUEUE_SIZE_SPI dequeue_transaction(); #endif } void SPI::clear_transfer_buffer() { #if TRANSACTION_QUEUE_SIZE_SPI _transaction_buffer.reset(); #endif } void SPI::abort_all_transfers() { clear_transfer_buffer(); abort_transfer(); } int SPI::set_dma_usage(DMAUsage usage) { if (spi_active(&_spi)) { return -1; } _usage = usage; return 0; } int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event) { #if TRANSACTION_QUEUE_SIZE_SPI transaction_t t; t.tx_buffer = const_cast<void *>(tx_buffer); t.tx_length = tx_length; t.rx_buffer = rx_buffer; t.rx_length = rx_length; t.event = event; t.callback = callback; t.width = bit_width; Transaction<SPI> transaction(this, t); if (_transaction_buffer.full()) { return -1; // the buffer is full } else { _transaction_buffer.push(transaction); return 0; } #else return -1; #endif } void SPI::start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event) { aquire(); _callback = callback; _irq.callback(&SPI::irq_handler_asynch); spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage); } #if TRANSACTION_QUEUE_SIZE_SPI void SPI::start_transaction(transaction_t *data) { start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event); } void SPI::dequeue_transaction() { Transaction<SPI> t; if (_transaction_buffer.pop(t)) { SPI* obj = t.get_object(); transaction_t* data = t.get_transaction(); obj->start_transaction(data); } } #endif void SPI::irq_handler_asynch(void) { int event = spi_irq_handler_asynch(&_spi); if (_callback && (event & SPI_EVENT_ALL)) { _callback.call(event & SPI_EVENT_ALL); } #if TRANSACTION_QUEUE_SIZE_SPI if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { // SPI peripheral is free (event happend), dequeue transaction dequeue_transaction(); } #endif } #endif } // namespace mbed #endif