This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/esp-synopsys-usb-otg/src/endpoint_memory.rs
T
swaitsandClaude Opus 4.6 3102fc747a 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>
2026-03-29 20:42:54 -06:00

186 lines
5.0 KiB
Rust

#![allow(dead_code)]
use crate::target::{fifo_read_into, UsbRegisters};
use crate::UsbPeripheral;
use core::marker::PhantomData;
use core::slice;
use usb_device::{Result, UsbError};
use vcell::VolatileCell;
#[derive(Eq, PartialEq)]
pub enum EndpointBufferState {
Empty,
DataOut,
DataSetup,
}
pub struct EndpointBuffer {
buffer: &'static mut [VolatileCell<u32>],
data_size: u16,
has_data: bool,
is_setup: bool,
}
impl EndpointBuffer {
pub fn new(buffer: &'static mut [u32]) -> Self {
Self {
buffer: unsafe { &mut *(buffer as *mut [u32] as *mut [VolatileCell<u32>]) },
data_size: 0,
has_data: false,
is_setup: false,
}
}
pub fn read_packet(&mut self, mut buf: &mut [u8]) -> Result<usize> {
if !self.has_data {
return Err(UsbError::WouldBlock);
}
let data_size = self.data_size as usize;
if buf.len() < data_size {
return Err(UsbError::BufferOverflow);
}
let mut index = 0;
let mut current_size = data_size;
while current_size >= 4 {
let word = self.buffer[index].get();
index += 1;
let bytes = word.to_ne_bytes();
buf[..4].copy_from_slice(&bytes);
buf = &mut buf[4..];
current_size -= 4;
}
if current_size > 0 {
let word = self.buffer[index].get();
let bytes = word.to_ne_bytes();
buf[..current_size].copy_from_slice(&bytes[..current_size]);
}
self.has_data = false;
Ok(data_size)
}
pub fn fill_from_fifo(
&mut self,
usb: UsbRegisters,
data_size: u16,
is_setup: bool,
) -> Result<()> {
if self.has_data {
return Err(UsbError::WouldBlock);
}
if data_size as usize > self.capacity() {
return Err(UsbError::BufferOverflow);
}
let words = (data_size as usize + 3) / 4;
fifo_read_into(usb, &self.buffer[..words]);
self.is_setup = is_setup;
self.data_size = data_size;
self.has_data = true;
Ok(())
}
pub fn state(&self) -> EndpointBufferState {
if self.has_data {
if self.is_setup {
EndpointBufferState::DataSetup
} else {
EndpointBufferState::DataOut
}
} else {
EndpointBufferState::Empty
}
}
pub fn capacity(&self) -> usize {
self.buffer.len() * 4
}
}
impl Default for EndpointBuffer {
fn default() -> Self {
EndpointBuffer::new(&mut [])
}
}
pub struct EndpointMemoryAllocator<USB> {
next_free_offset: usize,
max_size_words: usize,
memory: &'static mut [u32],
tx_fifo_size_words: [u16; 9],
_marker: PhantomData<USB>,
}
impl<USB: UsbPeripheral> EndpointMemoryAllocator<USB> {
pub fn new(memory: &'static mut [u32]) -> Self {
Self {
next_free_offset: 0,
max_size_words: 0,
memory,
tx_fifo_size_words: [0; 9],
_marker: PhantomData,
}
}
pub fn allocate_rx_buffer(&mut self, size: usize) -> Result<EndpointBuffer> {
let size_words = (size + 3) / 4;
let offset = self.next_free_offset;
if offset + size_words > self.memory.len() {
return Err(UsbError::EndpointMemoryOverflow);
}
self.next_free_offset += size_words;
self.max_size_words = core::cmp::max(self.max_size_words, size_words);
let buffer = unsafe {
let ptr = self.memory.as_mut_ptr().add(offset);
slice::from_raw_parts_mut(ptr, size_words)
};
Ok(EndpointBuffer::new(buffer))
}
pub fn allocate_tx_buffer(&mut self, ep_number: u8, size: usize) -> Result<()> {
let ep_number = ep_number as usize;
assert!(ep_number < self.tx_fifo_size_words.len());
if self.tx_fifo_size_words[ep_number] != 0 {
return Err(UsbError::InvalidEndpoint);
}
let used = 30
+ self.total_rx_buffer_size_words() as usize
+ self.tx_fifo_size_words.iter().sum::<u16>() as usize;
let size_words = core::cmp::max((size + 3) / 4, 16);
if (used + size_words) > USB::FIFO_DEPTH_WORDS {
return Err(UsbError::EndpointMemoryOverflow);
}
self.tx_fifo_size_words[ep_number] = size_words as u16;
Ok(())
}
/// Returns the size of memory allocated for OUT endpoints in words
pub fn total_rx_buffer_size_words(&self) -> u16 {
self.next_free_offset as u16
}
pub fn tx_fifo_size_words(&self, ep_number: usize) -> u16 {
self.tx_fifo_size_words[ep_number]
}
pub fn max_buffer_size_words(&self) -> usize {
self.max_size_words
}
}