forked from M-Labs/humpback-dds
mqtt_mux: add cmd
This commit is contained in:
parent
d47f9b4655
commit
9ea56ebde5
35
src/lib.rs
35
src/lib.rs
|
@ -176,7 +176,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn set_clock_source(&mut self, source: ClockSource, frequency: f64) -> Result<(), Error<E>> {
|
||||
fn set_clock(&mut self, source: ClockSource, frequency: f64, division: u8) -> Result<(), Error<E>> {
|
||||
// Change clock source through configuration register
|
||||
self.set_clock_source(source)?;
|
||||
|
||||
// Modify the master clock frequency
|
||||
// Prevent redundunt call to change f_ref_clk
|
||||
self.f_master_clk = frequency;
|
||||
|
||||
self.set_clock_division(division)
|
||||
}
|
||||
|
||||
fn set_clock_source(&mut self, source: ClockSource) -> Result<(), Error<E>> {
|
||||
// Change clock source through configuration register
|
||||
match source {
|
||||
ClockSource::OSC => self.config_register.set_configurations(&mut [
|
||||
|
@ -190,19 +201,15 @@ where
|
|||
ClockSource::SMA => self.config_register.set_configurations(&mut [
|
||||
(CFGMask::CLK_SEL0, 1),
|
||||
]),
|
||||
}?;
|
||||
}.map(|_| ())
|
||||
}
|
||||
|
||||
// Save the new master clock frequency
|
||||
fn set_clock_frequency(&mut self, frequency: f64) -> Result<(), Error<E>> {
|
||||
// Update master clock frequency
|
||||
self.f_master_clk = frequency;
|
||||
|
||||
// Calculate reference clock frequency after clock division from configuration register
|
||||
let f_ref_clk = self.f_master_clk / (self.config_register.get_configuration(CFGMask::DIV) as f64);
|
||||
|
||||
// Update all DDS chips on reference clock frequency
|
||||
for dds_channel in 0..4 {
|
||||
self.dds[dds_channel].set_ref_clk_frequency(f_ref_clk)?;
|
||||
}
|
||||
Ok(())
|
||||
// Update all DDS f_ref_clk
|
||||
self.set_dds_ref_clk()
|
||||
}
|
||||
|
||||
fn set_clock_division(&mut self, division: u8) -> Result<(), Error<E>> {
|
||||
|
@ -219,8 +226,12 @@ where
|
|||
_ => Err(Error::ParameterError),
|
||||
}?;
|
||||
|
||||
self.set_dds_ref_clk()
|
||||
}
|
||||
|
||||
fn set_dds_ref_clk(&mut self) -> Result<(), Error<E>> {
|
||||
// Calculate reference clock frequency after clock division from configuration register
|
||||
let f_ref_clk = self.f_master_clk / (division as f64);
|
||||
let f_ref_clk = self.f_master_clk / (self.config_register.get_configuration(CFGMask::DIV) as f64);
|
||||
|
||||
// Update all DDS chips on reference clock frequency
|
||||
for dds_channel in 0..4 {
|
||||
|
|
254
src/mqtt_mux.rs
254
src/mqtt_mux.rs
|
@ -22,6 +22,11 @@ use crate::Error;
|
|||
pub enum MqttTopic {
|
||||
Switch(u8),
|
||||
Attenuation(u8),
|
||||
Clock,
|
||||
ClockSource,
|
||||
ClockFrequency,
|
||||
ClockDivision,
|
||||
SystemClock(u8),
|
||||
Singletone(u8, u8),
|
||||
SingletoneFrequency(u8, u8),
|
||||
SingletoneAmplitude(u8, u8),
|
||||
|
@ -35,6 +40,11 @@ pub enum MqttTopic {
|
|||
pub enum MqttCommand {
|
||||
Switch(u8, bool),
|
||||
Attenuation(u8, f32),
|
||||
Clock(UrukulClockSource, f64, u8),
|
||||
ClockSource(UrukulClockSource),
|
||||
ClockFrequency(f64),
|
||||
ClockDivision(u8),
|
||||
SystemClock(u8, f64),
|
||||
Singletone(u8, u8, f64, f64, f64),
|
||||
SingletoneFrequency(u8, u8, f64),
|
||||
SingletoneAmplitude(u8, u8, f64),
|
||||
|
@ -76,7 +86,7 @@ impl<SPI, E> MqttMux<SPI> where SPI: Transfer<u8, Error = E> {
|
|||
singletone_frequency,
|
||||
singletone_amplitude,
|
||||
singletone_phase,
|
||||
profile // Note: Put profile at the end
|
||||
profile
|
||||
))
|
||||
)(topic)
|
||||
}
|
||||
|
@ -85,6 +95,11 @@ impl<SPI, E> MqttMux<SPI> where SPI: Transfer<u8, Error = E> {
|
|||
match topic {
|
||||
MqttTopic::Switch(ch) => switch_message(ch, message),
|
||||
MqttTopic::Attenuation(ch) => attenuation_message(ch, message),
|
||||
MqttTopic::Clock => clock_message(message),
|
||||
MqttTopic::ClockSource => clock_source_message(message),
|
||||
MqttTopic::ClockFrequency => clock_frequency_message(message),
|
||||
MqttTopic::ClockDivision => clock_division_message(message),
|
||||
MqttTopic::SystemClock(ch) => system_clock_message(ch, message),
|
||||
MqttTopic::Singletone(ch, prof) => singletone_message(ch, prof, message),
|
||||
MqttTopic::SingletoneFrequency(ch, prof) => singletone_frequency_message(ch, prof, message),
|
||||
MqttTopic::SingletoneAmplitude(ch, prof) => singletone_amplitude_message(ch, prof, message),
|
||||
|
@ -97,6 +112,11 @@ impl<SPI, E> MqttMux<SPI> where SPI: Transfer<u8, Error = E> {
|
|||
match command {
|
||||
MqttCommand::Switch(ch, state) => self.urukul.set_channel_switch(ch.into(), state),
|
||||
MqttCommand::Attenuation(ch, ampl) => self.urukul.set_channel_attenuation(ch, ampl),
|
||||
MqttCommand::Clock(src, freq, div) => self.urukul.set_clock(src, freq, div),
|
||||
MqttCommand::ClockSource(src) => self.urukul.set_clock_source(src),
|
||||
MqttCommand::ClockFrequency(freq) => self.urukul.set_clock_frequency(freq),
|
||||
MqttCommand::ClockDivision(div) => self.urukul.set_clock_division(div),
|
||||
MqttCommand::SystemClock(ch, freq) => self.urukul.set_channel_sys_clk(ch, freq),
|
||||
MqttCommand::Singletone(ch, prof, freq, ampl, deg) => self.urukul.set_channel_single_tone_profile(ch, prof, freq, ampl, deg),
|
||||
MqttCommand::SingletoneFrequency(ch, prof, freq) => self.urukul.set_channel_single_tone_profile_frequency(ch, prof, freq),
|
||||
MqttCommand::SingletoneAmplitude(ch, prof, ampl) => self.urukul.set_channel_single_tone_profile_amplitude(ch, prof, ampl),
|
||||
|
@ -152,6 +172,16 @@ fn select_profile<'a>(topic: &'a str) -> IResult<&'a str, u8> {
|
|||
)(topic)
|
||||
}
|
||||
|
||||
fn select_clock<'a>(topic: &'a str) -> IResult<&'a str, ()> {
|
||||
value(
|
||||
(),
|
||||
preceded(
|
||||
tag("Clock"),
|
||||
topic_separator
|
||||
)
|
||||
)(topic)
|
||||
}
|
||||
|
||||
// Selection parser for Singletone
|
||||
// Note: This fucntion assumes singletone is not the most specific sub-topic
|
||||
fn select_singletone<'a>(topic: &'a str) -> IResult<&'a str, ()> {
|
||||
|
@ -161,12 +191,6 @@ fn select_singletone<'a>(topic: &'a str) -> IResult<&'a str, ()> {
|
|||
)(topic)
|
||||
}
|
||||
|
||||
fn check_end_slice(message: &[u8]) -> IResult<&[u8], ()> {
|
||||
not(
|
||||
take(1_usize)
|
||||
)(message)
|
||||
}
|
||||
|
||||
// Read whitespace
|
||||
fn whitespace(message: &[u8]) -> IResult<&[u8], ()> {
|
||||
value((), take_while(is_space))(message)
|
||||
|
@ -252,6 +276,175 @@ fn attenuation_message(channel: u8, message: &[u8]) -> IResult<&[u8], MqttComman
|
|||
)(message)
|
||||
}
|
||||
|
||||
// Parser for Clock Source Command Topic
|
||||
fn clock_source<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
||||
all_consuming(
|
||||
value(
|
||||
MqttTopic::ClockSource,
|
||||
preceded(
|
||||
clock_source,
|
||||
tag("Source")
|
||||
)
|
||||
)
|
||||
)(topic)
|
||||
}
|
||||
|
||||
// Parser for Clock Source Command Message
|
||||
fn clock_source_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
|
||||
all_consuming(
|
||||
alt((
|
||||
value(MqttCommand::ClockSource(UrukulClockSource::OSC), tag_no_case("OSC")),
|
||||
value(MqttCommand::ClockSource(UrukulClockSource::MMCX), tag_no_case("MMCX")),
|
||||
value(MqttCommand::ClockSource(UrukulClockSource::SMA), tag_no_case("SMA"))
|
||||
))
|
||||
)(message)
|
||||
}
|
||||
|
||||
// Parser for Clock Frequency Command Topic
|
||||
fn clock_frequency<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
||||
all_consuming(
|
||||
value(
|
||||
MqttTopic::ClockFrequency,
|
||||
preceded(
|
||||
clock_source,
|
||||
tag("Frequency")
|
||||
)
|
||||
)
|
||||
)(topic)
|
||||
}
|
||||
|
||||
// Parser for Clock Frequency Command Message
|
||||
fn clock_frequency_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
|
||||
all_consuming(
|
||||
map(
|
||||
read_frequency,
|
||||
|freq: f64| MqttCommand::ClockFrequency(freq)
|
||||
)
|
||||
)(message)
|
||||
}
|
||||
|
||||
// Parser for Clock Division Command Topic
|
||||
fn clock_division<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
||||
all_consuming(
|
||||
value(
|
||||
MqttTopic::ClockDivision,
|
||||
preceded(
|
||||
clock_source,
|
||||
tag("Division")
|
||||
)
|
||||
)
|
||||
)(topic)
|
||||
}
|
||||
|
||||
// Parser for Clock Division Command Message
|
||||
fn clock_division_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
|
||||
all_consuming(
|
||||
map(
|
||||
digit1,
|
||||
|div: &[u8]| MqttCommand::ClockDivision(
|
||||
u8::from_str_radix(
|
||||
core::str::from_utf8(div).unwrap(),
|
||||
10
|
||||
).unwrap()
|
||||
)
|
||||
)
|
||||
)(message)
|
||||
}
|
||||
|
||||
// Parser for one-command master clock setup topic
|
||||
fn clock<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
||||
all_consuming(
|
||||
value(
|
||||
MqttTopic::Clock,
|
||||
tag("Clock")
|
||||
)
|
||||
)(topic)
|
||||
}
|
||||
|
||||
// Parser for one-command master clock setup message
|
||||
fn clock_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
|
||||
all_consuming(
|
||||
map(
|
||||
delimited(
|
||||
tag("{"),
|
||||
tuple((
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("\"source\":"),
|
||||
preceded(
|
||||
whitespace,
|
||||
terminated(
|
||||
alt((
|
||||
value(UrukulClockSource::OSC, tag_no_case("OSC")),
|
||||
value(UrukulClockSource::MMCX, tag_no_case("MMCX")),
|
||||
value(UrukulClockSource::SMA, tag_no_case("SMA"))
|
||||
)),
|
||||
tag(",")
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("\"frequency\":"),
|
||||
preceded(
|
||||
whitespace,
|
||||
terminated(
|
||||
read_frequency,
|
||||
tag(",")
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("\"division\":"),
|
||||
preceded(
|
||||
whitespace,
|
||||
terminated(
|
||||
map_res(
|
||||
digit1,
|
||||
|div: &[u8]| u8::from_str_radix(core::str::from_utf8(div).unwrap(), 10)
|
||||
),
|
||||
whitespace
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)),
|
||||
tag("}")
|
||||
),
|
||||
|(src, freq, div): (UrukulClockSource, f64, u8)| MqttCommand::Clock(src, freq, div)
|
||||
)
|
||||
)(message)
|
||||
}
|
||||
|
||||
// Topic parser for f_sys_clk of any channels
|
||||
fn system_clock<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
||||
all_consuming(
|
||||
map(
|
||||
terminated(
|
||||
select_channel,
|
||||
tag("SystemClock")
|
||||
),
|
||||
|channel: u8| MqttTopic::SystemClock(channel)
|
||||
)
|
||||
)(topic)
|
||||
}
|
||||
|
||||
// Message parser for f_sys_clk of any channels
|
||||
fn system_clock_message(channel: u8, message: &[u8]) -> IResult<&[u8], MqttCommand> {
|
||||
all_consuming(
|
||||
map(
|
||||
read_frequency,
|
||||
|freq: f64| MqttCommand::SystemClock(channel, freq)
|
||||
)
|
||||
)(message)
|
||||
}
|
||||
|
||||
// Parser for Singletone frequenct Command Topic
|
||||
fn singletone_frequency<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
||||
all_consuming(
|
||||
|
@ -364,28 +557,65 @@ fn singletone<'a>(topic: &'a str) -> IResult<&'a str, MqttTopic> {
|
|||
}
|
||||
|
||||
// Parser for one-command singletone profile Command
|
||||
// Using JSON like command structure
|
||||
// Possible enhancement: further modularize parsing of all separate fields
|
||||
fn singletone_message(channel: u8, profile: u8, message: &[u8]) -> IResult<&[u8], MqttCommand> {
|
||||
all_consuming(
|
||||
map(
|
||||
tuple((
|
||||
read_frequency,
|
||||
preceded(
|
||||
message_separator,
|
||||
double
|
||||
tag("{"),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("\"frequency\":"),
|
||||
preceded(
|
||||
whitespace,
|
||||
read_frequency
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
preceded(
|
||||
message_separator,
|
||||
tag(","),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("\"amplitude\":"),
|
||||
preceded(
|
||||
whitespace,
|
||||
double
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
preceded(
|
||||
tag(","),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("\"phase\":"),
|
||||
preceded(
|
||||
whitespace,
|
||||
terminated(
|
||||
double,
|
||||
preceded(
|
||||
opt(
|
||||
preceded(
|
||||
whitespace,
|
||||
tag_no_case("deg")
|
||||
)
|
||||
),
|
||||
preceded(
|
||||
whitespace,
|
||||
tag("}")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
)),
|
||||
|(freq, ampl, phase): (f64, f64, f64)| MqttCommand::Singletone(channel, profile, freq, ampl, phase)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue