use anyhow::{Context, Result};
use rppal::gpio::{Level, OutputPin};
use crate::{
pin::{PinType, RHPin},
pwm::PWM,
};
const PERIOD: u16 = 4095;
const PRESCALER: u16 = 10;
struct Motor {
pwm: PWM,
dir: OutputPin,
}
impl Motor {
fn new(pwm_pin: PinType, dir_pin: PinType) -> Result<Self> {
let mut pwm = PWM::new(pwm_pin)?;
let dir_pin = RHPin::new(dir_pin)?;
let mut dir = dir_pin.gpio_pin.into_output();
pwm.period(PERIOD)?;
pwm.prescaler(PRESCALER)?;
pwm.pulse_width_percent(0)?;
dir.write(Level::Low);
Ok(Self { pwm, dir })
}
fn speed(&mut self, speed: i8) -> Result<()> {
let dir: Level = if speed > 0 { Level::High } else { Level::Low };
self.pwm.pulse_width_percent(speed.unsigned_abs())?;
self.dir.write(dir);
Ok(())
}
}
pub struct Motors {
left_motor: Motor,
right_motor: Motor,
}
impl Motors {
pub fn new() -> Result<Self> {
let left_motor_pwm_pin = PinType::P12;
let left_motor_dir_pin = PinType::D4;
let right_motor_pwm_pin = PinType::P13;
let right_motor_dir_pin = PinType::D5;
let left_motor =
Motor::new(left_motor_pwm_pin, left_motor_dir_pin).context("LEFT MOTOR INIT FAILED")?;
let right_motor = Motor::new(right_motor_pwm_pin, right_motor_dir_pin)
.context("RIGHT MOTOR INIT FAILED")?;
Ok(Self {
left_motor,
right_motor,
})
}
pub fn stop(&mut self) {
let _ = self.left_motor.speed(0);
let _ = self.right_motor.speed(0);
}
fn speed(&mut self, left_speed: i8, right_speed: i8) {
let _ = self.left_motor.speed(left_speed);
let _ = self.right_motor.speed(-right_speed); }
pub fn forward(&mut self, speed: i8) {
self.speed(speed, speed);
}
pub fn backward(&mut self, speed: i8) {
self.speed(-speed, -speed);
}
pub fn turn_left(&mut self, speed: i8) {
self.speed(-speed, speed);
}
pub fn turn_right(&mut self, speed: i8) {
self.speed(speed, -speed);
}
}