diff --git a/pmme-device/rust-version/.cargo/config.toml b/pmme-device/rust-version/.cargo/config.toml index f632639..246270b 100644 --- a/pmme-device/rust-version/.cargo/config.toml +++ b/pmme-device/rust-version/.cargo/config.toml @@ -3,7 +3,8 @@ target = "xtensa-esp32-espidf" [target.xtensa-esp32-espidf] linker = "ldproxy" -runner = "espflash flash --monitor" +# runner = "espflash flash --monitor --speed 921600 # or even 1500000" +runner = "espflash flash --monitor --baud 921600" rustflags = [ "--cfg", "espidf_time64"] [unstable] diff --git a/pmme-device/rust-version/Cargo.toml b/pmme-device/rust-version/Cargo.toml index 39efb1c..cc2e393 100644 --- a/pmme-device/rust-version/Cargo.toml +++ b/pmme-device/rust-version/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rust-version" +name = "pmme-device" version = "0.1.0" authors = ["Joseph Ferano "] edition = "2021" @@ -7,7 +7,7 @@ resolver = "2" rust-version = "1.77" [[bin]] -name = "rust-version" +name = "pmme-device" harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors [profile.release] @@ -20,11 +20,15 @@ opt-level = "z" [features] default = [] -experimental = ["esp-idf-svc/experimental"] +# experimental = ["esp-idf-svc/experimental"] [dependencies] log = "0.4" esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } +anyhow = "1.0.98" +embedded-graphics = "0.8.1" +ssd1306 = "0.10.0" +# esp-idf-hal = { version = "0.45.2", features = ["std"] } [build-dependencies] embuild = "0.33" diff --git a/pmme-device/rust-version/rust.raw b/pmme-device/rust-version/rust.raw new file mode 100644 index 0000000..cbb43ec Binary files /dev/null and b/pmme-device/rust-version/rust.raw differ diff --git a/pmme-device/rust-version/src/main.rs b/pmme-device/rust-version/src/main.rs index 43b4fbd..70dc6e3 100644 --- a/pmme-device/rust-version/src/main.rs +++ b/pmme-device/rust-version/src/main.rs @@ -1,13 +1,87 @@ -fn main() { +use anyhow::{bail, Result, Context, anyhow}; +use esp_idf_svc::hal::delay::FreeRtos; +use esp_idf_svc::hal::i2c::{I2cConfig, I2cDriver}; +use esp_idf_svc::hal::peripherals::Peripherals; +use esp_idf_svc::hal::delay::BLOCK; +use esp_idf_svc::hal::prelude::FromValueType; + +use embedded_graphics::{ + mono_font::{ + ascii::{FONT_10X20, FONT_5X8, FONT_6X12, FONT_9X15}, + MonoTextStyle, MonoTextStyleBuilder, + }, + image::{Image, ImageRaw}, + pixelcolor::BinaryColor, + prelude::*, + text::Text, +}; +use ssd1306::{I2CDisplayInterface, Ssd1306, size::*, rotation::*}; +use ssd1306::mode::DisplayConfig; + +use std::thread; +use log::info; + +const SSD1306_ADDRESS: u8 = 0x3c; + +fn oled_task(mut i2c: I2cDriver) -> Result<()> { + info!("Staring OLED Task"); + + let interface = I2CDisplayInterface::new(i2c); + let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0) + .into_buffered_graphics_mode(); + + display.init().unwrap(); + + let raw: ImageRaw = ImageRaw::new(include_bytes!("../rust.raw"), 64); + let im = Image::new(&raw, Point::new(32, 0)); + + im.draw(&mut display).unwrap(); + display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?; + + FreeRtos::delay_ms(3000); + loop { + display.clear(BinaryColor::Off).map_err(|e| anyhow!("Could not clear display! {:?}", e))?; + Text::new( + "PM 2.5: 4", + Point::new(20, 40), + MonoTextStyle::new(&FONT_10X20, BinaryColor::On), + ).draw(&mut display).map_err(|e| anyhow!("Could not draw text! {:?}", e))?; + display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?; + FreeRtos::delay_ms(500); + } +} + +fn main() -> Result<()> { // It is necessary to call this function once. Otherwise some patches to the runtime // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 esp_idf_svc::sys::link_patches(); - // Bind the log crate to the ESP Logging facilities + // Initialize NVS + // esp_idf_hal::nvs::EspDefaultNvsPartition::take() + // .context("Could not take NVS partition")?; esp_idf_svc::log::EspLogger::initialize_default(); - loop { - log::info!("Hello, world!"); - std::thread::sleep(std::time::Duration::from_secs(1)); + let peripherals = Peripherals::take()?; + let i2c = peripherals.i2c0; + let sda = peripherals.pins.gpio21; + let scl = peripherals.pins.gpio22; + + let config = I2cConfig::new().baudrate(100.kHz().into()); + let i2c = I2cDriver::new(i2c, sda, scl, &config)?; + + let handles = vec! [ + thread::spawn(move || { + if let Err(e) = oled_task(i2c) { + log::error!("OLED Task Error: {:?}", e); + } + }), + // thread::spawn(move || { + + // }), + ]; + for h in handles { + h.join().unwrap(); } + + Ok(()) }