예제 #1
0
void nrfx_clock_irq_handler(void)
{
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED));
        nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);

#if defined(USE_WORKAROUND_FOR_ANOMALY_201)
        if (!m_clock_cb.hfclk_started)
        {
            m_clock_cb.hfclk_started = true;
            m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
        }
#else
        m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
#endif
    }
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED));
        nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);

        m_clock_cb.event_handler(NRFX_CLOCK_EVT_LFCLK_STARTED);
    }
#if CALIBRATION_SUPPORT
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_CTTO));
        nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);

        m_clock_cb.event_handler(NRFX_CLOCK_EVT_CTTO);
    }

    if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
    {
#if defined(USE_WORKAROUND_FOR_ANOMALY_192)
        *(volatile uint32_t *)0x40000C34 = 0x00000000;
#endif
        nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_DONE));
        nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
        m_clock_cb.cal_state = CAL_STATE_IDLE;
        m_clock_cb.event_handler(NRFX_CLOCK_EVT_CAL_DONE);
    }
#endif // CALIBRATION_SUPPORT
}
예제 #2
0
static void spis_irq_handler(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb)
{
    // @note: as multiple events can be pending for processing, the correct event processing order
    // is as follows:
    // - SPI semaphore acquired event.
    // - SPI transaction complete event.

    // Check for SPI semaphore acquired event.
    if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ACQUIRED))
    {
        nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
        NRF_LOG_DEBUG("SPIS: Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SPIS_EVENT_ACQUIRED));

        switch (p_cb->spi_state)
        {
            case SPIS_BUFFER_RESOURCE_REQUESTED:
                nrf_spis_tx_buffer_set(p_spis, (uint8_t *)p_cb->tx_buffer, p_cb->tx_buffer_size);
                nrf_spis_rx_buffer_set(p_spis, (uint8_t *)p_cb->rx_buffer, p_cb->rx_buffer_size);

                nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_RELEASE);

                spis_state_change(p_spis, p_cb, SPIS_BUFFER_RESOURCE_CONFIGURED);
                break;

            default:
                // No implementation required.
                break;
        }
    }

    // Check for SPI transaction complete event.
    if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_END))
    {
        nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
        NRF_LOG_DEBUG("SPIS: Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SPIS_EVENT_END));

        switch (p_cb->spi_state)
        {
            case SPIS_BUFFER_RESOURCE_CONFIGURED:
                spis_state_change(p_spis, p_cb, SPIS_XFER_COMPLETED);
                break;

            default:
                // No implementation required.
                break;
        }
    }
}
예제 #3
0
HRESULT	CaptureHelper::DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError err)
{
	printf("\n === '%s' event (%s)\n", EVT_TO_STR(event), ERR_TO_STR(err));
	
	switch (event){
		case bmdDeckControlPrepareForCaptureEvent:
			// We receive this event a few frames before we reach the in-point. The serial timecode
			// attached to IDeckLinkVideoFrames (received in VideoInputFrameArrived) is now
			// valid and can be used to find the in- and out-points.
			m_captureStarted = true;
			break;
		case bmdDeckControlCaptureCompleteEvent:
			// we receive this event a few frames after the out-point.
			// It is now safe to unblock the main thread, close the 
			// connection to the deck and release the IDeckLinkDeckControl 
			// and IDeckLinkInput interfaces

			// fallthrough
			
		case bmdDeckControlAbortedEvent:
			m_captureStarted = false;
			
			// unblock the main thread
			pthread_mutex_lock(&m_mutex);
				if (m_waitingForCaptureEnd)
					pthread_cond_signal(&m_condition);
			pthread_mutex_unlock(&m_mutex);
			break;
	}
	
	return S_OK;
	
}
예제 #4
0
/*
 * IDeckLinkDeckControlStatusCallback methods
 */
