This commit is contained in:
Pascal Engélibert 2023-10-07 13:33:14 +02:00
parent a4884bd189
commit 865599e059
64 changed files with 6448 additions and 1221 deletions

1
.gitignore vendored
View file

@ -1 +0,0 @@
/target

1134
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,35 +0,0 @@
[package]
name = "rustphone"
version = "0.1.0"
authors = ["tuxmain <tuxmain@zettascript.org>"]
repository = "https://git.txmn.tk/tuxmain/rustphone"
license = "AGPL-3.0-only"
edition = "2021"
[dependencies]
arrayvec = { version = "0.7.4", default_features = false }
atsamd-hal = { version = "0.15.1", default_features = false, features = ["samd21g", "samd21g-rt", "usb"] }
cfg-if = "1.0.0"
embedded-graphics = "0.7.1"
embedded-text = "0.5.0"
embedded-sdmmc = { version = "0.3.0", default_features = false }
epd-waveshare = "0.5.0"
maduino_zero_4g = { git = "https://github.com/ZettaScript/atsamd", branch = "maduino-zero-4g", features = ["usb"] }
panic-halt = "0.2.0"
tz-rs = { version = "0.6.14", default_features = false, features = ["const"] }
tzdb = { version = "0.5.7", optional = true }
# simulator
embedded-graphics-simulator = { version = "0.4.1", optional = true }
[features]
#default = ["simulator"]
simulator = ["embedded-graphics-simulator", "tzdb"]
[profile.release]
lto = "fat"
opt-level = 3
[patch."https://github.com/ZettaScript/atsamd"]
maduino_zero_4g = { path = "../atsamd/boards/maduino_zero_4g" }

View file

@ -22,7 +22,11 @@ GSM will be shutting down in France in a few years so if you have an old cellpho
## Install tools
```bash
# Choose one line depending on your distro
sudo pacman -S arm-none-eabi-gcc
sudo apt install gcc-arm-none-eabi
# Install Rust target
rustup target add thumbv6m-none-eabi
```
@ -38,6 +42,12 @@ cargo run --features simulator
cargo build --release --target thumbv6m-none-eabi
```
Read usb:
```bash
cat /dev/serial/by-id/usb-2222_3333-if00
```
## Pins
* D2
@ -102,3 +112,25 @@ ncb1 upz2 tdk3
eow4 lqh5 age6
sfx7 rmj8 ivy9
```
## OS
In case we switch to some more powerful MCU like ESP32.
Using an RTOS would be better than creating a monolithical horror. It would also make it easier to split the software into modular programs and store some programs in different memories (e.g. store kernel in internal flash and user programs in SPI flash).
Rusty embedded RTOS's:
* https://bern-rtos.org/
* does not support Xtensa
* supports Cortex-M
* does not seem to support dynamic programs
* https://www.drone-os.com/
* does not support Xtensa
* supports Cortex-M
* explicitly does not support dynamic programs
Needs:
* Kernel writes user programs to SPI flash (can it be done via chip programming or has it do be done by kernel? then USB, SD, debug probe, UART??)
* Handle hardware-specific work (provide high level interfaces for GPIO, SD, screen, modem, wifi, bluetooth...)
* Dynamic threads

1
common/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

16
common/Cargo.lock generated Normal file
View file

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "common"
version = "0.1.0"
dependencies = [
"embedded-hal",
]
[[package]]
name = "embedded-hal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"

7
common/Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "common"
version = "0.1.0"
edition = "2021"
[dependencies]
embedded-hal = "1.0.0"

9
common/rustfmt.toml Normal file
View file

@ -0,0 +1,9 @@
hard_tabs = true
newline_style = "Unix"
imports_granularity = "Crate"
unstable_features = true
format_code_in_doc_comments = true
format_macro_bodies = true
format_macro_matchers = true
format_strings = true

5
common/src/cm.rs Normal file
View file

@ -0,0 +1,5 @@
/// CPU to Modem
pub enum CMMessage {
Ping(u32),
Pong(u32),
}

15
common/src/lib.rs Normal file
View file

@ -0,0 +1,15 @@
pub mod cm;
pub mod mc;
pub const VERSION: u32 = 1;
enum State {
/// Not ready, not even pinged
Idle,
/// Ping failed
Fail,
/// Waiting for pong
Pinging,
/// Ready to work
Ready,
}

26
common/src/mc.rs Normal file
View file

@ -0,0 +1,26 @@
use crate::{cm::CMMessage, State};
/// Modem to CPU
pub enum MCMessage {
Ping(u32),
Pong(u32),
}
/// Modem-side connection driver
pub struct MCConnection<SPI> {
spi: SPI,
state: State,
}
impl<SPI> MCConnection<SPI> where SPI: embedded_hal::spi::SpiDevice {
pub fn new(spi: SPI) -> Self {
Self {
spi,
state: State::Idle,
}
}
fn handle_message(message: CMMessage) {
}
}

View file

@ -0,0 +1,27 @@
[build]
target = "xtensa-esp32-none-elf"
[target.'cfg(target_arch = "xtensa")']
#runner = "espflash flash --monitor --flash-size 4mb --chip esp32 --partition-table partition.csv --flash-freq 40mhz --flash-mode qio"
runner = "espflash flash --monitor --flash-size 4mb --chip esp32"
rustflags = [
# Optimization
"-Z", "location-detail=none",
"-C", "link-args=-Wl,--sort-section=alignment",
"-C", "inline-threshold=7",
# GNU LD
"-C", "link-arg=-Wl,-Tlinkall.x",
"-C", "link-arg=-nostartfiles",
# LLD
# "-C", "link-arg=-Tlinkall.x",
# "-C", "linker=rust-lld",
]
[env]
ESP_LOGLEVEL = "info"
[unstable]
build-std = ["core", "panic_abort"]
#build-std = ["core"]

17
esp/.cargo/config.toml Normal file
View file

@ -0,0 +1,17 @@
[target.xtensa-esp32-none-elf]
runner = "espflash flash --monitor"
[env]
ESP_LOG="info"
[build]
rustflags = [
"-C", "link-arg=-Wl,-Tlinkall.x",
"-C", "link-arg=-Trom_functions.x",
"-C", "link-arg=-nostartfiles",
]
target = "xtensa-esp32-none-elf"
[unstable]
build-std = ["alloc", "core"]

3
esp/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
wifi-ssid.txt
wifi-psw.txt
target

4
esp/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"rust-analyzer.cargo.allTargets": false,
"rust-analyzer.cargo.target": "xtensa-esp32-none-elf",
}

1552
esp/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

53
esp/Cargo.toml Normal file
View file

@ -0,0 +1,53 @@
[package]
name = "rustphone"
version = "0.1.0"
edition = "2021"
[dependencies]
cfg-if = "1.0.0"
critical-section = "1.2.0"
embassy-embedded-hal = "0.2.0"
embassy-executor = { version = "0.6.3", features = ["task-arena-size-20480"] }
embassy-net = { version = "0.4.0", features = [ "tcp", "udp", "dhcpv4", "medium-ethernet"] }
embassy-sync = "0.6.1"
embassy-time = { version = "0.3.2", features = ["generic-queue-8"] }
embedded-graphics = "0.8.1"
embedded-hal = "1.0.0"
embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", features = ["unproven"] }
embedded-io = "0.6.1"
embedded-io-async = "0.6.1"
embedded-layout = "0.4.1"
embedded-text = "0.7.2"
#embedded-tls = { version = "0.17.0", default-features = false }
epd-waveshare = { path = "../../epd-waveshare", optional = true }
esp-alloc = "0.5.0"
esp-backtrace = { version = "0.14.2", features = ["esp32", "exception-handler", "panic-handler", "println"] }
esp-hal = { version = "0.22.0", features = ["esp32"] }
esp-hal-embassy = { version = "0.5.0", features = ["esp32"] }
esp-println = { version = "0.12.0", features = ["esp32", "log"] }
esp-wifi = { version = "0.11.0", default-features = false, features = ["esp32", "utils", "wifi", "esp-alloc", "log"] }
log = "0.4.21"
#oled_async = { path = "../../oled_async", features = ["spi"] }
nb = "1.1.0"
#panic-halt = "0.2.0"
rand_core = "0.6.4"
#sh1106 = { version = "0.5.0", optional = true }
sh1106 = { git = "https://github.com/techmccat/sh1106", branch = "hal-1", optional = true }
static_cell = { version = "2.1.0", features = ["nightly"] }
[features]
default = ["display_sh1106"]
display_epd = ["dep:epd-waveshare"]
display_sh1106 = ["dep:sh1106"]
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
opt-level = 's'
lto = 'fat'
overflow-checks = false
#panic = "abort"
strip = true

11
esp/README.md Normal file
View file

@ -0,0 +1,11 @@
## Build
```bash
cargo +esp run --release --target xtensa-esp32-none-elf
```
## Links
https://github.com/ivmarkov/rust-esp32-std-demo/blob/main/src/main.rs#L1505
OLED SPI/I2C V2 1.3in SH1106 5/3.3V

5
esp/build.rs Normal file
View file

