SPI-Brigde (capseld), for polling interrupt, it is neccessary to adapt the constructor and the function getInt()

SC18IS602.cpp

Committer:
x1dmoesc
Date:
2019-02-18
Revision:
2:cb90c271c412
Parent:
1:2a7edc2be6df
Child:
3:9cf83f16c17d

File content as of revision 2:cb90c271c412:

#include "SC18IS602.h"
#include "mbed.h"

//******************************************************************************//
// constructor
//******************************************************************************//
SC18IS602::SC18IS602(I2C *_i2c, uint8_t uiAdr)                  //
    :   SC18IS602_W(HARD_ADR | (uiAdr & USER_ADR_MASK) << 1),                   // Initialisation list:     const WRITE
        SC18IS602_R( SC18IS602_W | 0x01),                                       //                          const READ
        iINT(0){
                                                                                //
    i2c = _i2c;                                                                 //
    bAck = NACK;                                                                //
    for(int i = 0; i < BUFFER_SIZE; i++)                                        // clear buffer
        cCmd[i] = 0;   
        
    if(getInt())  clearInt();                                                   //
    wait(0.01);
    
    //getInt_ptr = NULL;

}



//******************************************************************************//
// constructor
//******************************************************************************//
SC18IS602::SC18IS602(I2C *_i2c, PCA9555 *_pca , uint8_t uiAdr)                  //
    :   SC18IS602_W(HARD_ADR | (uiAdr & USER_ADR_MASK) << 1),                   // Initialisation list:     const WRITE
        SC18IS602_R( SC18IS602_W | 0x01),                                       //                          const READ
        iINT(1){
                                                                                //
    i2c = _i2c;                                                                 //
    pca = _pca;                                                                 //
    bAck = NACK;                                                                //
    for(int i = 0; i < BUFFER_SIZE; i++)                                        // clear buffer
        cCmd[i] = 0;   
    
    if(getInt())  clearInt();                                                   //
    wait(0.01);
}



//******************************************************************************//
// constructor
//******************************************************************************//
SC18IS602::SC18IS602(I2C *_i2c, DigitalIn *_IntPin, uint8_t uiAdr)//
    :   SC18IS602_W(HARD_ADR | (uiAdr & USER_ADR_MASK) << 1),                   // Initialisation list:     const WRITE
        SC18IS602_R( SC18IS602_W | 0x01),                                       //                          const READ
        iINT(2){
                                                                                //
    i2c = _i2c;                                                                 //
    IntPin = _IntPin;                                                                 //
    bAck = NACK;                                                                //
    for(int i = 0; i < BUFFER_SIZE; i++)                                        // clear buffer
        cCmd[i] = 0;   
        
    if(getInt())  clearInt();                                                   //
    wait(0.01);

}


//******************************************************************************//
// 
//******************************************************************************//
bool SC18IS602::configSPI(uint8_t uiConf){                                      //
                                                                                //
    cCmd[0] = ADR_SPI_CONF;                                                     //
    cCmd[1] = uiConf & 0x2F;                                                    // clear reserved bits 0b0010'1111
    sprintf(cDebug, "Config SPI:%*s0x%02x", 5, " ", uiConf);
    return sendViaI2C(cCmd, 2, cDebug);                                        //
}



//******************************************************************************//
// 
//******************************************************************************//
bool SC18IS602::enableGPIO(uint8_t uiConf){                                     //
                                                                                //
    cCmd[0] = ADR_GPIO.EN;                                                      //
    cCmd[1] = uiConf & 0x0F;                                                    // clear reserved bits 0b0000'1111
    return sendViaI2C(cCmd, 2, "Enable GPIO");                                                //
}




//******************************************************************************//
// 
//******************************************************************************//
bool SC18IS602::configGPIO(uint8_t uiConf){                                     //
                                                                                //
    cCmd[0] = ADR_GPIO.CONF;                                                    //
    cCmd[1] = uiConf;                                                           // clear reserved bits 0b0000'1111
    return sendViaI2C(cCmd, 2);                                                //
}



