Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 18:05:56 by
 1.7.2
 1.7.2