#include "freq_meter.h"
#include "nrfx_gpiote.h"
#include "nrfx_ppi.h"

#define TILT_PIN NRF_DT_GPIOTE_INST(DT_NODELABEL(tilt_int1), gpios)
#define IN_PIN NRF_DT_GPIOTE_INST(DT_NODELABEL(in_int1), gpios)

const struct gpio_dt_spec int1_tilt = GPIO_DT_SPEC_GET(DT_NODELABEL(tilt_int1), gpios);
const struct gpio_dt_spec int1_in = GPIO_DT_SPEC_GET(DT_NODELABEL(in_int1), gpios);
nrfx_timer_t timer1 = NRFX_TIMER_INSTANCE(1);
nrfx_timer_t timer2 = NRFX_TIMER_INSTANCE(2);
nrfx_timer_t timer3 = NRFX_TIMER_INSTANCE(3);
uint8_t tilt_channel, in_channel;


void counter_init(nrfx_timer_t *p_timer)
{
    uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(p_timer->p_reg);
    nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
    //timer_config.frequency=NRF_TIMER_FREQ_16MHz;
    timer_config.bit_width=NRF_TIMER_BIT_WIDTH_24;

    // Inicjalizacja timera
    nrfx_timer_init(p_timer, &timer_config, NULL);    

    // Włączenie przerwań dla timera
    //nrfx_timer_int_enable(p_timer, NRF_TIMER_INT_COMPARE0_MASK);

    // Uruchomienie timera
    nrfx_timer_enable(p_timer);
}


void counter1_init(void)
{
	counter_init(&timer1);
}
void counter2_init(void)
{
	counter_init(&timer2);
}

void timer_init(nrfx_timer_event_handler_t irq_handler)
{    
    uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer3.p_reg);
    nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);

    //timer_config.frequency=NRF_TIMER_FREQ_16MHz;
    timer_config.bit_width=NRF_TIMER_BIT_WIDTH_24;
    // Inicjalizacja timera
    nrfx_timer_init(&timer3, &timer_config, irq_handler);    

    // Konfiguracja wartości do porównania (62500 - 1s)
    uint32_t ticks = nrfx_timer_us_to_ticks(&timer3, 1000000);
    nrfx_timer_extended_compare(&timer3, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    // Włączenie przerwań dla porównania 0
    nrfx_timer_compare_int_enable(&timer3,0);
    

    // Uruchomienie timera
    nrfx_timer_enable(&timer3);
}

void gpiote_init(uint32_t pin_tilt, uint32_t pin_in)
{        
    nrfx_gpiote_init(NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
    nrfx_gpiote_channel_alloc(&tilt_channel);
    nrfx_gpiote_channel_alloc(&in_channel);

    nrfx_gpiote_input_config_t config = NRFX_GPIOTE_DEFAULT_INPUT_CONFIG;    
    config.pull = NRF_GPIO_PIN_NOPULL;    
    nrfx_gpiote_input_configure(pin_tilt, &config,NRFX_GPIOTE_TRIGGER_LOTOHI,NULL);
    nrfx_gpiote_input_configure(pin_in, &config,NRFX_GPIOTE_TRIGGER_LOTOHI,NULL);
    /*
    NRF_GPIOTE->CONFIG[tilt_channel] = 0x01 << 0;
    NRF_GPIOTE->CONFIG[tilt_channel] = pin_tilt << 8;
    NRF_GPIOTE->CONFIG[tilt_channel] = 1 << 16;
    NRF_GPIOTE->CONFIG[in_channel] = 0x01 << 0;
    NRF_GPIOTE->CONFIG[in_channel] = pin_tilt << 8;
    NRF_GPIOTE->CONFIG[in_channel] = 1 << 16;
    */
}

void ppi_timer_stop_counter_init(void)
{
   static uint8_t stop1_channel,stop2_channel;
   nrfx_ppi_channel_alloc(&stop1_channel);
   nrfx_ppi_channel_alloc(&stop2_channel); 
   nrfx_ppi_channel_assign(
                stop1_channel,
                nrfx_timer_event_address_get(&timer3,NRF_TIMER_EVENT_COMPARE0),
                nrfx_timer_task_address_get(&timer1,NRF_TIMER_TASK_STOP)
                );
   nrfx_ppi_channel_assign(
                stop2_channel,
                nrfx_timer_event_address_get(&timer3,NRF_TIMER_EVENT_COMPARE0),
                nrfx_timer_task_address_get(&timer2,NRF_TIMER_TASK_STOP)
                );             
   nrfx_ppi_channel_enable(stop1_channel);
   nrfx_ppi_channel_enable(stop2_channel);
}

void ppi_timer_start_counter_init(void) {
    static uint8_t start1_channel,start2_channel;
    nrfx_ppi_channel_alloc(&start1_channel);
    nrfx_ppi_channel_alloc(&start2_channel); 
    nrfx_ppi_channel_assign(
        start1_channel,
        nrfx_timer_event_address_get(&timer3,NRF_TIMER_EVENT_COMPARE1),
        nrfx_timer_task_address_get(&timer1,NRF_TIMER_TASK_START)
    );
    nrfx_ppi_channel_assign(
        start2_channel,
        nrfx_timer_event_address_get(&timer3,NRF_TIMER_EVENT_COMPARE1),
        nrfx_timer_task_address_get(&timer2,NRF_TIMER_TASK_START)
    );
    nrfx_ppi_channel_enable(start1_channel);
    nrfx_ppi_channel_enable(start2_channel);
}

void ppi_gpiote_counter_init(void)
{
    /**/
    static uint8_t count1_channel,count2_channel;
    nrfx_ppi_channel_alloc(&count1_channel);
    nrfx_ppi_channel_alloc(&count2_channel);    
    
    //uint32_t e_addr_tilt = (uint32_t)&NRF_GPIOTE->EVENTS_IN[tilt_channel];
    //uint32_t e_addr_in = (uint32_t)&NRF_GPIOTE->EVENTS_IN[in_channel];    
    nrfx_ppi_channel_assign(
        count1_channel,
        nrfx_gpiote_in_event_address_get(int1_tilt.pin),      
        nrfx_timer_task_address_get(&timer1,NRF_TIMER_TASK_COUNT)
    );
    
    nrfx_ppi_channel_assign(
        count2_channel,
        nrfx_gpiote_in_event_address_get(int1_in.pin),
        nrfx_timer_task_address_get(&timer2,NRF_TIMER_TASK_COUNT)
    );
    nrfx_ppi_channel_enable(count1_channel);
    nrfx_ppi_channel_enable(count2_channel);    
}
