This driver is a stripped down version of the Radiohead 1.45 driver, and covers fewer radios. Threading and an event queue have been added to make the ISR's more stable across architectures. Specifically The STM32L4 parts
Dependents: Threaded_LoRa_Modem
RHHardwareSPI.cpp
- Committer:
- davidr99
- Date:
- 2015-10-15
- Revision:
- 0:ab4e012489ef
- Child:
- 1:dfeb5e8b199a
File content as of revision 0:ab4e012489ef:
// RHHardwareSPI.h // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2011 Mike McCauley // Contributed by Joanna Rutkowska // $Id: RHHardwareSPI.cpp,v 1.12 2015/07/01 00:46:05 mikem Exp $ #include <RHHardwareSPI.h> // Declare a single default instance of the hardware SPI interface class RHHardwareSPI hardware_spi; #ifdef RH_HAVE_HARDWARE_SPI #if (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc // Declare an SPI interface to use HardwareSPI _SPI(1); #elif (RH_PLATFORM == RH_PLATFORM_STM32STD) // STM32F4 Discovery // Declare an SPI interface to use HardwareSPI _SPI(1); #elif (RH_PLATFORM == RH_PLATFORM_MBED) // MBed // Declare an SPI interface to use #define SPI_MOSI PB_15 #define SPI_MISO PB_14 #define SPI_CLK PB_13 SPI _SPI(SPI_MOSI, SPI_MISO, SPI_CLK); #define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)]) static const uint8_t reverse_lookup[] = { 0, 8, 4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 }; #endif // Arduino Due has default SPI pins on central SPI headers, and not on 10, 11, 12, 13 // as per otherArduinos // http://21stdigitalhome.blogspot.com.au/2013/02/arduino-due-hardware-SPI.html #if defined (__arm__) && !defined(CORE_TEENSY) // Arduino Due in 1.5.5 has no definitions for SPI dividers // SPI clock divider is based on MCK of 84MHz #define SPI_CLOCK_DIV16 (VARIANT_MCK/84000000) // 1MHz #define SPI_CLOCK_DIV8 (VARIANT_MCK/42000000) // 2MHz #define SPI_CLOCK_DIV4 (VARIANT_MCK/21000000) // 4MHz #define SPI_CLOCK_DIV2 (VARIANT_MCK/10500000) // 8MHz #define SPI_CLOCK_DIV1 (VARIANT_MCK/5250000) // 16MHz #endif RHHardwareSPI::RHHardwareSPI(Frequency frequency, BitOrder bitOrder, DataMode dataMode) : RHGenericSPI(frequency, bitOrder, dataMode) { } uint8_t RHHardwareSPI::transfer(uint8_t data) { #if (RH_PLATFORM == RH_PLATFORM_MBED) if (_bitOrder == BitOrderLSBFirst) data = REVERSE_BITS(data); return _SPI.write(data); #else return _SPI.transfer(data); #endif } void RHHardwareSPI::attachInterrupt() { #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) _SPI.attachInterrupt(); #endif } void RHHardwareSPI::detachInterrupt() { #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) _SPI.detachInterrupt(); #endif } void RHHardwareSPI::begin() { // Sigh: there are no common symbols for some of these SPI options across all platforms #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_UNO32) uint8_t dataMode; if (_dataMode == DataMode0) dataMode = SPI_MODE0; else if (_dataMode == DataMode1) dataMode = SPI_MODE1; else if (_dataMode == DataMode2) dataMode = SPI_MODE2; else if (_dataMode == DataMode3) dataMode = SPI_MODE3; else dataMode = SPI_MODE0; #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(__arm__) && defined(CORE_TEENSY) // Temporary work-around due to problem where avr_emulation.h does not work properly for the setDataMode() cal SPCR &= ~SPI_MODE_MASK; #else _SPI.setDataMode(dataMode); #endif #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined (__arm__) && !defined(CORE_TEENSY) // Arduino Due in 1.5.5 has its own BitOrder :-( ::BitOrder bitOrder; #else uint8_t bitOrder; #endif if (_bitOrder == BitOrderLSBFirst) bitOrder = LSBFIRST; else bitOrder = MSBFIRST; _SPI.setBitOrder(bitOrder); uint8_t divider; switch (_frequency) { case Frequency1MHz: default: #if F_CPU == 8000000 divider = SPI_CLOCK_DIV8; #else divider = SPI_CLOCK_DIV16; #endif break; case Frequency2MHz: #if F_CPU == 8000000 divider = SPI_CLOCK_DIV4; #else divider = SPI_CLOCK_DIV8; #endif break; case Frequency4MHz: #if F_CPU == 8000000 divider = SPI_CLOCK_DIV2; #else divider = SPI_CLOCK_DIV4; #endif break; case Frequency8MHz: divider = SPI_CLOCK_DIV2; // 4MHz on an 8MHz Arduino break; case Frequency16MHz: divider = SPI_CLOCK_DIV2; // Not really 16MHz, only 8MHz. 4MHz on an 8MHz Arduino break; } _SPI.setClockDivider(divider); _SPI.begin(); #elif (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc spi_mode dataMode; // Hmmm, if we do this as a switch, GCC on maple gets v confused! if (_dataMode == DataMode0) dataMode = SPI_MODE_0; else if (_dataMode == DataMode1) dataMode = SPI_MODE_1; else if (_dataMode == DataMode2) dataMode = SPI_MODE_2; else if (_dataMode == DataMode3) dataMode = SPI_MODE_3; else dataMode = SPI_MODE_0; uint32 bitOrder; if (_bitOrder == BitOrderLSBFirst) bitOrder = LSBFIRST; else bitOrder = MSBFIRST; SPIFrequency frequency; // Yes, I know these are not exact equivalents. switch (_frequency) { case Frequency1MHz: default: frequency = SPI_1_125MHZ; break; case Frequency2MHz: frequency = SPI_2_25MHZ; break; case Frequency4MHz: frequency = SPI_4_5MHZ; break; case Frequency8MHz: frequency = SPI_9MHZ; break; case Frequency16MHz: frequency = SPI_18MHZ; break; } _SPI.begin(frequency, bitOrder, dataMode); #elif (RH_PLATFORM == RH_PLATFORM_STM32STD) // STM32F4 discovery uint8_t dataMode; if (_dataMode == DataMode0) dataMode = SPI_MODE0; else if (_dataMode == DataMode1) dataMode = SPI_MODE1; else if (_dataMode == DataMode2) dataMode = SPI_MODE2; else if (_dataMode == DataMode3) dataMode = SPI_MODE3; else dataMode = SPI_MODE0; uint32_t bitOrder; if (_bitOrder == BitOrderLSBFirst) bitOrder = LSBFIRST; else bitOrder = MSBFIRST; SPIFrequency frequency; // Yes, I know these are not exact equivalents. switch (_frequency) { case Frequency1MHz: default: frequency = SPI_1_3125MHZ; break; case Frequency2MHz: frequency = SPI_2_625MHZ; break; case Frequency4MHz: frequency = SPI_5_25MHZ; break; case Frequency8MHz: frequency = SPI_10_5MHZ; break; case Frequency16MHz: frequency = SPI_21_0MHZ; break; } _SPI.begin(frequency, bitOrder, dataMode); #elif (RH_PLATFORM == RH_PLATFORM_RASPI) // Raspberry PI uint8_t dataMode; if (_dataMode == DataMode0) dataMode = BCM2835_SPI_MODE0; else if (_dataMode == DataMode1) dataMode = BCM2835_SPI_MODE1; else if (_dataMode == DataMode2) dataMode = BCM2835_SPI_MODE2; else if (_dataMode == DataMode3) dataMode = BCM2835_SPI_MODE3; uint8_t bitOrder; if (_bitOrder == BitOrderLSBFirst) bitOrder = BCM2835_SPI_BIT_ORDER_LSBFIRST; else bitOrder = BCM2835_SPI_BIT_ORDER_MSBFIRST; uint32_t divider; switch (_frequency) { case Frequency1MHz: default: divider = BCM2835_SPI_CLOCK_DIVIDER_256; break; case Frequency2MHz: divider = BCM2835_SPI_CLOCK_DIVIDER_128; break; case Frequency4MHz: divider = BCM2835_SPI_CLOCK_DIVIDER_64; break; case Frequency8MHz: divider = BCM2835_SPI_CLOCK_DIVIDER_32; break; case Frequency16MHz: divider = BCM2835_SPI_CLOCK_DIVIDER_16; break; } _SPI.begin(divider, bitOrder, dataMode); #elif (RH_PLATFORM == RH_PLATFORM_MBED) // MBed uint8_t dataMode; if (_dataMode == DataMode0) dataMode = 0; else if (_dataMode == DataMode1) dataMode = 1; else if (_dataMode == DataMode2) dataMode = 2; else if (_dataMode == DataMode3) dataMode = 3; _SPI.format(8, dataMode); int frequency; switch (_frequency) { case Frequency1MHz: default: frequency = 1000000; break; case Frequency2MHz: frequency = 2000000; break; case Frequency4MHz: frequency = 4000000; break; case Frequency8MHz: frequency = 8000000; break; case Frequency16MHz: frequency = 16000000; break; } _SPI.frequency(frequency); #else #warning RHHardwareSPI does not support this platform yet. Consider adding it and contributing a patch. #endif } void RHHardwareSPI::end() { #if (RH_PLATFORM == RH_PLATFORM_MBED) // no end for SPI #else return _SPI.end(); #endif } #endif