@ -0,0 +1,5 @@
fn main() {
//println!("cargo:rustc-link-arg-bins=-Tlinkall.x");
//println!("cargo:rustc-link-arg-bins=-Tesp32_rom_functions.x");
//println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}

4
esp/partition.csv Normal file
View file

@ -0,0 +1,4 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x7000,
factory, app, factory, 0x10000, 2M,
spiffs, data, spiffs, , 2M,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x7000
3 factory app factory 0x10000 2M
4 spiffs data spiffs 2M

1982
esp/rom_functions.x Normal file

File diff suppressed because it is too large Load diff

2
esp/rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "esp"

9
esp/rustfmt.toml Normal file
View file

@ -0,0 +1,9 @@
hard_tabs = true
newline_style = "Unix"
imports_granularity = "Crate"
unstable_features = true
format_code_in_doc_comments = true
format_macro_bodies = true
format_macro_matchers = true
format_strings = true

9
esp/src/display.rs Normal file
View file

@ -0,0 +1,9 @@
cfg_if::cfg_if! {
if #[cfg(feature = "display_sh1106")] {
mod sh1106;
pub use sh1106::*;
} else if #[cfg(feature = "display_epd")] {
mod epd;
pub use epd::*;
}
}

96
esp/src/display/epd.rs Normal file
View file

@ -0,0 +1,96 @@
use core::cell::RefCell;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_sync::blocking_mutex::{raw::NoopRawMutex, NoopMutex};
use embedded_graphics::prelude::*;
use epd_waveshare::{
epd1in54::{Display1in54, Epd1in54},
prelude::*,
};
use esp_hal::{
delay::Delay,
gpio::{GpioPin, Input, InputPin, Level, Output, Pull},
peripherals::SPI2,
spi::{master::Spi, FullDuplexMode},
};
use esp_println::println;
use static_cell::StaticCell;
type EpdSpi<'a> =
SpiDevice<'a, NoopRawMutex, Spi<'a, SPI2, FullDuplexMode>, Output<'a, GpioPin<15>>>;
type Epd = Epd1in54<
EpdSpi<'static>,
Input<'static, GpioPin<18>>,
Output<'static, GpioPin<19>>,
Output<'static, GpioPin<21>>,
Delay,
>;
pub type Color = epd_waveshare::color::Color;
pub const BLACK: Color = epd_waveshare::color::Color::Black;
pub const WHITE: Color = epd_waveshare::color::Color::White;
//static DISPLAY: StaticCell<Display> = StaticCell::new();
pub fn init(
spi: &mut EpdSpi<'static>,
busy: GpioPin<18>,
dc: GpioPin<19>,
rst: GpioPin<21>,
delay: &mut Delay,
) -> Epd {
Epd::new(
spi,
Input::new(busy, Pull::Down),
Output::new(dc, Level::High),
Output::new(rst, Level::High),
delay,
Some(5),
)
.unwrap()
}
#[embassy_executor::task]
pub async fn run(mut spi: EpdSpi<'static>, mut epd: Epd, mut delay: Delay) {
println!("EPD start");
epd.clear_frame(&mut spi, &mut delay).unwrap();
epd.display_frame(&mut spi, &mut delay).unwrap();
let small_buffer = [Color::Black.get_byte_value(); 8]; //8x8
epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 96, 96, 8, 8)
.unwrap();
// Display updated frame
epd.display_frame(&mut spi, &mut delay).unwrap();
delay.delay_millis(5000);
// Set the EPD to sleep
epd.sleep(&mut spi, &mut delay).unwrap();
println!("EPD done");
}
/*pub struct Display {
epd: Epd,
display: Display1in54,
}
impl Display {
pub fn new(spi: &mut Spi<_, _>) -> Self {
Self {
epd: Epd1in54::new(&mut spi, cs, busy, dc, rst, &mut delay),
display: Display1in54::default(),
}
}
pub fn update(&self) {
//self.epd.update_and_display_frame( & mut spi, & self.display.buffer());
}
pub fn inner(&self) -> &Display1in54 {
&self.display
}
pub fn inner_mut(&mut self) -> &mut Display1in54 {
&mut self.display
}
}*/

98
esp/src/display/sh1106.rs Normal file
View file

@ -0,0 +1,98 @@
use crate::string::String;
use core::cell::RefCell;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_sync::{
blocking_mutex::{
raw::{CriticalSectionRawMutex, NoopRawMutex},
NoopMutex,
},
channel::Channel,
};
use embedded_graphics::{
mono_font::{ascii::FONT_5X8, MonoTextStyle},
pixelcolor::BinaryColor,
prelude::*,
primitives::{PrimitiveStyle, Rectangle},
text::renderer::CharacterStyle,
};
use embedded_text::{
alignment::HorizontalAlignment,
style::{HeightMode, TextBoxStyleBuilder},
TextBox,
};
use esp_hal::{
delay::Delay,
gpio::{AnyPin, GpioPin, Input, InputPin, Level, Output, Pull},
peripherals::SPI2,
spi::master::Spi,
};
use esp_println::println;
use sh1106::{prelude::*, Builder};
use static_cell::StaticCell;
type OledSpi<'a> =
SpiDevice<'a, NoopRawMutex, Spi<'a, esp_hal::Blocking, SPI2>, Output<'a, GpioPin<15>>>;
pub static CHANNEL: Channel<CriticalSectionRawMutex, String<1024>, 2> = Channel::new();
/*pub fn init(
spi: OledSpi<'static>,
dc: GpioPin<19>,
) -> GraphicsMode<SpiInterface<OledSpi<'static>, Output<'static, GpioPin<19>>>> {
Builder::new()
.connect_spi(spi, Output::new(dc, Level::High))
.into()
}*/
pub fn init(
spi: OledSpi<'static>,
dc: AnyPin,
) -> GraphicsMode<SpiInterface<OledSpi<'static>, Output<'static, AnyPin>>> {
Builder::new()
.connect_spi(spi, Output::new(dc, Level::High))
.into()
}
#[embassy_executor::task]
pub async fn run(
mut display: GraphicsMode<SpiInterface<OledSpi<'static>, Output<'static, GpioPin<19>>>>,
delay: Delay,
) {
display.init().unwrap();
display.flush().unwrap();
let mut character_style = MonoTextStyle::new(&FONT_5X8, BinaryColor::On);
character_style.set_background_color(Some(BinaryColor::Off));
let textbox_style = TextBoxStyleBuilder::new()
.height_mode(HeightMode::FitToText)
.alignment(HorizontalAlignment::Left)
.paragraph_spacing(3)
.build();
let bounds = Rectangle::new(Point::zero(), Size::new(128, 0));
loop {
let buf = CHANNEL.receive().await;
let text = buf.as_ref();
display.clear();
let text_box = TextBox::with_textbox_style(
&text[0..text.len().min(100)],
bounds,
character_style,
textbox_style,
);
text_box.draw(&mut display).ok();
/*Rectangle::with_center(Point::new(20, 20), Size::new(8, 8))
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
.draw(&mut display)
.ok();
Rectangle::with_center(Point::new(25, 25), Size::new(8, 8))
.into_styled(PrimitiveStyle::with_fill(BinaryColor::Off))
.draw(&mut display)
.ok();*/
display.flush().ok();
}
}

225
esp/src/main.rs Normal file
View file

@ -0,0 +1,225 @@
#![no_std]
#![no_main]
#![feature(array_windows)]
#![feature(impl_trait_in_assoc_type)]
#![feature(type_alias_impl_trait)]
mod display;
mod modem;
//mod rng;
mod string;
#[macro_use]
mod util;
mod wifi;
use string::String;
use util::*;
use core::cell::RefCell;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_sync::blocking_mutex::NoopMutex;
//use embedded_tls::{Aes256GcmSha384, TlsConfig, TlsConnection, TlsContext};
use embassy_executor::Spawner;
use embassy_net::{tcp::TcpSocket, Ipv4Address};
use embassy_time::{Duration, Timer};
use embedded_io_async::Write;
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
gpio::{self, Level},
prelude::*,
spi::{self, master::Spi},
timer::{timg::TimerGroup, AnyTimer, OneShotTimer},
Blocking,
};
use esp_println::println;
use log::info;
#[main]
async fn main(spawner: Spawner) {
let mut peripherals = esp_hal::init({
let mut config = esp_hal::Config::default();
config.cpu_clock = CpuClock::max();
config
});
esp_alloc::heap_allocator!(72 * 1024);
esp_println::logger::init_logger_from_env();
let timer0 = esp_hal::timer::timg::TimerGroup::new(&mut peripherals.TIMG1);
esp_hal_embassy::init(timer0.timer0);
info!("Embassy ok");
//let timer1 = esp_hal::timer::timg::TimerGroup::new(&mut peripherals.TIMG0);
/*let _init = esp_wifi::init(
timer1.timer0,
esp_hal::rng::Rng::new(&mut peripherals.RNG),
peripherals.RADIO_CLK,
)
.unwrap();*/
//let system = SystemControl::new(peripherals.SYSTEM);
//let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//let io = Io::new(peripherals.IO_MUX);
//rng::init(peripherals.RNG, peripherals.ADC1);
let mut trng = esp_hal::rng::Trng::new(peripherals.RNG, &mut peripherals.ADC1);
let seed = {
let mut buf = [0; 8];
trng.read(&mut buf);
u64::from_be_bytes(buf)
};
let rng = trng.downgrade();
let sclk = peripherals.GPIO14;
let miso = peripherals.GPIO12;
let mosi = peripherals.GPIO13;
let cs = peripherals.GPIO15;
let spi = Spi::<Blocking, esp_hal::peripherals::SPI2>::new_typed_with_config(
mk_static!(esp_hal::peripherals::SPI2, peripherals.SPI2),
spi::master::Config {
frequency: 400.kHz(),
..Default::default()
},
)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso);
let spi = NoopMutex::new(RefCell::new(spi));
let spi_dev = SpiDevice::new(
mk_static!(
NoopMutex<RefCell<Spi<'static, esp_hal::Blocking, esp_hal::peripherals::SPI2>>>,
spi
),
gpio::Output::new_typed(cs, Level::High),
);
info!("SPI ok");
let delay = Delay::new();
#[cfg(feature = "display_epd")]
let mut display = display::init(
&mut spi_dev,
io.pins.gpio18,
io.pins.gpio19,
io.pins.gpio21,
&mut delay,
);
#[cfg(feature = "display_sh1106")]
//let mut display = display::init(spi_dev, io.pins.gpio19);
let display = sh1106::Builder::new()
.connect_spi(
spi_dev,
gpio::Output::new_typed(peripherals.GPIO19, Level::High),
)
.into();
info!("Display ok");
let timg0 = TimerGroup::new(peripherals.TIMG0);
let (wifi_interface, wifi_controller) =
wifi::pre_init(timg0.timer0, rng, peripherals.RADIO_CLK, peripherals.WIFI);
info!("Wifi pre-init ok");
/*let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1);
esp_hal_embassy::init(
mk_static!(
[OneShotTimer<AnyTimer>; 1],
[OneShotTimer::new(AnyTimer::from(timg1.timer0))]
),
);*/
#[cfg(feature = "display_sh1106")]
let _gpio21 = gpio::Output::new(peripherals.GPIO21, Level::High);
#[cfg(feature = "display_sh1106")]
spawner.spawn(display::run(display, delay)).ok();
#[cfg(feature = "display_epd")]
spawner.spawn(display::run(spi_dev, display, delay)).ok();
let net_stack = wifi::post_init(&spawner, wifi_interface, wifi_controller, seed);
info!("Wifi post-init ok");
let mut rx_buffer = [0; 4096];
let mut tx_buffer = [0; 4096];
'get: loop {
Timer::after(Duration::from_millis(1_000)).await;
let mut socket = TcpSocket::new(&net_stack, &mut rx_buffer, &mut tx_buffer);
socket.set_timeout(Some(embassy_time::Duration::from_millis(10_000)));
let remote_endpoint = (Ipv4Address::new(192, 168, 1, 14), 80);
println!("conn...");
let r = socket.connect(remote_endpoint).await;
if let Err(e) = r {
println!("conn err: {:?}", e);
continue;
}
println!("conn!");
/*let mut read_record_buffer = [0; 16384];
let mut write_record_buffer = [0; 16384];
let tls_config = TlsConfig::new().with_server_name("txmn.tk").with_psk(&[], &[]);
let mut tls = TlsConnection::new(socket, &mut read_record_buffer, &mut write_record_buffer);
if let Err(e) = tls.open(TlsContext::new(
&tls_config,
&mut prng,
))
.await {
println!("TLS err: {:?}", e);
continue;
}*/
let mut buf = [0; 1024];
loop {
/*let r = socket
.write_all(b"GET /fortune.php?raw HTTP/1.0\r\nHost: txmn.tk\r\n\r\n")
.await;
if let Err(e) = r {
println!("w err: {:?}", e);
break;
}
let n = match socket.read(&mut buf).await {
Ok(0) => {
println!("EOF");
break;
}
Ok(n) => n,
Err(e) => {
println!("r err: {:?}", e);
break;
}
};*/
socket
.write_all(b"GET /fortune.php?raw HTTP/1.0\r\nHost: txmn.tk\r\n\r\n")
.await
.unwrap();
socket.flush().await.unwrap();
let n = match socket.read(&mut buf).await {
Ok(0) => {
println!("EOF");
break;
}
Ok(n) => n,
Err(e) => {
println!("r err: {:?}", e);
break;
}
};
println!("{}", core::str::from_utf8(&buf[..n]).unwrap());
#[cfg(feature = "display_sh1106")]
if let Some(content_start) = buf.array_windows().position(|o| o == b"\r\n\r\n") {
if let Some(text) = String::from_ascii(&buf[content_start + 4..n]) {
display::CHANNEL.send(text).await;
}
}
//break 'get;
}
Timer::after(Duration::from_millis(5_000)).await;
}
}

1
esp/src/modem.rs Normal file
View file

@ -0,0 +1 @@

13
esp/src/rng.rs Normal file
View file

@ -0,0 +1,13 @@
use core::cell::OnceCell;
use embassy_sync::{mutex::Mutex, blocking_mutex::NoopMutex};
use esp_hal::{peripherals::Peripherals, rng::Trng};
static TRNG: OnceCell<Mutex<NoopMutex<Trng>, Trng>> = OnceCell::new();
pub fn init(rng: Peripherals::RNG, adc1: Peripherals::ADC1) {
TRNG.set(Mutex::new(Trng::new(peripherals.RNG, &mut peripherals.ADC1))).unwrap();
}
pub async fn randomize(buf: &mut [u8]) {
TRNG.get().expect("no RNG").lock().await.read(buf)
}

45
esp/src/string.rs Normal file
View file

@ -0,0 +1,45 @@
use core::{mem::MaybeUninit, str::from_utf8_unchecked};
#[derive(Clone)]
pub struct String<const N: usize> {
buf: [u8; N],
len: usize,
}
impl<const N: usize> String<N> {
pub fn from_str(s: &str) -> Self {
let mut buf = [0; N];
buf[0..s.as_bytes().len()].copy_from_slice(s.as_bytes());
Self { len: s.len(), buf }
}
pub fn from_ascii(s: &[u8]) -> Option<Self> {
if s.len() < N && s.is_ascii() {
let mut buf = [0; N];
buf[0..s.len()].copy_from_slice(s);
Some(Self { len: s.len(), buf })
} else {
None
}
}
pub fn from_buf_ascii(buf: [u8; N], len: usize) -> Option<Self> {
if len < N && buf[0..len].is_ascii() {
Some(Self { buf, len })
} else {
None
}
}
}
impl<const N: usize> AsRef<str> for String<N> {
fn as_ref(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(&self.buf[0..self.len]) }
}
}
impl<const N: usize> AsMut<str> for String<N> {
fn as_mut(&mut self) -> &mut str {
unsafe { core::str::from_utf8_unchecked_mut(&mut self.buf[0..self.len]) }
}
}

8
esp/src/util.rs Normal file
View file

@ -0,0 +1,8 @@
macro_rules! mk_static {
($t:ty, $val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}

112
esp/src/wifi.rs Normal file
View file

@ -0,0 +1,112 @@
//use crate::rng::randomize;
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use esp_hal::{peripheral::Peripheral, rng::Rng};
use esp_println::println;
use esp_wifi::{
wifi::{WifiController, WifiDevice, WifiEvent, WifiStaDevice, WifiState},
EspWifiController, EspWifiTimerSource,
};
use static_cell::StaticCell;
const SSID: &str = include_str!("../wifi-ssid.txt");
const PASSWORD: &str = include_str!("../wifi-psw.txt");
static WIFI_CONTROLLER: StaticCell<WifiController> = StaticCell::new();
pub fn pre_init<'d, T: EspWifiTimerSource>(
timer: impl Peripheral<P = T> + 'static,
rng: Rng,
radio_clk: esp_hal::peripherals::RADIO_CLK,
wifi: esp_hal::peripherals::WIFI,
) -> (
WifiDevice<'static, WifiStaDevice>,
&'static mut WifiController<'static>,
) {
let wifi_init = esp_wifi::init(timer, rng, radio_clk).unwrap();
let wifi_init = mk_static!(EspWifiController, wifi_init);
let (wifi_interface, wifi_controller) =
esp_wifi::wifi::new_with_mode(wifi_init, wifi, WifiStaDevice).unwrap();
(wifi_interface, WIFI_CONTROLLER.init(wifi_controller))
}
pub fn post_init(
spawner: &Spawner,
interface: WifiDevice<'static, WifiStaDevice>,
controller: &'static mut WifiController,
seed: u64,
) -> &'static embassy_net::Stack<WifiDevice<'static, WifiStaDevice>> {
let net_stack = &*mk_static!(
embassy_net::Stack<WifiDevice<'_, WifiStaDevice>>,
embassy_net::Stack::new(
interface,
embassy_net::Config::dhcpv4(Default::default()),
mk_static!(
embassy_net::StackResources<3>,
embassy_net::StackResources::<3>::new()
),
seed
)
);
spawner.spawn(connection(controller, &net_stack)).ok();
spawner.spawn(net_task(&net_stack)).ok();
net_stack
}
/// Connection task
///
/// Reconnects automatically when needed.
#[embassy_executor::task]
pub async fn connection(
controller: &'static mut WifiController<'static>,
stack: &'static embassy_net::Stack<WifiDevice<'static, WifiStaDevice>>,
) {
loop {
match esp_wifi::wifi::wifi_state() {
WifiState::StaConnected => {
controller.wait_for_event(WifiEvent::StaDisconnected).await;
Timer::after(Duration::from_millis(5000)).await
}
_ => {}
}
if !matches!(controller.is_started(), Ok(true)) {
let client_config =
esp_wifi::wifi::Configuration::Client(esp_wifi::wifi::ClientConfiguration {
ssid: SSID.try_into().unwrap(),
password: PASSWORD.try_into().unwrap(),
auth_method: esp_wifi::wifi::AuthMethod::WPA2Personal,
..Default::default()
});
controller.set_configuration(&client_config).unwrap();
controller.start_async().await.unwrap();
}
match controller.connect_async().await {
Ok(_) => {
while !stack.is_link_up() {
Timer::after(Duration::from_millis(500)).await;
}
loop {
if let Some(config) = stack.config_v4() {
println!("IP {}", config.address);
break;
}
Timer::after(Duration::from_millis(500)).await;
}
}
Err(e) => {
println!("Wifi err: {e:?}");
Timer::after(Duration::from_millis(5000)).await
}
}
}
}
#[embassy_executor::task]
pub async fn net_task(stack: &'static embassy_net::Stack<WifiDevice<'static, WifiStaDevice>>) {
stack.run().await
}

