Beispiel #1
0
void noTone(uint8_t pin)
{
    uint8_t nrf_pin;

    nrf_pin = Pin_nRF51822_to_Arduino(pin);
    if(nrf_pin >= 31)
        return;

    if(nrf_pin != tone_pin)
        return;
    // Stop TIMER
    TONE_USED_TIMER->TASKS_STOP = 1;
    NVIC_DisableIRQ(TONE_USED_TIMER_IRQn);

#if defined(SOFTDEVICE_PRESENT)
    uint8_t softdevice_enabled;
    sd_softdevice_is_enabled(&softdevice_enabled);
    if(softdevice_enabled == 0) {
        NRF_PPI->CHEN &= (1 << TONE_USED_PPI_CHANNAL);
    }
    else {
        sd_ppi_channel_enable_clr(1 << TONE_USED_PPI_CHANNAL);
    }
#else
    NRF_PPI->CHEN &= (1 << TONE_USED_PPI_CHANNAL);
#endif
    // Disable GPIOTE
    NRF_GPIOTE->CONFIG[TONE_USED_GPIOTE_NUM] &= ~( GPIOTE_CONFIG_MODE_Msk | GPIOTE_CONFIG_POLARITY_Msk);
    // Reset variables
    tone_pin    = 0xFF;
    finish_flag = 0;
    inter_count = 0;
}
bool twi_master_write_read(uint8_t address, uint8_t *tx_data, uint8_t tx_data_length, uint8_t *rx_data, uint8_t rx_data_length,twi_config_t *cfg)
{
    if (tx_data_length == 0 || rx_data_length == 0)
    {    
        return false;
    }
		active_config =cfg;

    cfg->twi->ADDRESS = address;
    tx_data_ptr = tx_data;
    tx_bytes_to_send = tx_data_length - 1;
    rx_data_ptr = rx_data;
    rx_bytes_to_receive = rx_data_length;
       
    if (rx_bytes_to_receive == 1)
    {
        sd_ppi_channel_assign(cfg->twi_ppi_ch, &cfg->twi->EVENTS_BB, &cfg->twi->TASKS_STOP);
    }
    else
    {
        sd_ppi_channel_assign(cfg->twi_ppi_ch, &cfg->twi->EVENTS_BB, &cfg->twi->TASKS_SUSPEND);
    }
    sd_ppi_channel_enable_clr(1 << cfg->twi_ppi_ch);        
    
    cfg->twi->TXD = *tx_data_ptr++;
    cfg->twi->TASKS_STARTTX = 1;
    cfg->twi_operation_complete = false;
		while(cfg->twi_operation_complete == false);
		active_config =0;
    return cfg->twi_ack_received;
}
static void ppi_disable_channels(uint32_t ch_msk)
{
#if(USE_WITH_SOFTDEVICE == 1)
    sd_ppi_channel_enable_clr(ch_msk);
#else
    NRF_PPI->CHENCLR = (ch_msk);   
#endif
}
Beispiel #4
0
static bool twi_master_read(uint8_t *data, uint8_t data_length,
bool issue_stop_condition) {
	uint32_t timeout = MAX_TIMEOUT_LOOPS; /* max loops to wait for RXDREADY event*/

	if (data_length == 0) {
		/* gently return false for requesting data of size 0 */
		return false;
	}

	if (data_length == 1) {
		//NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;

		sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
				&(NRF_TWI1->TASKS_STOP));
	} else {
		//NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
		sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
				&(NRF_TWI1->TASKS_SUSPEND));

	}
	//NRF_PPI->CHENSET = PPI_CHENSET_CH0_Msk;
	sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk);
	NRF_TWI1->TASKS_STARTRX = 1;
	while (true) {

		while ((NRF_TWI1->EVENTS_RXDREADY == 0) && (--timeout)) { //nrf_app_event_wait();
		}

		if (timeout == 0) {
			/* timeout before receiving event*/
			return false;
		}

		NRF_TWI1->EVENTS_RXDREADY = 0;
		*data++ = NRF_TWI1->RXD;

		/* configure PPI to stop TWI master before we get last BB event */
		if (--data_length == 1) {
			//  NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
			sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
					&(NRF_TWI1->TASKS_STOP));
		}

		if (data_length == 0)
			break;

		NRF_TWI1->TASKS_RESUME = 1;
	}

	/* wait until stop sequence is sent and clear the EVENTS_STOPPED */
	while (NRF_TWI1->EVENTS_STOPPED == 0) {  //nrf_app_event_wait();
	}
	NRF_TWI1->EVENTS_STOPPED = 0;

	//  NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
	sd_ppi_channel_enable_clr(PPI_CHEN_CH0_Msk);
	return true;
}
uint32_t nrf_drv_ppi_uninit(void)
{
    uint32_t err_code = NRF_SUCCESS;
    uint32_t mask = NRF_PPI_ALL_APP_GROUPS_MASK;
    nrf_ppi_channel_group_t group;

    if (m_drv_state != NRF_DRV_STATE_UNINITIALIZED)
    {
        m_drv_state = NRF_DRV_STATE_UNINITIALIZED;

        // Disable all channels and groups
#if (NRF_PPI_RESTRICTED > 0)
        err_code = sd_ppi_channel_enable_clr(NRF_PPI_ALL_APP_CHANNELS_MASK);
        if (err_code != NRF_SUCCESS)
        {
            return NRF_ERROR_INTERNAL;
        }

        for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
        {
            if(mask & group_to_mask(group))
            {
                err_code = sd_ppi_group_task_disable((uint8_t)group);
                if (err_code != NRF_SUCCESS)
                {
                    return NRF_ERROR_INTERNAL;
                }
            }
        }
#else
        nrf_ppi_channel_disable_all();

        for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
        {
            if(mask & group_to_mask(group))
            {
                nrf_ppi_channel_group_clear(group);
            }
        }
#endif

        channel_allocated_clr_all();
        group_allocated_clr_all();
    }
    else
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }
    return err_code;
}
bool twi_master_init(twi_init_config_t *init_cfg,twi_config_t *cfg)
{
    cfg->twi_operation_complete = true;
    cfg->twi_ack_received = true;

          
    /* To secure correct signal levels on the pins used by the TWI
       master when the system is in OFF mode, and when the TWI master is 
       disabled, these pins must be configured in the GPIO peripheral.
    */ 
    NRF_GPIO->PIN_CNF[init_cfg->twi_pinselect_scl] = 
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);    

    NRF_GPIO->PIN_CNF[init_cfg->twi_pinselect_sda] = 
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos); 
    
    cfg->twi->EVENTS_RXDREADY = 0;
    cfg->twi->EVENTS_TXDSENT = 0;
    cfg->twi->PSELSCL = init_cfg->twi_pinselect_scl;
    cfg->twi->PSELSDA = init_cfg->twi_pinselect_sda;
    
    switch(init_cfg->frequency)
    {
        case TWI_FREQ_100KHZ:
            cfg->twi->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos;
            break;
        case TWI_FREQ_400KHZ:
            cfg->twi->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K400 << TWI_FREQUENCY_FREQUENCY_Pos;
            break;
    }
    sd_ppi_channel_assign(cfg->twi_ppi_ch, &cfg->twi->EVENTS_BB, &cfg->twi->TASKS_SUSPEND);
    sd_ppi_channel_enable_clr(1 << cfg->twi_ppi_ch);
    sd_nvic_SetPriority(init_cfg->twi_interrupt_no, TWI_IRQ_PRIORITY_SD);
    sd_nvic_EnableIRQ(init_cfg->twi_interrupt_no);
    cfg->twi->INTENSET = TWI_INTENSET_TXDSENT_Msk | TWI_INTENSET_STOPPED_Msk | TWI_INTENSET_ERROR_Msk | TWI_INTENSET_RXDREADY_Msk;
    cfg->twi->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
    return twi_master_clear_bus(init_cfg);
}
/** @brief Function for initializing the twi_master.
 */
