0.1.0 PCA9549

This commit is contained in:
Rob Tillaart 2023-12-12 19:35:17 +01:00
parent b777645d61
commit dd21cb1907
16 changed files with 709 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/PCA9549/.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart

View File

@ -0,0 +1,13 @@
name: Arduino-lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- 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
steps:
- uses: actions/checkout@v3
- 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
steps:
- uses: actions/checkout@v3
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
with:
pattern: "\\.json$"

View File

@ -0,0 +1,11 @@
# Change Log PCA9549
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] - 2023-12-12
- initial version

21
libraries/PCA9549/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023-2023 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.

View File

@ -0,0 +1,141 @@
//
// FILE: PCA9549.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2023-12-12
// PURPOSE: Arduino Library for PCA9549 I2C octal bus switch.
// URL: https://github.com/RobTillaart/PCA9549
#include "PCA9549.h"
PCA9549::PCA9549(uint8_t deviceAddress, TwoWire *wire)
{
_address = deviceAddress;
_wire = wire;
_mask = 0x00;
_resetPin = -1;
_forced = false;
_error = PCA9549_OK;
}
bool PCA9549::begin(uint8_t mask)
{
if (! isConnected()) return false;
setChannelMask(mask);
return true;
}
bool PCA9549::isConnected()
{
_wire->beginTransmission(_address);
return ( _wire->endTransmission() == 0);
}
bool PCA9549::enableChannel(uint8_t channel)
{
if (channel >= 8) return false;
if (!isEnabled(channel))
{
setChannelMask(_mask | (0x01 << channel));
}
return true;
}
bool PCA9549::disableChannel(uint8_t channel)
{
if (channel >= 8) return false;
if (!isEnabled(channel))
{
setChannelMask(_mask & ~(0x01 << channel));
}
return true;
}
bool PCA9549::selectChannel(uint8_t channel)
{
if (channel >= 8) return false;
setChannelMask(0x01 << channel);
return true;
}
bool PCA9549::isEnabled(uint8_t channel)
{
if (channel >= 8) return false;
return (_mask & (0x01 << channel));
}
bool PCA9549::disableAllChannels()
{
return setChannelMask(0x00);
}
bool PCA9549::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 PCA9549::getChannelMask()
{
if (_forced) // read from device.
{
_wire->requestFrom(_address, (uint8_t)1);
_mask = _wire->read();
}
return _mask;
}
void PCA9549::setResetPin(uint8_t resetPin)
{
_resetPin = resetPin;
pinMode(_resetPin, OUTPUT);
digitalWrite(_resetPin, HIGH);
}
void PCA9549::reset()
{
digitalWrite(_resetPin, LOW);
delayMicroseconds(1); // TODO datasheet page ? - 500 ns
digitalWrite(_resetPin, HIGH);
}
void PCA9549::setForced(bool forced)
{
_forced = forced;
};
bool PCA9549::getForced()
{
return _forced;
};
int PCA9549::getError()
{
int error = _error;
_error = PCA9549_OK;
return error;
}
// -- END OF FILE --

View File

@ -0,0 +1,65 @@
#pragma once
//
// FILE: PCA9549.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2023-12-12
// PURPOSE: Arduino Library for PCA9549 I2C octal bus switch.
// URL: https://github.com/RobTillaart/PCA9549
#include "Arduino.h"
#include "Wire.h"
#define PCA9549_LIB_VERSION (F("0.1.0"))
#define PCA9549_OK 0x00
class PCA9549
{
public:
// deviceAddress = 0x70 .. 0x77
PCA9549(uint8_t deviceAddress, TwoWire *wire = &Wire);
bool begin(uint8_t mask = 0x00); // default no channels enabled
bool isConnected(); // find multiplexer on I2C bus
// channel = 0..channelCount()-1
bool enableChannel(uint8_t channel); // enable this channel non exclusive
bool disableChannel(uint8_t channel);
bool selectChannel(uint8_t channel); // enable only this channel
bool isEnabled(uint8_t channel);
bool disableAllChannels();
// mask = 0x00 .. 0xFF - every bit is a channel.
// note 1: these are set simultaneously.
bool setChannelMask(uint8_t mask);
uint8_t getChannelMask();
// reset
void setResetPin(uint8_t resetPin);
void reset(); // trigger reset pin
// 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
uint8_t _resetPin; // default not set == -1 (255)
bool _forced;
int _error;
};
// -- END OF FILE --

128
libraries/PCA9549/README.md Normal file
View File

@ -0,0 +1,128 @@
[![Arduino CI](https://github.com/RobTillaart/PCA9549/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/PCA9549/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/PCA9549/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/PCA9549/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/PCA9549/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/PCA9549.svg)](https://github.com/RobTillaart/PCA9549/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/PCA9549/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/PCA9549.svg?maxAge=3600)](https://github.com/RobTillaart/PCA9549/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/PCA9549.svg)](https://registry.platformio.org/libraries/robtillaart/PCA9549)
# PCA9549
Arduino Library for PCA9549 I2C octal bus switch.
## Description
Library for the PCA9549 and compatibles.
The library allows you to switch on/off 8 channels uniquely or simultaneously.
**Warning**
The library is not tested yet.
The library caches the channels enabled, and if a channel is enabled,
it will not be enabled again (low level) to optimize performance.
#### I2C
I2C address of the device itself is 0x70 .. 0x77.
#### Related
- https://github.com/RobTillaart/TCA9549 - strong interface and code similarity
## Interface
```cpp
#include "PCA9549.h"
```
#### Constructor
- **PCA9549(const uint8_t deviceAddress, TwoWire \*wire = &Wire)** Constructor.
deviceAddress = 0x70 .. 0x77, 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.
#### 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.
- **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.
#### Reset
- **void setResetPin(uint8_t resetPin)** sets the pin to reset the chip. (Not tested)
- **void reset()** trigger the reset pin.
- **int getError()** returns the last I2C error.
#### Forced IO
When forced IO is set all writes and read - **getChannelMask()** - will go to the device.
If the flag is set to false it will cache the value of the channels enabled.
This will result in more responsive / faster calls.
Note that writes are only optimized if the channels are already set.
- **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 |
|:------------------------|:-------:|:------------------------|
| PCA9549_OK | 00 | no error |
## Future
#### Must
- improve documentation.
#### Should
- keep aligned with TCA9548 / PCA9548 library where meaningful.
- add examples e.g. real life scenarios.
- test with hardware
#### Could
- improve error handling.
#### 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,70 @@
//
// FILE: PCA9549_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo PCA9543 I2C multiplexer
// URL: https://github.com/RobTillaart/PCA9549
#include "PCA9549.h"
PCA9549 PCA(0x70);
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("PCA9549_LIB_VERSION: ");
Serial.println(PCA9549_LIB_VERSION);
Serial.println();
Wire.begin();
if (PCA.begin() == false)
{
Serial.println("COULD NOT CONNECT");
}
Serial.print("MASK:\t");
Serial.println(PCA.getChannelMask(), HEX);
for (int chan = 0; chan < 8; chan++)
{
Serial.print("PRE:\t");
Serial.print(PCA.isEnabled(chan));
PCA.enableChannel(chan);
Serial.print("\t");
Serial.println(PCA.isEnabled(chan));
delay(100);
}
Serial.println();
PCA.setChannelMask(0x00);
Serial.print("MASK:\t");
Serial.println(PCA.getChannelMask(), HEX);
for (int chan = 0; chan < 8; chan++)
{
PCA.enableChannel(chan);
Serial.print("MASK:\t");
Serial.println(PCA.getChannelMask(), HEX);
delay(100);
}
for (int chan = 0; chan < 8; chan++)
{
PCA.disableChannel(chan);
Serial.print("MASK:\t");
Serial.println(PCA.getChannelMask(), HEX);
delay(100);
}
Serial.println();
Serial.println("done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,32 @@
# Syntax Colouring Map For PCA9549
# Data types (KEYWORD1)
PCA9549 KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
isConnected KEYWORD2
enableChannel KEYWORD2
disableChannel KEYWORD2
selectChannel KEYWORD2
isEnabled KEYWORD2
disableAllChannels KEYWORD2
setChannelMask KEYWORD2
getChannelMask KEYWORD2
setResetPin KEYWORD2
reset KEYWORD2
setForced KEYWORD2
getForced KEYWORD2
getError KEYWORD2
# Constants (LITERAL1)
PCA9549_LIB_VERSION LITERAL1
PCA9549_OK LITERAL1

View File

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

View File

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

View File

@ -0,0 +1,127 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2023-12-12
// PURPOSE: unit tests for the PCA9549 I2C octal bus switch.
// https://github.com/RobTillaart/PCA9549
// 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 "PCA9549.h"
int expect; // TODO needed as there seems a problem with 8 bit comparisons (char?)
uint32_t start, stop;
unittest_setup()
{
fprintf(stderr, "PCA9549_LIB_VERSION: %s\n", (char *) PCA9549_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constants)
{
assertEqual(0, PCA9549_OK);
}
unittest(test_constructor)
{
PCA9549 pca(0x70);
Wire.begin();
assertTrue(pca.begin());
assertTrue(pca.isConnected());
}
unittest(test_enable)
{
PCA9549 pca(0x70);
Wire.begin();
bool b = pca.begin();
assertEqual(b, true);
uint8_t mask = 0x00;
for (int chan = 0; chan < 8; chan++)
{
pca.enableChannel(chan);
assertTrue(pca.isEnabled(chan));
}
assertEqual(0xFF, pca.getChannelMask());
pca.setChannelMask(0x00);
assertEqual(0x00, pca.getChannelMask());
}
unittest(test_select)
{
PCA9549 pca(0x70);
Wire.begin();
bool b = pca.begin();
assertEqual(b, true);
uint8_t mask = 0x00;
for (int chan = 0; chan < 8; chan++)
{
pca.selectChannel(chan);
assertTrue(pca.isEnabled(chan));
}
assertEqual(0x80, pca.getChannelMask());
pca.setChannelMask(0x00);
assertEqual(0x00, pca.getChannelMask());
}
unittest_main()
// -- END OF FILE --