
#include "config.h"

/**@brief Function for Watchdog initialization.
 */
static void wdt_start(unsigned int second)
{
	NRF_WDT->CONFIG = (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos) | ( WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos);   //Configure Watchdog. a) Pause watchdog while the CPU is halted by the debugger.  b) Keep the watchdog running while the CPU is sleeping.
	NRF_WDT->CRV = second*32768;             //cca number of seconds timeout set
	NRF_WDT->RREN |= WDT_RREN_RR0_Msk;  //Enable reload register 0
	NRF_WDT->RR[0] = WDT_RR_RR_Reload;  //Reload watchdog register 0
	NRF_WDT->TASKS_START = 1;           //Start the Watchdog timer
}

/**@brief Function for Real time clock initialization.
 */
static void rtc_start(unsigned int second)
{
	NRF_RTC1->PRESCALER = 4095;	//8Hz

  NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
  NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
  NRF_RTC1->CC[0] = second * 8;  // interrupt at ~128Hz

  NVIC_ClearPendingIRQ(RTC1_IRQn);
  NVIC_EnableIRQ(RTC1_IRQn);

  NRF_RTC1->TASKS_START = 1;

}

void wait_ms(unsigned int ms)	//16MHz --> 16000 cycles = 1ms
{
	while(16000*ms)
		ms--;
}

/**@brief Function for GPIO configuration.
 */
void gpio_config(void)
{
		
		nrf_gpio_cfg_input(7, GPIO_PIN_CNF_PULL_Disabled);
	
		//if pin 7 already set to 0 reset after WDT
		if(!(NRF_GPIO->IN & GPIO_IN_PIN7_Msk))
		{
			rtc_start(5);
			__SEV();	//clear event register
			__WFE();	//wait for event
			__WFE();
		}
		else
		{
			//set pin 7 as wake up pin high to low
			NRF_GPIO->PIN_CNF[7] = (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
                                        | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
                                        | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
                                        | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
                                        | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
			
			NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;	//interrupt set for GPIOTE
			NVIC_EnableIRQ(GPIOTE_IRQn);
			
			//wait 30 seconds for ADXL interrupt
			//when no interrupt is received in 30 seconds the WDT does reset
			rtc_start(30);
			__SEV();	//clear event register
			__WFE();	//wait for event possibly __WFI()????
			__WFE();

		}
}



/**@brief Function for GPIO configuration in DEEP SLEEP MODE -->> only ADXL interrupt can wake up the Nordic.
 */
void gpio_config_deep_sleep(void)
{
		
		nrf_gpio_cfg_input(7, GPIO_PIN_CNF_PULL_Disabled);
	
		//set pin 7 as wake up pin high to low
		NRF_GPIO->PIN_CNF[7] = (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
                         | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
                         | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
                         | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
                         | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
		
			//deep sleep, wait for ADXL interrupt
			NRF_POWER->SYSTEMOFF = 1;	
}


/**@brief Function for SPI initialization.
 */
void spi_init(void)
{
	/////
					rtc_start(5);
			__SEV();	//clear event register
			__WFE();	//wait for event possibly __WFI()????
			__WFE();
	/////
	nrf_gpio_cfg_output(0);	//CS0
	nrf_gpio_pin_set(0);
	
	nrf_gpio_cfg_input(1, GPIO_PIN_CNF_PULL_Disabled);	//MISO1
	NRF_SPI0->PSELMISO = 1;
	
	nrf_gpio_cfg_output(2);	//MOSI2
	NRF_SPI0->PSELMOSI = 2;
	
	nrf_gpio_cfg_output(4);	//SCLK4
	NRF_SPI0->PSELSCK = 4;
	
	NRF_SPI0->FREQUENCY = 0x10000000;	//1MHz
	NRF_SPI0->CONFIG = 0;	//CPHA = CPOL = 0, MSB first
	NRF_SPI0->ENABLE = 1;	//Enable SPI
	
}


/**@brief Function for SPI sending byte.
 */
uint8_t spi_write_byte(uint8_t byte)
{
	NRF_SPI0->TXD = byte;
	while(!(NRF_SPI0->EVENTS_READY));	//wait fo transaction to be finished
	NRF_SPI0->EVENTS_READY = 0;
	return NRF_SPI0->RXD;
}


/**@brief Function for SPI sending packet.
 */
void spi_send(uint8_t *tx_buf)
{
	nrf_gpio_pin_clear(0);	//CS0
	uint8_t read =0;
	
	for(uint8_t i=0; i<3; i++)
	{
		read = spi_write_byte(*tx_buf++);
		
	}
	
	nrf_gpio_pin_set(0);	//CS0	
}

/**@brief Function for SPI reading byte.
 */
uint8_t spi_read(uint8_t *tx_buf)
{
	nrf_gpio_pin_clear(0);	//CS0
	uint8_t read =0;
	
	for(uint8_t i=0; i<3; i++)
	{
		read = spi_write_byte(*tx_buf++);
		
	}
	
	nrf_gpio_pin_set(0);	//CS	0
	return read;
} 

/**@brief Function for ADXL362 configuration.
 */
void adxl_config(void)
{
		uint8_t soft_reset[] = {0x0A, 0x1F, 0x52};				//soft reset
		uint8_t adxl_threshold1[] = {0x0A, 0x20, 0x96};
		uint8_t adxl_threshold2[] = {0x0A, 0x21, 0x00};		//set activity threshold to 150 mg
		uint8_t adxl_activity[] = {0x0A, 0x27, 0x03};			//reference activity enable
		uint8_t adxl_int[] = {0x0A, 0x2A, 0x90};					//maps activity bit to interrput1, active low
		uint8_t adxl_int2[] = {0x0A, 0x2B, 0x90};					//maps activity bit to interrput2, active low
		uint8_t adxl_wakeup[] = {0x0A, 0x2D, 0x0A};				//begin measurement in wake up mode
		uint8_t status[] = {0x0B, 0x0B,0x00};
		
		spi_send(&soft_reset[0]);
		wait_ms(5);
		spi_send(&adxl_threshold1[0]);
		spi_send(&adxl_threshold2[0]);
		spi_send(&adxl_activity[0]);
		spi_send(&adxl_int[0]);
		spi_send(&adxl_int2[0]);
		spi_send(&adxl_wakeup[0]);
		wait_ms(5);
		
		if(spi_read(&status[0]) >= 0xC0)	//adxl init error? reset in 5seconds
		{
			/////
					rtc_start(5);
			__SEV();	//clear event register
			__WFE();	//wait for event possibly __WFI()????
			__WFE();
			/////
		}
		
}

/**@brief Function for RTC iterrupt.
 */
void RTC1_IRQHandler(void)
{
      // This handler will be run after wakeup from system ON (RTC wakeup)
    if(NRF_RTC1->EVENTS_COMPARE[0])
    {
      NRF_RTC1->EVENTS_COMPARE[0] = 0;
			NVIC_SystemReset();	//soft reset
    }
}


/**@brief Function for GPIOTE iterrupt handler from ADXL.
 */
void GPIOTE_IRQHandler(void)
{
    // This handler will be run after interrput from ADXL (GPIO wakeup)
    if(NRF_GPIOTE->EVENTS_PORT)
    {
        NRF_GPIOTE->EVENTS_PORT = 0;	//clear event
				NVIC_SystemReset();	//soft reset
    }		
		
}
