this is a first compilation of a library for IQS5xx. For now, it work with the iqs572ev02 devellopment board. The code is inspired with the sample code provide by Azotech. I have some issu with the interrupt pin RDY, which seem to be high even I don't touch de board.

Dependencies:   mbed

IQS5xx/IQS5xx.cpp

Committer:
skydarc
Date:
2020-01-01
Revision:
2:bd4b620316aa
Parent:
0:4907da2299a4

File content as of revision 2:bd4b620316aa:

/* IQS572.cpp
 * Tested with mbed board: LPC1768
 * Author: skydarc
 * skydarc@gmail.com
 */
 
#include "mbed.h"
#include "IQS5xx.h"
#include <new>


IQS5xx::IQS5xx(PinName sda, PinName scl, PinName rdy) : i2c_(*reinterpret_cast<I2C*>(i2cRaw)), _readyPin(rdy) {
    
    // Placement new to avoid additional heap memory allocation.
    new(i2cRaw) I2C(sda, scl);
    
    //_readyPin.input();
}

//*****************************************************************************
//
//! Acknowledge the reset flag
//!
//! This function simply sets the ACK_RESET bit found in the SYSTEM_CONTROL_0 
//! register.  By setting this bit the SHOW_RESET flag is cleared in the 
//! SYSTEM_INFO_0 register.  During normal operation, the SHOW_RESET bit can be 
//! monitored and if it becomes set, then an unexpected reset has occurred.  
//! If any device configuration is needed, it must then be repeated.
//!
//! \param None
//!
//! \return None
//
//*****************************************************************************
void IQS5xx::AcknowledgeReset(void) {
    static  uint8_t System_ctrl_0 = ACK_RESET;  

    I2C_Write(SystemControl0_adr, &System_ctrl_0, 1);
}

void IQS5xx::checkVersion(void) {
  
    uint8_t ui8DataBuffer[15];  // defaut size : 6
    //
    // Dont wait for RDY here, since the device could be in EventMode, and then
    // there will be no communication window to complete this.  Rather do a 
    // forced communication, where clock stretching will be done on the IQS5xx
    // until an appropriate time to complete the i2c.
    //
    I2C_Read(ProductNumber_adr, &ui8DataBuffer[0] ,6);
  
    printf("Product %d ", (ui8DataBuffer[0]<<8) + ui8DataBuffer[1]); 
    printf("Project %d ", (ui8DataBuffer[2]<<8) + ui8DataBuffer[3]);
    printf("Version %d.%d\n", ui8DataBuffer[4], ui8DataBuffer[5]);
    
    ////////////////////////
    // check other address :
    ////////////////////////
    
    // System Config 1
    ui8DataBuffer[0] = 3; 
    I2C_Write(SystemConfig1_adr, &ui8DataBuffer[0] ,1);
    I2C_Read(SystemConfig1_adr, &ui8DataBuffer[0] ,1);
    printf("System Config : %d\n", ui8DataBuffer[0]); 
      
    // swipe initial distance
    ui8DataBuffer[1] = 150; ui8DataBuffer[0] = 0; 
    I2C_Write(SwipeInitDistance_adr, &ui8DataBuffer[0] ,2);
    I2C_Read(SwipeInitDistance_adr, &ui8DataBuffer[0] ,2);
    printf("Swp init dist. : %d\n", (ui8DataBuffer[0]<<8) + ui8DataBuffer[1]); 
    
    // X resolution
    ui8DataBuffer[1] = 0; ui8DataBuffer[0] = 8; 
    I2C_Write(XResolution_adr, &ui8DataBuffer[0] ,2);
    I2C_Read(XResolution_adr, &ui8DataBuffer[0] ,2);
    printf("X resolution : %d\n", (ui8DataBuffer[0]<<8) + ui8DataBuffer[1]); 
    
    // Yresolution
    ui8DataBuffer[1] = 0; ui8DataBuffer[0] = 8; 
    I2C_Write(YResolution_adr, &ui8DataBuffer[0] ,2);
    I2C_Read(YResolution_adr, &ui8DataBuffer[0] ,2);
    printf("Y resolution : %d\n", (ui8DataBuffer[0]<<8) + ui8DataBuffer[1]);
    
    // Rx mapping
    I2C_Read(RxMapping_adr, &ui8DataBuffer[0] ,10);
    printf("mapping Rx :"); 
    printf(" %d,", ui8DataBuffer[0]);
    printf(" %d,", ui8DataBuffer[1]);
    printf(" %d,", ui8DataBuffer[2]);
    printf(" %d,", ui8DataBuffer[3]);
    printf(" %d,", ui8DataBuffer[4]);
    printf(" %d,", ui8DataBuffer[5]);
    printf(" %d,", ui8DataBuffer[6]);
    printf(" %d\n", ui8DataBuffer[7]);
    
    // Tx mapping
    I2C_Read(TxMapping_adr, &ui8DataBuffer[0] ,10);
    printf("mapping Tx :"); 
    printf(" %d,", ui8DataBuffer[0]);
    printf(" %d,", ui8DataBuffer[1]);
    printf(" %d,", ui8DataBuffer[2]);
    printf(" %d,", ui8DataBuffer[3]);
    printf(" %d,", ui8DataBuffer[4]);
    printf(" %d,", ui8DataBuffer[5]);
    printf(" %d,", ui8DataBuffer[6]);
    printf(" %d\n", ui8DataBuffer[7]);
    
    // total chanel Rx
    ui8DataBuffer[0] = 3; 
    I2C_Write(TotalRx_adr, &ui8DataBuffer[0] ,1);
    I2C_Read(TotalRx_adr, &ui8DataBuffer[0] ,1);
    printf("nombre cannaux Rx : %d\n", ui8DataBuffer[0]); 

    // total chanel Tx
    ui8DataBuffer[0] = 4; 
    I2C_Write(TotalTx_adr, &ui8DataBuffer[0] ,1);
    I2C_Read(TotalTx_adr, &ui8DataBuffer[0] ,1);
    printf("nombre cannaux Tx : %d\n", ui8DataBuffer[0]);  
}