/******************************************************************************/
// sends via I2C and returns ACK or NACK
/******************************************************************************/
bool SC18IS602::sendViaI2C(const char *cData, int iLength, string sDebug)
{  
    bAck = not i2c->write(SC18IS602_W, cData, iLength);       
    //printf("%d\n", bAck);
    if (bAck == ACK) {
        return ACK;
        
    } else {
        if(sizeof(sDebug) != NULL)  printf("%s:%*s", sDebug.c_str(), 10, " ");
        printf("NACK\n");    
        return NACK;
    }
}



/******************************************************************************/
// sends via I2C and returns ACK or NACK
/******************************************************************************/
bool SC18IS602::readViaI2C(char *cData, int iLength, string sDebug){  

    bAck = not i2c->read(SC18IS602_R, cData, iLength);       
    
    if (bAck == ACK) {
        return ACK;
        
    } else {
        if(sizeof(sDebug) != NULL)  printf("%s:%*s", sDebug.c_str(), 10, " ");
        printf("NACK\n"); 
        return NACK;
    }
}


//******************************************************************************//
//  get interrupt status
//******************************************************************************//
bool SC18IS602::getInt(){
    //printf("Wait for Int...\n");  
    //wait(0.1);
    if(iINT == 0){ 
        return INTERRUPT;
    }
    
    if(iINT == 1){
        //printf("GPIO\n");
        return pca->getGPIO1_B7(true);
    }
    
    if(iINT == 2){
        //printf("PIN\n");
        return IntPin->read();
    }
    
    return not INTERRUPT;
}



/******************************************************************************/
// clears the interrupt pin
// returns 0(ACK) on success otherwise 1 (NACK)
/******************************************************************************/
bool SC18IS602::clearInt(){
    cCmd[0] = 0xF1;
    return sendViaI2C(cCmd, 1, "clear interrupt");
}


//******************************************************************************//
// toggle GPIO Pins                                                             //
//******************************************************************************//
bool SC18IS602::gpio_toggle(uint8_t uiPort){                                    //
    
    uiPort &= 0x0F;                                                             // clear reserved bits
    
    cCmd[0] = ADR_GPIO.READ;                                                    // Read from GPIO port
    sendViaI2C(cCmd, 1, "Read GPIO");
    bAck = (bool) readViaI2C(&cCmd[1], 1);
        
    if(bAck == NACK) return bAck;                                               // if NACK, return
    
    cCmd[0] = ADR_GPIO.WRITE;
    cCmd[1] ^= uiPort;                                                          // toogle given pins (uiTogllePin)
    return sendViaI2C(cCmd, 2, "GPIO tog");

}


/******************************************************************************/
// swith the GPIO Pin for debugging on
/******************************************************************************/
bool SC18IS602::gpio_pin3_off()
{
    cCmd[0] = ADR_GPIO.WRITE;
    cCmd[1] = (1 << GPIO.CS3);
    return sendViaI2C(cCmd, 2, "GPIO off");
}


/******************************************************************************/
// swith the GPIO Pin for debugging off
/******************************************************************************/
bool SC18IS602::gpio_pin3_on()
{
    cCmd[0] = ADR_GPIO.WRITE;
    cCmd[1] = (0 << GPIO.CS3);
    return sendViaI2C(cCmd, 2, "GPIO on");
}



