#include "timer_count.h" #define MEAS_PIN 11 #define OSCILLATOR_INIT_DELAY_MS 5 #define USER_NODE DT_PATH(zephyr_user) static const struct gpio_dt_spec hum_en = GPIO_DT_SPEC_GET(USER_NODE, hum_en_gpios); uint32_t count = 0; uint32_t timer_status = 0; void configure_clock_pin(uint32_t pin_number){ nrf_gpio_cfg( pin_number, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE); *(volatile uint32_t *)(NRF_GPIOTE_BASE + 0x600 + (4 * pin_number)) = 1; } void timer_init() //gate timer { NRF_TIMER1->TASKS_STOP = 1; //trigger stop NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; //mode timer NRF_TIMER1->PRESCALER = 4; // Fhck / 2^8 -1MHz //total gate time of timer 10000 - 100mS NRF_TIMER1->CC[0] = 50000; //end gate count NRF_TIMER1->CC[1] = 1; //start gate count. don't start at 0 to no start on clear. NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos); NRF_TIMER1->TASKS_CLEAR = 1; //trigger zero timer NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); //interrupt on end gate count NRF_TIMER1->EVENTS_COMPARE[0] = 0; //rest event flag for gate end NRF_TIMER1->EVENTS_COMPARE[1] = 0; //rest event flag for gate start } static void counter_init() //actual counter { NRF_TIMER2->TASKS_STOP = 1; //trigger stop NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter; //counter NRF_TIMER2->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos); NRF_TIMER2->TASKS_CLEAR = 1; //trigger zero counter NRF_TIMER2->EVENTS_COMPARE[0] = 0; //reset event for compare } //counter input pin setting static void gpiote_init(uint32_t pin) //Pin must be in port 0 { NRF_GPIOTE->CONFIG[0] = 0x01 << 0; // MODE: Event NRF_GPIOTE->CONFIG[0] |= pin << 8; // Pin number NRF_GPIOTE->CONFIG[0] |= GPIOTE_CONFIG_POLARITY_LoToHi << 16; // Event rising edge } //hardware trigger: stop of counter on event of end timer1 gate static void ppi_timer_stop_counter_init() { NRF_PPI->CHEN |= 1 << 2; //channel *(&(NRF_PPI->CH2_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0]; //attach end gate event *(&(NRF_PPI->CH2_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_STOP; //to counter stop trigger NRF_PPI->CHENSET |= 1 << 2; //set channel } //hardware trigger: start of counter on event of begin timer1 (gate) event.gate static void ppi_timer_start_counter_init() { NRF_PPI->CHEN |= 1 << 4;// channel *(&(NRF_PPI->CH4_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[1]; //attach gate start event *(&(NRF_PPI->CH4_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_START; //to counter start trigger NRF_PPI->CHENSET |= 1 << 4; } static void ppi_gpiote_counter_init() //hardware attachment for the gpiote that was selected above { NRF_PPI->CHEN |= 1 << 1; *(&(NRF_PPI->CH1_EEP)) = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0]; //attach pin change *(&(NRF_PPI->CH1_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_COUNT;//to one count NRF_PPI->CHENSET |= 1 << 1; } //gate end interrupt handler. Count is done at hardware and percice interrupt execution isnt critical void TIMER1_IRQHandler(void) { if (NRF_TIMER1->EVENTS_COMPARE[0] != 0){ //end gate event NRF_TIMER1->EVENTS_COMPARE[0] = 0; //reset end gate flag NRF_TIMER1->EVENTS_COMPARE[1] = 0; //reset start gate flag NRF_TIMER2->TASKS_CAPTURE[0] = 1; //trigger get counter value count = NRF_TIMER2->CC[0]; NRF_TIMER1->TASKS_CLEAR = 1; //reset timer NRF_TIMER2->TASKS_CLEAR = 1; //reset counter timer_status = STATE_FINISHED; NRF_TIMER1->TASKS_STOP = 1; //stop gpio_pin_set_dt(&hum_en, 0); //NRF_TIMER1->TASKS_START = 1; //start next count gate } } void configure_measurement() { int ret = 0; NVIC_ClearPendingIRQ(TIMER1_IRQn); NVIC_EnableIRQ(TIMER1_IRQn); //enable timer1 interrupt IRQ_CONNECT(TIMER1_IRQn, 5, TIMER1_IRQHandler, 0, 0); //link interrupt flag to handler if (!device_is_ready(hum_en.port)) { printk("hum_en device not ready\n"); return; } ret = gpio_pin_configure_dt(&hum_en, GPIO_OUTPUT_ACTIVE); if (ret < 0) { printk("Failed to configure hum_en\n"); return; } configure_clock_pin(MEAS_PIN); counter_init(); timer_init(); gpiote_init(MEAS_PIN); ppi_gpiote_counter_init(); ppi_timer_stop_counter_init(); ppi_timer_start_counter_init(); } void make_measurement() { if( timer_status == STATE_RUNNING) { //manage error here return; } gpio_pin_set_dt(&hum_en, 1); k_sleep(K_MSEC(OSCILLATOR_INIT_DELAY_MS)); timer_status = STATE_RUNNING; NRF_TIMER1->TASKS_START = 1; } uint32_t read_measurement(){ if(timer_status != STATE_FINISHED) { return -timer_status; } else{ return count; } }