V148
Fork of RadioHead-148 by
RHHardwareSPI.cpp
- Committer:
- davidr99
- Date:
- 2015-10-15
- Revision:
- 0:ab4e012489ef
- Child:
- 1:b7641da2b203
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