use std::sync::Arc;
use ddevmem::{register_map, DevMem};
use tokio::sync::Mutex;
register_map! {
pub unsafe map DmaRegs (u32) {
0x00 =>
rw ctrl: u32 {
enable: 0 as bool,
nch: 1..=3 as u8
},
0x04 =>
ro sr: u32 {
busy: 0 as bool,
err: 1 as bool
},
0x10 =>
rw fifo: [u32; 8],
0x40 =>
rw chan: [u32; 4] {
enable: 0 as bool,
prio: 1..=3 as u8,
dir: 4 as enum DmaDir {
M2P = 0,
P2M = 1,
}
}
}
}
register_map! {
pub unsafe map UartRegs (u32) {
0x00 =>
rw cr: u32 {
tx_en: 0 as bool,
rx_en: 1 as bool,
stop: 2..=3 as enum StopBits {
One = 0,
OnePointFive = 1,
Two = 2,
},
parity: 4..=5 as enum Parity {
None = 0,
Even = 1,
Odd = 2,
Mark = 3,
},
word_len: 6..=9 as u8,
flow_ctl: 10 as bool
},
0x04 =>
rw brd: u32,
0x08 =>
ro sr: u32 {
tx_empty: 0 as bool,
tx_full: 1 as bool,
rx_empty: 2 as bool,
rx_full: 3 as bool,
parity_err: 4 as bool,
frame_err: 5 as bool,
rx_count: 8..=11 as u8
},
0x0C =>
rw isr: u32 {
tx_empty: 0 as bool,
rx_byte: 1 as bool,
parity: 2 as bool,
frame: 3 as bool
},
0x10 =>
wo cmd: u32 {
tx_reset: 0 as bool,
rx_reset: 1 as bool,
send_break: 2 as bool,
abort: 3 as bool
},
0x14 =>
wo txd: u32,
0x18 =>
ro rxd: u32
}
}
register_map! {
pub unsafe map AdcRegs (u16) {
0x00 =>
rw cr: u16 {
enable: 0 as bool,
continuous: 1 as bool,
channel: 2..=4 as u8,
resolution: 5..=6 as enum AdcResolution {
Bits8 = 0,
Bits10 = 1,
Bits12 = 2,
Bits14 = 3,
},
trigger: 8..=9 as enum AdcTrigger {
Software = 0,
Timer1 = 1,
Timer2 = 2,
External = 3,
}
},
0x02 =>
ro data: u16,
0x04 =>
rw threshold: u16,
0x06 =>
ro sr: u16 {
busy: 0 as bool,
eoc: 1 as bool,
awd: 2 as bool
},
0x08 =>
wo start: u16
}
}
register_map! {
pub unsafe map I2cRegs (u8) {
0x00 =>
rw cr: u8 {
enable: 0 as bool,
master: 1 as bool,
speed: 2..=3 as enum I2cSpeed {
Standard100k = 0,
Fast400k = 1,
FastPlus1M = 2,
HighSpeed3M = 3,
},
ack: 4 as bool
},
0x01 =>
rw oar: u8 {
addr: 0..=6 as u8
},
0x02 =>
ro sr: u8 {
busy: 0 as bool,
msl: 1 as bool,
addr: 2 as bool,
btf: 3 as bool,
af: 4 as bool,
arlo: 5 as bool
},
0x03 =>
rw dr: u8,
0x04 =>
wo cmd: u8 {
start: 0 as bool,
stop: 1 as bool,
reset: 7 as bool
}
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let uart_mem = unsafe { DevMem::new(0x43D8_0000, Some(256)).unwrap() };
let adc_mem = unsafe { DevMem::new(0x83C1_0000, Some(256)).unwrap() };
let i2c_mem = unsafe { DevMem::new(0x83B4_0000, Some(256)).unwrap() };
let dma_mem = unsafe { DevMem::new(0x4040_0000, Some(256)).unwrap() };
let mut uart = unsafe { UartRegs::new(Arc::new(uart_mem)).unwrap() };
let mut adc = unsafe { AdcRegs::new(Arc::new(adc_mem)).unwrap() };
let mut i2c = unsafe { I2cRegs::new(Arc::new(i2c_mem)).unwrap() };
let mut dma = unsafe { DmaRegs::new(Arc::new(dma_mem)).unwrap() };
uart.set_cr_tx_en(true);
uart.set_cr_rx_en(true);
uart.set_cr_word_len(8);
uart.set_cr_parity(Parity::Even);
uart.set_cr_stop(StopBits::One);
uart.set_brd(115_200);
adc.set_cr_enable(true);
adc.set_cr_continuous(true);
adc.set_cr_channel(3);
adc.set_cr_resolution(AdcResolution::Bits12);
adc.set_cr_trigger(AdcTrigger::Timer1);
adc.set_threshold(2048);
i2c.set_cr_enable(true);
i2c.set_cr_master(true);
i2c.set_cr_speed(I2cSpeed::Fast400k);
i2c.set_cr_ack(true);
i2c.set_oar_addr(0x42);
dma.set_ctrl_enable(true);
dma.set_ctrl_nch(4);
for i in 0..dma.fifo_len() {
dma.set_fifo(i, 0xDEAD_0000 | i as u32);
}
for i in 0..4 {
dma.set_chan_enable(i, true);
dma.set_chan_prio(i, (i as u8) + 1);
dma.set_chan_dir(i, if i % 2 == 0 { DmaDir::M2P } else { DmaDir::P2M });
}
let regs_router = ddevmem::web::WebUi::new()
.with_title("ddevmem showcase — UART · ADC · I2C · DMA")
.add("uart", Arc::new(Mutex::new(uart)))
.add("adc", Arc::new(Mutex::new(adc)))
.add("i2c", Arc::new(Mutex::new(i2c)))
.add("dma", Arc::new(Mutex::new(dma)))
.build();
let app = axum::Router::new().nest("/hw", regs_router);
let listener = tokio::net::TcpListener::bind("0.0.0.0:8800").await.unwrap();
println!("Showcase web UI at http://localhost:8800/hw");
println!(" uart (u32 bus) — typed bitfields, wo command + txd, ro rxd");
println!(" adc (u16 bus) — enum trigger/resolution, ro data, wo start");
println!(" i2c (u8 bus) — narrow bus, 7-bit address field, wo cmd");
println!(" dma (u32 bus) — register arrays: fifo[0..8], chan[0..4]");
axum::serve(listener, app).await.unwrap();
}