View file

@ -0,0 +1,2 @@
(kicad_pcb (version 20211014) (generator pcbnew)
)

View file

@ -0,0 +1,75 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "rustphone.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View file

@ -0,0 +1,326 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.1,
"copper_line_width": 0.2,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"other_line_width": 0.15,
"silk_line_width": 0.15,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"rules": {
"min_copper_edge_clearance": 0.0,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0
},
"track_widths": [],
"via_dimensions": []
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "rustphone.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"33d5e076-e860-4c0d-8690-a28c727934d6",
""
]
],
"text_variables": {}
}

View file

@ -0,0 +1,421 @@
(kicad_sch (version 20211123) (generator eeschema)
(uuid 33d5e076-e860-4c0d-8690-a28c727934d6)
(paper "A4")
(lib_symbols
(symbol "RF_Module:ESP32-WROOM-32" (in_bom yes) (on_board yes)
(property "Reference" "U" (id 0) (at -12.7 34.29 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "ESP32-WROOM-32" (id 1) (at 1.27 34.29 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "RF_Module:ESP32-WROOM-32" (id 2) (at 0 -38.1 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf" (id 3) (at -7.62 1.27 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_keywords" "RF Radio BT ESP ESP32 Espressif onboard PCB antenna" (id 4) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_description" "RF Module, ESP32-D0WDQ6 SoC, Wi-Fi 802.11b/g/n, Bluetooth, BLE, 32-bit, 2.7-3.6V, onboard antenna, SMD" (id 5) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_fp_filters" "ESP32?WROOM?32*" (id 6) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "ESP32-WROOM-32_0_1"
(rectangle (start -12.7 33.02) (end 12.7 -33.02)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type background))
)
)
(symbol "ESP32-WROOM-32_1_1"
(pin power_in line (at 0 -35.56 90) (length 2.54)
(name "GND" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -12.7 180) (length 2.54)
(name "IO25" (effects (font (size 1.27 1.27))))
(number "10" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -15.24 180) (length 2.54)
(name "IO26" (effects (font (size 1.27 1.27))))
(number "11" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -17.78 180) (length 2.54)
(name "IO27" (effects (font (size 1.27 1.27))))
(number "12" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 10.16 180) (length 2.54)
(name "IO14" (effects (font (size 1.27 1.27))))
(number "13" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 15.24 180) (length 2.54)
(name "IO12" (effects (font (size 1.27 1.27))))
(number "14" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -35.56 90) (length 2.54) hide
(name "GND" (effects (font (size 1.27 1.27))))
(number "15" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 12.7 180) (length 2.54)
(name "IO13" (effects (font (size 1.27 1.27))))
(number "16" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at -15.24 -5.08 0) (length 2.54)
(name "SHD/SD2" (effects (font (size 1.27 1.27))))
(number "17" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at -15.24 -7.62 0) (length 2.54)
(name "SWP/SD3" (effects (font (size 1.27 1.27))))
(number "18" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at -15.24 -12.7 0) (length 2.54)
(name "SCS/CMD" (effects (font (size 1.27 1.27))))
(number "19" (effects (font (size 1.27 1.27))))
)
(pin power_in line (at 0 35.56 270) (length 2.54)
(name "VDD" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at -15.24 -10.16 0) (length 2.54)
(name "SCK/CLK" (effects (font (size 1.27 1.27))))
(number "20" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at -15.24 0 0) (length 2.54)
(name "SDO/SD0" (effects (font (size 1.27 1.27))))
(number "21" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at -15.24 -2.54 0) (length 2.54)
(name "SDI/SD1" (effects (font (size 1.27 1.27))))
(number "22" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 7.62 180) (length 2.54)
(name "IO15" (effects (font (size 1.27 1.27))))
(number "23" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 25.4 180) (length 2.54)
(name "IO2" (effects (font (size 1.27 1.27))))
(number "24" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 30.48 180) (length 2.54)
(name "IO0" (effects (font (size 1.27 1.27))))
(number "25" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 20.32 180) (length 2.54)
(name "IO4" (effects (font (size 1.27 1.27))))
(number "26" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 5.08 180) (length 2.54)
(name "IO16" (effects (font (size 1.27 1.27))))
(number "27" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 2.54 180) (length 2.54)
(name "IO17" (effects (font (size 1.27 1.27))))
(number "28" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 17.78 180) (length 2.54)
(name "IO5" (effects (font (size 1.27 1.27))))
(number "29" (effects (font (size 1.27 1.27))))
)
(pin input line (at -15.24 30.48 0) (length 2.54)
(name "EN" (effects (font (size 1.27 1.27))))
(number "3" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 0 180) (length 2.54)
(name "IO18" (effects (font (size 1.27 1.27))))
(number "30" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -2.54 180) (length 2.54)
(name "IO19" (effects (font (size 1.27 1.27))))
(number "31" (effects (font (size 1.27 1.27))))
)
(pin no_connect line (at -12.7 -27.94 0) (length 2.54) hide
(name "NC" (effects (font (size 1.27 1.27))))
(number "32" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -5.08 180) (length 2.54)
(name "IO21" (effects (font (size 1.27 1.27))))
(number "33" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 22.86 180) (length 2.54)
(name "RXD0/IO3" (effects (font (size 1.27 1.27))))
(number "34" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 27.94 180) (length 2.54)
(name "TXD0/IO1" (effects (font (size 1.27 1.27))))
(number "35" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -7.62 180) (length 2.54)
(name "IO22" (effects (font (size 1.27 1.27))))
(number "36" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -10.16 180) (length 2.54)
(name "IO23" (effects (font (size 1.27 1.27))))
(number "37" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -35.56 90) (length 2.54) hide
(name "GND" (effects (font (size 1.27 1.27))))
(number "38" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -35.56 90) (length 2.54) hide
(name "GND" (effects (font (size 1.27 1.27))))
(number "39" (effects (font (size 1.27 1.27))))
)
(pin input line (at -15.24 25.4 0) (length 2.54)
(name "SENSOR_VP" (effects (font (size 1.27 1.27))))
(number "4" (effects (font (size 1.27 1.27))))
)
(pin input line (at -15.24 22.86 0) (length 2.54)
(name "SENSOR_VN" (effects (font (size 1.27 1.27))))
(number "5" (effects (font (size 1.27 1.27))))
)
(pin input line (at 15.24 -25.4 180) (length 2.54)
(name "IO34" (effects (font (size 1.27 1.27))))
(number "6" (effects (font (size 1.27 1.27))))
)
(pin input line (at 15.24 -27.94 180) (length 2.54)
(name "IO35" (effects (font (size 1.27 1.27))))
(number "7" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -20.32 180) (length 2.54)
(name "IO32" (effects (font (size 1.27 1.27))))
(number "8" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 15.24 -22.86 180) (length 2.54)
(name "IO33" (effects (font (size 1.27 1.27))))
(number "9" (effects (font (size 1.27 1.27))))
)
)
)
(symbol "power:+3.3V" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes)
(property "Reference" "#PWR" (id 0) (at 0 -3.81 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "+3.3V" (id 1) (at 0 3.556 0)
(effects (font (size 1.27 1.27)))
)
(property "Footprint" "" (id 2) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_keywords" "global power" (id 4) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_description" "Power symbol creates a global label with name \"+3.3V\"" (id 5) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "+3.3V_0_1"
(polyline
(pts
(xy -0.762 1.27)
(xy 0 2.54)
)
(stroke (width 0) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy 0 0)
(xy 0 2.54)
)
(stroke (width 0) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy 0 2.54)
(xy 0.762 1.27)
)
(stroke (width 0) (type default) (color 0 0 0 0))
(fill (type none))
)
)
(symbol "+3.3V_1_1"
(pin power_in line (at 0 0 90) (length 0) hide
(name "+3.3V" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
)
)
(symbol "power:GND" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes)
(property "Reference" "#PWR" (id 0) (at 0 -6.35 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "GND" (id 1) (at 0 -3.81 0)
(effects (font (size 1.27 1.27)))
)
(property "Footprint" "" (id 2) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_keywords" "global power" (id 4) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_description" "Power symbol creates a global label with name \"GND\" , ground" (id 5) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "GND_0_1"
(polyline
(pts
(xy 0 0)
(xy 0 -1.27)
(xy 1.27 -1.27)
(xy 0 -2.54)
(xy -1.27 -1.27)
(xy 0 -1.27)
)
(stroke (width 0) (type default) (color 0 0 0 0))
(fill (type none))
)
)
(symbol "GND_1_1"
(pin power_in line (at 0 0 270) (length 0) hide
(name "GND" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
)
)
)
(wire (pts (xy 148.59 62.23) (xy 148.59 66.04))
(stroke (width 0) (type default) (color 0 0 0 0))
(uuid 19d45abe-91d7-44a3-8fc5-e46648ba6dca)
)
(wire (pts (xy 163.83 73.66) (xy 168.91 73.66))
(stroke (width 0) (type default) (color 0 0 0 0))
(uuid 20286759-2770-44a3-981c-a9525dd4f09f)
)
(wire (pts (xy 163.83 78.74) (xy 168.91 78.74))
(stroke (width 0) (type default) (color 0 0 0 0))
(uuid 2447ec89-9baa-4310-bb23-4a1a090d8e88)
)
(global_label "ESP TX" (shape output) (at 168.91 73.66 0) (fields_autoplaced)
(effects (font (size 1.27 1.27)) (justify left))
(uuid 88f45ca8-1b2d-438a-95f5-b3f574f8e065)
(property "Intersheet References" "${INTERSHEET_REFS}" (id 0) (at 178.0964 73.5806 0)
(effects (font (size 1.27 1.27)) (justify left) hide)
)
)
(global_label "ESP RX" (shape input) (at 168.91 78.74 0) (fields_autoplaced)
(effects (font (size 1.27 1.27)) (justify left))
(uuid f6d3abd9-3e7f-41d5-b834-6386537d250a)
(property "Intersheet References" "${INTERSHEET_REFS}" (id 0) (at 178.3988 78.6606 0)
(effects (font (size 1.27 1.27)) (justify left) hide)
)
)
(symbol (lib_id "RF_Module:ESP32-WROOM-32") (at 148.59 101.6 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 2ddc8287-4db8-4b01-8738-0389a16e3708)
(property "Reference" "U?" (id 0) (at 150.6094 63.5 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "ESP32-WROOM-32" (id 1) (at 150.6094 66.04 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "RF_Module:ESP32-WROOM-32" (id 2) (at 148.59 139.7 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf" (id 3) (at 140.97 100.33 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 617d04b2-778c-4c17-b858-abcdd87ed5b7))
(pin "10" (uuid 3004ebc3-bcf5-4092-b803-ca947cf2f90d))
(pin "11" (uuid d226c80a-1255-43dd-9817-db9552d0dd41))
(pin "12" (uuid 0c5ca6d6-e9e4-4fae-bfed-eb44cf00a3fc))
(pin "13" (uuid 152dafdd-42cc-419d-984f-03b43f5ac05f))
(pin "14" (uuid a4086a5f-6ceb-4da4-950b-0100d4410dd5))
(pin "15" (uuid 8a142bd5-6085-40f3-a1e2-aa080db5ab7a))
(pin "16" (uuid 139b4af1-4fda-4b9b-8d0e-3b0ee118e1e3))
(pin "17" (uuid ee59e263-238a-4c1a-810d-0025094f1a66))
(pin "18" (uuid 7c47d99e-229e-4aa6-8be1-671b3b997f0e))
(pin "19" (uuid 4f89f528-213c-495c-88d8-539d701afa14))
(pin "2" (uuid 78226c67-7fbf-463c-a731-2e441c462c86))
(pin "20" (uuid d113318f-305a-40cd-bfc5-0bbf3dd34e2d))
(pin "21" (uuid abf0bcdb-358d-4b4f-9408-6b7af4492045))
(pin "22" (uuid 465e70d8-3d2b-4572-8fd0-26bdae47888f))
(pin "23" (uuid 955413b9-9a01-4429-8bb0-744d9a1a79a7))
(pin "24" (uuid 06863726-082f-414b-8c9b-cd1f5426f031))
(pin "25" (uuid 47eb2e08-3651-4af6-a977-0b826e8e6b6f))
(pin "26" (uuid c6f3a5bc-1aae-4b29-a584-7fe00842fe49))
(pin "27" (uuid 31fe87fa-6ed4-42c7-ab81-85287f0a39cb))
(pin "28" (uuid 9f8db0f6-f71e-42a6-a3a4-afdb7209929c))
(pin "29" (uuid 3dafa118-5795-412a-9e7c-4676c3b27c63))
(pin "3" (uuid 605d6339-d73b-4f8c-9721-5cc90db53fbe))
(pin "30" (uuid bd5d1957-7306-4457-bb58-c3c54052381a))
(pin "31" (uuid 6ce6cb43-08a0-43b3-8441-0a76687518e9))
(pin "32" (uuid 616d353d-5028-4919-a055-f8b5b771ae3d))
(pin "33" (uuid de4abf6b-d48b-4e4a-a3ae-ef4c26998ae2))
(pin "34" (uuid 45e26484-7da1-4e9b-a121-6f723b4b0e38))
(pin "35" (uuid 7ff6d162-54f4-42c5-b530-da891e99bc33))
(pin "36" (uuid 317cf7e4-2ddf-4397-bce5-34caa6d55514))
(pin "37" (uuid 5d389f71-e54e-4a5f-b073-f349879cf868))
(pin "38" (uuid cba4f270-2f67-432f-a3bb-b03a782f4df2))
(pin "39" (uuid 9ea9dcba-626d-424e-8b66-3a4374e45b8f))
(pin "4" (uuid 153b854d-e387-49c3-8e17-ad306c73923b))
(pin "5" (uuid 65e6c4a1-65aa-4587-9d85-55c921c3bcb6))
(pin "6" (uuid 68676eb5-0218-439e-a23e-ca472fd30102))
(pin "7" (uuid 9a407737-9e4e-410c-b7d3-34d2fcee2801))
(pin "8" (uuid 12ed85d5-5bd5-4d63-8061-a225758d357d))
(pin "9" (uuid addc2c4b-dd27-4fda-be5f-c5712082dcc4))
)
(symbol (lib_id "power:+3.3V") (at 148.59 62.23 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 43ce7471-58df-4f74-95ff-b4582314a8a7)
(property "Reference" "#PWR?" (id 0) (at 148.59 66.04 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "+3.3V" (id 1) (at 148.59 57.15 0))
(property "Footprint" "" (id 2) (at 148.59 62.23 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 148.59 62.23 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 26d213df-d0ad-4c0a-978f-3a5307875fbb))
)
(symbol (lib_id "power:GND") (at 148.59 137.16 0) (unit 1)
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 75bdc9a1-b579-426b-add2-c5bee9cca894)
(property "Reference" "#PWR?" (id 0) (at 148.59 143.51 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "GND" (id 1) (at 148.59 142.24 0))
(property "Footprint" "" (id 2) (at 148.59 137.16 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 148.59 137.16 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 041548c8-17e0-4608-b805-26d5cd153184))
)
(sheet_instances
(path "/" (page "1"))
)
(symbol_instances
(path "/43ce7471-58df-4f74-95ff-b4582314a8a7"
(reference "#PWR?") (unit 1) (value "+3.3V") (footprint "")
)
(path "/75bdc9a1-b579-426b-add2-c5bee9cca894"
(reference "#PWR?") (unit 1) (value "GND") (footprint "")
)
(path "/2ddc8287-4db8-4b01-8738-0389a16e3708"
(reference "U?") (unit 1) (value "ESP32-WROOM-32") (footprint "RF_Module:ESP32-WROOM-32")
)
)
)

17
samd/.cargo/config.toml Normal file
View file

@ -0,0 +1,17 @@
# samd21 is a Cortex-M0 and thus thumbv6m
[build]
target = "thumbv6m-none-eabi"
[target.thumbv6m-none-eabi]
runner = 'arm-none-eabi-gdb'
#runner = 'probe-run --chip ATSAMD21G18A'
rustflags = [
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
]

1
samd/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

768
samd/Cargo.lock generated Normal file
View file

@ -0,0 +1,768 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "atsamd-hal"
version = "0.17.0"
dependencies = [
"aes",
"atsamd-hal-macros",
"atsamd21g",
"bitfield",
"bitflags",
"cipher",
"cortex-m",
"embedded-hal 0.2.7",
"embedded-hal 1.0.0",
"embedded-hal-nb",
"embedded-io",
"embedded-sdmmc",
"fugit",
"modular-bitfield",
"nb 1.1.0",
"num-traits",
"opaque-debug",
"paste",
"rand_core",
"seq-macro",
"typenum",
"usb-device",
"vcell",
"void",
]
[[package]]
name = "atsamd-hal-macros"
version = "0.1.0"
dependencies = [
"litrs",
"phf",
"phf_codegen",
"serde",
"serde_yaml",
]
[[package]]
name = "atsamd21g"
version = "0.13.0"
dependencies = [
"cortex-m",
"cortex-m-rt",
"critical-section",
"vcell",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bare-metal"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
dependencies = [
"rustc_version",
]
[[package]]
name = "bitfield"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]]
name = "cortex-m"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
dependencies = [
"bare-metal",
"bitfield",
"critical-section",
"embedded-hal 0.2.7",
"volatile-register",
]
[[package]]
name = "cortex-m-rt"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1"
dependencies = [
"cortex-m-rt-macros",
]
[[package]]
name = "cortex-m-rt-macros"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "cpufeatures"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
dependencies = [
"libc",
]
[[package]]
name = "critical-section"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242"
[[package]]
name = "embedded-hal"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
dependencies = [
"nb 0.1.3",
"void",
]
[[package]]
name = "embedded-hal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
[[package]]
name = "embedded-hal-nb"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605"
dependencies = [
"embedded-hal 1.0.0",
"nb 1.1.0",
]
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "embedded-sdmmc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d3bf0a2b5becb87e9a329d9290f131e4d10fec39b56d129926826a7cbea1e7a"
dependencies = [
"byteorder",
"embedded-hal 0.2.7",
"log",
"nb 0.1.3",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fugit"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
dependencies = [
"gcd",
]
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.76",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-core",
"futures-macro",
"futures-sink",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "gcd"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "hash32"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heapless"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [
"hash32",
"stable_deref_trait",
]
[[package]]
name = "indexmap"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "lilos"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090b27a32adb71568314e1c256f3f79b917e74194f0aba4d0e7493537e2820e9"
dependencies = [
"cfg-if",
"cortex-m",
"cortex-m-rt",
"lilos-list",
"pin-project",
]
[[package]]
name = "lilos-list"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a0f878c972c8b8c28a03b0b433c7f4b0861de43de55fe04546fe44ff7fa32b8"
dependencies = [
"pin-project",
]
[[package]]
name = "litrs"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
dependencies = [
"proc-macro2",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "maduino_zero_4g"
version = "0.1.0"
dependencies = [
"atsamd-hal",
"cortex-m",
"cortex-m-rt",
"embedded-sdmmc",
"usb-device",
]
[[package]]
name = "modular-bitfield"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
dependencies = [
"modular-bitfield-impl",
"static_assertions",
]
[[package]]
name = "modular-bitfield-impl"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "nb"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
dependencies = [
"nb 1.1.0",
]
[[package]]
name = "nb"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "panic-halt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "phf"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.76",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "portable-atomic"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "rustphone"
version = "0.1.0"
dependencies = [
"atsamd-hal",
"cortex-m",
"futures",
"lilos",
"maduino_zero_4g",
"nb 1.1.0",
"panic-halt",
"usb-device",
"usbd-serial",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "seq-macro"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
[[package]]
name = "serde"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.76",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unsafe-libyaml"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "usb-device"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6"
dependencies = [
"heapless",
"portable-atomic",
]
[[package]]
name = "usbd-serial"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065e4eaf93db81d5adac82d9cef8f8da314cb640fa7f89534b972383f1cf80fc"
dependencies = [
"embedded-hal 0.2.7",
"embedded-io",
"nb 1.1.0",
"usb-device",
]
[[package]]
name = "vcell"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "volatile-register"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
dependencies = [
"vcell",
]

48
samd/Cargo.toml Normal file
View file

@ -0,0 +1,48 @@
[package]
name = "rustphone"
version = "0.1.0"
authors = ["tuxmain <tuxmain@zettascript.org>"]
repository = "https://git.txmn.tk/tuxmain/rustphone"
license = "AGPL-3.0-only"
edition = "2021"
[dependencies]
#arrayvec = { version = "0.7.4", default_features = false }
atsamd-hal = { git = "https://github.com/ZettaScript/atsamd", branch = "maduino-zero-4g", default_features = false, features = ["dma", "samd21g", "samd21g-rt", "usb"] }
#cfg-if = "1.0.0"
cortex-m = "0.7.7"
#embedded-graphics = "0.8.1"
#embedded-layout = "0.4.1"
#embedded-text = "0.7.0"
#embedded-sdmmc = { version = "0.3.0", default_features = false }
#epd-waveshare = "0.5.0"
#epd-waveshare = { git = "https://github.com/caemor/epd-waveshare.git" }
#epd-waveshare = { path = "../../epd-waveshare" }
futures = { version = "0.3.30", default-features = false, features = ["async-await"] }
lilos = { version = "1.2.0" }
maduino_zero_4g = { git = "https://github.com/ZettaScript/atsamd", branch = "maduino-zero-4g", features = ["dma", "usb"] }
nb = "1.1.0"
panic-halt = "0.2.0"
#static_assertions = "1.1.0"
#tz-rs = { version = "0.6.14", default_features = false, features = ["const"] }
#tzdb = { version = "0.6.1", optional = true }
usbd-serial = "0.2"
usb-device = "0.3.1"
# simulator
#embedded-graphics-simulator = { version = "0.6.0", optional = true }
[features]
#default = ["simulator"]
#simulator = ["embedded-graphics-simulator", "tzdb"]
[profile.release]
panic = "abort"
lto = "fat"
opt-level = 3
debug = 0
[patch."https://github.com/ZettaScript/atsamd"]
atsamd-hal = { path = "../../atsamd/hal" }
maduino_zero_4g = { path = "../../atsamd/boards/maduino_zero_4g" }

2
samd/flash.sh Normal file
View file

@ -0,0 +1,2 @@
cargo flash --release --target thumbv6m-none-eabi --chip ATSAMD21G18A --protocol swd || exit 1
probe-run -v --no-flash --chip ATSAMD21G18A target/thumbv6m-none-eabi/release/rustphone

6
samd/memory.x Normal file
View file

@ -0,0 +1,6 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}
_stack_start = ORIGIN(RAM) + LENGTH(RAM);

3
samd/openocd.sh Normal file
View file

@ -0,0 +1,3 @@
cargo build --release --target thumbv6m-none-eabi || exit 1
cp target/thumbv6m-none-eabi/release/rustphone /tmp/rustphone.elf || exit 1
openocd -f /usr/share/openocd/scripts/board/atmel_samd21_xplained_pro.cfg -c "program /tmp/rustphone.elf verify reset exit"

View file

@ -1,6 +1,6 @@
use crate::{
apps::{self, App},
display::Display,
display::*,
keypad::*,
state::{self, ModeState},
strf, Context,
@ -12,6 +12,7 @@ use embedded_graphics::{
pixelcolor::BinaryColor,
prelude::*,
text::{Alignment, Text},
geometry::Dimensions
};
pub struct Clock;
@ -52,8 +53,8 @@ impl App for Clock {
// TODO move at init
let clock_text_style = MonoTextStyleBuilder::new()
.font(&FONT_10X20)
.text_color(BinaryColor::On)
.background_color(BinaryColor::Off)
.text_color(WHITE)
.background_color(BLACK)
.build();
for key_event in &ctx.key_events {

View file

@ -1,6 +1,6 @@
use crate::{
apps::App,
display::Display,
display::*,
keypad::{Key, KeyEvent, KeyEventType, KeyEvents, KeyInputMode},
state::{ModeState, State},
Context,
@ -47,8 +47,8 @@ impl App for Dial {
// TODO move to init
let dial_text_style = MonoTextStyleBuilder::new()
.font(&FONT_10X20)
.text_color(BinaryColor::On)
.background_color(BinaryColor::Off)
.text_color(WHITE)
.background_color(BLACK)
.build();
let textbox_style = TextBoxStyleBuilder::new()
.height_mode(HeightMode::FitToText)
@ -69,6 +69,7 @@ impl App for Dial {
}
Key::OptionRight => {
if mode_state.line.pop().is_some() {
// TODO redraw background over the erased character
mode_state.line_changed = true;
} else {
return Some(ModeState::Clock(Default::default()));

View file

@ -1,6 +1,10 @@
use embedded_graphics::{pixelcolor::BinaryColor, prelude::*};
use embedded_graphics::{prelude::*};
use epd_waveshare::epd1in54::{Display1in54, Epd1in54};
pub type Color = epd_waveshare::color::Color;
pub const BLACK: Color = epd_waveshare::color::Color::Black;
pub const WHITE: Color = epd_waveshare::color::Color::White;
pub struct Display {
//epd: Epd1in54,
display: Display1in54,

View file

@ -3,6 +3,10 @@ use embedded_graphics_simulator::{
BinaryColorTheme, OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window,
};
pub type Color = BinaryColor;
pub const BLACK: Color = BinaryColor::Off;
pub const WHITE: Color = BinaryColor::On;
static mut WINDOW: core::mem::MaybeUninit<Window> = core::mem::MaybeUninit::uninit();
pub fn window() -> &'static Window {

View file

@ -69,8 +69,7 @@ impl Keypad {
#[cfg(feature = "simulator")]
fn get_keys(&self) -> [bool; NB_KEYS] {
use embedded_graphics_simulator::sdl2::Keycode;
use embedded_graphics_simulator::SimulatorEvent;
use embedded_graphics_simulator::{sdl2::Keycode, SimulatorEvent};
let mut keys = [false; NB_KEYS];
crate::display::window_mut()
@ -88,7 +87,7 @@ impl Keypad {
Keycode::Num8 | Keycode::Kp8 => Some(Key::D8),
Keycode::Num9 | Keycode::Kp9 => Some(Key::D9),
Keycode::KpEnter | Keycode::Return => Some(Key::Enter),
Keycode::Asterisk => Some(Key::Asterisk),
Keycode::Asterisk | Keycode::KpMultiply => Some(Key::Asterisk),
Keycode::Hash | Keycode::KpHash => Some(Key::Hash),
// TODO more
_ => None,
@ -148,19 +147,22 @@ impl KeyEvent {
pub fn get_char(&self, key_input_mode: KeyInputMode) -> Option<char> {
use Key::*;
match key_input_mode {
KeyInputMode::Digit => match self.key {
D0 => Some('0'),
D1 => Some('1'),
D2 => Some('2'),
D3 => Some('3'),
D4 => Some('4'),
D5 => Some('5'),
D6 => Some('6'),
D7 => Some('7'),
D8 => Some('8'),
D9 => Some('9'),
Asterisk => Some('*'),
Hash => Some('#'),
KeyInputMode::Digit => match (self.key, self.repeats) {
(D0, _) => Some('0'),
(D1, _) => Some('1'),
(D2, _) => Some('2'),
(D3, _) => Some('3'),
(D4, _) => Some('4'),
(D5, _) => Some('5'),
(D6, _) => Some('6'),
(D7, _) => Some('7'),
(D8, _) => Some('8'),
(D9, _) => Some('9'),
(Asterisk, 1) => Some('*'),
(Asterisk, 2) => Some('+'),
(Asterisk, 3) => Some('p'),
(Asterisk, 4) => Some('W'),
(Hash, _) => Some('#'),
_ => None,
},
_ => {

View file

@ -10,18 +10,24 @@ mod gui;
mod keypad;
mod state;
mod strf;
mod text_input;
mod time;
use apps::App;
use display::Display;
use display::*;
use energy::EnergyStatus;
use keypad::KeyEvents;
use state::*;
use arrayvec::ArrayString;
use core::fmt::Write;
use core::sync::atomic;
use cortex_m::peripheral::NVIC;
use embedded_graphics::{
mono_font::{ascii::FONT_10X20, ascii::FONT_6X10, ascii::FONT_9X15, MonoTextStyleBuilder},
mono_font::{
ascii::{FONT_10X20, FONT_6X10, FONT_9X15},
MonoTextStyleBuilder,
},
pixelcolor::BinaryColor,
prelude::*,
primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle, StrokeAlignment},
@ -30,38 +36,121 @@ use embedded_graphics::{
#[cfg(not(feature = "simulator"))]
use maduino_zero_4g::{
self as bsp,
hal::{
clock::GenericClockController,
hal::{rtc::Rtc,
clock::{enable_external_32kosc, enable_internal_32kosc, ClockGenId, ClockSource, GenericClockController},
delay::Delay,
pac::{CorePeripherals, Peripherals},
prelude::*,
pac::{CorePeripherals, Peripherals, interrupt, RTC},
prelude::*,sleeping_delay::SleepingDelay
},
};
#[cfg(not(feature = "simulator"))]
use panic_halt as _;
use tz::DateTime;
// Check that stack overflow is unlikely
#[cfg(not(feature = "simulator"))]
static_assertions::const_assert!(
core::mem::size_of::<(
State,
ModeState,
Peripherals,
maduino_zero_4g::Pins,
CorePeripherals,
keypad::Keypad,
Display,
Context,
fs::Fs,
)>() < 16 * 1024
);
static INTERRUPT_FIRED: atomic::AtomicBool = atomic::AtomicBool::new(false);
#[cfg_attr(not(feature = "simulator"), bsp::entry)]
fn main() -> ! {
cfg_if::cfg_if! {
if #[cfg(not(feature = "simulator"))] {
let mut peripherals = Peripherals::take().unwrap();
let mut pins = maduino_zero_4g::Pins::new(peripherals.PORT);
let core = CorePeripherals::take().unwrap();
let mut core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
let mut delay = Delay::new(core.SYST, &mut clocks);
enable_external_32kosc(&mut peripherals.SYSCTRL);
let timer_clock = clocks
.configure_gclk_divider_and_source(ClockGenId::GCLK2, 1, ClockSource::XOSC32K, false)
.unwrap();
let mut fs = fs::Fs::new(atsamd_hal::sercom::spi::Config::new(
/*let mut clocks = GenericClockController::with_internal_8mhz(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
// Get a clock & make a sleeping delay object. use internal 32k clock that runs
// in standby
enable_internal_32kosc(&mut peripherals.SYSCTRL);
let timer_clock = clocks
.configure_gclk_divider_and_source(ClockGenId::GCLK1, 1, ClockSource::OSC32K, false)
.unwrap();*/
clocks.configure_standby(ClockGenId::GCLK2, true);
let rtc_clock = clocks.rtc(&timer_clock).unwrap();
let timer = Rtc::count32_mode(peripherals.RTC, rtc_clock.freq(), &mut peripherals.PM);
let mut sleeping_delay = SleepingDelay::new(timer, &INTERRUPT_FIRED);
//let mut delay = Delay::new(core.SYST, &mut clocks);
/* let mut fs = fs::Fs::new(atsamd_hal::sercom::spi::Config::new(
&peripherals.PM,
peripherals.SERCOM4,
atsamd_hal::sercom::spi::Pads::default().data_in(pins.sd_miso).data_out(pins.sd_mosi).sclk(pins.sd_sck),
10_u32.mhz(),
10_u32.MHz(),
).enable(), pins.d4.into_push_pull_output());
*/
// We can use the RTC in standby for maximum power savings
core.SCB.set_sleepdeep();
// enable interrupts
unsafe {
core.NVIC.set_priority(interrupt::RTC, 2);
NVIC::unmask(interrupt::RTC);
}
// Turn off unnecessary peripherals
peripherals.PM.ahbmask.modify(|_, w| {
w.usb_().clear_bit();
w.dmac_().clear_bit()
});
peripherals.PM.apbamask.modify(|_, w| {
w.eic_().clear_bit();
w.wdt_().clear_bit();
w.sysctrl_().clear_bit();
w.pac0_().clear_bit()
});
peripherals.PM.apbbmask.modify(|_, w| {
w.usb_().clear_bit();
w.dmac_().clear_bit();
w.nvmctrl_().clear_bit();
w.dsu_().clear_bit();
w.pac1_().clear_bit()
});
// Thankfully the only one default on here is ADC
peripherals.PM.apbcmask.modify(|_, w| w.adc_().clear_bit());
let mut led = pins.d9.into_push_pull_output();
loop {
sleeping_delay.delay_ms(1000u16);
led.set_high().unwrap();
sleeping_delay.delay_ms(1000u16);
led.set_low().unwrap();
}
}
}
@ -81,17 +170,17 @@ fn main() -> ! {
let mut display = Display::new();
let mut keypad = keypad::Keypad::default();
let thin_stroke = PrimitiveStyle::with_stroke(BinaryColor::On, 1);
let thick_stroke = PrimitiveStyle::with_stroke(BinaryColor::On, 3);
let fill = PrimitiveStyle::with_fill(BinaryColor::On);
let thin_stroke = PrimitiveStyle::with_stroke(WHITE, 1);
let thick_stroke = PrimitiveStyle::with_stroke(WHITE, 3);
let fill = PrimitiveStyle::with_fill(WHITE);
let statusbar_text_style = MonoTextStyleBuilder::new()
.font(&FONT_9X15)
.text_color(BinaryColor::On)
.background_color(BinaryColor::Off)
.text_color(WHITE)
.background_color(BLACK)
.build();
let key_label_text_style = MonoTextStyleBuilder::new()
.font(&FONT_6X10)
.text_color(BinaryColor::On)
.text_color(WHITE)
.build();
Line::new(Point::new(0, 13), Point::new(199, 13))
@ -121,19 +210,26 @@ fn main() -> ! {
if energy_status != ctx.state.energy {
ctx.update = true;
Text::with_alignment(
/*Text::with_alignment(
unsafe { core::str::from_utf8_unchecked(&strf::fmt_energy(&energy_status)) },
Point::new(0, 9),
statusbar_text_style,
Alignment::Left,
)
.draw(ctx.display.inner_mut())
.unwrap();
.unwrap();*/
ctx.state.energy = energy_status;
}
ctx.now = time::now();
//ctx.now = time::now();
//ctx.now = tz::DateTime::from_timespec(rtc.count32() as i64, 0, tz::TimeZoneRef::utc()).unwrap();
if ctx.now.second() % 2 == 0 {
led.set_high().unwrap();
} else {
led.set_low().unwrap();
}
let hour = ctx.now.hour();
let minute = ctx.now.minute();
@ -143,19 +239,19 @@ fn main() -> ! {
ctx.state.hour = hour;
ctx.state.minute = minute;
Text::with_alignment(
/*Text::with_alignment(
unsafe { core::str::from_utf8_unchecked(&strf::fmt_time_hm(hour, minute)) },
Point::new(199, 9),
statusbar_text_style,
Alignment::Right,
)
.draw(ctx.display.inner_mut())
.unwrap();
.unwrap();*/
}
ctx.key_events = keypad.update();
if let Some(new_mode_state) = match &mut mode_state {
/*if let Some(new_mode_state) = match &mut mode_state {
ModeState::Nothing => Some(ModeState::Clock(Default::default())),
ModeState::Clock(clock_state) => apps::clock::Clock::update(&mut ctx, clock_state),
ModeState::Dial(dial_state) => apps::dial::Dial::update(&mut ctx, dial_state),
@ -175,11 +271,11 @@ fn main() -> ! {
}
ModeState::Dial(dial_state) => apps::dial::Dial::on_enter(&mut ctx, dial_state),
}
}
}*/
if ctx.key_labels_change {
/*if ctx.key_labels_change {
let bg_style = PrimitiveStyleBuilder::new()
.fill_color(BinaryColor::Off)
.fill_color(BLACK)
.build();
Rectangle::new(Point::new(0, 190), Size::new(200, 12))
.into_styled(bg_style)
@ -211,7 +307,7 @@ fn main() -> ! {
.draw(ctx.display.inner_mut())
.unwrap();
ctx.key_labels_change = false;
}
}*/
#[cfg(feature = "simulator")]
{
@ -222,8 +318,8 @@ fn main() -> ! {
if ctx.update {
ctx.display.update();
}
#[cfg(not(feature = "simulator"))]
delay.delay_ms(50_u8);
//#[cfg(not(feature = "simulator"))]
//delay.delay_ms(50_u8);
ctx.update = false;
ctx.hm_change = false;
@ -239,3 +335,17 @@ pub struct Context<'a> {
pub update: bool,
pub key_events: KeyEvents,
}
#[interrupt]
fn RTC() {
// Let the sleepingtimer know that the interrupt fired, and clear it
INTERRUPT_FIRED.store(true, atomic::Ordering::Relaxed);
unsafe {
RTC::ptr()
.as_ref()
.unwrap()
.mode0()
.intflag
.modify(|_, w| w.cmp0().set_bit());
}
}

View file

@ -0,0 +1,6 @@
use arrayvec::ArrayString;
pub struct TextInput<const N: usize> {
cursor: usize,
value: ArrayString<N>,
}

113
samd/src/main.rs Normal file
View file

@ -0,0 +1,113 @@
#![no_std]
#![no_main]
mod usb;
use core::{convert::Infallible, mem::MaybeUninit, pin::pin, time::Duration};
use cortex_m::peripheral::NVIC;
use lilos::time::sleep_for;
use maduino_zero_4g::{
self as bsp,
hal::{
clock::GenericClockController,
ehal::digital::OutputPin,
pac::{interrupt, CorePeripherals, Peripherals},
prelude::*,
usb::UsbBus,dmac::{DmaController, PriorityLevel}
},
};
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{SerialPort, USB_CLASS_CDC};
use panic_halt as _;
#[bsp::entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let mut pins = maduino_zero_4g::Pins::new(peripherals.PORT);
let mut core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
let mut dmac = DmaController::init(peripherals.DMAC, &mut peripherals.PM);
let mut led1 = pins.d9.into_push_pull_output();
let mut led2 = pins.d8.into_push_pull_output();
let mut modem_uart = bsp::setup_modem(
&mut clocks,
(115200).Hz(),
peripherals.SERCOM0,
&mut peripherals.PM,
pins.d0,
pins.d1,
);
let bus_allocator = unsafe {
usb::USB_ALLOCATOR = Some(bsp::usb_allocator(
peripherals.USB,
&mut clocks,
&mut peripherals.PM,
pins.usb_dm,
pins.usb_dp,
));
usb::USB_ALLOCATOR.as_ref().unwrap()
};
unsafe {
usb::USB_SERIAL = Some(SerialPort::new(bus_allocator));
usb::USB_BUS = Some(
UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x2222, 0x3333))
.device_class(USB_CLASS_CDC)
.build(),
);
}
unsafe {
core.NVIC.set_priority(interrupt::USB, 1);
NVIC::unmask(interrupt::USB);
}
let mut delay = atsamd_hal::delay::Delay::new(core.SYST, &mut clocks);
delay.delay_ms(1000u16);
let mut syst = delay.free();
lilos::time::initialize_sys_tick(&mut syst, 32_000_000);
/*let (mut rx, mut tx) = modem_uart.split();
const LENGTH: usize = 256;
let tx_buffer: &'static mut [u8; LENGTH] =
cortex_m::singleton!(: [u8; LENGTH] = [0x00; LENGTH]).unwrap();
let rx_buffer: &'static mut [u8; LENGTH] =
cortex_m::singleton!(: [u8; LENGTH] = [0x00; LENGTH]).unwrap();
for (c_buf, c_str) in tx_buffer.iter_mut().zip(b"AT+CGMM\r\n") {
*c_buf = *c_str;
}
let channels = dmac.split();
let chan0 = channels.0.init(PriorityLevel::LVL0);
let chan1 = channels.1.init(PriorityLevel::LVL0);
let tx_dma = tx.send_with_dma(&mut tx_buffer[..9], chan0, |_| {});
let (_chan0, _tx, _tx_buffer) = tx_dma.wait();
let rx_dma = rx.receive_with_dma(rx_buffer, chan1, |_| {});
let (_chan1, _rx, rx_buffer) = rx_dma.wait();
cortex_m::interrupt::free(|_| unsafe {
if let Some(serial) = usb::USB_SERIAL.as_mut() {
let _ = serial.write(rx_buffer);
}
});*/
let fut1 = pin!(blinky(Duration::from_millis(1000), led1));
let fut2 = pin!(blinky(Duration::from_millis(333), led2));
let fut3 = pin!(usb::log_usb(Duration::from_millis(2000)));
//let fut3 = pin!(usb::usb_echo());
lilos::exec::run_tasks(&mut [fut1, fut2, fut3], lilos::exec::ALL_TASKS)
}
async fn blinky<P: OutputPin>(interval: Duration, mut led: P) -> Infallible {
loop {
led.set_high().ok();
sleep_for(interval).await;
led.set_low().ok();
sleep_for(interval).await;
}
}

100
samd/src/usb.rs Normal file
View file

@ -0,0 +1,100 @@
use core::{convert::Infallible, mem::MaybeUninit, time::Duration};
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{embedded_io::{ReadReady, WriteReady}, SerialPort, USB_CLASS_CDC};
use maduino_zero_4g::{
self as bsp,
hal::{
clock::GenericClockController,
ehal::digital::OutputPin,
pac::{interrupt, CorePeripherals, Peripherals},
prelude::*,
usb::UsbBus,
},pac::USB,
};
use cortex_m::peripheral::NVIC;
pub static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
pub static mut USB_BUS: Option<UsbDevice<UsbBus>> = None;
pub static mut USB_SERIAL: Option<SerialPort<UsbBus>> = None;
pub async fn usb_echo() -> Infallible {
let mut q_storage: [MaybeUninit<u8>; 256] = [MaybeUninit::uninit(); 256];
let mut q = lilos::spsc::Queue::new(&mut q_storage);
let (q_push, q_pop) = q.split();
futures::future::join(usb_echo_rx(q_push), usb_echo_tx(q_pop)).await.0
}
async fn usb_echo_rx(
mut q: lilos::spsc::Pusher<'_, u8>,
) -> Infallible {
loop {
q.reserve().await.push(usb_recv().await);
}
}
// https://github.com/cbiffle/lilos/blob/main/examples/stm32f4/uart-echo/src/main.rs
async fn usb_echo_tx(
mut q: lilos::spsc::Popper<'_, u8>,
) -> Infallible {
loop {
usb_send(q.pop().await).await;
}
}
static TXE: lilos::exec::Notify = lilos::exec::Notify::new();
async fn usb_send(c: u8) {
unsafe {
if let Some(serial) = USB_SERIAL.as_mut() {
RXE.until(|| serial.write_ready().unwrap_or(false)).await;
//serial.write(&[c]).ok();
lilos::time::sleep_for(Duration::from_millis(100)).await;
}
}
}
static RXE: lilos::exec::Notify = lilos::exec::Notify::new();
async fn usb_recv() -> u8 {
unsafe {
if let Some(serial) = USB_SERIAL.as_mut() {
RXE.until(|| serial.read_ready().unwrap_or(false)).await;
let mut buf = [0];
//serial.read(&mut buf).ok();
lilos::time::sleep_for(Duration::from_millis(100)).await;
return buf[0];
}
}
0
}
pub async fn log_usb(interval: Duration) -> Infallible {
loop {
lilos::time::sleep_for(interval).await;
cortex_m::interrupt::free(|_| unsafe {
if let Some(serial) = USB_SERIAL.as_mut() {
let _ = serial.write(b"log line\r\n");
}
});
}
}
fn poll_usb() {
unsafe {
if let Some(usb_dev) = USB_BUS.as_mut() {
if let Some(serial) = USB_SERIAL.as_mut() {
usb_dev.poll(&mut [serial]);
// Make the other side happy
let mut buf = [0u8; 16];
let _ = serial.read(&mut buf);
}
}
};
}
#[interrupt]
fn USB() {
poll_usb();
//RXE.notify();
//TXE.notify();
}