#include <zephyr.h>
#include <nrfx_rtc.h>
#include <nrfx_clock.h>
#include <hal/nrf_gpio.h>
#include <hal/nrf_rtc.h>
#include <hal/nrf_gpiote.h>
#include <hal/nrf_dppi.h>
#include <nrfx_dppi.h>

#include <nrfx_timer.h>
#include <nrfx_gpiote.h>
#include <helpers/nrfx_gppi.h>


#define LED_1 DT_GPIO_PIN(DT_ALIAS(led1), gpios)
#define LED_2 DT_GPIO_PIN(DT_ALIAS(led2), gpios)
#define BTN   DT_GPIO_PIN(DT_ALIAS(factoryrestore), gpios)

const nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(0);
#define DESIRED_MSEC 1
uint8_t secs = 0;

/** @brief Set bit at given position. */
#define DPPI_BIT_SET(pos) (1uL << (pos))

#define EVENT_INDEX         (0)
#define TASK_INDEX          (1)
#define DPPI_CHANNEL        (0)

static void rtc_handler(nrfx_rtc_int_type_t int_type)
{

  if(int_type == NRFX_RTC_INT_TICK)
  {
    nrf_gpio_pin_toggle(LED_2);
    
  }
  else if(int_type == NRFX_RTC_INT_COMPARE0)
  {
    nrf_gpio_pin_toggle(LED_2);
    int counter = nrfx_rtc_counter_get(&rtc);

    counter += (DESIRED_MSEC * 8);

    nrfx_rtc_cc_set(&rtc,0,counter,true);

    secs++;
    //printk("secs: %d\n", secs);
  }
  
}

static void dppi_setup(void)
{
    //nrf_rtc_publish_set(rtc.p_reg, NRFX_RTC_INT_COMPARE0, DPPI_CHANNEL);

    ///* Configure GPIOTE Index 1 to be a Task*/
    //nrf_gpiote_task_configure(NRF_GPIOTE, TASK_INDEX,LED_1,NRF_GPIOTE_POLARITY_TOGGLE,NRF_GPIOTE_INITIAL_VALUE_LOW);

    ///* Index 1 will Subscribe on DPPI Channel 0 */
    //nrf_gpiote_subscribe_set(NRF_GPIOTE, NRF_GPIOTE_TASK_OUT_1,DPPI_CHANNEL);

    ///* Enable Subscribe */
    //nrf_gpiote_task_enable(NRF_GPIOTE, TASK_INDEX);

    ///* Enable DPPI Channel */
    //nrf_dppi_channels_enable(NRF_DPPIC, DPPI_BIT_SET(DPPI_CHANNEL));

    	uint8_t dppi_ch_1;
	uint32_t err = nrfx_dppi_channel_alloc(&dppi_ch_1);
	if (err != NRFX_SUCCESS) {
		printk("Err %d\n", err);
		return;
	}

        nrfx_gppi_channel_endpoints_setup(dppi_ch_1,
                                          nrf_rtc_event_address_get(rtc.p_reg, NRF_RTC_EVENT_TICK),
                                          nrf_gpiote_task_address_get(NRF_GPIOTE, nrfx_gpiote_out_task_get(LED_1))
                                         );



        /////* Tie it all together */
        //nrf_rtc_publish_set(rtc.p_reg, NRF_RTC_EVENT_TICK, dppi_ch_1);

        //nrf_gpiote_subscribe_set(NRF_GPIOTE, NRF_GPIOTE_TASK_OUT_0, dppi_ch_1);

        
        err = nrfx_dppi_channel_enable(dppi_ch_1);
	if (err != NRFX_SUCCESS) {
		printk("Err %d\n", err);
		return;
	}


}

static void rtc_config(void)
{
  uint32_t err_code;

  nrfx_rtc_config_t rtc_config = NRFX_RTC_DEFAULT_CONFIG;
  rtc_config.prescaler = 4095; //tick = 32768 / (4095 + 1) = 8HZ = 125ms

  err_code = nrfx_rtc_init(&rtc, &rtc_config, rtc_handler);
  if (err_code != NRFX_SUCCESS) {
      printk("timer_init error: %d\n", err_code);
      return;
  }
  nrfx_rtc_tick_enable(&rtc, true);

  nrfx_rtc_enable(&rtc);

   IRQ_DIRECT_CONNECT(RTC0_IRQn, 0, nrfx_rtc_0_irq_handler, 0);
  irq_enable(RTC0_IRQn);
}


static void gpio_config(void)
{
    uint32_t err = nrfx_gpiote_init(0);
      if (err != NRFX_SUCCESS) {
              printk("gpiote1 err: %x", err);
              return;
    }
    	nrfx_gpiote_out_config_t const out_config = {
		.action = NRF_GPIOTE_POLARITY_TOGGLE,
		.init_state = 0,
		.task_pin = true,
	};

	/* Initialize output pin. SET task will turn the LED on,
	 * CLR will turn it off and OUT will toggle it.
	 */
	err = nrfx_gpiote_out_init(LED_1, &out_config);
	if (err != NRFX_SUCCESS) {
		printk("nrfx_gpiote_out_init error: %08x", err);
		return;
	}
    nrf_gpio_cfg_output(LED_2);
    nrfx_gpiote_out_task_enable(LED_1);
}

void main() {

    printk("RTC sample started\n");

    gpio_config();

    rtc_config();

    dppi_setup();
       
 

    //printk("[0] is %d\n",nrf_rtc_event_check(rtc.p_reg, NRF_RTC_EVENT_TICK));
    //printk("[1] is %d\n",nrf_gpiote_te_is_enabled(NRF_GPIOTE, TASK_INDEX));
    //printk("[2] is %d\n",nrf_dppi_channel_check(NRF_DPPIC,DPPI_CHANNEL));

}

