Adafruit_SPIDevice.cpp (11686B)
1 #include <Adafruit_SPIDevice.h> 2 #include <Arduino.h> 3 4 //#define DEBUG_SERIAL Serial 5 6 /*! 7 * @brief Create an SPI device with the given CS pin and settins 8 * @param cspin The arduino pin number to use for chip select 9 * @param freq The SPI clock frequency to use, defaults to 1MHz 10 * @param dataOrder The SPI data order to use for bits within each byte, 11 * defaults to SPI_BITORDER_MSBFIRST 12 * @param dataMode The SPI mode to use, defaults to SPI_MODE0 13 * @param theSPI The SPI bus to use, defaults to &theSPI 14 */ 15 Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq, 16 BitOrder dataOrder, uint8_t dataMode, 17 SPIClass *theSPI) { 18 _cs = cspin; 19 _sck = _mosi = _miso = -1; 20 _spi = theSPI; 21 _begun = false; 22 _spiSetting = new SPISettings(freq, dataOrder, dataMode); 23 _freq = freq; 24 _dataOrder = dataOrder; 25 _dataMode = dataMode; 26 } 27 28 /*! 29 * @brief Create an SPI device with the given CS pin and settins 30 * @param cspin The arduino pin number to use for chip select 31 * @param sckpin The arduino pin number to use for SCK 32 * @param misopin The arduino pin number to use for MISO, set to -1 if not 33 * used 34 * @param mosipin The arduino pin number to use for MOSI, set to -1 if not 35 * used 36 * @param freq The SPI clock frequency to use, defaults to 1MHz 37 * @param dataOrder The SPI data order to use for bits within each byte, 38 * defaults to SPI_BITORDER_MSBFIRST 39 * @param dataMode The SPI mode to use, defaults to SPI_MODE0 40 */ 41 Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, 42 int8_t misopin, int8_t mosipin, 43 uint32_t freq, BitOrder dataOrder, 44 uint8_t dataMode) { 45 _cs = cspin; 46 _sck = sckpin; 47 _miso = misopin; 48 _mosi = mosipin; 49 50 #ifdef BUSIO_USE_FAST_PINIO 51 csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin)); 52 csPinMask = digitalPinToBitMask(cspin); 53 if (mosipin != -1) { 54 mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin)); 55 mosiPinMask = digitalPinToBitMask(mosipin); 56 } 57 if (misopin != -1) { 58 misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin)); 59 misoPinMask = digitalPinToBitMask(misopin); 60 } 61 clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin)); 62 clkPinMask = digitalPinToBitMask(sckpin); 63 #endif 64 65 _freq = freq; 66 _dataOrder = dataOrder; 67 _dataMode = dataMode; 68 _begun = false; 69 _spiSetting = new SPISettings(freq, dataOrder, dataMode); 70 _spi = NULL; 71 } 72 73 /*! 74 * @brief Release memory allocated in constructors 75 */ 76 Adafruit_SPIDevice::~Adafruit_SPIDevice() { 77 if (_spiSetting) { 78 delete _spiSetting; 79 _spiSetting = nullptr; 80 } 81 } 82 83 /*! 84 * @brief Initializes SPI bus and sets CS pin high 85 * @return Always returns true because there's no way to test success of SPI 86 * init 87 */ 88 bool Adafruit_SPIDevice::begin(void) { 89 pinMode(_cs, OUTPUT); 90 digitalWrite(_cs, HIGH); 91 92 if (_spi) { // hardware SPI 93 _spi->begin(); 94 } else { 95 pinMode(_sck, OUTPUT); 96 97 if ((_dataMode == SPI_MODE0) || (_dataMode == SPI_MODE1)) { 98 // idle low on mode 0 and 1 99 digitalWrite(_sck, LOW); 100 } else { 101 // idle high on mode 2 or 3 102 digitalWrite(_sck, HIGH); 103 } 104 if (_mosi != -1) { 105 pinMode(_mosi, OUTPUT); 106 digitalWrite(_mosi, HIGH); 107 } 108 if (_miso != -1) { 109 pinMode(_miso, INPUT); 110 } 111 } 112 113 _begun = true; 114 return true; 115 } 116 117 /*! 118 * @brief Transfer (send/receive) one byte over hard/soft SPI 119 * @param buffer The buffer to send and receive at the same time 120 * @param len The number of bytes to transfer 121 */ 122 void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) { 123 if (_spi) { 124 // hardware SPI is easy 125 126 #if defined(SPARK) 127 _spi->transfer(buffer, buffer, len, NULL); 128 #elif defined(STM32) 129 for (size_t i = 0; i < len; i++) { 130 _spi->transfer(buffer[i]); 131 } 132 #else 133 _spi->transfer(buffer, len); 134 #endif 135 return; 136 } 137 138 uint8_t startbit; 139 if (_dataOrder == SPI_BITORDER_LSBFIRST) { 140 startbit = 0x1; 141 } else { 142 startbit = 0x80; 143 } 144 145 bool towrite, lastmosi = !(buffer[0] & startbit); 146 uint8_t bitdelay_us = (1000000 / _freq) / 2; 147 148 // for softSPI we'll do it by hand 149 for (size_t i = 0; i < len; i++) { 150 // software SPI 151 uint8_t reply = 0; 152 uint8_t send = buffer[i]; 153 154 /* 155 Serial.print("\tSending software SPI byte 0x"); 156 Serial.print(send, HEX); 157 Serial.print(" -> 0x"); 158 */ 159 160 // Serial.print(send, HEX); 161 for (uint8_t b = startbit; b != 0; 162 b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1) { 163 164 if (bitdelay_us) { 165 delayMicroseconds(bitdelay_us); 166 } 167 168 if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) { 169 towrite = send & b; 170 if ((_mosi != -1) && (lastmosi != towrite)) { 171 #ifdef BUSIO_USE_FAST_PINIO 172 if (towrite) 173 *mosiPort |= mosiPinMask; 174 else 175 *mosiPort &= ~mosiPinMask; 176 #else 177 digitalWrite(_mosi, towrite); 178 #endif 179 lastmosi = towrite; 180 } 181 182 #ifdef BUSIO_USE_FAST_PINIO 183 *clkPort |= clkPinMask; // Clock high 184 #else 185 digitalWrite(_sck, HIGH); 186 #endif 187 188 if (bitdelay_us) { 189 delayMicroseconds(bitdelay_us); 190 } 191 192 if (_miso != -1) { 193 #ifdef BUSIO_USE_FAST_PINIO 194 if (*misoPort & misoPinMask) { 195 #else 196 if (digitalRead(_miso)) { 197 #endif 198 reply |= b; 199 } 200 } 201 202 #ifdef BUSIO_USE_FAST_PINIO 203 *clkPort &= ~clkPinMask; // Clock low 204 #else 205 digitalWrite(_sck, LOW); 206 #endif 207 } else { // if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3) 208 209 #ifdef BUSIO_USE_FAST_PINIO 210 *clkPort |= clkPinMask; // Clock high 211 #else 212 digitalWrite(_sck, HIGH); 213 #endif 214 215 if (bitdelay_us) { 216 delayMicroseconds(bitdelay_us); 217 } 218 219 if (_mosi != -1) { 220 #ifdef BUSIO_USE_FAST_PINIO 221 if (send & b) 222 *mosiPort |= mosiPinMask; 223 else 224 *mosiPort &= ~mosiPinMask; 225 #else 226 digitalWrite(_mosi, send & b); 227 #endif 228 } 229 230 #ifdef BUSIO_USE_FAST_PINIO 231 *clkPort &= ~clkPinMask; // Clock low 232 #else 233 digitalWrite(_sck, LOW); 234 #endif 235 236 if (_miso != -1) { 237 #ifdef BUSIO_USE_FAST_PINIO 238 if (*misoPort & misoPinMask) { 239 #else 240 if (digitalRead(_miso)) { 241 #endif 242 reply |= b; 243 } 244 } 245 } 246 if (_miso != -1) { 247 buffer[i] = reply; 248 } 249 } 250 } 251 return; 252 } 253 254 /*! 255 * @brief Transfer (send/receive) one byte over hard/soft SPI 256 * @param send The byte to send 257 * @return The byte received while transmitting 258 */ 259 uint8_t Adafruit_SPIDevice::transfer(uint8_t send) { 260 uint8_t data = send; 261 transfer(&data, 1); 262 return data; 263 } 264 265 /*! 266 * @brief Manually begin a transaction (calls beginTransaction if hardware 267 * SPI) 268 */ 269 void Adafruit_SPIDevice::beginTransaction(void) { 270 if (_spi) { 271 _spi->beginTransaction(*_spiSetting); 272 } 273 } 274 275 /*! 276 * @brief Manually end a transaction (calls endTransaction if hardware SPI) 277 */ 278 void Adafruit_SPIDevice::endTransaction(void) { 279 if (_spi) { 280 _spi->endTransaction(); 281 } 282 } 283 284 /*! 285 * @brief Write a buffer or two to the SPI device. 286 * @param buffer Pointer to buffer of data to write 287 * @param len Number of bytes from buffer to write 288 * @param prefix_buffer Pointer to optional array of data to write before 289 * buffer. 290 * @param prefix_len Number of bytes from prefix buffer to write 291 * @return Always returns true because there's no way to test success of SPI 292 * writes 293 */ 294 bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len, 295 uint8_t *prefix_buffer, size_t prefix_len) { 296 if (_spi) { 297 _spi->beginTransaction(*_spiSetting); 298 } 299 300 digitalWrite(_cs, LOW); 301 // do the writing 302 for (size_t i = 0; i < prefix_len; i++) { 303 transfer(prefix_buffer[i]); 304 } 305 for (size_t i = 0; i < len; i++) { 306 transfer(buffer[i]); 307 } 308 digitalWrite(_cs, HIGH); 309 310 if (_spi) { 311 _spi->endTransaction(); 312 } 313 314 #ifdef DEBUG_SERIAL 315 DEBUG_SERIAL.print(F("\tSPIDevice Wrote: ")); 316 if ((prefix_len != 0) && (prefix_buffer != NULL)) { 317 for (uint16_t i = 0; i < prefix_len; i++) { 318 DEBUG_SERIAL.print(F("0x")); 319 DEBUG_SERIAL.print(prefix_buffer[i], HEX); 320 DEBUG_SERIAL.print(F(", ")); 321 } 322 } 323 for (uint16_t i = 0; i < len; i++) { 324 DEBUG_SERIAL.print(F("0x")); 325 DEBUG_SERIAL.print(buffer[i], HEX); 326 DEBUG_SERIAL.print(F(", ")); 327 if (i % 32 == 31) { 328 DEBUG_SERIAL.println(); 329 } 330 } 331 DEBUG_SERIAL.println(); 332 #endif 333 334 return true; 335 } 336 337 /*! 338 * @brief Read from SPI into a buffer from the SPI device. 339 * @param buffer Pointer to buffer of data to read into 340 * @param len Number of bytes from buffer to read. 341 * @param sendvalue The 8-bits of data to write when doing the data read, 342 * defaults to 0xFF 343 * @return Always returns true because there's no way to test success of SPI 344 * writes 345 */ 346 bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) { 347 memset(buffer, sendvalue, len); // clear out existing buffer 348 if (_spi) { 349 _spi->beginTransaction(*_spiSetting); 350 } 351 digitalWrite(_cs, LOW); 352 transfer(buffer, len); 353 digitalWrite(_cs, HIGH); 354 355 if (_spi) { 356 _spi->endTransaction(); 357 } 358 359 #ifdef DEBUG_SERIAL 360 DEBUG_SERIAL.print(F("\tSPIDevice Read: ")); 361 for (uint16_t i = 0; i < len; i++) { 362 DEBUG_SERIAL.print(F("0x")); 363 DEBUG_SERIAL.print(buffer[i], HEX); 364 DEBUG_SERIAL.print(F(", ")); 365 if (len % 32 == 31) { 366 DEBUG_SERIAL.println(); 367 } 368 } 369 DEBUG_SERIAL.println(); 370 #endif 371 372 return true; 373 } 374 375 /*! 376 * @brief Write some data, then read some data from SPI into another buffer. 377 * The buffers can point to same/overlapping locations. This does not 378 * transmit-receive at the same time! 379 * @param write_buffer Pointer to buffer of data to write from 380 * @param write_len Number of bytes from buffer to write. 381 * @param read_buffer Pointer to buffer of data to read into. 382 * @param read_len Number of bytes from buffer to read. 383 * @param sendvalue The 8-bits of data to write when doing the data read, 384 * defaults to 0xFF 385 * @return Always returns true because there's no way to test success of SPI 386 * writes 387 */ 388 bool Adafruit_SPIDevice::write_then_read(uint8_t *write_buffer, 389 size_t write_len, uint8_t *read_buffer, 390 size_t read_len, uint8_t sendvalue) { 391 if (_spi) { 392 _spi->beginTransaction(*_spiSetting); 393 } 394 395 digitalWrite(_cs, LOW); 396 // do the writing 397 for (size_t i = 0; i < write_len; i++) { 398 transfer(write_buffer[i]); 399 } 400 401 #ifdef DEBUG_SERIAL 402 DEBUG_SERIAL.print(F("\tSPIDevice Wrote: ")); 403 for (uint16_t i = 0; i < write_len; i++) { 404 DEBUG_SERIAL.print(F("0x")); 405 DEBUG_SERIAL.print(write_buffer[i], HEX); 406 DEBUG_SERIAL.print(F(", ")); 407 if (write_len % 32 == 31) { 408 DEBUG_SERIAL.println(); 409 } 410 } 411 DEBUG_SERIAL.println(); 412 #endif 413 414 // do the reading 415 for (size_t i = 0; i < read_len; i++) { 416 read_buffer[i] = transfer(sendvalue); 417 } 418 419 #ifdef DEBUG_SERIAL 420 DEBUG_SERIAL.print(F("\tSPIDevice Read: ")); 421 for (uint16_t i = 0; i < read_len; i++) { 422 DEBUG_SERIAL.print(F("0x")); 423 DEBUG_SERIAL.print(read_buffer[i], HEX); 424 DEBUG_SERIAL.print(F(", ")); 425 if (read_len % 32 == 31) { 426 DEBUG_SERIAL.println(); 427 } 428 } 429 DEBUG_SERIAL.println(); 430 #endif 431 432 digitalWrite(_cs, HIGH); 433 434 if (_spi) { 435 _spi->endTransaction(); 436 } 437 438 return true; 439 }