HRESULT ETTHelper::DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error)
{
	printf("\n === '%s' event (error: %s)\n", EVT_TO_STR(event), ERR_TO_STR(error));
	
	switch (event){
		case bmdDeckControlPrepareForExportEvent:
			// We receive this event a few frames before the inpoint. 
			// At this point, we must call IDeckLinkOutput::StartScheduledPlayback()
			printf("Starting playback\n");
			if (m_deckLinkOutput->StartScheduledPlayback(0, m_timeScale, 1.0) == S_OK)
				m_exportStarted = true;
			else
				printf("Error starting playback\n");
			break;
		case bmdDeckControlExportCompleteEvent:
			// We receive this event a few frames after the out-point.
			// It is now safe to unblock the main thread, close the 
			// connection to the deck and release the IDeckLinkDeckControl 
			// and IDeckLinkOutput interfaces
	
			// fallthrough
			
		case bmdDeckControlAbortedEvent:
			m_exportStarted = false;
			
			// unblock main thread
			pthread_mutex_lock(&m_mutex);
				if (m_waitingForExportEnd)
					pthread_cond_signal(&m_condition);
			pthread_mutex_unlock(&m_mutex);
			break;
	}
	
	return S_OK;
}
예제 #5
0
void POWER_CLOCK_IRQHandler(void)
#endif
{
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED));
        nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);
        m_clock_cb.hfclk_on = true;
        clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
    }
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED));
        nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);
        m_clock_cb.lfclk_on = true;
        clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
    }
#if CALIBRATION_SUPPORT
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_CTTO));
        nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
        nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
    }

    if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_DONE));
        nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
        nrf_drv_clock_hfclk_release();
        bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT);
        m_clock_cb.cal_state = CAL_STATE_IDLE;
        if (m_clock_cb.cal_done_handler)
        {
            m_clock_cb.cal_done_handler(aborted ?
                NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE);
        }
    }
#endif // CALIBRATION_SUPPORT
}
static void comp_execute_handler(nrf_comp_event_t event, uint32_t event_mask)
{
    if (nrf_comp_event_check(event) && nrf_comp_int_enable_check(event_mask))
    {
        nrf_comp_event_clear(event);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));

        m_comp_event_handler(event);
    }
}
예제 #7
0
static void lpcomp_execute_handler(nrf_lpcomp_event_t event, uint32_t event_mask)
{
    if ( nrf_lpcomp_event_check(event) && nrf_lpcomp_int_enable_check(event_mask) )
    {
        nrf_lpcomp_event_clear(event);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(event));

        m_lpcomp_events_handler(event);
    }
}
예제 #8
0
파일: nrfx_rtc.c 프로젝트: turon/openthread
static void irq_handler(NRF_RTC_Type * p_reg,
                        uint32_t       instance_id,
                        uint32_t       channel_count)
{
    uint32_t i;
    uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK;
    nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0;

    for (i = 0; i < channel_count; i++)
    {
        if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event))
        {
            nrf_rtc_event_disable(p_reg,int_mask);
            nrf_rtc_int_disable(p_reg,int_mask);
            nrf_rtc_event_clear(p_reg,event);
            NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
            m_handlers[instance_id]((nrfx_rtc_int_type_t)i);
        }
        int_mask <<= 1;
        event    = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t));
    }
    event = NRF_RTC_EVENT_TICK;
    if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) &&
        nrf_rtc_event_pending(p_reg, event))
    {
        nrf_rtc_event_clear(p_reg, event);
        NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
        m_handlers[instance_id](NRFX_RTC_INT_TICK);
    }

    event = NRF_RTC_EVENT_OVERFLOW;
    if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) &&
        nrf_rtc_event_pending(p_reg, event))
    {
        nrf_rtc_event_clear(p_reg,event);
        NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
        m_handlers[instance_id](NRFX_RTC_INT_OVERFLOW);
    }
}
예제 #9
0
void nrfx_clock_irq_handler(void)
{
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED));
        nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);

        m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
    }
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED));
        nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);

        m_clock_cb.event_handler(NRFX_CLOCK_EVT_LFCLK_STARTED);
    }
