Compare commits

...

109 commits

Author SHA1 Message Date
Limor "Ladyada" Fried
e75ac29ca6
Merge pull request #145 from brentru/add-genericdevice-end
Add end() for GenericDevice
2025-06-28 19:34:03 -04:00
brentru
d8a04619f0 Add - end() for GenericDevice 2025-06-18 16:01:02 -04:00
Tyeth Gundry
a09a91d13e
Update library.properties - bump version to 1.17.1 2025-04-29 13:04:24 +01:00
Limor "Ladyada" Fried
159f86a3bd
Merge pull request #140 from mak0t0san/patch-1
Update CMakeLists.txt to include "Adafruit_GenericDevice.cpp"
2025-04-28 11:14:02 -04:00
Limor "Ladyada" Fried
5e8f137415
Merge pull request #144 from meshtastic/master
Add PORTDUINO check to Adafruit_SPIDevice.h
2025-04-28 11:13:42 -04:00
Jonathan Bennett
fcd9217179
fix for clang-format in Adafruit_SPIDevice.h 2025-04-26 09:47:42 -05:00
Jonathan Bennett
18a22e98ac
Add PORTDUINO check to Adafruit_SPIDevice.h
The PORTDUINO target on ARMv7 was triggering the defined(__arm__) code block, and failing compilation as a result. Quick fix to check for PORTDUINO.
2025-04-26 09:34:15 -05:00
Makoto Schoppert
276c7b3ad8
Update CMakeLists.txt
Missing source file "Adafruit_GenericDevice.cpp"
2025-01-31 22:43:45 -05:00
Limor "Ladyada" Fried
055013b58d
Merge pull request #139 from adafruit/genericdevice2
refactor the whole thing to get rid of static-ness. also clang examples
2025-01-08 15:13:46 -05:00
ladyada
186ea35211 reclang 2025-01-08 15:05:13 -05:00
ladyada
8a32dc72c9 refactor the whole thing to get rid of static-ness. also clang examples 2025-01-08 15:03:00 -05:00
Limor "Ladyada" Fried
cc66c422eb
Merge pull request #137 from adafruit/genericdevice
add generic device for non-standard transports
2025-01-08 10:38:11 -05:00
ladyada
1a7e578832 test skip for uart 2025-01-08 10:25:38 -05:00
ladyada
c6b5c0b2b7 Merge branch 'genericdevice' of github.com:adafruit/Adafruit_BusIO into genericdevice 2025-01-08 10:15:13 -05:00
ladyada
2663ca269f woops fix serial 2025-01-08 10:15:09 -05:00
Limor "Ladyada" Fried
ff26e5a112
Merge branch 'master' into genericdevice 2025-01-08 10:13:44 -05:00
Limor "Ladyada" Fried
55e4f835bc
Merge pull request #131 from johnboiles/master
For ESP-IDF builds use arduino-esp32 instead of arduino dependency
2025-01-08 09:39:59 -05:00
Limor "Ladyada" Fried
17506175b2
Merge pull request #136 from facchinm/improve_fast_pin_io
Avoid fast pins IO on RTOS based boards
2025-01-08 09:38:46 -05:00
ladyada
c0237922d3 add claude credits! 2025-01-08 09:35:51 -05:00
ladyada
fcc8dfaf63 bump 2025-01-08 09:31:54 -05:00
ladyada
70ad31700a some tests for uart mode 2025-01-08 09:30:58 -05:00
ladyada
c602ea03e0 doxyclanged! 2025-01-08 09:29:49 -05:00
ladyada
66448b37ec clang 2025-01-07 22:08:13 -05:00
ladyada
c43db9d7c2 still need to doxy/clang 2025-01-07 22:03:15 -05:00
Tyeth Gundry
9eda3f4641
Update library.properties - bump version to 1.16.3 2025-01-07 16:23:28 +00:00
ladyada
9bd286898c Merge branch 'master' of github.com:adafruit/Adafruit_BusIO 2025-01-05 15:12:18 -05:00
ladyada
14d379e4d3 small typo fix 2025-01-05 15:12:13 -05:00
Martino Facchin
c99c8564a2 fixup: clang-format fix 2024-12-16 09:41:55 +01:00
Martino Facchin
9eeac1d181 Avoid fast pins IO on RTOS based boards
Better fix than 80943e663f
2024-12-13 15:54:58 +01:00
Tyeth Gundry
ddf66b491e
Update library.properties - bump version to 1.16.2 2024-10-29 21:57:16 +00:00
Limor "Ladyada" Fried
0b68c51a4a
Merge pull request #135 from caternuson/giga_i2c_patch
Patch for GIGA I2C quirk
2024-10-24 17:46:15 -04:00
caternuson
31148fe857 clangerdified 2024-10-24 14:37:54 -07:00
caternuson
9af8ab9607 giga i2c hack fix 2024-10-24 14:25:57 -07:00
John Boiles
18df8eaf8b For ESP-IDF builds use arduino-esp32 instead of arduino dependency 2024-07-31 17:09:25 -07:00
Tyeth Gundry
15fbda592d
Update library.properties - bump version to 1.16.1 2024-05-21 12:15:23 +01:00
Ha Thach
fccf89cac9
Merge pull request #129 from silabs-bozont/master
Fix compatibility with Silicon Labs boards
2024-05-15 16:48:46 +07:00
Tamas Jozsi
95e8f81499 Fix compatibility with Silicon Labs boards
The Silicon Labs core moved to use ArduinoCore-API which
has a native 'BitOrder' definition
2024-05-10 17:48:14 +02:00
Tyeth Gundry
e1aa388418
Update library.properties - bump version to 1.16.0 2024-04-16 18:44:56 +01:00
Limor "Ladyada" Fried
970ccbfd67
Merge pull request #125 from mecparts/master
Add compatibility with Arduino R4 boards
2024-04-14 22:24:24 -04:00
mecparts
5f170d8e4f
Amended code formatting 2024-02-11 14:16:08 -07:00
mecparts
d5aa1a353e
Add compatibility with Arduino R4 boards 2024-02-11 13:28:45 -07:00
Tyeth Gundry
fc25cd4967
Update library.properties - bump version to 1.15.0 2024-01-16 19:08:05 +00:00
Ha Thach
ec19ba1d6c
Merge pull request #124 from silabs-bozont/master
Add compatibility with Silicon Labs Arduino boards
2024-01-11 11:42:02 +07:00
Tamas Jozsi
16e4726718 Add compatibility with Silicon Labs Arduino boards 2024-01-05 17:14:45 +01:00
Carter Nelson
9ebca64d82
Update library.properties 2023-10-10 09:30:15 -07:00
Limor "Ladyada" Fried
c07701e0b1
Merge pull request #121 from caternuson/esp32_warns
Remove volatile compound assignments
2023-10-09 18:09:30 -04:00
caternuson
2708c120c6 remove volatile compound assignments 2023-10-09 13:52:00 -07:00
ladyada
4d276155d7 klzng 2023-10-09 12:15:35 -04:00
ladyada
a9498c8f62 kick! 2023-10-09 12:13:50 -04:00
ladyada
ad776484f3 Merge branch 'master' of github.com:adafruit/Adafruit_BusIO 2023-09-25 00:53:11 -04:00
ladyada
fbba4799ad more specific debug during scan 2023-09-25 00:53:07 -04:00
Tyeth Gundry
ee0faec7ee
Update library.properties - bump version to 1.14.4 2023-09-19 11:39:09 +01:00
Dan Halbert
7cc1d0a5fd
Merge pull request #120 from Wol/patch-1
Remove offensive term in comments
2023-09-15 23:01:30 -04:00
Luke Lowrey
9108618560
Fix line length 2023-09-16 00:59:38 +01:00
Luke Lowrey
1b7f5a9590
Remove offensive term in comments
Tidying up the language used - https://dictionary.cambridge.org/dictionary/english/spaz https://en.wiktionary.org/wiki/spaz
2023-09-16 00:30:41 +01:00
Ha Thach
4f899a2dd6
Merge pull request #119 from OlafFilies/XMC_enable
By adding two macros all Infineons XMC MCUs are now able to use the l…
2023-09-13 13:46:01 +07:00
Filies Olaf (IFAG DES TOC PSA)
5162b240d7 Forgot the || inthe macro list 2023-09-11 17:21:18 +02:00
Filies Olaf (IFAG DES TOC PSA)
8097aa568f By adding two macros all Infineons XMC MCUs are now able to use the library 2023-09-11 16:50:03 +02:00
Tyeth Gundry
3ea940b745
Update library.properties - bump version to 1.14.3 2023-08-15 12:03:13 +01:00
Limor "Ladyada" Fried
5473c1801c
Merge pull request #117 from DeflateAwning/master
Add explicit type casting to fix build error
2023-08-13 13:53:57 -04:00
DeflateAwning
7fd30d0bf8 Add explicit type casting to fix build error 2023-06-21 23:25:44 -06:00
dherrada
42e31a252f Update CI action versions 2023-05-12 11:23:57 -04:00
Carter Nelson
186bfb005c
Update library.properties 2022-11-02 09:53:19 -07:00
Carter Nelson
6a2e9b6a88
Merge pull request #110 from caternuson/iss109
Init HW SPI members
2022-11-02 09:52:40 -07:00
caternuson
369413c66d init hw spi members 2022-11-01 12:23:15 -07:00
Eva Herrada
0348f74375
Bump to 1.14.0 2022-10-25 17:24:30 -04:00
Carter Nelson
8f3a45e263
Merge pull request #108 from caternuson/iss81_spi_refac
Refactor for better SW SPI only support
2022-10-24 10:58:05 -07:00
caternuson
3736ebfde1 refactor for better sw spi only support 2022-08-22 15:18:26 -07:00
Eva Herrada
e89ae64bd3
Bump to 1.13.2 2022-08-12 17:16:53 -04:00
Limor "Ladyada" Fried
4b8f6e312c
Merge pull request #106 from RobTillaart/master
Fix #105 - make I2C setspeed more robust
2022-08-12 15:06:06 -04:00
rob tillaart
319d44c093 fix build 2022-08-08 22:02:39 +02:00
rob tillaart
e238822921 clang-format 2022-08-08 21:31:17 +02:00
Rob Tillaart
3cc0846d78
Fix #105 - make setspeed more robust
- prevent out of range I2C speeds for AVR
2022-08-08 21:17:42 +02:00
Eva Herrada
8fce6cda99
Bump to 1.13.1 2022-08-02 12:26:14 -04:00
lady ada
5c159aa9a1 oi nevermind 2022-08-02 11:23:11 -04:00
lady ada
0e5b03fcfb clang 2022-08-02 11:11:30 -04:00
lady ada
fe6bb61052 Merge branch 'master' of github.com:adafruit/Adafruit_BusIO 2022-08-02 11:06:54 -04:00
lady ada
a8b7958a1a be more specific on fixing arduino i2c speeds 2022-08-02 11:06:49 -04:00
Eva Herrada
eeda9eeee2
Bump to 1.13.0 2022-08-01 13:40:43 -04:00
lady ada
a493f3d7a3 clang 2022-07-31 23:26:58 -04:00
lady ada
8c7a20af42 Merge branch 'master' of github.com:adafruit/Adafruit_BusIO 2022-07-31 23:25:28 -04:00
lady ada
399aeea376 https://github.com/adafruit/Adafruit_BusIO/issues/100 2022-07-31 23:25:24 -04:00
Limor "Ladyada" Fried
23ac286bd0
Merge pull request #104 from adafruit/fixavrsetspeed
manually handle AVR i2c setspeed to handle slow clocks
2022-07-31 17:46:19 -04:00
lady ada
3e0e740d56 clang 2022-07-31 17:06:55 -04:00
lady ada
36da2e4611 prescaler is not calculated here https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/Wire/src/utility/twi.c#L139 which means we cannot get below 30.5mhz! 2022-07-31 17:04:44 -04:00
Eva Herrada
c421326131
Bump to 1.12.0 2022-06-28 16:19:19 -04:00
lady ada
1cb88a65b7 add ESP32 large buffer support (doesnt fix bno085 but worth a short)
cc @caternuson
2022-06-25 21:12:11 -04:00
Eva Herrada
515f63f49c
Bump to 1.11.6 2022-05-09 15:56:03 -04:00
Limor "Ladyada" Fried
bb7c77ad09
Merge pull request #95 from eringerli/workflow
updated github workflow
2022-05-02 18:29:58 -04:00
Limor "Ladyada" Fried
02665fd93f
Merge pull request #96 from KurtE/t4x_neutered
T4.x - Software SPI - don't use FAST_PINIO
2022-05-02 18:29:41 -04:00
Limor "Ladyada" Fried
b949d28bde
Merge pull request #93 from eringerli/cs-transaction-management
better transaction management
2022-05-02 18:29:00 -04:00
KurtE
17cf18bf5b T4.x - Software SPI - don't use FAST_PINIO
The original problem was that the code defined the registers and mask as 8 bits, when the T4.x ones are 32 bits.  So it only worked on a subset of pins.

