Merge #106
106: More gha r=jordens a=jordens Co-authored-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
commit
1d6c77252c
|
@ -1,3 +1,3 @@
|
||||||
block_labels = [ "S-blocked" ]
|
block_labels = [ "S-blocked" ]
|
||||||
delete_merged_branches = true
|
delete_merged_branches = true
|
||||||
status = [ "continuous-integration/travis-ci/push" ]
|
status = ["ci"]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
name: Continuous Integration
|
name: Continuous Integration
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
@ -6,20 +7,99 @@ on:
|
||||||
- trying
|
- trying
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
style:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Install toolchain
|
- uses: actions-rs/toolchain@v1
|
||||||
run: rustup toolchain install nightly
|
with:
|
||||||
- name: Use toolchain
|
profile: minimal
|
||||||
run: rustup override add nightly
|
toolchain: stable
|
||||||
- name: Install target
|
override: true
|
||||||
run: rustup target add thumbv7em-none-eabihf
|
components: rustfmt
|
||||||
- name: Build release
|
- name: cargo fmt --check
|
||||||
run: cargo build --verbose --release
|
uses: actions-rs/cargo@v1
|
||||||
- name: Build semihosting
|
with:
|
||||||
run: cargo build --verbose --features semihosting
|
command: fmt
|
||||||
- name: Build bkpt
|
args: --all -- --check
|
||||||
run: cargo build --verbose --features bkpt,semihosting
|
|
||||||
|
clippy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
target: thumbv7em-none-eabihf
|
||||||
|
override: true
|
||||||
|
components: clippy
|
||||||
|
- name: cargo clippy
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
|
||||||
|
compile:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
toolchain:
|
||||||
|
- stable
|
||||||
|
- beta
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install Rust ${{ matrix.toolchain }}
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ matrix.toolchain }}
|
||||||
|
target: thumbv7em-none-eabihf
|
||||||
|
override: true
|
||||||
|
- name: cargo check
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: check
|
||||||
|
args: --verbose
|
||||||
|
- name: cargo build
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
- name: cargo build release
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --release
|
||||||
|
- name: cargo build release+semihosting
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --release --features semihosting
|
||||||
|
|
||||||
|
# Tell bors about it
|
||||||
|
# https://github.com/rtic-rs/cortex-m-rtic/blob/8a4f9c6b8ae91bebeea0791680f89375a78bffc6/.github/workflows/build.yml#L566-L603
|
||||||
|
ci-success:
|
||||||
|
name: ci
|
||||||
|
if: github.event_name == 'push' && success()
|
||||||
|
needs:
|
||||||
|
- style
|
||||||
|
- clippy
|
||||||
|
- compile
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Mark the job as a success
|
||||||
|
run: exit 0
|
||||||
|
ci-failure:
|
||||||
|
name: ci
|
||||||
|
if: github.event_name == 'push' && !success()
|
||||||
|
needs:
|
||||||
|
- style
|
||||||
|
- clippy
|
||||||
|
- compile
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Mark the job as a failure
|
||||||
|
run: exit 1
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[submodule "stm32h7xx-hal"]
|
|
||||||
path = stm32h7xx-hal
|
|
||||||
url = https://github.com/quartiq/stm32h7xx-hal.git
|
|
32
.travis.yml
32
.travis.yml
|
@ -1,32 +0,0 @@
|
||||||
language: rust
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- rust: stable
|
|
||||||
env: FEATURES='' ARGS='--release'
|
|
||||||
- rust: stable
|
|
||||||
env: FEATURES='semihosting'
|
|
||||||
- rust: beta
|
|
||||||
env: FEATURES='' ARGS='--release'
|
|
||||||
allow_failures:
|
|
||||||
- rust: nightly
|
|
||||||
env: FEATURES='' ARGS='--release'
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- staging
|
|
||||||
- trying
|
|
||||||
- master
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- rustup target add thumbv7em-none-eabihf
|
|
||||||
- rustup component add clippy
|
|
||||||
- rustup component add rustfmt
|
|
||||||
|
|
||||||
script:
|
|
||||||
- "cargo build --target thumbv7em-none-eabihf --features \"$FEATURES\" $ARGS"
|
|
||||||
- cargo clippy
|
|
||||||
- cargo fmt --all -- --check
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
|
@ -284,15 +284,6 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "panic-itm"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "98830d17a95587207e41edaa3009b143d326ce134b0e3538ac98246a67d66cc3"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "panic-semihosting"
|
name = "panic-semihosting"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -460,7 +451,7 @@ dependencies = [
|
||||||
"serde-json-core",
|
"serde-json-core",
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
"stm32h7-ethernet",
|
"stm32h7-ethernet",
|
||||||
"stm32h7xx-hal 0.5.0",
|
"stm32h7xx-hal 0.5.0 (git+https://github.com/quartiq/stm32h7xx-hal.git?branch=feature/pounder-support)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -495,16 +486,14 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stm32h7xx-hal"
|
name = "stm32h7xx-hal"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
source = "git+https://github.com/quartiq/stm32h7xx-hal.git?branch=feature/pounder-support#ff00e938f2b226211c178f26c092f36462c44404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bare-metal",
|
"bare-metal",
|
||||||
"cast",
|
"cast",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"cortex-m-log",
|
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"cortex-m-rtfm",
|
|
||||||
"embedded-hal",
|
"embedded-hal",
|
||||||
"nb",
|
"nb",
|
||||||
"panic-itm",
|
|
||||||
"paste",
|
"paste",
|
||||||
"stm32h7",
|
"stm32h7",
|
||||||
"void",
|
"void",
|
||||||
|
|
73
Cargo.toml
73
Cargo.toml
|
@ -1,11 +1,72 @@
|
||||||
[workspace]
|
[package]
|
||||||
|
name = "stabilizer"
|
||||||
members = [
|
version = "0.3.0"
|
||||||
"stabilizer",
|
authors = ["Robert Jördens <rj@quartiq.de>"]
|
||||||
"stm32h7xx-hal",
|
description = "Firmware for the Sinara Stabilizer board (stm32h743, eth, poe, 2 adc, 2 dac)"
|
||||||
"ad9959",
|
categories = ["embedded", "no-std", "hardware-support", "science"]
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
keywords = ["ethernet", "stm32h7", "adc", "dac", "physics"]
|
||||||
|
repository = "https://github.com/quartiq/stabilizer"
|
||||||
|
readme = "README.md"
|
||||||
|
documentation = "https://docs.rs/stabilizer/"
|
||||||
|
edition = "2018"
|
||||||
|
exclude = [
|
||||||
|
".travis.yml",
|
||||||
|
".gitignore",
|
||||||
|
"doc/",
|
||||||
|
"doc/*"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
travis-ci = { repository = "quartiq/stabilizer", branch = "master" }
|
||||||
|
maintenance = { status = "experimental" }
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
features = []
|
||||||
|
default-target = "thumbv7em-none-eabihf"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cortex-m = { version = "0.6", features = ["const-fn"] }
|
||||||
|
cortex-m-rt = { version = "0.6", features = ["device"] }
|
||||||
|
cortex-m-log = { version = "0.6", features = ["log-integration"] }
|
||||||
|
log = "0.4"
|
||||||
|
panic-semihosting = { version = "0.5", optional = true }
|
||||||
|
panic-halt = "0.2"
|
||||||
|
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||||
|
heapless = { version = "0.5", features = ["serde"] }
|
||||||
|
serde-json-core = "0.1"
|
||||||
|
cortex-m-rtfm = "0.5"
|
||||||
|
embedded-hal = "0.2.3"
|
||||||
|
nb = "0.1.2"
|
||||||
|
asm-delay = "0.7.0"
|
||||||
|
enum-iterator = "0.6.0"
|
||||||
|
|
||||||
|
[dependencies.mcp23017]
|
||||||
|
git = "https://github.com/mrd0ll4r/mcp23017.git"
|
||||||
|
|
||||||
|
[dependencies.smoltcp]
|
||||||
|
version = "0.6"
|
||||||
|
features = ["ethernet", "proto-ipv4", "socket-tcp", "proto-ipv6"]
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.ad9959]
|
||||||
|
path = "ad9959"
|
||||||
|
|
||||||
|
[dependencies.stm32h7-ethernet]
|
||||||
|
git = "https://github.com/quartiq/stm32h7-ethernet.git"
|
||||||
|
branch = "master"
|
||||||
|
features = ["stm32h743v"]
|
||||||
|
|
||||||
|
[dependencies.stm32h7xx-hal]
|
||||||
|
git = "https://github.com/quartiq/stm32h7xx-hal.git"
|
||||||
|
branch = "feature/pounder-support"
|
||||||
|
features = ["stm32h743v", "rt", "unproven"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
||||||
|
bkpt = [ ]
|
||||||
|
nightly = ["cortex-m/inline-asm"]
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
incremental = false
|
incremental = false
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
![Continuous Integration](https://github.com/quartiq/stabilizer/workflows/Continuous%20Integration/badge.svg)
|
||||||
|
|
||||||
# Stabilizer Firmware
|
# Stabilizer Firmware
|
||||||
|
|
||||||
![Flow diagram](stabilizer_pid.svg)
|
![Flow diagram](stabilizer_pid.svg)
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use bit_field::BitField;
|
use bit_field::BitField;
|
||||||
use embedded_hal::{
|
use embedded_hal::{blocking::delay::DelayMs, digital::v2::OutputPin};
|
||||||
digital::v2::OutputPin,
|
|
||||||
blocking::delay::DelayMs,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A device driver for the AD9959 direct digital synthesis (DDS) chip.
|
/// A device driver for the AD9959 direct digital synthesis (DDS) chip.
|
||||||
///
|
///
|
||||||
|
@ -93,12 +90,11 @@ pub enum Error {
|
||||||
Frequency,
|
Frequency,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <PinE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
|
impl<PinE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
|
||||||
where
|
where
|
||||||
INTERFACE: Interface,
|
INTERFACE: Interface,
|
||||||
DELAY: DelayMs<u8>,
|
DELAY: DelayMs<u8>,
|
||||||
UPDATE: OutputPin<Error = PinE>,
|
UPDATE: OutputPin<Error = PinE>,
|
||||||
|
|
||||||
{
|
{
|
||||||
/// Construct and initialize the DDS.
|
/// Construct and initialize the DDS.
|
||||||
///
|
///
|
||||||
|
@ -111,13 +107,15 @@ where
|
||||||
/// * `clock_frequency` - The clock frequency of the reference clock input.
|
/// * `clock_frequency` - The clock frequency of the reference clock input.
|
||||||
/// * `multiplier` - The desired clock multiplier for the system clock. This multiplies
|
/// * `multiplier` - The desired clock multiplier for the system clock. This multiplies
|
||||||
/// `clock_frequency` to generate the system clock.
|
/// `clock_frequency` to generate the system clock.
|
||||||
pub fn new<RST>(interface: INTERFACE,
|
pub fn new<RST>(
|
||||||
|
interface: INTERFACE,
|
||||||
reset_pin: &mut RST,
|
reset_pin: &mut RST,
|
||||||
io_update: UPDATE,
|
io_update: UPDATE,
|
||||||
delay: DELAY,
|
delay: DELAY,
|
||||||
desired_mode: Mode,
|
desired_mode: Mode,
|
||||||
clock_frequency: f32,
|
clock_frequency: f32,
|
||||||
multiplier: u8) -> Result<Self, Error>
|
multiplier: u8,
|
||||||
|
) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
RST: OutputPin,
|
RST: OutputPin,
|
||||||
{
|
{
|
||||||
|
@ -135,25 +133,39 @@ where
|
||||||
reset_pin.set_high().or_else(|_| Err(Error::Pin))?;
|
reset_pin.set_high().or_else(|_| Err(Error::Pin))?;
|
||||||
|
|
||||||
// Delay for a clock cycle to allow the device to reset.
|
// Delay for a clock cycle to allow the device to reset.
|
||||||
ad9959.delay.delay_ms((1000.0 / clock_frequency as f32) as u8);
|
ad9959
|
||||||
|
.delay
|
||||||
|
.delay_ms((1000.0 / clock_frequency as f32) as u8);
|
||||||
|
|
||||||
reset_pin.set_low().or_else(|_| Err(Error::Pin))?;
|
reset_pin.set_low().or_else(|_| Err(Error::Pin))?;
|
||||||
|
|
||||||
ad9959.interface.configure_mode(Mode::SingleBitTwoWire).map_err(|_| Error::Interface)?;
|
ad9959
|
||||||
|
.interface
|
||||||
|
.configure_mode(Mode::SingleBitTwoWire)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Program the interface configuration in the AD9959. Default to all channels enabled.
|
// Program the interface configuration in the AD9959. Default to all channels enabled.
|
||||||
let mut csr: [u8; 1] = [0xF0];
|
let mut csr: [u8; 1] = [0xF0];
|
||||||
csr[0].set_bits(1..3, desired_mode as u8);
|
csr[0].set_bits(1..3, desired_mode as u8);
|
||||||
ad9959.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
ad9959
|
||||||
|
.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Latch the configuration registers to make them active.
|
// Latch the configuration registers to make them active.
|
||||||
ad9959.latch_configuration()?;
|
ad9959.latch_configuration()?;
|
||||||
|
|
||||||
ad9959.interface.configure_mode(desired_mode).map_err(|_| Error::Interface)?;
|
ad9959
|
||||||
|
.interface
|
||||||
|
.configure_mode(desired_mode)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Read back the CSR to ensure it specifies the mode correctly.
|
// Read back the CSR to ensure it specifies the mode correctly.
|
||||||
let mut updated_csr: [u8; 1] = [0];
|
let mut updated_csr: [u8; 1] = [0];
|
||||||
ad9959.interface.read(Register::CSR as u8, &mut updated_csr).map_err(|_| Error::Interface)?;
|
ad9959
|
||||||
|
.interface
|
||||||
|
.read(Register::CSR as u8, &mut updated_csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
if updated_csr[0] != csr[0] {
|
if updated_csr[0] != csr[0] {
|
||||||
return Err(Error::Check);
|
return Err(Error::Check);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +180,8 @@ where
|
||||||
self.io_update.set_high().or_else(|_| Err(Error::Pin))?;
|
self.io_update.set_high().or_else(|_| Err(Error::Pin))?;
|
||||||
// The SYNC_CLK is 1/4 the system clock frequency. The IO_UPDATE pin must be latched for one
|
// The SYNC_CLK is 1/4 the system clock frequency. The IO_UPDATE pin must be latched for one
|
||||||
// full SYNC_CLK pulse to register. For safety, we latch for 5 here.
|
// full SYNC_CLK pulse to register. For safety, we latch for 5 here.
|
||||||
self.delay.delay_ms((5000.0 / self.system_clock_frequency()) as u8);
|
self.delay
|
||||||
|
.delay_ms((5000.0 / self.system_clock_frequency()) as u8);
|
||||||
self.io_update.set_low().or_else(|_| Err(Error::Pin))?;
|
self.io_update.set_low().or_else(|_| Err(Error::Pin))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -182,30 +195,36 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The actual frequency configured for the internal system clock.
|
/// The actual frequency configured for the internal system clock.
|
||||||
pub fn configure_system_clock(&mut self,
|
pub fn configure_system_clock(
|
||||||
|
&mut self,
|
||||||
reference_clock_frequency: f32,
|
reference_clock_frequency: f32,
|
||||||
multiplier: u8) -> Result<f64, Error>
|
multiplier: u8,
|
||||||
{
|
) -> Result<f64, Error> {
|
||||||
self.reference_clock_frequency = reference_clock_frequency;
|
self.reference_clock_frequency = reference_clock_frequency;
|
||||||
|
|
||||||
if multiplier != 1 && (multiplier > 20 || multiplier < 4) {
|
if multiplier != 1 && (multiplier > 20 || multiplier < 4) {
|
||||||
return Err(Error::Bounds);
|
return Err(Error::Bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
let frequency = multiplier as f64 * self.reference_clock_frequency as f64;
|
let frequency =
|
||||||
|
multiplier as f64 * self.reference_clock_frequency as f64;
|
||||||
if frequency > 500_000_000.0f64 {
|
if frequency > 500_000_000.0f64 {
|
||||||
return Err(Error::Frequency);
|
return Err(Error::Frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Update / disable any enabled channels?
|
// TODO: Update / disable any enabled channels?
|
||||||
let mut fr1: [u8; 3] = [0, 0, 0];
|
let mut fr1: [u8; 3] = [0, 0, 0];
|
||||||
self.interface.read(Register::FR1 as u8, &mut fr1).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::FR1 as u8, &mut fr1)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
fr1[0].set_bits(2..=6, multiplier);
|
fr1[0].set_bits(2..=6, multiplier);
|
||||||
|
|
||||||
let vco_range = frequency > 255e6;
|
let vco_range = frequency > 255e6;
|
||||||
fr1[0].set_bit(7, vco_range);
|
fr1[0].set_bit(7, vco_range);
|
||||||
|
|
||||||
self.interface.write(Register::FR1 as u8, &fr1).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::FR1 as u8, &fr1)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
self.system_clock_multiplier = multiplier;
|
self.system_clock_multiplier = multiplier;
|
||||||
|
|
||||||
Ok(self.system_clock_frequency())
|
Ok(self.system_clock_frequency())
|
||||||
|
@ -219,7 +238,9 @@ where
|
||||||
/// Get the current reference clock multiplier.
|
/// Get the current reference clock multiplier.
|
||||||
pub fn get_reference_clock_multiplier(&mut self) -> Result<u8, Error> {
|
pub fn get_reference_clock_multiplier(&mut self) -> Result<u8, Error> {
|
||||||
let mut fr1: [u8; 3] = [0, 0, 0];
|
let mut fr1: [u8; 3] = [0, 0, 0];
|
||||||
self.interface.read(Register::FR1 as u8, &mut fr1).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::FR1 as u8, &mut fr1)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(fr1[0].get_bits(2..=6) as u8)
|
Ok(fr1[0].get_bits(2..=6) as u8)
|
||||||
}
|
}
|
||||||
|
@ -233,49 +254,66 @@ where
|
||||||
/// True if the self test succeeded. False otherwise.
|
/// True if the self test succeeded. False otherwise.
|
||||||
pub fn self_test(&mut self) -> Result<bool, Error> {
|
pub fn self_test(&mut self) -> Result<bool, Error> {
|
||||||
let mut csr: [u8; 1] = [0];
|
let mut csr: [u8; 1] = [0];
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
let old_csr = csr[0];
|
let old_csr = csr[0];
|
||||||
|
|
||||||
// Enable all channels.
|
// Enable all channels.
|
||||||
csr[0].set_bits(4..8, 0xF);
|
csr[0].set_bits(4..8, 0xF);
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Read back the enable.
|
// Read back the enable.
|
||||||
csr[0] = 0;
|
csr[0] = 0;
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
if csr[0].get_bits(4..8) != 0xF {
|
if csr[0].get_bits(4..8) != 0xF {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all channel enables.
|
// Clear all channel enables.
|
||||||
csr[0].set_bits(4..8, 0x0);
|
csr[0].set_bits(4..8, 0x0);
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Read back the enable.
|
// Read back the enable.
|
||||||
csr[0] = 0xFF;
|
csr[0] = 0xFF;
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
if csr[0].get_bits(4..8) != 0 {
|
if csr[0].get_bits(4..8) != 0 {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the CSR.
|
// Restore the CSR.
|
||||||
csr[0] = old_csr;
|
csr[0] = old_csr;
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current system clock frequency in Hz.
|
/// Get the current system clock frequency in Hz.
|
||||||
fn system_clock_frequency(&self) -> f64 {
|
fn system_clock_frequency(&self) -> f64 {
|
||||||
self.system_clock_multiplier as f64 * self.reference_clock_frequency as f64
|
self.system_clock_multiplier as f64
|
||||||
|
* self.reference_clock_frequency as f64
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable an output channel.
|
/// Enable an output channel.
|
||||||
pub fn enable_channel(&mut self, channel: Channel) -> Result<(), Error> {
|
pub fn enable_channel(&mut self, channel: Channel) -> Result<(), Error> {
|
||||||
let mut csr: [u8; 1] = [0];
|
let mut csr: [u8; 1] = [0];
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
csr[0].set_bit(channel as usize + 4, true);
|
csr[0].set_bit(channel as usize + 4, true);
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -283,9 +321,13 @@ where
|
||||||
/// Disable an output channel.
|
/// Disable an output channel.
|
||||||
pub fn disable_channel(&mut self, channel: Channel) -> Result<(), Error> {
|
pub fn disable_channel(&mut self, channel: Channel) -> Result<(), Error> {
|
||||||
let mut csr: [u8; 1] = [0];
|
let mut csr: [u8; 1] = [0];
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
csr[0].set_bit(channel as usize + 4, false);
|
csr[0].set_bit(channel as usize + 4, false);
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -293,7 +335,9 @@ where
|
||||||
/// Determine if an output channel is enabled.
|
/// Determine if an output channel is enabled.
|
||||||
pub fn is_enabled(&mut self, channel: Channel) -> Result<bool, Error> {
|
pub fn is_enabled(&mut self, channel: Channel) -> Result<bool, Error> {
|
||||||
let mut csr: [u8; 1] = [0; 1];
|
let mut csr: [u8; 1] = [0; 1];
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(csr[0].get_bit(channel as usize + 4))
|
Ok(csr[0].get_bit(channel as usize + 4))
|
||||||
}
|
}
|
||||||
|
@ -304,24 +348,37 @@ where
|
||||||
/// * `channel` - The channel to configure.
|
/// * `channel` - The channel to configure.
|
||||||
/// * `register` - The register to update.
|
/// * `register` - The register to update.
|
||||||
/// * `data` - The contents to write to the provided register.
|
/// * `data` - The contents to write to the provided register.
|
||||||
fn modify_channel(&mut self, channel: Channel, register: Register, data: &[u8]) -> Result<(), Error> {
|
fn modify_channel(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
register: Register,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Result<(), Error> {
|
||||||
// Disable all other outputs so that we can update the configuration register of only the
|
// Disable all other outputs so that we can update the configuration register of only the
|
||||||
// specified channel.
|
// specified channel.
|
||||||
let mut csr: [u8; 1] = [0];
|
let mut csr: [u8; 1] = [0];
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
let mut new_csr = csr;
|
let mut new_csr = csr;
|
||||||
new_csr[0].set_bits(4..8, 0);
|
new_csr[0].set_bits(4..8, 0);
|
||||||
new_csr[0].set_bit(4 + channel as usize, true);
|
new_csr[0].set_bit(4 + channel as usize, true);
|
||||||
|
|
||||||
self.interface.write(Register::CSR as u8, &new_csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &new_csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
self.interface.write(register as u8, &data).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(register as u8, &data)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Latch the configuration and restore the previous CSR. Note that the re-enable of the
|
// Latch the configuration and restore the previous CSR. Note that the re-enable of the
|
||||||
// channel happens immediately, so the CSR update does not need to be latched.
|
// channel happens immediately, so the CSR update does not need to be latched.
|
||||||
self.latch_configuration()?;
|
self.latch_configuration()?;
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -332,23 +389,36 @@ where
|
||||||
/// * `channel` - The channel to read.
|
/// * `channel` - The channel to read.
|
||||||
/// * `register` - The register to read.
|
/// * `register` - The register to read.
|
||||||
/// * `data` - A location to store the read register contents.
|
/// * `data` - A location to store the read register contents.
|
||||||
fn read_channel(&mut self, channel: Channel, register: Register, mut data: &mut [u8]) -> Result<(), Error> {
|
fn read_channel(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
register: Register,
|
||||||
|
mut data: &mut [u8],
|
||||||
|
) -> Result<(), Error> {
|
||||||
// Disable all other channels in the CSR so that we can read the configuration register of
|
// Disable all other channels in the CSR so that we can read the configuration register of
|
||||||
// only the desired channel.
|
// only the desired channel.
|
||||||
let mut csr: [u8; 1] = [0];
|
let mut csr: [u8; 1] = [0];
|
||||||
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(Register::CSR as u8, &mut csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
let mut new_csr = csr;
|
let mut new_csr = csr;
|
||||||
new_csr[0].set_bits(4..8, 0);
|
new_csr[0].set_bits(4..8, 0);
|
||||||
new_csr[0].set_bit(4 + channel as usize, true);
|
new_csr[0].set_bit(4 + channel as usize, true);
|
||||||
|
|
||||||
self.interface.write(Register::CSR as u8, &new_csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &new_csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
self.interface.read(register as u8, &mut data).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.read(register as u8, &mut data)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
// Restore the previous CSR. Note that the re-enable of the channel happens immediately, so
|
// Restore the previous CSR. Note that the re-enable of the channel happens immediately, so
|
||||||
// the CSR update does not need to be latched.
|
// the CSR update does not need to be latched.
|
||||||
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
|
self.interface
|
||||||
|
.write(Register::CSR as u8, &csr)
|
||||||
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -361,10 +431,19 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The actual programmed phase offset of the channel in turns.
|
/// The actual programmed phase offset of the channel in turns.
|
||||||
pub fn set_phase(&mut self, channel: Channel, phase_turns: f32) -> Result<f32, Error> {
|
pub fn set_phase(
|
||||||
let phase_offset: u16 = (phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
phase_turns: f32,
|
||||||
|
) -> Result<f32, Error> {
|
||||||
|
let phase_offset: u16 =
|
||||||
|
(phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
|
||||||
|
|
||||||
self.modify_channel(channel, Register::CPOW0, &phase_offset.to_be_bytes())?;
|
self.modify_channel(
|
||||||
|
channel,
|
||||||
|
Register::CPOW0,
|
||||||
|
&phase_offset.to_be_bytes(),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok((phase_offset as f32) / ((1 << 14) as f32))
|
Ok((phase_offset as f32) / ((1 << 14) as f32))
|
||||||
}
|
}
|
||||||
|
@ -393,7 +472,11 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The actual normalized amplitude of the channel relative to full-scale range.
|
/// The actual normalized amplitude of the channel relative to full-scale range.
|
||||||
pub fn set_amplitude(&mut self, channel: Channel, amplitude: f32) -> Result<f32, Error> {
|
pub fn set_amplitude(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
amplitude: f32,
|
||||||
|
) -> Result<f32, Error> {
|
||||||
if amplitude < 0.0 || amplitude > 1.0 {
|
if amplitude < 0.0 || amplitude > 1.0 {
|
||||||
return Err(Error::Bounds);
|
return Err(Error::Bounds);
|
||||||
}
|
}
|
||||||
|
@ -406,7 +489,6 @@ where
|
||||||
// full-scale at 0x3FF (amplitude of 1), so the multiplier should be disabled whenever
|
// full-scale at 0x3FF (amplitude of 1), so the multiplier should be disabled whenever
|
||||||
// full-scale is used.
|
// full-scale is used.
|
||||||
if amplitude_control < (1 << 10) {
|
if amplitude_control < (1 << 10) {
|
||||||
|
|
||||||
let masked_control = amplitude_control & 0x3FF;
|
let masked_control = amplitude_control & 0x3FF;
|
||||||
acr[1] = masked_control.to_be_bytes()[0];
|
acr[1] = masked_control.to_be_bytes()[0];
|
||||||
acr[2] = masked_control.to_be_bytes()[1];
|
acr[2] = masked_control.to_be_bytes()[1];
|
||||||
|
@ -432,7 +514,8 @@ where
|
||||||
self.read_channel(channel, Register::ACR, &mut acr)?;
|
self.read_channel(channel, Register::ACR, &mut acr)?;
|
||||||
|
|
||||||
if acr[1].get_bit(4) {
|
if acr[1].get_bit(4) {
|
||||||
let amplitude_control: u16 = (((acr[1] as u16) << 8) | (acr[2] as u16)) & 0x3FF;
|
let amplitude_control: u16 =
|
||||||
|
(((acr[1] as u16) << 8) | (acr[2] as u16)) & 0x3FF;
|
||||||
Ok(amplitude_control as f32 / (1 << 10) as f32)
|
Ok(amplitude_control as f32 / (1 << 10) as f32)
|
||||||
} else {
|
} else {
|
||||||
Ok(1.0)
|
Ok(1.0)
|
||||||
|
@ -447,18 +530,28 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The actual programmed frequency of the channel.
|
/// The actual programmed frequency of the channel.
|
||||||
pub fn set_frequency(&mut self, channel: Channel, frequency: f64) -> Result<f64, Error> {
|
pub fn set_frequency(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
frequency: f64,
|
||||||
|
) -> Result<f64, Error> {
|
||||||
if frequency < 0.0 || frequency > self.system_clock_frequency() {
|
if frequency < 0.0 || frequency > self.system_clock_frequency() {
|
||||||
return Err(Error::Bounds);
|
return Err(Error::Bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The function for channel frequency is `f_out = FTW * f_s / 2^32`, where FTW is the
|
// The function for channel frequency is `f_out = FTW * f_s / 2^32`, where FTW is the
|
||||||
// frequency tuning word and f_s is the system clock rate.
|
// frequency tuning word and f_s is the system clock rate.
|
||||||
let tuning_word: u32 = ((frequency as f64 / self.system_clock_frequency())
|
let tuning_word: u32 =
|
||||||
|
((frequency as f64 / self.system_clock_frequency())
|
||||||
* 1u64.wrapping_shl(32) as f64) as u32;
|
* 1u64.wrapping_shl(32) as f64) as u32;
|
||||||
|
|
||||||
self.modify_channel(channel, Register::CFTW0, &tuning_word.to_be_bytes())?;
|
self.modify_channel(
|
||||||
Ok((tuning_word as f64 / 1u64.wrapping_shl(32) as f64) * self.system_clock_frequency())
|
channel,
|
||||||
|
Register::CFTW0,
|
||||||
|
&tuning_word.to_be_bytes(),
|
||||||
|
)?;
|
||||||
|
Ok((tuning_word as f64 / 1u64.wrapping_shl(32) as f64)
|
||||||
|
* self.system_clock_frequency())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the frequency of a channel.
|
/// Get the frequency of a channel.
|
||||||
|
@ -475,6 +568,7 @@ where
|
||||||
let tuning_word = u32::from_be_bytes(tuning_word);
|
let tuning_word = u32::from_be_bytes(tuning_word);
|
||||||
|
|
||||||
// Convert the tuning word into a frequency.
|
// Convert the tuning word into a frequency.
|
||||||
Ok(tuning_word as f64 * self.system_clock_frequency() / ((1u64 << 32)) as f64)
|
Ok(tuning_word as f64 * self.system_clock_frequency()
|
||||||
|
/ (1u64 << 32) as f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use embedded_hal;
|
use embedded_hal;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use enum_iterator::IntoEnumIterator;
|
use enum_iterator::IntoEnumIterator;
|
||||||
|
@ -9,13 +9,13 @@ pub enum Gain {
|
||||||
G1 = 0b00,
|
G1 = 0b00,
|
||||||
G2 = 0b01,
|
G2 = 0b01,
|
||||||
G5 = 0b10,
|
G5 = 0b10,
|
||||||
G10 = 0b11
|
G10 = 0b11,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A programmable gain amplifier that allows for setting the gain via GPIO.
|
/// A programmable gain amplifier that allows for setting the gain via GPIO.
|
||||||
pub struct ProgrammableGainAmplifier<A0, A1> {
|
pub struct ProgrammableGainAmplifier<A0, A1> {
|
||||||
a0: A0,
|
a0: A0,
|
||||||
a1: A1
|
a1: A1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<u8> for Gain {
|
impl TryFrom<u8> for Gain {
|
||||||
|
@ -24,7 +24,7 @@ impl TryFrom<u8> for Gain {
|
||||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
for gain in Gain::into_enum_iter() {
|
for gain in Gain::into_enum_iter() {
|
||||||
if value == gain as u8 {
|
if value == gain as u8 {
|
||||||
return Ok(gain)
|
return Ok(gain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,9 +44,8 @@ where
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `a0` - An output connected to the A0 input of the amplifier.
|
/// * `a0` - An output connected to the A0 input of the amplifier.
|
||||||
/// * `a1` - An output connected to the A1 input of the amplifier.
|
/// * `a1` - An output connected to the A1 input of the amplifier.
|
||||||
pub fn new(a0: A0, a1: A1) -> Self
|
pub fn new(a0: A0, a1: A1) -> Self {
|
||||||
{
|
let mut afe = Self { a0: a0, a1: a1 };
|
||||||
let mut afe = Self { a0: a0, a1: a1};
|
|
||||||
|
|
||||||
afe.set_gain(Gain::G1);
|
afe.set_gain(Gain::G1);
|
||||||
|
|
|
@ -4,7 +4,8 @@ const I2C_ADDR: u8 = 0x50;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn read_eui48<T>(i2c: &mut T) -> Result<[u8; 6], T::Error>
|
pub fn read_eui48<T>(i2c: &mut T) -> Result<[u8; 6], T::Error>
|
||||||
where T: WriteRead
|
where
|
||||||
|
T: WriteRead,
|
||||||
{
|
{
|
||||||
let mut buffer = [0u8; 6];
|
let mut buffer = [0u8; 6];
|
||||||
i2c.write_read(I2C_ADDR, &[0xFA_u8], &mut buffer)?;
|
i2c.write_read(I2C_ADDR, &[0xFA_u8], &mut buffer)?;
|
|
@ -29,25 +29,18 @@ extern crate log;
|
||||||
|
|
||||||
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
|
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
|
||||||
use asm_delay;
|
use asm_delay;
|
||||||
use rtfm::cyccnt::{Instant, U32Ext};
|
|
||||||
use cortex_m_rt::exception;
|
|
||||||
use cortex_m;
|
use cortex_m;
|
||||||
|
use cortex_m_rt::exception;
|
||||||
|
use rtfm::cyccnt::{Instant, U32Ext};
|
||||||
use stm32h7xx_hal as hal;
|
use stm32h7xx_hal as hal;
|
||||||
use stm32h7xx_hal::{
|
use stm32h7xx_hal::prelude::*;
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
use embedded_hal::{
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
digital::v2::OutputPin,
|
|
||||||
};
|
|
||||||
|
|
||||||
use stm32h7_ethernet as ethernet;
|
|
||||||
use smoltcp as net;
|
use smoltcp as net;
|
||||||
|
use stm32h7_ethernet as ethernet;
|
||||||
|
|
||||||
use heapless::{
|
use heapless::{consts::*, String};
|
||||||
String,
|
|
||||||
consts::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[link_section = ".sram3.eth"]
|
#[link_section = ".sram3.eth"]
|
||||||
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
||||||
|
@ -89,7 +82,9 @@ pub struct NetStorage {
|
||||||
|
|
||||||
static mut NET_STORE: NetStorage = NetStorage {
|
static mut NET_STORE: NetStorage = NetStorage {
|
||||||
// Placeholder for the real IP address, which is initialized at runtime.
|
// Placeholder for the real IP address, which is initialized at runtime.
|
||||||
ip_addrs: [net::wire::IpCidr::Ipv6(net::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX)],
|
ip_addrs: [net::wire::IpCidr::Ipv6(
|
||||||
|
net::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX,
|
||||||
|
)],
|
||||||
|
|
||||||
neighbor_cache: [None; 8],
|
neighbor_cache: [None; 8],
|
||||||
};
|
};
|
||||||
|
@ -105,11 +100,13 @@ const TCP_TX_BUFFER_SIZE: usize = 8192;
|
||||||
|
|
||||||
type AFE1 = afe::ProgrammableGainAmplifier<
|
type AFE1 = afe::ProgrammableGainAmplifier<
|
||||||
hal::gpio::gpiof::PF2<hal::gpio::Output<hal::gpio::PushPull>>,
|
hal::gpio::gpiof::PF2<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
hal::gpio::gpiof::PF5<hal::gpio::Output<hal::gpio::PushPull>>>;
|
hal::gpio::gpiof::PF5<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
|
>;
|
||||||
|
|
||||||
type AFE2 = afe::ProgrammableGainAmplifier<
|
type AFE2 = afe::ProgrammableGainAmplifier<
|
||||||
hal::gpio::gpiod::PD14<hal::gpio::Output<hal::gpio::PushPull>>,
|
hal::gpio::gpiod::PD14<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>>;
|
hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
|
>;
|
||||||
|
|
||||||
macro_rules! route_request {
|
macro_rules! route_request {
|
||||||
($request:ident,
|
($request:ident,
|
||||||
|
@ -176,8 +173,12 @@ const APP: () = {
|
||||||
eeprom_i2c: hal::i2c::I2c<hal::stm32::I2C2>,
|
eeprom_i2c: hal::i2c::I2c<hal::stm32::I2C2>,
|
||||||
|
|
||||||
timer: hal::timer::Timer<hal::stm32::TIM2>,
|
timer: hal::timer::Timer<hal::stm32::TIM2>,
|
||||||
net_interface: net::iface::EthernetInterface<'static, 'static, 'static,
|
net_interface: net::iface::EthernetInterface<
|
||||||
ethernet::EthernetDMA<'static>>,
|
'static,
|
||||||
|
'static,
|
||||||
|
'static,
|
||||||
|
ethernet::EthernetDMA<'static>,
|
||||||
|
>,
|
||||||
eth_mac: ethernet::EthernetMAC,
|
eth_mac: ethernet::EthernetMAC,
|
||||||
mac_addr: net::wire::EthernetAddress,
|
mac_addr: net::wire::EthernetAddress,
|
||||||
|
|
||||||
|
@ -200,7 +201,7 @@ const APP: () = {
|
||||||
let rcc = dp.RCC.constrain();
|
let rcc = dp.RCC.constrain();
|
||||||
let mut clocks = rcc
|
let mut clocks = rcc
|
||||||
//TODO: Re-enable HSE for Stabilizer platform.
|
//TODO: Re-enable HSE for Stabilizer platform.
|
||||||
// .use_hse(8.mhz())
|
// .use_hse(8.mhz())
|
||||||
.sysclk(400.mhz())
|
.sysclk(400.mhz())
|
||||||
.hclk(200.mhz())
|
.hclk(200.mhz())
|
||||||
.per_ck(100.mhz())
|
.per_ck(100.mhz())
|
||||||
|
@ -215,7 +216,10 @@ const APP: () = {
|
||||||
|
|
||||||
clocks.rb.rsr.write(|w| w.rmvf().set_bit());
|
clocks.rb.rsr.write(|w| w.rmvf().set_bit());
|
||||||
|
|
||||||
clocks.rb.d2ccip1r.modify(|_, w| w.spi123sel().pll2_p().spi45sel().pll2_q());
|
clocks
|
||||||
|
.rb
|
||||||
|
.d2ccip1r
|
||||||
|
.modify(|_, w| w.spi123sel().pll2_p().spi45sel().pll2_q());
|
||||||
|
|
||||||
let mut delay = hal::delay::Delay::new(cp.SYST, clocks.clocks);
|
let mut delay = hal::delay::Delay::new(cp.SYST, clocks.clocks);
|
||||||
|
|
||||||
|
@ -241,11 +245,17 @@ const APP: () = {
|
||||||
|
|
||||||
// Configure the SPI interfaces to the ADCs and DACs.
|
// Configure the SPI interfaces to the ADCs and DACs.
|
||||||
let adc1_spi = {
|
let adc1_spi = {
|
||||||
let spi_miso = gpiob.pb14.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
let spi_miso = gpiob
|
||||||
let spi_sck = gpiob.pb10.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
.pb14
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let spi_sck = gpiob
|
||||||
|
.pb10
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _spi_nss = gpiob.pb9.into_alternate_af5();
|
let _spi_nss = gpiob.pb9.into_alternate_af5();
|
||||||
|
|
||||||
let config = hal::spi::Config::new(hal::spi::Mode{
|
let config = hal::spi::Config::new(hal::spi::Mode {
|
||||||
polarity: hal::spi::Polarity::IdleHigh,
|
polarity: hal::spi::Polarity::IdleHigh,
|
||||||
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
||||||
})
|
})
|
||||||
|
@ -259,7 +269,8 @@ const APP: () = {
|
||||||
(spi_sck, spi_miso, hal::spi::NoMosi),
|
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||||
config,
|
config,
|
||||||
50.mhz(),
|
50.mhz(),
|
||||||
&clocks);
|
&clocks,
|
||||||
|
);
|
||||||
|
|
||||||
spi.listen(hal::spi::Event::Eot);
|
spi.listen(hal::spi::Event::Eot);
|
||||||
|
|
||||||
|
@ -267,12 +278,17 @@ const APP: () = {
|
||||||
};
|
};
|
||||||
|
|
||||||
let adc2_spi = {
|
let adc2_spi = {
|
||||||
let spi_miso = gpiob.pb4.into_alternate_af6().set_speed(hal::gpio::Speed::VeryHigh);
|
let spi_miso = gpiob
|
||||||
let spi_sck = gpioc.pc10.into_alternate_af6().set_speed(hal::gpio::Speed::VeryHigh);
|
.pb4
|
||||||
|
.into_alternate_af6()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let spi_sck = gpioc
|
||||||
|
.pc10
|
||||||
|
.into_alternate_af6()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _spi_nss = gpioa.pa15.into_alternate_af6();
|
let _spi_nss = gpioa.pa15.into_alternate_af6();
|
||||||
|
|
||||||
|
let config = hal::spi::Config::new(hal::spi::Mode {
|
||||||
let config = hal::spi::Config::new(hal::spi::Mode{
|
|
||||||
polarity: hal::spi::Polarity::IdleHigh,
|
polarity: hal::spi::Polarity::IdleHigh,
|
||||||
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
||||||
})
|
})
|
||||||
|
@ -286,7 +302,8 @@ const APP: () = {
|
||||||
(spi_sck, spi_miso, hal::spi::NoMosi),
|
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||||
config,
|
config,
|
||||||
50.mhz(),
|
50.mhz(),
|
||||||
&clocks);
|
&clocks,
|
||||||
|
);
|
||||||
|
|
||||||
spi.listen(hal::spi::Event::Eot);
|
spi.listen(hal::spi::Event::Eot);
|
||||||
|
|
||||||
|
@ -294,11 +311,17 @@ const APP: () = {
|
||||||
};
|
};
|
||||||
|
|
||||||
let dac1_spi = {
|
let dac1_spi = {
|
||||||
let spi_miso = gpioe.pe5.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
let spi_miso = gpioe
|
||||||
let spi_sck = gpioe.pe2.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
.pe5
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let spi_sck = gpioe
|
||||||
|
.pe2
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _spi_nss = gpioe.pe4.into_alternate_af5();
|
let _spi_nss = gpioe.pe4.into_alternate_af5();
|
||||||
|
|
||||||
let config = hal::spi::Config::new(hal::spi::Mode{
|
let config = hal::spi::Config::new(hal::spi::Mode {
|
||||||
polarity: hal::spi::Polarity::IdleHigh,
|
polarity: hal::spi::Polarity::IdleHigh,
|
||||||
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
||||||
})
|
})
|
||||||
|
@ -308,16 +331,27 @@ const APP: () = {
|
||||||
.frame_size(16)
|
.frame_size(16)
|
||||||
.swap_mosi_miso();
|
.swap_mosi_miso();
|
||||||
|
|
||||||
let spi = dp.SPI4.spi((spi_sck, spi_miso, hal::spi::NoMosi), config, 50.mhz(), &clocks);
|
let spi = dp.SPI4.spi(
|
||||||
|
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||||
|
config,
|
||||||
|
50.mhz(),
|
||||||
|
&clocks,
|
||||||
|
);
|
||||||
spi
|
spi
|
||||||
};
|
};
|
||||||
|
|
||||||
let dac2_spi = {
|
let dac2_spi = {
|
||||||
let spi_miso = gpiof.pf8.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
let spi_miso = gpiof
|
||||||
let spi_sck = gpiof.pf7.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
.pf8
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let spi_sck = gpiof
|
||||||
|
.pf7
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _spi_nss = gpiof.pf6.into_alternate_af5();
|
let _spi_nss = gpiof.pf6.into_alternate_af5();
|
||||||
|
|
||||||
let config = hal::spi::Config::new(hal::spi::Mode{
|
let config = hal::spi::Config::new(hal::spi::Mode {
|
||||||
polarity: hal::spi::Polarity::IdleHigh,
|
polarity: hal::spi::Polarity::IdleHigh,
|
||||||
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
||||||
})
|
})
|
||||||
|
@ -327,7 +361,12 @@ const APP: () = {
|
||||||
.frame_size(16)
|
.frame_size(16)
|
||||||
.swap_mosi_miso();
|
.swap_mosi_miso();
|
||||||
|
|
||||||
let spi = dp.SPI5.spi((spi_sck, spi_miso, hal::spi::NoMosi), config, 50.mhz(), &clocks);
|
let spi = dp.SPI5.spi(
|
||||||
|
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||||
|
config,
|
||||||
|
50.mhz(),
|
||||||
|
&clocks,
|
||||||
|
);
|
||||||
|
|
||||||
spi
|
spi
|
||||||
};
|
};
|
||||||
|
@ -342,40 +381,63 @@ const APP: () = {
|
||||||
fp_led_2.set_low().unwrap();
|
fp_led_2.set_low().unwrap();
|
||||||
fp_led_3.set_low().unwrap();
|
fp_led_3.set_low().unwrap();
|
||||||
|
|
||||||
|
|
||||||
let pounder_devices = {
|
let pounder_devices = {
|
||||||
let ad9959 = {
|
let ad9959 = {
|
||||||
let qspi_interface = {
|
let qspi_interface = {
|
||||||
// Instantiate the QUADSPI pins and peripheral interface.
|
// Instantiate the QUADSPI pins and peripheral interface.
|
||||||
// TODO: Place these into a pins structure that is provided to the QSPI
|
// TODO: Place these into a pins structure that is provided to the QSPI
|
||||||
// constructor.
|
// constructor.
|
||||||
let _qspi_clk = gpiob.pb2.into_alternate_af9().set_speed(hal::gpio::Speed::VeryHigh);
|
let _qspi_clk = gpiob
|
||||||
let _qspi_ncs = gpioc.pc11.into_alternate_af9().set_speed(hal::gpio::Speed::VeryHigh);
|
.pb2
|
||||||
let _qspi_io0 = gpioe.pe7.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh);
|
.into_alternate_af9()
|
||||||
let _qspi_io1 = gpioe.pe8.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh);
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _qspi_io2 = gpioe.pe9.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh);
|
let _qspi_ncs = gpioc
|
||||||
let _qspi_io3 = gpioe.pe10.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh);
|
.pc11
|
||||||
|
.into_alternate_af9()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _qspi_io0 = gpioe
|
||||||
|
.pe7
|
||||||
|
.into_alternate_af10()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _qspi_io1 = gpioe
|
||||||
|
.pe8
|
||||||
|
.into_alternate_af10()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _qspi_io2 = gpioe
|
||||||
|
.pe9
|
||||||
|
.into_alternate_af10()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _qspi_io3 = gpioe
|
||||||
|
.pe10
|
||||||
|
.into_alternate_af10()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
|
||||||
let qspi = hal::qspi::Qspi::new(dp.QUADSPI, &mut clocks, 10.mhz()).unwrap();
|
let qspi =
|
||||||
|
hal::qspi::Qspi::new(dp.QUADSPI, &mut clocks, 10.mhz())
|
||||||
|
.unwrap();
|
||||||
pounder::QspiInterface::new(qspi).unwrap()
|
pounder::QspiInterface::new(qspi).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut reset_pin = gpioa.pa0.into_push_pull_output();
|
let mut reset_pin = gpioa.pa0.into_push_pull_output();
|
||||||
let io_update = gpiog.pg7.into_push_pull_output();
|
let io_update = gpiog.pg7.into_push_pull_output();
|
||||||
|
|
||||||
|
|
||||||
let asm_delay = {
|
let asm_delay = {
|
||||||
let frequency_hz = clocks.clocks.c_ck().0;
|
let frequency_hz = clocks.clocks.c_ck().0;
|
||||||
asm_delay::AsmDelay::new(asm_delay::bitrate::Hertz (frequency_hz))
|
asm_delay::AsmDelay::new(asm_delay::bitrate::Hertz(
|
||||||
|
frequency_hz,
|
||||||
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
ad9959::Ad9959::new(qspi_interface,
|
ad9959::Ad9959::new(
|
||||||
|
qspi_interface,
|
||||||
&mut reset_pin,
|
&mut reset_pin,
|
||||||
io_update,
|
io_update,
|
||||||
asm_delay,
|
asm_delay,
|
||||||
ad9959::Mode::FourBitSerial,
|
ad9959::Mode::FourBitSerial,
|
||||||
100_000_000f32,
|
100_000_000f32,
|
||||||
5).unwrap()
|
5,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let io_expander = {
|
let io_expander = {
|
||||||
|
@ -386,11 +448,20 @@ const APP: () = {
|
||||||
};
|
};
|
||||||
|
|
||||||
let spi = {
|
let spi = {
|
||||||
let spi_mosi = gpiod.pd7.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
let spi_mosi = gpiod
|
||||||
let spi_miso = gpioa.pa6.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
.pd7
|
||||||
let spi_sck = gpiog.pg11.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh);
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let spi_miso = gpioa
|
||||||
|
.pa6
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let spi_sck = gpiog
|
||||||
|
.pg11
|
||||||
|
.into_alternate_af5()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
|
||||||
let config = hal::spi::Config::new(hal::spi::Mode{
|
let config = hal::spi::Config::new(hal::spi::Mode {
|
||||||
polarity: hal::spi::Polarity::IdleHigh,
|
polarity: hal::spi::Polarity::IdleHigh,
|
||||||
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
phase: hal::spi::Phase::CaptureOnSecondTransition,
|
||||||
})
|
})
|
||||||
|
@ -398,7 +469,12 @@ const APP: () = {
|
||||||
|
|
||||||
// The maximum frequency of this SPI must be limited due to capacitance on the MISO
|
// The maximum frequency of this SPI must be limited due to capacitance on the MISO
|
||||||
// line causing a long RC decay.
|
// line causing a long RC decay.
|
||||||
dp.SPI1.spi((spi_sck, spi_miso, spi_mosi), config, 5.mhz(), &clocks)
|
dp.SPI1.spi(
|
||||||
|
(spi_sck, spi_miso, spi_mosi),
|
||||||
|
config,
|
||||||
|
5.mhz(),
|
||||||
|
&clocks,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let adc1 = {
|
let adc1 = {
|
||||||
|
@ -418,13 +494,16 @@ const APP: () = {
|
||||||
let adc1_in_p = gpiof.pf11.into_analog();
|
let adc1_in_p = gpiof.pf11.into_analog();
|
||||||
let adc2_in_p = gpiof.pf14.into_analog();
|
let adc2_in_p = gpiof.pf14.into_analog();
|
||||||
|
|
||||||
pounder::PounderDevices::new(io_expander,
|
pounder::PounderDevices::new(
|
||||||
|
io_expander,
|
||||||
ad9959,
|
ad9959,
|
||||||
spi,
|
spi,
|
||||||
adc1,
|
adc1,
|
||||||
adc2,
|
adc2,
|
||||||
adc1_in_p,
|
adc1_in_p,
|
||||||
adc2_in_p).unwrap()
|
adc2_in_p,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut eeprom_i2c = {
|
let mut eeprom_i2c = {
|
||||||
|
@ -440,15 +519,42 @@ const APP: () = {
|
||||||
eth_phy_nrst.set_low().unwrap();
|
eth_phy_nrst.set_low().unwrap();
|
||||||
delay.delay_us(200u8);
|
delay.delay_us(200u8);
|
||||||
eth_phy_nrst.set_high().unwrap();
|
eth_phy_nrst.set_high().unwrap();
|
||||||
let _rmii_ref_clk = gpioa.pa1.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
let _rmii_ref_clk = gpioa
|
||||||
let _rmii_mdio = gpioa.pa2.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
.pa1
|
||||||
let _rmii_mdc = gpioc.pc1.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
.into_alternate_af11()
|
||||||
let _rmii_crs_dv = gpioa.pa7.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _rmii_rxd0 = gpioc.pc4.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
let _rmii_mdio = gpioa
|
||||||
let _rmii_rxd1 = gpioc.pc5.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
.pa2
|
||||||
let _rmii_tx_en = gpiob.pb11.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
.into_alternate_af11()
|
||||||
let _rmii_txd0 = gpiob.pb12.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
let _rmii_txd1 = gpiog.pg14.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh);
|
let _rmii_mdc = gpioc
|
||||||
|
.pc1
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _rmii_crs_dv = gpioa
|
||||||
|
.pa7
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _rmii_rxd0 = gpioc
|
||||||
|
.pc4
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _rmii_rxd1 = gpioc
|
||||||
|
.pc5
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _rmii_tx_en = gpiob
|
||||||
|
.pb11
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _rmii_txd0 = gpiob
|
||||||
|
.pb12
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
|
let _rmii_txd1 = gpiog
|
||||||
|
.pg14
|
||||||
|
.into_alternate_af11()
|
||||||
|
.set_speed(hal::gpio::Speed::VeryHigh);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mac_addr = match eeprom::read_eui48(&mut eeprom_i2c) {
|
let mac_addr = match eeprom::read_eui48(&mut eeprom_i2c) {
|
||||||
|
@ -467,16 +573,21 @@ const APP: () = {
|
||||||
dp.ETHERNET_MTL,
|
dp.ETHERNET_MTL,
|
||||||
dp.ETHERNET_DMA,
|
dp.ETHERNET_DMA,
|
||||||
&mut DES_RING,
|
&mut DES_RING,
|
||||||
mac_addr.clone())
|
mac_addr.clone(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { ethernet::enable_interrupt() };
|
unsafe { ethernet::enable_interrupt() };
|
||||||
|
|
||||||
let store = unsafe { &mut NET_STORE };
|
let store = unsafe { &mut NET_STORE };
|
||||||
|
|
||||||
store.ip_addrs[0] = net::wire::IpCidr::new(net::wire::IpAddress::v4(10, 0, 16, 99), 24);
|
store.ip_addrs[0] = net::wire::IpCidr::new(
|
||||||
|
net::wire::IpAddress::v4(10, 0, 16, 99),
|
||||||
|
24,
|
||||||
|
);
|
||||||
|
|
||||||
let neighbor_cache = net::iface::NeighborCache::new(&mut store.neighbor_cache[..]);
|
let neighbor_cache =
|
||||||
|
net::iface::NeighborCache::new(&mut store.neighbor_cache[..]);
|
||||||
|
|
||||||
let interface = net::iface::EthernetInterfaceBuilder::new(eth_dma)
|
let interface = net::iface::EthernetInterfaceBuilder::new(eth_dma)
|
||||||
.ethernet_addr(mac_addr)
|
.ethernet_addr(mac_addr)
|
||||||
|
@ -497,15 +608,19 @@ const APP: () = {
|
||||||
cp.DWT.enable_cycle_counter();
|
cp.DWT.enable_cycle_counter();
|
||||||
|
|
||||||
let mut dma = hal::dma::Dma::dma(dp.DMA1, dp.DMAMUX1, &clocks);
|
let mut dma = hal::dma::Dma::dma(dp.DMA1, dp.DMAMUX1, &clocks);
|
||||||
dma.configure_m2p_stream(hal::dma::Stream::One,
|
dma.configure_m2p_stream(
|
||||||
|
hal::dma::Stream::One,
|
||||||
&SPI_START_CODE as *const _ as u32,
|
&SPI_START_CODE as *const _ as u32,
|
||||||
&adc1_spi.spi.cr1 as *const _ as u32,
|
&adc1_spi.spi.cr1 as *const _ as u32,
|
||||||
hal::dma::DMAREQ_ID::TIM2_CH1);
|
hal::dma::DMAREQ_ID::TIM2_CH1,
|
||||||
|
);
|
||||||
|
|
||||||
dma.configure_m2p_stream(hal::dma::Stream::Two,
|
dma.configure_m2p_stream(
|
||||||
|
hal::dma::Stream::Two,
|
||||||
&SPI_START_CODE as *const _ as u32,
|
&SPI_START_CODE as *const _ as u32,
|
||||||
&adc2_spi.spi.cr1 as *const _ as u32,
|
&adc2_spi.spi.cr1 as *const _ as u32,
|
||||||
hal::dma::DMAREQ_ID::TIM2_CH2);
|
hal::dma::DMAREQ_ID::TIM2_CH2,
|
||||||
|
);
|
||||||
|
|
||||||
// Configure timer 2 to trigger conversions for the ADC
|
// Configure timer 2 to trigger conversions for the ADC
|
||||||
let mut timer2 = dp.TIM2.timer(500.khz(), &mut clocks);
|
let mut timer2 = dp.TIM2.timer(500.khz(), &mut clocks);
|
||||||
|
@ -540,11 +655,16 @@ const APP: () = {
|
||||||
let output: u16 = {
|
let output: u16 = {
|
||||||
let a: u16 = c.resources.adc2.read().unwrap();
|
let a: u16 = c.resources.adc2.read().unwrap();
|
||||||
let x0 = f32::from(a as i16);
|
let x0 = f32::from(a as i16);
|
||||||
let y0 = c.resources.iir_ch[1].update(&mut c.resources.iir_state[1], x0);
|
let y0 =
|
||||||
|
c.resources.iir_ch[1].update(&mut c.resources.iir_state[1], x0);
|
||||||
y0 as i16 as u16 ^ 0x8000
|
y0 as i16 as u16 ^ 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
c.resources.dac2.spi.ifcr.write(|w| w.eotc().set_bit().txtfc().set_bit());
|
c.resources
|
||||||
|
.dac2
|
||||||
|
.spi
|
||||||
|
.ifcr
|
||||||
|
.write(|w| w.eotc().set_bit().txtfc().set_bit());
|
||||||
c.resources.dac2.send(output).unwrap();
|
c.resources.dac2.send(output).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,26 +675,34 @@ const APP: () = {
|
||||||
let output: u16 = {
|
let output: u16 = {
|
||||||
let a: u16 = c.resources.adc1.read().unwrap();
|
let a: u16 = c.resources.adc1.read().unwrap();
|
||||||
let x0 = f32::from(a as i16);
|
let x0 = f32::from(a as i16);
|
||||||
let y0 = c.resources.iir_ch[0].update(&mut c.resources.iir_state[0], x0);
|
let y0 =
|
||||||
|
c.resources.iir_ch[0].update(&mut c.resources.iir_state[0], x0);
|
||||||
y0 as i16 as u16 ^ 0x8000
|
y0 as i16 as u16 ^ 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
c.resources.dac1.spi.ifcr.write(|w| w.eotc().set_bit().txtfc().set_bit());
|
c.resources
|
||||||
|
.dac1
|
||||||
|
.spi
|
||||||
|
.ifcr
|
||||||
|
.write(|w| w.eotc().set_bit().txtfc().set_bit());
|
||||||
c.resources.dac1.send(output).unwrap();
|
c.resources.dac1.send(output).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(resources=[net_interface, pounder, mac_addr, eth_mac, iir_state, iir_ch, afe1, afe2])]
|
#[idle(resources=[net_interface, pounder, mac_addr, eth_mac, iir_state, iir_ch, afe1, afe2])]
|
||||||
fn idle(mut c: idle::Context) -> ! {
|
fn idle(mut c: idle::Context) -> ! {
|
||||||
|
|
||||||
let mut socket_set_entries: [_; 8] = Default::default();
|
let mut socket_set_entries: [_; 8] = Default::default();
|
||||||
let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]);
|
let mut sockets =
|
||||||
|
net::socket::SocketSet::new(&mut socket_set_entries[..]);
|
||||||
|
|
||||||
let mut rx_storage = [0; TCP_RX_BUFFER_SIZE];
|
let mut rx_storage = [0; TCP_RX_BUFFER_SIZE];
|
||||||
let mut tx_storage = [0; TCP_TX_BUFFER_SIZE];
|
let mut tx_storage = [0; TCP_TX_BUFFER_SIZE];
|
||||||
let tcp_handle = {
|
let tcp_handle = {
|
||||||
let tcp_rx_buffer = net::socket::TcpSocketBuffer::new(&mut rx_storage[..]);
|
let tcp_rx_buffer =
|
||||||
let tcp_tx_buffer = net::socket::TcpSocketBuffer::new(&mut tx_storage[..]);
|
net::socket::TcpSocketBuffer::new(&mut rx_storage[..]);
|
||||||
let tcp_socket = net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
let tcp_tx_buffer =
|
||||||
|
net::socket::TcpSocketBuffer::new(&mut tx_storage[..]);
|
||||||
|
let tcp_socket =
|
||||||
|
net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
||||||
sockets.add(tcp_socket)
|
sockets.add(tcp_socket)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -697,8 +825,10 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sleep = match c.resources.net_interface.poll(&mut sockets,
|
let sleep = match c.resources.net_interface.poll(
|
||||||
net::time::Instant::from_millis(time as i64)) {
|
&mut sockets,
|
||||||
|
net::time::Instant::from_millis(time as i64),
|
||||||
|
) {
|
||||||
Ok(changed) => changed == false,
|
Ok(changed) => changed == false,
|
||||||
Err(net::Error::Unrecognized) => true,
|
Err(net::Error::Unrecognized) => true,
|
||||||
Err(e) => {
|
Err(e) => {
|
|
@ -8,14 +8,17 @@ use super::{Channel, Error};
|
||||||
/// reading the shfit register. The downside of this approach is that any read is destructive, so a
|
/// reading the shfit register. The downside of this approach is that any read is destructive, so a
|
||||||
/// read-writeback approach is employed.
|
/// read-writeback approach is employed.
|
||||||
pub trait AttenuatorInterface {
|
pub trait AttenuatorInterface {
|
||||||
|
|
||||||
/// Set the attenuation of a single channel.
|
/// Set the attenuation of a single channel.
|
||||||
///
|
///
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `channel` - The pounder channel to configure the attenuation of.
|
/// * `channel` - The pounder channel to configure the attenuation of.
|
||||||
/// * `attenuation` - The desired attenuation of the channel in dB. This has a resolution of
|
/// * `attenuation` - The desired attenuation of the channel in dB. This has a resolution of
|
||||||
/// 0.5dB.
|
/// 0.5dB.
|
||||||
fn set_attenuation(&mut self, channel: Channel, attenuation: f32) -> Result<f32, Error> {
|
fn set_attenuation(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
attenuation: f32,
|
||||||
|
) -> Result<f32, Error> {
|
||||||
if attenuation > 31.5 || attenuation < 0.0 {
|
if attenuation > 31.5 || attenuation < 0.0 {
|
||||||
return Err(Error::Bounds);
|
return Err(Error::Bounds);
|
||||||
}
|
}
|
||||||
|
@ -72,6 +75,12 @@ pub trait AttenuatorInterface {
|
||||||
fn reset_attenuators(&mut self) -> Result<(), Error>;
|
fn reset_attenuators(&mut self) -> Result<(), Error>;
|
||||||
|
|
||||||
fn latch_attenuators(&mut self, channel: Channel) -> Result<(), Error>;
|
fn latch_attenuators(&mut self, channel: Channel) -> Result<(), Error>;
|
||||||
fn read_all_attenuators(&mut self, channels: &mut [u8; 4]) -> Result<(), Error>;
|
fn read_all_attenuators(
|
||||||
fn write_all_attenuators(&mut self, channels: &[u8; 4]) -> Result<(), Error>;
|
&mut self,
|
||||||
|
channels: &mut [u8; 4],
|
||||||
|
) -> Result<(), Error>;
|
||||||
|
fn write_all_attenuators(
|
||||||
|
&mut self,
|
||||||
|
channels: &[u8; 4],
|
||||||
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
use mcp23017;
|
|
||||||
use ad9959;
|
use ad9959;
|
||||||
|
use mcp23017;
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
mod attenuators;
|
mod attenuators;
|
||||||
mod rf_power;
|
mod rf_power;
|
||||||
|
@ -11,10 +11,7 @@ use super::hal;
|
||||||
use attenuators::AttenuatorInterface;
|
use attenuators::AttenuatorInterface;
|
||||||
use rf_power::PowerMeasurementInterface;
|
use rf_power::PowerMeasurementInterface;
|
||||||
|
|
||||||
use embedded_hal::{
|
use embedded_hal::{adc::OneShot, blocking::spi::Transfer};
|
||||||
blocking::spi::Transfer,
|
|
||||||
adc::OneShot,
|
|
||||||
};
|
|
||||||
|
|
||||||
const EXT_CLK_SEL_PIN: u8 = 8 + 7;
|
const EXT_CLK_SEL_PIN: u8 = 8 + 7;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -106,8 +103,12 @@ impl QspiInterface {
|
||||||
// This driver only supports operation in 4-bit mode due to bus inconsistencies between the
|
// This driver only supports operation in 4-bit mode due to bus inconsistencies between the
|
||||||
// QSPI peripheral and the DDS. Instead, we will bit-bang communications in
|
// QSPI peripheral and the DDS. Instead, we will bit-bang communications in
|
||||||
// single-bit-two-wire to the DDS to configure it to 4-bit operation.
|
// single-bit-two-wire to the DDS to configure it to 4-bit operation.
|
||||||
qspi.configure_mode(hal::qspi::QspiMode::FourBit).map_err(|_| Error::Qspi)?;
|
qspi.configure_mode(hal::qspi::QspiMode::FourBit)
|
||||||
Ok(Self { qspi: qspi, mode: ad9959::Mode::SingleBitTwoWire })
|
.map_err(|_| Error::Qspi)?;
|
||||||
|
Ok(Self {
|
||||||
|
qspi: qspi,
|
||||||
|
mode: ad9959::Mode::SingleBitTwoWire,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +190,9 @@ impl ad9959::Interface for QspiInterface {
|
||||||
let byte_position = 3 - (bit >> 1) as usize;
|
let byte_position = 3 - (bit >> 1) as usize;
|
||||||
|
|
||||||
if byte & (1 << bit) != 0 {
|
if byte & (1 << bit) != 0 {
|
||||||
encoded_data[(byte_index + 1) * 4 + byte_position] |= 1 << offset;
|
encoded_data
|
||||||
|
[(byte_index + 1) * 4 + byte_position] |=
|
||||||
|
1 << offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,14 +202,14 @@ impl ad9959::Interface for QspiInterface {
|
||||||
(encoded_data[0], &encoded_data[1..end_index])
|
(encoded_data[0], &encoded_data[1..end_index])
|
||||||
};
|
};
|
||||||
|
|
||||||
self.qspi.write(encoded_address, &encoded_payload).map_err(|_| Error::Qspi)
|
self.qspi
|
||||||
},
|
.write(encoded_address, &encoded_payload)
|
||||||
|
.map_err(|_| Error::Qspi)
|
||||||
|
}
|
||||||
ad9959::Mode::FourBitSerial => {
|
ad9959::Mode::FourBitSerial => {
|
||||||
self.qspi.write(addr, &data).map_err(|_| Error::Qspi)
|
self.qspi.write(addr, &data).map_err(|_| Error::Qspi)
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
Err(Error::Qspi)
|
|
||||||
}
|
}
|
||||||
|
_ => Err(Error::Qspi),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,15 +223,19 @@ impl ad9959::Interface for QspiInterface {
|
||||||
return Err(Error::Qspi);
|
return Err(Error::Qspi);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.qspi.read(0x80_u8 | addr, &mut dest).map_err(|_| Error::Qspi)
|
self.qspi
|
||||||
|
.read(0x80_u8 | addr, &mut dest)
|
||||||
|
.map_err(|_| Error::Qspi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A structure containing implementation for Pounder hardware.
|
/// A structure containing implementation for Pounder hardware.
|
||||||
pub struct PounderDevices<DELAY> {
|
pub struct PounderDevices<DELAY> {
|
||||||
pub ad9959: ad9959::Ad9959<QspiInterface,
|
pub ad9959: ad9959::Ad9959<
|
||||||
|
QspiInterface,
|
||||||
DELAY,
|
DELAY,
|
||||||
hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>>,
|
hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
|
>,
|
||||||
mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
|
mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
|
||||||
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
|
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
|
||||||
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
|
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
|
||||||
|
@ -250,11 +257,13 @@ where
|
||||||
/// * `adc2` - The ADC2 peripheral for measuring power.
|
/// * `adc2` - The ADC2 peripheral for measuring power.
|
||||||
/// * `adc1_in_p` - The input channel for the RF power measurement on IN0.
|
/// * `adc1_in_p` - The input channel for the RF power measurement on IN0.
|
||||||
/// * `adc2_in_p` - The input channel for the RF power measurement on IN1.
|
/// * `adc2_in_p` - The input channel for the RF power measurement on IN1.
|
||||||
pub fn new(mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
|
pub fn new(
|
||||||
ad9959: ad9959::Ad9959<QspiInterface,
|
mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
|
||||||
|
ad9959: ad9959::Ad9959<
|
||||||
|
QspiInterface,
|
||||||
DELAY,
|
DELAY,
|
||||||
hal::gpio::gpiog::PG7<
|
hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
hal::gpio::Output<hal::gpio::PushPull>>>,
|
>,
|
||||||
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
|
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
|
||||||
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
|
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
|
||||||
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
|
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
|
||||||
|
@ -274,9 +283,18 @@ where
|
||||||
// Configure power-on-default state for pounder. All LEDs are on, on-board oscillator
|
// Configure power-on-default state for pounder. All LEDs are on, on-board oscillator
|
||||||
// selected, attenuators out of reset. Note that testing indicates the output state needs to
|
// selected, attenuators out of reset. Note that testing indicates the output state needs to
|
||||||
// be set first to properly update the output registers.
|
// be set first to properly update the output registers.
|
||||||
devices.mcp23017.all_pin_mode(mcp23017::PinMode::OUTPUT).map_err(|_| Error::I2c)?;
|
devices
|
||||||
devices.mcp23017.write_gpio(mcp23017::Port::GPIOA, 0x3F).map_err(|_| Error::I2c)?;
|
.mcp23017
|
||||||
devices.mcp23017.write_gpio(mcp23017::Port::GPIOB, 1 << 5).map_err(|_| Error::I2c)?;
|
.all_pin_mode(mcp23017::PinMode::OUTPUT)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
devices
|
||||||
|
.mcp23017
|
||||||
|
.write_gpio(mcp23017::Port::GPIOA, 0x3F)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
devices
|
||||||
|
.mcp23017
|
||||||
|
.write_gpio(mcp23017::Port::GPIOB, 1 << 5)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
|
||||||
// Select the on-board clock with a 4x prescaler (400MHz).
|
// Select the on-board clock with a 4x prescaler (400MHz).
|
||||||
devices.select_onboard_clock(4u8)?;
|
devices.select_onboard_clock(4u8)?;
|
||||||
|
@ -289,9 +307,17 @@ where
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `frequency` - The frequency of the external clock source.
|
/// * `frequency` - The frequency of the external clock source.
|
||||||
/// * `multiplier` - The multiplier of the reference clock to use in the DDS.
|
/// * `multiplier` - The multiplier of the reference clock to use in the DDS.
|
||||||
fn select_external_clock(&mut self, frequency: f32, prescaler: u8) -> Result<(), Error>{
|
fn select_external_clock(
|
||||||
self.mcp23017.digital_write(EXT_CLK_SEL_PIN, true).map_err(|_| Error::I2c)?;
|
&mut self,
|
||||||
self.ad9959.configure_system_clock(frequency, prescaler).map_err(|_| Error::Dds)?;
|
frequency: f32,
|
||||||
|
prescaler: u8,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.mcp23017
|
||||||
|
.digital_write(EXT_CLK_SEL_PIN, true)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
self.ad9959
|
||||||
|
.configure_system_clock(frequency, prescaler)
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -301,8 +327,12 @@ where
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `multiplier` - The multiplier of the reference clock to use in the DDS.
|
/// * `multiplier` - The multiplier of the reference clock to use in the DDS.
|
||||||
fn select_onboard_clock(&mut self, multiplier: u8) -> Result<(), Error> {
|
fn select_onboard_clock(&mut self, multiplier: u8) -> Result<(), Error> {
|
||||||
self.mcp23017.digital_write(EXT_CLK_SEL_PIN, false).map_err(|_| Error::I2c)?;
|
self.mcp23017
|
||||||
self.ad9959.configure_system_clock(100_000_000f32, multiplier).map_err(|_| Error::Dds)?;
|
.digital_write(EXT_CLK_SEL_PIN, false)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
self.ad9959
|
||||||
|
.configure_system_clock(100_000_000f32, multiplier)
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -311,9 +341,15 @@ where
|
||||||
///
|
///
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `config` - The configuration of the DDS clock desired.
|
/// * `config` - The configuration of the DDS clock desired.
|
||||||
pub fn configure_dds_clock(&mut self, config: DdsClockConfig) -> Result<(), Error> {
|
pub fn configure_dds_clock(
|
||||||
|
&mut self,
|
||||||
|
config: DdsClockConfig,
|
||||||
|
) -> Result<(), Error> {
|
||||||
if config.external_clock {
|
if config.external_clock {
|
||||||
self.select_external_clock(config.reference_clock, config.multiplier)
|
self.select_external_clock(
|
||||||
|
config.reference_clock,
|
||||||
|
config.multiplier,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
self.select_onboard_clock(config.multiplier)
|
self.select_onboard_clock(config.multiplier)
|
||||||
}
|
}
|
||||||
|
@ -324,11 +360,21 @@ where
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The current pounder DDS clock configuration.
|
/// The current pounder DDS clock configuration.
|
||||||
pub fn get_dds_clock_config(&mut self) -> Result<DdsClockConfig, Error> {
|
pub fn get_dds_clock_config(&mut self) -> Result<DdsClockConfig, Error> {
|
||||||
let external_clock = self.mcp23017.digital_read(EXT_CLK_SEL_PIN).map_err(|_| Error::I2c)?;
|
let external_clock = self
|
||||||
let multiplier = self.ad9959.get_reference_clock_multiplier().map_err(|_| Error::Dds)?;
|
.mcp23017
|
||||||
|
.digital_read(EXT_CLK_SEL_PIN)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
let multiplier = self
|
||||||
|
.ad9959
|
||||||
|
.get_reference_clock_multiplier()
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
let reference_clock = self.ad9959.get_reference_clock_frequency();
|
let reference_clock = self.ad9959.get_reference_clock_frequency();
|
||||||
|
|
||||||
Ok(DdsClockConfig{multiplier, reference_clock, external_clock})
|
Ok(DdsClockConfig {
|
||||||
|
multiplier,
|
||||||
|
reference_clock,
|
||||||
|
external_clock,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the state of a Pounder input channel.
|
/// Get the state of a Pounder input channel.
|
||||||
|
@ -338,7 +384,10 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The read-back channel input state.
|
/// The read-back channel input state.
|
||||||
pub fn get_input_channel_state(&mut self, channel: Channel) -> Result<InputChannelState, Error> {
|
pub fn get_input_channel_state(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
) -> Result<InputChannelState, Error> {
|
||||||
match channel {
|
match channel {
|
||||||
Channel::In0 | Channel::In1 => {
|
Channel::In0 | Channel::In1 => {
|
||||||
let channel_state = self.get_dds_channel_state(channel)?;
|
let channel_state = self.get_dds_channel_state(channel)?;
|
||||||
|
@ -349,7 +398,7 @@ where
|
||||||
Ok(InputChannelState {
|
Ok(InputChannelState {
|
||||||
attenuation: attenuation,
|
attenuation: attenuation,
|
||||||
power: power,
|
power: power,
|
||||||
mixer: channel_state
|
mixer: channel_state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(Error::InvalidChannel),
|
_ => Err(Error::InvalidChannel),
|
||||||
|
@ -363,13 +412,33 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The read-back channel state.
|
/// The read-back channel state.
|
||||||
fn get_dds_channel_state(&mut self, channel: Channel) -> Result<DdsChannelState, Error> {
|
fn get_dds_channel_state(
|
||||||
let frequency = self.ad9959.get_frequency(channel.into()).map_err(|_| Error::Dds)?;
|
&mut self,
|
||||||
let phase_offset = self.ad9959.get_phase(channel.into()).map_err(|_| Error::Dds)?;
|
channel: Channel,
|
||||||
let amplitude = self.ad9959.get_amplitude(channel.into()).map_err(|_| Error::Dds)?;
|
) -> Result<DdsChannelState, Error> {
|
||||||
let enabled = self.ad9959.is_enabled(channel.into()).map_err(|_| Error::Dds)?;
|
let frequency = self
|
||||||
|
.ad9959
|
||||||
|
.get_frequency(channel.into())
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
let phase_offset = self
|
||||||
|
.ad9959
|
||||||
|
.get_phase(channel.into())
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
let amplitude = self
|
||||||
|
.ad9959
|
||||||
|
.get_amplitude(channel.into())
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
let enabled = self
|
||||||
|
.ad9959
|
||||||
|
.is_enabled(channel.into())
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
|
||||||
Ok(DdsChannelState {phase_offset, frequency, amplitude, enabled})
|
Ok(DdsChannelState {
|
||||||
|
phase_offset,
|
||||||
|
frequency,
|
||||||
|
amplitude,
|
||||||
|
enabled,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the state of a DDS output channel.
|
/// Get the state of a DDS output channel.
|
||||||
|
@ -379,7 +448,10 @@ where
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The read-back output channel state.
|
/// The read-back output channel state.
|
||||||
pub fn get_output_channel_state(&mut self, channel: Channel) -> Result<OutputChannelState, Error> {
|
pub fn get_output_channel_state(
|
||||||
|
&mut self,
|
||||||
|
channel: Channel,
|
||||||
|
) -> Result<OutputChannelState, Error> {
|
||||||
match channel {
|
match channel {
|
||||||
Channel::Out0 | Channel::Out1 => {
|
Channel::Out0 | Channel::Out1 => {
|
||||||
let channel_state = self.get_dds_channel_state(channel)?;
|
let channel_state = self.get_dds_channel_state(channel)?;
|
||||||
|
@ -399,15 +471,29 @@ where
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `channel` - The pounder channel to configure.
|
/// * `channel` - The pounder channel to configure.
|
||||||
/// * `state` - The state to configure the channel for.
|
/// * `state` - The state to configure the channel for.
|
||||||
pub fn set_channel_state(&mut self, channel: Channel, state: ChannelState) -> Result<(), Error> {
|
pub fn set_channel_state(
|
||||||
self.ad9959.set_frequency(channel.into(), state.parameters.frequency).map_err(|_| Error::Dds)?;
|
&mut self,
|
||||||
self.ad9959.set_phase(channel.into(), state.parameters.phase_offset).map_err(|_| Error::Dds)?;
|
channel: Channel,
|
||||||
self.ad9959.set_amplitude(channel.into(), state.parameters.amplitude).map_err(|_| Error::Dds)?;
|
state: ChannelState,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.ad9959
|
||||||
|
.set_frequency(channel.into(), state.parameters.frequency)
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
self.ad9959
|
||||||
|
.set_phase(channel.into(), state.parameters.phase_offset)
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
self.ad9959
|
||||||
|
.set_amplitude(channel.into(), state.parameters.amplitude)
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
|
|
||||||
if state.parameters.enabled {
|
if state.parameters.enabled {
|
||||||
self.ad9959.enable_channel(channel.into()).map_err(|_| Error::Dds)?;
|
self.ad9959
|
||||||
|
.enable_channel(channel.into())
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
} else {
|
} else {
|
||||||
self.ad9959.disable_channel(channel.into()).map_err(|_| Error::Dds)?;
|
self.ad9959
|
||||||
|
.disable_channel(channel.into())
|
||||||
|
.map_err(|_| Error::Dds)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_attenuation(channel, state.attenuation)?;
|
self.set_attenuation(channel, state.attenuation)?;
|
||||||
|
@ -416,14 +502,17 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
|
impl<DELAY> AttenuatorInterface for PounderDevices<DELAY> {
|
||||||
{
|
|
||||||
/// Reset all of the attenuators to a power-on default state.
|
/// Reset all of the attenuators to a power-on default state.
|
||||||
fn reset_attenuators(&mut self) -> Result<(), Error> {
|
fn reset_attenuators(&mut self) -> Result<(), Error> {
|
||||||
self.mcp23017.digital_write(ATT_RST_N_PIN, false).map_err(|_| Error::I2c)?;
|
self.mcp23017
|
||||||
|
.digital_write(ATT_RST_N_PIN, false)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
// TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is
|
// TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is
|
||||||
// sufficient. Document the delay here.
|
// sufficient. Document the delay here.
|
||||||
self.mcp23017.digital_write(ATT_RST_N_PIN, true).map_err(|_| Error::I2c)?;
|
self.mcp23017
|
||||||
|
.digital_write(ATT_RST_N_PIN, true)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -440,10 +529,14 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
|
||||||
Channel::Out1 => ATT_LE3_PIN,
|
Channel::Out1 => ATT_LE3_PIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.mcp23017.digital_write(pin, true).map_err(|_| Error::I2c)?;
|
self.mcp23017
|
||||||
|
.digital_write(pin, true)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
// TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is
|
// TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is
|
||||||
// sufficient. Document the delay here.
|
// sufficient. Document the delay here.
|
||||||
self.mcp23017.digital_write(pin, false).map_err(|_| Error::I2c)?;
|
self.mcp23017
|
||||||
|
.digital_write(pin, false)
|
||||||
|
.map_err(|_| Error::I2c)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -452,8 +545,13 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
|
||||||
///
|
///
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `channels` - A slice to store the channel readings into.
|
/// * `channels` - A slice to store the channel readings into.
|
||||||
fn read_all_attenuators(&mut self, channels: &mut [u8; 4]) -> Result<(), Error> {
|
fn read_all_attenuators(
|
||||||
self.attenuator_spi.transfer(channels).map_err(|_| Error::Spi)?;
|
&mut self,
|
||||||
|
channels: &mut [u8; 4],
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.attenuator_spi
|
||||||
|
.transfer(channels)
|
||||||
|
.map_err(|_| Error::Spi)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -462,10 +560,15 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
|
||||||
///
|
///
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `channels` - The data to write into the attenuators.
|
/// * `channels` - The data to write into the attenuators.
|
||||||
fn write_all_attenuators(&mut self, channels: &[u8; 4]) -> Result<(), Error> {
|
fn write_all_attenuators(
|
||||||
|
&mut self,
|
||||||
|
channels: &[u8; 4],
|
||||||
|
) -> Result<(), Error> {
|
||||||
let mut result = [0_u8; 4];
|
let mut result = [0_u8; 4];
|
||||||
result.clone_from_slice(channels);
|
result.clone_from_slice(channels);
|
||||||
self.attenuator_spi.transfer(&mut result).map_err(|_| Error::Spi)?;
|
self.attenuator_spi
|
||||||
|
.transfer(&mut result)
|
||||||
|
.map_err(|_| Error::Spi)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -482,13 +585,19 @@ impl<DELAY> PowerMeasurementInterface for PounderDevices<DELAY> {
|
||||||
fn sample_converter(&mut self, channel: Channel) -> Result<f32, Error> {
|
fn sample_converter(&mut self, channel: Channel) -> Result<f32, Error> {
|
||||||
let adc_scale = match channel {
|
let adc_scale = match channel {
|
||||||
Channel::In0 => {
|
Channel::In0 => {
|
||||||
let adc_reading: u32 = self.adc1.read(&mut self.adc1_in_p).map_err(|_| Error::Adc)?;
|
let adc_reading: u32 = self
|
||||||
|
.adc1
|
||||||
|
.read(&mut self.adc1_in_p)
|
||||||
|
.map_err(|_| Error::Adc)?;
|
||||||
adc_reading as f32 / self.adc1.max_sample() as f32
|
adc_reading as f32 / self.adc1.max_sample() as f32
|
||||||
},
|
}
|
||||||
Channel::In1 => {
|
Channel::In1 => {
|
||||||
let adc_reading: u32 = self.adc2.read(&mut self.adc2_in_p).map_err(|_| Error::Adc)?;
|
let adc_reading: u32 = self
|
||||||
|
.adc2
|
||||||
|
.read(&mut self.adc2_in_p)
|
||||||
|
.map_err(|_| Error::Adc)?;
|
||||||
adc_reading as f32 / self.adc2.max_sample() as f32
|
adc_reading as f32 / self.adc2.max_sample() as f32
|
||||||
},
|
}
|
||||||
_ => return Err(Error::InvalidChannel),
|
_ => return Err(Error::InvalidChannel),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{Error, Channel};
|
use super::{Channel, Error};
|
||||||
|
|
||||||
/// Provide an interface to measure RF input power in dB.
|
/// Provide an interface to measure RF input power in dB.
|
||||||
pub trait PowerMeasurementInterface {
|
pub trait PowerMeasurementInterface {
|
|
@ -1,24 +1,13 @@
|
||||||
use heapless::{
|
use heapless::{consts::*, String, Vec};
|
||||||
consts::*,
|
|
||||||
String,
|
|
||||||
Vec
|
|
||||||
};
|
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use serde::{
|
use serde_json_core::{de::from_slice, ser::to_string};
|
||||||
Deserialize,
|
|
||||||
Serialize
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde_json_core::{
|
|
||||||
de::from_slice,
|
|
||||||
ser::to_string
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::net;
|
|
||||||
use super::iir;
|
use super::iir;
|
||||||
|
use super::net;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub enum AccessRequest {
|
pub enum AccessRequest {
|
||||||
|
@ -62,7 +51,6 @@ impl<'a> Request<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
|
|
||||||
/// Remove all double quotation marks from the `value` field of a response.
|
/// Remove all double quotation marks from the `value` field of a response.
|
||||||
fn sanitize_value(&mut self) {
|
fn sanitize_value(&mut self) {
|
||||||
let mut new_value: String<U256> = String::new();
|
let mut new_value: String<U256> = String::new();
|
||||||
|
@ -101,9 +89,12 @@ impl Response {
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `attrbute` - The attribute of the success.
|
/// * `attrbute` - The attribute of the success.
|
||||||
/// * `value` - The value of the attribute.
|
/// * `value` - The value of the attribute.
|
||||||
pub fn success<'a, 'b>(attribute: &'a str, value: &'b str) -> Self
|
pub fn success<'a, 'b>(attribute: &'a str, value: &'b str) -> Self {
|
||||||
{
|
let mut res = Self {
|
||||||
let mut res = Self { code: 200, attribute: String::from(attribute), value: String::from(value)};
|
code: 200,
|
||||||
|
attribute: String::from(attribute),
|
||||||
|
value: String::from(value),
|
||||||
|
};
|
||||||
res.sanitize_value();
|
res.sanitize_value();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -115,9 +106,12 @@ impl Response {
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `attrbute` - The attribute of the success.
|
/// * `attrbute` - The attribute of the success.
|
||||||
/// * `message` - The message denoting the error.
|
/// * `message` - The message denoting the error.
|
||||||
pub fn error<'a, 'b>(attribute: &'a str, message: &'b str) -> Self
|
pub fn error<'a, 'b>(attribute: &'a str, message: &'b str) -> Self {
|
||||||
{
|
let mut res = Self {
|
||||||
let mut res = Self { code: 400, attribute: String::from(attribute), value: String::from(message)};
|
code: 400,
|
||||||
|
attribute: String::from(attribute),
|
||||||
|
value: String::from(message),
|
||||||
|
};
|
||||||
res.wrap_and_sanitize_value();
|
res.wrap_and_sanitize_value();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -129,9 +123,12 @@ impl Response {
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `attrbute` - The attribute of the success.
|
/// * `attrbute` - The attribute of the success.
|
||||||
/// * `message` - The message denoting the status.
|
/// * `message` - The message denoting the status.
|
||||||
pub fn custom<'a>(code: i32, message : &'a str) -> Self
|
pub fn custom<'a>(code: i32, message: &'a str) -> Self {
|
||||||
{
|
let mut res = Self {
|
||||||
let mut res = Self { code: code, attribute: String::from(""), value: String::from(message)};
|
code: code,
|
||||||
|
attribute: String::from(""),
|
||||||
|
value: String::from(message),
|
||||||
|
};
|
||||||
res.wrap_and_sanitize_value();
|
res.wrap_and_sanitize_value();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -171,16 +168,13 @@ impl Server {
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `socket` - The socket to check contents from.
|
/// * `socket` - The socket to check contents from.
|
||||||
/// * `f` - A closure that can be called if a request has been received on the server.
|
/// * `f` - A closure that can be called if a request has been received on the server.
|
||||||
pub fn poll<F>(
|
pub fn poll<F>(&mut self, socket: &mut net::socket::TcpSocket, mut f: F)
|
||||||
&mut self,
|
|
||||||
socket: &mut net::socket::TcpSocket,
|
|
||||||
mut f: F,
|
|
||||||
)
|
|
||||||
where
|
where
|
||||||
F: FnMut(&Request) -> Response
|
F: FnMut(&Request) -> Response,
|
||||||
{
|
{
|
||||||
while socket.can_recv() {
|
while socket.can_recv() {
|
||||||
let found = socket.recv(|buf| {
|
let found = socket
|
||||||
|
.recv(|buf| {
|
||||||
let (len, found) =
|
let (len, found) =
|
||||||
match buf.iter().position(|&c| c as char == '\n') {
|
match buf.iter().position(|&c| c as char == '\n') {
|
||||||
Some(end) => (end + 1, true),
|
Some(end) => (end + 1, true),
|
||||||
|
@ -193,14 +187,20 @@ impl Server {
|
||||||
self.data.extend_from_slice(&buf[..len]).unwrap();
|
self.data.extend_from_slice(&buf[..len]).unwrap();
|
||||||
}
|
}
|
||||||
(len, found)
|
(len, found)
|
||||||
}).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if found {
|
if found {
|
||||||
if self.discard {
|
if self.discard {
|
||||||
self.discard = false;
|
self.discard = false;
|
||||||
json_reply(socket, &Response::custom(520, "command buffer overflow"));
|
json_reply(
|
||||||
|
socket,
|
||||||
|
&Response::custom(520, "command buffer overflow"),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let r = from_slice::<Request>(&self.data[..self.data.len() - 1]);
|
let r = from_slice::<Request>(
|
||||||
|
&self.data[..self.data.len() - 1],
|
||||||
|
);
|
||||||
match r {
|
match r {
|
||||||
Ok(mut res) => {
|
Ok(mut res) => {
|
||||||
// Note that serde_json_core doesn't escape quotations within a string.
|
// Note that serde_json_core doesn't escape quotations within a string.
|
||||||
|
@ -210,10 +210,13 @@ impl Server {
|
||||||
res.restore_value();
|
res.restore_value();
|
||||||
let response = f(&res);
|
let response = f(&res);
|
||||||
json_reply(socket, &response);
|
json_reply(socket, &response);
|
||||||
},
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("parse error {:?}", err);
|
warn!("parse error {:?}", err);
|
||||||
json_reply(socket, &Response::custom(550, "parse error"));
|
json_reply(
|
||||||
|
socket,
|
||||||
|
&Response::custom(550, "parse error"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,4 +225,3 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,583 +0,0 @@
|
||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
[[package]]
|
|
||||||
name = "ad9959"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "git+https://github.com/quartiq/ad9959.git?branch=feature/basic-driver#b45bce3f0dd7a58b5a272b778001dc9422c2c160"
|
|
||||||
dependencies = [
|
|
||||||
"bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aligned"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aligned"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"as-slice 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "as-slice"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "asm-delay"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"bitrate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bare-metal"
|
|
||||||
version = "0.2.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bit_field"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitrate"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.3.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cast"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "0.1.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m"
|
|
||||||
version = "0.5.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"aligned 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m"
|
|
||||||
version = "0.6.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m-log"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m-rt"
|
|
||||||
version = "0.6.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m-rt-macros 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m-rt-macros"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m-rtfm"
|
|
||||||
version = "0.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rt 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rtfm-macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"heapless 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rtfm-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m-rtfm-macros"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rtfm-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cortex-m-semihosting"
|
|
||||||
version = "0.3.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embedded-hal"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "enum-iterator"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"enum-iterator-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "enum-iterator-derive"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.12.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.13.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hash32"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heapless"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"as-slice 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"hash32 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indexmap"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "managed"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mcp23017"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "git+https://github.com/mrd0ll4r/mcp23017.git#a3d072754abca60a92ece820f7cfb767a0c11669"
|
|
||||||
dependencies = [
|
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nb"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "panic-halt"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "panic-semihosting"
|
|
||||||
version = "0.5.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste"
|
|
||||||
version = "0.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"paste-impl 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste-impl"
|
|
||||||
version = "0.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-hack"
|
|
||||||
version = "0.5.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "r0"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rtfm-core"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rtfm-syntax"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"indexmap 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc_version"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver-parser"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.111"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde-json-core"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"heapless 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.111"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smoltcp"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stabilizer"
|
|
||||||
version = "0.3.0"
|
|
||||||
dependencies = [
|
|
||||||
"ad9959 0.1.0 (git+https://github.com/quartiq/ad9959.git?branch=feature/basic-driver)",
|
|
||||||
"asm-delay 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-log 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rt 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rtfm 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"enum-iterator 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"heapless 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"mcp23017 0.1.1 (git+https://github.com/mrd0ll4r/mcp23017.git)",
|
|
||||||
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"panic-semihosting 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde-json-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"stm32h7-ethernet 0.1.1 (git+https://github.com/quartiq/stm32h7-ethernet.git)",
|
|
||||||
"stm32h7xx-hal 0.5.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stable_deref_trait"
|
|
||||||
version = "1.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stm32h7"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rt 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stm32h7-ethernet"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "git+https://github.com/quartiq/stm32h7-ethernet.git#cf9b8bb2e1b440d8ada6ac6048f48dc4ed9c269a"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"stm32h7xx-hal 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stm32h7xx-hal"
|
|
||||||
version = "0.5.0"
|
|
||||||
dependencies = [
|
|
||||||
"bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rt 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"paste 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"stm32h7 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stm32h7xx-hal"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cortex-m-rt 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"paste 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"stm32h7 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typenum"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vcell"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "void"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "volatile-register"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
"checksum ad9959 0.1.0 (git+https://github.com/quartiq/ad9959.git?branch=feature/basic-driver)" = "<none>"
|
|
||||||
"checksum aligned 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d39da9b88ae1a81c03c9c082b8db83f1d0e93914126041962af61034ab44c4a5"
|
|
||||||
"checksum aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94"
|
|
||||||
"checksum as-slice 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37dfb65bc03b2bc85ee827004f14a6817e04160e3b1a28931986a666a9290e70"
|
|
||||||
"checksum asm-delay 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e0c8eec73de29ae94b2aff405a272304bc286204ddb1cdf20d7e2249078ae20"
|
|
||||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
|
||||||
"checksum bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
|
||||||
"checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0"
|
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|
||||||
"checksum bitrate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c147d86912d04bef727828fda769a76ca81629a46d8ba311a8d58a26aa91473d"
|
|
||||||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
|
||||||
"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
|
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|
||||||
"checksum cortex-m 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0b159a1e8306949579de3698c841dba58058197b65c60807194e4fa1e7a554"
|
|
||||||
"checksum cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2954942fbbdd49996704e6f048ce57567c3e1a4e2dc59b41ae9fde06a01fc763"
|
|
||||||
"checksum cortex-m-log 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "978caafe65d1023d38b00c76b83564788fc351d954a5005fb72cf992c0d61458"
|
|
||||||
"checksum cortex-m-rt 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "00d518da72bba39496024b62607c1d8e37bcece44b2536664f1132a73a499a28"
|
|
||||||
"checksum cortex-m-rt-macros 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4717562afbba06e760d34451919f5c3bf3ac15c7bb897e8b04862a7428378647"
|
|
||||||
"checksum cortex-m-rtfm 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf0b9fd3f042cb3793d15daf3cea201b2f25c99b0b5b936a551bb6909c3ae5b"
|
|
||||||
"checksum cortex-m-rtfm-macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c62092f6ff344e9b0adb748f0302ed69889ba2fae1fce446e3788d4726ea73bb"
|
|
||||||
"checksum cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "113ef0ecffee2b62b58f9380f4469099b30e9f9cbee2804771b4203ba1762cfa"
|
|
||||||
"checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b"
|
|
||||||
"checksum enum-iterator 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7"
|
|
||||||
"checksum enum-iterator-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
|
|
||||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
|
||||||
"checksum generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
|
|
||||||
"checksum hash32 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
|
|
||||||
"checksum heapless 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "73a8a2391a3bc70b31f60e7a90daa5755a360559c0b6b9c5cfc0fee482362dc0"
|
|
||||||
"checksum indexmap 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
|
|
||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
|
||||||
"checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6"
|
|
||||||
"checksum mcp23017 0.1.1 (git+https://github.com/mrd0ll4r/mcp23017.git)" = "<none>"
|
|
||||||
"checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc"
|
|
||||||
"checksum panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
|
||||||
"checksum panic-semihosting 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c03864ac862876c16a308f5286f4aa217f1a69ac45df87ad3cd2847f818a642c"
|
|
||||||
"checksum paste 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "d508492eeb1e5c38ee696371bf7b9fc33c83d46a7d451606b96458fbbbdc2dec"
|
|
||||||
"checksum paste-impl 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "84f328a6a63192b333fce5fbb4be79db6758a4d518dfac6d54412f1492f72d32"
|
|
||||||
"checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
|
|
||||||
"checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
|
|
||||||
"checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
|
|
||||||
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
|
|
||||||
"checksum rtfm-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec893edb2aa5b70320b94896ffea22a7ebb1cf3f942bb67cd5b60a865a63493"
|
|
||||||
"checksum rtfm-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4455e23c34df3d66454e7e218a4d76a7f83321d04a806be614463341cec4116e"
|
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
|
||||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
|
||||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|
||||||
"checksum serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
|
|
||||||
"checksum serde-json-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf406405ada9ef326ca78677324ac66994ff348fc48a16030be08caeed29825"
|
|
||||||
"checksum serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
|
|
||||||
"checksum smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a"
|
|
||||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
|
||||||
"checksum stm32h7 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9beb5e2a223c82f263c3051bba4614aebc6e98bd40217df3cd8817c83ac7bd8"
|
|
||||||
"checksum stm32h7-ethernet 0.1.1 (git+https://github.com/quartiq/stm32h7-ethernet.git)" = "<none>"
|
|
||||||
"checksum stm32h7xx-hal 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "987c66628f30012ed9a41cc738421c5caece03292c0cc8fd1e99956f122735bd"
|
|
||||||
"checksum syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
|
|
||||||
"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
|
||||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
|
||||||
"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|
||||||
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
|
|
@ -1,67 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "stabilizer"
|
|
||||||
version = "0.3.0"
|
|
||||||
authors = ["Robert Jördens <rj@quartiq.de>"]
|
|
||||||
description = "Firmware for the Sinara Stabilizer board (stm32h743, eth, poe, 2 adc, 2 dac)"
|
|
||||||
categories = ["embedded", "no-std", "hardware-support", "science"]
|
|
||||||
license = "GPL-3.0-or-later"
|
|
||||||
keywords = ["ethernet", "stm32h7", "adc", "dac", "physics"]
|
|
||||||
repository = "https://github.com/quartiq/stabilizer"
|
|
||||||
readme = "README.md"
|
|
||||||
documentation = "https://docs.rs/stabilizer/"
|
|
||||||
edition = "2018"
|
|
||||||
exclude = [
|
|
||||||
".travis.yml",
|
|
||||||
".gitignore",
|
|
||||||
"doc/",
|
|
||||||
"doc/*"
|
|
||||||
]
|
|
||||||
|
|
||||||
[badges]
|
|
||||||
travis-ci = { repository = "quartiq/stabilizer", branch = "master" }
|
|
||||||
maintenance = { status = "experimental" }
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = []
|
|
||||||
default-target = "thumbv7em-none-eabihf"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cortex-m = { version = "0.6", features = ["const-fn"] }
|
|
||||||
cortex-m-rt = { version = "0.6", features = ["device"] }
|
|
||||||
cortex-m-log = { version = "0.6", features = ["log-integration"] }
|
|
||||||
log = "0.4"
|
|
||||||
panic-semihosting = { version = "0.5", optional = true }
|
|
||||||
panic-halt = "0.2"
|
|
||||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
|
||||||
heapless = { version = "0.5", features = ["serde"] }
|
|
||||||
serde-json-core = "0.1"
|
|
||||||
cortex-m-rtfm = "0.5"
|
|
||||||
embedded-hal = "0.2.3"
|
|
||||||
nb = "0.1.2"
|
|
||||||
asm-delay = "0.7.0"
|
|
||||||
enum-iterator = "0.6.0"
|
|
||||||
|
|
||||||
[dependencies.mcp23017]
|
|
||||||
git = "https://github.com/mrd0ll4r/mcp23017.git"
|
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
|
||||||
version = "0.6"
|
|
||||||
features = ["ethernet", "proto-ipv4", "socket-tcp", "proto-ipv6"]
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.ad9959]
|
|
||||||
path = "../ad9959"
|
|
||||||
|
|
||||||
[dependencies.stm32h7-ethernet]
|
|
||||||
git = "https://github.com/quartiq/stm32h7-ethernet.git"
|
|
||||||
features = ["stm32h743v"]
|
|
||||||
|
|
||||||
[dependencies.stm32h7xx-hal]
|
|
||||||
path = "../stm32h7xx-hal/"
|
|
||||||
features = ["stm32h743v", "rt", "unproven"]
|
|
||||||
|
|
||||||
[features]
|
|
||||||
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
|
||||||
bkpt = [ ]
|
|
||||||
nightly = ["cortex-m/inline-asm"]
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit ff00e938f2b226211c178f26c092f36462c44404
|
|
Loading…
Reference in New Issue