mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-25 15:29:37 -05:00
Merge branch 'external_clock'
This commit is contained in:
commit
01bad2805c
@ -269,11 +269,23 @@ void ClockManager::init() {
|
|||||||
clock_generator.enable_fanout();
|
clock_generator.enable_fanout();
|
||||||
clock_generator.set_pll_input_sources(si5351_pll_input_sources);
|
clock_generator.set_pll_input_sources(si5351_pll_input_sources);
|
||||||
|
|
||||||
const bool use_clkin = false;
|
const auto clkin_present = !clock_generator.clkin_loss_of_signal();
|
||||||
|
auto clkin_valid = false;
|
||||||
|
|
||||||
|
if( clkin_present ) {
|
||||||
|
// Measure Si5351B CLKIN frequency against LPC43xx IRC oscillator
|
||||||
|
set_gp_clkin_to_clkin_direct();
|
||||||
|
start_frequency_monitor_measurement(cgu::CLK_SEL::GP_CLKIN);
|
||||||
|
wait_For_frequency_monitor_measurement_done();
|
||||||
|
const auto clkin_frequency = get_frequency_monitor_measurement_in_hertz();
|
||||||
|
|
||||||
|
// CLKIN is required to be 10MHz. FREQ_MON measurement is accurate to 1.5%
|
||||||
|
// due to LPC43xx IRC oscillator precision.
|
||||||
|
clkin_valid = (clkin_frequency >= 9850000) && (clkin_frequency <= 10150000);
|
||||||
|
}
|
||||||
|
|
||||||
clock_generator.set_clock_control(
|
clock_generator.set_clock_control(
|
||||||
use_clkin ?
|
clkin_valid ? si5351_clock_control_clkin : si5351_clock_control_xtal
|
||||||
si5351_clock_control_clkin
|
|
||||||
: si5351_clock_control_xtal
|
|
||||||
);
|
);
|
||||||
|
|
||||||
clock_generator.write(si5351_pll_a_xtal_reg);
|
clock_generator.write(si5351_pll_a_xtal_reg);
|
||||||
@ -422,6 +434,38 @@ void ClockManager::disable_gp_clkin_source() {
|
|||||||
clock_generator.disable_output(clock_generator_output_mcu_clkin);
|
clock_generator.disable_output(clock_generator_output_mcu_clkin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClockManager::set_gp_clkin_to_clkin_direct() {
|
||||||
|
clock_generator.set_clock_control(
|
||||||
|
clock_generator_output_mcu_clkin,
|
||||||
|
{ ClockControl::CLK_IDRV_2mA | ClockControl::CLK_SRC_CLKIN | ClockControl::CLK_INV_Normal | ClockControl::MS_INT_Integer | ClockControl::CLK_PDN_Power_On }
|
||||||
|
);
|
||||||
|
enable_gp_clkin_source();
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
void ClockManager::enable_xtal_oscillator() {
|
||||||
LPC_CGU->XTAL_OSC_CTRL.BYPASS = 0;
|
LPC_CGU->XTAL_OSC_CTRL.BYPASS = 0;
|
||||||
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 1;
|
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 1;
|
||||||
|
@ -66,6 +66,8 @@ public:
|
|||||||
|
|
||||||
void set_reference_ppb(const int32_t ppb);
|
void set_reference_ppb(const int32_t ppb);
|
||||||
|
|
||||||
|
uint32_t get_frequency_monitor_measurement_in_hertz();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
I2C& i2c0;
|
I2C& i2c0;
|
||||||
si5351::Si5351& clock_generator;
|
si5351::Si5351& clock_generator;
|
||||||
@ -75,6 +77,10 @@ private:
|
|||||||
|
|
||||||
void enable_gp_clkin_source();
|
void enable_gp_clkin_source();
|
||||||
void disable_gp_clkin_source();
|
void disable_gp_clkin_source();
|
||||||
|
void set_gp_clkin_to_clkin_direct();
|
||||||
|
|
||||||
|
void start_frequency_monitor_measurement(const cgu::CLK_SEL clk_sel);
|
||||||
|
void wait_For_frequency_monitor_measurement_done();
|
||||||
|
|
||||||
void enable_xtal_oscillator();
|
void enable_xtal_oscillator();
|
||||||
void disable_xtal_oscillator();
|
void disable_xtal_oscillator();
|
||||||
|
@ -310,6 +310,10 @@ public:
|
|||||||
while(device_status() & 0x80);
|
while(device_status() & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool clkin_loss_of_signal() {
|
||||||
|
return (device_status() >> 4) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
void enable_fanout() {
|
void enable_fanout() {
|
||||||
write_register(Register::FanoutEnable, 0b11010000);
|
write_register(Register::FanoutEnable, 0b11010000);
|
||||||
}
|
}
|
||||||
@ -373,6 +377,11 @@ public:
|
|||||||
update_all_clock_control();
|
update_all_clock_control();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_clock_control(const size_t n, const ClockControl::Type clock_control) {
|
||||||
|
_clock_control[n] = clock_control;
|
||||||
|
write_register(Register::CLKControl_Base + n, _clock_control[n]);
|
||||||
|
}
|
||||||
|
|
||||||
void enable_clock(const size_t n) {
|
void enable_clock(const size_t n) {
|
||||||
_clock_control[n] &= ~ClockControl::CLK_PDN_Mask;
|
_clock_control[n] &= ~ClockControl::CLK_PDN_Mask;
|
||||||
write_register(Register::CLKControl_Base + n, _clock_control[n]);
|
write_register(Register::CLKControl_Base + n, _clock_control[n]);
|
||||||
|
Loading…
Reference in New Issue
Block a user