V148

Fork of RadioHead-148 by David Rimer

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