feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
@@ -0,0 +1 @@
|
||||
{"files":{".cargo_vcs_info.json":"e84afd10acd627e67ef9e58036c16f4b27959e07acb783379a55d4728c08e1c6","CHANGELOG.md":"602460216c9c4f2e51649aaefa95489ced263b3e19fccdb01216bd03d51f7eaf","Cargo.toml":"671771b4725def85bb01da18463dc2190ab87226ad8f9038de4054ab5f9dd33c","Cargo.toml.orig":"28d4e103c6c19609434705af627cf34370952a743560091fb8813162abd750cb","README.md":"b9f5bcbfc95982b6e62b2804b326c4c92d7f3d9c1ec158259527d28c54cbc110","src/lib.rs":"b58ba0ef8e200a46dd46f611518c93aa37f7bdfb3681e956e2bd0bed9f4e3561"},"package":"524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d"}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"git": {
|
||||
"sha1": "35ffdf2143991422c67f4b3517303a0b8f7a3bbe"
|
||||
},
|
||||
"path_in_vcs": "embassy-net-driver"
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0 - 2023-10-18
|
||||
|
||||
- Added support for IEEE 802.15.4 mediums.
|
||||
- Added `Driver::hardware_address()`, `HardwareAddress`.
|
||||
- Removed `Medium` enum. The medium is deduced out of the hardware address.
|
||||
- Removed `Driver::ethernet_address()`. Replacement is `hardware_address()`.
|
||||
|
||||
## 0.1.0 - 2023-06-29
|
||||
|
||||
- First release
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "embassy-net-driver"
|
||||
version = "0.2.0"
|
||||
description = "Driver trait for the `embassy-net` async TCP/IP network stack."
|
||||
readme = "README.md"
|
||||
categories = [
|
||||
"embedded",
|
||||
"no-std",
|
||||
"asynchronous",
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/embassy-rs/embassy"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["defmt"]
|
||||
|
||||
[package.metadata.embassy_docs]
|
||||
features = ["defmt"]
|
||||
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-driver-v$VERSION/embassy-net-driver/src/"
|
||||
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-driver/src/"
|
||||
target = "thumbv7em-none-eabi"
|
||||
|
||||
[dependencies.defmt]
|
||||
version = "0.3"
|
||||
optional = true
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
# embassy-net-driver
|
||||
|
||||
This crate contains the driver trait necessary for adding [`embassy-net`](https://crates.io/crates/embassy-net) support
|
||||
for a new hardware platform.
|
||||
|
||||
If you want to *use* `embassy-net` with already made drivers, you should depend on the main `embassy-net` crate, not on this crate.
|
||||
|
||||
If you are writing a driver, you should depend only on this crate, not on the main `embassy-net` crate.
|
||||
This will allow your driver to continue working for newer `embassy-net` major versions, without needing an update,
|
||||
if the driver trait has not had breaking changes.
|
||||
|
||||
See also [`embassy-net-driver-channel`](https://crates.io/crates/embassy-net-driver-channel), which provides a higer-level API
|
||||
to construct a driver that processes packets in its own background task and communicates with the `embassy-net` task via
|
||||
packet queues for RX and TX.
|
||||
|
||||
## Interoperability
|
||||
|
||||
This crate can run on any executor.
|
||||
|
||||
## License
|
||||
|
||||
This work is licensed under either of
|
||||
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
Vendored
+217
@@ -0,0 +1,217 @@
|
||||
#![no_std]
|
||||
#![warn(missing_docs)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use core::task::Context;
|
||||
|
||||
/// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum HardwareAddress {
|
||||
/// Ethernet medium, with a A six-octet Ethernet address.
|
||||
///
|
||||
/// Devices of this type send and receive Ethernet frames,
|
||||
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
|
||||
///
|
||||
/// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
|
||||
Ethernet([u8; 6]),
|
||||
/// 6LoWPAN over IEEE802.15.4, with an eight-octet address.
|
||||
Ieee802154([u8; 8]),
|
||||
/// Indicates that a Driver is IP-native, and has no hardware address.
|
||||
///
|
||||
/// Devices of this type send and receive IP frames, without an
|
||||
/// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
|
||||
///
|
||||
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
|
||||
Ip,
|
||||
}
|
||||
|
||||
/// Main `embassy-net` driver API.
|
||||
///
|
||||
/// This is essentially an interface for sending and receiving raw network frames.
|
||||
///
|
||||
/// The interface is based on _tokens_, which are types that allow to receive/transmit a
|
||||
/// single packet. The `receive` and `transmit` functions only construct such tokens, the
|
||||
/// real sending/receiving operation are performed when the tokens are consumed.
|
||||
pub trait Driver {
|
||||
/// A token to receive a single network packet.
|
||||
type RxToken<'a>: RxToken
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
/// A token to transmit a single network packet.
|
||||
type TxToken<'a>: TxToken
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
/// Construct a token pair consisting of one receive token and one transmit token.
|
||||
///
|
||||
/// If there is a packet ready to be received, this function must return `Some`.
|
||||
/// If there isn't, it must return `None`, and wake `cx.waker()` when a packet is ready.
|
||||
///
|
||||
/// The additional transmit token makes it possible to generate a reply packet based
|
||||
/// on the contents of the received packet. For example, this makes it possible to
|
||||
/// handle arbitrarily large ICMP echo ("ping") requests, where the all received bytes
|
||||
/// need to be sent back, without heap allocation.
|
||||
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>;
|
||||
|
||||
/// Construct a transmit token.
|
||||
///
|
||||
/// If there is free space in the transmit buffer to transmit a packet, this function must return `Some`.
|
||||
/// If there isn't, it must return `None`, and wake `cx.waker()` when space becomes available.
|
||||
///
|
||||
/// Note that [`TxToken::consume`] is infallible, so it is not allowed to return a token
|
||||
/// if there is no free space and fail later.
|
||||
fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>>;
|
||||
|
||||
/// Get the link state.
|
||||
///
|
||||
/// This function must return the current link state of the device, and wake `cx.waker()` when
|
||||
/// the link state changes.
|
||||
fn link_state(&mut self, cx: &mut Context) -> LinkState;
|
||||
|
||||
/// Get a description of device capabilities.
|
||||
fn capabilities(&self) -> Capabilities;
|
||||
|
||||
/// Get the device's hardware address.
|
||||
///
|
||||
/// The returned hardware address also determines the "medium" of this driver. This indicates
|
||||
/// what kind of packet the sent/received bytes are, and determines some behaviors of
|
||||
/// the interface. For example, ARP/NDISC address resolution is only done for Ethernet mediums.
|
||||
fn hardware_address(&self) -> HardwareAddress;
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Driver> Driver for &mut T {
|
||||
type RxToken<'a> = T::RxToken<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
type TxToken<'a> = T::TxToken<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
|
||||
T::transmit(self, cx)
|
||||
}
|
||||
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||
T::receive(self, cx)
|
||||
}
|
||||
fn capabilities(&self) -> Capabilities {
|
||||
T::capabilities(self)
|
||||
}
|
||||
fn link_state(&mut self, cx: &mut Context) -> LinkState {
|
||||
T::link_state(self, cx)
|
||||
}
|
||||
fn hardware_address(&self) -> HardwareAddress {
|
||||
T::hardware_address(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// A token to receive a single network packet.
|
||||
pub trait RxToken {
|
||||
/// Consumes the token to receive a single network packet.
|
||||
///
|
||||
/// This method receives a packet and then calls the given closure `f` with the raw
|
||||
/// packet bytes as argument.
|
||||
fn consume<R, F>(self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R;
|
||||
}
|
||||
|
||||
/// A token to transmit a single network packet.
|
||||
pub trait TxToken {
|
||||
/// Consumes the token to send a single network packet.
|
||||
///
|
||||
/// This method constructs a transmit buffer of size `len` and calls the passed
|
||||
/// closure `f` with a mutable reference to that buffer. The closure should construct
|
||||
/// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure
|
||||
/// returns, the transmit buffer is sent out.
|
||||
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R;
|
||||
}
|
||||
|
||||
/// A description of device capabilities.
|
||||
///
|
||||
/// Higher-level protocols may achieve higher throughput or lower latency if they consider
|
||||
/// the bandwidth or packet size limitations.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub struct Capabilities {
|
||||
/// Maximum transmission unit.
|
||||
///
|
||||
/// The network device is unable to send or receive frames larger than the value returned
|
||||
/// by this function.
|
||||
///
|
||||
/// For Ethernet devices, this is the maximum Ethernet frame size, including the Ethernet header (14 octets), but
|
||||
/// *not* including the Ethernet FCS (4 octets). Therefore, Ethernet MTU = IP MTU + 14.
|
||||
///
|
||||
/// Note that in Linux and other OSes, "MTU" is the IP MTU, not the Ethernet MTU, even for Ethernet
|
||||
/// devices. This is a common source of confusion.
|
||||
///
|
||||
/// Most common IP MTU is 1500. Minimum is 576 (for IPv4) or 1280 (for IPv6). Maximum is 9216 octets.
|
||||
pub max_transmission_unit: usize,
|
||||
|
||||
/// Maximum burst size, in terms of MTU.
|
||||
///
|
||||
/// The network device is unable to send or receive bursts large than the value returned
|
||||
/// by this function.
|
||||
///
|
||||
/// If `None`, there is no fixed limit on burst size, e.g. if network buffers are
|
||||
/// dynamically allocated.
|
||||
pub max_burst_size: Option<usize>,
|
||||
|
||||
/// Checksum behavior.
|
||||
///
|
||||
/// If the network device is capable of verifying or computing checksums for some protocols,
|
||||
/// it can request that the stack not do so in software to improve performance.
|
||||
pub checksum: ChecksumCapabilities,
|
||||
}
|
||||
|
||||
/// A description of checksum behavior for every supported protocol.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub struct ChecksumCapabilities {
|
||||
/// Checksum behavior for IPv4.
|
||||
pub ipv4: Checksum,
|
||||
/// Checksum behavior for UDP.
|
||||
pub udp: Checksum,
|
||||
/// Checksum behavior for TCP.
|
||||
pub tcp: Checksum,
|
||||
/// Checksum behavior for ICMPv4.
|
||||
pub icmpv4: Checksum,
|
||||
/// Checksum behavior for ICMPv6.
|
||||
pub icmpv6: Checksum,
|
||||
}
|
||||
|
||||
/// A description of checksum behavior for a particular protocol.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Checksum {
|
||||
/// Verify checksum when receiving and compute checksum when sending.
|
||||
Both,
|
||||
/// Verify checksum when receiving.
|
||||
Rx,
|
||||
/// Compute checksum before sending.
|
||||
Tx,
|
||||
/// Ignore checksum completely.
|
||||
None,
|
||||
}
|
||||
|
||||
impl Default for Checksum {
|
||||
fn default() -> Checksum {
|
||||
Checksum::Both
|
||||
}
|
||||
}
|
||||
|
||||
/// The link state of a network device.
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum LinkState {
|
||||
/// The link is down.
|
||||
Down,
|
||||
/// The link is up.
|
||||
Up,
|
||||
}
|
||||
Reference in new issue
Block a user