arduinoprojects

git clone https://git.tarina.org/arduinoprojects
Log | Files | Refs

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 }