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
|
||||
* 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>> {
|
||||
|
||||
@ -411,7 +439,7 @@ where
|
||||
/*
|
||||
* Set phase offset of a single tone profile
|
||||
* 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>> {
|
||||
|
||||
@ -435,7 +463,7 @@ where
|
||||
/*
|
||||
* Set amplitude offset of a single tone profile
|
||||
* 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>> {
|
||||
|
||||
|
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)?;
|
||||
topic_string
|
||||
},
|
||||
String::from(
|
||||
match self.urukul.test() {
|
||||
Ok(0) => "Reset successful.",
|
||||
_ => "Reset error!",
|
||||
}
|
||||
)
|
||||
String::from(
|
||||
match self.urukul.test() {
|
||||
Ok(0) => "Reset successful.",
|
||||
_ => "Reset error!",
|
||||
}
|
||||
)
|
||||
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||
Ok(vec)
|
||||
}
|
||||
}
|
||||
|
||||
MqttCommand::Switch(ch, _) => {
|
||||
vec.push((
|
||||
@ -177,10 +177,46 @@ impl<'s, SPI, E> MqttMux<'s, SPI> where SPI: Transfer<u8, Error = E> {
|
||||
)
|
||||
)
|
||||
}
|
||||
))
|
||||
),
|
||||
MqttCommand::SystemClock(ch, _) => Ok(
|
||||
Some((
|
||||
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
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);
|
||||
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)?;
|
||||
message_str
|
||||
}
|
||||
))
|
||||
),
|
||||
MqttCommand::Profile(_) => Ok(
|
||||
Some((
|
||||
"Urukul/Feedback/Profile",
|
||||
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
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 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)?;
|
||||
message_str
|
||||
}
|
||||
))
|
||||
),
|
||||
_ => Ok(Some(("Urukul/Feedback/Unimplemented", String::from("test")))),
|
||||
)).map_err(|_| Error::VectorOutOfSpace)?;
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
// _ => {
|
||||
// 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>> {
|
||||
self.urukul.get_channel_switch_status(channel.into()).map(
|
||||
|stat| if stat {
|
||||
"on"
|
||||
} else {
|
||||
"off"
|
||||
})
|
||||
fn get_clock_source_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/Source")
|
||||
.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)
|
||||
}
|
||||
|
||||
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>> {
|
||||
if channel >= 4 || profile >= 8 || frequency < 0.0 {
|
||||
|
Loading…
Reference in New Issue
Block a user