Added more unittests

This commit is contained in:
Christoffer Martinsson 2025-09-16 08:37:06 +02:00
parent b98614fe8e
commit 9f95813f97
3 changed files with 86 additions and 15 deletions

View File

@ -416,6 +416,10 @@ pub fn calculate_axis_value(
) -> u16 {
use crate::hardware::{ADC_MAX, ADC_MIN, AXIS_CENTER};
if min >= max || center <= min || center >= max {
return center;
}
if value <= min {
return ADC_MIN;
}
@ -660,6 +664,20 @@ mod tests {
assert_eq!(result, AXIS_CENTER);
}
#[test]
fn test_calculate_axis_value_degenerate_calibration() {
let expo_lut = ExpoLUT::new(0.0);
// When calibration collapses to a single point (min=max=center),
// the output should remain at that center rather than clamping low/high.
let result = calculate_axis_value(2100, 2100, 2100, 2100, (0, 0, 0), false, &expo_lut);
assert_eq!(result, 2100);
// Also handle centers outside the valid window by returning center directly.
let result = calculate_axis_value(1500, 1400, 2000, 1400, (0, 0, 0), false, &expo_lut);
assert_eq!(result, 1400);
}
#[test]
fn test_remap_function() {
// Test basic remapping

View File

@ -8,9 +8,9 @@
//! - Evaluate special combinations (bootloader, calibration, etc.)
//! - Expose a compact state consumed by USB report generation
use crate::mapping::*;
use crate::button_matrix::ButtonMatrix;
use crate::hardware::{NUMBER_OF_BUTTONS, AXIS_CENTER, BUTTON_ROWS, BUTTON_COLS};
use crate::hardware::{AXIS_CENTER, BUTTON_COLS, BUTTON_ROWS, NUMBER_OF_BUTTONS};
use crate::mapping::*;
use embedded_hal::digital::InputPin;
use rp2040_hal::timer::Timer;
@ -39,14 +39,13 @@ pub struct Button {
// ==================== SPECIAL ACTIONS ====================
/// Highlevel actions triggered by dedicated button combinations.
#[derive(Debug, PartialEq)]
pub enum SpecialAction {
None,
Bootloader,
StartCalibration,
CancelCalibration,
ThrottleHold(u16), // Value to hold
ThrottleHold(u16), // Value to hold
VirtualThrottleToggle,
CalibrationSetModeM10,
CalibrationSetModeM7,
@ -55,7 +54,6 @@ pub enum SpecialAction {
// ==================== BUTTON MANAGER ====================
/// Aggregates and processes all buttons, exposing a stable API to the rest of the firmware.
pub struct ButtonManager {
pub buttons: [Button; TOTAL_BUTTONS],
}
@ -77,7 +75,10 @@ impl ButtonManager {
}
/// Update button states from the button matrix snapshot.
pub fn update_from_matrix(&mut self, matrix: &mut ButtonMatrix<BUTTON_ROWS, BUTTON_COLS, NUMBER_OF_BUTTONS>) {
pub fn update_from_matrix(
&mut self,
matrix: &mut ButtonMatrix<BUTTON_ROWS, BUTTON_COLS, NUMBER_OF_BUTTONS>,
) {
for (index, key) in matrix.buttons_pressed().iter().enumerate() {
self.buttons[index].pressed = *key;
}
@ -162,7 +163,11 @@ impl ButtonManager {
}
/// Check for special button combinations (bootloader, calibration state/mode, VT, etc.).
pub fn check_special_combinations(&self, unprocessed_axis_value: u16, calibration_active: bool) -> SpecialAction {
pub fn check_special_combinations(
&self,
unprocessed_axis_value: u16,
calibration_active: bool,
) -> SpecialAction {
// Secondary way to enter bootloader
if self.buttons[BUTTON_FRONT_LEFT_LOWER].pressed
&& self.buttons[BUTTON_TOP_LEFT_MODE].pressed
@ -297,13 +302,14 @@ fn update_button_press_type(button: &mut Button, current_time: u32) {
// Autorelease generated USB press after minimum hold time
const USB_MIN_HOLD_MS: u32 = 50;
if button.usb_press_active
&& (!button.pressed
&& !button.long_press_handled
&& current_time - button.usb_press_start_time >= USB_MIN_HOLD_MS)
|| (!button.enable_long_hold
&& button.long_press_handled
&& current_time - button.usb_press_start_time >= USB_MIN_HOLD_MS)
let elapsed = current_time.saturating_sub(button.usb_press_start_time);
let should_release = if button.long_press_handled {
!button.enable_long_hold && elapsed >= USB_MIN_HOLD_MS
} else {
!button.pressed && elapsed >= USB_MIN_HOLD_MS
};
if button.usb_press_active && should_release
{
button.usb_changed = true;
button.usb_press_active = false;
@ -483,6 +489,37 @@ mod tests {
assert!(button.long_press_handled);
}
#[test]
fn test_button_press_type_long_press_auto_release_once() {
let mut button = Button::default();
button.usb_button_long = 2;
button.enable_long_press = true;
button.enable_long_hold = false;
// Press the button
button.pressed = true;
update_button_press_type(&mut button, 0);
button.previous_pressed = button.pressed;
// Hold long enough to trigger the long press path
update_button_press_type(&mut button, 250);
assert!(button.usb_press_active);
assert_eq!(button.active_usb_button, 2);
// Clear the changed flag to emulate USB stack observing it
button.usb_changed = false;
// Keep holding and ensure we auto-release exactly once
update_button_press_type(&mut button, 320);
assert!(!button.usb_press_active);
assert!(button.usb_changed);
button.usb_changed = false;
update_button_press_type(&mut button, 400);
assert!(!button.usb_press_active);
assert!(!button.usb_changed);
}
#[test]
fn test_timer_integration_method_exists() {
let manager = ButtonManager::new();

View File

@ -135,7 +135,9 @@ impl CalibrationManager {
];
// Save calibration data to storage
let _ = storage::write_calibration_data(write_fn, &axis_data, self.gimbal_mode);
if storage::write_calibration_data(write_fn, &axis_data, self.gimbal_mode).is_err() {
return false;
}
// End calibration mode
self.active = false;
@ -519,6 +521,20 @@ mod tests {
assert!(!manager.is_active()); // Should end calibration
}
#[test]
fn test_save_calibration_failure_keeps_active() {
let mut manager = CalibrationManager::new();
manager.start_calibration();
let axes = [GimbalAxis::new(); NBR_OF_GIMBAL_AXIS];
let mut write_fn = |_page: u32, _data: &[u8]| Err(());
let result = manager.save_calibration(&axes, &mut write_fn);
assert!(!result);
assert!(manager.is_active());
}
#[test]
fn test_save_calibration_inactive() {
let mut manager = CalibrationManager::new(); // Note: not starting calibration