David Rimer / RadioHead-148
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RHHardwareSPI.cpp Source File

RHHardwareSPI.cpp

00001 // RHHardwareSPI.h
00002 // Author: Mike McCauley (mikem@airspayce.com)
00003 // Copyright (C) 2011 Mike McCauley
00004 // Contributed by Joanna Rutkowska
00005 // $Id: RHHardwareSPI.cpp,v 1.12 2015/07/01 00:46:05 mikem Exp $
00006 
00007 #include <RHHardwareSPI.h>
00008 
00009 // Declare a single default instance of the hardware SPI interface class
00010 RHHardwareSPI hardware_spi;
00011 
00012 #ifdef RH_HAVE_HARDWARE_SPI
00013 
00014 #if (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc
00015 // Declare an SPI interface to use
00016 HardwareSPI _SPI(1);
00017 #elif (RH_PLATFORM == RH_PLATFORM_STM32STD) // STM32F4 Discovery
00018 // Declare an SPI interface to use
00019 HardwareSPI _SPI(1);
00020 #elif (RH_PLATFORM == RH_PLATFORM_MBED) // MBed
00021 // Declare an SPI interface to use
00022 #define SPI_MOSI    PB_15
00023 #define SPI_MISO    PB_14
00024 #define SPI_CLK     PB_13
00025 
00026 SPI _SPI(SPI_MOSI, SPI_MISO, SPI_CLK);
00027 
00028 #define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)])
00029     
00030 static const uint8_t reverse_lookup[] = { 0, 8,  4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 };
00031 
00032 #endif
00033 
00034 // Arduino Due has default SPI pins on central SPI headers, and not on 10, 11, 12, 13
00035 // as per otherArduinos
00036 // http://21stdigitalhome.blogspot.com.au/2013/02/arduino-due-hardware-SPI.html
00037 #if defined (__arm__) && !defined(CORE_TEENSY)
00038  // Arduino Due in 1.5.5 has no definitions for SPI dividers
00039  // SPI clock divider is based on MCK of 84MHz  
00040  #define SPI_CLOCK_DIV16 (VARIANT_MCK/84000000) // 1MHz
00041  #define SPI_CLOCK_DIV8  (VARIANT_MCK/42000000) // 2MHz
00042  #define SPI_CLOCK_DIV4  (VARIANT_MCK/21000000) // 4MHz
00043  #define SPI_CLOCK_DIV2  (VARIANT_MCK/10500000) // 8MHz
00044  #define SPI_CLOCK_DIV1  (VARIANT_MCK/5250000)  // 16MHz
00045 #endif
00046 
00047 RHHardwareSPI::RHHardwareSPI(Frequency frequency, BitOrder bitOrder, DataMode dataMode)
00048     :
00049     RHGenericSPI(frequency, bitOrder, dataMode)
00050 {
00051 }
00052 
00053 uint8_t RHHardwareSPI::transfer(uint8_t data) 
00054 {
00055 #if (RH_PLATFORM == RH_PLATFORM_MBED)
00056     if (_bitOrder == BitOrderLSBFirst)
00057         data = REVERSE_BITS(data);
00058     
00059     return _SPI.write(data);
00060 #else
00061     return _SPI.transfer(data);
00062 #endif
00063 }
00064 
00065 void RHHardwareSPI::attachInterrupt() 
00066 {
00067 #if (RH_PLATFORM == RH_PLATFORM_ARDUINO)
00068     _SPI.attachInterrupt();
00069 #endif
00070 }
00071 
00072 void RHHardwareSPI::detachInterrupt() 
00073 {
00074 #if (RH_PLATFORM == RH_PLATFORM_ARDUINO)
00075     _SPI.detachInterrupt();
00076 #endif
00077 }
00078     
00079 void RHHardwareSPI::begin() 
00080 {
00081     // Sigh: there are no common symbols for some of these SPI options across all platforms
00082 #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_UNO32)
00083     uint8_t dataMode;
00084     if (_dataMode == DataMode0)
00085     dataMode = SPI_MODE0;
00086     else if (_dataMode == DataMode1)
00087     dataMode = SPI_MODE1;
00088     else if (_dataMode == DataMode2)
00089     dataMode = SPI_MODE2;
00090     else if (_dataMode == DataMode3)
00091     dataMode = SPI_MODE3;
00092     else
00093     dataMode = SPI_MODE0;
00094 #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(__arm__) && defined(CORE_TEENSY)
00095     // Temporary work-around due to problem where avr_emulation.h does not work properly for the setDataMode() cal
00096     SPCR &= ~SPI_MODE_MASK;
00097 #else
00098     _SPI.setDataMode(dataMode);
00099 #endif
00100 
00101 #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined (__arm__) && !defined(CORE_TEENSY)
00102     // Arduino Due in 1.5.5 has its own BitOrder :-(
00103     ::BitOrder bitOrder;
00104 #else
00105     uint8_t bitOrder;
00106 #endif
00107     if (_bitOrder == BitOrderLSBFirst)
00108     bitOrder = LSBFIRST;
00109     else
00110     bitOrder = MSBFIRST;
00111     _SPI.setBitOrder(bitOrder);
00112 
00113     uint8_t divider;
00114     switch (_frequency)
00115     {
00116     case Frequency1MHz:
00117     default:
00118 #if F_CPU == 8000000
00119         divider = SPI_CLOCK_DIV8;
00120 #else
00121         divider = SPI_CLOCK_DIV16;
00122 #endif
00123         break;
00124 
00125     case Frequency2MHz:
00126 #if F_CPU == 8000000
00127         divider = SPI_CLOCK_DIV4;
00128 #else
00129         divider = SPI_CLOCK_DIV8;
00130 #endif
00131         break;
00132 
00133     case Frequency4MHz:
00134 #if F_CPU == 8000000
00135         divider = SPI_CLOCK_DIV2;
00136 #else
00137         divider = SPI_CLOCK_DIV4;
00138 #endif
00139         break;
00140 
00141     case Frequency8MHz:
00142         divider = SPI_CLOCK_DIV2; // 4MHz on an 8MHz Arduino
00143         break;
00144 
00145     case Frequency16MHz:
00146         divider = SPI_CLOCK_DIV2; // Not really 16MHz, only 8MHz. 4MHz on an 8MHz Arduino
00147         break;
00148 
00149     }
00150     _SPI.setClockDivider(divider);
00151     _SPI.begin();
00152 
00153 #elif (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc
00154     spi_mode dataMode;
00155     // Hmmm, if we do this as a switch, GCC on maple gets v confused!
00156     if (_dataMode == DataMode0)
00157     dataMode = SPI_MODE_0;
00158     else if (_dataMode == DataMode1)
00159     dataMode = SPI_MODE_1;
00160     else if (_dataMode == DataMode2)
00161     dataMode = SPI_MODE_2;
00162     else if (_dataMode == DataMode3)
00163     dataMode = SPI_MODE_3;
00164     else
00165     dataMode = SPI_MODE_0;
00166 
00167     uint32 bitOrder;
00168     if (_bitOrder == BitOrderLSBFirst)
00169     bitOrder = LSBFIRST;
00170     else
00171     bitOrder = MSBFIRST;
00172 
00173     SPIFrequency frequency; // Yes, I know these are not exact equivalents.
00174     switch (_frequency)
00175     {
00176     case Frequency1MHz:
00177     default:
00178         frequency = SPI_1_125MHZ;
00179         break;
00180 
00181     case Frequency2MHz:
00182         frequency = SPI_2_25MHZ;
00183         break;
00184 
00185     case Frequency4MHz:
00186         frequency = SPI_4_5MHZ;
00187         break;
00188 
00189     case Frequency8MHz:
00190         frequency = SPI_9MHZ;
00191         break;
00192 
00193     case Frequency16MHz:
00194         frequency = SPI_18MHZ;
00195         break;
00196 
00197     }
00198     _SPI.begin(frequency, bitOrder, dataMode);
00199 
00200 #elif (RH_PLATFORM == RH_PLATFORM_STM32STD) // STM32F4 discovery
00201     uint8_t dataMode;
00202     if (_dataMode == DataMode0)
00203     dataMode = SPI_MODE0;
00204     else if (_dataMode == DataMode1)
00205     dataMode = SPI_MODE1;
00206     else if (_dataMode == DataMode2)
00207     dataMode = SPI_MODE2;
00208     else if (_dataMode == DataMode3)
00209     dataMode = SPI_MODE3;
00210     else
00211     dataMode = SPI_MODE0;
00212 
00213     uint32_t bitOrder;
00214     if (_bitOrder == BitOrderLSBFirst)
00215     bitOrder = LSBFIRST;
00216     else
00217     bitOrder = MSBFIRST;
00218 
00219     SPIFrequency frequency; // Yes, I know these are not exact equivalents.
00220     switch (_frequency)
00221     {
00222     case Frequency1MHz:
00223     default:
00224         frequency = SPI_1_3125MHZ;
00225         break;
00226 
00227     case Frequency2MHz:
00228         frequency = SPI_2_625MHZ;
00229         break;
00230 
00231     case Frequency4MHz:
00232         frequency = SPI_5_25MHZ;
00233         break;
00234 
00235     case Frequency8MHz:
00236         frequency = SPI_10_5MHZ;
00237         break;
00238 
00239     case Frequency16MHz:
00240         frequency = SPI_21_0MHZ;
00241         break;
00242 
00243     }
00244     _SPI.begin(frequency, bitOrder, dataMode);
00245 #elif (RH_PLATFORM == RH_PLATFORM_RASPI) // Raspberry PI
00246   uint8_t dataMode;
00247   if (_dataMode == DataMode0)
00248     dataMode = BCM2835_SPI_MODE0;
00249   else if (_dataMode == DataMode1)
00250     dataMode = BCM2835_SPI_MODE1;
00251   else if (_dataMode == DataMode2)
00252     dataMode = BCM2835_SPI_MODE2;
00253   else if (_dataMode == DataMode3)
00254     dataMode = BCM2835_SPI_MODE3;
00255 
00256   uint8_t bitOrder;
00257   if (_bitOrder == BitOrderLSBFirst)
00258     bitOrder = BCM2835_SPI_BIT_ORDER_LSBFIRST;
00259   else
00260     bitOrder = BCM2835_SPI_BIT_ORDER_MSBFIRST;
00261 
00262   uint32_t divider;
00263   switch (_frequency)
00264   {
00265     case Frequency1MHz:
00266     default:
00267       divider = BCM2835_SPI_CLOCK_DIVIDER_256;
00268       break;
00269     case Frequency2MHz:
00270       divider = BCM2835_SPI_CLOCK_DIVIDER_128;
00271       break;
00272     case Frequency4MHz:
00273       divider = BCM2835_SPI_CLOCK_DIVIDER_64;
00274       break;
00275     case Frequency8MHz:
00276       divider = BCM2835_SPI_CLOCK_DIVIDER_32;
00277       break;
00278     case Frequency16MHz:
00279       divider = BCM2835_SPI_CLOCK_DIVIDER_16;
00280       break;
00281   }
00282   _SPI.begin(divider, bitOrder, dataMode);
00283 #elif (RH_PLATFORM == RH_PLATFORM_MBED) // MBed
00284     uint8_t dataMode;
00285     if (_dataMode == DataMode0)
00286         dataMode = 0;
00287     else if (_dataMode == DataMode1)
00288         dataMode = 1;
00289     else if (_dataMode == DataMode2)
00290         dataMode = 2;
00291     else if (_dataMode == DataMode3)
00292         dataMode = 3;
00293         
00294     _SPI.format(8, dataMode);
00295     
00296     int frequency;
00297     switch (_frequency)
00298     {
00299         case Frequency1MHz:
00300         default:
00301             frequency = 1000000;
00302             break;
00303     
00304         case Frequency2MHz:
00305             frequency = 2000000;
00306             break;
00307     
00308         case Frequency4MHz:
00309             frequency = 4000000;
00310             break;
00311     
00312         case Frequency8MHz:
00313             frequency = 8000000;
00314             break;
00315     
00316         case Frequency16MHz:
00317             frequency = 16000000;
00318             break;
00319     }
00320     _SPI.frequency(frequency);
00321 #else
00322  #warning RHHardwareSPI does not support this platform yet. Consider adding it and contributing a patch.
00323 #endif
00324 }
00325 
00326 void RHHardwareSPI::end() 
00327 {
00328 #if (RH_PLATFORM == RH_PLATFORM_MBED)
00329     // no end for SPI
00330 #else
00331     return _SPI.end();
00332 #endif
00333 }
00334 
00335 #endif
00336