mqtt_mux: add feedback for singletone/clock

pull/4/head
occheung 2020-09-29 17:02:43 +08:00
parent b75c83be61
commit 21999b6cbf
3 changed files with 262 additions and 30 deletions

View File

@ -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>> {

View File

@ -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
}
))
}
}

View File

@ -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 {