diff --git a/README.md b/README.md index 23c2cdc..215c435 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,29 @@ # SparkFun Toolkit Arduino Library ![Toolkit Tests Builds](https://github.com/sparkfun/SparkFun_Toolkit/actions/workflows/compile-sketch.yml/badge.svg) +![GitHub issues](https://img.shields.io/github/issues/sparkfun/SparkFun_Toolkit) +![GitHub release (with filter)](https://img.shields.io/github/v/release/sparkfun/SparkFun_Toolkit) +![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/sparkfun/SparkFun_Toolkit) + + + +The SparkFun Toolkit provides a common set of core functionality for use across the SparkFun Arduino Driver library. Instead of each device driver library implementing it's own communication layers, error types and design, the SparkFun Toolkit library is used. + +By using the SparkFun Toolkit, Arduino drivers achieve the following benefits: + +* Use a well-tested and validated implementation +* Reduce development effort +* Implement functionality following a common structure +* Set the foundation for future enhancements - as the capabilities of the toolkit grow, these features become available with little to any implementation effort. + +## Current Status + +### December 2023 + +The SparkFun Toolkit is available as a *Beta* release, with the intent of testing and validation by SparkFun. The community are free to use this toolkit with the understanding that interfaces, types and class structures could change. + +### Documentation + +||| +|---|---| +|[Bus Implementation](docs/ar_ibus.md) | The architecture and use of the Tookkit Communication Bus Interface diff --git a/docs/ar_ibus.md b/docs/ar_ibus.md index 6bb0bad..91a3933 100644 --- a/docs/ar_ibus.md +++ b/docs/ar_ibus.md @@ -1,10 +1,26 @@ -# Overview - Device Bus interface - sfeTkIBus +# Overview - Device Bus Interface - sfeTkIBus One of the foundational capabilities of the SparkFun Toolkit is bus communication with devices. This is a common task almost all libraries implement using their own implementation for I2C, SPI or UART bus communication. For bus communication, the SparkFun Toolkit is designed to provide a common implementation for use across all SparkFun libraries. Additionally, the bus architecture is modeled on a *driver* pattern, separating the individual bus setup/configuration from data communication, enabling a single device implementation to easily support a variety of device bus types. -The key goals set for the Bus implementation in the Toolkit include: +### The Bus Interface Design Pattern + +This pattern allows an application to develop against the common bus interface without regard to the underlying bus type or implementation. This *plug-in* nature of this model enables core application reuse across a range of bus devices. What to use a different bus type? Just use a different driver. + +This pattern is show in the following diagram: + +![Driver Pattern](images/tk_ibus_p1.png) + +This pattern extends across different platforms, allowing a common platform independent application core to utilize platform specific bus drivers. + +![Platform Independence](images/tk_ibus_p2.png) + +The platform dependant drivers implement the core Bus Interface (IBus) for communication, with platform specific setup and management left to the underlying implementation. Since the application core only works with the Bus Interface, if implemented correctly, the same core works across different bus types and across different development environments. + +## Goals + +For the initial implementation the key goals set for the Bus implementation in the Toolkit include: * Separate device setup from device communication * Define a common bus interface for use across a variety of common device bus types @@ -13,7 +29,7 @@ The key goals set for the Bus implementation in the Toolkit include: ## Architecture Overview -To meet the goals for this subsystem, the Flux framework follows a ***Driver Pattern***, defining a common interface for bus communication. Device drivers are designed around this interface, leaving bus configuration and implementation to platform specific implementation. +As outlined above, the SparkFun Toolkit follows a ***Driver Pattern***, defining a common interface for bus communication. Device drivers are designed around this interface, leaving bus configuration and implementation to platform specific implementation. The key class to support this pattern are: @@ -41,9 +57,13 @@ The interface methods: > [!NOTE] > This interface only defines the methods to read and write data on the given bus. Any address, or bus specific settings is provided/implemented by the implementation/specialization of this interface. +The Inteface diagram for the ```sfeTkIBus``` is: + +![IIBus Interface](images/tk_uml_ibus.png) + ### The sfeTkII2C Implementation -This class sub-classes from the ```sfeTkIBus``` interface adding additional functionally focused on supporting an I2C implementation. This interface provides the additional functionality. +This class sub-classes from the ```sfeTkIBus``` interface adding additional functionally focused on supporting an I2C implementation. This class does not implement the IIBus interface, so it's abstract, but the class adds the additional functionality. | Method| Definition | |------|-------| @@ -54,6 +74,10 @@ This class sub-classes from the ```sfeTkIBus``` interface adding additional func > [!NOTE] > The ```sfeTkII2C``` class manages the device address for the I2C bus. As such, each I2C device instantiates/uses an instance of the ```sfeTkII2C``` class. +The class diagram for the ```sfeTkII2C``` interface is the following: + +![II2C Class Diagram](images/tk_uml_ii2c.png) + ### The sfeTkISPI Implementation This class sub-classes from the ```sfeTkIBus``` interface adding additional functionally focused on supporting an SPI implementation. This interface provides the additional functionality. @@ -68,31 +92,35 @@ This class sub-classes from the ```sfeTkIBus``` interface adding additional func The class diagram of these base class interfaces/implementation: -![IBus diagram](images/tk_IBUS.png) +![ISPI Class Diagram](images/tk_uml_ispi.png) -## sfeTkIIBus - Arduino Implementation +## sfeTkIBus - Arduino Implementation The initial implementation of the toolkit IBus interface is for the Arduino environment. This implementation consists of two classes, ```sfeTkArdI2C``` and ```sfeTkArdSPI```, each of which sub-class from their respective bus type interfaces within the core toolkit. These driver implementations provide the platform specific implementation for the toolkit bus interfaces, supporting the methods defined by the interfaces, as well as contain and manage the platform specific settings and attributes for each bus type. > [!IMPORTANT] -> The intent is that each user of an particular bus - a device in most cases - contains an instance of the specific bus object. +> The intent is that each user of an particular - a device in most cases - contains an instance of the specific bus class. -The class diagram for the Arduino implementation is as follows: +### The sfeTkArdI2C Class -![Arduino IBus Implementation](images/tk_ibus_ard.png) +This class provides the Arduino implementation of I2C in the SparkFun Toolkit. It implements the methods of the ```sfeTkIBus``` and ```sfeTkII2C``` interfaces, as well as manages any Arduino specific state. -### The sfeTkArdI2C Class +The class diagram for the sfeTkArdI2C class: -This class provides the Arduino implementation of I2C in the SparkFun Toolkit. It implements the methods of the ```sfeTkIIBus``` and ```sfeTkII2C``` interfaces, as well as manages any Arduino specific state. +![Arduino I2C Class Diagram](images/tk_uml_ardi2c.png) ### The sfeTkArdSPI Class -This class provides the Arduino implementation of SPI in the SparkFun Toolkit. It implements the methods of the ```sfeTkIIBus``` and ```sfeTkISPI``` interfaces, as well as manages any Arduino specific state for the SPI bus - namely the SPISettings class. +This class provides the Arduino implementation of SPI in the SparkFun Toolkit. It implements the methods of the ```sfeTkIBus``` and ```sfeTkISPI``` interfaces, as well as manages any Arduino specific state for the SPI bus - namely the SPISettings class. Before each use of the SPI bus, the methods of the ```sfeTkArdSPI``` uses an internal SPISettings class to ensure the SPI bus is operating in the desired mode for the device. +The class diagram for the sfeTkArdSPI class: + +![Arduino SPI Class Diagram](images/tk_uml_ardspi.png) + ## sfeTkIBus Use The general steps when using the sfeTkIBus in device development are outlined in the following steps. This example uses the Arduino implementation of the bus. @@ -101,7 +129,7 @@ The general pattern for a device driver implementation that uses the SparkFun To ### Implement a Platform Independent Driver -The first step is to implement a core, platform independent version of the driver that communicates to the target device using the methods of a ```sfeTkIIBus``` interface. +The first step is to implement a core, platform independent version of the driver that communicates to the target device using the methods of a ```sfeTkIBus``` interface. By limiting use to the IBus interface, the core implementation can use any bus type or platform that implements the sfeTkIBus interface. >[!IMPORTANT] > At this level, the driver is only using a ```sfeTkIBus``` interface, not any specific bus implementation. @@ -111,7 +139,10 @@ This driver has the following unique functionality: 1) A method to set the object that implements the ```sfeTkIBus``` interface object should use. Since 1) If the device supports identification capabilities, the driver provides this functionality. -#### SImple Example of an Independent Driver Implementation +#### Simple Example of an Independent Driver Implementation + +>[!NOTE] +> This code is **pseudo-code**, used to demonstrate the key concepts of the implementation pattern. This implementation would take the following form: @@ -121,7 +152,7 @@ class myDriverClass { public: - myDriverClass(uint8_t address) : _addr{address}{} + myDriverClass(uint8_t address) : _addr{address}, _theBus{nullptr}{} bool begin() { @@ -139,9 +170,9 @@ public: if (!_theBus || !data || len == 0) return false; - int status = _theBus->writeRegisterRegion(THE_REG, data, len); + sfeTkError_t status = _theBus->writeRegisterRegion(THE_REG, data, len); - return (status == 0); + return (status == kSTkErrOk); } bool checkDeviceID() @@ -150,6 +181,7 @@ public: return true; } private: + uint8_t _addr; sfeTkIBus *_theBus; }; ``` @@ -180,7 +212,7 @@ class myArduinoDriverI2C : public myDriverClass bool begin() { - if (!_theI2CBus.init(MY_DEVICE_ADDRESS)) + if (_theI2CBus.init(MY_DEVICE_ADDRESS) != kSTkErrOk) return false; setCommunicationBus(&_theI2CBus); @@ -189,7 +221,7 @@ class myArduinoDriverI2C : public myDriverClass bool isConnected() { - if (!_theI2CBus.ping()) + if (_theI2CBus.ping() != kSTkErrOk) return false; return checkDeviceID(); @@ -219,7 +251,7 @@ class myArduinoDriveSPI : public myDriverClass { SPISettings spiSettings = SPISettings(4000000, MSBFIRST, SPI_MODE3); - if (!_theSPIBus.init(SPI, spiSettings, MY_DEFAULT_CS, true)) + if (_theSPIBus.init(SPI, spiSettings, MY_DEFAULT_CS, true) != kSTkErrOk) return false; setCommunicationBus(&_theSPIBus); @@ -235,3 +267,12 @@ private: sfeTkArdSPI _theSPIBus; }; ``` + +## Summary + +In summary, the SparkFun Toolkit Bus Interface sets a standard that device drivers can implement against without concern for platform or bus type. Using common interface implementation patterns, the implementation delivers on the goals for this subsystem - namely: + +* Separate device setup from device communication +* Define a common bus interface for use across a variety of common device bus types +* Deliver support for both SPI and I2C bus types initially, focusing on Arduino +* Structure the bus/toolkit implementation such that it's platform independent diff --git a/docs/images/tk_IBUS.png b/docs/images/tk_IBUS.png deleted file mode 100644 index 6cf0355..0000000 Binary files a/docs/images/tk_IBUS.png and /dev/null differ diff --git a/docs/images/tk_ibus_ard.png b/docs/images/tk_ibus_ard.png deleted file mode 100644 index 320518c..0000000 Binary files a/docs/images/tk_ibus_ard.png and /dev/null differ diff --git a/docs/images/tk_ibus_p1.png b/docs/images/tk_ibus_p1.png new file mode 100644 index 0000000..3503e47 Binary files /dev/null and b/docs/images/tk_ibus_p1.png differ diff --git a/docs/images/tk_ibus_p2.png b/docs/images/tk_ibus_p2.png new file mode 100644 index 0000000..c3beee7 Binary files /dev/null and b/docs/images/tk_ibus_p2.png differ diff --git a/docs/images/tk_uml_ardi2c.png b/docs/images/tk_uml_ardi2c.png new file mode 100644 index 0000000..7b3b20d Binary files /dev/null and b/docs/images/tk_uml_ardi2c.png differ diff --git a/docs/images/tk_uml_ardspi.png b/docs/images/tk_uml_ardspi.png new file mode 100644 index 0000000..1ced665 Binary files /dev/null and b/docs/images/tk_uml_ardspi.png differ diff --git a/docs/images/tk_uml_ibus.png b/docs/images/tk_uml_ibus.png new file mode 100644 index 0000000..8a7dfbd Binary files /dev/null and b/docs/images/tk_uml_ibus.png differ diff --git a/docs/images/tk_uml_ii2c.png b/docs/images/tk_uml_ii2c.png new file mode 100644 index 0000000..a8b6bae Binary files /dev/null and b/docs/images/tk_uml_ii2c.png differ diff --git a/docs/images/tk_uml_ispi.png b/docs/images/tk_uml_ispi.png new file mode 100644 index 0000000..c5e97a8 Binary files /dev/null and b/docs/images/tk_uml_ispi.png differ diff --git a/library.properties b/library.properties index 6f971ef..45a0a30 100644 --- a/library.properties +++ b/library.properties @@ -3,7 +3,7 @@ version=0.8.0 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A utility library that other SparkFun libraries can take advantage of. -paragraph= +paragraph=The SparkFun Toolkit provides a common set of core functionality for use across the SparkFun Arduino Driver library. Instead of each device driver library implementing a communication layers, error types and interface, the SparkFun Toolkit library is used. category=Other url=https://github.com/sparkfun/SparkFun_Toolkit architectures=* diff --git a/src/sfeTk/sfeTkIBus.h b/src/sfeTk/sfeTkIBus.h index 32d9ad1..5499f37 100644 --- a/src/sfeTk/sfeTkIBus.h +++ b/src/sfeTk/sfeTkIBus.h @@ -29,13 +29,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sfeTkError.h" - -// Define our error codes for the bus. Note Errors are negative, warnings/info postive +// Define our error codes for the bus. Note Errors are negative, warnings/info positive // BUT keep the same increment on the base -const sfeTkError_t kSTkErrBusNullPtr = kSTkErrFail * (kSTkErrBaseBus + 1); +const sfeTkError_t kSTkErrBusNotInit = kSTkErrFail * (kSTkErrBaseBus + 1); const sfeTkError_t kSTkErrBusTimeout = kSTkErrFail * (kSTkErrBaseBus + 2); -const sfeTkError_t kSTkErrBusNoReponse = kSTkErrFail * (kSTkErrBaseBus + 3); +const sfeTkError_t kSTkErrBusNoResponse = kSTkErrFail * (kSTkErrBaseBus + 3); const sfeTkError_t kSTkErrBusDataTooLong = kSTkErrFail * (kSTkErrBaseBus + 4); const sfeTkError_t kSTkErrBusNullSettings = kSTkErrFail * (kSTkErrBaseBus + 5); const sfeTkError_t kSTkErrBusNullBuffer = kSTkErrFail * (kSTkErrBaseBus + 6); @@ -47,6 +46,16 @@ const sfeTkError_t kSTkErrBusNotEnabled = kSTkErrBaseBus + 8; class sfeTkIBus { public: + /*-------------------------------------------------------------------------- + @brief Write a single byte to the device + + @param data Data to write. + + @retval sfeTkError_t - kSTkErrOk on successful execution. + + */ + virtual sfeTkError_t writeByte(uint8_t data) = 0; + /*-------------------------------------------------------------------------- @brief Write a single byte to the given register diff --git a/src/sfeTk/sfeTkII2C.h b/src/sfeTk/sfeTkII2C.h index 8ff4d14..e35d7d0 100644 --- a/src/sfeTk/sfeTkII2C.h +++ b/src/sfeTk/sfeTkII2C.h @@ -31,7 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class sfeTkII2C : public sfeTkIBus { public: - sfeTkII2C() : _address{kNoAddress} + // set the address to No address and stop bit to the default value of 1 + sfeTkII2C() : _address{kNoAddress}, _stop{kDefaultStopBit} { } sfeTkII2C(uint8_t addr) : _address{addr} @@ -68,10 +69,32 @@ class sfeTkII2C : public sfeTkIBus return _address; } + /*-------------------------------------------------------------------------- + @brief setter for I2C stops (vs restarts) + + */ + virtual void setStop(uint8_t stop) + { + _stop = stop; + } + + /*-------------------------------------------------------------------------- + @brief getter for I2C stops (vs restarts) + + @retval uint8_t returns the value of "send stop" + + */ + virtual uint8_t getStop(void) + { + return _stop; + } + static constexpr uint8_t kNoAddress = 0; + static constexpr uint8_t kDefaultStopBit = 1; private: uint8_t _address; + uint8_t _stop; }; //}; diff --git a/src/sfeTkArdI2C.cpp b/src/sfeTkArdI2C.cpp index 1a31702..dc553e1 100644 --- a/src/sfeTkArdI2C.cpp +++ b/src/sfeTkArdI2C.cpp @@ -23,8 +23,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sfeTkArdI2C.h" - - //--------------------------------------------------------------------------------- // init() // @@ -80,9 +78,27 @@ sfeTkError_t sfeTkArdI2C::ping() { // no port, no if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; + + _i2cPort->beginTransmission(address()); + return _i2cPort->endTransmission() == 0 ? kSTkErrOk : kSTkErrFail; +} + +//--------------------------------------------------------------------------------- +// writeByte() +// +// Writes a single byte to the device. +// +// Returns true on success, false on failure +// +sfeTkError_t sfeTkArdI2C::writeByte(uint8_t dataToWrite) +{ + if (!_i2cPort) + return kSTkErrBusNotInit; + // do the Arduino I2C work _i2cPort->beginTransmission(address()); + _i2cPort->write(dataToWrite); return _i2cPort->endTransmission() == 0 ? kSTkErrOk : kSTkErrFail; } @@ -96,7 +112,7 @@ sfeTkError_t sfeTkArdI2C::ping() sfeTkError_t sfeTkArdI2C::writeRegisterByte(uint8_t devReg, uint8_t dataToWrite) { if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; // do the Arduino I2C work _i2cPort->beginTransmission(address()); @@ -104,6 +120,7 @@ sfeTkError_t sfeTkArdI2C::writeRegisterByte(uint8_t devReg, uint8_t dataToWrite) _i2cPort->write(dataToWrite); return _i2cPort->endTransmission() == 0 ? kSTkErrOk : kSTkErrFail; } + //--------------------------------------------------------------------------------- // writeRegisterWord() // @@ -114,7 +131,7 @@ sfeTkError_t sfeTkArdI2C::writeRegisterByte(uint8_t devReg, uint8_t dataToWrite) sfeTkError_t sfeTkArdI2C::writeRegisterWord(uint8_t devReg, uint16_t dataToWrite) { if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; return writeRegisterRegion(devReg, (uint8_t *)&dataToWrite, sizeof(uint16_t)); } @@ -129,13 +146,13 @@ sfeTkError_t sfeTkArdI2C::writeRegisterWord(uint8_t devReg, uint16_t dataToWrite sfeTkError_t sfeTkArdI2C::writeRegisterRegion(uint8_t devReg, const uint8_t *data, size_t length) { if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; _i2cPort->beginTransmission(address()); _i2cPort->write(devReg); _i2cPort->write(data, (int)length); - return _i2cPort->endTransmission() ? kSTkErrFail : kSTkErrOk; + return _i2cPort->endTransmission() ? kSTkErrFail : kSTkErrOk; } //--------------------------------------------------------------------------------- @@ -148,7 +165,7 @@ sfeTkError_t sfeTkArdI2C::writeRegisterRegion(uint8_t devReg, const uint8_t *dat sfeTkError_t sfeTkArdI2C::readRegisterByte(uint8_t devReg, uint8_t &dataToRead) { if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; // Return value uint8_t result = 0; @@ -157,7 +174,7 @@ sfeTkError_t sfeTkArdI2C::readRegisterByte(uint8_t devReg, uint8_t &dataToRead) _i2cPort->beginTransmission(address()); _i2cPort->write(devReg); - _i2cPort->endTransmission(); + _i2cPort->endTransmission((int)getStop()); _i2cPort->requestFrom(address(), (uint8_t)1); while (_i2cPort->available()) // slave may send less than requested @@ -181,7 +198,7 @@ sfeTkError_t sfeTkArdI2C::readRegisterByte(uint8_t devReg, uint8_t &dataToRead) sfeTkError_t sfeTkArdI2C::readRegisterWord(uint8_t devReg, uint16_t &dataToRead) { if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; uint32_t nRead = readRegisterRegion(devReg, (uint8_t *)&dataToRead, sizeof(uint16_t)); @@ -199,31 +216,33 @@ int32_t sfeTkArdI2C::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t nu { // got port if (!_i2cPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; uint16_t nOrig = numBytes; // original number of bytes. uint8_t nChunk; uint16_t nReturned; - uint16_t i; // counter in loop + uint16_t i; // counter in loop bool bFirstInter = true; // Flag for first iteration - used to send devRegister while (numBytes > 0) { - _i2cPort->beginTransmission(address()); - if (bFirstInter) { + _i2cPort->beginTransmission(address()); + _i2cPort->write(devReg); + + if (_i2cPort->endTransmission(getStop()) != 0) + return kSTkErrFail; // error with the end transmission + bFirstInter = false; } - if (_i2cPort->endTransmission() != 0) - return kSTkErrFail; // error with the end transmission - // We're chunking in data - keeping the max chunk to kMaxI2CBufferLength nChunk = numBytes > _bufferChunkSize ? _bufferChunkSize : numBytes; - nReturned = _i2cPort->requestFrom((int)address(), (int)nChunk, (int)true); + // 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())); // No data returned, no dice if (nReturned == 0) diff --git a/src/sfeTkArdI2C.h b/src/sfeTkArdI2C.h index 2a9e0e0..34f3327 100644 --- a/src/sfeTkArdI2C.h +++ b/src/sfeTkArdI2C.h @@ -92,6 +92,16 @@ class sfeTkArdI2C : public sfeTkII2C */ sfeTkError_t ping(); + /*-------------------------------------------------------------------------- + @brief Write a single byte to the device + @note sfeTkIBus interface method + + @param data Data to write. + + @retval returns kStkErrOk on success + */ + sfeTkError_t writeByte(uint8_t data); + /*-------------------------------------------------------------------------- @brief Write a single byte to the given register @note sfeTkIBus interface method diff --git a/src/sfeTkArdSPI.cpp b/src/sfeTkArdSPI.cpp index 89783dd..c933ed3 100644 --- a/src/sfeTkArdSPI.cpp +++ b/src/sfeTkArdSPI.cpp @@ -81,6 +81,33 @@ sfeTkError_t sfeTkArdSPI::init(bool bInit) return init(cs(), bInit); } +//--------------------------------------------------------------------------------- +// writeRegisterByte() +// +// Writes a single byte to the device. +// +// Returns kSTkErrOk on success +// +sfeTkError_t sfeTkArdSPI::writeByte(uint8_t dataToWrite) +{ + + if (!_spiPort) + return kSTkErrBusNotInit; + + // Apply settings + _spiPort->beginTransaction(_sfeSPISettings); + // Signal communication start + digitalWrite(cs(), LOW); + + _spiPort->transfer(dataToWrite); + + // End communication + digitalWrite(cs(), HIGH); + _spiPort->endTransaction(); + + return kSTkErrOk; +} + //--------------------------------------------------------------------------------- // writeRegisterByte() // @@ -92,7 +119,7 @@ sfeTkError_t sfeTkArdSPI::writeRegisterByte(uint8_t devReg, uint8_t dataToWrite) { if (!_spiPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; // Apply settings _spiPort->beginTransaction(_sfeSPISettings); @@ -108,6 +135,7 @@ sfeTkError_t sfeTkArdSPI::writeRegisterByte(uint8_t devReg, uint8_t dataToWrite) return kSTkErrOk; } + //--------------------------------------------------------------------------------- // writeRegisterWord() // @@ -129,7 +157,7 @@ sfeTkError_t sfeTkArdSPI::writeRegisterWord(uint8_t devReg, uint16_t dataToWrite sfeTkError_t sfeTkArdSPI::writeRegisterRegion(uint8_t devReg, const uint8_t *data, size_t length) { if (!_spiPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; // Apply settings before work _spiPort->beginTransaction(_sfeSPISettings); @@ -167,7 +195,7 @@ sfeTkError_t sfeTkArdSPI::readRegisterWord(uint8_t devReg, uint16_t &data) sfeTkError_t sfeTkArdSPI::readRegisterRegion(uint8_t devReg, uint8_t *data, size_t numBytes) { if (!_spiPort) - return kSTkErrBusNullPtr; + return kSTkErrBusNotInit; // Apply settings _spiPort->beginTransaction(_sfeSPISettings); diff --git a/src/sfeTkArdSPI.h b/src/sfeTkArdSPI.h index 447a5a7..d8ff00b 100644 --- a/src/sfeTkArdSPI.h +++ b/src/sfeTkArdSPI.h @@ -39,8 +39,13 @@ class sfeTkArdSPI : public sfeTkISPI /* @brief Constructor */ - sfeTkArdSPI(void) : _spiPort(nullptr){}; + sfeTkArdSPI(void) : _spiPort(nullptr) + { + } + sfeTkArdSPI(uint8_t csPin) : sfeTkISPI(csPin) + { + } // copy constructor sfeTkArdSPI(sfeTkArdSPI const &rhs) : sfeTkISPI(), _spiPort{rhs._spiPort}, _sfeSPISettings{rhs._sfeSPISettings} { @@ -77,6 +82,15 @@ class sfeTkArdSPI : public sfeTkISPI */ sfeTkError_t init(SPIClass &spiPort, SPISettings &busSPISettings, uint8_t csPin, bool bInit = false); + /*-------------------------------------------------------------------------- + @brief Write a single byte to the device + + @param data Data to write. + + @retval sfeTkError_t - kSTkErrOk on success + */ + sfeTkError_t writeByte(uint8_t data); + /*-------------------------------------------------------------------------- @brief Write a single byte to the given register