Skip to content
Snippets Groups Projects
Commit 64eea5b9 authored by Stephen D's avatar Stephen D
Browse files

vibrator

parent 36a21837
Branches
No related tags found
No related merge requests found
......@@ -212,7 +212,7 @@ impl Controller {
}
// Returns true if new unread message
pub fn tick(&mut self, spi: &mut MySpi) -> bool {
pub fn tick(&mut self, spi: &mut MySpi, display_on: bool) -> bool {
if !self.radio.is_busy_rxing(spi) {
let now = monotonics::now();
let msg = self
......@@ -251,8 +251,8 @@ impl Controller {
}
}
let (for_us, resp) = self.radio.tick(spi, &mut self.storage);
if let Some(msg_id) = resp {
let ticked = self.radio.tick(spi, &mut self.storage);
if let Some(msg_id) = ticked.message_ack_id {
self.refresh_rx_led();
while let Some((tx_id, _)) = self
......@@ -265,11 +265,24 @@ impl Controller {
}
}
if for_us {
if let Some(msg_id) = ticked.message_rx_id {
self.refresh_rx_led();
}
for_us
if !display_on {
true
} else if let Some(msg) = self.storage.get_message(msg_id) {
// only emit true if we're not in the chat for the given person already
if let View::Chat(v) = &self.cur_view {
!(v.callsign() == msg.callsign() && v.ssid() == msg.ssid())
} else {
true
}
} else {
true
}
} else {
false
}
}
pub fn red_led_on(&self) -> bool {
......
......@@ -169,7 +169,7 @@ impl<
row_ser: RSER,
row_ld: RLD,
) -> Self {
Self {
let mut s = Self {
timer,
col_clk,
......@@ -186,7 +186,12 @@ impl<
red: false,
green: false,
blue: false,
}
};
// Turn off LEDs
s.write_cols(0);
s
}
pub fn set_led(&mut self, led: Led, on: bool) {
......
......@@ -9,6 +9,7 @@ mod keyboard;
mod radio;
mod storage;
mod touchpad;
mod vibrate;
mod voltage;
use panic_rtt_target as _;
......@@ -30,6 +31,7 @@ mod app {
radio::{RadioController, MAX_PACKET_LEN},
storage::Storage,
touchpad::Touchpad,
vibrate::Vibrator,
voltage::VoltMeter,
};
use cortex_m::{delay::Delay, singleton};
......@@ -44,6 +46,7 @@ mod app {
gpio::{
bank0::{
Gpio0, Gpio1, Gpio12, Gpio14, Gpio15, Gpio18, Gpio2, Gpio23, Gpio6, Gpio7, Gpio8,
Gpio9,
},
FunctionI2C, FunctionSio, FunctionSpi, Pin, PinState, PullDown, PullNone, PullUp,
SioInput, SioOutput,
......@@ -102,6 +105,8 @@ mod app {
Pin<Gpio7, FunctionSio<SioOutput>, PullDown>,
>;
type MyVibrator = Vibrator<Pin<Gpio9, FunctionSio<SioOutput>, PullDown>>;
#[monotonic(binds = TIMER_IRQ_0, default = true)]
type MyMono = Monotonic<Alarm0>;
......@@ -111,6 +116,8 @@ mod app {
display_on: bool,
#[lock_free]
keyboard: MyKeyboard,
#[lock_free]
vibrator: MyVibrator,
}
#[local]
......@@ -180,7 +187,7 @@ mod app {
.build();
*/
// let mut vibrator = pins.gpio9.into_push_pull_output();
let vibrator = Vibrator::new(pins.gpio9.into_push_pull_output());
let mut delay = Delay::new(ctx.core.SYST, clocks.system_clock.freq().to_Hz());
......@@ -287,6 +294,7 @@ mod app {
controller,
display_on: true,
keyboard,
vibrator,
},
Local {
keyboard_bl,
......@@ -427,8 +435,9 @@ mod app {
display.clear(Rgb565::BLACK).unwrap();
}
if g.tick(spi.as_mut().unwrap()) {
if g.tick(spi.as_mut().unwrap(), display_on) {
let _ = notif_light_on::spawn();
let _ = vibrate_activate::spawn();
}
});
......@@ -466,6 +475,21 @@ mod app {
let _ = notif_light_on::spawn_after(NOTIF_LED_OFF_TIME_MS.millis());
}
#[task(priority = 2, shared = [vibrator])]
fn vibrate_activate(ctx: vibrate_activate::Context) {
let vibrator = ctx.shared.vibrator;
let ms = vibrator.activate();
let _ = vibrate_tick::spawn_after(ms.millis());
}
#[task(priority = 2, shared = [vibrator])]
fn vibrate_tick(ctx: vibrate_tick::Context) {
if let Some(ms) = ctx.shared.vibrator.step() {
let _ = vibrate_tick::spawn_after(ms.millis());
}
}
#[idle]
fn idle(_: idle::Context) -> ! {
loop {
......
......@@ -27,6 +27,13 @@ const HARDWARE_ID: u16 = 0x7c87;
const SOFTWARE_ID: u8 = 0;
const MAX_HOPS: u8 = 3;
pub struct TickResponse {
// We rx'd a message and saved it with this ID
pub message_rx_id: Option<u16>,
// We rx'd an ack to a message we tx'd. This is the ID of the tx'd message
pub message_ack_id: Option<u16>,
}
pub struct RadioController {
radio: Option<MyRf4463>,
buf: &'static mut [u8; MAX_PACKET_LEN],
......@@ -54,9 +61,9 @@ impl RadioController {
s
}
// Returns (message was destined for us, the message id of the message that was ack'd, if any)
// Returns (message id that we rx'd, the message id of the message that was ack'd)
// (Yes, I know the fact that we're doing that is kind of spaghetti)
pub fn tick(&mut self, spi: &mut MySpi, storage: &mut Storage) -> (bool, Option<u16>) {
pub fn tick(&mut self, spi: &mut MySpi, storage: &mut Storage) -> TickResponse {
Self::radio_handler_opt(&mut self.radio, |rad| {
if rad.is_busy_txing() {
rad.interrupt(spi, None, Some(self.buf)).ok()?;
......@@ -72,12 +79,15 @@ impl RadioController {
let Ok(data) = rad.finish_rx(spi, &mut self.buf[..]) else {
self.radio = None;
return (false, None);
return TickResponse {
message_rx_id: None,
message_ack_id: None,
};
};
if let Some(data) = data {
if let Ok(packet) = Packet::fully_decode(data.data(), &mut buf) {
let for_us = self.handle_rx(spi, storage, &packet).is_some();
let message_rx_id = self.handle_rx(spi, storage, &packet);
// not very DRY that this is duplicated TODO
Self::radio_handler_opt(&mut self.radio, |rad| {
......@@ -88,7 +98,12 @@ impl RadioController {
Some(())
});
return (for_us, self.handle_ack(storage, &packet));
let message_ack_id = self.handle_ack(storage, &packet);
return TickResponse {
message_rx_id,
message_ack_id,
};
}
}
}
......@@ -101,7 +116,10 @@ impl RadioController {
Some(())
});
(false, None)
TickResponse {
message_rx_id: None,
message_ack_id: None,
}
}
pub fn is_busy_rxing(&mut self, spi: &mut MySpi) -> bool {
......@@ -212,7 +230,7 @@ impl RadioController {
spi: &mut MySpi,
storage: &mut Storage,
packet: &Packet<MAX_PACKET_LEN>,
) -> Option<()> {
) -> Option<u16> {
let settings = storage.settings();
// filter to only packets destined for us
......@@ -252,9 +270,9 @@ impl RadioController {
msg.ack_number = dest.ack_num();
storage.push_message(msg);
let id = storage.push_message(msg);
Some(())
Some(id)
}
fn send_ack(
......
......@@ -20,6 +20,7 @@ const MESSAGE_LENGTH: usize =
const MAX_MESSAGES: usize = 1024;
pub const MESSAGE_HEADER_END: usize =
MESSAGE_HEADER_START + MESSAGE_HEADER_SIZE + MAX_MESSAGES * MESSAGE_LENGTH;
const MAX_ADDRESSEES: usize = 32;
const MAX_RETRIES: u8 = 5;
......@@ -372,7 +373,7 @@ pub struct AddresseeIter<'a, 'b> {
group: &'a MessageGroup,
manager: &'b FlashManager,
i: u16,
seen: FnvIndexSet<(String<MAX_CONTACT_CALLSIGN_LENGTH>, u8), MAX_MESSAGES>,
seen: FnvIndexSet<(String<MAX_CONTACT_CALLSIGN_LENGTH>, u8), MAX_ADDRESSEES>,
}
impl<'a, 'b> AddresseeIter<'a, 'b> {
......@@ -393,6 +394,10 @@ impl<'a, 'b> Iterator for AddresseeIter<'a, 'b> {
type Item = (String<MAX_CONTACT_CALLSIGN_LENGTH>, u8, bool);
fn next(&mut self) -> Option<Self::Item> {
if self.seen.len() == self.seen.capacity() {
return None;
}
while self.i > 0 {
self.i -= 1;
......
use core::convert::Infallible;
use embedded_hal::digital::v2::OutputPin;
const VIBRATE_ON_TIME_MS: u64 = 1000;
const VIBRATE_OFF_TIME_MS: u64 = 1500;
const VIBRATE_TIMES: u8 = 2;
enum VibrateState {
Off,
VibrateOn(u8),
VibrateOff(u8),
}
pub struct Vibrator<P: OutputPin<Error = Infallible>> {
pin: P,
state: VibrateState,
}
impl<P: OutputPin<Error = Infallible>> Vibrator<P> {
pub fn new(mut pin: P) -> Self {
pin.set_high().unwrap();
Self {
pin,
state: VibrateState::Off,
}
}
// Returns the # of ms until step should be called
pub fn activate(&mut self) -> u64 {
self.state = VibrateState::VibrateOn(0);
self.pin.set_low().unwrap();
VIBRATE_ON_TIME_MS
}
// Returns the # of ms until this should be called again
pub fn step(&mut self) -> Option<u64> {
match self.state {
VibrateState::Off => None,
VibrateState::VibrateOn(t) => {
self.state = VibrateState::VibrateOff(t);
self.pin.set_high().unwrap();
Some(VIBRATE_OFF_TIME_MS)
}
VibrateState::VibrateOff(t) => {
if t >= VIBRATE_TIMES - 1 {
self.state = VibrateState::Off;
None
} else {
self.state = VibrateState::VibrateOn(t + 1);
self.pin.set_low().unwrap();
Some(VIBRATE_ON_TIME_MS)
}
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment