class pah8011 for mbed

pixart_pah8011.cpp

Committer:
bell_huang
Date:
2019-01-23
Revision:
6:d196b612b14a
Parent:
5:37451de228e4

File content as of revision 6:d196b612b14a:

#include "pixart_pah8011.h"


extern "C" {
    
    
    #include "pah_comm.h"
    #include "pah_driver.h"
    #include "pah_platform_functions.h"
    #include <string.h>
    
    
    void disable_debug_printf(const char *fmt, ...)
    {
        // do nothing
    }

    DEBUG_PRINT_HANDLE debug_printf = disable_debug_printf;
    
    void delay_ms(uint64_t ms)
    {
        wait_ms(ms);
    }

} // extern "C"


namespace pixart {
    
    
    static pah_ret mbed_i2c_write(struct pah_drv_comm_s *comm, uint8_t addr, uint8_t data)
    {
        pah8011 *pah8011_state = (pah8011*)comm->user_data;
        I2C *i2c = pah8011_state->get_i2c();
        int rc = 0;
        char data_write[2];
    
        data_write[0] = addr;
        data_write[1] = data;
        
        rc = i2c->write((pah8011_state->get_i2c_slave_id() << 1), data_write, 2, 0);
        if (rc != 0)
            return PAH_RET_PLAT_FAILED;
        
        return PAH_RET_SUCCESS;
    }
    
    static pah_ret mbed_i2c_burst_read(struct pah_drv_comm_s *comm, uint8_t addr, uint8_t *data, uint32_t rx_size)
    {
        pah8011 *pah8011_state = (pah8011*)comm->user_data;
        I2C *i2c = pah8011_state->get_i2c();
        int rc = 0;
        
        rc = i2c->write((pah8011_state->get_i2c_slave_id() << 1), (const char*)&addr, 1, 1);
        if (rc != 0)
            return PAH_RET_PLAT_FAILED;
        
        rc = i2c->read((pah8011_state->get_i2c_slave_id() << 1), (char*)data, rx_size, 0);
        if (rc != 0)
            return PAH_RET_PLAT_FAILED;
        
        return PAH_RET_SUCCESS;
    }
    
    static pah_ret mbed_i2c_read(struct pah_drv_comm_s *comm, uint8_t addr, uint8_t *data)
    {
        return mbed_i2c_burst_read(comm, addr, data, 1);
    }
    
    static pah_ret mbed_spi_write(struct pah_drv_comm_s *comm, uint8_t addr, uint8_t data)
    {
        pah8011 *pah8011_state = (pah8011*)comm->user_data;
        SPI *spi = pah8011_state->get_spi();
        DigitalOut *spi_cs = pah8011_state->get_spi_cs();
        
        *spi_cs = 1;
        
        char data_write[2];
        data_write[0] = addr;
        data_write[1] = data;
        
        spi->write(data_write, 2, NULL, 0);
        
        *spi_cs = 0;
        return PAH_RET_SUCCESS;
    }
    
    static pah_ret mbed_spi_burst_read(struct pah_drv_comm_s *comm, uint8_t addr, uint8_t *data, uint32_t rx_size)
    {
        pah8011 *pah8011_state = (pah8011*)comm->user_data;
        SPI *spi = pah8011_state->get_spi();
        DigitalOut *spi_cs = pah8011_state->get_spi_cs();
        
        *spi_cs = 1;
        /*
        spi->write(addr);
        
        for (uint32_t i = 0; i < rx_size; ++i)
            data[i] = spi->write(0x00);
        */
        
        static char buf[256];
        buf[0] = addr;
        
        static const uint8_t WRITE_LENGTH = 1;
        spi->write(buf, WRITE_LENGTH, buf, WRITE_LENGTH + rx_size);
        
        memcpy(data, &buf[WRITE_LENGTH], rx_size);
        
        *spi_cs = 0;
        return PAH_RET_SUCCESS;
    }
    
