use core::alloc::Layout; use core::cell::{OnceCell, RefCell}; use core::fmt::Write; use core::time::Duration; use alloc::boxed::Box; use alloc::rc::Rc; use alloc::vec; use bt_hci::controller::ExternalController; use critical_section::Mutex; use embassy_embedded_hal::adapter::BlockingAsync; use embassy_executor::Spawner; use embassy_time::Timer; use esp_alloc::{HeapRegion, MemoryCapability}; use esp_hal::clock::CpuClock; use esp_hal::dma::{BurstConfig, DmaDescriptor, DmaTxBuf, ExternalBurstConfig}; use esp_hal::gpio::{Flex, Input, InputConfig, Io, Level, Output, OutputConfig, Pull}; use esp_hal::handler; use esp_hal::i2c::master::{I2c, I2cAddress}; use esp_hal::interrupt::Priority; use esp_hal::interrupt::software::SoftwareInterruptControl; use esp_hal::lcd_cam::LcdCam; use esp_hal::lcd_cam::lcd::dpi::Dpi; use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; use esp_hal::peripherals::Peripherals; use esp_hal::psram::{FlashFreq, PsramConfig, PsramSize, SpiRamFreq, SpiTimingConfigCoreClock}; use esp_hal::rng::TrngSource; use esp_hal::system::Stack; use esp_hal::time::Instant; use esp_hal::timer::timg::TimerGroup; use esp_hal::uart::{Uart, UartTx}; use esp_hal::usb_serial_jtag::{UsbSerialJtag, UsbSerialJtagTx}; use esp_hal::{Blocking, ram}; use esp_radio::Controller; use esp_radio::ble::controller::BleConnector; use esp_rtos::embassy::{Executor, InterruptExecutor}; use esp_storage::FlashStorage; use itertools::chain; use log::{LevelFilter, Log, error, info}; use rmk::channel::EVENT_CHANNEL; use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig}; use rmk::debounce::default_debouncer::DefaultDebouncer; use rmk::embassy_futures::yield_now; use rmk::input_device::Runnable; use rmk::{join_all}; use rmk::keyboard::Keyboard; use rmk::storage::async_flash_wrapper; use rmk::{initialize_keymap_and_storage, run_devices, run_rmk}; use slint::platform::software_renderer::{Rgb565Pixel, TargetPixel}; use slint::{ComponentHandle, PhysicalSize, WindowSize}; use slint::platform::Platform; use static_cell::StaticCell; static ALT_LOGGER_UART: Mutex>>> = Mutex::new(RefCell::new(None)); struct AlternativeLogger; impl Log for AlternativeLogger { #[allow(unused)] fn enabled(&self, _: &log::Metadata) -> bool { // Filtered by `log` already true } #[allow(unused)] fn log(&self, record: &log::Record) { critical_section::with(|cs| { let mut uart = ALT_LOGGER_UART.borrow(cs).borrow_mut(); let mut uart = uart.as_mut().unwrap(); print_log_record(&mut uart, record); }) } fn flush(&self) {} } const RESET: &str = "\u{001B}[0m"; const RED: &str = "\u{001B}[31m"; const GREEN: &str = "\u{001B}[32m"; const YELLOW: &str = "\u{001B}[33m"; const BLUE: &str = "\u{001B}[34m"; const CYAN: &str = "\u{001B}[35m"; #[cfg(feature = "alt-log")] macro_rules! println { () => {{ do_print(Default::default()); }}; ($($arg:tt)*) => {{ do_print(::core::format_args!($($arg)*)); }}; } #[cfg(not(feature = "alt-log"))] use esp_println::println; fn do_print(args: core::fmt::Arguments<'_>) { critical_section::with(|cs| { let mut uart = ALT_LOGGER_UART.borrow(cs).borrow_mut(); let mut uart = uart.as_mut().unwrap(); uart.write_fmt(args).unwrap(); uart.write_str("\n").unwrap(); uart.flush().unwrap(); }) } fn print_log_record(uart: &mut UartTx<'_, Blocking>, record: &log::Record) { let color = match record.level() { log::Level::Error => RED, log::Level::Warn => YELLOW, log::Level::Info => GREEN, log::Level::Debug => BLUE, log::Level::Trace => CYAN, }; let reset = RESET; let args = format_args!("{}{:>5} - {}{}\n", color, record.level(), record.args(), reset); uart.write_fmt(args).unwrap(); uart.flush().unwrap(); } #[cfg(feature = "alt-log")] #[panic_handler] fn panic_handler(info: &core::panic::PanicInfo) -> ! { use esp_backtrace::Backtrace; println!("{RED}"); println!("====================== PANIC ======================"); println!("{info}{RESET}"); println!(""); println!("Backtrace:"); println!(""); let backtrace = Backtrace::capture(); for frame in backtrace.frames() { println!("0x{:x}", frame.program_counter()); } loop {} } pub fn setup_alternative_logging(alt_uart: UartTx<'static, Blocking>, level_filter: LevelFilter) { critical_section::with(|cs| { *ALT_LOGGER_UART.borrow(cs).borrow_mut() = Some(alt_uart); }); unsafe { log::set_logger_racy(&AlternativeLogger).unwrap(); log::set_max_level_racy(level_filter); } }