update
This commit is contained in:
parent
e14619a047
commit
37936d121d
6 changed files with 157 additions and 12 deletions
|
|
@ -67,4 +67,4 @@ ws.onmessage = (e) => {
|
|||
}
|
||||
};
|
||||
|
||||
console.log("Started on :7070");
|
||||
console.log(`Started on :${socket.port}`);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
50
pico/src/owned_str_writer.rs
Normal file
50
pico/src/owned_str_writer.rs
Normal 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)
|
||||
}
|
||||
|
|
@ -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(());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue