#![no_std] #![no_main] #![feature(ascii_char)] #![deny( clippy::mem_forget, reason = "mem::forget is generally not safe to do with esp_hal types, especially those \ holding buffers for the duration of a data transfer." )] #![deny(clippy::large_stack_frames)] use core::mem::MaybeUninit; use alloc::boxed::Box; use esp_hal::{ clock::CpuClock, delay::Delay, gpio::{Level, Output, OutputConfig}, i2c::{self, master::I2c}, interrupt::software::SoftwareInterruptControl, main, spi::master::{Config, Spi}, system::Stack, time::Rate, timer::timg::TimerGroup, uart::{self, Uart}, }; use esp_backtrace as _; use crate::{ async_io::AsyncIO, at_commands::ATCommands, display::{Display, Position, Rgb565, SetAddressMode}, font::FontRenderer, state::StateManager, states::InitATState, sx1509::{Register, Sx1509}, }; extern crate alloc; mod async_io; mod at_commands; mod display; mod font; mod state; mod states; mod sx1509; // This creates a default app-descriptor required by the esp-idf bootloader. // For more information see: esp_bootloader_esp_idf::esp_app_desc!(); #[allow( clippy::large_stack_frames, reason = "it's not unusual to allocate larger buffers etc. in main" )] #[main] fn main() -> ! { // generator version: 1.3.0 // generator parameters: --chip esp32 -o esp32-wroom-32e -o alloc -o esp-backtrace -o log -o vscode esp_println::logger::init_logger_from_env(); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); // The following pins are used to bootstrap the chip. They are available // for use, but check the datasheet of the module for more information on them. // - GPIO0 // - GPIO2 // - GPIO5 // - GPIO12 // - GPIO15 // These GPIO pins are in use by some feature of the module and should not be used. let _ = peripherals.GPIO6; let _ = peripherals.GPIO7; let _ = peripherals.GPIO8; let _ = peripherals.GPIO9; let _ = peripherals.GPIO10; let _ = peripherals.GPIO11; let _ = peripherals.GPIO16; let _ = peripherals.GPIO17; esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 98768); let spi = Spi::new( peripherals.SPI2, Config::default() .with_frequency(Rate::from_mhz(80)) .with_mode(esp_hal::spi::Mode::_2) .with_read_bit_order(esp_hal::spi::BitOrder::MsbFirst) .with_write_bit_order(esp_hal::spi::BitOrder::MsbFirst), ) .unwrap() .with_sck(peripherals.GPIO5) .with_mosi(peripherals.GPIO19) .with_miso(peripherals.GPIO21) .with_cs(peripherals.GPIO4); let rst = Output::new(peripherals.GPIO14, Level::Low, OutputConfig::default()); let dc = Output::new(peripherals.GPIO32, Level::Low, OutputConfig::default()); let mut display = Display { spi, dc, rst, delay: Delay::new(), }; display.init(SetAddressMode { color_order: display::ColorOrder::Rgb, ..Default::default() }); display.set_tearing(display::TearingMode::Off); let sim_rst = Output::new(peripherals.GPIO27, Level::High, OutputConfig::default()); let sim_pwr_key = Output::new(peripherals.GPIO12, Level::High, OutputConfig::default()); let uart = Uart::new( peripherals.UART2, uart::Config::default() .with_baudrate(115200) .with_data_bits(uart::DataBits::_8) .with_parity(uart::Parity::None) .with_sw_flow_ctrl(uart::SwFlowControl::Disabled), ) .unwrap() .with_rx(peripherals.GPIO7) .with_tx(peripherals.GPIO8); let mut sx1509 = Sx1509::from( I2c::new( peripherals.I2C0, i2c::master::Config::default().with_frequency(Rate::from_khz(400)), ) .unwrap() .with_scl(peripherals.GPIO20) .with_sda(peripherals.GPIO22), Output::new(peripherals.GPIO15, Level::High, OutputConfig::default()), ); sx1509.init().unwrap(); sx1509.set_pin_dir(15, sx1509::PinDirection::Output, true); let mut is_high = true; let delay = Delay::new(); loop { delay.delay_millis(500); is_high = !is_high; sx1509.write_pin(15, is_high); log::info!("Pin: {}", is_high) } // let mut at_commands = ATCommands::new(sim_rst, sim_pwr_key, uart); // let font_renderer = FontRenderer::create(30); // display.clear(Rgb565::black().as_color()); // font_renderer.render( // &mut display, // "Please wait", // Position::new(120, 120), // font::HorizontalAlignment::Center, // font::VerticalAlignment::Center, // Rgb565::black(), // Rgb565::white(), // ); // at_commands.init(); // let async_io = AsyncIO::default(); // let mut state_mgr = StateManager { // data: state::StateData::from(display, async_io.clone()), // curr_state: Box::new(InitATState::default()), // }; // static mut THREAD_2_STACK: Stack<{ 30 * 1024 }> = esp_hal::system::Stack { // mem: MaybeUninit::new([0u8; 30 * 1024]), // }; // let timg0 = TimerGroup::new(peripherals.TIMG0); // let software_interrupt = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); // esp_rtos::start(timg0.timer0, software_interrupt.software_interrupt0); // esp_rtos::start_second_core( // peripherals.CPU_CTRL, // software_interrupt.software_interrupt1, // unsafe { // #[allow(static_mut_refs)] // &mut THREAD_2_STACK // }, // { // let io = async_io.clone(); // || thread_2_main(io, at_commands) // }, // ); // loop { // state_mgr.update(); // state_mgr.draw(); // } // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.1.0/examples } fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static>) { loop { if let Some(command) = unsafe { async_io.check_at_command() } { let response = match command { async_io::ConstructedATCommand::Single(cmd) => at_commands.raw_command(cmd), async_io::ConstructedATCommand::AddInfo(cmd, add) => { at_commands.raw_two_part_command(cmd, add) } }; unsafe { async_io.set_at_response(response) }; } if let Some(event) = at_commands.readline() { log::info!("Event: {}", event); } } }