diff --git a/docs/00_Getting_Started.md b/docs/00_Getting_Started.md index c35f473a4..fba09cab7 100644 --- a/docs/00_Getting_Started.md +++ b/docs/00_Getting_Started.md @@ -24,8 +24,10 @@ Follow through this guide, and follow through the rest of the numbered guides in ### Troubleshooting 1. Check that your MicroUSB cable supports data transfer. Many MicroUSB cables are power-only. -2. Disable your antivirus if it starts removing the compiler. -3. Use the Ctrl+Shift+P command palate to run "STM32: Install all the build tools ...". +2. The dev-board has two connectors on it, only one of which (the CN1 connector) can be used to plug in the MicroUSB cable. Ensure that you are using the correct connector. +3. Disable your antivirus if it starts removing the compiler. +4. Use the Ctrl+Shift+P command palate to run "STM32: Install all the build tools ...". +5. The OBC has two USB connectors which are required for uploading code (the ST-Link) and communicating with a computer (the umbilical). Ensure the correct one(s) are connected to your computer when testing with the OBC. ## Testing and Debugging the Firmware diff --git a/docs/40_Logging.md b/docs/40_Logging.md index a455d135b..9a969e486 100644 --- a/docs/40_Logging.md +++ b/docs/40_Logging.md @@ -16,7 +16,7 @@ The logging system on this satellite is rather simple: call the `LOG_message(... ## How to use `LOG_message(...)` -YOU, a developer, must be use the `LOG_message(...)` function. Here's how: +YOU, a developer, must use the `LOG_message(...)` function. Here's how: 1. In just about every `.c` file, include: `#include "log/log.h"` 2. Call `LOG_message(...)` with the message you want to log with the relevant subsystem, log severity, which sinks (`LOG_SINK_ALL` by default), a message, and any printf-like arguments for format strings in the message: diff --git a/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h b/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h index c97ecc603..1dd1219c7 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h @@ -102,7 +102,7 @@ static const uint8_t ADCS_TELEMETRY_CUBEACP_CURRENT_ADCS_STATE_2 = 224; static const uint8_t ADCS_TELEMETRY_CUBEACP_JPG_CONVERSION_PROGRESS = 133; static const uint8_t ADCS_TELEMETRY_CUBEACP_CUBEACP_STATE = 135; static const uint8_t ADCS_TELEMETRY_CUBEACP_ADCS_EXECUTION_TIMES = 196; -static const uint8_t ADCS_TELEMETRY_CUBEACP_ACP_EXECUTION_STATE = 220; +static const uint8_t ADCS_TELEMETRY_CUBEACP_EXECUTION_STATE = 220; static const uint8_t ADCS_TELEMETRY_CUBEACP_IMAGE_CAPTURE_AND_SAVE_STATUS = 233; static const uint8_t ADCS_TELEMETRY_CUBEACP_MAGNETIC_FIELD_VECTOR = 151; static const uint8_t ADCS_TELEMETRY_CUBEACP_COARSE_SUN_VECTOR = 152; @@ -223,4 +223,69 @@ static const uint8_t ADCS_COMMAND_BOOTLOADER_RUN_PROGRAM = 101; static const uint8_t ADCS_COMMAND_BOOTLOADER_READ_INFO = 102; static const uint8_t ADCS_COMMAND_BOOTLOADER_COPY_TO_FLASH = 103; +// SD Log Bit Masks - Section 8 Table 216 of Firmware Manual +static const uint8_t ADCS_SD_LOG_MASK_COMMUNICATION_STATUS[10] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_EDAC_ERROR_COUNTERS[10] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_LAST_LOGGED_EVENT[10] = {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_SRAM_LATCHUP_COUNTERS[10] = {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_MAGNETORQUER_COMMAND[10] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_WHEEL_SPEED_COMMANDS[10] = {0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR[10] = {0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_COARSE_SUN_VECTOR[10] = {0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_FINE_SUN_VECTOR[10] = {0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_NADIR_VECTOR[10] = {0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RATE_SENSOR_RATES[10] = {0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_WHEEL_SPEED[10] = {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_1_BODY_VECTOR[10] = {0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_1_ORBIT_VECTOR[10] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_2_BODY_VECTOR[10] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_2_ORBIT_VECTOR[10] = {0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_3_BODY_VECTOR[10] = {0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_3_ORBIT_VECTOR[10] = {0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CUBESENSE1_CURRENT_MEASUREMENTS[10] = {0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CUBECONTROL_CURRENT_MEASUREMENTS[10] = {0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_WHEEL_CURRENTS[10] = {0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ADCS_MISC_CURRENT_MEASUREMENTS[10] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ADCS_TEMPERATURES[10] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RATE_SENSOR_TEMPERATURES[10] = {0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CURRENT_ADCS_STATE[10] = {0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES[10] = {0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ESTIMATED_QUATERNION[10] = {0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ESTIMATED_ANGULAR_RATES[10] = {0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_SATELLITE_POSITION_ECI[10] = {0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_SATELLITE_VELOCITY_ECI[10] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_SATELLITE_POSITION_LLH[10] = {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ECEF_POSITION[10] = {0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_IGRF_MODELLED_MAGNETIC_FIELD_VECTOR[10] = {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_MODELLED_SUN_VECTOR[10] = {0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ESTIMATED_GYRO_BIAS[10] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ESTIMATION_INNOVATION_VECTOR[10] = {0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_QUATERNION_ERROR_VECTOR[10] = {0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_QUATERNION_COVARIANCE[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_ANGULAR_RATE_COVARIANCE[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_GPS_STATUS[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_GPS_TIME[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_GPS_X[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_GPS_Y[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_GPS_Z[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_CAM2_SENSOR[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_CAM1_SENSOR[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_CSS_1_TO_6[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_CSS_7_TO_10[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_MAGNETOMETER[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_PERFORMANCE1[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_MAGNITUDE[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_1_RAW_DATA[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_2_RAW_DATA[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_3_RAW_DATA[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_TIMING[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_SECONDARY_MAGNETOMETER_RAW_MEASUREMENTS[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_RAW_RATE_SENSOR[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CURRENT_ADCS_STATE_2[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CUBESTAR_ESTIMATED_RATES[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CUBESTAR_ESTIMATED_QUATERNION[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_STAR_PERFORMANCE2[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; +static const uint8_t ADCS_SD_LOG_MASK_CUBESENSE2_CURRENT_MEASUREMENTS[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; + #endif /* INC_ADCS_COMMAND_IDS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_commands.h b/firmware/Core/Inc/adcs_drivers/adcs_commands.h index 16142f2b1..a1c2398ac 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -121,5 +121,14 @@ uint8_t ADCS_get_raw_gps_x(ADCS_raw_gps_struct_t *output_struct); uint8_t ADCS_get_raw_gps_y(ADCS_raw_gps_struct_t *output_struct); uint8_t ADCS_get_raw_gps_z(ADCS_raw_gps_struct_t *output_struct); uint8_t ADCS_get_measurements(ADCS_measurements_struct_t *output_struct); +uint8_t ADCS_get_acp_execution_state(ADCS_acp_execution_state_struct_t *output_struct); +uint8_t ADCS_get_current_state_1(ADCS_current_state_1_struct_t *output_struct); +uint8_t ADCS_get_raw_star_tracker_data(ADCS_raw_star_tracker_struct_t *output_struct); +uint8_t ADCS_save_image_to_sd(ADCS_camera_select_enum_t camera_select, ADCS_image_size_enum_t image_size); +uint8_t ADCS_get_current_unix_time(); +uint8_t ADCS_synchronise_unix_time(); +uint8_t ADCS_set_sd_log_config(uint8_t which_log, const uint8_t **log_array, uint8_t log_array_size, uint16_t log_period, ADCS_sd_log_destination_enum_t which_sd); +uint8_t ADCS_get_sd_log_config(uint8_t which_log, ADCS_sd_log_config_struct* config); + #endif /* INC_ADCS_COMMANDS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h b/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h index 5dec6ca22..6cdbe8731 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h @@ -16,6 +16,8 @@ static const uint16_t ADCS_PROCESSED_TIMEOUT = 1000; // byte transforms uint8_t ADCS_convert_uint16_to_reversed_uint8_array_members(uint8_t *array, uint16_t value, uint16_t index); uint8_t ADCS_convert_uint32_to_reversed_uint8_array_members(uint8_t *array, uint32_t value, uint16_t index); +uint8_t ADCS_convert_double_to_string(double input, uint8_t precision, char* output_string, uint16_t str_len); +uint8_t ADCS_combine_sd_log_bitmasks(const uint8_t **array_in, const uint8_t array_in_size, uint8_t *array_out); // TC/TLM functions (basic communication) uint8_t ADCS_i2c_send_command_and_check(uint8_t id, uint8_t* data, uint32_t data_length, uint8_t include_checksum); diff --git a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h index ce0cc196d..8edcfc118 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -4,43 +4,48 @@ #include "adcs_drivers/adcs_types.h" // ADCS packer functions -uint8_t ADCS_Pack_to_Ack_Struct(uint8_t* data_received, ADCS_cmd_ack_struct_t *result); -uint8_t ADCS_Pack_to_Identification_Struct(uint8_t* data_received, ADCS_id_struct_t *result); -uint8_t ADCS_Pack_to_Program_Status_Struct(uint8_t* data_received, ADCS_boot_running_status_struct_t *result); -uint8_t ADCS_Pack_to_Comms_Status_Struct(uint8_t* data_received, ADCS_comms_status_struct_t *result); -uint8_t ADCS_Pack_to_Power_Control_Struct(uint8_t* data_received, ADCS_power_control_struct_t *result); -uint8_t ADCS_Pack_to_Angular_Rates_Struct(uint8_t* data_received, ADCS_angular_rates_struct_t *result); -uint8_t ADCS_Pack_to_LLH_Position_Struct(uint8_t* data_received, ADCS_llh_position_struct_t *result); -uint8_t ADCS_Pack_to_Unix_Time_Save_Mode_Struct(uint8_t* data_received, ADCS_set_unix_time_save_mode_struct_t *result); -uint8_t ADCS_Pack_to_Orbit_Params_Struct(uint8_t* data_received, ADCS_orbit_params_struct_t *result); -uint8_t ADCS_Pack_to_Rated_Sensor_Rates_Struct(uint8_t* data_received, ADCS_rated_sensor_rates_struct_t *result); -uint8_t ADCS_Pack_to_Wheel_Speed_Struct(uint8_t* data_received, ADCS_wheel_speed_struct_t *result); -uint8_t ADCS_Pack_to_Magnetorquer_Command_Struct(uint8_t* data_received, ADCS_magnetorquer_command_struct_t *result); -uint8_t ADCS_Pack_to_Raw_Magnetometer_Values_Struct(uint8_t* data_received, ADCS_raw_magnetometer_values_struct_t *result); -uint8_t ADCS_Pack_to_Fine_Angular_Rates_Struct(uint8_t* data_received, ADCS_fine_angular_rates_struct_t *result); -uint8_t ADCS_Pack_to_Magnetometer_Config_Struct(uint8_t* data_received, ADCS_magnetometer_config_struct_t *result); -uint8_t ADCS_Pack_to_Commanded_Attitude_Angles_Struct(uint8_t* data_received, ADCS_commanded_angles_struct_t *result); -uint8_t ADCS_Pack_to_Estimation_Params_Struct(uint8_t* data_received, ADCS_estimation_params_struct_t *result); -uint8_t ADCS_Pack_to_Augmented_SGP4_Params_Struct(uint8_t* data_received, ADCS_augmented_sgp4_params_struct_t *result); -uint8_t ADCS_Pack_to_Tracking_Controller_Target_Reference_Struct(uint8_t* data_received, ADCS_tracking_controller_target_struct_t *result); -uint8_t ADCS_Pack_to_Rate_Gyro_Config_Struct(uint8_t* data_received, ADCS_rate_gyro_config_struct_t *result); -uint8_t ADCS_Pack_to_Estimated_Attitude_Angles_Struct(uint8_t *data_received, ADCS_estimated_attitude_angles_struct_t *angles); -uint8_t ADCS_Pack_to_Magnetic_Field_Vector_Struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components); -uint8_t ADCS_Pack_to_Fine_Sun_Vector_Struct(uint8_t *data_received, ADCS_fine_sun_vector_struct_t *vector_components); -uint8_t ADCS_Pack_to_Nadir_Vector_Struct(uint8_t *data_received, ADCS_nadir_vector_struct_t *vector_components); -uint8_t ADCS_Pack_to_Commanded_Wheel_Speed_Struct(uint8_t *data_received, ADCS_wheel_speed_struct_t *result); -uint8_t ADCS_Pack_to_IGRF_Magnetic_Field_Vector_Struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components); -uint8_t ADCS_Pack_to_Quaternion_Error_Vector_Struct(uint8_t *data_received, ADCS_quaternion_error_vector_struct_t *result); -uint8_t ADCS_Pack_to_Estimated_Gyro_Bias_Struct(uint8_t* data_received, ADCS_estimated_gyro_bias_struct_t *result); -uint8_t ADCS_Pack_to_Estimation_Innovation_Vector_Struct(uint8_t* data_received, ADCS_estimation_innovation_vector_struct_t *result); -uint8_t ADCS_Pack_to_Raw_Cam1_Sensor_Struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result); -uint8_t ADCS_Pack_to_Raw_Cam2_Sensor_Struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result); -uint8_t ADCS_Pack_to_Raw_Coarse_Sun_Sensor_1_to_6_Struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_1_to_6_struct_t *result); -uint8_t ADCS_Pack_to_Raw_Coarse_Sun_Sensor_7_to_10_Struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_7_to_10_struct_t *result); -uint8_t ADCS_Pack_to_CubeControl_Current_Struct(uint8_t* data_received, ADCS_cubecontrol_current_struct_t *result); -uint8_t ADCS_Pack_to_Raw_GPS_Status_Struct(uint8_t* data_received, ADCS_raw_gps_status_struct_t *result); -uint8_t ADCS_Pack_to_Raw_GPS_Time_Struct(uint8_t* data_received, ADCS_raw_gps_time_struct_t *result); -uint8_t ADCS_Pack_to_Raw_GPS_Struct(ADCS_gps_axis_enum_t axis, uint8_t *data_received, ADCS_raw_gps_struct_t *result); -uint8_t ADCS_Pack_to_Measurements_Struct(uint8_t* telemetry_data, ADCS_measurements_struct_t *measurements); +uint8_t ADCS_pack_to_ack_struct(uint8_t* data_received, ADCS_cmd_ack_struct_t *result); +uint8_t ADCS_pack_to_identification_struct(uint8_t* data_received, ADCS_id_struct_t *result); +uint8_t ADCS_pack_to_program_status_struct(uint8_t* data_received, ADCS_boot_running_status_struct_t *result); +uint8_t ADCS_pack_to_comms_status_struct(uint8_t* data_received, ADCS_comms_status_struct_t *result); +uint8_t ADCS_pack_to_power_control_struct(uint8_t* data_received, ADCS_power_control_struct_t *result); +uint8_t ADCS_pack_to_angular_rates_struct(uint8_t* data_received, ADCS_angular_rates_struct_t *result); +uint8_t ADCS_pack_to_llh_position_struct(uint8_t* data_received, ADCS_llh_position_struct_t *result); +uint8_t ADCS_pack_to_unix_time_save_mode_struct(uint8_t* data_received, ADCS_set_unix_time_save_mode_struct_t *result); +uint8_t ADCS_pack_to_orbit_params_struct(uint8_t* data_received, ADCS_orbit_params_struct_t *result); +uint8_t ADCS_pack_to_rated_sensor_rates_struct(uint8_t* data_received, ADCS_rated_sensor_rates_struct_t *result); +uint8_t ADCS_pack_to_wheel_speed_struct(uint8_t* data_received, ADCS_wheel_speed_struct_t *result); +uint8_t ADCS_pack_to_magnetorquer_command_struct(uint8_t* data_received, ADCS_magnetorquer_command_struct_t *result); +uint8_t ADCS_pack_to_raw_magnetometer_values_struct(uint8_t* data_received, ADCS_raw_magnetometer_values_struct_t *result); +uint8_t ADCS_pack_to_fine_angular_rates_struct(uint8_t* data_received, ADCS_fine_angular_rates_struct_t *result); +uint8_t ADCS_pack_to_magnetometer_config_struct(uint8_t* data_received, ADCS_magnetometer_config_struct_t *result); +uint8_t ADCS_pack_to_commanded_attitude_angles_struct(uint8_t* data_received, ADCS_commanded_angles_struct_t *result); +uint8_t ADCS_pack_to_estimation_params_struct(uint8_t* data_received, ADCS_estimation_params_struct_t *result); +uint8_t ADCS_pack_to_augmented_sgp4_params_struct(uint8_t* data_received, ADCS_augmented_sgp4_params_struct_t *result); +uint8_t ADCS_pack_to_tracking_controller_target_reference_struct(uint8_t* data_received, ADCS_tracking_controller_target_struct_t *result); +uint8_t ADCS_pack_to_rate_gyro_config_struct(uint8_t* data_received, ADCS_rate_gyro_config_struct_t *result); +uint8_t ADCS_pack_to_estimated_attitude_angles_struct(uint8_t *data_received, ADCS_estimated_attitude_angles_struct_t *angles); +uint8_t ADCS_pack_to_magnetic_field_vector_struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components); +uint8_t ADCS_pack_to_fine_sun_vector_struct(uint8_t *data_received, ADCS_fine_sun_vector_struct_t *vector_components); +uint8_t ADCS_pack_to_nadir_vector_struct(uint8_t *data_received, ADCS_nadir_vector_struct_t *vector_components); +uint8_t ADCS_pack_to_commanded_wheel_speed_struct(uint8_t *data_received, ADCS_wheel_speed_struct_t *result); +uint8_t ADCS_pack_to_igrf_magnetic_field_vector_struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components); +uint8_t ADCS_pack_to_quaternion_error_vector_struct(uint8_t *data_received, ADCS_quaternion_error_vector_struct_t *result); +uint8_t ADCS_pack_to_estimated_gyro_bias_struct(uint8_t* data_received, ADCS_estimated_gyro_bias_struct_t *result); +uint8_t ADCS_pack_to_estimation_innovation_vector_struct(uint8_t* data_received, ADCS_estimation_innovation_vector_struct_t *result); +uint8_t ADCS_pack_to_raw_cam1_sensor_struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result); +uint8_t ADCS_pack_to_raw_cam2_sensor_struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result); +uint8_t ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_1_to_6_struct_t *result); +uint8_t ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_7_to_10_struct_t *result); +uint8_t ADCS_pack_to_cubecontrol_current_struct(uint8_t* data_received, ADCS_cubecontrol_current_struct_t *result); +uint8_t ADCS_pack_to_raw_gps_status_struct(uint8_t* data_received, ADCS_raw_gps_status_struct_t *result); +uint8_t ADCS_pack_to_raw_gps_time_struct(uint8_t* data_received, ADCS_raw_gps_time_struct_t *result); +uint8_t ADCS_pack_to_raw_gps_struct(ADCS_gps_axis_enum_t axis, uint8_t *data_received, ADCS_raw_gps_struct_t *result); +uint8_t ADCS_pack_to_measurements_struct(uint8_t* telemetry_data, ADCS_measurements_struct_t *measurements); +uint8_t ADCS_pack_to_acp_execution_state_struct(uint8_t* data_received, ADCS_acp_execution_state_struct_t* output_struct); +uint8_t ADCS_pack_to_current_state_1_struct(uint8_t* data_received, ADCS_current_state_1_struct_t* output_struct); +uint8_t ADCS_pack_to_raw_star_tracker_struct(uint8_t* input_data, ADCS_raw_star_tracker_struct_t* output_data); +uint8_t ADCS_pack_to_unix_time_ms(uint8_t *data_received, uint64_t *output_data); +uint8_t ADCS_pack_to_sd_log_config_struct(uint8_t *data_received, uint8_t which_log, ADCS_sd_log_config_struct *config); #endif /* INC_ADCS_STRUCT_PACKERS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_types.h b/firmware/Core/Inc/adcs_drivers/adcs_types.h index 7930f9c75..369b9b499 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -196,7 +196,70 @@ typedef enum ADCS_gps_axis_enum_t { ADCS_GPS_AXIS_Z = 2 } ADCS_gps_axis_enum_t; -/* Structs */ +typedef enum ADCS_current_execution_point_enum_t { + ADCS_CURRENT_EXECUTION_POINT_BUSY_INITIALIZATION = 0, + ADCS_CURRENT_EXECUTION_POINT_IDLE = 1, + ADCS_CURRENT_EXECUTION_POINT_SENSOR_ACTUATOR_COMMS= 2, + ADCS_CURRENT_EXECUTION_POINT_ADCS_UPDATE = 3, + ADCS_CURRENT_EXECUTION_POINT_PERIPHERAL_POWER_COMMANDS = 4, + ADCS_CURRENT_EXECUTION_POINT_CPU_TEMPERATURE_SAMPLING = 5, + ADCS_CURRENT_EXECUTION_POINT_IMAGE_DOWNLOAD = 6, + ADCS_CURRENT_EXECUTION_POINT_IMAGE_COMPRESSION = 7, + ADCS_CURRENT_EXECUTION_POINT_SAVING_IMAGE_TO_SD = 8, + ADCS_CURRENT_EXECUTION_POINT_LOGGING = 9, + ADCS_CURRENT_EXECUTION_POINT_LOG_FILE_COMPRESSION = 10, + ADCS_CURRENT_EXECUTION_POINT_SAVING_LOG_TO_SD = 11, + ADCS_CURRENT_EXECUTION_POINT_WRITING_TO_FLASH = 12 +} ADCS_current_execution_point_enum_t; + +typedef enum ADCS_asgp4_mode_enum_t { + ADCS_ASGP4_MODE_OFF = 0, + ADCS_ASGP4_MODE_TRIGGER = 1, + ADCS_ASGP4_MODE_BACKGROUND = 2, + ADCS_ASGP4_MODE_AUGMENT = 3, +} ADCS_asgp4_mode_enum_t; + +typedef enum ADCS_camera_select_enum_t { + ADCS_CAMERA_SELECT_1 = 0, + ADCS_CAMERA_SELECT_2 = 1, + ADCS_CAMERA_SELECT_STAR = 2, +} ADCS_camera_select_enum_t; + +typedef enum ADCS_image_size_enum_t { + ADCS_IMAGE_SIZE_1024_X_1024_PX = 0, + ADCS_IMAGE_SIZE_512_X_512_PX = 1, + ADCS_IMAGE_SIZE_256_X_256_PX = 2, + ADCS_IMAGE_SIZE_128_X_128_PX = 3, + ADCS_IMAGE_SIZE_64_X_64_PX = 4, +} ADCS_image_size_enum_t; + +typedef enum ADCS_sd_log_destination_enum_t { + ADCS_SD_LOG_DESTINATION_PRIMARY_SD = 0, + ADCS_SD_LOG_DESTINATION_SECONDARY_SD = 1, +} ADCS_sd_log_destination_enum_t; + +typedef enum ADCS_commissioning_step_enum_t { + ADCS_COMMISISONING_STEP_DETERMINE_INITIAL_ANGULAR_RATES = 1, + ADCS_COMMISISONING_STEP_INITIAL_DETUMBLING = 2, + ADCS_COMMISISONING_STEP_CONTINUED_DETUMBLING_TO_Y_THOMSON = 3, + ADCS_COMMISISONING_STEP_MAGNETOMETER_DEPLOYMENT = 4, + ADCS_COMMISISONING_STEP_MAGNETOMETER_CALIBRATION = 5, + ADCS_COMMISISONING_STEP_ANGULAR_RATE_AND_PITCH_ANGLE_ESTIMATION = 6, + ADCS_COMMISISONING_STEP_Y_WHEEL_RAMP_UP_TEST = 7, + ADCS_COMMISISONING_STEP_INITIAL_Y_MOMENTUM_ACTIVATION = 8, + ADCS_COMMISISONING_STEP_CONTINUED_Y_MOMENTUM_ACTIVATION_AND_MAGNETOMETER_EKF = 9, + ADCS_COMMISISONING_STEP_CUBESENSE_SUN_NADIR = 10, + ADCS_COMMISISONING_STEP_EKF_ACTIVATION_SUN_AND_NADIR = 11, + ADCS_COMMISISONING_STEP_CUBESTAR_STAR_TRACKER = 12, + ADCS_COMMISISONING_STEP_EKF_ACTIVATION_WITH_STAR_VECTOR_MEASUREMENTS = 13, + ADCS_COMMISISONING_STEP_ZERO_BIAS_3_AXIS_REACTION_WHEEL_CONTROL = 14, + ADCS_COMMISISONING_STEP_EKF_WITH_RATE_GYRO_STAR_TRACKER_MEASUREMENTS = 15, + ADCS_COMMISISONING_STEP_SUN_TRACKING_3_AXIS_CONTROL = 16, + ADCS_COMMISISONING_STEP_GROUND_TARGET_TRACKING_CONTROLLER = 17, + ADCS_COMMISISONING_STEP_GPS_RECEIVER = 18 +} ADCS_commissioning_step_enum_t; + +/* Command Structs */ typedef struct ADCS_cmd_ack_struct_t { uint8_t last_id; @@ -240,7 +303,7 @@ typedef struct ADCS_angular_rates_struct_t { typedef struct ADCS_llh_position_struct_t { int32_t latitude_mdeg; int32_t longitude_mdeg; - int32_t altitude_meters; + uint32_t altitude_meters; } ADCS_llh_position_struct_t; typedef struct ADCS_Power_Control_struct_t{ @@ -517,4 +580,103 @@ typedef struct ADCS_measurements_struct_t { int32_t star3_orbit_z_micro; } ADCS_measurements_struct_t; +typedef struct ADCS_acp_execution_state_struct_t { + uint16_t time_since_iteration_start_ms; + ADCS_current_execution_point_enum_t current_execution_point; +} ADCS_acp_execution_state_struct_t; + +typedef struct ADCS_current_state_1_struct_t { + ADCS_estimation_mode_enum_t estimation_mode; + ADCS_control_mode_enum_t control_mode; + ADCS_run_mode_enum_t run_mode; + ADCS_asgp4_mode_enum_t asgp4_mode; + bool cubecontrol_signal_enabled:1; // 1-bit bool + bool cubecontrol_motor_enabled:1; // 1-bit bool + bool cubesense1_enabled:1; // 1-bit bool + bool cubesense2_enabled:1; // 1-bit bool + bool cubewheel1_enabled:1; // 1-bit bool + bool cubewheel2_enabled:1; // 1-bit bool + bool cubewheel3_enabled:1; // 1-bit bool + bool cubestar_enabled:1; // 1-bit bool + bool gps_receiver_enabled:1; // 1-bit bool + bool gps_lna_power_enabled:1; // 1-bit bool + bool motor_driver_enabled:1; // 1-bit bool + bool sun_above_local_horizon:1; // 1-bit bool + bool cubesense1_comm_error:1; // 1-bit bool + bool cubesense2_comm_error:1; // 1-bit bool + bool cubecontrol_signal_comm_error:1; // 1-bit bool + bool cubecontrol_motor_comm_error:1; // 1-bit bool + bool cubewheel1_comm_error:1; // 1-bit bool + bool cubewheel2_comm_error:1; // 1-bit bool + bool cubewheel3_comm_error:1; // 1-bit bool + bool cubestar_comm_error:1; // 1-bit bool + bool magnetometer_range_error:1; // 1-bit bool + bool cam1_sram_overcurrent_detected:1; // 1-bit bool + bool cam1_3v3_overcurrent_detected:1; // 1-bit bool + bool cam1_sensor_busy_error:1; // 1-bit bool + bool cam1_sensor_detection_error:1; // 1-bit bool + bool sun_sensor_range_error:1; // 1-bit bool + bool cam2_sram_overcurrent_detected:1; // 1-bit bool + bool cam2_3v3_overcurrent_detected:1; // 1-bit bool + bool cam2_sensor_busy_error:1; // 1-bit bool + bool cam2_sensor_detection_error:1; // 1-bit bool + bool nadir_sensor_range_error:1; // 1-bit bool + bool rate_sensor_range_error:1; // 1-bit bool + bool wheel_speed_range_error:1; // 1-bit bool + bool coarse_sun_sensor_error:1; // 1-bit bool + bool startracker_match_error:1; // 1-bit bool + bool startracker_overcurrent_detected:1; // 1-bit bool +} ADCS_current_state_1_struct_t; + +typedef struct ADCS_raw_star_tracker_struct_t { + uint8_t num_stars_detected; + uint8_t star_image_noise; + uint8_t invalid_stars; + uint8_t num_stars_identified; + uint8_t identification_mode; + uint8_t image_dark_value; + uint16_t sample_period; + bool image_capture_success:1; // 1-bit bool + bool detection_success:1; // 1-bit bool + bool identification_success:1; // 1-bit bool + bool attitude_success:1; // 1-bit bool + bool processing_time_error:1; // 1-bit bool + bool tracking_module_enabled:1; // 1-bit bool + bool prediction_enabled:1; // 1-bit bool + bool comms_error:1; // 1-bit bool + uint8_t star1_confidence; + uint8_t star2_confidence; + uint8_t star3_confidence; + uint16_t magnitude_star1; + uint16_t magnitude_star2; + uint16_t magnitude_star3; + uint16_t catalogue_star1; + int16_t centroid_x_star1; + int16_t centroid_y_star1; + uint16_t catalogue_star2; + int16_t centroid_x_star2; + int16_t centroid_y_star2; + uint16_t catalogue_star3; + int16_t centroid_x_star3; + int16_t centroid_y_star3; + uint16_t capture_time_ms; + uint16_t detection_time_ms; + uint16_t identification_time_ms; + int32_t x_axis_rate_micro; + int32_t y_axis_rate_micro; + int32_t z_axis_rate_micro; + int32_t q0_micro; + int32_t q1_micro; + int32_t q2_micro; +} ADCS_raw_star_tracker_struct_t; + +typedef struct ADCS_sd_log_config_struct { + uint8_t which_log; + uint8_t log_bitmask[10]; + uint16_t log_period; // TODO: figure out whether this is ms or something else + ADCS_sd_log_destination_enum_t which_sd; +} ADCS_sd_log_config_struct; + +// TODO: We also need to downlink ADCS data from SD card + #endif /* INC_ADCS_TYPES_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h b/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h index cfc631bb8..b2e265c88 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h @@ -47,5 +47,10 @@ uint8_t ADCS_raw_gps_time_struct_TO_json(const ADCS_raw_gps_time_struct_t *data, uint8_t ADCS_raw_gps_struct_TO_json(const ADCS_raw_gps_struct_t *data, char json_output_str[], uint16_t json_output_str_len); uint8_t ADCS_measurements_struct_TO_json(const ADCS_measurements_struct_t *data, char json_output_str[], uint16_t json_output_str_len); uint8_t ADCS_generic_telemetry_uint8_array_TO_json(const uint8_t *data, const uint16_t data_length, char json_output_str[], uint16_t json_output_str_len); +uint8_t ADCS_acp_execution_struct_TO_json(const ADCS_acp_execution_state_struct_t *data, char json_output_str[], uint16_t json_output_str_len); +uint8_t ADCS_current_state_1_struct_TO_json(const ADCS_current_state_1_struct_t *data, char json_output_str[], uint16_t json_output_str_len); +uint8_t ADCS_raw_star_tracker_struct_TO_json(const ADCS_raw_star_tracker_struct_t *data, char json_output_str[], uint16_t json_output_str_len); +uint8_t ADCS_unix_time_ms_TO_json(const uint64_t *data, char json_output_str[], uint16_t json_output_str_len); +uint8_t ADCS_sd_log_config_struct_TO_json(const ADCS_sd_log_config_struct *data, char json_output_str[], uint16_t json_output_str_len); #endif /* INC_ADCS_TYPES_TO_JSON_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/telecommands/telecommand_adcs.h b/firmware/Core/Inc/telecommands/telecommand_adcs.h index cd15a48e2..c6a57c9fa 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -4,9 +4,11 @@ #include #include "telecommands/telecommand_definitions.h" +#include "telecommands/telecommand_executor.h" // if we fail to properly extract a value, we should return the reason for that failure #define ABORT_CMD_FOR_FAILED_EXTRACT(x) uint8_t result = x; if (!(result)) { return result; } +#define CHECK_ADCS_COMMAND_SUCCESS(x) if ((x)) { return x; } uint8_t TCMDEXEC_adcs_reset(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len); @@ -203,4 +205,31 @@ uint8_t TCMDEXEC_adcs_generic_command(const char *args_str, TCMD_TelecommandChan uint8_t TCMDEXEC_adcs_generic_telemetry_request(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len); +uint8_t TCMDEXEC_adcs_acp_execution_state(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_get_current_state_1(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_get_raw_star_tracker_data(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_request_commissioning_telemetry(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_synchronise_unix_time(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_get_current_unix_time(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_set_sd_log_config(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_adcs_get_sd_log_config(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); + #endif // __INCLUDE_GUARD__TELECOMMAND_adcs_H diff --git a/firmware/Core/Inc/telecommands/telecommand_executor.h b/firmware/Core/Inc/telecommands/telecommand_executor.h index 94ffe9bff..d8c8d9041 100644 --- a/firmware/Core/Inc/telecommands/telecommand_executor.h +++ b/firmware/Core/Inc/telecommands/telecommand_executor.h @@ -14,6 +14,10 @@ uint8_t TCMD_add_tcmd_to_agenda(const TCMD_parsed_tcmd_to_execute_t *parsed_tcmd); +uint8_t TCMD_add_delayed_tcmd_to_agenda(const TCMD_parsed_tcmd_to_execute_t *parsed_tcmd, uint32_t time_delay_ms); + +uint8_t TCMD_add_repeated_tcmd_to_agenda(const TCMD_parsed_tcmd_to_execute_t *parsed_tcmd, const uint32_t repeat_period_ms, const uint32_t times_to_repeat); + uint16_t TCMD_get_agenda_used_slots_count(); int16_t TCMD_get_last_tcmd_agenda_slot_sent(); diff --git a/firmware/Core/Inc/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index a70540498..453be6125 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -43,6 +43,12 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_status_struct(); uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_time_struct(); uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_struct(); uint8_t TEST_EXEC__ADCS_pack_to_measurements_struct(); +uint8_t TEST_EXEC__ADCS_pack_to_acp_execution_state_struct(); +uint8_t TEST_EXEC__ADCS_pack_to_current_state_1_struct(); +uint8_t TEST_EXEC__ADCS_pack_to_raw_star_tracker_struct(); +uint8_t TEST_EXEC__ADCS_pack_to_unix_time_ms(); +uint8_t TEST_EXEC__ADCS_pack_to_sd_log_config_struct(); +uint8_t TEST_EXEC__ADCS_convert_double_to_string(); #endif // __INCLUDE_GUARD__ADCS_TEST_PROTOTYPES_H__ diff --git a/firmware/Core/Src/adcs_drivers/adcs_commands.c b/firmware/Core/Src/adcs_drivers/adcs_commands.c index 932e07953..3ff6e0abb 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -11,6 +11,7 @@ #include "adcs_drivers/adcs_types_to_json.h" #include "adcs_drivers/adcs_commands.h" #include "adcs_drivers/adcs_internal_drivers.h" +#include "timekeeping/timekeeping.h" #include #include #include @@ -29,7 +30,7 @@ uint8_t ADCS_cmd_ack(ADCS_cmd_ack_struct_t *ack) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_COMMAND_ACK, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // map temp buffer to Ack struct - ADCS_Pack_to_Ack_Struct(&data_received[0], ack); + ADCS_pack_to_ack_struct(&data_received[0], ack); if (tlm_status == 0) { return ack->error_flag; @@ -57,7 +58,7 @@ uint8_t ADCS_get_identification(ADCS_id_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_IDENTIFICATION, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Identification_Struct(&data_received[0], output_struct); + ADCS_pack_to_identification_struct(&data_received[0], output_struct); return tlm_status; } @@ -71,7 +72,7 @@ uint8_t ADCS_get_program_status(ADCS_boot_running_status_struct_t *output_struct uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_BOOT_RUNNING_PROGRAM_STATUS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); - ADCS_Pack_to_Program_Status_Struct(&data_received[0], output_struct); + ADCS_pack_to_program_status_struct(&data_received[0], output_struct); return tlm_status; } @@ -86,7 +87,7 @@ uint8_t ADCS_get_communication_status(ADCS_comms_status_struct_t *output_struct) uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_SATSTATE_COMM_STATUS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); - ADCS_Pack_to_Comms_Status_Struct(&data_received[0], output_struct); + ADCS_pack_to_comms_status_struct(&data_received[0], output_struct); return tlm_status; } @@ -227,7 +228,7 @@ uint8_t ADCS_get_power_control(ADCS_power_control_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_ADCS_POWER_CONTROL, data_received, data_length, ADCS_INCLUDE_CHECKSUM); - ADCS_Pack_to_Power_Control_Struct(data_received, output_struct); + ADCS_pack_to_power_control_struct(data_received, output_struct); return tlm_status; }/// @brief Instruct the ADCS to set the magnetometer configuration. @@ -315,7 +316,7 @@ uint8_t ADCS_get_estimate_angular_rates(ADCS_angular_rates_struct_t *output_stru uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_ESTIMATED_ANGULAR_RATES, data_received, data_length, ADCS_INCLUDE_CHECKSUM); - ADCS_Pack_to_Angular_Rates_Struct(data_received, output_struct); + ADCS_pack_to_angular_rates_struct(data_received, output_struct); return tlm_status; } @@ -329,7 +330,7 @@ uint8_t ADCS_get_llh_position(ADCS_llh_position_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_SATELLITE_POSITION_LLH, data_received, data_length, ADCS_INCLUDE_CHECKSUM); - ADCS_Pack_to_LLH_Position_Struct(data_received, output_struct); + ADCS_pack_to_llh_position_struct(data_received, output_struct); return tlm_status; } @@ -363,7 +364,7 @@ uint8_t ADCS_get_unix_time_save_mode(ADCS_set_unix_time_save_mode_struct_t *outp uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_GET_UNIX_TIME_SAVE_TO_FLASH, data_received, data_length, ADCS_INCLUDE_CHECKSUM); - ADCS_Pack_to_Unix_Time_Save_Mode_Struct(data_received, output_struct); + ADCS_pack_to_unix_time_save_mode_struct(data_received, output_struct); return tlm_status; } @@ -408,7 +409,7 @@ uint8_t ADCS_get_sgp4_orbit_params(ADCS_orbit_params_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_SGP4_ORBIT_PARAMETERS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Orbit_Params_Struct(data_received, output_struct); + ADCS_pack_to_orbit_params_struct(data_received, output_struct); return tlm_status; } @@ -422,7 +423,7 @@ uint8_t ADCS_get_rate_sensor_rates(ADCS_rated_sensor_rates_struct_t *output_stru uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RATE_SENSOR_RATES, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Rated_Sensor_Rates_Struct(data_received, output_struct); + ADCS_pack_to_rated_sensor_rates_struct(data_received, output_struct); return tlm_status; } @@ -436,7 +437,7 @@ uint8_t ADCS_get_wheel_speed(ADCS_wheel_speed_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_WHEEL_SPEED, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Wheel_Speed_Struct(data_received, output_struct); + ADCS_pack_to_wheel_speed_struct(data_received, output_struct); return tlm_status; } @@ -450,7 +451,7 @@ uint8_t ADCS_get_magnetorquer_command(ADCS_magnetorquer_command_struct_t *output uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_MAGNETORQUER_COMMAND, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Magnetorquer_Command_Struct(data_received, output_struct); + ADCS_pack_to_magnetorquer_command_struct(data_received, output_struct); return tlm_status; } @@ -464,7 +465,7 @@ uint8_t ADCS_get_raw_magnetometer_values(ADCS_raw_magnetometer_values_struct_t * uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_MAGNETOMETER, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_Magnetometer_Values_Struct(data_received, output_struct); + ADCS_pack_to_raw_magnetometer_values_struct(data_received, output_struct); return tlm_status; } @@ -478,7 +479,7 @@ uint8_t ADCS_get_estimate_fine_angular_rates(ADCS_fine_angular_rates_struct_t *o uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_FINE_ESTIMATED_ANGULAR_RATES, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Fine_Angular_Rates_Struct(data_received, output_struct); + ADCS_pack_to_fine_angular_rates_struct(data_received, output_struct); return tlm_status; } @@ -492,7 +493,7 @@ uint8_t ADCS_get_magnetometer_config(ADCS_magnetometer_config_struct_t *output_s uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_MAGNETOMETER_CONFIG, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Magnetometer_Config_Struct(data_received, output_struct); + ADCS_pack_to_magnetometer_config_struct(data_received, output_struct); return tlm_status; } @@ -506,7 +507,7 @@ uint8_t ADCS_get_commanded_attitude_angles(ADCS_commanded_angles_struct_t *outpu uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_COMMANDED_ATTITUDE_ANGLES, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Commanded_Attitude_Angles_Struct(data_received, output_struct); + ADCS_pack_to_commanded_attitude_angles_struct(data_received, output_struct); return tlm_status; } @@ -599,7 +600,7 @@ uint8_t ADCS_get_estimation_params(ADCS_estimation_params_struct_t *output_struc uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_ESTIMATION_PARAMETERS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Estimation_Params_Struct(data_received, output_struct); + ADCS_pack_to_estimation_params_struct(data_received, output_struct); return tlm_status; }/// @brief Set the Augmented SGP4 Parameters of the ADCS. @@ -656,7 +657,7 @@ uint8_t ADCS_get_augmented_sgp4_params(ADCS_augmented_sgp4_params_struct_t *outp uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_AUGMENTED_SGP4_PARAMETERS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Augmented_SGP4_Params_Struct(data_received, output_struct); + ADCS_pack_to_augmented_sgp4_params_struct(data_received, output_struct); return tlm_status; }/// @brief Instruct the ADCS to execute the ADCS_Set_Tracking_Controller_Target_Reference command. @@ -687,7 +688,7 @@ uint8_t ADCS_get_tracking_controller_target_reference(ADCS_tracking_controller_t uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_TRACKING_CONTROLLER_TARGET_REFERENCE, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Tracking_Controller_Target_Reference_Struct(data_received, output_struct); + ADCS_pack_to_tracking_controller_target_reference_struct(data_received, output_struct); return tlm_status; } @@ -727,7 +728,7 @@ uint8_t ADCS_get_rate_gyro_config(ADCS_rate_gyro_config_struct_t *output_struct) uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_GET_RATE_GYRO_CONFIG, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Rate_Gyro_Config_Struct(data_received, output_struct); + ADCS_pack_to_rate_gyro_config_struct(data_received, output_struct); return tlm_status; } @@ -741,7 +742,7 @@ uint8_t ADCS_get_estimated_attitude_angles(ADCS_estimated_attitude_angles_struct uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_ESTIMATED_ATTITUDE_ANGLES, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Estimated_Attitude_Angles_Struct(&data_received[0], output_struct); + ADCS_pack_to_estimated_attitude_angles_struct(&data_received[0], output_struct); return tlm_status; } @@ -755,7 +756,7 @@ uint8_t ADCS_get_magnetic_field_vector(ADCS_magnetic_field_vector_struct_t *outp uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_MAGNETIC_FIELD_VECTOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Magnetic_Field_Vector_Struct(&data_received[0], output_struct); + ADCS_pack_to_magnetic_field_vector_struct(&data_received[0], output_struct); return tlm_status; } @@ -769,7 +770,7 @@ uint8_t ADCS_get_fine_sun_vector(ADCS_fine_sun_vector_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_FINE_SUN_VECTOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Fine_Sun_Vector_Struct(&data_received[0], output_struct); + ADCS_pack_to_fine_sun_vector_struct(&data_received[0], output_struct); return tlm_status; } @@ -783,7 +784,7 @@ uint8_t ADCS_get_nadir_vector(ADCS_nadir_vector_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_NADIR_VECTOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Nadir_Vector_Struct(&data_received[0], output_struct); + ADCS_pack_to_nadir_vector_struct(&data_received[0], output_struct); return tlm_status; } @@ -797,7 +798,7 @@ uint8_t ADCS_get_commanded_wheel_speed(ADCS_wheel_speed_struct_t *output_struct) uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_WHEEL_SPEED_COMMANDS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Commanded_Wheel_Speed_Struct(data_received, output_struct); + ADCS_pack_to_commanded_wheel_speed_struct(data_received, output_struct); return tlm_status; } @@ -811,7 +812,7 @@ uint8_t ADCS_get_igrf_magnetic_field_vector(ADCS_magnetic_field_vector_struct_t uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_IGRF_MODELLED_MAGNETIC_FIELD_VECTOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_IGRF_Magnetic_Field_Vector_Struct(&data_received[0], output_struct); + ADCS_pack_to_igrf_magnetic_field_vector_struct(&data_received[0], output_struct); return tlm_status; } @@ -825,7 +826,7 @@ uint8_t ADCS_get_quaternion_error_vector(ADCS_quaternion_error_vector_struct_t * uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_QUATERNION_ERROR_VECTOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Quaternion_Error_Vector_Struct(&data_received[0], output_struct); + ADCS_pack_to_quaternion_error_vector_struct(&data_received[0], output_struct); return tlm_status; } @@ -839,7 +840,7 @@ uint8_t ADCS_get_estimated_gyro_bias(ADCS_estimated_gyro_bias_struct_t *output_s uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_ESTIMATED_GYRO_BIAS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Estimated_Gyro_Bias_Struct(&data_received[0], output_struct); + ADCS_pack_to_estimated_gyro_bias_struct(&data_received[0], output_struct); return tlm_status; } @@ -853,7 +854,7 @@ uint8_t ADCS_get_estimation_innovation_vector(ADCS_estimation_innovation_vector_ uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_ESTIMATION_INNOVATION_VECTOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Estimation_Innovation_Vector_Struct(&data_received[0], output_struct); + ADCS_pack_to_estimation_innovation_vector_struct(&data_received[0], output_struct); return tlm_status; } @@ -867,7 +868,7 @@ uint8_t ADCS_get_raw_cam1_sensor(ADCS_raw_cam_sensor_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_CAM1_SENSOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_Cam1_Sensor_Struct(&data_received[0], output_struct); + ADCS_pack_to_raw_cam1_sensor_struct(&data_received[0], output_struct); return tlm_status; } @@ -881,7 +882,7 @@ uint8_t ADCS_get_raw_cam2_sensor(ADCS_raw_cam_sensor_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_CAM2_SENSOR, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_Cam2_Sensor_Struct(&data_received[0], output_struct); + ADCS_pack_to_raw_cam2_sensor_struct(&data_received[0], output_struct); return tlm_status; } @@ -895,7 +896,7 @@ uint8_t ADCS_get_raw_coarse_sun_sensor_1_to_6(ADCS_raw_coarse_sun_sensor_1_to_6_ uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_COARSE_SUN_SENSOR_1_TO_6, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_Coarse_Sun_Sensor_1_to_6_Struct(&data_received[0], output_struct); + ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct(&data_received[0], output_struct); return tlm_status; } @@ -909,7 +910,7 @@ uint8_t ADCS_get_raw_coarse_sun_sensor_7_to_10(ADCS_raw_coarse_sun_sensor_7_to_1 uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_COARSE_SUN_SENSOR_7_TO_10, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_Coarse_Sun_Sensor_7_to_10_Struct(&data_received[0], output_struct); + ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct(&data_received[0], output_struct); return tlm_status; } @@ -923,7 +924,7 @@ uint8_t ADCS_get_cubecontrol_current(ADCS_cubecontrol_current_struct_t *output_s uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_CUBECONTROL_CURRENT_MEASUREMENTS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_CubeControl_Current_Struct(&data_received[0], output_struct); + ADCS_pack_to_cubecontrol_current_struct(&data_received[0], output_struct); return tlm_status; } @@ -937,7 +938,7 @@ uint8_t ADCS_get_raw_gps_status(ADCS_raw_gps_status_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_GPS_STATUS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_GPS_Status_Struct(&data_received[0], output_struct); + ADCS_pack_to_raw_gps_status_struct(&data_received[0], output_struct); return tlm_status; } @@ -951,7 +952,7 @@ uint8_t ADCS_get_raw_gps_time(ADCS_raw_gps_time_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_GPS_TIME, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_GPS_Time_Struct(data_received, output_struct); + ADCS_pack_to_raw_gps_time_struct(data_received, output_struct); return tlm_status; } @@ -965,7 +966,7 @@ uint8_t ADCS_get_raw_gps_x(ADCS_raw_gps_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_GPS_X, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_GPS_Struct(ADCS_GPS_AXIS_X, data_received, output_struct); + ADCS_pack_to_raw_gps_struct(ADCS_GPS_AXIS_X, data_received, output_struct); return tlm_status; } @@ -979,7 +980,7 @@ uint8_t ADCS_get_raw_gps_y(ADCS_raw_gps_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_GPS_Y, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_GPS_Struct(ADCS_GPS_AXIS_Y, data_received, output_struct); + ADCS_pack_to_raw_gps_struct(ADCS_GPS_AXIS_Y, data_received, output_struct); return tlm_status; } @@ -993,7 +994,7 @@ uint8_t ADCS_get_raw_gps_z(ADCS_raw_gps_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_GPS_Z, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Raw_GPS_Struct(ADCS_GPS_AXIS_Z, data_received, output_struct); + ADCS_pack_to_raw_gps_struct(ADCS_GPS_AXIS_Z, data_received, output_struct); return tlm_status; } @@ -1007,7 +1008,145 @@ uint8_t ADCS_get_measurements(ADCS_measurements_struct_t *output_struct) { uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_ADCS_MEASUREMENTS, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer - ADCS_Pack_to_Measurements_Struct(data_received, output_struct); + ADCS_pack_to_measurements_struct(data_received, output_struct); return tlm_status; } + +/// @brief Instruct the ADCS to execute the ADCS_execution_state command. +/// @param output_struct Pointer to struct in which to place packed ADCS telemetry data +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_get_acp_execution_state(ADCS_acp_execution_state_struct_t *output_struct) { + uint8_t data_length = 3; + uint8_t data_received[data_length]; // define temp buffer + + uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_EXECUTION_STATE, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer + + ADCS_pack_to_acp_execution_state_struct(data_received, output_struct); + + return tlm_status; +} + +/// @brief Instruct the ADCS to execute the ADCS_get_current_state_1 command. (There's an ADCS_current_state_2 command which is presently not implemented) +/// @param output_struct Pointer to struct in which to place packed ADCS telemetry data +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_get_current_state_1(ADCS_current_state_1_struct_t *output_struct) { + uint8_t data_length = 6; + uint8_t data_received[data_length]; // define temp buffer + + uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_ADCS_STATE, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer + + ADCS_pack_to_current_state_1_struct(data_received, output_struct); + + return tlm_status; +} + +/// @brief Instruct the ADCS to execute the ADCS_get_raw_star_tracker_data command. +/// @param output_struct Pointer to struct in which to place packed ADCS telemetry data +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_get_raw_star_tracker_data(ADCS_raw_star_tracker_struct_t *output_struct) { + uint8_t data_length = 6; + uint8_t data_received[data_length]; // define temp buffer + + uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_CUBEACP_RAW_STAR_TRACKER, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer + + ADCS_pack_to_raw_star_tracker_struct(data_received, output_struct); + + return tlm_status; +} + +/// @brief Instruct the ADCS to save an image to the SD card. +/// @param[in] camera_select Which camera to save the image from; can be Camera 1 (0), Camera 2 (1), or Star (2) +/// @param[in] image_size Resolution of the image to save; can be 1024x1024 (0), 512x512, (1) 256x256, (2) 128x128, (3) or 64x64 (4) +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_save_image_to_sd(ADCS_camera_select_enum_t camera_select, ADCS_image_size_enum_t image_size) { + uint8_t data_send[2] = {camera_select, image_size}; + uint8_t cmd_status = ADCS_i2c_send_command_and_check(ADCS_COMMAND_SAVE_IMAGE, data_send, sizeof(data_send), ADCS_INCLUDE_CHECKSUM); + return cmd_status; +} + +/// @brief Instruct the ADCS to synchronise its Unix epoch time to the current OBC Unix time. +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_synchronise_unix_time() { + uint64_t current_unix_time_ms = TIM_get_current_unix_epoch_time_ms(); + + uint32_t s_component = current_unix_time_ms / 1000; + uint16_t ms_component = current_unix_time_ms % 1000; + + uint8_t data_send[6]; + ADCS_convert_uint32_to_reversed_uint8_array_members(data_send, s_component, 0); + ADCS_convert_uint16_to_reversed_uint8_array_members(data_send, ms_component, 4); + + uint8_t cmd_status = ADCS_i2c_send_command_and_check(ADCS_COMMAND_SET_CURRENT_UNIX_TIME, data_send, sizeof(data_send), ADCS_INCLUDE_CHECKSUM); + return cmd_status; +} + +/// @brief Instruct the ADCS to execute the ADCS_get_current_unix_time command. +/// @param epoch_time_ms Pointer to uint64 to store the time since the Unix epoch in ms, according to the ADCS +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_get_current_unix_time(uint64_t* epoch_time_ms) { + uint8_t data_length = 6; + uint8_t data_received[data_length]; // define temp buffer + + uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(ADCS_TELEMETRY_GET_CURRENT_UNIX_TIME, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer + + ADCS_pack_to_unix_time_ms(data_received, epoch_time_ms); + + return tlm_status; +} + +/// @brief Instruct the ADCS to execute the ADCS_Set_Run_Mode command. +/// @param[in] which_log 1 or 2; which specific log number to log to the SD card +/// @param[in] log_array Pointer to list of bitmasks to set the log config +/// @param[in] log_array_size Number of things to log +/// @param[in] log_period Period to log data to the SD card; if zero, then disable logging +/// @param[in] which_sd Which SD card to log to; 0 for primary, 1 for secondary +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_set_sd_log_config(uint8_t which_log, const uint8_t **log_array, uint8_t log_array_size, uint16_t log_period, ADCS_sd_log_destination_enum_t which_sd) { + uint8_t data_send[13]; + ADCS_combine_sd_log_bitmasks(log_array, log_array_size, data_send); // saves to the first 10 bytes of data_send + ADCS_convert_uint16_to_reversed_uint8_array_members(data_send, log_period, 10); + data_send[12] = which_sd; + + uint8_t command_id; + switch (which_log) { + case 1: + command_id = ADCS_COMMAND_CUBEACP_SET_SD_LOG1_CONFIG; + break; + case 2: + command_id = ADCS_COMMAND_CUBEACP_SET_SD_LOG2_CONFIG; + break; + default: + return 7; // invalid log to log + } + + uint8_t cmd_status = ADCS_i2c_send_command_and_check(command_id, data_send, sizeof(data_send), ADCS_INCLUDE_CHECKSUM); + return cmd_status; +} + +/// @brief Instruct the ADCS to execute the ADCS_get_sd_log_config command. +/// @param[in] config Pointer to struct to store the config data +/// @param[in] which_log 1 or 2; which specific log number to log to the SD card +/// @return 0 if successful, non-zero if a HAL or ADCS error occurred in transmission. +uint8_t ADCS_get_sd_log_config(uint8_t which_log, ADCS_sd_log_config_struct* config) { + uint8_t data_length = 13; + uint8_t data_received[data_length]; // define temp buffer + + uint8_t command_id; + switch (which_log) { + case 1: + command_id = ADCS_TELEMETRY_CUBEACP_GET_SD_LOG1_CONFIG; + break; + case 2: + command_id = ADCS_TELEMETRY_CUBEACP_GET_SD_LOG2_CONFIG; + break; + default: + return 7; // invalid log to log + } + + uint8_t tlm_status = ADCS_i2c_request_telemetry_and_check(command_id, data_received, data_length, ADCS_INCLUDE_CHECKSUM); // populate buffer + + ADCS_pack_to_sd_log_config_struct(data_received, which_log, config); + + return tlm_status; +} \ No newline at end of file diff --git a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c index 61e52231f..0d1a7eb15 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "stm32l4xx_hal.h" @@ -166,6 +167,51 @@ uint8_t ADCS_convert_uint32_to_reversed_uint8_array_members(uint8_t *array, uint return 0; } +/// @brief Convert a double into a string with a given decimal precision. +/// @note This is used because snprintf doesn't support printing doubles. +/// @param[in] input Value to convert. +/// @param[in] precision Number of decimal places to use. +/// @param[out] output_string Character array to write the string number to. +/// @param[in] str_len Length of the output string. +/// @return 0 once complete, 1 if the string is too short, 2 if there was an error printing to the string. +uint8_t ADCS_convert_double_to_string(double input, uint8_t precision, char* output_string, uint16_t str_len) { + if (str_len < 3*precision) { + return 1; + } + + int32_t data_int_portion = (int32_t)(input); + uint32_t data_decimal_portion = (uint32_t)(fabs((input - data_int_portion)) * pow(10, precision)); + + int16_t snprintf_ret; + if (data_int_portion == 0 && input < 0) { + snprintf_ret = snprintf(output_string, str_len, "-%ld.%0*lu", data_int_portion, precision, data_decimal_portion); + } else { + snprintf_ret = snprintf(output_string, str_len, "%ld.%0*lu", data_int_portion, precision, data_decimal_portion); + } + + if (snprintf_ret < 0) { + return 2; + } + + return 0; +} + +/// @brief Take an arbitrary number (up to 63) of 10-byte uint8 arrays and return a single array which is the bitwise OR of all of them. +/// @param[in] array_in Array of pointers to 10-byte uint8 data arrays +/// @param[in] array_in_size Size of the array_in array +/// @param[out] array_out 10-byte uint8 data array to send the result to +/// @return 0 once complete. +uint8_t ADCS_combine_sd_log_bitmasks(const uint8_t **array_in, const uint8_t array_in_size, uint8_t *array_out) { + for (uint8_t i = 0; i < array_in_size; i++) { + for (uint8_t j = 0; j < 10; j++) { + // iterate through array_out and bitwise OR each element with + // the corresponding element in the array array_in[i] + array_out[j] |= array_in[i][j]; + } + } + return 0; +} + static uint8_t CRC8Table[256]; /// @brief Initialise the lookup table for 8-bit CRC calculation. Code provided by ADCS Firmware Reference Manual (p.18-19). diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 1899b8da8..392f13320 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -12,7 +12,7 @@ /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Ack_Struct(uint8_t* data_received, ADCS_cmd_ack_struct_t *result) { +uint8_t ADCS_pack_to_ack_struct(uint8_t* data_received, ADCS_cmd_ack_struct_t *result) { // map temp buffer to Ack struct result->last_id = data_received[0]; @@ -27,7 +27,7 @@ uint8_t ADCS_Pack_to_Ack_Struct(uint8_t* data_received, ADCS_cmd_ack_struct_t *r /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Identification_Struct(uint8_t *data_received, ADCS_id_struct_t *result) { +uint8_t ADCS_pack_to_identification_struct(uint8_t *data_received, ADCS_id_struct_t *result) { result->node_type = data_received[0]; result->interface_version = data_received[1]; result->major_firmware_version = data_received[2]; @@ -41,7 +41,7 @@ uint8_t ADCS_Pack_to_Identification_Struct(uint8_t *data_received, ADCS_id_struc /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Program_Status_Struct(uint8_t* data_received, ADCS_boot_running_status_struct_t *result) { +uint8_t ADCS_pack_to_program_status_struct(uint8_t* data_received, ADCS_boot_running_status_struct_t *result) { // map to struct result->reset_cause = (data_received[0] & 0xF0) >> 4; // takes upper four bits of byte 0 result->boot_cause = data_received[0] & 0x0F; // take upper four bits of byte 0 @@ -57,7 +57,7 @@ uint8_t ADCS_Pack_to_Program_Status_Struct(uint8_t* data_received, ADCS_boot_run /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Comms_Status_Struct(uint8_t *data_received, ADCS_comms_status_struct_t *result) { +uint8_t ADCS_pack_to_comms_status_struct(uint8_t *data_received, ADCS_comms_status_struct_t *result) { result->cmd_counter = data_received[1] << 8 | data_received[0]; // uint16_t result->tlm_counter = data_received[3] << 8 | data_received[2]; // uint16_t // bits we care about: 0b10011000 (the others are for UART and CAN, which we are not using) @@ -71,7 +71,7 @@ uint8_t ADCS_Pack_to_Comms_Status_Struct(uint8_t *data_received, ADCS_comms_stat /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Power_Control_Struct(uint8_t* data_received, ADCS_power_control_struct_t *result) { +uint8_t ADCS_pack_to_power_control_struct(uint8_t* data_received, ADCS_power_control_struct_t *result) { // map to struct; all of these are two-bit enums // within the byte, everything goes in reverse order!! @@ -95,7 +95,7 @@ uint8_t ADCS_Pack_to_Power_Control_Struct(uint8_t* data_received, ADCS_power_con /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Angular_Rates_Struct(uint8_t *data_received, ADCS_angular_rates_struct_t *result) { +uint8_t ADCS_pack_to_angular_rates_struct(uint8_t *data_received, ADCS_angular_rates_struct_t *result) { // values given as int16, deg/s value is raw value * 0.01, give integer as m_deg/s // need to convert to int16 first, then double, to ensure negative numbers are represented correctly result->x_rate_mdeg_per_sec = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; @@ -108,12 +108,12 @@ uint8_t ADCS_Pack_to_Angular_Rates_Struct(uint8_t *data_received, ADCS_angular_r /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_LLH_Position_Struct(uint8_t *data_received, ADCS_llh_position_struct_t *result) { +uint8_t ADCS_pack_to_llh_position_struct(uint8_t *data_received, ADCS_llh_position_struct_t *result) { // formatted value (deg or km) = raw value * 0.01 // need to convert to int16 first, then double, to ensure negative numbers are represented correctly result->latitude_mdeg = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; result->longitude_mdeg = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])) * 10; - result->altitude_meters = (int32_t) ((int16_t) (data_received[5] << 8 | data_received[4])) * 10; + result->altitude_meters = (uint32_t) ((uint16_t) (data_received[5] << 8 | data_received[4])) * 10; return 0; } @@ -121,7 +121,7 @@ uint8_t ADCS_Pack_to_LLH_Position_Struct(uint8_t *data_received, ADCS_llh_positi /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Unix_Time_Save_Mode_Struct(uint8_t *data_received, ADCS_set_unix_time_save_mode_struct_t *result) { +uint8_t ADCS_pack_to_unix_time_save_mode_struct(uint8_t *data_received, ADCS_set_unix_time_save_mode_struct_t *result) { result->save_now = data_received[0] & 0x1; // 0b00000001 result->save_on_update = (data_received[0] & 0x2) >> 1; // 0b00000010 result->save_periodic = (data_received[0] & 0x4) >> 2; // 0b00000100 @@ -133,7 +133,7 @@ uint8_t ADCS_Pack_to_Unix_Time_Save_Mode_Struct(uint8_t *data_received, ADCS_set /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Orbit_Params_Struct(uint8_t *data_received, ADCS_orbit_params_struct_t *result) { +uint8_t ADCS_pack_to_orbit_params_struct(uint8_t *data_received, ADCS_orbit_params_struct_t *result) { memcpy(&result->inclination_deg, &data_received[0], sizeof(double)); memcpy(&result->eccentricity, &data_received[8], sizeof(double)); memcpy(&result->ascending_node_right_ascension_deg, &data_received[16], sizeof(double)); @@ -149,7 +149,7 @@ uint8_t ADCS_Pack_to_Orbit_Params_Struct(uint8_t *data_received, ADCS_orbit_para /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Rated_Sensor_Rates_Struct(uint8_t *data_received, ADCS_rated_sensor_rates_struct_t *result) { +uint8_t ADCS_pack_to_rated_sensor_rates_struct(uint8_t *data_received, ADCS_rated_sensor_rates_struct_t *result) { // formatted value (deg/s) = raw value * 0.01 // need to convert to int16 first, then double, to ensure negative numbers are represented correctly result->x_mdeg_per_sec = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; @@ -162,7 +162,7 @@ uint8_t ADCS_Pack_to_Rated_Sensor_Rates_Struct(uint8_t *data_received, ADCS_rate /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Wheel_Speed_Struct(uint8_t *data_received, ADCS_wheel_speed_struct_t *result) { +uint8_t ADCS_pack_to_wheel_speed_struct(uint8_t *data_received, ADCS_wheel_speed_struct_t *result) { // all values in rpm result->actual_wheel_speed = true; // actual wheel speed result->x_rpm = data_received[1] << 8 | data_received[0]; @@ -175,7 +175,7 @@ uint8_t ADCS_Pack_to_Wheel_Speed_Struct(uint8_t *data_received, ADCS_wheel_speed /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Magnetorquer_Command_Struct(uint8_t *data_received, ADCS_magnetorquer_command_struct_t *result) { +uint8_t ADCS_pack_to_magnetorquer_command_struct(uint8_t *data_received, ADCS_magnetorquer_command_struct_t *result) { // formatted value (sec) = raw value * 0.01 result->x_ms = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; result->y_ms = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])) * 10; @@ -187,7 +187,7 @@ uint8_t ADCS_Pack_to_Magnetorquer_Command_Struct(uint8_t *data_received, ADCS_ma /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_Magnetometer_Values_Struct(uint8_t *data_received, ADCS_raw_magnetometer_values_struct_t *result) { +uint8_t ADCS_pack_to_raw_magnetometer_values_struct(uint8_t *data_received, ADCS_raw_magnetometer_values_struct_t *result) { result->x_raw = data_received[1] << 8 | data_received[0]; result->y_raw = data_received[3] << 8 | data_received[2]; result->z_raw = data_received[5] << 8 | data_received[4]; @@ -198,7 +198,7 @@ uint8_t ADCS_Pack_to_Raw_Magnetometer_Values_Struct(uint8_t *data_received, ADCS /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Fine_Angular_Rates_Struct(uint8_t *data_received, ADCS_fine_angular_rates_struct_t *result) { +uint8_t ADCS_pack_to_fine_angular_rates_struct(uint8_t *data_received, ADCS_fine_angular_rates_struct_t *result) { // formatted value (deg/s) = raw value * 0.001 result->x_mdeg_per_sec = (int16_t) (data_received[1] << 8 | data_received[0]); result->y_mdeg_per_sec = (int16_t) (data_received[3] << 8 | data_received[2]); @@ -210,7 +210,7 @@ uint8_t ADCS_Pack_to_Fine_Angular_Rates_Struct(uint8_t *data_received, ADCS_fine /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Magnetometer_Config_Struct(uint8_t *data_received, ADCS_magnetometer_config_struct_t *result) { +uint8_t ADCS_pack_to_magnetometer_config_struct(uint8_t *data_received, ADCS_magnetometer_config_struct_t *result) { // formatted value for mounting transform angles (deg/s) = raw value * 0.01 result->mounting_transform_alpha_angle_mdeg_per_sec = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; result->mounting_transform_beta_angle_mdeg_per_sec = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])) * 10; @@ -235,7 +235,7 @@ uint8_t ADCS_Pack_to_Magnetometer_Config_Struct(uint8_t *data_received, ADCS_mag /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Commanded_Attitude_Angles_Struct(uint8_t *data_received, ADCS_commanded_angles_struct_t *result) { +uint8_t ADCS_pack_to_commanded_attitude_angles_struct(uint8_t *data_received, ADCS_commanded_angles_struct_t *result) { // Formatted value is obtained using the formula: (formatted value) [deg] = RAWVAL*0.01 result->x_mdeg = ((int16_t)(data_received[1] << 8 | data_received[0])) * 10; result->y_mdeg = ((int16_t)(data_received[3] << 8 | data_received[2])) * 10; @@ -247,7 +247,7 @@ uint8_t ADCS_Pack_to_Commanded_Attitude_Angles_Struct(uint8_t *data_received, AD /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Estimation_Params_Struct(uint8_t* data_received, ADCS_estimation_params_struct_t *result) { +uint8_t ADCS_pack_to_estimation_params_struct(uint8_t* data_received, ADCS_estimation_params_struct_t *result) { // map temp buffer to struct memcpy(&result->magnetometer_rate_filter_system_noise, &data_received[0], 4); memcpy(&result->extended_kalman_filter_system_noise, &data_received[4], 4); @@ -275,7 +275,7 @@ uint8_t ADCS_Pack_to_Estimation_Params_Struct(uint8_t* data_received, ADCS_estim /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Augmented_SGP4_Params_Struct(uint8_t* data_received, ADCS_augmented_sgp4_params_struct_t *result) { +uint8_t ADCS_pack_to_augmented_sgp4_params_struct(uint8_t* data_received, ADCS_augmented_sgp4_params_struct_t *result) { // map temp buffer to struct result->incl_coefficient_milli = (int16_t) (data_received[1] << 8 | data_received[0]); result->raan_coefficient_milli = (int16_t) (data_received[3] << 8 | data_received[2]); @@ -302,7 +302,7 @@ uint8_t ADCS_Pack_to_Augmented_SGP4_Params_Struct(uint8_t* data_received, ADCS_a /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Tracking_Controller_Target_Reference_Struct(uint8_t* data_received, ADCS_tracking_controller_target_struct_t *ref) { +uint8_t ADCS_pack_to_tracking_controller_target_reference_struct(uint8_t* data_received, ADCS_tracking_controller_target_struct_t *ref) { // map temp buffer to struct memcpy(&ref->longitude_degrees, &data_received[0], 4); memcpy(&ref->latitude_degrees, &data_received[4], 4); @@ -315,7 +315,7 @@ uint8_t ADCS_Pack_to_Tracking_Controller_Target_Reference_Struct(uint8_t* data_r /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Rate_Gyro_Config_Struct(uint8_t* data_received, ADCS_rate_gyro_config_struct_t *result) { +uint8_t ADCS_pack_to_rate_gyro_config_struct(uint8_t* data_received, ADCS_rate_gyro_config_struct_t *result) { result->gyro1 = data_received[0]; result->gyro2 = data_received[1]; result->gyro3 = data_received[2]; @@ -334,7 +334,7 @@ uint8_t ADCS_Pack_to_Rate_Gyro_Config_Struct(uint8_t* data_received, ADCS_rate_g /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Estimated_Attitude_Angles_Struct(uint8_t *data_received, ADCS_estimated_attitude_angles_struct_t *angles) { +uint8_t ADCS_pack_to_estimated_attitude_angles_struct(uint8_t *data_received, ADCS_estimated_attitude_angles_struct_t *angles) { angles->estimated_roll_angle_mdeg = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; angles->estimated_pitch_angle_mdeg = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])) * 10; angles->estimated_yaw_angle_mdeg = (int32_t) ((int16_t) (data_received[5] << 8 | data_received[4])) * 10; @@ -345,7 +345,7 @@ uint8_t ADCS_Pack_to_Estimated_Attitude_Angles_Struct(uint8_t *data_received, AD /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Magnetic_Field_Vector_Struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components) { +uint8_t ADCS_pack_to_magnetic_field_vector_struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components) { // gives vector components in nT (10^-9 Teslas) vector_components->x_nT = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; vector_components->y_nT = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])) * 10; @@ -357,7 +357,7 @@ uint8_t ADCS_Pack_to_Magnetic_Field_Vector_Struct(uint8_t *data_received, ADCS_m /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Fine_Sun_Vector_Struct(uint8_t *data_received, ADCS_fine_sun_vector_struct_t *vector_components) { +uint8_t ADCS_pack_to_fine_sun_vector_struct(uint8_t *data_received, ADCS_fine_sun_vector_struct_t *vector_components) { vector_components->x_micro = ((int32_t) ((int16_t) (data_received[1] << 8 | data_received[0]))) * 100; vector_components->y_micro = ((int32_t) ((int16_t) (data_received[3] << 8 | data_received[2]))) * 100; vector_components->z_micro = ((int32_t) ((int16_t) (data_received[5] << 8 | data_received[4]))) * 100; @@ -368,7 +368,7 @@ uint8_t ADCS_Pack_to_Fine_Sun_Vector_Struct(uint8_t *data_received, ADCS_fine_su /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Nadir_Vector_Struct(uint8_t *data_received, ADCS_nadir_vector_struct_t *vector_components) { +uint8_t ADCS_pack_to_nadir_vector_struct(uint8_t *data_received, ADCS_nadir_vector_struct_t *vector_components) { vector_components->x_micro = ((int32_t) ((int16_t) (data_received[1] << 8 | data_received[0]))) * 100; vector_components->y_micro = ((int32_t) ((int16_t) (data_received[3] << 8 | data_received[2]))) * 100; vector_components->z_micro = ((int32_t) ((int16_t) (data_received[5] << 8 | data_received[4]))) * 100; @@ -379,7 +379,7 @@ uint8_t ADCS_Pack_to_Nadir_Vector_Struct(uint8_t *data_received, ADCS_nadir_vect /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Commanded_Wheel_Speed_Struct(uint8_t *data_received, ADCS_wheel_speed_struct_t *result) { +uint8_t ADCS_pack_to_commanded_wheel_speed_struct(uint8_t *data_received, ADCS_wheel_speed_struct_t *result) { // all values in rpm result->actual_wheel_speed = false; // commanded, not actual result->x_rpm = data_received[1] << 8 | data_received[0]; @@ -392,7 +392,7 @@ uint8_t ADCS_Pack_to_Commanded_Wheel_Speed_Struct(uint8_t *data_received, ADCS_w /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_IGRF_Magnetic_Field_Vector_Struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components) { +uint8_t ADCS_pack_to_igrf_magnetic_field_vector_struct(uint8_t *data_received, ADCS_magnetic_field_vector_struct_t *vector_components) { // gives vector components in nT (10^-9 Teslas) vector_components->x_nT = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])) * 10; vector_components->y_nT = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])) * 10; @@ -404,7 +404,7 @@ uint8_t ADCS_Pack_to_IGRF_Magnetic_Field_Vector_Struct(uint8_t *data_received, A /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Quaternion_Error_Vector_Struct(uint8_t *data_received, ADCS_quaternion_error_vector_struct_t *result) { +uint8_t ADCS_pack_to_quaternion_error_vector_struct(uint8_t *data_received, ADCS_quaternion_error_vector_struct_t *result) { result->quaternion_error_q1_micro = ((int32_t) ((int16_t) (data_received[1] << 8 | data_received[0]))) * 100; result->quaternion_error_q2_micro = ((int32_t) ((int16_t) (data_received[3] << 8 | data_received[2]))) * 100; result->quaternion_error_q3_micro = ((int32_t) ((int16_t) (data_received[5] << 8 | data_received[4]))) * 100; @@ -416,7 +416,7 @@ uint8_t ADCS_Pack_to_Quaternion_Error_Vector_Struct(uint8_t *data_received, ADCS /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Estimated_Gyro_Bias_Struct(uint8_t* data_received, ADCS_estimated_gyro_bias_struct_t *result) { +uint8_t ADCS_pack_to_estimated_gyro_bias_struct(uint8_t* data_received, ADCS_estimated_gyro_bias_struct_t *result) { result->estimated_x_gyro_bias_mdeg_per_sec = (int32_t) ((int16_t) (data_received[1] << 8 | data_received[0])); result->estimated_y_gyro_bias_mdeg_per_sec = (int32_t) ((int16_t) (data_received[3] << 8 | data_received[2])); result->estimated_z_gyro_bias_mdeg_per_sec = (int32_t) ((int16_t) (data_received[5] << 8 | data_received[4])); @@ -428,7 +428,7 @@ uint8_t ADCS_Pack_to_Estimated_Gyro_Bias_Struct(uint8_t* data_received, ADCS_est /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Estimation_Innovation_Vector_Struct(uint8_t* data_received, ADCS_estimation_innovation_vector_struct_t *result) { +uint8_t ADCS_pack_to_estimation_innovation_vector_struct(uint8_t* data_received, ADCS_estimation_innovation_vector_struct_t *result) { result->innovation_vector_x_micro = ((int32_t) ((int16_t) (data_received[1] << 8 | data_received[0]))) * 100; result->innovation_vector_y_micro = ((int32_t) ((int16_t) (data_received[3] << 8 | data_received[2]))) * 100; result->innovation_vector_z_micro = ((int32_t) ((int16_t) (data_received[5] << 8 | data_received[4]))) * 100; @@ -440,7 +440,7 @@ uint8_t ADCS_Pack_to_Estimation_Innovation_Vector_Struct(uint8_t* data_received, /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_Cam1_Sensor_Struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result) { +uint8_t ADCS_pack_to_raw_cam1_sensor_struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result) { result->which_sensor = ADCS_WHICH_CAM_SENSOR_CAM1; result->cam_centroid_x = (int16_t) (data_received[1] << 8 | data_received[0]); result->cam_centroid_y = (int16_t) (data_received[3] << 8 | data_received[2]); @@ -454,7 +454,7 @@ uint8_t ADCS_Pack_to_Raw_Cam1_Sensor_Struct(uint8_t* data_received, ADCS_raw_cam /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_Cam2_Sensor_Struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result) { +uint8_t ADCS_pack_to_raw_cam2_sensor_struct(uint8_t* data_received, ADCS_raw_cam_sensor_struct_t *result) { result->which_sensor = ADCS_WHICH_CAM_SENSOR_CAM2; result->cam_centroid_x = (int16_t) (data_received[1] << 8 | data_received[0]); result->cam_centroid_y = (int16_t) (data_received[3] << 8 | data_received[2]); @@ -468,7 +468,7 @@ uint8_t ADCS_Pack_to_Raw_Cam2_Sensor_Struct(uint8_t* data_received, ADCS_raw_cam /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_Coarse_Sun_Sensor_1_to_6_Struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_1_to_6_struct_t *result) { +uint8_t ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_1_to_6_struct_t *result) { result->coarse_sun_sensor_1 = data_received[0]; result->coarse_sun_sensor_2 = data_received[1]; result->coarse_sun_sensor_3 = data_received[2]; @@ -483,7 +483,7 @@ uint8_t ADCS_Pack_to_Raw_Coarse_Sun_Sensor_1_to_6_Struct(uint8_t* data_received, /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_Coarse_Sun_Sensor_7_to_10_Struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_7_to_10_struct_t *result) { +uint8_t ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct(uint8_t* data_received, ADCS_raw_coarse_sun_sensor_7_to_10_struct_t *result) { result->coarse_sun_sensor_7 = data_received[0]; result->coarse_sun_sensor_8 = data_received[1]; result->coarse_sun_sensor_9 = data_received[2]; @@ -496,7 +496,7 @@ uint8_t ADCS_Pack_to_Raw_Coarse_Sun_Sensor_7_to_10_Struct(uint8_t* data_received /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_CubeControl_Current_Struct(uint8_t* data_received, ADCS_cubecontrol_current_struct_t *result) { +uint8_t ADCS_pack_to_cubecontrol_current_struct(uint8_t* data_received, ADCS_cubecontrol_current_struct_t *result) { // everything in mA after multiplying RAWVAL*0.48828125 (aka dividing by 2.048 exactly) result->cubecontrol_3v3_current_mA = (( double ) ((uint16_t) (data_received[1] << 8 | data_received[0]))) / 2.048; result->cubecontrol_5v_current_mA = (( double ) ((uint16_t) (data_received[3] << 8 | data_received[2]))) / 2.048; @@ -509,7 +509,7 @@ uint8_t ADCS_Pack_to_CubeControl_Current_Struct(uint8_t* data_received, ADCS_cub /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_GPS_Status_Struct(uint8_t* data_received, ADCS_raw_gps_status_struct_t *result) { +uint8_t ADCS_pack_to_raw_gps_status_struct(uint8_t* data_received, ADCS_raw_gps_status_struct_t *result) { result->gps_solution_status = (ADCS_gps_solution_status_enum_t) data_received[0]; result->num_tracked_satellites = data_received[1]; result->num_used_satellites = data_received[2]; @@ -524,7 +524,7 @@ uint8_t ADCS_Pack_to_Raw_GPS_Status_Struct(uint8_t* data_received, ADCS_raw_gps_ /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_GPS_Time_Struct(uint8_t* data_received, ADCS_raw_gps_time_struct_t *result) { +uint8_t ADCS_pack_to_raw_gps_time_struct(uint8_t* data_received, ADCS_raw_gps_time_struct_t *result) { result->gps_reference_week = (uint16_t)(data_received[1] << 8 | data_received[0]); result->gps_time_ms = (uint32_t) (data_received[5] << 24 | data_received[4] << 16 | data_received[3] << 8 | data_received[2]); @@ -535,7 +535,7 @@ uint8_t ADCS_Pack_to_Raw_GPS_Time_Struct(uint8_t* data_received, ADCS_raw_gps_ti /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Raw_GPS_Struct(ADCS_gps_axis_enum_t axis, uint8_t *data_received, ADCS_raw_gps_struct_t *result) { +uint8_t ADCS_pack_to_raw_gps_struct(ADCS_gps_axis_enum_t axis, uint8_t *data_received, ADCS_raw_gps_struct_t *result) { result->axis = axis; // this function works for three commands, so we need to keep this information result->ecef_position_meters = (int32_t) (data_received[3] << 24 | data_received[2] << 16 | data_received[1] << 8 | data_received[0]); // ECEF Position Z [m] @@ -548,7 +548,7 @@ uint8_t ADCS_Pack_to_Raw_GPS_Struct(ADCS_gps_axis_enum_t axis, uint8_t *data_rec /// @param[in] data_received Raw data bytes obtained from the ADCS over I2C. /// @param[out] result Structure containing the formated data for this command. /// @return 0 once the function is finished running. -uint8_t ADCS_Pack_to_Measurements_Struct(uint8_t* telemetry_data, ADCS_measurements_struct_t *measurements) { +uint8_t ADCS_pack_to_measurements_struct(uint8_t* telemetry_data, ADCS_measurements_struct_t *measurements) { // Parse each telemetry entry according to Table 150 in the Firmware Reference Manual measurements->magnetic_field_x_nT = (int32_t)((int16_t)(telemetry_data[1] << 8 | telemetry_data[0])) * 10; @@ -588,5 +588,128 @@ uint8_t ADCS_Pack_to_Measurements_Struct(uint8_t* telemetry_data, ADCS_measureme measurements->star3_orbit_y_micro = (int32_t)((int16_t)(telemetry_data[69] << 8 | telemetry_data[68])) * 100; measurements->star3_orbit_z_micro = (int32_t)((int16_t)(telemetry_data[71] << 8 | telemetry_data[70])) * 100; + return 0; +} + +uint8_t ADCS_pack_to_acp_execution_state_struct(uint8_t* data_received, ADCS_acp_execution_state_struct_t* output_struct) { + output_struct->time_since_iteration_start_ms = (uint16_t)(data_received[1] << 8 | data_received[0]); + output_struct->current_execution_point = (ADCS_current_execution_point_enum_t) data_received[2]; + return 0; +} + +uint8_t ADCS_pack_to_current_state_1_struct(uint8_t* data_received, ADCS_current_state_1_struct_t* output_struct) { + + output_struct->estimation_mode = (data_received[0] >> 4) & 0xf; + + output_struct->control_mode = (data_received[0]) & 0xf; + + output_struct->run_mode = (data_received[1]) & 0x3; + output_struct->asgp4_mode = (data_received[1] >> 2) & 0x3; + output_struct->cubecontrol_signal_enabled = (data_received[1] >> 4) & 0x01; // 1-bit bool + output_struct->cubecontrol_motor_enabled = (data_received[1] >> 5) & 0x01; // 1-bit bool + output_struct->cubesense1_enabled = (data_received[1] >> 6) & 0x01; // 1-bit bool + output_struct->cubesense2_enabled = (data_received[1] >> 7) & 0x01; // 1-bit bool + + output_struct->cubewheel1_enabled = (data_received[2]) & 0x01; // 1-bit bool + output_struct->cubewheel2_enabled = (data_received[2] >> 1) & 0x01; // 1-bit bool + output_struct->cubewheel3_enabled = (data_received[2] >> 2) & 0x01; // 1-bit bool + output_struct->cubestar_enabled = (data_received[2] >> 3) & 0x01; // 1-bit bool + output_struct->gps_receiver_enabled = (data_received[2] >> 4) & 0x01; // 1-bit bool + output_struct->gps_lna_power_enabled = (data_received[2] >> 5) & 0x01; // 1-bit bool + output_struct->motor_driver_enabled = (data_received[2] >> 6) & 0x01; // 1-bit bool + output_struct->sun_above_local_horizon = (data_received[2] >> 7) & 0x01; // 1-bit bool + + output_struct->cubesense1_comm_error = (data_received[3]) & 0x01; // 1-bit bool + output_struct->cubesense2_comm_error = (data_received[3] >> 1) & 0x01; // 1-bit bool + output_struct->cubecontrol_signal_comm_error = (data_received[3] >> 2) & 0x01; // 1-bit bool + output_struct->cubecontrol_motor_comm_error = (data_received[3] >> 3) & 0x01; // 1-bit bool + output_struct->cubewheel1_comm_error = (data_received[3] >> 4) & 0x01; // 1-bit bool + output_struct->cubewheel2_comm_error = (data_received[3] >> 5) & 0x01; // 1-bit bool + output_struct->cubewheel3_comm_error = (data_received[3] >> 6) & 0x01; // 1-bit bool + output_struct->cubestar_comm_error = (data_received[3] >> 7) & 0x01; // 1-bit bool + + output_struct->magnetometer_range_error = (data_received[4]) & 0x01; // 1-bit bool + output_struct->cam1_sram_overcurrent_detected = (data_received[4] >> 1) & 0x01; // 1-bit bool + output_struct->cam1_3v3_overcurrent_detected = (data_received[4] >> 2) & 0x01; // 1-bit bool + output_struct->cam1_sensor_busy_error = (data_received[4] >> 3) & 0x01; // 1-bit bool + output_struct->cam1_sensor_detection_error = (data_received[4] >> 4) & 0x01; // 1-bit bool + output_struct->sun_sensor_range_error = (data_received[4] >> 5) & 0x01; // 1-bit bool + output_struct->cam2_sram_overcurrent_detected = (data_received[4] >> 6) & 0x01; // 1-bit bool + output_struct->cam2_3v3_overcurrent_detected = (data_received[4] >> 7) & 0x01; // 1-bit bool + + output_struct->cam2_sensor_busy_error = (data_received[5]) & 0x01; // 1-bit bool + output_struct->cam2_sensor_detection_error = (data_received[5] >> 1) & 0x01; // 1-bit bool + output_struct->nadir_sensor_range_error = (data_received[5] >> 2) & 0x01; // 1-bit bool + output_struct->rate_sensor_range_error = (data_received[5] >> 3) & 0x01; // 1-bit bool + output_struct->wheel_speed_range_error = (data_received[5] >> 4) & 0x01; // 1-bit bool + output_struct->coarse_sun_sensor_error = (data_received[5] >> 5) & 0x01; // 1-bit bool + output_struct->startracker_match_error = (data_received[5] >> 6) & 0x01; // 1-bit bool + output_struct->startracker_overcurrent_detected = (data_received[5] >> 7) & 0x01; // 1-bit bool + + return 0; +} + +uint8_t ADCS_pack_to_raw_star_tracker_struct(uint8_t *input_data, ADCS_raw_star_tracker_struct_t *output_data) { + + output_data->num_stars_detected = input_data[0]; + output_data->star_image_noise = input_data[1]; + output_data->invalid_stars = input_data[2]; + output_data->num_stars_identified = input_data[3]; + output_data->identification_mode = input_data[4]; + output_data->image_dark_value = input_data[5]; + output_data->image_capture_success = input_data[6] & 0x01; + output_data->detection_success = (input_data[6] >> 1) & 0x01; + output_data->identification_success = (input_data[6] >> 2) & 0x01; + output_data->attitude_success = (input_data[6] >> 3) & 0x01; + output_data->processing_time_error = (input_data[6] >> 4) & 0x01; + output_data->tracking_module_enabled = (input_data[6] >> 5) & 0x01; + output_data->prediction_enabled = (input_data[6] >> 6) & 0x01; + output_data->comms_error = (input_data[6] >> 7) & 0x01; + output_data->sample_period = (input_data[8] << 8) | input_data[7]; + output_data->star1_confidence = input_data[9]; + output_data->star2_confidence = input_data[10]; + output_data->star3_confidence = input_data[11]; + output_data->magnitude_star1 = (input_data[13] << 8) | input_data[12]; + output_data->magnitude_star2 = (input_data[15] << 8) | input_data[14]; + output_data->magnitude_star3 = (input_data[17] << 8) | input_data[16]; + output_data->catalogue_star1 = (input_data[19] << 8) | input_data[18]; + output_data->centroid_x_star1 = (input_data[21] << 8) | input_data[20]; + output_data->centroid_y_star1 = (input_data[23] << 8) | input_data[22]; + output_data->catalogue_star2 = (input_data[25] << 8) | input_data[24]; + output_data->centroid_x_star2 = (input_data[27] << 8) | input_data[26]; + output_data->centroid_y_star2 = (input_data[29] << 8) | input_data[28]; + output_data->catalogue_star3 = (input_data[31] << 8) | input_data[30]; + output_data->centroid_x_star3 = (input_data[33] << 8) | input_data[32]; + output_data->centroid_y_star3 = (input_data[35] << 8) | input_data[34]; + output_data->capture_time_ms = (input_data[37] << 8) | input_data[36]; + output_data->detection_time_ms = (input_data[39] << 8) | input_data[38]; + output_data->identification_time_ms = (input_data[41] << 8) | input_data[40]; + output_data->x_axis_rate_micro = (int32_t) ((int16_t) ((input_data[43] << 8) | input_data[42])) * 100; + output_data->y_axis_rate_micro = (int32_t) ((int16_t) ((input_data[45] << 8) | input_data[44])) * 100; + output_data->z_axis_rate_micro = (int32_t) ((int16_t) ((input_data[47] << 8) | input_data[46])) * 100; + output_data->q0_micro = (int32_t) ((int16_t) ((input_data[49] << 8) | input_data[48])) * 100; + output_data->q1_micro = (int32_t) ((int16_t) ((input_data[51] << 8) | input_data[50])) * 100; + output_data->q2_micro = (int32_t) ((int16_t) ((input_data[53] << 8) | input_data[52])) * 100; + + return 0; +} + +uint8_t ADCS_pack_to_unix_time_ms(uint8_t *data_received, uint64_t *output_data) { + + // use ULL to perform unsigned, not signed, multiplication + *output_data = ((data_received[3] << 24 | data_received[2] << 16 | data_received[1] << 8 | data_received[0]) * 1000ULL) + ((data_received[5] << 8) | data_received[4]); + return 0; + +} + +uint8_t ADCS_pack_to_sd_log_config_struct(uint8_t *data_received, uint8_t which_log, ADCS_sd_log_config_struct *config) { + + for (uint8_t i = 0; i < 10; i++) { + (config->log_bitmask)[i] = data_received[i]; + } + config->which_log = which_log; + config->log_period = (data_received[11] << 8) | data_received[10]; + config->which_sd = data_received[12]; + return 0; } \ No newline at end of file diff --git a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c index fab666711..4dcdedf71 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -6,7 +6,7 @@ #include #include #include - +#include #include #include #include @@ -195,12 +195,33 @@ uint8_t ADCS_set_unix_time_save_mode_struct_TO_json(const ADCS_set_unix_time_sav /// @param[in] json_output_str_len Length of the JSON output buffer. /// @return 0 if successful, 1 for invalid input, 2 for snprintf encoding error, 3 for too short string buffer uint8_t ADCS_orbit_params_struct_TO_json(const ADCS_orbit_params_struct_t *data, char json_output_str[], uint16_t json_output_str_len) { - if (data == NULL || json_output_str == NULL || json_output_str_len < 256) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 257) { return 1; // Error: invalid input } - int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, "{\"inclination_deg\":%.6f,\"eccentricity\":%.6f,\"ascending_node_right_ascension_deg\":%.6f,\"perigee_argument_deg\":%.6f,\"b_star_drag_term\":%.6f,\"mean_motion_orbits_per_day\":%.6f,\"mean_anomaly_deg\":%.6f,\"epoch_year_point_day\":%.6f}", - data->inclination_deg, data->eccentricity, data->ascending_node_right_ascension_deg, data->perigee_argument_deg, data->b_star_drag_term, data->mean_motion_orbits_per_day, data->mean_anomaly_deg, data->epoch_year_point_day); - + + // snprintf doesn't support printing floats, so we convert them separately + + char inclination_deg_str[20]; + char eccentricity_str[20]; + char ascending_node_right_ascension_deg_str[20]; + char perigee_argument_deg_str[20]; + char b_star_drag_term_str[20]; + char mean_motion_orbits_per_day_str[20]; + char mean_anomaly_deg_str[20]; + char epoch_year_point_day_str[20]; + + ADCS_convert_double_to_string(data->inclination_deg, 6, &inclination_deg_str[0], 20); + ADCS_convert_double_to_string(data->eccentricity, 6, &eccentricity_str[0], 20); + ADCS_convert_double_to_string(data->ascending_node_right_ascension_deg, 6, &ascending_node_right_ascension_deg_str[0], 20); + ADCS_convert_double_to_string(data->perigee_argument_deg, 6, &perigee_argument_deg_str[0], 20); + ADCS_convert_double_to_string(data->b_star_drag_term, 6, &b_star_drag_term_str[0], 20); + ADCS_convert_double_to_string(data->mean_motion_orbits_per_day, 6, &mean_motion_orbits_per_day_str[0], 20); + ADCS_convert_double_to_string(data->mean_anomaly_deg, 6, &mean_anomaly_deg_str[0], 20); + ADCS_convert_double_to_string(data->epoch_year_point_day, 6, &epoch_year_point_day_str[0], 20); + + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, "{\"inclination_deg\":%s,\"eccentricity\":%s,\"ascending_node_right_ascension_deg\":%s,\"perigee_argument_deg\":%s,\"b_star_drag_term\":%s,\"mean_motion_orbits_per_day\":%s,\"mean_anomaly_deg\":%s,\"epoch_year_point_day\":%s}", + inclination_deg_str, eccentricity_str, ascending_node_right_ascension_deg_str, perigee_argument_deg_str, b_star_drag_term_str, mean_motion_orbits_per_day_str, mean_anomaly_deg_str, epoch_year_point_day_str); + if (snprintf_ret < 0) { return 2; // Error: snprintf encoding error } @@ -479,13 +500,25 @@ uint8_t ADCS_augmented_sgp4_params_struct_TO_json(const ADCS_augmented_sgp4_para /// @param[in] json_output_str_len Length of the JSON output buffer. /// @return 0 if successful, 1 for invalid input, 2 for snprintf encoding error, 3 for too short string buffer uint8_t ADCS_tracking_controller_target_struct_TO_json(const ADCS_tracking_controller_target_struct_t *data, char json_output_str[], uint16_t json_output_str_len) { - if (data == NULL || json_output_str == NULL || json_output_str_len < 40) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 90) { return 1; // Error: invalid input } - // 4 decimals in %.4f longitude and latitude gives within roughly 11 m + + // snprintf doesn't support printing floats, so convert them separately + + char longitude_string[20]; + char latitude_string[20]; + char altitude_string[20]; + + ADCS_convert_double_to_string(data->longitude_degrees, 4, &longitude_string[0], 20); + ADCS_convert_double_to_string(data->latitude_degrees, 4, &latitude_string[0], 20); + ADCS_convert_double_to_string(data->altitude_meters, 4, &altitude_string[0], 20); + + + // 4 decimals in %.4f longitude and latitude gives within roughly 11 m int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, - "{\"lon\":%.4f,\"lat\":%.4f,\"alt\":%.4f}", - data->longitude_degrees, data->latitude_degrees, data->altitude_meters); + "{\"lon\":%s,\"lat\":%s,\"alt\":%s}", + longitude_string, latitude_string, altitude_string); if (snprintf_ret < 0) { return 2; // Error: snprintf encoding error @@ -774,16 +807,25 @@ uint8_t ADCS_raw_coarse_sun_sensor_7_to_10_struct_TO_json(const ADCS_raw_coarse_ /// @param[in] json_output_str_len Length of the JSON output buffer. /// @return 0 if successful, 1 for invalid input, 2 for snprintf encoding error, 3 for too short string buffer uint8_t ADCS_cubecontrol_current_struct_TO_json(const ADCS_cubecontrol_current_struct_t *data, char json_output_str[], uint16_t json_output_str_len) { - if (data == NULL || json_output_str == NULL || json_output_str_len < 117) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 118) { return 1; // Error: invalid input } + + // snprintf doesn't support printing floats, so convert them separately + + char three_volt_current_string[20]; + char five_volt_current_string[20]; + char vbat_current_string[20]; + + ADCS_convert_double_to_string(data->cubecontrol_3v3_current_mA, 1, &three_volt_current_string[0], 20); + ADCS_convert_double_to_string(data->cubecontrol_5v_current_mA, 1, &five_volt_current_string[0], 20); + ADCS_convert_double_to_string(data->cubecontrol_vbat_current_mA, 1, &vbat_current_string[0], 20); + // measured up to 0.1 mA (100 uA); current measured in 0.48828125 mA steps int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, - "{\"cubecontrol_3v3_current_mA\":%.1f,\"cubecontrol_5v_current_mA\":%.1f," - "\"cubecontrol_vbat_current_mA\":%.1f}", - data->cubecontrol_3v3_current_mA, data->cubecontrol_5v_current_mA, - data->cubecontrol_vbat_current_mA); - + "{\"cubecontrol_3v3_current_mA\":%s,\"cubecontrol_5v_current_mA\":%s," + "\"cubecontrol_vbat_current_mA\":%s}", + three_volt_current_string, five_volt_current_string, vbat_current_string); if (snprintf_ret < 0) { return 2; // Error: snprintf encoding error } @@ -957,5 +999,177 @@ uint8_t ADCS_generic_telemetry_uint8_array_TO_json(const uint8_t *data, const ui return 3; // Error: string buffer too short } } + return 0; +} + +/// @brief Converts ADCS_acp_execution_struct to a JSON string. +/// @param[in] data Pointer to the ADCS_acp_execution_struct. +/// @param[out] json_output_str Buffer to hold the JSON string. +/// @param[in] json_output_str_len Length of the JSON output buffer. +/// @return 0 if successful, 1 for invalid input, 2 for snprintf encoding error, 3 for too short string buffer +uint8_t ADCS_acp_execution_struct_TO_json(const ADCS_acp_execution_state_struct_t *data, char json_output_str[], uint16_t json_output_str_len) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 80) { + return 1; // Error: invalid input + } + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, + "{\"time_since_iteration_start_ms\":%d,\"current_execution_point\":%d}", + data->time_since_iteration_start_ms, data->current_execution_point); + + if (snprintf_ret < 0) { + return 2; // Error: snprintf encoding error + } + if (snprintf_ret >= json_output_str_len) { + return 3; // Error: string buffer too short + } + + return 0; +} + +/// @brief Converts ADCS_current_state_1_struct to a JSON string. +/// @param[in] data Pointer to the ADCS_current_state_1_struct. +/// @param[out] json_output_str Buffer to hold the JSON string. +/// @param[in] json_output_str_len Length of the JSON output buffer. +/// @return 0 if successful, 1 for invalid input, 2 for snprintf encoding error, 3 for too short string buffer +uint8_t ADCS_current_state_1_struct_TO_json(const ADCS_current_state_1_struct_t *data, char json_output_str[], uint16_t json_output_str_len) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 80) { + return 1; // Error: invalid input + } + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, + "{\"attitude_estimation_mode\":%d,\"control_mode\":%d," + "\"adcs_run_mode\":%d,\"asgp4_mode\":%d," + "\"cubecontrol_signal_enabled\":%d,\"cubecontrol_motor_enabled\":%d," + "\"cubesense1_enabled\":%d,\"cubesense2_enabled\":%d," + "\"cubewheel1_enabled\":%d,\"cubewheel2_enabled\":%d," + "\"cubewheel3_enabled\":%d,\"cubestar_enabled\":%d," + "\"gps_receiver_enabled\":%d,\"gps_lna_power_enabled\":%d," + "\"motor_driver_enabled\":%d,\"sun_above_local_horizon\":%d," + "\"cubesense1_comm_error\":%d,\"cubesense2_comm_error\":%d," + "\"cubecontrol_signal_comm_error\":%d,\"cubecontrol_motor_comm_error\":%d," + "\"cubewheel1_comm_error\":%d,\"cubewheel2_comm_error\":%d," + "\"cubewheel3_comm_error\":%d,\"cubestar_comm_error\":%d," + "\"magnetometer_range_error\":%d,\"cam1_sram_overcurrent_detected\":%d," + "\"cam1_3v3_overcurrent_detected\":%d,\"cam1_sensor_busy_error\":%d," + "\"cam1_sensor_detection_error\":%d,\"sun_sensor_range_error\":%d," + "\"cam2_sram_overcurrent_detected\":%d,\"cam2_3v3_overcurrent_detected\":%d," + "\"cam2_sensor_busy_error\":%d,\"cam2_sensor_detection_error\":%d," + "\"nadir_sensor_range_error\":%d,\"rate_sensor_range_error\":%d," + "\"wheel_speed_range_error\":%d,\"coarse_sun_sensor_error\":%d," + "\"startracker_match_error\":%d,\"startracker_overcurrent_detected\":%d}", + data->estimation_mode, data->control_mode, + data->run_mode, data->asgp4_mode, + data->cubecontrol_signal_enabled, data->cubecontrol_motor_enabled, + data->cubesense1_enabled, data->cubesense2_enabled, + data->cubewheel1_enabled, data->cubewheel2_enabled, + data->cubewheel3_enabled, data->cubestar_enabled, + data->gps_receiver_enabled, data->gps_lna_power_enabled, + data->motor_driver_enabled, data->sun_above_local_horizon, + data->cubesense1_comm_error, data->cubesense2_comm_error, + data->cubecontrol_signal_comm_error, data->cubecontrol_motor_comm_error, + data->cubewheel1_comm_error, data->cubewheel2_comm_error, + data->cubewheel3_comm_error, data->cubestar_comm_error, + data->magnetometer_range_error, data->cam1_sram_overcurrent_detected, + data->cam1_3v3_overcurrent_detected, data->cam1_sensor_busy_error, + data->cam1_sensor_detection_error, data->sun_sensor_range_error, + data->cam2_sram_overcurrent_detected, data->cam2_3v3_overcurrent_detected, + data->cam2_sensor_busy_error, data->cam2_sensor_detection_error, + data->nadir_sensor_range_error, data->rate_sensor_range_error, + data->wheel_speed_range_error, data->coarse_sun_sensor_error, + data->startracker_match_error, data->startracker_overcurrent_detected); + + if (snprintf_ret < 0) { + return 2; // Error: snprintf encoding error + } + if (snprintf_ret >= json_output_str_len) { + return 3; // Error: string buffer too short + } + + return 0; +} + +uint8_t ADCS_raw_star_tracker_struct_TO_json(const ADCS_raw_star_tracker_struct_t *data, char json_output_str[], uint16_t json_output_str_len) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 1400) { + return 1; // Error: invalid input or too short buffer + } + + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, + "{\"num_stars_detected\":%u,\"star_image_noise\":%u,\"invalid_stars\":%u," + "\"num_stars_identified\":%u,\"identification_mode\":%u,\"image_dark_value\":%u," + "\"image_capture_success\":%s,\"detection_success\":%s,\"identification_success\":%s," + "\"attitude_success\":%s,\"processing_time_error\":%s,\"tracking_module_enabled\":%s," + "\"prediction_enabled\":%s,\"comms_error\":%s,\"sample_period\":%u," + "\"star1_confidence\":%u,\"star2_confidence\":%u,\"star3_confidence\":%u," + "\"magnitude_star1\":%u,\"magnitude_star2\":%u,\"magnitude_star3\":%u," + "\"catalogue_star1\":%u,\"centroid_x_star1\":%d,\"centroid_y_star1\":%d," + "\"catalogue_star2\":%u,\"centroid_x_star2\":%d,\"centroid_y_star2\":%d," + "\"catalogue_star3\":%u,\"centroid_x_star3\":%d,\"centroid_y_star3\":%d," + "\"capture_time_ms\":%u,\"detection_time_ms\":%u,\"identification_time_ms\":%u," + "\"x_axis_rate_micro\":%ld,\"y_axis_rate_micro\":%ld,\"z_axis_rate_micro\":%ld," + "\"q0_micro\":%ld,\"q1_micro\":%ld,\"q2_micro\":%ld}", + data->num_stars_detected, data->star_image_noise, data->invalid_stars, + data->num_stars_identified, data->identification_mode, data->image_dark_value, + data->image_capture_success ? "true" : "false", data->detection_success ? "true" : "false", + data->identification_success ? "true" : "false", data->attitude_success ? "true" : "false", + data->processing_time_error ? "true" : "false", data->tracking_module_enabled ? "true" : "false", + data->prediction_enabled ? "true" : "false", data->comms_error ? "true" : "false", + data->sample_period, data->star1_confidence, data->star2_confidence, data->star3_confidence, + data->magnitude_star1, data->magnitude_star2, data->magnitude_star3, data->catalogue_star1, + data->centroid_x_star1, data->centroid_y_star1, data->catalogue_star2, data->centroid_x_star2, + data->centroid_y_star2, data->catalogue_star3, data->centroid_x_star3, data->centroid_y_star3, + data->capture_time_ms, data->detection_time_ms, data->identification_time_ms, + data->x_axis_rate_micro, data->y_axis_rate_micro, data->z_axis_rate_micro, data->q0_micro, data->q1_micro, data->q2_micro); + + if (snprintf_ret < 0) { + return 2; // Error: snprintf encoding error + } + if (snprintf_ret >= json_output_str_len) { + return 3; // Error: string buffer too short + } + + return 0; +} + +uint8_t ADCS_unix_time_ms_TO_json(const uint64_t *data, char json_output_str[], uint16_t json_output_str_len) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 50) { + return 1; // Error: invalid input or too short buffer + } + + uint16_t ms = *data % 1000; + const time_t time_s = *data / 1000; + struct tm time_struct; + char buf[80]; + + // Format time, "ddd yyyy-mm-dd hh:mm:ss" + time_struct = *localtime(&time_s); + strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S", &time_struct); + + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len,"{\"current_adcs_unix_time\":%s.%d}",buf, ms); + + if (snprintf_ret < 0) { + return 2; // Error: snprintf encoding error + } + if (snprintf_ret >= json_output_str_len) { + return 3; // Error: string buffer too short + } + + return 0; +} + +uint8_t ADCS_sd_log_config_struct_TO_json(const ADCS_sd_log_config_struct *data, char json_output_str[], uint16_t json_output_str_len) { + if (data == NULL || json_output_str == NULL || json_output_str_len < 150) { + return 1; // Error: invalid input + } + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, + "{\"which_log\":%d,\"log_bitmask\":0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x,\"log_period\":%d,\"which_sd\":%d}", + data->which_log, (data->log_bitmask)[0], (data->log_bitmask)[1], (data->log_bitmask)[2], (data->log_bitmask)[3], + (data->log_bitmask)[4], (data->log_bitmask)[5], (data->log_bitmask)[6], (data->log_bitmask)[7], (data->log_bitmask)[8], + (data->log_bitmask)[9], data->log_period, data->which_sd); + + if (snprintf_ret < 0) { + return 2; // Error: snprintf encoding error + } + if (snprintf_ret >= json_output_str_len) { + return 3; // Error: string buffer too short + } + return 0; } \ No newline at end of file diff --git a/firmware/Core/Src/telecommands/telecommand_adcs.c b/firmware/Core/Src/telecommands/telecommand_adcs.c index c8f8e7a16..03f25d374 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -2,6 +2,7 @@ #include "telecommands/telecommand_args_helpers.h" #include "transforms/arrays.h" #include "unit_tests/unit_test_executor.h" +#include "timekeeping/timekeeping.h" #include #include @@ -10,6 +11,7 @@ #include "adcs_drivers/adcs_types.h" #include "adcs_drivers/adcs_commands.h" +#include "adcs_drivers/adcs_command_ids.h" #include "adcs_drivers/adcs_struct_packers.h" #include "adcs_drivers/adcs_types_to_json.h" @@ -259,7 +261,7 @@ uint8_t TCMDEXEC_adcs_communication_status(const char *args_str, TCMD_Telecomman /// @brief Telecommand: Request the given telemetry data from the ADCS /// @param args_str -/// - No arguments for this command +/// - Arg 0: timeout for deployment [seconds] /// @return 0 on success, >0 on error uint8_t TCMDEXEC_adcs_deploy_magnetometer(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len) { @@ -311,7 +313,7 @@ uint8_t TCMDEXEC_adcs_attitude_control_mode(const char *args_str, TCMD_Telecomma /// @brief Telecommand: Request the given telemetry data from the ADCS /// @param args_str -/// - No arguments for this command +/// - Arg 0: Attitude estimation mode to set (Table 79 in Firmware Manual) /// @return 0 on success, >0 on error uint8_t TCMDEXEC_adcs_attitude_estimation_mode(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len) { @@ -855,10 +857,10 @@ uint8_t TCMDEXEC_adcs_set_commanded_attitude_angles(const char *args_str, TCMD_T /// - Arg 9: use_css (bool; whether or not to use the CSS measurement in extended_kalman_filter) /// - Arg 10: use_star_tracker (bool; whether or not to use the star tracker measurement in extended_kalman_filter) /// - Arg 11: nadir_sensor_terminator_test (bool; select to ignore nadir sensor measurements when terminator is in FOV) -/// - Arg 12: automatic_magnetometer_recovery (bool; select whether automatic switch to redundant magnetometer should occur in case of failure) +/// - Arg 12: automatic_magnetometer_recovery (bool; select whether automatic switch to redundant magnetometer should occur in case of {failure) /// - Arg 13: magnetometer_mode (enum; select magnetometer mode for estimation and control) /// - Arg 14: magnetometer_selection_for_raw_magnetometer_telemetry (enum; select magnetometer mode for the second raw telemetry frame) -/// - Arg 15: automatic_estimation_transition_due_to_rate_sensor_errors (bool; enable/disable automatic transition from MEMS rate estimation mode to RKF in case of rate sensor error) +/// - Arg 15: automatic_estimation_transition_due_to_rate_sensor_errors (bool; enable/disable automatic transition from MEMS rate estimation mode to RKF in case of {rate sensor error) /// - Arg 16: wheel_30s_power_up_delay (bool; present in CubeSupport but not in the manual -- need to test) /// - Arg 17: cam1_and_cam2_sampling_period (uint8; the manual calls it this, but CubeSupport calls it "error counter reset period" -- need to test) /// @return 0 on success, >0 on error @@ -1664,5 +1666,401 @@ uint8_t TCMDEXEC_adcs_measurements(const char *args_str, TCMD_TelecommandChannel return 2; } + return status; +} + +/// @brief Telecommand: Request the given telemetry data from the ADCS +/// @param args_str +/// - No arguments for this command +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_acp_execution_state(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + ADCS_acp_execution_state_struct_t packed_struct; + uint8_t status = ADCS_get_acp_execution_state(&packed_struct); + + if (status != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS telemetry request failed (err %d)", status); + return 1; + } + + const uint8_t result_json = ADCS_acp_execution_struct_TO_json( + &packed_struct, response_output_buf, response_output_buf_len); + + if (result_json != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS telemetry request JSON failed (err %d)", result_json); + return 2; + } + + return status; +} + +/// @brief Telecommand: Request the given telemetry data from the ADCS +/// @param args_str +/// - No arguments for this command +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_get_current_state_1(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + ADCS_current_state_1_struct_t packed_struct; + uint8_t status = ADCS_get_current_state_1(&packed_struct); + + if (status != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS telemetry request failed (err %d)", status); + return 1; + } + + const uint8_t result_json = ADCS_current_state_1_struct_TO_json( + &packed_struct, response_output_buf, response_output_buf_len); + + if (result_json != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS telemetry request JSON failed (err %d)", result_json); + return 2; + } + + return status; +} + +/// @brief Telecommand: Request raw star tracker telemetry data from the ADCS +/// @param args_str +/// - No arguments for this command +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_get_raw_star_tracker_data(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + ADCS_raw_star_tracker_struct_t packed_struct; + uint8_t status = ADCS_get_raw_star_tracker_data(&packed_struct); + + if (status != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS raw star tracker telemetry request failed (err %d)", status); + return 1; + } + + const uint8_t result_json = ADCS_raw_star_tracker_struct_TO_json( + &packed_struct, response_output_buf, response_output_buf_len); + + if (result_json != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS raw star tracker telemetry JSON conversion failed (err %d)", result_json); + return 2; + } + + return status; +} + +/// @brief Telecommand: Save an image to the ADCS onboard SD card +/// @param args_str +/// - Arg 0: Which camera to save the image from; can be Camera 1 (0), Camera 2 (1), or Star (2) +/// - Arg 1: Resolution of the image to save; can be 1024x1024 (0), 512x512, (1) 256x256, (2) 128x128, (3) or 64x64 (4) +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + // parse arguments: first into int64_t, then convert to correct form for input + const uint8_t num_args = 2; + uint64_t arguments[num_args]; + uint8_t args_8[num_args]; + for (uint8_t i = 0; i < num_args; i++) { + TCMD_extract_uint64_arg(args_str, strlen(args_str), i, &arguments[i]); + args_8[i] = (uint8_t) arguments[i]; + } + + uint8_t status = ADCS_save_image_to_sd(args_8[0], args_8[1]); + return status; +} + +/// @brief Telecommand: Synchronise the current ADCS Unix epoch time +/// @param args_str +/// - No arguments for this command +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_synchronise_unix_time(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + uint8_t status = ADCS_synchronise_unix_time(); + return status; +} + +/// @brief Telecommand: Retrieve the current ADCS Unix epoch time +/// @param args_str +/// - No arguments for this command +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_get_current_unix_time(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + + uint64_t unix_time_ms; + uint8_t status = ADCS_get_current_unix_time(&unix_time_ms); + + if (status != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS Unix time telemetry request failed (err %d)", status); + return 1; + } + + const uint8_t result_json = ADCS_unix_time_ms_TO_json( + &unix_time_ms, response_output_buf, response_output_buf_len); + + if (result_json != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS Unix time telemetry JSON conversion failed (err %d)", result_json); + return 2; + } + + return status; +} + +/// @brief Telecommand: Repeatedly log given data from an SD card +/// @param args_str +/// - Arg 0: which_log; 1 or 2; which specific log number to log to the SD card +/// - Arg 1: log_array; Hex array of bitmasks for log config (10 hex bytes) +/// - Arg 2: log_period; Period to log data to the SD card; if zero, then disable logging +/// - Arg 3: which_sd; Which SD card to log to, 0 for primary, 1 for secondary +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_set_sd_log_config(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + + uint64_t which_log; + TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &which_log); + + // parse hex array arguments + uint8_t hex_data_array[10]; + uint16_t data_length; + TCMD_extract_hex_array_arg(args_str, 1, &hex_data_array[0], data_length, &data_length); + + const uint8_t *data_pointer[1] = {hex_data_array}; + + uint64_t log_period; + TCMD_extract_uint64_arg(args_str, strlen(args_str), 2, &log_period); + + uint64_t which_sd; + TCMD_extract_uint64_arg(args_str, strlen(args_str), 3, &which_sd); + + uint8_t status = ADCS_set_sd_log_config((uint8_t) which_log, data_pointer, 1, (uint8_t) log_period, (uint8_t) which_sd); + + return status; +} + +/// @brief Telecommand: Retrieve the current ADCS SD log configuration +/// @param args_str +/// - Arg 0: which log to retrieve the configuration for (1 or 2) +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_get_sd_log_config(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + + uint64_t which_log; + TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &which_log); + + ADCS_sd_log_config_struct result_struct; + uint8_t status = ADCS_get_sd_log_config((uint8_t) which_log, &result_struct); + + if (status != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS SD log config telemetry request failed (err %d)", status); + return 1; + } + + const uint8_t result_json = ADCS_sd_log_config_struct_TO_json( + &result_struct, response_output_buf, response_output_buf_len); + + if (result_json != 0) { + snprintf(response_output_buf, response_output_buf_len, + "ADCS SD log config telemetry JSON conversion failed (err %d)", result_json); + return 2; + } + + return status; +} + +/// @brief Telecommand: Request commissioning telemetry from the ADCS and save it to the memory module +/// @param args_str +/// - Arg 0: Which commissioning step to request telemetry for (1-18) +/// - Arg 1: Log number (1 or 2) +/// - Arg 2: Destination SD card (0 = primary, 1 = secondary) +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_adcs_request_commissioning_telemetry(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + // parse arguments: first into int64_t, then convert to correct form for input + uint64_t arguments[3]; + for (uint8_t i = 0; i < 3; i++) { + TCMD_extract_uint64_arg(args_str, strlen(args_str), i, &arguments[i]); + } + ADCS_commissioning_step_enum_t commissioning_step = (ADCS_commissioning_step_enum_t) arguments[0]; + uint8_t log_number = (uint8_t) arguments[1]; + ADCS_sd_log_destination_enum_t sd_destination = (ADCS_sd_log_destination_enum_t) arguments[2]; + + if (log_number == 0 || log_number > 2) { + snprintf(response_output_buf, response_output_buf_len, + "Commissioning SD log number may be only 1 or 2"); + return 8; + } + + if (sd_destination > 1) { + snprintf(response_output_buf, response_output_buf_len, + "SD destination number may only be 0 (primary) or 1 (secondary)"); + return 9; + } + + ADCS_acp_execution_state_struct_t current_state; + do { // wait until 500ms has passed since last update + uint8_t state_status = ADCS_get_acp_execution_state(¤t_state); + if (state_status) { + snprintf(response_output_buf, response_output_buf_len, + "ACP execution state telemetry request failed (err %d)", state_status); + return 1; + } + } while (current_state.time_since_iteration_start_ms <= 500); + + uint8_t status = 0; + // TODO: check perod in Commissioning Manual, and check if need to convert to ms + switch(commissioning_step) { + case ADCS_COMMISISONING_STEP_DETERMINE_INITIAL_ANGULAR_RATES: { + const uint8_t num_logs = 3; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[3] = {ADCS_SD_LOG_MASK_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_RAW_MAGNETOMETER}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_INITIAL_DETUMBLING: { + const uint8_t num_logs = 4; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[4] = {ADCS_SD_LOG_MASK_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_RAW_MAGNETOMETER, ADCS_SD_LOG_MASK_MAGNETORQUER_COMMAND}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_CONTINUED_DETUMBLING_TO_Y_THOMSON: { + const uint8_t num_logs = 4; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[4] = {ADCS_SD_LOG_MASK_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_RAW_MAGNETOMETER, ADCS_SD_LOG_MASK_MAGNETORQUER_COMMAND}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_MAGNETOMETER_DEPLOYMENT: { + const uint8_t num_logs = 4; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[4] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_RAW_MAGNETOMETER, ADCS_SD_LOG_MASK_CUBECONTROL_CURRENT_MEASUREMENTS}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_MAGNETOMETER_CALIBRATION: { + const uint8_t num_logs = 3; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[3] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + // TODO: Magnetic Field Vector **should** be the calibrated measurements from the magnetometer, but we should see if we can check with CubeSpace about that + break; + } + case ADCS_COMMISISONING_STEP_ANGULAR_RATE_AND_PITCH_ANGLE_ESTIMATION: { + const uint8_t num_logs = 4; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[4] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_Y_WHEEL_RAMP_UP_TEST: { + const uint8_t num_logs = 5; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[5] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_WHEEL_SPEED, ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_INITIAL_Y_MOMENTUM_ACTIVATION: { + const uint8_t num_logs = 6; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[6] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_WHEEL_SPEED, ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_SATELLITE_POSITION_LLH}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_CONTINUED_Y_MOMENTUM_ACTIVATION_AND_MAGNETOMETER_EKF: { + const uint8_t num_logs = 6; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[6] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_WHEEL_SPEED, ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_SATELLITE_POSITION_LLH}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_CUBESENSE_SUN_NADIR: { + const uint8_t num_logs = 9; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[9] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, + ADCS_SD_LOG_MASK_RAW_CSS_1_TO_6, ADCS_SD_LOG_MASK_RAW_CSS_7_TO_10, ADCS_SD_LOG_MASK_RAW_CAM1_SENSOR, ADCS_SD_LOG_MASK_RAW_CAM2_SENSOR, + ADCS_SD_LOG_MASK_FINE_SUN_VECTOR, ADCS_SD_LOG_MASK_NADIR_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_EKF_ACTIVATION_SUN_AND_NADIR: { + const uint8_t num_logs = 9; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[9] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, + ADCS_SD_LOG_MASK_RAW_CSS_1_TO_6, ADCS_SD_LOG_MASK_RAW_CSS_7_TO_10, ADCS_SD_LOG_MASK_RAW_CAM1_SENSOR, ADCS_SD_LOG_MASK_RAW_CAM2_SENSOR, + ADCS_SD_LOG_MASK_FINE_SUN_VECTOR, ADCS_SD_LOG_MASK_NADIR_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_CUBESTAR_STAR_TRACKER: { + const uint8_t num_logs = 8; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[8] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, + ADCS_SD_LOG_MASK_STAR_PERFORMANCE1, ADCS_SD_LOG_MASK_STAR_PERFORMANCE2, + ADCS_SD_LOG_MASK_STAR_1_RAW_DATA, ADCS_SD_LOG_MASK_STAR_2_RAW_DATA, ADCS_SD_LOG_MASK_STAR_3_RAW_DATA}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_EKF_ACTIVATION_WITH_STAR_VECTOR_MEASUREMENTS: { + const uint8_t num_logs = 8; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[8] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, + ADCS_SD_LOG_MASK_STAR_PERFORMANCE1, ADCS_SD_LOG_MASK_STAR_PERFORMANCE2, + ADCS_SD_LOG_MASK_STAR_1_RAW_DATA, ADCS_SD_LOG_MASK_STAR_2_RAW_DATA, ADCS_SD_LOG_MASK_STAR_3_RAW_DATA}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_ZERO_BIAS_3_AXIS_REACTION_WHEEL_CONTROL: { + const uint8_t num_logs = 4; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[4] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_WHEEL_SPEED}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_EKF_WITH_RATE_GYRO_STAR_TRACKER_MEASUREMENTS: { + const uint8_t num_logs = 12; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[12] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_ESTIMATED_GYRO_BIAS, ADCS_SD_LOG_MASK_ESTIMATION_INNOVATION_VECTOR, + ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_FINE_SUN_VECTOR, ADCS_SD_LOG_MASK_NADIR_VECTOR, ADCS_SD_LOG_MASK_WHEEL_SPEED, ADCS_SD_LOG_MASK_MAGNETORQUER_COMMAND, + ADCS_SD_LOG_MASK_IGRF_MODELLED_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_QUATERNION_ERROR_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_SUN_TRACKING_3_AXIS_CONTROL: { + const uint8_t num_logs = 12; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[12] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_ESTIMATED_GYRO_BIAS, ADCS_SD_LOG_MASK_ESTIMATION_INNOVATION_VECTOR, + ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_FINE_SUN_VECTOR, ADCS_SD_LOG_MASK_NADIR_VECTOR, ADCS_SD_LOG_MASK_WHEEL_SPEED, ADCS_SD_LOG_MASK_MAGNETORQUER_COMMAND, + ADCS_SD_LOG_MASK_IGRF_MODELLED_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_QUATERNION_ERROR_VECTOR}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_GROUND_TARGET_TRACKING_CONTROLLER: { + const uint8_t num_logs = 14; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[14] = {ADCS_SD_LOG_MASK_FINE_ESTIMATED_ANGULAR_RATES, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES, ADCS_SD_LOG_MASK_ESTIMATED_GYRO_BIAS, ADCS_SD_LOG_MASK_ESTIMATION_INNOVATION_VECTOR, + ADCS_SD_LOG_MASK_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_RATE_SENSOR_RATES, ADCS_SD_LOG_MASK_FINE_SUN_VECTOR, ADCS_SD_LOG_MASK_NADIR_VECTOR, ADCS_SD_LOG_MASK_WHEEL_SPEED, ADCS_SD_LOG_MASK_MAGNETORQUER_COMMAND, + ADCS_SD_LOG_MASK_IGRF_MODELLED_MAGNETIC_FIELD_VECTOR, ADCS_SD_LOG_MASK_QUATERNION_ERROR_VECTOR, ADCS_SD_LOG_MASK_SATELLITE_POSITION_LLH, ADCS_SD_LOG_MASK_ESTIMATED_ATTITUDE_ANGLES}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + case ADCS_COMMISISONING_STEP_GPS_RECEIVER: { + const uint8_t num_logs = 6; + const uint8_t period_s = 10; + const uint8_t* commissioning_data[6] = {ADCS_SD_LOG_MASK_SATELLITE_POSITION_LLH, ADCS_SD_LOG_MASK_RAW_GPS_STATUS, ADCS_SD_LOG_MASK_RAW_GPS_TIME, + ADCS_SD_LOG_MASK_RAW_GPS_X, ADCS_SD_LOG_MASK_RAW_GPS_Y, ADCS_SD_LOG_MASK_RAW_GPS_Z}; + status = ADCS_set_sd_log_config(log_number, commissioning_data, num_logs, period_s, sd_destination); + break; + } + + default: { + snprintf(response_output_buf, response_output_buf_len, + "Commissioning step case out of range (err %d)", 1); + return 1; + } + } + return status; } \ No newline at end of file diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index 5cb3feef7..defb87dbe 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -323,7 +323,7 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { { .tcmd_name = "adcs_deploy_magnetometer", .tcmd_func = TCMDEXEC_adcs_deploy_magnetometer, - .number_of_args = 0, + .number_of_args = 1, .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, { @@ -347,7 +347,7 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { { .tcmd_name = "adcs_attitude_estimation_mode", .tcmd_func = TCMDEXEC_adcs_attitude_estimation_mode, - .number_of_args = 0, + .number_of_args = 1, .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, { @@ -668,6 +668,61 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .number_of_args = 2, .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, + { + .tcmd_name = "adcs_acp_execution_state", + .tcmd_func = TCMDEXEC_adcs_acp_execution_state, + .number_of_args = 0, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_get_current_state_1", + .tcmd_func = TCMDEXEC_adcs_get_current_state_1, + .number_of_args = 0, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_get_raw_star_tracker_data", + .tcmd_func = TCMDEXEC_adcs_get_raw_star_tracker_data, + .number_of_args = 0, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_save_image_to_sd", + .tcmd_func = TCMDEXEC_adcs_save_image_to_sd, + .number_of_args = 2, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_request_commissioning_telemetry", + .tcmd_func = TCMDEXEC_adcs_request_commissioning_telemetry, + .number_of_args = 3, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_synchronise_unix_time", + .tcmd_func = TCMDEXEC_adcs_synchronise_unix_time, + .number_of_args = 0, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_get_current_unix_time", + .tcmd_func = TCMDEXEC_adcs_get_current_unix_time, + .number_of_args = 0, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_set_sd_log_config", + .tcmd_func = TCMDEXEC_adcs_set_sd_log_config, + .number_of_args = 4, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_get_sd_log_config", + .tcmd_func = TCMDEXEC_adcs_get_sd_log_config, + .number_of_args = 1, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + // ****************** END SECTION: telecommand_adcs ****************** // ****************** SECTION: log_telecommand_defs ****************** diff --git a/firmware/Core/Src/telecommands/telecommand_executor.c b/firmware/Core/Src/telecommands/telecommand_executor.c index 5255359c4..c95580742 100644 --- a/firmware/Core/Src/telecommands/telecommand_executor.c +++ b/firmware/Core/Src/telecommands/telecommand_executor.c @@ -79,6 +79,65 @@ uint8_t TCMD_add_tcmd_to_agenda(const TCMD_parsed_tcmd_to_execute_t *parsed_tcmd } +/// @brief Adds a telecommand to the agenda (schedule/queue) of telecommands to execute, with a delay in execution. +/// @param parsed_tcmd The parsed telecommand to add to the agenda. +/// @param time_delay_ms The time to delay the telecommand execution. +/// @return 0 on success, 1 if the agenda is full. +/// @note Performs a deep copy of the `parsed_tcmd` arg into the agenda. +uint8_t TCMD_add_delayed_tcmd_to_agenda(const TCMD_parsed_tcmd_to_execute_t *parsed_tcmd, uint32_t time_delay_ms) { + + // Find the first empty slot in the agenda. + for (uint16_t slot_num = 0; slot_num < TCMD_AGENDA_SIZE; slot_num++) { + // Skip filled slots. + if (TCMD_agenda_is_valid[slot_num]) { + continue; + } + + // Copy the parsed telecommand into the agenda. + TCMD_agenda[slot_num].tcmd_idx = parsed_tcmd->tcmd_idx; + TCMD_agenda[slot_num].tcmd_channel = parsed_tcmd->tcmd_channel; + TCMD_agenda[slot_num].timestamp_sent = parsed_tcmd->timestamp_sent; + TCMD_agenda[slot_num].timestamp_to_execute = (parsed_tcmd->timestamp_to_execute) + time_delay_ms; + + for (uint16_t j = 0; j < TCMD_ARGS_STR_NO_PARENS_SIZE; j++) { + TCMD_agenda[slot_num].args_str_no_parens[j] = parsed_tcmd->args_str_no_parens[j]; + } + + // Mark the slot as valid. + TCMD_agenda_is_valid[slot_num] = 1; + + // Incrementing counters used for stats + TCMD_total_tcmd_queued_count++; + TCMD_latest_received_tcmd_timestamp_sent = parsed_tcmd->timestamp_sent; + + // DEBUG_uart_print_str("Telecommand added to agenda at slot "); + // DEBUG_uart_print_uint32(slot_num); + // DEBUG_uart_print_str("\n"); + return 0; + } + return 1; +} + + +/// @brief Adds a telecommand to the agenda (schedule/queue) of telecommands to execute, and does so repeatedly. +/// @param parsed_tcmd The parsed telecommand to add to the agenda. +/// @param repeat_period_ms The period of repetition, in ms. +/// @param times_to_repeat The number of times to repeat the telecommand. +/// @return 0 on success, 1 if the agenda is full. +/// @note Performs a deep copy of the `parsed_tcmd` arg into the agenda. +uint8_t TCMD_add_repeated_tcmd_to_agenda(const TCMD_parsed_tcmd_to_execute_t *parsed_tcmd, const uint32_t repeat_period_ms, const uint32_t times_to_repeat) { + uint32_t times_scheduled = 0; + + while (times_scheduled < times_to_repeat) { + + TCMD_add_delayed_tcmd_to_agenda(parsed_tcmd, times_scheduled * repeat_period_ms); + + times_scheduled++; + + } + return 0; +} + /// @brief Gets the number of used slots in the agenda. /// @return The number of currently-filled slots in the agenda. /// @note This function is mostly intended for "system stats" telecommands and logging. diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index a79eeb152..1fbaa943a 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -1,4 +1,5 @@ #include "adcs_drivers/adcs_struct_packers.h" +#include "adcs_drivers/adcs_internal_drivers.h" #include "unit_tests/unit_test_helpers.h" // for all unit tests #include "unit_tests/test_adcs.h" // for ADCS tests #include "transforms/number_comparisons.h" // for comparing doubles @@ -10,7 +11,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_ack_struct() { uint8_t input_params[4] = {0x11, 0x01, 0x03, 0x04}; ADCS_cmd_ack_struct_t result; - ADCS_Pack_to_Ack_Struct(input_params, &result); + ADCS_pack_to_ack_struct(input_params, &result); TEST_ASSERT_TRUE(result.last_id == 17); TEST_ASSERT_TRUE(result.processed == true); @@ -23,7 +24,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_ack_struct() { uint8_t TEST_EXEC__ADCS_pack_to_identification_struct() { uint8_t input_params[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; ADCS_id_struct_t result; - ADCS_Pack_to_Identification_Struct(input_params, &result); + ADCS_pack_to_identification_struct(input_params, &result); TEST_ASSERT_TRUE(result.node_type == 17); TEST_ASSERT_TRUE(result.interface_version == 34); @@ -38,7 +39,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_identification_struct() { uint8_t TEST_EXEC__ADCS_pack_to_program_status_struct() { uint8_t input_params[6] = {0xF2, 0x22, 0x33, 0x02, 0x55, 0x66}; ADCS_boot_running_status_struct_t result; - ADCS_Pack_to_Program_Status_Struct(input_params, &result); + ADCS_pack_to_program_status_struct(input_params, &result); TEST_ASSERT_TRUE(result.reset_cause == ADCS_RESET_CAUSE_UNKNOWN); TEST_ASSERT_TRUE(result.boot_cause == ADCS_BOOT_CAUSE_COMMUNICATIONS_TIMEOUT); @@ -53,7 +54,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_program_status_struct() { uint8_t TEST_EXEC__ADCS_pack_to_comms_status_struct() { uint8_t input_params[5] = {0x11, 0x22, 0x33, 0x44, 0x55}; ADCS_comms_status_struct_t result; - ADCS_Pack_to_Comms_Status_Struct(input_params, &result); + ADCS_pack_to_comms_status_struct(input_params, &result); TEST_ASSERT_TRUE(result.cmd_counter == 8721); TEST_ASSERT_TRUE(result.tlm_counter == 17459); @@ -67,7 +68,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_comms_status_struct() { uint8_t TEST_EXEC__ADCS_pack_to_power_control_struct() { uint8_t input_params[3] = {0x11, 0x22, 0x31}; ADCS_power_control_struct_t result; - ADCS_Pack_to_Power_Control_Struct(input_params, &result); + ADCS_pack_to_power_control_struct(input_params, &result); TEST_ASSERT_TRUE(result.cube_control_motor == ADCS_POWER_SELECT_OFF); TEST_ASSERT_TRUE(result.cube_control_signal == ADCS_POWER_SELECT_ON); @@ -86,7 +87,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_power_control_struct() { uint8_t TEST_EXEC__ADCS_pack_to_angular_rates_struct() { uint8_t input_params[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xff}; ADCS_angular_rates_struct_t result; - ADCS_Pack_to_Angular_Rates_Struct(input_params, &result); + ADCS_pack_to_angular_rates_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_rate_mdeg_per_sec == 87210); TEST_ASSERT_TRUE(result.y_rate_mdeg_per_sec == 174590); @@ -98,7 +99,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_angular_rates_struct() { uint8_t TEST_EXEC__ADCS_pack_to_llh_position_struct() { uint8_t input_params[6] = {0x11, 0x22, 0x33, 0xff, 0x55, 0x66}; ADCS_llh_position_struct_t result; - ADCS_Pack_to_LLH_Position_Struct(input_params, &result); + ADCS_pack_to_llh_position_struct(input_params, &result); TEST_ASSERT_TRUE(result.latitude_mdeg == 87210); TEST_ASSERT_TRUE(result.longitude_mdeg == -2050); @@ -110,7 +111,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_llh_position_struct() { uint8_t TEST_EXEC__ADCS_pack_to_unix_time_save_mode_struct() { uint8_t input_params[2] = {0x11, 0x22}; ADCS_set_unix_time_save_mode_struct_t result; - ADCS_Pack_to_Unix_Time_Save_Mode_Struct(input_params, &result); + ADCS_pack_to_unix_time_save_mode_struct(input_params, &result); TEST_ASSERT_TRUE(result.save_now == true); TEST_ASSERT_TRUE(result.save_on_update == false); @@ -131,7 +132,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_orbit_params_struct() { 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x40, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x99, 0x28, 0x40}; ADCS_orbit_params_struct_t result; - ADCS_Pack_to_Orbit_Params_Struct(input_params, &result); + ADCS_pack_to_orbit_params_struct(input_params, &result); TEST_ASSERT_TRUE(GEN_compare_doubles(result.inclination_deg, 1.2, ADCS_TEST_EPSILON)); TEST_ASSERT_TRUE(GEN_compare_doubles(result.eccentricity, 0.67, ADCS_TEST_EPSILON)); @@ -147,7 +148,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_orbit_params_struct() { uint8_t TEST_EXEC__ADCS_pack_to_rated_sensor_rates_struct() { uint8_t input_params[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xff}; ADCS_rated_sensor_rates_struct_t result; - ADCS_Pack_to_Rated_Sensor_Rates_Struct(input_params, &result); + ADCS_pack_to_rated_sensor_rates_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_mdeg_per_sec == 87210); TEST_ASSERT_TRUE(result.y_mdeg_per_sec == 174590); @@ -159,7 +160,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_rated_sensor_rates_struct() { uint8_t TEST_EXEC__ADCS_pack_to_wheel_speed_struct() { uint8_t input_params[6] = {0x11, 0x22, 0x33, 0xff, 0x55, 0x66}; ADCS_wheel_speed_struct_t result; - ADCS_Pack_to_Wheel_Speed_Struct(input_params, &result); + ADCS_pack_to_wheel_speed_struct(input_params, &result); TEST_ASSERT_TRUE(result.actual_wheel_speed == true); TEST_ASSERT_TRUE(result.x_rpm == 8721); TEST_ASSERT_TRUE(result.y_rpm == -205); @@ -173,7 +174,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_magnetorquer_command_struct() uint8_t input_params[6] = {0x11, 0x22, 0x33, 0xff, 0x55, 0x66}; ADCS_magnetorquer_command_struct_t result; - ADCS_Pack_to_Magnetorquer_Command_Struct(input_params, &result); + ADCS_pack_to_magnetorquer_command_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_ms == 87210); TEST_ASSERT_TRUE(result.y_ms == -2050); TEST_ASSERT_TRUE(result.z_ms == 261970); @@ -185,7 +186,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_magnetometer_values_struct() { uint8_t input_params[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xff}; ADCS_raw_magnetometer_values_struct_t result; - ADCS_Pack_to_Raw_Magnetometer_Values_Struct(input_params, &result); + ADCS_pack_to_raw_magnetometer_values_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_raw == 8721); TEST_ASSERT_TRUE(result.y_raw == 17459); TEST_ASSERT_TRUE(result.z_raw == -171); @@ -198,7 +199,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_fine_angular_rates_struct() uint8_t input_params[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xff}; ADCS_fine_angular_rates_struct_t result; - ADCS_Pack_to_Fine_Angular_Rates_Struct(input_params, &result); + ADCS_pack_to_fine_angular_rates_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_mdeg_per_sec == 8721); TEST_ASSERT_TRUE(result.y_mdeg_per_sec == 17459); TEST_ASSERT_TRUE(result.z_mdeg_per_sec == -171); @@ -215,7 +216,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_magnetometer_config_struct() 0x22, 0x22, 0xDE, 0xDD, 0x22, 0x22}; ADCS_magnetometer_config_struct_t result; - ADCS_Pack_to_Magnetometer_Config_Struct(input_params, &result); + ADCS_pack_to_magnetometer_config_struct(input_params, &result); TEST_ASSERT_TRUE(result.mounting_transform_alpha_angle_mdeg_per_sec == 87380); TEST_ASSERT_TRUE(result.mounting_transform_beta_angle_mdeg_per_sec == -87380); TEST_ASSERT_TRUE(result.mounting_transform_gamma_angle_mdeg_per_sec == 87380); @@ -240,7 +241,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_commanded_attitude_angles_struct() uint8_t input_params[6] = {0x11, 0xaa, 0x22, 0xbb, 0x33, 0xcc}; ADCS_commanded_angles_struct_t result; - ADCS_Pack_to_Commanded_Attitude_Angles_Struct(input_params, &result); + ADCS_pack_to_commanded_attitude_angles_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_mdeg == -219990); TEST_ASSERT_TRUE(result.y_mdeg == -176300); TEST_ASSERT_TRUE(result.z_mdeg == -132610); @@ -255,7 +256,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_estimation_params_struct() 0xD3, 0x40, 0x66, 0x66, 0xF6, 0x40, 0xAA, 0x0D, 0x2C}; ADCS_estimation_params_struct_t result; - ADCS_Pack_to_Estimation_Params_Struct(input_params, &result); + ADCS_pack_to_estimation_params_struct(input_params, &result); TEST_ASSERT_TRUE(GEN_compare_doubles(result.magnetometer_rate_filter_system_noise, 1.1, ADCS_TEST_EPSILON)); TEST_ASSERT_TRUE(GEN_compare_doubles(result.extended_kalman_filter_system_noise, 2.2, ADCS_TEST_EPSILON)); TEST_ASSERT_TRUE(GEN_compare_doubles(result.coarse_sun_sensor_measurement_noise, 3.3, ADCS_TEST_EPSILON)); @@ -286,7 +287,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_augmented_sgp4_params_struct() 0xD4, 0x0D, 0xD6, 0xD7, 0x10, 0x00}; ADCS_augmented_sgp4_params_struct_t result; - ADCS_Pack_to_Augmented_SGP4_Params_Struct(input_params, &result); + ADCS_pack_to_augmented_sgp4_params_struct(input_params, &result); TEST_ASSERT_TRUE(result.incl_coefficient_milli == 1100); TEST_ASSERT_TRUE(result.raan_coefficient_milli == 2200); TEST_ASSERT_TRUE(result.ecc_coefficient_milli == 3300); @@ -313,7 +314,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_tracking_controller_target_reference_struct() uint8_t input_params[12] = {0xCD, 0xCC, 0xDC, 0x42, 0x33, 0x33, 0x8B, 0xC2, 0x66, 0x66, 0x86, 0x3F}; ADCS_tracking_controller_target_struct_t result; - ADCS_Pack_to_Tracking_Controller_Target_Reference_Struct(input_params, &result); + ADCS_pack_to_tracking_controller_target_reference_struct(input_params, &result); TEST_ASSERT_TRUE(GEN_compare_doubles(result.longitude_degrees, 110.4, 10*ADCS_TEST_EPSILON)); TEST_ASSERT_TRUE(GEN_compare_doubles(result.latitude_degrees, -69.6, 10*ADCS_TEST_EPSILON)); TEST_ASSERT_TRUE(GEN_compare_doubles(result.altitude_meters, 1.05, ADCS_TEST_EPSILON)); @@ -327,7 +328,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_rate_gyro_config_struct() uint8_t input_params[10] = {0xCD, 0xCC, 0xDC, 0x42, 0x33, 0x33, 0x8B, 0xC2, 0x66, 0x66}; ADCS_rate_gyro_config_struct_t result; - ADCS_Pack_to_Rate_Gyro_Config_Struct(input_params, &result); + ADCS_pack_to_rate_gyro_config_struct(input_params, &result); TEST_ASSERT_TRUE(result.gyro1 == 205); TEST_ASSERT_TRUE(result.gyro2 == 204); TEST_ASSERT_TRUE(result.gyro3 == 220); @@ -344,7 +345,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_estimated_attitude_angles_struct() uint8_t input_params[6] = {0x10, 0x27, 0x34, 0xff, 0x56, 0x78}; ADCS_estimated_attitude_angles_struct_t result; - ADCS_Pack_to_Estimated_Attitude_Angles_Struct(input_params, &result); + ADCS_pack_to_estimated_attitude_angles_struct(input_params, &result); TEST_ASSERT_TRUE(result.estimated_roll_angle_mdeg == 100000); TEST_ASSERT_TRUE(result.estimated_pitch_angle_mdeg == -2040); @@ -358,7 +359,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_magnetic_field_vector_struct() uint8_t input_params[6] = {0x10, 0x27, 0x34, 0xff, 0x56, 0x78}; ADCS_magnetic_field_vector_struct_t result; - ADCS_Pack_to_Magnetic_Field_Vector_Struct(input_params, &result); + ADCS_pack_to_magnetic_field_vector_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_nT == 100000); TEST_ASSERT_TRUE(result.y_nT == -2040); @@ -372,7 +373,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_nadir_vector_struct() uint8_t input_params[6] = {0x01, 0x10, 0xf1, 0x11, 0xF0, 0xF1}; ADCS_nadir_vector_struct_t result; - ADCS_Pack_to_Nadir_Vector_Struct(input_params, &result); + ADCS_pack_to_nadir_vector_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_micro == 409700); TEST_ASSERT_TRUE(result.y_micro == 459300); @@ -386,7 +387,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_commanded_wheel_speed_struct() uint8_t input_params[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0xd6}; ADCS_wheel_speed_struct_t result; - ADCS_Pack_to_Commanded_Wheel_Speed_Struct(input_params, &result); + ADCS_pack_to_commanded_wheel_speed_struct(input_params, &result); TEST_ASSERT_TRUE(result.actual_wheel_speed == false); TEST_ASSERT_TRUE(result.x_rpm == 513); TEST_ASSERT_TRUE(result.y_rpm == 1027); @@ -400,7 +401,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_igrf_magnetic_field_vector_struct() uint8_t input_params[6] = {0x09, 0xf8, 0x07, 0x06, 0x05, 0xd4}; ADCS_magnetic_field_vector_struct_t result; - ADCS_Pack_to_IGRF_Magnetic_Field_Vector_Struct(input_params, &result); + ADCS_pack_to_igrf_magnetic_field_vector_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_nT == -20390); TEST_ASSERT_TRUE(result.y_nT == 15430); @@ -414,7 +415,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_quaternion_error_vector_struct() uint8_t input_params[6] = {0x01, 0x02, 0x03, 0xe4, 0x05, 0x06}; ADCS_quaternion_error_vector_struct_t result; - ADCS_Pack_to_Quaternion_Error_Vector_Struct(input_params, &result); + ADCS_pack_to_quaternion_error_vector_struct(input_params, &result); TEST_ASSERT_TRUE(result.quaternion_error_q1_micro == 51300); TEST_ASSERT_TRUE(result.quaternion_error_q2_micro == -716500); @@ -428,7 +429,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_estimated_gyro_bias_struct() uint8_t input_params[6] = {0x01, 0x02, 0x03, 0xe4, 0x05, 0x06}; ADCS_estimated_gyro_bias_struct_t result; - ADCS_Pack_to_Estimated_Gyro_Bias_Struct(input_params, &result); + ADCS_pack_to_estimated_gyro_bias_struct(input_params, &result); TEST_ASSERT_TRUE(result.estimated_x_gyro_bias_mdeg_per_sec == 513); TEST_ASSERT_TRUE(result.estimated_y_gyro_bias_mdeg_per_sec == -7165); @@ -442,7 +443,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_estimation_innovation_vector_struct() uint8_t input_params[6] = {0x01, 0x02, 0x03, 0xe4, 0x05, 0x06}; ADCS_estimation_innovation_vector_struct_t result; - ADCS_Pack_to_Estimation_Innovation_Vector_Struct(input_params, &result); + ADCS_pack_to_estimation_innovation_vector_struct(input_params, &result); TEST_ASSERT_TRUE(result.innovation_vector_x_micro == 51300); TEST_ASSERT_TRUE(result.innovation_vector_y_micro == -716500); @@ -456,7 +457,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_cam1_sensor_struct() uint8_t input_params[6] = {0x01, 0x02, 0x03, 0xd4, 0x05, 0x06}; ADCS_raw_cam_sensor_struct_t result; - ADCS_Pack_to_Raw_Cam1_Sensor_Struct(input_params, &result); + ADCS_pack_to_raw_cam1_sensor_struct(input_params, &result); TEST_ASSERT_TRUE(result.which_sensor == ADCS_WHICH_CAM_SENSOR_CAM1); TEST_ASSERT_TRUE(result.cam_centroid_x == 513); @@ -472,7 +473,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_cam2_sensor_struct() uint8_t input_params[6] = {0x01, 0x02, 0x03, 0xd4, 0x05, 0x06}; ADCS_raw_cam_sensor_struct_t result; - ADCS_Pack_to_Raw_Cam1_Sensor_Struct(input_params, &result); + ADCS_pack_to_raw_cam1_sensor_struct(input_params, &result); TEST_ASSERT_TRUE(result.which_sensor == ADCS_WHICH_CAM_SENSOR_CAM1); TEST_ASSERT_TRUE(result.cam_centroid_x == 513); @@ -488,7 +489,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_fine_sun_vector_struct() { uint8_t input_params[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}; ADCS_fine_sun_vector_struct_t result; - ADCS_Pack_to_Fine_Sun_Vector_Struct(input_params, &result); + ADCS_pack_to_fine_sun_vector_struct(input_params, &result); TEST_ASSERT_TRUE(result.x_micro == 1333000); TEST_ASSERT_TRUE(result.y_micro == 3080600); @@ -500,7 +501,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_fine_sun_vector_struct() { uint8_t TEST_EXEC__ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct() { uint8_t input_params[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}; ADCS_raw_coarse_sun_sensor_1_to_6_struct_t result; - ADCS_Pack_to_Raw_Coarse_Sun_Sensor_1_to_6_Struct(input_params, &result); + ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct(input_params, &result); TEST_ASSERT_TRUE(result.coarse_sun_sensor_1 == 18); TEST_ASSERT_TRUE(result.coarse_sun_sensor_2 == 52); TEST_ASSERT_TRUE(result.coarse_sun_sensor_3 == 86); @@ -512,7 +513,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct() { uint8_t TEST_EXEC__ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct() { uint8_t input_params[4] = {0x12, 0x34, 0x56, 0x78}; ADCS_raw_coarse_sun_sensor_7_to_10_struct_t result; - ADCS_Pack_to_Raw_Coarse_Sun_Sensor_7_to_10_Struct(input_params, &result); + ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct(input_params, &result); TEST_ASSERT_TRUE(result.coarse_sun_sensor_7 == 18); TEST_ASSERT_TRUE(result.coarse_sun_sensor_8 == 52); TEST_ASSERT_TRUE(result.coarse_sun_sensor_9 == 86); @@ -524,7 +525,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_cubecontrol_current_struct() { uint8_t input_params[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}; ADCS_cubecontrol_current_struct_t result; - ADCS_Pack_to_CubeControl_Current_Struct(input_params, &result); + ADCS_pack_to_cubecontrol_current_struct(input_params, &result); TEST_ASSERT_TRUE(GEN_compare_doubles(result.cubecontrol_3v3_current_mA, 6508.7890625, ADCS_TEST_EPSILON / 100.0)); TEST_ASSERT_TRUE(GEN_compare_doubles(result.cubecontrol_5v_current_mA, 15041.9921875, ADCS_TEST_EPSILON / 100.0)); @@ -535,7 +536,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_cubecontrol_current_struct() { uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_status_struct() { uint8_t input_params[6] = {0x08, 0x34, 0x56, 0x78, 0x9a, 0xbc}; ADCS_raw_gps_status_struct_t result; - ADCS_Pack_to_Raw_GPS_Status_Struct(input_params, &result); + ADCS_pack_to_raw_gps_status_struct(input_params, &result); TEST_ASSERT_TRUE(result.gps_solution_status == ADCS_GPS_SOLUTION_STATUS_LARGE_RESIDUALS); TEST_ASSERT_TRUE(result.num_tracked_satellites == 52); TEST_ASSERT_TRUE(result.num_used_satellites == 86); @@ -548,7 +549,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_status_struct() { uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_time_struct() { uint8_t input_params[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}; ADCS_raw_gps_time_struct_t result; - ADCS_Pack_to_Raw_GPS_Time_Struct(input_params, &result); + ADCS_pack_to_raw_gps_time_struct(input_params, &result); TEST_ASSERT_TRUE(result.gps_reference_week == 13330); TEST_ASSERT_TRUE(GEN_compare_doubles(result.gps_time_ms, 3164239958, ADCS_TEST_EPSILON)); return 0; @@ -557,13 +558,13 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_time_struct() { uint8_t TEST_EXEC__ADCS_pack_to_raw_gps_struct() { uint8_t input_params[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}; ADCS_raw_gps_struct_t result; - ADCS_Pack_to_Raw_GPS_Struct(ADCS_GPS_AXIS_Y, input_params, &result); + ADCS_pack_to_raw_gps_struct(ADCS_GPS_AXIS_Y, input_params, &result); TEST_ASSERT_TRUE(result.axis == ADCS_GPS_AXIS_Y); TEST_ASSERT_TRUE(result.ecef_position_meters == 2018915346); TEST_ASSERT_TRUE(result.ecef_velocity_meters_per_sec == -17254); uint8_t input_params_two[6] = {0x12, 0x34, 0xee, 0xff, 0x9a, 0x0c}; - ADCS_Pack_to_Raw_GPS_Struct(ADCS_GPS_AXIS_X, input_params_two, &result); + ADCS_pack_to_raw_gps_struct(ADCS_GPS_AXIS_X, input_params_two, &result); TEST_ASSERT_TRUE(result.axis == ADCS_GPS_AXIS_X); TEST_ASSERT_TRUE(result.ecef_position_meters == -1166318); TEST_ASSERT_TRUE(result.ecef_velocity_meters_per_sec == 3226); @@ -584,7 +585,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_measurements_struct() { 0x32, 0x15, 0x47, 0x9e, 0x3c, 0x4a, 0xd3, 0x1c}; ADCS_measurements_struct_t result; - ADCS_Pack_to_Measurements_Struct(input_params, &result); + ADCS_pack_to_measurements_struct(input_params, &result); TEST_ASSERT_TRUE(result.magnetic_field_x_nT == 73780); TEST_ASSERT_TRUE(result.magnetic_field_y_nT == -149410); @@ -625,3 +626,169 @@ uint8_t TEST_EXEC__ADCS_pack_to_measurements_struct() { return 0; } + + +uint8_t TEST_EXEC__ADCS_pack_to_acp_execution_state_struct() { + + uint8_t input_params[3] = {0x44, 0xab, 0x03}; + ADCS_acp_execution_state_struct_t result; + + ADCS_pack_to_acp_execution_state_struct(input_params, &result); + + TEST_ASSERT_TRUE(result.time_since_iteration_start_ms == 43844); + TEST_ASSERT_TRUE(result.current_execution_point == ADCS_CURRENT_EXECUTION_POINT_ADCS_UPDATE); + + return 0; + +} + +uint8_t TEST_EXEC__ADCS_pack_to_current_state_1_struct() { + + uint8_t input_params[6] = {0x44, 0xab, 0x03, 0x44, 0xab, 0x03}; + ADCS_current_state_1_struct_t result; + + ADCS_pack_to_current_state_1_struct(input_params, &result); + + TEST_ASSERT_TRUE(result.estimation_mode == ADCS_ESTIMATION_MODE_MAGNETOMETER_AND_FINE_SUN_TRIAD_ALGORITHM); + TEST_ASSERT_TRUE(result.control_mode == ADCS_CONTROL_MODE_Y_WHEEL_MOMENTUM_STABILIZED_STEADY_STATE); + TEST_ASSERT_TRUE(result.run_mode == ADCS_RUN_MODE_SIMULATION); + TEST_ASSERT_TRUE(result.asgp4_mode == ADCS_ASGP4_MODE_BACKGROUND); + TEST_ASSERT_TRUE(result.cubecontrol_signal_enabled == false); + TEST_ASSERT_TRUE(result.cubecontrol_motor_enabled == true); + TEST_ASSERT_TRUE(result.cubesense1_enabled == false); + TEST_ASSERT_TRUE(result.cubesense2_enabled == true); + TEST_ASSERT_TRUE(result.cubewheel1_enabled == true); + TEST_ASSERT_TRUE(result.cubewheel2_enabled == true); + TEST_ASSERT_TRUE(result.cubewheel3_enabled == false); + TEST_ASSERT_TRUE(result.cubestar_enabled == false); + TEST_ASSERT_TRUE(result.gps_receiver_enabled == false); + TEST_ASSERT_TRUE(result.gps_lna_power_enabled == false); + TEST_ASSERT_TRUE(result.motor_driver_enabled == false); + TEST_ASSERT_TRUE(result.sun_above_local_horizon == false); + TEST_ASSERT_TRUE(result.cubesense1_comm_error == false); + TEST_ASSERT_TRUE(result.cubesense2_comm_error == false); + TEST_ASSERT_TRUE(result.cubecontrol_signal_comm_error == true); + TEST_ASSERT_TRUE(result.cubecontrol_motor_comm_error == false); + TEST_ASSERT_TRUE(result.cubewheel1_comm_error == false); + TEST_ASSERT_TRUE(result.cubewheel2_comm_error == false); + TEST_ASSERT_TRUE(result.cubewheel3_comm_error == true); + TEST_ASSERT_TRUE(result.cubestar_comm_error == false); + TEST_ASSERT_TRUE(result.magnetometer_range_error == true); + TEST_ASSERT_TRUE(result.cam1_sram_overcurrent_detected == true); + TEST_ASSERT_TRUE(result.cam1_3v3_overcurrent_detected == false); + TEST_ASSERT_TRUE(result.cam1_sensor_busy_error == true); + TEST_ASSERT_TRUE(result.cam1_sensor_detection_error == false); + TEST_ASSERT_TRUE(result.sun_sensor_range_error == true); + TEST_ASSERT_TRUE(result.cam2_sram_overcurrent_detected == false); + TEST_ASSERT_TRUE(result.cam2_3v3_overcurrent_detected == true); + TEST_ASSERT_TRUE(result.cam2_sensor_busy_error == true); + TEST_ASSERT_TRUE(result.cam2_sensor_detection_error == true); + TEST_ASSERT_TRUE(result.nadir_sensor_range_error == false); + TEST_ASSERT_TRUE(result.rate_sensor_range_error == false); + TEST_ASSERT_TRUE(result.wheel_speed_range_error == false); + TEST_ASSERT_TRUE(result.coarse_sun_sensor_error == false); + TEST_ASSERT_TRUE(result.startracker_match_error == false); + TEST_ASSERT_TRUE(result.startracker_overcurrent_detected == false); + + return 0; + +} + +uint8_t TEST_EXEC__ADCS_pack_to_raw_star_tracker_struct() { + uint8_t input_params[57] = {0xae, 0xbc, 0x22, 0x53, 0x78, 0x37, 0x48, 0x83, 0x49, 0x85, 0x74, 0x78, + 0x90, 0xab, 0x89, 0x09, 0x0e, 0x97, 0x89, 0xc8, 0x88, 0x7d, 0x09, 0x0e, + 0x07, 0x90, 0xd0, 0x9c, 0xed, 0xc9, 0x07, 0xac, 0x0b, 0x70, 0xe7, 0x7d, + 0xc0, 0x9e, 0xae, 0xbc, 0x22, 0x53, 0x78, 0x37, 0x48, 0x83, 0x49, 0x85, + 0x74, 0x78, 0x90, 0xab, 0x89, 0xae}; + + ADCS_raw_star_tracker_struct_t result; + ADCS_pack_to_raw_star_tracker_struct(input_params, &result); + + TEST_ASSERT_TRUE(result.num_stars_detected == 174); + TEST_ASSERT_TRUE(result.star_image_noise == 188); + TEST_ASSERT_TRUE(result.invalid_stars == 34); + TEST_ASSERT_TRUE(result.num_stars_identified == 83); + TEST_ASSERT_TRUE(result.identification_mode == 120); + TEST_ASSERT_TRUE(result.image_dark_value == 55); + TEST_ASSERT_TRUE(result.image_capture_success == false); + TEST_ASSERT_TRUE(result.detection_success == false); + TEST_ASSERT_TRUE(result.identification_success == false); + TEST_ASSERT_TRUE(result.attitude_success == true); + TEST_ASSERT_TRUE(result.processing_time_error == false); + TEST_ASSERT_TRUE(result.tracking_module_enabled == false); + TEST_ASSERT_TRUE(result.prediction_enabled == true); + TEST_ASSERT_TRUE(result.comms_error == false); + TEST_ASSERT_TRUE(result.sample_period == 18819); + TEST_ASSERT_TRUE(result.star1_confidence == 133); + TEST_ASSERT_TRUE(result.star2_confidence == 116); + TEST_ASSERT_TRUE(result.star3_confidence == 120); + TEST_ASSERT_TRUE(result.magnitude_star1 == 43920); + TEST_ASSERT_TRUE(result.magnitude_star2 == 2441); + TEST_ASSERT_TRUE(result.magnitude_star3 == 38670); + TEST_ASSERT_TRUE(result.catalogue_star1 == 51337); + TEST_ASSERT_TRUE(result.centroid_x_star1 == 32136); + TEST_ASSERT_TRUE(result.centroid_y_star1 == 3593); + TEST_ASSERT_TRUE(result.catalogue_star2 == 36871); + TEST_ASSERT_TRUE(result.centroid_x_star2 == -25392); + TEST_ASSERT_TRUE(result.centroid_y_star2 == -13843); + TEST_ASSERT_TRUE(result.catalogue_star3 == 44039); + TEST_ASSERT_TRUE(result.centroid_x_star3 == 28683); + TEST_ASSERT_TRUE(result.centroid_y_star3 == 32231); + TEST_ASSERT_TRUE(result.capture_time_ms == 40640); + TEST_ASSERT_TRUE(result.detection_time_ms == 48302); + TEST_ASSERT_TRUE(result.identification_time_ms == 21282); + TEST_ASSERT_TRUE(result.x_axis_rate_micro == 1420000); + TEST_ASSERT_TRUE(result.y_axis_rate_micro == -3192800); + TEST_ASSERT_TRUE(result.z_axis_rate_micro == -3141500); + TEST_ASSERT_TRUE(result.q0_micro == 3083600); + TEST_ASSERT_TRUE(result.q1_micro == -2161600); + TEST_ASSERT_TRUE(result.q2_micro == -2085500); + + return 0; +} + + +uint8_t TEST_EXEC__ADCS_pack_to_unix_time_ms() { + uint8_t input_params[6] = {0x56, 0x8b, 0x21, 0x67, 0x62, 0x02}; + uint64_t result; + + ADCS_pack_to_unix_time_ms(input_params, &result); + TEST_ASSERT_TRUE(result == 1730251606610); + + return 0; +} + +uint8_t TEST_EXEC__ADCS_pack_to_sd_log_config_struct() { + uint8_t input_params[13] = {0x56, 0x8b, 0x21, 0x67, 0x62, 0x02, 0x8c, 0x11, 0x62, 0x02, 0x8c, 0x11, 0x01}; + ADCS_sd_log_config_struct result_struct; + + ADCS_pack_to_sd_log_config_struct(input_params, 1, &result_struct); + + for (uint8_t i = 0; i < 10; i++) { + TEST_ASSERT_TRUE((result_struct.log_bitmask)[i] == input_params[i]); + } + + TEST_ASSERT_TRUE(result_struct.log_period == 4492); + TEST_ASSERT_TRUE(result_struct.which_sd == ADCS_SD_LOG_DESTINATION_SECONDARY_SD); + + return 0; +} + +uint8_t TEST_EXEC__ADCS_convert_double_to_string() { + char output_string[20]; + + TEST_ASSERT_TRUE(ADCS_convert_double_to_string(-2.5,6,&output_string[0],20) == 0); + TEST_ASSERT_TRUE(strcmp(output_string, "-2.500000") == 0); + + TEST_ASSERT_TRUE(ADCS_convert_double_to_string(1000,2,&output_string[0],20) == 0); + TEST_ASSERT_TRUE(strcmp(output_string, "1000.00") == 0); + + TEST_ASSERT_TRUE(ADCS_convert_double_to_string(-4,3,&output_string[0],20) == 0); + TEST_ASSERT_TRUE(strcmp(output_string, "-4.000") == 0); + + TEST_ASSERT_TRUE(ADCS_convert_double_to_string(-0.9,1,&output_string[0],20) == 0); + TEST_ASSERT_TRUE(strcmp(output_string, "-0.9") == 0); + + return 0; + +} \ No newline at end of file diff --git a/firmware/Core/Src/unit_tests/unit_test_inventory.c b/firmware/Core/Src/unit_tests/unit_test_inventory.c index d07d59763..6da33f41d 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -60,229 +60,265 @@ const TEST_Definition_t TEST_definitions[] = { { .test_func = TEST_EXEC__ADCS_pack_to_ack_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Ack_Struct" + .test_func_name = "ADCS_pack_to_ack_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_identification_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Identification_Struct" + .test_func_name = "ADCS_pack_to_identification_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_program_status_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Program_Status_Struct" + .test_func_name = "ADCS_pack_to_program_status_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_comms_status_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Comms_Status_Struct" + .test_func_name = "ADCS_pack_to_comms_status_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_power_control_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Power_Control_Struct" + .test_func_name = "ADCS_pack_to_power_control_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_angular_rates_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Angular_Rates_Struct" + .test_func_name = "ADCS_pack_to_angular_rates_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_llh_position_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_LLH_Position_Struct" + .test_func_name = "ADCS_pack_to_llh_position_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_unix_time_save_mode_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Unix_Time_Save_Mode_Struct" + .test_func_name = "ADCS_pack_to_unix_time_save_mode_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_orbit_params_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Orbit_Params_Struct" + .test_func_name = "ADCS_pack_to_orbit_params_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_rated_sensor_rates_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Rated_Sensor_Rates_Struct" + .test_func_name = "ADCS_pack_to_rated_sensor_rates_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_wheel_speed_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Wheel_Speed_Struct" + .test_func_name = "ADCS_pack_to_wheel_speed_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_magnetorquer_command_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Magnetorquer_Command_Struct" + .test_func_name = "ADCS_pack_to_magnetorquer_command_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_magnetometer_values_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_Magnetometer_Values_Struct" + .test_func_name = "ADCS_pack_to_raw_magnetometer_values_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_fine_angular_rates_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Fine_Angular_Rates_Struct" + .test_func_name = "ADCS_pack_to_fine_angular_rates_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_magnetometer_config_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Magnetometer_Config_Struct" + .test_func_name = "ADCS_pack_to_magnetometer_config_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_commanded_attitude_angles_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Commanded_Attitude_Angles_Struct" + .test_func_name = "ADCS_pack_to_commanded_attitude_angles_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_estimation_params_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Estimation_Params_Struct" + .test_func_name = "ADCS_pack_to_estimation_params_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_augmented_sgp4_params_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Augmented_SGP4_Params_Struct" + .test_func_name = "ADCS_pack_to_augmented_sgp4_params_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_tracking_controller_target_reference_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Tracking_Controller_Target_Reference_Struct" + .test_func_name = "ADCS_pack_to_tracking_controller_target_reference_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_rate_gyro_config_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Rate_Gyro_Config_Struct" + .test_func_name = "ADCS_pack_to_rate_gyro_config_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_estimated_attitude_angles_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Estimated_Attitude_Angles_Struct" + .test_func_name = "ADCS_pack_to_estimated_attitude_angles_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_magnetic_field_vector_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Magnetic_Field_Vector_Struct" + .test_func_name = "ADCS_pack_to_magnetic_field_vector_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_fine_sun_vector_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Fine_Sun_Vector_Struct" + .test_func_name = "ADCS_pack_to_fine_sun_vector_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_nadir_vector_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Nadir_Vector_Struct" + .test_func_name = "ADCS_pack_to_nadir_vector_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_commanded_wheel_speed_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Commanded_Wheel_Speed_Struct" + .test_func_name = "ADCS_pack_to_commanded_wheel_speed_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_igrf_magnetic_field_vector_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_IGRF_Magnetic_Field_Vector_Struct" + .test_func_name = "ADCS_pack_to_igrf_magnetic_field_vector_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_quaternion_error_vector_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Quaternion_Error_Vector_Struct" + .test_func_name = "ADCS_pack_to_quaternion_error_vector_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_estimated_gyro_bias_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Estimated_Gyro_Bias_Struct" + .test_func_name = "ADCS_pack_to_estimated_gyro_bias_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_estimation_innovation_vector_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Estimation_Innovation_Vector_Struct" + .test_func_name = "ADCS_pack_to_estimation_innovation_vector_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_cam1_sensor_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_Cam1_Sensor_Struct" + .test_func_name = "ADCS_pack_to_raw_cam1_sensor_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_cam2_sensor_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_Cam2_Sensor_Struct" + .test_func_name = "ADCS_pack_to_raw_cam2_sensor_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_Coarse_Sun_Sensor_1_to_6_Struct" + .test_func_name = "ADCS_pack_to_raw_coarse_sun_sensor_1_to_6_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_Coarse_Sun_Sensor_7_to_10_Struct" + .test_func_name = "ADCS_pack_to_raw_coarse_sun_sensor_7_to_10_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_cubecontrol_current_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_CubeControl_Current_Struct" + .test_func_name = "ADCS_pack_to_cubecontrol_current_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_gps_status_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_GPS_Status_Struct" + .test_func_name = "ADCS_pack_to_raw_gps_status_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_gps_time_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_GPS_Time_Struct" + .test_func_name = "ADCS_pack_to_raw_gps_time_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_raw_gps_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Raw_GPS_Struct" + .test_func_name = "ADCS_pack_to_raw_gps_struct" }, { .test_func = TEST_EXEC__ADCS_pack_to_measurements_struct, .test_file = "unit_tests/test_adcs", - .test_func_name = "ADCS_Pack_to_Measurements_Struct" + .test_func_name = "ADCS_pack_to_measurements_struct" + }, + + { + .test_func = TEST_EXEC__ADCS_pack_to_acp_execution_state_struct, + .test_file = "unit_tests/test_adcs", + .test_func_name = "ADCS_pack_to_acp_execution_state_struct" + }, + + { + .test_func = TEST_EXEC__ADCS_pack_to_current_state_1_struct, + .test_file = "unit_tests/test_adcs", + .test_func_name = "ADCS_pack_to_current_state_1_struct" + }, + + { + .test_func = TEST_EXEC__ADCS_pack_to_raw_star_tracker_struct, + .test_file = "unit_tests/test_adcs", + .test_func_name = "ADCS_pack_to_raw_star_tracker_struct" + }, + + { + .test_func = TEST_EXEC__ADCS_pack_to_unix_time_ms, + .test_file = "unit_tests/test_adcs", + .test_func_name = "ADCS_pack_to_unix_time_ms" + }, + + { + .test_func = TEST_EXEC__ADCS_pack_to_sd_log_config_struct, + .test_file = "unit_tests/test_adcs", + .test_func_name = "ADCS_pack_to_sd_log_config_struct" + }, + + { + .test_func = TEST_EXEC__ADCS_convert_double_to_string, + .test_file = "unit_tests/test_adcs", + .test_func_name = "ADCS_convert_double_to_string" }, // ****************** END SECTION: test_adcs ******************