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

Revision:
0:ab4e012489ef
Child:
1:dfeb5e8b199a
--- /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
+