Compare commits
14 Commits
629d265d12
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d639adc45 | |||
| 46d6bf1001 | |||
| 208c5709d6 | |||
| a489493a66 | |||
|
|
e509c36df9 | ||
|
|
d431678011 | ||
|
|
bf425b8b6c | ||
|
|
ec33c2de17 | ||
|
|
ba20217b63 | ||
|
|
6d56a07fd4 | ||
|
|
771fe86bd9 | ||
|
|
fd5a6e6373 | ||
|
|
8d7eee8842 | ||
|
|
429a530b65 |
54
.travis.yml
54
.travis.yml
@@ -1,54 +0,0 @@
|
|||||||
# Based on the "trust" template v0.1.2
|
|
||||||
# https://github.com/japaric/trust/tree/v0.1.2
|
|
||||||
|
|
||||||
language: rust
|
|
||||||
services: docker
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# Linux
|
|
||||||
- env: TARGET=x86_64-unknown-linux-gnu
|
|
||||||
rust: nightly
|
|
||||||
|
|
||||||
# Bare metal
|
|
||||||
- env: TARGET=thumbv6m-none-eabi
|
|
||||||
rust: nightly
|
|
||||||
- env: TARGET=thumbv7m-none-eabi
|
|
||||||
rust: nightly
|
|
||||||
- env: TARGET=thumbv7em-none-eabi
|
|
||||||
rust: nightly
|
|
||||||
- env: TARGET=thumbv7em-none-eabihf
|
|
||||||
rust: nightly
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- set -e
|
|
||||||
- rustup self update
|
|
||||||
|
|
||||||
install:
|
|
||||||
- sh ci/install.sh
|
|
||||||
- source ~/.cargo/env || true
|
|
||||||
|
|
||||||
script:
|
|
||||||
- bash ci/script.sh
|
|
||||||
|
|
||||||
after_script: set +e
|
|
||||||
|
|
||||||
cache:
|
|
||||||
cargo: true
|
|
||||||
directories:
|
|
||||||
- $HOME/.xargo
|
|
||||||
|
|
||||||
before_cache:
|
|
||||||
# Travis can't cache files that are not readable by "others"
|
|
||||||
- chmod -R a+r $HOME/.cargo
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- /^v\d+\.\d+\.\d+.*$/
|
|
||||||
- auto
|
|
||||||
- master
|
|
||||||
- try
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
on_success: never
|
|
||||||
14
Cargo.toml
14
Cargo.toml
@@ -1,11 +1,19 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "si5351"
|
name = "si5351"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
categories = ["embedded-hal-driver", "ham-radio", "clock", "pll" ]
|
keywords = ["embedded", "no-std", "embedded-hal-driver", "clock", "ham-radio"]
|
||||||
|
categories = ["embedded", "no-std"]
|
||||||
authors = ["Ilya Epifanov <elijah.epifanov@gmail.com>"]
|
authors = ["Ilya Epifanov <elijah.epifanov@gmail.com>"]
|
||||||
description = "A platform agnostic driver for the Si5351 clock generator"
|
description = "A platform agnostic driver for the Si5351 clock generator"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
exclude = [".travis.yml", ".gitignore"]
|
||||||
|
repository = "https://github.com/ilya-epifanov/si5351"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[badges.travis-ci]
|
||||||
|
branch = "master"
|
||||||
|
repository = "jamwaffles/ssd1306"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embedded-hal = "0.1"
|
embedded-hal = "0.2.2"
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
|
|||||||
@@ -186,7 +186,7 @@
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
Copyright 2018 Ilya Epifanov
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
25
LICENSE-MIT
Normal file
25
LICENSE-MIT
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Copyright (c) 2018 Ilya Epifanov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any
|
||||||
|
person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without
|
||||||
|
limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software
|
||||||
|
is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||||
|
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
17
README.md
17
README.md
@@ -1 +1,18 @@
|
|||||||
# si5351
|
# si5351
|
||||||
|
|
||||||
|
Fork of github.com/ilya-epifanov/si5351
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Licensed under either of
|
||||||
|
|
||||||
|
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||||
|
* MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||||
|
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||||
|
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
|
||||||
|
additional terms or conditions.
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
[dependencies.core]
|
|
||||||
stage = 0
|
|
||||||
|
|
||||||
[dependencies.compiler_builtins]
|
|
||||||
git = "https://github.com/rust-lang-nursery/compiler-builtins"
|
|
||||||
features = ["mem"]
|
|
||||||
stage = 1
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
set -ex
|
|
||||||
|
|
||||||
main() {
|
|
||||||
# This fetches latest stable release of Xargo
|
|
||||||
local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/xargo \
|
|
||||||
| cut -d/ -f3 \
|
|
||||||
| grep -E '^v[0.1.0-9.]+$' \
|
|
||||||
| sort --version-sort \
|
|
||||||
| tail -n1)
|
|
||||||
|
|
||||||
curl -LSfs https://japaric.github.io/trust/install.sh | \
|
|
||||||
sh -s -- \
|
|
||||||
--force \
|
|
||||||
--git japaric/xargo \
|
|
||||||
--tag $tag \
|
|
||||||
--target x86_64-unknown-linux-musl
|
|
||||||
|
|
||||||
rustup component add rust-src
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
||||||
16
ci/script.sh
16
ci/script.sh
@@ -1,16 +0,0 @@
|
|||||||
# This script takes care of testing your crate
|
|
||||||
|
|
||||||
set -euxo pipefail
|
|
||||||
|
|
||||||
main() {
|
|
||||||
case $TARGET in
|
|
||||||
x86_64-unknown-linux-gnu)
|
|
||||||
cargo check --target $TARGET
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
xargo check --target $TARGET
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
||||||
180
src/lib.rs
180
src/lib.rs
@@ -1,14 +1,91 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Ilya Epifanov
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||||
|
http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||||
|
http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||||
|
copied, modified, or distributed except according to those terms.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
A platform agnostic Rust driver for the [Si5351], based on the
|
||||||
|
[`embedded-hal`] traits.
|
||||||
|
|
||||||
|
## The Device
|
||||||
|
|
||||||
|
The Silicon Labs [Si5351] is an any-frequency CMOS clock generator.
|
||||||
|
|
||||||
|
The device has an I²C interface.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Import this crate and an `embedded_hal` implementation:
|
||||||
|
|
||||||
|
```
|
||||||
|
extern crate stm32f103xx_hal as hal;
|
||||||
|
extern crate si5351;
|
||||||
|
```
|
||||||
|
|
||||||
|
Initialize I²C bus (differs between `embedded_hal` implementations):
|
||||||
|
|
||||||
|
```no_run
|
||||||
|
# extern crate stm32f103xx_hal as hal;
|
||||||
|
use hal::i2c::I2c;
|
||||||
|
type I2C = ...;
|
||||||
|
|
||||||
|
# fn main() {
|
||||||
|
let i2c: I2C = initialize_i2c();
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
Then instantiate the device:
|
||||||
|
|
||||||
|
```no_run
|
||||||
|
# extern crate stm32f103xx_hal as hal;
|
||||||
|
# extern crate si5351;
|
||||||
|
use si5351;
|
||||||
|
use si5351::{Si5351, Si5351Device};
|
||||||
|
|
||||||
|
# fn main() {
|
||||||
|
let mut clock = Si5351Device<I2C>::new(i2c, false, 25_000_000);
|
||||||
|
clock.init(si5351::CrystalLoad::_10)?;
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you have an [Adafruit module], you can use shortcut functions to initializate it:
|
||||||
|
```no_run
|
||||||
|
# extern crate stm32f103xx_hal as hal;
|
||||||
|
# extern crate si5351;
|
||||||
|
use si5351;
|
||||||
|
use si5351::{Si5351, Si5351Device};
|
||||||
|
|
||||||
|
# fn main() {
|
||||||
|
let mut clock = Si5351Device<I2C>::new_adafruit_module(i2c);
|
||||||
|
clock.init_adafruit_module()?;
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
And set frequency on one of the outputs:
|
||||||
|
|
||||||
|
```no_run
|
||||||
|
use si5351;
|
||||||
|
|
||||||
|
clock.set_frequency(si5351::PLL::A, si5351::ClockOutput::Clk0, 14_175_000)?;
|
||||||
|
```
|
||||||
|
|
||||||
|
[Si5351]: https://www.silabs.com/documents/public/data-sheets/Si5351-B.pdf
|
||||||
|
[`embedded-hal`]: https://github.com/japaric/embedded-hal
|
||||||
|
[Adafruit module]: https://www.adafruit.com/product/2045
|
||||||
|
*/
|
||||||
//#![deny(missing_docs)]
|
//#![deny(missing_docs)]
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![feature(unsize)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
extern crate embedded_hal as hal;
|
use embedded_hal as hal;
|
||||||
|
|
||||||
use core::mem;
|
//use core::mem;
|
||||||
use hal::blocking::i2c::{Write, WriteRead};
|
use crate::hal::blocking::i2c::{Write, WriteRead};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -150,6 +227,14 @@ enum Register {
|
|||||||
Clk5 = 21,
|
Clk5 = 21,
|
||||||
Clk6 = 22,
|
Clk6 = 22,
|
||||||
Clk7 = 23,
|
Clk7 = 23,
|
||||||
|
Clk0Phoff = 165,
|
||||||
|
Clk1Phoff,
|
||||||
|
Clk2Phoff,
|
||||||
|
Clk3Phoff,
|
||||||
|
Clk4Phoff,
|
||||||
|
Clk5Phoff,
|
||||||
|
Clk6Phoff, //Not in datasheet
|
||||||
|
Clk7Phoff, //Not in datasheet
|
||||||
PLLReset = 177,
|
PLLReset = 177,
|
||||||
CrystalLoad = 183,
|
CrystalLoad = 183,
|
||||||
}
|
}
|
||||||
@@ -262,16 +347,17 @@ fn i2c_error<E>(_: E) -> Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Si5351 driver
|
/// Si5351 driver
|
||||||
pub struct Si5351Device<'a, I2C: 'a> {
|
pub struct Si5351Device<I2C> {
|
||||||
i2c: &'a mut I2C,
|
i2c: I2C,
|
||||||
address: u8,
|
address: u8,
|
||||||
xtal_freq: u32,
|
xtal_freq: u32,
|
||||||
clk_enabled_mask: u8,
|
clk_enabled_mask: u8,
|
||||||
ms_int_mode_mask: u8,
|
ms_int_mode_mask: u8,
|
||||||
ms_src_mask: u8,
|
ms_src_mask: u8,
|
||||||
|
last_mdiv: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Si5351<'a> {
|
pub trait Si5351 {
|
||||||
fn init_adafruit_module(&mut self) -> Result<(), Error>;
|
fn init_adafruit_module(&mut self) -> Result<(), Error>;
|
||||||
fn init(&mut self, xtal_load: CrystalLoad) -> Result<(), Error>;
|
fn init(&mut self, xtal_load: CrystalLoad) -> Result<(), Error>;
|
||||||
fn read_device_status(&mut self) -> Result<DeviceStatusBits, Error>;
|
fn read_device_status(&mut self) -> Result<DeviceStatusBits, Error>;
|
||||||
@@ -290,14 +376,22 @@ pub trait Si5351<'a> {
|
|||||||
fn setup_multisynth_int(&mut self, ms: Multisynth, mult: u16, r_div: OutputDivider) -> Result<(), Error>;
|
fn setup_multisynth_int(&mut self, ms: Multisynth, mult: u16, r_div: OutputDivider) -> Result<(), Error>;
|
||||||
fn setup_multisynth(&mut self, ms: Multisynth, div: u16, num: u32, denom: u32, r_div: OutputDivider) -> Result<(), Error>;
|
fn setup_multisynth(&mut self, ms: Multisynth, div: u16, num: u32, denom: u32, r_div: OutputDivider) -> Result<(), Error>;
|
||||||
fn select_clock_pll(&mut self, clocl: ClockOutput, pll: PLL);
|
fn select_clock_pll(&mut self, clocl: ClockOutput, pll: PLL);
|
||||||
|
|
||||||
|
fn set_quad(&mut self, freq: u32) -> Result<f32, Error>;
|
||||||
|
fn set_phase_offset(&mut self, clk: ClockOutput, phase_offset: u8) -> Result<(), Error>;
|
||||||
|
fn reset_pll(&mut self, pll: PLL) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I2C, E> Si5351Device<'a, I2C>
|
impl<T> Si5351Device<T> {
|
||||||
|
pub fn get_xtal_freq(&self) -> u32 {self.xtal_freq}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2C, E> Si5351Device<I2C>
|
||||||
where
|
where
|
||||||
I2C: WriteRead<Error=E> + Write<Error=E>,
|
I2C: WriteRead<Error=E> + Write<Error=E>,
|
||||||
{
|
{
|
||||||
/// Creates a new driver from a I2C peripheral
|
/// Creates a new driver from a I2C peripheral
|
||||||
pub fn new(i2c: &'a mut I2C, address_bit: bool, xtal_freq: u32) -> Self {
|
pub fn new(i2c: I2C, address_bit: bool, xtal_freq: u32) -> Self {
|
||||||
let si5351 = Si5351Device {
|
let si5351 = Si5351Device {
|
||||||
i2c,
|
i2c,
|
||||||
address: ADDRESS | if address_bit { 1 } else { 0 },
|
address: ADDRESS | if address_bit { 1 } else { 0 },
|
||||||
@@ -305,12 +399,14 @@ impl<'a, I2C, E> Si5351Device<'a, I2C>
|
|||||||
clk_enabled_mask: 0,
|
clk_enabled_mask: 0,
|
||||||
ms_int_mode_mask: 0,
|
ms_int_mode_mask: 0,
|
||||||
ms_src_mask: 0,
|
ms_src_mask: 0,
|
||||||
|
last_mdiv: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
si5351
|
si5351
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_adafruit_module(i2c: &'a mut I2C) -> Self {
|
|
||||||
|
pub fn new_adafruit_module(i2c: I2C) -> Self {
|
||||||
Si5351Device::new(i2c, false, 25_000_000)
|
Si5351Device::new(i2c, false, 25_000_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +457,7 @@ impl<'a, I2C, E> Si5351Device<'a, I2C>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_pll(&mut self, pll: PLL) -> Result<(), Error> {
|
pub fn reset_pll(&mut self, pll: PLL) -> Result<(), Error> {
|
||||||
self.write_register(Register::PLLReset, match pll {
|
self.write_register(Register::PLLReset, match pll {
|
||||||
PLL::A => PLLResetBits::PLLA_RST.bits(),
|
PLL::A => PLLResetBits::PLLA_RST.bits(),
|
||||||
PLL::B => PLLResetBits::PLLB_RST.bits(),
|
PLL::B => PLLResetBits::PLLB_RST.bits(),
|
||||||
@@ -371,7 +467,7 @@ impl<'a, I2C, E> Si5351Device<'a, I2C>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_register(&mut self, reg: Register) -> Result<u8, Error> {
|
fn read_register(&mut self, reg: Register) -> Result<u8, Error> {
|
||||||
let mut buffer: [u8; 1] = unsafe { mem::uninitialized() };
|
let mut buffer: [u8; 1] = /*unsafe { mem::uninitialized() }*/ [0];
|
||||||
self.i2c.write_read(self.address, &[reg.addr()], &mut buffer).map_err(i2c_error)?;
|
self.i2c.write_read(self.address, &[reg.addr()], &mut buffer).map_err(i2c_error)?;
|
||||||
Ok(buffer[0])
|
Ok(buffer[0])
|
||||||
}
|
}
|
||||||
@@ -387,9 +483,14 @@ impl<'a, I2C, E> Si5351Device<'a, I2C>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I2C, E> Si5351<'a> for Si5351Device<'a, I2C> where
|
impl<I2C, E> Si5351 for Si5351Device<I2C> where
|
||||||
I2C: WriteRead<Error=E> + Write<Error=E>
|
I2C: WriteRead<Error=E> + Write<Error=E>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
fn reset_pll(&mut self, pll: PLL) -> Result<(), Error> {
|
||||||
|
self.reset_pll(pll)
|
||||||
|
}
|
||||||
|
|
||||||
fn init_adafruit_module(&mut self) -> Result<(), Error> {
|
fn init_adafruit_module(&mut self) -> Result<(), Error> {
|
||||||
self.init(CrystalLoad::_10)
|
self.init(CrystalLoad::_10)
|
||||||
}
|
}
|
||||||
@@ -477,6 +578,59 @@ impl<'a, I2C, E> Si5351<'a> for Si5351Device<'a, I2C> where
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn set_quad(&mut self, freq: u32) -> Result<f32, Error> {
|
||||||
|
let ms0 = Multisynth::MS0;
|
||||||
|
let ms1 = Multisynth::MS1;
|
||||||
|
let mut ms_div = 126;
|
||||||
|
let mut mult = (freq*ms_div) as f32 / self.get_xtal_freq() as f32;
|
||||||
|
while mult > 90.0 {
|
||||||
|
ms_div -= (ms_div as f32 * 0.2) as u32;
|
||||||
|
mult = (freq*ms_div) as f32 / self.get_xtal_freq() as f32;
|
||||||
|
}
|
||||||
|
if mult < 15.0 {return Err(Error::InvalidParameter);}
|
||||||
|
|
||||||
|
//easy calc fraction not the most accurate
|
||||||
|
let denom: u32 = 1048575;
|
||||||
|
let num = ((mult % 1.0) * denom as f32) as u32;
|
||||||
|
let mult = mult as u8;
|
||||||
|
let ms_div = ms_div as u8;
|
||||||
|
|
||||||
|
self.setup_pll(PLL::A, mult, num, denom)?;
|
||||||
|
self.setup_multisynth_int(ms0, ms_div as u16, OutputDivider::Div1)?;
|
||||||
|
self.setup_multisynth_int(ms1, ms_div as u16, OutputDivider::Div1)?;
|
||||||
|
self.select_clock_pll(ClockOutput::Clk0, PLL::A);
|
||||||
|
self.select_clock_pll(ClockOutput::Clk1, PLL::A);
|
||||||
|
self.set_clock_enabled(ClockOutput::Clk0, true);
|
||||||
|
self.set_clock_enabled(ClockOutput::Clk1, true);
|
||||||
|
self.flush_clock_control(ClockOutput::Clk0)?;
|
||||||
|
self.flush_clock_control(ClockOutput::Clk1)?;
|
||||||
|
|
||||||
|
if self.last_mdiv != ms_div {
|
||||||
|
self.set_phase_offset(ClockOutput::Clk1, ms_div as u8)?;
|
||||||
|
self.reset_pll(PLL::A)?;
|
||||||
|
}
|
||||||
|
self.last_mdiv = ms_div;
|
||||||
|
self.flush_output_enabled()?;
|
||||||
|
|
||||||
|
let freq_num = self.xtal_freq as f32 * (mult as f32 + (num as f32 / denom as f32));
|
||||||
|
Ok( freq_num / ms_div as f32 )
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_phase_offset(&mut self, clk: ClockOutput, phase_offset: u8) -> Result<(), Error> {
|
||||||
|
if phase_offset & 1<<7 > 0 {return Err(Error::InvalidParameter);}
|
||||||
|
let reg = match clk {
|
||||||
|
ClockOutput::Clk0 => Register::Clk0Phoff,
|
||||||
|
ClockOutput::Clk1 => Register::Clk1Phoff,
|
||||||
|
ClockOutput::Clk2 => Register::Clk2Phoff,
|
||||||
|
ClockOutput::Clk3 => Register::Clk3Phoff,
|
||||||
|
ClockOutput::Clk4 => Register::Clk4Phoff,
|
||||||
|
ClockOutput::Clk5 => Register::Clk5Phoff,
|
||||||
|
ClockOutput::Clk6 => Register::Clk6Phoff,
|
||||||
|
ClockOutput::Clk7 => Register::Clk7Phoff,
|
||||||
|
};
|
||||||
|
self.write_register(reg, phase_offset)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn set_clock_enabled(&mut self, clk: ClockOutput, enabled: bool) {
|
fn set_clock_enabled(&mut self, clk: ClockOutput, enabled: bool) {
|
||||||
let bit = 1u8 << clk.ix();
|
let bit = 1u8 << clk.ix();
|
||||||
|
|||||||
Reference in New Issue
Block a user