bool twi_master_init(void)
{
    /* To secure correct signal levels on the pins used by the TWI
       master when the system is in OFF mode, and when the TWI master is 
       disabled, these pins must be configured in the GPIO peripheral.
    */
    NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] =     \
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos) \
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)  \
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos) \
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);   

    NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] =      \
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos) \
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)  \
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos) \
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);    

    NRF_TWI1->EVENTS_RXDREADY = 0;
    NRF_TWI1->EVENTS_TXDSENT  = 0;
    NRF_TWI1->PSELSCL         = TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER;
    NRF_TWI1->PSELSDA         = TWI_MASTER_CONFIG_DATA_PIN_NUMBER;
    NRF_TWI1->FREQUENCY       = TWI_FREQUENCY_FREQUENCY_K400 << TWI_FREQUENCY_FREQUENCY_Pos;
    
    sd_softdevice_is_enabled(&sd_enabled);
    if(sd_enabled)
    {
        sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_SUSPEND);
        sd_ppi_channel_enable_clr(1 << 0);
    }
    else
    {
        NRF_PPI->CH[0].EEP        = (uint32_t)&NRF_TWI1->EVENTS_BB;
        NRF_PPI->CH[0].TEP        = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
        NRF_PPI->CHENCLR          = PPI_CHENCLR_CH0_Msk;
    }    

    NRF_TWI1->ENABLE          = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;

    return twi_master_clear_bus();
}
Beispiel #8
0
//#pragma GCC
bool twi_master_init(void) {
	/* To secure correct signal levels on the pins used by the TWI
	 master when the system is in OFF mode, and when the TWI master is
	 disabled, these pins must be configured in the GPIO peripheral.
	 */
	uint32_t err_code =0;(void)err_code;

	NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] =
			(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
					| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
					| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
					| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
					| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);

	NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] =
			(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
					| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
					| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
					| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
					| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);

	NRF_TWI1->EVENTS_RXDREADY = 0;
	NRF_TWI1->EVENTS_TXDSENT = 0;
	NRF_TWI1->PSELSCL = TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER;
	NRF_TWI1->PSELSDA = TWI_MASTER_CONFIG_DATA_PIN_NUMBER;
	NRF_TWI1->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K400
			<< TWI_FREQUENCY_FREQUENCY_Pos;

	/*
	 NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TWI1->EVENTS_BB;
	 NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
	 NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;*/
	err_code = sd_ppi_channel_assign(0, &(NRF_TWI1->EVENTS_BB),
			&(NRF_TWI1->TASKS_SUSPEND));
	ASSERT(err_code == NRF_SUCCESS);

	err_code = sd_ppi_channel_enable_clr(PPI_CHEN_CH0_Msk);
	ASSERT(err_code == NRF_SUCCESS);

	NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;

	return twi_master_clear_bus();
}
uint32_t freePPIChannel(uint8_t channel_num)
{
	uint32_t err_code = NRF_SUCCESS;
	uint8_t  softdevice_enabled;

	APP_ERROR_CHECK_BOOL(channel_num != UNAVAILABLE_PPI_CHANNEL
			&& channel_num < NB_PPI_APP_CHANNELS_SD_DISABLED);

	err_code = sd_softdevice_is_enabled(&softdevice_enabled);
	APP_ERROR_CHECK(err_code);
	if (softdevice_enabled == 0)
	{
		NRF_PPI->CHEN &= ~(1 << channel_num);
	}
	else
	{
		err_code = sd_ppi_channel_enable_clr(1 << channel_num);
		APP_ERROR_CHECK(err_code);
	}
}
bool twi_master_write(uint8_t address, uint8_t *tx_data, uint8_t tx_data_length,twi_config_t *cfg)
{
    if (tx_data_length == 0)
    {    
        return false;
    }
		active_config =cfg;

		sd_ppi_channel_enable_clr(1 << cfg->twi_ppi_ch);

    
    cfg->twi->ADDRESS = address;
    tx_data_ptr = tx_data;
    tx_bytes_to_send = tx_data_length - 1;
    rx_bytes_to_receive = 0;
    cfg->twi->TXD = *tx_data_ptr++;
    cfg->twi->TASKS_STARTTX = 1;
    cfg->twi_operation_complete = false;
    
    while(cfg->twi_operation_complete == false);
		active_config =0;
    return cfg->twi_ack_received;
}
Beispiel #11
0
uint32_t nrf_drv_ppi_channel_disable(nrf_ppi_channel_t channel)
{
    uint32_t err_code;

    if (!is_app_channel(channel))
    {
        err_code = NRF_ERROR_INVALID_PARAM;
    }
    else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }
    else
    {
#if (NRF_PPI_RESTRICTED > 0)
        err_code = sd_ppi_channel_enable_clr(channel_to_mask(channel));
#else
        nrf_ppi_channel_disable(channel);
        err_code = NRF_SUCCESS;
#endif
    }

    return err_code;
}
Beispiel #12
0
uint32_t nrf_drv_ppi_channel_free(nrf_ppi_channel_t channel)
{
    uint32_t err_code;

    if (!is_programmable_app_channel(channel))
    {
        err_code = NRF_ERROR_INVALID_PARAM;
    }
    else
    {
        // First disable this channel
#if (NRF_PPI_RESTRICTED > 0)
        err_code = sd_ppi_channel_enable_clr(channel_to_mask(channel));
#else
        nrf_ppi_channel_disable(channel);
        err_code = NRF_SUCCESS;
#endif
        CRITICAL_REGION_ENTER();
        channel_allocated_clr(channel);
        CRITICAL_REGION_EXIT();
    }

    return err_code;
}
/**********************************************************************
name :
function : disconnect PPI
**********************************************************************/
void ppiOffFromGPIO(uint32_t pin)
{
	uint8_t channel;
	uint32_t err_code = NRF_SUCCESS;
	uint8_t  softdevice_enabled;

	err_code = sd_softdevice_is_enabled(&softdevice_enabled);
	APP_ERROR_CHECK(err_code);

	if(Timer1_Occupied_Pin[0] == pin)
	{
		channel = GPIOTE_Channel_for_Analog[0];

		if(softdevice_enabled == 0)
		{
			NRF_PPI->CHEN &= ~( 1 << PPI_Channels_Occupied[channel][0] );
			NRF_PPI->CHEN &= ~( 1 << PPI_Channels_Occupied[channel][1] );
		}
		else
		{
			err_code = sd_ppi_channel_enable_clr( 1 << PPI_Channels_Occupied[channel][0] );
			APP_ERROR_CHECK(err_code);
			err_code = sd_ppi_channel_enable_clr( 1 << PPI_Channels_Occupied[channel][1] );
			APP_ERROR_CHECK(err_code);
		}
		PPI_Channels_Occupied[channel][0] = 255;
		PPI_Channels_Occupied[channel][1] = 255;
		Timer1_Occupied_Pin[0] = 255;

		gpioteChannelClean(channel);
		GPIOTE_Channel_for_Analog[0] = 255;
	}
	else if(Timer1_Occupied_Pin[1] == pin)
	{

		channel = GPIOTE_Channel_for_Analog[1];
		if(softdevice_enabled == 0)
		{
			NRF_PPI->CHEN &= ~( 1 << PPI_Channels_Occupied[channel][0] );
			NRF_PPI->CHEN &= ~( 1 << PPI_Channels_Occupied[channel][1] );
		}
		else
		{
			err_code = sd_ppi_channel_enable_clr( 1 << PPI_Channels_Occupied[channel][0] );
			APP_ERROR_CHECK(err_code);
			err_code = sd_ppi_channel_enable_clr( 1 << PPI_Channels_Occupied[channel][1] );
			APP_ERROR_CHECK(err_code);
		}
		PPI_Channels_Occupied[channel][0] = 255;
		PPI_Channels_Occupied[channel][1] = 255;
		Timer1_Occupied_Pin[1] = 255;
		gpioteChannelClean(channel);
		GPIOTE_Channel_for_Analog[1] = 255;

	}
	else if(Timer1_Occupied_Pin[2] == pin)
	{
		channel = GPIOTE_Channel_for_Analog[2];
		if(softdevice_enabled == 0)
		{
			NRF_PPI->CHEN &= ~( 1 << PPI_Channels_Occupied[channel][0] );
			NRF_PPI->CHEN &= ~( 1 << PPI_Channels_Occupied[channel][1] );
		}
		else
		{
			err_code = sd_ppi_channel_enable_clr( 1 << PPI_Channels_Occupied[channel][0] );
			APP_ERROR_CHECK(err_code);
			err_code = sd_ppi_channel_enable_clr( 1 << PPI_Channels_Occupied[channel][1] );
			APP_ERROR_CHECK(err_code);
		}
		PPI_Channels_Occupied[channel][0] = 255;
		PPI_Channels_Occupied[channel][1] = 255;
		Timer1_Occupied_Pin[2] = 255;

		gpioteChannelClean(channel);
		GPIOTE_Channel_for_Analog[2] = 255;
	}

	//if all PWM stop, disable TIMER1
	if( Timer1_Occupied_Pin[0] == 255 && Timer1_Occupied_Pin[1] == 255 && Timer1_Occupied_Pin[2] == 255 )
	{
		NRF_TIMER1->TASKS_STOP = 1;
		NRF_TIMER1->INTENCLR = (TIMER_INTENCLR_COMPARE3_Disabled << TIMER_INTENCLR_COMPARE3_Pos);
		NVIC_DisableIRQ(TIMER1_IRQn);
		IntController_unlinkInterrupt(TIMER1_IRQn);
	}

}
/** @brief Function for read by twi_master. 
 */
