Skip to content

Commit

Permalink
Merge pull request #137 from adafruit/genericdevice
Browse files Browse the repository at this point in the history
add generic device for non-standard transports
  • Loading branch information
ladyada authored Jan 8, 2025
2 parents 55e4f83 + 1a7e578 commit cc66c42
Show file tree
Hide file tree
Showing 10 changed files with 491 additions and 16 deletions.
43 changes: 31 additions & 12 deletions Adafruit_BusIO_Register.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,26 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register(
_width = width;
}

/*!
* @brief Create a register we access over a GenericDevice
* @param genericdevice Generic device to use
* @param reg_addr Register address we will read/write
* @param width Width of the register in bytes (1-4)
* @param byteorder Byte order of register data (LSBFIRST or MSBFIRST)
* @param address_width Width of the register address in bytes (1 or 2)
*/
Adafruit_BusIO_Register::Adafruit_BusIO_Register(
Adafruit_GenericDevice *genericdevice, uint16_t reg_addr, uint8_t width,
uint8_t byteorder, uint8_t address_width) {
_i2cdevice = nullptr;
_spidevice = nullptr;
_genericdevice = genericdevice;
_addrwidth = address_width;
_address = reg_addr;
_byteorder = byteorder;
_width = width;
}

/*!
* @brief Write a buffer of data to the register location
* @param buffer Pointer to data to write
Expand All @@ -96,17 +116,14 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register(
* uncheckable)
*/
bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {

uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
(uint8_t)(_address >> 8)};

if (_i2cdevice) {
return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth);
}
if (_spidevice) {
if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) {
// very special case!

// pass the special opcode address which we set as the high byte of the
// regaddr
addrbuffer[0] =
Expand All @@ -116,7 +133,6 @@ bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
// the address appears to be a byte longer
return _spidevice->write(buffer, len, addrbuffer, _addrwidth + 1);
}

if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
addrbuffer[0] &= ~0x80;
}
Expand All @@ -129,6 +145,9 @@ bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
}
return _spidevice->write(buffer, len, addrbuffer, _addrwidth);
}
if (_genericdevice) {
return _genericdevice->writeRegister(addrbuffer, _addrwidth, buffer, len);
}
return false;
}

Expand Down Expand Up @@ -192,23 +211,20 @@ uint32_t Adafruit_BusIO_Register::read(void) {
uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; }

/*!
* @brief Read a buffer of data from the register location
* @param buffer Pointer to data to read into
* @param len Number of bytes to read
* @return True on successful write (only really useful for I2C as SPI is
* uncheckable)
*/
@brief Read a number of bytes from a register into a buffer
@param buffer Buffer to read data into
@param len Number of bytes to read into the buffer
@return true on successful read, otherwise false
*/
bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
(uint8_t)(_address >> 8)};

if (_i2cdevice) {
return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
}
if (_spidevice) {
if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) {
// very special case!

// pass the special opcode address which we set as the high byte of the
// regaddr
addrbuffer[0] =
Expand All @@ -230,6 +246,9 @@ bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
}
return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
}
if (_genericdevice) {
return _genericdevice->readRegister(addrbuffer, _addrwidth, buffer, len);
}
return false;
}

Expand Down
7 changes: 7 additions & 0 deletions Adafruit_BusIO_Register.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#if !defined(SPI_INTERFACES_COUNT) || \
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))

#include <Adafruit_GenericDevice.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_SPIDevice.h>

Expand Down Expand Up @@ -57,6 +58,11 @@ class Adafruit_BusIO_Register {
uint8_t width = 1, uint8_t byteorder = LSBFIRST,
uint8_t address_width = 1);

Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice,
uint16_t reg_addr, uint8_t width = 1,
uint8_t byteorder = LSBFIRST,
uint8_t address_width = 1);

