This commit is contained in:
Daniel Bulant 2026-05-10 12:43:10 +02:00
parent e14619a047
commit 37936d121d
No known key found for this signature in database
6 changed files with 157 additions and 12 deletions

View file

@ -67,4 +67,4 @@ ws.onmessage = (e) => {
}
};
console.log("Started on :7070");
console.log(`Started on :${socket.port}`);

View file

@ -9,7 +9,7 @@ use embassy_rp::{
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, mutex::Mutex};
use embassy_time::{Duration, Timer};
use crate::{Irqs, unwrap};
use crate::{Irqs, WHEEL_VALUE, unwrap};
/// Button input notification channel
pub static INPUT: Channel<CriticalSectionRawMutex, u8, 64> = Channel::new();
@ -43,10 +43,20 @@ pub async fn rotation_read_task(
let left_diff = old - angle as i32;
let right_diff = angle as i32 - old;
let diff = if left_diff.abs() < right_diff.abs() {
left_diff
-left_diff
} else {
right_diff
};
let mut wheel = WHEEL_VALUE.lock().await;
if wheel.max != wheel.min {
let wheel_range = wheel.max - wheel.min;
wheel.value += diff * wheel_range / 4096;
if wheel.value < wheel.min {
wheel.value = wheel.min;
} else if wheel.value > wheel.max {
wheel.value = wheel.max;
}
}
Timer::after(Duration::from_millis(50)).await;
}
}

View file

@ -2,6 +2,7 @@
#![no_main]
use core::str::FromStr;
use embassy_net::tcp::{TcpReader, TcpWriter};
use embassy_rp::multicore::{Stack, spawn_core1};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
@ -9,11 +10,13 @@ use embassy_sync::mutex::Mutex;
use embassy_sync::signal::Signal;
use embedded_io::Write;
use owned_str::OwnedStr;
use ufmt::uwrite;
use crate::buffer::WriteBuffer;
use crate::input::{ANGLE, INPUT, InputConfig};
use crate::net::network_setup_task;
use crate::screen::lcd_display_task;
use crate::owned_str_writer::{OwnedStrWriter, center_str};
use crate::screen::{lcd_display_task, overwrite_lcd};
use ag_lcd::{Blink, Cursor, Display, LcdDisplay};
use defmt::*;
use embassy_executor::Executor;
@ -23,7 +26,7 @@ use embassy_rp::peripherals::{DMA_CH0, I2C0, PIO0};
use embassy_rp::pio::InterruptHandler;
use embassy_rp::{bind_interrupts, dma};
use embassy_rp::{peripherals::USB, usb};
use embassy_time::Delay;
use embassy_time::{Delay, Timer};
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
@ -31,6 +34,7 @@ use {defmt_rtt as _, panic_probe as _};
mod buffer;
mod input;
mod net;
mod owned_str_writer;
mod screen;
const WIFI_NETWORK: &str = "flamme";
@ -61,14 +65,27 @@ struct QuestionData {
text: OwnedStr<256>,
q_type: QuestionType,
points: i32,
generation: usize,
}
#[derive(Clone, Copy)]
struct WheelData {
value: i32,
min: i32,
max: i32,
}
static QUESTION: Mutex<CriticalSectionRawMutex, Option<QuestionData>> = Mutex::new(None);
static QUESTION_UPDATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
static WHEEL_VALUE: Mutex<CriticalSectionRawMutex, i32> = Mutex::new(0);
static WHEEL_VALUE: Mutex<CriticalSectionRawMutex, WheelData> = Mutex::new(WheelData {
value: 0,
min: 0,
max: 0,
});
pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
let mut buf = [0u8; 1024];
let mut generation = 1;
while let Ok(len) = read.read(&mut buf).await {
if len == 0 {
@ -79,7 +96,11 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
};
let mut counter = 0;
let mut question_data = None;
let mut future_wheel = 0;
let mut future_wheel = WheelData {
value: 0,
min: 0,
max: 0,
};
for line in str.lines() {
if line == "$$" {
counter = 1;
@ -110,8 +131,10 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
} => {
if key == "rangeMin" {
*min = value.parse().unwrap();
future_wheel.min = *min;
} else {
*max = value.parse().unwrap();
future_wheel.max = *max;
}
}
}
@ -121,7 +144,7 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
match q_type {
QuestionType::Numeric { min, max } => {
let diff = max - min;
future_wheel = min + diff / 2;
future_wheel.value = min + diff / 2;
}
_ => {}
}
@ -130,12 +153,14 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
text: OwnedStr::new(),
q_type,
points,
generation,
});
counter = 2;
continue;
}
if counter == 2 {
question_data.as_mut().unwrap().text = OwnedStr::from_str(line).unwrap();
generation += 1;
counter = 0;
}
}
@ -159,6 +184,60 @@ pub async fn tcp_write_loop(mut write: TcpWriter<'_>) {
}
}
const ARROW_RIGHT: char = char::from_u32(0b0111_1110).unwrap();
const ARROW_LEFT: char = char::from_u32(0b0111_1111).unwrap();
const DOT: char = char::from_u32(0b1010_0101).unwrap();
#[embassy_executor::task]
pub async fn main_loop() {
let mut last_gen = 0;
let mut title_offset = 0;
loop {
Timer::after_millis(50).await;
let wheel = *WHEEL_VALUE.lock().await;
let question = QUESTION.lock().await;
let Some(question) = question.as_ref() else {
continue;
};
title_offset += 1;
if question.generation != last_gen {
last_gen = question.generation;
title_offset = 0;
}
let title_line = if question.text.len() > 16 {
title_offset %= question.text.len() - 16;
&question.text[title_offset..title_offset + 16]
} else {
&question.text
};
let number_str: OwnedStr<16> = match question.q_type {
QuestionType::Choice => {
let mut writer = OwnedStrWriter::new();
writer.push(DOT);
writer.push(' ');
uwrite!(writer, "{}", question.points).unwrap();
writer.into()
}
QuestionType::Numeric { min, max } => {
let mut writer = OwnedStrWriter::new();
if wheel.value > min {
writer.push(ARROW_LEFT);
writer.push(' ');
}
uwrite!(writer, "{}", wheel.value);
if wheel.value < max {
writer.push(ARROW_RIGHT);
writer.push(' ');
}
writer.into()
}
};
let second_line = center_str::<16>(&number_str, 16).unwrap();
overwrite_lcd(title_line, &second_line);
}
}
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();

