| @ -0,0 +1,15 @@ | |||||
| [target.xtensa-esp32-none-elf] | |||||
| runner = "espflash flash --monitor --chip esp32 --log-format defmt" | |||||
| [env] | |||||
| DEFMT_LOG="info" | |||||
| [build] | |||||
| rustflags = [ | |||||
| "-C", "link-arg=-nostartfiles", | |||||
| ] | |||||
| target = "xtensa-esp32-none-elf" | |||||
| [unstable] | |||||
| build-std = ["core"] | |||||
| @ -0,0 +1,18 @@ | |||||
| # Generated by Cargo | |||||
| # will have compiled files and executables | |||||
| debug/ | |||||
| target/ | |||||
| .vscode/ | |||||
| # These are backup files generated by rustfmt | |||||
| **/*.rs.bk | |||||
| # MSVC Windows builds of rustc generate these, which store debugging information | |||||
| *.pdb | |||||
| # RustRover | |||||
| # JetBrains specific template is maintained in a separate JetBrains.gitignore that can | |||||
| # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore | |||||
| # and can be added to the global gitignore or merged into this file. For a more nuclear | |||||
| # option (not recommended) you can uncomment the following to ignore the entire idea folder. | |||||
| #.idea/ | |||||
| @ -0,0 +1,45 @@ | |||||
| [package] | |||||
| edition = "2021" | |||||
| name = "e-ink-hello" | |||||
| version = "0.1.0" | |||||
| [[bin]] | |||||
| name = "e-ink-hello" | |||||
| path = "./src/bin/main.rs" | |||||
| [dependencies] | |||||
| critical-section = "1.2.0" | |||||
| defmt = "0.3.10" | |||||
| embassy-executor = { version = "0.7.0", features = [ | |||||
| "defmt", | |||||
| "task-arena-size-20480", | |||||
| ] } | |||||
| embassy-time = "0.4.0" | |||||
| esp-hal = { version = "1.0.0-beta.0", features = [ | |||||
| "defmt", | |||||
| "esp32", | |||||
| "unstable", | |||||
| ] } | |||||
| esp-hal-embassy = { version = "0.7.0", features = ["esp32"] } | |||||
| esp-println = { version = "0.13.0", features = ["defmt-espflash", "esp32"] } | |||||
| static_cell = { version = "2.1.0", features = ["nightly"] } | |||||
| epd-waveshare = { features = [ | |||||
| "graphics", | |||||
| ], git = "https://github.com/ImplFerris/epd-waveshare", branch = "1in54_v2_fix" } | |||||
| embedded-hal-bus = { version = "0.1" } | |||||
| embedded-graphics = "0.8.1" | |||||
| [profile.dev] | |||||
| # Rust debug is too slow. | |||||
| # For debug builds always builds with some optimization | |||||
| opt-level = "s" | |||||
| [profile.release] | |||||
| codegen-units = 1 # LLVM can perform better optimizations using a single thread | |||||
| debug = 2 | |||||
| debug-assertions = false | |||||
| incremental = false | |||||
| lto = 'fat' | |||||
| opt-level = 's' | |||||
| overflow-checks = false | |||||
| @ -0,0 +1,53 @@ | |||||
| fn main() { | |||||
| linker_be_nice(); | |||||
| println!("cargo:rustc-link-arg=-Tdefmt.x"); | |||||
| // make sure linkall.x is the last linker script (otherwise might cause problems with flip-link) | |||||
| println!("cargo:rustc-link-arg=-Tlinkall.x"); | |||||
| } | |||||
| fn linker_be_nice() { | |||||
| let args: Vec<String> = std::env::args().collect(); | |||||
| if args.len() > 1 { | |||||
| let kind = &args[1]; | |||||
| let what = &args[2]; | |||||
| match kind.as_str() { | |||||
| "undefined-symbol" => match what.as_str() { | |||||
| "_defmt_timestamp" => { | |||||
| eprintln!(); | |||||
| eprintln!("💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`"); | |||||
| eprintln!(); | |||||
| } | |||||
| "_stack_start" => { | |||||
| eprintln!(); | |||||
| eprintln!("💡 Is the linker script `linkall.x` missing?"); | |||||
| eprintln!(); | |||||
| } | |||||
| "esp_wifi_preempt_enable" | |||||
| | "esp_wifi_preempt_yield_task" | |||||
| | "esp_wifi_preempt_task_create" => { | |||||
| eprintln!(); | |||||
| eprintln!("💡 `esp-wifi` has no scheduler enabled. Make sure you have the `builtin-scheduler` feature enabled, or that you provide an external scheduler."); | |||||
| eprintln!(); | |||||
| } | |||||
| "embedded_test_linker_file_not_added_to_rustflags" => { | |||||
| eprintln!(); | |||||
| eprintln!("💡 `embedded-test` not found - make sure `embedded-test.x` is added as a linker script for tests"); | |||||
| eprintln!(); | |||||
| } | |||||
| _ => (), | |||||
| }, | |||||
| // we don't have anything helpful for "missing-lib" yet | |||||
| _ => { | |||||
| std::process::exit(1); | |||||
| } | |||||
| } | |||||
| std::process::exit(0); | |||||
| } | |||||
| println!( | |||||
| "cargo:rustc-link-arg=-Wl,--error-handling-script={}", | |||||
| std::env::current_exe().unwrap().display() | |||||
| ); | |||||
| } | |||||
| @ -0,0 +1,33 @@ | |||||
| { | |||||
| "version": 1, | |||||
| "editor": "wokwi", | |||||
| "parts": [ | |||||
| { | |||||
| "type": "board-esp32-devkit-c-v4", | |||||
| "id": "esp", | |||||
| "top": 0.59, | |||||
| "left": 0.67, | |||||
| "attrs": { | |||||
| "flashSize": "16" | |||||
| } | |||||
| } | |||||
| ], | |||||
| "connections": [ | |||||
| [ | |||||
| "esp:TX", | |||||
| "$serialMonitor:RX", | |||||
| "", | |||||
| [] | |||||
| ], | |||||
| [ | |||||
| "esp:RX", | |||||
| "$serialMonitor:TX", | |||||
| "", | |||||
| [] | |||||
| ] | |||||
| ], | |||||
| "serialMonitor": { | |||||
| "display": "terminal", | |||||
| "convertEol": true | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,2 @@ | |||||
| [toolchain] | |||||
| channel = "book-1.0.0-beta" | |||||
| @ -0,0 +1,101 @@ | |||||
| #![no_std] | |||||
| #![no_main] | |||||
| use defmt::info; | |||||
| use embassy_executor::Spawner; | |||||
| use embassy_time::{Delay, Duration, Timer}; | |||||
| use embedded_graphics::mono_font::ascii::FONT_10X20; | |||||
| use embedded_graphics::prelude::*; | |||||
| use epd_waveshare::prelude::WaveshareDisplay; | |||||
| use esp_hal::clock::CpuClock; | |||||
| use esp_hal::timer::timg::TimerGroup; | |||||
| use esp_println as _; | |||||
| use embedded_graphics::mono_font::MonoTextStyleBuilder; | |||||
| use embedded_graphics::text::{Baseline, Text}; | |||||
| use embedded_hal_bus::spi::ExclusiveDevice; | |||||
| use epd_waveshare::color::Color; | |||||
| use epd_waveshare::epd1in54_v2::{Display1in54, Epd1in54}; | |||||
| use esp_hal::gpio::{Input, InputConfig, Level, Output, OutputConfig, Pull}; | |||||
| use esp_hal::spi::master::{Config as SpiConfig, Spi}; | |||||
| use esp_hal::spi::Mode as SpiMode; | |||||
| use esp_hal::time::Rate; | |||||
| #[panic_handler] | |||||
| fn panic(info: &core::panic::PanicInfo) -> ! { | |||||
| esp_println::println!("Panic occurred: {:?}", info); | |||||
| loop {} | |||||
| } | |||||
| #[esp_hal_embassy::main] | |||||
| async fn main(_spawner: Spawner) { | |||||
| // generator version: 0.3.1 | |||||
| let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); | |||||
| let peripherals = esp_hal::init(config); | |||||
| let timer0 = TimerGroup::new(peripherals.TIMG1); | |||||
| esp_hal_embassy::init(timer0.timer0); | |||||
| info!("Embassy initialized!"); | |||||
| let spi = Spi::new( | |||||
| peripherals.SPI2, | |||||
| SpiConfig::default() | |||||
| .with_frequency(Rate::from_mhz(4)) | |||||
| .with_mode(SpiMode::_0), | |||||
| ) | |||||
| .unwrap() | |||||
| //CLK | |||||
| .with_sck(peripherals.GPIO18) | |||||
| //DIN | |||||
| .with_mosi(peripherals.GPIO23); | |||||
| let busy_in = Input::new( | |||||
| peripherals.GPIO22, | |||||
| InputConfig::default().with_pull(Pull::None), | |||||
| ); | |||||
| let cs = Output::new(peripherals.GPIO33, Level::Low, OutputConfig::default()); | |||||
| let mut spi_dev = ExclusiveDevice::new(spi, cs, Delay); | |||||
| let dc = Output::new(peripherals.GPIO17, Level::Low, OutputConfig::default()); | |||||
| let reset = Output::new(peripherals.GPIO16, Level::Low, OutputConfig::default()); | |||||
| let mut display = Display1in54::default(); | |||||
| let mut epd = Epd1in54::new(&mut spi_dev, busy_in, dc, reset, &mut Delay, None).unwrap(); | |||||
| epd.clear_frame(&mut spi_dev, &mut Delay).unwrap(); | |||||
| epd.display_frame(&mut spi_dev, &mut Delay).unwrap(); | |||||
| Timer::after(Duration::from_secs(2)).await; | |||||
| display.clear(Color::White).unwrap(); | |||||
| epd.update_and_display_frame(&mut spi_dev, display.buffer(), &mut Delay) | |||||
| .unwrap(); | |||||
| Timer::after(Duration::from_secs(2)).await; | |||||
| draw_text(&mut display, "impl Rust for ESP32", 3, 100); | |||||
| epd.update_and_display_frame(&mut spi_dev, display.buffer(), &mut Delay) | |||||
| .unwrap(); | |||||
| Timer::after(Duration::from_secs(5)).await; | |||||
| epd.sleep(&mut spi_dev, &mut Delay).unwrap(); | |||||
| loop { | |||||
| info!("Hello world!"); | |||||
| Timer::after(Duration::from_secs(60)).await; | |||||
| } | |||||
| } | |||||
| fn draw_text(display: &mut Display1in54, text: &str, x: i32, y: i32) { | |||||
| let text_style = MonoTextStyleBuilder::new() | |||||
| .font(&FONT_10X20) | |||||
| .text_color(Color::Black) | |||||
| .build(); | |||||
| Text::with_baseline(text, Point::new(x, y), text_style, Baseline::Top) | |||||
| .draw(display) | |||||
| .unwrap(); | |||||
| } | |||||
| @ -0,0 +1 @@ | |||||
| #![no_std] | |||||
| @ -0,0 +1,31 @@ | |||||
| //! Demo test suite using embedded-test | |||||
| //! | |||||
| //! You can run this using `cargo test` as usual. | |||||
| #![no_std] | |||||
| #![no_main] | |||||
| #[cfg(test)] | |||||
| #[embedded_test::tests(executor = esp_hal_embassy::Executor::new())] | |||||
| mod tests { | |||||
| use defmt::assert_eq; | |||||
| use esp_hal::timer::timg::TimerGroup; | |||||
| #[init] | |||||
| fn init() { | |||||
| let peripherals = esp_hal::init(esp_hal::Config::default()); | |||||
| let timer0 = TimerGroup::new(peripherals.TIMG1); | |||||
| esp_hal_embassy::init(timer0.timer0); | |||||
| rtt_target::rtt_init_defmt!(); | |||||
| } | |||||
| #[test] | |||||
| async fn hello_test() { | |||||
| defmt::info!("Running test!"); | |||||
| embassy_time::Timer::after(embassy_time::Duration::from_millis(100)).await; | |||||
| assert_eq!(1 + 1, 2); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,5 @@ | |||||
| [wokwi] | |||||
| version = 1 | |||||
| gdbServerPort = 3333 | |||||
| elf = "target/xtensa-esp32-none-elf/debug/e-ink-hello" | |||||
| firmware = "target/xtensa-esp32-none-elf/debug/e-ink-hello" | |||||