void nrf_drv_saadc_uninit(void) { ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); nrf_saadc_int_disable(NRF_SAADC_INT_ALL); nrf_drv_common_irq_disable(SAADC_IRQn); nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); // Wait for ADC being stopped. uint32_t timeout = HW_TIMEOUT; while (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED) == 0 && timeout > 0) { --timeout; } ASSERT(timeout > 0); nrf_saadc_disable(); m_cb.adc_state = NRF_SAADC_STATE_IDLE; for (uint8_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel) { if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED) { (void)nrf_drv_saadc_channel_uninit(channel); } } m_cb.state = NRF_DRV_STATE_UNINITIALIZED; }
ret_code_t nrf_drv_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value) { if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) { return NRF_ERROR_BUSY; } m_cb.adc_state = NRF_SAADC_STATE_BUSY; nrf_saadc_int_disable(NRF_SAADC_INT_END); nrf_saadc_buffer_init(p_value, 1); nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); uint32_t timeout = 100000; while (0 == nrf_saadc_event_check(NRF_SAADC_EVENT_END) && timeout > 0) { timeout--; } nrf_saadc_event_clear(NRF_SAADC_EVENT_END); nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); nrf_saadc_int_enable(NRF_SAADC_INT_END); m_cb.adc_state = NRF_SAADC_STATE_IDLE; return NRF_SUCCESS; }
ret_code_t nrf_drv_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size) { ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); ASSERT((size % m_cb.active_channels) == 0); nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) { nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); return NRF_ERROR_BUSY; } if (m_cb.adc_state == NRF_SAADC_STATE_BUSY) { if ( m_cb.p_secondary_buffer) { nrf_saadc_int_enable(NRF_SAADC_INT_END); return NRF_ERROR_BUSY; } else { m_cb.p_secondary_buffer = p_buffer; m_cb.secondary_buffer_size = size; if (!m_cb.low_power_mode) { while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0) ; nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); nrf_saadc_buffer_init(p_buffer, size); } nrf_saadc_int_enable(NRF_SAADC_INT_END); return NRF_SUCCESS; } } nrf_saadc_int_enable(NRF_SAADC_INT_END); m_cb.adc_state = NRF_SAADC_STATE_BUSY; m_cb.p_buffer = p_buffer; m_cb.buffer_size = size; m_cb.p_secondary_buffer = NULL; if (m_cb.low_power_mode) { m_cb.buffer_size_left = size; nrf_saadc_buffer_init(p_buffer, m_cb.active_channels); } else { nrf_saadc_buffer_init(p_buffer, size); nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); } return NRF_SUCCESS; }
nrf_saadc_value_t nrf_analog_read() { nrf_saadc_value_t result; nrf_saadc_buffer_init(&result,1); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); while(!nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)); nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); while(!nrf_saadc_event_check(NRF_SAADC_EVENT_END)); nrf_saadc_event_clear(NRF_SAADC_EVENT_END); nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); while(!nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)); nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); return result; }
ret_code_t nrf_drv_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value) { if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) { return NRF_ERROR_BUSY; } m_cb.adc_state = NRF_SAADC_STATE_BUSY; nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); nrf_saadc_buffer_init(p_value, 1); if (m_cb.active_channels > 1) { for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) { nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); } } nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); uint32_t timeout = HW_TIMEOUT; while (0 == nrf_saadc_event_check(NRF_SAADC_EVENT_END) && timeout > 0) { timeout--; } nrf_saadc_event_clear(NRF_SAADC_EVENT_END); if (m_cb.active_channels > 1) { for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) { nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln); } } if (m_cb.low_power_mode) { nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); } else { nrf_saadc_int_enable(NRF_SAADC_INT_END); } m_cb.adc_state = NRF_SAADC_STATE_IDLE; return NRF_SUCCESS; }
void SAADC_IRQHandler(void) { if (nrf_saadc_event_check(NRF_SAADC_EVENT_END)) { nrf_saadc_event_clear(NRF_SAADC_EVENT_END); if (!m_cb.low_power_mode || m_cb.conversions_end) { nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_DONE; evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer; evt.data.done.size = m_cb.buffer_size; if (m_cb.p_secondary_buffer == NULL) { m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else { m_cb.p_buffer = m_cb.p_secondary_buffer; m_cb.buffer_size = m_cb.secondary_buffer_size; m_cb.p_secondary_buffer = NULL; if (!m_cb.low_power_mode) { nrf_saadc_task_trigger(NRF_SAADC_TASK_START); } } m_cb.event_handler(&evt); m_cb.conversions_end = false; } } if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)) { nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); if (m_cb.buffer_size_left == 0) { // Sampling finished, next buffer in progress. m_cb.buffer_size_left = m_cb.buffer_size - m_cb.active_channels; nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size - m_cb.buffer_size_left], m_cb.active_channels); } else if (m_cb.buffer_size_left > m_cb.active_channels) { // More samples to convert than for single event. m_cb.buffer_size_left -= m_cb.active_channels; nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size - m_cb.buffer_size_left], m_cb.active_channels); } else if ((m_cb.buffer_size_left == m_cb.active_channels) && (m_cb.p_secondary_buffer != NULL)) { // Samples to convert for one event, prepare next buffer. m_cb.conversions_end = true; m_cb.buffer_size_left = 0; nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer, m_cb.active_channels); } else if (m_cb.buffer_size_left == m_cb.active_channels) { // Samples to convert for one event, but no second buffer. m_cb.conversions_end = true; m_cb.buffer_size_left = 0; } nrf_saadc_event_clear(NRF_SAADC_EVENT_END); nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); } if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE)) { nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); m_cb.adc_state = NRF_SAADC_STATE_IDLE; nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_CALIBRATEDONE; m_cb.event_handler(&evt); } if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) { nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else { uint32_t limit_flags = m_cb.limits_enabled_flags; uint32_t flag_idx; nrf_saadc_event_t event; while (limit_flags) { flag_idx = __CLZ(limit_flags); limit_flags &= ~((1UL << 31) >> flag_idx); event = FLAG_IDX_TO_EVENT(flag_idx); if (nrf_saadc_event_check(event)) { nrf_saadc_event_clear(event); nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_LIMIT; evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event); evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event); m_cb.event_handler(&evt); } } } }
ret_code_t nrf_drv_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size) { ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); nrf_saadc_int_disable(NRF_SAADC_INT_END); if (m_cb.adc_state == NRF_SAADC_STATE_BUSY) { if ( m_cb.p_secondary_buffer) { nrf_saadc_int_enable(NRF_SAADC_INT_END); return NRF_ERROR_BUSY; } else { m_cb.p_secondary_buffer = p_buffer; m_cb.secondary_buffer_size = size; if (m_cb.active_channels == 1) { while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0); nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); nrf_saadc_buffer_init(p_buffer, size); } nrf_saadc_int_enable(NRF_SAADC_INT_END); return NRF_SUCCESS; } } nrf_saadc_int_enable(NRF_SAADC_INT_END); m_cb.adc_state = NRF_SAADC_STATE_BUSY; m_cb.scan_pos = NRF_SAADC_CHANNEL_COUNT; for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) { if (m_cb.psel[i].pselp) { m_cb.scan_pos = i; break; } } // Find the first enabled channel. if (m_cb.scan_pos >= NRF_SAADC_CHANNEL_COUNT) { return NRF_ERROR_INVALID_STATE; } m_cb.buffer = p_buffer; m_cb.buffer_size = size; m_cb.buffer_pos = 0; m_cb.p_secondary_buffer = NULL; nrf_saadc_channel_input_set(m_cb.scan_pos, m_cb.psel[m_cb.scan_pos].pselp, m_cb.psel[m_cb.scan_pos].pseln); if (m_cb.active_channels == 1) { nrf_saadc_buffer_init(p_buffer, size); } else { nrf_saadc_buffer_init(p_buffer, 1); } nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); return NRF_SUCCESS; }
void SAADC_IRQHandler(void) { if (nrf_saadc_event_check(NRF_SAADC_EVENT_END)) { nrf_saadc_event_clear(NRF_SAADC_EVENT_END); if (m_cb.active_channels == 1) { nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_DONE; evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.buffer; evt.data.done.size = m_cb.buffer_size; if (m_cb.p_secondary_buffer == NULL) { m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else { m_cb.buffer = m_cb.p_secondary_buffer; m_cb.buffer_size = m_cb.secondary_buffer_size; m_cb.p_secondary_buffer = NULL; nrf_saadc_task_trigger(NRF_SAADC_TASK_START); } m_cb.event_handler(&evt); } else { //PAN-28: scan mode is not working correctly, emulated by interrupts m_cb.buffer_pos++; uint16_t buffer_pos = m_cb.buffer_pos; if (buffer_pos == m_cb.buffer_size) { nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_DONE; evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.buffer; evt.data.done.size = m_cb.buffer_size; m_cb.adc_state = NRF_SAADC_STATE_IDLE; if (m_cb.p_secondary_buffer == NULL) { m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else { (void)nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *)m_cb.p_secondary_buffer, (uint16_t)m_cb.secondary_buffer_size); } m_cb.event_handler(&evt); } else { // uint8_t current_scan_pos = m_cb.scan_pos; nrf_saadc_channel_input_set(current_scan_pos, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); nrf_saadc_buffer_init((nrf_saadc_value_t *)(m_cb.buffer + m_cb.buffer_pos), 1); // Find the next enabled channel. for (++m_cb.scan_pos; m_cb.scan_pos < NRF_SAADC_CHANNEL_COUNT; ++m_cb.scan_pos) { if (m_cb.psel[m_cb.scan_pos].pselp) { nrf_saadc_channel_input_set(m_cb.scan_pos, m_cb.psel[m_cb.scan_pos].pselp, m_cb.psel[m_cb.scan_pos].pseln); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); return; } } //if scanning is done prepare for next round. for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) { if (m_cb.psel[i].pselp) { m_cb.scan_pos = i; break; } } nrf_saadc_channel_input_set(m_cb.scan_pos, m_cb.psel[m_cb.scan_pos].pselp, m_cb.psel[m_cb.scan_pos].pseln); nrf_saadc_task_trigger(NRF_SAADC_TASK_START); } } } if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) { nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else { uint32_t limit_flags = m_cb.limits_enabled_flags; uint32_t flag_idx; nrf_saadc_event_t event; while (limit_flags) { flag_idx = __CLZ(limit_flags); limit_flags &= ~(0x80000000 >> flag_idx); event = FLAG_IDX_TO_EVENT(flag_idx); if (nrf_saadc_event_check(event)) { nrf_saadc_event_clear(event); nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_LIMIT; evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event); evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event); m_cb.event_handler(&evt); } } } }