diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h index aff6aa0fae52e61e076aaa5f6fb5c765aa967ec0..68e70d36d0f6bb9e6b3ae4fec8a22b41723e84a9 100644 --- a/include/cmp_data_types.h +++ b/include/cmp_data_types.h @@ -82,7 +82,7 @@ #define MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS 16 /* TBC */ -/* struct holding the maximum length of the different data products types in bits */ +/* struct holding the maximum length of the different data product types in bits */ struct cmp_max_used_bits { uint8_t version; unsigned int s_exp_flags; diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h index 93da3d06a62f51cac7eee52a4c665d4fdc964b0f..3a32cbc9b4163404104f9bcc47bd379ff5552502 100644 --- a/include/cmp_rdcu.h +++ b/include/cmp_rdcu.h @@ -22,6 +22,7 @@ #define _CMP_RDCU_H_ #include <cmp_support.h> +#include <cmp_rdcu_cfg.h> /* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */ @@ -35,18 +36,6 @@ #define SLAVE_BUSY_ERR_BIT 0x07 /* The bus master has received the "slave busy" status (only HW compression) */ -struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode, - uint32_t model_value, uint32_t lossy_par); -int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress, - uint32_t data_samples, uint16_t *model_of_data, - uint32_t rdcu_data_adr, uint32_t rdcu_model_adr, - uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr, - uint32_t rdcu_buffer_lenght); -int rdcu_cfg_imagette(struct cmp_cfg *cfg, - uint32_t golomb_par, uint32_t spillover_par, - uint32_t ap1_golomb_par, uint32_t ap1_spillover_par, - uint32_t ap2_golomb_par, uint32_t ap2_spillover_par); - int rdcu_compress_data(const struct cmp_cfg *cfg); int rdcu_read_cmp_status(struct cmp_status *status); @@ -62,6 +51,4 @@ int rdcu_interrupt_compression(void); void rdcu_enable_interrput_signal(void); void rdcu_disable_interrput_signal(void); -int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg); - #endif /* _CMP_RDCU_H_ */ diff --git a/include/cmp_rdcu_cfg.h b/include/cmp_rdcu_cfg.h new file mode 100644 index 0000000000000000000000000000000000000000..ca7b27917b0fd897645bb9e68696f102522af496 --- /dev/null +++ b/include/cmp_rdcu_cfg.h @@ -0,0 +1,42 @@ +/** + * @file cmp_rdcu_rdcu.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at), + * @date 2020 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief hardware compressor configuration library + */ + + +#ifndef _CMP_RDCU_CFG_H_ +#define _CMP_RDCU_CFG_H_ + +#include <cmp_support.h> + + +struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode, + uint32_t model_value, uint32_t lossy_par); + +int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress, + uint32_t data_samples, uint16_t *model_of_data, + uint32_t rdcu_data_adr, uint32_t rdcu_model_adr, + uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr, + uint32_t rdcu_buffer_lenght); + +int rdcu_cfg_imagette(struct cmp_cfg *cfg, + uint32_t golomb_par, uint32_t spillover_par, + uint32_t ap1_golomb_par, uint32_t ap1_spillover_par, + uint32_t ap2_golomb_par, uint32_t ap2_spillover_par); + +int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg); + +#endif /* _CMP_RDCU_CFG_H_ */ diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c index f2b34ee5872f560a701f4c2e74714de645522925..4437a39bab13d57fe910afaefbd093d5cb87338b 100644 --- a/lib/cmp_data_types.c +++ b/lib/cmp_data_types.c @@ -18,7 +18,6 @@ #include <stdint.h> -#include <stdio.h> #include <limits.h> @@ -67,10 +66,10 @@ struct cmp_max_used_bits max_used_bits = { /** - * @brief sets the maximum length of the different data products types + * @brief sets the maximum length of the different data product types * * @param set_max_used_bits pointer to a structure with the maximum length - * of the different data products types in bits + * of the different data product types in bits */ void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits) @@ -81,10 +80,10 @@ void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits) /** - * @brief get the maximum length of the different data products types + * @brief get the maximum length of the different data product types * * @returns a structure with the used maximum length of the different data - * products types in bits + * product types in bits */ struct cmp_max_used_bits cmp_get_max_used_bits(void) diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c index 4dce331fdcde91ef58f8e81e132587b49a52b696..1ca2b20873f5ab0815ccb569a82e043c58d82ea7 100644 --- a/lib/cmp_entity.c +++ b/lib/cmp_entity.c @@ -1928,8 +1928,7 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg, break; case DATA_TYPE_F_CAM_OFFSET: case DATA_TYPE_F_CAM_BACKGROUND: - /* TODO: fix this*/ - /* fall through */ + /* TODO: implement this*/ case DATA_TYPE_UNKNOWN: default: return -1; @@ -1977,7 +1976,7 @@ int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *i } if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(info->cmp_mode_used)) { - debug_print("Error: The raw bit is set in data product type filed, but no raw compression mode is used.\n"); + debug_print("Error: The entity's raw data bit does not match up with the compression mode.\n"); return -1; } @@ -2292,8 +2291,8 @@ static time_t my_timegm(struct tm *tm) /* * @brief Generate a timestamp for the compression header * - * @param ts pointer to an object of type struct timespec of the timestamp - * time, null for now + * @param ts pointer to an object of type struct timespec of the + * timestamp time, NULL for now * * @returns returns compression header timestamp or 0 on error */ diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c index c98d0f1ffb94114f2218db41251bfd040bb65c37..c4bf17a8ee8188fc4b885e584a669314655e6bbd 100644 --- a/lib/cmp_icu.c +++ b/lib/cmp_icu.c @@ -51,7 +51,7 @@ typedef uint32_t (*generate_cw_f_pt)(uint32_t value, uint32_t encoder_par1, /* structure to hold a setup to encode a value */ struct encoder_setupt { - generate_cw_f_pt generate_cw_f; /* pointer to the code word encoder */ + generate_cw_f_pt generate_cw_f; /* function pointer to a code word encoder */ int (*encode_method_f)(uint32_t data, uint32_t model, int stream_len, const struct encoder_setupt *setup); /* pointer to the encoding function */ uint32_t *bitstream_adr; /* start address of the compressed data bitstream */ @@ -122,7 +122,7 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, void *updated_model, uint32_t *compressed_data, uint32_t compressed_data_len_samples) { - uint32_t data_size, hdr_size; + uint32_t cmp_data_size, hdr_size; if (!cfg) { debug_print("Error: pointer to the compression configuration structure is NULL.\n"); @@ -139,15 +139,15 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, if (cmp_cfg_icu_buffers_is_invalid(cfg)) return 0; - data_size = cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type); + cmp_data_size = cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type); hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW); - if ((data_size + hdr_size) > CMP_ENTITY_MAX_SIZE || data_size > CMP_ENTITY_MAX_SIZE) { + if ((cmp_data_size + hdr_size) > CMP_ENTITY_MAX_SIZE || cmp_data_size > CMP_ENTITY_MAX_SIZE) { debug_print("Error: The buffer for the compressed data is too large to fit in a compression entity.\n"); return 0; } - return data_size; + return cmp_data_size; } diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c index 40b52a73ba8c231dd61998518e911c84403f2401..abb97efe073ed06b3ccc3e9812610d8a8e06b33d 100644 --- a/lib/cmp_rdcu.c +++ b/lib/cmp_rdcu.c @@ -26,17 +26,15 @@ * rdcu_compress_data() function. */ + #include <stdint.h> #include <stdio.h> -#include <string.h> -#include <rdcu_cmd.h> #include <cmp_debug.h> #include <cmp_support.h> -#include <cmp_data_types.h> +#include <cmp_rdcu_cfg.h> #include <rdcu_ctrl.h> #include <rdcu_rmap.h> -#include <my_inttypes.h> #define IMA_SAM2BYT \ @@ -81,350 +79,6 @@ static void sync(void) } -/** - * @brief create an RDCU compression configuration - * - * @param data_type compression data product type - * @param cmp_mode compression mode - * @param model_value model weighting parameter (only needed for model compression mode) - * @param lossy_par lossy rounding parameter (use CMP_LOSSLESS for lossless compression) - * - * @returns a compression configuration containing the chosen parameters; - * on error the data_type record is set to DATA_TYPE_UNKNOWN - */ - -struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode, - uint32_t model_value, uint32_t lossy_par) -{ - struct cmp_cfg cfg; - - memset(&cfg, 0, sizeof(cfg)); - - cfg.data_type = data_type; - cfg.cmp_mode = cmp_mode; - cfg.model_value = model_value; - cfg.round = lossy_par; - - if (cmp_cfg_gen_par_is_invalid(&cfg, RDCU_CHECK)) - cfg.data_type = DATA_TYPE_UNKNOWN; - - return cfg; -} - - -/** - * @brief check if a buffer is in outside the RDCU SRAM - * - * @param addr start address of the buffer - * @param size length of the buffer in bytes - * - * @returns 0 if buffer in inside the RDCU SRAM, 1 when the buffer is outside - */ - -static int outside_sram_range(uint32_t addr, uint32_t size) -{ - if (addr + size > RDCU_SRAM_END) - return 1; - - if (addr > RDCU_SRAM_END) - return 1; - - if (size > RDCU_SRAM_SIZE) - return 1; - - return 0; -} - - -/** - * @brief check if two buffers are overlapping - * @note implement according to https://stackoverflow.com/a/325964 - * - * @param start_a start address of the 1st buffer - * @param end_a end address of the 1st buffer - * @param start_b start address of the 2nd buffer - * @param end_b end address of the 2nd buffer - * - * @returns 0 if buffers are not overlapping, otherwise buffer are - * overlapping - */ - -static int buffers_overlap(uint32_t start_a, uint32_t end_a, uint32_t start_b, - uint32_t end_b) -{ - if (start_a < end_b && end_a > start_b) - return 1; - else - return 0; -} - - -/** - * @brief check if RDCU buffer settings are invalid - * - * @param cfg a pointer to a compression configuration - * - * @returns 0 if buffers configuration is valid, otherwise the configuration is - * invalid - */ - -static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) -{ - int cfg_invalid = 0; - - if (cfg->cmp_mode == CMP_MODE_RAW) { - if (cfg->buffer_length < cfg->samples) { - debug_print("rdcu_buffer_length is smaller than the samples parameter. There is not enough space to copy the data in RAW mode.\n"); - cfg_invalid++; - } - } - - if (cfg->rdcu_data_adr & 0x3) { - debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned.\n"); - cfg_invalid++; - } - - if (cfg->rdcu_buffer_adr & 0x3) { - debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned.\n"); - cfg_invalid++; - } - - if (outside_sram_range(cfg->rdcu_data_adr, cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.\n"); - cfg_invalid++; - } - - if (outside_sram_range(cfg->rdcu_buffer_adr, cfg->buffer_length * IMA_SAM2BYT)) { - debug_print("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.\n"); - cfg_invalid++; - } - - if (buffers_overlap(cfg->rdcu_data_adr, - cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT, - cfg->rdcu_buffer_adr, - cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT)) { - debug_print("Error: The RDCU data to compress buffer and the RDCU compressed data buffer are overlapping.\n"); - cfg_invalid++; - } - - if (model_mode_is_used(cfg->cmp_mode)) { - if (cfg->model_buf && cfg->model_buf == cfg->input_buf) { - debug_print("Error: The model buffer (model_buf) and the data to be compressed (input_buf) are equal.\n"); - cfg_invalid++; - } - - if (cfg->rdcu_model_adr & 0x3) { - debug_print("Error: The RDCU model start address is not 4-Byte aligned.\n"); - cfg_invalid++; - } - - if (outside_sram_range(cfg->rdcu_model_adr, cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The RDCU model buffer is outside the RDCU SRAM address space.\n"); - cfg_invalid++; - } - - if (buffers_overlap( - cfg->rdcu_model_adr, - cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT, - cfg->rdcu_data_adr, - cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The model buffer and the data to compress buffer are overlapping.\n"); - cfg_invalid++; - } - - if (buffers_overlap( - cfg->rdcu_model_adr, - cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT, - cfg->rdcu_buffer_adr, - cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT) - ) { - debug_print("Error: The model buffer and the compressed data buffer are overlapping.\n"); - cfg_invalid++; - } - - if (cfg->rdcu_model_adr != cfg->rdcu_new_model_adr) { - if (cfg->rdcu_new_model_adr & 0x3) { - debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned.\n"); - cfg_invalid++; - } - - if (outside_sram_range(cfg->rdcu_new_model_adr, - cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The RDCU updated model buffer is outside the RDCU SRAM address space.\n"); - cfg_invalid++; - } - - if (buffers_overlap( - cfg->rdcu_new_model_adr, - cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT, - cfg->rdcu_data_adr, - cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT) - ) { - debug_print("Error: The updated model buffer and the data to compress buffer are overlapping.\n"); - cfg_invalid++; - } - - if (buffers_overlap( - cfg->rdcu_new_model_adr, - cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT, - cfg->rdcu_buffer_adr, - cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT) - ) { - debug_print("Error: The updated model buffer and the compressed data buffer are overlapping.\n"); - cfg_invalid++; - } - if (buffers_overlap( - cfg->rdcu_new_model_adr, - cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT, - cfg->rdcu_model_adr, - cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT) - ) { - debug_print("Error: The updated model buffer and the model buffer are overlapping.\n"); - cfg_invalid++; - } - } - } - -#ifdef SKIP_CMP_PAR_CHECK - return 0; -#endif - return cfg_invalid; -} - - -/** - * @brief setup of the different data buffers for an RDCU compression - * - * @param cfg pointer to a compression configuration (created - * with the rdcu_cfg_create() function) - * @param data_to_compress pointer to the data to be compressed (if NULL no - * data transfer to the RDCU) - * @param data_samples length of the data to be compressed measured in - * 16-bit data samples (ignoring the collection header) - * @param model_of_data pointer to model data buffer (only needed for - * model compression mode, if NULL no model data - * transfer to the RDCU) - * @param rdcu_data_adr RDCU SRAM data to compress start address - * @param rdcu_model_adr RDCU SRAM model start address (only need for - * model compression mode) - * @param rdcu_new_model_adr RDCU SRAM new/updated model start address(can be the - * by the same as rdcu_model_adr for in-place model update) - * @param rdcu_buffer_adr RDCU SRAM compressed data start address - * @param rdcu_buffer_lenght length of the RDCU compressed data SRAM buffer - * measured in 16-bit units (same as data_samples) - * - * @returns 0 if parameters are valid, non-zero if parameters are invalid - */ - -int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress, - uint32_t data_samples, uint16_t *model_of_data, - uint32_t rdcu_data_adr, uint32_t rdcu_model_adr, - uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr, - uint32_t rdcu_buffer_lenght) -{ - if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); - return -1; - } - - cfg->input_buf = data_to_compress; - cfg->samples = data_samples; - cfg->model_buf = model_of_data; - cfg->rdcu_data_adr = rdcu_data_adr; - cfg->rdcu_model_adr = rdcu_model_adr; - cfg->rdcu_new_model_adr = rdcu_new_model_adr; - cfg->rdcu_buffer_adr = rdcu_buffer_adr; - cfg->buffer_length = rdcu_buffer_lenght; - - return rdcu_cfg_buffers_is_invalid(cfg); -} - - -/** - * @brief set up the configuration parameters for an RDCU imagette compression - * - * @param cfg pointer to a compression configuration (created - * with the rdcu_cfg_create() function) - * @param golomb_par imagette compression parameter - * @param spillover_par imagette spillover threshold parameter - * @param ap1_golomb_par adaptive 1 imagette compression parameter - * @param ap1_spillover_par adaptive 1 imagette spillover threshold parameter - * @param ap2_golomb_par adaptive 2 imagette compression parameter - * @param ap2_spillover_par adaptive 2 imagette spillover threshold parameter - * - * @returns 0 if parameters are valid, non-zero if parameters are invalid - */ - -int rdcu_cfg_imagette(struct cmp_cfg *cfg, - uint32_t golomb_par, uint32_t spillover_par, - uint32_t ap1_golomb_par, uint32_t ap1_spillover_par, - uint32_t ap2_golomb_par, uint32_t ap2_spillover_par) -{ - if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); - return -1; - } - - cfg->golomb_par = golomb_par; - cfg->spill = spillover_par; - cfg->ap1_golomb_par = ap1_golomb_par; - cfg->ap1_spill = ap1_spillover_par; - cfg->ap2_golomb_par = ap2_golomb_par; - cfg->ap2_spill = ap2_spillover_par; - - return cmp_cfg_imagette_is_invalid(cfg, RDCU_CHECK); -} - - -/** - * @brief check if the compressor configuration is invalid for an RDCU compression, - * see the user manual for more information (PLATO-UVIE-PL-UM-0001). - * - * @param cfg pointer to a compression configuration contains all parameters - * required for compression - * - * @returns 0 if parameters are valid, non-zero if parameters are invalid - */ - -int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg) -{ - int cfg_invalid = 0; - - if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); - return -1; - } - - if (!cfg->input_buf) - debug_print("Warning: The data to compress buffer is set to NULL. No data will be transferred to the rdcu_data_adr in the RDCU SRAM.\n"); - - if (model_mode_is_used(cfg->cmp_mode)) { - if (!cfg->model_buf) - debug_print("Warning: The model buffer is set to NULL. No model data will be transferred to the rdcu_model_adr in the RDCU SRAM.\n"); - } - - if (cfg->samples == 0) - debug_print("Warning: The samples parameter is set to 0. No data will be compressed.\n"); - - if (cfg->icu_new_model_buf) - debug_print("Warning: ICU updated model buffer is set. This buffer is not used for an RDCU compression.\n"); - - if (cfg->icu_output_buf) - debug_print("Warning: ICU compressed data buffer is set. This buffer is not used for an RDCU compression.\n"); - - if (cfg->buffer_length == 0) { - debug_print("Error: The buffer_length is set to 0. There is no place to store the compressed data.\n"); - cfg_invalid++; - } - - cfg_invalid += cmp_cfg_gen_par_is_invalid(cfg, RDCU_CHECK); - cfg_invalid += rdcu_cfg_buffers_is_invalid(cfg); - cfg_invalid += cmp_cfg_imagette_is_invalid(cfg, RDCU_CHECK); - - return cfg_invalid; -} - - /** * @brief set up RDCU compression register * diff --git a/lib/cmp_rdcu_cfg.c b/lib/cmp_rdcu_cfg.c new file mode 100644 index 0000000000000000000000000000000000000000..9a0ee8ddac60cf5e0670de018c126810b4fd3484 --- /dev/null +++ b/lib/cmp_rdcu_cfg.c @@ -0,0 +1,374 @@ +/** + * @file cmp_rdcu_cfg.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at), + * @date 2020 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief hardware compressor configuration library + * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 + */ + + +#include <stdint.h> +#include <string.h> + +#include <cmp_debug.h> +#include <cmp_support.h> +#include <rdcu_cmd.h> + + +#define IMA_SAM2BYT \ +2 /* imagette sample to byte conversion factor; one imagette samples has 16 bits (2 bytes) */ + + +/** + * @brief create an RDCU compression configuration + * + * @param data_type compression data product type + * @param cmp_mode compression mode + * @param model_value model weighting parameter (only needed for model compression mode) + * @param lossy_par lossy rounding parameter (use CMP_LOSSLESS for lossless compression) + * + * @returns a compression configuration containing the chosen parameters; + * on error the data_type record is set to DATA_TYPE_UNKNOWN + */ + +struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode, + uint32_t model_value, uint32_t lossy_par) +{ + struct cmp_cfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.data_type = data_type; + cfg.cmp_mode = cmp_mode; + cfg.model_value = model_value; + cfg.round = lossy_par; + + if (cmp_cfg_gen_par_is_invalid(&cfg, RDCU_CHECK)) + cfg.data_type = DATA_TYPE_UNKNOWN; + + return cfg; +} + + +/** + * @brief check if a buffer is in outside the RDCU SRAM + * + * @param addr start address of the buffer + * @param size length of the buffer in bytes + * + * @returns 0 if buffer in inside the RDCU SRAM, 1 when the buffer is outside + */ + +static int outside_sram_range(uint32_t addr, uint32_t size) +{ + if (addr + size > RDCU_SRAM_END) + return 1; + + if (addr > RDCU_SRAM_END) + return 1; + + if (size > RDCU_SRAM_SIZE) + return 1; + + return 0; +} + + +/** + * @brief check if two buffers are overlapping + * @note implement according to https://stackoverflow.com/a/325964 + * + * @param start_a start address of the 1st buffer + * @param end_a end address of the 1st buffer + * @param start_b start address of the 2nd buffer + * @param end_b end address of the 2nd buffer + * + * @returns 0 if buffers are not overlapping, otherwise buffer are + * overlapping + */ + +static int buffers_overlap(uint32_t start_a, uint32_t end_a, uint32_t start_b, + uint32_t end_b) +{ + if (start_a < end_b && end_a > start_b) + return 1; + else + return 0; +} + + +/** + * @brief check if RDCU buffer settings are invalid + * + * @param cfg a pointer to a compression configuration + * + * @returns 0 if buffers configuration is valid, otherwise the configuration is + * invalid + */ + +static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) +{ + int cfg_invalid = 0; + + if (cfg->cmp_mode == CMP_MODE_RAW) { + if (cfg->buffer_length < cfg->samples) { + debug_print("rdcu_buffer_length is smaller than the samples parameter. There is not enough space to copy the data in RAW mode.\n"); + cfg_invalid++; + } + } + + if (cfg->rdcu_data_adr & 0x3) { + debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned.\n"); + cfg_invalid++; + } + + if (cfg->rdcu_buffer_adr & 0x3) { + debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned.\n"); + cfg_invalid++; + } + + if (outside_sram_range(cfg->rdcu_data_adr, cfg->samples * IMA_SAM2BYT)) { + debug_print("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.\n"); + cfg_invalid++; + } + + if (outside_sram_range(cfg->rdcu_buffer_adr, cfg->buffer_length * IMA_SAM2BYT)) { + debug_print("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.\n"); + cfg_invalid++; + } + + if (buffers_overlap(cfg->rdcu_data_adr, + cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT, + cfg->rdcu_buffer_adr, + cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT)) { + debug_print("Error: The RDCU data to compress buffer and the RDCU compressed data buffer are overlapping.\n"); + cfg_invalid++; + } + + if (model_mode_is_used(cfg->cmp_mode)) { + if (cfg->model_buf && cfg->model_buf == cfg->input_buf) { + debug_print("Error: The model buffer (model_buf) and the data to be compressed (input_buf) are equal.\n"); + cfg_invalid++; + } + + if (cfg->rdcu_model_adr & 0x3) { + debug_print("Error: The RDCU model start address is not 4-Byte aligned.\n"); + cfg_invalid++; + } + + if (outside_sram_range(cfg->rdcu_model_adr, cfg->samples * IMA_SAM2BYT)) { + debug_print("Error: The RDCU model buffer is outside the RDCU SRAM address space.\n"); + cfg_invalid++; + } + + if (buffers_overlap( + cfg->rdcu_model_adr, + cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT, + cfg->rdcu_data_adr, + cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT)) { + debug_print("Error: The model buffer and the data to compress buffer are overlapping.\n"); + cfg_invalid++; + } + + if (buffers_overlap( + cfg->rdcu_model_adr, + cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT, + cfg->rdcu_buffer_adr, + cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT) + ) { + debug_print("Error: The model buffer and the compressed data buffer are overlapping.\n"); + cfg_invalid++; + } + + if (cfg->rdcu_model_adr != cfg->rdcu_new_model_adr) { + if (cfg->rdcu_new_model_adr & 0x3) { + debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned.\n"); + cfg_invalid++; + } + + if (outside_sram_range(cfg->rdcu_new_model_adr, + cfg->samples * IMA_SAM2BYT)) { + debug_print("Error: The RDCU updated model buffer is outside the RDCU SRAM address space.\n"); + cfg_invalid++; + } + + if (buffers_overlap( + cfg->rdcu_new_model_adr, + cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT, + cfg->rdcu_data_adr, + cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT) + ) { + debug_print("Error: The updated model buffer and the data to compress buffer are overlapping.\n"); + cfg_invalid++; + } + + if (buffers_overlap( + cfg->rdcu_new_model_adr, + cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT, + cfg->rdcu_buffer_adr, + cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT) + ) { + debug_print("Error: The updated model buffer and the compressed data buffer are overlapping.\n"); + cfg_invalid++; + } + if (buffers_overlap( + cfg->rdcu_new_model_adr, + cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT, + cfg->rdcu_model_adr, + cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT) + ) { + debug_print("Error: The updated model buffer and the model buffer are overlapping.\n"); + cfg_invalid++; + } + } + } + +#ifdef SKIP_CMP_PAR_CHECK + return 0; +#endif + return cfg_invalid; +} + + +/** + * @brief setup of the different data buffers for an RDCU compression + * + * @param cfg pointer to a compression configuration (created + * with the rdcu_cfg_create() function) + * @param data_to_compress pointer to the data to be compressed (if NULL no + * data transfer to the RDCU) + * @param data_samples length of the data to be compressed (plus the + * collection header) measured in 16-bit data samples + * @param model_of_data pointer to the model data buffer (only needed for + * model compression mode, if NULL no model data is + * transferred to the RDCU) + * @param rdcu_data_adr RDCU SRAM data to compress start address + * @param rdcu_model_adr RDCU SRAM model start address (only needed for + * model compression mode) + * @param rdcu_new_model_adr RDCU SRAM new/updated model start address (can be + * the same as rdcu_model_adr for in-place model update) + * @param rdcu_buffer_adr RDCU SRAM compressed data start address + * @param rdcu_buffer_lenght length of the RDCU compressed data SRAM buffer + * measured in 16-bit units (same as data_samples) + * + * @returns 0 if parameters are valid, non-zero if parameters are invalid + */ + +int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress, + uint32_t data_samples, uint16_t *model_of_data, + uint32_t rdcu_data_adr, uint32_t rdcu_model_adr, + uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr, + uint32_t rdcu_buffer_lenght) +{ + if (!cfg) { + debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + return -1; + } + + cfg->input_buf = data_to_compress; + cfg->samples = data_samples; + cfg->model_buf = model_of_data; + cfg->rdcu_data_adr = rdcu_data_adr; + cfg->rdcu_model_adr = rdcu_model_adr; + cfg->rdcu_new_model_adr = rdcu_new_model_adr; + cfg->rdcu_buffer_adr = rdcu_buffer_adr; + cfg->buffer_length = rdcu_buffer_lenght; + + return rdcu_cfg_buffers_is_invalid(cfg); +} + + +/** + * @brief set up the configuration parameters for an RDCU imagette compression + * + * @param cfg pointer to a compression configuration (created + * with the rdcu_cfg_create() function) + * @param golomb_par imagette compression parameter + * @param spillover_par imagette spillover threshold parameter + * @param ap1_golomb_par adaptive 1 imagette compression parameter + * @param ap1_spillover_par adaptive 1 imagette spillover threshold parameter + * @param ap2_golomb_par adaptive 2 imagette compression parameter + * @param ap2_spillover_par adaptive 2 imagette spillover threshold parameter + * + * @returns 0 if parameters are valid, non-zero if parameters are invalid + */ + +int rdcu_cfg_imagette(struct cmp_cfg *cfg, + uint32_t golomb_par, uint32_t spillover_par, + uint32_t ap1_golomb_par, uint32_t ap1_spillover_par, + uint32_t ap2_golomb_par, uint32_t ap2_spillover_par) +{ + if (!cfg) { + debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + return -1; + } + + cfg->golomb_par = golomb_par; + cfg->spill = spillover_par; + cfg->ap1_golomb_par = ap1_golomb_par; + cfg->ap1_spill = ap1_spillover_par; + cfg->ap2_golomb_par = ap2_golomb_par; + cfg->ap2_spill = ap2_spillover_par; + + return cmp_cfg_imagette_is_invalid(cfg, RDCU_CHECK); +} + + +/** + * @brief check if the compressor configuration is invalid for an RDCU compression, + * see the user manual for more information (PLATO-UVIE-PL-UM-0001). + * + * @param cfg pointer to a compression configuration contains all parameters + * required for compression + * + * @returns 0 if parameters are valid, non-zero if parameters are invalid + */ + +int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg) +{ + int cfg_invalid = 0; + + if (!cfg) { + debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + return -1; + } + + if (!cfg->input_buf) + debug_print("Warning: The data to compress buffer is set to NULL. No data will be transferred to the rdcu_data_adr in the RDCU SRAM.\n"); + + if (model_mode_is_used(cfg->cmp_mode)) { + if (!cfg->model_buf) + debug_print("Warning: The model buffer is set to NULL. No model data will be transferred to the rdcu_model_adr in the RDCU SRAM.\n"); + } + + if (cfg->samples == 0) + debug_print("Warning: The samples parameter is set to 0. No data will be compressed.\n"); + + if (cfg->icu_new_model_buf) + debug_print("Warning: ICU updated model buffer is set. This buffer is not used for an RDCU compression.\n"); + + if (cfg->icu_output_buf) + debug_print("Warning: ICU compressed data buffer is set. This buffer is not used for an RDCU compression.\n"); + + if (cfg->buffer_length == 0) { + debug_print("Error: The buffer_length is set to 0. There is no place to store the compressed data.\n"); + cfg_invalid++; + } + + cfg_invalid += cmp_cfg_gen_par_is_invalid(cfg, RDCU_CHECK); + cfg_invalid += rdcu_cfg_buffers_is_invalid(cfg); + cfg_invalid += cmp_cfg_imagette_is_invalid(cfg, RDCU_CHECK); + + return cfg_invalid; +} diff --git a/lib/cmp_support.c b/lib/cmp_support.c index a279a048268418996da74fd3e945669bc9d9d6e3..0849c0fc693199867fd771c387e2a1bc1db077db 100644 --- a/lib/cmp_support.c +++ b/lib/cmp_support.c @@ -372,7 +372,7 @@ unsigned int cmp_up_model(unsigned int data, unsigned int model, /** - * @brief get the maximum valid spill threshold value for a RDCU HW imagette + * @brief get the maximum valid spill threshold value for a imagette * compression in diff or model mode * * @param golomb_par Golomb parameter @@ -400,7 +400,7 @@ uint32_t cmp_ima_max_spill(unsigned int golomb_par) /** - * @brief get the maximum valid spill threshold value for a ICU SW compression + * @brief get the maximum valid spill threshold value for a non-imagette compression * in diff or model mode * * @param cmp_par compression parameter @@ -457,10 +457,10 @@ unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit) int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) { int cfg_invalid = 0; - int invalid_data_type; - int unsupported_cmp_mode; - int check_model_value; - uint32_t max_round_value; + int invalid_data_type = 1; + int unsupported_cmp_mode = 1; + int check_model_value = 1; + uint32_t max_round_value = 0; char *str = ""; if (!cfg) @@ -517,7 +517,7 @@ int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) /** - * @brief check if the buffer parameters are invalid + * @brief check if the ICU buffer parameters are invalid * * @param cfg pointer to the compressor configuration * @@ -671,7 +671,7 @@ static int cmp_pars_are_invalid(uint32_t cmp_par, uint32_t spill, enum cmp_mode /** * @brief check if the imagette specific compression parameters are invalid * - * @param cfg pointer to the compressor configuration + * @param cfg pointer to a compressor configuration * @param opt check options: * RDCU_CHECK for a imagette RDCU compression check * ICU_CHECK for a imagette ICU compression check @@ -823,7 +823,7 @@ int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg) cmp_cfg_fx_cob_get_need_pars(cfg->data_type, &needed_pars); - if (needed_pars.fx) /* this is always true because every flux/center of brightness data type contains a flux parameter */ + if (needed_pars.fx) /* this is always true because every flux/center of brightness data type contains a flux parameter */ cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_fx, cfg->spill_fx, cfg->cmp_mode, cfg->data_type, "flux"); if (needed_pars.exp_flags) @@ -883,9 +883,9 @@ int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg) /** - * @brief check if a compression configuration is invalid for ICU compression + * @brief check if a compression configuration is invalid for a ICU compression * - * @param cfg pointer to the compressor configuration + * @param cfg pointer to a compressor configuration * * @returns 0 if the compression configuration is valid, otherwise invalid */ diff --git a/lib/meson.build b/lib/meson.build index f072ce4371b24f303ac3f51a607735870fd216f2..9a4f44df75ab19c0a0901977e7e572c00ec38e23 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -9,6 +9,7 @@ cmplib_sources = files([ 'decmp.c', 'rdcu_pkt_to_file.c', 'cmp_guess.c', + 'cmp_rdcu_cfg.c', 'cmp_rdcu.c', 'rdcu_cmd.c', 'rdcu_rmap.c' diff --git a/meson.build b/meson.build index 53603eebf0b0e1af1fb963b45023abc37659c990..5f282685062ecf880cd5317d705516848d10c2c9 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('cmp_tool', 'c', - version : '0.09', + version : '0.10', meson_version : '>= 0.56', license : 'GPL-2.0', default_options : ['warning_level=3', 'c_std=gnu99'] diff --git a/test/cmp_rdcu/meson.build b/test/cmp_decmp/meson.build similarity index 57% rename from test/cmp_rdcu/meson.build rename to test/cmp_decmp/meson.build index 9c51877aabb3fdeca82b456ec8626ad0bf1c9aeb..9c72c6b3a1e093d7041f8088843fa79385938034 100644 --- a/test/cmp_rdcu/meson.build +++ b/test/cmp_decmp/meson.build @@ -1,7 +1,7 @@ -test_case = files('test_cmp_rdcu.c') +test_case = files('test_cmp_decmp.c') test_runner = test_runner_generator.process(test_case) -test_cmp_rdcu = executable('test_cmp_rdcu', +test_cmp_decmp = executable('test_cmp_decmp', test_case, test_runner, include_directories : incdir, link_with : cmp_lib, @@ -9,4 +9,4 @@ test_cmp_rdcu = executable('test_cmp_rdcu', build_by_default : false ) -test('Hardware Compressor Control Library Tests', test_cmp_rdcu) +test('Compression Decompression Unit Tests', test_cmp_decmp) diff --git a/test/cmp_icu/test_cmp_decmp.c b/test/cmp_decmp/test_cmp_decmp.c similarity index 100% rename from test/cmp_icu/test_cmp_decmp.c rename to test/cmp_decmp/test_cmp_decmp.c diff --git a/test/cmp_icu/meson.build b/test/cmp_icu/meson.build index 7c9b356ed371262c44ba3ef897861ee4c7d25cd2..9c06d726172c0e6e65e9b0b52cc70608a11a86cc 100644 --- a/test/cmp_icu/meson.build +++ b/test/cmp_icu/meson.build @@ -12,20 +12,6 @@ test_cmp_icu = executable('test_cmp_icu', test('cmp_icu Unit Tests', test_cmp_icu) -test_case = files('test_cmp_decmp.c') -test_runner = test_runner_generator.process(test_case) - -test_cmp_decmp = executable('test_cmp_decmp', - test_case, test_runner, - include_directories : incdir, - link_with : cmp_lib, - dependencies : unity_dep, - build_by_default : false -) - -test('Compression Decompression Unit Tests', test_cmp_decmp) - - test_case = files('test_decmp.c') test_runner = test_runner_generator.process(test_case) diff --git a/test/cmp_rdcu_cfg/meson.build b/test/cmp_rdcu_cfg/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1eab608f2707f6906ce4c946f9342dc4fb8d5b14 --- /dev/null +++ b/test/cmp_rdcu_cfg/meson.build @@ -0,0 +1,12 @@ +test_case = files('test_cmp_rdcu_cfg.c') +test_runner = test_runner_generator.process(test_case) + +test_cmp_rdcu_cfg = executable('test_cmp_rdcu_cfg', + test_case, test_runner, + include_directories : incdir, + link_with : cmp_lib, + dependencies : unity_dep, + build_by_default : false +) + +test('Hardware Compressor Configuration Library Tests', test_cmp_rdcu_cfg) diff --git a/test/cmp_rdcu/test_cmp_rdcu.c b/test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c similarity index 99% rename from test/cmp_rdcu/test_cmp_rdcu.c rename to test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c index c4b3b7dde1515580992b8b3d5f007646f70f51d7..62ae05d9056237a50183367c4cbe85100c448830 100644 --- a/test/cmp_rdcu/test_cmp_rdcu.c +++ b/test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c @@ -1,5 +1,5 @@ /** - * @file test_cmp_rdcu.c + * @file test_cmp_rdcu_cfg.c * @author Dominik Loidolt (dominik.loidolt@univie.ac.at), * @date 2022 * @@ -13,13 +13,13 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * @brief hardware compressor control library tests + * @brief hardware compressor configuration tests */ #include <stdint.h> #include <unity.h> -#include <cmp_rdcu.h> +#include <cmp_rdcu_cfg.h> #include <rdcu_cmd.h> diff --git a/test/meson.build b/test/meson.build index ff30bdfab4896c831abe21b220acb66b32308409..b6139e5bb3e34a72038783bab4a6c1073cbee79c 100644 --- a/test/meson.build +++ b/test/meson.build @@ -37,6 +37,7 @@ subdir('cmp_tool') unity_dep = dependency('unity', fallback : ['unity', 'unity_dep']) subdir('cmp_icu') +subdir('cmp_decmp') subdir('cmp_data_types') subdir('cmp_entity') -subdir('cmp_rdcu') +subdir('cmp_rdcu_cfg')