From 05fe3d8c4f8598b4882b6a47b06775ba91a591de Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:05:17 -0700 Subject: [PATCH 01/38] Refactor LoRa: Move async FSM to lora_async.c --- app/rev2/Makefile | 1 + app/rev2/flight.c | 6 ++++-- init/rev2/config/Src/stm32h7xx_it.c | 6 +++--- test/app/rev2/flight/mock/test_flight_stubs.c | 6 +++--- test/app/rev2/flight/test_flight.c | 6 +++--- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/rev2/Makefile b/app/rev2/Makefile index d849cf8e..e67d4370 100644 --- a/app/rev2/Makefile +++ b/app/rev2/Makefile @@ -87,6 +87,7 @@ $(DRIVER_DIR)/ignition/ignition.c \ $(DRIVER_DIR)/imu/imu.c \ $(DRIVER_DIR)/led/led.c \ $(DRIVER_DIR)/lora/lora.c \ +$(DRIVER_DIR)/lora/lora_async.c \ $(MOD_DIR)/sensor/sensor.c \ $(DRIVER_DIR)/usb/usb.c \ $(DRIVER_DIR)/gps/gps.c \ diff --git a/app/rev2/flight.c b/app/rev2/flight.c index 096ac12e..ac2f905e 100644 --- a/app/rev2/flight.c +++ b/app/rev2/flight.c @@ -30,6 +30,7 @@ Includes #include #include "main.h" #include "led.h" +#include "lora.h" #include "usb.h" #include "math.h" #include "sensor.h" @@ -149,6 +150,7 @@ if ( preset_data.config_settings.enabled_features & GPS_ENABLED ) sensorCalibrationSWCON(); write_preset( flash_handle, flash_address ); flash_erase_preserve_preset( flash_handle, flash_address ); +lora_fsm_set_mode( LORA_ASYNC_TX ); fc_state_update( FC_STATE_LAUNCH_DETECT ); @@ -202,11 +204,11 @@ if ( ( fc_state == FC_STATE_ASCENT ) update_state(); /*------------------------------------------------------------------------------ - Update Telemetry FSM + Update LoRa FSM ------------------------------------------------------------------------------*/ if ( preset_data.config_settings.enabled_features & WIRELESS_TRANSMISSION_ENABLED ) { - telemetry_update( TELEMETRY_EVENT_SYNCHRONOUS_UPDATE ); + lora_fsm_update( LORA_FSM_EVENT_SYNCHRONOUS_UPDATE ); } /*------------------------------------------------------------------------------ diff --git a/init/rev2/config/Src/stm32h7xx_it.c b/init/rev2/config/Src/stm32h7xx_it.c index 7234faf8..b2fcce76 100644 --- a/init/rev2/config/Src/stm32h7xx_it.c +++ b/init/rev2/config/Src/stm32h7xx_it.c @@ -38,7 +38,7 @@ Standard Includes #include "imu.h" #include "baro.h" #include "timer.h" -#include "telemetry.h" +#include "lora.h" #include "error_sdr.h" #include @@ -326,7 +326,7 @@ void HAL_SPI_TxRxCpltCallback( SPI_HandleTypeDef *hspi ) { /* Driver contract: pull NSS high */ HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET ); /* Update telemetry FSM */ - telemetry_update( TELEMETRY_EVENT_REG_READ_CPLT ); + lora_fsm_update( LORA_FSM_EVENT_REG_READ_CPLT ); } } @@ -336,7 +336,7 @@ void HAL_SPI_TxCpltCallback( SPI_HandleTypeDef *hspi ) { /* Driver contract: pull NSS high */ HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET ); /* Update telemetry FSM */ - telemetry_update( TELEMETRY_EVENT_WRITE_CPLT ); + lora_fsm_update( LORA_FSM_EVENT_WRITE_CPLT ); } } diff --git a/test/app/rev2/flight/mock/test_flight_stubs.c b/test/app/rev2/flight/mock/test_flight_stubs.c index 7ade9869..2b1ca6ec 100644 --- a/test/app/rev2/flight/mock/test_flight_stubs.c +++ b/test/app/rev2/flight/mock/test_flight_stubs.c @@ -34,7 +34,7 @@ uint16_t flash_busy_counts = 0; uint16_t sensor_dump_calls = 0; bool store_frame_called = false; bool is_apogee_detected = false; -TELEMETRY_EVENT last_event = TELEMETRY_EVENT_CANCEL; +LORA_FSM_EVENT last_event = LORA_FSM_EVENT_CANCEL; /* internal use */ @@ -62,7 +62,7 @@ sensor_dump_calls = 0; store_frame_called = false; is_apogee_detected = false; preset_data.config_settings.flash_rate_limit = 0; -last_event = TELEMETRY_EVENT_CANCEL; +last_event = LORA_FSM_EVENT_CANCEL; } void set_return_ign_deploy_main @@ -446,7 +446,7 @@ FLIGHT_COMP_STATE_TYPE get_fc_state() return flight_computer_state; } -void telemetry_update(TELEMETRY_EVENT event) { +void telemetry_update(LORA_FSM_EVENT event) { last_event = event; } diff --git a/test/app/rev2/flight/test_flight.c b/test/app/rev2/flight/test_flight.c index e70ead97..6fff17fc 100644 --- a/test/app/rev2/flight/test_flight.c +++ b/test/app/rev2/flight/test_flight.c @@ -52,7 +52,7 @@ extern uint16_t preset_preserving_flash_erase_calls; extern uint16_t flash_busy_calls; extern uint16_t flash_busy_counts; extern bool store_frame_called; -extern TELEMETRY_EVENT last_event; +extern LORA_FSM_EVENT last_event; /* hijacked globals */ extern uint32_t pid_previous; @@ -704,7 +704,7 @@ flight_loop /*------------------------------------------------------------------------------ Verify results ------------------------------------------------------------------------------*/ -TEST_ASSERT_EQ_UINT("Test that the last telemetry state update was not caused by this function", last_event, TELEMETRY_EVENT_CANCEL); +TEST_ASSERT_EQ_UINT("Test that the last telemetry state update was not caused by this function", last_event, LORA_FSM_EVENT_CANCEL); TEST_end_nested_case(); @@ -748,7 +748,7 @@ flight_loop /*------------------------------------------------------------------------------ Verify results ------------------------------------------------------------------------------*/ -TEST_ASSERT_EQ_UINT("Test that the last telemetry state update was a synchronous update.", last_event, TELEMETRY_EVENT_SYNCHRONOUS_UPDATE); +TEST_ASSERT_EQ_UINT("Test that the last telemetry state update was a synchronous update.", last_event, LORA_FSM_EVENT_SYNCHRONOUS_UPDATE); TEST_end_nested_case(); From 277aa0fff243349f8bc7d4d7537deb31d1eaf291 Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:06:05 -0700 Subject: [PATCH 02/38] Update tests --- test/app/rev2/flight/mock/test_flight_stubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/app/rev2/flight/mock/test_flight_stubs.c b/test/app/rev2/flight/mock/test_flight_stubs.c index 2b1ca6ec..34b8b807 100644 --- a/test/app/rev2/flight/mock/test_flight_stubs.c +++ b/test/app/rev2/flight/mock/test_flight_stubs.c @@ -446,7 +446,7 @@ FLIGHT_COMP_STATE_TYPE get_fc_state() return flight_computer_state; } -void telemetry_update(LORA_FSM_EVENT event) { +void lora_fsm_update(LORA_FSM_EVENT event) { last_event = event; } From e8e2644440a47a5ac8b74a5f81e238a94ae2ff29 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 21 Jun 2026 21:00:39 -0700 Subject: [PATCH 03/38] Pull up submoduiles (for CI) --- driver | 2 +- mod | 2 +- test/SDECv2 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver b/driver index 42a63d0f..04f73299 160000 --- a/driver +++ b/driver @@ -1 +1 @@ -Subproject commit 42a63d0fda862aa673b210b20bf40402efcf655b +Subproject commit 04f73299405bdf72057bc4c20f22f52997ca2659 diff --git a/mod b/mod index 690f370d..4b4b8803 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 690f370d123ae97ce51bcff911b79703235791b8 +Subproject commit 4b4b8803545c48ccd0e37f6c57ab55eae55cb0dc diff --git a/test/SDECv2 b/test/SDECv2 index 8388be49..a6e26514 160000 --- a/test/SDECv2 +++ b/test/SDECv2 @@ -1 +1 @@ -Subproject commit 8388be4913e38c39a22721f990ad76418dd9e992 +Subproject commit a6e26514b254b110c7c31fe5f26664a1804e291a From ddb13e6dcad307d9721e11b354b1ca25920baf14 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Wed, 10 Jun 2026 13:30:08 -0700 Subject: [PATCH 04/38] Remap Z axis to vertical --- app/rev2/main.h | 4 ++-- app/rev2/sensor_calibrate.c | 22 +++++++++++----------- app/rev2/state_transition.c | 31 +++++-------------------------- 3 files changed, 18 insertions(+), 39 deletions(-) diff --git a/app/rev2/main.h b/app/rev2/main.h index 6fe33068..ae16acea 100644 --- a/app/rev2/main.h +++ b/app/rev2/main.h @@ -80,8 +80,8 @@ extern "C" { #define VERSION_PRERELEASE_NUMBER (uint8_t)0 /* Tunable (but not configurable) constants */ -#define COAST_DETECT_SAMPLES 3 /* does not need to be tuned per vehicle, our system should work for all */ -#define COAST_DETECT_THRESHOLD 1.25 +#define COAST_DETECT_SAMPLES 5 /* does not need to be tuned per vehicle, our system should work for all */ +#define COAST_DETECT_THRESHOLD 0.75 /*------------------------------------------------------------------------------ Typedefs diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index 1e197934..1942f90f 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -42,17 +42,6 @@ extern IMU_OFFSET imu_offset; extern BARO_PRESET baro_preset; extern float velo_x_prev, velo_y_prev, velo_z_prev; -float acc_x_nonzero[1000]; -float acc_y_nonzero[1000]; -float acc_z_nonzero[1000]; - -float gyro_x_nonzero[1000]; -float gyro_y_nonzero[1000]; -float gyro_z_nonzero[1000]; - -float baro_pres_nonzero[1000]; -float baro_temp_nonzero[1000]; - /******************************************************************************* * * * PROCEDURE: * @@ -119,6 +108,17 @@ void sensorCalibrationSWCON(){ calc_gyro_y = calc_gyro_y / ( samples ); calc_gyro_z = calc_gyro_z / ( samples ); + debug_assert( calc_acc_z != 0.0f, ERROR_SENSOR_CMD_ERROR ); + /* If z is positive, gravity is down */ + if ( calc_acc_z > 0.0f ) + { + set_mount_orientation( MOUNT_ORIENTATION_Z_UP ); + } + else /* FC mounted upside down, so remap */ + { + set_mount_orientation( MOUNT_ORIENTATION_Z_DOWN ); + } + calc_baro_pres = calc_baro_pres / ( samples ); calc_baro_temp = calc_baro_temp / ( samples ); diff --git a/app/rev2/state_transition.c b/app/rev2/state_transition.c index f356a230..a08deacb 100644 --- a/app/rev2/state_transition.c +++ b/app/rev2/state_transition.c @@ -39,6 +39,8 @@ /* Error Handling */ #include "error_sdr.h" +#include "math_sdr.h" + /*------------------------------------------------------------------------------ Global Variables ------------------------------------------------------------------------------*/ @@ -71,9 +73,9 @@ bool launch_detection { static uint8_t acc_detect_cnts = 0; static uint8_t baro_detect_cnts = 0; -float accX = sensor_data.imu_data.imu_converted.accel_x; +float accZ = sensor_data.imu_data.imu_converted.accel_z; float pressure = sensor_data.baro_pressure; -float acc_scalar = sqrtf(accX*accX); +float acc_scalar = fabsf(accZ); if ( preset_data.config_settings.enabled_features & LAUNCH_DETECT_ACCEL_ENABLED ) { @@ -183,32 +185,9 @@ bool coast_detect { /* local variables */ static uint8_t positive_readings = 0; -bool gravity_is_negative_x; - -/* determine thrust vs gravity axis */ -if( preset_data.imu_offset.accel_x < 0 ) - { - gravity_is_negative_x = true; - } -else if( preset_data.imu_offset.accel_x > 0 ) - { - gravity_is_negative_x = false; - } -else - { - // TODO: log warning -- we will not compute coast state for - // this flight without knowing what our axis of gravity is. - return false; - } /* check if accel is sufficiently low */ -if( gravity_is_negative_x - && ( sensor_data.imu_data.imu_converted.accel_x < (-1) * COAST_DETECT_THRESHOLD * 9.8f ) ) - { - positive_readings++; - } -else if( !gravity_is_negative_x - && ( sensor_data.imu_data.imu_converted.accel_x > COAST_DETECT_THRESHOLD * 9.8f ) ) +if ( sensor_data.imu_data.imu_converted.accel_z < COAST_DETECT_THRESHOLD * GRAVITY ) { positive_readings++; } From 5b0bac01bf37548f1b78eccf6b8f6e036834f49e Mon Sep 17 00:00:00 2001 From: NArmistead Date: Fri, 19 Jun 2026 13:26:37 -0700 Subject: [PATCH 05/38] Move new sensor init to sensor_calibrate --- app/rev2/sensor_calibrate.c | 12 ++++-------- test/app/rev2/sensor_calibrate/mock/MOCK_hal.c | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index 1942f90f..e4503a8b 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -122,7 +122,7 @@ void sensorCalibrationSWCON(){ calc_baro_pres = calc_baro_pres / ( samples ); calc_baro_temp = calc_baro_temp / ( samples ); - preset_data.imu_offset.accel_x = calc_acc_x; + preset_data.imu_offset.accel_x = calc_acc_x; /* na todo: check if this needs to be flipped */ preset_data.imu_offset.accel_y = calc_acc_y; preset_data.imu_offset.accel_z = calc_acc_z; @@ -133,13 +133,8 @@ void sensorCalibrationSWCON(){ preset_data.baro_preset.baro_pres = calc_baro_pres; preset_data.baro_preset.baro_temp = calc_baro_temp; - // Reset velocity for accurate data - velo_x_prev = 0.00; - velo_y_prev = 0.00; - velo_z_prev = 0.00; - - // set sensor tick to current time - sensor_initialize_tick(); + /* Initialize sensor */ + sensor_init( &preset_data ); #ifdef DEBUG char sensor_dbg_msg[128]; @@ -153,6 +148,7 @@ void sensorCalibrationSWCON(){ calc_acc_x, calc_acc_y, calc_acc_z, calc_gyro_x, calc_gyro_y, calc_gyro_z, calc_baro_pres, calc_baro_temp); debug_log(sensor_dbg_msg, msg_len, LOG_LVL_INFO); #endif + } diff --git a/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c b/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c index 49ec1c8c..3222d378 100644 --- a/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c +++ b/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c @@ -68,7 +68,7 @@ sensor_dump_calls++; return SENSOR_OK; } -void sensor_initialize_tick(void) {} +void sensor_init(void) {} DEBUG_STATUS debug_log ( From 5511e7df987b8c8f76865f54880359468174a44d Mon Sep 17 00:00:00 2001 From: NArmistead Date: Sun, 21 Jun 2026 21:57:43 -0700 Subject: [PATCH 06/38] Remove IMU_DATA --- app/rev2/flash_appa.c | 4 ++-- app/rev2/flight.c | 4 ++-- app/rev2/sensor_calibrate.c | 12 ++++++------ app/rev2/state_transition.c | 4 ++-- test/app/rev2/flight/test_flight.c | 8 ++++---- test/app/rev2/launch_detect/test_launch_detect.c | 12 ++++++------ .../rev2/sensor_calibrate/test_sensor_calibrate.c | 14 +++++++------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/rev2/flash_appa.c b/app/rev2/flash_appa.c index 6b829d9a..231740d0 100644 --- a/app/rev2/flash_appa.c +++ b/app/rev2/flash_appa.c @@ -309,7 +309,7 @@ idx = 6; if ( preset_data.config_settings.enabled_data & STORE_CONV ) { memcpy( &buffer[idx], - &sensor_data.imu_data.imu_converted, + &sensor_data.imu_converted, sizeof( IMU_CONVERTED )); idx += sizeof( IMU_CONVERTED ); memcpy( &buffer[idx], &sensor_data.baro_pressure, sizeof(float)); @@ -321,7 +321,7 @@ if ( preset_data.config_settings.enabled_data & STORE_CONV ) if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM ) { memcpy( &buffer[idx], - &sensor_data.imu_data.state_estimate, + &sensor_data.state_estimate, sizeof( STATE_ESTIMATION )); idx += sizeof( STATE_ESTIMATION ); memcpy( &buffer[idx], &sensor_data.baro_alt, sizeof(float)); diff --git a/app/rev2/flight.c b/app/rev2/flight.c index ac2f905e..db60f716 100644 --- a/app/rev2/flight.c +++ b/app/rev2/flight.c @@ -359,8 +359,8 @@ uint8_t max_range_4 = preset_data.servo_preset.rp_servo4 + preset_data.config_se uint8_t min_range_4 = preset_data.servo_preset.rp_servo4 - preset_data.config_settings.control_max_deflection_angle; /* Read velocity and body state from sensor */ -float velocity = sensor_data.imu_data.state_estimate.velocity; -float roll_rate = sensor_data.imu_data.imu_converted.gyro_x; +float velocity = sensor_data.state_estimate.velocity; +float roll_rate = sensor_data.imu_converted.gyro_x; /* Get timing */ pid_delta = HAL_GetTick() - pid_previous; diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index e4503a8b..fcc5be79 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -90,12 +90,12 @@ void sensorCalibrationSWCON(){ for (int i = 0; i < samples; i++){ sensor_status = sensor_dump( &sensor_data ); debug_assert( sensor_status == SENSOR_OK, ERROR_SENSOR_CMD_ERROR ); - calc_acc_x = calc_acc_x + sensor_data.imu_data.imu_converted.accel_x; - calc_acc_y = calc_acc_y + sensor_data.imu_data.imu_converted.accel_y; - calc_acc_z = calc_acc_z + sensor_data.imu_data.imu_converted.accel_z; - calc_gyro_x = calc_gyro_x + sensor_data.imu_data.imu_converted.gyro_x; - calc_gyro_y = calc_gyro_y + sensor_data.imu_data.imu_converted.gyro_y; - calc_gyro_z = calc_gyro_z + sensor_data.imu_data.imu_converted.gyro_z; + calc_acc_x = calc_acc_x + sensor_data.imu_converted.accel_x; + calc_acc_y = calc_acc_y + sensor_data.imu_converted.accel_y; + calc_acc_z = calc_acc_z + sensor_data.imu_converted.accel_z; + calc_gyro_x = calc_gyro_x + sensor_data.imu_converted.gyro_x; + calc_gyro_y = calc_gyro_y + sensor_data.imu_converted.gyro_y; + calc_gyro_z = calc_gyro_z + sensor_data.imu_converted.gyro_z; calc_baro_pres = calc_baro_pres + sensor_data.baro_pressure; calc_baro_temp = calc_baro_temp + sensor_data.baro_temp; } diff --git a/app/rev2/state_transition.c b/app/rev2/state_transition.c index a08deacb..529fa370 100644 --- a/app/rev2/state_transition.c +++ b/app/rev2/state_transition.c @@ -73,7 +73,7 @@ bool launch_detection { static uint8_t acc_detect_cnts = 0; static uint8_t baro_detect_cnts = 0; -float accZ = sensor_data.imu_data.imu_converted.accel_z; +float accZ = sensor_data.imu_converted.accel_z; float pressure = sensor_data.baro_pressure; float acc_scalar = fabsf(accZ); @@ -187,7 +187,7 @@ bool coast_detect static uint8_t positive_readings = 0; /* check if accel is sufficiently low */ -if ( sensor_data.imu_data.imu_converted.accel_z < COAST_DETECT_THRESHOLD * GRAVITY ) +if ( sensor_data.imu_converted.accel_z < COAST_DETECT_THRESHOLD * GRAVITY ) { positive_readings++; } diff --git a/test/app/rev2/flight/test_flight.c b/test/app/rev2/flight/test_flight.c index 6fff17fc..a4d57c35 100644 --- a/test/app/rev2/flight/test_flight.c +++ b/test/app/rev2/flight/test_flight.c @@ -371,8 +371,8 @@ for( uint8_t test_num = 0; test_num < sizeof(cases) / sizeof(struct test_case); /* active roll setup. values are not important, we just need to check control flow. */ pid_previous = 0; launch_detect_time = 0; - sensor_data.imu_data.state_estimate.velocity = 0.0f; /* not important yet */ - sensor_data.imu_data.imu_converted.gyro_x = 100.0f; /* crazy val to check NE assert */ + sensor_data.state_estimate.velocity = 0.0f; /* not important yet */ + sensor_data.imu_converted.gyro_x = 100.0f; /* crazy val to check NE assert */ preset_data.config_settings.control_delay_after_launch = 0; preset_data.config_settings.control_max_deflection_angle = 25; preset_data.config_settings.roll_control_constant_p = 2.0f; @@ -809,8 +809,8 @@ for( uint8_t test_num = 0; test_num < sizeof(cases) / sizeof(struct test_case); stubs_reset(); pid_previous = 0; launch_detect_time = 0; - sensor_data.imu_data.state_estimate.velocity = 0.0f; /* not important yet */ - sensor_data.imu_data.imu_converted.gyro_x = cases[test_num].roll_rate; + sensor_data.state_estimate.velocity = 0.0f; /* not important yet */ + sensor_data.imu_converted.gyro_x = cases[test_num].roll_rate; set_return_HAL_GetTick( cases[test_num].time_since_launch ); preset_data.config_settings.control_delay_after_launch = cases[test_num].delay_after_launch_configuration; preset_data.config_settings.control_max_deflection_angle = cases[test_num].max_deflection_angle; diff --git a/test/app/rev2/launch_detect/test_launch_detect.c b/test/app/rev2/launch_detect/test_launch_detect.c index 46798fc7..c62f380e 100644 --- a/test/app/rev2/launch_detect/test_launch_detect.c +++ b/test/app/rev2/launch_detect/test_launch_detect.c @@ -114,9 +114,9 @@ for ( int test_num = 0; test_num < NUM_CASES_LAUNCH_DETECT; test_num++ ) for ( int i = 0; i < NUM_EXPECTED_SAMPLES; i++ ) { - sensor_data.imu_data.imu_converted.accel_x = inputsAcc[test_num][i]; - sensor_data.imu_data.imu_converted.accel_y = inputsAcc[test_num][i]; - sensor_data.imu_data.imu_converted.accel_z = inputsAcc[test_num][i]; + sensor_data.imu_converted.accel_x = inputsAcc[test_num][i]; + sensor_data.imu_converted.accel_y = inputsAcc[test_num][i]; + sensor_data.imu_converted.accel_z = inputsAcc[test_num][i]; sensor_data.baro_pressure = inputsBaro[test_num][i]; fut_return = launch_detection(&sample_ld_time); @@ -130,9 +130,9 @@ for ( int test_num = 0; test_num < NUM_CASES_LAUNCH_DETECT; test_num++ ) } } /* reset test */ - sensor_data.imu_data.imu_converted.accel_x = 0; - sensor_data.imu_data.imu_converted.accel_y = 0; - sensor_data.imu_data.imu_converted.accel_z = 0; + sensor_data.imu_converted.accel_x = 0; + sensor_data.imu_converted.accel_y = 0; + sensor_data.imu_converted.accel_z = 0; sensor_data.baro_pressure = 0; launch_detection(&sample_ld_time); sample_ld_time = 0; diff --git a/test/app/rev2/sensor_calibrate/test_sensor_calibrate.c b/test/app/rev2/sensor_calibrate/test_sensor_calibrate.c index dc6c5d8d..f3122ff0 100644 --- a/test/app/rev2/sensor_calibrate/test_sensor_calibrate.c +++ b/test/app/rev2/sensor_calibrate/test_sensor_calibrate.c @@ -70,13 +70,13 @@ memset( sensor_dump_mock, 0, sizeof( SENSOR_DATA ) * 100 ); preset_data.config_settings.sensor_calibration_samples = 100; for( int i = 0; i < 50; i++ ) { - sensor_dump_mock[i].imu_data.imu_converted.accel_x = 100; - sensor_dump_mock[i].imu_data.imu_converted.accel_y = 100; - sensor_dump_mock[i].imu_data.imu_converted.accel_z = 100; - sensor_dump_mock[i].imu_data.imu_converted.gyro_x = 100; - sensor_dump_mock[i].imu_data.imu_converted.gyro_y = 100; - sensor_dump_mock[i].imu_data.imu_converted.gyro_z = 100; - sensor_dump_mock[i].imu_data.imu_converted.gyro_y = 100; + sensor_dump_mock[i].imu_converted.accel_x = 100; + sensor_dump_mock[i].imu_converted.accel_y = 100; + sensor_dump_mock[i].imu_converted.accel_z = 100; + sensor_dump_mock[i].imu_converted.gyro_x = 100; + sensor_dump_mock[i].imu_converted.gyro_y = 100; + sensor_dump_mock[i].imu_converted.gyro_z = 100; + sensor_dump_mock[i].imu_converted.gyro_y = 100; sensor_dump_mock[i].baro_pressure = 100; sensor_dump_mock[i].baro_temp = 100; } From f2accaefe362eff00f97b7237b3fdab621122c00 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Sun, 21 Jun 2026 22:26:14 -0700 Subject: [PATCH 07/38] Minor incomplete test mock changes --- test/app/rev2/flight/mock/test_flight_stubs.c | 7 ------- test/app/rev2/sensor_calibrate/mock/MOCK_hal.c | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/test/app/rev2/flight/mock/test_flight_stubs.c b/test/app/rev2/flight/mock/test_flight_stubs.c index c5ece3e5..ebb475cc 100644 --- a/test/app/rev2/flight/mock/test_flight_stubs.c +++ b/test/app/rev2/flight/mock/test_flight_stubs.c @@ -388,13 +388,6 @@ FLASH_STATUS get_sensor_frame return FLASH_OK; } -void sensor_frame_size_init - ( - void - ) -{ - -} /* launch_detect.c */ bool launch_detection diff --git a/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c b/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c index 3222d378..b464a789 100644 --- a/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c +++ b/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c @@ -68,7 +68,7 @@ sensor_dump_calls++; return SENSOR_OK; } -void sensor_init(void) {} +void sensor_init( PRESET_DATA* preset_data ) {} DEBUG_STATUS debug_log ( From dac52e53c5ee72e48beb9be2b856a5801a2cc866 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Sun, 21 Jun 2026 22:53:44 -0700 Subject: [PATCH 08/38] Remove baro velo --- app/rev2/flash_appa.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/rev2/flash_appa.c b/app/rev2/flash_appa.c index 231740d0..5b33d39c 100644 --- a/app/rev2/flash_appa.c +++ b/app/rev2/flash_appa.c @@ -326,8 +326,6 @@ if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM ) idx += sizeof( STATE_ESTIMATION ); memcpy( &buffer[idx], &sensor_data.baro_alt, sizeof(float)); idx += 4; - memcpy( &buffer[idx], &sensor_data.baro_velo, sizeof(float)); - idx += 4; } if ( preset_data.config_settings.enabled_data & STORE_GPS ) @@ -400,7 +398,7 @@ if ( preset_data.config_settings.enabled_data & STORE_CONV ) if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM ) { size += sizeof( STATE_ESTIMATION ); - size += 2 * sizeof( float ); /* baro alt/velo */ + size += sizeof( float ); /* baro alt */ } if ( preset_data.config_settings.enabled_data & STORE_GPS ) From 21efa37a72d62e1eea92bca389e8a4b1a9e8b02a Mon Sep 17 00:00:00 2001 From: NArmistead Date: Sun, 21 Jun 2026 22:54:11 -0700 Subject: [PATCH 09/38] Pull up submodules --- driver | 2 +- mod | 2 +- test/SDECv2 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver b/driver index 04f73299..e40d3ccd 160000 --- a/driver +++ b/driver @@ -1 +1 @@ -Subproject commit 04f73299405bdf72057bc4c20f22f52997ca2659 +Subproject commit e40d3ccd1a0c07882189e5d8e5934716cc956307 diff --git a/mod b/mod index 4b4b8803..203e341f 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 4b4b8803545c48ccd0e37f6c57ab55eae55cb0dc +Subproject commit 203e341fb5721b33b8d8503afbe386d79dfa8428 diff --git a/test/SDECv2 b/test/SDECv2 index a6e26514..8388be49 160000 --- a/test/SDECv2 +++ b/test/SDECv2 @@ -1 +1 @@ -Subproject commit a6e26514b254b110c7c31fe5f26664a1804e291a +Subproject commit 8388be4913e38c39a22721f990ad76418dd9e992 From 99fe196e553ff0c3888344db6da1b6f2d9a1106a Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:14:46 -0700 Subject: [PATCH 10/38] Update integration tests --- test/SDECv2 | 2 +- test/app/rev2/terminal_int/terminal_int_test.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/SDECv2 b/test/SDECv2 index 8388be49..262c2a03 160000 --- a/test/SDECv2 +++ b/test/SDECv2 @@ -1 +1 @@ -Subproject commit 8388be4913e38c39a22721f990ad76418dd9e992 +Subproject commit 262c2a030843cb31fdf5aba1bfbf014d03a46106 diff --git a/test/app/rev2/terminal_int/terminal_int_test.py b/test/app/rev2/terminal_int/terminal_int_test.py index 4236f154..08898fef 100644 --- a/test/app/rev2/terminal_int/terminal_int_test.py +++ b/test/app/rev2/terminal_int/terminal_int_test.py @@ -24,10 +24,10 @@ def check_sensor(tester, sensor_name, readout): max = float('inf') match sensor_name: # RAW VALUES - case "accXconv" | "accYconv" | "accZconv": + case "accXconv" | "accYconv" | "accZconv" | "acc_z": min = -12 max = 12 - case "gyroXconv" | "gyroYconv" | "gyroZconv": + case "gyroXconv" | "gyroYconv" | "gyroZconv" | "roll_rate": min = -25 max = 25 case "magXconv" | "magYconv": @@ -36,6 +36,9 @@ def check_sensor(tester, sensor_name, readout): case "magZconv": min = -125 max = 125 + case "quat_w" | "quat_x" | "quat_y" | "quat_z": + min = -1 + max = 1 case "pres": min = 90000 max = 101300 From 41e34d8542d2724625164c8aed6dabf33a2e0179 Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:52:56 -0700 Subject: [PATCH 11/38] Pull up mod --- mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod b/mod index 203e341f..f03bfd12 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 203e341fb5721b33b8d8503afbe386d79dfa8428 +Subproject commit f03bfd125ce0b314084ceba00a3c82400fb541eb From 29c9f5fb8cbcc12b50c05b262818133470f6c342 Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Mon, 22 Jun 2026 14:12:04 -0700 Subject: [PATCH 12/38] Fix tests --- test/app/rev2/error_int/test_error_int.c | 8 ++++---- test/app/rev2/flight/mock/test_flight_stubs.c | 11 +++++++++++ test/app/rev2/flight/test_flight.c | 6 +++--- test/app/rev2/sensor_calibrate/mock/MOCK_hal.c | 6 ++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/test/app/rev2/error_int/test_error_int.c b/test/app/rev2/error_int/test_error_int.c index 46432fd1..a56286f0 100644 --- a/test/app/rev2/error_int/test_error_int.c +++ b/test/app/rev2/error_int/test_error_int.c @@ -216,7 +216,7 @@ void test_log_messages /*------------------------------------------------------------------------------ Set up test ------------------------------------------------------------------------------*/ -char test_msg[TEXT_MESSAGE_LENGTH] = "This message tests the log message system."; +char test_msg[TEXT_MESSAGE_LENGTH] = "This msg tsts the log msg system."; TEXT_MESSAGE return_buffer; memset( &return_buffer, 0, sizeof( TEXT_MESSAGE ) ); TEST_ASSERT_FALSE( "Precondition: Verify that there's no pending messages.", error_is_pending_info() ); @@ -224,7 +224,7 @@ TEST_ASSERT_FALSE( "Precondition: Verify that there's no pending messages.", err /*------------------------------------------------------------------------------ Adding to buffer: Call FUT ------------------------------------------------------------------------------*/ -error_log_info( test_msg ); +error_log_info( "This msg tsts the log msg system." ); /*------------------------------------------------------------------------------ Adding to buffer: Verify Result @@ -264,7 +264,7 @@ void test_warning_messages /*------------------------------------------------------------------------------ Set up test ------------------------------------------------------------------------------*/ -char test_msg[TEXT_MESSAGE_LENGTH] = "This message tests the warning message system."; +char test_msg[TEXT_MESSAGE_LENGTH] = "This msg tsts the log msg system."; TEXT_MESSAGE return_buffer; memset( &return_buffer, 0, sizeof( TEXT_MESSAGE ) ); TEST_ASSERT_FALSE( "Precondition: Verify that there's no pending messages.", error_is_pending_info() ); @@ -272,7 +272,7 @@ TEST_ASSERT_FALSE( "Precondition: Verify that there's no pending messages.", err /*------------------------------------------------------------------------------ Adding to buffer: Call FUT ------------------------------------------------------------------------------*/ -error_log_warning( test_msg ); +error_log_warning( "This msg tsts the log msg system." ); /*------------------------------------------------------------------------------ Adding to buffer: Verify Result diff --git a/test/app/rev2/flight/mock/test_flight_stubs.c b/test/app/rev2/flight/mock/test_flight_stubs.c index ebb475cc..884058a9 100644 --- a/test/app/rev2/flight/mock/test_flight_stubs.c +++ b/test/app/rev2/flight/mock/test_flight_stubs.c @@ -36,6 +36,7 @@ uint16_t sensor_dump_calls = 0; bool store_frame_called = false; bool is_apogee_detected = false; LORA_FSM_EVENT last_event = LORA_FSM_EVENT_CANCEL; +LORA_ASYNC_OP_MODE last_op_mode = LORA_ASYNC_OFF; /* internal use */ @@ -455,4 +456,14 @@ DEBUG_STATUS debug_log { /* Do nothing. Ideally, our tests should run in release mode though. */ return DEBUG_OK; +} + +LORA_STATUS lora_fsm_set_mode + ( + LORA_ASYNC_OP_MODE new_mode + ) +{ +last_op_mode = new_mode; +return LORA_OK; + } \ No newline at end of file diff --git a/test/app/rev2/flight/test_flight.c b/test/app/rev2/flight/test_flight.c index a4d57c35..a772d263 100644 --- a/test/app/rev2/flight/test_flight.c +++ b/test/app/rev2/flight/test_flight.c @@ -53,6 +53,7 @@ extern uint16_t flash_busy_calls; extern uint16_t flash_busy_counts; extern bool store_frame_called; extern LORA_FSM_EVENT last_event; +extern LORA_ASYNC_OP_MODE last_op_mode; /* hijacked globals */ extern uint32_t pid_previous; @@ -141,12 +142,11 @@ flight_calib /*------------------------------------------------------------------------------ Verify results ------------------------------------------------------------------------------*/ -/* The only critical parts of this are GPS enablement based on feature flags. All - others can be proven by analysis. */ TEST_ASSERT_EQ_UINT("Test that GPS was enabled.", was_gps_enabled, true); +TEST_ASSERT_EQ_UINT("Test that TX mode was enabled.", last_op_mode, LORA_ASYNC_TX); /*------------------------------------------------------------------------------ -Case 1: GPS Disabled +Case 2: GPS Disabled ------------------------------------------------------------------------------*/ stubs_reset(); preset_data.config_settings.enabled_features = 0u; diff --git a/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c b/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c index b464a789..8aa93548 100644 --- a/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c +++ b/test/app/rev2/sensor_calibrate/mock/MOCK_hal.c @@ -83,3 +83,9 @@ return DEBUG_OK; } void error_fail_fast(ERROR_CODE error_code) {} + +void set_mount_orientation + ( + MOUNT_ORIENTATION orientation + ) +{} From b0dd24f9cac360d126b4884366639ad48dac406e Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Mon, 22 Jun 2026 14:27:45 -0700 Subject: [PATCH 13/38] Initialize LoRa before entering flight state --- app/rev2/flight.c | 23 ++++++++++++++++++- test/app/rev2/flight/mock/test_flight_stubs.c | 12 ++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/rev2/flight.c b/app/rev2/flight.c index db60f716..2fc97ee6 100644 --- a/app/rev2/flight.c +++ b/app/rev2/flight.c @@ -138,6 +138,8 @@ void flight_calib uint32_t* flash_address ) { +LORA_STATUS lora_status = LORA_OK; + led_set_color( LED_YELLOW ); buzzer_multi_beeps(50, 50, 4); @@ -150,7 +152,26 @@ if ( preset_data.config_settings.enabled_features & GPS_ENABLED ) sensorCalibrationSWCON(); write_preset( flash_handle, flash_address ); flash_erase_preserve_preset( flash_handle, flash_address ); -lora_fsm_set_mode( LORA_ASYNC_TX ); + +if ( preset_data.config_settings.enabled_features & WIRELESS_TRANSMISSION_ENABLED ) + { + if( !lora_is_lora_initialized() ) + { + lora_status = lora_configure( &preset_data.lora_preset ); + } + + /* If the modem fails to configure, disable TX in RAM (but do not write back to flash) */ + if( lora_status != LORA_OK ) + { + preset_data.config_settings.enabled_features &= ~WIRELESS_TRANSMISSION_ENABLED; + + /* Give an indication */ + led_set_color(LED_RED); + buzzer_multi_beeps(400, 200, 3); + led_set_color(LED_YELLOW); + } + lora_fsm_set_mode( LORA_ASYNC_TX ); + } fc_state_update( FC_STATE_LAUNCH_DETECT ); diff --git a/test/app/rev2/flight/mock/test_flight_stubs.c b/test/app/rev2/flight/mock/test_flight_stubs.c index 884058a9..3ceaf29e 100644 --- a/test/app/rev2/flight/mock/test_flight_stubs.c +++ b/test/app/rev2/flight/mock/test_flight_stubs.c @@ -466,4 +466,16 @@ LORA_STATUS lora_fsm_set_mode last_op_mode = new_mode; return LORA_OK; +} + +LORA_STATUS lora_configure(LORA_PRESET* preset_ptr) +{ +return LORA_OK; + +} + +bool lora_is_lora_initialized(void) +{ +return false; + } \ No newline at end of file From 80592317e7a09703b6accbaaf49f463c4bea5605 Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Mon, 22 Jun 2026 14:28:30 -0700 Subject: [PATCH 14/38] Pull up driver --- driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver b/driver index e40d3ccd..43593b09 160000 --- a/driver +++ b/driver @@ -1 +1 @@ -Subproject commit e40d3ccd1a0c07882189e5d8e5934716cc956307 +Subproject commit 43593b0913ad78048186b7008ee12b776ee734f4 From 79686aa10625cd01a57f37a75f279786e8b9c13c Mon Sep 17 00:00:00 2001 From: NArmistead Date: Tue, 23 Jun 2026 21:38:05 -0700 Subject: [PATCH 15/38] Rename mount orientation enum --- app/rev2/sensor_calibrate.c | 4 ++-- mod | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index fcc5be79..827b5845 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -112,11 +112,11 @@ void sensorCalibrationSWCON(){ /* If z is positive, gravity is down */ if ( calc_acc_z > 0.0f ) { - set_mount_orientation( MOUNT_ORIENTATION_Z_UP ); + set_mount_orientation( MOUNT_ORIENTATION_IMU_NORMAL ); } else /* FC mounted upside down, so remap */ { - set_mount_orientation( MOUNT_ORIENTATION_Z_DOWN ); + set_mount_orientation( MOUNT_ORIENTATION_IMU_INVERTED ); } calc_baro_pres = calc_baro_pres / ( samples ); diff --git a/mod b/mod index f03bfd12..91a01986 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit f03bfd125ce0b314084ceba00a3c82400fb541eb +Subproject commit 91a019869ee5641ac6b6307281d7454613cc7a27 From 8483f40db1ba8247a31a51330443a3ffc387e93b Mon Sep 17 00:00:00 2001 From: NArmistead Date: Sun, 28 Jun 2026 23:41:05 -0700 Subject: [PATCH 16/38] Correct sensor calib with axis remap --- app/rev2/sensor_calibrate.c | 30 +++++++++++++++++++----------- mod | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index 827b5845..0f4fdbf8 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -58,7 +58,6 @@ void sensorCalibrationSWCON(){ #endif uint16_t samples = preset_data.config_settings.sensor_calibration_samples; SENSOR_STATUS sensor_status = SENSOR_OK; - (void)sensor_status; preset_data.imu_offset.accel_x = 0.00; preset_data.imu_offset.accel_y = 0.00; @@ -109,20 +108,11 @@ void sensorCalibrationSWCON(){ calc_gyro_z = calc_gyro_z / ( samples ); debug_assert( calc_acc_z != 0.0f, ERROR_SENSOR_CMD_ERROR ); - /* If z is positive, gravity is down */ - if ( calc_acc_z > 0.0f ) - { - set_mount_orientation( MOUNT_ORIENTATION_IMU_NORMAL ); - } - else /* FC mounted upside down, so remap */ - { - set_mount_orientation( MOUNT_ORIENTATION_IMU_INVERTED ); - } calc_baro_pres = calc_baro_pres / ( samples ); calc_baro_temp = calc_baro_temp / ( samples ); - preset_data.imu_offset.accel_x = calc_acc_x; /* na todo: check if this needs to be flipped */ + preset_data.imu_offset.accel_x = calc_acc_x; preset_data.imu_offset.accel_y = calc_acc_y; preset_data.imu_offset.accel_z = calc_acc_z; @@ -132,6 +122,24 @@ void sensorCalibrationSWCON(){ preset_data.baro_preset.baro_pres = calc_baro_pres; preset_data.baro_preset.baro_temp = calc_baro_temp; + + /* Sensor dump readings already factor in the orientation, which is assumed at startup to be inverted. + If gravity is a negative value at calib, flip the orientaion and offsets back accordingly. */ + if ( calc_acc_z > 0.0f ) + { + set_mount_orientation( MOUNT_ORIENTATION_IMU_INVERTED ); + } + else + { + set_mount_orientation( MOUNT_ORIENTATION_IMU_NORMAL ); + + /* Flip the X and Z offsets back to match */ + preset_data.imu_offset.accel_x *= -1; + preset_data.imu_offset.accel_z *= -1; + + preset_data.imu_offset.gyro_x *= -1; + preset_data.imu_offset.gyro_z *= -1; + } /* Initialize sensor */ sensor_init( &preset_data ); diff --git a/mod b/mod index 91a01986..1edd7ae5 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 91a019869ee5641ac6b6307281d7454613cc7a27 +Subproject commit 1edd7ae5e9e1d161f9a4e35b0712aabbff19cd91 From c06902058c4c8a00729710f1266a6db6c643ceac Mon Sep 17 00:00:00 2001 From: NArmistead Date: Sun, 28 Jun 2026 23:48:32 -0700 Subject: [PATCH 17/38] oops -Werror (fix CI) --- app/rev2/sensor_calibrate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index 0f4fdbf8..63d38075 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -58,6 +58,7 @@ void sensorCalibrationSWCON(){ #endif uint16_t samples = preset_data.config_settings.sensor_calibration_samples; SENSOR_STATUS sensor_status = SENSOR_OK; + (void)sensor_status; preset_data.imu_offset.accel_x = 0.00; preset_data.imu_offset.accel_y = 0.00; From 12a74d097b3e3691081db538f312b6692e15faa8 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Tue, 30 Jun 2026 17:46:14 -0700 Subject: [PATCH 18/38] Pull up mod --- mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod b/mod index 1edd7ae5..61e4ecde 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 1edd7ae5e9e1d161f9a4e35b0712aabbff19cd91 +Subproject commit 61e4ecdebebf9355bf63da927443bea186c554a9 From c52b410d8ada78610936bc6a277ddabe39bfa557 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 13:47:16 -0700 Subject: [PATCH 19/38] Resolve bug where the flight computer would crash on startup if LoRa was configured improperly --- app/rev2/flight.c | 3 +++ app/rev2/main.c | 23 ----------------------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/app/rev2/flight.c b/app/rev2/flight.c index 2fc97ee6..e291263c 100644 --- a/app/rev2/flight.c +++ b/app/rev2/flight.c @@ -35,6 +35,7 @@ Includes #include "math.h" #include "sensor.h" #include "buzzer.h" +#include "debug_sdr.h" #include "error_sdr.h" #include "ignition.h" #include "telemetry.h" @@ -158,6 +159,7 @@ if ( preset_data.config_settings.enabled_features & WIRELESS_TRANSMISSION_ENABLE if( !lora_is_lora_initialized() ) { lora_status = lora_configure( &preset_data.lora_preset ); + debug_assert( lora_status == LORA_OK, ERROR_LORA_INIT_ERROR ); } /* If the modem fails to configure, disable TX in RAM (but do not write back to flash) */ @@ -170,6 +172,7 @@ if ( preset_data.config_settings.enabled_features & WIRELESS_TRANSMISSION_ENABLE buzzer_multi_beeps(400, 200, 3); led_set_color(LED_YELLOW); } + lora_fsm_set_mode( LORA_ASYNC_TX ); } diff --git a/app/rev2/main.c b/app/rev2/main.c index c879c93a..04000f1d 100644 --- a/app/rev2/main.c +++ b/app/rev2/main.c @@ -297,29 +297,6 @@ if ( read_status == FLASH_FAIL ) { error_fail_fast( ERROR_FLASH_CMD_ERROR ); } - -/*------------------------------------------------------------------------------ - LoRA Initialization -------------------------------------------------------------------------------*/ -if ( preset_data.config_settings.enabled_features & WIRELESS_TRANSMISSION_ENABLED ) - { - LORA_STATUS lora_init_status = lora_configure( &(preset_data.lora_preset) ); - if( lora_init_status == LORA_USING_DEFAULTS ) - { - /* give an indicator of default configs*/ - for( int i = 0; i < 4; i++ ) - { - led_set_color( LED_YELLOW ); - buzzer_beep( 400 ); - led_set_color( LED_CYAN ); - delay_ms( 400 ); - } - } - else if( lora_init_status != LORA_OK ) - { - error_fail_fast( ERROR_LORA_INIT_ERROR ); - } - } /*------------------------------------------------------------------------------ End of init // Begin program From f6fa5f055162e47035ba1f3d4ec48f3252a98f56 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 16:15:08 -0700 Subject: [PATCH 20/38] Pull up emulator --- emulator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emulator b/emulator index b94dc304..0109193e 160000 --- a/emulator +++ b/emulator @@ -1 +1 @@ -Subproject commit b94dc304a5eab64c5f3f4b917ef860850b4fe652 +Subproject commit 0109193e0e4a2f5b847b50d299ac95fe36088e62 From 2458909425138f48bbd31848185df42dcdbdb818 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 16:19:16 -0700 Subject: [PATCH 21/38] fix: Unit tests --- test/app/rev2/main/test_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/app/rev2/main/test_main.c b/test/app/rev2/main/test_main.c index 5e4e2b55..98a62f35 100644 --- a/test/app/rev2/main/test_main.c +++ b/test/app/rev2/main/test_main.c @@ -108,15 +108,15 @@ struct test_case struct test_case cases[] = { { "Normal Case: Initialization Correct", false, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_OK, false, ERROR_NO_ERROR }, - { "Normal Case: Initialization w/ Valid LoRa", true, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_OK, false, ERROR_NO_ERROR }, - { "Normal Case: Initialization w/ Invalid Lora", true, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_USING_DEFAULTS, false, ERROR_NO_ERROR}, +// { "Normal Case: Initialization w/ Valid LoRa", true, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_OK, false, ERROR_NO_ERROR }, /* MOVED TO FLIGHT */ +// { "Normal Case: Initialization w/ Invalid Lora", true, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_USING_DEFAULTS, false, ERROR_NO_ERROR}, /* MOVED TO FLIGHT */ { "Robust Case: Flash Init Fail", false, FLASH_INIT_FAIL, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_OK, false, ERROR_FLASH_INIT_ERROR }, // { "Robust Case: Baro Init Fail", false, FLASH_OK, BARO_FAIL, IMU_OK, SERVO_OK, FLASH_OK, LORA_OK, false, ERROR_BARO_INIT_ERROR }, // { "Robust Case: IMU Init Fail", false, FLASH_OK, BARO_OK, IMU_FAIL, SERVO_OK, FLASH_OK, LORA_OK, false, ERROR_IMU_INIT_ERROR }, { "Robust Case: Servo Init Fail", false, FLASH_OK, BARO_OK, IMU_OK, SERVO_FAIL, FLASH_OK, LORA_OK, false, ERROR_SERVO_INIT_ERROR }, { "Robust Case: Read Preset Fail", false, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_FAIL, LORA_OK, false, ERROR_FLASH_CMD_ERROR }, { "Robust Case: Switch Terminal Toggled", false, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_OK, true, ERROR_DATA_HAZARD_ERROR }, - { "Robust Case: LoRa init fail", true, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_FAIL, false, ERROR_LORA_INIT_ERROR } +// { "Robust Case: LoRa init fail", true, FLASH_OK, BARO_OK, IMU_OK, SERVO_OK, FLASH_OK, LORA_FAIL, false, ERROR_LORA_INIT_ERROR } }; for( uint8_t test_num = 0; test_num < sizeof(cases) / sizeof(struct test_case); test_num++ ) From 8a9886c74d1f7216185569631a429586ca5ada7f Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 18:38:30 -0700 Subject: [PATCH 22/38] Add ground station emulator --- app/rev2/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/rev2/Makefile b/app/rev2/Makefile index cf4be3ba..0f5c8533 100644 --- a/app/rev2/Makefile +++ b/app/rev2/Makefile @@ -132,8 +132,10 @@ $(BASE_DIR)/emulator/src/emulator_timer.c \ $(BASE_DIR)/emulator/src/emulator_error.c \ $(BASE_DIR)/emulator/src/emulator_init.c \ $(BASE_DIR)/emulator/src/emulator_gpio.c \ +$(BASE_DIR)/emulator/src/emulator_ground_station.c \ $(BASE_DIR)/emulator/src/emulator_uart.c \ $(BASE_DIR)/emulator/src/emulator_spi.c \ +$(BASE_DIR)/emulator/src/emulator_lora.c \ $(BASE_DIR)/emulator/src/emulator_i2c.c \ $(BASE_DIR)/emulator/src/emulator_gui.c \ $(BASE_DIR)/emulator/src/shaders/shaders.c \ From f000f42e6ebe5c14fe746fccd1a811e8affb876d Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 18:38:49 -0700 Subject: [PATCH 23/38] Pull up emulator --- emulator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emulator b/emulator index 0109193e..9a3e3094 160000 --- a/emulator +++ b/emulator @@ -1 +1 @@ -Subproject commit 0109193e0e4a2f5b847b50d299ac95fe36088e62 +Subproject commit 9a3e30944bd62964335d2473eeb5616adcf0f29a From e13c9846b401b18bd766c50de06eae679c160767 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 19:14:13 -0700 Subject: [PATCH 24/38] Pull up submodules --- emulator | 2 +- mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emulator b/emulator index 9a3e3094..ead7aa98 160000 --- a/emulator +++ b/emulator @@ -1 +1 @@ -Subproject commit 9a3e30944bd62964335d2473eeb5616adcf0f29a +Subproject commit ead7aa98ef4af8c42cc69800ae68b23c27d87bbd diff --git a/mod b/mod index 61e4ecde..e4db23eb 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 61e4ecdebebf9355bf63da927443bea186c554a9 +Subproject commit e4db23eb872d2ebf67aec28b5e9bcd9eeadb86eb From 4fdb507f97e32d59e5ac60cba2c77eeea7c81285 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 19:16:24 -0700 Subject: [PATCH 25/38] Add LoRa/telem verification to flight_int test --- test/app/rev2/flight_int/flight_int_test.py | 67 +++++++++++++++++-- .../rev2/flight_int/support/test_presets.json | 2 +- .../sdr_emulator_utils/emulator_runner.py | 11 ++- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/test/app/rev2/flight_int/flight_int_test.py b/test/app/rev2/flight_int/flight_int_test.py index d2ab671d..fa5f2aba 100644 --- a/test/app/rev2/flight_int/flight_int_test.py +++ b/test/app/rev2/flight_int/flight_int_test.py @@ -5,10 +5,11 @@ import json import csv import shutil +import threading from SDECv2.BaseController import Firmware, BaseController from SDECv2.BaseController import create_controllers -from SDECv2.Parser import Parser, PresetConfig, DataBitmask, FeatureBitmask, create_configs +from SDECv2.Parser import Parser, PresetConfig, DataBitmask, FeatureBitmask, Telemetry, create_configs from SDECv2.SerialController import SerialSentry, SerialObj, Comport from sdr_emulator_utils import Emulator, Tester @@ -27,6 +28,32 @@ tmp_dir = Path("tmp") tmp_dir.mkdir(exist_ok=True) +# Set up threading/sync objects +stop_event = threading.Event() +telemetry_obj = Telemetry() + +POLL_INTERVAL = 1/60 + +# Inspired by the API dashboard thread +def dashboard_update_thread(serial_connection: SerialObj): + next_time = time.perf_counter() + while not stop_event.is_set(): + next_time += POLL_INTERVAL + + try: + serial_connection.reset_input_buffer() + telemetry_obj.dashboard_dump(serial_connection) + except ValueError as e: # Serial returned bad values + print("Warning: The telemetry thread received an error. Attempting to recover, but this may not work.") + serial_connection.reset_input_buffer() + tester.assert_eq(False, True, "The dashboard thread received an error: {e}.") + + sleep_time = next_time - time.perf_counter() + if sleep_time > 0: + time.sleep(sleep_time) + else: + next_time = time.perf_counter() + # connect try: ######################################################## @@ -52,6 +79,9 @@ print("[setup] Uploading presets") parser = Parser.upload_preset(serial_connection, path="support/test_presets.json") tester.assert_eq(type(parser), Parser, "The parser object was created successfully.") + + print("[setup] Uploading LoRa presets") + parser.upload_lora_preset(serial_connection, "support/test_presets.json") # give enough time to complete the serial transaction print("[setup] Waiting for completion") @@ -65,19 +95,48 @@ ###################### EXECUTE ######################### ######################################################## print("[execute] Starting emulator") - emulator.start(fast_arm=True) + emulator.start(fast_arm=True, connect_gs=True) time.sleep(5) - print("[execute] Waiting 10 seconds for calibration") - time.sleep(10) # Allow enough time for calib to complete + print("[execute] Set up dashboard drain") + dashboard_dump_thread = threading.Thread( + target=dashboard_update_thread, + args=[serial_connection], + daemon=True + ) + + print("[execute] Connecting") + serial_connection.reset_input_buffer() + serial_connection.connect() + + # assert proper connection + print("[execute] Verifying connection") + tester.assert_eq(serial_connection.target.controller.id, b'\x10', "Check that connect completed successfully (GS HW Opcode).") + tester.assert_eq(serial_connection.target.firmware.id, b'\x11', "Check that connect completed successfully (GS FW Opcode).") + + print("[execute] Start dashboard drain") + dashboard_dump_thread.start() + + print("[execute] Waiting 20 seconds for calibration & sufficient LoRa messages") + time.sleep(20) # Allow enough time for calib to complete print("[execute] Tearing down execute phase") + stop_event.set() + dashboard_dump_thread.join() emulator.stop() time.sleep(5) ######################################################## ###################### VERIFY ########################## ######################################################## + print("[verify] Check that a dashboard_dump message was received.") + dump_msg = telemetry_obj.get_latest_dashboard_dump() + tester.assert_eq(dump_msg is not None, True, "Dashboard Dump message is not None.") + + print("[verify] Check that a vehicle_id message was received.") + id_msg = telemetry_obj.get_latest_wireless_stats() + tester.assert_eq(id_msg["target"] != "Connecting...", True, "Vehicle ID message received.") + print("[verify] Starting emulator") emulator.start() time.sleep(5) diff --git a/test/app/rev2/flight_int/support/test_presets.json b/test/app/rev2/flight_int/support/test_presets.json index e3c9ffda..f993ccbd 100644 --- a/test/app/rev2/flight_int/support/test_presets.json +++ b/test/app/rev2/flight_int/support/test_presets.json @@ -4,7 +4,7 @@ "Dual Deploy": false, "Active Roll Control": false, "Active Pitch Yaw Control": false, - "Wireless Transmission": false, + "Wireless Transmission": true, "Launch Detect Baro": true, "Launch Detect Accel": true, "GPS": true diff --git a/test/utilities/sdr_emulator_utils/emulator_runner.py b/test/utilities/sdr_emulator_utils/emulator_runner.py index 45be5925..ec67cf32 100644 --- a/test/utilities/sdr_emulator_utils/emulator_runner.py +++ b/test/utilities/sdr_emulator_utils/emulator_runner.py @@ -61,7 +61,7 @@ def generate_coverage(self) -> bool: os.chdir(cwd) return result.returncode == 0 - def start(self, fast_arm = False) -> subprocess.Popen: + def start(self, fast_arm = False, connect_gs = False) -> subprocess.Popen: args = [] if os.name == "nt": args.append("build/appa.exe") @@ -83,7 +83,14 @@ def start(self, fast_arm = False) -> subprocess.Popen: **kwargs ) assert proc.stdin is not None - proc.stdin.write(os.environ["EMULATOR_COMPORT"] + "\n") + + # Startup Interactions + # 1: FC SDEC Comport + # 2: GS SDEC Comport + if not connect_gs: + proc.stdin.write(os.environ["EMULATOR_COMPORT"] + "\n" + "\n") + else: + proc.stdin.write("\n" + os.environ["EMULATOR_COMPORT"] + "\n") proc.stdin.flush() proc.stdin.close() os.chdir(cwd) From e58c355285fc8bc3eb9e3e0af78badef2baa5ac9 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 19:24:59 -0700 Subject: [PATCH 26/38] Add CodeQL to try to track down the memory bug --- .github/workflows/codeql.yml | 135 ++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 33 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 249b9bda..1e2408de 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -10,15 +10,15 @@ # supported CodeQL languages. # name: "CodeQL Advanced" - + on: push: - branches: [ "main" ] + branches: [ "main", "integration/**" ] pull_request: - branches: [ "main" ] + branches: [ "main", "integration/**" ] schedule: - cron: '41 0 * * 1' - + jobs: analyze: name: Analyze (${{ matrix.language }}) @@ -27,18 +27,18 @@ jobs: # - https://gh.io/supported-runners-and-hardware-resources # - https://gh.io/using-larger-runners (GitHub.com only) # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + runs-on: ubuntu-latest permissions: # required for all workflows security-events: write - + # required to fetch internal or private CodeQL packs packages: read - + # only required for workflows in private repositories actions: read contents: read - + strategy: fail-fast: false matrix: @@ -60,15 +60,26 @@ jobs: uses: actions/checkout@v6 with: submodules: 'recursive' - + # Add any setup steps before running the `github/codeql-action/init` action. # This includes steps like installing compilers or runtimes (`actions/setup-node` # or others). This is typically only required for manual builds. - # - name: Setup runtime (example) - # uses: actions/setup-example@v1 - - # Initializes the CodeQL tools for scanning. + - name: Check out firmware compiler + if: matrix.language == 'c-cpp' + uses: carlosperate/arm-none-eabi-gcc-action@v1 + with: + release: '13.3.Rel1' # <-- The compiler release to use + - name: Check out X11 tools for emulator build + if: matrix.language == 'c-cpp' + run: | + sudo apt-get update + sudo apt-get install -y libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxcb-xinput-dev libxi-dev + + # ------------------------------------------------------------------ + # Non-c-cpp languages (e.g. 'actions'): single init / build / analyze + # ------------------------------------------------------------------ - name: Initialize CodeQL + if: matrix.language != 'c-cpp' uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} @@ -79,33 +90,91 @@ jobs: # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. - + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - - name: Check out firmware compiler - uses: carlosperate/arm-none-eabi-gcc-action@v1 + + - name: Perform CodeQL Analysis + if: matrix.language != 'c-cpp' + uses: github/codeql-action/analyze@v4 with: - release: '13.3.Rel1' # <-- The compiler release to use - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - name: Run manual build steps - if: matrix.build-mode == 'manual' + category: "/language:${{matrix.language}}" + + # ------------------------------------------------------------------ + # c-cpp: split into three databases/categories so rev2, rev3, and the + # emulator build show up as separate results in code scanning instead + # of being merged into a single combined database. + # ------------------------------------------------------------------ + + # --- rev2 release build --- + - name: Initialize CodeQL (rev2 release) + if: matrix.language == 'c-cpp' + uses: github/codeql-action/init@v4 + with: + languages: c-cpp + build-mode: manual + config: | + paths-ignore: + - auto + + - name: Build rev2 release + if: matrix.language == 'c-cpp' shell: bash run: | - # Release Build cd app/rev2 make DEBUG=0 - - # Rev 3 Test App (drivers) - cd ../rev3 + + - name: Analyze rev2 release + if: matrix.language == 'c-cpp' + uses: github/codeql-action/analyze@v4 + with: + category: "/language:c-cpp/rev2" + + # --- rev3 test app (drivers) --- + - name: Initialize CodeQL (rev3) + if: matrix.language == 'c-cpp' + uses: github/codeql-action/init@v4 + with: + languages: c-cpp + build-mode: manual + config: | + paths-ignore: + - auto + + - name: Build rev3 test app + if: matrix.language == 'c-cpp' + shell: bash + run: | + cd app/rev3 make - - - name: Perform CodeQL Analysis + + - name: Analyze rev3 + if: matrix.language == 'c-cpp' uses: github/codeql-action/analyze@v4 with: - category: "/language:${{matrix.language}}" + category: "/language:c-cpp/rev3" + + # --- emulator build --- + - name: Initialize CodeQL (emulator) + if: matrix.language == 'c-cpp' + uses: github/codeql-action/init@v4 + with: + languages: c-cpp + build-mode: manual + config: | + paths-ignore: + - auto + + - name: Build emulator + if: matrix.language == 'c-cpp' + shell: bash + run: | + cd app/rev2 + make clean + make emulator + + - name: Analyze emulator + if: matrix.language == 'c-cpp' + uses: github/codeql-action/analyze@v4 + with: + category: "/language:c-cpp/emulator" From 5f2e54d4c5542ff011feb19bc1aefcec37cea69a Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 19:52:39 -0700 Subject: [PATCH 27/38] Pull up emulator to fix OBO --- emulator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emulator b/emulator index ead7aa98..77b588c8 160000 --- a/emulator +++ b/emulator @@ -1 +1 @@ -Subproject commit ead7aa98ef4af8c42cc69800ae68b23c27d87bbd +Subproject commit 77b588c8ea605cf6b6e23986773e2391bb391979 From ff61f411b90b4b08dcc044cce3b00331095f3be8 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 20:01:45 -0700 Subject: [PATCH 28/38] Pull up mod --- mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod b/mod index e4db23eb..fda21c44 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit e4db23eb872d2ebf67aec28b5e9bcd9eeadb86eb +Subproject commit fda21c44cffc908267233b7c5c37e365d2278b09 From 67643a24b27deded94198b189a6ea413ad0a8d69 Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 20:27:14 -0700 Subject: [PATCH 29/38] Pull up driver and add driver tests to project-level CI --- .github/workflows/test-runner.yml | 49 +++++++++++++++++++++++++++++-- driver | 2 +- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-runner.yml b/.github/workflows/test-runner.yml index 04636bdd..dfed4626 100644 --- a/.github/workflows/test-runner.yml +++ b/.github/workflows/test-runner.yml @@ -18,7 +18,7 @@ on: permissions: contents: read jobs: - unit-tests: + app-unit-tests: runs-on: ubuntu-latest strategy: matrix: @@ -63,6 +63,51 @@ jobs: run: echo 'Artifact ID is ${{ steps.promote-results.outputs.artifact-id }}' - run: echo "🍏 This job's status is ${{ job.status }}." + driver-unit-tests: + runs-on: ubuntu-latest + strategy: + matrix: + tests: [gps, servo] + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" + - run: echo "🔎 The name of your branch is ${{ github.ref }}." + - name: Install test environment + run: | + python -m pip install --upgrade pip + pip install gcovr + - name: Check out FCF repository code + uses: actions/checkout@v6 + with: + ref: ${{ github.event.inputs.fw-branch || github.ref }} + submodules: 'recursive' + - run: echo "💡 The repository has been cloned to the runner." + - run: echo "đŸ–Ĩī¸ The workflow is now ready to test your code on the runner." + - name: List files in the repository + run: | + ls ${{ github.workspace }} + + - name: Build and run the appa/${{ matrix.tests }} tests + run: | + cd ${{ github.workspace }}/driver/_test/driver/${{ matrix.tests }} + make test + - name: Check for fails. + run: | + cd ${{ github.workspace }}/driver/_test/driver/${{ matrix.tests }} + tail -3 results.txt | grep "Result: PASS" + - name: Consolidate ${{ matrix.tests }} artifacts + run: mv ${{ github.workspace }}/driver/_test/driver/${{ matrix.tests }}/results.txt ${{ github.workspace }}/driver/_test/driver/${{ matrix.tests }}/coverage/results.txt + - name: "Promote Artifacts" + uses: actions/upload-artifact@v6 + id: promote-results + with: + name: ${{ matrix.tests }}-artifacts + path: ${{ github.workspace }}/driver/_test/driver/${{ matrix.tests }}/coverage/ + include-hidden-files: true + - name: Output artifact ID + run: echo 'Artifact ID is ${{ steps.promote-results.outputs.artifact-id }}' + - run: echo "🍏 This job's status is ${{ job.status }}." + emulator-tests: runs-on: ubuntu-latest timeout-minutes: 7 @@ -162,7 +207,7 @@ jobs: # Take coverage reports and merge them consolidate-coverage: runs-on: ubuntu-latest - needs: [unit-tests, emulator-tests] + needs: [app-unit-tests, driver-unit-tests, emulator-tests] steps: - name: Install gcovr run: | diff --git a/driver b/driver index 43593b09..b311d278 160000 --- a/driver +++ b/driver @@ -1 +1 @@ -Subproject commit 43593b0913ad78048186b7008ee12b776ee734f4 +Subproject commit b311d278d430c44a33b826de614d567d74b3da2e From 7511d075e99fe8c7a434f649c2030ba9749627ec Mon Sep 17 00:00:00 2001 From: etsells Date: Sun, 5 Jul 2026 20:31:23 -0700 Subject: [PATCH 30/38] Pull up driver/test_framework --- driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver b/driver index b311d278..4df5e8bd 160000 --- a/driver +++ b/driver @@ -1 +1 @@ -Subproject commit b311d278d430c44a33b826de614d567d74b3da2e +Subproject commit 4df5e8bd02fcd5c216b4a084b2ab8690943bee20 From 5c2b45f0cd195d3c9f07c171737f3b3c011b4049 Mon Sep 17 00:00:00 2001 From: etsells Date: Mon, 6 Jul 2026 18:13:52 -0700 Subject: [PATCH 31/38] Pull up emulator --- app/rev2/Makefile | 1 + emulator | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/rev2/Makefile b/app/rev2/Makefile index 0f5c8533..d74f0d04 100644 --- a/app/rev2/Makefile +++ b/app/rev2/Makefile @@ -136,6 +136,7 @@ $(BASE_DIR)/emulator/src/emulator_ground_station.c \ $(BASE_DIR)/emulator/src/emulator_uart.c \ $(BASE_DIR)/emulator/src/emulator_spi.c \ $(BASE_DIR)/emulator/src/emulator_lora.c \ +$(BASE_DIR)/emulator/src/emulator_serial.c \ $(BASE_DIR)/emulator/src/emulator_i2c.c \ $(BASE_DIR)/emulator/src/emulator_gui.c \ $(BASE_DIR)/emulator/src/shaders/shaders.c \ diff --git a/emulator b/emulator index 77b588c8..d08921b9 160000 --- a/emulator +++ b/emulator @@ -1 +1 @@ -Subproject commit 77b588c8ea605cf6b6e23986773e2391bb391979 +Subproject commit d08921b926f1678724859a16aab4d2a712040cca From 880b211d780396daf5f001b9523004de3d563156 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Wed, 8 Jul 2026 19:59:16 -0700 Subject: [PATCH 32/38] coast detect z to x one liner, pull up mod --- app/rev2/state_transition.c | 2 +- mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/rev2/state_transition.c b/app/rev2/state_transition.c index 529fa370..fddd3ea5 100644 --- a/app/rev2/state_transition.c +++ b/app/rev2/state_transition.c @@ -187,7 +187,7 @@ bool coast_detect static uint8_t positive_readings = 0; /* check if accel is sufficiently low */ -if ( sensor_data.imu_converted.accel_z < COAST_DETECT_THRESHOLD * GRAVITY ) +if ( sensor_data.imu_converted.accel_x < COAST_DETECT_THRESHOLD * GRAVITY ) { positive_readings++; } diff --git a/mod b/mod index fda21c44..c857f8af 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit fda21c44cffc908267233b7c5c37e365d2278b09 +Subproject commit c857f8af0225ed4fc62cfcd54c855bdbe140e948 From 6e11f3e1e99cc13fda825ca903c9049dbab17e82 Mon Sep 17 00:00:00 2001 From: etsells Date: Sat, 11 Jul 2026 12:21:04 -0700 Subject: [PATCH 33/38] Pull up mod --- mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod b/mod index c857f8af..654bbb34 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit c857f8af0225ed4fc62cfcd54c855bdbe140e948 +Subproject commit 654bbb346c14c6e8f8c37e69680d462e5f2b0b01 From d9dcfeae7483cdd67fec1a6c25d3695223a53ebe Mon Sep 17 00:00:00 2001 From: etsells Date: Sat, 11 Jul 2026 12:27:26 -0700 Subject: [PATCH 34/38] Test updates + submodule pullup --- emulator | 2 +- mod | 2 +- test/app/rev2/terminal_int/terminal_int_test.py | 17 +---------------- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/emulator b/emulator index d08921b9..3f9f5549 160000 --- a/emulator +++ b/emulator @@ -1 +1 @@ -Subproject commit d08921b926f1678724859a16aab4d2a712040cca +Subproject commit 3f9f5549e9f94160d8da3be27405ece3718888c6 diff --git a/mod b/mod index 654bbb34..91d13bb6 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 654bbb346c14c6e8f8c37e69680d462e5f2b0b01 +Subproject commit 91d13bb685965cf9166f698fa9e551d37622bb76 diff --git a/test/app/rev2/terminal_int/terminal_int_test.py b/test/app/rev2/terminal_int/terminal_int_test.py index 08898fef..ca90c6d3 100644 --- a/test/app/rev2/terminal_int/terminal_int_test.py +++ b/test/app/rev2/terminal_int/terminal_int_test.py @@ -16,15 +16,12 @@ # Helper functions def check_sensor(tester, sensor_name, readout): - # These sensors will not trigger a fail if the readout is invalid - postponed_list = ["pos", "altg", "speedg", "utc_time", "long", "lat", "ns", "ew", "gll_s", "rmc_s"] - if readout: min = float('-inf') max = float('inf') match sensor_name: # RAW VALUES - case "accXconv" | "accYconv" | "accZconv" | "acc_z": + case "accXconv" | "accYconv" | "accZconv" | "acc_x" | "acc_y" | "acc_z": min = -12 max = 12 case "gyroXconv" | "gyroYconv" | "gyroZconv" | "roll_rate": @@ -55,18 +52,6 @@ def check_sensor(tester, sensor_name, readout): # This is true since the else branch's assert wasn't reached tester.assert_float_in_range(readout, min, max, f"Check that {sensor_name} is in the expected range.") - else: - # GPS is expected to fail if there are no valid readings, and GPS is only enabled after arming. - # This is known behavior that you may want to consider a bug. If you would like this fixed, - # please open a ticket. - # - # Position is known to be defective as of v2.6.0. The issue was noticed during mod#102 - # and we chose not to address it. The reading will instead be removed at a later date - # when space is needed in the sensor data struct. - # - # Follow mod#101 for updates on this. - if sensor_name not in postponed_list: - tester.assert_neq(0, 0, f"{sensor_name} has no available reading, so autofail.") sdec_comport = os.environ.get("SDEC_COMPORT") emulator_comport = os.environ.get("EMULATOR_COMPORT") From d79aef785338f8a1a06a3c3c4c224dd637bc95a3 Mon Sep 17 00:00:00 2001 From: etsells Date: Mon, 13 Jul 2026 18:17:39 -0700 Subject: [PATCH 35/38] Pull up mod --- mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod b/mod index 91d13bb6..2680f5b5 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 91d13bb685965cf9166f698fa9e551d37622bb76 +Subproject commit 2680f5b5184fdcb1078754a8526e1f0b1b70b68c From f331337093d0c77e4029d70d92fcd21ad296df6e Mon Sep 17 00:00:00 2001 From: NArmistead Date: Mon, 20 Jul 2026 01:47:01 -0700 Subject: [PATCH 36/38] Corrections to mount orientation --- app/rev2/main.c | 1 + app/rev2/main.h | 3 ++- app/rev2/sensor_calibrate.c | 20 ++++++++++---------- mod | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/rev2/main.c b/app/rev2/main.c index 04000f1d..0e29f8a0 100644 --- a/app/rev2/main.c +++ b/app/rev2/main.c @@ -297,6 +297,7 @@ if ( read_status == FLASH_FAIL ) { error_fail_fast( ERROR_FLASH_CMD_ERROR ); } +set_mount_orientation( preset_data.last_orientation ); /*------------------------------------------------------------------------------ End of init // Begin program diff --git a/app/rev2/main.h b/app/rev2/main.h index ae16acea..e8cc5f10 100644 --- a/app/rev2/main.h +++ b/app/rev2/main.h @@ -141,8 +141,9 @@ typedef struct _PRESET_DATA /* total: 88 bytes */ IMU_OFFSET imu_offset; /* 24 bytes */ BARO_PRESET baro_preset; /* 8 bytes */ SERVO_PRESET servo_preset; /* 4 bytes */ + MOUNT_ORIENTATION last_orientation; /* 4 bytes */ } PRESET_DATA; - _Static_assert( sizeof(PRESET_DATA) == 96, "PRESET_DATA size invalid." ); + _Static_assert( sizeof(PRESET_DATA) == 100, "PRESET_DATA size invalid." ); typedef enum __attribute__((packed)) _FLIGHT_COMP_STATE { diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index 63d38075..7b35a97e 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -60,6 +60,9 @@ void sensorCalibrationSWCON(){ SENSOR_STATUS sensor_status = SENSOR_OK; (void)sensor_status; + /* Make sure this is consistent at calib, then flip after if we need to */ + set_mount_orientation( MOUNT_ORIENTATION_IMU_INVERTED ); + preset_data.imu_offset.accel_x = 0.00; preset_data.imu_offset.accel_y = 0.00; preset_data.imu_offset.accel_z = 0.00; @@ -108,7 +111,7 @@ void sensorCalibrationSWCON(){ calc_gyro_y = calc_gyro_y / ( samples ); calc_gyro_z = calc_gyro_z / ( samples ); - debug_assert( calc_acc_z != 0.0f, ERROR_SENSOR_CMD_ERROR ); + debug_assert( calc_acc_x != 0.0f, ERROR_SENSOR_CMD_ERROR ); calc_baro_pres = calc_baro_pres / ( samples ); calc_baro_temp = calc_baro_temp / ( samples ); @@ -126,20 +129,16 @@ void sensorCalibrationSWCON(){ /* Sensor dump readings already factor in the orientation, which is assumed at startup to be inverted. If gravity is a negative value at calib, flip the orientaion and offsets back accordingly. */ - if ( calc_acc_z > 0.0f ) - { - set_mount_orientation( MOUNT_ORIENTATION_IMU_INVERTED ); - } - else + if ( calc_acc_x < 0.0f ) { set_mount_orientation( MOUNT_ORIENTATION_IMU_NORMAL ); - /* Flip the X and Z offsets back to match */ + /* Flip the X and Z offsets to match */ preset_data.imu_offset.accel_x *= -1; preset_data.imu_offset.accel_z *= -1; preset_data.imu_offset.gyro_x *= -1; - preset_data.imu_offset.gyro_z *= -1; + preset_data.imu_offset.gyro_z *= -1; } /* Initialize sensor */ @@ -153,8 +152,9 @@ void sensorCalibrationSWCON(){ tdelta, (float)tdelta / samples ); debug_ignore_emulator_warnings_stop(); debug_log(sensor_dbg_msg, msg_len, LOG_LVL_INFO); - msg_len = snprintf(sensor_dbg_msg, 128, "IMU Offsets: %.04f %.04f %.04f %.04f %.04f %.04f. Baro Offsets: %.04f %.04f.", - calc_acc_x, calc_acc_y, calc_acc_z, calc_gyro_x, calc_gyro_y, calc_gyro_z, calc_baro_pres, calc_baro_temp); + MOUNT_ORIENTATION orientation = get_mount_orientation(); + msg_len = snprintf(sensor_dbg_msg, 128, "IMU Offsets: %.04f %.04f %.04f %.04f %.04f %.04f. Baro Offsets: %.04f %.04f. Orientation: %d", + calc_acc_x, calc_acc_y, calc_acc_z, calc_gyro_x, calc_gyro_y, calc_gyro_z, calc_baro_pres, calc_baro_temp, orientation ); debug_log(sensor_dbg_msg, msg_len, LOG_LVL_INFO); #endif diff --git a/mod b/mod index 2680f5b5..719e2eb8 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 2680f5b5184fdcb1078754a8526e1f0b1b70b68c +Subproject commit 719e2eb84f76a5ed71774be1f875c618c605ec81 From 4a547e08ef0e19eab66625896b29563308e21b30 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Mon, 20 Jul 2026 07:28:19 -0700 Subject: [PATCH 37/38] test stub for mount orientation, pull up driver --- driver | 2 +- test/app/rev2/main/mock/mocks.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/driver b/driver index 4df5e8bd..8091bc52 160000 --- a/driver +++ b/driver @@ -1 +1 @@ -Subproject commit 4df5e8bd02fcd5c216b4a084b2ab8690943bee20 +Subproject commit 8091bc52b8477477ff8f05439f4f3c0e90582816 diff --git a/test/app/rev2/main/mock/mocks.c b/test/app/rev2/main/mock/mocks.c index a4cef76d..ea353217 100644 --- a/test/app/rev2/main/mock/mocks.c +++ b/test/app/rev2/main/mock/mocks.c @@ -139,6 +139,14 @@ IMU_STATUS imu_init return imu_init_return; } +void set_mount_orientation + ( + MOUNT_ORIENTATION orientation + ) +{ +// stub +} + SERVO_STATUS servo_init ( void From 45209a8bd5d32b4148456f6feae0a412fe4d2721 Mon Sep 17 00:00:00 2001 From: NArmistead Date: Tue, 21 Jul 2026 10:04:45 -0700 Subject: [PATCH 38/38] Hopefully better way to do orientation --- app/rev2/main.c | 11 ++++++++++- app/rev2/main.h | 3 +-- app/rev2/sensor_calibrate.c | 9 +-------- mod | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/app/rev2/main.c b/app/rev2/main.c index 0e29f8a0..b73f940d 100644 --- a/app/rev2/main.c +++ b/app/rev2/main.c @@ -297,7 +297,16 @@ if ( read_status == FLASH_FAIL ) { error_fail_fast( ERROR_FLASH_CMD_ERROR ); } -set_mount_orientation( preset_data.last_orientation ); + +/* Set orientation based on saved data */ +if ( preset_data.imu_offset.accel_x < 0.0f ) + { + set_mount_orientation( MOUNT_ORIENTATION_IMU_NORMAL ); + } +else + { + set_mount_orientation( MOUNT_ORIENTATION_IMU_INVERTED ); + } /*------------------------------------------------------------------------------ End of init // Begin program diff --git a/app/rev2/main.h b/app/rev2/main.h index e8cc5f10..ae16acea 100644 --- a/app/rev2/main.h +++ b/app/rev2/main.h @@ -141,9 +141,8 @@ typedef struct _PRESET_DATA /* total: 88 bytes */ IMU_OFFSET imu_offset; /* 24 bytes */ BARO_PRESET baro_preset; /* 8 bytes */ SERVO_PRESET servo_preset; /* 4 bytes */ - MOUNT_ORIENTATION last_orientation; /* 4 bytes */ } PRESET_DATA; - _Static_assert( sizeof(PRESET_DATA) == 100, "PRESET_DATA size invalid." ); + _Static_assert( sizeof(PRESET_DATA) == 96, "PRESET_DATA size invalid." ); typedef enum __attribute__((packed)) _FLIGHT_COMP_STATE { diff --git a/app/rev2/sensor_calibrate.c b/app/rev2/sensor_calibrate.c index 7b35a97e..991b1111 100644 --- a/app/rev2/sensor_calibrate.c +++ b/app/rev2/sensor_calibrate.c @@ -128,17 +128,10 @@ void sensorCalibrationSWCON(){ preset_data.baro_preset.baro_temp = calc_baro_temp; /* Sensor dump readings already factor in the orientation, which is assumed at startup to be inverted. - If gravity is a negative value at calib, flip the orientaion and offsets back accordingly. */ + If we read a negative value for gravity, flip the orientation */ if ( calc_acc_x < 0.0f ) { set_mount_orientation( MOUNT_ORIENTATION_IMU_NORMAL ); - - /* Flip the X and Z offsets to match */ - preset_data.imu_offset.accel_x *= -1; - preset_data.imu_offset.accel_z *= -1; - - preset_data.imu_offset.gyro_x *= -1; - preset_data.imu_offset.gyro_z *= -1; } /* Initialize sensor */ diff --git a/mod b/mod index 719e2eb8..2c2e9c8c 160000 --- a/mod +++ b/mod @@ -1 +1 @@ -Subproject commit 719e2eb84f76a5ed71774be1f875c618c605ec81 +Subproject commit 2c2e9c8ce8f84ce7fc340b30ff8f5463447a47c8