bool read(uint8_t *buffer, uint8_t len);
bool read(uint8_t *value);
bool read(uint16_t *value);
Expand All @@ -77,6 +83,7 @@ class Adafruit_BusIO_Register {
private:
Adafruit_I2CDevice *_i2cdevice;
Adafruit_SPIDevice *_spidevice;
Adafruit_GenericDevice *_genericdevice;
Adafruit_BusIO_SPIRegType _spiregtype;
uint16_t _address;
uint8_t _width, _addrwidth, _byteorder;
Expand Down
78 changes: 78 additions & 0 deletions Adafruit_GenericDevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
Written with help by Claude!
https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time
chats are not shareable :(
*/

#include "Adafruit_GenericDevice.h"

/*! @brief Create a Generic device with the provided read/write functions
@param read_func Function pointer for reading raw data
@param write_func Function pointer for writing raw data
@param readreg_func Function pointer for reading registers (optional)
@param writereg_func Function pointer for writing registers (optional) */
Adafruit_GenericDevice::Adafruit_GenericDevice(
busio_genericdevice_read_t read_func,
busio_genericdevice_write_t write_func,
busio_genericdevice_readreg_t readreg_func,
busio_genericdevice_writereg_t writereg_func) {
_read_func = read_func;
_write_func = write_func;
_readreg_func = readreg_func;
_writereg_func = writereg_func;
_begun = false;
}

/*! @brief Initializes the device
@return true if initialization was successful, otherwise false */
bool Adafruit_GenericDevice::begin(void) {
_begun = true;
return true;
}

/*! @brief Write a buffer of data
@param buffer Pointer to buffer of data to write
@param len Number of bytes to write
@return true if write was successful, otherwise false */
bool Adafruit_GenericDevice::write(const uint8_t *buffer, size_t len) {
if (!_begun)
return false;
return _write_func(buffer, len);
}

/*! @brief Read data into a buffer
@param buffer Pointer to buffer to read data into
@param len Number of bytes to read
@return true if read was successful, otherwise false */
bool Adafruit_GenericDevice::read(uint8_t *buffer, size_t len) {
if (!_begun)
return false;
return _read_func(buffer, len);
}

/*! @brief Read from a register location
@param addr_buf Buffer containing register address
@param addrsiz Size of register address in bytes
@param buf Buffer to store read data
@param bufsiz Size of data to read in bytes
@return true if read was successful, otherwise false */
bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz,
uint8_t *buf, uint16_t bufsiz) {
if (!_begun || !_readreg_func)
return false;
return _readreg_func(addr_buf, addrsiz, buf, bufsiz);
}

/*! @brief Write to a register location
@param addr_buf Buffer containing register address
@param addrsiz Size of register address in bytes
@param buf Buffer containing data to write
@param bufsiz Size of data to write in bytes
@return true if write was successful, otherwise false */
bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz,
const uint8_t *buf,
uint16_t bufsiz) {
if (!_begun || !_writereg_func)
return false;
return _writereg_func(addr_buf, addrsiz, buf, bufsiz);
}
50 changes: 50 additions & 0 deletions Adafruit_GenericDevice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#ifndef ADAFRUIT_GENERICDEVICE_H
#define ADAFRUIT_GENERICDEVICE_H

#include <Arduino.h>

typedef bool (*busio_genericdevice_read_t)(uint8_t *buffer, size_t len);
typedef bool (*busio_genericdevice_write_t)(const uint8_t *buffer, size_t len);
typedef bool (*busio_genericdevice_readreg_t)(uint8_t *addr_buf,
uint8_t addrsiz, uint8_t *buf,
uint16_t bufsiz);
typedef bool (*busio_genericdevice_writereg_t)(uint8_t *addr_buf,
uint8_t addrsiz,
const uint8_t *buf,
uint16_t bufsiz);

/*!
* @brief Class for communicating with a device via generic read/write functions
*/
class Adafruit_GenericDevice {
public:
Adafruit_GenericDevice(
busio_genericdevice_read_t read_func,
busio_genericdevice_write_t write_func,
busio_genericdevice_readreg_t readreg_func = nullptr,
busio_genericdevice_writereg_t writereg_func = nullptr);

bool begin(void);

bool read(uint8_t *buffer, size_t len);
bool write(const uint8_t *buffer, size_t len);
bool readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf,
uint16_t bufsiz);
bool writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf,
uint16_t bufsiz);

protected:
/*! @brief Function pointer for reading raw data from the device */
busio_genericdevice_read_t _read_func;
/*! @brief Function pointer for writing raw data to the device */
busio_genericdevice_write_t _write_func;
/*! @brief Function pointer for reading a 'register' from the device */
busio_genericdevice_readreg_t _readreg_func;
/*! @brief Function pointer for writing a 'register' to the device */
busio_genericdevice_writereg_t _writereg_func;

bool _begun; ///< whether we have initialized yet (in case the function needs
///< to do something)
};

#endif // ADAFRUIT_GENERICDEVICE_H
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Adafruit Bus IO Library [![Build Status](https://github.com/adafruit/Adafruit_BusIO/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BusIO/actions)


This is a helper library to abstract away I2C & SPI transactions and registers
This is a helper library to abstract away I2C, SPI, and 'generic transport' (e.g. UART) transactions and registers

Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!

Expand Down
Empty file.
Loading

0 comments on commit cc66c42

Please sign in to comment.