From c7bda9660bc41ac89e02154738ed33081c25ce1f Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:43:21 -0600 Subject: [PATCH 01/22] fix numbers of telecommand args --- firmware/Core/Src/telecommands/telecommand_adcs.c | 4 ++-- firmware/Core/Src/telecommands/telecommand_definitions.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/Core/Src/telecommands/telecommand_adcs.c b/firmware/Core/Src/telecommands/telecommand_adcs.c index c8f8e7a16..b56e072ce 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -259,7 +259,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 +311,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) { diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index f10edb209..d294c80d5 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -289,7 +289,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, }, { @@ -313,7 +313,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, }, { From 9777f589272b08bf2cbf1a829b36ae353afed846 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:43:36 -0600 Subject: [PATCH 02/22] snprintf doesn't support floats --- .../Src/adcs_drivers/adcs_types_to_json.c | 57 ++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) 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..5ef088b91 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -195,12 +195,37 @@ 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 into pairs of ints instead + + int32_t data_int_portions[8]; + + data_int_portions[0] = (int32_t)(data->inclination_deg); + data_int_portions[1] = (int32_t)(data->eccentricity); + data_int_portions[2] = (int32_t)(data->ascending_node_right_ascension_deg); + data_int_portions[3] = (int32_t)(data->perigee_argument_deg); + data_int_portions[4] = (int32_t)(data->b_star_drag_term); + data_int_portions[5] = (int32_t)(data->mean_motion_orbits_per_day); + data_int_portions[6] = (int32_t)(data->mean_anomaly_deg); + data_int_portions[7] = (int32_t)(data->epoch_year_point_day); + + int32_t data_decimal_portions[8]; + data_decimal_portions[0] = (int32_t)((data->inclination_deg - data_int_portions[0]) * 1000000); + data_decimal_portions[1] = (int32_t)((data->eccentricity - data_int_portions[1]) * 1000000); + data_decimal_portions[2] = (int32_t)((data->ascending_node_right_ascension_deg - data_int_portions[2]) * 1000000); + data_decimal_portions[3] = (int32_t)((data->perigee_argument_deg - data_int_portions[3]) * 1000000); + data_decimal_portions[4] = (int32_t)((data->b_star_drag_term - data_int_portions[4]) * 1000000); + data_decimal_portions[5] = (int32_t)((data->mean_motion_orbits_per_day - data_int_portions[5]) * 1000000); + data_decimal_portions[6] = (int32_t)((data->mean_anomaly_deg - data_int_portions[6]) * 1000000); + data_decimal_portions[7] = (int32_t)((data->epoch_year_point_day - data_int_portions[7]) * 1000000); + + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, "{\"inclination_deg\":%ld.%ld,\"eccentricity\":%ld.%ld,\"ascending_node_right_ascension_deg\":%ld.%ld,\"perigee_argument_deg\":%ld.%ld,\"b_star_drag_term\":%ld.%ld,\"mean_motion_orbits_per_day\":%ld.%ld,\"mean_anomaly_deg\":%ld.%ld,\"epoch_year_point_day\":%ld.%ld}", + data_int_portions[0], data_decimal_portions[0], data_int_portions[1], data_decimal_portions[1], data_int_portions[2], data_decimal_portions[2], data_int_portions[3], data_decimal_portions[3], data_int_portions[4], data_decimal_portions[4], data_int_portions[5], data_decimal_portions[5], data_int_portions[6], data_decimal_portions[6], data_int_portions[7], data_decimal_portions[7]); + if (snprintf_ret < 0) { return 2; // Error: snprintf encoding error } @@ -774,15 +799,31 @@ 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 we convert them to a pair of ints + + int16_t data_int_portions[8]; + + data_int_portions[0] = (int16_t)(data->cubecontrol_3v3_current_mA); + data_int_portions[1] = (int16_t)(data->cubecontrol_5v_current_mA); + data_int_portions[2] = (int16_t)(data->cubecontrol_vbat_current_mA); + + uint8_t data_decimal_portions[8]; + + data_decimal_portions[0] = (uint8_t)((data->cubecontrol_3v3_current_mA - data_int_portions[0]) * 10); + data_decimal_portions[1] = (uint8_t)((data->cubecontrol_5v_current_mA - data_int_portions[1]) * 10); + data_decimal_portions[2] = (uint8_t)((data->cubecontrol_vbat_current_mA - data_int_portions[2]) * 10); + // 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\":%d.%d,\"cubecontrol_5v_current_mA\":%d.%d," + "\"cubecontrol_vbat_current_mA\":%d.%d}", + data_int_portions[0], data_decimal_portions[0], + data_int_portions[1], data_decimal_portions[1], + data_int_portions[2], data_decimal_portions[2]); if (snprintf_ret < 0) { return 2; // Error: snprintf encoding error From de7b5044851f87d5ecd2af35165cee0911059537 Mon Sep 17 00:00:00 2001 From: Kale Fordham <71345320+KaleF07@users.noreply.github.com> Date: Sat, 5 Oct 2024 18:26:54 -0600 Subject: [PATCH 03/22] Updated flash driver and littlefs helper to use NAND memory module (MT29F1G Series) (#177) * Replaced all flash driver code for NAND chip Replaced all previous code for FLASH driver for NAND flash module. * Updated memory module configuration Updated littlefs_helper.c configuration to use NAND memory module configuration values * Changes to flash_driver and flash_telecommand_defs Made changes to flash to handle full page reading and writing, added flash telecommand that unblocks block locks. * Minor changes to flash telecommands Minor changes to flash read hex telecommand for testing, added docstring for FLASH_reset function and telecommand. * Cleaned code from testing Removed all debugging printing lines to prepare for merging. Added new timeout variable for handling HAL_SPI transmits of 2176 bytes. * Removed Unblock_block_lock telecommand, Removed the telecommand unblock_block_locks and added automatic execution during write functions, minor changes to other flash telecommands. * Update LFS_benchmark_write_read to write many files * Fixed improper page addressing issue Fixed issue with improper page addressing where littlefs sent page address in bytes rather than the actual page address. * Minor changes based on PR review Removed unnecessary lines of code and added additional helpful comments based on PR comments * Updated littlefs benchmark test function Updated the littlefs benchmark write & read function to test both writing to the same file and to a new file. * Minor changes to fs benchmark file * Update littlefs_benchmark.c Added additional parameter in benchmark docstring. * Updated FLASH_MAX_BYTES_PER_PAGE Updated the naming and usage of variable FLASH_MAX_BYTES_PER_PAGE that keeps track of the maximum bytes per page for the FLASH NAND module. * Update flash_driver.h * Updated LFS_benchmark_write_read Updated name of LFS_benchmark_write_read_enum_t and added else statement for mode within function. --------- Co-authored-by: Saksham Puri <84263133+Saksham-P@users.noreply.github.com> Co-authored-by: parker-research <166864283+parker-research@users.noreply.github.com> --- firmware/Core/Inc/littlefs/flash_driver.h | 69 ++- .../Core/Inc/littlefs/littlefs_benchmark.h | 10 +- .../Inc/telecommands/flash_telecommand_defs.h | 4 + firmware/Core/Src/littlefs/flash_benchmark.c | 2 +- firmware/Core/Src/littlefs/flash_driver.c | 483 ++++++++++++++++-- .../Core/Src/littlefs/flash_testing_demos.c | 2 +- .../Core/Src/littlefs/littlefs_benchmark.c | 61 ++- firmware/Core/Src/littlefs/littlefs_driver.c | 8 +- firmware/Core/Src/littlefs/littlefs_helper.c | 14 +- .../Src/telecommands/flash_telecommand_defs.c | 91 +++- .../Src/telecommands/lfs_telecommand_defs.c | 2 +- .../telecommands/telecommand_definitions.c | 6 + 12 files changed, 640 insertions(+), 112 deletions(-) diff --git a/firmware/Core/Inc/littlefs/flash_driver.h b/firmware/Core/Inc/littlefs/flash_driver.h index 11db2a776..46b5f838e 100644 --- a/firmware/Core/Inc/littlefs/flash_driver.h +++ b/firmware/Core/Inc/littlefs/flash_driver.h @@ -8,44 +8,58 @@ #include "littlefs/lfs.h" - /*----------------------------- CONFIG VARIABLES ----------------------------- */ - -// number of CS pins available +// Number of CS pins available #define FLASH_NUMBER_OF_FLASH_DEVICES 8 // TODO: update to 8, or 10 with FRAM maybe -#define FLASH_CHIP_SIZE_BYTES 67108864 // 64MiB // TODO: update -/*-----------------------------COMMAND VARIABLES-----------------------------*/ -// All comments in this section refer to the "S25FL512S 512Mb (64MB)" Datasheet by Infineon +// Total size of a singular Memory Module in bytes +#define FLASH_CHIP_SIZE_BYTES 134217728 // 128MiB // TODO: update + +// Number of pages contained within a single block of memory module +#define FLASH_CHIP_PAGES_PER_BLOCK 64 + +// NAND Flash Memory Datasheet https://www.farnell.com/datasheets/3151163.pdf +// Each page is divided into a 2048-byte data storage region, and a 128 bytes spare area (2176 bytes total). +#define FLASH_MAX_BYTES_PER_PAGE 2048 + +/*-------------------------------FLASH FEATURES-------------------------------*/ +// Features that can be accessed using Get Feature command -static const uint8_t FLASH_CMD_READ_3_BYTE_ADDR = 0x03; // Read - Section 9.4.1 -static const uint8_t FLASH_CMD_READ_4_BYTE_ADDR = 0x13; // Read - Section 9.4.1 +static const uint8_t FLASH_FEAT_BLOCK_LOCK = 0xA0; // Block Lock + +static const uint8_t FLASH_FEAT_CONFIG = 0xB0; // Configuration Register + +static const uint8_t FLASH_FEAT_STATUS = 0xC0; // Status Register + +static const uint8_t FLASH_FEAT_DIE_SELECT = 0xD0; // Die Select + +/*-----------------------------COMMAND VARIABLES-----------------------------*/ +// All comments in this section refer to the "MT29F1G 1Gib (128MiB)" Datasheet by Micron -static const uint8_t FLASH_CMD_WRITE_3_BYTE_ADDR = 0x02; // Page Program - Section 9.5.2 -static const uint8_t FLASH_CMD_WRITE_4_BYTE_ADDR = 0x12; // Page Program - Section 9.5.2 +static const uint8_t FLASH_CMD_PAGE_READ = 0x13; // Read Page +static const uint8_t FLASH_CMD_READ_FROM_CACHE = 0x03; // Read Page -static const uint8_t FLASH_CMD_SECTOR_ERASE_3_BYTE_ADDR = 0xD8; // Sector Erase - Section 9.6.1 -static const uint8_t FLASH_CMD_SECTOR_ERASE_4_BYTE_ADDR = 0xDC; // Sector Erase - Section 9.6.1 +static const uint8_t FLASH_CMD_PROGRAM_LOAD = 0x02; // Load Program into cache resgiters +static const uint8_t FLASH_CMD_PROGRAM_EXEC = 0x10; // Send data from cache to memory -static const uint8_t FLASH_CMD_WRITE_DISABLE = 0x04; // Write Disable - Section 9.3.9 -static const uint8_t FLASH_CMD_WRITE_ENABLE = 0x06; // Write Enable - Section 9.3.8 +static const uint8_t FLASH_CMD_BLOCK_ERASE = 0xD8; // Block Erase -static const uint8_t FLASH_CMD_READ_STATUS_REG_1 = 0x05; // Read Status 1 - Section 9.3.1, Byte Descriptions in 7.6.1 -static const uint8_t FLASH_CMD_READ_STATUS_REG_2 = 0x07; // Read Status 2 - Section 9.3.2 -static const uint8_t FLASH_CMD_CLEAR_STATUS = 0x30; // Clear Status - Section 9.3.10 +static const uint8_t FLASH_CMD_WRITE_ENABLE = 0x06; // Write Enable +static const uint8_t FLASH_CMD_WRITE_DISABLE = 0x04; // Write Disable -static const uint8_t FLASH_CMD_READ_CONFIG = 0x35; // Read Config - Section 9.3.3 +static const uint8_t FLASH_CMD_GET_FEATURES = 0x0F; // Get Features +static const uint8_t FLASH_CMD_SET_FEATURES = 0x1F; // Set Features -static const uint8_t FLASH_CMD_SOFTWARE_RESET = 0xF0; // Software Reset - Section 9.9.1 +static const uint8_t FLASH_CMD_READ_ID = 0x9F; // Read ID (0x2C 0x14) -static const uint8_t FLASH_CMD_READ_ID = 0x9F; // "RDID" - Read ID - Section 9.2.2 +static const uint8_t FLASH_CMD_RESET = 0xFF; // Reset operation // ------------------- Status Register 1 - Byte Masks ------------------- -// Source: Section 7.6.1 +// Source: Table 5 static const uint8_t FLASH_SR1_WRITE_IN_PROGRESS_MASK = (1 << 0); static const uint8_t FLASH_SR1_WRITE_ENABLE_LATCH_MASK = (1 << 1); -static const uint8_t FLASH_SR1_PROGRAMMING_ERROR_MASK = (1 << 6); -static const uint8_t FLASH_SR1_ERASE_ERROR_MASK = (1 << 5); +static const uint8_t FLASH_SR1_PROGRAMMING_ERROR_MASK = (1 << 3); +static const uint8_t FLASH_SR1_ERASE_ERROR_MASK = (1 << 2); /*-----------------------------FLASH ERROR CODES-----------------------------*/ typedef enum { @@ -62,13 +76,16 @@ typedef enum { /*-----------------------------DRIVER FUNCTIONS-----------------------------*/ void FLASH_activate_chip_select(uint8_t chip_number); void FLASH_deactivate_chip_select(); +FLASH_error_enum_t FLASH_unblock_block_lock(SPI_HandleTypeDef *hspi, uint8_t chip_number, uint8_t *buf); FLASH_error_enum_t FLASH_read_status_register(SPI_HandleTypeDef *hspi, uint8_t chip_number, uint8_t *buf); +FLASH_error_enum_t FLASH_read_block_lock_register(SPI_HandleTypeDef *hspi, uint8_t chip_number, uint8_t *buf); FLASH_error_enum_t FLASH_write_enable(SPI_HandleTypeDef *hspi, uint8_t chip_number); FLASH_error_enum_t FLASH_write_disable(SPI_HandleTypeDef *hspi, uint8_t chip_number); -FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t addr); -FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t addr, uint8_t *packet_buffer, lfs_size_t packet_buffer_len); -FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t addr, uint8_t *rx_buffer, lfs_size_t rx_buffer_len); +FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t page); +FLASH_error_enum_t FLASH_write_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t page, uint8_t *packet_buffer, lfs_size_t packet_buffer_len); +FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t page, uint8_t *rx_buffer, lfs_size_t rx_buffer_len); FLASH_error_enum_t FLASH_is_reachable(SPI_HandleTypeDef *hspi, uint8_t chip_number); +FLASH_error_enum_t FLASH_reset(SPI_HandleTypeDef *hspi, uint8_t chip_number); #endif /* __INCLUDE_GUARD__FLASH_DRIVER_H__ */ diff --git a/firmware/Core/Inc/littlefs/littlefs_benchmark.h b/firmware/Core/Inc/littlefs/littlefs_benchmark.h index e3686e575..e9b512d36 100644 --- a/firmware/Core/Inc/littlefs/littlefs_benchmark.h +++ b/firmware/Core/Inc/littlefs/littlefs_benchmark.h @@ -1,9 +1,17 @@ #ifndef __INCLUDE_GUARD__LITTLEFS_BENCHMARK_H__ #define __INCLUDE_GUARD__LITTLEFS_BENCHMARK_H__ +/*-----------------------------INCLUDES----------------------------------------*/ #include +/*-------------------------------BENCHMARK FEATURES----------------------------*/ +typedef enum { + LFS_SINGLE_FILE, + LFS_NEW_FILE +} LFS_benchmark_mode_enum_t; -uint8_t LFS_benchmark_write_read(uint16_t write_chunk_size, uint16_t write_chunk_count, char* response_str, uint16_t response_str_len); +/*-----------------------------BENCHMARK FUNCTIONS-----------------------------*/ +uint8_t LFS_benchmark_write_read(uint16_t write_chunk_size, uint16_t write_chunk_count, char* response_str, uint16_t response_str_len, LFS_benchmark_mode_enum_t mode); +uint8_t LFS_benchmark_write_read_single_and_new(uint16_t write_chunk_size, uint16_t write_chunk_count, char* response_str, uint16_t response_str_len); #endif // __INCLUDE_GUARD__LITTLEFS_BENCHMARK_H__ diff --git a/firmware/Core/Inc/telecommands/flash_telecommand_defs.h b/firmware/Core/Inc/telecommands/flash_telecommand_defs.h index ac8b83c4b..d7a3e16b1 100644 --- a/firmware/Core/Inc/telecommands/flash_telecommand_defs.h +++ b/firmware/Core/Inc/telecommands/flash_telecommand_defs.h @@ -5,6 +5,7 @@ #include #include "telecommands/telecommand_definitions.h" +/*----------------------------- TELECOMMAND DEFINITIONS ----------------------------- */ uint8_t TCMDEXEC_flash_activate_each_cs(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len); @@ -22,5 +23,8 @@ uint8_t TCMDEXEC_flash_erase(const char *args_str, TCMD_TelecommandChannel_enum_ uint8_t TCMDEXEC_flash_benchmark_erase_write_read(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len); + +uint8_t TCMDEXEC_flash_reset(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len); #endif /* __INCLUDE_GUARD__FLASH_TELECOMMAND_DEFS_H__ */ diff --git a/firmware/Core/Src/littlefs/flash_benchmark.c b/firmware/Core/Src/littlefs/flash_benchmark.c index 6b16e8376..2c8427c45 100644 --- a/firmware/Core/Src/littlefs/flash_benchmark.c +++ b/firmware/Core/Src/littlefs/flash_benchmark.c @@ -45,7 +45,7 @@ uint8_t FLASH_benchmark_erase_write_read(uint8_t chip_num, uint32_t test_data_ad } // TODO: for very large writes, split into multiple writes (instead of allocating the whole amount on the stack) const uint32_t write_send_start_time = HAL_GetTick(); - const FLASH_error_enum_t write_result = FLASH_write(hspi_ptr, chip_num, test_data_address, write_buffer, test_data_length); + const FLASH_error_enum_t write_result = FLASH_write_data(hspi_ptr, chip_num, test_data_address, write_buffer, test_data_length); if (write_result != 0) { snprintf( &response_str[strlen(response_str)], diff --git a/firmware/Core/Src/littlefs/flash_driver.c b/firmware/Core/Src/littlefs/flash_driver.c index f567f1cc2..71e5b017a 100644 --- a/firmware/Core/Src/littlefs/flash_driver.c +++ b/firmware/Core/Src/littlefs/flash_driver.c @@ -11,6 +11,8 @@ // 512 bytes should take 2ms at 2Mbps. // TODO: ^ investigate the HAL_SPI_Receive overhead (2ms expected, >5ms observed) #define FLASH_HAL_TIMEOUT_MS 10 +// FIXME: For sending or receiving 2176 bytes, the timeout should be >10ms. Created temporary fix for now. +#define FLASH_HAL_MAX_BYTE_TIMEOUT_MS 50 // The following timeout values are sourced from Section 11.3.1, Table 56: "CFI system interface string" // and are interpreted using: https://www.infineon.com/dgdl/Infineon-AN98488_Quick_Guide_to_Common_Flash_Interface-ApplicationNotes-v05_00-EN.pdf @@ -85,6 +87,79 @@ void FLASH_deactivate_chip_select() HAL_GPIO_WritePin(PIN_MEM_NCS_FRAM_1_GPIO_Port, PIN_MEM_NCS_FRAM_1_Pin, GPIO_PIN_SET); } +/** + * @brief Unblocks all blocked blocks of memory on the NAND flash memory module + * + * @param hspi - Pointer to the SPI HAL handle + * @param chip_number - the chip select number to activate + * @param buf - Pointer to a buffer to store the new Block Lock Register value. Length: 1 byte. + * @return FLASH_ERR_OK on success, < 0 on failure + * + * @note unblocking blocks of memory is necessary to write to memory + */ +FLASH_error_enum_t FLASH_unblock_block_lock(SPI_HandleTypeDef *hspi, uint8_t chip_number, uint8_t *buf) { + + static const uint8_t data_bytes = 0x00; + + // Send SET FEATURES command + FLASH_activate_chip_select(chip_number); + const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_SET_FEATURES, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result_1 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_1 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Send the byte address of block lock register + const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_FEAT_BLOCK_LOCK, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the byte, check why + if (tx_result_2 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_2 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Send the data bytes of what we want the Block Lock register to be + const HAL_StatusTypeDef tx_result_3 = HAL_SPI_Transmit(hspi, (uint8_t *)&data_bytes, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the byte, check why + if (tx_result_3 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_3 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Call a function that reads the block lock register here to check if it changed anything + const FLASH_error_enum_t block_lock_result_2 = FLASH_read_block_lock_register(hspi, chip_number, buf); + if (block_lock_result_2 != FLASH_ERR_OK) { + FLASH_deactivate_chip_select(); + + if (block_lock_result_2 == FLASH_ERR_SPI_TRANSMIT_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + FLASH_deactivate_chip_select(); + return FLASH_ERR_OK; +} + /** * @brief Read Status Register and store the values in given buffer * @param hspi - Pointer to the SPI HAL handle @@ -94,19 +169,95 @@ void FLASH_deactivate_chip_select() */ FLASH_error_enum_t FLASH_read_status_register(SPI_HandleTypeDef *hspi, uint8_t chip_number, uint8_t *buf) { + // Send GET FEATURES command FLASH_activate_chip_select(chip_number); - const HAL_StatusTypeDef tx_result = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_READ_STATUS_REG_1, 1, FLASH_HAL_TIMEOUT_MS); - if (tx_result != HAL_OK) { + const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_GET_FEATURES, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result_1 != HAL_OK) { FLASH_deactivate_chip_select(); - if (tx_result == HAL_TIMEOUT) { + if (tx_result_1 == HAL_TIMEOUT) { return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; } return FLASH_ERR_SPI_TRANSMIT_FAILED; } + // Send the byte address of status register + const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_FEAT_STATUS, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the byte, check why + if (tx_result_2 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_2 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Receive the Status Register bits const HAL_StatusTypeDef rx_result = HAL_SPI_Receive(hspi, (uint8_t *)buf, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't receive the byte, check why + if (rx_result != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (rx_result == HAL_TIMEOUT) { + return FLASH_ERR_SPI_RECEIVE_TIMEOUT; + } + + return FLASH_ERR_SPI_RECEIVE_FAILED; + } + + FLASH_deactivate_chip_select(); + return FLASH_ERR_OK; +} + +/** + * @brief Read Block Lock Register and store the values in given buffer + * @param hspi - Pointer to the SPI HAL handle + * @param chip_number - the chip select number to activate + * @param buf - Pointer to a buffer to store Block Lock Register value. Length: 1 byte. + * @retval FLASH_ERR_OK on success, < 0 on failure + */ +FLASH_error_enum_t FLASH_read_block_lock_register(SPI_HandleTypeDef *hspi, uint8_t chip_number, uint8_t *buf) +{ + // Send GET FEATURES command + FLASH_activate_chip_select(chip_number); + const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_GET_FEATURES, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result_1 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_1 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Send the byte address of block lock register + const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_FEAT_BLOCK_LOCK, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the byte, check why + if (tx_result_2 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_2 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Receive the Block Lock Register bits + const HAL_StatusTypeDef rx_result = HAL_SPI_Receive(hspi, (uint8_t *)buf, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't receive the byte, check why if (rx_result != HAL_OK) { FLASH_deactivate_chip_select(); @@ -132,9 +283,12 @@ FLASH_error_enum_t FLASH_write_enable(SPI_HandleTypeDef *hspi, uint8_t chip_numb // Buffer to store status register value uint8_t status_reg_buffer[1] = {0}; + // Send the WRITE ENABLE Command FLASH_activate_chip_select(chip_number); const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_WRITE_ENABLE, 1, FLASH_HAL_TIMEOUT_MS); FLASH_deactivate_chip_select(); + + // If couldn't send the command, check why if (tx_result_1 != HAL_OK) { if (tx_result_1 == HAL_TIMEOUT) { @@ -148,6 +302,7 @@ FLASH_error_enum_t FLASH_write_enable(SPI_HandleTypeDef *hspi, uint8_t chip_numb const uint32_t start_loop_time_ms = HAL_GetTick(); while (1) { + // Get status register bits const FLASH_error_enum_t read_status_result = FLASH_read_status_register(hspi, chip_number, status_reg_buffer); if (read_status_result != FLASH_ERR_OK) { FLASH_deactivate_chip_select(); @@ -187,9 +342,12 @@ FLASH_error_enum_t FLASH_write_disable(SPI_HandleTypeDef *hspi, uint8_t chip_num // Buffer to store status register value uint8_t status_reg_buffer[1] = {0}; + // Send WRITE DISABLE Command FLASH_activate_chip_select(chip_number); const HAL_StatusTypeDef tx_status = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_WRITE_DISABLE, 1, FLASH_HAL_TIMEOUT_MS); FLASH_deactivate_chip_select(); + + // If couldn't send the command, check why if (tx_status != HAL_OK) { if (tx_status == HAL_TIMEOUT) { @@ -203,6 +361,7 @@ FLASH_error_enum_t FLASH_write_disable(SPI_HandleTypeDef *hspi, uint8_t chip_num const uint32_t start_loop_time_ms = HAL_GetTick(); while (1) { + // Get status register bits const FLASH_error_enum_t read_status_result = FLASH_read_status_register(hspi, chip_number, status_reg_buffer); if (read_status_result != FLASH_ERR_OK) { FLASH_deactivate_chip_select(); @@ -220,9 +379,11 @@ FLASH_error_enum_t FLASH_write_disable(SPI_HandleTypeDef *hspi, uint8_t chip_num return FLASH_ERR_DEVICE_BUSY_TIMEOUT; } - DEBUG_uart_print_str("DEBUG: status_reg = 0x"); - DEBUG_uart_print_array_hex(status_reg_buffer, 1); - DEBUG_uart_print_str("\n"); + if (FLASH_enable_hot_path_debug_logs) { + DEBUG_uart_print_str("DEBUG: status_reg = 0x"); + DEBUG_uart_print_array_hex(status_reg_buffer, 1); + DEBUG_uart_print_str("\n"); + } } // Should never be reached: @@ -230,27 +391,37 @@ FLASH_error_enum_t FLASH_write_disable(SPI_HandleTypeDef *hspi, uint8_t chip_num } /** - * @brief Sends Sector Erase Command + * @brief Sends Block Erase Command * @param hspi - Pointer to the SPI HAL handle * @param chip_number - the chip select number to activate - * @param addr - block number that is to be erased + * @param page - page number to erase the block the page is contained in * @retval FLASH_ERR_OK on success, < 0 on failure */ -FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t addr) +FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t page) { - // Split address into its 4 bytes - uint8_t addr_bytes[4] = {(addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF}; + // Split address into its 3 bytes + uint8_t addr_bytes[3] = {(page >> 16) & 0xFF, (page >> 8) & 0xFF, page & 0xFF}; + + // Set Block Lock Register to 0x00 + uint8_t block_lock_reg_buffer[1] = {0}; + const FLASH_error_enum_t block_lock_result = FLASH_unblock_block_lock(hspi, chip_number, block_lock_reg_buffer); + if (block_lock_result != FLASH_ERR_OK) { + FLASH_deactivate_chip_select(); + return block_lock_result; + } - // Send Write Enable Command + // Send WRITE ENABLE Command const FLASH_error_enum_t wren_result = FLASH_write_enable(hspi, chip_number); if (wren_result != FLASH_ERR_OK) { FLASH_deactivate_chip_select(); return wren_result; } - // Send Sector Erase Command + // Send BLOCK ERASE Command FLASH_activate_chip_select(chip_number); - const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_SECTOR_ERASE_4_BYTE_ADDR, 1, FLASH_HAL_TIMEOUT_MS); + const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_BLOCK_ERASE, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why if (tx_result_1 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -260,7 +431,11 @@ FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs return FLASH_ERR_SPI_TRANSMIT_FAILED; } - const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)addr_bytes, 4, FLASH_HAL_TIMEOUT_MS); + + // Send the address bytes + const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)addr_bytes, 3, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the bytes, check why if (tx_result_2 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -275,10 +450,11 @@ FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs // Buffer to store status register value uint8_t status_reg_buffer[1] = {0}; - // Keep looping as long as device is busy (until the Write Enable Latch is active [1]) + // Keep looping as long as device is busy (until the Operation In Progress bit is active [1]) const uint32_t start_loop_time_ms = HAL_GetTick(); while (1) { + // Get status register bits const FLASH_error_enum_t read_status_result = FLASH_read_status_register(hspi, chip_number, status_reg_buffer); if (read_status_result != FLASH_ERR_OK) { FLASH_deactivate_chip_select(); @@ -302,9 +478,11 @@ FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs return FLASH_ERR_DEVICE_BUSY_TIMEOUT; } - DEBUG_uart_print_str("DEBUG: status_reg = 0x"); - DEBUG_uart_print_array_hex(status_reg_buffer, 1); - DEBUG_uart_print_str("\n"); + if (FLASH_enable_hot_path_debug_logs) { + DEBUG_uart_print_str("DEBUG: status_reg = 0x"); + DEBUG_uart_print_array_hex(status_reg_buffer, 1); + DEBUG_uart_print_str("\n"); + } } // Should never be reached: @@ -315,26 +493,42 @@ FLASH_error_enum_t FLASH_erase(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs * @brief Sends Page Program Command * @param hspi - Pointer to the SPI HAL handle * @param chip_number - the chip select number to activate - * @param addr - block number that is to be written + * @param page - page number the data is to be written to * @param packet_buffer - Pointer to buffer containing data to write * @param packet_buffer_len - integer that indicates the size of the data to write * @retval FLASH_ERR_OK on success, < 0 on failure */ -FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t addr, uint8_t *packet_buffer, lfs_size_t packet_buffer_len) +FLASH_error_enum_t FLASH_write_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t page, uint8_t *packet_buffer, lfs_size_t packet_buffer_len) { - // Split address into its 4 bytes - uint8_t addr_bytes[4] = {(addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF}; + // Split main address into its 3 bytes + uint8_t addr_bytes[3] = {(page >> 16) & 0xFF, (page >> 8) & 0xFF, page & 0xFF}; + + // Define the address where data will be stored in cache register (First 4 bits are dummy bits) + // TODO: Is it fine to always have this at 0? + uint16_t cache_addr = 0x0000; + uint8_t cache_addr_bytes[2] = {(cache_addr >> 8) & 0xFF, cache_addr & 0xFF}; // modify + // check for packet buffer length > 2176 (pg.29 of datasheet, program load) + + // Set Block Lock Register to 0x00 + uint8_t block_lock_reg_buffer[1] = {0}; + const FLASH_error_enum_t block_lock_result = FLASH_unblock_block_lock(hspi, chip_number, block_lock_reg_buffer); + if (block_lock_result != FLASH_ERR_OK) { + FLASH_deactivate_chip_select(); + return block_lock_result; + } - // Enable WREN Command, so that we can write to the memory module + // Send WRITE ENABLE Command const FLASH_error_enum_t wren_result = FLASH_write_enable(hspi, chip_number); if (wren_result != FLASH_ERR_OK) { FLASH_deactivate_chip_select(); return wren_result; } - // Send WREN Command and the Data required with the command + // Send PROGAM LOAD Command FLASH_activate_chip_select(chip_number); - const uint8_t tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_WRITE_4_BYTE_ADDR, 1, FLASH_HAL_TIMEOUT_MS); + const uint8_t tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_PROGRAM_LOAD, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why if (tx_result_1 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -344,7 +538,11 @@ FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs return FLASH_ERR_SPI_TRANSMIT_FAILED; } - const uint8_t tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)addr_bytes, 4, FLASH_HAL_TIMEOUT_MS); + + // Send Cache Register address + const uint8_t tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)cache_addr_bytes, 2, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the bytes, check why if (tx_result_2 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -354,7 +552,11 @@ FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs return FLASH_ERR_SPI_TRANSMIT_FAILED; } - const uint8_t tx_result_3 = HAL_SPI_Transmit(hspi, (uint8_t *)packet_buffer, packet_buffer_len, FLASH_HAL_TIMEOUT_MS); + + // Send the data bytes + const uint8_t tx_result_3 = HAL_SPI_Transmit(hspi, packet_buffer, packet_buffer_len, FLASH_HAL_MAX_BYTE_TIMEOUT_MS); + + // If couldn't send the bytes, check why if (tx_result_3 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -365,10 +567,44 @@ FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs return FLASH_ERR_SPI_TRANSMIT_FAILED; } + // TODO: If Write doesn't work as intended or not all data bits are stored + // do the status register check loop here before deactivating chip select + FLASH_deactivate_chip_select(); + + // Send PROGAM EXECUTE Command + FLASH_activate_chip_select(chip_number); + const uint8_t tx_result_4 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_PROGRAM_EXEC, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result_4 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_4 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Send address bytes + const uint8_t tx_result_5 = HAL_SPI_Transmit(hspi, (uint8_t *)addr_bytes, 3, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the bytes, check why + if (tx_result_5 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_5 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + FLASH_deactivate_chip_select(); + // Buffer to store status register value uint8_t status_reg_buffer[1] = {0}; - // Keep looping as long as device is busy (until the Write Enable Latch is active [1]) + // Keep looping as long as device is busy (until the Operation In Progress bit is active [1]) const uint32_t start_loop_time_ms = HAL_GetTick(); while (1) { @@ -395,9 +631,11 @@ FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs return FLASH_ERR_DEVICE_BUSY_TIMEOUT; } - DEBUG_uart_print_str("DEBUG: status_reg = 0x"); - DEBUG_uart_print_array_hex(status_reg_buffer, 1); - DEBUG_uart_print_str("\n"); + if (FLASH_enable_hot_path_debug_logs) { + DEBUG_uart_print_str("DEBUG: status_reg = 0x"); + DEBUG_uart_print_array_hex(status_reg_buffer, 1); + DEBUG_uart_print_str("\n"); + } } // Should never be reached: @@ -405,22 +643,28 @@ FLASH_error_enum_t FLASH_write(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs } /** - * @brief Sends Page Program Command + * @brief Sends Page Read Command * @param hspi - Pointer to the SPI HAL handle - * @param chip_number - the chip select number to activate - * @param addr - block number that is to be read - * @param rx_buffer - a to buffer where the read data will be stored - * @param rx_buffer_len - integer that indicates the capacity of `rx_buffer` + * @param chip_number - The chip select number to activate + * @param page - page number to be read + * @param rx_buffer - A buffer where the read data will be stored + * @param rx_buffer_len - Integer that indicates the capacity of `rx_buffer` * @retval FLASH_ERR_OK on success, < 0 on failure */ -FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t addr, uint8_t *rx_buffer, lfs_size_t rx_buffer_len) +FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, lfs_block_t page, uint8_t *rx_buffer, lfs_size_t rx_buffer_len) { - // Split address into its 4 bytes - uint8_t addr_bytes[4] = {(addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF}; + uint8_t read_addr_bytes[3] = {(page >> 16) & 0xFF, (page >> 8) & 0xFF, page & 0xFF}; + + // Define the address where data will be read from in cache register (First 4 bits are dummy bits) + // TODO: Is it fine to always have this at 0? + uint16_t cache_addr = 0x0000; + uint8_t cache_addr_bytes[2] = {(cache_addr >> 8) & 0xFF,cache_addr & 0xFF}; - // Send Read Command and the data required with it + // Send PAGE READ command FLASH_activate_chip_select(chip_number); - const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_READ_4_BYTE_ADDR, 1, FLASH_HAL_TIMEOUT_MS); + const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_PAGE_READ, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why if (tx_result_1 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -430,7 +674,11 @@ FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, return FLASH_ERR_SPI_TRANSMIT_FAILED; } - const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)addr_bytes, 4, FLASH_HAL_TIMEOUT_MS); + + // Send Address bytes + const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, (uint8_t *)read_addr_bytes, 3, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the bytes, check why if (tx_result_2 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -440,7 +688,89 @@ FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, return FLASH_ERR_SPI_TRANSMIT_FAILED; } - const HAL_StatusTypeDef rx_result_1 = HAL_SPI_Receive(hspi, (uint8_t *)rx_buffer, rx_buffer_len, FLASH_HAL_TIMEOUT_MS); + + // Set Chip Select HIGH + FLASH_deactivate_chip_select(); + + // Buffer to store status register value + uint8_t status_reg_buffer[1] = {0}; + + // Keep looping as long as device is busy (until the Operation In Progress bit is active [1]) + const uint32_t start_loop_time_ms = HAL_GetTick(); + while (1) + { + const FLASH_error_enum_t read_status_result = FLASH_read_status_register(hspi, chip_number, status_reg_buffer); + if (read_status_result != FLASH_ERR_OK) { + FLASH_deactivate_chip_select(); + return read_status_result; + } + + if ((status_reg_buffer[0] & FLASH_SR1_WRITE_IN_PROGRESS_MASK) == 0) { + // Success condition: write in progress has completed. + break; + } + + // Do this comparison AFTER checking the success condition (for speed, and to avoid timing out on a success). + if (HAL_GetTick() - start_loop_time_ms > FLASH_LOOP_WRITE_TIMEOUT_MS) { + DEBUG_uart_print_str("Flash read timeout\n"); + return FLASH_ERR_DEVICE_BUSY_TIMEOUT; + } + + if (FLASH_enable_hot_path_debug_logs) { + DEBUG_uart_print_str("DEBUG: status_reg = 0x"); + DEBUG_uart_print_array_hex(status_reg_buffer, 1); + DEBUG_uart_print_str("\n"); + } + } + FLASH_deactivate_chip_select(); + + // Send READ FROM CACHE command + FLASH_activate_chip_select(chip_number); + const HAL_StatusTypeDef tx_result_3 = HAL_SPI_Transmit(hspi, (uint8_t *)&FLASH_CMD_READ_FROM_CACHE, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result_3 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_3 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Send cache address bytes + const HAL_StatusTypeDef tx_result_4 = HAL_SPI_Transmit(hspi, (uint8_t *)cache_addr_bytes, 2, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the bytes, check why + if (tx_result_4 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_4 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Send cache address bytes again just as 2 dummy bytes to use 2 8-bit clock cycles + const HAL_StatusTypeDef tx_result_5 = HAL_SPI_Transmit(hspi, (uint8_t *) cache_addr_bytes, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the bytes, check why + if (tx_result_5 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_5 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + // Receive the data into the buffer + const HAL_StatusTypeDef rx_result_1 = HAL_SPI_Receive(hspi, (uint8_t *)rx_buffer, rx_buffer_len, FLASH_HAL_MAX_BYTE_TIMEOUT_MS); + + // If couldn't receive data, check why if (rx_result_1 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -450,12 +780,47 @@ FLASH_error_enum_t FLASH_read_data(SPI_HandleTypeDef *hspi, uint8_t chip_number, return FLASH_ERR_SPI_RECEIVE_FAILED; } + + // Set Chip Select HIGH FLASH_deactivate_chip_select(); - // TODO: Haven't yet implemented a way to check any errors while reading data from memory - return 0; + // TODO: Are there any other errors that can occur while reading? + return FLASH_ERR_OK; } +/** + * @brief Resets the NAND flash memory module + * @param hspi - Pointer to the SPI HAL handle + * @param chip_number - The chip select number to activate + * @retval FLASH_ERR_OK on success, <0 on failure + */ +FLASH_error_enum_t FLASH_reset(SPI_HandleTypeDef *hspi, uint8_t chip_number) +{ + FLASH_activate_chip_select(chip_number); + + uint8_t tx_buffer[1] = {FLASH_CMD_RESET}; + HAL_StatusTypeDef tx_result = HAL_SPI_Transmit(hspi, tx_buffer, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + + return FLASH_ERR_OK; +} + +/** + * @brief Checks if the FLASH chip is reachable by checking it's ID + * @param hspi - Pointer to the SPI HAL handle + * @param chip_number - The chip select number to activate + * @retval FLASH_ERR_OK on success, < 0 on failure + */ FLASH_error_enum_t FLASH_is_reachable(SPI_HandleTypeDef *hspi, uint8_t chip_number) { // TODO: confirm if this works with the CS2 logical chip on each physical FLASH chip; @@ -465,9 +830,11 @@ FLASH_error_enum_t FLASH_is_reachable(SPI_HandleTypeDef *hspi, uint8_t chip_numb uint8_t rx_buffer[5]; memset(rx_buffer, 0, 5); - // Transmit the READ_ID_CMD + // Send READ ID Command FLASH_activate_chip_select(chip_number); const HAL_StatusTypeDef tx_result_1 = HAL_SPI_Transmit(hspi, tx_buffer, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why if (tx_result_1 != HAL_OK) { FLASH_deactivate_chip_select(); @@ -478,8 +845,24 @@ FLASH_error_enum_t FLASH_is_reachable(SPI_HandleTypeDef *hspi, uint8_t chip_numb return FLASH_ERR_SPI_TRANSMIT_FAILED; } + // Send the command again just as a dummy byte + const HAL_StatusTypeDef tx_result_2 = HAL_SPI_Transmit(hspi, tx_buffer, 1, FLASH_HAL_TIMEOUT_MS); + + // If couldn't send the command, check why + if (tx_result_2 != HAL_OK) { + FLASH_deactivate_chip_select(); + + if (tx_result_2 == HAL_TIMEOUT) { + return FLASH_ERR_SPI_TRANSMIT_TIMEOUT; + } + + return FLASH_ERR_SPI_TRANSMIT_FAILED; + } + // Receive the response const HAL_StatusTypeDef rx_result = HAL_SPI_Receive(hspi, rx_buffer, 5, FLASH_HAL_TIMEOUT_MS); + + // If couldn't receive, checky why if (rx_result != HAL_OK) { FLASH_deactivate_chip_select(); @@ -498,7 +881,7 @@ FLASH_error_enum_t FLASH_is_reachable(SPI_HandleTypeDef *hspi, uint8_t chip_numb // rx_buffer[2] is 0x20=512 for 512 Mib (mebibits) // TODO: maybe check the capacity as well here, esp. in deployment uint8_t are_bytes_correct = 0; - if (rx_buffer[0] == 0x01 && rx_buffer[1] == 0x02) { + if (rx_buffer[0] == 0x2C && rx_buffer[1] == 0x14) { DEBUG_uart_print_str("SUCCESS: FLASH_is_reachable received IDs: "); are_bytes_correct = 1; } else { @@ -511,7 +894,7 @@ FLASH_error_enum_t FLASH_is_reachable(SPI_HandleTypeDef *hspi, uint8_t chip_numb if (!are_bytes_correct) { // error: IDs don't match - return 3; + return FLASH_ERR_UNKNOWN; } - return 0; // success + return FLASH_ERR_OK; // success } diff --git a/firmware/Core/Src/littlefs/flash_testing_demos.c b/firmware/Core/Src/littlefs/flash_testing_demos.c index bd711fcdc..28d4a6447 100644 --- a/firmware/Core/Src/littlefs/flash_testing_demos.c +++ b/firmware/Core/Src/littlefs/flash_testing_demos.c @@ -13,7 +13,7 @@ void demo_flash_write() { uint32_t num_bytes = strlen((char*)bytes_to_write); for (uint8_t i = 0; i < 2; i++) { - FLASH_error_enum_t result = FLASH_write(&hspi1, chip_num, flash_addr, bytes_to_write, num_bytes); + FLASH_error_enum_t result = FLASH_write_data(&hspi1, chip_num, flash_addr, bytes_to_write, num_bytes); if (result != 0) { DEBUG_uart_print_str("Error in FLASH_write\n"); return; diff --git a/firmware/Core/Src/littlefs/littlefs_benchmark.c b/firmware/Core/Src/littlefs/littlefs_benchmark.c index a06528740..2ed36792e 100644 --- a/firmware/Core/Src/littlefs/littlefs_benchmark.c +++ b/firmware/Core/Src/littlefs/littlefs_benchmark.c @@ -11,11 +11,31 @@ /// @param write_chunk_size Number of bytes to write in each chunk. /// @param write_chunk_count Number of chunks to write. /// @param response_str -/// @param response_str_len +/// @param response_str_len +/// @param mode Check to see if we are writing to a new file or the same file. /// @return 0 on success. >0 if there was an error. -uint8_t LFS_benchmark_write_read(uint16_t write_chunk_size, uint16_t write_chunk_count, char* response_str, uint16_t response_str_len) { - const char file_name[] = "benchmark_test.txt"; - response_str[0] = '\0'; +uint8_t LFS_benchmark_write_read(uint16_t write_chunk_size, uint16_t write_chunk_count, char* response_str, uint16_t response_str_len, LFS_benchmark_mode_enum_t mode) { + char file_name[100]; + + if(mode == LFS_NEW_FILE) { + const char dir_name[] = "benchmark_write_read"; + // FIXME: check if we care about return value + lfs_mkdir(&LFS_filesystem, dir_name); + snprintf( + file_name, + sizeof(file_name), + "%s/benchmark_test_%lu.txt", + dir_name, + HAL_GetTick() + ); + } else { + // Default to single file mode + snprintf( + file_name, + sizeof(file_name), + "benchmark_test.txt" + ); + } uint8_t expected_checksum = 0; @@ -137,7 +157,7 @@ uint8_t LFS_benchmark_write_read(uint16_t write_chunk_size, uint16_t write_chunk snprintf( &response_str[strlen(response_str)], response_str_len - strlen(response_str), - "Read close: %lu ms\n", read_close_end_time - read_close_start_time); + "Read close: %lu ms\n\n", read_close_end_time - read_close_start_time); // Verify checksum if (read_checksum != expected_checksum) { @@ -151,3 +171,34 @@ uint8_t LFS_benchmark_write_read(uint16_t write_chunk_size, uint16_t write_chunk return 0; } +/// @brief Benchmarks the write/read operations on the LittleFS file system for both cases: writing to a new file and writing to an existing file. +/// @details This function will write test data to a static filename, read it back, and verify the read data for both cases. +/// @param write_chunk_size Number of bytes to write in each chunk. +/// @param write_chunk_count Number of chunks to write. +/// @param response_str +/// @param response_str_len +/// @return 0 on success. >0 if there was an error. +uint8_t LFS_benchmark_write_read_single_and_new(uint16_t write_chunk_size, uint16_t write_chunk_count, char* response_str, uint16_t response_str_len) { + response_str[0] = '\0'; + + snprintf( + &response_str[strlen(response_str)], + response_str_len - strlen(response_str), + "Benchmark writing to the same file: \n"); + uint8_t benchmark_same_file_result = LFS_benchmark_write_read(write_chunk_size, write_chunk_count, response_str, response_str_len, LFS_SINGLE_FILE); + if(benchmark_same_file_result != 0) { + return benchmark_same_file_result; + } + + snprintf( + &response_str[strlen(response_str)], + response_str_len - strlen(response_str), + "Benchmark writing to a new file: \n"); + uint8_t benchmark_new_file_result = LFS_benchmark_write_read(write_chunk_size, write_chunk_count, response_str, response_str_len, LFS_NEW_FILE); + if(benchmark_new_file_result != 0) { + return benchmark_same_file_result; + } + + return 0; + +} \ No newline at end of file diff --git a/firmware/Core/Src/littlefs/littlefs_driver.c b/firmware/Core/Src/littlefs/littlefs_driver.c index a1edfaca8..acca87460 100644 --- a/firmware/Core/Src/littlefs/littlefs_driver.c +++ b/firmware/Core/Src/littlefs/littlefs_driver.c @@ -21,7 +21,7 @@ int LFS_block_device_read(const struct lfs_config *c, lfs_block_t block, lfs_off return FLASH_read_data( hspi_lfs_ptr, LFS_get_chip_number(block), - (block * c->block_size + off), + ((block * c->block_size) + off)/FLASH_MAX_BYTES_PER_PAGE, (uint8_t *)buffer, size ); @@ -34,10 +34,10 @@ int LFS_block_device_read(const struct lfs_config *c, lfs_block_t block, lfs_off */ int LFS_block_device_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) { - return FLASH_write( + return FLASH_write_data( hspi_lfs_ptr, LFS_get_chip_number(block), - (block * c->block_size + off), + ((block * c->block_size) + off)/FLASH_MAX_BYTES_PER_PAGE, (uint8_t *)buffer, size ); @@ -53,7 +53,7 @@ int LFS_block_device_erase(const struct lfs_config *c, lfs_block_t block) return FLASH_erase( hspi_lfs_ptr, LFS_get_chip_number(block), - block * c->block_size + block * FLASH_CHIP_PAGES_PER_BLOCK ); } diff --git a/firmware/Core/Src/littlefs/littlefs_helper.c b/firmware/Core/Src/littlefs/littlefs_helper.c index 6e476b8c9..cca4483aa 100644 --- a/firmware/Core/Src/littlefs/littlefs_helper.c +++ b/firmware/Core/Src/littlefs/littlefs_helper.c @@ -14,8 +14,10 @@ // Variables to track LittleFS on Flash Memory Module uint8_t LFS_is_lfs_mounted = 0; -#define FLASH_CHIP_PAGE_SIZE_BYTES 512 -#define FLASH_CHIP_BLOCK_SIZE_BYTES 262144 +// NAND Flash Memory Datasheet https://www.farnell.com/datasheets/3151163.pdf +// Each page is divided into a 2048-byte data storage region, and a 128 bytes spare area (2176 bytes total). +#define FLASH_CHIP_PAGE_SIZE_BYTES 2048 +#define FLASH_CHIP_BLOCK_SIZE_BYTES FLASH_CHIP_PAGE_SIZE_BYTES * FLASH_CHIP_PAGES_PER_BLOCK #define FLASH_LOOKAHEAD_SIZE 16 // LittleFS Buffers for reading and writing @@ -214,10 +216,14 @@ int8_t LFS_make_directory(const char dir_name[]) return 1; } - int8_t make_dir_result = lfs_mkdir(&LFS_filesystem, dir_name); + const int8_t make_dir_result = lfs_mkdir(&LFS_filesystem, dir_name); if (make_dir_result < 0) { - DEBUG_uart_print_str("Error creating directory.\n"); + LOG_message( + LOG_SYSTEM_LFS, LOG_SEVERITY_WARNING, LOG_SINK_ALL, + "Error %d creating directory.", + make_dir_result + ); return make_dir_result; } diff --git a/firmware/Core/Src/telecommands/flash_telecommand_defs.c b/firmware/Core/Src/telecommands/flash_telecommand_defs.c index 25edd0e99..5549f45cb 100644 --- a/firmware/Core/Src/telecommands/flash_telecommand_defs.c +++ b/firmware/Core/Src/telecommands/flash_telecommand_defs.c @@ -10,6 +10,9 @@ #include #include +uint8_t read_buf[FLASH_MAX_BYTES_PER_PAGE]; +uint8_t bytes_to_write[FLASH_MAX_BYTES_PER_PAGE]; + /// @brief Telecommand: Read bytes as hex from a flash address /// @param args_str No args. /// @return 0 always @@ -94,7 +97,6 @@ uint8_t TCMDEXEC_flash_each_is_reachable(const char *args_str, TCMD_TelecommandC /// @return 0 on success, >0 on error uint8_t TCMDEXEC_flash_read_hex(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len) { - const uint16_t max_num_bytes = 256; uint64_t chip_num, flash_addr, arg_num_bytes; uint8_t arg0_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &chip_num); @@ -117,15 +119,14 @@ uint8_t TCMDEXEC_flash_read_hex(const char *args_str, TCMD_TelecommandChannel_en return 2; } - if (arg_num_bytes > max_num_bytes || arg_num_bytes == 0) { + if (arg_num_bytes > FLASH_MAX_BYTES_PER_PAGE || arg_num_bytes == 0) { snprintf( response_output_buf, response_output_buf_len, "Invalid number of bytes to read: %lu. Must be 1 to %d.", - (uint32_t)arg_num_bytes, max_num_bytes); // TODO: fix this cast + (uint32_t)arg_num_bytes, FLASH_MAX_BYTES_PER_PAGE); // TODO: fix this cast return 3; } - uint8_t read_buf[max_num_bytes]; uint32_t num_bytes = (uint32_t)arg_num_bytes; FLASH_error_enum_t result = FLASH_read_data(&hspi1, chip_num, flash_addr, read_buf, num_bytes); @@ -137,6 +138,7 @@ uint8_t TCMDEXEC_flash_read_hex(const char *args_str, TCMD_TelecommandChannel_en } // Convert read data to hex + // FIXME: This can't print whole page of data (2048 bytes). Fix so that it can. for (uint16_t i = 0; i < num_bytes; i++) { snprintf( &response_output_buf[strlen(response_output_buf)], @@ -151,7 +153,7 @@ uint8_t TCMDEXEC_flash_read_hex(const char *args_str, TCMD_TelecommandChannel_en "\n"); } } - + return 0; } @@ -164,16 +166,13 @@ uint8_t TCMDEXEC_flash_read_hex(const char *args_str, TCMD_TelecommandChannel_en /// @return 0 on success, >0 on error uint8_t TCMDEXEC_flash_write_hex(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len) { - const uint16_t max_num_bytes = 256; uint16_t num_bytes; - uint64_t chip_num, flash_addr_u64; + uint64_t chip_num_u64, flash_addr_u64; - uint8_t bytes_to_write[max_num_bytes]; - - const uint8_t arg0_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &chip_num); + const uint8_t arg0_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &chip_num_u64); const uint8_t arg1_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 1, &flash_addr_u64); const uint8_t arg2_result = TCMD_extract_hex_array_arg( - args_str, 2, bytes_to_write, max_num_bytes, &num_bytes + args_str, 2, bytes_to_write, FLASH_MAX_BYTES_PER_PAGE, &num_bytes ); if (arg0_result != 0 || arg1_result != 0 || arg2_result != 0) { @@ -184,7 +183,7 @@ uint8_t TCMDEXEC_flash_write_hex(const char *args_str, TCMD_TelecommandChannel_e return 1; } - if (chip_num >= FLASH_NUMBER_OF_FLASH_DEVICES) { + if (chip_num_u64 >= FLASH_NUMBER_OF_FLASH_DEVICES) { snprintf( response_output_buf, response_output_buf_len, "Chip number is out of range. Must be 0 to %d.", @@ -199,10 +198,10 @@ uint8_t TCMDEXEC_flash_write_hex(const char *args_str, TCMD_TelecommandChannel_e FLASH_CHIP_SIZE_BYTES - 1); return 3; } - uint32_t flash_addr = (uint32_t)flash_addr_u64; - - FLASH_error_enum_t result = FLASH_write(&hspi1, chip_num, flash_addr, bytes_to_write, num_bytes); + uint8_t chip_num = (uint8_t)chip_num_u64; + uint32_t flash_addr = (uint32_t)flash_addr_u64; + FLASH_error_enum_t result = FLASH_write_data(&hspi1, chip_num, flash_addr, bytes_to_write, num_bytes); if (result != 0) { snprintf( @@ -227,10 +226,10 @@ uint8_t TCMDEXEC_flash_write_hex(const char *args_str, TCMD_TelecommandChannel_e /// @return 0 on success, >0 on error uint8_t TCMDEXEC_flash_erase(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, char *response_output_buf, uint16_t response_output_buf_len) { - uint64_t chip_num, flash_addr; + uint64_t chip_num_u64, flash_addr_u64; - uint8_t arg0_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &chip_num); - uint8_t arg1_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 1, &flash_addr); + uint8_t arg0_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &chip_num_u64); + uint8_t arg1_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 1, &flash_addr_u64); if (arg0_result != 0 || arg1_result != 0) { snprintf( @@ -240,7 +239,7 @@ uint8_t TCMDEXEC_flash_erase(const char *args_str, TCMD_TelecommandChannel_enum_ return 1; } - if (chip_num >= FLASH_NUMBER_OF_FLASH_DEVICES) { + if (chip_num_u64 >= FLASH_NUMBER_OF_FLASH_DEVICES) { snprintf( response_output_buf, response_output_buf_len, "Chip number is out of range. Must be 0 to %d.", @@ -248,6 +247,9 @@ uint8_t TCMDEXEC_flash_erase(const char *args_str, TCMD_TelecommandChannel_enum_ return 2; } + uint8_t chip_num = (uint8_t)chip_num_u64; + uint32_t flash_addr = (uint32_t)flash_addr_u64; + FLASH_error_enum_t result = FLASH_erase(&hspi1, chip_num, flash_addr); if (result != 0) { @@ -257,6 +259,13 @@ uint8_t TCMDEXEC_flash_erase(const char *args_str, TCMD_TelecommandChannel_enum_ return 4; } + // success + snprintf( + &response_output_buf[strlen(response_output_buf)], + response_output_buf_len - strlen(response_output_buf) - 1, + " Successfully erased page at address %lu on chip %d.\n", + flash_addr, chip_num); + return 0; } @@ -294,3 +303,47 @@ uint8_t TCMDEXEC_flash_benchmark_erase_write_read(const char *args_str, TCMD_Tel return result; } + +/// @brief Telecommand: Reset the flash memory module. +/// @param args_str +/// - Arg 0: Chip Number (CS number) as uint +/// @return 0 on success, >0 on error +uint8_t TCMDEXEC_flash_reset(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, + char *response_output_buf, uint16_t response_output_buf_len) { + uint64_t chip_num_u64; + + const uint8_t arg0_result = TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &chip_num_u64); + + if (arg0_result != 0) { + snprintf( + response_output_buf, response_output_buf_len, + "Error parsing chip number argument: %d", arg0_result); + return 1; + } + + if (chip_num_u64 >= FLASH_NUMBER_OF_FLASH_DEVICES) { + snprintf( + response_output_buf, response_output_buf_len, + "Chip number is out of range. Must be 0 to %d.", + FLASH_NUMBER_OF_FLASH_DEVICES - 1); + return 2; + } + + uint8_t chip_num = (uint8_t)chip_num_u64; + const uint8_t comms_err = FLASH_reset(&hspi1, chip_num); + if (comms_err != 0) { + snprintf( + response_output_buf, response_output_buf_len, + "Error resetting flash chip: %d",comms_err); + return 2; + } + + // success + snprintf( + &response_output_buf[strlen(response_output_buf)], + response_output_buf_len - strlen(response_output_buf) - 1, + " Successfully reset chip %d.\n", + (uint8_t)chip_num); + + return 0; +} \ No newline at end of file diff --git a/firmware/Core/Src/telecommands/lfs_telecommand_defs.c b/firmware/Core/Src/telecommands/lfs_telecommand_defs.c index ad66033c1..d3c56b0d3 100644 --- a/firmware/Core/Src/telecommands/lfs_telecommand_defs.c +++ b/firmware/Core/Src/telecommands/lfs_telecommand_defs.c @@ -236,7 +236,7 @@ uint8_t TCMDEXEC_fs_benchmark_write_read(const char *args_str, TCMD_TelecommandC return 1; } - const int8_t benchmark_result = LFS_benchmark_write_read(arg_write_chunk_size, arg_write_chunk_count, response_output_buf, response_output_buf_len); + const int8_t benchmark_result = LFS_benchmark_write_read_single_and_new(arg_write_chunk_size, arg_write_chunk_count, response_output_buf, response_output_buf_len); response_output_buf[response_output_buf_len - 1] = '\0'; // ensure null-terminated if (benchmark_result != 0) { diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index d294c80d5..be02e241a 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -196,6 +196,12 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .number_of_args = 3, .readiness_level = TCMD_READINESS_LEVEL_FLIGHT_TESTING, }, + { + .tcmd_name = "flash_reset", + .tcmd_func = TCMDEXEC_flash_reset, + .number_of_args = 1, + .readiness_level = TCMD_READINESS_LEVEL_IN_PROGRESS, + }, // ****************** END SECTION: flash_telecommand_defs ****************** // ****************** SECTION: lfs_telecommand_defs ****************** From 6266845d36ecb9e7e4b916bae51998f14a296622 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:53:22 -0600 Subject: [PATCH 04/22] Create Current ACP Status commands --- .../Core/Inc/adcs_drivers/adcs_command_ids.h | 2 +- .../Core/Inc/adcs_drivers/adcs_commands.h | 1 + .../Inc/adcs_drivers/adcs_struct_packers.h | 1 + firmware/Core/Inc/adcs_drivers/adcs_types.h | 21 +++++++++++++++ .../Inc/adcs_drivers/adcs_types_to_json.h | 1 + .../Core/Inc/telecommands/telecommand_adcs.h | 3 +++ firmware/Core/Inc/unit_tests/test_adcs.h | 1 + .../Core/Src/adcs_drivers/adcs_commands.c | 14 ++++++++++ .../Src/adcs_drivers/adcs_struct_packers.c | 6 +++++ .../Src/adcs_drivers/adcs_types_to_json.c | 25 ++++++++++++++++- .../Core/Src/telecommands/telecommand_adcs.c | 27 +++++++++++++++++++ .../telecommands/telecommand_definitions.c | 6 +++++ firmware/Core/Src/unit_tests/test_adcs.c | 15 +++++++++++ .../Core/Src/unit_tests/unit_test_inventory.c | 6 +++++ 14 files changed, 127 insertions(+), 2 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h b/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h index c97ecc603..36d9e5113 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; diff --git a/firmware/Core/Inc/adcs_drivers/adcs_commands.h b/firmware/Core/Inc/adcs_drivers/adcs_commands.h index 16142f2b1..971953cfa 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -121,5 +121,6 @@ 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); #endif /* INC_ADCS_COMMANDS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h index ce0cc196d..79de24e6e 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -42,5 +42,6 @@ uint8_t ADCS_Pack_to_Raw_GPS_Status_Struct(uint8_t* data_received, ADCS_raw_gps_ 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); #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..e99062b03 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -196,6 +196,22 @@ typedef enum ADCS_gps_axis_enum_t { ADCS_GPS_AXIS_Z = 2 } ADCS_gps_axis_enum_t; +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; + /* Structs */ typedef struct ADCS_cmd_ack_struct_t { @@ -517,4 +533,9 @@ 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_sec; + ADCS_current_execution_point_enum_t current_execution_point; +} ADCS_acp_execution_state_struct_t; + #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..66f4ec414 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,6 @@ 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); #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..3117f5040 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -203,4 +203,7 @@ 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); + #endif // __INCLUDE_GUARD__TELECOMMAND_adcs_H diff --git a/firmware/Core/Inc/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index a70540498..81fe57854 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -43,6 +43,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 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(); #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..747a4a2bb 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -1011,3 +1011,17 @@ uint8_t ADCS_get_measurements(ADCS_measurements_struct_t *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 = 72; + 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; +} \ No newline at end of file diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 1899b8da8..71e2987a9 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -588,5 +588,11 @@ 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_sec = (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; } \ 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 5ef088b91..5f9773cd4 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -999,4 +999,27 @@ uint8_t ADCS_generic_telemetry_uint8_array_TO_json(const uint8_t *data, const ui } } return 0; -} \ No newline at end of file +} + +/// @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_sec\":%d,\"current_execution_point\":%d}", + data->time_since_iteration_start_sec, 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; +} diff --git a/firmware/Core/Src/telecommands/telecommand_adcs.c b/firmware/Core/Src/telecommands/telecommand_adcs.c index b56e072ce..308d7607b 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -1664,5 +1664,32 @@ 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; } \ 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 be02e241a..8fae436e3 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -640,6 +640,12 @@ 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, + }, // ****************** END SECTION: telecommand_adcs ****************** // ****************** SECTION: log_telecommand_defs ****************** diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index a79eeb152..1393e88a5 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -625,3 +625,18 @@ 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_sec == 43844); + TEST_ASSERT_TRUE(result.current_execution_point == ADCS_CURRENT_EXECUTION_POINT_ADCS_UPDATE); + + 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 42f21ecd3..0810ce629 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -282,6 +282,12 @@ const TEST_Definition_t TEST_definitions[] = { .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" + }, + // ****************** END SECTION: test_adcs ****************** { From c437f7fc0ff46f34fdf29ff2a360307fef45ef7e Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:51:30 -0600 Subject: [PATCH 05/22] Create Current ADCS State 1 command --- .../Core/Inc/adcs_drivers/adcs_commands.h | 1 + .../Inc/adcs_drivers/adcs_struct_packers.h | 1 + firmware/Core/Inc/adcs_drivers/adcs_types.h | 50 +++++++++++++++ .../Inc/adcs_drivers/adcs_types_to_json.h | 1 + .../Core/Inc/telecommands/telecommand_adcs.h | 3 + firmware/Core/Inc/unit_tests/test_adcs.h | 1 + .../Core/Src/adcs_drivers/adcs_commands.c | 16 ++++- .../Src/adcs_drivers/adcs_struct_packers.c | 52 ++++++++++++++++ .../Src/adcs_drivers/adcs_types_to_json.c | 61 +++++++++++++++++++ .../Core/Src/telecommands/telecommand_adcs.c | 27 ++++++++ .../telecommands/telecommand_definitions.c | 6 ++ firmware/Core/Src/unit_tests/test_adcs.c | 52 ++++++++++++++++ .../Core/Src/unit_tests/unit_test_inventory.c | 6 ++ 13 files changed, 276 insertions(+), 1 deletion(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_commands.h b/firmware/Core/Inc/adcs_drivers/adcs_commands.h index 971953cfa..5ef91ec77 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -122,5 +122,6 @@ 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); #endif /* INC_ADCS_COMMANDS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h index 79de24e6e..8fa9e26f9 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -43,5 +43,6 @@ uint8_t ADCS_Pack_to_Raw_GPS_Time_Struct(uint8_t* data_received, ADCS_raw_gps_ti 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); #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 e99062b03..3725e40a4 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -212,6 +212,13 @@ typedef enum ADCS_current_execution_point_enum_t { 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; + /* Structs */ typedef struct ADCS_cmd_ack_struct_t { @@ -538,4 +545,47 @@ typedef struct ADCS_acp_execution_state_struct_t { 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 ; + #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 66f4ec414..1afcf8fff 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h @@ -48,5 +48,6 @@ uint8_t ADCS_raw_gps_struct_TO_json(const ADCS_raw_gps_struct_t *data, char json 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); #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 3117f5040..676ce1b01 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -206,4 +206,7 @@ uint8_t TCMDEXEC_adcs_generic_telemetry_request(const char *args_str, TCMD_Telec 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); + #endif // __INCLUDE_GUARD__TELECOMMAND_adcs_H diff --git a/firmware/Core/Inc/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index 81fe57854..c2b2e3b76 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -44,6 +44,7 @@ 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(); #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 747a4a2bb..d20a04dc2 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -1016,12 +1016,26 @@ uint8_t ADCS_get_measurements(ADCS_measurements_struct_t *output_struct) { /// @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 = 72; + 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; } \ No newline at end of file diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 71e2987a9..87782e4f6 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -594,5 +594,57 @@ uint8_t ADCS_Pack_to_Measurements_Struct(uint8_t* telemetry_data, ADCS_measureme 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_sec = (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[1]) & 0xf; + + output_struct->run_mode = (data_received[2] >> 6) & 0x3; + output_struct->asgp4_mode = (data_received[2] >> 4) & 0x3; + output_struct->cubecontrol_signal_enabled = (data_received[2] >> 3) & 0x01; // 1-bit bool + output_struct->cubecontrol_motor_enabled = (data_received[2] >> 2) & 0x01; // 1-bit bool + output_struct->cubesense1_enabled = (data_received[2] >> 1) & 0x01; // 1-bit bool + output_struct->cubesense2_enabled = (data_received[2]) & 0x01; // 1-bit bool + + output_struct->cubewheel1_enabled = (data_received[3] >> 7) & 0x01; // 1-bit bool + output_struct->cubewheel2_enabled = (data_received[3] >> 6) & 0x01; // 1-bit bool + output_struct->cubewheel3_enabled = (data_received[3] >> 5) & 0x01; // 1-bit bool + output_struct->cubestar_enabled = (data_received[3] >> 4) & 0x01; // 1-bit bool + output_struct->gps_receiver_enabled = (data_received[3] >> 3) & 0x01; // 1-bit bool + output_struct->gps_lna_power_enabled = (data_received[3] >> 2) & 0x01; // 1-bit bool + output_struct->motor_driver_enabled = (data_received[3] >> 1) & 0x01; // 1-bit bool + output_struct->sun_above_local_horizon = (data_received[3]) & 0x01; // 1-bit bool + + output_struct->cubesense1_comm_error = (data_received[4] >> 7) & 0x01; // 1-bit bool + output_struct->cubesense2_comm_error = (data_received[4] >> 6) & 0x01; // 1-bit bool + output_struct->cubecontrol_signal_comm_error = (data_received[4] >> 5) & 0x01; // 1-bit bool + output_struct->cubecontrol_motor_comm_error = (data_received[4] >> 4) & 0x01; // 1-bit bool + output_struct->cubewheel1_comm_error = (data_received[4] >> 3) & 0x01; // 1-bit bool + output_struct->cubewheel2_comm_error = (data_received[4] >> 2) & 0x01; // 1-bit bool + output_struct->cubewheel3_comm_error = (data_received[4] >> 1) & 0x01; // 1-bit bool + output_struct->cubestar_comm_error = (data_received[4] >> 0) & 0x01; // 1-bit bool + + output_struct->magnetometer_range_error = (data_received[5] >> 7) & 0x01; // 1-bit bool + output_struct->cam1_sram_overcurrent_detected = (data_received[5] >> 6) & 0x01; // 1-bit bool + output_struct->cam1_3v3_overcurrent_detected = (data_received[5] >> 5) & 0x01; // 1-bit bool + output_struct->cam1_sensor_busy_error = (data_received[5] >> 4) & 0x01; // 1-bit bool + output_struct->cam1_sensor_detection_error = (data_received[5] >> 3) & 0x01; // 1-bit bool + output_struct->sun_sensor_range_error = (data_received[5] >> 2) & 0x01; // 1-bit bool + output_struct->cam2_sram_overcurrent_detected = (data_received[5] >> 1) & 0x01; // 1-bit bool + output_struct->cam2_3v3_overcurrent_detected = (data_received[5]) & 0x01; // 1-bit bool + + output_struct->cam2_sensor_busy_error = (data_received[6] >> 7) & 0x01; // 1-bit bool + output_struct->cam2_sensor_detection_error = (data_received[6] >> 6) & 0x01; // 1-bit bool + output_struct->nadir_sensor_range_error = (data_received[6] >> 5) & 0x01; // 1-bit bool + output_struct->rate_sensor_range_error = (data_received[6] >> 4) & 0x01; // 1-bit bool + output_struct->wheel_speed_range_error = (data_received[6] >> 3) & 0x01; // 1-bit bool + output_struct->coarse_sun_sensor_error = (data_received[6] >> 2) & 0x01; // 1-bit bool + output_struct->startracker_match_error = (data_received[6] >> 1) & 0x01; // 1-bit bool + output_struct->startracker_overcurrent_detected = (data_received[6]) & 0x01; // 1-bit bool + 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 5f9773cd4..0e0ccc414 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -1023,3 +1023,64 @@ uint8_t ADCS_acp_execution_struct_TO_json(const ADCS_acp_execution_state_struct_ 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; +} diff --git a/firmware/Core/Src/telecommands/telecommand_adcs.c b/firmware/Core/Src/telecommands/telecommand_adcs.c index 308d7607b..7c0b02c4b 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -1691,5 +1691,32 @@ uint8_t TCMDEXEC_adcs_acp_execution_state(const char *args_str, TCMD_Telecommand 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; } \ 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 8fae436e3..378d8e29c 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -645,6 +645,12 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .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, }, // ****************** END SECTION: telecommand_adcs ****************** diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index 1393e88a5..590fb885c 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -639,4 +639,56 @@ uint8_t TEST_EXEC__ADCS_pack_to_acp_execution_state_struct() { 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 = true); + TEST_ASSERT_TRUE(result.coarse_sun_sensor_error = true); + TEST_ASSERT_TRUE(result.startracker_match_error = true); + TEST_ASSERT_TRUE(result.startracker_overcurrent_detected = true); + + 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 0810ce629..062fa8772 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -287,6 +287,12 @@ const TEST_Definition_t TEST_definitions[] = { .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" + }, // ****************** END SECTION: test_adcs ****************** From 1e7cffecc30659ce01118c84850cc7967205f75a Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:23:22 -0600 Subject: [PATCH 06/22] Create commissioning structs --- firmware/Core/Inc/adcs_drivers/adcs_types.h | 152 +++++++++++++++++++- 1 file changed, 150 insertions(+), 2 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_types.h b/firmware/Core/Inc/adcs_drivers/adcs_types.h index 3725e40a4..442f6bf9c 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -219,7 +219,7 @@ typedef enum ADCS_asgp4_mode_enum_t { ADCS_ASGP4_MODE_AUGMENT = 3, } ADCS_asgp4_mode_enum_t; -/* Structs */ +/* Command Structs */ typedef struct ADCS_cmd_ack_struct_t { uint8_t last_id; @@ -586,6 +586,154 @@ typedef struct ADCS_current_state_1_struct_t { 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 ; +} ADCS_current_state_1_struct_t; + +typedef struct ADCS_raw_star_tracker_struct_t { + uint8_t pass; // TODO: make this work +} ADCS_raw_star_tracker_struct_t; + +/* Commissioning Structs */ + +typedef struct ADCS_commissioning_determine_initial_angular_rates_struct_t { + uint8_t pass; // need timestamp + ADCS_angular_rates_struct_t estimated_angular_rates; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; +} ADCS_commissioning_determine_initial_angular_rates_struct_t; + +typedef struct ADCS_commissioning_initial_detumbling_struct_t { + // works for detumbling and Y-thomson continued detumbling + uint8_t pass; // need timestamp + ADCS_angular_rates_struct_t estimated_angular_rates; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; + ADCS_magnetorquer_command_struct_t magnetorquer_commands; +} ADCS_commissioning_initial_detumbling_struct_t; + +typedef struct ADCS_commissioning_magnetometer_deployment_struct_t { + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; + ADCS_cubecontrol_current_struct_t cubecontrol_currents; +} ADCS_commissioning_magnetometer_deployment_struct_t; + +typedef struct ADCS_commissioning_magnetometer_calibration_struct_t { + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements +} ADCS_commissioning_magnetometer_calibration_struct_t; + +typedef struct ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t { + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements +} ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t; + +typedef struct ADCS_commissioning_y_wheel_ramp_up_test_struct_t { + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_wheel_speed_struct_t measured_wheel_speeds; + ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements +} ADCS_commissioning_y_wheel_ramp_up_test_struct_t; + +typedef struct ADCS_commissioning_initial_y_momentum_activation_struct_t { + // for both initial Y-momentum activation and Magnetometer EKF Y-momentum + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_wheel_speed_struct_t measured_wheel_speeds; + ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements + ADCS_llh_position_struct_t LLH_positions; +} ADCS_commissioning_initial_y_momentum_activation_struct_t; + +typedef struct ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t { + // for both initial sun/nadir commissioning and EKF sun/nadir commissioning + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + + ADCS_raw_coarse_sun_sensor_1_to_6_struct_t raw_css_1_to_6_measurements; + ADCS_raw_coarse_sun_sensor_7_to_10_struct_t raw_css_7_to_10_measurements; + + ADCS_raw_cam_sensor_struct_t raw_cam1_measurements; + ADCS_raw_cam_sensor_struct_t raw_cam2_measurements; + + ADCS_fine_sun_vector_struct_t fine_sun_vector; + ADCS_nadir_vector_struct_t nadir_vector; +} ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t; + +typedef struct ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t { + // for both non-EKF and EKF + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_raw_star_tracker_struct_t raw_star_tracker; // TODO: need Raw Star Tracker telemetry (ID 211) +} ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t; + +// TODO: We also need the ADCS_save_image command + +typedef struct ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t { + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_wheel_speed_struct_t measured_wheel_speeds; +} ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t; + +typedef struct ADCS_commissioning_sun_tracking_3_axis_control_struct_t { + // for both EKF rate gyro and sun tracking 3-axis control + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_estimated_gyro_bias_struct_t estimated_gyro_bias; + ADCS_estimation_innovation_vector_struct_t estimation_innovation_vector; + ADCS_magnetic_field_vector_struct_t magnetic_field_vector; + ADCS_fine_sun_vector_struct_t fine_sun_vector; + ADCS_nadir_vector_struct_t nadir_vector; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_wheel_speed_struct_t measured_wheel_speeds; + ADCS_magnetorquer_command_struct_t magnetorquer_commands; + ADCS_wheel_speed_struct_t commanded_wheel_speeds; + ADCS_magnetic_field_vector_struct_t igrf_magnetic_field_vector; + ADCS_quaternion_error_vector_struct_t quaternion_error_vector; +} ADCS_commissioning_sun_tracking_3_axis_control_struct_t; + +typedef struct ADCS_commissioning_ground_target_tracking_controller_struct_t { + uint8_t pass; // need timestamp + ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; + ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; + ADCS_estimated_gyro_bias_struct_t estimated_gyro_bias; + ADCS_estimation_innovation_vector_struct_t estimation_innovation_vector; + ADCS_magnetic_field_vector_struct_t magnetic_field_vector; + ADCS_fine_sun_vector_struct_t fine_sun_vector; + ADCS_nadir_vector_struct_t nadir_vector; + ADCS_rated_sensor_rates_struct_t rated_sensor_rates; + ADCS_wheel_speed_struct_t measured_wheel_speeds; + ADCS_magnetorquer_command_struct_t magnetorquer_commands; + ADCS_wheel_speed_struct_t commanded_wheel_speeds; + ADCS_magnetic_field_vector_struct_t igrf_magnetic_field_vector; + ADCS_quaternion_error_vector_struct_t quaternion_error_vector; + ADCS_llh_position_struct_t LLH_position; + ADCS_commanded_angles_struct_t commanded_attitude_angles; +} ADCS_commissioning_ground_target_tracking_controller_struct_t; + +typedef struct ADCS_commissioning_gps_receiver_commissioning_struct_t { + uint8_t pass; // need timestamp + ADCS_llh_position_struct_t LLH_position; + ADCS_raw_gps_status_struct_t raw_GPS_status; + ADCS_raw_gps_time_struct_t raw_GPS_time; + ADCS_raw_gps_struct_t raw_GPS_x; + ADCS_raw_gps_struct_t raw_GPS_y; + ADCS_raw_gps_struct_t raw_GPS_z; +} ADCS_commissioning_gps_receiver_commissioning_struct_t; #endif /* INC_ADCS_TYPES_H_ */ \ No newline at end of file From b7e8868be36a6034b0d6338b9c7ffeb53b305ed4 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:34:37 -0600 Subject: [PATCH 07/22] Create Raw Star Tracker command --- .../Core/Inc/adcs_drivers/adcs_commands.h | 1 + .../Inc/adcs_drivers/adcs_struct_packers.h | 1 + firmware/Core/Inc/adcs_drivers/adcs_types.h | 40 ++++- .../Inc/adcs_drivers/adcs_types_to_json.h | 1 + .../Core/Inc/telecommands/telecommand_adcs.h | 3 + firmware/Core/Inc/unit_tests/test_adcs.h | 1 + .../Core/Src/adcs_drivers/adcs_commands.c | 14 ++ .../Src/adcs_drivers/adcs_struct_packers.c | 131 ++++++++++------ .../Src/adcs_drivers/adcs_types_to_json.c | 42 ++++++ .../Core/Src/telecommands/telecommand_adcs.c | 29 +++- .../telecommands/telecommand_definitions.c | 6 + firmware/Core/Src/unit_tests/test_adcs.c | 141 ++++++++++++------ .../Core/Src/unit_tests/unit_test_inventory.c | 6 + 13 files changed, 327 insertions(+), 89 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_commands.h b/firmware/Core/Inc/adcs_drivers/adcs_commands.h index 5ef91ec77..e136236fa 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -123,5 +123,6 @@ 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); #endif /* INC_ADCS_COMMANDS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h index 8fa9e26f9..86e8e5412 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -44,5 +44,6 @@ uint8_t ADCS_Pack_to_Raw_GPS_Struct(ADCS_gps_axis_enum_t axis, uint8_t *data_rec 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); #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 442f6bf9c..dda52aa19 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -589,7 +589,45 @@ typedef struct ADCS_current_state_1_struct_t { } ADCS_current_state_1_struct_t; typedef struct ADCS_raw_star_tracker_struct_t { - uint8_t pass; // TODO: make this work + 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; /* Commissioning Structs */ 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 1afcf8fff..71fe269ab 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h @@ -49,5 +49,6 @@ uint8_t ADCS_measurements_struct_TO_json(const ADCS_measurements_struct_t *data, 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); #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 676ce1b01..dfa89acba 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -209,4 +209,7 @@ uint8_t TCMDEXEC_adcs_acp_execution_state(const char *args_str, TCMD_Telecommand 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); + #endif // __INCLUDE_GUARD__TELECOMMAND_adcs_H diff --git a/firmware/Core/Inc/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index c2b2e3b76..fb1ea9196 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -45,6 +45,7 @@ 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(); #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 d20a04dc2..1292d69a5 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -1037,5 +1037,19 @@ uint8_t ADCS_get_current_state_1(ADCS_current_state_1_struct_t *output_struct) { 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; } \ No newline at end of file diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 87782e4f6..28931b78f 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -601,50 +601,95 @@ uint8_t ADCS_pack_to_current_state_1_struct(uint8_t* data_received, ADCS_current output_struct->estimation_mode = (data_received[0] >> 4) & 0xf; - output_struct->control_mode = (data_received[1]) & 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_struct->run_mode = (data_received[2] >> 6) & 0x3; - output_struct->asgp4_mode = (data_received[2] >> 4) & 0x3; - output_struct->cubecontrol_signal_enabled = (data_received[2] >> 3) & 0x01; // 1-bit bool - output_struct->cubecontrol_motor_enabled = (data_received[2] >> 2) & 0x01; // 1-bit bool - output_struct->cubesense1_enabled = (data_received[2] >> 1) & 0x01; // 1-bit bool - output_struct->cubesense2_enabled = (data_received[2]) & 0x01; // 1-bit bool - - output_struct->cubewheel1_enabled = (data_received[3] >> 7) & 0x01; // 1-bit bool - output_struct->cubewheel2_enabled = (data_received[3] >> 6) & 0x01; // 1-bit bool - output_struct->cubewheel3_enabled = (data_received[3] >> 5) & 0x01; // 1-bit bool - output_struct->cubestar_enabled = (data_received[3] >> 4) & 0x01; // 1-bit bool - output_struct->gps_receiver_enabled = (data_received[3] >> 3) & 0x01; // 1-bit bool - output_struct->gps_lna_power_enabled = (data_received[3] >> 2) & 0x01; // 1-bit bool - output_struct->motor_driver_enabled = (data_received[3] >> 1) & 0x01; // 1-bit bool - output_struct->sun_above_local_horizon = (data_received[3]) & 0x01; // 1-bit bool - - output_struct->cubesense1_comm_error = (data_received[4] >> 7) & 0x01; // 1-bit bool - output_struct->cubesense2_comm_error = (data_received[4] >> 6) & 0x01; // 1-bit bool - output_struct->cubecontrol_signal_comm_error = (data_received[4] >> 5) & 0x01; // 1-bit bool - output_struct->cubecontrol_motor_comm_error = (data_received[4] >> 4) & 0x01; // 1-bit bool - output_struct->cubewheel1_comm_error = (data_received[4] >> 3) & 0x01; // 1-bit bool - output_struct->cubewheel2_comm_error = (data_received[4] >> 2) & 0x01; // 1-bit bool - output_struct->cubewheel3_comm_error = (data_received[4] >> 1) & 0x01; // 1-bit bool - output_struct->cubestar_comm_error = (data_received[4] >> 0) & 0x01; // 1-bit bool - - output_struct->magnetometer_range_error = (data_received[5] >> 7) & 0x01; // 1-bit bool - output_struct->cam1_sram_overcurrent_detected = (data_received[5] >> 6) & 0x01; // 1-bit bool - output_struct->cam1_3v3_overcurrent_detected = (data_received[5] >> 5) & 0x01; // 1-bit bool - output_struct->cam1_sensor_busy_error = (data_received[5] >> 4) & 0x01; // 1-bit bool - output_struct->cam1_sensor_detection_error = (data_received[5] >> 3) & 0x01; // 1-bit bool - output_struct->sun_sensor_range_error = (data_received[5] >> 2) & 0x01; // 1-bit bool - output_struct->cam2_sram_overcurrent_detected = (data_received[5] >> 1) & 0x01; // 1-bit bool - output_struct->cam2_3v3_overcurrent_detected = (data_received[5]) & 0x01; // 1-bit bool - - output_struct->cam2_sensor_busy_error = (data_received[6] >> 7) & 0x01; // 1-bit bool - output_struct->cam2_sensor_detection_error = (data_received[6] >> 6) & 0x01; // 1-bit bool - output_struct->nadir_sensor_range_error = (data_received[6] >> 5) & 0x01; // 1-bit bool - output_struct->rate_sensor_range_error = (data_received[6] >> 4) & 0x01; // 1-bit bool - output_struct->wheel_speed_range_error = (data_received[6] >> 3) & 0x01; // 1-bit bool - output_struct->coarse_sun_sensor_error = (data_received[6] >> 2) & 0x01; // 1-bit bool - output_struct->startracker_match_error = (data_received[6] >> 1) & 0x01; // 1-bit bool - output_struct->startracker_overcurrent_detected = (data_received[6]) & 0x01; // 1-bit bool + 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; } \ 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 0e0ccc414..670de6c52 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -1084,3 +1084,45 @@ uint8_t ADCS_current_state_1_struct_TO_json(const ADCS_current_state_1_struct_t 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; +} \ 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 7c0b02c4b..f91484006 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -1719,4 +1719,31 @@ uint8_t TCMDEXEC_adcs_get_current_state_1(const char *args_str, TCMD_Telecommand } return status; -} \ No newline at end of file +} + +/// @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; +} diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index 378d8e29c..fb06de362 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -651,6 +651,12 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .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, }, // ****************** END SECTION: telecommand_adcs ****************** diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index 590fb885c..bab756dc7 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -648,47 +648,100 @@ uint8_t TEST_EXEC__ADCS_pack_to_current_state_1_struct() { 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 = true); - TEST_ASSERT_TRUE(result.coarse_sun_sensor_error = true); - TEST_ASSERT_TRUE(result.startracker_match_error = true); - TEST_ASSERT_TRUE(result.startracker_overcurrent_detected = true); - - return 0; - -} \ No newline at end of file + 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; +} diff --git a/firmware/Core/Src/unit_tests/unit_test_inventory.c b/firmware/Core/Src/unit_tests/unit_test_inventory.c index 062fa8772..03e9f96d2 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -294,6 +294,12 @@ const TEST_Definition_t TEST_definitions[] = { .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" + }, + // ****************** END SECTION: test_adcs ****************** { From aaf66685d4f6c686ffac51f5622a24e12945c4fd Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:55:28 -0600 Subject: [PATCH 08/22] Create Save Image command --- .../Core/Inc/adcs_drivers/adcs_commands.h | 1 + firmware/Core/Inc/adcs_drivers/adcs_types.h | 18 +++++++++++++++-- .../Core/Inc/telecommands/telecommand_adcs.h | 3 +++ .../Core/Src/adcs_drivers/adcs_commands.c | 10 ++++++++++ .../Core/Src/telecommands/telecommand_adcs.c | 20 +++++++++++++++++++ .../telecommands/telecommand_definitions.c | 6 ++++++ 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_commands.h b/firmware/Core/Inc/adcs_drivers/adcs_commands.h index e136236fa..862a15571 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -124,5 +124,6 @@ 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); #endif /* INC_ADCS_COMMANDS_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 dda52aa19..5a7602652 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -219,6 +219,20 @@ typedef enum ADCS_asgp4_mode_enum_t { 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; + /* Command Structs */ typedef struct ADCS_cmd_ack_struct_t { @@ -714,10 +728,10 @@ typedef struct ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t { ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_raw_star_tracker_struct_t raw_star_tracker; // TODO: need Raw Star Tracker telemetry (ID 211) + ADCS_raw_star_tracker_struct_t raw_star_tracker; } ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t; -// TODO: We also need the ADCS_save_image command +// TODO: We also need to downlink ADCS data from SD card typedef struct ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t { uint8_t pass; // need timestamp diff --git a/firmware/Core/Inc/telecommands/telecommand_adcs.h b/firmware/Core/Inc/telecommands/telecommand_adcs.h index dfa89acba..73156f92f 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -212,4 +212,7 @@ uint8_t TCMDEXEC_adcs_get_current_state_1(const char *args_str, TCMD_Telecommand 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); + #endif // __INCLUDE_GUARD__TELECOMMAND_adcs_H diff --git a/firmware/Core/Src/adcs_drivers/adcs_commands.c b/firmware/Core/Src/adcs_drivers/adcs_commands.c index 1292d69a5..779b7b182 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -1052,4 +1052,14 @@ uint8_t ADCS_get_raw_star_tracker_data(ADCS_raw_star_tracker_struct_t *output_st ADCS_pack_to_raw_star_tracker_struct(data_received, output_struct); return tlm_status; +} + +/// @brief Instruct the ADCS to execute the ADCS_Set_Run_Mode command. +/// @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; } \ 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 f91484006..c76b851fa 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -1747,3 +1747,23 @@ uint8_t TCMDEXEC_adcs_get_raw_star_tracker_data(const char *args_str, TCMD_Telec 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; +} \ 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 fb06de362..416b9c31f 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -658,6 +658,12 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .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, + }, // ****************** END SECTION: telecommand_adcs ****************** // ****************** SECTION: log_telecommand_defs ****************** From 1d7b35360c0f0edc92cea4645619582cf4cef8b5 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:55:25 -0600 Subject: [PATCH 09/22] Create TCMDEXEC_adcs_request_commissioning_telemetry --- firmware/Core/Inc/adcs_drivers/adcs_types.h | 53 ++-- .../Core/Inc/telecommands/telecommand_adcs.h | 4 + .../Src/adcs_drivers/adcs_struct_packers.c | 2 +- .../Src/adcs_drivers/adcs_types_to_json.c | 4 +- .../Core/Src/telecommands/telecommand_adcs.c | 263 +++++++++++++++++- .../telecommands/telecommand_definitions.c | 6 + firmware/Core/Src/unit_tests/test_adcs.c | 2 +- 7 files changed, 312 insertions(+), 22 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_types.h b/firmware/Core/Inc/adcs_drivers/adcs_types.h index 5a7602652..a359ef90c 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -233,6 +233,27 @@ typedef enum ADCS_image_size_enum_t { ADCS_IMAGE_SIZE_64_X_64_PX = 4, } ADCS_image_size_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 { @@ -555,7 +576,7 @@ typedef struct ADCS_measurements_struct_t { } ADCS_measurements_struct_t; typedef struct ADCS_acp_execution_state_struct_t { - uint16_t time_since_iteration_start_sec; + uint16_t time_since_iteration_start_ms; ADCS_current_execution_point_enum_t current_execution_point; } ADCS_acp_execution_state_struct_t; @@ -647,7 +668,7 @@ typedef struct ADCS_raw_star_tracker_struct_t { /* Commissioning Structs */ typedef struct ADCS_commissioning_determine_initial_angular_rates_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_angular_rates_struct_t estimated_angular_rates; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; @@ -655,7 +676,7 @@ typedef struct ADCS_commissioning_determine_initial_angular_rates_struct_t { typedef struct ADCS_commissioning_initial_detumbling_struct_t { // works for detumbling and Y-thomson continued detumbling - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_angular_rates_struct_t estimated_angular_rates; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; @@ -663,7 +684,7 @@ typedef struct ADCS_commissioning_initial_detumbling_struct_t { } ADCS_commissioning_initial_detumbling_struct_t; typedef struct ADCS_commissioning_magnetometer_deployment_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; @@ -671,14 +692,14 @@ typedef struct ADCS_commissioning_magnetometer_deployment_struct_t { } ADCS_commissioning_magnetometer_deployment_struct_t; typedef struct ADCS_commissioning_magnetometer_calibration_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements } ADCS_commissioning_magnetometer_calibration_struct_t; typedef struct ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; @@ -686,7 +707,7 @@ typedef struct ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct } ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t; typedef struct ADCS_commissioning_y_wheel_ramp_up_test_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; @@ -694,20 +715,20 @@ typedef struct ADCS_commissioning_y_wheel_ramp_up_test_struct_t { ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements } ADCS_commissioning_y_wheel_ramp_up_test_struct_t; -typedef struct ADCS_commissioning_initial_y_momentum_activation_struct_t { +typedef struct ADCS_commissioning_y_momentum_activation_struct_t { // for both initial Y-momentum activation and Magnetometer EKF Y-momentum - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; ADCS_wheel_speed_struct_t measured_wheel_speeds; ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements ADCS_llh_position_struct_t LLH_positions; -} ADCS_commissioning_initial_y_momentum_activation_struct_t; +} ADCS_commissioning_y_momentum_activation_struct_t; typedef struct ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t { // for both initial sun/nadir commissioning and EKF sun/nadir commissioning - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; @@ -724,7 +745,7 @@ typedef struct ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t { typedef struct ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t { // for both non-EKF and EKF - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; @@ -734,7 +755,7 @@ typedef struct ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t { // TODO: We also need to downlink ADCS data from SD card typedef struct ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_rated_sensor_rates_struct_t rated_sensor_rates; @@ -743,7 +764,7 @@ typedef struct ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct typedef struct ADCS_commissioning_sun_tracking_3_axis_control_struct_t { // for both EKF rate gyro and sun tracking 3-axis control - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_estimated_gyro_bias_struct_t estimated_gyro_bias; @@ -760,7 +781,7 @@ typedef struct ADCS_commissioning_sun_tracking_3_axis_control_struct_t { } ADCS_commissioning_sun_tracking_3_axis_control_struct_t; typedef struct ADCS_commissioning_ground_target_tracking_controller_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; ADCS_estimated_gyro_bias_struct_t estimated_gyro_bias; @@ -779,7 +800,7 @@ typedef struct ADCS_commissioning_ground_target_tracking_controller_struct_t { } ADCS_commissioning_ground_target_tracking_controller_struct_t; typedef struct ADCS_commissioning_gps_receiver_commissioning_struct_t { - uint8_t pass; // need timestamp + uint64_t current_unix_time; ADCS_llh_position_struct_t LLH_position; ADCS_raw_gps_status_struct_t raw_GPS_status; ADCS_raw_gps_time_struct_t raw_GPS_time; diff --git a/firmware/Core/Inc/telecommands/telecommand_adcs.h b/firmware/Core/Inc/telecommands/telecommand_adcs.h index 73156f92f..7160c77ec 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -7,6 +7,7 @@ // 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); @@ -215,4 +216,7 @@ uint8_t TCMDEXEC_adcs_get_raw_star_tracker_data(const char *args_str, TCMD_Telec 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); + #endif // __INCLUDE_GUARD__TELECOMMAND_adcs_H diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 28931b78f..6458a1b0a 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -592,7 +592,7 @@ uint8_t ADCS_Pack_to_Measurements_Struct(uint8_t* telemetry_data, ADCS_measureme } 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_sec = (uint16_t)(data_received[1] << 8 | data_received[0]); + 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; } 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 670de6c52..0127722fe 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -1011,8 +1011,8 @@ uint8_t ADCS_acp_execution_struct_TO_json(const ADCS_acp_execution_state_struct_ return 1; // Error: invalid input } int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, - "{\"time_since_iteration_start_sec\":%d,\"current_execution_point\":%d}", - data->time_since_iteration_start_sec, data->current_execution_point); + "{\"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 diff --git a/firmware/Core/Src/telecommands/telecommand_adcs.c b/firmware/Core/Src/telecommands/telecommand_adcs.c index c76b851fa..7cc880a7f 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 @@ -855,10 +856,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 @@ -1765,5 +1766,263 @@ uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandCha } uint8_t status = ADCS_save_image_to_sd(args_8[0], args_8[1]); + return status; +} + +// TODO: agenda modification for repeating +/// @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) +/// @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 argument; + TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &argument); + ADCS_commissioning_step_enum_t commissioning_step = (ADCS_commissioning_step_enum_t) argument; + + 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; + + #define MEMORY_MODULE_FUNCTION(x) ; // TODO: delete this once memory module is implemented + + switch(commissioning_step) { + case ADCS_COMMISISONING_STEP_DETERMINE_INITIAL_ANGULAR_RATES: { + ADCS_commissioning_determine_initial_angular_rates_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_angular_rates(&commissioning_data.estimated_angular_rates); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_INITIAL_DETUMBLING: { + ADCS_commissioning_initial_detumbling_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_angular_rates(&commissioning_data.estimated_angular_rates); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); + status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_CONTINUED_DETUMBLING_TO_Y_THOMSON: { + ADCS_commissioning_initial_detumbling_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_angular_rates(&commissioning_data.estimated_angular_rates); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); + status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_MAGNETOMETER_DEPLOYMENT: { + ADCS_commissioning_magnetometer_deployment_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); + status += ADCS_get_cubecontrol_current(&commissioning_data.cubecontrol_currents); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_MAGNETOMETER_CALIBRATION: { + ADCS_commissioning_magnetometer_calibration_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_measurements(&commissioning_data.adcs_measurements); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_ANGULAR_RATE_AND_PITCH_ANGLE_ESTIMATION: { + ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_measurements(&commissioning_data.adcs_measurements); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_Y_WHEEL_RAMP_UP_TEST: { + ADCS_commissioning_y_wheel_ramp_up_test_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + status += ADCS_get_measurements(&commissioning_data.adcs_measurements); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_INITIAL_Y_MOMENTUM_ACTIVATION: { + ADCS_commissioning_y_momentum_activation_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + status += ADCS_get_measurements(&commissioning_data.adcs_measurements); + status += ADCS_get_llh_position(&commissioning_data.LLH_positions); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_CONTINUED_Y_MOMENTUM_ACTIVATION_AND_MAGNETOMETER_EKF: { + ADCS_commissioning_y_momentum_activation_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + status += ADCS_get_measurements(&commissioning_data.adcs_measurements); + status += ADCS_get_llh_position(&commissioning_data.LLH_positions); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_CUBESENSE_SUN_NADIR: { + ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_coarse_sun_sensor_1_to_6(&commissioning_data.raw_css_1_to_6_measurements); + status += ADCS_get_raw_coarse_sun_sensor_7_to_10(&commissioning_data.raw_css_7_to_10_measurements); + status += ADCS_get_raw_cam1_sensor(&commissioning_data.raw_cam1_measurements); + status += ADCS_get_raw_cam2_sensor(&commissioning_data.raw_cam2_measurements); + status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); + status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_EKF_ACTIVATION_SUN_AND_NADIR: { + ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_coarse_sun_sensor_1_to_6(&commissioning_data.raw_css_1_to_6_measurements); + status += ADCS_get_raw_coarse_sun_sensor_7_to_10(&commissioning_data.raw_css_7_to_10_measurements); + status += ADCS_get_raw_cam1_sensor(&commissioning_data.raw_cam1_measurements); + status += ADCS_get_raw_cam2_sensor(&commissioning_data.raw_cam2_measurements); + status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); + status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_CUBESTAR_STAR_TRACKER: { + ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_star_tracker_data(&commissioning_data.raw_star_tracker); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_EKF_ACTIVATION_WITH_STAR_VECTOR_MEASUREMENTS: { + ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_raw_star_tracker_data(&commissioning_data.raw_star_tracker); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_ZERO_BIAS_3_AXIS_REACTION_WHEEL_CONTROL: { + ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_EKF_WITH_RATE_GYRO_STAR_TRACKER_MEASUREMENTS: { + ADCS_commissioning_sun_tracking_3_axis_control_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_estimated_gyro_bias(&commissioning_data.estimated_gyro_bias); + status += ADCS_get_estimation_innovation_vector(&commissioning_data.estimation_innovation_vector); + status += ADCS_get_magnetic_field_vector(&commissioning_data.magnetic_field_vector); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); + status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); + status += ADCS_get_igrf_magnetic_field_vector(&commissioning_data.igrf_magnetic_field_vector); + status += ADCS_get_quaternion_error_vector(&commissioning_data.quaternion_error_vector); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_SUN_TRACKING_3_AXIS_CONTROL: { + ADCS_commissioning_sun_tracking_3_axis_control_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_estimated_gyro_bias(&commissioning_data.estimated_gyro_bias); + status += ADCS_get_estimation_innovation_vector(&commissioning_data.estimation_innovation_vector); + status += ADCS_get_magnetic_field_vector(&commissioning_data.magnetic_field_vector); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); + status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); + status += ADCS_get_igrf_magnetic_field_vector(&commissioning_data.igrf_magnetic_field_vector); + status += ADCS_get_quaternion_error_vector(&commissioning_data.quaternion_error_vector); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_GROUND_TARGET_TRACKING_CONTROLLER: { + ADCS_commissioning_ground_target_tracking_controller_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); + status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); + status += ADCS_get_estimated_gyro_bias(&commissioning_data.estimated_gyro_bias); + status += ADCS_get_estimation_innovation_vector(&commissioning_data.estimation_innovation_vector); + status += ADCS_get_magnetic_field_vector(&commissioning_data.magnetic_field_vector); + status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); + status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); + status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); + status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); + status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); + status += ADCS_get_igrf_magnetic_field_vector(&commissioning_data.igrf_magnetic_field_vector); + status += ADCS_get_quaternion_error_vector(&commissioning_data.quaternion_error_vector); + status += ADCS_get_llh_position(&commissioning_data.LLH_position); + status += ADCS_get_commanded_attitude_angles(&commissioning_data.commanded_attitude_angles); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + break; + } + case ADCS_COMMISISONING_STEP_GPS_RECEIVER: { + ADCS_commissioning_gps_receiver_commissioning_struct_t commissioning_data; + commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); + status += ADCS_get_llh_position(&commissioning_data.LLH_position); + status += ADCS_get_raw_gps_status(&commissioning_data.raw_GPS_status); + status += ADCS_get_raw_gps_time(&commissioning_data.raw_GPS_time); + status += ADCS_get_raw_gps_x(&commissioning_data.raw_GPS_x); + status += ADCS_get_raw_gps_y(&commissioning_data.raw_GPS_y); + status += ADCS_get_raw_gps_z(&commissioning_data.raw_GPS_z); + MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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 416b9c31f..701f31b4b 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -663,6 +663,12 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .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 = 1, + .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, // ****************** END SECTION: telecommand_adcs ****************** diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index bab756dc7..4eddb979f 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -634,7 +634,7 @@ uint8_t TEST_EXEC__ADCS_pack_to_acp_execution_state_struct() { ADCS_Pack_to_ACP_Execution_State_Struct(input_params, &result); - TEST_ASSERT_TRUE(result.time_since_iteration_start_sec == 43844); + 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; From e8eecb4cefdb4ac531f91ea7913fe722e83d17ff Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:57:48 -0600 Subject: [PATCH 10/22] Minor change: lowercase function names --- .../Inc/adcs_drivers/adcs_struct_packers.h | 78 +++++++++--------- .../Core/Src/adcs_drivers/adcs_commands.c | 82 +++++++++---------- .../Src/adcs_drivers/adcs_struct_packers.c | 78 +++++++++--------- firmware/Core/Src/unit_tests/test_adcs.c | 80 +++++++++--------- .../Core/Src/unit_tests/unit_test_inventory.c | 78 +++++++++--------- 5 files changed, 198 insertions(+), 198 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h index 86e8e5412..59e4e943b 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -4,45 +4,45 @@ #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_ACP_Execution_State_Struct(uint8_t* data_received, ADCS_acp_execution_state_struct_t* output_struct); +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); diff --git a/firmware/Core/Src/adcs_drivers/adcs_commands.c b/firmware/Core/Src/adcs_drivers/adcs_commands.c index 779b7b182..c3a42c58e 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -29,7 +29,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 +57,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 +71,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 +86,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 +227,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 +315,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 +329,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 +363,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 +408,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 +422,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 +436,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 +450,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 +464,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 +478,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 +492,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 +506,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 +599,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 +656,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 +687,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 +727,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 +741,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 +755,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 +769,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 +783,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 +797,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 +811,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 +825,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 +839,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 +853,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 +867,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 +881,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 +895,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 +909,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 +923,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 +937,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 +951,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 +965,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 +979,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 +993,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 +1007,7 @@ 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; } @@ -1021,7 +1021,7 @@ uint8_t ADCS_get_acp_execution_state(ADCS_acp_execution_state_struct_t *output_s 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); + ADCS_pack_to_acp_execution_state_struct(data_received, output_struct); return tlm_status; } diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 6458a1b0a..03d460afc 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,7 +108,7 @@ 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; @@ -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; @@ -591,7 +591,7 @@ uint8_t ADCS_Pack_to_Measurements_Struct(uint8_t* telemetry_data, ADCS_measureme return 0; } -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_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; diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index 4eddb979f..733b6e673 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -10,7 +10,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 +23,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 +38,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 +53,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 +67,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 +86,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 +98,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 +110,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 +131,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 +147,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 +159,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 +173,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 +185,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 +198,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 +215,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 +240,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 +255,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 +286,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 +313,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 +327,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 +344,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 +358,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 +372,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 +386,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 +400,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 +414,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 +428,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 +442,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 +456,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 +472,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 +488,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 +500,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 +512,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 +524,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 +535,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 +548,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 +557,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 +584,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); @@ -632,7 +632,7 @@ 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); + 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); diff --git a/firmware/Core/Src/unit_tests/unit_test_inventory.c b/firmware/Core/Src/unit_tests/unit_test_inventory.c index 03e9f96d2..de1aa85d0 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -57,235 +57,235 @@ 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_name = "ADCS_pack_to_acp_execution_state_struct" }, { From 5050a521b5a4ab22aa82c36bbff1ea378bcf820f Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:52:14 -0600 Subject: [PATCH 11/22] Create delayed and repeated telecommand functions I might have to revert this commit in future. --- .../Core/Inc/telecommands/telecommand_adcs.h | 4 ++ .../Inc/telecommands/telecommand_executor.h | 4 ++ .../Src/telecommands/telecommand_executor.c | 59 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/firmware/Core/Inc/telecommands/telecommand_adcs.h b/firmware/Core/Inc/telecommands/telecommand_adcs.h index 7160c77ec..7524d71e8 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -4,6 +4,7 @@ #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; } @@ -219,4 +220,7 @@ uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandCha 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 test_telecommand_delaying(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/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. From 900081adb885b64193792edfa3833d87d9f3fd20 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 26 Oct 2024 12:59:46 -0600 Subject: [PATCH 12/22] minor bugfix --- firmware/Core/Inc/adcs_drivers/adcs_types.h | 2 +- firmware/Core/Src/adcs_drivers/adcs_struct_packers.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_types.h b/firmware/Core/Inc/adcs_drivers/adcs_types.h index a359ef90c..95431a827 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -298,7 +298,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{ diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 03d460afc..35d375c7f 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -113,7 +113,7 @@ uint8_t ADCS_pack_to_llh_position_struct(uint8_t *data_received, ADCS_llh_positi // 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; } From 6e7e0d2e584333293240ef83dce1bc3c50c256a6 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:16:58 -0600 Subject: [PATCH 13/22] ADCS Unix time telecommands --- .../Core/Inc/adcs_drivers/adcs_commands.h | 2 + .../Inc/adcs_drivers/adcs_struct_packers.h | 1 + .../Inc/adcs_drivers/adcs_types_to_json.h | 1 + .../Core/Inc/telecommands/telecommand_adcs.h | 5 ++- firmware/Core/Inc/unit_tests/test_adcs.h | 1 + .../Core/Src/adcs_drivers/adcs_commands.c | 31 +++++++++++++++ .../Src/adcs_drivers/adcs_struct_packers.c | 8 ++++ .../Src/adcs_drivers/adcs_types_to_json.c | 17 +++++++++ .../Core/Src/telecommands/telecommand_adcs.c | 38 +++++++++++++++++++ .../telecommands/telecommand_definitions.c | 13 +++++++ firmware/Core/Src/unit_tests/test_adcs.c | 11 ++++++ .../Core/Src/unit_tests/unit_test_inventory.c | 6 +++ 12 files changed, 133 insertions(+), 1 deletion(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_commands.h b/firmware/Core/Inc/adcs_drivers/adcs_commands.h index 862a15571..8e2a606cd 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -125,5 +125,7 @@ uint8_t ADCS_get_acp_execution_state(ADCS_acp_execution_state_struct_t *output_s 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_set_current_unix_time(); #endif /* INC_ADCS_COMMANDS_H_ */ \ No newline at end of file diff --git a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h index 59e4e943b..25ccb51ae 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -45,5 +45,6 @@ uint8_t ADCS_pack_to_measurements_struct(uint8_t* telemetry_data, ADCS_measureme 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); #endif /* INC_ADCS_STRUCT_PACKERS_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 71fe269ab..f11ed7f71 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h @@ -50,5 +50,6 @@ uint8_t ADCS_generic_telemetry_uint8_array_TO_json(const uint8_t *data, const ui 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); #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 7524d71e8..1bb2f6bfc 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -220,7 +220,10 @@ uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandCha 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 test_telecommand_delaying(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, +uint8_t TCMDEXEC_adcs_set_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_get_current_unix_time(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/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index fb1ea9196..a66493feb 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -46,6 +46,7 @@ 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(); #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 c3a42c58e..4a6be346f 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 @@ -1062,4 +1063,34 @@ uint8_t ADCS_save_image_to_sd(ADCS_camera_select_enum_t camera_select, ADCS_imag 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_set_current_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; } \ No newline at end of file diff --git a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c index 35d375c7f..d4bca45d9 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -692,4 +692,12 @@ uint8_t ADCS_pack_to_raw_star_tracker_struct(uint8_t *input_data, ADCS_raw_star_ 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; + } \ 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 0127722fe..5df557a50 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -1124,5 +1124,22 @@ uint8_t ADCS_raw_star_tracker_struct_TO_json(const ADCS_raw_star_tracker_struct_ 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 + } + + int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len,"{\"current_adcs_unix_time\":%llu}",*data); + + 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 7cc880a7f..4a52db736 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -1769,6 +1769,44 @@ uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandCha 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_set_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 status = ADCS_set_current_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; +} + // TODO: agenda modification for repeating /// @brief Telecommand: Request commissioning telemetry from the ADCS and save it to the memory module /// @param args_str diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index 112099faf..1ea15c502 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -681,7 +681,20 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .tcmd_func = TCMDEXEC_adcs_request_commissioning_telemetry, .number_of_args = 1, .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, + }, + { + .tcmd_name = "adcs_set_current_unix_time", + .tcmd_func = TCMDEXEC_adcs_set_current_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, + }, + // ****************** END SECTION: telecommand_adcs ****************** // ****************** SECTION: log_telecommand_defs ****************** diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index 733b6e673..0bfc41723 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -745,3 +745,14 @@ uint8_t TEST_EXEC__ADCS_pack_to_raw_star_tracker_struct() { 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; +} \ 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 de1aa85d0..5c7fb0488 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -300,6 +300,12 @@ const TEST_Definition_t TEST_definitions[] = { .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" + }, + // ****************** END SECTION: test_adcs ****************** { From 9db01277759222fe84e6442d11154fd9a814efcb Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:56:27 -0600 Subject: [PATCH 14/22] Create SD Log Config commands --- .../Core/Inc/adcs_drivers/adcs_command_ids.h | 65 ++++++++++++++++++ .../Core/Inc/adcs_drivers/adcs_commands.h | 5 +- .../Inc/adcs_drivers/adcs_internal_drivers.h | 1 + .../Inc/adcs_drivers/adcs_struct_packers.h | 1 + firmware/Core/Inc/adcs_drivers/adcs_types.h | 12 ++++ .../Inc/adcs_drivers/adcs_types_to_json.h | 1 + .../Core/Inc/telecommands/telecommand_adcs.h | 8 ++- firmware/Core/Inc/unit_tests/test_adcs.h | 1 + .../Core/Src/adcs_drivers/adcs_commands.c | 60 ++++++++++++++++- .../Src/adcs_drivers/adcs_internal_drivers.c | 16 +++++ .../Src/adcs_drivers/adcs_struct_packers.c | 12 ++++ .../Src/adcs_drivers/adcs_types_to_json.c | 20 ++++++ .../Core/Src/telecommands/telecommand_adcs.c | 66 ++++++++++++++++++- .../telecommands/telecommand_definitions.c | 16 ++++- firmware/Core/Src/unit_tests/test_adcs.c | 19 +++++- .../Core/Src/unit_tests/unit_test_inventory.c | 8 ++- 16 files changed, 301 insertions(+), 10 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h b/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h index 36d9e5113..1dd1219c7 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_command_ids.h @@ -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 8e2a606cd..a1c2398ac 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_commands.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_commands.h @@ -126,6 +126,9 @@ 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_set_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..df661c2e3 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h @@ -16,6 +16,7 @@ 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_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 25ccb51ae..8edcfc118 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_struct_packers.h @@ -46,5 +46,6 @@ uint8_t ADCS_pack_to_acp_execution_state_struct(uint8_t* data_received, ADCS_acp 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 95431a827..1371a3a37 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -233,6 +233,11 @@ typedef enum ADCS_image_size_enum_t { 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, @@ -665,6 +670,13 @@ typedef struct ADCS_raw_star_tracker_struct_t { 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; + /* Commissioning Structs */ typedef struct ADCS_commissioning_determine_initial_angular_rates_struct_t { 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 f11ed7f71..b2e265c88 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types_to_json.h @@ -51,5 +51,6 @@ uint8_t ADCS_acp_execution_struct_TO_json(const ADCS_acp_execution_state_struct_ 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 1bb2f6bfc..c6a57c9fa 100644 --- a/firmware/Core/Inc/telecommands/telecommand_adcs.h +++ b/firmware/Core/Inc/telecommands/telecommand_adcs.h @@ -220,10 +220,16 @@ uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandCha 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_set_current_unix_time(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, +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/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index a66493feb..5299ca0dd 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -47,6 +47,7 @@ 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(); #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 4a6be346f..3ff6e0abb 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_commands.c +++ b/firmware/Core/Src/adcs_drivers/adcs_commands.c @@ -1055,7 +1055,7 @@ uint8_t ADCS_get_raw_star_tracker_data(ADCS_raw_star_tracker_struct_t *output_st return tlm_status; } -/// @brief Instruct the ADCS to execute the ADCS_Set_Run_Mode command. +/// @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. @@ -1067,7 +1067,7 @@ uint8_t ADCS_save_image_to_sd(ADCS_camera_select_enum_t camera_select, ADCS_imag /// @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_set_current_unix_time() { +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; @@ -1092,5 +1092,61 @@ uint8_t ADCS_get_current_unix_time(uint64_t* epoch_time_ms) { 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..1b1bcd289 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c @@ -166,6 +166,22 @@ uint8_t ADCS_convert_uint32_to_reversed_uint8_array_members(uint8_t *array, uint 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 d4bca45d9..392f13320 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_struct_packers.c @@ -700,4 +700,16 @@ uint8_t ADCS_pack_to_unix_time_ms(uint8_t *data_received, uint64_t *output_data) *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 5df557a50..9b58b0c2f 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -1141,5 +1141,25 @@ uint8_t ADCS_unix_time_ms_TO_json(const uint64_t *data, char json_output_str[], 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 4a52db736..62a213286 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -1773,9 +1773,9 @@ uint8_t TCMDEXEC_adcs_save_image_to_sd(const char *args_str, TCMD_TelecommandCha /// @param args_str /// - No arguments for this command /// @return 0 on success, >0 on error -uint8_t TCMDEXEC_adcs_set_current_unix_time(const char *args_str, TCMD_TelecommandChannel_enum_t tcmd_channel, +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_set_current_unix_time(); + uint8_t status = ADCS_synchronise_unix_time(); return status; } @@ -1807,6 +1807,68 @@ uint8_t TCMDEXEC_adcs_get_current_unix_time(const char *args_str, TCMD_Telecomma 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; +} + // TODO: agenda modification for repeating /// @brief Telecommand: Request commissioning telemetry from the ADCS and save it to the memory module /// @param args_str diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index 1ea15c502..41edfd045 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -683,8 +683,8 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, { - .tcmd_name = "adcs_set_current_unix_time", - .tcmd_func = TCMDEXEC_adcs_set_current_unix_time, + .tcmd_name = "adcs_synchronise_unix_time", + .tcmd_func = TCMDEXEC_adcs_synchronise_unix_time, .number_of_args = 0, .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, @@ -694,6 +694,18 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { .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 ****************** diff --git a/firmware/Core/Src/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index 0bfc41723..a55ca701e 100644 --- a/firmware/Core/Src/unit_tests/test_adcs.c +++ b/firmware/Core/Src/unit_tests/test_adcs.c @@ -755,4 +755,21 @@ uint8_t TEST_EXEC__ADCS_pack_to_unix_time_ms() { TEST_ASSERT_TRUE(result == 1730251606610); return 0; -} \ No newline at end of file +} + +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; +} + diff --git a/firmware/Core/Src/unit_tests/unit_test_inventory.c b/firmware/Core/Src/unit_tests/unit_test_inventory.c index 5c7fb0488..25883366f 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -304,7 +304,13 @@ const TEST_Definition_t TEST_definitions[] = { .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" + }, // ****************** END SECTION: test_adcs ****************** From ebd75163b5c9090b3190cbdbe7cf9b91f09dd8d3 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:36:06 -0700 Subject: [PATCH 15/22] Update request_commissioning_telemetry with SD logger command --- firmware/Core/Inc/adcs_drivers/adcs_types.h | 142 --------- .../Core/Src/telecommands/telecommand_adcs.c | 288 +++++++----------- .../telecommands/telecommand_definitions.c | 2 +- 3 files changed, 114 insertions(+), 318 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_types.h b/firmware/Core/Inc/adcs_drivers/adcs_types.h index 1371a3a37..369b9b499 100644 --- a/firmware/Core/Inc/adcs_drivers/adcs_types.h +++ b/firmware/Core/Inc/adcs_drivers/adcs_types.h @@ -677,148 +677,6 @@ typedef struct ADCS_sd_log_config_struct { ADCS_sd_log_destination_enum_t which_sd; } ADCS_sd_log_config_struct; -/* Commissioning Structs */ - -typedef struct ADCS_commissioning_determine_initial_angular_rates_struct_t { - uint64_t current_unix_time; - ADCS_angular_rates_struct_t estimated_angular_rates; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; -} ADCS_commissioning_determine_initial_angular_rates_struct_t; - -typedef struct ADCS_commissioning_initial_detumbling_struct_t { - // works for detumbling and Y-thomson continued detumbling - uint64_t current_unix_time; - ADCS_angular_rates_struct_t estimated_angular_rates; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; - ADCS_magnetorquer_command_struct_t magnetorquer_commands; -} ADCS_commissioning_initial_detumbling_struct_t; - -typedef struct ADCS_commissioning_magnetometer_deployment_struct_t { - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_raw_magnetometer_values_struct_t raw_magnetometer_measurements; - ADCS_cubecontrol_current_struct_t cubecontrol_currents; -} ADCS_commissioning_magnetometer_deployment_struct_t; - -typedef struct ADCS_commissioning_magnetometer_calibration_struct_t { - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements -} ADCS_commissioning_magnetometer_calibration_struct_t; - -typedef struct ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t { - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements -} ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t; - -typedef struct ADCS_commissioning_y_wheel_ramp_up_test_struct_t { - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_wheel_speed_struct_t measured_wheel_speeds; - ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements -} ADCS_commissioning_y_wheel_ramp_up_test_struct_t; - -typedef struct ADCS_commissioning_y_momentum_activation_struct_t { - // for both initial Y-momentum activation and Magnetometer EKF Y-momentum - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_wheel_speed_struct_t measured_wheel_speeds; - ADCS_measurements_struct_t adcs_measurements; // only need calibrated magnetometer measurements - ADCS_llh_position_struct_t LLH_positions; -} ADCS_commissioning_y_momentum_activation_struct_t; - -typedef struct ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t { - // for both initial sun/nadir commissioning and EKF sun/nadir commissioning - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - - ADCS_raw_coarse_sun_sensor_1_to_6_struct_t raw_css_1_to_6_measurements; - ADCS_raw_coarse_sun_sensor_7_to_10_struct_t raw_css_7_to_10_measurements; - - ADCS_raw_cam_sensor_struct_t raw_cam1_measurements; - ADCS_raw_cam_sensor_struct_t raw_cam2_measurements; - - ADCS_fine_sun_vector_struct_t fine_sun_vector; - ADCS_nadir_vector_struct_t nadir_vector; -} ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t; - -typedef struct ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t { - // for both non-EKF and EKF - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_raw_star_tracker_struct_t raw_star_tracker; -} ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t; - // TODO: We also need to downlink ADCS data from SD card -typedef struct ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t { - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_wheel_speed_struct_t measured_wheel_speeds; -} ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t; - -typedef struct ADCS_commissioning_sun_tracking_3_axis_control_struct_t { - // for both EKF rate gyro and sun tracking 3-axis control - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_estimated_gyro_bias_struct_t estimated_gyro_bias; - ADCS_estimation_innovation_vector_struct_t estimation_innovation_vector; - ADCS_magnetic_field_vector_struct_t magnetic_field_vector; - ADCS_fine_sun_vector_struct_t fine_sun_vector; - ADCS_nadir_vector_struct_t nadir_vector; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_wheel_speed_struct_t measured_wheel_speeds; - ADCS_magnetorquer_command_struct_t magnetorquer_commands; - ADCS_wheel_speed_struct_t commanded_wheel_speeds; - ADCS_magnetic_field_vector_struct_t igrf_magnetic_field_vector; - ADCS_quaternion_error_vector_struct_t quaternion_error_vector; -} ADCS_commissioning_sun_tracking_3_axis_control_struct_t; - -typedef struct ADCS_commissioning_ground_target_tracking_controller_struct_t { - uint64_t current_unix_time; - ADCS_fine_angular_rates_struct_t fine_estimated_angular_rates; - ADCS_estimated_attitude_angles_struct_t estimated_attitude_angles; - ADCS_estimated_gyro_bias_struct_t estimated_gyro_bias; - ADCS_estimation_innovation_vector_struct_t estimation_innovation_vector; - ADCS_magnetic_field_vector_struct_t magnetic_field_vector; - ADCS_fine_sun_vector_struct_t fine_sun_vector; - ADCS_nadir_vector_struct_t nadir_vector; - ADCS_rated_sensor_rates_struct_t rated_sensor_rates; - ADCS_wheel_speed_struct_t measured_wheel_speeds; - ADCS_magnetorquer_command_struct_t magnetorquer_commands; - ADCS_wheel_speed_struct_t commanded_wheel_speeds; - ADCS_magnetic_field_vector_struct_t igrf_magnetic_field_vector; - ADCS_quaternion_error_vector_struct_t quaternion_error_vector; - ADCS_llh_position_struct_t LLH_position; - ADCS_commanded_angles_struct_t commanded_attitude_angles; -} ADCS_commissioning_ground_target_tracking_controller_struct_t; - -typedef struct ADCS_commissioning_gps_receiver_commissioning_struct_t { - uint64_t current_unix_time; - ADCS_llh_position_struct_t LLH_position; - ADCS_raw_gps_status_struct_t raw_GPS_status; - ADCS_raw_gps_time_struct_t raw_GPS_time; - ADCS_raw_gps_struct_t raw_GPS_x; - ADCS_raw_gps_struct_t raw_GPS_y; - ADCS_raw_gps_struct_t raw_GPS_z; -} ADCS_commissioning_gps_receiver_commissioning_struct_t; - #endif /* INC_ADCS_TYPES_H_ */ \ 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 62a213286..03f25d374 100644 --- a/firmware/Core/Src/telecommands/telecommand_adcs.c +++ b/firmware/Core/Src/telecommands/telecommand_adcs.c @@ -11,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" @@ -1869,17 +1870,34 @@ uint8_t TCMDEXEC_adcs_get_sd_log_config(const char *args_str, TCMD_TelecommandCh return status; } -// TODO: agenda modification for repeating /// @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 argument; - TCMD_extract_uint64_arg(args_str, strlen(args_str), 0, &argument); - ADCS_commissioning_step_enum_t commissioning_step = (ADCS_commissioning_step_enum_t) argument; + 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 @@ -1892,231 +1910,151 @@ uint8_t TCMDEXEC_adcs_request_commissioning_telemetry(const char *args_str, TCMD } while (current_state.time_since_iteration_start_ms <= 500); uint8_t status = 0; - - #define MEMORY_MODULE_FUNCTION(x) ; // TODO: delete this once memory module is implemented - + // 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: { - ADCS_commissioning_determine_initial_angular_rates_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_angular_rates(&commissioning_data.estimated_angular_rates); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_initial_detumbling_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_angular_rates(&commissioning_data.estimated_angular_rates); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); - status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_initial_detumbling_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_angular_rates(&commissioning_data.estimated_angular_rates); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); - status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_magnetometer_deployment_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_magnetometer_values(&commissioning_data.raw_magnetometer_measurements); - status += ADCS_get_cubecontrol_current(&commissioning_data.cubecontrol_currents); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_magnetometer_calibration_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_measurements(&commissioning_data.adcs_measurements); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_angular_rate_and_pitch_angle_estimation_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_measurements(&commissioning_data.adcs_measurements); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_y_wheel_ramp_up_test_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - status += ADCS_get_measurements(&commissioning_data.adcs_measurements); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_y_momentum_activation_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - status += ADCS_get_measurements(&commissioning_data.adcs_measurements); - status += ADCS_get_llh_position(&commissioning_data.LLH_positions); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_y_momentum_activation_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - status += ADCS_get_measurements(&commissioning_data.adcs_measurements); - status += ADCS_get_llh_position(&commissioning_data.LLH_positions); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_coarse_sun_sensor_1_to_6(&commissioning_data.raw_css_1_to_6_measurements); - status += ADCS_get_raw_coarse_sun_sensor_7_to_10(&commissioning_data.raw_css_7_to_10_measurements); - status += ADCS_get_raw_cam1_sensor(&commissioning_data.raw_cam1_measurements); - status += ADCS_get_raw_cam2_sensor(&commissioning_data.raw_cam2_measurements); - status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); - status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_cubesense_sun_nadir_commissioning_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_coarse_sun_sensor_1_to_6(&commissioning_data.raw_css_1_to_6_measurements); - status += ADCS_get_raw_coarse_sun_sensor_7_to_10(&commissioning_data.raw_css_7_to_10_measurements); - status += ADCS_get_raw_cam1_sensor(&commissioning_data.raw_cam1_measurements); - status += ADCS_get_raw_cam2_sensor(&commissioning_data.raw_cam2_measurements); - status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); - status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_star_tracker_data(&commissioning_data.raw_star_tracker); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_cubestar_star_tracker_commissioning_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_raw_star_tracker_data(&commissioning_data.raw_star_tracker); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_zero_bias_3_axis_reaction_wheel_control_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_sun_tracking_3_axis_control_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_estimated_gyro_bias(&commissioning_data.estimated_gyro_bias); - status += ADCS_get_estimation_innovation_vector(&commissioning_data.estimation_innovation_vector); - status += ADCS_get_magnetic_field_vector(&commissioning_data.magnetic_field_vector); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); - status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); - status += ADCS_get_igrf_magnetic_field_vector(&commissioning_data.igrf_magnetic_field_vector); - status += ADCS_get_quaternion_error_vector(&commissioning_data.quaternion_error_vector); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_sun_tracking_3_axis_control_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_estimated_gyro_bias(&commissioning_data.estimated_gyro_bias); - status += ADCS_get_estimation_innovation_vector(&commissioning_data.estimation_innovation_vector); - status += ADCS_get_magnetic_field_vector(&commissioning_data.magnetic_field_vector); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); - status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); - status += ADCS_get_igrf_magnetic_field_vector(&commissioning_data.igrf_magnetic_field_vector); - status += ADCS_get_quaternion_error_vector(&commissioning_data.quaternion_error_vector); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_ground_target_tracking_controller_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_estimate_fine_angular_rates(&commissioning_data.fine_estimated_angular_rates); - status += ADCS_get_estimated_attitude_angles(&commissioning_data.estimated_attitude_angles); - status += ADCS_get_estimated_gyro_bias(&commissioning_data.estimated_gyro_bias); - status += ADCS_get_estimation_innovation_vector(&commissioning_data.estimation_innovation_vector); - status += ADCS_get_magnetic_field_vector(&commissioning_data.magnetic_field_vector); - status += ADCS_get_rate_sensor_rates(&commissioning_data.rated_sensor_rates); - status += ADCS_get_fine_sun_vector(&commissioning_data.fine_sun_vector); - status += ADCS_get_nadir_vector(&commissioning_data.nadir_vector); - status += ADCS_get_wheel_speed(&commissioning_data.measured_wheel_speeds); - status += ADCS_get_magnetorquer_command(&commissioning_data.magnetorquer_commands); - status += ADCS_get_igrf_magnetic_field_vector(&commissioning_data.igrf_magnetic_field_vector); - status += ADCS_get_quaternion_error_vector(&commissioning_data.quaternion_error_vector); - status += ADCS_get_llh_position(&commissioning_data.LLH_position); - status += ADCS_get_commanded_attitude_angles(&commissioning_data.commanded_attitude_angles); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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: { - ADCS_commissioning_gps_receiver_commissioning_struct_t commissioning_data; - commissioning_data.current_unix_time = TIM_get_current_unix_epoch_time_ms(); - status += ADCS_get_llh_position(&commissioning_data.LLH_position); - status += ADCS_get_raw_gps_status(&commissioning_data.raw_GPS_status); - status += ADCS_get_raw_gps_time(&commissioning_data.raw_GPS_time); - status += ADCS_get_raw_gps_x(&commissioning_data.raw_GPS_x); - status += ADCS_get_raw_gps_y(&commissioning_data.raw_GPS_y); - status += ADCS_get_raw_gps_z(&commissioning_data.raw_GPS_z); - MEMORY_MODULE_FUNCTION(commissioning_data); // save to memory module + 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); diff --git a/firmware/Core/Src/telecommands/telecommand_definitions.c b/firmware/Core/Src/telecommands/telecommand_definitions.c index 41edfd045..f5d59b94d 100644 --- a/firmware/Core/Src/telecommands/telecommand_definitions.c +++ b/firmware/Core/Src/telecommands/telecommand_definitions.c @@ -679,7 +679,7 @@ const TCMD_TelecommandDefinition_t TCMD_telecommand_definitions[] = { { .tcmd_name = "adcs_request_commissioning_telemetry", .tcmd_func = TCMDEXEC_adcs_request_commissioning_telemetry, - .number_of_args = 1, + .number_of_args = 3, .readiness_level = TCMD_READINESS_LEVEL_FOR_OPERATION, }, { From bafd10dc0ed85e3b5c23c4a629a5c3178f9697a5 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:31:03 -0700 Subject: [PATCH 16/22] Update printing doubles to JSON --- .../Inc/adcs_drivers/adcs_internal_drivers.h | 1 + .../Src/adcs_drivers/adcs_internal_drivers.c | 29 +++++++ .../Src/adcs_drivers/adcs_types_to_json.c | 75 ++++++++----------- 3 files changed, 62 insertions(+), 43 deletions(-) diff --git a/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h b/firmware/Core/Inc/adcs_drivers/adcs_internal_drivers.h index df661c2e3..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,7 @@ 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) diff --git a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c index 1b1bcd289..cc07342f2 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,34 @@ 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. +/// @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; + } + + int64_t data_int_portion = (int64_t)(input); + uint64_t data_decimal_portion = (uint64_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, "-%lld.%0*lld", data_int_portion, precision, data_decimal_portion); + } else { + snprintf_ret = snprintf(output_string, str_len, "%lld.%0*lld", 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 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 9b58b0c2f..eec2f3a4e 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c +++ b/firmware/Core/Src/adcs_drivers/adcs_types_to_json.c @@ -199,32 +199,28 @@ uint8_t ADCS_orbit_params_struct_TO_json(const ADCS_orbit_params_struct_t *data, return 1; // Error: invalid input } - // snprintf doesn't support printing floats, so we convert them into pairs of ints instead - - int32_t data_int_portions[8]; - - data_int_portions[0] = (int32_t)(data->inclination_deg); - data_int_portions[1] = (int32_t)(data->eccentricity); - data_int_portions[2] = (int32_t)(data->ascending_node_right_ascension_deg); - data_int_portions[3] = (int32_t)(data->perigee_argument_deg); - data_int_portions[4] = (int32_t)(data->b_star_drag_term); - data_int_portions[5] = (int32_t)(data->mean_motion_orbits_per_day); - data_int_portions[6] = (int32_t)(data->mean_anomaly_deg); - data_int_portions[7] = (int32_t)(data->epoch_year_point_day); - - int32_t data_decimal_portions[8]; - - data_decimal_portions[0] = (int32_t)((data->inclination_deg - data_int_portions[0]) * 1000000); - data_decimal_portions[1] = (int32_t)((data->eccentricity - data_int_portions[1]) * 1000000); - data_decimal_portions[2] = (int32_t)((data->ascending_node_right_ascension_deg - data_int_portions[2]) * 1000000); - data_decimal_portions[3] = (int32_t)((data->perigee_argument_deg - data_int_portions[3]) * 1000000); - data_decimal_portions[4] = (int32_t)((data->b_star_drag_term - data_int_portions[4]) * 1000000); - data_decimal_portions[5] = (int32_t)((data->mean_motion_orbits_per_day - data_int_portions[5]) * 1000000); - data_decimal_portions[6] = (int32_t)((data->mean_anomaly_deg - data_int_portions[6]) * 1000000); - data_decimal_portions[7] = (int32_t)((data->epoch_year_point_day - data_int_portions[7]) * 1000000); - - int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len, "{\"inclination_deg\":%ld.%ld,\"eccentricity\":%ld.%ld,\"ascending_node_right_ascension_deg\":%ld.%ld,\"perigee_argument_deg\":%ld.%ld,\"b_star_drag_term\":%ld.%ld,\"mean_motion_orbits_per_day\":%ld.%ld,\"mean_anomaly_deg\":%ld.%ld,\"epoch_year_point_day\":%ld.%ld}", - data_int_portions[0], data_decimal_portions[0], data_int_portions[1], data_decimal_portions[1], data_int_portions[2], data_decimal_portions[2], data_int_portions[3], data_decimal_portions[3], data_int_portions[4], data_decimal_portions[4], data_int_portions[5], data_decimal_portions[5], data_int_portions[6], data_decimal_portions[6], data_int_portions[7], data_decimal_portions[7]); + // 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 @@ -803,28 +799,21 @@ uint8_t ADCS_cubecontrol_current_struct_TO_json(const ADCS_cubecontrol_current_s return 1; // Error: invalid input } - // snprintf doesn't support printing floats, so we convert them to a pair of ints + // snprintf doesn't support printing floats, so convert them separately - int16_t data_int_portions[8]; + char three_volt_current_string[20]; + char five_volt_current_string[20]; + char vbat_current_string[20]; - data_int_portions[0] = (int16_t)(data->cubecontrol_3v3_current_mA); - data_int_portions[1] = (int16_t)(data->cubecontrol_5v_current_mA); - data_int_portions[2] = (int16_t)(data->cubecontrol_vbat_current_mA); - - uint8_t data_decimal_portions[8]; - - data_decimal_portions[0] = (uint8_t)((data->cubecontrol_3v3_current_mA - data_int_portions[0]) * 10); - data_decimal_portions[1] = (uint8_t)((data->cubecontrol_5v_current_mA - data_int_portions[1]) * 10); - data_decimal_portions[2] = (uint8_t)((data->cubecontrol_vbat_current_mA - data_int_portions[2]) * 10); + 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\":%d.%d,\"cubecontrol_5v_current_mA\":%d.%d," - "\"cubecontrol_vbat_current_mA\":%d.%d}", - data_int_portions[0], data_decimal_portions[0], - data_int_portions[1], data_decimal_portions[1], - data_int_portions[2], data_decimal_portions[2]); - + "{\"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 } From 4f750eb6d58a72d7d433378e53482800066a8776 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:42:17 -0700 Subject: [PATCH 17/22] Double-to-string unit test --- firmware/Core/Inc/unit_tests/test_adcs.h | 1 + firmware/Core/Src/unit_tests/test_adcs.c | 19 +++++++++++++++++++ .../Core/Src/unit_tests/unit_test_inventory.c | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/firmware/Core/Inc/unit_tests/test_adcs.h b/firmware/Core/Inc/unit_tests/test_adcs.h index 5299ca0dd..453be6125 100644 --- a/firmware/Core/Inc/unit_tests/test_adcs.h +++ b/firmware/Core/Inc/unit_tests/test_adcs.h @@ -48,6 +48,7 @@ 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/unit_tests/test_adcs.c b/firmware/Core/Src/unit_tests/test_adcs.c index a55ca701e..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 @@ -773,3 +774,21 @@ uint8_t TEST_EXEC__ADCS_pack_to_sd_log_config_struct() { 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 25883366f..be4a6c88f 100644 --- a/firmware/Core/Src/unit_tests/unit_test_inventory.c +++ b/firmware/Core/Src/unit_tests/unit_test_inventory.c @@ -312,6 +312,12 @@ const TEST_Definition_t TEST_definitions[] = { .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 ****************** { From 6a3589c3e48ff82a400ad2540b249ed60625cba0 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 23 Nov 2024 11:23:28 -0700 Subject: [PATCH 18/22] minor bugfix --- firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c index cc07342f2..2988a767d 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c @@ -178,14 +178,14 @@ uint8_t ADCS_convert_double_to_string(double input, uint8_t precision, char* out return 1; } - int64_t data_int_portion = (int64_t)(input); - uint64_t data_decimal_portion = (uint64_t)(fabs((input - data_int_portion)) * pow(10, precision)); + 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, "-%lld.%0*lld", data_int_portion, precision, data_decimal_portion); + 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, "%lld.%0*lld", data_int_portion, precision, data_decimal_portion); + snprintf_ret = snprintf(output_string, str_len, "%ld.%0*lu", data_int_portion, precision, data_decimal_portion); } if (snprintf_ret < 0) { From 7f948c6b4bf293d19ce1853b6b5effb3102544c2 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:25:57 -0700 Subject: [PATCH 19/22] minor comment change --- firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c index 2988a767d..283196909 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c @@ -167,7 +167,7 @@ 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. +/// @brief snprintf doesn't support printing doubles, so convert a double into a string with a given decimal precision. /// @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. From e4653272712cf6e0ef3056279132e591c40d79bf Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:01:55 -0700 Subject: [PATCH 20/22] documentation change --- firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c index 283196909..0d1a7eb15 100644 --- a/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c +++ b/firmware/Core/Src/adcs_drivers/adcs_internal_drivers.c @@ -167,7 +167,8 @@ uint8_t ADCS_convert_uint32_to_reversed_uint8_array_members(uint8_t *array, uint return 0; } -/// @brief snprintf doesn't support printing doubles, so convert a double into a string with a given decimal precision. +/// @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. From 68f3d37fe3d3bee26f6d461bb1dd7b0b5aaf034c Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:35:05 -0700 Subject: [PATCH 21/22] timekeeping and float bugfixes --- .../Src/adcs_drivers/adcs_types_to_json.c | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) 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 eec2f3a4e..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 @@ -500,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 @@ -1121,7 +1133,16 @@ uint8_t ADCS_unix_time_ms_TO_json(const uint64_t *data, char json_output_str[], return 1; // Error: invalid input or too short buffer } - int16_t snprintf_ret = snprintf(json_output_str, json_output_str_len,"{\"current_adcs_unix_time\":%llu}",*data); + 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 From 1778f3699e769bd114887d60e32ddfc9a5b2f8d0 Mon Sep 17 00:00:00 2001 From: DeemDeem52 <42725035+DeemDeem52@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:42:23 -0700 Subject: [PATCH 22/22] minor docs changes --- docs/00_Getting_Started.md | 6 ++++-- docs/40_Logging.md | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) 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: