0.1.0 ADG729

This commit is contained in:
Rob Tillaart 2024-07-03 17:21:50 +02:00
parent d6ac94a01c
commit 66e9ef06bb
16 changed files with 828 additions and 0 deletions

View File

@ -0,0 +1,28 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
# - due
# - zero
# - leonardo
- m4
- esp32
- esp8266
# - mega2560
- rpipico

4
libraries/ADG729/.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart
custom: "https://www.paypal.me/robtillaart"

View File

@ -0,0 +1,13 @@
name: Arduino-lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update
compliance: strict

View File

@ -0,0 +1,17 @@
name: Arduino CI
on: [push, pull_request]
jobs:
runTest:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -0,0 +1,18 @@
name: JSON check
on:
push:
paths:
- '**.json'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: json-syntax-check
uses: limitusus/json-syntax-check@v2
with:
pattern: "\\.json$"

177
libraries/ADG729/ADG729.cpp Normal file
View File

@ -0,0 +1,177 @@
//
// FILE: ADG729.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2024-07-03
// PURPOSE: Arduino Library for I2C ADG729 matrix switch. 2x4 Multiplexer.
// URL: https://github.com/RobTillaart/ADG729
#include "ADG729.h"
ADG729::ADG729(uint8_t deviceAddress, TwoWire *wire)
{
_address = deviceAddress;
_wire = wire;
_mask = 0x00;
_forced = false;
_error = ADG729_OK;
_channels = 8;
}
bool ADG729::begin(uint8_t mask)
{
if (! isConnected()) return false;
setChannelMask(mask);
return true;
}
bool ADG729::isConnected()
{
_wire->beginTransmission(_address);
return ( _wire->endTransmission() == 0);
}
uint8_t ADG729::channelCount()
{
return _channels;
}
///////////////////////////////////////////////////////
//
// Single channel interface
//
bool ADG729::enableChannel(uint8_t channel)
{
if (channel >= _channels) return false;
return setChannelMask(_mask | (0x01 << channel));
}
bool ADG729::disableChannel(uint8_t channel)
{
if (channel >= _channels) return false;
return setChannelMask(_mask & ~(0x01 << channel));
}
bool ADG729::selectChannel(uint8_t channel)
{
if (channel >= _channels) return false;
return setChannelMask(0x01 << channel);
}
bool ADG729::isEnabled(uint8_t channel)
{
if (channel >= _channels) return false;
return (_mask & (0x01 << channel));
}
bool ADG729::disableAllChannels()
{
return setChannelMask(0x00);
}
///////////////////////////////////////////////////////
//
// Dual channel interface
//
bool ADG729::enableAB(uint8_t channel)
{
if (channel >= 4) return false;
return setChannelMask(_mask | (0x11 << channel));
}
bool ADG729::disableAB(uint8_t channel)
{
if (channel >= 4) return false;
return setChannelMask(_mask & ~(0x11 << channel));
}
bool ADG729::selectAB(uint8_t channel)
{
if (channel >= 4) return false;
return setChannelMask(0x11 << channel);
}
bool ADG729::isEnabledAB(uint8_t channel)
{
if (channel >= 4) return false;
uint8_t tmp = (0x11 << channel);
return ((_mask & tmp) == tmp);
}
bool ADG729::select(uint8_t A, uint8_t B)
{
if (A >= 4) return false;
if (B >= 4) return false;
uint8_t tmp = (1 << A) | (1 << (B+4));
return setChannelMask(tmp);
}
///////////////////////////////////////////////////////
//
// Workers
//
bool ADG729::setChannelMask(uint8_t mask)
{
if ((_mask == mask) && (not _forced)) return true;
_mask = mask;
_wire->beginTransmission(_address);
_wire->write(_mask);
_error = _wire->endTransmission();
return (_error == 0);
}
uint8_t ADG729::getChannelMask()
{
if (_forced) // read from device.
{
_wire->requestFrom(_address, (uint8_t)1);
_mask = _wire->read();
}
return _mask;
}
///////////////////////////////////////////////////////
//
// Misc
//
void ADG729::setForced(bool forced)
{
_forced = forced;
}
bool ADG729::getForced()
{
return _forced;
}
int ADG729::getError()
{
int error = _error;
_error = ADG729_OK;
return error;
}
// -- END OF FILE --

80
libraries/ADG729/ADG729.h Normal file
View File

@ -0,0 +1,80 @@
#pragma once
//
// FILE: ADG729.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2024-07-03
// PURPOSE: Arduino Library for I2C ADG729 matrix switch. 2x4 Multiplexer.
// URL: https://github.com/RobTillaart/ADG729
// https://www.adafruit.com/product/5932
#include "Arduino.h"
#include "Wire.h"
#define ADG729_LIB_VERSION (F("0.1.0"))
// ERROR CODES (to be elaborated)
#define ADG729_OK 0
#define ADG729_ERROR_I2C -10 // not used yet
#define ADG729_ERROR_CHANNEL -20 // not used yet
class ADG729
{
public:
// deviceAddress = 0x4C .. 0x4F
ADG729(uint8_t deviceAddress, TwoWire *wire = &Wire);
bool begin(uint8_t mask = 0x00); // default no channels enabled
bool isConnected(); // find address on I2C bus
// channel = 0..7
uint8_t channelCount();
bool enableChannel(uint8_t channel); // enable channel NON exclusive
bool disableChannel(uint8_t channel);
bool selectChannel(uint8_t channel); // enable channel exclusive
bool isEnabled(uint8_t channel);
bool disableAllChannels();
// channel = 0..3
// sets both A and B with the same value.
bool enableAB(uint8_t channel);
bool disableAB(uint8_t channel);
bool selectAB(uint8_t channel);
bool isEnabledAB(uint8_t channel);
// A, B = 0..3
// sets A and B separately and uniquely.
bool select(uint8_t A, uint8_t B);
// mask = 0x00 .. 0xFF - every bit is a channel.
// although not for derived types.
// note 1: these are set simultaneously.
// note 2: these may include interrupt bits (in derived classes)
bool setChannelMask(uint8_t mask);
uint8_t getChannelMask();
// set forced IO (default false)
void setForced(bool forced = false);
bool getForced();
int getError();
protected:
uint8_t _address;
TwoWire* _wire;
uint8_t _mask; // caching mask = status of channels
bool _forced;
int _error;
uint8_t _channels;
};
// -- END OF FILE --

View File

@ -0,0 +1,11 @@
# Change Log ADG729
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.0] - 2024-07-03
- initial version

21
libraries/ADG729/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-2024 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

197
libraries/ADG729/README.md Normal file
View File

@ -0,0 +1,197 @@
[![Arduino CI](https://github.com/RobTillaart/ADG729/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/ADG729/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/ADG729/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/ADG729/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/ADG729/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/ADG729.svg)](https://github.com/RobTillaart/ADG729/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/ADG729/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/ADG729.svg?maxAge=3600)](https://github.com/RobTillaart/ADG729/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/ADG729.svg)](https://registry.platformio.org/libraries/robtillaart/ADG729)
# ADG729
Arduino Library for I2C ADG729 matrix switch. 2x4 Multiplexer.
## Description
**Experimental**
Library for the ADG729 dual 2x4 channel multiplexer.
The library allows you to select 0 to 8 switches uniquely or simultaneously.
These 8 switches are arranged in 2x4 switches to multiplex 2 lines A and B.
Both the A and B switches can be in 16 states, from 0000 - 1111.
The library caches the channels enabled, and if a channel is enabled,
it will not be enabled again (low level) to optimize performance.
This can however be overruled.
The device works with 2.3 V to 5.5 V so it should work with most MCU's.
Note: By connecting line A and B the ADG729 can act like an ADG728.
**Warning**
The library is not tested with hardware yet.
#### I2C
I2C address of the device itself is 0x4C .. 0x4F.
#### I2C performance
The ADG729 can work up to 400 KHz according to the datasheet.
#### Related
Other multiplexers
- https://github.com/RobTillaart/HC4051 (1x8 mux)
- https://github.com/RobTillaart/HC4052 (2x4 mux)
- https://github.com/RobTillaart/HC4053 (3x2 mux)
- https://github.com/RobTillaart/HC4067 (1x16 mux)
- https://github.com/RobTillaart/ADG725 (2x16 mux)
- https://github.com/RobTillaart/ADG726 (2x16 mux)
- https://github.com/RobTillaart/ADG729 (1x8 mux)
- https://github.com/RobTillaart/ADG729 (2x4 mux)
- https://github.com/RobTillaart/ADG731 (1x32 mux)
- https://github.com/RobTillaart/ADG732 (1x32 mux)
- https://github.com/RobTillaart/TCA9548 I2C multiplexer
## Interface
```cpp
#include "ADG729.h"
```
#### Interaction models
**Warning**
There are two interaction models with the ADG729.
These exist of single-channel and dual-channel functions.
Note that mixing these two interaction models might complicate the logic of your code.
However it is allowed.
#### Constructor
- **ADG729(const uint8_t deviceAddress, TwoWire \*wire = &Wire)** Constructor.
deviceAddress = 0x4C .. 0x4F, wire = Wire or WireN.
- **bool begin(uint8_t mask = 0x00)** set mask of channels to be enabled, default all disabled.
- **bool isConnected()** returns true if address of the multiplexer is found on I2C bus.
#### Single channel functions
All channel functions return true on success.
- **bool enableChannel(uint8_t channel)** enables channel 0 .. 7 **non-exclusive**.
Multiple channels can be enabled in parallel.
- **bool disableChannel(uint8_t channel)** disables channel 0 .. 7.
Will not disable other channels.
- **bool selectChannel(uint8_t channel)** enables a single channel 0 .. 7 **exclusive**.
All other channels will be disabled in the same call, so not before or after.
- **bool isEnabled(uint8_t channel)** returns true if the channel is enabled.
- **bool disableAllChannels()** fast way to disable all channels.
#### Dual Channel functions
All channel functions return true on success.
These functions set channels in pairs, the same channel for both A and B.
The advantage of the dual channel functions is that the switches are set simultaneously.
These functions are ideal e.g. to multiplex I2C or RS232 as these are buses
use two wires.
- **bool enableAB(uint8_t channel)** enables channel 0 .. 3 for both A and B **non-exclusive**.
- **bool disableAB(uint8_t channel)** disables channel 0 .. 3 for both A and B .
Will not disable other channels.
- **bool selectAB(uint8_t channel)** enables a single channel 0 .. 3 **exclusive**.
All other channels will be disabled in the same call, so not before or after.
- **bool isEnabledAB(uint8_t channel)** returns true if the channel is enabled for both A and B.
The **select()** function sets the A and B switch uniquely and independently at the same time.
It allows e.g. to make a routing matrix, if one connects A and B together.
Now one can select which A connects to which B, in total 4 x 4 possibilities.
- **bool select(uint8_t A, uint8_t B)** A, B = 0..3
#### Mask functions
Multiple channels can also be enabled in one call with a mask.
These functions do the hard work for the single and dual channel functions.
- **bool setChannelMask(uint8_t mask)** enables 0 or more channels simultaneously with a bit mask.
- **uint8_t getChannelMask()** reads back the bit mask of the channels enabled.
#### Debug
- **int getError()** returns the last (I2C) status / error.
#### Forced IO
When forced IO is set, all writes and read, e.g. **uint8_t getChannelMask()**,
will go to the device.
If the **forced-IO** flag is set to false, it will cache the value of the channels enabled.
This will result in far more responsive and faster calls.
Note that writes are only optimized if the channels are already set.
Forced IO is also used to speed up **getChannelMask()**.
- **void setForced(bool forced = false)** set forced write, slower but more robust.
- forced == false == fast mode (default).
- forced == true == slower, robust mode.
- **bool getForced()** returns set flag.
## Error Codes
Not implemented yet, preparation for future.
| name | value | description |
|:-----------------------|:-------:|:------------------------|
| ADG729_OK | 00 | no error |
| ADG729_ERROR_I2C | -10 | detected an I2C error |
| ADG729_ERROR_CHANNEL | -20 | channel out of range |
## Future
#### Must
- improve documentation.
- test with hardware.
#### Should
- add examples.
- improve error handling.
#### Could
- extend the unit tests.
#### Wont
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,

Binary file not shown.

View File

@ -0,0 +1,54 @@
//
// FILE: ADG729_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo ADG729 I2C multiplexer
// URL: https://github.com/RobTillaart/ADG729
#include "ADG729.h"
ADG729 MP(0x4C); // 0x4C..0x4F
uint8_t channels = 0;
uint8_t selected = 0;
uint32_t lastTime = 0;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("ADG729_LIB_VERSION: ");
Serial.println(ADG729_LIB_VERSION);
Serial.println();
Wire.begin();
// initialize multiplexer
if (MP.begin() == false)
{
Serial.println("Multiplexer error");
}
channels = MP.channelCount();
selected = 0;
}
void loop()
{
if ((millis() - lastTime) >= 5000)
{
lastTime = millis();
selected++;
if (selected >= MP.channelCount()) selected = 0;
MP.selectChannel(selected);
Serial.println(selected);
}
}
// -- END OF FILE --

View File

@ -0,0 +1,44 @@
# Syntax Colouring Map For ADG729
# Data types (KEYWORD1)
ADG729 KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
isConnected KEYWORD2
find KEYWORD2
channelCount KEYWORD2
enableChannel KEYWORD2
disableChannel KEYWORD2
selectChannel KEYWORD2
isEnabled KEYWORD2
disableAllChannels KEYWORD2
enableAB KEYWORD2
disableAB KEYWORD2
selectAB KEYWORD2
isEnabledAB KEYWORD2
select KEYWORD2
setChannelMask KEYWORD2
getChannelMask KEYWORD2
setForced KEYWORD2
getForced KEYWORD2
getError KEYWORD2
# Devices with interrupt
getInterruptMask KEYWORD2
# Constants (LITERAL1)
ADG729_LIB_VERSION LITERAL1
ADG729_OK LITERAL1
ADG729_ERROR_I2C LITERAL1
ADG729_ERROR_CHANNEL LITERAL1

View File

@ -0,0 +1,23 @@
{
"name": "ADG729",
"keywords": "I2C,multiplexer",
"description": "Arduino Library for I2C ADG729 matrix switch. 2x4 Multiplexer.",
"authors":
[
{
"name": "Rob Tillaart",
"email": "Rob.Tillaart@gmail.com",
"maintainer": true
}
],
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/ADG729"
},
"version": "0.1.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",
"headers": "ADG729.h"
}

View File

@ -0,0 +1,11 @@
name=ADG729
version=0.1.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino Library for I2C ADG729 matrix switch. 2x4 Multiplexer.
paragraph=
category=Signal Input/Output
url=https://github.com/RobTillaart/ADG729
architectures=*
includes=ADG729.h
depends=

View File

@ -0,0 +1,130 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2021-03-16
// PURPOSE: unit tests for the ADG729 I2C matrix switch. 2x4 Multiplexer.
// https://github.com/RobTillaart/ADG729
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//
// supported assertions
// ----------------------------
// assertEqual(expected, actual); // a == b
// assertNotEqual(unwanted, actual); // a != b
// assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b))
// assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b))
// assertLess(upperBound, actual); // a < b
// assertMore(lowerBound, actual); // a > b
// assertLessOrEqual(upperBound, actual); // a <= b
// assertMoreOrEqual(lowerBound, actual); // a >= b
// assertTrue(actual);
// assertFalse(actual);
// assertNull(actual);
// // special cases for floats
// assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon
// assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon
// assertInfinity(actual); // isinf(a)
// assertNotInfinity(actual); // !isinf(a)
// assertNAN(arg); // isnan(a)
// assertNotNAN(arg); // !isnan(a)
/*
most unit tests will test for fail
as there is no sensor connected
and there is no mockup.
It appears that Wire.write does not fail without sensor...
*/
#include <ArduinoUnitTests.h>
#include "Arduino.h"
#include "ADG729.h"
int expect; // TODO needed as there seems a problem with 8 bit comparisons (char?)
uint32_t start, stop;
unittest_setup()
{
fprintf(stderr, "ADG729_LIB_VERSION: %s\n", (char *) ADG729_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constants)
{
assertEqual(0, ADG729_OK);
assertEqual(-10, ADG729_ERROR_I2C);
assertEqual(-20, ADG729_ERROR_CHANNEL);
}
unittest(test_constructor)
{
ADG729 adg(0x4C);
Wire.begin();
assertTrue(adg.begin());
assertTrue(adg.isConnected());
assertEqual(8, adg.channelCount());
}
unittest(test_enable)
{
ADG729 adg(0x4C);
Wire.begin();
bool b = adg.begin();
assertEqual(b, true);
uint8_t mask = 0x00;
for (int chan = 0; chan < 8; chan++)
{
adg.enableChannel(chan);
assertTrue(adg.isEnabled(chan));
}
assertEqual(0xFF, adg.getChannelMask());
adg.setChannelMask(0x00);
assertEqual(0x00, adg.getChannelMask());
}
unittest(test_select)
{
ADG729 adg(0x4C);
Wire.begin();
bool b = adg.begin();
assertEqual(b, true);
uint8_t mask = 0x00;
for (int chan = 0; chan < 8; chan++)
{
adg.selectChannel(chan);
assertTrue(adg.isEnabled(chan));
}
assertEqual(0x80, adg.getChannelMask());
adg.setChannelMask(0x00);
assertEqual(0x00, adg.getChannelMask());
}
unittest_main()
// -- END OF FILE --