Compare commits
2 Commits
43ccb86697
...
82867178f9
Author | SHA1 | Date |
---|---|---|
occheung | 82867178f9 | |
occheung | f94528ae2a |
|
@ -7,7 +7,6 @@ use core::sync::atomic::{AtomicU32, Ordering};
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use cortex_m;
|
use cortex_m;
|
||||||
use cortex_m::asm::nop;
|
|
||||||
use cortex_m_rt::{
|
use cortex_m_rt::{
|
||||||
entry,
|
entry,
|
||||||
exception,
|
exception,
|
||||||
|
@ -15,14 +14,9 @@ use cortex_m_rt::{
|
||||||
extern crate smoltcp;
|
extern crate smoltcp;
|
||||||
|
|
||||||
use stm32h7xx_hal::ethernet;
|
use stm32h7xx_hal::ethernet;
|
||||||
use stm32h7xx_hal::gpio::Speed;
|
use stm32h7xx_hal::hal::digital::v2::InputPin;
|
||||||
use stm32h7xx_hal::hal::digital::v2::{
|
|
||||||
OutputPin,
|
|
||||||
InputPin,
|
|
||||||
};
|
|
||||||
use stm32h7xx_hal::rcc::CoreClocks;
|
use stm32h7xx_hal::rcc::CoreClocks;
|
||||||
use stm32h7xx_hal::{pac, prelude::*, spi, stm32, stm32::interrupt};
|
use stm32h7xx_hal::{pac, prelude::*, spi, stm32, stm32::interrupt};
|
||||||
use Speed::*;
|
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
str,
|
str,
|
||||||
|
@ -32,8 +26,8 @@ use core::mem::uninitialized;
|
||||||
|
|
||||||
// Exception: no phy::wait
|
// Exception: no phy::wait
|
||||||
//use smoltcp::phy::wait as phy_wait;
|
//use smoltcp::phy::wait as phy_wait;
|
||||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
|
use smoltcp::wire::{IpAddress, IpCidr};
|
||||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, Routes};
|
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||||
use smoltcp::socket::SocketSet;
|
use smoltcp::socket::SocketSet;
|
||||||
use smoltcp::socket::{SocketHandle, TcpSocket, TcpSocketBuffer};
|
use smoltcp::socket::{SocketHandle, TcpSocket, TcpSocketBuffer};
|
||||||
use smoltcp::time::{Duration, Instant};
|
use smoltcp::time::{Duration, Instant};
|
||||||
|
@ -44,16 +38,6 @@ use embedded_nal::TcpStack;
|
||||||
|
|
||||||
use firmware;
|
use firmware;
|
||||||
use firmware::{
|
use firmware::{
|
||||||
attenuator::Attenuator,
|
|
||||||
config_register::{
|
|
||||||
ConfigRegister,
|
|
||||||
CFGMask,
|
|
||||||
StatusMask,
|
|
||||||
},
|
|
||||||
dds::{
|
|
||||||
DDS,
|
|
||||||
DDSCFRMask,
|
|
||||||
},
|
|
||||||
cpld::{
|
cpld::{
|
||||||
CPLD,
|
CPLD,
|
||||||
},
|
},
|
||||||
|
@ -63,6 +47,10 @@ use firmware::{
|
||||||
Channel1SwitchCommand,
|
Channel1SwitchCommand,
|
||||||
Channel2SwitchCommand,
|
Channel2SwitchCommand,
|
||||||
Channel3SwitchCommand,
|
Channel3SwitchCommand,
|
||||||
|
Channel0AttenuationCommand,
|
||||||
|
Channel1AttenuationCommand,
|
||||||
|
Channel2AttenuationCommand,
|
||||||
|
Channel3AttenuationCommand,
|
||||||
ClockSourceCommand,
|
ClockSourceCommand,
|
||||||
ClockDivisionCommand,
|
ClockDivisionCommand,
|
||||||
},
|
},
|
||||||
|
@ -83,9 +71,6 @@ use scpi::{
|
||||||
ieee488_stb,
|
ieee488_stb,
|
||||||
ieee488_tst,
|
ieee488_tst,
|
||||||
ieee488_wai,
|
ieee488_wai,
|
||||||
nquery,
|
|
||||||
//Helpers
|
|
||||||
qonly,
|
|
||||||
scpi_crate_version,
|
scpi_crate_version,
|
||||||
scpi_status,
|
scpi_status,
|
||||||
scpi_system,
|
scpi_system,
|
||||||
|
@ -290,16 +275,20 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CHANNEL0" => {
|
"CHANNEL0" => {
|
||||||
"SWitch" => Channel0SwitchCommand
|
"SWitch" => Channel0SwitchCommand,
|
||||||
|
"Attenuation" => Channel0AttenuationCommand
|
||||||
},
|
},
|
||||||
"CHANNEL1" => {
|
"CHANNEL1" => {
|
||||||
"SWitch" => Channel1SwitchCommand
|
"SWitch" => Channel1SwitchCommand,
|
||||||
|
"Attenuation" => Channel1AttenuationCommand
|
||||||
},
|
},
|
||||||
"CHANNEL2" => {
|
"CHANNEL2" => {
|
||||||
"SWitch" => Channel2SwitchCommand
|
"SWitch" => Channel2SwitchCommand,
|
||||||
|
"Attenuation" => Channel2AttenuationCommand
|
||||||
},
|
},
|
||||||
"CHANNEL3" => {
|
"CHANNEL3" => {
|
||||||
"SWitch" => Channel3SwitchCommand
|
"SWitch" => Channel3SwitchCommand,
|
||||||
|
"Attenuation" => Channel3AttenuationCommand
|
||||||
},
|
},
|
||||||
"CLOCK" => {
|
"CLOCK" => {
|
||||||
"SOURCE" => ClockSourceCommand,
|
"SOURCE" => ClockSourceCommand,
|
||||||
|
@ -364,7 +353,7 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
if socket.can_recv() {
|
if socket.can_recv() {
|
||||||
let mut data = socket.recv(|buffer| {
|
let data = socket.recv(|buffer| {
|
||||||
(buffer.len(), buffer)
|
(buffer.len(), buffer)
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
if str::from_utf8(data).unwrap().trim() == "quit" {
|
if str::from_utf8(data).unwrap().trim() == "quit" {
|
||||||
|
@ -394,6 +383,7 @@ use stm32h7xx_hal::gpio::{
|
||||||
/*
|
/*
|
||||||
* Migrated ethernet setup pins
|
* Migrated ethernet setup pins
|
||||||
*/
|
*/
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
pub fn setup_ethernet_pins<REF_CLK, MDIO, MDC, CRS_DV, RXD0, RXD1, TX_EN, TXD0, TXD1>(
|
pub fn setup_ethernet_pins<REF_CLK, MDIO, MDC, CRS_DV, RXD0, RXD1, TX_EN, TXD0, TXD1>(
|
||||||
pa1: PA1<REF_CLK>, pa2: PA2<MDIO>, pc1: PC1<MDC>, pa7: PA7<CRS_DV>, pc4: PC4<RXD0>,
|
pa1: PA1<REF_CLK>, pa2: PA2<MDIO>, pc1: PC1<MDC>, pa7: PA7<CRS_DV>, pc4: PC4<RXD0>,
|
||||||
pc5: PC5<RXD1>, pg11: PG11<TX_EN>, pg13: PG13<TXD0>, pb13: PB13<TXD1>
|
pc5: PC5<RXD1>, pg11: PG11<TX_EN>, pg13: PG13<TXD0>, pb13: PB13<TXD1>
|
||||||
|
|
|
@ -40,20 +40,16 @@ where
|
||||||
}
|
}
|
||||||
let mut clone = self.data.clone();
|
let mut clone = self.data.clone();
|
||||||
// Transmit SPI once to set attenuation
|
// Transmit SPI once to set attenuation
|
||||||
match self.spi.transfer(&mut clone).map_err(Error::SPI) {
|
self.spi.transfer(&mut clone)
|
||||||
Err(e) => Err(Error::AttenuatorError),
|
.map(|_| ())
|
||||||
Ok(_) => Ok(()),
|
.map_err(|_| Error::AttenuatorError)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Error<E>> {
|
pub fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Error<E>> {
|
||||||
assert!(channel < 4);
|
assert!(channel < 4);
|
||||||
let mut arr: [f32; 4] = self.get_attenuation()?;
|
let mut arr: [f32; 4] = self.get_attenuation()?;
|
||||||
arr[channel as usize] = attenuation;
|
arr[channel as usize] = attenuation;
|
||||||
match self.set_attenuation(arr) {
|
self.set_attenuation(arr).map(|_| ())
|
||||||
Ok(v) => Ok(()),
|
|
||||||
Err(e) => Err(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_channel_attenuation(&mut self, channel: u8) -> Result<f32, Error<E>> {
|
pub fn get_channel_attenuation(&mut self, channel: u8) -> Result<f32, Error<E>> {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
macro_rules! construct_bitmask {
|
macro_rules! construct_bitmask {
|
||||||
($collection: ident; $unsigned_type: ty; $($name: ident, $shift: expr, $width: expr),+) => {
|
($collection: ident; $unsigned_type: ty; $($name: ident, $shift: expr, $width: expr),+) => {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
pub enum $collection {
|
pub enum $collection {
|
||||||
$(
|
$(
|
||||||
$name,
|
$name,
|
||||||
|
|
|
@ -213,6 +213,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
fn get_VCO_no(&mut self, f_sys_clk: u64, divider: u8) -> Result<u8, Error<E>> {
|
fn get_VCO_no(&mut self, f_sys_clk: u64, divider: u8) -> Result<u8, Error<E>> {
|
||||||
// Select a VCO
|
// Select a VCO
|
||||||
if divider == 1 {
|
if divider == 1 {
|
||||||
|
@ -387,10 +388,9 @@ macro_rules! impl_register_io {
|
||||||
for i in 0..$reg_byte_size {
|
for i in 0..$reg_byte_size {
|
||||||
arr[i+1] = bytes[i];
|
arr[i+1] = bytes[i];
|
||||||
}
|
}
|
||||||
match self.spi.transfer(&mut arr).map_err(Error::SPI) {
|
self.spi.transfer(&mut arr)
|
||||||
Ok(v) => Ok(()),
|
.map(|_| ())
|
||||||
Err(e) => Err(e),
|
.map_err(Error::SPI)
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
_ => panic!("Bad address for DDS writing.")
|
_ => panic!("Bad address for DDS writing.")
|
||||||
|
|
33
src/lib.rs
33
src/lib.rs
|
@ -153,6 +153,7 @@ pub trait UrukulTraits {
|
||||||
fn set_channel_switch(&mut self, channel: u32, status: bool) -> Result<(), Self::Error>;
|
fn set_channel_switch(&mut self, channel: u32, status: bool) -> Result<(), Self::Error>;
|
||||||
fn set_clock_source(&mut self, source: ClockSource) -> Result<(), Self::Error>;
|
fn set_clock_source(&mut self, source: ClockSource) -> Result<(), Self::Error>;
|
||||||
fn set_clock_division(&mut self, division: u8) -> Result<(), Self::Error>;
|
fn set_clock_division(&mut self, division: u8) -> Result<(), Self::Error>;
|
||||||
|
fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SPI, E> UrukulTraits for Urukul<SPI>
|
impl<SPI, E> UrukulTraits for Urukul<SPI>
|
||||||
|
@ -163,10 +164,7 @@ where
|
||||||
|
|
||||||
fn get_channel_switch_status(&mut self, channel: u32) -> Result<bool, Self::Error> {
|
fn get_channel_switch_status(&mut self, channel: u32) -> Result<bool, Self::Error> {
|
||||||
if channel < 4 {
|
if channel < 4 {
|
||||||
match self.config_register.get_status(StatusMask::RF_SW) {
|
self.config_register.get_status(StatusMask::RF_SW).map(|val| (val & (1 << channel)) != 0)
|
||||||
Ok(val) => Ok((val & (1 << channel)) != 0),
|
|
||||||
Err(_e) => Err(_e),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ParameterError)
|
Err(Error::ParameterError)
|
||||||
}
|
}
|
||||||
|
@ -182,19 +180,16 @@ where
|
||||||
prev & (!(1 << channel))
|
prev & (!(1 << channel))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match self.config_register.set_configurations(&mut [
|
self.config_register.set_configurations(&mut [
|
||||||
(CFGMask::RF_SW, next),
|
(CFGMask::RF_SW, next),
|
||||||
]) {
|
]).map(|_| ())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_e) => Err(_e),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ParameterError)
|
Err(Error::ParameterError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clock_source(&mut self, source: ClockSource) -> Result<(), Self::Error> {
|
fn set_clock_source(&mut self, source: ClockSource) -> Result<(), Self::Error> {
|
||||||
let result = match source {
|
match source {
|
||||||
ClockSource::OSC => self.config_register.set_configurations(&mut [
|
ClockSource::OSC => self.config_register.set_configurations(&mut [
|
||||||
(CFGMask::CLK_SEL0, 0),
|
(CFGMask::CLK_SEL0, 0),
|
||||||
(CFGMask::CLK_SEL1, 0),
|
(CFGMask::CLK_SEL1, 0),
|
||||||
|
@ -206,15 +201,11 @@ where
|
||||||
ClockSource::SMA => self.config_register.set_configurations(&mut [
|
ClockSource::SMA => self.config_register.set_configurations(&mut [
|
||||||
(CFGMask::CLK_SEL0, 1),
|
(CFGMask::CLK_SEL0, 1),
|
||||||
]),
|
]),
|
||||||
};
|
}.map(|_| ())
|
||||||
match result {
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_e) => Err(_e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clock_division(&mut self, division: u8) -> Result<(), Self::Error> {
|
fn set_clock_division(&mut self, division: u8) -> Result<(), Self::Error> {
|
||||||
let result = match division {
|
match division {
|
||||||
1 => self.config_register.set_configurations(&mut [
|
1 => self.config_register.set_configurations(&mut [
|
||||||
(CFGMask::DIV, 1),
|
(CFGMask::DIV, 1),
|
||||||
]),
|
]),
|
||||||
|
@ -225,10 +216,10 @@ where
|
||||||
(CFGMask::DIV, 3),
|
(CFGMask::DIV, 3),
|
||||||
]),
|
]),
|
||||||
_ => Err(Error::ParameterError),
|
_ => Err(Error::ParameterError),
|
||||||
};
|
}.map(|_| ())
|
||||||
match result {
|
}
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_e) => Err(_e),
|
fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Self::Error> {
|
||||||
}
|
self.attenuator.set_channel_attenuation(channel, attenuation)
|
||||||
}
|
}
|
||||||
}
|
}
|
30
src/main.rs
30
src/main.rs
|
@ -1,7 +1,10 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use panic_semihosting as _;
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
use log::{trace, debug, info, warn};
|
||||||
|
|
||||||
use stm32h7xx_hal::hal::digital::v2::{
|
use stm32h7xx_hal::hal::digital::v2::{
|
||||||
InputPin,
|
InputPin,
|
||||||
|
@ -11,7 +14,6 @@ use stm32h7xx_hal::{pac, prelude::*, spi};
|
||||||
|
|
||||||
use cortex_m;
|
use cortex_m;
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use cortex_m_semihosting::hprintln;
|
|
||||||
|
|
||||||
use firmware;
|
use firmware;
|
||||||
use firmware::{
|
use firmware::{
|
||||||
|
@ -30,10 +32,13 @@ use firmware::{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[path = "../examples/util/logger.rs"]
|
||||||
|
mod logger;
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
|
|
||||||
let cp = cortex_m::Peripherals::take().unwrap();
|
let mut cp = cortex_m::Peripherals::take().unwrap();
|
||||||
let dp = pac::Peripherals::take().unwrap();
|
let dp = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
let pwr = dp.PWR.constrain();
|
let pwr = dp.PWR.constrain();
|
||||||
|
@ -41,10 +46,17 @@ fn main() -> ! {
|
||||||
|
|
||||||
let rcc = dp.RCC.constrain();
|
let rcc = dp.RCC.constrain();
|
||||||
let ccdr = rcc
|
let ccdr = rcc
|
||||||
|
.use_hse(8.mhz())
|
||||||
.sys_ck(400.mhz())
|
.sys_ck(400.mhz())
|
||||||
.pll1_q_ck(48.mhz())
|
.pll1_q_ck(48.mhz())
|
||||||
|
.pll1_r_ck(400.mhz())
|
||||||
.freeze(vos, &dp.SYSCFG);
|
.freeze(vos, &dp.SYSCFG);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
logger::enable_itm(&dp.DBGMCU, &mut cp.DCB, &mut cp.ITM);
|
||||||
|
}
|
||||||
|
logger::init();
|
||||||
|
|
||||||
let mut delay = cp.SYST.delay(ccdr.clocks);
|
let mut delay = cp.SYST.delay(ccdr.clocks);
|
||||||
|
|
||||||
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
|
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
|
||||||
|
@ -58,10 +70,10 @@ fn main() -> ! {
|
||||||
let fpga_cdone = gpiod.pd15.into_pull_up_input();
|
let fpga_cdone = gpiod.pd15.into_pull_up_input();
|
||||||
|
|
||||||
match fpga_cdone.is_high() {
|
match fpga_cdone.is_high() {
|
||||||
Ok(true) => hprintln!("FPGA is ready."),
|
Ok(true) => info!("FPGA is ready."),
|
||||||
Ok(_) => hprintln!("FPGA is in reset state."),
|
Ok(_) => info!("FPGA is in reset state."),
|
||||||
Err(_) => hprintln!("Error: Cannot read C_DONE"),
|
Err(_) => info!("Error: Cannot read C_DONE"),
|
||||||
}.unwrap();
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Using SPI1, AF5
|
* Using SPI1, AF5
|
||||||
|
@ -150,10 +162,10 @@ fn main() -> ! {
|
||||||
0x04, // Recirculate mode
|
0x04, // Recirculate mode
|
||||||
]).unwrap();
|
]).unwrap();
|
||||||
|
|
||||||
hprintln!("{:#X?}", dds0.read_register(0x0E, &mut[
|
debug!("{:#X?}", dds0.read_register(0x0E, &mut[
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
]).unwrap()).unwrap();
|
]).unwrap());
|
||||||
|
|
||||||
// Choose profile 0
|
// Choose profile 0
|
||||||
config.set_configurations(&mut [
|
config.set_configurations(&mut [
|
||||||
|
|
|
@ -60,15 +60,10 @@ impl<'a, 'b, 'c, 'n> NetworkStack<'a, 'b, 'c, 'n> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, time: u32) -> bool {
|
pub fn update(&mut self, time: u32) -> bool {
|
||||||
match self.network_interface.poll(
|
self.network_interface.poll(
|
||||||
&mut self.sockets.borrow_mut(),
|
&mut self.sockets.borrow_mut(),
|
||||||
net::time::Instant::from_millis(time as i64),
|
net::time::Instant::from_millis(time as i64),
|
||||||
) {
|
).map_or(true, |changed| changed == false)
|
||||||
Ok(changed) => changed == false,
|
|
||||||
Err(e) => {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ephemeral_port(&self) -> u16 {
|
fn get_ephemeral_port(&self) -> u16 {
|
||||||
|
|
86
src/scpi.rs
86
src/scpi.rs
|
@ -7,26 +7,9 @@ use scpi::NumericValues;
|
||||||
|
|
||||||
use core::convert::{TryFrom, TryInto};
|
use core::convert::{TryFrom, TryInto};
|
||||||
use core::str;
|
use core::str;
|
||||||
use core::str::Utf8Error;
|
|
||||||
use scpi::ieee488::commands::*;
|
|
||||||
use scpi::scpi::commands::*;
|
|
||||||
use scpi::{
|
use scpi::{
|
||||||
ieee488_cls,
|
|
||||||
ieee488_ese,
|
|
||||||
ieee488_esr,
|
|
||||||
ieee488_idn,
|
|
||||||
ieee488_opc,
|
|
||||||
ieee488_rst,
|
|
||||||
ieee488_sre,
|
|
||||||
ieee488_stb,
|
|
||||||
ieee488_tst,
|
|
||||||
ieee488_wai,
|
|
||||||
nquery,
|
nquery,
|
||||||
//Helpers
|
|
||||||
qonly,
|
qonly,
|
||||||
scpi_crate_version,
|
|
||||||
scpi_status,
|
|
||||||
scpi_system,
|
|
||||||
};
|
};
|
||||||
use scpi::suffix::{Amplitude, Db};
|
use scpi::suffix::{Amplitude, Db};
|
||||||
use uom::si::frequency::{gigahertz, hertz, kilohertz, megahertz, Frequency};
|
use uom::si::frequency::{gigahertz, hertz, kilohertz, megahertz, Frequency};
|
||||||
|
@ -147,6 +130,10 @@ pub struct Channel2SwitchCommand {}
|
||||||
pub struct Channel3SwitchCommand {}
|
pub struct Channel3SwitchCommand {}
|
||||||
pub struct ClockSourceCommand {}
|
pub struct ClockSourceCommand {}
|
||||||
pub struct ClockDivisionCommand {}
|
pub struct ClockDivisionCommand {}
|
||||||
|
pub struct Channel0AttenuationCommand {}
|
||||||
|
pub struct Channel1AttenuationCommand {}
|
||||||
|
pub struct Channel2AttenuationCommand {}
|
||||||
|
pub struct Channel3AttenuationCommand {}
|
||||||
|
|
||||||
impl<T: Device + UrukulTraits> Command<T> for Channel0SwitchCommand {
|
impl<T: Device + UrukulTraits> Command<T> for Channel0SwitchCommand {
|
||||||
nquery!();
|
nquery!();
|
||||||
|
@ -270,17 +257,68 @@ impl<T:Device + UrukulTraits> Command<T> for ClockDivisionCommand {
|
||||||
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
||||||
|token| token.try_into())?;
|
|token| token.try_into())?;
|
||||||
trace!("Received master clock division factor: {}", div);
|
trace!("Received master clock division factor: {}", div);
|
||||||
match div {
|
if div == 1.0 || div == 2.0 || div == 4.0 {
|
||||||
1.0 | 2.0 | 4.0 => {
|
debug!("Set master clock division as {}", div);
|
||||||
debug!("Set master clock division as {}", div);
|
context.device.set_clock_division(div as u8)
|
||||||
context.device.set_clock_division(div as u8)
|
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
||||||
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
} else {
|
||||||
}
|
Err(Error::new(ErrorCode::IllegalParameterValue))
|
||||||
_ => Err(Error::new(ErrorCode::IllegalParameterValue)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T:Device + UrukulTraits> Command<T> for Channel0AttenuationCommand {
|
||||||
|
nquery!();
|
||||||
|
|
||||||
|
fn event(&self, context: &mut Context<T>, args: &mut Tokenizer) -> Result<()> {
|
||||||
|
let attenuation: f32 = args.next_data(false)?
|
||||||
|
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
||||||
|
|token| token.try_into())?;
|
||||||
|
trace!("Received channel 0 attenuation input: {}", attenuation);
|
||||||
|
context.device.set_channel_attenuation(0, attenuation)
|
||||||
|
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:Device + UrukulTraits> Command<T> for Channel1AttenuationCommand {
|
||||||
|
nquery!();
|
||||||
|
|
||||||
|
fn event(&self, context: &mut Context<T>, args: &mut Tokenizer) -> Result<()> {
|
||||||
|
let attenuation: f32 = args.next_data(false)?
|
||||||
|
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
||||||
|
|token| token.try_into())?;
|
||||||
|
trace!("Received channel 1 attenuation input: {}", attenuation);
|
||||||
|
context.device.set_channel_attenuation(1, attenuation)
|
||||||
|
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:Device + UrukulTraits> Command<T> for Channel2AttenuationCommand {
|
||||||
|
nquery!();
|
||||||
|
|
||||||
|
fn event(&self, context: &mut Context<T>, args: &mut Tokenizer) -> Result<()> {
|
||||||
|
let attenuation: f32 = args.next_data(false)?
|
||||||
|
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
||||||
|
|token| token.try_into())?;
|
||||||
|
trace!("Received channel 2 attenuation input: {}", attenuation);
|
||||||
|
context.device.set_channel_attenuation(2, attenuation)
|
||||||
|
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:Device + UrukulTraits> Command<T> for Channel3AttenuationCommand {
|
||||||
|
nquery!();
|
||||||
|
|
||||||
|
fn event(&self, context: &mut Context<T>, args: &mut Tokenizer) -> Result<()> {
|
||||||
|
let attenuation: f32 = args.next_data(false)?
|
||||||
|
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
||||||
|
|token| token.try_into())?;
|
||||||
|
trace!("Received channel 3 attenuation input: {}", attenuation);
|
||||||
|
context.device.set_channel_attenuation(3, attenuation)
|
||||||
|
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implement "Device" trait from SCPI
|
* Implement "Device" trait from SCPI
|
||||||
* TODO: Implement mandatory commands
|
* TODO: Implement mandatory commands
|
||||||
|
|
|
@ -51,13 +51,13 @@ where
|
||||||
|
|
||||||
fn transfer<'w>(&mut self, words: &'w mut[u8]) -> Result<&'w [u8], Self::Error> {
|
fn transfer<'w>(&mut self, words: &'w mut[u8]) -> Result<&'w [u8], Self::Error> {
|
||||||
self.0.do_on_get_ref_mut_data(move |mut dev| {
|
self.0.do_on_get_ref_mut_data(move |mut dev| {
|
||||||
dev.select_chip(self.1);
|
dev.select_chip(self.1).map_err(|_| Error::CSError)?;
|
||||||
let result = dev.spi.transfer(words).map_err(Error::SPI);
|
let result = dev.spi.transfer(words).map_err(Error::SPI)?;
|
||||||
dev.select_chip(0);
|
dev.select_chip(0).map_err(|_| Error::CSError)?;
|
||||||
if self.2 {
|
if self.2 {
|
||||||
dev.issue_io_update();
|
dev.issue_io_update().map_err(|_| Error::IOUpdateError)?;
|
||||||
}
|
}
|
||||||
result
|
Ok(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue