forked from M-Labs/humpback-dds
mqtt_mux: add feedback for singletone/clock
This commit is contained in:
parent
b75c83be61
commit
21999b6cbf
34
src/dds.rs
34
src/dds.rs
@ -382,10 +382,38 @@ where
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Getter function for single tone profiles
|
||||||
|
*/
|
||||||
|
pub fn get_single_tone_profile(&mut self, profile: u8) -> Result<(f64, f64, f64), Error<E>> {
|
||||||
|
|
||||||
|
assert!(profile < 8);
|
||||||
|
|
||||||
|
let mut profile_content: [u8; 8] = [0; 8];
|
||||||
|
self.read_register(0x0E + profile, &mut profile_content)?;
|
||||||
|
|
||||||
|
// Convert ftw, pow and asf to f_out, phase and amplitude factor
|
||||||
|
let ftw: u64 = (profile_content[4] as u64) << 24 |
|
||||||
|
(profile_content[5] as u64) << 16 |
|
||||||
|
(profile_content[6] as u64) << 8 |
|
||||||
|
(profile_content[7] as u64);
|
||||||
|
let f_out: f64 = ((ftw as f64)/(((1_u64) << 32) as f64))*self.f_sys_clk;
|
||||||
|
|
||||||
|
let pow: u64 = (profile_content[2] as u64) << 8 |
|
||||||
|
(profile_content[3] as u64);
|
||||||
|
let phase: f64 = ((pow as f64)/(((1_u64) << 16) as f64))*360.0;
|
||||||
|
|
||||||
|
let asf: u64 = (profile_content[0] as u64) << 8 |
|
||||||
|
(profile_content[1] as u64);
|
||||||
|
let amplitude: f64 = (asf as f64)/(((1_u64) << 14) as f64);
|
||||||
|
|
||||||
|
Ok((f_out, phase, amplitude))
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set frequency of a single tone profile
|
* Set frequency of a single tone profile
|
||||||
* Frequency: Must be non-negative
|
* Frequency: Must be non-negative
|
||||||
* Keep other field unchanged in the register
|
* Keep other field unchanged in the register
|
||||||
*/
|
*/
|
||||||
pub fn set_single_tone_profile_frequency(&mut self, profile: u8, f_out: f64) -> Result<(), Error<E>> {
|
pub fn set_single_tone_profile_frequency(&mut self, profile: u8, f_out: f64) -> Result<(), Error<E>> {
|
||||||
|
|
||||||
@ -411,7 +439,7 @@ where
|
|||||||
/*
|
/*
|
||||||
* Set phase offset of a single tone profile
|
* Set phase offset of a single tone profile
|
||||||
* Phase: Expressed in positive degree, i.e. [0.0, 360.0)
|
* Phase: Expressed in positive degree, i.e. [0.0, 360.0)
|
||||||
* Keep other field unchanged in the register
|
* Keep other field unchanged in the register
|
||||||
*/
|
*/
|
||||||
pub fn set_single_tone_profile_phase(&mut self, profile: u8, phase_offset: f64) -> Result<(), Error<E>> {
|
pub fn set_single_tone_profile_phase(&mut self, profile: u8, phase_offset: f64) -> Result<(), Error<E>> {
|
||||||
|
|
||||||
@ -435,7 +463,7 @@ where
|
|||||||
/*
|
/*
|
||||||
* Set amplitude offset of a single tone profile
|
* Set amplitude offset of a single tone profile
|
||||||
* Amplitude: In a scale from 0 to 1, taking float
|
* Amplitude: In a scale from 0 to 1, taking float
|
||||||
* Keep other field unchanged in the register
|
* Keep other field unchanged in the register
|
||||||
*/
|
*/
|
||||||
pub fn set_single_tone_profile_amplitude(&mut self, profile: u8, amp_scale_factor: f64) -> Result<(), Error<E>> {
|
pub fn set_single_tone_profile_amplitude(&mut self, profile: u8, amp_scale_factor: f64) -> Result<(), Error<E>> {
|
||||||
|
|
||||||
|
254
src/mqtt_mux.rs
254
src/mqtt_mux.rs
@ -123,15 +123,15 @@ impl<'s, SPI, E> MqttMux<'s, SPI> where SPI: Transfer<u8, Error = E> {
|
|||||||
.map_err(|_| Error::StringOutOfSpace)?;
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
topic_string
|
topic_string
|
||||||
},
|
},
|
||||||
String::from(
|
String::from(
|
||||||
match self.urukul.test() {
|
match self.urukul.test() {
|
||||||
Ok(0) => "Reset successful.",
|
Ok(0) => "Reset successful.",
|
||||||
_ => "Reset error!",
|
_ => "Reset error!",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)).map_err(|_| Error::VectorOutOfSpace)?;
|
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
MqttCommand::Switch(ch, _) => {
|
MqttCommand::Switch(ch, _) => {
|
||||||
vec.push((
|
vec.push((
|
||||||
@ -177,10 +177,46 @@ impl<'s, SPI, E> MqttMux<'s, SPI> where SPI: Transfer<u8, Error = E> {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
))
|
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
),
|
Ok(vec)
|
||||||
MqttCommand::SystemClock(ch, _) => Ok(
|
}
|
||||||
Some((
|
|
||||||
|
MqttCommand::Clock(_, _, _) => {
|
||||||
|
vec.push(
|
||||||
|
self.get_clock_source_message()?
|
||||||
|
).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
vec.push(
|
||||||
|
self.get_clock_frequency_message()?
|
||||||
|
).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
vec.push(
|
||||||
|
self.get_clock_division_message()?
|
||||||
|
).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
MqttCommand::ClockSource(_) => {
|
||||||
|
vec.push(
|
||||||
|
self.get_clock_source_message()?
|
||||||
|
).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
MqttCommand::ClockFrequency(_) => {
|
||||||
|
vec.push(
|
||||||
|
self.get_clock_frequency_message()?
|
||||||
|
).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
MqttCommand::ClockDivision(_) => {
|
||||||
|
vec.push(
|
||||||
|
self.get_clock_division_message()?
|
||||||
|
).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
MqttCommand::SystemClock(ch, _) => {
|
||||||
|
vec.push((
|
||||||
{
|
{
|
||||||
let mut topic_string = String::from(self.name);
|
let mut topic_string = String::from(self.name);
|
||||||
topic_string.push_str("/Feedback/Channel")
|
topic_string.push_str("/Feedback/Channel")
|
||||||
@ -201,11 +237,32 @@ impl<'s, SPI, E> MqttMux<'s, SPI> where SPI: Transfer<u8, Error = E> {
|
|||||||
.map_err(|_| Error::StringOutOfSpace)?;
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
message_str
|
message_str
|
||||||
}
|
}
|
||||||
))
|
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
),
|
Ok(vec)
|
||||||
MqttCommand::Profile(_) => Ok(
|
}
|
||||||
Some((
|
|
||||||
"Urukul/Feedback/Profile",
|
MqttCommand::Singletone(ch, pr, _, _, _) |
|
||||||
|
MqttCommand::SingletoneFrequency(ch, pr, _) |
|
||||||
|
MqttCommand::SingletoneAmplitude(ch, pr, _) |
|
||||||
|
MqttCommand::SingletonePhase(ch, pr, _) => {
|
||||||
|
let (f_out, phase, ampl) = self.urukul.get_channel_single_tone_profile(ch, pr)?;
|
||||||
|
vec.push(self.get_single_tone_frequency_message(ch, pr, f_out)?)
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
vec.push(self.get_single_tone_phase_message(ch, pr, phase)?)
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
vec.push(self.get_single_tone_amplitude_message(ch, pr, ampl)?)
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
MqttCommand::Profile(_) => {
|
||||||
|
vec.push((
|
||||||
|
{
|
||||||
|
let mut topic_string = String::from(self.name);
|
||||||
|
topic_string.push_str("/Feedback/Profile")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string
|
||||||
|
},
|
||||||
{
|
{
|
||||||
let mut message_str = String::new();
|
let mut message_str = String::new();
|
||||||
let prof = self.urukul.get_profile()?;
|
let prof = self.urukul.get_profile()?;
|
||||||
@ -213,11 +270,25 @@ impl<'s, SPI, E> MqttMux<'s, SPI> where SPI: Transfer<u8, Error = E> {
|
|||||||
.map_err(|_| Error::StringOutOfSpace)?;
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
message_str
|
message_str
|
||||||
}
|
}
|
||||||
))
|
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
),
|
Ok(vec)
|
||||||
_ => Ok(Some(("Urukul/Feedback/Unimplemented", String::from("test")))),
|
}
|
||||||
|
|
||||||
|
// _ => {
|
||||||
|
// vec.push((
|
||||||
|
// {
|
||||||
|
// let mut topic_string = String::from(self.name);
|
||||||
|
// topic_string.push_str("/Feedback/Unimplemented")
|
||||||
|
// .map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
// topic_string
|
||||||
|
// },
|
||||||
|
// String::from("test")
|
||||||
|
// ))
|
||||||
|
// .map_err(|_| Error::VectorOutOfSpace)?;
|
||||||
|
// Ok(vec)
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
None => Ok(None),
|
None => Ok(vec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,13 +511,142 @@ impl<'s, SPI, E> MqttMux<'s, SPI> where SPI: Transfer<u8, Error = E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_switch_status_message(&mut self, channel: u8) -> Result<&str, Error<E>> {
|
fn get_clock_source_message(&mut self) -> Result<(String<U128>, String<U64>), Error<E>> {
|
||||||
self.urukul.get_channel_switch_status(channel.into()).map(
|
Ok((
|
||||||
|stat| if stat {
|
{
|
||||||
"on"
|
let mut topic_string = String::from(self.name);
|
||||||
} else {
|
topic_string.push_str("/Feedback/Clock/Source")
|
||||||
"off"
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
})
|
topic_string
|
||||||
|
},
|
||||||
|
self.urukul.get_clock_source().map(
|
||||||
|
|src| match src {
|
||||||
|
UrukulClockSource::OSC => String::from("OSC"),
|
||||||
|
UrukulClockSource::MMCX => String::from("MMCX"),
|
||||||
|
UrukulClockSource::SMA => String::from("SMA")
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_clock_frequency_message(&mut self) -> Result<(String<U128>, String<U64>), Error<E>> {
|
||||||
|
Ok((
|
||||||
|
{
|
||||||
|
let mut topic_string = String::from(self.name);
|
||||||
|
topic_string.push_str("/Feedback/Clock/Frequency")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let mut freq_str = String::from(
|
||||||
|
self.float_buffer.format_finite(
|
||||||
|
self.urukul.get_clock_frequency()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
freq_str.push_str(" Hz").map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
freq_str
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_clock_division_message(&mut self) -> Result<(String<U128>, String<U64>), Error<E>> {
|
||||||
|
Ok((
|
||||||
|
{
|
||||||
|
let mut topic_string = String::from(self.name);
|
||||||
|
topic_string.push_str("/Feedback/Clock/Division")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string
|
||||||
|
},
|
||||||
|
{
|
||||||
|
self.urukul.get_clock_division().map(
|
||||||
|
|src| match src {
|
||||||
|
1 => String::from("1"),
|
||||||
|
2 => String::from("2"),
|
||||||
|
4 => String::from("4"),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_single_tone_frequency_message(&mut self, ch: u8, pr: u8, f_out: f64) -> Result<(String<U128>, String<U64>), Error<E>> {
|
||||||
|
Ok((
|
||||||
|
{
|
||||||
|
let mut topic_string = String::from(self.name);
|
||||||
|
topic_string.push_str("/Feedback/Channel")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push(char::from_digit(ch.into(), 10).unwrap())
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push_str("/Profile")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push(char::from_digit(pr.into(), 10).unwrap())
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push_str("/Singletone/Frequency")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let mut message_str = String::from(
|
||||||
|
self.float_buffer.format_finite(f_out)
|
||||||
|
);
|
||||||
|
message_str.push_str(" Hz")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
message_str
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_single_tone_amplitude_message(&mut self, ch: u8, pr: u8, ampl: f64) -> Result<(String<U128>, String<U64>), Error<E>> {
|
||||||
|
Ok((
|
||||||
|
{
|
||||||
|
let mut topic_string = String::from(self.name);
|
||||||
|
topic_string.push_str("/Feedback/Channel")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push(char::from_digit(ch.into(), 10).unwrap())
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push_str("/Profile")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push(char::from_digit(pr.into(), 10).unwrap())
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push_str("/Singletone/Amplitude")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let message_str = String::from(
|
||||||
|
self.float_buffer.format_finite(ampl)
|
||||||
|
);
|
||||||
|
message_str
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_single_tone_phase_message(&mut self, ch: u8, pr: u8, phase: f64) -> Result<(String<U128>, String<U64>), Error<E>> {
|
||||||
|
Ok((
|
||||||
|
{
|
||||||
|
let mut topic_string = String::from(self.name);
|
||||||
|
topic_string.push_str("/Feedback/Channel")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push(char::from_digit(ch.into(), 10).unwrap())
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push_str("/Profile")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push(char::from_digit(pr.into(), 10).unwrap())
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string.push_str("/Singletone/Phase")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
topic_string
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let mut message_str = String::from(
|
||||||
|
self.float_buffer.format_finite(phase)
|
||||||
|
);
|
||||||
|
message_str.push_str(" deg")
|
||||||
|
.map_err(|_| Error::StringOutOfSpace)?;
|
||||||
|
message_str
|
||||||
|
}
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +291,10 @@ where
|
|||||||
}
|
}
|
||||||
self.dds[usize::from(channel)].set_single_tone_profile(profile, frequency, phase, amplitude)
|
self.dds[usize::from(channel)].set_single_tone_profile(profile, frequency, phase, amplitude)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_channel_single_tone_profile(&mut self, channel: u8, profile: u8) -> Result<(f64, f64, f64), Error<E>> {
|
||||||
|
self.dds[usize::from(channel)].get_single_tone_profile(profile)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_channel_single_tone_profile_frequency(&mut self, channel: u8, profile: u8, frequency: f64)-> Result<(), Error<E>> {
|
pub fn set_channel_single_tone_profile_frequency(&mut self, channel: u8, profile: u8, frequency: f64)-> Result<(), Error<E>> {
|
||||||
if channel >= 4 || profile >= 8 || frequency < 0.0 {
|
if channel >= 4 || profile >= 8 || frequency < 0.0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user