From 30f2bc41498723b7439be037ebb19266e99d156a Mon Sep 17 00:00:00 2001
From: Jared Boone <jboone@earfeast.com>
Date: Sun, 5 Aug 2018 12:19:41 -0700
Subject: [PATCH] Clock Manager: Add API to measure LPC43xx clock inputs
 against IRC oscillator.

---
 firmware/application/clock_manager.cpp | 24 ++++++++++++++++++++++++
 firmware/application/clock_manager.hpp |  4 ++++
 2 files changed, 28 insertions(+)

diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp
index c8b75cce..0cbf462f 100644
--- a/firmware/application/clock_manager.cpp
+++ b/firmware/application/clock_manager.cpp
@@ -422,6 +422,30 @@ void ClockManager::disable_gp_clkin_source() {
 	clock_generator.disable_output(clock_generator_output_mcu_clkin);
 }
 
+void ClockManager::start_frequency_monitor_measurement(const cgu::CLK_SEL clk_sel) {
+	// Measure a clock input for 480 cycles of the LPC43xx IRC.
+	LPC_CGU->FREQ_MON = LPC_CGU_FREQ_MON_Type {
+		.RCNT = 480,
+		.FCNT = 0,
+		.MEAS = 0,
+		.CLK_SEL = toUType(clk_sel),
+		.RESERVED0 = 0
+	};
+	LPC_CGU->FREQ_MON.MEAS = 1;
+}
+
+void ClockManager::wait_For_frequency_monitor_measurement_done() {
+	// FREQ_MON mechanism fails to finish if there's no clock present on selected input?!
+	while(LPC_CGU->FREQ_MON.MEAS == 1);
+}
+
+uint32_t ClockManager::get_frequency_monitor_measurement_in_hertz() {
+	// Measurement is only as accurate as the LPC43xx IRC oscillator,
+	// which is +/- 1.5%. Measurement is for 480 IRC clcocks. Scale
+	// the cycle count to get a value in Hertz.
+	return LPC_CGU->FREQ_MON.FCNT * 25000;
+}
+
 void ClockManager::enable_xtal_oscillator() {
 	LPC_CGU->XTAL_OSC_CTRL.BYPASS = 0;
 	LPC_CGU->XTAL_OSC_CTRL.ENABLE = 1;
diff --git a/firmware/application/clock_manager.hpp b/firmware/application/clock_manager.hpp
index f1398529..de36d374 100644
--- a/firmware/application/clock_manager.hpp
+++ b/firmware/application/clock_manager.hpp
@@ -66,6 +66,8 @@ public:
 
 	void set_reference_ppb(const int32_t ppb);
 
+	uint32_t get_frequency_monitor_measurement_in_hertz();
+
 private:
 	I2C& i2c0;
 	si5351::Si5351& clock_generator;
@@ -75,6 +77,8 @@ private:
 
 	void enable_gp_clkin_source();
 	void disable_gp_clkin_source();
+	void start_frequency_monitor_measurement(const cgu::CLK_SEL clk_sel);
+	void wait_For_frequency_monitor_measurement_done();
 
 	void enable_xtal_oscillator();
 	void disable_xtal_oscillator();
-- 
GitLab