#include "all-headers.h"

static volatile uint32_t gUptime;

static void startSystick (BOOT_MODE) {
	SYST_RVR = CPU_MHZ * 1000 - 1 ; // Underflow every ms
	SYST_CVR = 0 ;
	SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_ENABLE ;
}

MACRO_BOOT_ROUTINE (startSystick);

static void activateSystickInterrupt (INIT_MODE) {
	SYST_CSR |= SYST_CSR_TICKINT;
}

MACRO_INIT_ROUTINE (activateSystickInterrupt);

void busyWaitDuring_initMode (INIT_MODE_ const uint32_t inDelayMS) {
	const uint32_t COUNTFLAG_MASK = 1 << 16 ;
	for (uint32_t i=0 ; i<inDelayMS ; i++) {
		while ((SYST_CSR & COUNTFLAG_MASK) == 0) {} // Busy wait, polling COUNTFLAG
	}
}

void busyWaitDuring (USER_MODE_ const uint32_t inDelayMS) {
	busyWaitUntil(MODE_ gUptime + inDelayMS);
}

void busyWaitUntil (USER_MODE_ const uint32_t inDeadLineMS) {
	while (inDeadLineMS > gUptime) {}
}

void systickInterruptServiceRoutine (SECTION_MODE) {
	const uint32_t newUptime = gUptime + 1 ;
	gUptime = newUptime ;

	// Run every section routines in real.time.interrupt.routine.array
	extern void (* __real_time_interrupt_routine_array_start) (SECTION_MODE_ const uint32_t inUptime) ;
	extern void (* __real_time_interrupt_routine_array_end) (SECTION_MODE_ const uint32_t inUptime) ;
	void (** ptr) (SECTION_MODE_ const uint32_t) = & __real_time_interrupt_routine_array_start ;
	while (ptr != & __real_time_interrupt_routine_array_end) {
		(* ptr) (MODE_ newUptime) ;
		ptr ++ ;
	}
}

uint32_t millis(ANY_MODE) {
	return gUptime;
}

uint32_t systick(ANY_MODE) {
	return SYST_CVR;
}