//*****************************************************************************
//
//! Display a snap state change
//!                            
//! If the state of any snap output has changed, then this function can be used
//! to display which Rx/Tx channel has changed status.  
//!                                  
//! \param None
//!                                           
//! \return None
//                                                      
//*****************************************************************************
void IQS5xx::DisplaySnap(void)
{
    uint8_t     ui8Tx, ui8Rx;
    uint16_t    ui16ToggledBits;
    
    for(ui8Tx = 0; ui8Tx < 15; ui8Tx++)
    {
        ui16ToggledBits = ui16PrevSnap[ui8Tx] ^ ui16SnapStatus[ui8Tx];

        for(ui8Rx = 0; ui8Rx < 10; ui8Rx++)
        {
            if(BitIsSet(ui16ToggledBits, ui8Rx))
            {
                if(BitIsSet(ui16SnapStatus[ui8Tx], ui8Rx))
                {
                    printf("Snap set on Rx:");
                }
                else
                {
                    printf("Snap released on Rx:");
                }
                printf(" %d / Tx: %d  channel    \n", ui8Rx, ui8Tx);
            }
        }
    }
}

//*****************************************************************************
//
//! Process the data received
//!                            
//! This function sorts the read bytes from the IQS5xx and prints relevant data 
//! on serial port. 
//! REL_X[n]: Relative X Position of the finger n; n is from (1 to 5)
//! REL_Y[n]: Relative X Position of the finger n; n is from (1 to 5)
//! ABS_X[n]: Absolute X Position of the finger n; n is from (1 to 5)
//! ABS_Y[n]: Absolute Y Position of the finger n; n is from (1 to 5)
//! ui16TouchStrength[n]   : Touch strength of finger n; n is from (1 to 5)
//! ui8Area[n]   : Touch area of finger n; this is number of channels under touch 
//! for a particular finger; 
//! Where 'n' is from (1 to 5)
//!                                  
//! \param None
//!                                           
//! \return None
//                                                      
//*****************************************************************************
void IQS5xx::Process_XY(void) 
{ 
    uint8_t     i; 
    static uint8_t ui8FirstTouch = 0;
    uint8_t     ui8NoOfFingers;
    uint8_t     ui8SystemFlags[2];
    int16_t     i16RelX[6];
    int16_t     i16RelY[6];
    uint16_t    ui16AbsX[6];
    uint16_t    ui16AbsY[6];
    uint16_t    ui16TouchStrength[6];
    uint8_t     ui8Area[6];
 
    ui8SystemFlags[0] = Data_Buff[2];
    ui8SystemFlags[1] = Data_Buff[3];
    ui8NoOfFingers = Data_Buff[4];
    //
    // Re-initialize the device if unexpected RESET detected
    //
    if((ui8SystemFlags[0] & SHOW_RESET) != 0)
    {
        printf("RESET DETECTED\n");
        AcknowledgeReset(); 
        return;
    }

    if((ui8SystemFlags[1] & SNAP_TOGGLE) != 0)
    {
        // A snap state has changed, thus indicate which channel
        //
        DisplaySnap();
        return;
    }

    if((Data_Buff[0]) == SINGLE_TAP) 
    {       
        printf("Single Tap  \n"); 
    }
    else if((Data_Buff[1]) == TWO_FINGER_TAP)   
    {
        printf("2 Finger Tap\n"); 
    }       

    if(ui8NoOfFingers != 0) 
    {
        if (!(ui8FirstTouch)) 
        {
            printf("Gestures:    \n");
            //printf(" RelX: ");
            //printf("RelY: ");
            //printf("Fig: ");
            //printf("X1:  "); printf("Y1:  "); printf("TS1: "); printf("TA1: ");
            //printf("X2:  "); printf("Y2:  "); printf("TS2: "); printf("TA2:\n");
            //printf("X3:  "); printf("Y3:  "); printf("TS3: "); printf("TA3: ");
            //printf("X4:  "); printf("Y4:  "); printf("TS4: "); printf("TA4: ");
            //printf("X5:  "); printf("Y5:  "); printf("TS5: "); printf("TA5: \n");
            ui8FirstTouch = 1;
        }

        switch (Data_Buff[0])
        {
            case SINGLE_TAP     :   printf("Single Tap  \n"); 
                                    break;
            case TAP_AND_HOLD   :   printf("Tap & Hold  \n"); 
                                    break;
            case SWIPE_X_NEG    :   printf("Swipe X-    \n"); 
                                    break;
            case SWIPE_X_POS    :   printf("Swipe X+    \n"); 
                                    break;
            case SWIPE_Y_POS    :   printf("Swipe Y+    \n"); 
                                    break;
            case SWIPE_Y_NEG    :   printf("Swipe Y-    \n"); 
                                    break;
        }

        switch (Data_Buff[1])
        {
            case TWO_FINGER_TAP :   printf("2 Finger Tap\n"); 
                                    break;
            case SCROLL         :   printf("Scroll      \n"); 
                                    break;
            case ZOOM           :   printf("Zoom        \n"); 
                                    break;
        }
        if((Data_Buff[0] | Data_Buff[1]) == 0) 
        {
            //printf("            ");
        }

        /*i16RelX[1] = ((Data_Buff[5] << 8) | (Data_Buff[6]));
        i16RelY[1] = ((Data_Buff[7] << 8) | (Data_Buff[8]));
        
        Print_signed(i16RelX[1]);
        Print_signed(i16RelY[1]);
        Print_unsigned(ui8NoOfFingers);    

        for (i = 0; i < 2; i++)
        {
            ui16AbsX[i+1] = ((Data_Buff[(7*i)+9] << 8) | (Data_Buff[(7*i)+10])); //9-16-23-30-37//10-17-24-31-38
            ui16AbsY[i+1] = ((Data_Buff[(7*i)+11] << 8) | (Data_Buff[(7*i)+12])); //11-18-25-32-39//12-19-26-33-40
            ui16TouchStrength[i+1] = ((Data_Buff[(7*i)+13] << 8) | (Data_Buff[(7*i)+14])); //13-20-27-34-11/14-21-28-35-42
            ui8Area[i+1] = (Data_Buff[7*i+15]); //15-22-29-36-43
            
            Print_unsigned(ui16AbsX[i+1]);
            Print_unsigned(ui16AbsY[i+1]);
            Print_unsigned(ui16TouchStrength[i+1]);
            Print_unsigned(ui8Area[i+1]);
        }
        printf("");*/
    } 
    else 
    {
        ui8FirstTouch = 0;
    }
}