So first fix would be to simply define these values as 32 bits.  But doing so leaves you code at risk as the Set/Clear code in this library is not atomic,
Example: *clkPort |= clkPinMask;

So if something happens in the small time window after the time the register is retrieved and then manipulated and written back, such as an interrupt.
Or maybe if other hardware is driving the pin.  These changes would be
clobbered by the above code.

Not sure how many other boards (if any) may be hit by the same issue.

It is not an issue with T3.x as the Teensy code uses the M3/M4 bitband support, so for each pin there is a unique memory address for it and these operations are atomic.

Note: the Arm M7 does not support bitbands.  However  in these caseAtomic code can be written for the T4.x by instead using the DR register of the IO port, you use the DR_SET, DR_CLEAR, DR_TOGGLE registers instead which do as the names imply
the do that operation only those pins who have a 1 bit set to the value...
2022-05-02 15:16:52 -07:00
Eva Herrada
204c1de9ab
Bump to 1.11.5 2022-05-02 17:50:30 -04:00
Christian Riggenbach
f82f699c64 reuse beginTransactionWithAssertingCS()/endTransactionWithDeassertingCS() 2022-05-02 22:37:27 +02:00
Christian Riggenbach
c00ec13218 moved setChipSelect() in front of beginTransactionWithAssertingCS()
This is a more logical order, as beginTransactionWithAssertingCS() and
endTransactionWithDeassertingCS() both call it.
2022-05-02 22:37:17 +02:00
Christian Riggenbach
41635e3c68 beginTransactionWithAssertingCS() and endTransactionWithDeassertingCS()
These two methods are similar to beginTransaction() and endTransaction(),
but, as the name implies, with CS management. They are both public, as
beginTransaction() and endTransaction() are too.
2022-05-02 22:35:38 +02:00
Christian Riggenbach
132124b093 updated github workflow 2022-05-02 22:12:18 +02:00
Limor "Ladyada" Fried
4ca049393f
Merge pull request #92 from eringerli/more-specific-documentation
More specific Documentation
2022-05-02 16:11:36 -04:00
Christian Riggenbach
a43f6e0921 more specific documentation 2022-05-02 20:57:10 +02:00
Eva Herrada
87af677566
Bump to 1.11.4 2022-04-25 15:18:37 -04:00
Limor "Ladyada" Fried
c702120651
Merge pull request #89 from eringerli/cleanup
Cleanup
2022-04-17 18:09:39 -04:00
Christian Riggenbach
4b18d396dc use the typesafe replacement nullptr instead of NULL (since C++11) 2022-04-17 15:03:17 +02:00
Christian Riggenbach
3561fd9ff6 delete works for nullptr, no need to set a member in the destructor 2022-04-17 14:43:57 +02:00
Eva Herrada
1c1c73ee85
Bump to 1.11.3 2022-03-17 11:05:04 -04:00
Ha Thach
ef3d84faa8
Merge pull request #84 from yilungao/spi-write-param-const-ness
write method parameter const-ness
2022-03-15 22:09:42 +07:00
Walt
b6f7b3abe1 applied clang-format 2022-03-14 22:45:53 -07:00
Walt
c41e829dcc write method parameter const-ness
fix https://github.com/adafruit/Adafruit_FRAM_SPI/issues/25
2022-03-10 21:43:30 -08:00
Carter Nelson
1741708a6a
Update library.properties 2022-03-01 06:58:02 -08:00
Limor "Ladyada" Fried
538b07a070
Merge pull request #83 from adafruit/revert-77-master
Revert "Faster hardware SPI writes on SAMD"
2022-02-28 21:06:36 -05:00
24 changed files with 1007 additions and 311 deletions

View file

@ -7,26 +7,27 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v2
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
- name: Install the prerequisites
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py main_platforms zero feather32u4
- name: Check for correct code formatting with clang-format
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: doxygen
- name: Check for correct documentation with doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit Bus IO Library"
run: bash ci/doxy_gen_and_deploy.sh
- name: Test the code on supported platforms
run: python3 ci/build_platform.py main_platforms zero feather32u4

View file

@ -21,7 +21,7 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
uint8_t byteorder,
uint8_t address_width) {
_i2cdevice = i2cdevice;
_spidevice = NULL;
_spidevice = nullptr;
_addrwidth = address_width;
_address = reg_addr;
_byteorder = byteorder;
@ -50,7 +50,7 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice,
uint8_t address_width) {
_spidevice = spidevice;
_spiregtype = type;
_i2cdevice = NULL;
_i2cdevice = nullptr;
_addrwidth = address_width;
_address = reg_addr;
_byteorder = byteorder;
@ -59,12 +59,12 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice,
/*!
* @brief Create a register we access over an I2C or SPI Device. This is a
* handy function because we can pass in NULL for the unused interface, allowing
* libraries to mass-define all the registers
* @param i2cdevice The I2CDevice to use for underlying I2C access, if NULL
* we use SPI
* @param spidevice The SPIDevice to use for underlying SPI access, if NULL
* we use I2C
* handy function because we can pass in nullptr for the unused interface,
* allowing libraries to mass-define all the registers
* @param i2cdevice The I2CDevice to use for underlying I2C access, if
* nullptr we use SPI
* @param spidevice The SPIDevice to use for underlying SPI access, if
* nullptr we use I2C
* @param reg_addr The address pointer value for the I2C/SMBus/SPI register,
* can be 8 or 16 bits
* @param type The method we use to read/write data to SPI (which is not
@ -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
@ -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] =
@ -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;
}
@ -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;
}
@ -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] =
@ -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;
}

View file

@ -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>
@ -57,6 +58,11 @@ public:
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);
@ -77,6 +83,7 @@ public:
private:
Adafruit_I2CDevice *_i2cdevice;
Adafruit_SPIDevice *_spidevice;
Adafruit_GenericDevice *_genericdevice;
Adafruit_BusIO_SPIRegType _spiregtype;
uint16_t _address;
uint8_t _width, _addrwidth, _byteorder;

View file

@ -0,0 +1,90 @@
/*
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 obj Pointer to object instance
* @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(
void *obj, busio_genericdevice_read_t read_func,
busio_genericdevice_write_t write_func,
busio_genericdevice_readreg_t readreg_func,
busio_genericdevice_writereg_t writereg_func) {
_obj = obj;
_read_func = read_func;
_write_func = write_func;
_readreg_func = readreg_func;
_writereg_func = writereg_func;
_begun = false;
}
/*! @brief Simple begin function (doesn't do much at this time)
@return true always
*/
bool Adafruit_GenericDevice::begin(void) {
_begun = true;
return true;
}
/*!
@brief Marks the GenericDevice as no longer in use.
@note: Since this is a GenericDevice, if you are using this with a Serial
object, this does NOT disable serial communication or release the RX/TX pins.
That must be done manually by calling Serial.end().
*/
void Adafruit_GenericDevice::end(void) { _begun = false; }
/*! @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(_obj, 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(_obj, 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(_obj, 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(_obj, addr_buf, addrsiz, buf, bufsiz);
}

56
Adafruit_GenericDevice.h Normal file
View file

@ -0,0 +1,56 @@
#ifndef ADAFRUIT_GENERICDEVICE_H
#define ADAFRUIT_GENERICDEVICE_H
#include <Arduino.h>
typedef bool (*busio_genericdevice_read_t)(void *obj, uint8_t *buffer,
size_t len);
typedef bool (*busio_genericdevice_write_t)(void *obj, const uint8_t *buffer,
size_t len);
typedef bool (*busio_genericdevice_readreg_t)(void *obj, uint8_t *addr_buf,
uint8_t addrsiz, uint8_t *data,
uint16_t datalen);
typedef bool (*busio_genericdevice_writereg_t)(void *obj, uint8_t *addr_buf,
uint8_t addrsiz,
const uint8_t *data,
uint16_t datalen);
/*!
* @brief Class for communicating with a device via generic read/write functions
*/
class Adafruit_GenericDevice {
public:
Adafruit_GenericDevice(
void *obj, 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);
void end(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)
private:
void *_obj; ///< Pointer to object instance
};
#endif // ADAFRUIT_GENERICDEVICE_H

View file

@ -1,6 +1,6 @@
#include "Adafruit_I2CDevice.h"
//#define DEBUG_SERIAL Serial
// #define DEBUG_SERIAL Serial
/*!
* @brief Create an I2C device at a given address
@ -13,6 +13,8 @@ Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) {
_begun = false;
#ifdef ARDUINO_ARCH_SAMD
_maxBufferSize = 250; // as defined in Wire.h's RingBuffer
#elif defined(ESP32)
_maxBufferSize = I2C_BUFFER_LENGTH;
#else
_maxBufferSize = 32;
#endif
@ -21,8 +23,8 @@ Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) {
/*!
* @brief Initializes and does basic address detection
* @param addr_detect Whether we should attempt to detect the I2C address
* with a scan. 99% of sensors/devices don't mind but once in a while, they spaz
* on a scan!
* with a scan. 99% of sensors/devices don't mind, but once in a while they
* don't respond well to a scan!
* @return True if I2C initialized and a device with the addr found
*/
bool Adafruit_I2CDevice::begin(bool addr_detect) {
@ -65,14 +67,21 @@ bool Adafruit_I2CDevice::detected(void) {
// A basic scanner, see if it ACK's
_wire->beginTransmission(_addr);
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("Address 0x"));
DEBUG_SERIAL.print(_addr, HEX);
#endif
#ifdef ARDUINO_ARCH_MBED
_wire->write(0); // forces a write request instead of a read
#endif
if (_wire->endTransmission() == 0) {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("Detected"));
DEBUG_SERIAL.println(F(" Detected"));
#endif
return true;
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("Not detected"));
DEBUG_SERIAL.println(F(" Not detected"));
#endif
return false;
}
@ -106,7 +115,7 @@ bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop,
_wire->beginTransmission(_addr);
// Write the prefix data (usually an address)
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
if (_wire->write(prefix_buffer, prefix_len) != prefix_len) {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
@ -128,7 +137,7 @@ bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop,
DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x"));
DEBUG_SERIAL.print(_addr, HEX);
DEBUG_SERIAL.print(F(" :: "));
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
for (uint16_t i = 0; i < prefix_len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(prefix_buffer[i], HEX);
@ -187,6 +196,8 @@ bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) {
bool Adafruit_I2CDevice::_read(uint8_t *buffer, size_t len, bool stop) {
#if defined(TinyWireM_h)
size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len);
#elif defined(ARDUINO_ARCH_MEGAAVR)
size_t recv = _wire->requestFrom(_addr, len, stop);
#else
size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop);
#endif
@ -257,9 +268,51 @@ uint8_t Adafruit_I2CDevice::address(void) { return _addr; }
* Not necessarily that the speed was achieved!
*/
bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) {
#if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && !defined(TinyWireM_h)
#if defined(__AVR_ATmega328__) || \
defined(__AVR_ATmega328P__) // fix arduino core set clock
// calculate TWBR correctly
if ((F_CPU / 18) < desiredclk) {
#ifdef DEBUG_SERIAL
Serial.println(F("I2C.setSpeed too high."));
#endif
return false;
}
uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2;
if (atwbr > 16320) {
#ifdef DEBUG_SERIAL
Serial.println(F("I2C.setSpeed too low."));
#endif
return false;
}
if (atwbr <= 255) {
atwbr /= 1;
TWSR = 0x0;
} else if (atwbr <= 1020) {
atwbr /= 4;
TWSR = 0x1;
} else if (atwbr <= 4080) {
atwbr /= 16;
TWSR = 0x2;
} else { // if (atwbr <= 16320)
atwbr /= 64;
TWSR = 0x3;
}
TWBR = atwbr;
#ifdef DEBUG_SERIAL
Serial.print(F("TWSR prescaler = "));
Serial.println(pow(4, TWSR));
Serial.print(F("TWBR = "));
Serial.println(atwbr);
#endif
return true;
#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \
!defined(TinyWireM_h)
_wire->setClock(desiredclk);
return true;
#else
(void)desiredclk;
return false;

View file

@ -15,7 +15,7 @@ public:
bool read(uint8_t *buffer, size_t len, bool stop = true);
bool write(const uint8_t *buffer, size_t len, bool stop = true,
const uint8_t *prefix_buffer = NULL, size_t prefix_len = 0);
const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
bool write_then_read(const uint8_t *write_buffer, size_t write_len,
uint8_t *read_buffer, size_t read_len,
bool stop = false);

View file

@ -1,9 +1,6 @@
#include "Adafruit_SPIDevice.h"
#if !defined(SPI_INTERFACES_COUNT) || \
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
//#define DEBUG_SERIAL Serial
// #define DEBUG_SERIAL Serial
/*!
* @brief Create an SPI device with the given CS pin and settings
@ -17,6 +14,7 @@
Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq,
BusIOBitOrder dataOrder,
uint8_t dataMode, SPIClass *theSPI) {
#ifdef BUSIO_HAS_HW_SPI
_cs = cspin;
_sck = _mosi = _miso = -1;
_spi = theSPI;
@ -25,6 +23,14 @@ Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq,
_freq = freq;
_dataOrder = dataOrder;
_dataMode = dataMode;
#else
// unused, but needed to suppress compiler warns
(void)cspin;
(void)freq;
(void)dataOrder;
(void)dataMode;
(void)theSPI;
#endif
}
/*!
@ -68,18 +74,14 @@ Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin,
_dataOrder = dataOrder;
_dataMode = dataMode;
_begun = false;
_spiSetting = new SPISettings(freq, dataOrder, dataMode);
_spi = NULL;
}
/*!
* @brief Release memory allocated in constructors
*/
Adafruit_SPIDevice::~Adafruit_SPIDevice() {
if (_spiSetting) {
if (_spiSetting)
delete _spiSetting;
_spiSetting = nullptr;
}
}
/*!
@ -94,7 +96,9 @@ bool Adafruit_SPIDevice::begin(void) {
}
if (_spi) { // hardware SPI
#ifdef BUSIO_HAS_HW_SPI
_spi->begin();
#endif
} else {
pinMode(_sck, OUTPUT);
@ -119,16 +123,19 @@ bool Adafruit_SPIDevice::begin(void) {
}
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @brief Transfer (send/receive) a buffer over hard/soft SPI, without
* transaction management
* @param buffer The buffer to send and receive at the same time
* @param len The number of bytes to transfer
*/
void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
//
// HARDWARE SPI
//
if (_spi) {
// hardware SPI is easy
#ifdef BUSIO_HAS_HW_SPI
#if defined(SPARK)
_spi->transfer(buffer, buffer, len, NULL);
_spi->transfer(buffer, buffer, len, nullptr);
#elif defined(STM32)
for (size_t i = 0; i < len; i++) {
_spi->transfer(buffer[i]);
@ -137,8 +144,12 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
_spi->transfer(buffer, len);
#endif
return;
#endif
}
//
// SOFTWARE SPI
//
uint8_t startbit;
if (_dataOrder == SPI_BITORDER_LSBFIRST) {
startbit = 0x1;
@ -149,9 +160,7 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
bool towrite, lastmosi = !(buffer[0] & startbit);
uint8_t bitdelay_us = (1000000 / _freq) / 2;
// for softSPI we'll do it by hand
for (size_t i = 0; i < len; i++) {
// software SPI
uint8_t reply = 0;
uint8_t send = buffer[i];
@ -174,9 +183,9 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
if ((_mosi != -1) && (lastmosi != towrite)) {
#ifdef BUSIO_USE_FAST_PINIO
if (towrite)
*mosiPort |= mosiPinMask;
*mosiPort = *mosiPort | mosiPinMask;
else
*mosiPort &= ~mosiPinMask;
*mosiPort = *mosiPort & ~mosiPinMask;
#else
digitalWrite(_mosi, towrite);
#endif
@ -184,7 +193,7 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
}
#ifdef BUSIO_USE_FAST_PINIO
*clkPort |= clkPinMask; // Clock high
*clkPort = *clkPort | clkPinMask; // Clock high
#else
digitalWrite(_sck, HIGH);
#endif
@ -204,14 +213,14 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
}
#ifdef BUSIO_USE_FAST_PINIO
*clkPort &= ~clkPinMask; // Clock low
*clkPort = *clkPort & ~clkPinMask; // Clock low
#else
digitalWrite(_sck, LOW);
#endif
} else { // if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3)
#ifdef BUSIO_USE_FAST_PINIO
*clkPort |= clkPinMask; // Clock high
*clkPort = *clkPort | clkPinMask; // Clock high
#else
digitalWrite(_sck, HIGH);
#endif
@ -223,16 +232,16 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
if (_mosi != -1) {
#ifdef BUSIO_USE_FAST_PINIO
if (send & b)
*mosiPort |= mosiPinMask;
*mosiPort = *mosiPort | mosiPinMask;
else
*mosiPort &= ~mosiPinMask;
*mosiPort = *mosiPort & ~mosiPinMask;
#else
digitalWrite(_mosi, send & b);
#endif
}
#ifdef BUSIO_USE_FAST_PINIO
*clkPort &= ~clkPinMask; // Clock low
*clkPort = *clkPort & ~clkPinMask; // Clock low
#else
digitalWrite(_sck, LOW);
#endif
@ -256,7 +265,8 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
}
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @brief Transfer (send/receive) one byte over hard/soft SPI, without
* transaction management
* @param send The byte to send
* @return The byte received while transmitting
*/
@ -272,7 +282,9 @@ uint8_t Adafruit_SPIDevice::transfer(uint8_t send) {
*/
void Adafruit_SPIDevice::beginTransaction(void) {
if (_spi) {
#ifdef BUSIO_HAS_HW_SPI
_spi->beginTransaction(*_spiSetting);
#endif
}
}
@ -281,12 +293,45 @@ void Adafruit_SPIDevice::beginTransaction(void) {
*/
void Adafruit_SPIDevice::endTransaction(void) {
if (_spi) {
#ifdef BUSIO_HAS_HW_SPI
_spi->endTransaction();
#endif
}
}
/*!
* @brief Write a buffer or two to the SPI device.
* @brief Assert/Deassert the CS pin if it is defined
* @param value The state the CS is set to
*/
void Adafruit_SPIDevice::setChipSelect(int value) {
if (_cs != -1) {
digitalWrite(_cs, value);
}
}
/*!
* @brief Write a buffer or two to the SPI device, with transaction
* management.
* @brief Manually begin a transaction (calls beginTransaction if hardware
* SPI) with asserting the CS pin
*/
void Adafruit_SPIDevice::beginTransactionWithAssertingCS() {
beginTransaction();
setChipSelect(LOW);
}
/*!
* @brief Manually end a transaction (calls endTransaction if hardware SPI)
* with deasserting the CS pin
*/
void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
setChipSelect(HIGH);
endTransaction();
}
/*!
* @brief Write a buffer or two to the SPI device, with transaction
* management.
* @param buffer Pointer to buffer of data to write
* @param len Number of bytes from buffer to write
* @param prefix_buffer Pointer to optional array of data to write before
@ -295,21 +340,19 @@ void Adafruit_SPIDevice::endTransaction(void) {
* @return Always returns true because there's no way to test success of SPI
* writes
*/
bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len,
uint8_t *prefix_buffer, size_t prefix_len) {
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len,
const uint8_t *prefix_buffer,
size_t prefix_len) {
beginTransactionWithAssertingCS();
setChipSelect(LOW);
// do the writing
#if defined(ARDUINO_ARCH_ESP32)
if (_spi) {
if (prefix_len > 0) {
_spi->transferBytes(prefix_buffer, nullptr, prefix_len);
_spi->transferBytes((uint8_t *)prefix_buffer, nullptr, prefix_len);
}
if (len > 0) {
_spi->transferBytes(buffer, nullptr, len);
_spi->transferBytes((uint8_t *)buffer, nullptr, len);
}
} else
#endif
@ -321,15 +364,11 @@ bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len,
transfer(buffer[i]);
}
}
setChipSelect(HIGH);
if (_spi) {
_spi->endTransaction();
}
endTransactionWithDeassertingCS();
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
for (uint16_t i = 0; i < prefix_len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(prefix_buffer[i], HEX);
@ -351,7 +390,8 @@ bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len,
}
/*!
* @brief Read from SPI into a buffer from the SPI device.
* @brief Read from SPI into a buffer from the SPI device, with transaction
* management.
* @param buffer Pointer to buffer of data to read into
* @param len Number of bytes from buffer to read.
* @param sendvalue The 8-bits of data to write when doing the data read,
@ -361,17 +401,10 @@ bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len,
*/
bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
memset(buffer, sendvalue, len); // clear out existing buffer
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
setChipSelect(LOW);
beginTransactionWithAssertingCS();
transfer(buffer, len);
setChipSelect(HIGH);
if (_spi) {
_spi->endTransaction();
}
endTransactionWithDeassertingCS();
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
@ -390,9 +423,9 @@ bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
}
/*!
* @brief Write some data, then read some data from SPI into another buffer.
* The buffers can point to same/overlapping locations. This does not
* transmit-receive at the same time!
* @brief Write some data, then read some data from SPI into another buffer,
* with transaction management. The buffers can point to same/overlapping
* locations. This does not transmit-receive at the same time!
* @param write_buffer Pointer to buffer of data to write from
* @param write_len Number of bytes from buffer to write.
* @param read_buffer Pointer to buffer of data to read into.
@ -402,19 +435,15 @@ bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
* @return Always returns true because there's no way to test success of SPI
* writes
*/
bool Adafruit_SPIDevice::write_then_read(uint8_t *write_buffer,
bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer,
size_t write_len, uint8_t *read_buffer,
size_t read_len, uint8_t sendvalue) {
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
setChipSelect(LOW);
beginTransactionWithAssertingCS();
// do the writing
#if defined(ARDUINO_ARCH_ESP32)
if (_spi) {
if (write_len > 0) {
_spi->transferBytes(write_buffer, nullptr, write_len);
_spi->transferBytes((uint8_t *)write_buffer, nullptr, write_len);
}
} else
#endif
@ -455,45 +484,25 @@ bool Adafruit_SPIDevice::write_then_read(uint8_t *write_buffer,
DEBUG_SERIAL.println();
#endif
setChipSelect(HIGH);
if (_spi) {
_spi->endTransaction();
}
endTransactionWithDeassertingCS();
return true;
}
/*!
* @brief Write some data and read some data at the same time from SPI
* into the same buffer. This is basicaly a wrapper for transfer() with
* CS-pin and transaction management.
* This /does/ transmit-receive at the same time!
* into the same buffer, with transaction management. This is basicaly a wrapper
* for transfer() with CS-pin and transaction management. This /does/
* transmit-receive at the same time!
* @param buffer Pointer to buffer of data to write/read to/from
* @param len Number of bytes from buffer to write/read.
* @return Always returns true because there's no way to test success of SPI
* writes
*/
bool Adafruit_SPIDevice::write_and_read(uint8_t *buffer, size_t len) {
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
setChipSelect(LOW);
beginTransactionWithAssertingCS();
transfer(buffer, len);
setChipSelect(HIGH);
if (_spi) {
_spi->endTransaction();
}
endTransactionWithDeassertingCS();
return true;
}
void Adafruit_SPIDevice::setChipSelect(int value) {
if (_cs == -1)
return;
digitalWrite(_cs, value);
}
#endif // SPI exists

View file

@ -5,8 +5,14 @@
#if !defined(SPI_INTERFACES_COUNT) || \
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
// HW SPI available
#include <SPI.h>
#define BUSIO_HAS_HW_SPI
#else
// SW SPI ONLY
enum { SPI_MODE0, SPI_MODE1, SPI_MODE2, _SPI_MODE4 };
typedef uint8_t SPIClass;
#endif
// some modern SPI definitions don't have BitOrder enum
#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \
@ -16,7 +22,8 @@
defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \
defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \
defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \
defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32)
defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32) || \
defined(ARDUINO_ARCH_XMC)
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = MSBFIRST,
@ -39,7 +46,27 @@ typedef enum _BitOrder {
typedef BitOrder BusIOBitOrder;
#endif
#if defined(__AVR__) || defined(TEENSYDUINO)
#if defined(__IMXRT1062__) // Teensy 4.x
// *Warning* I disabled the usage of FAST_PINIO as the set/clear operations
// used in the cpp file are not atomic and can effect multiple IO pins
// and if an interrupt happens in between the time the code reads the register
// and writes out the updated value, that changes one or more other IO pins
// on that same IO port, those change will be clobbered when the updated
// values are written back. A fast version can be implemented that uses the
// ports set and clear registers which are atomic.
// typedef volatile uint32_t BusIO_PortReg;
// typedef uint32_t BusIO_PortMask;
// #define BUSIO_USE_FAST_PINIO
#elif defined(__MBED__) || defined(__ZEPHYR__)
// Boards based on RTOS cores like mbed or Zephyr are not going to expose the
// low level registers needed for fast pin manipulation
#undef BUSIO_USE_FAST_PINIO
#elif defined(ARDUINO_ARCH_XMC)
#undef BUSIO_USE_FAST_PINIO
#elif defined(__AVR__) || defined(TEENSYDUINO)
typedef volatile uint8_t BusIO_PortReg;
typedef uint8_t BusIO_PortMask;
#define BUSIO_USE_FAST_PINIO
@ -51,7 +78,9 @@ typedef uint32_t BusIO_PortMask;
#define BUSIO_USE_FAST_PINIO
#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \
!defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_RP2040)
!defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_SILABS) && \
!defined(ARDUINO_UNOR4_MINIMA) && !defined(ARDUINO_UNOR4_WIFI) && \
!defined(PORTDUINO)
typedef volatile uint32_t BusIO_PortReg;
typedef uint32_t BusIO_PortMask;
#if !defined(__ASR6501__) && !defined(__ASR6502__)
@ -65,10 +94,15 @@ typedef uint32_t BusIO_PortMask;
/**! The class which defines how we will talk to this device over SPI **/
class Adafruit_SPIDevice {
public:
#ifdef BUSIO_HAS_HW_SPI
Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = &SPI);
#else
Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = nullptr);
#endif
Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi,
uint32_t freq = 1000000,
BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
@ -77,9 +111,9 @@ public:
bool begin(void);
bool read(uint8_t *buffer, size_t len, uint8_t sendvalue = 0xFF);
bool write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer = NULL,
size_t prefix_len = 0);
bool write_then_read(uint8_t *write_buffer, size_t write_len,
bool write(const uint8_t *buffer, size_t len,
const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
bool write_then_read(const uint8_t *write_buffer, size_t write_len,
uint8_t *read_buffer, size_t read_len,
uint8_t sendvalue = 0xFF);
bool write_and_read(uint8_t *buffer, size_t len);
@ -88,10 +122,17 @@ public:
void transfer(uint8_t *buffer, size_t len);
void beginTransaction(void);
void endTransaction(void);
void beginTransactionWithAssertingCS();
void endTransactionWithDeassertingCS();
private:
SPIClass *_spi;
SPISettings *_spiSetting;
#ifdef BUSIO_HAS_HW_SPI
SPIClass *_spi = nullptr;
SPISettings *_spiSetting = nullptr;
#else
uint8_t *_spi = nullptr;
uint8_t *_spiSetting = nullptr;
#endif
uint32_t _freq;
BusIOBitOrder _dataOrder;
uint8_t _dataMode;
@ -105,5 +146,4 @@ private:
bool _begun;
};
#endif // has SPI defined
#endif // Adafruit_SPIDevice_h

View file

@ -4,8 +4,8 @@
cmake_minimum_required(VERSION 3.5)
idf_component_register(SRCS "Adafruit_I2CDevice.cpp" "Adafruit_BusIO_Register.cpp" "Adafruit_SPIDevice.cpp"
idf_component_register(SRCS "Adafruit_I2CDevice.cpp" "Adafruit_BusIO_Register.cpp" "Adafruit_SPIDevice.cpp" "Adafruit_GenericDevice.cpp"
INCLUDE_DIRS "."
REQUIRES arduino)
REQUIRES arduino-esp32)
project(Adafruit_BusIO)

View file

@ -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!

View file

@ -0,0 +1,219 @@
/*
Advanced example of using bstracted transport for reading and writing
register data from a UART-based device such as a TMC2209
Written with help by Claude!
https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time
chats are not shareable :(
*/
#include "Adafruit_BusIO_Register.h"
#include "Adafruit_GenericDevice.h"
// Debugging macros
#define DEBUG_SERIAL Serial
#ifdef DEBUG_SERIAL
#define DEBUG_PRINT(x) DEBUG_SERIAL.print(x)
#define DEBUG_PRINTLN(x) DEBUG_SERIAL.println(x)
#define DEBUG_PRINT_HEX(x) \
do { \
if (x < 0x10) \
DEBUG_SERIAL.print('0'); \
DEBUG_SERIAL.print(x, HEX); \
DEBUG_SERIAL.print(' '); \
} while (0)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINT_HEX(x)
#endif
#define TMC2209_IOIN 0x06
class TMC2209_UART {
private:
Stream *_uart_stream;
uint8_t _addr;
static bool uart_read(void *thiz, uint8_t *buffer, size_t len) {
TMC2209_UART *dev = (TMC2209_UART *)thiz;
uint16_t timeout = 100;
while (dev->_uart_stream->available() < len && timeout--) {
delay(1);
}
if (timeout == 0) {
DEBUG_PRINTLN("Read timeout!");
return false;
}
DEBUG_PRINT("Reading: ");
for (size_t i = 0; i < len; i++) {
buffer[i] = dev->_uart_stream->read();
DEBUG_PRINT_HEX(buffer[i]);
}
DEBUG_PRINTLN("");
return true;
}
static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) {
TMC2209_UART *dev = (TMC2209_UART *)thiz;
DEBUG_PRINT("Writing: ");
for (size_t i = 0; i < len; i++) {
DEBUG_PRINT_HEX(buffer[i]);
}
DEBUG_PRINTLN("");
dev->_uart_stream->write(buffer, len);
return true;
}
static bool uart_readreg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz,
uint8_t *data, uint16_t datalen) {
TMC2209_UART *dev = (TMC2209_UART *)thiz;
while (dev->_uart_stream->available())
dev->_uart_stream->read();
uint8_t packet[4] = {0x05, uint8_t(dev->_addr << 1), addr_buf[0], 0x00};
packet[3] = calcCRC(packet, 3);
if (!uart_write(thiz, packet, 4))
return false;
// Read back echo
uint8_t echo[4];
if (!uart_read(thiz, echo, 4))
return false;
// Verify echo
for (uint8_t i = 0; i < 4; i++) {
if (echo[i] != packet[i]) {
DEBUG_PRINTLN("Echo mismatch");
return false;
}
}
uint8_t response[8]; // sync + 0xFF + reg + 4 data bytes + CRC
if (!uart_read(thiz, response, 8))
return false;
// Verify response
if (response[0] != 0x05) {
DEBUG_PRINTLN("Invalid sync byte");
return false;
}
if (response[1] != 0xFF) {
DEBUG_PRINTLN("Invalid reply address");
return false;
}
if (response[2] != addr_buf[0]) {
DEBUG_PRINTLN("Register mismatch");
return false;
}
uint8_t crc = calcCRC(response, 7);
if (crc != response[7]) {
DEBUG_PRINTLN("CRC mismatch");
return false;
}
memcpy(data, &response[3], 4);
return true;
}
static bool uart_writereg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz,
const uint8_t *data, uint16_t datalen) {
TMC2209_UART *dev = (TMC2209_UART *)thiz;
while (dev->_uart_stream->available())
dev->_uart_stream->read();
uint8_t packet[8] = {0x05,
uint8_t(dev->_addr << 1),
uint8_t(addr_buf[0] | 0x80),
data[0],
data[1],
data[2],
data[3],
0x00};
packet[7] = calcCRC(packet, 7);
if (!uart_write(thiz, packet, 8))
return false;
uint8_t echo[8];
if (!uart_read(thiz, echo, 8))
return false;
for (uint8_t i = 0; i < 8; i++) {
if (echo[i] != packet[i]) {
DEBUG_PRINTLN("Write echo mismatch");
return false;
}
}
return true;
}
static uint8_t calcCRC(uint8_t *data, uint8_t length) {
uint8_t crc = 0;
for (uint8_t i = 0; i < length; i++) {
uint8_t currentByte = data[i];
for (uint8_t j = 0; j < 8; j++) {
if ((crc >> 7) ^ (currentByte & 0x01)) {
crc = (crc << 1) ^ 0x07;
} else {
crc = crc << 1;
}
currentByte = currentByte >> 1;
}
}
return crc;
}
public:
TMC2209_UART(Stream *serial, uint8_t addr)
: _uart_stream(serial), _addr(addr) {}
Adafruit_GenericDevice *createDevice() {
return new Adafruit_GenericDevice(this, uart_read, uart_write, uart_readreg,
uart_writereg);
}
};
void setup() {
Serial.begin(115200);
while (!Serial)
;
delay(100);
Serial.println("TMC2209 Generic Device register read/write test!");
Serial1.begin(115200);
TMC2209_UART uart(&Serial1, 0);
Adafruit_GenericDevice *device = uart.createDevice();
device->begin();
// Create register object for IOIN
Adafruit_BusIO_Register ioin_reg(device,
TMC2209_IOIN, // device and register address
4, // width = 4 bytes
MSBFIRST, // byte order
1); // address width = 1 byte
Serial.print("IOIN = 0x");
Serial.println(ioin_reg.read(), HEX);
// Create RegisterBits for VERSION field (bits 31:24)
Adafruit_BusIO_RegisterBits version_bits(
&ioin_reg, 8, 24); // 8 bits wide, starting at bit 24
Serial.println("Reading VERSION...");
uint8_t version = version_bits.read();
Serial.print("VERSION = 0x");
Serial.println(version, HEX);
}
void loop() { delay(1000); }

View file

@ -0,0 +1,98 @@
/*
Abstracted transport for reading and writing data from a UART-based
device such as a TMC2209
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"
/**
* Basic UART device class that demonstrates using GenericDevice with a Stream
* interface. This example shows how to wrap a Stream (like HardwareSerial or
* SoftwareSerial) with read/write callbacks that can be used by BusIO's
* register functions.
*/
class UARTDevice {
public:
UARTDevice(Stream *serial) : _serial(serial) {}
// Static callback for writing data to UART
// Called by GenericDevice when data needs to be sent
static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) {
UARTDevice *dev = (UARTDevice *)thiz;
dev->_serial->write(buffer, len);
return true;
}
// Static callback for reading data from UART
// Includes timeout and will return false if not enough data available
static bool uart_read(void *thiz, uint8_t *buffer, size_t len) {
UARTDevice *dev = (UARTDevice *)thiz;
uint16_t timeout = 100;
while (dev->_serial->available() < len && timeout--) {
delay(1);
}
if (timeout == 0) {
return false;
}
for (size_t i = 0; i < len; i++) {
buffer[i] = dev->_serial->read();
}
return true;
}
// Create a GenericDevice instance using our callbacks
Adafruit_GenericDevice *createDevice() {
return new Adafruit_GenericDevice(this, uart_read, uart_write);
}
private:
Stream *_serial; // Underlying Stream instance (HardwareSerial, etc)
};
void setup() {
Serial.begin(115200);
while (!Serial)
;
delay(100);
Serial.println("Generic Device test!");
// Initialize UART for device communication
Serial1.begin(115200);
// Create UART wrapper and BusIO device
UARTDevice uart(&Serial1);
Adafruit_GenericDevice *device = uart.createDevice();
device->begin();
// Test write/read cycle
uint8_t write_buf[4] = {0x5, 0x0, 0x0, 0x48};
uint8_t read_buf[8];
Serial.println("Writing data...");
if (!device->write(write_buf, 4)) {
Serial.println("Write failed!");
return;
}
Serial.println("Reading response...");
if (!device->read(read_buf, 8)) {
Serial.println("Read failed!");
return;
}
// Print response bytes
Serial.print("Got response: ");
for (int i = 0; i < 8; i++) {
Serial.print("0x");
Serial.print(read_buf[i], HEX);
Serial.print(" ");
}
Serial.println();
}
void loop() { delay(1000); }

