Firmware for the b-parasite board, but in Rust!
at main 3.4 kB view raw
1use bt_hci::cmd::SyncCmd; 2use embassy_futures::join::join; 3use embassy_nrf::{mode, pac, rng}; 4use embassy_time::{Duration, Timer}; 5use nrf_mpsl::MultiprotocolServiceLayer; 6use nrf_sdc::vendor::ZephyrWriteBdAddr; 7use sachy_bthome::BtHomeAd; 8use sachy_fmt::{info, unwrap}; 9use trouble_host::prelude::*; 10 11use crate::{ 12 constants::{ 13 PARA_ADV_DURATION_SECS, PARA_BLE_TX_POWER, PARA_MAX_ADV_INTERVAL_MS, 14 PARA_MIN_ADV_INTERVAL_MS, PARA_NAME, 15 }, 16 state::{ADC_MEASUREMENT, SHTC3_MEASUREMENT, START_MEASUREMENTS}, 17}; 18 19#[embassy_executor::task] 20pub async fn mpsl_task(mpsl: &'static MultiprotocolServiceLayer<'static>) -> ! { 21 mpsl.run().await 22} 23 24pub fn build_sdc<'d, const N: usize>( 25 p: nrf_sdc::Peripherals<'d>, 26 rng: &'d mut rng::Rng<mode::Async>, 27 mpsl: &'d MultiprotocolServiceLayer, 28 mem: &'d mut nrf_sdc::Mem<N>, 29) -> Result<nrf_sdc::SoftdeviceController<'d>, nrf_sdc::Error> { 30 nrf_sdc::Builder::new()? 31 .support_adv()? 32 .build(p, rng, mpsl, mem) 33} 34 35fn build_addr() -> BdAddr { 36 let ficr = pac::FICR; 37 let high = u64::from(ficr.deviceid(1).read()); 38 let addr = high << 32 | u64::from(ficr.deviceid(0).read()); 39 let addr = addr | 0x0000_c000_0000_0000; 40 BdAddr::new(unwrap!(addr.to_le_bytes()[..6].try_into())) 41} 42 43#[embassy_executor::task] 44pub async fn run(controller: nrf_sdc::SoftdeviceController<'static>) { 45 let addr = build_addr(); 46 47 info!("Our address = {:?}", &addr); 48 49 // Set the bluetooth address 50 unwrap!(ZephyrWriteBdAddr::new(addr).exec(&controller).await); 51 52 let mut resources: HostResources<DefaultPacketPool, 0, 0> = HostResources::new(); 53 let stack = trouble_host::new(controller, &mut resources); 54 let Host { 55 mut peripheral, 56 mut runner, 57 .. 58 } = stack.build(); 59 60 let _ = join(runner.run(), async { 61 let mut start_measurements = unwrap!(START_MEASUREMENTS.receiver()); 62 63 let params: AdvertisementParameters = AdvertisementParameters { 64 interval_min: Duration::from_millis(PARA_MIN_ADV_INTERVAL_MS), 65 interval_max: Duration::from_millis(PARA_MAX_ADV_INTERVAL_MS), 66 tx_power: PARA_BLE_TX_POWER, 67 ..Default::default() 68 }; 69 70 loop { 71 start_measurements.changed().await; 72 73 let (adc, shtc3) = join(ADC_MEASUREMENT.wait(), SHTC3_MEASUREMENT.wait()).await; 74 75 let mut ad = BtHomeAd::default(); 76 77 let adv_data = ad 78 .add_data(adc.battery) 79 .add_data(shtc3.temperature) 80 .add_data(adc.lux) 81 .add_data(adc.voltage) 82 .add_data(shtc3.humidity) 83 .add_data(adc.moisture) 84 .add_local_name(PARA_NAME) 85 .encode(); 86 87 info!("Starting advertising"); 88 let advertiser = unwrap!( 89 peripheral 90 .advertise( 91 &params, 92 Advertisement::NonconnectableScannableUndirected { 93 adv_data, 94 scan_data: &[], 95 }, 96 ) 97 .await 98 ); 99 Timer::after_secs(PARA_ADV_DURATION_SECS).await; 100 drop(advertiser); 101 info!("Stopping advertising, sleeping..."); 102 } 103 }) 104 .await; 105}