V148
Fork of RadioHead-148 by
Diff: RHHardwareSPI.cpp
- Revision:
- 0:ab4e012489ef
- Child:
- 1:b7641da2b203
diff -r 000000000000 -r ab4e012489ef RHHardwareSPI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RHHardwareSPI.cpp Thu Oct 15 01:27:00 2015 +0000 @@ -0,0 +1,336 @@ +// 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 +