From af13766429be80c5f8870daf720c36df3af854c5 Mon Sep 17 00:00:00 2001 From: Dominik Loidolt <dominik.loidolt@univie.ac.at> Date: Fri, 11 Nov 2022 12:28:41 +0100 Subject: [PATCH] Split cmp_rdcu.c into two files, one for setup a rdcu configuration one to perform a compression add a directory for the compression-decompression test fix some typos --- include/cmp_data_types.h | 2 +- include/cmp_rdcu.h | 15 +- include/cmp_rdcu_cfg.h | 42 ++ lib/cmp_data_types.c | 9 +- lib/cmp_entity.c | 9 +- lib/cmp_icu.c | 10 +- lib/cmp_rdcu.c | 350 +--------------- lib/cmp_rdcu_cfg.c | 374 ++++++++++++++++++ lib/cmp_support.c | 22 +- lib/meson.build | 1 + meson.build | 2 +- test/{cmp_rdcu => cmp_decmp}/meson.build | 6 +- test/{cmp_icu => cmp_decmp}/test_cmp_decmp.c | 0 test/cmp_icu/meson.build | 14 - test/cmp_rdcu_cfg/meson.build | 12 + .../test_cmp_rdcu_cfg.c} | 6 +- test/meson.build | 3 +- 17 files changed, 466 insertions(+), 411 deletions(-) create mode 100644 include/cmp_rdcu_cfg.h create mode 100644 lib/cmp_rdcu_cfg.c rename test/{cmp_rdcu => cmp_decmp}/meson.build (57%) rename test/{cmp_icu => cmp_decmp}/test_cmp_decmp.c (100%) create mode 100644 test/cmp_rdcu_cfg/meson.build rename test/{cmp_rdcu/test_cmp_rdcu.c => cmp_rdcu_cfg/test_cmp_rdcu_cfg.c} (99%) diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h index aff6aa0..68e70d3 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 93da3d0..3a32cbc 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 0000000..ca7b279 --- /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 f2b34ee..4437a39 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 4dce331..1ca2b20 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 c98d0f1..c4bf17a 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 40b52a7..abb97ef 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 0000000..9a0ee8d --- /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 a279a04..0849c0f 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 f072ce4..9a4f44d 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 53603ee..5f28268 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 9c51877..9c72c6b 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 7c9b356..9c06d72 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 0000000..1eab608 --- /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 c4b3b7d..62ae05d 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 ff30bdf..b6139e5 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') -- GitLab