This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TouchKey_TAC8418 , I2C read issue

Other Parts Discussed in Thread: TCA8418

If the device use Key pad to read TAC8418 faster via I2C bus, the device will crash.  (I2C timeout)

1) How to clear TAC8418 buffer? (Key press event)

2) Could you provide any suggestion?

Best Regards,

  • Hello Hoo,

    Thanks for the question.

    1) To clear the buffer, the process depends on how you have the device set up. If you are using keyscan mode, you must first read the FIFO register A ( register 0x04) until you get 0x00 from it. Then you will need write a 0xFF to INT_STAT (0x02) to clear the interrupt status bits. If your FIFO is empty and your GPIO_INT_STAT registers are all 0x00, then the device will deassert (release) the INT pin and allow it to rise.

    If you are NOT using keyscan mode, then you simply need to read the GPIO_INT_STAT registers, unless you activated GPI events in the FIFO, then you need to do what I outlined above plus reading the GPIO_INT_STAT registers before writing 0xFF to 0x02.

    2) I can provide help with your device crashing issue, but I will need some more information. Could you explain what you mean by read TCA8418 faster? The device will operate on the I2C bus up to 400kHz. What are you steps that you take to make the device crash and I assume you mean the device NACKs when you address it? Also, do you have a schematic I could look at to better help you?

  • Hello  ,

    My devices are using key scan mode now.

    If the user press any key over 10 times in some function processing.

    The is code processing flow.

    1) Key A event

    2) function A processing.

    3) Key A,B,C,D... event over 10 times.

    4) function A done.

    5) Key read the FIFO register A until 10 times  or FIFO register = 0, delay 30ms per read. (For clear FIFO buffer)

    6) function done.

    7) The device is sometime crash.

    Please give me any suggestion. Thank you.

    Best Regards,

  • Hoo,

    Can you double check and make sure that your debouncing registers are enabled by setting them to 0? Registers 0x29 to 0x2B should all be set to 0x00 (this enables debouncing).

    If you hit the keys fast enough, it is possible you are filling the FIFO, if your FIFO is filled, then the device will not accept any new key presses until you clear the OVR_FLOW_INT bit in the INT_STAT register.
  • Hi Jonathan,

    I thought Keypad Lock/Unlock can solve my issue.

    I tried to set Configuration Register (Address 0×01) , K_LCK_IEN |= 0x04.

    Then , I read Configuration Register , K_LCK_IEN(bit2) = 1.

    Then , I hit key pad , KEY_EVENT_A != 0x00. The KEY_EVENT_A  didn't work.

    //=========================

    void I2C_KEYPad_LOCK()
    {
    Uint16 u16_Value = 0;
    Uint16 u16_I2C_LEY_Buf1 = 0;
    Uint16 rdData[2];
    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_CFG, (Uint16 *)&rdData);
    u16_Value = (u16_I2C_LEY_Buf1 | 0x04);
    I2C_KEY_Writer(I2C_KEY_SLAVEADDR , REG_CFG , u16_Value);
    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_CFG, (Uint16 *)&rdData);
    }

    //=========================

    Could you please give me suggestion what's the cause?

    How to prevent the generation of key event interrupts and recorded key events?

    Per 9.2.1.1 Keypad Lock/Unlock description as below.

    This user can lock the keypad through the lock/unlock feature in this device. Once the keypad is locked, it can

    prevent the generation of key event interrupts and recorded key events. The unlock keys can be programmed

    with any value of the keys in the keypad matrix or any GPI values that are part of the key event table. When the

    keypad lock interrupt mask timer is enabled, the user will need to press two specific keys before an keylock

    interrupt is generated or keypad events are recorded. After the keypad is locked, a key event interrupt is

    generated any time a user presses a key. This first interrupt also triggers the processor to turn on the LCD and

    display the unlock message. The processor will then read the lock status register to see if the keypad is

    unlocked. The next interrupt (keylock interrupt) will not be generated unless both unlock keys sequences are

    correct. If correct Unlock keys are not pressed before the mask timer expires, the state machine will start over

    again.

    Best Regards,

  • Hello Hoo,

    Excuse my delay, I am out of the office on business travel currently.

    I think you have a mis understanding of the descriptions.

    When you wrote K_LCK_IEN, you merely enabled key lock interrupt, which allows interrupts to be sent to alert the processor that a keypad has been unlocked or locked. It does not force a keypad lock.

    I currently do not have access to the materials required to walk you through all the steps to setup the keypad (since i'm out of office). I will have to get back to you on this.

    In short, what I do remember off the top of my head is that you must enable the keypad lock. Once th ekeypad is locked, you set the two unlock registers for the key presses you want to unlock th ekeypad.

    There is a register that controls the timing of these interrupts, and if you wish for the TCA8418 to send you no interrupts at all, you must set these to 0. This feature of sending 1 interrupt is aimed at phones, where the user may have a locked keypad, but they still want a button press to turn on the screen.

  • Hoo,

    So, I was able to find some information.

    So the way that you actually set the keypad lock is with a few registers.
    First, you will need to know the keys you wish to unlock the keypad (on the keymap) and enter the keymap values into the Unlock 1 and Unlock 2 registers (registers 0x0F, 0x10) to program the key sequence you wish to unlock the keypad.

    Then you will need to set the interrupt mask and timer values in Register 0x0E. Bits 2:0 are the lock 1 to lock 2 timer, which is a timer which is used to set the maximum amount of time allowed between the 2 unlock key combination to unlock the keypad in seconds [0 to 7 seconds, 0 is disabled/infinite time]). Bits 7:3 are used for letting a display get turned on by an interrupt. You should set this to 0 if you do not wish to have any interrupts fire until your keypad unlock has been triggered.

    Then in register 0x03, set bit 6 (K_LCK_EN) to actually enable the lock.
  • Hi Jonathan ,

    I tried set lock , it didn't work yet.

    main()
    {
    I2C_init(); // REG_KP_LCK_TIMER |= 0x07

    while(1)
    {
    if(KeyValue == Left)
    {
    Key_lock(); // REG_KEY_LCK_EC |= 0x40
    }

    }


    }


    Could you please provide an sample code for KEY lock/unlock?


    1) I2C_init()

    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_KP_LCK_TIMER, (Uint16 *)&rdData);
    u16_Value = (u16_I2C_LEY_Buf1 | 0x07);
    I2C_KEY_Writer(I2C_KEY_SLAVEADDR , REG_KP_LCK_TIMER , u16_Value);
    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_KP_LCK_TIMER, (Uint16 *)&rdData);

    2) Key_lock

    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_KEY_LCK_EC, (Uint16 *)&rdData);
    u16_Value = (u16_I2C_LEY_Buf1 | 0x40);
    I2C_KEY_Writer(I2C_KEY_SLAVEADDR , REG_KEY_LCK_EC , u16_Value);
    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_KEY_LCK_EC, (Uint16 *)&rdData);

    3) Key_unlock

    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_UNLOCK1, (Uint16 *)&rdData);
    u16_Value &= (0xFF);
    I2C_KEY_Writer(I2C_KEY_SLAVEADDR , REG_UNLOCK1 , u16_Value);
    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_UNLOCK1, (Uint16 *)&rdData);

    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_UNLOCK2, (Uint16 *)&rdData);
    u16_Value &= (0xFF);
    I2C_KEY_Writer(I2C_KEY_SLAVEADDR , REG_UNLOCK2 , u16_Value);
    u16_I2C_LEY_Buf1 = I2C_KEY_Reader((Uint16)REG_UNLOCK2, (Uint16 *)&rdData);
  • Hello Hoo,

    I am out of the office until Friday. We do not have any sample code of this function, but I will help you with the procedure needed to execute this.

    Perhaps you did not include it in your code, but I do not see a KeyValue variable defined anywhere, and it would seem that the key_lock() function never gets called as a result?

    In your key_init function, you should just set the u16_value to = 0x03 instead of ORing it with 0x07. We want the interrupt mask to be 0, you set it to 1 second.

  • Hi Jonathan ,

    If u16_value = 0x03 at key_init , it should be Lock1 only.

    TCA8418 datasheet is discription , KP_LCK_TIMER / KL[2:0] are for the Lock1 to Lock2 timer.

    Should I set Lock1 only?

    What is  interrupt mask to be 0,you set it to 1 second? Is it mean REG_KEY_LCK_EC / bit6 ?

    Please kindly guide me the init and process flow for TCA8418 Lock and un-Lock function.

    Below is key define.

    #define REG_CFG 0x01

    #define REG_INT_STAT 0x02
    #define REG_KEY_LCK_EC 0x03
    #define REG_KEY_EVENT_A 0x04
    #define REG_KEY_EVENT_B 0x05
    #define REG_KP_LCK_TIMER 0x0E
    #define REG_UNLOCK1 0x0F
    #define REG_UNLOCK2 0x10

    Best Regards,

  • Hi Jonathan ,

    I tried these setting as below.
    My device is loop in DDC_i2cTransfer(); // Please refer DDC_i2cTransfer code
    I cannot set un-lock command to I2C bus.

    while (cnt < bufLen) // If set key lock , it will loop in cnt < bufLen forever...
    {
    ...
    }



    #define Left 0x80
    main()
    {
    Uint16 KeyValue = 0;

    I2C_init();


    while(1)
    {
    KeyValue = GetKeyValue();
    if(KeyValue == Left)
    {
    Key_lock(); // REG_KEY_LCK_EC |= 0x40
    }

    }

    }





    Best Regards,

  • Hello Hoo,

    My mistake. Register 0x0E should be set to 0x07 (although 0x03 would work too). We want bits[7:3] = 0 and bits [2:0] > 0. Bits 7:3 are for a functionality that i don't believe you are using. It will send an interrupt when the keypad is locked if this time has experienced if a button is pressed, the example use case of this is the following: This device is in a phone with a screen. The screen turns off the backlight after 10 seconds, so you should put 10 into bits 7:3. The keypad gets locked, and the display sits by for 10 seconds then turns off. At soem point down the road, a button is pressed and the 8418 will see that 10 seconds have passed since the last interrupt was sent, so it will send an interrupt to the processor just so that the backlight screen can come on. No interrupts will be sent for another 10 seconds or until the unlock combination is pressed.

    Bits 2:0 are for setting the maximum time allowed between button pushes to unlock it. So let's say your Unlock 1 register = 21 and unlock 2 = 22. 0x0E[2:0] = 7 would mean that after you press key 21, you have 7 seconds to press key 22 to unlock the keyboard.

    I am having difficulty reading your code, I'm not familiar with the device you're writing this for.

    While looking at your while loop, I think that the issue might be that your interrupt mask time is set to non 0, so you get an interrupt and the FIFO is empty, and the software doesn't handle this.

    Make sure register 0x0E (Kp_lck_timer) is set to 0x07. Don't OR it with the contents, just statically set it to 0x07 and try again.
  • Hi Jonathan Valdez,

    The lock / un-lock function cannot work.
    Please provide process flow of code programming for lock/un-lock.

    For lock,
    What register need to set?

    For un-lock,
    What register need to set?
  • Hello Hoo,

    Now that I am in the office,I am able to test this myself to verify operation.

    As such, I just double checked to verify the following:

    To lock: You need to write a 1 to bit 6 (0x40) in register 0x03 (KEY_LCK_EC). Doing this will immediately lock the keyboard.

    To unlock: You may either write a 0 to bit 6 in register 0x03, or you may use the keypress combination.

     To program the unlock keys, you must program registers 0x0F and 0x10 (Unlock 1 and 2) to tell the device which key combination can unlock it. See below table for key values from datasheet on page 29:

    Lets say you want the key connect to C0 and R0 to be the first button press required (key 1), you would write 0x01 to register 0x0F.

    Then lets say you want the 2nd key press to be key 23 (R2 and C2), you would write 0x17 to register 0x10.

    Once these two registers are programmed and you have locked the keypad (write 0x40 to register 0x03), you won't get any interrupts until you press key 1 then 23. Once you press these two, you will get an interrupt (assuming you have K_LCK_IEN bit set in 0x01 register) letting you know an unlock has occured (can be checked by looking to see if Bits 5 and 4 in register 0x03 are 0 or 1 to signify whether its locked). Then any further key presses will send interrupts as expected until you lock the keyboard again.