Skip to content

Commit

Permalink
18-introduce-dfplayer-mini (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
1-rafael-1 committed Jul 13, 2024
1 parent a4918df commit 841ff8d
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 19 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ heapless = "0.8"
usbd-hid = "0.7.0"
serde = { version = "1.0.203", default-features = false, features = ["derive"] }
serde-json-core = "0.5.1"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal = "1.0"
embedded-hal-async = "1.0"
embedded-hal-bus = { version = "0.2.0", features = ["async"] }
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
embedded-io-async = { version = "0.6.0", features = ["defmt-03"] }
embedded-storage = { version = "0.3" }
static_cell = "2"
portable-atomic = { version = "1.5", features = ["critical-section"] }
Expand All @@ -93,6 +93,7 @@ embedded-sdmmc = "0.7.0"
reqwless = { version = "0.12.0", features = ["defmt"] }
tinybmp = "0.6.0"
assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev = "94ad10e2729afdf0fd5a77cd12e68409a982f58a" }
dfplayer-serial = { git = "https://github.com/1-rafael-1/dfplayer-serial" }


[build-dependencies]
Expand Down
58 changes: 43 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
#![no_main]

use crate::task::btn_mgr::{blue_button, green_button, yellow_button};
use crate::task::dfplayer::sound;
use crate::task::display::display;
use crate::task::resources::{
AssignedResources, BlueButtonResources, DisplayResources, GreenButtonResources,
NeopixelResources, RtcResources, WifiResources, YellowButtonResources,
AssignedResources, BlueButtonResources, DfPlayerResources, DisplayResources,
GreenButtonResources, NeopixelResources, RtcResources, TaskConfig, WifiResources,
YellowButtonResources,
};
use crate::task::time_updater::connect_and_update_rtc;
use core::cell::RefCell;
// for WiFi
use defmt::*; // global logger
use defmt::*;
use embassy_executor::Executor;
use embassy_executor::Spawner;
use embassy_rp::multicore::{spawn_core1, Stack};
Expand All @@ -37,22 +38,41 @@ async fn main(spawner: Spawner) {
// and assign the peripherals to the places, where we will use them
let r = split_resources!(p);

// configure, which tasks to spawn. For a production build we need all tasks, for troubleshooting we can disable some
// the tasks are all spawned in main.rs, so we can disable them here
// clutter in the output aside, the binary size is conveniently reduced by disabling tasks
let mut task_config = TaskConfig::new();
// task_config.spawn_connect_and_update_rtc = false;
// task_config.spawn_btn_green = false;
// task_config.spawn_btn_blue = false;
// task_config.spawn_btn_yellow = false;
// task_config.spawn_neopixel = false;
// task_config.spawn_display = false;
// task_config.spawn_dfplayer = true;

// Buttons
spawner.spawn(green_button(spawner, r.btn_green)).unwrap();
spawner.spawn(blue_button(spawner, r.btn_blue)).unwrap();
spawner.spawn(yellow_button(spawner, r.btn_yellow)).unwrap();
if task_config.spawn_btn_green {
spawner.spawn(green_button(spawner, r.btn_green)).unwrap();
};
if task_config.spawn_btn_blue {
spawner.spawn(blue_button(spawner, r.btn_blue)).unwrap();
};
if task_config.spawn_btn_yellow {
spawner.spawn(yellow_button(spawner, r.btn_yellow)).unwrap();
};

// RTC

// Initialize the RTC in a static cell, we will need it in multiple places
static RTC: StaticCell<RefCell<Rtc<'static, peripherals::RTC>>> = StaticCell::new();
let rtc_instance: Rtc<'static, peripherals::RTC> = Rtc::new(r.rtc.rtc_inst);
let rtc_ref = RTC.init(RefCell::new(rtc_instance));

// update the RTC
spawner
.spawn(connect_and_update_rtc(spawner, r.wifi, rtc_ref))
.unwrap();
if task_config.spawn_connect_and_update_rtc {
spawner
.spawn(connect_and_update_rtc(spawner, r.wifi, rtc_ref))
.unwrap();
}

// Neopixel
// Note! -> we may need more than one neopixel task eventually, in that case we will need mutexes around the resources
Expand All @@ -69,16 +89,24 @@ async fn main(spawner: Spawner) {
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1.run(|spawner| {
spawner
.spawn(task::neopixel::analog_clock(spawner, r.neopixel))
.unwrap();
if task_config.spawn_neopixel {
spawner
.spawn(task::neopixel::analog_clock(spawner, r.neopixel))
.unwrap();
}
});
},
);

// Display
if task_config.spawn_display {
spawner.spawn(display(spawner, r.display)).unwrap();
}

spawner.spawn(display(spawner, r.display)).unwrap();
// DFPlayer
if task_config.spawn_dfplayer {
spawner.spawn(sound(spawner, r.dfplayer)).unwrap();
}

// Main loop, doing very little
loop {
Expand Down
76 changes: 76 additions & 0 deletions src/task/dfplayer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use crate::task::resources::{DfPlayerResources, Irqs};
use defmt::{info, Debug2Format};
use dfplayer_serial::{DfPlayer, Equalizer, PlayBackSource};
use embassy_executor::Spawner;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::uart::{BufferedUart, Config};
use embassy_time::{Duration, Timer};

#[embassy_executor::task]
pub async fn sound(_spawner: Spawner, r: DfPlayerResources) {
info!("Sound task started");

let mut config = Config::default();
config.baudrate = 9600;

let mut tx_buffer = [0; 256];
let mut rx_buffer = [0; 256];

let mut uart = BufferedUart::new(
r.uart,
Irqs,
r.tx_pin,
r.rx_pin,
&mut tx_buffer,
&mut rx_buffer,
config,
);

let feedback_enable = false; // fails to acknoweledge when enabled
let timeout = Duration::from_secs(1);
let reset_duration_override = Some(Duration::from_millis(1000));

// power pin, not a part of the dfplayer, using a mosfet to control power to the dfplayer because it draws too much current when idle
let mut pwr = Output::new(r.power_pin, Level::Low);

loop {
// power on the dfplayer
info!("Powering on the dfplayer");
pwr.set_high();
Timer::after(Duration::from_secs(1)).await;
info!("Powered on the dfplayer");

let mut dfp_result =
DfPlayer::try_new(&mut uart, feedback_enable, timeout, reset_duration_override).await;

match dfp_result {
Ok(_) => info!("DfPlayer initialized successfully"),
Err(ref e) => info!(
"DfPlayer initialization failed with error {:?}",
Debug2Format(&e)
),
}

info!("Playing sound");
if let Ok(ref mut dfp) = dfp_result {
let _ = dfp.volume(5).await;
Timer::after(Duration::from_millis(100)).await;
let _ = dfp.equalizer(Equalizer::Classic).await;
Timer::after(Duration::from_millis(100)).await;
let _ = dfp.playback_source(PlayBackSource::SDCard).await;
Timer::after(Duration::from_millis(100)).await;
let _ = dfp.play(1).await;
Timer::after(Duration::from_secs(100)).await;
} else {
info!("DfPlayer not initialized, skipping sound playback.");
}
Timer::after(Duration::from_secs(10)).await;

// power off the dfplayer
info!("Powering off the dfplayer");
pwr.set_low();
Timer::after(Duration::from_secs(1)).await;

Timer::after(Duration::from_secs(10)).await;
}
}
4 changes: 2 additions & 2 deletions src/task/display.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::task::resources::{DisplayResources, Irqs};
use defmt::info;
use defmt::*;
use embassy_executor::Spawner;
use embassy_rp::i2c::{Config, I2c};
use embassy_time::{Duration, Timer};
Expand Down Expand Up @@ -154,7 +154,7 @@ impl<'a> Images<'a> {
"bat_100" => self.bat_100 = Image::new(&bmps.bat_100, new_position),
"bat_mains" => self.bat_mains = Image::new(&bmps.bat_mains, new_position),
"settings" => self.settings = Image::new(&bmps.settings, new_position),
_ => panic!("Unknown image name: {}", image_name),
_ => self::panic!("Unknown image name: {}", image_name),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/task/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod btn_mgr;
pub mod dfplayer;
pub mod display;
pub mod neopixel;
pub mod resources;
Expand Down
42 changes: 42 additions & 0 deletions src/task/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use assign_resources::assign_resources;
use embassy_rp::i2c::InterruptHandler as I2cInterruptHandler;
use embassy_rp::peripherals::I2C0;
use embassy_rp::peripherals::PIO0;
use embassy_rp::peripherals::UART1;
use embassy_rp::pio::InterruptHandler;
use embassy_rp::uart::BufferedInterruptHandler;
use embassy_rp::{bind_interrupts, peripherals};

// group the peripherlas into resources, to be used in the tasks
Expand Down Expand Up @@ -39,10 +41,50 @@ assign_resources! {
sda: PIN_12,
i2c0: I2C0,
},
dfplayer: DfPlayerResources {
uart: UART1,
tx_pin: PIN_4,
rx_pin: PIN_5,
rx_dma_ch: DMA_CH2,
tx_dma_ch: DMA_CH3,
power_pin: PIN_8, // not a part of the dfplayer, using a mosfet to control power to the dfplayer because it draws too much current when idle
},
}

// bind the interrupts, on a global scope, until i find a better way
bind_interrupts!(pub struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
I2C0_IRQ => I2cInterruptHandler<I2C0>;
// UART0_IRQ => UartInterruptHandler<UART0>;
UART1_IRQ => BufferedInterruptHandler<UART1>;
});

pub struct TaskConfig {
pub spawn_btn_green: bool,
pub spawn_btn_blue: bool,
pub spawn_btn_yellow: bool,
pub spawn_connect_and_update_rtc: bool,
pub spawn_neopixel: bool,
pub spawn_display: bool,
pub spawn_dfplayer: bool,
}

impl Default for TaskConfig {
fn default() -> Self {
TaskConfig {
spawn_btn_green: true,
spawn_btn_blue: true,
spawn_btn_yellow: true,
spawn_connect_and_update_rtc: true,
spawn_neopixel: true,
spawn_display: true,
spawn_dfplayer: true,
}
}
}

impl TaskConfig {
pub fn new() -> Self {
TaskConfig::default()
}
}

0 comments on commit 841ff8d

Please sign in to comment.