//*****************************************************************************
//
//! Terminate communication window
//!                            
//! The IQS5xx B000 does not close the communication window on the reception of 
//! the STOP bit; therefore this function sends the END COMMUNICATION WINDOW 
//! COMMAND (Please see datasheet for more information). RDY will go low after 
//! receiving any write to 0xEEEE followed by a STOP. 
//!                                  
//! \param None
//!                                           
//! \return None
//                                                      
//*****************************************************************************
void IQS5xx::Close_Comms() 
{
  uint8_t ui8DataBuffer[1];
  
  I2C_Write(END_WINDOW, &ui8DataBuffer[0], 1);
}

//*****************************************************************************
//
//! I2C write function
//!
//! This function writes the provided data to the address specified.  If  
//! anything in the write process is not successful, then it will be repeated
//! up till four more times.  If still not successful, it will write an error
//! message on the serial terminal.
//!
//! \param ui16RegisterAddress is the 16-bit memory map address on the IQS5xx
//! \param pData is a pointer to the first byte of a block of data to write
//! \param ui8NoOfBytes indicates how many bytes of data to write
//!
//! \return Boolean indicating success/fail of write attempt
//
//*****************************************************************************
uint8_t IQS5xx::I2C_Write(uint16_t ui16RegisterAddress, uint8_t *pData, uint8_t ui8NoOfBytes) {
    
    uint8_t ui8Retry = 4;
    
    ui8Success = I2C_Write2(ui16RegisterAddress, pData, ui8NoOfBytes);
    
    //
    // If comms was not successful, retry 4 more times
    //
    while((!ui8Success) && (ui8Retry != 0))
    {
        wait_ms(5);
        ui8Success = I2C_Write2(ui16RegisterAddress, pData, ui8NoOfBytes);
        ui8Retry--;
    }
    
    if(ui8Success) return(true);
    else {
        printf("Comms write error\n");
        return(false);
    }
}