    static pah_ret mbed_spi_read(struct pah_drv_comm_s *comm, uint8_t addr, uint8_t *data)
    {
        return mbed_spi_burst_read(comm, addr, data, 1);
    }
    
    
    pah8011::pah8011(I2C &i2c, uint8_t slave_id)
        : m_i2c(&i2c)
        , m_i2c_slave_id(slave_id)
        , m_spi(NULL)
        , m_spi_cs(NULL)
        , m_is_ppg_enabled(false)
        , m_is_touch_enabled(false)
    {
        pah_drv_comm_s pah_drv_comm = {
            .type           = pah_drv_comm_i2c,
            .user_data      = this,
            .max_length     = 256,
            .write          = mbed_i2c_write,
            .write_delay    = NULL,
            .read           = mbed_i2c_read,
            .burst_read     = mbed_i2c_burst_read,
        };
        pah_comm_set_drv_comm(&pah_drv_comm);
    }
    
    pah8011::pah8011(SPI &spi, DigitalOut &cs)
        : m_i2c(NULL)
        , m_i2c_slave_id(0x15)
        , m_spi(&spi)
        , m_spi_cs(&cs)
        , m_is_ppg_enabled(false)
        , m_is_touch_enabled(false)
    {
        m_spi->format(8, 3);
        
        pah_drv_comm_s pah_drv_comm = {
            .type           = pah_drv_comm_spi,
            .user_data      = this,
            .max_length     = 256,
            .write          = mbed_spi_write,
            .write_delay    = NULL,
            .read           = mbed_spi_read,
            .burst_read     = mbed_spi_burst_read,
        };
        pah_comm_set_drv_comm(&pah_drv_comm);
    }
    
    pah8011::~pah8011()
    {
        pah_deinit();
    }
    
    void pah8011::enable_debug_print(DEBUG_PRINT_HANDLE handler)
    {
        if (handler)
            debug_printf = handler;
        else
            debug_printf = disable_debug_printf;
    }
    
    bool pah8011::init()
    {
        pah_flags_s flags;
        memset(&flags, 0, sizeof(flags));
        
        flags.intshape_pulse_type = pah_intshape_pulse_type_level;
        
        if (!pah_init_with_flags(&flags))
            return false;
        
        return true;
    }
    
    bool pah8011::enable_ppg()
    {
        m_is_ppg_enabled = true;
        
        return select_mode();
    }
    
    bool pah8011::disable_ppg()
    {
        m_is_ppg_enabled = false;
        
        return select_mode();
    }
    
    bool pah8011::enable_touch()
    {
        m_is_touch_enabled = true;
        
        return select_mode();
    }
    
    bool pah8011::disable_touch()
    {
        m_is_touch_enabled = false;
        
        return select_mode();
    }
    
    bool pah8011::task()
    {
        pah_ret ret = pah_task();
        
        return ret == pah_success
            || ret == pah_no_interrupt;
    }
    
    bool pah8011::get_result(task_result &result)
    {
        if (!pah_has_fifo_data())
            return false;
            
        result.data         = (int32_t*)pah_get_fifo_data();
        result.num_per_ch   = pah_fifo_data_num_per_ch();
        result.ch_num       = pah_get_fifo_ch_num();
        result.is_touched   = pah_is_touched();
            
        return true;
    }
    
    I2C* pah8011::get_i2c() const
    {
        return m_i2c;
    }
    uint8_t pah8011::get_i2c_slave_id() const
    {
        return m_i2c_slave_id;
    }
    SPI* pah8011::get_spi() const
    {
        return m_spi;
    }
    DigitalOut* pah8011::get_spi_cs() const
    {
        return m_spi_cs;
    }
 
    bool pah8011::select_mode()
    {
        pah_mode mode = pah_stop_mode;
        
        if (m_is_ppg_enabled)
        {
            if (m_is_touch_enabled)
                mode = pah_ppg_touch_mode;
            else
                mode = pah_ppg_mode;
        }
        else if (m_is_touch_enabled)
        {
            mode = pah_touch_mode;
        }
        else
        {
            mode = pah_stop_mode;
        }
        
        return pah_enter_mode(mode);
    }
    
}