improved wheel handling + tests
This commit is contained in:
parent
6b38c36a28
commit
ea1db833f3
9 changed files with 2318 additions and 13 deletions
|
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
[target.xtensa-esp32-none-elf]
|
[target.xtensa-esp32-none-elf]
|
||||||
runner = "espflash flash --monitor"
|
runner = "espflash flash --monitor"
|
||||||
|
|
||||||
[build]
|
|
||||||
target = "xtensa-esp32-none-elf"
|
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-C", "link-arg=-Wl,-Tlinkall.x",
|
"-C", "link-arg=-Wl,-Tlinkall.x",
|
||||||
"-C", "link-arg=-nostartfiles",
|
"-C", "link-arg=-nostartfiles",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "xtensa-esp32-none-elf"
|
||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std = ["core", "alloc", "compiler_builtins"]
|
build-std = ["core", "alloc", "compiler_builtins"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let target = std::env::var("TARGET").unwrap_or_default();
|
||||||
|
if !target.starts_with("xtensa-") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
let kind = &args[1];
|
let kind = &args[1];
|
||||||
|
|
|
||||||
2187
esp32/host-tests/Cargo.lock
generated
Normal file
2187
esp32/host-tests/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,7 @@ use esp_hal::time::Rate;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
use crate::WHEEL_VALUE;
|
use crate::WHEEL_VALUE;
|
||||||
|
use esp32::{apply_wheel_delta, wheel_delta};
|
||||||
|
|
||||||
pub static INPUT: Channel<CriticalSectionRawMutex, u8, 64> = Channel::new();
|
pub static INPUT: Channel<CriticalSectionRawMutex, u8, 64> = Channel::new();
|
||||||
pub static ANGLE: Mutex<CriticalSectionRawMutex, u16> = Mutex::new(0);
|
pub static ANGLE: Mutex<CriticalSectionRawMutex, u16> = Mutex::new(0);
|
||||||
|
|
@ -34,18 +35,24 @@ pub async fn rotation_read_task(config: RotationConfig) {
|
||||||
let old = *locked as i32;
|
let old = *locked as i32;
|
||||||
*locked = angle;
|
*locked = angle;
|
||||||
drop(locked);
|
drop(locked);
|
||||||
let left_diff = old - angle as i32;
|
let diff = wheel_delta(old, angle as i32, crate::WHEEL_INVERTED);
|
||||||
let right_diff = angle as i32 - old;
|
|
||||||
let diff = if left_diff.abs() < right_diff.abs() { -left_diff } else { right_diff };
|
|
||||||
let mut wheel = WHEEL_VALUE.lock().await;
|
let mut wheel = WHEEL_VALUE.lock().await;
|
||||||
if wheel.max != wheel.min {
|
if wheel.max != wheel.min {
|
||||||
let wheel_range = wheel.max - wheel.min;
|
let min = wheel.min;
|
||||||
wheel.value += diff * wheel_range / 4096;
|
let max = wheel.max;
|
||||||
if wheel.value < wheel.min {
|
let mut value = wheel.value;
|
||||||
wheel.value = wheel.min;
|
let mut accumulated = wheel.accumulated;
|
||||||
} else if wheel.value > wheel.max {
|
let precision = crate::WHEEL_PRECISION;
|
||||||
wheel.value = wheel.max;
|
apply_wheel_delta(
|
||||||
}
|
&mut value,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
&mut accumulated,
|
||||||
|
diff,
|
||||||
|
precision,
|
||||||
|
);
|
||||||
|
wheel.value = value;
|
||||||
|
wheel.accumulated = accumulated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
esp32/src/lib.rs
Normal file
5
esp32/src/lib.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
mod wheel;
|
||||||
|
|
||||||
|
pub use wheel::{apply_wheel_delta, wheel_delta};
|
||||||
|
|
@ -29,6 +29,8 @@ const WIFI_NETWORK: &str = "flamme";
|
||||||
const WIFI_PASSWORD: &str = "12345678";
|
const WIFI_PASSWORD: &str = "12345678";
|
||||||
const TARGET_IP: &str = "84.238.32.253";
|
const TARGET_IP: &str = "84.238.32.253";
|
||||||
const TARGET_PORT: u16 = 7070;
|
const TARGET_PORT: u16 = 7070;
|
||||||
|
const WHEEL_PRECISION: i32 = 32;
|
||||||
|
const WHEEL_INVERTED: bool = false;
|
||||||
|
|
||||||
enum QuestionType {
|
enum QuestionType {
|
||||||
Choice,
|
Choice,
|
||||||
|
|
@ -47,6 +49,7 @@ struct WheelData {
|
||||||
value: i32,
|
value: i32,
|
||||||
min: i32,
|
min: i32,
|
||||||
max: i32,
|
max: i32,
|
||||||
|
accumulated: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
static QUESTION: Mutex<CriticalSectionRawMutex, Option<QuestionData>> = Mutex::new(None);
|
static QUESTION: Mutex<CriticalSectionRawMutex, Option<QuestionData>> = Mutex::new(None);
|
||||||
|
|
@ -55,6 +58,7 @@ static WHEEL_VALUE: Mutex<CriticalSectionRawMutex, WheelData> = Mutex::new(Wheel
|
||||||
value: 0,
|
value: 0,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 0,
|
max: 0,
|
||||||
|
accumulated: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
|
|
@ -79,6 +83,7 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
|
||||||
value: 0,
|
value: 0,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 0,
|
max: 0,
|
||||||
|
accumulated: 0,
|
||||||
};
|
};
|
||||||
for line in str.lines() {
|
for line in str.lines() {
|
||||||
if line == "$$" {
|
if line == "$$" {
|
||||||
|
|
@ -120,6 +125,7 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
|
||||||
if let QuestionType::Numeric { min, max } = q_type {
|
if let QuestionType::Numeric { min, max } = q_type {
|
||||||
let diff = max - min;
|
let diff = max - min;
|
||||||
future_wheel.value = min + diff / 2;
|
future_wheel.value = min + diff / 2;
|
||||||
|
future_wheel.accumulated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
question_data = Some(QuestionData {
|
question_data = Some(QuestionData {
|
||||||
|
|
|
||||||
48
esp32/src/wheel.rs
Normal file
48
esp32/src/wheel.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
pub const WHEEL_TICKS: i32 = 4096;
|
||||||
|
|
||||||
|
pub fn wheel_delta(old_angle: i32, current_angle: i32, inverted: bool) -> i32 {
|
||||||
|
let mut diff = current_angle - old_angle;
|
||||||
|
if diff.abs() > WHEEL_TICKS / 2 {
|
||||||
|
diff = if diff > 0 {
|
||||||
|
diff - WHEEL_TICKS
|
||||||
|
} else {
|
||||||
|
diff + WHEEL_TICKS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if inverted {
|
||||||
|
-diff
|
||||||
|
} else {
|
||||||
|
diff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_wheel_delta(
|
||||||
|
value: &mut i32,
|
||||||
|
min: i32,
|
||||||
|
max: i32,
|
||||||
|
accumulated: &mut i32,
|
||||||
|
diff: i32,
|
||||||
|
precision: i32,
|
||||||
|
) {
|
||||||
|
if max == min || precision <= 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*accumulated += diff;
|
||||||
|
let step_count = *accumulated / precision;
|
||||||
|
if step_count == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*accumulated -= step_count * precision;
|
||||||
|
*value += step_count;
|
||||||
|
if *value < min {
|
||||||
|
*value = min;
|
||||||
|
} else if *value > max {
|
||||||
|
*value = max;
|
||||||
|
}
|
||||||
|
if *value == min || *value == max {
|
||||||
|
*accumulated = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
esp32/test.sh
Normal file
1
esp32/test.sh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
rustc --test wheel-tests.rs -o wheel-tests && ./wheel-tests
|
||||||
46
esp32/wheel-tests.rs
Normal file
46
esp32/wheel-tests.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod wheel {
|
||||||
|
include!("src/wheel.rs");
|
||||||
|
}
|
||||||
|
|
||||||
|
use wheel::{apply_wheel_delta, wheel_delta};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wraps_forward_across_zero() {
|
||||||
|
assert_eq!(wheel_delta(4090, 5, false), 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wraps_backward_across_zero() {
|
||||||
|
assert_eq!(wheel_delta(5, 4090, false), -11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inverts_direction() {
|
||||||
|
assert_eq!(wheel_delta(10, 20, true), -10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn accumulates_before_applying_selection() {
|
||||||
|
let mut value = 5;
|
||||||
|
let mut accumulated = 0;
|
||||||
|
|
||||||
|
apply_wheel_delta(&mut value, 0, 10, &mut accumulated, 10, 32);
|
||||||
|
assert_eq!(value, 5);
|
||||||
|
assert_eq!(accumulated, 10);
|
||||||
|
|
||||||
|
apply_wheel_delta(&mut value, 0, 10, &mut accumulated, 22, 32);
|
||||||
|
assert_eq!(value, 6);
|
||||||
|
assert_eq!(accumulated, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clamps_and_resets_at_bounds() {
|
||||||
|
let mut value = 10;
|
||||||
|
let mut accumulated = 0;
|
||||||
|
|
||||||
|
apply_wheel_delta(&mut value, 0, 10, &mut accumulated, 64, 32);
|
||||||
|
assert_eq!(value, 10);
|
||||||
|
assert_eq!(accumulated, 0);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue