Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
45f4c65
Merge pull request #33 from sparkfun/main
gigapod Apr 30, 2024
ec4aaad
added methods to send 16bit works on the bus - using BIG endian byte …
gigapod Nov 4, 2024
e5fa8c1
add logic to detect system byte order at runtime; used this logic on …
gigapod Nov 7, 2024
a7e74d6
tweak var name
gigapod Nov 7, 2024
a81aefa
removing leading bit on transfer
lewispg228 Nov 7, 2024
c1e9004
bus type method
gigapod Nov 7, 2024
ec20fa5
moved the byte order function to an implementation file - the constex…
gigapod Nov 8, 2024
9846401
created a overloaded set of methods for reading and writing to registers
gigapod Nov 8, 2024
3a7adea
cleanup, re-org of byte order logic -move helpers into a namespace, m…
gigapod Nov 9, 2024
f1d7ac6
move to a byte swap method in the toolkit
gigapod Nov 9, 2024
66611b0
the template/constexpr was a cool/dynamic swap version, but not neede…
gigapod Nov 11, 2024
4cf2fb2
fix issue with outout of count - make sure it is words, not bytes
gigapod Nov 11, 2024
6542241
added abstract for millis and delay(); add include of the bus interfa…
gigapod Feb 7, 2025
b6be185
Merge pull request #38 from sparkfun/main
gigapod Feb 10, 2025
749c052
move to c header files and rmeove type_traits include - helps support…
gigapod Feb 10, 2025
e42d0fb
moved/changed how to handle core platform functions - define funcs in…
gigapod Feb 10, 2025
453d46b
moved from using a namespace to simple C functions - cleaner
gigapod Feb 10, 2025
dc0f0ca
change function prefix to *sftk_* - which follows common patterns - 3…
gigapod Feb 11, 2025
6e53aae
add getter for byte order
gigapod Feb 12, 2025
b3c91be
remove include - not needed
gigapod Feb 12, 2025
9d0f0f7
fix issue with not checking endianess
gigapod Feb 12, 2025
89652af
moved the byte order logic to the core bus interface; #include cleanup
gigapod Feb 13, 2025
9aba53f
added banner image
gigapod Feb 13, 2025
8b20d91
fix comment issues, move to using toolkit functions for swaping - not…
gigapod Feb 13, 2025
7f152ff
Merge pull request #39 from sparkfun/feature/16-bit-data-support
gigapod Feb 13, 2025
937889c
naming patter refactor sfeTk to sfTk ...etc; not tested
gigapod Feb 13, 2025
7f6dd7a
fixes for tk name changes - compile tested
gigapod Feb 13, 2025
09c3f2d
update file headers w/ doxygen comments, modern license declaration
gigapod Feb 13, 2025
353fc38
Merge pull request #41 from sparkfun/feature/naming-change
gigapod Feb 14, 2025
97dd5c6
added bswaps for int16 and int32
gigapod Feb 14, 2025
c8754d6
added helpful bit macros
gigapod Feb 15, 2025
e614963
fixo
gigapod Feb 15, 2025
c7e4a55
added overload for u16 addr, u32 data -- makes life much easlier in t…
gigapod Feb 19, 2025
65924a2
pushed all read/write of specific types [byte, word] to the bus inter…
gigapod Feb 19, 2025
922cd8b
updates for v1.0
gigapod Feb 20, 2025
66b60e0
pushed more to the main base class api wise so that a implementation …
gigapod Feb 21, 2025
ad51a30
cleanup - mostly comments
gigapod Feb 23, 2025
6f4ba12
add *using* for the subclass methods that are overloaded and virutal
gigapod Feb 24, 2025
0e3cc7f
testing of mermaid on GH
gigapod Feb 25, 2025
91a285e
update readme for v1
gigapod Feb 26, 2025
ac3d43e
colors...
gigapod Feb 26, 2025
c058c5a
colors...
gigapod Feb 26, 2025
c00b3d4
better title for badges
gigapod Feb 26, 2025
5e335ca
update for v1.0
gigapod Feb 26, 2025
9fe38ef
remove old images
gigapod Feb 26, 2025
b7c90c4
version bump
gigapod Feb 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-deploy-ghpages.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build Documentation and Deploy
name: Documentation

on:
push:
Expand Down
85 changes: 75 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
![SparkFun ToolKit](docs/images/gh-banner-2025-banner-toolkit.png "SparkFun Toolkit")
# SparkFun Toolkit Arduino Library

![Toolkit Tests Builds](https://github.com/sparkfun/SparkFun_Toolkit/actions/workflows/compile-sketch.yml/badge.svg)
Expand All @@ -6,38 +7,102 @@
![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/sparkfun/SparkFun_Toolkit)
![Documentation Build](https://github.com/sparkfun/SparkFun_Toolkit/actions/workflows/build-deploy-ghpages.yml/badge.svg)

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.
The SparkFun Toolkit provides a common set of core functionality for use across the spectrum of SparkFun developed embedded libraries and applications. It provides a well tested, extensively used, and abstract foundational layer of functionality to use across a wide-range of solutions.

This, the first iteration of the SparkFun Toolkit focuses on device communication - namely the communication between a embedded microprocessor and a peripheral devices. Focusing on the *communication bus* aspect of embedded development, the toolkit simplifies system development by providing a proven bus implementation, as well as a set of abstract interfaces that enable rapid development of multi-bus type implementations.

In addition to providing a set of common device bus communication functionality, the SparkFun Toolkit is structure to provide a *platform independent* solution. While the initial implementation targets Arduino development, the architecture is patterned to define a common core of functionality and interfaces that are platform agnostic. Use of the SparkFun Toolkit within a non-Arduino, c++ environment, requires the implementation of small set of platform specific functionality.

## Motivation

Often, the same core functionality is implemented with a majority of our Arduino libraries, each implementation providing the same functionality, but implemented differently. The result is solutions that have different quirks, and impossible to maintain/support effectively. The SparkFun Toolkit solves this issue.
Often, the same core functionality is implemented within a majority of our Arduino libraries, with each implementation providing the same functionality, but implemented differently. The result of this are different solutions that delivery the same functionality, but each have their unique quirks and behavior oddities. As this implementation patter expands, it becomes impossible to maintain/support effectively.

An example of this is software libraries provided in support of the SparkFun qwiic ecosystem. With over 200 sensors, input devices and accessories, the implementation and maintenance of the driver communication layers are difficult burden that the SparkFun Toolkit addresses.

## The SparkFun Toolkit

The SparkFun Toolkit provides a single implementation of common functionality used in the software developed for SparkFun boards. Initially targeted at the Arduino development environment, the SparkFun Toolkit delivers the following benefits:

* Use a well-tested and validated implementation
* Reduce development effort
* Implement functionality following a common structure
* Designed following a platform independent architectural pattern
* Set the foundation for future enhancements - as the capabilities of the toolkit grow, these features become available with little to any implementation effort.

### General Architecture

Implemented using C++, the SparkFun toolkit follows a simple two layered approach in it's design: A core foundational layer, and a platform specific layer.

```mermaid
---
title: General Architecture Structure
---
classDiagram
class CoreToolkit["Core Toolkit Interfaces"]
class PlatformOne["Platform Implementation"]
CoreToolkit <|-- PlatformOne

```
And as additional plaforms are added, they also implement/inherit from the SparkFun Toolkit Core.
```mermaid
---
title: Multi-Platform Structure
---
classDiagram
class CoreToolkit["Core Toolkit Interfaces"]
class PlatformOne["Platform One"]
class PlatformTwo["Platform Two"]

CoreToolkit <|-- PlatformOne
CoreToolkit <|-- PlatformTwo
```

When using the SparkFun Toolkit, the intent is for the implementation to follow the same pattern: A platform independent layer that works with the SparkFun Toolkit core, and a platform specific layer that utilizes the SparkFun Toolkit platform specific implementation.

```mermaid
---
title: Application Structure
---
classDiagram
direction TD
note for ApplicationCore "Application Logic"
class ApplicationCore["Application Core"]
class CoreToolkit["Core Toolkit Interfaces"]

note for CoreToolkit "SparkFun Toolkit"
class ApplicationPlatform["Application Platform"]
style ApplicationPlatform fill:#909090
class PlatformOne["Platform Implementation"]
style PlatformOne fill:#909090

CoreToolkit <|-- PlatformOne
ApplicationCore <--> Application Platform

```

If/when the application is moved to another platform, just the platform specific logic needs implementation.

## Documentation

The SparkFun Toolkit Development documentation is available [here](https://docs.sparkfun.com/SparkFun_Toolkit)
The SparkFun Toolkit Development documentation is available [here](https://docs.sparkfun.com/SparkFun_Toolkit). This includes doxygen generated class/API documentation, as well as additional architectural details.

## Examples

The best way to understand and use the SparkFun Toolkit is to see it being used on other libraries. For our SparkFun developed libraries and firmware that use the SparkFun Toolkit, their associated github repositories are tagged with [sparkfun-toolkit](https://github.com/topics/sparkfun-toolkit) tag.


## Installation and Use

To use the SparkFun Toolkit directly, or in library development kit is installable via the Arduino Library Manager - search for `SparkFun ToolKit` within the Arduino Library Manager to install.

However, for solutions that use the SparkFun Toolkit, it is installed automatically during the Arduino library installation process, by marking the Toolkit as a dependency when publishing your library.

To mark the `SparkFun Toolkit` as a dependency, add the following line to the `library.properties` file for your library.
To mark the `SparkFun Toolkit` as a dependency, add the following line to the `library.properties` file for your library.

```INI
depends=SparkFun Toolkit
depends=SparkFun Toolkit (>=1.0.0)
```

## Examples

The following Arduino Libraries are making use of the SparkFun Toolkit:
> [!NOTE]
> A version indicator is included to ensure your library uses the correct version of the toolkit.

* [SparkFun Qwiic Pulsed Coherent Radar Sensor XM125](https://github.com/sparkfun/SparkFun_Qwiic_XM125_Arduino_Library)
* [SparkFun Qwiic AS7331 Spectral UV Sensor](https://github.com/sparkfun/SparkFun_AS7331_Arduino_Library)
134 changes: 65 additions & 69 deletions docs/ar_ibus.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,35 +35,32 @@ The key class to support this pattern are:

| | |
|------|-------|
|**sfeTkIBus** | A virtual C++ class that device the bus ```sfeTkIBus``` interface |
|**sfeTkII2C** | Sub-class of the ```sfeTkIIBus``` interface, it provides an interface for I2C devices|
|**sfeTkISPI** | Sub-class of the ```sfeTkIIBus``` interface, it provides an interface for SPI devices |
|**sfTkIBus** | A virtual C++ class that device the bus ```sfeTkIBus``` interface |
|**sfTkII2C** | Sub-class of the ```sfeTkIIBus``` interface, it provides an interface for I2C devices|
|**sfTkISPI** | Sub-class of the ```sfeTkIIBus``` interface, it provides an interface for SPI devices |

### The sfeTkIBus Interface
### The sfTkIBus Interface

The key to meeting the goals of the Toolkit is the IBus interface. This interface defines the methods used to communicate with a device. The setup, configuration and implementation of this interface is performed by platform specific implementations of the interface.

The interface methods:
The bus implements methods that perform the following

| Method| Definition |
|------|-------|
|**writeRegisterByte** | Write a byte of data to a particular register of a device |
|**writeRegisterWord** | Write a word of data to a particular register of a device |
|**writeRegisterRegion** | Write an array of data to a particular register of a device|
|**readRegisterByte** | Read a byte of data from a particular register of a device |
|**readRegisterWord** | Read a word of data from a particular register of a device |
|**readRegisterRegion** | Read an array of data from a particular register of a device |
|**writeRegister(...)** | Overloaded set of methods to write data to a specified register|
|**readRegister(...)** | Overloaded set of methods to read data from a specified register|
|**writeData(...)** | An overloaded set of methods to write data directly to the device|

Additionally a set of explicitly named methods for different core types are provided.

> [!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)
Specific details for this class are detailed [here](https://docs.sparkfun.com/SparkFun_Toolkit/classsf_tk_i_bus.html)

### The sfeTkII2C Implementation
### The sfTkII2C Implementation

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.
This class sub-classes from the ```sfTkIBus``` 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 |
|------|-------|
Expand All @@ -72,15 +69,13 @@ This class sub-classes from the ```sfeTkIBus``` interface adding additional func
|**address** | Returns the address used by this I2C object |

> [!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 ```sfTkII2C``` class manages the device address for the I2C bus. As such, each I2C device instantiates/uses an instance of the ```sfTkII2C``` class.

The class diagram for the ```sfeTkII2C``` interface is the following:

![II2C Class Diagram](images/tk_uml_ii2c.png)
The details for the ```sfeTkII2C``` interface are [here](https://docs.sparkfun.com/SparkFun_Toolkit/classsf_tk_i_i2_c.html)

### 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.
This class sub-classes from the ```sfTkIBus``` interface adding additional functionally focused on supporting an SPI implementation. This interface provides the additional functionality.

| Method| Definition |
|------|-------|
Expand All @@ -90,53 +85,47 @@ This class sub-classes from the ```sfeTkIBus``` interface adding additional func
> [!NOTE]
> The ```sfeTkISPI``` class manages CS Pin for the SPI bus. As such, each SPI device instantiates/uses an instance of the ```sfeTkISPI``` class.

The class diagram of these base class interfaces/implementation:

![ISPI Class Diagram](images/tk_uml_ispi.png)
The details for the ```sfTkII2C``` interface are [here](https://docs.sparkfun.com/SparkFun_Toolkit/classsf_tk_i_s_p_i.html)

## sfeTkIBus - Arduino Implementation
## sfTkIBus - 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.
The initial implementation of the toolkit IBus interface is for the Arduino environment. This implementation consists of two classes, ```sfTkArdI2C``` and ```sfTkArdSPI```, 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 - a device in most cases - contains an instance of the specific bus class.

### The sfeTkArdI2C Class
### The sfTkArdI2C Class

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.
This class provides the Arduino implementation of I2C in the SparkFun Toolkit. It implements the methods of the ```sfTkIBus``` and ```sfTkII2C``` interfaces, as well as manages any Arduino specific state.

The class diagram for the sfeTkArdI2C class:
Details for this class are located [here](https://docs.sparkfun.com/SparkFun_Toolkit/classsf_tk_ard_i2_c.html)

![Arduino I2C Class Diagram](images/tk_uml_ardi2c.png)
### The sfTkArdSPI Class

### The sfeTkArdSPI Class
This class provides the Arduino implementation of SPI in the SparkFun Toolkit. It implements the methods of the ```sfTkIBus``` and ```sfTkISPI``` 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 ```sfTkArdSPI``` uses an internal SPISettings class to ensure the SPI bus is operating in the desired mode for the device.

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.
Details for this class are located [here](https://docs.sparkfun.com/SparkFun_Toolkit/classsf_tk_ard_s_p_i.html)

The class diagram for the sfeTkArdSPI class:
## sfTkIBus Use

![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.
The general steps when using the sfTkIBus in device development are outlined in the following steps. This example uses the Arduino implementation of the bus.

The general pattern for a device driver implementation that uses the SparkFun Toolkit is the following:

### 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 ```sfeTkIBus``` interface. By limiting use to the IBus interface, the core implementation can use any bus type or platform that implements the sfeTkIBus 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 ```sfTkIBus``` 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.
> At this level, the driver is only using a ```sfTkIBus``` interface, not any specific bus implementation.

This driver has the following unique functionality:

1) A method to set the object that implements the ```sfeTkIBus``` interface object should use. Since
1) A method to set the object that implements the ```sfTkIBus``` interface object should use or sets the bus in a ```begin()``` method.
1) If the device supports identification capabilities, the driver provides this functionality.

#### Simple Example of an Independent Driver Implementation
Expand All @@ -152,36 +141,42 @@ class myDriverClass
{
public:

myDriverClass(uint8_t address) : _addr{address}, _theBus{nullptr}{}
myDriverClass() : _theBus{nullptr}{}

bool begin()
sfTkError_t begin(sfTkBus *theBus = nullptr)
{
// initialize things ...

return true;
}
void setCommunicationBus(sfeTkIBus *theBus)
{
if (_theBus == nullptr)
return ksfTkErrFail;

_theBus = theBus;
return ksfTkErrOk;
}

bool updateDeviceData(uint8_t *data, size_t len)
sfTkError_t updateDeviceData(uint8_t *data, size_t len)
{
if (!_theBus || !data || len == 0)
return false;
return ksfTkErrFail;

sfeTkError_t status = _theBus->writeRegisterRegion(THE_REG, data, len);
return _theBus->writeRegister(THE_REG, data, len);

return (status == kSTkErrOk);
}

bool checkDeviceID()
sfTkError_t checkDeviceID()
{
// do some device ID checks in registers ...etc
return true;
return kSTkErrOk;
}
// and additional methods for the driver ..
sfTkError_t doSomethingA(int32_t);
sfTkError_t getValueA(uint32_t&);
sfTkError_t setPropertyB(double);


private:
uint8_t _addr;

sfeTkIBus *_theBus;
};
```
Expand Down Expand Up @@ -213,29 +208,27 @@ class myArduinoDriverI2C : public myDriverClass
myArduinoDriverI2C()
{}

bool begin()
bool begin(const uint8_t address = SF_BMV080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire)
{
if (_theI2CBus.init(MY_DEVICE_ADDRESS) != kSTkErrOk)
if (_theI2CBus.init(wirePOrt, MY_DEVICE_ADDRESS) != ksfTkErrOk)
return false;

// OPTIONAL: If your device supports repeat starts.
_theI2CBus.setStop(false);

setCommunicationBus(&_theI2CBus);

return myDriverClass::begin();
return myDriverClass::begin(&_theI2CBus);
}

bool isConnected()
{
if (_theI2CBus.ping() != kSTkErrOk)
if (_theI2CBus.ping() != ksfTkErrOk)
return false;

return checkDeviceID();
return checkDeviceID() == kstTkErrOk;
}

private:
sfeTkArdI2C _theI2CBus;
sfTkArdI2C _theI2CBus;
};
```

Expand All @@ -254,27 +247,30 @@ class myArduinoDriveSPI : public myDriverClass
myArduinoDriverSPI()
{}

bool begin()
bool begin(uint8_t csPin, SPIClass &spiPort = SPI,
SPISettings spiSettings = SPISettings(4000000, MSBFIRST, SPI_MODE0))

{
SPISettings spiSettings = SPISettings(4000000, MSBFIRST, SPI_MODE3);

if (_theSPIBus.init(SPI, spiSettings, MY_DEFAULT_CS, true) != kSTkErrOk)
if (_theSPIBus.init(spiPort, spiSettings, csPin, true) != ksfTkErrOk)
return false;
setCommunicationBus(&_theSPIBus);

return myDriverClass::begin();
return myDriverClass::begin(&_theSPIBus) == ksfTkErrOk;
}

bool isConnected()
{
return checkDeviceID();
return checkDeviceID() == ksfTkErrOk;
}

private:
sfeTkArdSPI _theSPIBus;
sfTkArdSPI _theSPIBus;
};
```

> [!IMPORTANT]
>The I2C and SPI versions of the driver just manage the specific bus setup and initialization - beyond that, the core class, which ***only*** operates using the bus interface class forms the core of both implementations.

## 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:
Expand Down
Binary file added docs/images/gh-banner-2025-banner-toolkit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/tk_uml_ardi2c.png
Binary file not shown.
Binary file removed docs/images/tk_uml_ardspi.png
Binary file not shown.
Binary file removed docs/images/tk_uml_ibus.png
Binary file not shown.
Binary file removed docs/images/tk_uml_ii2c.png
Binary file not shown.
Binary file removed docs/images/tk_uml_ispi.png
Binary file not shown.
Loading