diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..eba1110 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..737bcf8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# VSCode directories +.vscode + diff --git a/docs/ar_ibus.md b/docs/ar_ibus.md index 91a3933..85b972d 100644 --- a/docs/ar_ibus.md +++ b/docs/ar_ibus.md @@ -202,6 +202,9 @@ The following is an example of an I2C class in Arduino based on the previous pla > [!NOTE] > This class implements a ```isConnected()``` method that calls the ```ping()``` method of the I2C bus class being used, and if this passes, then calls the ```checkDeviceID()``` method of the superclass. +> [!NOTE] +> If your device supports repeated starts, make sure to include ```_theI2CBus.setStop(false)``` in your begin function. Otherwise this can cause issues with your device. + ```c++ class myArduinoDriverI2C : public myDriverClass @@ -214,6 +217,10 @@ class myArduinoDriverI2C : public myDriverClass { if (_theI2CBus.init(MY_DEVICE_ADDRESS) != kSTkErrOk) return false; + + // OPTIONAL: If your device supports repeat starts. + _theI2CBus.setStop(false); + setCommunicationBus(&_theI2CBus); return myDriverClass::begin(); diff --git a/library.properties b/library.properties index 45a0a30..9ffc27b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun Toolkit -version=0.8.0 +version=0.9.0 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A utility library that other SparkFun libraries can take advantage of. @@ -7,3 +7,4 @@ paragraph=The SparkFun Toolkit provides a common set of core functionality for u category=Other url=https://github.com/sparkfun/SparkFun_Toolkit architectures=* +includes=SparkFun_Toolkit.h diff --git a/src/sfeTk/sfeTkIBus.h b/src/sfeTk/sfeTkIBus.h index 5499f37..858f023 100644 --- a/src/sfeTk/sfeTkIBus.h +++ b/src/sfeTk/sfeTkIBus.h @@ -117,11 +117,13 @@ class sfeTkIBus @param devAddr The device's I2C address. @param devReg The device's register's address. @param data Data to write. + @param numBytes - length of data + @param[out] readBytes - number of bytes read @retval int returns kSTkErrOk on success, or kSTkErrFail code */ - virtual sfeTkError_t readRegisterRegion(uint8_t reg, uint8_t *data, size_t numBytes) = 0; + virtual sfeTkError_t readRegisterRegion(uint8_t reg, uint8_t *data, size_t numBytes, size_t &readBytes) = 0; }; //}; diff --git a/src/sfeTk/sfeTkII2C.h b/src/sfeTk/sfeTkII2C.h index e35d7d0..676866c 100644 --- a/src/sfeTk/sfeTkII2C.h +++ b/src/sfeTk/sfeTkII2C.h @@ -31,8 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class sfeTkII2C : public sfeTkIBus { public: - // set the address to No address and stop bit to the default value of 1 - sfeTkII2C() : _address{kNoAddress}, _stop{kDefaultStopBit} + // set the address to No address and stop flag to true + sfeTkII2C() : _address{kNoAddress}, _stop{true} { } sfeTkII2C(uint8_t addr) : _address{addr} @@ -70,31 +70,30 @@ class sfeTkII2C : public sfeTkIBus } /*-------------------------------------------------------------------------- - @brief setter for I2C stops (vs restarts) + @brief setter for I2C stop message (vs restarts) */ - virtual void setStop(uint8_t stop) + virtual void setStop(bool stop) { _stop = stop; } /*-------------------------------------------------------------------------- - @brief getter for I2C stops (vs restarts) + @brief getter for I2C stops message (vs restarts) - @retval uint8_t returns the value of "send stop" + @retval bool returns the value of "send stop" */ - virtual uint8_t getStop(void) + virtual bool stop(void) { return _stop; } static constexpr uint8_t kNoAddress = 0; - static constexpr uint8_t kDefaultStopBit = 1; private: uint8_t _address; - uint8_t _stop; + bool _stop; }; //}; diff --git a/src/sfeTkArdI2C.cpp b/src/sfeTkArdI2C.cpp index dc553e1..0f994be 100644 --- a/src/sfeTkArdI2C.cpp +++ b/src/sfeTkArdI2C.cpp @@ -174,7 +174,7 @@ sfeTkError_t sfeTkArdI2C::readRegisterByte(uint8_t devReg, uint8_t &dataToRead) _i2cPort->beginTransmission(address()); _i2cPort->write(devReg); - _i2cPort->endTransmission((int)getStop()); + _i2cPort->endTransmission(stop()); _i2cPort->requestFrom(address(), (uint8_t)1); while (_i2cPort->available()) // slave may send less than requested @@ -183,10 +183,10 @@ sfeTkError_t sfeTkArdI2C::readRegisterByte(uint8_t devReg, uint8_t &dataToRead) nData++; } - if (nData == 1) // Only update outputPointer if a single byte was returned + if (nData == sizeof(uint8_t)) // Only update outputPointer if a single byte was returned dataToRead = result; - return (nData == 1 ? kSTkErrOk : kSTkErrFail); + return (nData == sizeof(uint8_t) ? kSTkErrOk : kSTkErrFail); } //--------------------------------------------------------------------------------- // readRegisterWord() @@ -200,9 +200,10 @@ sfeTkError_t sfeTkArdI2C::readRegisterWord(uint8_t devReg, uint16_t &dataToRead) if (!_i2cPort) return kSTkErrBusNotInit; - uint32_t nRead = readRegisterRegion(devReg, (uint8_t *)&dataToRead, sizeof(uint16_t)); + size_t nRead; + sfeTkError_t retval = readRegisterRegion(devReg, (uint8_t *)&dataToRead, sizeof(uint16_t), nRead); - return (nRead == 2 ? kSTkErrOk : kSTkErrFail); + return (retval == kSTkErrOk && nRead == sizeof(uint16_t) ? kSTkErrOk : retval); } //--------------------------------------------------------------------------------- @@ -212,12 +213,19 @@ sfeTkError_t sfeTkArdI2C::readRegisterWord(uint8_t devReg, uint16_t &dataToRead) // // Returns the number of bytes read, < 0 is an error // -int32_t sfeTkArdI2C::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes) +sfeTkError_t sfeTkArdI2C::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes, size_t &readBytes) { + // got port if (!_i2cPort) return kSTkErrBusNotInit; + // Buffer valid? + if (!data) + return kSTkErrBusNullBuffer; + + readBytes = 0; + uint16_t nOrig = numBytes; // original number of bytes. uint8_t nChunk; uint16_t nReturned; @@ -232,7 +240,7 @@ int32_t sfeTkArdI2C::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t nu _i2cPort->write(devReg); - if (_i2cPort->endTransmission(getStop()) != 0) + if (_i2cPort->endTransmission(stop()) != 0) return kSTkErrFail; // error with the end transmission bFirstInter = false; @@ -242,11 +250,11 @@ int32_t sfeTkArdI2C::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t nu nChunk = numBytes > _bufferChunkSize ? _bufferChunkSize : numBytes; // Request the bytes. If this is the last chunk, always send a stop - nReturned = _i2cPort->requestFrom((int)address(), (int)nChunk, (int)(nChunk == numBytes ? true : getStop())); + nReturned = _i2cPort->requestFrom((int)address(), (int)nChunk, (int)(nChunk == numBytes ? true : stop())); // No data returned, no dice if (nReturned == 0) - return -1; // error + return kSTkErrBusUnderRead; // error // Copy the retrieved data chunk to the current index in the data segment for (i = 0; i < nReturned; i++) @@ -257,5 +265,7 @@ int32_t sfeTkArdI2C::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t nu } // end while - return nOrig - numBytes; // Success + readBytes = nOrig - numBytes; // Bytes read. + + return (readBytes == nOrig) ? kSTkErrOk : kSTkErrBusUnderRead; // Success } diff --git a/src/sfeTkArdI2C.h b/src/sfeTkArdI2C.h index 34f3327..69e488d 100644 --- a/src/sfeTkArdI2C.h +++ b/src/sfeTkArdI2C.h @@ -168,11 +168,14 @@ class sfeTkArdI2C : public sfeTkII2C @note This method is virtual to allow it to be overridden to support a device that requires a unique impl @param devReg The device's register's address. - @param data Data to write. + @param data Data being read. + @param numBytes Number of bytes to read. + @param[out] readBytes - Number of bytes read - @retval kStkErrOk on success + + @retval kSTkErrOk on success */ - sfeTkError_t readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes); + sfeTkError_t readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes, size_t &readBytes); // Buffer size chunk getter/setter /*-------------------------------------------------------------------------- diff --git a/src/sfeTkArdSPI.cpp b/src/sfeTkArdSPI.cpp index c933ed3..62f91c8 100644 --- a/src/sfeTkArdSPI.cpp +++ b/src/sfeTkArdSPI.cpp @@ -178,12 +178,18 @@ sfeTkError_t sfeTkArdSPI::writeRegisterRegion(uint8_t devReg, const uint8_t *dat sfeTkError_t sfeTkArdSPI::readRegisterByte(uint8_t devReg, uint8_t &data) { - return readRegisterRegion(devReg, &data, sizeof(data)) == 1; + size_t nRead; + sfeTkError_t retval = readRegisterRegion(devReg, (uint8_t *)&data, sizeof(uint8_t), nRead); + + return (retval == kSTkErrOk && nRead == sizeof(uint8_t) ? kSTkErrOk : retval); } sfeTkError_t sfeTkArdSPI::readRegisterWord(uint8_t devReg, uint16_t &data) { - return readRegisterRegion(devReg, (uint8_t *)&data, sizeof(data)) == 2; + size_t nRead; + sfeTkError_t retval = readRegisterRegion(devReg, (uint8_t *)&data, sizeof(uint16_t), nRead); + + return (retval == kSTkErrOk && nRead == sizeof(uint16_t) ? kSTkErrOk : retval); } //--------------------------------------------------------------------------------- // readRegisterRegion() @@ -192,7 +198,7 @@ sfeTkError_t sfeTkArdSPI::readRegisterWord(uint8_t devReg, uint16_t &data) // // Returns kSTkErrOk on success // -sfeTkError_t sfeTkArdSPI::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes) +sfeTkError_t sfeTkArdSPI::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes, size_t &readBytes) { if (!_spiPort) return kSTkErrBusNotInit; @@ -213,5 +219,7 @@ sfeTkError_t sfeTkArdSPI::readRegisterRegion(uint8_t devReg, uint8_t *data, size digitalWrite(cs(), HIGH); _spiPort->endTransaction(); + readBytes = numBytes; + return kSTkErrOk; } diff --git a/src/sfeTkArdSPI.h b/src/sfeTkArdSPI.h index d8ff00b..f386cc2 100644 --- a/src/sfeTkArdSPI.h +++ b/src/sfeTkArdSPI.h @@ -148,10 +148,12 @@ class sfeTkArdSPI : public sfeTkISPI @param devReg The device's register's address. @param data Data to write. + @param numBytes - length of data + @param[out] readBytes - Number of bytes read @retval sfeTkError_t - true on success */ - virtual sfeTkError_t readRegisterRegion(uint8_t reg, uint8_t *data, size_t numBytes); + virtual sfeTkError_t readRegisterRegion(uint8_t reg, uint8_t *data, size_t numBytes, size_t &readBytes); protected: // note: The instance data is protected, allowing access if a sub-class is