/**
 * rtt_util.c
 *
 * Helper functions for the Real-Time Timer (RTT) on the ATSAMG55 microcontroller.
 * Used for generic delays / timeouts.
 * 
 * Copyright (c) 2022 Bigscreen, Inc.
 */

#include <asf.h>
#include <stdbool.h>
#include "rtt_util.h"

void rtt_enable(void)
{
	RTT->RTT_MR = 3; // All special features disabled, prescaler = 3 (highest possible accuracy / granularity)
}

/* Returns the current value of the Real-time Timer. 
 * Functions that wish to implement a timeout should read and
 * store this value locally. Then later calls to "rtt_timeout_check"
 * should pass in this value to determine if the allotted time
 * has expired.
 */
volatile uint32_t rtt_read_timer_value(void)
{
	uint32_t rtt_val = RTT->RTT_VR;
	
	// What's up with this while loop?
	// Per the datasheet:
	//		As CRTV can be updated asynchronously, it must be read twice at the same value
	// So we're just making sure that the Current Real-Time Value (CRTV) (and no, I don't know
	// why the ASF library has a different name for this register) isn't changing in the middle
	// of our register read.
	while (rtt_val != RTT->RTT_VR) {
		rtt_val = RTT->RTT_VR;
	}

	return rtt_val;
}

bool rtt_timeout_check(volatile uint32_t start_time, uint32_t timeout_val) {
	// Wraparound detection. If the current time is ever less than the
	// start time, there was a wraparound.
	volatile uint32_t current_time = rtt_read_timer_value();
	
	// Note - wraparound case will be calculated correctly. If 
	// start_time is higher than current_time (because the RTT value
	// wrapped around after 0xFFFF.FFFF), the elapsed_time will
	// still get the correct value thanks to the unsigned int math.
	uint32_t elapsed_time = current_time - start_time;
	
	if(elapsed_time >= timeout_val) {
		return true;
	} else {
		return false;
	}
}