View file

@ -3,19 +3,20 @@
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(0x10);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("I2C address detection test");
if (!i2c_dev.begin()) {
Serial.print("Did not find device at 0x");
Serial.println(i2c_dev.address(), HEX);
while (1);
while (1)
;
}
Serial.print("Device found on address 0x");
Serial.println(i2c_dev.address(), HEX);
}
void loop() {
}
void loop() {}

View file

@ -3,16 +3,18 @@
#define I2C_ADDRESS 0x60
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("I2C device read and write test");
if (!i2c_dev.begin()) {
Serial.print("Did not find device at 0x");
Serial.println(i2c_dev.address(), HEX);
while (1);
while (1)
;
}
Serial.print("Device found on address 0x");
Serial.println(i2c_dev.address(), HEX);
@ -21,21 +23,23 @@ void setup() {
// Try to read 32 bytes
i2c_dev.read(buffer, 32);
Serial.print("Read: ");
for (uint8_t i=0; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
for (uint8_t i = 0; i < 32; i++) {
Serial.print("0x");
Serial.print(buffer[i], HEX);
Serial.print(", ");
}
Serial.println();
// read a register by writing first, then reading
buffer[0] = 0x0C; // we'll reuse the same buffer
buffer[0] = 0x0C; // we'll reuse the same buffer
i2c_dev.write_then_read(buffer, 1, buffer, 2, false);
Serial.print("Write then Read: ");
for (uint8_t i=0; i<2; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
for (uint8_t i = 0; i < 2; i++) {
Serial.print("0x");
Serial.print(buffer[i], HEX);
Serial.print(", ");
}
Serial.println();
}
void loop() {
}
void loop() {}

View file

@ -1,38 +1,43 @@
#include <Adafruit_I2CDevice.h>
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h>
#define I2C_ADDRESS 0x60
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("I2C device register test");
if (!i2c_dev.begin()) {
Serial.print("Did not find device at 0x");
Serial.println(i2c_dev.address(), HEX);
while (1);
while (1)
;
}
Serial.print("Device found on address 0x");
Serial.println(i2c_dev.address(), HEX);
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&i2c_dev, 0x0C, 2, LSBFIRST);
Adafruit_BusIO_Register id_reg =
Adafruit_BusIO_Register(&i2c_dev, 0x0C, 2, LSBFIRST);
uint16_t id;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
Serial.print("ID register = 0x");
Serial.println(id, HEX);
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&i2c_dev, 0x01, 2, LSBFIRST);
Adafruit_BusIO_Register thresh_reg =
Adafruit_BusIO_Register(&i2c_dev, 0x01, 2, LSBFIRST);
uint16_t thresh;
thresh_reg.read(&thresh);
Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX);
Serial.print("Initial threshold register = 0x");
Serial.println(thresh, HEX);
thresh_reg.write(~thresh);
Serial.print("Post threshold register = 0x"); Serial.println(thresh_reg.read(), HEX);
Serial.print("Post threshold register = 0x");
Serial.println(thresh_reg.read(), HEX);
}
void loop() {
}
void loop() {}

