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.
		
		
		
		
		
			
		
			
				
	
	
		
			162 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			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;
 | |
| }
 | |
| 
 |