//*****************************************************************************
//
//! I2C read function
//!
//! This function reads data from the address specified and stores this data
//! in the area provided by the pointer.  If anything in the read process is 
//! not successful, then it will be repeated up till four more times.  
//! If still not successful, it will write an error message on the serial 
//! terminal.
//!
//! \param ui16RegisterAddress is the 16-bit memory map address on the IQS5xx
//! \param pData is a pointer to where the read data must be stored
//! \param ui8NoOfBytes indicates how many bytes of data to read
//!
//! \return Boolean indicating success/fail of read attempt
//
//*****************************************************************************
uint8_t IQS5xx::I2C_Read(uint16_t ui16RegisterAddress, uint8_t *pData, uint8_t ui8NoOfBytes) {
    
    uint8_t ui8Retry = 4;
    
    ui8Success = I2C_Read2(ui16RegisterAddress, pData, ui8NoOfBytes);
    
    //
    // If comms was not successful, retry 4 more times
    //
    while((!ui8Success) && (ui8Retry != 0)) {
        wait_ms(5);
        ui8Success = I2C_Read2(ui16RegisterAddress, pData, ui8NoOfBytes);
        ui8Retry--;
    }
    
    if(ui8Success) return(true);
    else {
        printf("Comms read error\n");
        return(false);
    }
}

uint8_t IQS5xx::I2C_Write2(uint16_t ui16RegisterAddress, uint8_t *pData, uint8_t ui8NoOfBytes)
{
    uint8_t i;
    
    i2c_.start();

    if(i2c_.write(IQS5xx_ADDR<<1) == false) return(false);
    
    if(i2c_.write((uint8_t)(ui16RegisterAddress>>8)) == false) return(false);
    if(i2c_.write((uint8_t)ui16RegisterAddress) == false) return(false);
    
    for(i = 0; i < ui8NoOfBytes; i++) {       
        if(i2c_.write(*pData) == false) return(false);
        pData++;
    }

    i2c_.stop();
    
    return(true);
}

uint8_t IQS5xx::I2C_Read2(uint16_t ui16RegisterAddress, uint8_t *pData, uint8_t ui8NoOfBytes) {
    
    uint8_t i;
    
    if(ui8NoOfBytes == 0) ui8NoOfBytes++;
    
    i2c_.start();
    
    if(i2c_.write(IQS5xx_ADDR<<1) == false) return(false);
    
    if(i2c_.write((uint8_t)(ui16RegisterAddress>>8)) == false) return(false);
    if(i2c_.write((uint8_t)ui16RegisterAddress) == false) return(false);
    
    i2c_.start();
    
    if(i2c_.write((IQS5xx_ADDR<<1) + 0x01) == false) return(false);
    
    for(i = 0; i < ui8NoOfBytes; i++)
    {
        if(i == (ui8NoOfBytes - 1)) {
            *pData = i2c_.read(0);
        }
        else {
            *pData = i2c_.read(1);
        }
        pData++;
    }
    
    i2c_.stop();
    
    return(true);
}

//*****************************************************************************
//
//! Print a signed value on serial display
//!                            
//! Print the signed integer on the serial port with adjusted tabs 
//! on serial port for easy column reading. 
//!                                  
//! \param None
//!                                           
//! \return None
//                                                      
//*****************************************************************************
void IQS5xx::Print_signed(int16_t i16Num)
{
    if(i16Num < (-99))
    {
        printf(" ");
    }
    else if(i16Num < (-9))
    {
        printf("  ");
    }
    else if(i16Num < 0)
    {
        printf("   ");
    }
    else if(i16Num < 10)
    {
        printf("    ");
    }
    else if(i16Num < 100)
    {
        printf("   ");
    }
    else if(i16Num < 1000)
    {
        printf("  ");
    }
    printf("%d", i16Num);
}

//*****************************************************************************
//
//! Print an unsigned value on serial display
//!                            
//! Print the unsigned integer on the serial port with adjusted tabs 
//! on serial port for easy column reading. 
//!                                  
//! \param None
//!                                           
//! \return None
//                                                      
//*****************************************************************************
void IQS5xx::Print_unsigned(uint16_t ui16Num)
{
    if(ui16Num < 10)
    {
        printf("    ");
    }
    else if(ui16Num < 100)
    {
        printf("   ");
    }
    else if(ui16Num < 1000)
    {
        printf("  ");
    }
    else if(ui16Num < 10000)
    {
        printf(" ");
    }

    if(ui16Num > 10000)
    {
        printf("  xxx");
    }
    else
    {
        printf("%d", ui16Num);
    }
}