The PCAL6416A is a low-voltage 16-bit general purpose I/O (GPIO) expander with interrupt. This component library is compatible to basic operation as GPIO expanders: PCAL6416A, PCAL9555, PCA9555, PCA9535, PCA9539, PCAL9554, PCA9554 and PCA9538. On addition to this, this library is including mbed-SDK-style APIs. APIs that similar to DigitaiInOut, DigitalOut, DigitalIn, BusInOUt, BusOut and BusIn are available.

This is a copy of the PCA9555 library by Akifumi "Tedd" OKANO, which is compatible with PCAL6416A chip.

Committer:
andriym
Date:
Wed Feb 15 10:07:59 2017 +0000
Revision:
0:035111d3d631
A change of name for the PCAL955x library to make it searchable for people needing PCAL6416A library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andriym 0:035111d3d631 1 #include "mbed.h"
andriym 0:035111d3d631 2 #include "PCAL955x.h"
andriym 0:035111d3d631 3
andriym 0:035111d3d631 4 PCAL955x::PCAL955x( PinName i2c_sda, PinName i2c_scl, char i2c_address )
andriym 0:035111d3d631 5 : i2c_p( new I2C( i2c_sda, i2c_scl ) ),
andriym 0:035111d3d631 6 i2c( *i2c_p ),
andriym 0:035111d3d631 7 address( i2c_address ),
andriym 0:035111d3d631 8 pin_state( ~0x0 ),
andriym 0:035111d3d631 9 pin_direction( ~0x0 )
andriym 0:035111d3d631 10 {
andriym 0:035111d3d631 11 }
andriym 0:035111d3d631 12
andriym 0:035111d3d631 13 PCAL955x::PCAL955x( I2C &i2c_, char i2c_address )
andriym 0:035111d3d631 14 : i2c_p( NULL ),
andriym 0:035111d3d631 15 i2c( i2c_ ),
andriym 0:035111d3d631 16 address( i2c_address ),
andriym 0:035111d3d631 17 pin_state( ~0x0 ),
andriym 0:035111d3d631 18 pin_direction( ~0x0 )
andriym 0:035111d3d631 19 {
andriym 0:035111d3d631 20 }
andriym 0:035111d3d631 21
andriym 0:035111d3d631 22 PCAL955x::~PCAL955x()
andriym 0:035111d3d631 23 {
andriym 0:035111d3d631 24 if ( NULL != i2c_p )
andriym 0:035111d3d631 25 delete i2c_p;
andriym 0:035111d3d631 26 }
andriym 0:035111d3d631 27
andriym 0:035111d3d631 28 void PCAL955x::write( int bit_pattern )
andriym 0:035111d3d631 29 {
andriym 0:035111d3d631 30 pin_state = bit_pattern;
andriym 0:035111d3d631 31 reg_index_write( OUTPUT, pin_state );
andriym 0:035111d3d631 32 }
andriym 0:035111d3d631 33
andriym 0:035111d3d631 34 int PCAL955x::read( void )
andriym 0:035111d3d631 35 {
andriym 0:035111d3d631 36 return ( reg_index_read( INPUT ) );
andriym 0:035111d3d631 37 }
andriym 0:035111d3d631 38
andriym 0:035111d3d631 39 void PCAL955x::polarity( int bit_pattern )
andriym 0:035111d3d631 40 {
andriym 0:035111d3d631 41 reg_index_write( POLARITY, pin_direction );
andriym 0:035111d3d631 42 }
andriym 0:035111d3d631 43
andriym 0:035111d3d631 44 void PCAL955x::configure( int bit_pattern )
andriym 0:035111d3d631 45 {
andriym 0:035111d3d631 46 pin_direction = bit_pattern;
andriym 0:035111d3d631 47 reg_index_write( CONFIG, pin_direction );
andriym 0:035111d3d631 48 }
andriym 0:035111d3d631 49
andriym 0:035111d3d631 50 void PCAL955x::write_with_mask( int bitpattern, int mask_bits )
andriym 0:035111d3d631 51 {
andriym 0:035111d3d631 52 pin_state &= (bitpattern | mask_bits);
andriym 0:035111d3d631 53 pin_state |= (bitpattern & ~mask_bits);
andriym 0:035111d3d631 54
andriym 0:035111d3d631 55 write( pin_state );
andriym 0:035111d3d631 56 }
andriym 0:035111d3d631 57
andriym 0:035111d3d631 58 void PCAL955x::configure_with_mask( int bitpattern, int mask_bits )
andriym 0:035111d3d631 59 {
andriym 0:035111d3d631 60 pin_direction &= (bitpattern | mask_bits);
andriym 0:035111d3d631 61 pin_direction |= (bitpattern & ~mask_bits);
andriym 0:035111d3d631 62
andriym 0:035111d3d631 63 configure( pin_direction );
andriym 0:035111d3d631 64 }
andriym 0:035111d3d631 65
andriym 0:035111d3d631 66 void PCAL955x::interrupt_mask( int bit_pattern )
andriym 0:035111d3d631 67 {
andriym 0:035111d3d631 68 int new_config;
andriym 0:035111d3d631 69
andriym 0:035111d3d631 70 new_config = (~bit_pattern) | reg_index_read( CONFIG );
andriym 0:035111d3d631 71 reg_index_write( CONFIG, new_config );
andriym 0:035111d3d631 72 reg_index_write( INT_MASK, bit_pattern );
andriym 0:035111d3d631 73 }
andriym 0:035111d3d631 74
andriym 0:035111d3d631 75 int PCAL955x::interrupt_status( void )
andriym 0:035111d3d631 76 {
andriym 0:035111d3d631 77 return ( reg_index_read( INT_STAT ) );
andriym 0:035111d3d631 78 }
andriym 0:035111d3d631 79
andriym 0:035111d3d631 80
andriym 0:035111d3d631 81 void PCAL955x::bus_write( char *dp, int length )
andriym 0:035111d3d631 82 {
andriym 0:035111d3d631 83 #if 0
andriym 0:035111d3d631 84 printf( "bus_write: 0x%02X - ", address );
andriym 0:035111d3d631 85 for ( int i = 0; i < length; i++ )
andriym 0:035111d3d631 86 printf( " 0x%02X", *(dp + i) );
andriym 0:035111d3d631 87 printf( "\r\n" );
andriym 0:035111d3d631 88 #endif
andriym 0:035111d3d631 89
andriym 0:035111d3d631 90 i2c.write( address, dp, length );
andriym 0:035111d3d631 91 }
andriym 0:035111d3d631 92
andriym 0:035111d3d631 93 void PCAL955x::bus_read( char reg_addr, char *dp, int length )
andriym 0:035111d3d631 94 {
andriym 0:035111d3d631 95 i2c.write( address, (char *)(&reg_addr), 1, true );
andriym 0:035111d3d631 96 i2c.read( address, dp, length );
andriym 0:035111d3d631 97 }
andriym 0:035111d3d631 98
andriym 0:035111d3d631 99 void PCAL955x::write( int pin, int v )
andriym 0:035111d3d631 100 {
andriym 0:035111d3d631 101 if ( pin < number_of_pins() ) {
andriym 0:035111d3d631 102 if ( v )
andriym 0:035111d3d631 103 pin_state |= 0x01 << pin;
andriym 0:035111d3d631 104 else
andriym 0:035111d3d631 105 pin_state &= ~(0x01 << pin);
andriym 0:035111d3d631 106 } else {
andriym 0:035111d3d631 107 pin_state = v ? ~0x0 : 0x0;
andriym 0:035111d3d631 108 }
andriym 0:035111d3d631 109
andriym 0:035111d3d631 110 write( pin_state );
andriym 0:035111d3d631 111 }
andriym 0:035111d3d631 112
andriym 0:035111d3d631 113 int PCAL955x::read( int pin )
andriym 0:035111d3d631 114 {
andriym 0:035111d3d631 115 return ( (reg_index_read( INPUT ) >> pin) & 0x1 );
andriym 0:035111d3d631 116 }
andriym 0:035111d3d631 117
andriym 0:035111d3d631 118 void PCAL955x::configure( int pin, int v )
andriym 0:035111d3d631 119 {
andriym 0:035111d3d631 120 if ( pin < number_of_pins() ) {
andriym 0:035111d3d631 121 if ( v )
andriym 0:035111d3d631 122 pin_direction |= 0x01 << pin;
andriym 0:035111d3d631 123 else
andriym 0:035111d3d631 124 pin_direction &= ~(0x01 << pin);
andriym 0:035111d3d631 125 } else {
andriym 0:035111d3d631 126 pin_direction = v ? ~0x0 : 0x0;
andriym 0:035111d3d631 127 }
andriym 0:035111d3d631 128
andriym 0:035111d3d631 129 configure( pin_direction );
andriym 0:035111d3d631 130 }
andriym 0:035111d3d631 131
andriym 0:035111d3d631 132 PCAL955x::operator int( void )
andriym 0:035111d3d631 133 {
andriym 0:035111d3d631 134 return( read() );
andriym 0:035111d3d631 135 }