/*
 * Copyright (c) 2021 Pimax. All rights reserved.
 * Author    Date          ChangeLog
 * Master    2021-03-18    First version
 * Master    2021-03-24    optimize
 * Master    2021-04-06    add handler
 */
#include "twim.h"
#include "nrf_log.h"
#include "alps_board.h"
#include "FreeRTOS.h"
#include "task.h"

#undef HANDLER
// nrf_strerror_find
const nrf_drv_twi_t cs_twi_instance = NRF_DRV_TWI_INSTANCE(0);
const nrf_drv_twi_t haptic_twi_instance = NRF_DRV_TWI_INSTANCE(1);

volatile bool cs_xfer_done = false;
volatile bool cs_read_done = false;

volatile bool haptic_xfer_done = false;
volatile bool haptic_read_done = false;


#ifdef HANDLER
// if use HANDLER,no data received
static void cs_twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
    case NRF_DRV_TWI_EVT_DONE:
        if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
        {
            cs_xfer_done = true;
        }
        if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
        {
            cs_read_done = true;
        }
        break;
    default:
        break;
    }
}


static void haptic_twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
    case NRF_DRV_TWI_EVT_DONE:
        if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
        {
            haptic_xfer_done = true;
        }
        if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
        {
            haptic_read_done = true;
        }
        break;
    default:
        break;
    }
}


int twi_read_reg(const nrf_drv_twi_t *instance, 
                 uint8_t slave_addr, 
                 uint8_t reg_addr, 
                 uint8_t *read_data, 
                 uint8_t len)
{
    ret_code_t err_code;
    uint16_t times = 0;
    volatile bool *xfer_done = NULL;
    volatile bool *read_done = NULL;

    if(instance == &cs_twi_instance)
    {
        xfer_done = &cs_xfer_done;
        read_done = &cs_read_done;
    }else if(instance == &haptic_twi_instance)
    {
        xfer_done = &haptic_xfer_done;
        read_done = &haptic_read_done;
    }else
    {
        NRF_LOG_ERROR("args is error\r\n");
        return TWI_ARGS_ERROR;
    }

    *xfer_done = false;
    err_code = nrf_drv_twi_tx(instance, slave_addr, &reg_addr, 1, true);
    if(err_code != NRFX_SUCCESS)
    {
        NRF_LOG_ERROR("twi tx error:%s", nrf_strerror_find(err_code));
        return false;
    }
    while(*xfer_done == false)
    {
        times ++;
        if(times > 255)
        {
            NRF_LOG_ERROR("twi tx timeout\r\n");
            return TWI_XFER_TIMEOUT;
        }
    }

    *read_done = false;
    err_code = nrf_drv_twi_rx(instance, slave_addr, read_data, len);
    if(err_code != NRFX_SUCCESS)
    {
        NRF_LOG_ERROR("twi rx error:%s", nrf_strerror_find(err_code));
        return TWI_ERROR;
    }
    times = 0;
    while(*read_done == false)
    {
        times ++;
        if(times > 255)
        {
            NRF_LOG_ERROR("twi rx timeout\r\n");
            return TWI_XFER_TIMEOUT;
        }
    }

    return TWI_SUCCESS;
}


int twi_write_reg(nrf_drv_twi_t *const instance,
                  uint8_t slave_addr, 
                  const uint8_t *write_data, 
                  uint8_t len)
{
    ret_code_t err_code;
    uint16_t times = 0;
    volatile bool *xfer_done = NULL;

    if(instance == &cs_twi_instance)
    {
        xfer_done = &cs_xfer_done;
    }else if(instance == &haptic_twi_instance)
    {
        xfer_done = &haptic_xfer_done;
    }else
    {
        return TWI_ARGS_ERROR;
    }

    *xfer_done = false;
    err_code = nrf_drv_twi_tx(instance, slave_addr, write_data, len, false);
    if(err_code != NRFX_SUCCESS)
    {
        NRF_LOG_ERROR("twi tx error:%s", nrf_strerror_find(err_code));
        return TWI_ERROR;
    }
    while(*xfer_done == false)
    {
        times ++;
        if(times > 255)
            return TWI_XFER_TIMEOUT;
    }

    return TWI_SUCCESS;
}
#else
int twi_read_reg(const nrf_drv_twi_t *instance, 
                 uint8_t slave_addr, 
                 uint8_t reg_addr, 
                 uint8_t *read_data, 
                 uint8_t len)
{
    ret_code_t err_code;

    err_code = nrf_drv_twi_tx(instance, slave_addr, &reg_addr, 1, true);
    if(err_code != NRFX_SUCCESS)
    {
        NRF_LOG_ERROR("twi tx error:%s", nrf_strerror_find(err_code));
        return false;
    }

    err_code = nrf_drv_twi_rx(instance, slave_addr, read_data, len);
    if(err_code != NRFX_SUCCESS)
    {
        NRF_LOG_ERROR("twi rx error:%s", nrf_strerror_find(err_code));
        return TWI_ERROR;
    }

    return TWI_SUCCESS;
}


int twi_write_reg(nrf_drv_twi_t *const instance,
                  uint8_t slave_addr, 
                  const uint8_t *write_data, 
                  uint8_t len)
{
    ret_code_t err_code;

    err_code = nrf_drv_twi_tx(instance, slave_addr, write_data, len, false);
    if(err_code != NRFX_SUCCESS)
    {
        NRF_LOG_ERROR("twi tx error:%s", nrf_strerror_find(err_code));
        return TWI_ERROR;
    }

    return TWI_SUCCESS;
}
#endif

#pragma diag_suppress 188
void twi_init(void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_cs_config = {
       .scl                = CS_SCL_PIN,
       .sda                = SDA_SDA_PIN,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };
#ifdef HANDLER
    err_code = nrf_drv_twi_init(&cs_twi_instance, &twi_cs_config, cs_twi_handler, NULL);
#else
    err_code = nrf_drv_twi_init(&cs_twi_instance, &twi_cs_config, NULL, NULL);
#endif
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&cs_twi_instance);

    const nrf_drv_twi_config_t twi_haptic_config = {
       .scl                = HATPIC_SCL_PIN,
       .sda                = HATPIC_SDA_PIN,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };
#ifdef HANDLER
    err_code = nrf_drv_twi_init(&haptic_twi_instance, &twi_haptic_config, haptic_twi_handler, NULL);
#else
    err_code = nrf_drv_twi_init(&haptic_twi_instance, &twi_haptic_config, NULL, NULL);
#endif
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&haptic_twi_instance);
}


void twi_disable(void)
{
    nrf_drv_twi_uninit(&cs_twi_instance);
    nrf_drv_twi_disable(&cs_twi_instance);
    
    nrf_drv_twi_uninit(&haptic_twi_instance);
    nrf_drv_twi_disable(&haptic_twi_instance);
}