static bool twi_master_read(uint8_t *data, uint8_t data_length, bool issue_stop_condition)
{
    uint32_t timeout = MAX_TIMEOUT_LOOPS;   /* max loops to wait for RXDREADY event*/

    sd_softdevice_is_enabled(&sd_enabled);
    
    if (data_length == 0)
    {
        /* Return false for requesting data of size 0 */
        return false;
    }
    else if (data_length == 1)
    {
        if(sd_enabled)
        {
            sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_STOP);
        }
        else
        {
            NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
        }
    }
    else
    {
        if(sd_enabled)
        {
            sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_SUSPEND);
        }
        else
        {
            NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
        }
    }
    
    if(sd_enabled)
    {
        sd_ppi_channel_enable_set(1 << 0);
    }
    else
    {
        NRF_PPI->CHENSET          = PPI_CHENSET_CH0_Msk;
    }
    NRF_TWI1->EVENTS_RXDREADY = 0;
    NRF_TWI1->TASKS_STARTRX   = 1;
    
    /** @snippet [TWI HW master read] */                
    while (true)
    {
        while(NRF_TWI1->EVENTS_RXDREADY == 0 && NRF_TWI1->EVENTS_ERROR == 0 && (--timeout))
        {    
            // Do nothing.
        }
        NRF_TWI1->EVENTS_RXDREADY = 0;

        if (timeout == 0 || NRF_TWI1->EVENTS_ERROR != 0)
        {
          // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at 
          // Product Anomaly Notification document found at 
          // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
          NRF_TWI1->EVENTS_ERROR = 0;
          NRF_TWI1->ENABLE       = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; 
          NRF_TWI1->POWER        = 0; 
          nrf_delay_us(5); 
          NRF_TWI1->POWER        = 1; 
          NRF_TWI1->ENABLE       = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;

          (void)twi_master_init();          
          
          return false;
        }

        *data++ = NRF_TWI1->RXD;

        /* Configure PPI to stop TWI master before we get last BB event */
        if (--data_length == 1)
        {
            sd_softdevice_is_enabled(&sd_enabled);
            if(sd_enabled)
            {
                sd_ppi_channel_assign(0, &NRF_TWI1->EVENTS_BB, &NRF_TWI1->TASKS_STOP);
            }
            else
            {
                NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
            }
        }

        if (data_length == 0)
        {
            break;
        }

        // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at 
        // Product Anomaly Notification document found at 
        // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
        nrf_delay_us(20);      
        NRF_TWI1->TASKS_RESUME = 1;
    }
    /** @snippet [TWI HW master read] */                    

    /* Wait until stop sequence is sent */
    while(NRF_TWI1->EVENTS_STOPPED == 0)
    {
        // Do nothing.
    }
    NRF_TWI1->EVENTS_STOPPED = 0;
    
    sd_softdevice_is_enabled(&sd_enabled);
    if(sd_enabled)
    {
        sd_ppi_channel_enable_clr(1 << 0);
    }
    else
    {
        NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
    }
    return true;
}