PCA9538 I2C Expander

Dependents:   PCA9538_example MAX7314_Expander

PCA9538.h

Committer:
Suky
Date:
2011-02-02
Revision:
0:d0e0b38e5991

File content as of revision 0:d0e0b38e5991:

/*
   \file PCA9538.h
   \version: 1.0
   
   \brief Este fichero contiene class para control de PCA9538 creando pin digitales
          de salida o entrada, o control por registro (8-bits).
   
   \web www.micros-designs.com.ar
   \date 31/01/11
   
 *- Version Log --------------------------------------------------------------*
 *   Fecha       Autor                Comentarios                             *
 *----------------------------------------------------------------------------*
 * 31/01/11      Suky        Original                                         *
 *----------------------------------------------------------------------------*/ 
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////                                                                   ////
////        (C) Copyright 2011 www.micros-designs.com.ar               ////
//// Este código puede ser usado, modificado y distribuido libremente  ////
//// sin eliminar esta cabecera y  sin garantía de ningún tipo.        ////
////                                                                   ////
////                                                                   ////
/////////////////////////////////////////////////////////////////////////// 

/*                                EXAMPLE 
#include "mbed.h"
#include "PCA9538.h"

//PCA9538 MyExpand(p9,p10,0x70,p21); // sda,scl,address,Interrupts
DigitalOut myled(LED1);
DigitalOut myled2(LED2);
PCA9538PinOut myled3(exp_p4,p9,p10,0x70); // pin del PCA,sda,scl,address
PCA9538PinOut myled4(exp_p7,p9,p10,0x70);
PCA9538PinIn  mypuls(exp_p0,p9,p10,0x70);
//void vISRExpand(void);

int main() {
    //MyExpand.vInit(0x0F,&vISRExpand);
    //MyExpand.vWrite(0x00);
    while(1) {
        if(mypuls==0){
            myled2=1;
            wait(0.3);
            myled2=0;
            wait(0.3);
        }else{
            myled3=1;
            myled4=1;
            myled=myled3;
            wait(0.5);
            myled = 0;
            myled3=0;
            myled4=0;
            wait(0.5);
        }
    }
}


//void vISRExpand(void){
//
//    myled2=!myled2;
//    MyExpand.vWrite(MyExpand.cRead()<<4);
//}
*/
#include "mbed.h"

enum ExpPinName{
    exp_p0=0,
    exp_p1,
    exp_p2,
    exp_p3,
    exp_p4,
    exp_p5,
    exp_p6,
    exp_p7,    
};

class PCA9538PinOut{
    public:
        PCA9538PinOut(ExpPinName Pin,PinName PIN_SDA,PinName PIN_SCL,unsigned char Address);
        void vWrite(int value);
        int read();
        #ifdef MBED_OPERATORS
        PCA9538PinOut& operator= (int value);
        operator int();
        #endif
    protected:
        ExpPinName _Pin;
        unsigned char _Address;
        I2C Bus;
};

PCA9538PinOut::PCA9538PinOut(ExpPinName Pin,PinName PIN_SDA,PinName PIN_SCL,unsigned char Address)
    :Bus(PIN_SDA,PIN_SCL),_Pin(Pin),_Address(Address<<1){
    unsigned char Temp;
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x03);
    Bus.start();
    Bus.write(_Address | 0x01);
    Temp=Bus.read(0);
    Bus.stop();
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x03);
    Bus.write((~(0x01<<_Pin))&Temp);
    Bus.stop();  
}

void PCA9538PinOut::vWrite(int value){
    unsigned char Temp;
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x01);
    Bus.start();
    Bus.write(_Address | 0x01);
    Temp=Bus.read(0);
    Bus.stop();
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x01);
    if(value==0){
        Bus.write((~(0x01<<_Pin))&Temp);
    }else{
        Bus.write((0x01<<_Pin)|Temp);
    }    
    Bus.stop();
}