View file

@ -9,7 +9,9 @@ Adafruit_SPIDevice *spi_dev = NULL; // new Adafruit_SPIDevice(SPIDEVICE_CS);
Adafruit_I2CDevice *i2c_dev = new Adafruit_I2CDevice(I2C_ADDRESS);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("I2C or SPI device register test");
@ -27,12 +29,12 @@ void setup() {
}
}
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F);
uint8_t id=0;
Adafruit_BusIO_Register id_reg =
Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F);
uint8_t id = 0;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
Serial.print("ID register = 0x");
Serial.println(id, HEX);
}
void loop() {
}
void loop() {}

View file

@ -1,28 +1,34 @@
#include <Adafruit_SPIDevice.h>
#define SPIDEVICE_CS 10
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
//Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 13, 12, 11, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
Adafruit_SPIDevice spi_dev =
Adafruit_SPIDevice(SPIDEVICE_CS, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 13, 12, 11,
// 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("SPI device mode test");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
while (1)
;
}
}
void loop() {
Serial.println("\n\nTransfer test");
for (uint16_t x=0; x<=0xFF; x++) {
uint8_t i = x;
Serial.print("0x"); Serial.print(i, HEX);
for (uint16_t x = 0; x <= 0xFF; x++) {
uint8_t i = x;
Serial.print("0x");
Serial.print(i, HEX);
spi_dev.read(&i, 1, i);
Serial.print("/"); Serial.print(i, HEX);
Serial.print("/");
Serial.print(i, HEX);
Serial.print(", ");
delay(25);
}

View file

@ -3,15 +3,17 @@
#define SPIDEVICE_CS 10
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("SPI device read and write test");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
while (1)
;
}
uint8_t buffer[32];
@ -19,21 +21,23 @@ void setup() {
// Try to read 32 bytes
spi_dev.read(buffer, 32);
Serial.print("Read: ");
for (uint8_t i=0; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
for (uint8_t i = 0; i < 32; i++) {
Serial.print("0x");
Serial.print(buffer[i], HEX);
Serial.print(", ");
}
Serial.println();
// read a register by writing first, then reading
buffer[0] = 0x8F; // we'll reuse the same buffer
buffer[0] = 0x8F; // we'll reuse the same buffer
spi_dev.write_then_read(buffer, 1, buffer, 2, false);
Serial.print("Write then Read: ");
for (uint8_t i=0; i<2; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
for (uint8_t i = 0; i < 2; i++) {
Serial.print("0x");
Serial.print(buffer[i], HEX);
Serial.print(", ");
}
Serial.println();
}
void loop() {
}
void loop() {}

View file

@ -1,163 +1,233 @@
/***************************************************
/***************************************************
This is an example for how to use Adafruit_BusIO_RegisterBits from Adafruit_BusIO library.
This is an example for how to use Adafruit_BusIO_RegisterBits from
Adafruit_BusIO library.
Designed specifically to work with the Adafruit RTD Sensor
----> https://www.adafruit.com/products/3328
uisng a MAX31865 RTD-to-Digital Converter
----> https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
This sensor uses SPI to communicate, 4 pins are required to
This sensor uses SPI to communicate, 4 pins are required to
interface.
A fifth pin helps to detect when a new conversion is ready.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Example written (2020/3) by Andreas Hardtung/AnHard.
Example written (2020/3) by Andreas Hardtung/AnHard.
BSD license, all text above must be included in any redistribution
****************************************************/
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_SPIDevice.h>
#define MAX31865_SPI_SPEED (5000000)
#define MAX31865_SPI_SPEED (5000000)
#define MAX31865_SPI_BITORDER (SPI_BITORDER_MSBFIRST)
#define MAX31865_SPI_MODE (SPI_MODE1)
#define MAX31865_SPI_MODE (SPI_MODE1)
#define MAX31865_SPI_CS (10)
#define MAX31865_READY_PIN (2)
#define MAX31865_SPI_CS (10)
#define MAX31865_READY_PIN (2)
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(
MAX31865_SPI_CS, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER,
MAX31865_SPI_MODE, &SPI); // Hardware SPI
// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, 13, 12, 11,
// MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE); // Software
// SPI
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE, &SPI); // Hardware SPI
// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, 13, 12, 11, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE); // Software SPI
// MAX31865 chip related
// *********************************************************************************************
Adafruit_BusIO_Register config_reg =
Adafruit_BusIO_Register(&spi_dev, 0x00, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
Adafruit_BusIO_RegisterBits bias_bit =
Adafruit_BusIO_RegisterBits(&config_reg, 1, 7);
Adafruit_BusIO_RegisterBits auto_bit =
Adafruit_BusIO_RegisterBits(&config_reg, 1, 6);
Adafruit_BusIO_RegisterBits oneS_bit =
Adafruit_BusIO_RegisterBits(&config_reg, 1, 5);
Adafruit_BusIO_RegisterBits wire_bit =
Adafruit_BusIO_RegisterBits(&config_reg, 1, 4);
Adafruit_BusIO_RegisterBits faultT_bits =
Adafruit_BusIO_RegisterBits(&config_reg, 2, 2);
Adafruit_BusIO_RegisterBits faultR_bit =
Adafruit_BusIO_RegisterBits(&config_reg, 1, 1);
Adafruit_BusIO_RegisterBits fi50hz_bit =
Adafruit_BusIO_RegisterBits(&config_reg, 1, 0);
// MAX31865 chip related *********************************************************************************************
Adafruit_BusIO_Register config_reg = Adafruit_BusIO_Register(&spi_dev, 0x00, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
Adafruit_BusIO_RegisterBits bias_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 7);
Adafruit_BusIO_RegisterBits auto_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 6);
Adafruit_BusIO_RegisterBits oneS_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 5);
Adafruit_BusIO_RegisterBits wire_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 4);
Adafruit_BusIO_RegisterBits faultT_bits = Adafruit_BusIO_RegisterBits(&config_reg, 2, 2);
Adafruit_BusIO_RegisterBits faultR_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 1);
Adafruit_BusIO_RegisterBits fi50hz_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 0);
Adafruit_BusIO_Register rRatio_reg =
Adafruit_BusIO_Register(&spi_dev, 0x01, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
Adafruit_BusIO_RegisterBits rRatio_bits =
Adafruit_BusIO_RegisterBits(&rRatio_reg, 15, 1);
Adafruit_BusIO_RegisterBits fault_bit =
Adafruit_BusIO_RegisterBits(&rRatio_reg, 1, 0);
Adafruit_BusIO_Register rRatio_reg = Adafruit_BusIO_Register(&spi_dev, 0x01, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
Adafruit_BusIO_RegisterBits rRatio_bits = Adafruit_BusIO_RegisterBits(&rRatio_reg, 15, 1);
Adafruit_BusIO_RegisterBits fault_bit = Adafruit_BusIO_RegisterBits(&rRatio_reg, 1, 0);
Adafruit_BusIO_Register maxRratio_reg =
Adafruit_BusIO_Register(&spi_dev, 0x03, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
Adafruit_BusIO_RegisterBits maxRratio_bits =
Adafruit_BusIO_RegisterBits(&maxRratio_reg, 15, 1);
Adafruit_BusIO_Register maxRratio_reg = Adafruit_BusIO_Register(&spi_dev, 0x03, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
Adafruit_BusIO_RegisterBits maxRratio_bits = Adafruit_BusIO_RegisterBits(&maxRratio_reg, 15, 1);
Adafruit_BusIO_Register minRratio_reg =
Adafruit_BusIO_Register(&spi_dev, 0x05, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
Adafruit_BusIO_RegisterBits minRratio_bits =
Adafruit_BusIO_RegisterBits(&minRratio_reg, 15, 1);
Adafruit_BusIO_Register minRratio_reg = Adafruit_BusIO_Register(&spi_dev, 0x05, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
Adafruit_BusIO_RegisterBits minRratio_bits = Adafruit_BusIO_RegisterBits(&minRratio_reg, 15, 1);
Adafruit_BusIO_Register fault_reg = Adafruit_BusIO_Register(&spi_dev, 0x07, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
Adafruit_BusIO_RegisterBits range_high_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 7);
Adafruit_BusIO_RegisterBits range_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 6);
Adafruit_BusIO_RegisterBits refin_high_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 5);
Adafruit_BusIO_RegisterBits refin_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 4);
Adafruit_BusIO_RegisterBits rtdin_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 3);
Adafruit_BusIO_RegisterBits voltage_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 2);
Adafruit_BusIO_Register fault_reg =
Adafruit_BusIO_Register(&spi_dev, 0x07, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
Adafruit_BusIO_RegisterBits range_high_fault_bit =
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 7);
Adafruit_BusIO_RegisterBits range_low_fault_bit =
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 6);
Adafruit_BusIO_RegisterBits refin_high_fault_bit =
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 5);
Adafruit_BusIO_RegisterBits refin_low_fault_bit =
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 4);
Adafruit_BusIO_RegisterBits rtdin_low_fault_bit =
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 3);
Adafruit_BusIO_RegisterBits voltage_fault_bit =
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 2);
// Print the details of the configuration register.
void printConfig( void ) {
Serial.print("BIAS: "); if (bias_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
Serial.print(", AUTO: "); if (auto_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
Serial.print(", ONES: "); if (oneS_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
Serial.print(", WIRE: "); if (wire_bit.read() ) Serial.print("3"); else Serial.print("2/4");
Serial.print(", FAULTCLEAR: "); if (faultR_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
Serial.print(", "); if (fi50hz_bit.read() ) Serial.print("50HZ"); else Serial.print("60HZ");
void printConfig(void) {
Serial.print("BIAS: ");
if (bias_bit.read())
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(", AUTO: ");
if (auto_bit.read())
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(", ONES: ");
if (oneS_bit.read())
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(", WIRE: ");
if (wire_bit.read())
Serial.print("3");
else
Serial.print("2/4");
Serial.print(", FAULTCLEAR: ");
if (faultR_bit.read())
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(", ");
if (fi50hz_bit.read())
Serial.print("50HZ");
else
Serial.print("60HZ");
Serial.println();
}
// Check and print faults. Then clear them.
void checkFaults( void ) {
void checkFaults(void) {
if (fault_bit.read()) {
Serial.print("MAX: "); Serial.println(maxRratio_bits.read());
Serial.print("VAL: "); Serial.println( rRatio_bits.read());
Serial.print("MIN: "); Serial.println(minRratio_bits.read());
Serial.print("MAX: ");
Serial.println(maxRratio_bits.read());
Serial.print("VAL: ");
Serial.println(rRatio_bits.read());
Serial.print("MIN: ");
Serial.println(minRratio_bits.read());
if (range_high_fault_bit.read() ) Serial.println("Range high fault");
if ( range_low_fault_bit.read() ) Serial.println("Range low fault");
if (refin_high_fault_bit.read() ) Serial.println("REFIN high fault");
if ( refin_low_fault_bit.read() ) Serial.println("REFIN low fault");
if ( rtdin_low_fault_bit.read() ) Serial.println("RTDIN low fault");
if ( voltage_fault_bit.read() ) Serial.println("Voltage fault");
if (range_high_fault_bit.read())
Serial.println("Range high fault");
if (range_low_fault_bit.read())
Serial.println("Range low fault");
if (refin_high_fault_bit.read())
Serial.println("REFIN high fault");
if (refin_low_fault_bit.read())
Serial.println("REFIN low fault");
if (rtdin_low_fault_bit.read())
Serial.println("RTDIN low fault");
if (voltage_fault_bit.read())
Serial.println("Voltage fault");
faultR_bit.write(1); // clear fault
}
}
void setup() {
#if (MAX31865_1_READY_PIN != -1)
pinMode(MAX31865_READY_PIN ,INPUT_PULLUP);
#endif
#if (MAX31865_1_READY_PIN != -1)
pinMode(MAX31865_READY_PIN, INPUT_PULLUP);
#endif
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("SPI Adafruit_BusIO_RegisterBits test on MAX31865");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
while (1)
;
}
// Set up for automode 50Hz. We don't care about selfheating. We want the highest possible sampling rate.
// Set up for automode 50Hz. We don't care about selfheating. We want the
// highest possible sampling rate.
auto_bit.write(0); // Don't switch filtermode while auto_mode is on.
fi50hz_bit.write(1); // Set filter to 50Hz mode.
faultR_bit.write(1); // Clear faults.
bias_bit.write(1); // In automode we want to have the bias current always on.
delay(5); // Wait until bias current settles down.
// 10.5 time constants of the input RC network is required.
// 10ms worst case for 10kω reference resistor and a 0.1µF capacitor across the RTD inputs.
// Adafruit Module has 0.1µF and only 430/4300ω So here 0.43/4.3ms
auto_bit.write(1); // Now we can set automode. Automatically starting first conversion.
bias_bit.write(1); // In automode we want to have the bias current always on.
delay(5); // Wait until bias current settles down.
// 10.5 time constants of the input RC network is required.
// 10ms worst case for 10kω reference resistor and a 0.1µF capacitor
// across the RTD inputs. Adafruit Module has 0.1µF and only
// 430/4300ω So here 0.43/4.3ms
auto_bit.write(
1); // Now we can set automode. Automatically starting first conversion.
// Test the READY_PIN
#if (defined( MAX31865_READY_PIN ) && (MAX31865_READY_PIN != -1))
int i = 0;
while (digitalRead(MAX31865_READY_PIN) && i++ <= 100) { delay(1); }
if (i >= 100) {
Serial.print("ERROR: Max31865 Pin detection does not work. PIN:");
Serial.println(MAX31865_READY_PIN);
}
#else
delay(100);
#endif
// Test the READY_PIN
#if (defined(MAX31865_READY_PIN) && (MAX31865_READY_PIN != -1))
int i = 0;
while (digitalRead(MAX31865_READY_PIN) && i++ <= 100) {
delay(1);
}
if (i >= 100) {
Serial.print("ERROR: Max31865 Pin detection does not work. PIN:");
Serial.println(MAX31865_READY_PIN);
}
#else
delay(100);
#endif
// Set ratio range.
// Setting the temperatures would need some more calculation - not related to Adafruit_BusIO_RegisterBits.
// Setting the temperatures would need some more calculation - not related to
// Adafruit_BusIO_RegisterBits.
uint16_t ratio = rRatio_bits.read();
maxRratio_bits.write( (ratio < 0x8fffu-1000u) ? ratio + 1000u : 0x8fffu );
minRratio_bits.write( (ratio > 1000u) ? ratio - 1000u : 0u );
maxRratio_bits.write((ratio < 0x8fffu - 1000u) ? ratio + 1000u : 0x8fffu);
minRratio_bits.write((ratio > 1000u) ? ratio - 1000u : 0u);
printConfig();
checkFaults();
}
void loop() {
#if (defined( MAX31865_READY_PIN ) && (MAX31865_1_READY_PIN != -1))
// Is conversion ready?
if (!digitalRead(MAX31865_READY_PIN))
#else
// Warant conversion is ready.
delay(21); // 21ms for 50Hz-mode. 19ms in 60Hz-mode.
#endif
{
// Read ratio, calculate temperature, scale, filter and print.
Serial.println( rRatio2C( rRatio_bits.read() ) * 100.0f, 0); // Temperature scaled by 100
// Check, print, clear faults.
checkFaults();
}
#if (defined(MAX31865_READY_PIN) && (MAX31865_1_READY_PIN != -1))
// Is conversion ready?
if (!digitalRead(MAX31865_READY_PIN))
#else
// Warant conversion is ready.
delay(21); // 21ms for 50Hz-mode. 19ms in 60Hz-mode.
#endif
{
// Read ratio, calculate temperature, scale, filter and print.
Serial.println(rRatio2C(rRatio_bits.read()) * 100.0f,
0); // Temperature scaled by 100
// Check, print, clear faults.
checkFaults();
}
// Do something else.
//delay(15000);
// delay(15000);
}
// Module/Sensor related. Here Adafruit PT100 module with a 2_Wire PT100 Class C *****************************
// Module/Sensor related. Here Adafruit PT100 module with a 2_Wire PT100 Class C
// *****************************
float rRatio2C(uint16_t ratio) {
// A simple linear conversion.
const float R0 = 100.0f;
@ -165,28 +235,34 @@ float rRatio2C(uint16_t ratio) {
const float alphaPT = 0.003850f;
const float ADCmax = (1u << 15) - 1.0f;
const float rscale = Rref / ADCmax;
// Measured temperature in boiling water 101.08°C with factor a = 1 and b = 0. Rref and MAX at about 22±2°C.
// Measured temperature in ice/water bath 0.76°C with factor a = 1 and b = 0. Rref and MAX at about 22±2°C.
//const float a = 1.0f / (alphaPT * R0);
const float a = (100.0f/101.08f) / (alphaPT * R0);
//const float b = 0.0f; // 101.08
const float b = -0.76f; // 100.32 > 101.08
// Measured temperature in boiling water 101.08°C with factor a = 1 and b = 0.
// Rref and MAX at about 22±2°C. Measured temperature in ice/water bath 0.76°C
// with factor a = 1 and b = 0. Rref and MAX at about 22±2°C.
// const float a = 1.0f / (alphaPT * R0);
const float a = (100.0f / 101.08f) / (alphaPT * R0);
// const float b = 0.0f; // 101.08
const float b = -0.76f; // 100.32 > 101.08
return filterRing( ((ratio * rscale) - R0) * a + b );
return filterRing(((ratio * rscale) - R0) * a + b);
}
// General purpose *********************************************************************************************
// General purpose
// *********************************************************************************************
#define RINGLENGTH 250
float filterRing( float newVal ) {
static float ring[RINGLENGTH] = { 0.0 };
float filterRing(float newVal) {
static float ring[RINGLENGTH] = {0.0};
static uint8_t ringIndex = 0;
static bool ringFull = false;
if ( ringIndex == RINGLENGTH ) { ringFull = true; ringIndex = 0; }
if (ringIndex == RINGLENGTH) {
ringFull = true;
ringIndex = 0;
}
ring[ringIndex] = newVal;
uint8_t loopEnd = (ringFull) ? RINGLENGTH : ringIndex + 1;
float ringSum = 0.0f;
for (uint8_t i = 0; i < loopEnd; i++) ringSum += ring[i];
for (uint8_t i = 0; i < loopEnd; i++)
ringSum += ring[i];
ringIndex++;
return ringSum / loopEnd;
}

View file

@ -5,30 +5,36 @@
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS);
void setup() {
while (!Serial) { delay(10); }
while (!Serial) {
delay(10);
}
Serial.begin(115200);
Serial.println("SPI device register test");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
while (1)
;
}
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD);
Adafruit_BusIO_Register id_reg =
Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD);
uint8_t id = 0;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
Serial.print("ID register = 0x");
Serial.println(id, HEX);
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST);
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(
&spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST);
uint16_t thresh = 0;
thresh_reg.read(&thresh);
Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX);
Serial.print("Initial threshold register = 0x");
Serial.println(thresh, HEX);
thresh_reg.write(~thresh);
Serial.print("Post threshold register = 0x"); Serial.println(thresh_reg.read(), HEX);
Serial.print("Post threshold register = 0x");
Serial.println(thresh_reg.read(), HEX);
}
void loop() {
}
void loop() {}

View file

@ -1,5 +1,5 @@
name=Adafruit BusIO
version=1.11.1
version=1.17.2
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for abstracting away UART, I2C and SPI interfacing