//******************************************************************************//
//
//******************************************************************************//
bool SC18IS602::sendViaSPI(char cAdrByte, char *cDataBytes, uint8_t uiNum)
{
    if((int)uiNum >= BUFFER_SIZE - 1)                                           // If number of sending Bytes greather than BUFFER_SIZE - 1 (Register-Adress-Byte)
        return NACK;                                                            // returns NACK (failure)
    
    
    uiNumByte = 0;
    cCmd[uiNumByte] = CMD_RW.CS0;                                               // send via SPI and CS0 (SS0)
    cCmd[++uiNumByte] = cAdrByte;
    for(int n = uiNum - 1 ; n >= 0; n--) {
        cCmd[++uiNumByte] = cDataBytes[n];
    }
    
    
    uiNumByte++;                                                                // char cCmd counts from 0, so the number is +1    
    bAck = sendViaI2C(cCmd, uiNumByte, "TX via SPI");                           // send via SPI      
    waitFor(INTERRUPT);                                                  // If there was an interrupt, wait until it is cleared   
    clearInt();  
    waitFor(not INTERRUPT);                                                      // If there was an interrupt, wait until it is cleared
    
    return bAck;
}



//******************************************************************************//
//  returns reading data. The first byte is the status byte
//******************************************************************************//
bool SC18IS602::readViaSPI(char cAdrByte, char *cDataBytes, uint8_t uiNum)
{   
    if((int)uiNum >= BUFFER_SIZE - 1)                                           // If number of sending Bytes greather than BUFFER_SIZE - 1 (Register-Adress-Byte)
        return NACK;                                                            // returns NACK (failure)    

    
    // send first time Read comand
    uiNumByte = 0;
    cCmd[uiNumByte++] = CMD_RW.CS0;                                               // send via SPI and CS0 (SS0)
    cCmd[uiNumByte++] = cAdrByte;
    
    for(int n = uiNum - 1 ; n >= 0; n--) {
        cCmd[uiNumByte++] = 0x00;
    }

    
    if(getInt() == INTERRUPT){                                                  // If interrupt isn't cleard, then 
        //printf("Interrupt...");
        clearInt();                                                             // clear interrupt
        waitFor(not INTERRUPT);                                                 // wait until interrupt is cleard
    }
    
    

    bAck = sendViaI2C(cCmd, uiNumByte, "Send Rx Cmd via SPI");
    waitFor(INTERRUPT);
    clearInt();
    
 
    // send secound time read comand (dummy) to receive data from first read command   
    cCmd[0] = CMD_RW.CS0;                                               // send via SPI and CS0 (SS0)
    //cCmd[++uiNumByte] = cAdrByte;
    
    //for(int n = uiNum - 1 ; n >= 0; n--) {
    //    cCmd[++uiNumByte] = 0x00;
    //}
    //uiNumByte++; 
        
    
    waitFor(not INTERRUPT);                                                      // If there was an interrupt, wait until it is cleared                
    bAck =  sendViaI2C(cCmd, uiNumByte, "Send dummy data via SPI");
    waitFor(INTERRUPT);                                                      // wait until sending is finished and an interrupt occurs
    clearInt();
    uiNumByte--; 
    
    bAck = (bool) readViaI2C(cDataBytes, uiNumByte, "RX via SPI");
    
    /*printf("Rx: ");
    for(int i = 0; i < uiNumByte; i++){
        printf("0x%02x  ", cDataBytes[i]);
    }
    printf("\n");*/
   
    
    int n = 0;
    for(int i = 0;  i < int(uiNumByte/2); i++){
        n = uiNumByte - 1 - i;
        //printf("%d <-> %d\n", i, n);
        cDataBytes[i] = cDataBytes[i] ^ cDataBytes[n];
        cDataBytes[n] = cDataBytes[i] ^ cDataBytes[n];
        cDataBytes[i] = cDataBytes[i] ^ cDataBytes[n];
    }
    
    return bAck;
}



//******************************************************************************//
//
//******************************************************************************//
void SC18IS602::waitFor(bool bInt){
    iTimeOut = 1000;
    
    while((getInt() !=  bInt) and iTimeOut > 0) {
        iTimeOut--;
        wait(1e-3);
    }
    
    if(iTimeOut == 0) printf("TimeOut: Interrupt\n");        
}


//******************************************************************************//
// musst modified
//******************************************************************************//
/*void SC18IS602::setIntFuncPtr( bool (*Int_ptr)(void)){
    getInt_ptr = Int_ptr;
    
}*/