int PCA9538PinOut::read(){
    unsigned char Temp;
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x01);
    Bus.start();
    Bus.write(_Address | 0x01);
    Temp=Bus.read(0);
    Bus.stop();
    
    return((Temp>>_Pin)&0x01);
}

PCA9538PinOut& PCA9538PinOut::operator= (int value){
    vWrite(value);    
}

PCA9538PinOut::operator int(){

    return(read());
}
//*****************************************************************************
class PCA9538PinIn{
    public:
        PCA9538PinIn(ExpPinName Pin,PinName PIN_SDA,PinName PIN_SCL,unsigned char Address);
        int read();
        #ifdef MBED_OPERATORS
        operator int();
        #endif
    protected:
        ExpPinName _Pin;
        unsigned char _Address;
        I2C Bus;
};

PCA9538PinIn::PCA9538PinIn(ExpPinName Pin,PinName PIN_SDA,PinName PIN_SCL,unsigned char Address)
    :Bus(PIN_SDA,PIN_SCL),_Pin(Pin),_Address(Address<<1){
    unsigned char Temp;
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x03);
    Bus.start();
    Bus.write(_Address | 0x01);
    Temp=Bus.read(0);
    Bus.stop();
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x03);
    Bus.write((0x01<<_Pin)|Temp);
    Bus.stop();  
}

int PCA9538PinIn::read(){
    unsigned char Temp;
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x00);
    Bus.start();
    Bus.write(_Address | 0x01);
    Temp=Bus.read(0);
    Bus.stop();
    
    return((Temp>>_Pin)&0x01);
}

PCA9538PinIn::operator int(){

    return(read());
}
//*****************************************************************************
class PCA9538{
    public:
        PCA9538(PinName PIN_SDA,PinName PIN_SCL,unsigned char Address,PinName PIN_INT=NC);
        void vInit(unsigned char Dir,void (*fptr)(void));
        void vSetConfiguration(unsigned char Dir);
        void vSetPolarity(unsigned char Pol);
        unsigned char cRead(void);
        void vWrite(unsigned char Data);
        void vEnableSetInterrupt(void (*fptr)(void));
        void vDisableInterrupt(void);
        bool bReadPinINT(void);
    protected:
        I2C Bus;
        InterruptIn PCA9538_Event;
        DigitalIn _PIN_INT;
        unsigned char _Address;
};

PCA9538::PCA9538(PinName PIN_SDA,PinName PIN_SCL,unsigned char Address,PinName PIN_INT)
    : Bus(PIN_SDA,PIN_SCL),_PIN_INT(PIN_INT),PCA9538_Event(PIN_INT){
    _Address=Address<<1;
}

void PCA9538::vInit(unsigned char Dir,void (*fptr)(void)){

    //Bus.frequency(400000);
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x03);
    Bus.write(Dir);
    Bus.stop();
    
    if (fptr!=NULL){
        PCA9538_Event.fall(fptr);
    }
}

void PCA9538::vSetConfiguration(unsigned char Dir){
    
    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x03);
    Bus.write(Dir);
    Bus.stop();
}

void PCA9538::vSetPolarity(unsigned char Pol){

    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x02);
    Bus.write(Pol);
    Bus.stop();
}

unsigned char PCA9538::cRead(void){
    unsigned char Temp;

    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x00);
    Bus.start();
    Bus.write(_Address | 0x01);
    Temp=Bus.read(0);
    Bus.stop();
    
    return(Temp);
}

void PCA9538::vWrite(unsigned char Data){

    Bus.start();
    Bus.write(_Address & 0xFE);
    Bus.write(0x01);
    Bus.write(Data);
    Bus.stop();
}

void PCA9538::vEnableSetInterrupt(void (*fptr)(void)){
    PCA9538_Event.fall(fptr);
}

void PCA9538::vDisableInterrupt(void){
    PCA9538_Event.fall(NULL);
}

bool PCA9538::bReadPinINT(void){
    return(_PIN_INT);
}