View file

@ -6,7 +6,8 @@ use embassy_net::tcp::TcpSocket;
use crate::buffer::wait_for_config;
use crate::screen::SCREEN_BUFFER;
use crate::{
Irqs, TARGET_IP, TARGET_PORT, WIFI_NETWORK, WIFI_PASSWORD, tcp_read_loop, tcp_write_loop,
Irqs, TARGET_IP, TARGET_PORT, WIFI_NETWORK, WIFI_PASSWORD, main_loop, tcp_read_loop,
tcp_write_loop,
};
use cyw43::{JoinOptions, aligned_bytes};
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
@ -131,5 +132,7 @@ pub async fn network_setup_task(
let (read, write) = socket.split();
spawner.spawn(unwrap!(main_loop()));
join(tcp_read_loop(read), tcp_write_loop(write)).await;
}

View file

@ -0,0 +1,50 @@
use owned_str::{Error, OwnedStr};
use ufmt::uWrite;
pub struct OwnedStrWriter<const CAP: usize>(OwnedStr<CAP>);
impl<const CAP: usize> OwnedStrWriter<CAP> {
pub fn new() -> Self {
Self(OwnedStr::new())
}
pub fn push(&mut self, c: char) -> Result<(), Error> {
self.0.try_push(c).map(|_| ())
}
}
impl<const CAP: usize> From<OwnedStr<CAP>> for OwnedStrWriter<CAP> {
fn from(owned_str: OwnedStr<CAP>) -> Self {
Self(owned_str)
}
}
impl<const CAP: usize> From<OwnedStrWriter<CAP>> for OwnedStr<CAP> {
fn from(writer: OwnedStrWriter<CAP>) -> Self {
writer.0
}
}
impl<const CAP: usize> uWrite for OwnedStrWriter<CAP> {
type Error = owned_str::Error;
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.0.try_push_str(s).map(|_| ())
}
fn write_char(&mut self, c: char) -> Result<(), Self::Error> {
self.0.try_push(c).map(|_| ())
}
}
pub fn center_str<const CAP: usize>(
str: &str,
width: usize,
) -> Result<OwnedStr<CAP>, owned_str::Error> {
let mut res = OwnedStr::new();
let len = str.len();
let padding = (width.saturating_sub(len) + 1) / 2;
for _ in 0..padding {
res.try_push(' ')?;
}
res.try_push_str(str)?;
Ok(res)
}

View file

@ -1,7 +1,6 @@
use core::convert::Infallible;
use ag_lcd::LcdDisplay;
use embassy_futures::block_on;
use embassy_rp::gpio::Output;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal};
use embassy_time::{Delay, Timer};
@ -94,7 +93,11 @@ pub async fn lcd_display_task(mut lcd: LcdDisplay<Output<'static>, Delay>) {
pub async fn overwrite_lcd(line1: &str, line2: &str) {
let mut buffer = SCREEN_BUFFER.lock().await;
buffer.line1.copy_from_slice(line1.as_bytes());
buffer.line2.copy_from_slice(line2.as_bytes());
buffer.line1_ptr = 0;
buffer.line2_ptr = 0;
buffer.line1.fill(0);
buffer.line2.fill(0);
buffer.line1[..line1.len()].copy_from_slice(line1.as_bytes());
buffer.line2[..line2.len()].copy_from_slice(line2.as_bytes());
LCD_UPDATE.signal(());
}