bas
This commit is contained in:
parent
452abc36a5
commit
b89972c5e3
|
|
@ -757,6 +757,7 @@ dependencies = [
|
||||||
"embassy-nrf",
|
"embassy-nrf",
|
||||||
"embassy-sync 0.7.2",
|
"embassy-sync 0.7.2",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
|
"futures",
|
||||||
"nrf-softdevice",
|
"nrf-softdevice",
|
||||||
"panic-halt",
|
"panic-halt",
|
||||||
"panic-probe",
|
"panic-probe",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ embassy-time = { version = "0.5.0", features = ["tick-hz-32_768", "defmt", "defm
|
||||||
panic-halt = "1.0.0"
|
panic-halt = "1.0.0"
|
||||||
panic-probe = { version = "1.0.0", features = ["print-defmt"], optional = true }
|
panic-probe = { version = "1.0.0", features = ["print-defmt"], optional = true }
|
||||||
nrf-softdevice = { version = "0.1.0", features = ["s140", "ble-peripheral", "nrf52840", "nrf-softdevice-s140", "critical-section-impl", "defmt", "nrf52840-pac", "critical-section", "ble-gatt-server"] }
|
nrf-softdevice = { version = "0.1.0", features = ["s140", "ble-peripheral", "nrf52840", "nrf-softdevice-s140", "critical-section-impl", "defmt", "nrf52840-pac", "critical-section", "ble-gatt-server"] }
|
||||||
|
futures = { version = "0.3", default-features = false, features = [] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "odesa"
|
name = "odesa"
|
||||||
|
|
|
||||||
51
src/main.rs
51
src/main.rs
|
|
@ -5,7 +5,7 @@ mod fmt;
|
||||||
|
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ops::{AddAssign, SubAssign};
|
use core::ops::{AddAssign, SubAssign};
|
||||||
use defmt::Format;
|
use defmt::{error, Format};
|
||||||
#[cfg(not(feature = "defmt"))]
|
#[cfg(not(feature = "defmt"))]
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
|
|
@ -16,18 +16,20 @@ use defmt::info;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::{join3, join4};
|
use embassy_futures::join::{join3, join4};
|
||||||
use embassy_nrf::gpio::{AnyPin, Input, OutputDrive, Pull};
|
use embassy_nrf::gpio::{AnyPin, Input, OutputDrive, Pull};
|
||||||
use embassy_nrf::interrupt::Priority;
|
use embassy_nrf::interrupt::{InterruptExt, Priority};
|
||||||
use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
|
use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
|
||||||
use embassy_nrf::{bind_interrupts, saadc, Peri};
|
use embassy_nrf::{bind_interrupts, interrupt, saadc, Peri};
|
||||||
use embassy_nrf::peripherals::SAADC;
|
use embassy_nrf::peripherals::SAADC;
|
||||||
use embassy_nrf::saadc::{ChannelConfig, Gain, Reference, Saadc};
|
use embassy_nrf::saadc::{ChannelConfig, Gain, Reference, Saadc};
|
||||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::signal::Signal;
|
use embassy_sync::signal::Signal;
|
||||||
use embassy_time::{with_timeout, Duration, Timer};
|
use embassy_time::{with_timeout, Duration, Timer};
|
||||||
|
use futures::future::{select, Either};
|
||||||
|
use futures::pin_mut;
|
||||||
use nrf_softdevice::{raw, Softdevice};
|
use nrf_softdevice::{raw, Softdevice};
|
||||||
use nrf_softdevice::ble::advertisement_builder::{Flag, LegacyAdvertisementBuilder, LegacyAdvertisementPayload, ServiceList, ServiceUuid16};
|
use nrf_softdevice::ble::advertisement_builder::{Flag, LegacyAdvertisementBuilder, LegacyAdvertisementPayload, ServiceList, ServiceUuid16};
|
||||||
use nrf_softdevice::ble::{peripheral, gatt_server};
|
use nrf_softdevice::ble::{peripheral, gatt_server, Connection};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Format)]
|
#[derive(Copy, Clone, Eq, PartialEq, Format)]
|
||||||
enum SysAction {
|
enum SysAction {
|
||||||
|
|
@ -145,9 +147,11 @@ async fn main(spawner: Spawner) {
|
||||||
let server = Server::new(sd).expect("failed to enable softdevice");
|
let server = Server::new(sd).expect("failed to enable softdevice");
|
||||||
|
|
||||||
let mut channel_config = ChannelConfig::single_ended(p.P0_31.reborrow());
|
let mut channel_config = ChannelConfig::single_ended(p.P0_31.reborrow());
|
||||||
|
interrupt::SAADC.set_priority(Priority::P3);
|
||||||
channel_config.gain = Gain::GAIN1_6;
|
channel_config.gain = Gain::GAIN1_6;
|
||||||
channel_config.reference = Reference::INTERNAL;
|
channel_config.reference = Reference::INTERNAL;
|
||||||
let saadc = Saadc::new(p.SAADC, AdcIrqs, saadc::Config::default(), [channel_config]);
|
let saadc = Saadc::new(p.SAADC, AdcIrqs, saadc::Config::default(), [channel_config]);
|
||||||
|
saadc.calibrate().await;
|
||||||
|
|
||||||
let pwm_text = SimplePwm::new_3ch(p.PWM0, p.P1_00, p.P1_04, p.P1_06, &Default::default());
|
let pwm_text = SimplePwm::new_3ch(p.PWM0, p.P1_00, p.P1_04, p.P1_06, &Default::default());
|
||||||
let pwm_heart = SimplePwm::new_3ch(p.PWM2, p.P0_17, p.P0_20, p.P0_22, &Default::default());
|
let pwm_heart = SimplePwm::new_3ch(p.PWM2, p.P0_17, p.P0_20, p.P0_22, &Default::default());
|
||||||
|
|
@ -155,13 +159,13 @@ async fn main(spawner: Spawner) {
|
||||||
spawner.spawn(touch_button(p.P0_08.into())).expect("failed to spawn touch task");
|
spawner.spawn(touch_button(p.P0_08.into())).expect("failed to spawn touch task");
|
||||||
spawner.spawn(actions_task()).expect("failed to spawn actions task");
|
spawner.spawn(actions_task()).expect("failed to spawn actions task");
|
||||||
spawner.spawn(softdevice_task(sd)).expect("failed to spawn softdevice task");
|
spawner.spawn(softdevice_task(sd)).expect("failed to spawn softdevice task");
|
||||||
spawner.spawn(battery_task(saadc)).expect("failed to spawn softdevice task");
|
// spawner.spawn(battery_task(saadc)).expect("failed to spawn softdevice task");
|
||||||
|
|
||||||
join4(gatt_task(server, sd), moving_radar(p.P0_06.into()), heartbeat_task(pwm_heart), light_task(pwm_text)).await;
|
join4(gatt_task(server, saadc, sd), moving_radar(p.P0_06.into()), heartbeat_task(pwm_heart), light_task(pwm_text)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn gatt_task(server: Server, sd: &'static Softdevice) {
|
async fn gatt_task(server: Server, mut saadc: Saadc<'static, 1>, sd: &'static Softdevice) {
|
||||||
static ADV_DATA: LegacyAdvertisementPayload = LegacyAdvertisementBuilder::new()
|
static ADV_DATA: LegacyAdvertisementPayload = LegacyAdvertisementBuilder::new()
|
||||||
.flags(&[Flag::GeneralDiscovery, Flag::LE_Only])
|
.flags(&[Flag::GeneralDiscovery, Flag::LE_Only])
|
||||||
.services_16(ServiceList::Complete, &[ServiceUuid16::BATTERY])
|
.services_16(ServiceList::Complete, &[ServiceUuid16::BATTERY])
|
||||||
|
|
@ -185,11 +189,9 @@ async fn gatt_task(server: Server, sd: &'static Softdevice) {
|
||||||
|
|
||||||
info!("advertising done!");
|
info!("advertising done!");
|
||||||
|
|
||||||
// Run the GATT server on the connection. This returns when the connection gets disconnected.
|
|
||||||
//
|
let battery_fut = battery_task(&mut saadc, &server, &conn);
|
||||||
// Event enums (ServerEvent's) are generated by nrf_softdevice::gatt_server
|
let gatt_fut = gatt_server::run(&conn, &server, |e| match e {
|
||||||
// proc macro when applied to the Server struct above
|
|
||||||
let e = gatt_server::run(&conn, &server, |e| match e {
|
|
||||||
ServerEvent::Bas(e) => match e {
|
ServerEvent::Bas(e) => match e {
|
||||||
BatteryServiceEvent::BatteryLevelCccdWrite { notifications } => {
|
BatteryServiceEvent::BatteryLevelCccdWrite { notifications } => {
|
||||||
info!("battery notifications: {}", notifications)
|
info!("battery notifications: {}", notifications)
|
||||||
|
|
@ -265,10 +267,19 @@ async fn gatt_task(server: Server, sd: &'static Softdevice) {
|
||||||
info!("text color indications: {}, notifications: {}", indications, notifications)
|
info!("text color indications: {}, notifications: {}", indications, notifications)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
.await;
|
|
||||||
|
|
||||||
info!("gatt_server run exited with error: {:?}", e);
|
pin_mut!(battery_fut);
|
||||||
|
pin_mut!(gatt_fut);
|
||||||
|
|
||||||
|
let _ = match select(battery_fut, gatt_fut).await {
|
||||||
|
Either::Left((_, _)) => {
|
||||||
|
info!("Battery encountered an error and stopped!")
|
||||||
|
}
|
||||||
|
Either::Right((e, _)) => {
|
||||||
|
info!("GATT run exited with error: {:?}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,8 +341,7 @@ async fn touch_button(pin: Peri<'static, AnyPin>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
async fn battery_task<'a>(saadc: &'a mut Saadc<'_, 1>, server: &'a Server, connection: &'a Connection) {
|
||||||
async fn battery_task(mut saadc: Saadc<'static, 1>) {
|
|
||||||
const REFERENCE: f32 = 3.6;
|
const REFERENCE: f32 = 3.6;
|
||||||
let mut measurements = [0i16; 4];
|
let mut measurements = [0i16; 4];
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
@ -348,7 +358,10 @@ async fn battery_task(mut saadc: Saadc<'static, 1>) {
|
||||||
let total = (measurements.iter().sum::<i16>() / measurements.len() as i16) as u16;
|
let total = (measurements.iter().sum::<i16>() / measurements.len() as i16) as u16;
|
||||||
let percent = battery_mv_to_percent(total);
|
let percent = battery_mv_to_percent(total);
|
||||||
info!("Battery: {=i16}, {=u16}, {}%", voltage, total, percent);
|
info!("Battery: {=i16}, {=u16}, {}%", voltage, total, percent);
|
||||||
Timer::after_millis(2000).await;
|
if let Err(e) = server.bas.battery_level_notify(connection, &percent) {
|
||||||
|
error!("Error notifying battery level: {:?}", e);
|
||||||
|
}
|
||||||
|
Timer::after_millis(60000).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -403,7 +416,7 @@ async fn actions_task() {
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn radar_task() {
|
async fn radar_task() {
|
||||||
const MAX_TIME: usize = 24;
|
const MAX_TIME: usize = 480;
|
||||||
let mut time = MAX_TIME;
|
let mut time = MAX_TIME;
|
||||||
loop {
|
loop {
|
||||||
let action = {
|
let action = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue