/*! \fn     getTouchedPositionAnswer(uint8_t led_mask)
*   \brief  Use the capacitive interface to get quarter position
*   \param  led_mask    Led mask for the touchdetection routine
*   \return Number between 0 and 5 for valid pos, -1 otherwise
*/
int8_t getTouchedPositionAnswer(uint8_t led_mask)
{
    #ifdef HARDWARE_V1
        _delay_ms(2000);
    #endif
    #if defined(ALWAYS_ACCEPT_REQUESTS) || defined(HARDWARE_V1)
        // First quarter is discarded, it means we want yes or no!
        if (led_mask & LED_MASK_WHEEL_TLEFT)
        {
            return TOUCHPOS_RIGHT;
        }
        else
        {
            return TOUCHPOS_WHEEL_TLEFT;
        }
    #endif

    RET_TYPE touch_detect_result;
    
    // Switch on lights
    activityDetectedRoutine();
    
    // Clear possible remaining detection
    touchDetectionRoutine(led_mask);
    touchWaitForWheelReleased();
    touchClearCurrentDetections();
    
    // Wait for a touch press, delay stored in eeprom (1024 is quite close to 1000 ;-) )
    activateTimer(TIMER_USERINT, ((uint16_t)controlEepromParameter(getMooltipassParameterInEeprom(USER_INTER_TIMEOUT_PARAM), MIN_USER_INTER_DEL/1000, MAX_USER_INTER_DEL/1000)) << 10);
    do
    {
        // User interaction timeout or smartcard removed
        if ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED) || (isSmartCardAbsent() == RETURN_OK))
        {
            return -1;
        }
        touch_detect_result = touchDetectionRoutine(led_mask) & TOUCH_PRESS_MASK;
    }
    while (!touch_detect_result);
    
    // Did the user press one of the two touch buttons?
    if (touch_detect_result & RETURN_LEFT_PRESSED)
    {
        return TOUCHPOS_LEFT;
    }
    else if (touch_detect_result & RETURN_RIGHT_PRESSED)
    {
        return TOUCHPOS_RIGHT;
    }
    else
    {
        return (int8_t)getWheelTouchDetectionQuarter();
    }
}
/*! \fn     touchDetectionRoutine(uint8_t led_mask)
*   \brief  Touch detection routine
*   \param  led_mask    Mask containing which LEDs to switchoff
*   \return Touch detection result (see touch_detect_return_t)
*/
RET_TYPE touchDetectionRoutine(uint8_t led_mask)
{
    RET_TYPE return_val = RETURN_NO_CHANGE;
    uint8_t keys_detection_status;
    uint8_t led_states[NB_KEYS];
    uint8_t temp_bool = FALSE;
    uint8_t temp_uint;
    
    // Set the LEDs on by default
    memset((void*)led_states, AT42QT2120_OUTPUT_H_VAL, NB_KEYS);
    
    // Switch them off depending on mask    
    for (temp_uint = 0; temp_uint < NB_KEYS; temp_uint++)
    {
        if (led_mask & (1 << temp_uint))
        {
            led_states[temp_uint] = AT42QT2120_OUTPUT_L_VAL;
        }
    }
    
    if (isTouchChangeDetected())
    {
        // Set temp bool to TRUE
        temp_bool = TRUE;
        
        // Read detection status register
        readDataFromTS(REG_AT42QT_DET_STAT, &keys_detection_status);
        
        // Unused byte that needs to be read        
        readDataFromTS(REG_AT42QT_KEY_STAT1, &temp_uint);
        
        // If wheel is touched
        if (keys_detection_status & AT42QT2120_SDET_MASK)
        {
            // Get position and update global var
            readDataFromTS(REG_AT42QT_SLIDER_POS, &last_raw_wheel_position);
            
            // Update LED states
            led_states[getWheelTouchDetectionQuarter()] = AT42QT2120_OUTPUT_L_VAL;
            return_val |= RETURN_WHEEL_PRESSED;
        }
        else
        {
            return_val |= RETURN_WHEEL_RELEASED;
        }

        // Read button touched register
        readDataFromTS(REG_AT42QT_KEY_STAT2, &temp_uint);
        
        // If one button is touched
        if ((keys_detection_status & AT42QT2120_TDET_MASK) && !(keys_detection_status & AT42QT2120_SDET_MASK))
        {
            if (temp_uint & 0x02)
            {
                // Left button
                led_states[TOUCHPOS_LEFT] = AT42QT2120_OUTPUT_L_VAL;
                return_val |= RETURN_LEFT_PRESSED;
                return_val |= RETURN_RIGHT_RELEASED;
            }
            else if(temp_uint & 0x08)
            {
                // Right button
                led_states[TOUCHPOS_RIGHT] = AT42QT2120_OUTPUT_L_VAL;
                return_val |= RETURN_RIGHT_PRESSED;
                return_val |= RETURN_LEFT_RELEASED;
            }
            else
            {
                return_val |= RETURN_PROX_DETECTION;
            }
        }
        else
        {
            return_val |= RETURN_PROX_RELEASED;
            return_val |= RETURN_LEFT_RELEASED;
            return_val |= RETURN_RIGHT_RELEASED;
        }
        
        // Switch on cathode if activity
        if (return_val & TOUCH_PRESS_MASK)
        {
            activityDetectedRoutine();
        }
        
        // Touch inhibit logic
        if ((return_val & TOUCH_PRESS_MASK) == 0)
        {
            touch_inhibit = FALSE;
        } 
        else if (touch_inhibit == TRUE)
        {
            return_val = RETURN_NO_CHANGE;
        }
    }    
    
    // If there's a touch change or led mask has changed
    if ((temp_bool == TRUE) || (led_mask != last_led_mask))
    {
        last_led_mask = led_mask;
        writeDataToTS(LEFT_LED_REGISTER, led_states[TOUCHPOS_LEFT]);
        writeDataToTS(RIGHT_LED_REGISTER, led_states[TOUCHPOS_RIGHT]);
        writeDataToTS(WHEEL_TLEFT_LED_REGISTER, led_states[TOUCHPOS_WHEEL_TLEFT]);
        writeDataToTS(WHEEL_TRIGHT_LED_REGISTER, led_states[TOUCHPOS_WHEEL_TRIGHT]);
        writeDataToTS(WHEEL_BLEFT_LED_REGISTER, led_states[TOUCHPOS_WHEEL_BLEFT]);
        writeDataToTS(WHEEL_BRIGHT_LED_REGISTER,  led_states[TOUCHPOS_WHEEL_BRIGHT]);
        // In some rare cases LED state changes can create detections. In that case we add a small delay
        timerBasedDelayMs(2);
        touchClearCurrentDetections();
    }
    
    return return_val;   
}
/*! \fn     loginSelectionScreen(void)
*   \brief  Screen displayed to let the user choose/find a login
*   \return Valid child node address or 0 otherwise
*/
uint16_t loginSelectionScreen(void)
{
    char currentText[SEARCHTEXT_MAX_LENGTH+1];
    uint8_t displayRefreshNeeded = TRUE;
    uint16_t ret_val = NODE_ADDR_NULL;
    uint8_t wasWheelReleased = TRUE;
    uint16_t tempParentAddresses[5];
    uint8_t currentStringIndex = 0;
    uint8_t nbMatchedParents= 0;
    uint8_t finished = FALSE;
    RET_TYPE temp_rettype;
    uint8_t led_mask = 0;
    int8_t temp_int8;
    
    // Set current text to a
    last_matching_parent_addr = NODE_ADDR_NULL;
    last_matching_parent_number = 0;
    memcpy(currentText, "a\x00\x00\x00\x00", sizeof(currentText));
    
    // Draw bitmap, display it and write active buffer
    oledBitmapDrawFlash(0, 0, BITMAP_LOGIN_FIND, 0);
    oledDisplayOtherBuffer();
    oledWriteActiveBuffer();
    
    // While the user hasn't chosen a credential
    while(!finished)
    {
        if (displayRefreshNeeded == TRUE)
        {
            nbMatchedParents = displayCurrentSearchLoginTexts(currentText, tempParentAddresses, currentStringIndex);
            displayRefreshNeeded = FALSE;
            
            // Light only the available choices and right arrow
            led_mask = 0;
            for (temp_int8 = nbMatchedParents; temp_int8 < 5; temp_int8++)
            {
                led_mask |= (1 << temp_int8);
            }
        }
        
        // Detect key touches
        temp_rettype = touchDetectionRoutine(led_mask);
        
        // Algo to differentiate a tap from a scroll
        if ((temp_rettype & RETURN_WHEEL_PRESSED) && (wasWheelReleased == TRUE))
        {
            // We use the timer dedicated to touch inhibit for min
            activateTimer(TIMER_TOUCH_INHIBIT, TAP_MIN_DEL);
            // We use the timer dedicated to caps detect for max
            activateTimer(TIMER_CAPS, TAP_MAX_DEL);
            // This works because we use the same clearing flags 
            wasWheelReleased = FALSE;
        }
        else if (temp_rettype & RETURN_WHEEL_RELEASED)
        {
            // Check if it's a tap and that the selected domain is valid
            if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_RUNNING) && (hasTimerExpired(TIMER_TOUCH_INHIBIT, FALSE) == TIMER_EXPIRED) && (getWheelTouchDetectionQuarter() < nbMatchedParents))
            {
                ret_val = tempParentAddresses[getWheelTouchDetectionQuarter()];
                finished = TRUE;
            }
            wasWheelReleased = TRUE;
        }
        
        // Send it to the touch wheel interface logic
        temp_int8 = touchWheelIntefaceLogic(temp_rettype);

        // Position increment / decrement
        if (temp_int8 != 0)
        {
            if ((currentText[currentStringIndex] == 0x7A) && (temp_int8 == 1))
            {
                // z->0 wrap
                currentText[currentStringIndex] = 0x2F;
            }
            if ((currentText[currentStringIndex] == 0x39) && (temp_int8 == 1))
            {
                // 9->a wrap
                currentText[currentStringIndex] = 0x60;
            }
            else if ((currentText[currentStringIndex] == 0x30) && (temp_int8 == -1))
            {
                // 0->z wrap
                currentText[currentStringIndex] = 0x7B;
            }
            else if ((currentText[currentStringIndex] == 0x61) && (temp_int8 == -1))
            {
                // a->9 wrap
                currentText[currentStringIndex] = 0x3A;
            }
            currentText[currentStringIndex] += temp_int8;
            displayRefreshNeeded = TRUE;
        }
        
        if ((isSmartCardAbsent() == RETURN_OK) || (hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED))
        {
            // Smartcard removed or no interaction for a while
            finished = TRUE;
        }
        else if (temp_rettype & RETURN_LEFT_PRESSED)
        {
            // Change search index
            if (currentStringIndex > 0)
            {
                currentText[currentStringIndex--] = 0;
                displayRefreshNeeded = TRUE;
            } 
            else
            {
                finished = TRUE;
            }
        }
        else if ((temp_rettype & RETURN_RIGHT_PRESSED) && (nbMatchedParents > 4))
        {
            // Change search index only if we need to...
            currentText[++currentStringIndex] = 'a';
            displayRefreshNeeded = TRUE;
        }
    }
    
    // Set inactive buffer write by default
    oledWriteInactiveBuffer();
    
    return ret_val;
}    
/*! \fn     guiScreenLoop(uint8_t input_interface_result)
*   \brief  Function called to handle screen changes
*   \param  input_interface_result Touch detection result
*/
void guiScreenLoop(uint8_t input_interface_result)
{
    #if defined(MINI_VERSION)
        // If no press, you can return!
        if ((input_interface_result == WHEEL_ACTION_NONE) || (currentScreen == SCREEN_DEFAULT_INSERTED_INVALID) || (currentScreen == SCREEN_DEFAULT_INSERTED_UNKNOWN))
        {
            return;
        }

        if (currentScreen == SCREEN_DEFAULT_NINSERTED)
        {
            // No smart card inserted, ask the user to insert one
            guiDisplayInsertSmartCardScreenAndWait();
        }
        else if (currentScreen == SCREEN_MEMORY_MGMT)
        {
            // Currently in memory management mode, tell the user to finish it via the plugin/app
            guiDisplayInformationOnScreenAndWait(ID_STRING_CLOSEMEMMGMT);
            guiGetBackToCurrentScreen();
        }
        else if (currentScreen == SCREEN_DEFAULT_INSERTED_LCK)
        {
            // Locked screen and a detection happened, check that the user hasn't removed his card, launch unlocking process
            if ((cardDetectedRoutine() == RETURN_MOOLTIPASS_USER) && (validCardDetectedFunction(0) == RETURN_VCARD_OK))
            {
                // User approved his pin
                currentScreen = SCREEN_DEFAULT_INSERTED_NLCK;
            }
            
            // Go to the new screen
            guiGetBackToCurrentScreen();
        }
        else
        {
            if (input_interface_result == WHEEL_ACTION_UP)
            {
                // We can do that because of defines and bitmap order (see logic_fw_flash_storage and gui.h)
                if (currentScreen == SCREEN_LOCK)
                {
                    currentScreen = SCREEN_SETTINGS;
                } 
                else if (currentScreen == SCREEN_SETTINGS_CHANGE_PIN)
                {
                    currentScreen = SCREEN_SETTINGS_ERASE;
                }
                else
                {
                    currentScreen--;
                }
                // We can do that because of defines and bitmap order (see logic_fw_flash_storage and gui.h)
                for (uint8_t i = 0; i < NB_BMPS_PER_TRANSITION; i++)
                {
                    oledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK+NB_BMPS_PER_TRANSITION-1-i, OLED_SCROLL_FLIP);
                    timerBasedDelayMs(25);
                }
            }
            else if (input_interface_result == WHEEL_ACTION_DOWN)
            {
                // We can do that because of defines and bitmap order (see logic_fw_flash_storage and gui.h)
                for (uint8_t i = 0; i < NB_BMPS_PER_TRANSITION-1; i++)
                {
                    oledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK+1+i, OLED_SCROLL_FLIP);
                    timerBasedDelayMs(25);
                }
                if (currentScreen == SCREEN_SETTINGS)
                {
                    currentScreen = SCREEN_LOCK;
                }
                else if (currentScreen == SCREEN_SETTINGS_ERASE)
                {
                    currentScreen = SCREEN_SETTINGS_CHANGE_PIN;
                }
                else
                {
                    currentScreen++;
                }
                oledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_FLIP);              
            }
            else if (input_interface_result == WHEEL_ACTION_LONG_CLICK)
            {
                // Long press in main menu : lock, long press in settings menu: go back to login screen
                if ((currentScreen >= SCREEN_SETTINGS_CHANGE_PIN) && (currentScreen <= SCREEN_SETTINGS_ERASE))
                {
                    currentScreen = SCREEN_LOGIN;
                    oledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_UP);
                } 
                else
                {                    
                    currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                    handleSmartcardRemoved();
                    guiGetBackToCurrentScreen();
                }
            }
            else if (input_interface_result == WHEEL_ACTION_SHORT_CLICK)
            {
                switch(currentScreen)
                {
                    case SCREEN_LOCK:
                    {
                        // User wants to lock his mooltipass
                        currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                        handleSmartcardRemoved();
                        guiGetBackToCurrentScreen();
                        break;
                    }
                    case SCREEN_LOGIN:
                    {
                        // User wants to go to the login menu
                        if (getStartingParentAddress() != NODE_ADDR_NULL)
                        {
                            loginSelectLogic();
                        }
                        else
                        {
                            guiDisplayInformationOnScreenAndWait(ID_STRING_NO_CREDS);
                        }
                        guiGetBackToCurrentScreen();
                        break;
                    }
                    case SCREEN_FAVORITES:
                    {
                        // User wants to go to the favorite menu
                        favoritePickingLogic();
                        guiGetBackToCurrentScreen();
                        break;
                    }
                    case SCREEN_SETTINGS:
                    {
                        currentScreen = SCREEN_SETTINGS_CHANGE_PIN;
                        oledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_UP);
                        break;
                    }
                    case SCREEN_SETTINGS_HOME:
                    {
                        currentScreen = SCREEN_LOGIN;
                        oledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_UP);
                        break;
                    }
                    case SCREEN_SETTINGS_CHANGE_PIN:
                    {
                        // User wants to change his PIN code
                        
                        // Reauth user
                        if (removeCardAndReAuthUser() == RETURN_OK)
                        {
                            // User approved his pin, ask his new one
                            volatile uint16_t pin_code;
                            
                            if (guiAskForNewPin(&pin_code, ID_STRING_NEW_PINQ) == RETURN_NEW_PIN_OK)
                            {
                                // User successfully entered a new pin
                                writeSecurityCode(&pin_code);
                                // Inform of success
                                guiDisplayInformationOnScreenAndWait(ID_STRING_PIN_CHANGED);
                            }
                            else
                            {
                                // Inform of fail
                                guiDisplayInformationOnScreenAndWait(ID_STRING_PIN_NCGHANGED);
                            }
                            pin_code = 0x0000;
                        }
                        else
                        {
                            currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                        }
                        guiGetBackToCurrentScreen();
                        break;
                    }
                    case SCREEN_SETTINGS_BACKUP:
                    {
                        // User wants to clone his smartcard
                        volatile uint16_t pin_code;
                        RET_TYPE temp_rettype;
                        
                        // Reauth user
                        if (removeCardAndReAuthUser() == RETURN_OK)
                        {
                            // Ask for new pin
                            temp_rettype = guiAskForNewPin(&pin_code, ID_STRING_PIN_NEW_CARD);
                            if (temp_rettype == RETURN_NEW_PIN_OK)
                            {
                                // Start the cloning process
                                if (cloneSmartCardProcess(&pin_code) == RETURN_OK)
                                {
                                    // Well it worked....
                                }
                                else
                                {
                                    currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                                    guiDisplayInformationOnScreen(ID_STRING_TGT_CARD_NBL);
                                }
                                pin_code = 0x0000;
                            }
                            else if (temp_rettype == RETURN_NEW_PIN_DIFF)
                            {
                                currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                                guiDisplayInformationOnScreen(ID_STRING_PIN_DIFF);
                            }
                            else
                            {
                                guiGetBackToCurrentScreen();
                                return;
                            }
                        }
                        else
                        {
                            currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                            guiDisplayInformationOnScreen(ID_STRING_FAILED);
                        }
                        userViewDelay();
                        guiGetBackToCurrentScreen();
                        break;
                    }
                    case SCREEN_SETTINGS_ERASE:
                    {
                        // User wants to delete his profile in flash / eeprom....
                        if ((guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_AREYOUSURE)) == RETURN_OK) && (removeCardAndReAuthUser() == RETURN_OK) && (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_AREYOURLSURE)) == RETURN_OK))
                        {
                            uint8_t currentuserid = getCurrentUserID();
                            guiDisplayProcessingScreen();
                            deleteCurrentUserFromFlash();
                            
                            if (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_ERASE_TCARD)) == RETURN_OK)
                            {
                                guiDisplayProcessingScreen();
                                eraseSmartCard();
                                
                                // Erase other smartcards
                                while (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_OTHECARDFUSER)) == RETURN_OK)
                                {
                                    // Ask the user to insert other smartcards
                                    guiDisplayInformationOnScreen(ID_STRING_INSERT_OTHER);
                                    
                                    // Wait for the user to remove and enter another smartcard
                                    while (isCardPlugged() != RETURN_JRELEASED);
                                    
                                    // Wait for the user to insert a new smart card
                                    while (isCardPlugged() != RETURN_JDETECT);
                                    guiDisplayProcessingScreen();
                                    
                                    // Check the card type & ask user to enter his pin, check that the new user id loaded by validCardDetectedFunction is still the same
                                    if ((cardDetectedRoutine() == RETURN_MOOLTIPASS_USER) && (validCardDetectedFunction(0) == RETURN_VCARD_OK) && (currentuserid == getCurrentUserID()))
                                    {
                                        eraseSmartCard();
                                    }
                                }
                            }
                            
                            // Delete LUT entries
                            guiDisplayProcessingScreen();
                            deleteUserIdFromSMCUIDLUT(currentuserid);
                            
                            // Go to invalid screen
                            currentScreen = SCREEN_DEFAULT_INSERTED_INVALID;
                        }
                        else
                        {
                            handleSmartcardRemoved();
                            currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                        }
                        userViewDelay();
                        guiGetBackToCurrentScreen();
                        break;
                    }

                    default: break;
                }                
            }
        }
    #elif defined(HARDWARE_OLIVIER_V1)
        uint8_t state_machine_val = currentScreen;
    
        // If no press, you can return!
        if (!(input_interface_result & TOUCH_PRESS_MASK))
        {
            return;
        }
    
        // Prevent touches until the user lifts his finger
        touchInhibitUntilRelease();
    
        // Current screen is codded in the first 8 bytes, so we set the lowest 8 bytes to the detection quarter
        if (input_interface_result & RETURN_WHEEL_PRESSED)
        {
            state_machine_val |= getWheelTouchDetectionQuarter();
        }
        else
        {
            state_machine_val |= 0x0F;
        }
    
        if (currentScreen == SCREEN_DEFAULT_NINSERTED)
        {
            // No smart card inserted, ask the user to insert one
            guiDisplayInsertSmartCardScreenAndWait();
        }
        else if (currentScreen == SCREEN_MEMORY_MGMT)
        {
            // Currently in memory management mode, tell the user to finish it via the plugin/app
            guiDisplayInformationOnScreenAndWait(ID_STRING_CLOSEMEMMGMT);
            guiGetBackToCurrentScreen();
        }
        else if (currentScreen == SCREEN_DEFAULT_INSERTED_LCK)
        {
            // Locked screen and a detection happened, check that the user hasn't removed his card, launch unlocking process
            if ((cardDetectedRoutine() == RETURN_MOOLTIPASS_USER) && (validCardDetectedFunction(0) == RETURN_VCARD_OK))
            {
                // User approved his pin
                currentScreen = SCREEN_DEFAULT_INSERTED_NLCK;
            }
        
            // Go to the new screen
            guiGetBackToCurrentScreen();
        }
        else
        {
            if (state_machine_val == (SCREEN_DEFAULT_INSERTED_NLCK|TOUCHPOS_WHEEL_BRIGHT))
            {
                // User wants to lock his mooltipass
                currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                handleSmartcardRemoved();
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_DEFAULT_INSERTED_NLCK|TOUCHPOS_WHEEL_TRIGHT))
            {
                // User wants to go to the settings menu
                currentScreen = SCREEN_SETTINGS;
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_DEFAULT_INSERTED_NLCK|TOUCHPOS_WHEEL_BLEFT))
            {
                // User wants to go to the favorite menu
                favoritePickingLogic();
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_DEFAULT_INSERTED_NLCK|TOUCHPOS_WHEEL_TLEFT))
            {
                // User wants to go to the login menu
                if (getStartingParentAddress() != NODE_ADDR_NULL)
                {
                    loginSelectLogic();
                } 
                else
                {                
                    guiDisplayInformationOnScreenAndWait(ID_STRING_NO_CREDS);
                }
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_SETTINGS|TOUCHPOS_WHEEL_BLEFT))
            {
                // User wants to delete his profile in flash / eeprom....
                if ((guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_AREYOUSURE)) == RETURN_OK) && (removeCardAndReAuthUser() == RETURN_OK) && (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_AREYOURLSURE)) == RETURN_OK))
                {
                    uint8_t currentuserid = getCurrentUserID();
                    guiDisplayProcessingScreen();
                    deleteCurrentUserFromFlash();
                    
                    if (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_ERASE_TCARD)) == RETURN_OK)
                    {
                        guiDisplayProcessingScreen();
                        eraseSmartCard();
                        
                        // Erase other smartcards
                        while (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_OTHECARDFUSER)) == RETURN_OK)
                        {
                            // Ask the user to insert other smartcards
                            guiDisplayInformationOnScreen(ID_STRING_INSERT_OTHER);
                            
                            // Wait for the user to remove and enter another smartcard
                            while (isCardPlugged() != RETURN_JRELEASED);
                            
                            // Wait for the user to insert a new smart card
                            while (isCardPlugged() != RETURN_JDETECT);
                            guiDisplayProcessingScreen();
                            
                            // Check the card type & ask user to enter his pin, check that the new user id loaded by validCardDetectedFunction is still the same
                            if ((cardDetectedRoutine() == RETURN_MOOLTIPASS_USER) && (validCardDetectedFunction(0) == RETURN_VCARD_OK) && (currentuserid == getCurrentUserID()))
                            {
                                eraseSmartCard();
                            }
                        }
                    }                    
                    
                    // Delete LUT entries
                    guiDisplayProcessingScreen();
                    deleteUserIdFromSMCUIDLUT(currentuserid);
                    
                    // Go to invalid screen
                    currentScreen = SCREEN_DEFAULT_INSERTED_INVALID;
                }
                else
                {
                    handleSmartcardRemoved();
                    currentScreen = SCREEN_DEFAULT_INSERTED_LCK;                    
                }
                userViewDelay();
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_SETTINGS|TOUCHPOS_WHEEL_BRIGHT))
            {
                // User wants to clone his smartcard
                volatile uint16_t pin_code;
                RET_TYPE temp_rettype;
                
                // Reauth user
                if (removeCardAndReAuthUser() == RETURN_OK)
                {
                    // Ask for new pin
                    temp_rettype = guiAskForNewPin(&pin_code, ID_STRING_PIN_NEW_CARD);
                    if (temp_rettype == RETURN_NEW_PIN_OK)
                    {
                        // Start the cloning process
                        if (cloneSmartCardProcess(&pin_code) == RETURN_OK)
                        {
                            // Well it worked....
                        } 
                        else
                        {
                            currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                            guiDisplayInformationOnScreen(ID_STRING_TGT_CARD_NBL);
                        }
                        pin_code = 0x0000;
                    }
                    else if (temp_rettype == RETURN_NEW_PIN_DIFF)
                    {
                        currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                        guiDisplayInformationOnScreen(ID_STRING_PIN_DIFF);                        
                    }
                    else
                    {                        
                        guiGetBackToCurrentScreen();
                        return;
                    }
                }
                else
                {
                    currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                    guiDisplayInformationOnScreen(ID_STRING_FAILED);
                }
                userViewDelay();
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_SETTINGS|TOUCHPOS_WHEEL_TLEFT))
            {
                // User wants to go to the main menu
                currentScreen = SCREEN_DEFAULT_INSERTED_NLCK;
                guiGetBackToCurrentScreen();
            }
            else if (state_machine_val == (SCREEN_SETTINGS|TOUCHPOS_WHEEL_TRIGHT))
            {
                // User wants to change his PIN code
                
                // Reauth user
                if (removeCardAndReAuthUser() == RETURN_OK)
                {
                    // User approved his pin, ask his new one
                    volatile uint16_t pin_code;
                                        
                    if (guiAskForNewPin(&pin_code, ID_STRING_NEW_PINQ) == RETURN_NEW_PIN_OK)
                    {
                        // User successfully entered a new pin
                        writeSecurityCode(&pin_code);
                        // Inform of success
                        guiDisplayInformationOnScreenAndWait(ID_STRING_PIN_CHANGED);
                    }
                    else
                    {
                        // Inform of fail
                        guiDisplayInformationOnScreenAndWait(ID_STRING_PIN_NCGHANGED);
                    }
                    pin_code = 0x0000;
                }
                else
                {
                    currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                }
                guiGetBackToCurrentScreen();
            }
        }
    #endif 
}
/*! \fn     getTouchedPositionAnswer(uint8_t led_mask)
*   \brief  Use the capacitive interface to get quarter position
*   \param  led_mask    Led mask for the touchdetection routine
*   \return Number between 0 and 5 for valid pos, -1 otherwise
*/
int8_t getTouchedPositionAnswer(uint8_t led_mask)
{
    #if defined(ALWAYS_ACCEPT_REQUESTS)
        // First quarter is discarded, it means we want yes or no!
        if (led_mask & LED_MASK_WHEEL_TLEFT)
        {
            return TOUCHPOS_RIGHT;
        }
        else
        {
            return TOUCHPOS_WHEEL_TLEFT;
        }
    #endif

    uint8_t incomingData[RAWHID_TX_SIZE];
    RET_TYPE touch_detect_result;
    
    // Switch on lights
    activityDetectedRoutine();
    
    // Clear possible remaining detection
    touchDetectionRoutine(led_mask);
    
    // Additional masking in case we only want left / right
    uint8_t additional_mask = 0xFF;
    if (led_mask == LED_MASK_WHEEL)
    {
        additional_mask = RETURN_LEFT_PRESSED | RETURN_RIGHT_PRESSED;
    }
    
    // Wait for a touch press
    do
    {
        // User interaction timeout or smartcard removed
        if ((hasTimerExpired(TIMER_USERINT, TRUE) == TIMER_EXPIRED) || (isSmartCardAbsent() == RETURN_OK))
        {
            return -1;
        }
        // Read usb comms as the plugin could ask to cancel the request
        if ((getMooltipassParameterInEeprom(USER_REQ_CANCEL_PARAM) != FALSE) && (usbRawHidRecv(incomingData) == RETURN_COM_TRANSF_OK))
        {
            if (incomingData[HID_TYPE_FIELD] == CMD_CANCEL_REQUEST)
            {
                // Request cancelled
                return -1;
            }
            else
            {
                // Another packet (that shouldn't be sent!), ask to retry later...
                usbSendMessage(CMD_PLEASE_RETRY, 0, incomingData);
            }
        }
        touch_detect_result = touchDetectionRoutine(led_mask) & TOUCH_PRESS_MASK & additional_mask;
    }
    while (!touch_detect_result);
    
    // Prevent touches until the user lifts his finger
    touchInhibitUntilRelease();
    
    // Did the user press one of the two touch buttons?
    if (touch_detect_result & RETURN_LEFT_PRESSED)
    {
        return TOUCHPOS_LEFT;
    }
    else if (touch_detect_result & RETURN_RIGHT_PRESSED)
    {
        return TOUCHPOS_RIGHT;
    }
    else
    {
        return (int8_t)getWheelTouchDetectionQuarter();
    } 
}
/*! \fn     touchDetectionRoutine(uint8_t led_mask)
*   \brief  Touch detection routine
*   \param  led_mask    Mask containing which LEDs to switchoff
*   \return Touch detection result (see touch_detect_return_t)
*/
uint8_t mooltipass_touch_sensing::touchDetectionRoutine(uint8_t led_mask)
{
    uint8_t return_val = RETURN_NO_CHANGE;
    uint8_t keys_detection_status;
    uint8_t led_states[NB_KEYS];
    uint8_t temp_bool = false;
    uint8_t temp_uint;

    // Set the LEDs on by default
    memset((void*)led_states, AT42QT2120_OUTPUT_H_VAL, NB_KEYS);

    // Switch them off depending on mask
    for (temp_uint = 0; temp_uint < NB_KEYS; temp_uint++)
    {
        if (led_mask & (1 << temp_uint))
        {
            led_states[temp_uint] = AT42QT2120_OUTPUT_L_VAL;
        }
    }

    if (isTouchChangeDetected())
    {
        // Set temp bool to true
        temp_bool = true;

        // Read detection status register
        readDataFromTS(REG_AT42QT_DET_STAT, &keys_detection_status);

        // Unused byte that needs to be read
        readDataFromTS(REG_AT42QT_KEY_STAT1, &temp_uint);

        // If wheel is touched
        if (keys_detection_status & AT42QT2120_SDET_MASK)
        {
            // Get position and update global var
            readDataFromTS(REG_AT42QT_SLIDER_POS, &last_raw_wheel_position);

            // Update LED states
            led_states[getWheelTouchDetectionQuarter()] = AT42QT2120_OUTPUT_L_VAL;
            return_val |= RETURN_WHEEL_PRESSED;
        }
        else
        {
            return_val |= RETURN_WHEEL_RELEASED;
        }

        // Read button touched register
        readDataFromTS(REG_AT42QT_KEY_STAT2, &temp_uint);

        // If one button is touched
        if ((keys_detection_status & AT42QT2120_TDET_MASK) && !(keys_detection_status & AT42QT2120_SDET_MASK))
        {
            if (temp_uint & 0x02)
            {
                // Left button
                led_states[TOUCHPOS_LEFT] = AT42QT2120_OUTPUT_L_VAL;
                return_val |= RETURN_LEFT_PRESSED;
                return_val |= RETURN_RIGHT_RELEASED;
            }
            else if(temp_uint & 0x08)
            {
                // Right button
                led_states[TOUCHPOS_RIGHT] = AT42QT2120_OUTPUT_L_VAL;
                return_val |= RETURN_RIGHT_PRESSED;
                return_val |= RETURN_LEFT_RELEASED;
            }
            else
            {
                return_val |= RETURN_PROX_DETECTION;
            }
        }
        else
        {
            return_val |= RETURN_PROX_RELEASED;
            return_val |= RETURN_LEFT_RELEASED;
            return_val |= RETURN_RIGHT_RELEASED;
        }

        // Switch on cathode if activity
        if (return_val & TOUCH_PRESS_MASK)
        {
            //activityDetectedRoutine();
        }
    }

    // If there's a touch change or led mask has changed
    if ((temp_bool == true) || (led_mask != last_led_mask))
    {
        last_led_mask = led_mask;
        writeDataToTS(LEFT_LED_REGISTER, led_states[TOUCHPOS_LEFT]);
        writeDataToTS(RIGHT_LED_REGISTER, led_states[TOUCHPOS_RIGHT]);
        writeDataToTS(WHEEL_TLEFT_LED_REGISTER, led_states[TOUCHPOS_WHEEL_TLEFT]);
        writeDataToTS(WHEEL_TRIGHT_LED_REGISTER, led_states[TOUCHPOS_WHEEL_TRIGHT]);
        writeDataToTS(WHEEL_BLEFT_LED_REGISTER, led_states[TOUCHPOS_WHEEL_BLEFT]);
        writeDataToTS(WHEEL_BRIGHT_LED_REGISTER,  led_states[TOUCHPOS_WHEEL_BRIGHT]);
    }

    return return_val;
}