#if CALIBRATION_SUPPORT
    if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_CTTO));
        nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);

        m_clock_cb.event_handler(NRFX_CLOCK_EVT_CTTO);
    }

    if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
    {
        nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_DONE));
        nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
        m_clock_cb.cal_state = CAL_STATE_IDLE;
        m_clock_cb.event_handler(NRFX_CLOCK_EVT_CAL_DONE);
    }
#endif // CALIBRATION_SUPPORT
}
예제 #10
0
void nrfx_qdec_irq_handler(void)
{
    nrfx_qdec_event_t event;
    if ( nrf_qdec_event_check(NRF_QDEC_EVENT_SAMPLERDY) &&
         nrf_qdec_int_enable_check(NRF_QDEC_INT_SAMPLERDY_MASK) )
    {
        nrf_qdec_event_clear(NRF_QDEC_EVENT_SAMPLERDY);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_SAMPLERDY));

        event.type = NRF_QDEC_EVENT_SAMPLERDY;
        event.data.sample.value = (int8_t)nrf_qdec_sample_get();
        m_qdec_event_handler(event);
    }

    if ( nrf_qdec_event_check(NRF_QDEC_EVENT_REPORTRDY) &&
         nrf_qdec_int_enable_check(NRF_QDEC_INT_REPORTRDY_MASK) )
    {
        nrf_qdec_event_clear(NRF_QDEC_EVENT_REPORTRDY);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_REPORTRDY));

        event.type = NRF_QDEC_EVENT_REPORTRDY;

        event.data.report.acc    = (int16_t)nrf_qdec_accread_get();
        event.data.report.accdbl = (uint16_t)nrf_qdec_accdblread_get();
        m_qdec_event_handler(event);
    }

    if ( nrf_qdec_event_check(NRF_QDEC_EVENT_ACCOF) &&
         nrf_qdec_int_enable_check(NRF_QDEC_INT_ACCOF_MASK) )
    {
        nrf_qdec_event_clear(NRF_QDEC_EVENT_ACCOF);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_ACCOF));

        event.type = NRF_QDEC_EVENT_ACCOF;
        m_qdec_event_handler(event);
    }
}
예제 #11
0
static void uart_irq_handler(NRF_UART_Type *        p_uart,
                             uart_control_block_t * p_cb)
{
    if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_ERROR) &&
        nrf_uart_event_check(p_uart, NRF_UART_EVENT_ERROR))
    {
        nrfx_uart_event_t event;
        nrf_uart_event_clear(p_uart, NRF_UART_EVENT_ERROR);
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_UART_EVENT_ERROR));
        nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
                                     NRF_UART_INT_MASK_ERROR);
        if (!p_cb->rx_enabled)
        {
            nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
        }
        event.type                   = NRFX_UART_EVT_ERROR;
        event.data.error.error_mask  = nrf_uart_errorsrc_get_and_clear(p_uart);
        event.data.error.rxtx.bytes  = p_cb->rx_buffer_length;
        event.data.error.rxtx.p_data = p_cb->p_rx_buffer;

        // Abort transfer.
        p_cb->rx_buffer_length = 0;
        p_cb->rx_secondary_buffer_length = 0;

        p_cb->handler(&event,p_cb->p_context);
    }
    else if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_RXDRDY) &&
             nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXDRDY))
    {
        rx_byte(p_uart, p_cb);
        if (p_cb->rx_buffer_length == p_cb->rx_counter)
        {
            if (p_cb->rx_secondary_buffer_length)
            {
                uint8_t * p_data     = p_cb->p_rx_buffer;
                size_t    rx_counter = p_cb->rx_counter;

                // Switch to secondary buffer.
                p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length;
                p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer;
                p_cb->rx_secondary_buffer_length = 0;
                p_cb->rx_counter = 0;
                rx_done_event(p_cb, rx_counter, p_data);
            }
            else
            {
                if (!p_cb->rx_enabled)
                {
                    nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
                }
                nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
                                             NRF_UART_INT_MASK_ERROR);
                p_cb->rx_buffer_length = 0;
                rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
            }
        }
    }

    if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
    {
        if (p_cb->tx_counter < p_cb->tx_buffer_length &&
            !p_cb->tx_abort)
        {
            tx_byte(p_uart, p_cb);
        }
        else
        {
            nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
            if (p_cb->tx_buffer_length)
            {
                tx_done_event(p_cb, p_cb->tx_buffer_length);
            }
        }
    }

    if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXTO))
    {
        nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXTO);

        // RXTO event may be triggered as a result of abort call. In th
        if (p_cb->rx_enabled)
        {
            nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STARTRX);
        }
        if (p_cb->rx_buffer_length)
        {
            p_cb->rx_buffer_length = 0;
            rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
        }
    }
}
예제 #12
0
void I2S_IRQHandler(void)
{
    uint32_t const * p_data_received = NULL;
    uint32_t       * p_data_to_send  = NULL;

    if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD))
    {
        nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD);
        NRF_LOG_DEBUG("Event: %s.",
            (uint32_t)EVT_TO_STR(NRF_I2S_EVENT_TXPTRUPD));

        // If transmission is not enabled, but for some reason the TXPTRUPD
        // event has been generated, just ignore it.
        if (m_cb.p_tx_buffer != NULL)
        {
            uint32_t * p_tx_buffer_next;
            if (nrf_i2s_tx_buffer_get(NRF_I2S) == m_cb.p_tx_buffer)
            {
                p_tx_buffer_next = m_cb.p_tx_buffer + m_cb.buffer_half_size;
            }
            else
            {
                p_tx_buffer_next = m_cb.p_tx_buffer;
            }
            nrf_i2s_tx_buffer_set(NRF_I2S, p_tx_buffer_next);

            m_cb.tx_ready = true;

            // Now the part of the buffer that we've configured as "next" should
            // be filled by the application with proper data to be sent;
            // the peripheral is sending data from the other part of the buffer
            // (but it will finish soon...).
            p_data_to_send = p_tx_buffer_next;

        }
    }

    if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD))
    {
        nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD);
        NRF_LOG_DEBUG("Event: %s.",
            (uint32_t)EVT_TO_STR(NRF_I2S_EVENT_RXPTRUPD));

        // If reception is not enabled, but for some reason the RXPTRUPD event
        // has been generated, just ignore it.
        if (m_cb.p_rx_buffer != NULL)
        {
            uint32_t * p_rx_buffer_next;
            if (nrf_i2s_rx_buffer_get(NRF_I2S) == m_cb.p_rx_buffer)
            {
                p_rx_buffer_next = m_cb.p_rx_buffer + m_cb.buffer_half_size;
            }
            else
            {
                p_rx_buffer_next = m_cb.p_rx_buffer;
            }
            nrf_i2s_rx_buffer_set(NRF_I2S, p_rx_buffer_next);

            m_cb.rx_ready = true;

            // The RXPTRUPD event is generated for the first time right after
            // the transfer is started. Since there is no data received yet at
            // this point we only update the buffer pointer (it is done above),
            // there is no callback to the application.
            // [for synchronized mode this has to be handled differently -
            //  see below]
            if (m_cb.just_started && !m_cb.synchronized_mode)
            {
                m_cb.just_started = false;
            }
            else
            {
                // The RXPTRUPD event indicates that from now on the peripheral
                // will be filling the part of the buffer that was pointed at
                // the time the event has been generated, hence now we can let
                // the application process the data stored in the other part of
                // the buffer - the one that we've just set to be filled next.
                p_data_received = p_rx_buffer_next;
            }
        }
    }

    // Call the data handler passing received data to the application and/or
    // requesting data to be sent.
    if (!m_cb.synchronized_mode)
    {
        if ((p_data_received != NULL) || (p_data_to_send != NULL))
        {
            if (p_data_received != NULL)
            {
                NRF_LOG_DEBUG("Rx data:");
                NRF_LOG_HEXDUMP_DEBUG(p_data_received,
                    m_cb.buffer_half_size * sizeof(p_data_received[0]));
            }
            m_cb.handler(p_data_received, p_data_to_send,
                m_cb.buffer_half_size);
            if (p_data_to_send != NULL)
            {
                NRF_LOG_DEBUG("Tx data:");
                NRF_LOG_HEXDUMP_DEBUG(p_data_to_send,
                    m_cb.buffer_half_size * sizeof(p_data_to_send[0]));
            }
        }
    }
    // In the synchronized mode wait until the events for both RX and TX occur.
    // And ignore the initial occurrences of these events, since they only
    // indicate that the transfer has started - no data is received yet at
    // that moment, so we have got nothing to pass to the application.
    else
    {
        if (m_cb.rx_ready && m_cb.tx_ready)
        {
            m_cb.rx_ready = false;
            m_cb.tx_ready = false;

            if (m_cb.just_started)
            {
                m_cb.just_started = false;
            }
            else
            {
                NRF_LOG_DEBUG("Rx data:");
                NRF_LOG_HEXDUMP_DEBUG(nrf_i2s_rx_buffer_get(NRF_I2S),
                    m_cb.buffer_half_size * sizeof(p_data_to_send[0]));
                m_cb.handler(nrf_i2s_rx_buffer_get(NRF_I2S),
                             nrf_i2s_tx_buffer_get(NRF_I2S),
                             m_cb.buffer_half_size);
                NRF_LOG_DEBUG("Tx data:");
                NRF_LOG_HEXDUMP_DEBUG(nrf_i2s_tx_buffer_get(NRF_I2S),
                    m_cb.buffer_half_size * sizeof(p_data_to_send[0]));
            }
        }
    }
}
static void twim_irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb)
{

#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
    /* Handle only workaround case. Can be used without TWIM handler in IRQs. */
    if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
    {
        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
        nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
        if (p_twim->FREQUENCY == 0)
        {
            // Set enable to zero to reset TWIM internal state.
            nrf_twim_disable(p_twim);
            nrf_twim_enable(p_twim);

            // Set proper frequency.
            nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
            twim_list_enable_handle(p_twim, p_cb->flags);

            // Start proper transmission.
            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
            return;
        }
    }
#endif

    NRFX_ASSERT(p_cb->handler);

    if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
    {
        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
        NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
        if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
        {
            nrf_twim_int_disable(p_twim, p_cb->int_mask);
            p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
            nrf_twim_int_enable(p_twim, p_cb->int_mask);

            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
            return;
        }
    }

    nrfx_twim_evt_t event;

    if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
    {
        NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
        event.xfer_desc = p_cb->xfer_desc;
        if (p_cb->error)
        {

            event.xfer_desc.primary_length = (p_cb->xfer_desc.type == NRFX_TWIM_XFER_RX) ?
                nrf_twim_rxd_amount_get(p_twim) : nrf_twim_txd_amount_get(p_twim);
            event.xfer_desc.secondary_length = (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TXRX) ?
                nrf_twim_rxd_amount_get(p_twim) : nrf_twim_txd_amount_get(p_twim);

        }
        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
        if (!p_cb->repeated || p_cb->error)
        {
            nrf_twim_shorts_set(p_twim, 0);
            p_cb->int_mask = 0;
            nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
        }
    }
    else
    {
        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
        NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
        if (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TX)
        {
            event.xfer_desc = p_cb->xfer_desc;
            if (!p_cb->repeated)
            {
                nrf_twim_shorts_set(p_twim, 0);
                p_cb->int_mask = 0;
                nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
            }
        }
        else
        {
            nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
            p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
            nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
            nrf_twim_int_enable(p_twim, p_cb->int_mask);
            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
            return;
        }
    }

    uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
    if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
    {
        event.type = NRFX_TWIM_EVT_ADDRESS_NACK;
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_ADDRESS_NACK));
    }
    else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
    {
        event.type = NRFX_TWIM_EVT_DATA_NACK;
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DATA_NACK));
    }
    else
    {
        event.type = NRFX_TWIM_EVT_DONE;
        NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DONE));
    }

    if (!p_cb->repeated)
    {
        p_cb->busy = false;
    }
    p_cb->handler(&event, p_cb->p_context);
}