2020-03-14 06:39:22 +08:00
|
|
|
use core::fmt;
|
2020-03-20 02:51:59 +08:00
|
|
|
use core::num::ParseIntError;
|
|
|
|
use core::str::{from_utf8, Utf8Error};
|
2020-03-14 06:39:22 +08:00
|
|
|
use nom::{
|
|
|
|
IResult,
|
|
|
|
branch::alt,
|
|
|
|
bytes::complete::{is_a, tag, take_while1},
|
|
|
|
character::{is_digit, complete::{char, one_of}},
|
|
|
|
combinator::{complete, map, opt, value},
|
2020-03-20 05:21:17 +08:00
|
|
|
sequence::preceded,
|
2020-03-14 06:39:22 +08:00
|
|
|
multi::{fold_many0, fold_many1},
|
|
|
|
error::ErrorKind,
|
|
|
|
};
|
2020-03-20 02:51:59 +08:00
|
|
|
use num_traits::{Num, ParseFloatError};
|
2020-03-14 06:39:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum Error {
|
|
|
|
Parser(ErrorKind),
|
|
|
|
Incomplete,
|
|
|
|
UnexpectedInput(u8),
|
2020-03-20 02:51:59 +08:00
|
|
|
Utf8(Utf8Error),
|
|
|
|
ParseInt(ParseIntError),
|
|
|
|
// `num_traits::ParseFloatError` does not impl Clone
|
|
|
|
ParseFloat,
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'t> From<nom::Err<(&'t [u8], ErrorKind)>> for Error {
|
|
|
|
fn from(e: nom::Err<(&'t [u8], ErrorKind)>) -> Self {
|
|
|
|
match e {
|
|
|
|
nom::Err::Incomplete(_) =>
|
|
|
|
Error::Incomplete,
|
|
|
|
nom::Err::Error((_, e)) =>
|
|
|
|
Error::Parser(e),
|
|
|
|
nom::Err::Failure((_, e)) =>
|
|
|
|
Error::Parser(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-20 02:51:59 +08:00
|
|
|
impl From<Utf8Error> for Error {
|
|
|
|
fn from(e: Utf8Error) -> Self {
|
|
|
|
Error::Utf8(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ParseIntError> for Error {
|
|
|
|
fn from(e: ParseIntError) -> Self {
|
|
|
|
Error::ParseInt(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ParseFloatError> for Error {
|
|
|
|
fn from(_: ParseFloatError) -> Self {
|
|
|
|
Error::ParseFloat
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Error {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
|
|
match self {
|
|
|
|
Error::Incomplete =>
|
|
|
|
"incomplete input".fmt(fmt),
|
|
|
|
Error::UnexpectedInput(c) => {
|
|
|
|
"unexpected input: ".fmt(fmt)?;
|
|
|
|
c.fmt(fmt)
|
|
|
|
}
|
|
|
|
Error::Parser(e) => {
|
|
|
|
"parser: ".fmt(fmt)?;
|
|
|
|
(e as &dyn core::fmt::Debug).fmt(fmt)
|
|
|
|
}
|
2020-03-20 02:51:59 +08:00
|
|
|
Error::Utf8(e) => {
|
|
|
|
"utf8: ".fmt(fmt)?;
|
|
|
|
(e as &dyn core::fmt::Debug).fmt(fmt)
|
|
|
|
}
|
|
|
|
Error::ParseInt(e) => {
|
|
|
|
"parsing int: ".fmt(fmt)?;
|
2020-03-14 06:39:22 +08:00
|
|
|
(e as &dyn core::fmt::Debug).fmt(fmt)
|
|
|
|
}
|
2020-03-20 02:51:59 +08:00
|
|
|
Error::ParseFloat => {
|
|
|
|
"parsing float".fmt(fmt)
|
|
|
|
}
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum ShowCommand {
|
|
|
|
Input,
|
|
|
|
Reporting,
|
|
|
|
Pwm,
|
|
|
|
Pid,
|
|
|
|
SteinhartHart,
|
|
|
|
PostFilter,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum PidParameter {
|
|
|
|
Target,
|
|
|
|
KP,
|
|
|
|
KI,
|
|
|
|
KD,
|
|
|
|
OutputMin,
|
|
|
|
OutputMax,
|
|
|
|
IntegralMin,
|
|
|
|
IntegralMax,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Steinhart-Hart equation parameter
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum ShParameter {
|
2020-03-20 01:34:57 +08:00
|
|
|
T0,
|
2020-03-20 05:56:14 +08:00
|
|
|
B,
|
2020-03-20 01:34:57 +08:00
|
|
|
R0,
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
|
2020-03-20 01:34:57 +08:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
pub enum PwmPin {
|
|
|
|
ISet,
|
|
|
|
MaxIPos,
|
|
|
|
MaxINeg,
|
|
|
|
MaxV,
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
|
2020-03-20 01:34:57 +08:00
|
|
|
impl PwmPin {
|
|
|
|
pub fn name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
PwmPin::ISet => "i_set",
|
|
|
|
PwmPin::MaxIPos => "max_i_pos",
|
|
|
|
PwmPin::MaxINeg => "max_i_neg",
|
|
|
|
PwmPin::MaxV => "max_v",
|
|
|
|
}
|
|
|
|
}
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum Command {
|
|
|
|
Quit,
|
|
|
|
Show(ShowCommand),
|
|
|
|
Reporting(bool),
|
2020-03-20 01:34:57 +08:00
|
|
|
/// PWM parameter setting
|
2020-03-14 06:39:22 +08:00
|
|
|
Pwm {
|
|
|
|
channel: usize,
|
2020-03-20 01:34:57 +08:00
|
|
|
pin: PwmPin,
|
2020-09-17 04:05:31 +08:00
|
|
|
value: f64,
|
2020-03-14 06:39:22 +08:00
|
|
|
},
|
2020-03-20 01:34:57 +08:00
|
|
|
/// Enable PID control for `i_set`
|
|
|
|
PwmPid {
|
|
|
|
channel: usize,
|
|
|
|
},
|
|
|
|
/// PID parameter setting
|
2020-03-14 06:39:22 +08:00
|
|
|
Pid {
|
|
|
|
channel: usize,
|
|
|
|
parameter: PidParameter,
|
2020-03-19 04:56:52 +08:00
|
|
|
value: f64,
|
2020-03-14 06:39:22 +08:00
|
|
|
},
|
|
|
|
SteinhartHart {
|
|
|
|
channel: usize,
|
|
|
|
parameter: ShParameter,
|
2020-03-19 04:56:52 +08:00
|
|
|
value: f64,
|
2020-03-14 06:39:22 +08:00
|
|
|
},
|
|
|
|
PostFilter {
|
|
|
|
channel: usize,
|
|
|
|
rate: f32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
fn end(input: &[u8]) -> IResult<&[u8], ()> {
|
|
|
|
complete(
|
|
|
|
fold_many0(
|
|
|
|
one_of("\r\n\t "),
|
|
|
|
(), |(), _| ()
|
|
|
|
)
|
|
|
|
)(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn whitespace(input: &[u8]) -> IResult<&[u8], ()> {
|
|
|
|
fold_many1(char(' '), (), |(), _| ())(input)
|
|
|
|
}
|
|
|
|
|
2020-03-20 01:34:57 +08:00
|
|
|
fn unsigned(input: &[u8]) -> IResult<&[u8], Result<u32, Error>> {
|
2020-03-14 06:39:22 +08:00
|
|
|
take_while1(is_digit)(input)
|
|
|
|
.map(|(input, digits)| {
|
2020-03-20 02:51:59 +08:00
|
|
|
let result =
|
|
|
|
from_utf8(digits)
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
.and_then(|digits| u32::from_str_radix(digits, 10)
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
);
|
2020-03-14 06:39:22 +08:00
|
|
|
(input, result)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-03-19 04:56:52 +08:00
|
|
|
fn float(input: &[u8]) -> IResult<&[u8], Result<f64, Error>> {
|
2020-03-14 06:39:22 +08:00
|
|
|
let (input, sign) = opt(is_a("-"))(input)?;
|
|
|
|
let negative = sign.is_some();
|
|
|
|
let (input, digits) = take_while1(|c| is_digit(c) || c == '.' as u8)(input)?;
|
2020-03-20 02:51:59 +08:00
|
|
|
let result =
|
|
|
|
from_utf8(digits)
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
.and_then(|digits| f64::from_str_radix(digits, 10)
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
)
|
|
|
|
.map(|result: f64| if negative { -result } else { result });
|
2020-03-14 06:39:22 +08:00
|
|
|
Ok((input, result))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn off_on(input: &[u8]) -> IResult<&[u8], bool> {
|
|
|
|
alt((value(false, tag("off")),
|
|
|
|
value(true, tag("on"))
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn channel(input: &[u8]) -> IResult<&[u8], usize> {
|
|
|
|
map(one_of("01"), |c| (c as usize) - ('0' as usize))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn report(input: &[u8]) -> IResult<&[u8], Command> {
|
|
|
|
preceded(
|
|
|
|
tag("report"),
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
preceded(
|
|
|
|
tag("mode"),
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
// `report mode <on | off>` - Switch repoting mode
|
|
|
|
map(off_on, Command::Reporting)
|
|
|
|
),
|
|
|
|
// `report mode` - Show current reporting state
|
|
|
|
value(Command::Show(ShowCommand::Reporting), end)
|
|
|
|
))
|
|
|
|
)),
|
|
|
|
// `report` - Report once
|
|
|
|
value(Command::Show(ShowCommand::Input), end)
|
|
|
|
))
|
|
|
|
)(input)
|
|
|
|
}
|
|
|
|
|
2020-05-17 07:23:35 +08:00
|
|
|
fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, f64), Error>> {
|
2020-03-20 01:34:57 +08:00
|
|
|
let result_with_pin = |pin: PwmPin|
|
2020-05-17 07:23:35 +08:00
|
|
|
move |result: Result<f64, Error>|
|
2020-09-17 04:05:31 +08:00
|
|
|
result.map(|value| (pin, value));
|
2020-03-14 06:39:22 +08:00
|
|
|
|
|
|
|
alt((
|
|
|
|
map(
|
|
|
|
preceded(
|
|
|
|
tag("max_i_pos"),
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
2020-05-17 07:23:35 +08:00
|
|
|
float
|
2020-03-14 06:39:22 +08:00
|
|
|
)
|
|
|
|
),
|
2020-03-20 01:34:57 +08:00
|
|
|
result_with_pin(PwmPin::MaxIPos)
|
2020-03-14 06:39:22 +08:00
|
|
|
),
|
|
|
|
map(
|
|
|
|
preceded(
|
|
|
|
tag("max_i_neg"),
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
2020-05-17 07:23:35 +08:00
|
|
|
float
|
2020-03-14 06:39:22 +08:00
|
|
|
)
|
|
|
|
),
|
2020-03-20 01:34:57 +08:00
|
|
|
result_with_pin(PwmPin::MaxINeg)
|
2020-03-14 06:39:22 +08:00
|
|
|
),
|
|
|
|
map(
|
|
|
|
preceded(
|
|
|
|
tag("max_v"),
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
2020-05-17 07:23:35 +08:00
|
|
|
float
|
2020-03-14 06:39:22 +08:00
|
|
|
)
|
|
|
|
),
|
2020-03-20 01:34:57 +08:00
|
|
|
result_with_pin(PwmPin::MaxV)
|
2020-03-14 06:39:22 +08:00
|
|
|
),
|
2020-05-17 07:23:35 +08:00
|
|
|
map(float, result_with_pin(PwmPin::ISet)
|
2020-03-20 01:34:57 +08:00
|
|
|
))
|
|
|
|
)(input)
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// `pwm <0-1> pid` - Set PWM to be controlled by PID
|
2020-03-20 01:34:57 +08:00
|
|
|
fn pwm_pid(input: &[u8]) -> IResult<&[u8], ()> {
|
|
|
|
value((), tag("pid"))(input)
|
2020-03-14 06:39:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, _) = tag("pwm")(input)?;
|
|
|
|
alt((
|
2020-03-20 01:34:57 +08:00
|
|
|
|input| {
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, channel) = channel(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, result) = alt((
|
|
|
|
|input| {
|
|
|
|
let (input, ()) = pwm_pid(input)?;
|
|
|
|
Ok((input, Ok(Command::PwmPid { channel })))
|
|
|
|
},
|
|
|
|
|input| {
|
|
|
|
let (input, config) = pwm_setup(input)?;
|
|
|
|
match config {
|
2020-09-17 04:05:31 +08:00
|
|
|
Ok((pin, value)) =>
|
|
|
|
Ok((input, Ok(Command::Pwm { channel, pin, value }))),
|
2020-03-20 01:34:57 +08:00
|
|
|
Err(e) =>
|
|
|
|
Ok((input, Err(e))),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
))(input)?;
|
|
|
|
end(input)?;
|
|
|
|
Ok((input, result))
|
|
|
|
},
|
2020-03-14 06:39:22 +08:00
|
|
|
value(Ok(Command::Show(ShowCommand::Pwm)), end)
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `pid <0-1> <parameter> <value>`
|
|
|
|
fn pid_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, channel) = channel(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, parameter) =
|
|
|
|
alt((value(PidParameter::Target, tag("target")),
|
|
|
|
value(PidParameter::KP, tag("kp")),
|
|
|
|
value(PidParameter::KI, tag("ki")),
|
|
|
|
value(PidParameter::KD, tag("kd")),
|
|
|
|
value(PidParameter::OutputMin, tag("output_min")),
|
|
|
|
value(PidParameter::OutputMax, tag("output_max")),
|
|
|
|
value(PidParameter::IntegralMin, tag("integral_min")),
|
|
|
|
value(PidParameter::IntegralMax, tag("integral_max"))
|
|
|
|
))(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, value) = float(input)?;
|
|
|
|
let result = value
|
|
|
|
.map(|value| Command::Pid { channel, parameter, value });
|
|
|
|
Ok((input, result))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `pid` | `pid <pid_parameter>`
|
|
|
|
fn pid(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, _) = tag("pid")(input)?;
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
pid_parameter
|
|
|
|
),
|
|
|
|
value(Ok(Command::Show(ShowCommand::Pid)), end)
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `s-h <0-1> <parameter> <value>`
|
|
|
|
fn steinhart_hart_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, channel) = channel(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, parameter) =
|
2020-03-20 01:34:57 +08:00
|
|
|
alt((value(ShParameter::T0, tag("t0")),
|
2020-03-20 05:56:14 +08:00
|
|
|
value(ShParameter::B, tag("b")),
|
2020-03-20 01:34:57 +08:00
|
|
|
value(ShParameter::R0, tag("r0"))
|
2020-03-14 06:39:22 +08:00
|
|
|
))(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, value) = float(input)?;
|
|
|
|
let result = value
|
|
|
|
.map(|value| Command::SteinhartHart { channel, parameter, value });
|
|
|
|
Ok((input, result))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `s-h` | `s-h <steinhart_hart_parameter>`
|
|
|
|
fn steinhart_hart(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, _) = tag("s-h")(input)?;
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
steinhart_hart_parameter
|
|
|
|
),
|
|
|
|
value(Ok(Command::Show(ShowCommand::SteinhartHart)), end)
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn postfilter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, _) = tag("postfilter")(input)?;
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
|input| {
|
|
|
|
let (input, channel) = channel(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, _) = tag("rate")(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, rate) = float(input)?;
|
|
|
|
let result = rate
|
|
|
|
.map(|rate| Command::PostFilter {
|
2020-03-19 04:56:52 +08:00
|
|
|
channel,
|
|
|
|
rate: rate as f32,
|
2020-03-14 06:39:22 +08:00
|
|
|
});
|
|
|
|
Ok((input, result))
|
|
|
|
}
|
|
|
|
),
|
|
|
|
value(Ok(Command::Show(ShowCommand::PostFilter)), end)
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn command(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
alt((value(Ok(Command::Quit), tag("quit")),
|
|
|
|
map(report, Ok),
|
|
|
|
pwm,
|
|
|
|
pid,
|
|
|
|
steinhart_hart,
|
|
|
|
postfilter,
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Command {
|
|
|
|
pub fn parse(input: &[u8]) -> Result<Self, Error> {
|
|
|
|
match command(input) {
|
|
|
|
Ok((b"", result)) =>
|
|
|
|
result,
|
|
|
|
Ok((input_remain, _)) =>
|
|
|
|
Err(Error::UnexpectedInput(input_remain[0])),
|
|
|
|
Err(e) =>
|
|
|
|
Err(e.into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_quit() {
|
|
|
|
let command = Command::parse(b"quit");
|
|
|
|
assert_eq!(command, Ok(Command::Quit));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_report() {
|
|
|
|
let command = Command::parse(b"report");
|
|
|
|
assert_eq!(command, Ok(Command::Show(ShowCommand::Input)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_report_mode() {
|
|
|
|
let command = Command::parse(b"report mode");
|
|
|
|
assert_eq!(command, Ok(Command::Show(ShowCommand::Reporting)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_report_mode_on() {
|
|
|
|
let command = Command::parse(b"report mode on");
|
|
|
|
assert_eq!(command, Ok(Command::Reporting(true)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_report_mode_off() {
|
|
|
|
let command = Command::parse(b"report mode off");
|
|
|
|
assert_eq!(command, Ok(Command::Reporting(false)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pwm_manual() {
|
2020-03-20 01:34:57 +08:00
|
|
|
let command = Command::parse(b"pwm 1 16383");
|
2020-03-14 06:39:22 +08:00
|
|
|
assert_eq!(command, Ok(Command::Pwm {
|
|
|
|
channel: 1,
|
2020-03-20 01:34:57 +08:00
|
|
|
pin: PwmPin::ISet,
|
2020-09-17 07:48:27 +08:00
|
|
|
value: 16383.0,
|
2020-03-14 06:39:22 +08:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pwm_pid() {
|
|
|
|
let command = Command::parse(b"pwm 0 pid");
|
2020-03-20 01:34:57 +08:00
|
|
|
assert_eq!(command, Ok(Command::PwmPid {
|
2020-03-14 06:39:22 +08:00
|
|
|
channel: 0,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pwm_max_i_pos() {
|
2020-03-20 01:34:57 +08:00
|
|
|
let command = Command::parse(b"pwm 0 max_i_pos 7");
|
2020-03-14 06:39:22 +08:00
|
|
|
assert_eq!(command, Ok(Command::Pwm {
|
|
|
|
channel: 0,
|
2020-03-20 01:34:57 +08:00
|
|
|
pin: PwmPin::MaxIPos,
|
2020-09-17 07:48:27 +08:00
|
|
|
value: 7.0,
|
2020-03-14 06:39:22 +08:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pwm_max_i_neg() {
|
2020-03-20 01:34:57 +08:00
|
|
|
let command = Command::parse(b"pwm 0 max_i_neg 128");
|
2020-03-14 06:39:22 +08:00
|
|
|
assert_eq!(command, Ok(Command::Pwm {
|
|
|
|
channel: 0,
|
2020-03-20 01:34:57 +08:00
|
|
|
pin: PwmPin::MaxINeg,
|
2020-09-17 07:48:27 +08:00
|
|
|
value: 128.0,
|
2020-03-14 06:39:22 +08:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pwm_max_v() {
|
2020-03-20 01:34:57 +08:00
|
|
|
let command = Command::parse(b"pwm 0 max_v 32768");
|
2020-03-14 06:39:22 +08:00
|
|
|
assert_eq!(command, Ok(Command::Pwm {
|
|
|
|
channel: 0,
|
2020-03-20 01:34:57 +08:00
|
|
|
pin: PwmPin::MaxV,
|
2020-09-17 07:48:27 +08:00
|
|
|
value: 32768.0,
|
2020-03-14 06:39:22 +08:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pid() {
|
|
|
|
let command = Command::parse(b"pid");
|
|
|
|
assert_eq!(command, Ok(Command::Show(ShowCommand::Pid)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pid_target() {
|
|
|
|
let command = Command::parse(b"pid 0 target 36.5");
|
|
|
|
assert_eq!(command, Ok(Command::Pid {
|
|
|
|
channel: 0,
|
|
|
|
parameter: PidParameter::Target,
|
|
|
|
value: 36.5,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_pid_integral_max() {
|
|
|
|
let command = Command::parse(b"pid 1 integral_max 2000");
|
|
|
|
assert_eq!(command, Ok(Command::Pid {
|
|
|
|
channel: 1,
|
|
|
|
parameter: PidParameter::IntegralMax,
|
|
|
|
value: 2000.0,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_steinhart_hart() {
|
|
|
|
let command = Command::parse(b"s-h");
|
|
|
|
assert_eq!(command, Ok(Command::Show(ShowCommand::SteinhartHart)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_steinhart_hart_parallel_r() {
|
2020-03-20 01:34:57 +08:00
|
|
|
let command = Command::parse(b"s-h 1 t0 23.05");
|
2020-03-14 06:39:22 +08:00
|
|
|
assert_eq!(command, Ok(Command::SteinhartHart {
|
|
|
|
channel: 1,
|
2020-03-20 01:34:57 +08:00
|
|
|
parameter: ShParameter::T0,
|
2020-03-14 06:39:22 +08:00
|
|
|
value: 23.05,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_postfilter_rate() {
|
|
|
|
let command = Command::parse(b"postfilter 0 rate 21");
|
|
|
|
assert_eq!(command, Ok(Command::PostFilter {
|
|
|
|
channel: 0,
|
|
|
|
rate: 21.0,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|