You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
extr/pcf8574.c

162 lines
3.8 KiB
C

/*
pcf8574 lib 0x02
copyright (c) Davide Gironi, 2012
Released under GPLv3.
Please refer to LICENSE file for licensing information.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "pcf8574.h"
//path to i2c fleury lib
#include PCF8574_I2CFLEURYPATH
/*
* initialize
*/
void pcf8574_init() {
#if PCF8574_I2CINIT == 1
//init i2c
i2c_init();
_delay_us(10);
#endif
//reset the pin status
uint8_t i = 0;
for(i=0; i<PCF8574_MAXDEVICES; i++)
pcf8574_pinstatus[i] = 0;
}
/*
* get output status
*/
int8_t pcf8574_getoutput(uint8_t deviceid) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES)) {
data = pcf8574_pinstatus[deviceid];
}
return data;
}
/*
* get output pin status
*/
int8_t pcf8574_getoutputpin(uint8_t deviceid, uint8_t pin) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pin >= 0 && pin < PCF8574_MAXPINS)) {
data = pcf8574_pinstatus[deviceid];
data = (data >> pin) & 0b00000001;
}
return data;
}
/*
* set output pins
*/
int8_t pcf8574_setoutput(uint8_t deviceid, uint8_t data) {
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES)) {
pcf8574_pinstatus[deviceid] = data;
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_WRITE);
i2c_write(data);
i2c_stop();
return 0;
}
return -1;
}
/*
* set output pins, replace actual status of a device from pinstart for pinlength with data
*/
int8_t pcf8574_setoutputpins(uint8_t deviceid, uint8_t pinstart, uint8_t pinlength, int8_t data) {
//example:
//actual data is 0b01101110
//want to change ---
//pinstart 4
//data 101 (pinlength 3)
//result 0b01110110
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pinstart - pinlength + 1 >= 0 && pinstart - pinlength + 1 >= 0 && pinstart < PCF8574_MAXPINS && pinstart > 0 && pinlength > 0)) {
uint8_t b = 0;
b = pcf8574_pinstatus[deviceid];
uint8_t mask = ((1 << pinlength) - 1) << (pinstart - pinlength + 1);
data <<= (pinstart - pinlength + 1);
data &= mask;
b &= ~(mask);
b |= data;
pcf8574_pinstatus[deviceid] = b;
//update device
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_WRITE);
i2c_write(b);
i2c_stop();
return 0;
}
return -1;
}
/*
* set output pin
*/
int8_t pcf8574_setoutputpin(uint8_t deviceid, uint8_t pin, uint8_t data) {
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pin >= 0 && pin < PCF8574_MAXPINS)) {
uint8_t b = 0;
b = pcf8574_pinstatus[deviceid];
b = (data != 0) ? (b | (1 << pin)) : (b & ~(1 << pin));
pcf8574_pinstatus[deviceid] = b;
//update device
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_WRITE);
i2c_write(b);
i2c_stop();
return 0;
}
return -1;
}
/*
* set output pin high
*/
int8_t pcf8574_setoutputpinhigh(uint8_t deviceid, uint8_t pin) {
return pcf8574_setoutputpin(deviceid, pin, 1);
}
/*
* set output pin low
*/
int8_t pcf8574_setoutputpinlow(uint8_t deviceid, uint8_t pin) {
return pcf8574_setoutputpin(deviceid, pin, 0);
}
/*
* get input data
*/
int8_t pcf8574_getinput(uint8_t deviceid) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES)) {
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_READ);
data = ~i2c_readNak();
i2c_stop();
}
return data;
}
/*
* get input pin (up or low)
*/
int8_t pcf8574_getinputpin(uint8_t deviceid, uint8_t pin) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pin >= 0 && pin < PCF8574_MAXPINS)) {
data = pcf8574_getinput(deviceid);
if(data != -1) {
data = (data >> pin) & 0b00000001;
}
}
return data;
}