Compare commits
No commits in common. "ee4d24de6af22a26716dab29034c506986af2ab8" and "426be0d5f163bcbd701eaa5b81d85275214db3ba" have entirely different histories.
ee4d24de6a
...
426be0d5f1
|
@ -2,7 +2,7 @@ use embedded_hal::digital::v2::OutputPin;
|
|||
use embedded_hal::blocking::spi::Transfer;
|
||||
use super::checksum::{ChecksumMode, Checksum};
|
||||
use super::AdcError;
|
||||
use super::{regs, regs::RegisterData, Input};
|
||||
use super::{regs, regs::RegisterData, Input, RefSource};
|
||||
|
||||
/// AD7172-2 implementation
|
||||
///
|
||||
|
|
|
@ -63,19 +63,16 @@ macro_rules! def_reg {
|
|||
|
||||
macro_rules! reg_bit {
|
||||
($getter: ident, $byte: expr, $bit: expr, $doc: expr) => {
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $getter(&self) -> bool {
|
||||
self.0[$byte].get_bit($bit)
|
||||
}
|
||||
};
|
||||
($getter: ident, $setter: ident, $byte: expr, $bit: expr, $doc: expr) => {
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $getter(&self) -> bool {
|
||||
self.0[$byte].get_bit($bit)
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $setter(&mut self, value: bool) {
|
||||
self.0[$byte].set_bit($bit, value);
|
||||
|
@ -85,38 +82,32 @@ macro_rules! reg_bit {
|
|||
|
||||
macro_rules! reg_bits {
|
||||
($getter: ident, $byte: expr, $bits: expr, $doc: expr) => {
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $getter(&self) -> u8 {
|
||||
self.0[$byte].get_bits($bits)
|
||||
}
|
||||
};
|
||||
($getter: ident, $setter: ident, $byte: expr, $bits: expr, $doc: expr) => {
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $getter(&self) -> u8 {
|
||||
self.0[$byte].get_bits($bits)
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $setter(&mut self, value: u8) {
|
||||
self.0[$byte].set_bits($bits, value);
|
||||
}
|
||||
};
|
||||
($getter: ident, $byte: expr, $bits: expr, $ty: ty, $doc: expr) => {
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $getter(&self) -> $ty {
|
||||
self.0[$byte].get_bits($bits) as $ty
|
||||
}
|
||||
};
|
||||
($getter: ident, $setter: ident, $byte: expr, $bits: expr, $ty: ty, $doc: expr) => {
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $getter(&self) -> $ty {
|
||||
self.0[$byte].get_bits($bits).into()
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[doc = $doc]
|
||||
pub fn $setter(&mut self, value: $ty) {
|
||||
self.0[$byte].set_bits($bits, value as u8);
|
||||
|
@ -165,13 +156,11 @@ impl channel::Data {
|
|||
reg_bits!(setup, set_setup, 0, 4..=5, "Setup number");
|
||||
|
||||
/// Which input is connected to positive input of this channel
|
||||
#[allow(unused)]
|
||||
pub fn a_in_pos(&self) -> Input {
|
||||
((self.0[0].get_bits(0..=1) << 3) |
|
||||
self.0[1].get_bits(5..=7)).into()
|
||||
}
|
||||
/// Set which input is connected to positive input of this channel
|
||||
#[allow(unused)]
|
||||
pub fn set_a_in_pos(&mut self, value: Input) {
|
||||
let value = value as u8;
|
||||
self.0[0].set_bits(0..=1, value >> 3);
|
||||
|
@ -218,13 +207,11 @@ impl filt_con::Data {
|
|||
|
||||
def_reg!(Offset, u8, offset, 0x30, 3);
|
||||
impl offset::Data {
|
||||
#[allow(unused)]
|
||||
pub fn offset(&self) -> u32 {
|
||||
(u32::from(self.0[0]) << 16) |
|
||||
(u32::from(self.0[1]) << 8) |
|
||||
u32::from(self.0[2])
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn set_offset(&mut self, value: u32) {
|
||||
self.0[0] = (value >> 16) as u8;
|
||||
self.0[1] = (value >> 8) as u8;
|
||||
|
@ -234,13 +221,11 @@ impl offset::Data {
|
|||
|
||||
def_reg!(Gain, u8, gain, 0x38, 3);
|
||||
impl gain::Data {
|
||||
#[allow(unused)]
|
||||
pub fn gain(&self) -> u32 {
|
||||
(u32::from(self.0[0]) << 16) |
|
||||
(u32::from(self.0[1]) << 8) |
|
||||
u32::from(self.0[2])
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn set_gain(&mut self, value: u32) {
|
||||
self.0[0] = (value >> 16) as u8;
|
||||
self.0[1] = (value >> 8) as u8;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use core::fmt;
|
||||
use nom::{
|
||||
IResult,
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_while1},
|
||||
character::{is_digit, complete::char},
|
||||
combinator::{map, value},
|
||||
sequence::preceded,
|
||||
sequence::{preceded, tuple, Tuple},
|
||||
multi::fold_many1,
|
||||
error::ErrorKind,
|
||||
};
|
||||
|
@ -13,7 +12,7 @@ use btoi::{btoi, ParseIntegerError};
|
|||
use super::session::ReportMode;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Parser(ErrorKind),
|
||||
Incomplete,
|
||||
|
@ -40,43 +39,9 @@ impl From<ParseIntegerError> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
Error::ParseInteger(e) => {
|
||||
"parsing number: ".fmt(fmt)?;
|
||||
e.fmt(fmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ShowCommand {
|
||||
ReportMode,
|
||||
Pid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PidParameter {
|
||||
Target,
|
||||
KP,
|
||||
KI,
|
||||
KD,
|
||||
OutputMin,
|
||||
OutputMax,
|
||||
IntegralMin,
|
||||
IntegralMax,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -88,10 +53,6 @@ pub enum Command {
|
|||
width: u32,
|
||||
total: u32,
|
||||
},
|
||||
Pid {
|
||||
parameter: PidParameter,
|
||||
value: f32,
|
||||
},
|
||||
}
|
||||
|
||||
fn whitespace(input: &[u8]) -> IResult<&[u8], ()> {
|
||||
|
@ -152,54 +113,17 @@ fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|||
Ok((input, Ok(Command::Pwm { width, total })))
|
||||
}
|
||||
|
||||
fn pid_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
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)?;
|
||||
// TODO: parse float
|
||||
let (input, value) = unsigned(input)?;
|
||||
let result = value
|
||||
.map(|value| Command::Pid { parameter, value: value as f32 })
|
||||
.map_err(|e| e.into());
|
||||
Ok((input, result))
|
||||
}
|
||||
|
||||
fn pid(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
let (input, _) = tag("pid")(input)?;
|
||||
let (input, _) = whitespace(input)?;
|
||||
|
||||
alt((
|
||||
preceded(
|
||||
whitespace,
|
||||
pid_parameter
|
||||
),
|
||||
|input| Ok((input, Ok(Command::Show(ShowCommand::Pid))))
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn command(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
alt((value(Ok(Command::Quit), tag("quit")),
|
||||
|input| report(input).map(|(input, command)| {
|
||||
(input, Ok(command))
|
||||
}),
|
||||
pwm,
|
||||
pid,
|
||||
fn command(input: &[u8]) -> IResult<&[u8], Command> {
|
||||
alt((value(Command::Quit, tag("quit")),
|
||||
report
|
||||
))(input)
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn parse(input: &[u8]) -> Result<Self, Error> {
|
||||
match command(input) {
|
||||
Ok((b"", result)) =>
|
||||
result,
|
||||
Ok((b"", command)) =>
|
||||
Ok(command),
|
||||
Ok((input_remain, _)) =>
|
||||
Err(Error::UnexpectedInput(input_remain[0])),
|
||||
Err(e) =>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#![feature(const_fn, proc_macro_hygiene)]
|
||||
#![feature(const_fn)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use cortex_m_rt::{entry, heap_start};
|
||||
use core::fmt::{self, Write};
|
||||
use smoltcp::time::Instant;
|
||||
use smoltcp::wire::{IpCidr, IpAddress, EthernetAddress};
|
||||
|
@ -41,7 +41,6 @@ use command_parser::{Command, ShowCommand};
|
|||
mod session;
|
||||
use self::session::{Session, SessionOutput};
|
||||
mod ad7172;
|
||||
mod pid;
|
||||
|
||||
pub struct UART0;
|
||||
|
||||
|
@ -78,15 +77,6 @@ macro_rules! create_socket {
|
|||
|
||||
/// In nanoseconds
|
||||
const REPORT_INTERVAL: u64 = 100_000;
|
||||
const DEFAULT_PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
||||
kp: 1.0,
|
||||
ki: 1.0,
|
||||
kd: 1.0,
|
||||
output_min: 0.0,
|
||||
output_max: 0xffff as f32,
|
||||
integral_min: 0.0,
|
||||
integral_max: 0xffff as f32,
|
||||
};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
|
@ -153,8 +143,6 @@ fn main() -> ! {
|
|||
// SENS1_{P,N}
|
||||
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
|
||||
|
||||
let mut pid = pid::Controller::new(DEFAULT_PID_PARAMETERS.clone());
|
||||
|
||||
let mut hardware_addr = EthernetAddress(board::get_mac_address());
|
||||
if hardware_addr.is_multicast() {
|
||||
println!("programmed MAC address is invalid, using default");
|
||||
|
@ -212,7 +200,7 @@ fn main() -> ! {
|
|||
// ADC input
|
||||
adc.data_ready()
|
||||
.unwrap_or_else(|e| {
|
||||
writeln!(stdout, "ADC error: {:?}", e).unwrap();
|
||||
writeln!(stdout, "ADC error: {:?}", e);
|
||||
None
|
||||
}).map(|channel| {
|
||||
let data = adc.read_data().unwrap();
|
||||
|
@ -253,61 +241,21 @@ fn main() -> ! {
|
|||
if socket.may_recv() && socket.may_send() {
|
||||
let output = socket.recv(|buf| session.feed(buf));
|
||||
|
||||
// TODO: use "{}" to display pretty errors
|
||||
match output {
|
||||
Ok(SessionOutput::Nothing) => {}
|
||||
Ok(SessionOutput::Command(command)) => match command {
|
||||
Command::Quit =>
|
||||
socket.close(),
|
||||
Command::Report(mode) => {
|
||||
let _ = writeln!(socket, "Report mode: {}", mode);
|
||||
let _ = writeln!(socket, "Report mode: {:?}", mode);
|
||||
}
|
||||
Command::Show(ShowCommand::ReportMode) => {
|
||||
let _ = writeln!(socket, "Report mode: {}", session.report_mode());
|
||||
}
|
||||
Command::Show(ShowCommand::Pid) => {
|
||||
let _ = writeln!(socket, "PID settings");
|
||||
let _ = writeln!(socket, "target: {:.4}", pid.get_target());
|
||||
let p = pid.get_parameters();
|
||||
macro_rules! out {
|
||||
($p: tt) => {
|
||||
let _ = writeln!(socket, "{}: {:.4}", stringify!($p), p.$p);
|
||||
};
|
||||
}
|
||||
out!(kp);
|
||||
out!(ki);
|
||||
out!(kd);
|
||||
out!(output_min);
|
||||
out!(output_max);
|
||||
out!(integral_min);
|
||||
out!(integral_max);
|
||||
let _ = writeln!(socket, "Report mode: {:?}", session.report_mode());
|
||||
}
|
||||
Command::Pwm { width, total } => {
|
||||
board::set_timer_pwm(width, total);
|
||||
let _ = writeln!(socket, "PWM duty cycle: {}/{}", width, total);
|
||||
}
|
||||
Command::Pid { parameter, value } => {
|
||||
use command_parser::PidParameter::*;
|
||||
match parameter {
|
||||
Target =>
|
||||
pid.set_target(value),
|
||||
KP =>
|
||||
pid.update_parameters(|parameters| parameters.kp = value),
|
||||
KI =>
|
||||
pid.update_parameters(|parameters| parameters.ki = value),
|
||||
KD =>
|
||||
pid.update_parameters(|parameters| parameters.kd = value),
|
||||
OutputMin =>
|
||||
pid.update_parameters(|parameters| parameters.output_min = value),
|
||||
OutputMax =>
|
||||
pid.update_parameters(|parameters| parameters.output_max = value),
|
||||
IntegralMin =>
|
||||
pid.update_parameters(|parameters| parameters.integral_min = value),
|
||||
IntegralMax =>
|
||||
pid.update_parameters(|parameters| parameters.integral_max = value),
|
||||
}
|
||||
let _ = writeln!(socket, "PID parameter updated");
|
||||
}
|
||||
}
|
||||
Ok(SessionOutput::Error(e)) => {
|
||||
let _ = writeln!(socket, "Command error: {:?}", e);
|
||||
|
|
|
@ -56,22 +56,10 @@ impl Controller {
|
|||
output
|
||||
}
|
||||
|
||||
pub fn get_target(&mut self) -> f32 {
|
||||
self.target
|
||||
}
|
||||
|
||||
pub fn set_target(&mut self, target: f32) {
|
||||
self.target = target;
|
||||
}
|
||||
|
||||
pub fn get_parameters(&self) -> &Parameters {
|
||||
&self.parameters
|
||||
}
|
||||
|
||||
pub fn update_parameters<F: FnOnce(&mut Parameters)>(&mut self, f: F) {
|
||||
f(&mut self.parameters);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn reset(&mut self) {
|
||||
self.integral = 0.0;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use core::ops::Deref;
|
||||
use core::fmt;
|
||||
use super::command_parser::{Command, Error as ParserError};
|
||||
|
||||
const MAX_LINE_LEN: usize = 64;
|
||||
|
@ -61,16 +60,6 @@ pub enum ReportMode {
|
|||
Continuous,
|
||||
}
|
||||
|
||||
impl fmt::Display for ReportMode {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
ReportMode::Off => "off",
|
||||
ReportMode::Once => "once",
|
||||
ReportMode::Continuous => "continuous",
|
||||
}.fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SessionOutput {
|
||||
Nothing,
|
||||
Command(Command),
|
||||
|
|
Loading…
Reference in New Issue