The PCAL9555, PCAL9554 series is a low-voltage 16-bit/8-bit General Purpose Input/Output (GPIO) expander with interrupt. This conponent library is compatible to basic operation os GPIO expanders: 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.

Dependents:   PCAL9555_Hello OM13082-JoyStick OM13082_LED OM13082-test ... more

What is this?

This conponent library is compatible to basic operation os GPIO expanders: 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.

How to use?

Wiring

/media/uploads/nxp_ip/gpio16.png
Wiring between mbed and 16-bit GPIO expander

/media/uploads/nxp_ip/gpio08.png
Wiring between mbed and 8-bit GPIO expander

Very basic register level I/O bit operation

PCAL9555 and PCAL9554 are class libraries for those compatible GPIO expander chips.
Those class libraries provides interface for bit operation of its I/O port.
For 16-bit GPIO expanders, the input/output access and its direction setting can be done by 16-bit data. For 8-bit GPIO expanders, those can be done by 8-bit data.

  #include    "mbed.h"
  #include    "PCAL9555.h"
 
  PCAL9555    gpio( p28, p27, 0xE8 );     //  using PCA9539
 
  int main() {
      gpio.configure( 0xFFFF );           //  Set all pins: input
      printf( "  0x%04X\r\n", (int)gpio );//  Print pins state
 
      gpio.configure( 0x0000 );           //  Set all pins: output
      int count   = 0;
      while(1) {
          gpio.write( count++ );
      }
  }


High level APIs

To use the GPIO expanders more simple, this library is including mbed-SDK-style APIs.
APIs that similar to DigitaiInOut, DigitalOut, DigitalIn, BusInOut, BusOut and BusIn are available.

GpioDigitalOut, GpioDigitaiInOut, GpioDigitalIn

Next code shows sample of DigitalOut equivalent API GpioDigitalOut usage.
A pin on the PCAL9555 is defined as pin and its state is changed by assignment.
(For single pin operation, GpioDigitaiInOut and GpioDigitalIn are available also.)

  #include "mbed.h"
  #include "PCAL9555.h"
  
  PCAL9555        gpio_exp( p28, p27, 0xE8 );    //  SDA, SCL, Slave_address(option)
  GpioDigitalOut  pin( gpio_exp, X0_0 );
   
  int main() {
      while( 1 ) {
          pin = 1;
          wait( 0.2 );
          pin = 0;
          wait( 0.2 );
      }
  }


GpioBusOut, GpioBusInOut, GpioBusIn

BusOut equivalent API GpioBusOut is available too.
In next code, pins are grouped as mypins to manage the output as bus output.
(Same as GpioDigitalInOut and GpioDigitalIn APIs, GpioBusInOut and GpioBusIn are available also.)

  #include "mbed.h"
  #include "PCAL9555.h"
  
  PCAL9555    gpio_exp( p28, p27, 0xE8 );    //  SDA, SCL, Slave_address(option)
  GpioBusOut  mypins( gpio_exp, X0_0, X0_1, X0_2, X0_3 );
   
  int main() {
      while( 1 ) {
          for( int i = 0; i < 16; i++ ) {
              mypins  = i;
              wait( 0.25 );
          }
      }
  }


The high level APIs can be used in combination

Those high level APIs can be used in combination.
Each pins can be managed by instances.

  #include    "mbed.h"
  #include    "PCAL9555.h"
 
  PCAL9555        gpio( p28, p27, 0xE8 );     //  using PCA9539
 
  //  The GPIO pins are grouped in some groups and operated as bus I/O
  GpioBusIn       bus_in( gpio, X0_0, X0_1, X0_2, X0_3 );
  GpioBusOut      bus_out( gpio, X0_4, X0_5, X0_6 );
  GpioBusInOut    bus_io( gpio, X1_7, X1_6, X1_5, X1_4, X1_3, X1_2, X1_1, X1_0 );
  GpioDigitalOut  myled( gpio, X0_7 );
 
  int main() {
      bus_io.input();
      printf( "I/O = 0x%02X\r\n", (int)bus_io );
      printf( "In  = 0x%01X\r\n", (int)bus_in );
 
      bus_io.output();
 
      int count   = 0;
      while(1) {
          bus_out = count;
          bus_io  = count;
          myled   = count & 0x1;
          count++;
          wait( 0.1 );
      }
  }
Committer:
nxp_ip
Date:
Thu Mar 19 02:21:57 2015 +0000
Revision:
1:fd7cfa821b6a
Parent:
0:6c9a51a50eea
API document update

Who changed what in which revision?

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