Skip to content

Commit

Permalink
Merge pull request tock#4233 from alistair23/alistair/rainfall
Browse files Browse the repository at this point in the history
Add support for DFRobot Rain Sensor
  • Loading branch information
ppannuto authored Jan 17, 2025
2 parents 6836d23 + 2172074 commit dd1eaa1
Show file tree
Hide file tree
Showing 12 changed files with 644 additions and 1 deletion.
4 changes: 4 additions & 0 deletions boards/apollo3/lora_things_plus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@ atecc508a = []
# If the sensor is attached via the I2C Qwiic connecter you should
# enable this feature.
chirp_i2c_moisture = []

# This feature enables support for the DFRobot Rainfall Sensor.
# https://wiki.dfrobot.com/SKU_SEN0575_Gravity_Rainfall_Sensor
dfrobot_i2c_rainfall = []
5 changes: 5 additions & 0 deletions boards/apollo3/lora_things_plus/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ test-atecc508a:
test-chirp_i2c_moisture:
$(Q)OBJCOPY=${OBJCOPY} PORT=$(PORT) $(CARGO) test $(NO_RUN) \
--bin $(PLATFORM) --release --features chirp_i2c_moisture

.PHONY: test-dfrobot_i2c_rainfall
test-dfrobot_i2c_rainfall:
$(Q)OBJCOPY=${OBJCOPY} PORT=$(PORT) $(CARGO) test $(NO_RUN) \
--bin $(PLATFORM) --release --features dfrobot_i2c_rainfall
54 changes: 53 additions & 1 deletion boards/apollo3/lora_things_plus/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use {
kernel::hil::rng::Rng,
};

#[cfg(feature = "chirp_i2c_moisture")]
#[cfg(any(feature = "chirp_i2c_moisture", feature = "dfrobot_i2c_rainfall"))]
use capsules_core::virtualizers::virtual_i2c::MuxI2C;

/// Support routines for debugging I/O.
Expand Down Expand Up @@ -128,6 +128,13 @@ const LORA_GPIO_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhyGPIO as u
type ChirpI2cMoistureType = components::chirp_i2c_moisture::ChirpI2cMoistureComponentType<
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
>;
type DFRobotRainFallType = components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponentType<
capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
'static,
apollo3::stimer::STimer<'static>,
>,
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
>;
type BME280Sensor = components::bme280::Bme280ComponentType<
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
>;
Expand Down Expand Up @@ -170,6 +177,7 @@ struct LoRaThingsPlus {
humidity: &'static HumidityDriver,
air_quality: &'static capsules_extra::air_quality::AirQualitySensor<'static>,
moisture: Option<&'static components::moisture::MoistureComponentType<ChirpI2cMoistureType>>,
rainfall: Option<&'static components::rainfall::RainFallComponentType<DFRobotRainFallType>>,
rng: Option<
&'static capsules_core::rng::RngDriver<
'static,
Expand Down Expand Up @@ -287,6 +295,32 @@ unsafe fn setup_chirp_i2c_moisture(
moisture
}

#[cfg(feature = "dfrobot_i2c_rainfall")]
unsafe fn setup_dfrobot_i2c_rainfall(
board_kernel: &'static kernel::Kernel,
_memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
mux_alarm: &'static MuxAlarm<'static, apollo3::stimer::STimer<'static>>,
) -> &'static components::rainfall::RainFallComponentType<DFRobotRainFallType> {
let dfrobot_rainfall =
components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponent::new(
mux_i2c, 0x1D, mux_alarm,
)
.finalize(components::dfrobot_rainfall_sensor_component_static!(
apollo3::stimer::STimer<'static>,
apollo3::iom::Iom<'static>
));

let rainfall = components::rainfall::RainFallComponent::new(
board_kernel,
capsules_extra::rainfall::DRIVER_NUM,
dfrobot_rainfall,
)
.finalize(components::rainfall_component_static!(DFRobotRainFallType));

rainfall
}

/// Mapping of integer syscalls to objects that implement syscalls.
impl SyscallDriverLookup for LoRaThingsPlus {
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
Expand Down Expand Up @@ -320,6 +354,13 @@ impl SyscallDriverLookup for LoRaThingsPlus {
f(None)
}
}
capsules_extra::rainfall::DRIVER_NUM => {
if let Some(rainfall) = self.rainfall {
f(Some(rainfall))
} else {
f(None)
}
}
_ => f(None),
}
}
Expand Down Expand Up @@ -532,6 +573,16 @@ unsafe fn setup() -> (
#[cfg(not(feature = "chirp_i2c_moisture"))]
let moisture = None;

#[cfg(feature = "dfrobot_i2c_rainfall")]
let rainfall = Some(setup_dfrobot_i2c_rainfall(
board_kernel,
&memory_allocation_cap,
mux_i2c,
mux_alarm,
));
#[cfg(not(feature = "dfrobot_i2c_rainfall"))]
let rainfall = None;

#[cfg(feature = "atecc508a")]
let rng = Some(setup_atecc508a(
board_kernel,
Expand Down Expand Up @@ -764,6 +815,7 @@ unsafe fn setup() -> (
humidity,
air_quality,
moisture,
rainfall,
rng,
scheduler,
systick,
Expand Down
110 changes: 110 additions & 0 deletions boards/components/src/dfrobot_rainfall_sensor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Components for the DFRobot Rainfall Sensor.
//! <https://wiki.dfrobot.com/SKU_SEN0575_Gravity_Rainfall_Sensor>
//!
//! Usage
//! -----
//! ```rust
//! let dfrobot_rainfall =
//! components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponent::new(mux_i2c, 0x1D)
//! .finalize(components::dfrobot_rainfall_sensor_component_static!(
//! apollo3::iom::Iom<'static>
//! ));
//! ```
use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
use capsules_core::virtualizers::virtual_i2c::{I2CDevice, MuxI2C};
use capsules_extra::dfrobot_rainfall_sensor::{DFRobotRainFall, BUFFER_SIZE};
use core::mem::MaybeUninit;
use kernel::component::Component;
use kernel::hil::i2c;
use kernel::hil::time;
use kernel::hil::time::Alarm;

// Setup static space for the objects.
#[macro_export]
macro_rules! dfrobot_rainfall_sensor_component_static {
($A:ty, $I:ty $(,)?) => {{
let i2c_device =
kernel::static_buf!(capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, $I>);
let i2c_buffer =
kernel::static_buf!([u8; capsules_extra::dfrobot_rainfall_sensor::BUFFER_SIZE]);
let dfrobot_rainfall_sensor = kernel::static_buf!(
capsules_extra::dfrobot_rainfall_sensor::DFRobotRainFall<
'static,
VirtualMuxAlarm<'static, $A>,
capsules_core::virtualizers::virtual_i2c::I2CDevice<$I>,
>
);
let alarm = kernel::static_buf!(
capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
);

(i2c_device, i2c_buffer, dfrobot_rainfall_sensor, alarm)
};};
}

pub type DFRobotRainFallSensorComponentType<A, I> =
capsules_extra::dfrobot_rainfall_sensor::DFRobotRainFall<'static, A, I>;

pub struct DFRobotRainFallSensorComponent<
A: 'static + time::Alarm<'static>,
I: 'static + i2c::I2CMaster<'static>,
> {
i2c_mux: &'static MuxI2C<'static, I>,
i2c_address: u8,
alarm_mux: &'static MuxAlarm<'static, A>,
}

impl<A: 'static + time::Alarm<'static>, I: 'static + i2c::I2CMaster<'static>>
DFRobotRainFallSensorComponent<A, I>
{
pub fn new(
i2c: &'static MuxI2C<'static, I>,
i2c_address: u8,
alarm_mux: &'static MuxAlarm<'static, A>,
) -> Self {
DFRobotRainFallSensorComponent {
i2c_mux: i2c,
i2c_address,
alarm_mux,
}
}
}

impl<A: 'static + time::Alarm<'static>, I: 'static + i2c::I2CMaster<'static>> Component
for DFRobotRainFallSensorComponent<A, I>
{
type StaticInput = (
&'static mut MaybeUninit<I2CDevice<'static, I>>,
&'static mut MaybeUninit<[u8; BUFFER_SIZE]>,
&'static mut MaybeUninit<
DFRobotRainFall<'static, VirtualMuxAlarm<'static, A>, I2CDevice<'static, I>>,
>,
&'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
);
type Output =
&'static DFRobotRainFall<'static, VirtualMuxAlarm<'static, A>, I2CDevice<'static, I>>;

fn finalize(self, s: Self::StaticInput) -> Self::Output {
let dfrobot_rainfall_sensor_i2c = s.0.write(I2CDevice::new(self.i2c_mux, self.i2c_address));
let i2c_buffer = s.1.write([0; BUFFER_SIZE]);
let alarm = s.3.write(VirtualMuxAlarm::new(self.alarm_mux));
alarm.setup();

let dfrobot_rainfall_sensor = s.2.write(DFRobotRainFall::new(
dfrobot_rainfall_sensor_i2c,
i2c_buffer,
alarm,
));

alarm.set_alarm_client(dfrobot_rainfall_sensor);
dfrobot_rainfall_sensor_i2c.set_client(dfrobot_rainfall_sensor);
dfrobot_rainfall_sensor.startup();
dfrobot_rainfall_sensor
}
}
2 changes: 2 additions & 0 deletions boards/components/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub mod dac;
pub mod date_time;
pub mod debug_queue;
pub mod debug_writer;
pub mod dfrobot_rainfall_sensor;
pub mod eui64;
pub mod flash;
pub mod fm25cl;
Expand Down Expand Up @@ -71,6 +72,7 @@ pub mod process_console;
pub mod process_printer;
pub mod proximity;
pub mod pwm;
pub mod rainfall;
pub mod rf233;
pub mod rng;
pub mod sched;
Expand Down
69 changes: 69 additions & 0 deletions boards/components/src/rainfall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Component for any rainfall sensor.
//!
//! Usage
//! -----
//! ```rust
//! let rainfall = components::rainfall::RainFallComponent::new(
//! board_kernel,
//! capsules_extra::rainfall::DRIVER_NUM,
//! dfrobot_rainfall,
//! )
//! .finalize(components::rainfall_component_static!(DFRobotRainFallType));
//! ```
use capsules_extra::rainfall::RainFallSensor;
use core::mem::MaybeUninit;
use kernel::capabilities;
use kernel::component::Component;
use kernel::create_capability;
use kernel::hil;

#[macro_export]
macro_rules! rainfall_component_static {
($H: ty $(,)?) => {{
kernel::static_buf!(capsules_extra::rainfall::RainFallSensor<'static, $H>)
};};
}

pub type RainFallComponentType<H> = capsules_extra::rainfall::RainFallSensor<'static, H>;

pub struct RainFallComponent<T: 'static + hil::sensors::RainFallDriver<'static>> {
board_kernel: &'static kernel::Kernel,
driver_num: usize,
sensor: &'static T,
}

impl<T: 'static + hil::sensors::RainFallDriver<'static>> RainFallComponent<T> {
pub fn new(
board_kernel: &'static kernel::Kernel,
driver_num: usize,
sensor: &'static T,
) -> RainFallComponent<T> {
RainFallComponent {
board_kernel,
driver_num,
sensor,
}
}
}

impl<T: 'static + hil::sensors::RainFallDriver<'static>> Component for RainFallComponent<T> {
type StaticInput = &'static mut MaybeUninit<RainFallSensor<'static, T>>;
type Output = &'static RainFallSensor<'static, T>;

fn finalize(self, s: Self::StaticInput) -> Self::Output {
let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);

let rainfall = s.write(RainFallSensor::new(
self.sensor,
self.board_kernel.create_grant(self.driver_num, &grant_cap),
));

hil::sensors::RainFallDriver::set_client(self.sensor, rainfall);
rainfall
}
}
1 change: 1 addition & 0 deletions capsules/core/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub enum NUM {
Pressure = 0x60008,
Distance = 0x60009,
Moisture = 0x6000A,
RainFall = 0x6000B,

// Sensor ICs
Tsl2561 = 0x70000,
Expand Down
2 changes: 2 additions & 0 deletions capsules/extra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ These implement a driver to setup and read various physical sensors.
- **[CCS811](src/ccs811.rs)**: VOC gas sensor.
- **[Chirp I2C Moisture](src/chirp_i2c_moisture.rs)**: I2C moisture sensor
from Chirp project.
- **[DFRobot Rainfall Sensor](src/dfrobot_rainfall_sensor.rs)**: Rainfall sensor.
- **[FXOS8700CQ](src/fxos8700cq.rs)**: Accelerometer and magnetometer.
- **[HS3003](src/hs3003.rs)**: Temperature and humidity sensor.
- **[HTS221](src/hts221.rs)**: Temperature and humidity sensor.
Expand Down Expand Up @@ -130,6 +131,7 @@ These provide common and better abstractions for userspace.
- **[Pressure](src/pressure.rs)**: Pressure sensors.
- **[Proximity](src/proximity.rs)**: Proximity sensors.
- **[PWM](src/pwm.rs)**: Pulse-width modulation support.
- **[Rainfall](src/rainfall.rs)**: Query rainfall sensors.
- **[Read Only State](src/read_only_state.rs)**: Read-only state sharing.
- **[Screen](src/screen.rs)**: Displays and screens.
- **[Screen Shared](src/screen_shared.rs)**: App-specific screen windows.
Expand Down
Loading

0 comments on commit dd1eaa1

Please sign in to comment.