2015-07-08 11:39:24 -04:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
|
|
|
*
|
|
|
|
* This file is part of PortaPack.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "si5351.hpp"
|
|
|
|
|
|
|
|
#include "utility.hpp"
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
namespace si5351 {
|
|
|
|
|
|
|
|
void Si5351::reset() {
|
2023-05-18 16:16:05 -04:00
|
|
|
wait_for_device_ready();
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
write_register(Register::InterruptStatusSticky, 0x00);
|
|
|
|
write_register(Register::InterruptStatusMask, 0xf0);
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
disable_output_mask(0xff);
|
|
|
|
write_register(Register::OEBPinEnableControlMask, 0xff);
|
|
|
|
write_register(Register::PLLInputSource, 0x00);
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
set_clock_control({ClockControl::power_off(), ClockControl::power_off(),
|
|
|
|
ClockControl::power_off(), ClockControl::power_off(),
|
|
|
|
ClockControl::power_off(), ClockControl::power_off(),
|
|
|
|
ClockControl::power_off(), ClockControl::power_off()});
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
write(std::array<uint8_t, 70>{Register::CLK3_0DisableState});
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
write(std::array<uint8_t, 14>{
|
|
|
|
Register::SpreadSpectrumParameters_Base});
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
write(std::array<uint8_t, 4>{
|
|
|
|
Register::VCXOParameters_Base});
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
write(std::array<uint8_t, 7>{
|
|
|
|
Register::CLKInitialPhaseOffset_Base});
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
write_register(Register::CrystalInternalLoadCapacitance, 0b11010010);
|
|
|
|
write_register(Register::FanoutEnable, 0x00);
|
2015-07-08 11:39:24 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
reset_plls();
|
2015-07-08 11:39:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Si5351::regvalue_t Si5351::read_register(const uint8_t reg) {
|
2023-05-18 16:16:05 -04:00
|
|
|
const std::array<uint8_t, 1> tx{reg};
|
|
|
|
std::array<uint8_t, 1> rx{0x00};
|
|
|
|
_bus.transmit(_address, tx.data(), tx.size());
|
|
|
|
_bus.receive(_address, rx.data(), rx.size());
|
|
|
|
return rx[0];
|
2015-07-08 11:39:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Si5351::set_ms_frequency(
|
2023-05-18 16:16:05 -04:00
|
|
|
const size_t ms_number,
|
|
|
|
const uint32_t frequency,
|
|
|
|
const uint32_t vco_frequency,
|
|
|
|
const size_t r_div) {
|
|
|
|
/* TODO: Factor out the VCO frequency, which should be an attribute held
|
|
|
|
* by the Si5351 object.
|
|
|
|
*/
|
|
|
|
const uint32_t a = vco_frequency / frequency;
|
|
|
|
const uint32_t remainder = vco_frequency - (frequency * a);
|
|
|
|
const uint32_t denom = gcd(remainder, frequency);
|
|
|
|
const uint32_t b = remainder / denom;
|
|
|
|
const uint32_t c = frequency / denom;
|
|
|
|
|
|
|
|
/* TODO: Switch between integer and fractional modes depending on the
|
|
|
|
* values of a and b.
|
|
|
|
*/
|
|
|
|
const MultisynthFractional ms{
|
|
|
|
.f_src = vco_frequency,
|
|
|
|
.a = a,
|
|
|
|
.b = b,
|
|
|
|
.c = c,
|
|
|
|
.r_div = r_div,
|
|
|
|
};
|
|
|
|
const auto regs = ms.reg(ms_number);
|
|
|
|
write(regs);
|
2015-07-08 11:39:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace si5351 */
|