This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI: prevent repeated start between non stop transfer

Hi,

I am debugging an SSD1306 OLED library, and in the datasheet, it does not explicitly mention support for repeated start bits. But using the nrf_drv_ API's with NRF_DRV_TWI_FLAG_TX_NO_STOP flag set, the successive nrf_drv_twi_tx or nrf_drv_twi_xfer function starts sending data with a start condition.

image description

As shown by the logic analyzer, the Green dot is a start ad red dot is a stop. I dont not want the last green dot to the right. Is this possible using the nrf_drv_twi_ API ?

Parents Reply Children
  • He wants to do the same thing as I'm trying to right now. I'm working with the sensor MPL3115A2 and it does not work with a repeated start either, similar to above. First of all I'm using the TWI Manager and I'm using defines to split my communication. I want to do, for example:

    1. Write <Data1> to CTRL register1
    2. Write <Data2> to CTRL register 2
    3. Write <Data3> to INT_SRC register
    4. ...

    by using defines as follows:

    #define MPL3115A2_READ(p_reg_addr, p_buffer, byte_cnt) \
        NRF_TWI_MNGR_WRITE(MPL3115A2_ADDR, p_reg_addr, 1, NRF_TWI_MNGR_NO_STOP), \
        NRF_TWI_MNGR_READ (MPL3115A2_ADDR, p_buffer, byte_cnt, 0)

    As you see above It is easy to create one define that can handle both different register addresses and data. With this method however you will always get a repeated start between the WRITE and READ, i.e.

    START | ADDR + W | REG ADDR | START | DATA | STOP

    As mentioned the MPL3115A2 among others obviously does not support repeated start, but required communication in the shape of:

    START | ADDR + W | REG ADDR | DATA | STOP

    Thus removing the START generated from the NRF_TWI_MNGR_READ.

    Right now I have solved this as follows:

    #define MPL3115A2_WRITE_REG(p_data)\
        NRF_TWI_MNGR_WRITE(MPL3115A2_ADDR, p_data, 2, 0)
        
    static inline void init_press_measure()
    {
        static uint8_t config_1[2] = {MPL3115A2_CTRL_REG1, MPL3115A2_OVERSAMPLE_RATIO_128};
        
        static nrf_twi_mngr_transfer_t const transfers[] =
        {
            MPL3115A2_WRITE_REG(config_1),
        };
        
        static nrf_twi_mngr_transaction_t NRF_TWI_MNGR_BUFFER_LOC_IND transaction =
        {
            .callback            = NULL,
            .p_user_data         = NULL,
            .p_transfers         = transfers,
            .number_of_transfers = sizeof(transfers) / sizeof(transfers[0])
        };
        
        APP_ERROR_CHECK(nrf_twi_mngr_schedule(&m_nrf_twi_mngr, &transaction));
    }

    In other words, I have to create a temporary array with the length of 2 and assign values and then use that configuration variable.

    If it was possible to add a flag such as "NRF_TWI_MNGR_NO_START" it would have been possible to create a neat macro such as below:

    uint8_t NRF_TWI_MNGR_BUFFER_LOC_IND mpl3115a2_ctrl_reg1 = MPL3115A2_CTRL_REG1;
    uint8_t mpl3115a2_oversample_ratio_128 = MPL3115A2_OVERSAMPLE_RATIO_128;
    
    #define MPL3115A2_WRITE_CTRL_REG1(p_data) \
        MPL3115A2_WRITE_REG(&mpl3115a2_ctrl_reg1, p_data, 2)
        
    #define MPL3115A2_WRITE_REG(p_reg_addr, p_buffer, byte_cnt) \
        NRF_TWI_MNGR_WRITE(MPL3115A2_ADDR, p_reg_addr, 1, NRF_TWI_MNGR_NO_STOP), \
        NRF_TWI_MNGR_WRITE(MPL3115A2_ADDR, p_buffer, byte_cnt, NRF_TWI_MNGR_NO_START)
        
    ...
        static nrf_twi_mngr_transfer_t const transfers[] =
        {
            MPL3115A2_WRITE_CTRL_REG1(&mpl3115a2_oversample_ratio_128),
            ...
        };
    ...

    I also see now that it would be very neat if it was possible to also add support for not using pointers. I don't know if that is a good idea or not resource wise but it would allow you to keep almost all configuration data in defines and give you a very clean interface without the need to declare a lot of extra variables only for the reason to point at them.

    #define MPL3115A2_WRITE_CTRL_REG1(data) \
        MPL3115A2_WRITE_REG(MPL3115A2_CTRL_REG1, data, 2)
        
    #define MPL3115A2_WRITE_REG(reg_addr, data, byte_cnt) \
        NRF_TWI_MNGR_WRITE(MPL3115A2_ADDR, reg_addr, 1, NRF_TWI_MNGR_NO_STOP), \
        NRF_TWI_MNGR_WRITE(MPL3115A2_ADDR, data, byte_cnt, NRF_TWI_MNGR_NO_START)
        
    ...
        static nrf_twi_mngr_transfer_t const transfers[] =
        {
            MPL3115A2_WRITE_CTRL_REG1(MPL3115A2_OVERSAMPLE_RATIO_128),
            ...
        };
    ...
    

    Regards

    Robert

Related