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_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, mutex::Mutex};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
|
||||||
use crate::{Irqs, unwrap};
|
use crate::{Irqs, WHEEL_VALUE, unwrap};
|
||||||
|
|
||||||
/// Button input notification channel
|
/// Button input notification channel
|
||||||
pub static INPUT: Channel<CriticalSectionRawMutex, u8, 64> = Channel::new();
|
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 left_diff = old - angle as i32;
|
||||||
let right_diff = angle as i32 - old;
|
let right_diff = angle as i32 - old;
|
||||||
let diff = if left_diff.abs() < right_diff.abs() {
|
let diff = if left_diff.abs() < right_diff.abs() {
|
||||||
left_diff
|
-left_diff
|
||||||
} else {
|
} else {
|
||||||
right_diff
|
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;
|
Timer::after(Duration::from_millis(50)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
use embassy_net::tcp::{TcpReader, TcpWriter};
|
use embassy_net::tcp::{TcpReader, TcpWriter};
|
||||||
use embassy_rp::multicore::{Stack, spawn_core1};
|
use embassy_rp::multicore::{Stack, spawn_core1};
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
|
|
@ -9,11 +10,13 @@ use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::signal::Signal;
|
use embassy_sync::signal::Signal;
|
||||||
use embedded_io::Write;
|
use embedded_io::Write;
|
||||||
use owned_str::OwnedStr;
|
use owned_str::OwnedStr;
|
||||||
|
use ufmt::uwrite;
|
||||||
|
|
||||||
use crate::buffer::WriteBuffer;
|
use crate::buffer::WriteBuffer;
|
||||||
use crate::input::{ANGLE, INPUT, InputConfig};
|
use crate::input::{ANGLE, INPUT, InputConfig};
|
||||||
use crate::net::network_setup_task;
|
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 ag_lcd::{Blink, Cursor, Display, LcdDisplay};
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
|
|
@ -23,7 +26,7 @@ use embassy_rp::peripherals::{DMA_CH0, I2C0, PIO0};
|
||||||
use embassy_rp::pio::InterruptHandler;
|
use embassy_rp::pio::InterruptHandler;
|
||||||
use embassy_rp::{bind_interrupts, dma};
|
use embassy_rp::{bind_interrupts, dma};
|
||||||
use embassy_rp::{peripherals::USB, usb};
|
use embassy_rp::{peripherals::USB, usb};
|
||||||
use embassy_time::Delay;
|
use embassy_time::{Delay, Timer};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
@ -31,6 +34,7 @@ use {defmt_rtt as _, panic_probe as _};
|
||||||
mod buffer;
|
mod buffer;
|
||||||
mod input;
|
mod input;
|
||||||
mod net;
|
mod net;
|
||||||
|
mod owned_str_writer;
|
||||||
mod screen;
|
mod screen;
|
||||||
|
|
||||||
const WIFI_NETWORK: &str = "flamme";
|
const WIFI_NETWORK: &str = "flamme";
|
||||||
|
|
@ -61,14 +65,27 @@ struct QuestionData {
|
||||||
text: OwnedStr<256>,
|
text: OwnedStr<256>,
|
||||||
q_type: QuestionType,
|
q_type: QuestionType,
|
||||||
points: i32,
|
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: Mutex<CriticalSectionRawMutex, Option<QuestionData>> = Mutex::new(None);
|
||||||
static QUESTION_UPDATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
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<'_>) {
|
pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
|
||||||
let mut buf = [0u8; 1024];
|
let mut buf = [0u8; 1024];
|
||||||
|
let mut generation = 1;
|
||||||
|
|
||||||
while let Ok(len) = read.read(&mut buf).await {
|
while let Ok(len) = read.read(&mut buf).await {
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
|
|
@ -79,7 +96,11 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
|
||||||
};
|
};
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
let mut question_data = None;
|
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() {
|
for line in str.lines() {
|
||||||
if line == "$$" {
|
if line == "$$" {
|
||||||
counter = 1;
|
counter = 1;
|
||||||
|
|
@ -110,8 +131,10 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
|
||||||
} => {
|
} => {
|
||||||
if key == "rangeMin" {
|
if key == "rangeMin" {
|
||||||
*min = value.parse().unwrap();
|
*min = value.parse().unwrap();
|
||||||
|
future_wheel.min = *min;
|
||||||
} else {
|
} else {
|
||||||
*max = value.parse().unwrap();
|
*max = value.parse().unwrap();
|
||||||
|
future_wheel.max = *max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +144,7 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
|
||||||
match q_type {
|
match q_type {
|
||||||
QuestionType::Numeric { min, max } => {
|
QuestionType::Numeric { min, max } => {
|
||||||
let diff = max - min;
|
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(),
|
text: OwnedStr::new(),
|
||||||
q_type,
|
q_type,
|
||||||
points,
|
points,
|
||||||
|
generation,
|
||||||
});
|
});
|
||||||
counter = 2;
|
counter = 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if counter == 2 {
|
if counter == 2 {
|
||||||
question_data.as_mut().unwrap().text = OwnedStr::from_str(line).unwrap();
|
question_data.as_mut().unwrap().text = OwnedStr::from_str(line).unwrap();
|
||||||
|
generation += 1;
|
||||||
counter = 0;
|
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 mut CORE1_STACK: Stack<4096> = Stack::new();
|
||||||
static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
|
static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
|
||||||
static EXECUTOR1: 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::buffer::wait_for_config;
|
||||||
use crate::screen::SCREEN_BUFFER;
|
use crate::screen::SCREEN_BUFFER;
|
||||||
use crate::{
|
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::{JoinOptions, aligned_bytes};
|
||||||
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
|
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
|
||||||
|
|
@ -131,5 +132,7 @@ pub async fn network_setup_task(
|
||||||
|
|
||||||
let (read, write) = socket.split();
|
let (read, write) = socket.split();
|
||||||
|
|
||||||
|
spawner.spawn(unwrap!(main_loop()));
|
||||||
|
|
||||||
join(tcp_read_loop(read), tcp_write_loop(write)).await;
|
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 core::convert::Infallible;
|
||||||
|
|
||||||
use ag_lcd::LcdDisplay;
|
use ag_lcd::LcdDisplay;
|
||||||
use embassy_futures::block_on;
|
|
||||||
use embassy_rp::gpio::Output;
|
use embassy_rp::gpio::Output;
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal};
|
||||||
use embassy_time::{Delay, Timer};
|
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) {
|
pub async fn overwrite_lcd(line1: &str, line2: &str) {
|
||||||
let mut buffer = SCREEN_BUFFER.lock().await;
|
let mut buffer = SCREEN_BUFFER.lock().await;
|
||||||
buffer.line1.copy_from_slice(line1.as_bytes());
|
buffer.line1_ptr = 0;
|
||||||
buffer.line2.copy_from_slice(line2.as_bytes());
|
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(());
|
LCD_UPDATE.signal(());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue