Files
2020-11-24 10:04:03 -08:00

225 lines
5.1 KiB
C++

// ---------------------------------------------------------------------------
// Created by Francisco Malpartida on 20/08/11.
// Copyright (C) - 2018
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License v3.0
// along with this program.
// If not, see <https://www.gnu.org/licenses/gpl-3.0.en.html>.
//
// ---------------------------------------------------------------------------
//
// Thread Safe: No
// Extendable: Yes
//
// @file SI2CIO.h
// This file implements a basic IO library using the PCF8574 I2C IO Expander
// chip, but using software I2C.
//
// @brief
// Implement a basic IO library to drive the PCF8574* I2C IO Expander ASIC.
// The library implements basic IO general methods to configure IO pin direction
// read and write uint8_t operations and basic pin level routines to set or read
// a particular IO port.
//
//
// @version API 1.0.0
//
// @author F. Malpartida - fmalpartida@gmail.com
// Adapted to SoftIC2 by Adrian Piccioli - adrianpiccioli@gmail.com
// ---------------------------------------------------------------------------
#if defined (__AVR__)
#if (ARDUINO < 100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
#include <inttypes.h>
/*#define SCL_PIN 6
#define SCL_PORT PORTD
#define SDA_PIN 7
#define SDA_PORT PORTD*/
//#define I2C_FASTMODE 1
//#define I2C_SLOWMODE 1
#define SCL_PIN 0
#define SCL_PORT PORTB
#define SDA_PIN 1
#define SDA_PORT PORTB
#include "SI2CIO.h"
#include "SoftI2CMaster.h"
// CLASS VARIABLES
// ---------------------------------------------------------------------------
// CONSTRUCTOR
// ---------------------------------------------------------------------------
SI2CIO::SI2CIO ( )
{
_i2cAddr = 0x0;
_dirMask = 0xFF; // mark all as INPUTs
_shadow = 0x0; // no values set
_initialised = false;
}
// PUBLIC METHODS
// ---------------------------------------------------------------------------
//
// begin
int SI2CIO::begin ( uint8_t i2cAddr )
{
// convert to 8 bit addresses for mapping as needed by the bitbang library
_i2cAddr = ( i2cAddr << 1 );
i2c_init();
_initialised = i2c_start(_i2cAddr | I2C_READ);
_shadow = i2c_read(true);
i2c_stop();
return ( _initialised );
}
//
// pinMode
void SI2CIO::pinMode ( uint8_t pin, uint8_t dir )
{
if ( _initialised )
{
if ( OUTPUT == dir )
{
_dirMask &= ~( 1 << pin );
}
else
{
_dirMask |= ( 1 << pin );
}
}
}
//
// portMode
void SI2CIO::portMode ( uint8_t dir )
{
if ( _initialised )
{
if ( dir == INPUT )
{
_dirMask = 0xFF;
}
else
{
_dirMask = 0x00;
}
}
}
//
// read
uint8_t SI2CIO::read ( void )
{
uint8_t retVal = 0;
if ( _initialised )
{
i2c_start(_i2cAddr | I2C_READ);
retVal = (_dirMask & i2c_read(true));
i2c_stop();
}
return ( retVal );
}
//
// write
int SI2CIO::write ( uint8_t value )
{
int status = 0;
if ( _initialised )
{
// Only write HIGH the values of the ports that have been initialised as
// outputs updating the output shadow of the device
_shadow = ( value & ~(_dirMask) );
status = i2c_start(_i2cAddr | I2C_WRITE);
status &= i2c_write(_shadow);
i2c_stop();
}
return ( (status == 0) );
}
//
// digitalRead
uint8_t SI2CIO::digitalRead ( uint8_t pin )
{
uint8_t pinVal = 0;
// Check if initialised and that the pin is within range of the device
// -------------------------------------------------------------------
if ( ( _initialised ) && ( pin <= 7 ) )
{
// Remove the values which are not inputs and get the value of the pin
pinVal = this->read() & _dirMask;
pinVal = ( pinVal >> pin ) & 0x01; // Get the pin value
}
return (pinVal);
}
//
// digitalWrite
int SI2CIO::digitalWrite ( uint8_t pin, uint8_t level )
{
uint8_t writeVal;
int status = 0;
// Check if initialised and that the pin is within range of the device
// -------------------------------------------------------------------
if ( ( _initialised ) && ( pin <= 7 ) )
{
// Only write to HIGH the port if the port has been configured as
// an OUTPUT pin. Add the new state of the pin to the shadow
writeVal = ( 1 << pin ) & ~_dirMask;
if ( level == HIGH )
{
_shadow |= writeVal;
}
else
{
_shadow &= ~writeVal;
}
status = this->write ( _shadow );
}
return ( status );
}
//
// PRIVATE METHODS
// ---------------------------------------------------------------------------
#endif // defined (__AVR__)