From 721a8263099862b2927c9c0c12bc31dd46a0ed01 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 31 May 2022 15:19:12 +0200
Subject: [PATCH] add compression of non-imagette data

---
 cmp_tool.c                                 |  411 +--
 include/cmp_data_types.h                   |  350 ++-
 include/cmp_entity.h                       |   65 +-
 include/cmp_guess.h                        |   10 +-
 include/cmp_icu.h                          |   43 +-
 include/cmp_io.h                           |   10 +-
 include/cmp_rdcu.h                         |   28 +-
 include/cmp_support.h                      |  248 +-
 include/decmp.h                            |    8 +-
 lib/cmp_data_types.c                       |  936 ++----
 lib/cmp_entity.c                           |  679 +++--
 lib/cmp_guess.c                            |  127 +-
 lib/cmp_icu.c                              | 3207 ++++++++++++--------
 lib/cmp_icu_new.c                          |  422 ---
 lib/cmp_io.c                               |  295 +-
 lib/cmp_rdcu.c                             |  586 ++--
 lib/cmp_support.c                          |  919 +++---
 lib/decmp.c                                | 1599 ++--------
 lib/meson.build                            |    4 +-
 lib/rdcu_pkt_to_file.c                     |   14 +-
 meson.build                                |    2 +
 test/cmp_icu/meson.build                   |   26 +-
 test/cmp_icu/test_cmp_icu.c                | 1454 ++++++++-
 test/cmp_icu/test_cmp_icu_new.c            |  894 ------
 test/cmp_icu/test_decmp.c                  |  442 +++
 test/cmp_tool/cmp_tool_integration_test.py |  188 +-
 test/meson.build                           |    4 -
 27 files changed, 6847 insertions(+), 6124 deletions(-)
 mode change 100755 => 100644 cmp_tool.c
 delete mode 100644 lib/cmp_icu_new.c
 delete mode 100644 test/cmp_icu/test_cmp_icu_new.c
 create mode 100644 test/cmp_icu/test_decmp.c

diff --git a/cmp_tool.c b/cmp_tool.c
old mode 100755
new mode 100644
index e3b2716..c30ae6e
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -28,6 +28,7 @@
 #include "cmp_tool-config.h"
 #include "cmp_io.h"
 #include "cmp_icu.h"
+#include "cmp_rdcu.h" /*TODO: shift setup to support */
 #include "decmp.h"
 #include "cmp_guess.h"
 #include "cmp_entity.h"
@@ -37,11 +38,21 @@
 
 #define BUFFER_LENGTH_DEF_FAKTOR 2
 
-
 #define DEFAULT_MODEL_ID 53264  /* random default id */
 #define DEFAULT_MODEL_COUNTER 0
 
 
+/* find a good set of compression parameters for a given dataset */
+static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
+			  int guess_level);
+
+/* compress the data and write the results to files */
+static int compression(struct cmp_cfg *cfg, struct cmp_info *info);
+
+/* decompress the data and write the results in file(s)*/
+static int decompression(struct cmp_entity *ent, uint16_t *input_model_buf);
+
+
 /*
  * For long options that have no equivalent short option, use a
  * non-character as a pseudo short option, starting with CHAR_MAX + 1.
@@ -94,17 +105,6 @@ static int verbose_en;
 /* if non zero add a compression entity header in front of the compressed data */
 static int include_cmp_header = 1;
 
-/* find a good set of compression parameters for a given dataset */
-static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
-			  int guess_level);
-
-/* compress the data and write the results to files */
-static int compression(struct cmp_cfg *cfg, struct cmp_info *info);
-
-/* decompress the data and write the results in file(s)*/
-static int decompression(uint32_t *cmp_data_adr, uint16_t *input_model_buf,
-			 struct cmp_info *info);
-
 /* model ID string set by the --model_id option */
 static const char *model_id_str;
 
@@ -140,16 +140,16 @@ int main(int argc, char **argv)
 	int guess_level = DEFAULT_GUESS_LEVEL;
 	int print_diff_cfg = 0;
 
-	struct cmp_cfg cfg = {0}; /* compressor configuration struct */
-	struct cmp_info info = {0}; /* decompression information struct */
-
-	/* buffer containing all read in compressed data for decompression (including header if used) */
-	void *decomp_input_buf = NULL;
-	/* address to the compressed data for the decompression */
-	uint32_t *cmp_data_adr = NULL;
+	/* buffer containing all read in compressed data for decompression */
+	struct cmp_entity *decomp_entity = NULL;
 	/* buffer containing the read in model */
 	uint16_t *input_model_buf = NULL;
 
+	struct cmp_info info = {0}; /* decompression information struct */
+	struct cmp_cfg cfg = {0}; /* compressor configuration struct */
+
+	cfg.data_type = DATA_TYPE_IMAGETTE; /* use imagette as default data type */
+
 	/* show help if no arguments are provided */
 	if (argc < 2) {
 		print_help(program_name);
@@ -190,7 +190,7 @@ int main(int argc, char **argv)
 			verbose_en = 1;
 			break;
 		case 'V': /* --version */
-			printf("%s version %s\n", PROGRAM_NAME, VERSION);
+			printf("%s version %s\n", PROGRAM_NAME, CMP_TOOL_VERSION);
 			exit(EXIT_SUCCESS);
 			break;
 		case DIFF_CFG_OPTION:
@@ -262,20 +262,38 @@ int main(int argc, char **argv)
 #endif
 
 	if (print_model_cfg == 1) {
-		print_cfg(&DEFAULT_CFG_MODEL, print_rdcu_cfg);
+		cfg = rdcu_cfg_create(CMP_DEF_IMA_MODEL_DATA_TYPE, CMP_DEF_IMA_MODEL_CMP_MODE,
+				      CMP_DEF_IMA_MODEL_MODEL_VALUE, CMP_DEF_IMA_MODEL_LOSSY_PAR);
+		rdcu_cfg_buffers(&cfg, NULL, 0, NULL, CMP_DEF_IMA_MODEL_RDCU_DATA_ADR,
+				 CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR, CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR,
+				 CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR, 0);
+		rdcu_cfg_imagette(&cfg,
+				  CMP_DEF_IMA_MODEL_GOLOMB_PAR, CMP_DEF_IMA_MODEL_SPILL_PAR,
+				  CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP1_SPILL_PAR,
+				  CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP2_SPILL_PAR);
+		print_cfg(&cfg, print_rdcu_cfg);
 		exit(EXIT_SUCCESS);
 	}
 
 	if (print_diff_cfg == 1) {
-		print_cfg(&DEFAULT_CFG_DIFF, print_rdcu_cfg);
+		cfg = rdcu_cfg_create(CMP_DEF_IMA_DIFF_DATA_TYPE, CMP_DEF_IMA_DIFF_CMP_MODE,
+				      CMP_DEF_IMA_DIFF_MODEL_VALUE, CMP_DEF_IMA_DIFF_LOSSY_PAR);
+		rdcu_cfg_buffers(&cfg, NULL, 0, NULL, CMP_DEF_IMA_DIFF_RDCU_DATA_ADR,
+				 CMP_DEF_IMA_DIFF_RDCU_MODEL_ADR, CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR,
+				 CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR, 0);
+		rdcu_cfg_imagette(&cfg,
+				  CMP_DEF_IMA_DIFF_GOLOMB_PAR, CMP_DEF_IMA_DIFF_SPILL_PAR,
+				  CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR, CMP_DEF_IMA_DIFF_AP1_SPILL_PAR,
+				   CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR, CMP_DEF_IMA_DIFF_AP2_SPILL_PAR);
+		print_cfg(&cfg, print_rdcu_cfg);
 		exit(EXIT_SUCCESS);
 	}
 
 	printf("#########################################################\n");
 	printf("### PLATO Compression/Decompression Tool Version %s ###\n",
-	       VERSION);
+	       CMP_TOOL_VERSION);
 	printf("#########################################################\n");
-	if (!strcmp(VERSION, "0.07") || !strcmp(VERSION, "0.08"))
+	if (!strcmp(CMP_TOOL_VERSION, "0.07") || !strcmp(CMP_TOOL_VERSION, "0.08"))
 		printf("Info: Note that the behaviour of the cmp_tool has changed. From now on, the compressed data will be preceded by a header by default. The old behaviour can be achieved with the --no_header option.\n\n");
 
 	if (!data_file_name) {
@@ -293,6 +311,7 @@ int main(int argc, char **argv)
 
 	if (cmp_operation || guess_operation) {
 		ssize_t size;
+		uint32_t input_size;
 
 		if (cmp_operation) {
 			printf("## Starting the compression ##\n");
@@ -308,21 +327,26 @@ int main(int argc, char **argv)
 		printf("Importing data file %s ... ", data_file_name);
 		/* count the samples in the data file when samples == 0 */
 		if (cfg.samples == 0) {
-			size = read_file16(data_file_name, NULL, 0, 0);
-			if (size <= 0) /* empty file is treated as an error */
+			int samples;
+			size = read_file_data(data_file_name, cfg.data_type, NULL, 0, 0);
+			if (size <= 0 || size > UINT32_MAX) /* empty file is treated as an error */
 				goto fail;
-			cfg.samples = size/size_of_a_sample(cfg.cmp_mode);
+			samples = cmp_input_size_to_samples(size, cfg.data_type);
+			if (samples < 0)
+				goto fail;
+			cfg.samples = (uint32_t)samples;
 			printf("\nNo samples parameter set. Use samples = %u.\n... ", cfg.samples);
 		}
 
-		cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.cmp_mode));
+		input_size = cmp_cal_size_of_data(cfg.samples, cfg.data_type);
+		cfg.input_buf = malloc(input_size);
 		if (!cfg.input_buf) {
 			fprintf(stderr, "%s: Error allocating memory for input data buffer.\n", PROGRAM_NAME);
 			goto fail;
 		}
 
-		size = read_file16(data_file_name, cfg.input_buf, cfg.samples,
-				   verbose_en);
+		size = read_file_data(data_file_name, cfg.data_type, cfg.input_buf,
+				      input_size, verbose_en);
 		if (size < 0)
 			goto fail;
 		printf("DONE\n");
@@ -330,7 +354,8 @@ int main(int argc, char **argv)
 	} else { /* decompression mode*/
 		printf("## Starting the decompression ##\n");
 		if (info_file_name) {
-			ssize_t size;
+			ssize_t f_size;
+			size_t ent_size;
 			uint32_t cmp_size_byte;
 
 			printf("Importing decompression information file %s ... ", info_file_name);
@@ -341,63 +366,58 @@ int main(int argc, char **argv)
 
 			printf("Importing compressed data file %s ... ", data_file_name);
 			cmp_size_byte = cmp_bit_to_4byte(info.cmp_size);
-			cmp_data_adr = decomp_input_buf = malloc(cmp_size_byte);
-			if (!decomp_input_buf) {
+
+			ent_size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW,
+						  cmp_size_byte);
+			if (ent_size <= 0)
+				goto fail;
+			decomp_entity = malloc(ent_size);
+			if (!decomp_entity) {
 				fprintf(stderr, "%s: Error allocating memory for decompression input buffer.\n", PROGRAM_NAME);
 				goto fail;
 			}
+			ent_size = cmp_ent_create(decomp_entity, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW,
+						  cmp_size_byte);
+			if (ent_size <= 0)
+				goto fail;
 
-			size = read_file32(data_file_name, decomp_input_buf,
-					   cmp_size_byte/4, verbose_en);
-			if (size < 0)
+			if (info.cmp_mode_used == CMP_MODE_RAW)
+				/* the raw data does not have to be a multiple of 4 bytes */
+				cmp_size_byte = (info.cmp_size+7)/CHAR_BIT;
+
+			f_size = read_file8(data_file_name, cmp_ent_get_data_buf(decomp_entity),
+					    cmp_size_byte, verbose_en);
+			if (f_size < 0)
+				goto fail;
+
+			error = cmp_ent_write_rdcu_cmp_pars(decomp_entity, &info, NULL);
+			if (error)
 				goto fail;
 		} else { /* read in compressed data with header */
 			ssize_t size;
 			size_t buf_size;
-			struct cmp_entity *ent;
 
 			printf("Importing compressed data file %s ... ", data_file_name);
 			buf_size = size = read_file_cmp_entity(data_file_name,
 							       NULL, 0, 0);
-			if (size < 0)
+			if (size < 0 || size > UINT32_MAX)
 				goto fail;
 			/* to be save allocate at least the size of the cmp_entity struct */
 			if (buf_size < sizeof(struct cmp_entity))
 				buf_size = sizeof(struct cmp_entity);
 
-			decomp_input_buf = ent = malloc(buf_size);
-			if (!ent) {
+			decomp_entity = malloc(buf_size);
+			if (!decomp_entity) {
 				fprintf(stderr, "%s: Error allocating memory for the compression entity buffer.\n", PROGRAM_NAME);
 				goto fail;
 			}
-			size = read_file_cmp_entity(data_file_name, ent, size,
-						  verbose_en);
-			if (size < 0)
-				goto fail;
-			printf("DONE\n");
-
-			printf("Parse the compression entity header ... ");
-			error = cmp_ent_read_imagette_header(ent, &info);
-			if (error)
-				goto fail;
-			if (verbose_en)
-				print_cmp_info(&info);
-
-			/* we reuse the entity buffer for the compressed data */
-			cmp_data_adr = (uint32_t *)decomp_input_buf;
-			size = cmp_ent_get_cmp_data(ent, cmp_data_adr, buf_size);
-			ent = NULL;
+			size = read_file_cmp_entity(data_file_name, decomp_entity,
+						    size, verbose_en);
 			if (size < 0)
 				goto fail;
 
 			if (verbose_en) {
-				size_t i;
-				printf("\ncompressed data:\n");
-				for (i = 0; i < size/sizeof(uint32_t); i++) {
-					printf("%08X ", cmp_data_adr[i]);
-					if (i && !((i+1) % 4))
-						printf("\n");
-				}
+				cmp_ent_print(decomp_entity);
 				printf("\n");
 			}
 		}
@@ -406,10 +426,11 @@ int main(int argc, char **argv)
 
 	/* read in model */
 	if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
-	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used)) ||
+	    (!cmp_operation && model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity))) ||
 	    (guess_operation && model_file_name)) {
 		ssize_t size;
-		uint32_t model_length;
+		uint32_t model_size;
+		enum cmp_data_type data_type;
 
 		printf("Importing model file %s ... ", model_file_name ? model_file_name : "");
 		if (!model_file_name) {
@@ -417,19 +438,22 @@ int main(int argc, char **argv)
 			goto fail;
 		}
 
-		if (cmp_operation || guess_operation)
-			model_length = cfg.samples;
-		else
-			model_length = info.samples_used;
+		if (cmp_operation || guess_operation) {
+			data_type = cfg.data_type;
+			model_size = cmp_cal_size_of_data(cfg.samples, cfg.data_type);
+		} else {
+			data_type = cmp_ent_get_data_type(decomp_entity);
+			model_size = cmp_ent_get_original_size(decomp_entity);
+		}
 
-		input_model_buf = malloc(model_length * size_of_a_sample(cfg.cmp_mode));
+		input_model_buf = malloc(model_size);
 		if (!input_model_buf) {
 			fprintf(stderr, "%s: Error allocating memory for model buffer.\n", PROGRAM_NAME);
 			goto fail;
 		}
 
-		size = read_file16(model_file_name, input_model_buf,
-				   model_length, verbose_en);
+		size = read_file_data(model_file_name, data_type, input_model_buf,
+				      model_size, verbose_en);
 		if (size < 0)
 			goto fail;
 		printf("DONE\n");
@@ -446,7 +470,7 @@ int main(int argc, char **argv)
 		if (error)
 			goto fail;
 	} else {
-		error = decompression(cmp_data_adr, input_model_buf, &info);
+		error = decompression(decomp_entity, input_model_buf);
 		if (error)
 			goto fail;
 	}
@@ -454,17 +478,28 @@ int main(int argc, char **argv)
 	/* write our the updated model for compressed or decompression */
 	if (!guess_operation &&
 	    ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
-	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used)))) {
+	    (!cmp_operation && model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity))))) {
+		enum cmp_data_type data_type = DATA_TYPE_UNKOWN;
+		uint32_t model_size;
+
 		printf("Write updated model to file %s_upmodel.dat ... ", output_prefix);
-		error = write_to_file16(input_model_buf, info.samples_used,
-					output_prefix, "_upmodel.dat", verbose_en);
+		if (cmp_operation) {
+			data_type = cfg.data_type;
+			model_size = cmp_cal_size_of_data(cfg.samples, data_type);
+		} else {
+			data_type = cmp_ent_get_data_type(decomp_entity);
+			model_size = cmp_ent_get_original_size(decomp_entity);
+		}
+
+		error = write_input_data_to_file(input_model_buf, model_size, data_type,
+						 output_prefix, "_upmodel.dat", verbose_en);
 		if (error)
 			goto fail;
 		printf("DONE\n");
 	}
 
 	free(cfg.input_buf);
-	free(decomp_input_buf);
+	free(decomp_entity);
 	free(input_model_buf);
 
 	exit(EXIT_SUCCESS);
@@ -473,56 +508,33 @@ fail:
 	printf("FAILED\n");
 
 	free(cfg.input_buf);
-	free(decomp_input_buf);
+	free(decomp_entity);
 	free(input_model_buf);
 
 	exit(EXIT_FAILURE);
 }
 
 
-static enum cmp_ent_data_type cmp_ent_map_cmp_mode_data_type(uint32_t cmp_mode)
-{
-	enum cmp_ent_data_type data_type;
-
-	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
-		if (print_rdcu_cfg)
-			data_type = DATA_TYPE_IMAGETTE_ADAPTIVE;
-		else
-			data_type = DATA_TYPE_IMAGETTE;
-		break;
-	default:
-		printf("No mapping between compression mode and header data type\n!");
-		return DATA_TYPE_UNKOWN;
-	}
-
-	/* set raw bit if needed */
-	if (raw_mode_is_used(cmp_mode))
-		data_type |= 1UL << RAW_BIT_DATA_TYPE_POS;
-
-	return data_type;
-}
-
-
 /* find a good set of compression parameters for a given dataset */
 static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 			  int guess_level)
 {
 	int error;
 	uint32_t cmp_size_bit;
-	float cr;
+	double cr;
 
 	printf("Search for a good set of compression parameters (level: %d) ... ", guess_level);
 	if (!strcmp(guess_cmp_mode, "RDCU")) {
+		if (print_rdcu_cfg)
+			cfg->data_type = DATA_TYPE_IMAGETTE_ADAPTIVE;
+		else
+			cfg->data_type = DATA_TYPE_IMAGETTE;
 		if (cfg->model_buf)
 			cfg->cmp_mode = CMP_GUESS_DEF_MODE_MODEL;
 		else
 			cfg->cmp_mode = CMP_GUESS_DEF_MODE_DIFF;
 	} else {
+		cfg->data_type = DATA_TYPE_IMAGETTE; /* TODO*/
 		error = cmp_mode_parse(guess_cmp_mode, &cfg->cmp_mode);
 		if (error) {
 			fprintf(stderr, "%s: Error: unknown compression mode: %s\n", PROGRAM_NAME, guess_cmp_mode);
@@ -540,7 +552,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 
 	if (include_cmp_header)
 		cmp_size_bit = CHAR_BIT * (cmp_bit_to_4byte(cmp_size_bit) +
-			cmp_ent_cal_hdr_size(cmp_ent_map_cmp_mode_data_type(cfg->cmp_mode)));
+			cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW));
 
 	printf("DONE\n");
 
@@ -550,7 +562,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 		return -1;
 	printf("DONE\n");
 
-	cr = (8.0 * cfg->samples * size_of_a_sample(cfg->cmp_mode))/cmp_size_bit;
+	cr = (8.0 * cmp_cal_size_of_data(cfg->samples, cfg->data_type))/cmp_size_bit;
 	printf("Guessed parameters can compress the data with a CR of %.2f.\n", cr);
 
 	return 0;
@@ -594,48 +606,58 @@ static int gen_rdcu_write_pkts(struct cmp_cfg *cfg)
 }
 
 
-/* add a compression entity header in front of the data */
-static int add_cmp_ent_hdr(struct cmp_cfg *cfg, struct cmp_info *info,
-			   uint64_t start_time)
+/**
+ * @brief generate the compression information used based on the compression
+ *	configuration, to emulate the RDCU behaviour
+ *
+ * @param cfg		compression configuration struct
+ * @param cmp_size_bit	length of the bitstream in bits
+ * @param info		compressor information struct to set the used compression
+ *	parameters (can be NULL)
+ *
+ * @note set cmp_size, ap1_cmp_size, ap2_cmp_size will be set to 0
+ *
+ * @returns 0 on success, error otherwise
+ * TODO: set cmp_err in error case
+ */
+
+static int cmp_gernate_rdcu_info(const struct cmp_cfg *cfg, int cmp_size_bit, struct cmp_info *info)
 {
-	int error;
-	uint32_t red_val;
-	uint8_t model_counter = DEFAULT_MODEL_COUNTER;
-	uint16_t model_id = DEFAULT_MODEL_ID;
-	size_t s, cmp_hdr_size;
-	struct cmp_entity *ent;
-	enum cmp_ent_data_type data_type = cmp_ent_map_cmp_mode_data_type(cfg->cmp_mode);
+	if (!cfg)
+		return -1;
 
-	if (model_id_str) {
-		error = atoui32("model_id", model_id_str, &red_val);
-		if (error || red_val > UINT16_MAX)
-			return -1;
-		model_id = red_val;
-	}
-	if (model_counter_str) {
-		error = atoui32("model_counter", model_counter_str, &red_val);
-		if (error || red_val > UINT8_MAX)
-			return -1;
-		model_counter = red_val;
-	} else {
-		if (model_mode_is_used(cfg->cmp_mode))
-			model_counter = DEFAULT_MODEL_COUNTER + 1;
-	}
+	if (cfg->cmp_mode > UINT8_MAX)
+		return -1;
 
-	cmp_hdr_size = cmp_ent_cal_hdr_size(data_type);
-	if (!cmp_hdr_size)
+	if (cfg->round > UINT8_MAX)
 		return -1;
-	memmove((uint8_t *)cfg->icu_output_buf+cmp_hdr_size, cfg->icu_output_buf,
-		cmp_bit_to_4byte(info->cmp_size));
 
-	ent = (struct cmp_entity *)cfg->icu_output_buf;
-	s = cmp_ent_build(ent, data_type, cmp_tool_gen_version_id(VERSION),
-			  start_time, cmp_ent_create_timestamp(NULL), model_id,
-			  model_counter, info, cfg);
-	if (!s) {
-		fprintf(stderr, "%s: error occurred while creating the compression entity header.\n", PROGRAM_NAME);
+	if (cfg->model_value > UINT8_MAX)
 		return -1;
+
+	if (info) {
+		info->cmp_err = 0;
+		info->cmp_mode_used = (uint8_t)cfg->cmp_mode;
+		info->model_value_used = (uint8_t)cfg->model_value;
+		info->round_used = (uint8_t)cfg->round;
+		info->spill_used = cfg->spill;
+		info->golomb_par_used = cfg->golomb_par;
+		info->samples_used = cfg->samples;
+		info->cmp_size = 0;
+		info->ap1_cmp_size = 0;
+		info->ap2_cmp_size = 0;
+		info->rdcu_new_model_adr_used = cfg->rdcu_new_model_adr;
+		info->rdcu_cmp_adr_used = cfg->rdcu_buffer_adr;
+
+		if (cmp_size_bit == CMP_ERROR_SAMLL_BUF)
+			/* the icu_output_buf is to small to store the whole bitstream */
+			info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
+		if (cmp_size_bit < 0)
+			info->cmp_size = 0;
+		else
+			info->cmp_size = (uint32_t)cmp_size_bit;
 	}
+
 	return 0;
 }
 
@@ -643,12 +665,14 @@ static int add_cmp_ent_hdr(struct cmp_cfg *cfg, struct cmp_info *info,
 /* compress the data and write the results to files */
 static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 {
-	int error;
-	uint32_t cmp_size_byte;
-	size_t out_buf_size;
+	int cmp_size, error;
+	uint32_t cmp_size_byte, out_buf_size;
+	size_t s;
 	uint64_t start_time = cmp_ent_create_timestamp(NULL);
-
-	cfg->icu_output_buf = NULL;
+	struct cmp_entity *cmp_entity = NULL;
+	uint8_t model_counter = DEFAULT_MODEL_COUNTER;
+	uint16_t model_id = DEFAULT_MODEL_ID;
+	void *data_to_write_to_file;
 
 	if (cfg->buffer_length == 0) {
 		cfg->buffer_length = (cfg->samples+1) * BUFFER_LENGTH_DEF_FAKTOR; /* +1 to prevent malloc(0)*/
@@ -666,30 +690,65 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 
 	printf("Compress data ... ");
 	/* round up to a multiple of 4 */
-	out_buf_size = (cmp_cal_size_of_data(cfg->buffer_length, cfg->cmp_mode) + 3) & ~0x3U;
+	out_buf_size = (cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type) + 3) & ~0x3U;
 
-	cfg->icu_output_buf = malloc(out_buf_size + sizeof(struct cmp_entity));
-	if (cfg->icu_output_buf == NULL) {
+	cmp_entity = calloc(1, out_buf_size + sizeof(struct cmp_entity));
+	if (cmp_entity == NULL) {
 		fprintf(stderr, "%s: Error allocating memory for output buffer.\n", PROGRAM_NAME);
 		goto error_cleanup;
 	}
+	s = cmp_ent_create(cmp_entity, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, out_buf_size);
+	if (!s) {
+		fprintf(stderr, "%s: error occurred while creating the compression entity header.\n", PROGRAM_NAME);
+		goto error_cleanup;
+	}
+	cfg->icu_output_buf = cmp_ent_get_data_buf(cmp_entity);
 
-	error = icu_compress_data(cfg, info);
-	if (error || info->cmp_err != 0) {
-		printf("\nCompression error 0x%02X\n... ", info->cmp_err);
+	cmp_size = icu_compress_data(cfg);
+	cmp_gernate_rdcu_info(cfg, cmp_size, info);
+	if (cmp_size < 0 || info->cmp_err != 0) {
+		if (info->cmp_err)
+			printf("\nCompression error 0x%02X\n... ", info->cmp_err);
 		/* TODO: add a parse cmp error function */
 		/* if ((info->cmp_err >> SMALL_BUFFER_ERR_BIT) & 1U) */
 		/*	fprintf(stderr, "%s: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n", PROGRAM_NAME); */
 		goto error_cleanup;
 	}
 
+	if (model_id_str) {
+		uint32_t red_val;
+		error = atoui32("model_id", model_id_str, &red_val);
+		if (error || red_val > UINT16_MAX)
+			return -1;
+		model_id = (uint16_t)red_val;
+	}
+	if (model_counter_str) {
+		uint32_t red_val;
+		error = atoui32("model_counter", model_counter_str, &red_val);
+		if (error || red_val > UINT8_MAX)
+			return -1;
+		model_counter = (uint8_t)red_val;
+	} else {
+		if (model_mode_is_used(cfg->cmp_mode))
+			model_counter = DEFAULT_MODEL_COUNTER + 1;
+	}
+
+	s = cmp_ent_build(cmp_entity,  cmp_tool_gen_version_id(CMP_TOOL_VERSION),
+			  start_time, cmp_ent_create_timestamp(NULL), model_id,
+			  model_counter, cfg, cmp_size);
+	if (!s) {
+		fprintf(stderr, "%s: error occurred while creating the compression entity header.\n", PROGRAM_NAME);
+		goto error_cleanup;
+	}
 	if (include_cmp_header) {
-		error = add_cmp_ent_hdr(cfg, info, start_time);
-		if (error)
-			goto error_cleanup;
-		cmp_size_byte = cmp_ent_get_size((struct cmp_entity *)cfg->icu_output_buf);
+		data_to_write_to_file = cmp_entity;
+		cmp_size_byte = cmp_ent_get_size(cmp_entity);
 	} else {
-		cmp_size_byte = cmp_bit_to_4byte(info->cmp_size);
+		data_to_write_to_file = cmp_ent_get_data_buf(cmp_entity);
+		if (cfg->cmp_mode == CMP_MODE_RAW)
+			cmp_size_byte = info->cmp_size/CHAR_BIT;
+		else
+			cmp_size_byte = cmp_bit_to_4byte(info->cmp_size);
 	}
 
 	printf("DONE\n");
@@ -703,7 +762,7 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 	}
 
 	printf("Write compressed data to file %s.cmp ... ", output_prefix);
-	error = write_cmp_data_file(cfg->icu_output_buf, cmp_size_byte,
+	error = write_cmp_data_file(data_to_write_to_file, cmp_size_byte,
 				    output_prefix, ".cmp", verbose_en);
 	if (error)
 		goto error_cleanup;
@@ -724,52 +783,56 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 		printf("\n");
 	}
 
-	free(cfg->icu_output_buf);
+	free(cmp_entity);
 	cfg->icu_output_buf = NULL;
 
 	return 0;
 
 error_cleanup:
-	free(cfg->icu_output_buf);
+	free(cmp_entity);
 	cfg->icu_output_buf = NULL;
+
 	return -1;
 }
 
 
 /* decompress the data and write the results in file(s)*/
-static int decompression(uint32_t *cmp_data_adr, uint16_t *input_model_buf,
-			 struct cmp_info *info)
+static int decompression(struct cmp_entity *ent, uint16_t *input_model_buf)
 {
 	int error;
+	int decomp_size;
 	uint16_t *decomp_output;
 
 	printf("Decompress data ... ");
 
-	if (info->samples_used == 0) {
+	decomp_size = decompress_cmp_entiy(ent, input_model_buf, input_model_buf, NULL);
+	if (decomp_size < 0)
+		return -1;
+	if (decomp_size == 0) {
 		printf("\nWarring: No data are decompressed.\n... ");
 		printf("DONE\n");
 		return 0;
 	}
 
-	decomp_output = malloc(cmp_cal_size_of_data(info->samples_used,
-						    info->cmp_mode_used));
+	decomp_output = malloc((size_t)decomp_size);
 	if (decomp_output == NULL) {
 		fprintf(stderr, "%s: Error allocating memory for decompressed data.\n", PROGRAM_NAME);
 		return -1;
 	}
 
-	error = decompress_data(cmp_data_adr, input_model_buf, info,
-				decomp_output);
-	if (error) {
+	decomp_size = decompress_cmp_entiy(ent, input_model_buf, input_model_buf, decomp_output);
+	if (decomp_size <= 0) {
 		free(decomp_output);
 		return -1;
 	}
+
 	printf("DONE\n");
 
 	printf("Write decompressed data to file %s.dat ... ", output_prefix);
 
-	error = write_to_file16(decomp_output, info->samples_used,
-				output_prefix, ".dat", verbose_en);
+	error = write_input_data_to_file(decomp_output, (uint32_t)decomp_size, cmp_ent_get_data_type(ent),
+					 output_prefix, ".dat", verbose_en);
+
 	free(decomp_output);
 	if (error)
 		return -1;
diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 2ec635e..75b69be 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -14,17 +14,20 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
+ * @see for N-DPU packed definition: PLATO-LESIA-PL-RP-0031 Issue: 1.9 (N-DPU->ICU data rate)
+ * @see for calculation of the max used bits: PLATO-LESIA-PDC-TN-0054 Issue: 1.7
  *
- * Three data rates:
+ * Three data rates (for N-DPU):
  * fast cadence (nominally 25s)
  * short cadence (nominally 50s)
  * long cadence (nominally 600s)
  *
  * The science products are identified as this:
- * FX = normal light flux
- * NCOB = normal center of brightness
- * EFX = extended flux
- * ECOB = extended center of brightness
+ * exp_flags = selected exposure flags
+ * fx = normal light flux
+ * ncob = normal center of brightness
+ * efx = extended flux
+ * ecob = extended center of brightness
  * The prefixes F, S and L stand for Fast, Short and Long cadence
  */
 
@@ -34,173 +37,240 @@
 #include <stdint.h>
 
 #include "compiler.h"
+#include "cmp_support.h"
+
+#define MAX_USED_NC_IMAGETTE_BITS		16
+#define MAX_USED_SATURATED_IMAGETTE_BITS	16 /* TBC */
+#define MAX_USED_FC_IMAGETTE_BITS		16 /* TBC */
+
+#define MAX_USED_F_FX_BITS	21 /* max exp. int value: (1.078*10^5)/0.1 = 1,078,000 -> 21 bits */
+#define MAX_USED_F_EFX_BITS	MAX_USED_F_FX_BITS /* we use the same as f_fx */
+#define MAX_USED_F_NCOB_BITS	20 /* max exp. int value: 6/10^−5 = 6*10^5 -> 20 bits */
+#define MAX_USED_F_ECOB_BITS	32 /* TBC */
+
+#define MAX_USED_S_FX_EXPOSURE_FLAGS_BITS	2 /* 2 flags + 6 spare bits */
+#define MAX_USED_S_FX_BITS			24 /* max exp. int value: (1.078*10^5-34.71)/0.01 = 10,780,000-> 24 bits */
+#define MAX_USED_S_EFX_BITS			MAX_USED_S_FX_BITS /* we use the same as s_fx */
+#define MAX_USED_S_NCOB_BITS			MAX_USED_F_NCOB_BITS
+#define MAX_USED_S_ECOB_BITS			32 /* TBC */
+
+#define MAX_USED_L_FX_EXPOSURE_FLAGS_BITS	24 /* 24 flags */
+#define MAX_USED_L_FX_BITS			MAX_USED_S_FX_BITS
+#define MAX_USED_L_FX_VARIANCE_BITS		32 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_L_EFX_BITS			MAX_USED_L_FX_BITS /* we use the same as l_fx */
+#define MAX_USED_L_NCOB_BITS			MAX_USED_F_NCOB_BITS
+#define MAX_USED_L_ECOB_BITS			32 /* TBC */
+#define MAX_USED_L_COB_VARIANCE_BITS		25 /* max exp int value: 0.1739/10^−8 = 17390000 -> 25 bits */
+
+#define MAX_USED_NC_OFFSET_MEAN_BITS		2 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_NC_OFFSET_VARIANCE_BITS	10 /* max exp. int value: 9.31/0.01 = 931 -> 10 bits */
+
+#define MAX_USED_NC_BACKGROUND_MEAN_BITS		16 /* max exp. int value: (391.8-(-50))/0.01 = 44,180 -> 16 bits */
+#define MAX_USED_NC_BACKGROUND_VARIANCE_BITS		16 /* max exp. int value: 6471/0.1 = 64710 -> 16 bit */
+#define MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS	5 /* maximum = 16 -> 5 bits */
+
+#define MAX_USED_SMEARING_MEAN_BITS		15 /* max exp. int value: (219.9 - -50)/0.01 = 26.990 */
+#define MAX_USED_SMEARING_VARIANCE_MEAN_BITS	16 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_SMEARING_OUTLIER_PIXELS_BITS	11 /* maximum = 1200 -> 11 bits */
+
+#define MAX_USED_FC_OFFSET_MEAN_BITS		32 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_FC_OFFSET_VARIANCE_BITS	9  /* max exp. int value: 342/1 = 342 -> 9 bits */
+#define MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS	16 /* TBC */
+
+#define MAX_USED_FC_BACKGROUND_MEAN_BITS		10 /* max exp. int value: (35.76-(-50))/0.1 = 858 -> 10 bits*/
+#define MAX_USED_FC_BACKGROUND_VARIANCE_BITS		6 /* max exp. int value: 53.9/1 = 54 -> 6 bits */
+#define MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS	16 /* TBC */
+
+
+/* struct holding the maximum length of the different data products types in bits */
+struct cmp_max_used_bits {
+	unsigned int version;
+	unsigned int s_exp_flags;
+	unsigned int s_fx;
+	unsigned int s_efx;
+	unsigned int s_ncob; /* s_ncob_x and s_ncob_y */
+	unsigned int s_ecob; /* s_ecob_x and s_ncob_y */
+	unsigned int f_fx;
+	unsigned int f_efx;
+	unsigned int f_ncob; /* f_ncob_x and f_ncob_y */
+	unsigned int f_ecob; /* f_ecob_x and f_ncob_y */
+	unsigned int l_exp_flags;
+	unsigned int l_fx;
+	unsigned int l_fx_variance;
+	unsigned int l_efx;
+	unsigned int l_ncob; /* l_ncob_x and l_ncob_y */
+	unsigned int l_ecob; /* l_ecob_x and l_ncob_y */
+	unsigned int l_cob_variance; /* l_cob_x_variance and l_cob_y_variance */
+	unsigned int nc_imagette;
+	unsigned int saturated_imagette;
+	unsigned int nc_offset_mean;
+	unsigned int nc_offset_variance;
+	unsigned int nc_background_mean;
+	unsigned int nc_background_variance;
+	unsigned int nc_background_outlier_pixels;
+	unsigned int smeating_mean;
+	unsigned int smeating_variance_mean;
+	unsigned int smearing_outlier_pixels;
+	unsigned int fc_imagette;
+	unsigned int fc_offset_mean;
+	unsigned int fc_offset_variance;
+	unsigned int fc_offset_pixel_in_error;
+	unsigned int fc_background_mean;
+	unsigned int fc_background_variance;
+	unsigned int fc_background_outlier_pixels;
+};
+
+
+/* Set and read the max_used_bits, which specify how many bits are needed to
+ * represent the highest possible value.
+ */
+void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits);
+struct cmp_max_used_bits cmp_get_max_used_bits(void);
+
+/* for internal use only! */
+extern struct cmp_max_used_bits max_used_bits;
 
-#define MODE_RAW_S_FX           100
-#define MODE_MODEL_ZERO_S_FX	101
-#define MODE_DIFF_ZERO_S_FX	102
-#define MODE_MODEL_MULTI_S_FX	103
-#define MODE_DIFF_MULTI_S_FX	104
-
-#define MODE_MODEL_ZERO_S_FX_EFX	110
-#define MODE_DIFF_ZERO_S_FX_EFX		111
-#define MODE_MODEL_MULTI_S_FX_EFX	112
-#define MODE_DIFF_MULTI_S_FX_EFX	113
-
-#define MODE_MODEL_ZERO_S_FX_NCOB	120
-#define MODE_DIFF_ZERO_S_FX_NCOB	121
-#define MODE_MODEL_MULTI_S_FX_NCOB	122
-#define MODE_DIFF_MULTI_S_FX_NCOB	123
-
-#define MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB	130
-#define MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB	131
-#define MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB	132
-#define MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB	133
-
-#define MODE_MODEL_ZERO_F_FX	140
-#define MODE_DIFF_ZERO_F_FX	141
-#define MODE_MODEL_MULTI_F_FX	142
-#define MODE_DIFF_MULTI_F_FX	143
-
-#define MODE_MODEL_ZERO_F_FX_EFX	150
-#define MODE_DIFF_ZERO_F_FX_EFX		151
-#define MODE_MODEL_MULTI_F_FX_EFX	152
-#define MODE_DIFF_MULTI_F_FX_EFX	153
-
-#define MODE_MODEL_ZERO_F_FX_NCOB	160
-#define MODE_DIFF_ZERO_F_FX_NCOB	161
-#define MODE_MODEL_MULTI_F_FX_NCOB	162
-#define MODE_DIFF_MULTI_F_FX_NCOB	163
-
-#define MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB	170
-#define MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB	171
-#define MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB	172
-#define MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB	173
-
-#define MODE_RAW_32		200
-#define MODE_DIFF_ZERO_32	201
-#define MODE_DIFF_MULTI_32	202
-#define MODE_MODEL_ZERO_32	203
-#define MODE_MODEL_MULTI_32	204
-
-int lossy_rounding_16(uint16_t *data_buf, unsigned int samples, unsigned int
-		      round);
-int de_lossy_rounding_16(uint16_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used);
 
-int lossy_rounding_32(uint32_t *data_buf, unsigned int samples, unsigned int
-		      round);
-int de_lossy_rounding_32(uint32_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used);
+/* Source data header structure for multi entry packet */
+#define MULTI_ENTRY_HDR_SIZE 12
+compile_time_assert(MULTI_ENTRY_HDR_SIZE % sizeof(uint32_t) == 0, N_DPU_ICU_MULTI_ENTRY_HDR_NOT_4_BYTE_ALLIED);
 
-void cmp_input_big_to_cpu_endiannessy(void *data, u_int32_t data_size_byte,
-				      uint32_t cmp_mode);
+struct multi_entry_hdr {
+	uint32_t timestamp_coarse;
+	uint16_t timestamp_fine;
+	uint16_t configuration_id;
+	uint16_t collection_id;
+	uint16_t collection_length;
+	uint8_t  entry[];
+} __attribute__((packed));
+compile_time_assert(sizeof(struct multi_entry_hdr) == MULTI_ENTRY_HDR_SIZE, N_DPU_ICU_MULTI_ENTRY_HDR_SIZE_IS_NOT_CORRECT);
 
-/* @see for packed definition: PLATO-LESIA-PL-RP-0031 Issue: 1.9 (N-DPU->ICU data rate) */
-#define N_DPU_ICU_MULTI_ENTRY_HDR_SIZE 12
 
-struct n_dpu_icu_multi_entry_hdr {
-	uint64_t ncxx_timestamp:48;
-	uint16_t ncxx_configuration_id;
-	uint16_t ncxx_collection_id;
-	uint16_t ncxx_collection_length;
+struct s_fx {
+	uint8_t exp_flags; /* selected exposure flags (2 flags + 6 spare bits) */
+	uint32_t fx;       /* normal light flux */
 } __attribute__((packed));
-compile_time_assert(sizeof(struct n_dpu_icu_multi_entry_hdr) == N_DPU_ICU_MULTI_ENTRY_HDR_SIZE, N_DPU_ICU_MULTI_ENTRY_HDR_SIZE_IS_NOT_CORRECT);
 
 
-struct S_FX {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
+struct s_fx_efx {
+	uint8_t exp_flags;
+	uint32_t fx;
+	uint32_t efx;
 } __attribute__((packed));
 
-struct S_FX sub_S_FX(struct S_FX a, struct S_FX b);
-struct S_FX add_S_FX(struct S_FX a, struct S_FX b);
-int lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples,
-			       unsigned int round);
-int de_lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples_used,
-			   unsigned int round_used);
-struct S_FX cal_up_model_S_FX(struct S_FX data_buf, struct S_FX model_buf,
-			      unsigned int model_value);
+
+struct s_fx_ncob {
+	uint8_t exp_flags;
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+} __attribute__((packed));
 
 
-struct S_FX_EFX {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
-	uint32_t EFX;
+struct s_fx_efx_ncob_ecob {
+	uint8_t exp_flags;
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t efx;
+	uint32_t ecob_x;
+	uint32_t ecob_y;
 } __attribute__((packed));
 
-struct S_FX_EFX sub_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b);
-struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b);
-int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples,
-				   unsigned int round);
-int de_lossy_rounding_S_FX_EFX(struct S_FX_EFX *data_buf, unsigned int
-			       samples_used, unsigned int round_used);
-struct S_FX_EFX cal_up_model_S_FX_EFX(struct S_FX_EFX data_buf, struct S_FX_EFX
-				      model_buf, unsigned int model_value);
 
+struct f_fx {
+	uint32_t fx;
+} __attribute__((packed));
 
-struct S_FX_NCOB {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
+
+struct f_fx_efx {
+	uint32_t fx;
+	uint32_t efx;
 } __attribute__((packed));
 
-struct S_FX_NCOB sub_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b);
-struct S_FX_NCOB add_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b);
-int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
-			     unsigned int round);
-int de_lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int
-				samples_used, unsigned int round_used);
-struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf,
-					struct S_FX_NCOB model_buf,
-					unsigned int model_value);
+
+struct f_fx_ncob {
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+} __attribute__((packed));
 
 
-struct S_FX_EFX_NCOB_ECOB {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
-	uint32_t EFX;
-	uint32_t ECOB_X;
-	uint32_t ECOB_Y;
+struct f_fx_efx_ncob_ecob {
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t efx;
+	uint32_t ecob_x;
+	uint32_t ecob_y;
 } __attribute__((packed));
 
-struct S_FX_EFX_NCOB_ECOB sub_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b);
-struct S_FX_EFX_NCOB_ECOB add_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b);
-int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-				      unsigned int samples, unsigned int round);
-int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					 unsigned int samples,
-					 unsigned int round);
 
-struct F_FX {
-	uint32_t FX;
+struct l_fx {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t fx_variance;
 } __attribute__((packed));
 
 
-struct F_FX_EFX {
-	uint32_t FX;
-	uint32_t EFX;
+struct l_fx_efx {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t efx;
+	uint32_t fx_variance;
 } __attribute__((packed));
 
 
-struct F_FX_NCOB {
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
+struct l_fx_ncob {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t fx_variance;
+	uint32_t cob_x_variance;
+	uint32_t cob_y_variance;
 } __attribute__((packed));
 
 
-struct F_FX_EFX_NCOB_ECOB {
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
-	uint32_t EFX;
-	uint32_t ECOB_X;
-	uint32_t ECOB_Y;
+struct l_fx_efx_ncob_ecob {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t efx;
+	uint32_t ecob_x;
+	uint32_t ecob_y;
+	uint32_t fx_variance;
+	uint32_t cob_x_variance;
+	uint32_t cob_y_variance;
 } __attribute__((packed));
 
+
+struct nc_offset {
+	uint32_t mean;
+	uint32_t variance;
+} __attribute__((packed));
+
+
+struct nc_background {
+	uint32_t mean;
+	uint32_t variance;
+	uint16_t outlier_pixels;
+} __attribute__((packed));
+
+
+struct smearing {
+	uint32_t mean;
+	uint16_t variance_mean;
+	uint16_t outlier_pixels;
+} __attribute__((packed));
+
+
+size_t size_of_a_sample(enum cmp_data_type data_type);
+unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type);
+int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type);
+
+int cmp_input_big_to_cpu_endianness(void *data, u_int32_t data_size_byte,
+				    enum cmp_data_type data_type);
+
 #endif /* CMP_DATA_TYPE_H */
diff --git a/include/cmp_entity.h b/include/cmp_entity.h
index 2d6bf54..a06715f 100644
--- a/include/cmp_entity.h
+++ b/include/cmp_entity.h
@@ -33,34 +33,6 @@
 #include "cmp_support.h"
 
 
-/* Defined Compression Data Product Types */
-enum cmp_ent_data_type {
-	DATA_TYPE_IMAGETTE = 1,
-	DATA_TYPE_IMAGETTE_ADAPTIVE,
-	DATA_TYPE_SAT_IMAGETTE,
-	DATA_TYPE_SAT_IMAGETTE_ADAPTIVE,
-	DATA_TYPE_OFFSET,
-	DATA_TYPE_BACKGROUND,
-	DATA_TYPE_SMEARING,
-	DATA_TYPE_S_FX,
-	DATA_TYPE_S_FX_DFX,
-	DATA_TYPE_S_FX_NCOB,
-	DATA_TYPE_S_FX_DFX_NCOB_ECOB,
-	DATA_TYPE_L_FX,
-	DATA_TYPE_L_FX_DFX,
-	DATA_TYPE_L_FX_NCOB,
-	DATA_TYPE_L_FX_DFX_NCOB_ECOB,
-	DATA_TYPE_F_FX,
-	DATA_TYPE_F_FX_DFX,
-	DATA_TYPE_F_FX_NCOB,
-	DATA_TYPE_F_FX_DFX_NCOB_ECOB,
-	DATA_TYPE_F_CAM_IMAGETTE,
-	DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE,
-	DATA_TYPE_F_CAM_OFFSET,
-	DATA_TYPE_F_CAM_BACKGROUND,
-	DATA_TYPE_UNKOWN = 0x7FFF,
-};
-
 #define GENERIC_HEADER_SIZE 32
 #define SPECIFIC_IMAGETTE_HEADER_SIZE		4
 #define SPECIFIC_IMAGETTE_ADAPTIVE_HEADER_SIZE	12
@@ -155,21 +127,31 @@ compile_time_assert(sizeof(struct cmp_entity) == NON_IMAGETTE_HEADER_SIZE, CMP_E
 
 
 
-/* brief create a compression entity by setting the size of the
- * compression entity and the data product type in the entity header
+/* create a compression entity by setting the size of the compression entity and
+ * the data product type in the entity header
  */
-size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		      uint32_t cmp_size_byte);
+uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type,
+			int raw_mode_flag, uint32_t cmp_size_byte);
 
 /* create a compression entity and set the header fields */
-size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		     uint32_t version_id, uint64_t start_time,
-		     uint64_t end_time, uint16_t model_id, uint8_t model_counter,
-		     struct cmp_info *info, struct cmp_cfg *cfg);
+size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id,
+		     uint64_t start_time, uint64_t end_time, uint16_t model_id,
+		     uint8_t model_counter, struct cmp_cfg *cfg, int cmp_size_bits);
+
+/* read in a compression entity header */
+int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg);
 
-/* read in a imagette compression entity header to a info struct */
-int cmp_ent_read_imagette_header(struct cmp_entity *ent, struct cmp_info *info);
+/* write the compression parameters from a compression configuration into the
+ * compression entity header
+ */
+int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
+			   int cmp_size_bits);
 
+/* write the parameters from the RDCU decompression information structure in the
+ * compression entity header
+ */
+int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *info,
+				const struct cmp_cfg *cfg);
 
 
 /* set functions for generic compression entity header */
@@ -187,8 +169,7 @@ int cmp_ent_set_coarse_end_time(struct cmp_entity *ent, uint32_t coarse_time);
 int cmp_ent_set_fine_end_time(struct cmp_entity *ent, uint16_t fine_time);
 
 int cmp_ent_set_data_type(struct cmp_entity *ent,
-			  enum cmp_ent_data_type data_type);
-int cmp_ent_data_type_valid(enum cmp_ent_data_type data_type);
+			  enum cmp_data_type data_type, int raw_mode);
 int cmp_ent_set_cmp_mode(struct cmp_entity *ent, uint32_t cmp_mode_used);
 int cmp_ent_set_model_value(struct cmp_entity *ent, uint32_t model_value_used);
 int cmp_ent_set_model_id(struct cmp_entity *ent, uint32_t model_id);
@@ -247,7 +228,7 @@ uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent);
 uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent);
 uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent);
 
-enum cmp_ent_data_type cmp_ent_get_data_type(struct cmp_entity *ent);
+enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent);
 int cmp_ent_get_data_type_raw_bit(struct cmp_entity *ent);
 uint8_t cmp_ent_get_cmp_mode(struct cmp_entity *ent);
 uint8_t cmp_ent_get_model_value_used(struct cmp_entity *ent);
@@ -301,7 +282,7 @@ ssize_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf,
 			     size_t data_buf_size);
 
 /* calculate the size of the compression entity header */
-uint32_t cmp_ent_cal_hdr_size(enum cmp_ent_data_type data_type);
+uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode);
 
 
 #if __has_include(<time.h>)
diff --git a/include/cmp_guess.h b/include/cmp_guess.h
index fe2ed09..9d3ac42 100644
--- a/include/cmp_guess.h
+++ b/include/cmp_guess.h
@@ -22,17 +22,23 @@
 
 #include "cmp_support.h"
 
+
+
 #define DEFAULT_GUESS_LEVEL 2
 
-#define CMP_GUESS_DEF_MODE_DIFF		MODE_DIFF_ZERO
-#define CMP_GUESS_DEF_MODE_MODEL	MODE_MODEL_MULTI
+#define CMP_GUESS_DEF_MODE_DIFF		CMP_MODE_DIFF_ZERO
+#define CMP_GUESS_DEF_MODE_MODEL	CMP_MODE_MODEL_MULTI
 
+/* good guess for the spill parameter using the MODE_DIFF_MULTI */
+#define CMP_GOOD_SPILL_DIFF_MULTI 2U
 /* how often the model is updated before it is reset default value */
 #define CMP_GUESS_N_MODEL_UPDATE_DEF	8
 
 uint32_t cmp_guess(struct cmp_cfg *cfg, int level);
 void cmp_guess_set_model_updates(int n_model_updates);
 
+uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode);
+
 uint16_t cmp_guess_model_value(int n_model_updates);
 
 #endif /* CMP_GUESS_H */
diff --git a/include/cmp_icu.h b/include/cmp_icu.h
index cd7f193..81a1160 100644
--- a/include/cmp_icu.h
+++ b/include/cmp_icu.h
@@ -13,7 +13,6 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- *
  * @brief software compression library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  */
@@ -21,13 +20,45 @@
 #ifndef _CMP_ICU_H_
 #define _CMP_ICU_H_
 
-#include "../include/cmp_support.h"
+#include "cmp_support.h"
+
+
+/* return code if the bitstream buffer is too small to store the whole bitstream */
+#define CMP_ERROR_SAMLL_BUF -2
+
+/* return code if the value or the model is bigger than the max_used_bits
+ * parameter allows
+ */
+#define CMP_ERROR_HIGH_VALUE -3
+
+
+/* create and setup a compression configuration */
+struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
+				  uint32_t model_value, uint32_t lossy_par);
+
+size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
+			   uint32_t data_samples, void *model_of_data,
+			   void *updated_model, uint32_t *compressed_data,
+			   uint32_t compressed_data_len_samples);
+
+int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
+			 uint32_t spillover_par);
+
+int cmp_cfg_fx_cob(struct cmp_cfg *cfg,
+		   uint32_t cmp_par_exp_flags, uint32_t spillover_exp_flags,
+		   uint32_t cmp_par_fx, uint32_t spillover_fx,
+		   uint32_t cmp_par_ncob, uint32_t spillover_ncob,
+		   uint32_t cmp_par_efx, uint32_t spillover_efx,
+		   uint32_t cmp_par_ecob, uint32_t spillover_ecob,
+		   uint32_t cmp_par_fx_cob_variance, uint32_t spillover_fx_cob_variance);
 
-int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info);
+int cmp_cfg_aux(struct cmp_cfg *cfg,
+		uint32_t cmp_par_mean, uint32_t spillover_mean,
+		uint32_t cmp_par_variance, uint32_t spillover_variance,
+		uint32_t cmp_par_pixels_error, uint32_t spillover_pixels_error);
 
 
-int cmp_pre_process(struct cmp_cfg *cfg);
-int cmp_map_to_pos(struct cmp_cfg *cfg);
-uint32_t cmp_encode_data(struct cmp_cfg *cfg);
+/* start the compression */
+int icu_compress_data(const struct cmp_cfg *cfg);
 
 #endif /* _CMP_ICU_H_ */
diff --git a/include/cmp_io.h b/include/cmp_io.h
index 39cfe59..f807825 100644
--- a/include/cmp_io.h
+++ b/include/cmp_io.h
@@ -31,8 +31,10 @@ void print_help(const char *program_name);
 int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en);
 int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en);
 
-ssize_t read_file_data(const char *file_name, unsigned int cmp_mode, void *buf,
-		       uint32_t buf_size, int verbose_en);
+ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t buf_size,
+		   int verbose_en);
+ssize_t read_file_data(const char *file_name, enum cmp_data_type data_type,
+		       void *buf, uint32_t buf_size, int verbose_en);
 ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 			     uint32_t ent_size, int verbose_en);
 ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_size,
@@ -42,8 +44,8 @@ uint32_t cmp_tool_gen_version_id(const char *version);
 
 int write_cmp_data_file(const void *buf, uint32_t buf_size, const char
 			*output_prefix, const char *name_extension, int verbose);
-int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
-		    *output_prefix, const char *name_extension, int verbose);
+int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type data_type,
+			     const char *output_prefix, const char *name_extension, int verbose);
 int write_info(const struct cmp_info *info, const char *output_prefix,
 	       int rdcu_cfg);
 int write_cfg(const struct cmp_cfg *cfg, const char *output_prefix, int rdcu_cfg,
diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h
index ee5cffb..14e0af9 100644
--- a/include/cmp_rdcu.h
+++ b/include/cmp_rdcu.h
@@ -21,10 +21,34 @@
 #ifndef _CMP_RDCU_H_
 #define _CMP_RDCU_H_
 
-#include <stdint.h>
-#include "../include/cmp_support.h"
+#include "cmp_support.h"
 
 
+/* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */
+#define SMALL_BUFFER_ERR_BIT	0x00 /* The length for the compressed data buffer is too small */
+#define CMP_MODE_ERR_BIT	0x01 /* The cmp_mode parameter is not set correctly */
+#define MODEL_VALUE_ERR_BIT	0x02 /* The model_value parameter is not set correctly */
+#define CMP_PAR_ERR_BIT		0x03 /* The spill, golomb_par combination is not set correctly */
+#define AP1_CMP_PAR_ERR_BIT	0x04 /* The ap1_spill, ap1_golomb_par combination is not set correctly (only HW compression) */
+#define AP2_CMP_PAR_ERR_BIT	0x05 /* The ap2_spill, ap2_golomb_par combination is not set correctly (only HW compression) */
+#define MB_ERR_BIT		0x06 /* Multi bit error detected by the memory controller (only HW compression) */
+#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_cmp_cfg_is_invalid(const struct cmp_cfg *cfg);
+
 int rdcu_compress_data(const struct cmp_cfg *cfg);
 
 int rdcu_read_cmp_status(struct cmp_status *status);
diff --git a/include/cmp_support.h b/include/cmp_support.h
index cfe4bbd..850f0a7 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -23,97 +23,165 @@
 #include <stddef.h>
 
 
-#define GOLOMB_PAR_EXPOSURE_FLAGS 1
-
-/* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */
-#define SMALL_BUFFER_ERR_BIT	0x00 /* The length for the compressed data buffer is too small */
-#define CMP_MODE_ERR_BIT	0x01 /* The cmp_mode parameter is not set correctly */
-#define MODEL_VALUE_ERR_BIT	0x02 /* The model_value parameter is not set correctly */
-#define CMP_PAR_ERR_BIT		0x03 /* The spill, golomb_par combination is not set correctly */
-#define AP1_CMP_PAR_ERR_BIT	0x04 /* The ap1_spill, ap1_golomb_par combination is not set correctly (only HW compression) */
-#define AP2_CMP_PAR_ERR_BIT	0x05 /* The ap2_spill, ap2_golomb_par combination is not set correctly (only HW compression) */
-#define MB_ERR_BIT		0x06 /* Multi bit error detected by the memory controller (only HW compression) */
-#define SLAVE_BUSY_ERR_BIT	0x07 /* The bus master has received the "slave busy" status (only HW compression) */
-
-#define MODE_RAW 0
-#define MODE_MODEL_ZERO 1
-#define MODE_DIFF_ZERO 2
-#define MODE_MODEL_MULTI 3
-#define MODE_DIFF_MULTI 4
+#define CMP_LOSSLESS	0
+#define CMP_PAR_UNUNSED	0
+
 
 #define MAX_MODEL_VALUE                                                        \
-	16UL /* the maximal model values used in the update equation for the new model */
+	16U /* the maximal model values used in the update equation for the new model */
 
 /* valid compression parameter ranges for RDCU compression according to PLATO-UVIE-PL-UM-0001 */
-#define MAX_RDCU_CMP_MODE	4UL
-#define MIN_RDCU_GOLOMB_PAR	1UL
-#define MAX_RDCU_GOLOMB_PAR	63UL
-#define MIN_RDCU_SPILL		2UL
-#define MAX_RDCU_ROUND		2UL
+#define MAX_RDCU_CMP_MODE	4U
+#define MIN_RDCU_GOLOMB_PAR	1U
+#define MAX_RDCU_GOLOMB_PAR	63U
+#define MIN_RDCU_SPILL		2U
+#define MAX_RDCU_ROUND		2U
 /* for maximum spill value look at get_max_spill function */
 
 /* valid compression parameter ranges for ICU compression */
-#define MIN_ICU_GOLOMB_PAR	1UL
-#define MAX_ICU_GOLOMB_PAR	UINT32_MAX
-#define MIN_ICU_SPILL		2UL
+#define MIN_ICU_GOLOMB_PAR	1U
+#define MAX_ICU_GOLOMB_PAR	0x80000000U
+#define MIN_ICU_SPILL		2U
 /* for maximum spill value look at get_max_spill function */
-#define MAX_ICU_ROUND		3UL
+#define MAX_ICU_ROUND		3U
+#define MAX_STUFF_CMP_PAR	32U
+
+
+/* default imagette RDCU compression parameters for model compression */
+#define CMP_DEF_IMA_MODEL_DATA_TYPE		DATA_TYPE_IMAGETTE
+#define CMP_DEF_IMA_MODEL_CMP_MODE		CMP_MODE_MODEL_MULTI
+#define CMP_DEF_IMA_MODEL_MODEL_VALUE		8
+#define CMP_DEF_IMA_MODEL_LOSSY_PAR		0
+
+#define CMP_DEF_IMA_MODEL_GOLOMB_PAR		4
+#define CMP_DEF_IMA_MODEL_SPILL_PAR		48
+#define CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR	3
+#define CMP_DEF_IMA_MODEL_AP1_SPILL_PAR		35
+#define CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR	5
+#define CMP_DEF_IMA_MODEL_AP2_SPILL_PAR		60
+
+#define CMP_DEF_IMA_MODEL_RDCU_DATA_ADR		0x000000
+#define CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR	0x200000
+#define CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR	0x400000
+#define CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR	0x600000
+
+/* default imagette RDCU compression parameters for 1d-differencing compression */
+#define CMP_DEF_IMA_DIFF_DATA_TYPE		DATA_TYPE_IMAGETTE
+#define CMP_DEF_IMA_DIFF_CMP_MODE		CMP_MODE_DIFF_ZERO
+#define CMP_DEF_IMA_DIFF_MODEL_VALUE		8 /* not needed for 1d-differencing cmp_mode */
+#define CMP_DEF_IMA_DIFF_LOSSY_PAR		0
+
+#define CMP_DEF_IMA_DIFF_GOLOMB_PAR		7
+#define CMP_DEF_IMA_DIFF_SPILL_PAR		60
+#define CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR		6
+#define CMP_DEF_IMA_DIFF_AP1_SPILL_PAR		48
+#define CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR		8
+#define CMP_DEF_IMA_DIFF_AP2_SPILL_PAR		72
+
+#define CMP_DEF_IMA_DIFF_RDCU_DATA_ADR		0x000000
+#define CMP_DEF_IMA_DIFF_RDCU_MODEL_ADR		0x000000 /* not needed for 1d-differencing cmp_mode */
+#define CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR	0x000000 /* not needed for 1d-differencing cmp_mode */
+#define CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR	0x600000
+
+
+/* defined compression data product types */
+enum cmp_data_type {
+	DATA_TYPE_UNKOWN,
+	DATA_TYPE_IMAGETTE,
+	DATA_TYPE_IMAGETTE_ADAPTIVE,
+	DATA_TYPE_SAT_IMAGETTE,
+	DATA_TYPE_SAT_IMAGETTE_ADAPTIVE,
+	DATA_TYPE_OFFSET,
+	DATA_TYPE_BACKGROUND,
+	DATA_TYPE_SMEARING,
+	DATA_TYPE_S_FX,
+	DATA_TYPE_S_FX_DFX,
+	DATA_TYPE_S_FX_NCOB,
+	DATA_TYPE_S_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_L_FX,
+	DATA_TYPE_L_FX_DFX,
+	DATA_TYPE_L_FX_NCOB,
+	DATA_TYPE_L_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_F_FX,
+	DATA_TYPE_F_FX_DFX,
+	DATA_TYPE_F_FX_NCOB,
+	DATA_TYPE_F_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_F_CAM_IMAGETTE,
+	DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE,
+	DATA_TYPE_F_CAM_OFFSET,
+	DATA_TYPE_F_CAM_BACKGROUND,
+};
 
-#define SAM2BYT                                                                \
-	2 /* sample to byte conversion factor; one samples has 16 bits (2 bytes) */
 
-#define CMP_GOOD_SPILL_DIFF_MULTI 2 /* good guess for the spill parameter using the MODE_DIFF_MULTI */
+/* defined compression mode */
+enum cmp_mode {
+	CMP_MODE_RAW,
+	CMP_MODE_MODEL_ZERO,
+	CMP_MODE_DIFF_ZERO,
+	CMP_MODE_MODEL_MULTI,
+	CMP_MODE_DIFF_MULTI,
+	CMP_MODE_STUFF
+};
+
 
 /**
  * @brief The cmp_cfg structure can contain the complete configuration of the HW as
  *      well as the SW compressor.
- * @note when using the 1d-differentiating mode or the raw mode (cmp_error =
- *	0,2,4), the model parameters (model_value, model_buf, rdcu_model_adr,
- *	rdcu_new_model_adr) are ignored
  * @note the icu_output_buf will not be used for HW compression
  * @note the rdcu_***_adr parameters are ignored for SW compression
- * @note semi adaptive compression not supported for SW compression;
- *		configuration parameters ap1\_golomb\_par, ap2\_golomb\_par, ap1\_spill,
- *		ap2\_spill will be ignored;
  */
 
 struct cmp_cfg {
+	void *input_buf;            /* Pointer to the data to compress buffer */
+	void *model_buf;            /* Pointer to the model buffer */
+	void *icu_new_model_buf;    /* Pointer to the updated model buffer (not used for RDCU compression )*/
+	uint32_t *icu_output_buf;   /* Pointer to the compressed data buffer (not used for RDCU compression) */
+	uint32_t samples;           /* Number of samples to compress, length of the data and model buffer
+				     * (including the multi entity header by non-imagette data)
+				     */
+	uint32_t buffer_length;     /* Length of the compressed data buffer in number of samples */
+	uint32_t rdcu_data_adr;     /* RDCU data to compress start address, the first data address in the RDCU SRAM; HW only */
+	uint32_t rdcu_model_adr;    /* RDCU model start address, the first model address in the RDCU SRAM */
+	uint32_t rdcu_new_model_adr;/* RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored */
+	uint32_t rdcu_buffer_adr;   /* RDCU compressed data start address, the first output data address in the RDCU SRAM */
+	enum cmp_data_type data_type; /* Compression Data Product Types */
 	uint32_t cmp_mode;          /* 0: raw mode
 				     * 1: model mode with zero escape symbol mechanism
 				     * 2: 1d differencing mode without input model with zero escape symbol mechanism
 				     * 3: model mode with multi escape symbol mechanism
 				     * 4: 1d differencing mode without input model multi escape symbol mechanism
 				     */
-	uint32_t golomb_par;        /* Golomb parameter for dictionary selection */
-	uint32_t spill;             /* Spillover threshold for encoding outliers */
 	uint32_t model_value;       /* Model weighting parameter */
-	uint32_t round;             /* Number of noise bits to be rounded */
-	uint32_t ap1_golomb_par;    /* Adaptive 1 spillover threshold; HW only */
-	uint32_t ap1_spill;         /* Adaptive 1 Golomb parameter; HW only */
-	uint32_t ap2_golomb_par;    /* Adaptive 2 spillover threshold; HW only */
+	uint32_t round;             /* lossy compression parameter */
+	uint32_t golomb_par;        /* Golomb parameter for imagette data compression */
+	uint32_t spill;             /* Spillover threshold parameter for imagette compression */
+	uint32_t ap1_golomb_par;    /* Adaptive 1 spillover threshold for imagette data; HW only */
+	uint32_t ap1_spill;         /* Adaptive 1 Golomb parameter for imagette data; HW only */
+	uint32_t ap2_golomb_par;    /* Adaptive 2 spillover threshold for imagette data; HW only */
 	uint32_t ap2_spill;         /* Adaptive 2 Golomb parameter; HW only */
-	void *input_buf;            /* Pointer to the data to compress buffer */
-	uint32_t rdcu_data_adr;     /* RDCU data to compress start address, the first data address in the RDCU SRAM; HW only */
-	void *model_buf;            /* Pointer to the model buffer */
-	uint32_t rdcu_model_adr;    /* RDCU model start address, the first model address in the RDCU SRAM */
-	void *icu_new_model_buf;    /* Pointer to the updated model buffer */
-	uint32_t rdcu_new_model_adr;/* RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored*/
-	uint32_t samples;           /* Number of samples (16 bit value) to compress, length of the data and model buffer */
-	uint32_t *icu_output_buf;   /* Pointer to the compressed data buffer (not used for RDCU compression) */
-	uint32_t rdcu_buffer_adr;   /* RDCU compressed data start address, the first output data address in the RDCU SRAM */
-	uint32_t buffer_length;     /* Length of the compressed data buffer in number of samples (16 bit values)*/
+	uint32_t cmp_par_exp_flags; /* Compression parameter for exposure flags compression */
+	uint32_t spill_exp_flags;   /* Spillover threshold parameter for exposure flags compression */
+	uint32_t cmp_par_fx;	    /* Compression parameter for normal flux compression */
+	uint32_t spill_fx;          /* Spillover threshold parameter for normal flux compression */
+	uint32_t cmp_par_ncob;      /* Compression parameter for normal center of brightness compression */
+	uint32_t spill_ncob;        /* Spillover threshold parameter for normal center of brightness compression */
+	uint32_t cmp_par_efx;       /* Compression parameter for extended flux compression */
+	uint32_t spill_efx;         /* Spillover threshold parameter for extended flux compression */
+	uint32_t cmp_par_ecob;      /* Compression parameter for executed center of brightness compression */
+	uint32_t spill_ecob;        /* Spillover threshold parameter for executed center of brightness compression */
+	uint32_t cmp_par_fx_cob_variance; /* Compression parameter for flux/COB variance compression */
+	uint32_t spill_fx_cob_variance; /* Spillover threshold parameter for flux/COB variance compression */
+	uint32_t cmp_par_mean;      /* Compression parameter for auxiliary science mean compression */
+	uint32_t spill_mean;        /* Spillover threshold parameter for auxiliary science mean compression */
+	uint32_t cmp_par_variance;  /* Compression parameter for auxiliary science variance compression */
+	uint32_t spill_variance;    /* Spillover threshold parameter for auxiliary science variance compression */
+	uint32_t cmp_par_pixels_error; /* Compression parameter for auxiliary science outlier pixels number compression */
+	uint32_t spill_pixels_error; /* Spillover threshold parameter for auxiliary science outlier pixels number compression */
 };
 
 
-extern const struct cmp_cfg DEFAULT_CFG_MODEL;
-
-extern const struct cmp_cfg DEFAULT_CFG_DIFF;
-
-
-/**
- * @brief The cmp_status structure can contain the information of the
- *      compressor status register from the RDCU, see RDCU-FRS-FN-0632,
- *      but can also be used for the SW compression.
+/* The cmp_status structure can contain the information of the compressor status
+ * register from the RDCU, see RDCU-FRS-FN-0632.
  */
 
 struct cmp_status {
@@ -125,18 +193,12 @@ struct cmp_status {
 };
 
 
-/**
- * @brief The cmp_info structure can contain the information and metadata of an
- *      executed compression of the HW as well as the SW compressor.
- *
- * @note if SW compression is used the parameters rdcu_model_adr_used, rdcu_cmp_adr_used,
- *      ap1_cmp_size, ap2_cmp_size are not used and are therefore set to zero
+/* The cmp_info structure can contain the information and metadata of an
+ * executed RDCU compression.
  */
 
 struct cmp_info {
 	uint32_t cmp_mode_used;       /* Compression mode used */
-	uint8_t  model_value_used;    /* Model weighting parameter used */
-	uint8_t  round_used;          /* Number of noise bits to be rounded used */
 	uint32_t spill_used;          /* Spillover threshold used */
 	uint32_t golomb_par_used;     /* Golomb parameter used */
 	uint32_t samples_used;        /* Number of samples (16 bit value) to be stored */
@@ -145,6 +207,8 @@ struct cmp_info {
 	uint32_t ap2_cmp_size;        /* Adaptive compressed data size 2; measured in bits */
 	uint32_t rdcu_new_model_adr_used; /* Updated model start  address used */
 	uint32_t rdcu_cmp_adr_used;   /* Compressed data start address */
+	uint8_t  model_value_used;    /* Model weighting parameter used */
+	uint8_t  round_used;          /* Number of noise bits to be rounded used */
 	uint16_t cmp_err;             /* Compressor errors
 				       * [bit 0] small_buffer_err; The length for the compressed data buffer is too small
 				       * [bit 1] cmp_mode_err; The cmp_mode parameter is not set correctly
@@ -155,33 +219,43 @@ struct cmp_info {
 				       * [bit 6] mb_err; Multi bit error detected by the memory controller (only HW compression)
 				       * [bit 7] slave_busy_err; The bus master has received the "slave busy" status (only HW compression)
 				       * [bit 8] slave_blocked_err; The bus master has received the “slave blocked” status (only HW compression)
-				       * [bit 9] invalid address_err; The bus master has received the “invalid address” status (only HW compression) */
+				       * [bit 9] invalid address_err; The bus master has received the “invalid address” status (only HW compression)
+				       */
 };
 
+
 int is_a_pow_of_2(unsigned int v);
 int ilog_2(uint32_t x);
 
-int model_mode_is_used(unsigned int cmp_mode);
-int diff_mode_is_used(unsigned int cmp_mode);
-int raw_mode_is_used(unsigned int cmp_mode);
-int rdcu_supported_mode_is_used(unsigned int cmp_mode);
-int cmp_mode_available(unsigned int cmp_mode);
+unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit);
+
+int cmp_cfg_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg);
+uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type);
+
+int cmp_data_type_valid(enum cmp_data_type data_type);
+int rdcu_supported_data_type_is_used(enum cmp_data_type data_type);
+int cmp_imagette_data_type_is_used(enum cmp_data_type data_type);
+int cmp_ap_imagette_data_type_is_used(enum cmp_data_type data_type);
+int cmp_fx_cob_data_type_is_used(enum cmp_data_type data_type);
+int cmp_aux_data_type_is_used(enum cmp_data_type data_type);
 
-int zero_escape_mech_is_used(unsigned int cmp_mode);
-int multi_escape_mech_is_used(unsigned int cmp_mode);
+int cmp_mode_is_supported(enum cmp_mode cmp_mode);
+int model_mode_is_used(enum cmp_mode cmp_mode);
+int diff_mode_is_used(enum cmp_mode cmp_mode);
+int raw_mode_is_used(enum cmp_mode cmp_mode);
+int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode);
+int zero_escape_mech_is_used(enum cmp_mode cmp_mode);
+int multi_escape_mech_is_used(enum cmp_mode cmp_mode);
 
 unsigned int round_fwd(unsigned int value, unsigned int round);
 unsigned int round_inv(unsigned int value, unsigned int round);
-unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
-			  model_value);
-
-uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode);
-uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode);
-
-size_t size_of_a_sample(unsigned int cmp_mode);
-int cmp_input_size_to_samples(unsigned int size, unsigned int cmp_mode);
-unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit);
-unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode);
+unsigned int cmp_up_model(unsigned int data, unsigned int model,
+			  unsigned int model_value, unsigned int round);
 
 
 void print_cmp_cfg(const struct cmp_cfg *cfg);
diff --git a/include/decmp.h b/include/decmp.h
index 139273f..2f8478c 100644
--- a/include/decmp.h
+++ b/include/decmp.h
@@ -19,13 +19,17 @@
 #ifndef DECMP_H_
 #define DECMP_H_
 
-#include "../include/cmp_support.h"
+#include "cmp_entity.h"
+#include "cmp_support.h"
 
 void *malloc_decompressed_data(const struct cmp_info *info);
 
-int decompress_data(const void *compressed_data, void *de_model_buf,
+int decompress_data(uint32_t *compressed_data, void *de_model_buf,
 		    const struct cmp_info *info, void *decompressed_data);
 
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+			 void *up_model_buf, void *decompressed_data);
+
 double get_compression_ratio(const struct cmp_info *info);
 
 #endif /* DECMP_H_ */
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index cf8c08c..749964d 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -17,770 +17,504 @@
  */
 
 
-#include "../include/cmp_data_types.h"
-#include "../include/cmp_support.h"
-#include "../include/cmp_debug.h"
-#include "../include/byteorder.h"
+#include "cmp_data_types.h"
+#include "cmp_debug.h"
+#include "byteorder.h"
+
+
+/* the maximum length of the different data products types in bits */
+struct cmp_max_used_bits max_used_bits = {
+	0, /* default version */
+	MAX_USED_S_FX_EXPOSURE_FLAGS_BITS, /* s_fx_exp_flags */
+	MAX_USED_S_FX_BITS, /* s_fx */
+	MAX_USED_S_EFX_BITS, /* s_efx */
+	MAX_USED_S_NCOB_BITS, /* s_ncob_x and s_ncob_y */
+	MAX_USED_S_ECOB_BITS, /* s_ecob_x and s_ncob_y */
+	MAX_USED_F_FX_BITS, /* f_fx */
+	MAX_USED_F_EFX_BITS, /* f_efx */
+	MAX_USED_F_NCOB_BITS, /* f_ncob_x and f_ncob_y */
+	MAX_USED_F_ECOB_BITS, /* f_ecob_x and f_ncob_y */
+	MAX_USED_L_FX_EXPOSURE_FLAGS_BITS, /* l_fx_exp_flags */
+	MAX_USED_L_FX_BITS, /* l_fx */
+	MAX_USED_L_FX_VARIANCE_BITS, /* l_fx_variance */
+	MAX_USED_L_EFX_BITS, /* l_efx */
+	MAX_USED_L_NCOB_BITS, /* l_ncob_x and l_ncob_y */
+	MAX_USED_L_ECOB_BITS, /* l_ecob_x and l_ncob_y */
+	MAX_USED_L_COB_VARIANCE_BITS, /* l_cob_x_variance and l_cob_y_variance */
+	MAX_USED_NC_IMAGETTE_BITS, /* nc_imagette */
+	MAX_USED_SATURATED_IMAGETTE_BITS, /* saturated_imagette */
+	MAX_USED_NC_OFFSET_MEAN_BITS, /* nc_offset_mean */
+	MAX_USED_NC_OFFSET_VARIANCE_BITS, /* nc_offset_variance */
+	MAX_USED_NC_BACKGROUND_MEAN_BITS, /* nc_background_mean */
+	MAX_USED_NC_BACKGROUND_VARIANCE_BITS, /* nc_background_variance */
+	MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS, /* nc_background_outlier_pixels */
+	MAX_USED_SMEARING_MEAN_BITS, /* smeating_mean */
+	MAX_USED_SMEARING_VARIANCE_MEAN_BITS, /* smeating_variance_mean */
+	MAX_USED_SMEARING_OUTLIER_PIXELS_BITS, /* smearing_outlier_pixels */
+	MAX_USED_FC_IMAGETTE_BITS, /* fc_imagette */
+	MAX_USED_FC_OFFSET_MEAN_BITS, /* fc_offset_mean */
+	MAX_USED_FC_OFFSET_VARIANCE_BITS, /* fc_offset_variance */
+	MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS, /* fc_offset_pixel_in_error */
+	MAX_USED_FC_BACKGROUND_MEAN_BITS, /* fc_background_mean */
+	MAX_USED_FC_BACKGROUND_VARIANCE_BITS, /* fc_background_variance */
+	MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS /* fc_background_outlier_pixels */
+};
 
 
 /**
- * @brief rounding down the least significant digits of a uint16_t data buffer
+ * @brief sets the maximum length of the different data products types
  *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- *
- * @param  data_buf	uint16_t formatted data buffer
- * @param  samples	the size of the data buffer measured in uint16_t samples
- * @param  round	number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
+ * @param set_max_used_bits	pointer to a structure with the maximum length
+ *				of the different data products types in bits
  */
 
-int lossy_rounding_16(uint16_t *data_buf, unsigned int samples, unsigned int
-		      round)
+void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++)
-		data_buf[i] = round_fwd(data_buf[i], round);  /* this is the lossy step */
-
-	return 0;
+	if (set_max_used_bits)
+		max_used_bits = *set_max_used_bits;
 }
 
 
 /**
- * @brief rounding back the least significant digits of the data buffer
- *
- * @param data_buf	pointer to the data to process
- * @param samples_used	the size of the data and model buffer in 16 bit units
- * @param round_used	used number of bits to round; if zero no rounding takes place
+ * @brief get the maximum length of the different data products types
  *
- * @returns 0 on success, error otherwise
+ * @returns a structure with the used maximum length of the different data
+ *	products types in bits
  */
 
-int de_lossy_rounding_16(uint16_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is necessary */
-	if (round_used == 0)
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		/* check if data are not to big for a overflow */
-		uint16_t mask = (uint16_t)(~0U << (16-round_used));
-		if (data_buf[i] & mask) {
-			debug_print("de_lossy_rounding_16 failed!\n");
-			return -1;
-		}
-		data_buf[i] = round_inv(data_buf[i], round_used);
-	}
-	return 0;
-}
-
-
-static void be_to_cpus_16(uint16_t *a, uint32_t samples)
+struct cmp_max_used_bits cmp_get_max_used_bits(void)
 {
-	size_t i;
-
-	for (i = 0; i < samples; ++i)
-		be16_to_cpus(&a[i]);
+	return max_used_bits;
 }
 
 
 /**
- * @brief rounding down the least significant digits of a uint32_t data buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
+ * @brief calculate the size of a sample for the different compression data type
  *
- * @param  data_buf	a uint32_t formatted data buffer
- * @param  samples	the size of the data buffer measured in uint16_t samples
- * @param  round	number of bits to round; if zero no rounding takes place
+ * @param data_type	compression data_type
  *
- * @returns 0 on success, error otherwise
+ * @returns the size of a data sample in bytes for the selected compression
+ *	data type; zero on unknown data type
  */
 
-int lossy_rounding_32(uint32_t *data_buf, unsigned int samples, unsigned int
-		      round)
+size_t size_of_a_sample(enum cmp_data_type data_type)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++)
-		data_buf[i] = round_fwd(data_buf[i], round);  /* this is the lossy step */
-
-	return 0;
-}
-
-
-int de_lossy_rounding_32(uint32_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is necessary */
-	if (round_used == 0)
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		/* check if data are not to big for a overflow */
-		uint32_t mask = (uint32_t)(~0U << (32-round_used));
-		if (data_buf[i] & mask) {
-			debug_print("de_lossy_rounding_32 failed!\n");
-			return -1;
-		}
-		data_buf[i] = round_inv(data_buf[i], round_used);
+	size_t sample_size = 0;
+
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		sample_size = sizeof(uint16_t);
+		break;
+	case DATA_TYPE_OFFSET:
+		sample_size = sizeof(struct nc_offset);
+		break;
+	case DATA_TYPE_BACKGROUND:
+		sample_size = sizeof(struct nc_background);
+		break;
+	case DATA_TYPE_SMEARING:
+		sample_size = sizeof(struct smearing);
+		break;
+	case DATA_TYPE_S_FX:
+		sample_size = sizeof(struct s_fx);
+		break;
+	case DATA_TYPE_S_FX_DFX:
+		sample_size = sizeof(struct s_fx_efx);
+		break;
+	case DATA_TYPE_S_FX_NCOB:
+		sample_size = sizeof(struct s_fx_ncob);
+		break;
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		sample_size = sizeof(struct s_fx_efx_ncob_ecob);
+		break;
+	case DATA_TYPE_L_FX:
+		sample_size = sizeof(struct l_fx);
+		break;
+	case DATA_TYPE_L_FX_DFX:
+		sample_size = sizeof(struct l_fx_efx);
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		sample_size = sizeof(struct l_fx_ncob);
+		break;
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		sample_size = sizeof(struct l_fx_efx_ncob_ecob);
+		break;
+	case DATA_TYPE_F_FX:
+		sample_size = sizeof(struct f_fx);
+		break;
+	case DATA_TYPE_F_FX_DFX:
+		sample_size = sizeof(struct f_fx_efx);
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		sample_size = sizeof(struct f_fx_ncob);
+		break;
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		sample_size = sizeof(struct f_fx_efx_ncob_ecob);
+		break;
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
+	case DATA_TYPE_UNKOWN:
+	default:
+		debug_print("Error: Compression data type is not supported.\n");
+		break;
 	}
-	return 0;
-}
-
-
-struct S_FX sub_S_FX(struct S_FX a, struct S_FX b)
-{
-	struct S_FX result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-
-	return result;
-}
-
-
-struct S_FX add_S_FX(struct S_FX a, struct S_FX b)
-{
-	struct S_FX result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-
-	return result;
+	return sample_size;
 }
 
 
 /**
- * @brief rounding down the least significant digits of a S_FX data buffer
+ * @brief calculate the need bytes for the data
  *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
+ * @param samples	number of data samples
+ * @param data_type	compression data_type
  *
- * @param  data_buf	a S_FX formatted data buffer
- * @param  samples	the size of the data buffer measured in S_FX samples
- * @param  round	number of bits to round; if zero no rounding takes place
+ * @note for non-imagette data program types the multi entry header size is added
  *
- * @returns 0 on success, error otherwise
+ * @returns the size in bytes to store the data sample
  */
 
-int lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples, unsigned
-			int round)
+unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type)
 {
-	size_t i;
+	unsigned int s = size_of_a_sample(data_type);
 
-	if (!samples)
+	if (!s)
 		return 0;
 
-	if (!data_buf)
-		return -1;
+	s *= samples;
 
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++)
-		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
+	if (!rdcu_supported_data_type_is_used(data_type))
+		s += MULTI_ENTRY_HDR_SIZE;
 
-	return 0;
+	return s;
 }
 
 
-int de_lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples_used,
-			   unsigned int round_used)
-{
-	size_t i;
+/**
+ * @brief calculates the number of samples for a given data size for the
+ *	different compression modes
+ *
+ * @param size		size of the data in bytes
+ * @param data_type	compression data type
+ *
+ * @returns the number samples for the given compression mode; negative on error
+ */
 
-	if (!samples_used)
-		return 0;
+int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type)
+{
+	int samples_size = (int)size_of_a_sample(data_type);
 
-	if (!data_buf)
+	if (!samples_size)
 		return -1;
 
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("Errolr: de_lossy_rounding_S_FX failed\n");
+	if (!rdcu_supported_data_type_is_used(data_type)) {
+		if (size < MULTI_ENTRY_HDR_SIZE)
 			return -1;
-		}
-
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
+		size -= MULTI_ENTRY_HDR_SIZE;
 	}
-	return 0;
-}
-
-
-struct S_FX cal_up_model_S_FX(struct S_FX data_buf, struct S_FX model_buf,
-			      unsigned int model_value)
-{
-	struct S_FX result;
 
-	result.EXPOSURE_FLAGS = (uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-						      model_buf.EXPOSURE_FLAGS,
-						      model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
+	if (size % samples_size)
+		return -1;
 
-	return result;
+	return size/samples_size;
 }
 
 
-void be_to_cpus_S_FX(struct S_FX *a, uint32_t samples)
+static uint32_t be24_to_cpu(uint32_t a)
 {
-	size_t i;
-
-	for (i = 0; i < samples; ++i)
-		a[i].FX = be32_to_cpu(a[i].FX);
+	return be32_to_cpu(a) >> 8;
 }
 
 
-struct S_FX_EFX sub_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
+static void be_to_cpus_16(uint16_t *a, int samples)
 {
-	struct S_FX_EFX result;
+	int i;
 
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-	result.EFX = a.EFX - b.EFX;
-
-	return result;
+	for (i = 0; i < samples; ++i)
+		be16_to_cpus(&a[i]);
 }
 
 
-struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
+static void be_to_cpus_nc_offset(struct nc_offset *a, int samples)
 {
-	struct S_FX_EFX result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-	result.EFX = a.EFX + b.EFX;
+	int i;
 
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].mean = be32_to_cpu(a[i].mean);
+		a[i].variance = be32_to_cpu(a[i].variance);
+	}
 }
 
 
-/**
- * @brief rounding down the least significant digits of a S_FX_EFX data buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
- *
- * @param  data		S_FX_EFX formatted data buffer
- * @param  samples	the size of the data buffer measured in S_FX_EFX samples
- * @param  round	number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples,
-			    unsigned int round)
+static void be_to_cpus_nc_background(struct nc_background *a, int samples)
 {
-	size_t i;
+	int i;
 
-	if (!samples)
-		return 0;
-
-	if (!data)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++) {
-		data[i].FX = round_fwd(data[i].FX, round);
-		data[i].EFX = round_fwd(data[i].EFX, round);
+	for (i = 0; i < samples; ++i) {
+		a[i].mean = be32_to_cpu(a[i].mean);
+		a[i].variance = be32_to_cpu(a[i].variance);
+		a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels);
 	}
-	return 0;
 }
 
 
-int de_lossy_rounding_S_FX_EFX(struct S_FX_EFX *data_buf, unsigned int
-			       samples_used, unsigned int round_used)
+static void be_to_cpus_smearing(struct smearing *a, int samples)
 {
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("de_lossy_rounding_S_FX failed!\n");
-			return -1;
-		}
-		if (data_buf[i].EFX & mask) {
-			debug_print("de_lossy_rounding_S_FX failed!\n");
-			return -1;
-		}
+	int i;
 
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
-		data_buf[i].EFX = round_inv(data_buf[i].EFX, round_used);
+	for (i = 0; i < samples; ++i) {
+		a[i].mean = be32_to_cpu(a[i].mean);
+		a[i].variance_mean = be16_to_cpu(a[i].variance_mean);
+		a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels);
 	}
-	return 0;
 }
 
 
-struct S_FX_EFX cal_up_model_S_FX_EFX(struct S_FX_EFX data_buf, struct S_FX_EFX
-				      model_buf, unsigned int model_value)
+static void be_to_cpus_s_fx(struct s_fx *a, int samples)
 {
-	struct S_FX_EFX result;
+	int i;
 
-	result.EXPOSURE_FLAGS =
-		(uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-				      model_buf.EXPOSURE_FLAGS, model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
-	result.EFX = cal_up_model(data_buf.EFX, model_buf.FX, model_value);
-
-	return result;
+	for (i = 0; i < samples; ++i)
+		a[i].fx = be32_to_cpu(a[i].fx);
 }
 
 
-void be_to_cpus_S_FX_EFX(struct S_FX_EFX *a, uint32_t samples)
+static void be_to_cpus_s_fx_efx(struct s_fx_efx *a, int samples)
 {
-	size_t i;
+	int i;
 
 	for (i = 0; i < samples; ++i) {
-		a[i].FX = be32_to_cpu(a[i].FX);
-		a[i].EFX = be32_to_cpu(a[i].EFX);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].efx = be32_to_cpu(a[i].efx);
 	}
 }
 
 
-struct S_FX_NCOB sub_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b)
+static void be_to_cpus_s_fx_ncob(struct s_fx_ncob *a, int samples)
 {
-	struct S_FX_NCOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-	result.NCOB_X = a.NCOB_X - b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y - b.NCOB_Y;
-
-	return result;
-}
-
+	int i;
 
-struct S_FX_NCOB add_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b)
-{
-	struct S_FX_NCOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-	result.NCOB_X = a.NCOB_X + b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y + b.NCOB_Y;
-
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+	}
 }
 
 
-/**
- * @brief rounding down the least significant digits of a S_FX_NCOB data buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
- *
- * @param  data_buf	a S_FX_NCOB formatted data buffer
- * @param  samples	the size of the data buffer measured in S_FX_NCOB samples
- * @param  round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
-			     unsigned int round)
+static void be_to_cpus_s_fx_efx_ncob_ecob(struct s_fx_efx_ncob_ecob *a, int samples)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
+	int i;
 
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++) {
-		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
-		data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
-		data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].ecob_x = be32_to_cpu(a[i].ecob_x);
+		a[i].ecob_y = be32_to_cpu(a[i].ecob_y);
 	}
-	return 0;
 }
 
 
-int de_lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int
-				samples_used, unsigned int round_used)
+static void be_to_cpus_l_fx(struct l_fx *a, int samples)
 {
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("de_lossy_rounding_S_FX_NCOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_X & mask) {
-			debug_print("de_lossy_rounding_S_FX_NCOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_Y & mask) {
-			debug_print("de_lossy_rounding_S_FX_NCOB failed!\n");
-			return -1;
-		}
+	int i;
 
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
-		data_buf[i].NCOB_X = round_inv(data_buf[i].NCOB_X, round_used);
-		data_buf[i].NCOB_Y = round_inv(data_buf[i].NCOB_Y, round_used);
+	for (i = 0; i < samples; ++i) {
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
 	}
-	return 0;
 }
 
 
-struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf, struct S_FX_NCOB
-					model_buf, unsigned int model_value)
+static void be_to_cpus_l_fx_efx(struct l_fx_efx *a, int samples)
 {
-	struct S_FX_NCOB result;
+	int i;
 
-	result.EXPOSURE_FLAGS =
-		(uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-				      model_buf.EXPOSURE_FLAGS, model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
-	result.NCOB_X = cal_up_model(data_buf.NCOB_X, model_buf.NCOB_X, model_value);
-	result.NCOB_Y = cal_up_model(data_buf.NCOB_Y, model_buf.NCOB_Y, model_value);
-
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
+	}
 }
 
 
-void be_to_cpus_S_FX_NCOB(struct S_FX_NCOB *a, uint32_t samples)
+static void be_to_cpus_l_fx_ncob(struct l_fx_ncob *a, int samples)
 {
-	size_t i;
+	int i;
 
 	for (i = 0; i < samples; ++i) {
-		a[i].FX = be32_to_cpu(a[i].FX);
-		a[i].NCOB_X = be32_to_cpu(a[i].NCOB_X);
-		a[i].NCOB_Y = be32_to_cpu(a[i].NCOB_Y);
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
+		a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance);
+		a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance);
 	}
 }
 
 
-struct S_FX_EFX_NCOB_ECOB sub_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b)
+static void be_to_cpus_l_fx_efx_ncob_ecob(struct l_fx_efx_ncob_ecob *a, int samples)
 {
-	struct S_FX_EFX_NCOB_ECOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-	result.NCOB_X = a.NCOB_X - b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y - b.NCOB_Y;
-	result.EFX = a.EFX - b.EFX;
-	result.ECOB_X = a.ECOB_X - b.ECOB_X;
-	result.ECOB_Y = a.ECOB_Y - b.ECOB_Y;
+	int i;
 
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].ecob_x = be32_to_cpu(a[i].ecob_x);
+		a[i].ecob_y = be32_to_cpu(a[i].ecob_y);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
+		a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance);
+		a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance);
+	}
 }
 
 
-struct S_FX_EFX_NCOB_ECOB add_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b)
+static void be_to_cpus_f_fx(struct f_fx *a, int samples)
 {
-	struct S_FX_EFX_NCOB_ECOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-	result.NCOB_X = a.NCOB_X + b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y + b.NCOB_Y;
-	result.EFX = a.EFX + b.EFX;
-	result.ECOB_X = a.ECOB_X + b.ECOB_X;
-	result.ECOB_Y = a.ECOB_Y + b.ECOB_Y;
+	int i;
 
-	return result;
+	for (i = 0; i < samples; ++i)
+		a[i].fx = be32_to_cpu(a[i].fx);
 }
 
 
-/**
- * @brief rounding down the least significant digits of a S_FX_EFX_NCOB_ECOB data
- *	buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
- *
- * @param  data_buf	a S_FX_EFX_NCOB_ECOB formatted data buffer
- * @param  samples	the size of the data buffer measured in
- *	S_FX_EFX_NCOB_ECOB samples
- * @param  round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-				      unsigned int samples, unsigned int round)
+static void be_to_cpus_f_fx_efx(struct f_fx_efx *a, int samples)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
+	int i;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
-		data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
-		data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
-		data_buf[i].EFX = round_fwd(data_buf[i].EFX, round);
-		data_buf[i].ECOB_X = round_fwd(data_buf[i].ECOB_X, round);
-		data_buf[i].ECOB_Y = round_fwd(data_buf[i].ECOB_Y, round);
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].efx = be32_to_cpu(a[i].efx);
 	}
-	return 0;
 }
 
 
-int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					 unsigned int samples_used,
-					 unsigned int round_used)
+static void be_to_cpus_f_fx_ncob(struct f_fx_ncob *a, int samples)
 {
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
+	int i;
 
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_X & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_Y & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].EFX & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].ECOB_X & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].ECOB_Y & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
-		data_buf[i].NCOB_X = round_inv(data_buf[i].NCOB_X, round_used);
-		data_buf[i].NCOB_Y = round_inv(data_buf[i].NCOB_Y, round_used);
-		data_buf[i].EFX = round_inv(data_buf[i].EFX, round_used);
-		data_buf[i].ECOB_X = round_inv(data_buf[i].ECOB_X, round_used);
-		data_buf[i].ECOB_Y = round_inv(data_buf[i].ECOB_Y, round_used);
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
 	}
-	return 0;
-}
-
-
-struct S_FX_EFX_NCOB_ECOB cal_up_model_S_FX_EFX_NCOB_ECOB
-	(struct S_FX_EFX_NCOB_ECOB data_buf, struct S_FX_EFX_NCOB_ECOB
-	 model_buf, unsigned int model_value)
-{
-	struct S_FX_EFX_NCOB_ECOB result;
-
-	result.EXPOSURE_FLAGS =
-		(uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-				      model_buf.EXPOSURE_FLAGS, model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
-	result.NCOB_X = cal_up_model(data_buf.NCOB_X, model_buf.NCOB_X, model_value);
-	result.NCOB_Y = cal_up_model(data_buf.NCOB_Y, model_buf.NCOB_Y, model_value);
-	result.EFX = cal_up_model(data_buf.EFX, model_buf.EFX, model_value);
-	result.ECOB_X = cal_up_model(data_buf.ECOB_X, model_buf.ECOB_X, model_value);
-	result.ECOB_Y = cal_up_model(data_buf.ECOB_Y, model_buf.ECOB_Y, model_value);
-
-	return result;
 }
 
 
-void be_to_cpus_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *a, uint32_t samples)
+static void be_to_cpus_f_fx_efx_ncob_ecob(struct f_fx_efx_ncob_ecob *a, int samples)
 {
-	size_t i;
+	int i;
 
 	for (i = 0; i < samples; ++i) {
-		a[i].FX = be32_to_cpu(a[i].FX);
-		a[i].NCOB_X = be32_to_cpu(a[i].NCOB_X);
-		a[i].NCOB_Y = be32_to_cpu(a[i].NCOB_Y);
-		a[i].EFX = be32_to_cpu(a[i].EFX);
-		a[i].ECOB_X = be32_to_cpu(a[i].ECOB_X);
-		a[i].ECOB_Y = be32_to_cpu(a[i].ECOB_Y);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].ecob_x = be32_to_cpu(a[i].ecob_x);
+		a[i].ecob_y = be32_to_cpu(a[i].ecob_y);
 	}
 }
 
 
 /**
- * @brief swap the endianness of science products form big endian to the cpu
- *	endianness in place
+ * @brief swap the endianness of uncompressed data form big endian to the cpu
+ *	endianness (or the other way around) in place
  *
- * @param  data		pointer to a data sample
- * @param  cmp_mode	compression mode
+ * @param data			pointer to a data sample
+ * @param data_size_byte	size of the data in bytes
+ * @param data_type		compression data type
+ *
+ * @returns 0 on success; non-zero on failure
  */
 
-void cmp_input_big_to_cpu_endiannessy(void *data, u_int32_t data_size_byte,
-				      uint32_t cmp_mode)
+int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
+				    enum cmp_data_type data_type)
 {
-	int samples = cmp_input_size_to_samples(data_size_byte, cmp_mode);
+	int samples = cmp_input_size_to_samples(data_size_byte, data_type);
 
-	if (!data)
-		return;
+	if (!data) /* nothing to do */
+		return 0;
 
 	if (samples < 0) {
 		debug_print("Error: Can not convert data size in samples.\n");
-		return;
+		return -1;
 	}
 
-	if (!rdcu_supported_mode_is_used(cmp_mode))
-		data = (uint8_t *)data + N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
-
-	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
+	/* we do not convert the endianness of the multi entry header */
+	if (!rdcu_supported_data_type_is_used(data_type))
+		data = (uint8_t *)data + MULTI_ENTRY_HDR_SIZE;
+
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		be_to_cpus_16(data, samples);
 		break;
-	case MODE_RAW_S_FX:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		be_to_cpus_S_FX(data, samples);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		be_to_cpus_S_FX_EFX(data, samples);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		be_to_cpus_S_FX_EFX_NCOB_ECOB(data, samples);
-		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		/* be_to_cpus_F_FX(data, samples); */
-		/* break; */
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-		/* be_to_cpus_F_FX_EFX(data, samples); */
-		/* break; */
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-		/* be_to_cpus_F_FX_NCOB(data, samples); */
-		/* break; */
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-		/* be_to_cpus_F_FX_EFX_NCOB_ECOB(data, samples); */
-		/* break; */
-	case MODE_RAW_32:
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-		/* be32_to_cpus(data); */
-		/* break; */
-	default:
-		debug_print("Error: Compression mode not supported.\n");
+	case DATA_TYPE_OFFSET:
+		be_to_cpus_nc_offset(data, samples);
+		break;
+	case DATA_TYPE_BACKGROUND:
+		be_to_cpus_nc_background(data, samples);
+		break;
+	case DATA_TYPE_SMEARING:
+		be_to_cpus_smearing(data, samples);
+		break;
+	case DATA_TYPE_S_FX:
+		be_to_cpus_s_fx(data, samples);
+		break;
+	case DATA_TYPE_S_FX_DFX:
+		be_to_cpus_s_fx_efx(data, samples);
 		break;
+	case DATA_TYPE_S_FX_NCOB:
+		be_to_cpus_s_fx_ncob(data, samples);
+		break;
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		be_to_cpus_s_fx_efx_ncob_ecob(data, samples);
+		break;
+	case DATA_TYPE_L_FX:
+		be_to_cpus_l_fx(data, samples);
+		break;
+	case DATA_TYPE_L_FX_DFX:
+		be_to_cpus_l_fx_efx(data, samples);
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		be_to_cpus_l_fx_ncob(data, samples);
+		break;
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		be_to_cpus_l_fx_efx_ncob_ecob(data, samples);
+		break;
+	case DATA_TYPE_F_FX:
+		be_to_cpus_f_fx(data, samples);
+		break;
+	case DATA_TYPE_F_FX_DFX:
+		be_to_cpus_f_fx_efx(data, samples);
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		be_to_cpus_f_fx_ncob(data, samples);
+		break;
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		be_to_cpus_f_fx_efx_ncob_ecob(data, samples);
+		break;
+	/* TODO: implement F_CAM conversion */
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
+	case DATA_TYPE_UNKOWN:
+	default:
+		debug_print("Error: Can not swap endianness for this compression data type.\n");
+		return -1;
 	}
+
+	return 0;
 }
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index 99aa3bd..d058b17 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -17,24 +17,30 @@
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  */
 
+
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
 #include <limits.h>
-#if __has_include(<time.h>)
-	#include <time.h>
-	#include <stdlib.h>
+#if defined __has_include
+#  if __has_include(<time.h>)
+#    include <time.h>
+#    include <stdlib.h>
+#    define HAS_TIME_H 1
+#  endif
 #endif
 
-#include "../include/cmp_entity.h"
-#include "../include/cmp_support.h"
-#include "../include/byteorder.h"
+#include "byteorder.h"
+#include "cmp_debug.h"
+#include "cmp_support.h"
+#include "cmp_data_types.h"
+#include "cmp_entity.h"
 
 
-#if __has_include(<time.h>)
+#ifdef HAS_TIME_H
 /* Used as epoch Wed Jan  1 00:00:00 2020 */
 #  if defined(_WIN32) || defined(_WIN64)
-const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0, };
+const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0 };
 #  else
 const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0, 0, NULL };
 #  endif /* _WIN */
@@ -42,69 +48,61 @@ const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0, 0, NULL };
 
 
 /**
- * @brief calculate the size of the compression entity header based of the data
+ * @brief calculate the size of the compression entity header based on the data
  *	product type
  *
  * @param data_type	compression entity data product type
+ * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
  *
  * @returns size of the compression entity header in bytes, 0 on unknown data
  *	type
  */
 
-uint32_t cmp_ent_cal_hdr_size(enum cmp_ent_data_type data_type)
-{
-	switch (data_type) {
-	case DATA_TYPE_IMAGETTE:
-	case DATA_TYPE_F_CAM_IMAGETTE:
-		return IMAGETTE_HEADER_SIZE;
-	case DATA_TYPE_IMAGETTE_ADAPTIVE:
-	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
-		return IMAGETTE_ADAPTIVE_HEADER_SIZE;
-	case DATA_TYPE_SAT_IMAGETTE:
-	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
-	case DATA_TYPE_OFFSET:
-	case DATA_TYPE_BACKGROUND:
-	case DATA_TYPE_SMEARING:
-	case DATA_TYPE_S_FX:
-	case DATA_TYPE_S_FX_DFX:
-	case DATA_TYPE_S_FX_NCOB:
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
-	case DATA_TYPE_L_FX:
-	case DATA_TYPE_L_FX_DFX:
-	case DATA_TYPE_L_FX_NCOB:
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
-	case DATA_TYPE_F_FX:
-	case DATA_TYPE_F_FX_DFX:
-	case DATA_TYPE_F_FX_NCOB:
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
-	case DATA_TYPE_F_CAM_OFFSET:
-	case DATA_TYPE_F_CAM_BACKGROUND:
-		return NON_IMAGETTE_HEADER_SIZE;
-	case DATA_TYPE_UNKOWN:
-		return 0;
+uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode_flag)
+{
+	uint32_t size = 0;
+
+	if (raw_mode_flag) {
+		if (cmp_data_type_valid(data_type))
+			/* for raw data we do not need a specific header */
+			size = GENERIC_HEADER_SIZE;
+	} else {
+		switch (data_type) {
+		case DATA_TYPE_IMAGETTE:
+		case DATA_TYPE_SAT_IMAGETTE:
+		case DATA_TYPE_F_CAM_IMAGETTE:
+			size = IMAGETTE_HEADER_SIZE;
+			break;
+		case DATA_TYPE_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+			size = IMAGETTE_ADAPTIVE_HEADER_SIZE;
+			break;
+		case DATA_TYPE_OFFSET:
+		case DATA_TYPE_BACKGROUND:
+		case DATA_TYPE_SMEARING:
+		case DATA_TYPE_S_FX:
+		case DATA_TYPE_S_FX_DFX:
+		case DATA_TYPE_S_FX_NCOB:
+		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_L_FX:
+		case DATA_TYPE_L_FX_DFX:
+		case DATA_TYPE_L_FX_NCOB:
+		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_FX:
+		case DATA_TYPE_F_FX_DFX:
+		case DATA_TYPE_F_FX_NCOB:
+		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_CAM_OFFSET:
+		case DATA_TYPE_F_CAM_BACKGROUND:
+			size = NON_IMAGETTE_HEADER_SIZE;
+			break;
+		case DATA_TYPE_UNKOWN:
+			size = 0;
+			break;
+		}
 	}
-
-	if ((data_type >> RAW_BIT_DATA_TYPE_POS) & 1U)
-		return GENERIC_HEADER_SIZE;
-
-	return 0;
-}
-
-
-/**
- * @brief check if the compression entity data product type is supported
- *
- * @param data_type	compression entity data product type to check
- *
- * @returns zero if data_type is invalid; non-zero if data_type is valid
- */
-
-int cmp_ent_data_type_valid(enum cmp_ent_data_type data_type)
-{
-	if (cmp_ent_cal_hdr_size(data_type))
-		return 1;
-	else
-		return 0;
+	return size;
 }
 
 
@@ -326,19 +324,23 @@ int cmp_ent_set_fine_end_time(struct cmp_entity *ent, uint16_t fine_time)
 /**
  * @brief set the data product type in the compression entity header
  *
- * @param ent		pointer to a compression entity (including the
- *	uncompressed data bit)
+ * @param ent		pointer to a compression entity
  * @param data_type	compression entity data product type
+ * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
  *
  * @returns 0 on success, otherwise error
  */
 
 int cmp_ent_set_data_type(struct cmp_entity *ent,
-			  enum cmp_ent_data_type data_type)
+			  enum cmp_data_type data_type,
+			  int raw_mode_flag)
 {
 	if (!ent)
 		return -1;
 
+	if (raw_mode_flag)
+		data_type |= 1U << RAW_BIT_DATA_TYPE_POS;
+
 	if (data_type > UINT16_MAX)
 		return -1;
 
@@ -932,7 +934,7 @@ int cmp_ent_set_non_ima_cmp_par6(struct cmp_entity *ent, uint32_t cmp_par_6_used
 
 
 /**
- * @brief get the ASW version identifier form the compression entity header
+ * @brief get the ASW version identifier from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -949,7 +951,7 @@ uint32_t cmp_ent_get_version_id(struct cmp_entity *ent)
 
 
 /**
- * @brief get the size of the compression entity form the compression entity header
+ * @brief get the size of the compression entity from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -970,7 +972,7 @@ uint32_t cmp_ent_get_size(struct cmp_entity *ent)
 
 
 /**
- * @brief get the original data size form the compression entity header
+ * @brief get the original data size from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -991,7 +993,7 @@ uint32_t cmp_ent_get_original_size(struct cmp_entity *ent)
 
 
 /**
- * @brief get the compression start timestamp form the compression entity header
+ * @brief get the compression start timestamp from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1012,7 +1014,7 @@ uint64_t cmp_ent_get_start_timestamp(struct cmp_entity *ent)
 
 
 /**
- * @brief get the coarse time form the compression start timestamp in the
+ * @brief get the coarse time from the compression start timestamp in the
  *	compression entity header
  *
  * @returns the coarse part of the compression start timestamp on success, 0 on
@@ -1029,7 +1031,7 @@ uint32_t cmp_ent_get_coarse_start_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get the fine time form the compression start timestamp in the
+ * @brief get the fine time from the compression start timestamp in the
  *	compression entity header
  *
  * @returns the fine part of the compression start timestamp on success, 0 on
@@ -1046,7 +1048,7 @@ uint16_t cmp_ent_get_fine_start_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get the compression end timestamp form the compression entity header
+ * @brief get the compression end timestamp from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1067,7 +1069,7 @@ uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent)
 
 
 /**
- * @brief get the coarse time form the compression end timestamp in the
+ * @brief get the coarse time from the compression end timestamp in the
  *	compression entity header
  *
  * @returns the coarse part of the compression end timestamp on success, 0 on
@@ -1084,7 +1086,7 @@ uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get the fine time form the compression end timestamp in the
+ * @brief get the fine time from the compression end timestamp in the
  *	compression entity header
  *
  * @returns the fine part of the compression end timestamp on success, 0 on
@@ -1101,30 +1103,33 @@ uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get data_type form the compression entity header
+ * @brief get data_type from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
- * @returns the data_type (including the uncompressed data bit) on success,
+ * @returns the data_type NOT including the uncompressed data bit on success,
  *	DATA_TYPE_UNKOWN on error
  */
 
-enum cmp_ent_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
+enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
 {
+	enum cmp_data_type data_type;
+
 	if (!ent)
 		return DATA_TYPE_UNKOWN;
 
-	enum cmp_ent_data_type data_type = be16_to_cpu(ent->data_type);
+	data_type = be16_to_cpu(ent->data_type);
+	data_type &= (1U << RAW_BIT_DATA_TYPE_POS)-1; /* remove uncompressed data flag */
 
-	if (cmp_ent_data_type_valid(data_type))
-		return data_type;
-	else
-		return DATA_TYPE_UNKOWN;
+	if (!cmp_data_type_valid(data_type))
+		data_type = DATA_TYPE_UNKOWN;
+
+	return data_type;
 }
 
 
 /**
- * @brief get raw bit form the data_type field of the compression entity header
+ * @brief get the raw bit from the data_type field of the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1176,7 +1181,7 @@ uint8_t cmp_ent_get_model_value_used(struct cmp_entity *ent)
 
 
 /**
- * @brief get model id form the compression entity header
+ * @brief get model id from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1210,7 +1215,7 @@ uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used lossy compression parameter form the compression entity header
+ * @brief get the used lossy compression parameter from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1227,7 +1232,7 @@ uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold parameter form the (adaptive)
+ * @brief get the used spillover threshold parameter from the (adaptive)
  *	imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1245,7 +1250,7 @@ uint16_t cmp_ent_get_ima_spill(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used Golomb parameter form the (adaptive) imagette specific
+ * @brief get the used Golomb parameter from the (adaptive) imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1263,7 +1268,7 @@ uint8_t cmp_ent_get_ima_golomb_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 1 spillover threshold parameter form the
+ * @brief get the used adaptive 1 spillover threshold parameter from the
  *	adaptive imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1281,7 +1286,7 @@ uint16_t cmp_ent_get_ima_ap1_spill(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 1 Golomb parameter form adaptive imagette
+ * @brief get the used adaptive 1 Golomb parameter from adaptive imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1299,7 +1304,7 @@ uint8_t cmp_ent_get_ima_ap1_golomb_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 2 spillover threshold parameter form the
+ * @brief get the used adaptive 2 spillover threshold parameter from the
  *	adaptive imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1317,7 +1322,7 @@ uint16_t cmp_ent_get_ima_ap2_spill(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 2 spillover threshold parameter form the
+ * @brief get the used adaptive 2 spillover threshold parameter from the
  *	adaptive imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1335,7 +1340,7 @@ uint8_t cmp_ent_get_ima_ap2_golomb_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 1 parameter form the non-imagette
+ * @brief get the used spillover threshold 1 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1357,7 +1362,7 @@ uint32_t cmp_ent_get_non_ima_spill1(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 1 form the non-imagette specific
+ * @brief get the used compression parameter 1 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1375,7 +1380,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par1(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 2 parameter form the non-imagette
+ * @brief get the used spillover threshold 2 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1397,7 +1402,7 @@ uint32_t cmp_ent_get_non_ima_spill2(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 2 form the non-imagette specific
+ * @brief get the used compression parameter 2 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1415,7 +1420,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par2(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 3 parameter form the non-imagette
+ * @brief get the used spillover threshold 3 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1437,7 +1442,7 @@ uint32_t cmp_ent_get_non_ima_spill3(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 3 form the non-imagette specific
+ * @brief get the used compression parameter 3 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1455,7 +1460,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par3(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 4 parameter form the non-imagette
+ * @brief get the used spillover threshold 4 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1477,7 +1482,7 @@ uint32_t cmp_ent_get_non_ima_spill4(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 4 form the non-imagette specific
+ * @brief get the used compression parameter 4 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1495,7 +1500,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par4(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 5 parameter form the non-imagette
+ * @brief get the used spillover threshold 5 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1517,7 +1522,7 @@ uint32_t cmp_ent_get_non_ima_spill5(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 5 form the non-imagette specific
+ * @brief get the used compression parameter 5 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1535,7 +1540,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par5(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 6 parameter form the non-imagette
+ * @brief get the used spillover threshold 6 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1557,7 +1562,7 @@ uint32_t cmp_ent_get_non_ima_spill6(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 6 form the non-imagette specific
+ * @brief get the used compression parameter 6 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1588,7 +1593,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par6(struct cmp_entity *ent)
 
 void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 {
-	enum cmp_ent_data_type data_type;
+	enum cmp_data_type data_type;
 
 	if (!ent)
 		return NULL;
@@ -1634,7 +1639,7 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 
 
 /**
- * @brief copy the data form a compression entity to a buffer
+ * @brief copy the data from a compression entity to a buffer
  *
  * @param ent		pointer to the compression entity containing the compressed data
  * @param data_buf	pointer where the destination data buffer where the
@@ -1699,7 +1704,8 @@ ssize_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf,
 
 static uint32_t cmp_ent_get_hdr_size(struct cmp_entity *ent)
 {
-	return cmp_ent_cal_hdr_size(cmp_ent_get_data_type(ent));
+	return cmp_ent_cal_hdr_size(cmp_ent_get_data_type(ent),
+				    cmp_ent_get_data_type_raw_bit(ent));
 }
 
 
@@ -1727,108 +1733,67 @@ uint32_t cmp_ent_get_cmp_data_size(struct cmp_entity *ent)
 
 
 /**
- * @brief set the parameters in the non-imagette specific compression
- *	entity header
+ * @brief write the compression parameters from a compression configuration
+ *	into the compression entity header
+ * @note no compressed data are put into the entity and no change of the entity
+ *	size
  *
- * @param ent	pointer to a compression entity
- * @param info	decompression information structure
- *
- * @returns 0 on success, otherwise error
+ * @param ent		pointer to a compression entity
+ * @param cfg		pointer to a compression configuration
+ * @param cmp_size_bits	size of the compressed data in bits
  *
- * @warning this functions is not implemented jet
+ * @returns 0 on success, negative on error
  */
 
-static int cmp_ent_write_non_ima_parameters(struct cmp_entity *ent, struct cmp_info *info)
+int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
+			   int cmp_size_bits)
 {
-	if (!info)
-		return -1;
-	(void)ent;
-
-	printf("not implemented jet!\n");
-	return -1;
-#if 0
-	if (cmp_ent_set_non_ima_spill1(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par1(ent, info->))
-		return -1;
-
-	if (cmp_ent_set_non_ima_spill2(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par2(ent, info->))
-		return -1;
-
-	if (cmp_ent_set_non_ima_spill3(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par3(ent, info->))
-		return -1;
-
-	if (cmp_ent_set_non_ima_spill4(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par4(ent, info->))
-		return -1;
+	uint32_t ent_cmp_data_size;
 
-	if (cmp_ent_set_non_ima_spill5(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par5(ent, info->))
+	if (!cfg)
 		return -1;
 
-	if (cmp_ent_set_non_ima_spill6(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par6(ent, info->))
+	if (cmp_size_bits < 0)
 		return -1;
-	return 0;
-#endif
-}
-
 
-/**
- * @brief write the compression parameters in the entity header based on the data
- *	product type set in the entity and the provided decompression information
- *	struct
- *
- * @param ent	pointer to a compression entity
- * @param info	decompression information structure
- * @param cfg	compression configuration structure for adaptive compression
- *	parameters (can be NULL)
- *
- * @returns 0 on success, negative on error
- */
-
-static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
-				struct cmp_cfg *cfg)
-{
-	uint32_t ent_cmp_data_size;
-
-	if (!info)
+	if (cfg->data_type != cmp_ent_get_data_type(ent)) {
+		debug_print("Error: The entity data product type dos not match the configuration data product type.\n");
 		return -1;
+	}
 
 	ent_cmp_data_size = cmp_ent_get_cmp_data_size(ent);
 
 	/* check if the entity can hold the compressed data */
-	if (ent_cmp_data_size < cmp_bit_to_4byte(info->cmp_size))
+	if (ent_cmp_data_size < cmp_bit_to_4byte((unsigned int)cmp_size_bits)) {
+		debug_print("Error: The entity size is to small to hold the compressed data.\n");
 		return -2;
+	}
 
 	/* set compression parameter fields in the generic entity header */
-	if (cmp_ent_set_original_size(ent, cmp_cal_size_of_data(info->samples_used,
-								info->cmp_mode_used)))
+	if (cmp_ent_set_original_size(ent, cmp_cal_size_of_data(cfg->samples,
+								cfg->data_type)))
 		return -1;
-	if (cmp_ent_set_cmp_mode(ent, info->cmp_mode_used))
+	if (cmp_ent_set_cmp_mode(ent, cfg->cmp_mode))
 		return -1;
-	if (cmp_ent_set_model_value(ent, info->model_value_used))
+	if (cmp_ent_set_model_value(ent, cfg->model_value))
 		return -1;
-	if (cmp_ent_set_lossy_cmp_par(ent, info->round_used))
+	if (cmp_ent_set_lossy_cmp_par(ent, cfg->round))
 		return -1;
 
-	if (cmp_ent_get_data_type_raw_bit(ent))
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
+		/* check the raw data bit */
+		if (!cmp_ent_get_data_type_raw_bit(ent)) {
+			debug_print("Error: The entity's raw data bit is not set, but the configuration contains raw data.\n");
+			return -1;
+		}
 		/* no specific header is used for raw data we are done */
 		return 0;
+	}
 
 	switch (cmp_ent_get_data_type(ent)) {
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
-		if (!cfg)
-			return -1;
 		if (cmp_ent_set_ima_ap1_spill(ent, cfg->ap1_spill))
 			return -1;
 		if (cmp_ent_set_ima_ap1_golomb_par(ent, cfg->ap1_golomb_par))
@@ -1841,14 +1806,44 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
 	case DATA_TYPE_IMAGETTE:
 	case DATA_TYPE_SAT_IMAGETTE:
 	case DATA_TYPE_F_CAM_IMAGETTE:
-		if (cmp_ent_set_ima_spill(ent, info->spill_used))
+		if (cmp_ent_set_ima_spill(ent, cfg->spill))
 			return -1;
-		if (cmp_ent_set_ima_golomb_par(ent, info->golomb_par_used))
+		if (cmp_ent_set_ima_golomb_par(ent, cfg->golomb_par))
 			return -1;
 		break;
 	case DATA_TYPE_OFFSET:
 	case DATA_TYPE_BACKGROUND:
 	case DATA_TYPE_SMEARING:
+		if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_mean))
+			return -1;
+		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_mean))
+			return -1;
+
+		if (cmp_ent_set_non_ima_spill2(ent, cfg->cmp_par_variance))
+			return -1;
+		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->spill_variance))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_pixels_error))
+			return -1;
+		if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_pixels_error))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par4(ent, 0))
+			return -1;
+		if (cmp_ent_set_non_ima_spill4(ent, 0))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par5(ent, 0))
+			return -1;
+		if (cmp_ent_set_non_ima_spill5(ent, 0))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par6(ent, 0))
+			return -1;
+		if (cmp_ent_set_non_ima_spill6(ent, 0))
+			return -1;
+		break;
 	case DATA_TYPE_S_FX:
 	case DATA_TYPE_S_FX_DFX:
 	case DATA_TYPE_S_FX_NCOB:
@@ -1861,12 +1856,43 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
 	case DATA_TYPE_F_FX_DFX:
 	case DATA_TYPE_F_FX_NCOB:
 	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_exp_flags))
+			return -1;
+		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_exp_flags))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_fx))
+			return -1;
+		if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_fx))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_ncob))
+			return -1;
+		if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_ncob))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par4(ent, cfg->cmp_par_efx))
+			return -1;
+		if (cmp_ent_set_non_ima_spill4(ent, cfg->spill_efx))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par5(ent, cfg->cmp_par_ecob))
+			return -1;
+		if (cmp_ent_set_non_ima_spill5(ent, cfg->spill_ecob))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par6(ent, cfg->cmp_par_fx_cob_variance))
+			return -1;
+		if (cmp_ent_set_non_ima_spill6(ent, cfg->spill_fx_cob_variance))
+			return -1;
+
+		break;
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
-		if (cmp_ent_write_non_ima_parameters(ent, info))
+		/* TODO: fix this*/
 			return -1;
 		break;
-	case DATA_TYPE_UNKOWN: /* fall through */
+	case DATA_TYPE_UNKOWN:
 	default:
 		return -1;
 	}
@@ -1876,12 +1902,94 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
 
 
 /**
- * @brief create a compression entity by setting the size of the
- * compression entity and the data product type in the entity header
+ * @brief write the parameters from the RDCU decompression information structure
+ *	in the compression entity header
+ * @note no compressed data are put into the entity and no change of the entity
+ *	size
+ *
+ * @param ent	pointer to a compression entity
+ * @param info	pointer to a decompression information structure
+ * @param cfg	pointer to a compression configuration structure for adaptive
+ *	compression parameters (can be NULL if non adaptive data_type is used)
+ *
+ * @returns 0 on success, negative on error
+ */
+
+int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *info,
+				const struct cmp_cfg *cfg)
+{
+	uint32_t ent_cmp_data_size;
+	enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
+
+	if (!info)
+		return -1;
+
+	ent_cmp_data_size = cmp_ent_get_cmp_data_size(ent);
+
+	/* check if the entity can hold the compressed data */
+	if (ent_cmp_data_size < cmp_bit_to_4byte(info->cmp_size)) {
+		debug_print("Error: The entity size is to small to hold the compressed data.\n");
+		return -2;
+	}
+
+	if (!rdcu_supported_data_type_is_used(data_type)) {
+		debug_print("Error: The compression data type is not one of the types supported by the RDCU.\n");
+		return -1;
+	}
+
+	/* set compression parameter fields in the generic entity header */
+	if (cmp_ent_set_original_size(ent, cmp_cal_size_of_data(info->samples_used, DATA_TYPE_IMAGETTE)))
+		return -1;
+	if (cmp_ent_set_cmp_mode(ent, info->cmp_mode_used))
+		return -1;
+	if (cmp_ent_set_model_value(ent, info->model_value_used))
+		return -1;
+	if (cmp_ent_set_lossy_cmp_par(ent, info->round_used))
+		return -1;
+
+	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");
+		return -1;
+	}
+	if (raw_mode_is_used(info->cmp_mode_used))
+		/* no specific header is used for raw data we are done */
+		return 0;
+
+	if (cmp_ent_set_ima_spill(ent, info->spill_used))
+		return -1;
+	if (cmp_ent_set_ima_golomb_par(ent, info->golomb_par_used))
+		return -1;
+
+	/* use the adaptive imagette parameter from the compression configuration
+	 * if an adaptive imagette compression data type is ent in the entity
+	 */
+	if (cmp_ap_imagette_data_type_is_used(data_type)) {
+		if (!cfg) {
+			debug_print("Error: Need the compression configuration to get the adaptive parameters.\n");
+			return -1;
+		}
+		if (cmp_ent_set_ima_ap1_spill(ent, cfg->ap1_spill))
+			return -1;
+		if (cmp_ent_set_ima_ap1_golomb_par(ent, cfg->ap1_golomb_par))
+			return -1;
+		if (cmp_ent_set_ima_ap2_spill(ent, cfg->ap2_spill))
+			return -1;
+		if (cmp_ent_set_ima_ap2_golomb_par(ent, cfg->ap2_golomb_par))
+			return -1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * @brief create a compression entity by setting the size of the compression
+ *	entity and the data product type in the entity header
  *
  * @param ent		pointer to a compression entity; if NULL, the function
- *	returns the needed size
+ *			returns the needed size
  * @param data_type	compression entity data product type
+ * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
  * @param cmp_size_byte	size of the compressed data in bytes
  *
  * @note if the entity size is smaller than the largest header, the function
@@ -1890,12 +1998,12 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
  * @returns the size of the compression entity or 0 on error
  */
 
-size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		      uint32_t cmp_size_byte)
+uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type,
+			int raw_mode_flag, uint32_t cmp_size_byte)
 {
 	int err;
-	uint32_t hdr_size = cmp_ent_cal_hdr_size(data_type);
-	size_t ent_size = hdr_size + cmp_size_byte;
+	uint32_t hdr_size = cmp_ent_cal_hdr_size(data_type, raw_mode_flag);
+	uint32_t ent_size = hdr_size + cmp_size_byte;
 	uint32_t ent_size_cpy = ent_size;
 
 	if (!hdr_size)
@@ -1904,6 +2012,9 @@ size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 	if (cmp_size_byte > CMP_ENTITY_MAX_SIZE)
 		return 0;
 
+	if (ent_size > CMP_ENTITY_MAX_SIZE)
+		return 0;
+
 	if (ent_size < sizeof(struct cmp_entity))
 		ent_size = sizeof(struct cmp_entity);
 
@@ -1916,7 +2027,7 @@ size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 	if (err)
 		return 0;
 
-	err = cmp_ent_set_data_type(ent, data_type);
+	err = cmp_ent_set_data_type(ent, data_type, raw_mode_flag);
 	if (err)
 		return 0;
 
@@ -1927,35 +2038,37 @@ size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 /**
  * @brief create a compression entity and set the header fields
  *
- * @note this function simplifies the entity setup by creating a entity and
+ * @note this function simplifies the entity set up by creating an entity and
  *	setting the header fields in one function call
+ * @note no compressed data are put into the entity
  *
  * @param ent			pointer to a compression entity; if NULL, the
  *	function returns the needed size
- * @param data_type		compression entity data product type
- * @param version_id	applications software version identifier
+ * @param version_id		applications software version identifier
  * @param start_time		compression start timestamp (coarse and fine)
  * @param end_time		compression end timestamp (coarse and fine)
  * @param model_id		model identifier
  * @param model_counter		model counter
- * @param info			decompression information structure
- * @param cfg			compression configuration structure for adaptive
- *	compression parameters (can be NULL)
+ * @param cfg			pointer to compression configuration (can be NULL)
+ * @param cmp_size_bits		length of the compressed data in bits
  *
  * @returns the size of the compression entity or 0 on error
  */
 
-size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		     uint32_t version_id, uint64_t start_time,
-		     uint64_t end_time, uint16_t model_id, uint8_t model_counter,
-		     struct cmp_info *info, struct cmp_cfg *cfg)
+size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id,
+		     uint64_t start_time, uint64_t end_time, uint16_t model_id,
+		     uint8_t model_counter, struct cmp_cfg *cfg, int cmp_size_bits)
 {
 	uint32_t ent_size;
 
-	if (!info)
+	if (!cfg)
 		return 0;
 
-	ent_size = cmp_ent_create(ent, data_type, cmp_bit_to_4byte(info->cmp_size));
+	if (cmp_size_bits < 0)
+		return 0;
+
+	ent_size = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW,
+				  cmp_bit_to_4byte((unsigned int)cmp_size_bits));
 	if (!ent_size)
 		return 0;
 
@@ -1970,7 +2083,7 @@ size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 			return 0;
 		if (cmp_ent_set_model_counter(ent, model_counter))
 			return 0;
-		if (cmp_ent_write_cmp_pars(ent, info, cfg))
+		if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits))
 			return 0;
 	}
 
@@ -1979,82 +2092,116 @@ size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 
 
 /**
- * @brief read in read in a imagette compression entity header to a info struct
+ * @brief read in an imagette compression entity header to a
+ *	compression configuration
  *
- * @param ent			pointer to a compression entity
- * @param info			pointer to decompression information structure
- *	to store the read values
+ * @param ent	pointer to a compression entity
+ * @param cfg	pointer to a compression configuration
  *
  * @returns 0 on success; otherwise error
  */
 
-int cmp_ent_read_imagette_header(struct cmp_entity *ent, struct cmp_info *info)
+int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 {
-	uint32_t original_size;
-	uint32_t sample_size;
+	int samples;
 
-	if (!ent)
-		return -1;
-
-	if (!info)
-		return -1;
-
-	info->cmp_mode_used = cmp_ent_get_cmp_mode(ent);
-	info->model_value_used = cmp_ent_get_model_value_used(ent);
-	info->round_used = cmp_ent_get_lossy_cmp_par(ent);
-	info->spill_used = cmp_ent_get_ima_spill(ent);
-	info->golomb_par_used = cmp_ent_get_ima_golomb_par(ent);
-	info->cmp_size = cmp_ent_get_cmp_data_size(ent)*CHAR_BIT;
-
-	sample_size = size_of_a_sample(info->cmp_mode_used);
-	if (!sample_size) {
-		info->samples_used = 0;
+	cfg->data_type = cmp_ent_get_data_type(ent);
+	if (!cmp_data_type_valid(cfg->data_type)) {
+		debug_print("Error: Compression data type not supported.\n");
 		return -1;
 	}
 
-	original_size = cmp_ent_get_original_size(ent);
-	if (original_size % sample_size != 0) {
-		fprintf(stderr, "Error: original_size and cmp_mode compression header field are not compatible.\n");
-		info->samples_used = 0;
+	cfg->cmp_mode = cmp_ent_get_cmp_mode(ent);
+	cfg->model_value = cmp_ent_get_model_value_used(ent);
+	cfg->round = cmp_ent_get_lossy_cmp_par(ent);
+	cfg->buffer_length = cmp_ent_get_cmp_data_size(ent);
+
+	samples = cmp_input_size_to_samples(cmp_ent_get_original_size(ent), cfg->data_type);
+	if (samples < 0) {
+		debug_print("Error: original_size and data product type in the compression header field are not compatible.\n");
+		cfg->samples = 0;
 		return -1;
 	}
 
-	info->samples_used = original_size / sample_size;
+	cfg->samples = samples;
 
-	if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(info->cmp_mode_used)) {
-		fprintf(stderr, "Error: The raw bit is set in Data Product Type Filed, but no raw compression mode is used.\n");
+	if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(cfg->cmp_mode)) {
+		debug_print("Error: The raw bit is set in data product type filed, but no raw compression mode is used.\n");
 		return -1;
 	}
-	return 0;
-}
-
 
-#if 0
-int cmp_ent_read_adaptive_imagette_header(struct cmp_entity *ent, struct cmp_info *info)
-{
-	if (!ent)
-		return -1;
+	cfg->icu_output_buf = cmp_ent_get_data_buf(ent);
 
-	if (!info)
-		return -1;
-
-	if (cmp_ent_get_imagette_header(ent, info))
+	switch (cfg->data_type) {
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+		cfg->ap1_golomb_par = cmp_ent_get_ima_ap1_golomb_par(ent);
+		cfg->ap1_spill = cmp_ent_get_ima_ap1_spill(ent);
+		cfg->ap2_golomb_par = cmp_ent_get_ima_ap2_golomb_par(ent);
+		cfg->ap2_spill = cmp_ent_get_ima_ap2_spill(ent);
+		/* fall through */
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+		cfg->spill = cmp_ent_get_ima_spill(ent);
+		cfg->golomb_par = cmp_ent_get_ima_golomb_par(ent);
+		break;
+	case DATA_TYPE_OFFSET:
+	case DATA_TYPE_BACKGROUND:
+	case DATA_TYPE_SMEARING:
+		cfg->cmp_par_mean = cmp_ent_get_non_ima_cmp_par1(ent);
+		cfg->spill_mean = cmp_ent_get_non_ima_spill1(ent);
+		cfg->cmp_par_variance = cmp_ent_get_non_ima_cmp_par2(ent);
+		cfg->spill_variance = cmp_ent_get_non_ima_spill2(ent);
+		cfg->cmp_par_pixels_error = cmp_ent_get_non_ima_cmp_par3(ent);
+		cfg->spill_pixels_error = cmp_ent_get_non_ima_spill3(ent);
+		break;
+	case DATA_TYPE_S_FX:
+	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_NCOB:
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX:
+	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_NCOB:
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX:
+	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_NCOB:
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		cfg->cmp_par_exp_flags = cmp_ent_get_non_ima_cmp_par1(ent);
+		cfg->spill_exp_flags = cmp_ent_get_non_ima_spill1(ent);
+		cfg->cmp_par_fx = cmp_ent_get_non_ima_cmp_par2(ent);
+		cfg->spill_fx = cmp_ent_get_non_ima_spill2(ent);
+		cfg->cmp_par_ncob = cmp_ent_get_non_ima_cmp_par3(ent);
+		cfg->spill_ncob = cmp_ent_get_non_ima_spill3(ent);
+		cfg->cmp_par_efx = cmp_ent_get_non_ima_cmp_par4(ent);
+		cfg->spill_efx = cmp_ent_get_non_ima_spill4(ent);
+		cfg->cmp_par_ecob = cmp_ent_get_non_ima_cmp_par5(ent);
+		cfg->spill_ecob = cmp_ent_get_non_ima_spill5(ent);
+		cfg->cmp_par_fx_cob_variance = cmp_ent_get_non_ima_cmp_par6(ent);
+		cfg->spill_fx_cob_variance = cmp_ent_get_non_ima_spill6(ent);
+		break;
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
+		/* TODO: fix this*/
+			return -1;
+		break;
+	case DATA_TYPE_UNKOWN: /* fall through */
+	default:
 		return -1;
-	/* info->ap1_cmp_size_byte = cmp_ent_get_ap1_cmp_size_byte(ent); */
-	/* info->ap2_cmp_size_byte = cmp_ent_get_ap2_cmp_size_byte(ent); */
-	/* get ap1_spill and ap1/2 gpar*/
+	}
 
 	return 0;
 }
-#endif
 
 
-#if __has_include(<time.h>)
+#ifdef HAS_TIME_H
 /*
  * @brief Covert a calendar time expressed as a struct tm object to time since
  *	 epoch as a time_t object. The function interprets the input structure
  *	 as representing Universal Coordinated Time (UTC).
- * @note timegm is a GNU C Library extensions, not standardized. This function
+ * @note timegm is a GNU C Library extension, not standardized. This function
  *	is used as a portable alternative
  * @note The function is thread-unsafe
  *
@@ -2067,9 +2214,9 @@ int cmp_ent_read_adaptive_imagette_header(struct cmp_entity *ent, struct cmp_inf
 
 static time_t my_timegm(struct tm *tm)
 {
-#if defined(_WIN32) || defined(_WIN64)
+#  if defined(_WIN32) || defined(_WIN64)
 	return _mkgmtime(tm);
-#else
+#  else
 	time_t ret;
 	char *tz;
 
@@ -2086,14 +2233,14 @@ static time_t my_timegm(struct tm *tm)
 		unsetenv("TZ");
 	tzset();
 	return ret;
-#endif
+#  endif
 }
 
 
 /*
  * @brief Generate a timestamp for the compression header
  *
- * @param ts  pointer to 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
  */
@@ -2186,7 +2333,7 @@ void cmp_ent_print(struct cmp_entity *ent)
 
 
 /**
- * @brief parse the generic compressed entity header
+ * @brief parses the generic compressed entity header
  *
  * @param ent	pointer to a compression entity
  */
@@ -2197,13 +2344,14 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 		 model_value_used, model_id, model_counter, lossy_cmp_par_used,
 		 start_coarse_time, end_coarse_time;
 	uint16_t start_fine_time, end_fine_time;
-	enum cmp_ent_data_type data_type;
+	enum cmp_data_type data_type;
 	int raw_bit;
 
 	version_id = cmp_ent_get_version_id(ent);
 	if (version_id & CMP_TOOL_VERSION_ID_BIT) {
 		uint16_t major = (version_id & 0x7FFF0000U) >> 16U;
 		uint16_t minor = version_id & 0xFFFFU;
+
 		printf("Compressed with cmp_tool version: %u.%02u\n", major, minor);
 	} else
 		printf("ICU ASW Version ID: %u\n", version_id);
@@ -2226,10 +2374,11 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 	end_fine_time = cmp_ent_get_fine_end_time(ent);
 	printf("Compression Fine End Time: %d\n", end_fine_time);
 
-#if __has_include(<time.h>)
+#ifdef HAS_TIME_H
 	{
 		struct tm epoch_date = EPOCH_DATE;
 		time_t time = my_timegm(&epoch_date) + start_coarse_time;
+
 		printf("Data were compressed on (local time): %s", ctime(&time));
 	}
 #endif
@@ -2319,17 +2468,26 @@ static void cmp_ent_parese_adaptive_imagette_header(struct cmp_entity *ent)
 
 static void cmp_ent_parese_specific_header(struct cmp_entity *ent)
 {
-	enum cmp_ent_data_type data_type = cmp_ent_get_data_type(ent);
+	enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
+
+	if (cmp_ent_get_data_type_raw_bit(ent)) {
+		printf("Uncompressed data bit is set no specific header is used.\n");
+		return;
+	}
 
 	switch (data_type) {
 	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
 		cmp_ent_parese_imagette_header(ent);
 		break;
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		cmp_ent_parese_adaptive_imagette_header(ent);
 		break;
 	default:
-		printf("Data Product Type not supported!\n");
+		printf("For this data product type no parse functions is implemented!\n");
 		break;
 	}
 }
@@ -2347,3 +2505,4 @@ void cmp_ent_parse(struct cmp_entity *ent)
 
 	cmp_ent_parese_specific_header(ent);
 }
+
diff --git a/lib/cmp_guess.c b/lib/cmp_guess.c
index 265b9c5..c173814 100644
--- a/lib/cmp_guess.c
+++ b/lib/cmp_guess.c
@@ -17,12 +17,14 @@
  *	dataset
  */
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "../include/cmp_icu.h"
-#include "../include/cmp_guess.h"
+#include "cmp_data_types.h"
+#include "cmp_icu.h"
+#include "cmp_guess.h"
 
 
 /* how often the model is updated before it is rested */
@@ -67,6 +69,43 @@ uint16_t cmp_guess_model_value(int n_model_updates)
 }
 
 
+/**
+ * @brief get a good spill threshold parameter for the selected Golomb parameter
+ *	and compression mode
+ *
+ * @param golomb_par	Golomb parameter
+ * @param cmp_mode	compression mode
+ *
+ * @returns a good spill parameter (optimal for zero escape mechanism)
+ * @warning icu compression not support yet!
+ */
+
+uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode)
+{
+	const uint32_t LUT_RDCU_MULIT[MAX_RDCU_GOLOMB_PAR+1] = {0, 8, 16, 23,
+		30, 36, 44, 51, 58, 64, 71, 77, 84, 90, 97, 108, 115, 121, 128,
+		135, 141, 148, 155, 161, 168, 175, 181, 188, 194, 201, 207, 214,
+		229, 236, 242, 250, 256, 263, 269, 276, 283, 290, 296, 303, 310,
+		317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397,
+		405, 411, 418, 424, 431, 452 };
+
+	if (zero_escape_mech_is_used(cmp_mode))
+		return get_max_spill(golomb_par, DATA_TYPE_IMAGETTE);
+
+	if (cmp_mode == CMP_MODE_MODEL_MULTI) {
+		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
+			return 0;
+		else
+			return LUT_RDCU_MULIT[golomb_par];
+	}
+
+	if (cmp_mode == CMP_MODE_DIFF_MULTI)
+		return CMP_GOOD_SPILL_DIFF_MULTI;
+
+	return 0;
+}
+
+
 /**
  * @brief guess a good configuration with pre_cal_method
  *
@@ -79,18 +118,17 @@ uint16_t cmp_guess_model_value(int n_model_updates)
 static uint32_t pre_cal_method(struct cmp_cfg *cfg)
 {
 	uint32_t g;
-	uint32_t cmp_size;
-	uint32_t cmp_size_best = ~0U;
+	int cmp_size, cmp_size_best = INT_MAX;
 	uint32_t golomb_par_best = 0;
 	uint32_t spill_best = 0;
 
 	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
-		uint32_t s = cmp_get_good_spill(g, cfg->cmp_mode);
+		uint32_t s = cmp_rdcu_get_good_spill(g, cfg->cmp_mode);
 
 		cfg->golomb_par = g;
 		cfg->spill = s;
-		cmp_size = cmp_encode_data(cfg);
-		if (cmp_size == 0) {
+		cmp_size = icu_compress_data(cfg);
+		if (cmp_size <= 0) {
 			return 0;
 		} else if (cmp_size < cmp_size_best) {
 			cmp_size_best = cmp_size;
@@ -120,8 +158,7 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 	uint32_t g, s;
 	uint32_t n_cal_steps = 0, last = 0;
 	const uint32_t max_cal_steps = CMP_GUESS_MAX_CAL_STEPS;
-	uint32_t cmp_size;
-	uint32_t cmp_size_best = ~0U;
+	int cmp_size, cmp_size_best = INT_MAX;
 	uint32_t golomb_par_best = 0;
 	uint32_t spill_best = 0;
 	uint32_t percent;
@@ -134,12 +171,12 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 	fflush(stdout);
 
 	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
-		for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->cmp_mode); s++) {
+		for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->data_type); s++) {
 			cfg->golomb_par = g;
 			cfg->spill = s;
 
-			cmp_size = cmp_encode_data(cfg);
-			if (cmp_size == 0) {
+			cmp_size = icu_compress_data(cfg);
+			if (cmp_size <= 0) {
 				return 0;
 			} else if (cmp_size < cmp_size_best) {
 				cmp_size_best = cmp_size;
@@ -185,19 +222,19 @@ static void add_rdcu_pars_internal(struct cmp_cfg *cfg)
 		cfg->ap2_golomb_par = cfg->golomb_par + 1;
 	}
 
-	cfg->ap1_spill = cmp_get_good_spill(cfg->ap1_golomb_par, cfg->cmp_mode);
-	cfg->ap2_spill = cmp_get_good_spill(cfg->ap2_golomb_par, cfg->cmp_mode);
+	cfg->ap1_spill = cmp_rdcu_get_good_spill(cfg->ap1_golomb_par, cfg->cmp_mode);
+	cfg->ap2_spill = cmp_rdcu_get_good_spill(cfg->ap2_golomb_par, cfg->cmp_mode);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
-		cfg->rdcu_data_adr = DEFAULT_CFG_MODEL.rdcu_data_adr;
-		cfg->rdcu_model_adr = DEFAULT_CFG_MODEL.rdcu_model_adr;
-		cfg->rdcu_new_model_adr = DEFAULT_CFG_MODEL.rdcu_new_model_adr;
-		cfg->rdcu_buffer_adr = DEFAULT_CFG_MODEL.rdcu_buffer_adr;
+		cfg->rdcu_data_adr = CMP_DEF_IMA_MODEL_RDCU_DATA_ADR;
+		cfg->rdcu_model_adr = CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR;
+		cfg->rdcu_new_model_adr = CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR;
+		cfg->rdcu_buffer_adr = CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR;
 	} else {
-		cfg->rdcu_data_adr = DEFAULT_CFG_DIFF.rdcu_data_adr;
-		cfg->rdcu_model_adr = DEFAULT_CFG_DIFF.rdcu_model_adr;
-		cfg->rdcu_new_model_adr = DEFAULT_CFG_DIFF.rdcu_new_model_adr;
-		cfg->rdcu_buffer_adr = DEFAULT_CFG_DIFF.rdcu_buffer_adr;
+		cfg->rdcu_data_adr = CMP_DEF_IMA_DIFF_RDCU_DATA_ADR;
+		cfg->rdcu_model_adr = CMP_DEF_IMA_DIFF_RDCU_MODEL_ADR;
+		cfg->rdcu_new_model_adr = CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR;
+		cfg->rdcu_buffer_adr = CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR;
 	}
 }
 
@@ -220,7 +257,6 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 {
 	size_t size;
 	struct cmp_cfg work_cfg;
-	int err;
 	uint32_t cmp_size = 0;
 
 	if (!cfg)
@@ -228,38 +264,28 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 
 	if (!cfg->input_buf)
 		return 0;
+	if (model_mode_is_used(cfg->cmp_mode))
+		if (!cfg->model_buf)
+			return 0;
 
-	if (!rdcu_supported_mode_is_used(cfg->cmp_mode)) {
+	if (!rdcu_supported_cmp_mode_is_used(cfg->cmp_mode)) {
 		printf("This compression mode is not implied yet.\n");
 		return 0;
 	}
 	/* make a working copy of the input data (and model) because the
-	 * following function works inplace */
+	 * following function works inplace
+	 */
 	work_cfg = *cfg;
-	work_cfg.input_buf = NULL;
-	work_cfg.model_buf = NULL;
 	work_cfg.icu_new_model_buf = NULL;
 	work_cfg.icu_output_buf = NULL;
 	work_cfg.buffer_length = 0;
+	work_cfg.data_type = DATA_TYPE_IMAGETTE; /* TODO: adapt to others data types */
 
-	size = cfg->samples * size_of_a_sample(work_cfg.cmp_mode);
+	size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
 	if (size == 0)
 		goto error;
-	work_cfg.input_buf = malloc(size);
-	if (!work_cfg.input_buf) {
-		printf("malloc() failed!\n");
-		goto error;
-	}
-	memcpy(work_cfg.input_buf, cfg->input_buf, size);
-
-	if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode)) {
-		work_cfg.model_buf = malloc(size);
-		if (!work_cfg.model_buf) {
-			printf("malloc() failed!\n");
-			goto error;
-		}
-		memcpy(work_cfg.model_buf, cfg->model_buf, size);
 
+	if (model_mode_is_used(cfg->cmp_mode)) {
 		work_cfg.icu_new_model_buf = malloc(size);
 		if (!work_cfg.icu_new_model_buf) {
 			printf("malloc() failed!\n");
@@ -267,14 +293,6 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 		}
 	}
 
-	err = cmp_pre_process(&work_cfg);
-	if (err)
-		goto error;
-
-	err = cmp_map_to_pos(&work_cfg);
-	if (err)
-		goto error;
-
 	/* find the best parameters */
 	switch (level) {
 	case 3:
@@ -294,8 +312,6 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 	if (!cmp_size)
 		goto error;
 
-	free(work_cfg.input_buf);
-	free(work_cfg.model_buf);
 	free(work_cfg.icu_new_model_buf);
 
 	cfg->golomb_par = work_cfg.golomb_par;
@@ -303,16 +319,15 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 
 	cfg->model_value = cmp_guess_model_value(num_model_updates);
 
-	if (rdcu_supported_mode_is_used(cfg->cmp_mode))
+	if (rdcu_supported_data_type_is_used(cfg->data_type))
 		add_rdcu_pars_internal(cfg);
 
-	cfg->buffer_length = ((cmp_size + 32)&~0x1FU)/(size_of_a_sample(work_cfg.cmp_mode)*8);
+	/* TODO: check that for non-imagette data */
+	cfg->buffer_length = ((cmp_size + 32)&~0x1FU)/(size_of_a_sample(cfg->data_type)*8);
 
 	return cmp_size;
 
 error:
-	free(work_cfg.input_buf);
-	free(work_cfg.model_buf);
 	free(work_cfg.icu_new_model_buf);
 	return 0;
 }
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 5409045..057ee64 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -15,1761 +15,2396 @@
  *
  * @brief software compression library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
+ *
+ * To compress data, first create a compression configuration with the
+ * cmp_cfg_icu_create() function.
+ * Then set the different data buffers with the data to compressed, the model
+ * data and the compressed data with the cmp_cfg_icu_buffers() function.
+ * Then set the compression data type specific compression parameters. For
+ * imagette data use the cmp_cfg_icu_imagette() function. For flux and center of
+ * brightness data use the cmp_cfg_fx_cob() function. And for background, offset
+ * and smearing data use the cmp_cfg_aux() function.
+ * Finally, you can compress the data with the icu_compress_data() function.
  */
 
 
-#include <stdio.h>
 #include <stdint.h>
 #include <string.h>
 #include <limits.h>
 
-#include "../include/cmp_support.h"
-#include "../include/cmp_data_types.h"
-#include "../include/cmp_icu.h"
-#include "../include/byteorder.h"
-#include "../include/cmp_debug.h"
+#include "byteorder.h"
+#include "cmp_debug.h"
+#include "cmp_data_types.h"
+#include "cmp_support.h"
+#include "cmp_icu.h"
+
+
+/* pointer to a code word generation function */
+typedef uint32_t (*generate_cw_f_pt)(uint32_t value, uint32_t encoder_par1,
+				     uint32_t encoder_par2, uint32_t *cw);
+
+
+/* structure to hold a setup to encode a value */
+struct encoder_setupt {
+	generate_cw_f_pt generate_cw_f; /* pointer to the code word generation function */
+	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 */
+	uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */
+	uint32_t encoder_par1; /* encoding parameter 1 */
+	uint32_t encoder_par2; /* encoding parameter 2 */
+	uint32_t spillover_par; /* outlier parameter */
+	uint32_t lossy_par; /* lossy compression parameter */
+	uint32_t max_data_bits; /* how many bits are needed to represent the highest possible value */
+};
 
 
 /**
- * @brief check if the compressor configuration is valid for a SW compression,
- *	see the user manual for more information (PLATO-UVIE-PL-UM-0001).
+ * @brief create a ICU compression configuration
  *
- * @param cfg	configuration contains all parameters required for compression
- * @param info	compressor information contains information of an executed
- *		compression (can be NULL)
+ * @param data_type	compression data product types
+ * @param cmp_mode	compression mode
+ * @param model_value	model weighting parameter (only need for model compression mode)
+ * @param lossy_par	lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
  *
- * @returns 0 when configuration is valid, invalid configuration otherwise
+ * @returns compression configuration containing the chosen parameters;
+ *	on error the data_type record is set to DATA_TYPE_UNKOWN
  */
 
-int icu_cmp_cfg_valid(const struct cmp_cfg *cfg, struct cmp_info *info)
+struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
+				  uint32_t model_value, uint32_t lossy_par)
 {
-	int cfg_invalid = 0;
-
-	if (!cfg) {
-		debug_print("Error: compression configuration structure is NULL.\n");
-		return -1;
-	}
+	int cfg_valid;
+	struct cmp_cfg cfg = {0};
 
-	if (!info)
-		debug_print("Warning: compressor information structure is NULL.\n");
+	cfg.data_type = data_type;
+	cfg.cmp_mode = cmp_mode;
+	cfg.model_value = model_value;
+	cfg.round = lossy_par;
 
-	if (info)
-		info->cmp_err = 0;  /* reset errors */
-
-	if (cfg->input_buf == NULL) {
-		debug_print("Error: The input_buf buffer for the data to be compressed is NULL.\n");
-		cfg_invalid++;
-	}
+	cfg_valid = cmp_cfg_icu_gen_par_is_valid(&cfg);
+	if (!cfg_valid)
+		cfg.data_type = DATA_TYPE_UNKOWN;
 
-	if (cfg->samples == 0)
-		debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
+	return cfg;
+}
 
-	/* icu_output_buf can be NULL if rdcu compression is used */
-	if (cfg->icu_output_buf == NULL) {
-		debug_print("Error: The icu_output_buf buffer for the compressed data is NULL.\n");
-		cfg_invalid++;
-	}
 
-	if (cfg->buffer_length == 0 && cfg->samples != 0) {
-		debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n");
-		cfg_invalid++;
-	}
+/**
+ * @brief setup of the different data buffers for an ICU compression
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the cmp_cfg_icu_create() function)
+ * @param data_to_compress	pointer to the data to be compressed
+ * @param data_samples		length of the data to be compressed measured in
+ *				data samples/entitys (multi entity header not
+ *				included by imagette data)
+ * @param model_of_data		pointer to model data buffer (can be NULL if no
+ *				model compression mode is used)
+ * @param updated_model		pointer to store the updated model for the next
+ *				model mode compression (can be the same as the model_of_data
+ *				buffer for in-place update or NULL if updated model is not needed)
+ * @param compressed_data	pointer to the compressed data buffer (can be NULL)
+ * @param compressed_data_len_samples	length of the compressed_data buffer in
+ *					measured in the same units as the data_samples
+ *
+ * @returns the size of the compressed_data buffer on success; 0 if the
+ *	parameters are invalid
+ */
 
-	if (cfg->icu_output_buf == cfg->input_buf) {
-		debug_print("Error: The icu_output_buf buffer is the same as the input_buf buffer.\n");
-		cfg_invalid++;
+size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
+			   uint32_t data_samples, void *model_of_data,
+			   void *updated_model, uint32_t *compressed_data,
+			   uint32_t compressed_data_len_samples)
+{
+	if (!cfg) {
+		debug_print("Error: pointer to the compression configuration structure is NULL.\n");
+		return 0;
 	}
 
-	if (model_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->model_buf == NULL) {
-			debug_print("Error: The model_buf buffer for the model data is NULL.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->model_buf == cfg->input_buf) {
-			debug_print("Error: The model_buf buffer is the same as the input_buf buffer.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->model_buf == cfg->icu_output_buf) {
-			debug_print("Error: The model_buf buffer is the same as the icu_output_buf buffer.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->icu_new_model_buf == cfg->input_buf) {
-			debug_print("Error: The icu_new_model_buf buffer is the same as the input_buf buffer.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->icu_new_model_buf == cfg->icu_output_buf) {
-			debug_print("Error: The icu_output_buf buffer is the same as the icu_output_buf buffer.\n");
-			cfg_invalid++;
-		}
-	}
+	cfg->input_buf = data_to_compress;
+	cfg->model_buf = model_of_data;
+	cfg->samples = data_samples;
+	cfg->icu_new_model_buf = updated_model;
+	cfg->icu_output_buf = compressed_data;
+	cfg->buffer_length = compressed_data_len_samples;
 
-	if (raw_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->samples > cfg->buffer_length) {
-			debug_print("Error: The buffer_length is to small to hold the data form the input_buf.\n");
-			cfg_invalid++;
-		}
-	} else {
-		if (cfg->samples*size_of_a_sample(cfg->cmp_mode) <
-		    cfg->buffer_length*sizeof(uint16_t)/3) /* TODO: have samples and buffer_lengt the same unit */
-			debug_print("Warning: The size of the icu_output_buf is 3 times smaller than the input_buf. This is probably unintentional.\n");
-	}
+	if (!cmp_cfg_icu_buffers_is_valid(cfg))
+		return 0;
 
+	return cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type);
+}
 
-	if (!(diff_mode_is_used(cfg->cmp_mode)
-	     || model_mode_is_used(cfg->cmp_mode)
-	     || raw_mode_is_used(cfg->cmp_mode))) {
-		debug_print("Error: selected cmp_mode: %u is not supported\n.",
-			    cfg->cmp_mode);
-		if (info)
-			info->cmp_err |= 1UL << CMP_MODE_ERR_BIT;
-		cfg_invalid++;
-	}
 
-	if (raw_mode_is_used(cfg->cmp_mode)) /* additional checks are not needed for the raw mode */
-		return -cfg_invalid;
+/**
+ * @brief set up the configuration parameters for an ICU imagette compression
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the cmp_cfg_icu_create() function)
+ * @param cmp_par		imagette compression parameter (Golomb parameter)
+ * @param spillover_par		imagette spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
 
-	if (model_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->model_value > MAX_MODEL_VALUE) {
-			debug_print("Error: selected model_value: %u is invalid. Largest supported value is: %lu.\n",
-				    cfg->model_value, MAX_MODEL_VALUE);
-			if (info)
-				info->cmp_err |= 1UL << MODEL_VALUE_ERR_BIT;
-			cfg_invalid++;
-		}
-	}
+int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
+			 uint32_t spillover_par)
+{
+	if (!cfg)
+		return -1;
 
-	if (cfg->golomb_par < MIN_ICU_GOLOMB_PAR ||
-	    cfg->golomb_par > MAX_ICU_GOLOMB_PAR) {
-		debug_print("Error: The selected Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%lu, %u].\n",
-			    cfg->golomb_par, MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
-		if (info)
-			info->cmp_err |= 1UL << CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+	cfg->golomb_par = cmp_par;
+	cfg->spill = spillover_par;
 
-	if (cfg->spill < MIN_ICU_SPILL) {
-		debug_print("Error: The selected spillover threshold value: %u is too small. Smallest possible spillover value is: %lu.\n",
-			    cfg->spill, MIN_ICU_SPILL);
-		if (info)
-			info->cmp_err |= 1UL << CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+	if (!cmp_cfg_imagette_is_valid(cfg))
+		return -1;
 
-	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->cmp_mode)) {
-		debug_print("Error: The selected spillover threshold value: %u is too large for the selected Golomb parameter: %u, the largest possible spillover value in the selected compression mode is: %u.\n",
-			    cfg->spill, cfg->golomb_par,
-			    get_max_spill(cfg->golomb_par, cfg->cmp_mode));
-		if (info)
-			info->cmp_err |= 1UL << CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+	return 0;
+}
 
-#ifdef ADAPTIVE_CHECK_ENA
-	/*
-	 * ap1_spill and ap2_spill are not used for the icu_compression
-	 */
 
-	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->cmp_mode)) {
-		if (info)
-			info->cmp_err |= 1UL << AP1_CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+/**
+ * @brief set up of the configuration parameters for a flux/COB compression
+ * @note not all parameters are needed for every flux/COB compression data type
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the cmp_cfg_icu_create() function)
+ * @param cmp_par_exp_flags	exposure flags compression parameter
+ * @param spillover_exp_flags	exposure flags spillover threshold parameter
+ * @param cmp_par_fx		normal flux compression parameter
+ * @param spillover_fx		normal flux spillover threshold parameter
+ * @param cmp_par_ncob		normal center of brightness compression parameter
+ * @param spillover_ncob	normal center of brightness spillover threshold parameter
+ * @param cmp_par_efx		extended flux compression parameter
+ * @param spillover_efx		extended flux spillover threshold parameter
+ * @param cmp_par_ecob		extended center of brightness compression parameter
+ * @param spillover_ecob	extended center of brightness spillover threshold parameter
+ * @param cmp_par_fx_cob_variance	flux/COB variance compression parameter
+ * @param spillover_fx_cob_variance	flux/COB variance spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
 
-	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->cmp_mode)) {
-		if (info)
-			info->cmp_err |= 1UL << AP2_CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
-#endif
+int cmp_cfg_fx_cob(struct cmp_cfg *cfg,
+		   uint32_t cmp_par_exp_flags, uint32_t spillover_exp_flags,
+		   uint32_t cmp_par_fx, uint32_t spillover_fx,
+		   uint32_t cmp_par_ncob, uint32_t spillover_ncob,
+		   uint32_t cmp_par_efx, uint32_t spillover_efx,
+		   uint32_t cmp_par_ecob, uint32_t spillover_ecob,
+		   uint32_t cmp_par_fx_cob_variance, uint32_t spillover_fx_cob_variance)
+{
+	if (!cfg)
+		return -1;
 
-	if (cfg->round > MAX_ICU_ROUND) {
-		debug_print("Error: selected round parameter: %u is not supported. Largest supported value is: %lu.\n",
-			    cfg->round, MAX_ICU_ROUND);
-		cfg_invalid++;
-	}
+	cfg->cmp_par_exp_flags = cmp_par_exp_flags;
+	cfg->cmp_par_fx = cmp_par_fx;
+	cfg->cmp_par_ncob = cmp_par_ncob;
+	cfg->cmp_par_efx = cmp_par_efx;
+	cfg->cmp_par_ecob = cmp_par_ecob;
+	cfg->cmp_par_fx_cob_variance = cmp_par_fx_cob_variance;
+
+	cfg->spill_exp_flags = spillover_exp_flags;
+	cfg->spill_fx = spillover_fx;
+	cfg->spill_ncob = spillover_ncob;
+	cfg->spill_efx = spillover_efx;
+	cfg->spill_ecob = spillover_ecob;
+	cfg->spill_fx_cob_variance = spillover_fx_cob_variance;
+
+	if (!cmp_cfg_fx_cob_is_valid(cfg))
+		return -1;
 
-	return -(cfg_invalid);
+	return 0;
 }
 
 
 /**
- * @brief sets the compression information used based on the compression
- *	configuration
- *
- * @param cfg	compression configuration struct
- * @param info	compressor information struct to set the used compression
- *	parameters (can be NULL)
- *
- * @note set cmp_size, ap1_cmp_size, ap2_cmp_size will be set to 0
- *
- * @returns 0 on success, error otherwise
+ * @brief set up of the configuration parameters for an auxiliary science data compression
+ * @note auxiliary compression data types are: DATA_TYPE_OFFSET, DATA_TYPE_BACKGROUND,
+	DATA_TYPE_SMEARING, DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND
+ * @note not all parameters are needed for the every auxiliary compression data types
+ *
+ * @param cfg				pointer to a compression configuration (
+ *					created with the cmp_cfg_icu_create() function)
+ * @param cmp_par_mean			mean compression parameter
+ * @param spillover_mean		mean spillover threshold parameter
+ * @param cmp_par_variance		variance compression parameter
+ * @param spillover_variance		variance spillover threshold parameter
+ * @param cmp_par_pixels_error		outlier pixels number compression parameter
+ * @param spillover_pixels_error	outlier pixels number spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
  */
 
-
-static int set_info(struct cmp_cfg *cfg, struct cmp_info *info)
+int cmp_cfg_aux(struct cmp_cfg *cfg,
+		uint32_t cmp_par_mean, uint32_t spillover_mean,
+		uint32_t cmp_par_variance, uint32_t spillover_variance,
+		uint32_t cmp_par_pixels_error, uint32_t spillover_pixels_error)
 {
 	if (!cfg)
 		return -1;
 
-	if (cfg->cmp_mode > UINT8_MAX)
-		return -1;
+	cfg->cmp_par_mean = cmp_par_mean;
+	cfg->cmp_par_variance = cmp_par_variance;
+	cfg->cmp_par_pixels_error = cmp_par_pixels_error;
 
-	if (cfg->round > UINT8_MAX)
-		return -1;
+	cfg->spill_mean = spillover_mean;
+	cfg->spill_variance = spillover_variance;
+	cfg->spill_pixels_error = spillover_pixels_error;
 
-	if (cfg->model_value > UINT8_MAX)
+	if (!cmp_cfg_aux_is_valid(cfg))
 		return -1;
 
-	if (info) {
-		info->cmp_err = 0;
-		info->cmp_mode_used = (uint8_t)cfg->cmp_mode;
-		info->model_value_used = (uint8_t)cfg->model_value;
-		info->round_used = (uint8_t)cfg->round;
-		info->spill_used = cfg->spill;
-		info->golomb_par_used = cfg->golomb_par;
-		info->samples_used = cfg->samples;
-		info->cmp_size = 0;
-		info->ap1_cmp_size = 0;
-		info->ap2_cmp_size = 0;
-		info->rdcu_new_model_adr_used = cfg->rdcu_new_model_adr;
-		info->rdcu_cmp_adr_used = cfg->rdcu_buffer_adr;
-	}
 	return 0;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a uint16_t data buffer
- *
- * @note change the data_buf in-place
- * @note output is I[0] = I[0], I[i] = I[i] - I[i-1], where i is 1,2,..samples-1
+ * @brief map a signed value into a positive value range
  *
- * @param data_buf	pointer to the uint16_t formatted data buffer to process
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value_to_map	signed value to map
+ * @param max_data_bits	how many bits are needed to represent the
+ *			highest possible value
  *
- * @returns 0 on success, error otherwise
+ * @returns the positive mapped value
  */
 
-static int diff_16(uint16_t *data_buf, unsigned int samples, unsigned int round)
+static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits)
 {
-	size_t i;
-
-	if (!data_buf)
-		return -1;
-
-	lossy_rounding_16(data_buf, samples, round);
-
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data_buf[i] = data_buf[i] - data_buf[i-1];
+	uint32_t result;
+	uint32_t mask = (~0U >> (32 - max_data_bits)); /* mask the used bits */
+
+	value_to_map &= mask;
+	if (value_to_map >> (max_data_bits - 1)) { /* check the leading signed bit */
+		value_to_map |= ~mask; /* convert to 32-bit signed integer */
+		/* map negative values to uneven numbers */
+		result = (-value_to_map) * 2 - 1; /* possible integer overflow is intended */
+	} else {
+		/* map positive values to even numbers */
+		result = value_to_map * 2; /* possible integer overflow is intended */
 	}
-	return 0;
+
+	return result;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a uint32_t data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
- *
- * @param data_buf	pointer to the uint32_t formatted data buffer to process
- * @param samples	amount of data samples in the data_buf buffer
- * @param round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
+ * @brief put the value of up to 32 bits into a bitstream
+ *
+ * @param value			the value to put
+ * @param n_bits		number of bits to put in the bitstream
+ * @param bit_offset		bit index where the bits will be put, seen from
+ *				the very beginning of the bitstream
+ * @param bitstream_adr		this is the pointer to the beginning of the
+ *				bitstream (can be NULL)
+ * @param max_stream_len	maximum length of the bitstream in bits; is
+ *				ignored if bitstream_adr is NULL
+ *
+ * @returns length in bits of the generated bitstream on success; returns
+ *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
+ *          the bitstream buffer is too small to put the value in the bitstream
  */
 
-static int diff_32(uint32_t *data_buf, unsigned int samples, unsigned int round)
+static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
+			uint32_t *bitstream_adr, unsigned int max_stream_len)
 {
-	size_t i;
+	uint32_t *local_adr;
+	uint32_t mask;
+	unsigned int shiftRight, shiftLeft, bitsLeft, bitsRight;
+	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
 
-	if (!data_buf)
+	/* Leave in case of erroneous input */
+	if (bit_offset < 0)
 		return -1;
 
-	lossy_rounding_32(data_buf, samples, round);
+	if (n_bits == 0)
+		return stream_len;
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data_buf[i] = data_buf[i] - data_buf[i-1];
+	if (n_bits > 32)
+		return -1;
+
+	/* Do we need to write data to the bitstream? */
+	if (!bitstream_adr)
+		return stream_len;
+
+	/* Check if bitstream buffer is large enough */
+	if ((unsigned int)stream_len > max_stream_len) {
+		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
+		return CMP_ERROR_SAMLL_BUF;
 	}
-	return 0;
-}
 
+	/* (M) is the n_bits parameter large enough to cover all value bits; the
+	 * calculations can be re-used in the unsegmented code, so we have no overhead
+	 */
+	shiftRight = 32 - n_bits;
+	mask = 0xFFFFFFFFU >> shiftRight;
+	value &= mask;
 
-/**
- * @brief 1d-differentiating pre-processing and round of a S_FX data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
- *
- * @param data		pointer to a S_FX data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
+	/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
+	local_adr = bitstream_adr + (bit_offset >> 5);
+	bitsLeft = bit_offset & 0x1F;
 
-static int diff_S_FX(struct S_FX *data, unsigned int samples, unsigned int
-		     round)
-{
-	size_t i;
-	int err;
+	/* Calculate the bitsRight for the unsegmented case. If bitsRight is
+	 * negative we need to split the value over two words
+	 */
+	bitsRight = shiftRight - bitsLeft;
 
-	if (!data)
-		return -1;
+	if ((int)bitsRight >= 0) {
+		/*         UNSEGMENTED
+		 *
+		 *|-----------|XXXXX|----------------|
+		 *   bitsLeft    n       bitsRight
+		 *
+		 *  -> to get the mask:
+		 *  shiftRight = bitsLeft + bitsRight = 32 - n
+		 *  shiftLeft = bitsRight = 32 - n - bitsLeft = shiftRight - bitsLeft
+		 */
 
-	err = lossy_rounding_S_FX(data, samples, round);
-	if (err)
-		return err;
+		shiftLeft = bitsRight;
+
+		/* generate the mask, the bits for the values will be true
+		 * shiftRight = 32 - n_bits; see (M) above!
+		 * mask = (0XFFFFFFFF >> shiftRight) << shiftLeft; see (M) above!
+		 */
+		mask <<= shiftLeft;
+		value <<= shiftLeft;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value */
+		*(local_adr) |= value;
+
+	} else {
+		/*                             SEGMENTED
+		 *
+		 *|-----------------------------|XXX| |XX|------------------------------|
+		 *          bitsLeft              n1   n2          bitsRight
+		 *
+		 *  -> to get the mask part 1:
+		 *  shiftRight = bitsLeft
+		 *  n1 = n - (bitsLeft + n - 32) = 32 - bitsLeft
+		 *
+		 *  -> to get the mask part 2:
+		 *  n2 = bitsLeft + n - 32 = -(32 - n - bitsLeft) = -(bitsRight_UNSEGMENTED)
+		 *  shiftLeft = 32 - n2 = 32 - (bitsLeft + n - 32) = 64 - bitsLeft - n
+		 *
+		 */
+
+		unsigned int n2 = -bitsRight;
+
+		/* part 1: */
+		shiftRight = bitsLeft;
+		mask = 0XFFFFFFFFU >> shiftRight;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value part 1 */
+		*(local_adr) |= (value >> n2);
+
+		/* part 2: */
+		/* adjust address */
+		local_adr += 1;
+		shiftLeft = 32 - n2;
+		mask = 0XFFFFFFFFU >> n2;
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX(data[i], data[i-1]);
+		/* clear the destination */
+		*(local_adr) &= mask;
+
+		/* assign the value part 2 */
+		*(local_adr) |= (value << shiftLeft);
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a S_FX_EFX data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
+ * @brief forms the codeword according to the Rice code
  *
- * @param data		pointer to a S_FX_EFX data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value		value to be encoded
+ * @param m		Golomb parameter, only m's which are power of 2 are allowed
+ * @param log2_m	Rice parameter, is log_2(m) calculate outside function
+ *			for better performance
+ * @param cw		address were the encode code word is stored
  *
- * @returns 0 on success, error otherwise
+ * @returns the length of the formed code word in bits
+ * @note no check if the generated code word is not longer than 32 bits!
  */
 
-static int diff_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples, unsigned
-			 int round)
+static uint32_t rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
+			     uint32_t *cw)
 {
-	size_t i;
-	int err;
+	uint32_t g;  /* quotient of value/m */
+	uint32_t q;  /* quotient code without ending zero */
+	uint32_t r;  /* remainder of value/m */
+	uint32_t rl; /* remainder length */
 
-	if (!data)
-		return -1;
+	g = value >> log2_m; /* quotient, number of leading bits */
+	q = (1U << g) - 1;   /* prepare the quotient code without ending zero */
 
-	err = lossy_rounding_S_FX_EFX(data, samples, round);
-	if (err)
-		return err;
+	r = value & (m-1);   /* calculate the remainder */
+	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the quotient code) */
+	*cw = (q << rl) | r; /* put the quotient and remainder code together */
+	/*
+	 * NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined
+	 * behavior. However, in this case, a valid code with a maximum of 32
+	 * bits can only be formed if q = 0. Any shift with 0 << x always
+	 * results in 0, which forms the correct codeword in this case. For
+	 * performance reasons, this undefined behaviour is not caught.
+	 */
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX_EFX(data[i], data[i-1]);
-	}
-	return 0;
+	return rl + g;	      /* calculate the length of the code word */
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a S_FX_NCOB data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
+ * @brief forms a codeword according to the Golomb code
  *
- * @param data		pointer to a S_FX_NCOB data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value		value to be encoded
+ * @param m		Golomb parameter (have to be bigger than 0)
+ * @param log2_m	is log_2(m) calculate outside function for better
+ *			performance
+ * @param cw		address were the formed code word is stored
  *
- * @returns 0 on success, error otherwise
+ * @returns the length of the formed code word in bits
+ * @note no check if the generated code word is not longer than 32 bits!
  */
 
-static int diff_S_FX_NCOB(struct S_FX_NCOB *data, unsigned int samples, unsigned
-			  int round)
+static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
+			       uint32_t *cw)
 {
-	size_t i;
-	int err;
-
-	if (!data)
-		return -1;
+	uint32_t len0, b, g, q, lg;
+	uint32_t len;
+	uint32_t cutoff;
 
-	err = lossy_rounding_S_FX_NCOB(data, samples, round);
-	if (err)
-		return err;
+	len0 = log2_m + 1;                 /* codeword length in group 0 */
+	cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX_NCOB(data[i], data[i-1]);
+	if (value < cutoff) { /* group 0 */
+		*cw = value;
+		len = len0;
+	} else { /* other groups */
+		g = (value-cutoff) / m; /* this group is which one */
+		b = cutoff << 1;        /* form the base codeword */
+		lg = len0 + g;          /* it has lg remainder bits */
+		q = (1U << g) - 1;      /* prepare the left side in unary */
+		*cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */
+		len = lg + 1;           /* length of the codeword */
 	}
-	return 0;
+	return len;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a S_FX_EFX_NCOB_ECOB data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
+ * @brief generate a code word without an outlier mechanism and put in the
+ *	bitstream
  *
- * @param data		pointer to a S_FX_EFX_NCOB_ECOB data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value		value to encode in the bitstream
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  */
 
-static int diff_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data, unsigned int
-				   samples, unsigned int round)
+static int encode_normal(uint32_t value, int stream_len,
+			 const struct encoder_setupt *setup)
 {
-	size_t i;
-	int err;
-
-	if (!data)
-		return -1;
+	uint32_t code_word, cw_len;
 
-	err = lossy_rounding_S_FX_EFX_NCOB_ECOB(data, samples, round);
-	if (err)
-		return err;
-
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX_EFX_NCOB_ECOB(data[i], data[i-1]);
-	}
+	cw_len = setup->generate_cw_f(value, setup->encoder_par1,
+				      setup->encoder_par2, &code_word);
 
-	return 0;
+	return put_n_bits32(code_word, cw_len, stream_len, setup->bitstream_adr,
+			    setup->max_stream_len);
 }
 
 
 /**
- * @brief model pre-processing and rounding of a uint16_t data buffer
+ * @brief subtract the model from the data, encode the result and put it into
+ *	bitstream, for encoding outlier use the zero escape symbol mechanism
  *
- * @note overwrite the data_buf in-place with the result
- * @note update the model_buf in-place if up_model_buf = NULL
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param model_buf	pointer to the model buffer of the data to process
- * @param up_model_buf	pointer to the updated model buffer can be NULL
- * @param samples	amount of data samples in the data_buf and model_buf buffer
- * @param model_value	model weighting parameter
- * @param round		number of bits to round; if zero no rounding takes place
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
- * @returns 0 on success, error otherwise
+ * @note no check if the data or model are in the allowed range
+ * @note no check if the setup->spillover_par is in the allowed range
  */
 
-static int model_16(uint16_t *data_buf, uint16_t *model_buf, uint16_t *up_model_buf,
-		    unsigned int samples, unsigned int model_value, unsigned int round)
+static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
+			     const struct encoder_setupt *setup)
 {
-	size_t i;
+	data -= model; /* possible underflow is intended */
 
-	if (!data_buf)
-		return -1;
+	data = map_to_pos(data, setup->max_data_bits);
 
-	if (!model_buf)
-		return -1;
+	/* For performance reasons, we check to see if there is an outlier
+	 * before adding one, rather than the other way around:
+	 * data++;
+	 * if (data < setup->spillover_par && data != 0)
+	 *	return ...
+	 */
+	if (data < (setup->spillover_par - 1)) { /* detect non-outlier */
+		data++; /* add 1 to every value so we can use 0 as escape symbol */
+		return encode_normal(data, stream_len, setup);
+	}
 
-	if (model_value > MAX_MODEL_VALUE)
-		return -1;
+	data++; /* add 1 to every value so we can use 0 as escape symbol */
 
-	if (!up_model_buf)
-		up_model_buf = model_buf;
+	/* use zero as escape symbol */
+	stream_len = encode_normal(0, stream_len, setup);
+	if (stream_len <= 0)
+		return stream_len;
 
-	for (i = 0; i < samples; i++) {
-		uint16_t round_input = (uint16_t)round_fwd(data_buf[i], round);
-		uint16_t round_model = (uint16_t)round_fwd(model_buf[i], round);
-		/* possible underflow is intended */
-		data_buf[i] = round_input - round_model; /* TDOO: check if this is the right order */
-		/* round back input because for decompression the accurate data
-		 * are not available
-		 */
-		up_model_buf[i] = (uint16_t)cal_up_model(round_inv(round_input, round),
-							 model_buf[i], model_value);
-	}
-	return 0;
+	/* put the data unencoded in the bitstream */
+	stream_len = put_n_bits32(data, setup->max_data_bits, stream_len,
+				  setup->bitstream_adr, setup->max_stream_len);
+
+	return stream_len;
 }
 
 
 /**
- * @brief model pre-processing and round_input of a uint32_t data buffer
+ * @brief subtract the model from the data, encode the result and put it into
+ *	bitstream, for encoding outlier use the multi escape symbol mechanism
  *
- * @note overwrite the data_buf in-place with the result
- * @note update the model_buf in-place if up_model_buf = NULL
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @param data_buf	pointer to the uint32_t data buffer to process
- * @param model_buf	pointer to the model buffer of the data to process
- * @param samples	amount of data samples in the data_buf and model_buf buffer
- * @param model_value	model weighting parameter
- * @param round		number of bits to round; if zero no rounding takes place
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
- * @returns 0 on success, error otherwise
+ * @note no check if the data or model are in the allowed range
+ * @note no check if the setup->spillover_par is in the allowed range
  */
 
-static int model_32(uint32_t *data_buf, uint32_t *model_buf, unsigned int samples,
-		    unsigned int model_value, unsigned int round)
+static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
+			      const struct encoder_setupt *setup)
 {
-	size_t i;
+	uint32_t unencoded_data;
+	unsigned int unencoded_data_len;
+	uint32_t escape_sym, escape_sym_offset;
 
-	if (!data_buf)
-		return -1;
+	data -= model; /* possible underflow is intended */
 
-	if (!model_buf)
-		return -1;
+	data = map_to_pos(data, setup->max_data_bits);
 
-	if (model_value > MAX_MODEL_VALUE)
-		return -1;
+	if (data < setup->spillover_par) /* detect non-outlier */
+		return  encode_normal(data, stream_len, setup);
 
-	for (i = 0; i < samples; i++) {
-		uint32_t round_input = round_fwd(data_buf[i], round);
-		uint32_t round_model = round_fwd(model_buf[i], round);
-		/* possible underflow is intended */
-		data_buf[i] = round_input - round_model;
-		/* round back input because for decompression the accurate data
-		 * are not available
-		 */
-		model_buf[i] = cal_up_model(round_inv(round_input, round),
-					    model_buf[i], model_value);
-	}
-	return 0;
+	/*
+	 * In this mode we put the difference between the data and the spillover
+	 * threshold value (unencoded_data) after an encoded escape symbol, which
+	 * indicate that the next codeword is unencoded.
+	 * We use different escape symbol depended on the size the needed bit of
+	 * unencoded data:
+	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is spillover_par + 0
+	 * 3, 4 bits needed for unencoded data -> escape symbol is spillover_par + 1
+	 * 5, 6 bits needed for unencoded data -> escape symbol is spillover_par + 2
+	 * and so on
+	 */
+	unencoded_data = data - setup->spillover_par;
+
+	if (!unencoded_data) /* catch __builtin_clz(0) because the result is undefined.*/
+		escape_sym_offset = 0;
+	else
+		escape_sym_offset = (31U - (uint32_t)__builtin_clz(unencoded_data)) >> 1;
+
+	escape_sym = setup->spillover_par + escape_sym_offset;
+	unencoded_data_len = (escape_sym_offset + 1U) << 1;
+
+	/* put the escape symbol in the bitstream */
+	stream_len = encode_normal(escape_sym, stream_len, setup);
+	if (stream_len <= 0)
+		return stream_len;
+
+	/* put the unencoded data in the bitstream */
+	stream_len = put_n_bits32(unencoded_data, unencoded_data_len, stream_len,
+				  setup->bitstream_adr, setup->max_stream_len);
+
+	return stream_len;
 }
 
 
 /**
- * @brief model pre-processing and round_input of a S_FX data buffer
+ * @brief put the value unencoded with(setup->cmp_par_1 bits without any changes
+ *	in the bitstream
  *
- * @note overwrite the data_buf in-place with the result
- * @note update the model_buf in-place if up_model_buf = NULL
+ * @param value		value to put unchanged in the bitstream
+ *	(setup->cmp_par_1 how many bits of the value are used)
+ * @param unused	this parameter is ignored
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @param data_buf	pointer to the S_FX data buffer to process
- * @param model_buf	pointer to the updated model buffer (if NULL model_buf
- *	will be overwrite with the updated model)
- * @param samples	amount of data samples in the data_buf and model_buf buffer
- * @param model_value	model weighting parameter
- * @param round		number of bits to round; if zero no rounding takes place
+ * @returns the bit length of the bitstream with the added unencoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
- * @returns 0 on success, error otherwise
  */
 
-int model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf,
-		      struct S_FX *up_model_buf, unsigned int samples,
-		      unsigned int model_value, unsigned int round)
+static int encode_value_none(uint32_t value, uint32_t unused, int stream_len,
+			     const struct encoder_setupt *setup)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
+	(void)(unused);
 
-	if (!model_buf)
-		return -1;
+	return put_n_bits32(value, setup->encoder_par1, stream_len,
+			    setup->bitstream_adr, setup->max_stream_len);
+}
 
-	if (model_value > MAX_MODEL_VALUE)
-		return -1;
 
-	if (!up_model_buf)  /* overwrite the model buffer if no up_model_buf is set */
-		up_model_buf = model_buf;
+/**
+ * @brief encodes the data with the model and the given setup and put it into
+ *	the bitstream
+ *
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
+ *
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream, CMP_ERROR_HIGH_VALUE if
+ *	the value or the model is bigger than the max_used_bits parameter allows
+ */
 
+static int encode_value(uint32_t data, uint32_t model, int stream_len,
+			const struct encoder_setupt *setup)
+{
+	uint32_t mask = ~(0xFFFFFFFFU >> (32-setup->max_data_bits));
 
-	for (i = 0; i < samples; i++) {
-		struct S_FX round_data = data_buf[i];
-		struct S_FX round_model = model_buf[i];
-		int err;
+	/* lossy rounding of the data if lossy_par > 0 */
+	data = round_fwd(data, setup->lossy_par);
+	model = round_fwd(model, setup->lossy_par);
 
-		err = lossy_rounding_S_FX(&round_data, 1, round);
-		if (err)
-			return err;
+	if (data & mask || model & mask) {
+		debug_print("Error: The data or the model of the data are bigger than expected.\n");
+		return CMP_ERROR_HIGH_VALUE;
+	}
 
-		err = lossy_rounding_S_FX(&round_model, 1, round);
-		if (err)
-			return err;
+	return setup->encode_method_f(data, model, stream_len, setup);
+}
 
-		/* possible underflow is intended */
-		data_buf[i] = sub_S_FX(round_data, round_model);
 
-		/* round back input because for decompression the accurate data
-		 * are not available
-		 */
-		err = de_lossy_rounding_S_FX(&round_data, 1, round);
-		if (err)
-			return err;
-		up_model_buf[i] = cal_up_model_S_FX(round_data, model_buf[i],
-						    model_value);
-	}
+/**
+ * @brief calculate the maximum length of the bitstream/icu_output_buf in bits
+ * @note we round down to the next 4-byte allied address because we access the
+ *	cmp_buffer in uint32_t words
+ *
+ * @param buffer_length	length of the icu_output_buf in samples
+ * @param data_type	used compression data type
+ *
+ * @returns buffer size in bits
+ *
+ */
 
-	return 0;
+static uint32_t cmp_buffer_length_to_bits(uint32_t buffer_length, enum cmp_data_type data_type)
+{
+	return (cmp_cal_size_of_data(buffer_length, data_type) & ~0x3U) * CHAR_BIT;
 }
 
 
 /**
- * @brief data pre-processing to decorrelate the data
+ * @brief configure an encoder setup structure to have a setup to encode a vale
  *
- * @param cfg	configuration contains all parameters required for compression
+ * @param setup		pointer to the encoder setup
+ * @param cmp_par	compression parameter
+ * @param spillover	spillover_par parameter
+ * @param lossy_par	lossy compression parameter
+ * @param max_data_bits	how many bits are needed to represent the highest possible value
+ * @param cfg		pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns 0 on success; otherwise error
  */
 
-int cmp_pre_process(struct cmp_cfg *cfg)
+static int configure_encoder_setup(struct encoder_setupt *setup,
+				   uint32_t cmp_par, uint32_t spillover,
+				   uint32_t lossy_par, uint32_t max_data_bits,
+				   const struct cmp_cfg *cfg)
 {
-	if (!cfg)
+	if (!setup)
 		return -1;
 
-	if (cfg->samples == 0)
-		return 0;
+	if (!cfg)
+		return -1;
 
-	if (!cfg->input_buf)
+	setup->encoder_par1 = cmp_par;
+	setup->spillover_par = spillover;
+	if (max_data_bits > 32) {
+		debug_print("Error: max_data_bits parameter is bigger than 32 bits.\n");
 		return -1;
+	}
+	setup->max_data_bits = max_data_bits;
+	setup->lossy_par = lossy_par;
 
 	switch (cfg->cmp_mode) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return 0; /* in raw mode no pre-processing is necessary */
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-		return model_16((uint16_t *)cfg->input_buf, (uint16_t *)cfg->model_buf,
-				(uint16_t *)cfg->icu_new_model_buf, cfg->samples,
-				cfg->model_value, cfg->round);
-		break;
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return diff_16((uint16_t *)cfg->input_buf, cfg->samples,
-			       cfg->round);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-		return model_S_FX((struct S_FX *)cfg->input_buf, (struct S_FX *)cfg->model_buf,
-				  (struct S_FX *)cfg->icu_new_model_buf, cfg->samples,
-				  cfg->model_value, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return diff_S_FX((struct S_FX *)cfg->input_buf, cfg->samples, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return diff_S_FX_EFX((struct S_FX_EFX *)cfg->input_buf,
-				     cfg->samples, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return diff_S_FX_NCOB((struct S_FX_NCOB *)cfg->input_buf,
-				      cfg->samples, cfg->round);
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_DIFF_ZERO:
+		setup->encode_method_f = &encode_value_zero;
+		if (ilog_2(cmp_par) < 0)
+			return -1;
+		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
 		break;
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return diff_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)cfg->input_buf,
-					       cfg->samples, cfg->round);
+	case CMP_MODE_MODEL_MULTI:
+	case CMP_MODE_DIFF_MULTI:
+		setup->encode_method_f = &encode_value_multi;
+		if (ilog_2(cmp_par) < 0)
+			return -1;
+		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
 		break;
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-		return model_32((uint32_t *)cfg->input_buf, (uint32_t *)cfg->model_buf,
-				cfg->samples, cfg->model_value, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return diff_32((uint32_t *)cfg->input_buf, cfg->samples, cfg->round);
+	case CMP_MODE_STUFF:
+		setup->encode_method_f = &encode_value_none;
+		setup->max_data_bits = cmp_par;
 		break;
 	default:
-		debug_print("Error: Compression mode not supported.\n");
+		return -1;
 	}
 
-	return -1;
-}
-
-
-static uint8_t map_to_pos_alg_8(int8_t value_to_map)
-{
-	if (value_to_map < 0)
-		/* NOTE: possible integer overflow is intended */
-		return (uint8_t)((-value_to_map) * 2 - 1);
-	else
-		/* NOTE: possible integer overflow is intended */
-		return (uint8_t)(value_to_map * 2);
-}
-
-
-static uint16_t map_to_pos_alg_16(int16_t value_to_map)
-{
-	if (value_to_map < 0)
-		/* NOTE: possible integer overflow is intended */
-		return (uint16_t)((-value_to_map) * 2 - 1);
+	/* for encoder_par1 which are a power of two we can use the faster rice_encoder */
+	if (is_a_pow_of_2(setup->encoder_par1))
+		setup->generate_cw_f = &rice_encoder;
 	else
-		/* NOTE: possible integer overflow is intended */
-		return (uint16_t)(value_to_map * 2);
-}
+		setup->generate_cw_f = &golomb_encoder;
 
+	setup->bitstream_adr = cfg->icu_output_buf;
+	setup->max_stream_len = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
 
-static uint32_t map_to_pos_alg_32(int32_t value_to_map)
-{
-	if (value_to_map < 0)
-		/* NOTE: possible integer overflow is intended */
-		return (uint32_t)((-value_to_map) * 2 - 1);
-	else
-		/* NOTE: possible integer overflow is intended */
-		return (uint32_t)(value_to_map * 2);
+	return 0;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a 16 bit buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress imagette data
  *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream, CMP_ERROR_HIGH_VALUE if the value or the model is
+ *	bigger than the max_used_bits parameter allows
  */
 
-static int map_to_pos_16(uint16_t *data_buf, uint32_t samples, int zero_mode_used)
+static int compress_imagette(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
+	struct encoder_setupt setup;
+
+	uint16_t *data_buf = cfg->input_buf;
+	uint16_t *model_buf = cfg->model_buf;
+	uint16_t model = 0;
+	uint16_t *next_model_p = data_buf;
+	uint16_t *up_model_buf = NULL;
+
+	if (cfg->samples == 0)
+		return 0;
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+		up_model_buf = cfg->icu_new_model_buf;
+	}
 
-	if (!data_buf)
+	err = configure_encoder_setup(&setup, cfg->golomb_par, cfg->spill,
+				      cfg->round, max_used_bits.nc_imagette, cfg);
+	if (err)
 		return -1;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i] = map_to_pos_alg_16(data_buf[i]);
-		if (zero_mode_used)
-			data_buf[i] += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i], model, stream_len, &setup);
+		if (stream_len <= 0)
+			break;
+
+		if (up_model_buf)
+			up_model_buf[i] = cmp_up_model(data_buf[i], model, cfg->model_value,
+						       setup.lossy_par);
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a 32 bit buffer
+ * @brief compress the multi-entry packet header structure and sets the data,
+ *	model and up_model pointers to the data after the header
  *
- * @note overwrite the data_buf in-place with the result
+ * @param data		pointer to a pointer pointing to the data to be compressed
+ * @param model		pointer to a pointer pointing to the model of the data
+ * @param up_model	pointer to a pointer pointing to the updated model buffer
+ * @param cfg		pointer to the compression configuration structure
  *
- * @param data_buf	pointer to the uint32_t data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @returns the bit length of the bitstream on success; negative on error,
  *
- * @returns 0 on success, error otherwise
+ * @note the (void **) cast relies on all pointer types having the same internal
+ *	representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html
  */
 
-static int map_to_pos_32(uint32_t *data_buf, uint32_t samples, int
-			 zero_mode_used)
+static int compress_multi_entry_hdr(void **data, void **model, void **up_model,
+				    const struct cmp_cfg *cfg)
 {
-	size_t i;
-
-	if (!data_buf)
+	if (cfg->buffer_length < 1)
 		return -1;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i] = map_to_pos_alg_32(data_buf[i]);
-		if (zero_mode_used)
-			data_buf[i] += 1;
+	if (*data) {
+		if (cfg->icu_output_buf)
+			memcpy(cfg->icu_output_buf, *data, MULTI_ENTRY_HDR_SIZE);
+		*data = (uint8_t *)*data + MULTI_ENTRY_HDR_SIZE;
 	}
-	return 0;
+
+	if (*model)
+		*model = (uint8_t *)*model + MULTI_ENTRY_HDR_SIZE;
+
+	if (*up_model) {
+		if (*data)
+			memcpy(*up_model, *data, MULTI_ENTRY_HDR_SIZE);
+		*up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE;
+	}
+
+	return MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress short normal light flux (S_FX) data
  *
- * @param data_buf	pointer to the S_FX data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-int map_to_pos_S_FX(struct S_FX *data_buf, uint32_t samples, int
-			   zero_mode_used)
+static int compress_s_fx(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
+	struct s_fx *data_buf = cfg->input_buf;
+	struct s_fx *model_buf = cfg->model_buf;
+	struct s_fx *up_model_buf = NULL;
+	struct s_fx *next_model_p;
+	struct s_fx model;
+	struct encoder_setupt setup_exp_flag, setup_fx;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
 
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX_EFX buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress S_FX_EFX data
  *
- * @param data_buf	pointer to the S_FX_EFX data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static int map_to_pos_S_FX_EFX(struct S_FX_EFX *data_buf, uint32_t samples, int
-			       zero_mode_used)
+static int compress_s_fx_efx(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
+	struct s_fx_efx *data_buf = cfg->input_buf;
+	struct s_fx_efx *model_buf = cfg->model_buf;
+	struct s_fx_efx *up_model_buf = NULL;
+	struct s_fx_efx *next_model_p;
+	struct s_fx_efx model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_efx;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].EFX = map_to_pos_alg_32(data_buf[i].EFX);
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.s_efx, cfg);
+	if (err)
+		return -1;
 
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
-			data_buf[i].EFX += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX_NCOB buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress S_FX_NCOB data
  *
- * @param data_buf	pointer to the S_FX_NCOB data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static int map_to_pos_S_FX_NCOB(struct S_FX_NCOB *data_buf, uint32_t samples,
-				int zero_mode_used)
+static int compress_s_fx_ncob(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
+	struct s_fx_ncob *data_buf = cfg->input_buf;
+	struct s_fx_ncob *model_buf = cfg->model_buf;
+	struct s_fx_ncob *up_model_buf = NULL;
+	struct s_fx_ncob *next_model_p;
+	struct s_fx_ncob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = map_to_pos_alg_32(data_buf[i].NCOB_Y);
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.s_ncob, cfg);
+	if (err)
+		return -1;
 
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
-			data_buf[i].NCOB_X += 1;
-			data_buf[i].NCOB_Y += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX_EFX_NCOB_ECOB buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress S_FX_EFX_NCOB_ECOB data
  *
- * @param data_buf	pointer to the S_FX_EFX_NCOB_ECOB data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static int map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					 uint32_t samples, int zero_mode_used)
+static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = map_to_pos_alg_32(data_buf[i].NCOB_Y);
-		data_buf[i].EFX = map_to_pos_alg_32(data_buf[i].EFX);
-		data_buf[i].ECOB_X = map_to_pos_alg_32(data_buf[i].ECOB_X);
-		data_buf[i].ECOB_Y = map_to_pos_alg_32(data_buf[i].ECOB_Y);
-
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
-			data_buf[i].NCOB_X += 1;
-			data_buf[i].NCOB_Y += 1;
-			data_buf[i].EFX += 1;
-			data_buf[i].ECOB_X += 1;
-			data_buf[i].ECOB_Y += 1;
+	struct s_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct s_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct s_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct s_fx_efx_ncob_ecob *next_model_p;
+	struct s_fx_efx_ncob_ecob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_efx,
+			      setup_ecob;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.s_ncob, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.s_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				      cfg->round, max_used_bits.s_ecob, cfg);
+	if (err)
+		return -1;
+
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range
+ * @brief compress F_FX data
  *
- * @note change the data_buf in-place
+ * @param cfg	pointer to the compression configuration structure
  *
- * @param cfg	configuration contains all parameters required for compression
- *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-int cmp_map_to_pos(struct cmp_cfg *cfg)
+static int compress_f_fx(const struct cmp_cfg *cfg)
 {
-	int zero_mode_used;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!cfg)
-		return -1;
+	struct f_fx *data_buf = cfg->input_buf;
+	struct f_fx *model_buf = cfg->model_buf;
+	struct f_fx *up_model_buf = NULL;
+	struct f_fx *next_model_p;
+	struct f_fx model;
+	struct encoder_setupt setup_fx;
 
-	if (cfg->samples == 0)
-		return 0;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (!cfg->input_buf)
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
 		return -1;
 
-	zero_mode_used = zero_escape_mech_is_used(cfg->cmp_mode);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
 
-	switch (cfg->cmp_mode) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return 0; /* in raw mode no mapping is necessary */
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return map_to_pos_16((uint16_t *)cfg->input_buf, cfg->samples,
-				     zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return map_to_pos_S_FX((struct S_FX *)cfg->input_buf,
-				       cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return map_to_pos_S_FX_EFX((struct S_FX_EFX *)cfg->input_buf,
-					   cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return map_to_pos_S_FX_NCOB((struct S_FX_NCOB *)cfg->input_buf,
-					    cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return map_to_pos_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)cfg->input_buf,
-						     cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return map_to_pos_32((uint32_t *)cfg->input_buf, cfg->samples,
-				     zero_mode_used);
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+		}
 
-	}
+		if (i >= cfg->samples-1)
+			break;
 
-	return -1;
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
 /**
- * @brief forms the codeword accurate to the Rice code and returns its length
+ * @brief compress F_FX_EFX data
  *
- * @param m		Golomb parameter, only m's which are power of 2 and >0
- *			are allowed!
- * @param log2_m	Rice parameter, is log_2(m) calculate outside function
- *			for better performance
- * @param value		value to be encoded
- * @param cw		address were the encode code word is stored
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns length of the encoded code word in bits
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static unsigned int Rice_encoder(unsigned int value, unsigned int m,
-				 unsigned int log2_m, unsigned int *cw)
+static int compress_f_fx_efx(const struct cmp_cfg *cfg)
 {
-	unsigned int g;  /* quotient of value/m */
-	unsigned int q;  /* quotient code without ending zero */
-	unsigned int r;  /* remainder of value/m */
-	unsigned int rl; /* remainder length */
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	g = value >> log2_m; /* quotient, number of leading bits */
-	q = (1U << g) - 1;    /* prepare the quotient code without ending zero */
+	struct f_fx_efx *data_buf = cfg->input_buf;
+	struct f_fx_efx *model_buf = cfg->model_buf;
+	struct f_fx_efx *up_model_buf = NULL;
+	struct f_fx_efx *next_model_p;
+	struct f_fx_efx model;
+	struct encoder_setupt setup_fx, setup_efx;
 
-	r = value & (m-1);   /* calculate the remainder */
-	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the
-			      * quotient code)
-			      */
-	*cw = (q << rl) | r; /* put the quotient and remainder code together */
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	return rl + g;	      /* calculate the length of the code word */
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.f_efx, cfg);
+	if (err)
+		return -1;
+
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
 /**
- * @brief forms the codeword accurate to the Golomb code and returns its length
+ * @brief compress F_FX_NCOB data
  *
- * @param m		Golomb parameter, only m's which are power of 2 and >0
- *			are allowed!
- * @param log2_m	is log_2(m) calculate outside function for better
- *			performance
- * @param value		value to be encoded
- * @param cw		address were the encode code word is stored
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns length of the encoded code word in bits
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static unsigned int Golomb_encoder(unsigned int value, unsigned int m,
-				   unsigned int log2_m, unsigned int *cw)
+static int compress_f_fx_ncob(const struct cmp_cfg *cfg)
 {
-	unsigned int len0, b, g, q, lg;
-	unsigned int len;
-	unsigned int cutoff;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	len0 = log2_m + 1; /* codeword length in group 0 */
-	cutoff = (1U << (log2_m+1)) - m; /* members in group 0 */
-	if (cutoff == 0) /* for powers of two we fix cutoff = m */
-		cutoff = m;
+	struct f_fx_ncob *data_buf = cfg->input_buf;
+	struct f_fx_ncob *model_buf = cfg->model_buf;
+	struct f_fx_ncob *up_model_buf = NULL;
+	struct f_fx_ncob *next_model_p;
+	struct f_fx_ncob model;
+	struct encoder_setupt setup_fx, setup_ncob;
 
-	if (value < cutoff) { /* group 0 */
-		*cw = value;
-		len = len0;
-	} else { /* other groups */
-		b = (cutoff << 1); /* form the base codeword */
-		g = (value-cutoff)/m; /* this group is which one  */
-		lg = len0 + g; /* it has lg remainder bits */
-		q = (1U << g) - 1; /* prepare the left side in unary */
-		*cw = (q << (len0+1)) + b + (value-cutoff)-g*m; /* composed codeword */
-		len = lg + 1; /* length of the codeword */
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
 	}
-	return len;
-}
 
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.f_ncob, cfg);
+	if (err)
+		return -1;
 
-typedef unsigned int (*encoder_ptr)(unsigned int, unsigned int, unsigned int,
-				    unsigned int*);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+		}
 
-static encoder_ptr select_encoder(unsigned int golomb_par)
-{
-	if (!golomb_par)
-		return NULL;
+		if (i >= cfg->samples-1)
+			break;
 
-	if (is_a_pow_of_2(golomb_par))
-		return &Rice_encoder;
-	else
-		return &Golomb_encoder;
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
 /**
- * @brief    safe (but slow) way to put the value of up to 32 bits into a
- *           bitstream accessed as 32-bit RAM in big endian
- * @param    value      the value to put, it will be masked
- * @param    bitOffset  bit index where the bits will be put, seen from the very
- *			beginning of the bitstream
- * @param    nBits      number of bits to put in the bitstream
- * @param    destAddr   this is the pointer to the beginning of the bitstream
- * @param    dest_len   length of the bitstream buffer (starting at destAddr)
- * @returns  TODO number of bits written, 0 if the number was too big, -2 if the
- *	     destAddr buffer is to small to store the bitstream
- * @note     works in SRAM2
+ * @brief compress F_FX_EFX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static unsigned int put_n_bits32(unsigned int value, unsigned int bitOffset,
-				 unsigned int nBits, unsigned int *destAddr,
-				 unsigned int dest_len)
+static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 {
-	unsigned int *localAddr;
-	unsigned int bitsLeft, shiftRight, shiftLeft, localEndPos;
-	unsigned int mask;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!destAddr)
-		return nBits;
+	struct f_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct f_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct f_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct f_fx_efx_ncob_ecob *next_model_p;
+	struct f_fx_efx_ncob_ecob model;
+	struct encoder_setupt setup_fx, setup_ncob, setup_efx, setup_ecob;
 
-	/* check if destination buffer is large enough */
-	/* TODO: adapt that to the other science products */
-	if ((bitOffset + nBits) > ((dest_len&~0x1U)*16)) {
-		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
-		return -2U;
-	}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	/* leave in case of erroneous input */
-	if (nBits == 0)
-		return 0;
-	if (nBits > 32)
-		return 0;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	/* separate the bitOffset into word offset (set localAddr pointer) and local bit offset (bitsLeft) */
-	localAddr = destAddr + (bitOffset >> 5);
-	bitsLeft = bitOffset & 0x1f;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	/* (M) we mask the value first to match its size in nBits */
-	/* the calculations can be re-used in the unsegmented code, so we have no overhead */
-	shiftRight = 32 - nBits;
-	mask = 0xffffffff >> shiftRight;
-	value &= mask;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.f_ncob, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.f_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				      cfg->round, max_used_bits.f_ecob, cfg);
+	if (err)
+		return -1;
 
-	/* to see if we need to split the value over two words we need the right end position */
-	localEndPos = bitsLeft + nBits;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
+		}
 
-	if (localEndPos <= 32) {
-		/*         UNSEGMENTED
-		 *
-		 *|-----------|XXXXX|----------------|
-		 *   bitsLeft    n       bitsRight
-		 *
-		 *  -> to get the mask:
-		 *  shiftRight = bitsLeft + bitsRight = 32 - n
-		 *  shiftLeft = bitsRight
-		 *
-		 */
+		if (i >= cfg->samples-1)
+			break;
 
-		/* shiftRight = 32 - nBits; */ /* see (M) above! */
-		shiftLeft = shiftRight - bitsLeft;
+		model = next_model_p[i];
+	}
+	return stream_len;
+}
 
-		/* generate the mask, the bits for the values will be true */
-		/* mask = (0xffffffff >> shiftRight) << shiftLeft; */ /* see (M) above! */
-		mask <<= shiftLeft;
 
-		/* clear the destination with inverse mask */
-		*(localAddr) &= ~mask;
+/**
+ * @brief compress L_FX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-		/* assign the value */
-		*(localAddr) |= (value << (32 - localEndPos)); /* NOTE: 32-localEndPos = shiftLeft can be simplified */
+static int compress_l_fx(const struct cmp_cfg *cfg)
+{
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	} else {
-		/*                             SEGMENTED
-		 *
-		 *|-----------------------------|XXX| |XX|------------------------------|
-		 *          bitsLeft              n1   n2          bitsRight
-		 *
-		 *  -> to get the mask part 1:
-		 *  shiftright = bitsleft
-		 *  n1 = n - (bitsleft + n - 32) = 32 - bitsleft
-		 *
-		 *  -> to get the mask part 2:
-		 *  n2 = bitsleft + n - 32
-		 *  shiftleft = 32 - n2 = 32 - (bitsleft + n - 32) = 64 - bitsleft - n
-		 *
-		 */
+	struct l_fx *data_buf = cfg->input_buf;
+	struct l_fx *model_buf = cfg->model_buf;
+	struct l_fx *up_model_buf = NULL;
+	struct l_fx *next_model_p;
+	struct l_fx model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_fx_var;
 
-		unsigned int n2 = bitsLeft + nBits - 32;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-		/* part 1: */
-		shiftRight = bitsLeft;
-		mask = 0xffffffff >> shiftRight;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-		/* clear the destination with inverse mask */
-		*(localAddr) &= ~mask;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-		/* assign the value part 1 */
-		*(localAddr) |= (value >> n2);
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
+		return -1;
 
-		/* part 2: */
-		/* adjust address */
-		localAddr += 1;
-		shiftLeft = 64 - bitsLeft - nBits;
-		mask = 0xffffffff << shiftLeft;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+		}
 
-		/* clear the destination with inverse mask */
-		*(localAddr) &= ~mask;
+		if (i >= cfg->samples-1)
+			break;
 
-		/* assign the value part 2 */
-		*(localAddr) |= (value << (32 - n2));
+		model = next_model_p[i];
 	}
-	return nBits;
+	return stream_len;
 }
 
 
-struct encoder_struct {
-	encoder_ptr encoder;
-	unsigned int log2_golomb_par; /* pre-calculated for performance increase */
-	uint32_t cmp_size; /* Compressed data size; measured in bits */
-};
-
+/**
+ * @brief compress L_FX_EFX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-static int encode_raw(struct cmp_cfg *cfg, struct encoder_struct *enc)
+static int compress_l_fx_efx(const struct cmp_cfg *cfg)
 {
-	size_t cmp_size_in_bytes;
-
-	if (!cfg)
-		return -1;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!cfg->icu_output_buf)
-		return -1;
+	struct l_fx_efx *data_buf = cfg->input_buf;
+	struct l_fx_efx *model_buf = cfg->model_buf;
+	struct l_fx_efx *up_model_buf = NULL;
+	struct l_fx_efx *next_model_p;
+	struct l_fx_efx model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_efx, setup_fx_var;
 
-	if (!cfg->input_buf)
-		return -1;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	cmp_size_in_bytes = cfg->samples * size_of_a_sample(cfg->cmp_mode);
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	enc->cmp_size = cmp_size_in_bytes * CHAR_BIT; /* cmp_size is measured in bits */
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (cmp_size_in_bytes > cfg->buffer_length * sizeof(uint16_t))
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.l_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
 		return -1;
 
-	memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size_in_bytes);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+		}
 
-	return 0;
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
-static int encode_raw_16(struct cmp_cfg *cfg, struct encoder_struct *enc)
+/**
+ * @brief compress L_FX_NCOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_l_fx_ncob(const struct cmp_cfg *cfg)
 {
 	int err;
+	int stream_len = 0;
 	size_t i;
 
-	enc->cmp_size = 0;
+	struct l_fx_ncob *data_buf = cfg->input_buf;
+	struct l_fx_ncob *model_buf = cfg->model_buf;
+	struct l_fx_ncob *up_model_buf = NULL;
+	struct l_fx_ncob *next_model_p;
+	struct l_fx_ncob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob,
+			      setup_fx_var, setup_cob_var;
 
-	for (i = 0; i < cfg->samples; i++) {
-		uint16_t *p = cfg->input_buf;
-		err = put_n_bits32(p[i], enc->cmp_size, 16, cfg->icu_output_buf,
-				   cfg->buffer_length);
-		if (err <= 0)
-			return err;
-		enc->cmp_size += 16;
-	}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	return 0;
-}
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-static int encode_raw_S_FX(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	int err;
-
-	err = encode_raw(cfg, enc);
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
 	if (err)
-		return err;
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.l_ncob, cfg);
+	if (err)
+		return -1;
+	/* we use compression parameter for both variance data fields */
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_cob_variance, cfg);
+	if (err)
+		return -1;
 
-#if defined(__LITTLE_ENDIAN)
-	{
-		size_t i;
-		for (i = 0; i < cfg->samples; i++) {
-			struct S_FX *output_buf = (void *)cfg->icu_output_buf;
-			output_buf[i].FX = cpu_to_be32(output_buf[i].FX);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_x_variance, model.cob_x_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_y_variance, model.cob_y_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+			up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-#endif
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_normal(uint32_t value_to_encode, struct cmp_cfg *cfg,
-			 struct encoder_struct *enc)
+/**
+ * @brief compress L_FX_EFX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 {
-	unsigned int code_word;
-	unsigned int cw_len;
 	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!enc->encoder)
-		return -1;
-
-	cw_len = enc->encoder(value_to_encode, cfg->golomb_par,
-			      enc->log2_golomb_par, &code_word);
-
-	err = put_n_bits32(code_word, enc->cmp_size, cw_len,
-			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0)
-		return err;
-
-	enc->cmp_size += cw_len;
+	struct l_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct l_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct l_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct l_fx_efx_ncob_ecob *next_model_p;
+	struct l_fx_efx_ncob_ecob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_efx,
+			      setup_ecob, setup_fx_var, setup_cob_var;
 
-	return 0;
-}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-static int encode_outlier_zero(uint32_t value_to_encode, int max_bits,
-			       struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	int err;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (max_bits > 32)
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
+	if (err)
 		return -1;
-
-	/* use zero as escape symbol */
-	err = encode_normal(0, cfg, enc);
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
 	if (err)
-		return err;
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.l_ncob, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.l_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				      cfg->round, max_used_bits.l_ecob, cfg);
+	if (err)
+		return -1;
+	/* we use compression parameter for both variance data fields */
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_cob_variance, cfg);
+	if (err)
+		return -1;
 
-	/* put the data unencoded in the bitstream */
-	err = put_n_bits32(value_to_encode, enc->cmp_size, max_bits,
-			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0)
-		return err;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_x_variance, model.cob_x_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_y_variance, model.cob_y_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+			up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+		}
 
-	enc->cmp_size += max_bits;
+		if (i >= cfg->samples-1)
+			break;
 
-	return 0;
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
-static int cal_multi_offset(unsigned int unencoded_data)
-{
-	if (unencoded_data <= 0x3)
-		return 0;
-	if (unencoded_data <= 0xF)
-		return 1;
-	if (unencoded_data <= 0x3F)
-		return 2;
-	if (unencoded_data <= 0xFF)
-		return 3;
-	if (unencoded_data <= 0x3FF)
-		return 4;
-	if (unencoded_data <= 0xFFF)
-		return 5;
-	if (unencoded_data <= 0x3FFF)
-		return 6;
-	if (unencoded_data <= 0xFFFF)
-		return 7;
-	if (unencoded_data <= 0x3FFFF)
-		return 8;
-	if (unencoded_data <= 0xFFFFF)
-		return 9;
-	if (unencoded_data <= 0x3FFFFF)
-		return 10;
-	if (unencoded_data <= 0xFFFFFF)
-		return 11;
-	if (unencoded_data <= 0x3FFFFFF)
-		return 12;
-	if (unencoded_data <= 0xFFFFFFF)
-		return 13;
-	if (unencoded_data <= 0x3FFFFFFF)
-		return 14;
-	else
-		return 15;
-}
-
+/**
+ * @brief compress offset data from the normal cameras
+ *
+ * @param cfg	pointer to the compression configuration structure
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-static int encode_outlier_multi(uint32_t value_to_encode, struct cmp_cfg *cfg,
-				struct encoder_struct *enc)
+static int compress_nc_offset(const struct cmp_cfg *cfg)
 {
-	uint32_t unencoded_data;
-	unsigned int unencoded_data_len;
-	uint32_t escape_sym;
-	int escape_sym_offset;
 	int err;
+	int stream_len = 0;
+	size_t i;
 
-	/*
-	 * In this mode we put the difference between the data and the spillover
-	 * threshold value (unencoded_data) after a encoded escape symbol, which
-	 * indicate that the next codeword is unencoded.
-	 * We use different escape symbol depended on the size the needed bit of
-	 * unencoded data:
-	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is spill + 0
-	 * 3, 4 bits needed for unencoded data -> escape symbol is spill + 1
-	 * ..
-	 */
-
-	unencoded_data = value_to_encode - cfg->spill;
-	escape_sym_offset = cal_multi_offset(unencoded_data);
-	escape_sym  = cfg->spill + escape_sym_offset;
-	unencoded_data_len = (escape_sym_offset + 1) * 2;
-
-	/* put the escape symbol in the bitstream */
-	err = encode_normal(escape_sym, cfg, enc);
-	if (err)
-		return err;
-
-	/* put the unencoded data in the bitstream */
-	err = put_n_bits32(unencoded_data, enc->cmp_size, unencoded_data_len,
-			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0)
-		return err;
-
-	enc->cmp_size += unencoded_data_len;
-
-	return 0;
-}
-
-static int encode_outlier(uint32_t value_to_encode, int bit_len, struct cmp_cfg
-			  *cfg, struct encoder_struct *enc)
-{
-	if (multi_escape_mech_is_used(cfg->cmp_mode))
-		return encode_outlier_multi(value_to_encode, cfg, enc);
-
-	if (zero_escape_mech_is_used(cfg->cmp_mode))
-		return encode_outlier_zero(value_to_encode, bit_len, cfg, enc);
-
-	return -1;
-}
-
+	struct nc_offset *data_buf = cfg->input_buf;
+	struct nc_offset *model_buf = cfg->model_buf;
+	struct nc_offset *up_model_buf = NULL;
+	struct nc_offset *next_model_p;
+	struct nc_offset model;
+	struct encoder_setupt setup_mean, setup_var;
 
-int encode_value(uint32_t value_to_encode, int bit_len, struct cmp_cfg *cfg,
-		 struct encoder_struct *enc)
-{
-	/* 0 is an outlier in case of a zero-escape mechanism, because an
-	 * overflow can occur by incrementing by one
-	 */
-	if (value_to_encode >= cfg->spill ||
-	    (zero_escape_mech_is_used(cfg->cmp_mode) && value_to_encode == 0))
-		return encode_outlier(value_to_encode, bit_len, cfg, enc);
-	else
-		return encode_normal(value_to_encode, cfg, enc);
-}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-static int encode_16(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	size_t i;
-	uint16_t *data_to_encode;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (!cfg)
+	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				      cfg->round, max_used_bits.nc_offset_mean, cfg);
+	if (err)
 		return -1;
-
-	if (!enc)
+	err = configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				      cfg->round, max_used_bits.nc_offset_variance, cfg);
+	if (err)
 		return -1;
 
-	data_to_encode = cfg->input_buf;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].mean, model.mean,
+					  stream_len, &setup_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].variance, model.variance,
+					  stream_len, &setup_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, model.mean,
+				cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, model.variance,
+				cfg->model_value, setup_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err = encode_value(data_to_encode[i], 16, cfg, enc);
-		if (err)
-			return err;
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_32(struct cmp_cfg *cfg, struct encoder_struct *enc)
+/**
+ * @brief compress background data from the normal cameras
+ *
+ * @param cfg	pointer to the compression configuration structure
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_nc_background(const struct cmp_cfg *cfg)
 {
-	uint32_t *data_to_encode = cfg->input_buf;
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err = encode_value(data_to_encode[i], 32, cfg, enc);
-		if (err)
-			return err;
-	}
-	return 0;
-}
+	struct nc_background *data_buf = cfg->input_buf;
+	struct nc_background *model_buf = cfg->model_buf;
+	struct nc_background *up_model_buf = NULL;
+	struct nc_background *next_model_p;
+	struct nc_background model;
+	struct encoder_setupt setup_mean, setup_var, setup_pix;
 
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-static int encode_S_FX(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	struct S_FX *data_to_encode = cfg->input_buf;
-	size_t i;
-	struct cmp_cfg cfg_exp_flag = *cfg;
-	struct encoder_struct enc_exp_flag = *enc;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	cfg_exp_flag.golomb_par = GOLOMB_PAR_EXPOSURE_FLAGS;
-	enc_exp_flag.log2_golomb_par = ilog_2(GOLOMB_PAR_EXPOSURE_FLAGS);
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
+	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				      cfg->round, max_used_bits.nc_background_mean, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				      cfg->round, max_used_bits.nc_background_variance, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+				      cfg->round, max_used_bits.nc_background_outlier_pixels, cfg);
+	if (err)
+		return -1;
 
-		/* err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, &cfg_exp_flag, enc); */
-		err = encode_normal(data_to_encode[i].EXPOSURE_FLAGS, &cfg_exp_flag, &enc_exp_flag);
-		if (err)
-			return err;
-		enc->cmp_size = enc_exp_flag.cmp_size;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].mean, model.mean,
+					  stream_len, &setup_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].variance, model.variance,
+					  stream_len, &setup_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].outlier_pixels, model.outlier_pixels,
+					  stream_len, &setup_pix);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, model.mean,
+				cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, model.variance,
+				cfg->model_value, setup_var.lossy_par);
+			up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, model.outlier_pixels,
+				cfg->model_value, setup_pix.lossy_par);
+		}
 
-		enc->log2_golomb_par = ilog_2(cfg->golomb_par);
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+		if (i >= cfg->samples-1)
+			break;
 
-		enc_exp_flag.cmp_size = enc->cmp_size;
+		model = next_model_p[i];
 	}
-
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_S_FX_EFX(struct cmp_cfg *cfg, struct encoder_struct *enc)
+/**
+ * @brief compress smearing data from the normal cameras
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_smearing(const struct cmp_cfg *cfg)
 {
-	struct S_FX_EFX *data_to_encode = cfg->input_buf;
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
+	struct smearing *data_buf = cfg->input_buf;
+	struct smearing *model_buf = cfg->model_buf;
+	struct smearing *up_model_buf = NULL;
+	struct smearing *next_model_p;
+	struct smearing model;
+	struct encoder_setupt setup_mean, setup_var_mean, setup_pix;
 
-		err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, cfg, enc);
-		if (err)
-			return err;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-		err = encode_value(data_to_encode[i].EFX, 32, cfg, enc);
-		if (err)
-			return err;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
 	}
-	return 0;
-}
-
 
-static int encode_S_FX_NCOB(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	struct S_FX_NCOB *data_to_encode = cfg->input_buf;
-	size_t i;
-
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
-
-		err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, cfg, enc);
-		if (err)
-			return err;
+	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				      cfg->round, max_used_bits.smeating_mean, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_var_mean, cfg->cmp_par_variance, cfg->spill_variance,
+				      cfg->round, max_used_bits.smeating_variance_mean, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+				      cfg->round, max_used_bits.smearing_outlier_pixels, cfg);
+	if (err)
+		return -1;
 
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].mean, model.mean,
+					  stream_len, &setup_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].variance_mean, model.variance_mean,
+					  stream_len, &setup_var_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].outlier_pixels, model.outlier_pixels,
+					  stream_len, &setup_pix);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, model.mean,
+				cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance_mean = cmp_up_model(data_buf[i].variance_mean, model.variance_mean,
+				cfg->model_value, setup_var_mean.lossy_par);
+			up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, model.outlier_pixels,
+				cfg->model_value, setup_pix.lossy_par);
+		}
 
-		err = encode_value(data_to_encode[i].NCOB_X, 32, cfg, enc);
-		if (err)
-			return err;
+		if (i >= cfg->samples-1)
+			break;
 
-		err = encode_value(data_to_encode[i].NCOB_Y, 32, cfg, enc);
-		if (err)
-			return err;
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_S_FX_EFX_NCOB_ECOB(struct cmp_cfg *cfg, struct encoder_struct
-				     *enc)
-{
-	struct S_FX_EFX_NCOB_ECOB *data_to_encode = cfg->input_buf;
-	size_t i;
-
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
-
-		err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, cfg, enc);
-		if (err)
-			return err;
-
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+/**
+ * @brief fill the last part of the bitstream with zeros
+ *
+ * @param cfg		pointer to the compression configuration structure
+ * @param cmp_size	length of the bitstream in bits
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-		err = encode_value(data_to_encode[i].NCOB_X, 32, cfg, enc);
-		if (err)
-			return err;
+static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size)
+{
+	unsigned int output_buf_len_bits, n_pad_bits;
 
-		err = encode_value(data_to_encode[i].NCOB_Y, 32, cfg, enc);
-		if (err)
-			return err;
+	if (cmp_size < 0)
+		return cmp_size;
 
-		err = encode_value(data_to_encode[i].EFX, 32, cfg, enc);
-		if (err)
-			return err;
+	/* maximum length of the bitstream/icu_output_buf in bits */
+	output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
 
-		err = encode_value(data_to_encode[i].ECOB_X, 32, cfg, enc);
-		if (err)
-			return err;
+	/* no padding in RAW mode*/
+	if (cfg->cmp_mode == CMP_MODE_RAW)
+		return cmp_size;
 
-		err = encode_value(data_to_encode[i].ECOB_Y, 32, cfg, enc);
-		if (err)
-			return err;
+	n_pad_bits = 32 - ((unsigned int)cmp_size & 0x1FU);
+	if (n_pad_bits < 32) {
+		int n_bits = put_n_bits32(0, n_pad_bits, cmp_size, cfg->icu_output_buf,
+					  output_buf_len_bits);
+		if (n_bits < 0)
+			return n_bits;
 	}
-	return 0;
-}
-
 
-/* pad the bitstream with zeros */
-int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size)
-{
-	int n_bits = 0;
-
-	if (!cfg)
-		return -1;
-
-	/* is padding needed */
-	if (cmp_size) {
-		int n_pad_bits = 32U - (cmp_size & 0x1f);
-		if (n_pad_bits < 32) {
-			 n_bits = put_n_bits32(0, cmp_size, n_pad_bits,
-					       cfg->icu_output_buf,
-					       cfg->buffer_length);
-			if (n_bits <= 0)
-				return -2;
-		}
-	}
-	return n_bits;
+	return cmp_size;
 }
 
 
-uint32_t cmp_encode_data(struct cmp_cfg *cfg)
-{
-	struct encoder_struct enc;
-	int err, n_bits;
+/**
+ * @brief change the endianness of the compressed data to big-endian
+ *
+ * @param cfg		pointer to the compression configuration structure
+ * @param cmp_size	length of the bitstream in bits
+ *
+ * @returns 0 on success; non-zero on failure
+ */
 
-	enc.encoder = select_encoder(cfg->golomb_par);
-	enc.log2_golomb_par = ilog_2(cfg->golomb_par);
-	enc.cmp_size = 0;
+static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, unsigned int cmp_size)
+{
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+	size_t i;
+	uint32_t *p;
 
-	switch (cfg->cmp_mode) {
-	case MODE_RAW:
-		err = encode_raw_16(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		err = encode_16(cfg, &enc);
-		break;
-	case MODE_RAW_S_FX:
-		err = encode_raw_S_FX(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		err = encode_S_FX(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		err = encode_S_FX_EFX(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		err = encode_S_FX_NCOB(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		err = encode_S_FX_EFX_NCOB_ECOB(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		err = encode_32(cfg, &enc);
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		return -1;
-		break;
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
+		int err = cmp_input_big_to_cpu_endianness(cfg->icu_output_buf,
+							  cmp_size/CHAR_BIT, cfg->data_type);
+		return err;
 	}
 
-	n_bits = pad_bitstream(cfg, enc.cmp_size);
-	if (n_bits < 0)
-		return n_bits;
-
-#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-	{
-		size_t i;
-		uint32_t *p = (uint32_t *)cfg->icu_output_buf;
-
-		if (p) {
-			for (i = 0; i < cmp_bit_to_4byte(enc.cmp_size)/sizeof(uint32_t); i++)
-				cpu_to_be32s(&p[i]);
-		}
+	if (rdcu_supported_data_type_is_used(cfg->data_type)) {
+		p = cfg->icu_output_buf;
+	} else {
+		p = &cfg->icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
+		cmp_size -= MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
 	}
-#endif /*__BYTE_ORDER__ */
 
-	if (err)
-		return err;
-	else
-		return enc.cmp_size;
+	for (i = 0; i < cmp_bit_to_4byte(cmp_size)/sizeof(uint32_t); i++)
+		cpu_to_be32s(&p[i]);
+#else
+	/* do nothing data are already in big-endian */
+	(void)cfg;
+#endif /*__BYTE_ORDER__ */
+	return 0;
 }
 
 
 /**
  * @brief	compress data on the ICU
  *
- * @param cfg	compressor configuration contains all parameters required for
- *		compression
- * @param info	compressor information contains information of the executed
- *		compression
+ * @param cfg	pointer to a compression configuration (created with the
+ *		cmp_cfg_icu_create() function, setup with the cmp_cfg_xxx() functions)
  *
- * @note this function violates the input_buf in place
- * @note if icu_new_model_buf = model_buf or NULL, the model will be updated in place
  * @note the validity of the cfg structure is checked before the compression is
  *	 started
- * @note when using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
- *      the model parameters (model_value, model_buf, rdcu_model_adr) are ignored
- * @note the rdcu_***_adr configuration parameters are ignored for icu
- *	 compression
- * @note semi adaptive compression not supported; configuration parameters
- *	 ap1\_golomb\_par, ap2\_golomb\_par, ap1\_spill ap2\_spill will be
- *	 ignored; information parameters ap1_cmp_size, ap2_cmp_size will always
- *	 be 0
- *
- * @returns 0 on success, error otherwise
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF (-2) if the compressed data buffer is too small to
+ *	hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or
+ *	model value is bigger than the max_used_bits parameter allows (set with
+ *	the cmp_set_max_used_bits() function)
  */
 
-int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info)
+int icu_compress_data(const struct cmp_cfg *cfg)
 {
-	int err;
 	int cmp_size = 0;
 
-	err = set_info(cfg, info);
-	if (err)
-		return err;
+	if (!cfg)
+		return -1;
 
-	err = icu_cmp_cfg_valid(cfg, info);
-	if (err)
-		return err;
+	if (cfg->samples == 0) /* nothing to compress we are done*/
+		return 0;
 
-	err = cmp_pre_process(cfg);
-	if (err)
-		return err;
+	if (!cmp_cfg_is_valid(cfg))
+		return -1;
 
-	err = cmp_map_to_pos(cfg);
-	if (err)
-		return err;
+	if (model_mode_is_used(cfg->cmp_mode) && !cfg->model_buf)
+		return -1;
 
-	cmp_size = cmp_encode_data(cfg);
-	if (cmp_size == -2 && info)
-		/* the icu_output_buf is to small to store the whole bitstream */
-		info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
-	if (cmp_size < 0)
-		return cmp_size;
-	if (info)
-		info->cmp_size = cmp_size;
+	if (raw_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->samples > cfg->buffer_length) {
+			cmp_size = CMP_ERROR_SAMLL_BUF;
+		} else {
+			cmp_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+			if (cfg->icu_output_buf)
+				memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size);
+			cmp_size *= CHAR_BIT; /* convert to bits */
+		}
+	} else {
+		switch (cfg->data_type) {
+		case DATA_TYPE_IMAGETTE:
+		case DATA_TYPE_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_SAT_IMAGETTE:
+		case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_F_CAM_IMAGETTE:
+		case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+			cmp_size = compress_imagette(cfg);
+			break;
+
+		case DATA_TYPE_S_FX:
+			cmp_size = compress_s_fx(cfg);
+			break;
+		case DATA_TYPE_S_FX_DFX:
+			cmp_size = compress_s_fx_efx(cfg);
+			break;
+		case DATA_TYPE_S_FX_NCOB:
+			cmp_size = compress_s_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+			cmp_size = compress_s_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_F_FX:
+			cmp_size = compress_f_fx(cfg);
+			break;
+		case DATA_TYPE_F_FX_DFX:
+			cmp_size = compress_f_fx_efx(cfg);
+			break;
+		case DATA_TYPE_F_FX_NCOB:
+			cmp_size = compress_f_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+			cmp_size = compress_f_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_L_FX:
+			cmp_size = compress_l_fx(cfg);
+			break;
+		case DATA_TYPE_L_FX_DFX:
+			cmp_size = compress_l_fx_efx(cfg);
+			break;
+		case DATA_TYPE_L_FX_NCOB:
+			cmp_size = compress_l_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+			cmp_size = compress_l_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_OFFSET:
+			cmp_size = compress_nc_offset(cfg);
+			break;
+		case DATA_TYPE_BACKGROUND:
+			cmp_size = compress_nc_background(cfg);
+			break;
+		case DATA_TYPE_SMEARING:
+			cmp_size = compress_smearing(cfg);
+			break;
+
+		case DATA_TYPE_F_CAM_OFFSET:
+		case DATA_TYPE_F_CAM_BACKGROUND:
+		case DATA_TYPE_UNKOWN:
+		default:
+			debug_print("Error: Data type not supported.\n");
+			cmp_size = -1;
+		}
+	}
 
-	return 0;
+	if (cfg->icu_output_buf && cmp_size > 0) {
+		cmp_size = pad_bitstream(cfg, cmp_size);
+		cmp_data_to_big_endian(cfg, (unsigned int)cmp_size);
+	}
+
+	return cmp_size;
 }
diff --git a/lib/cmp_icu_new.c b/lib/cmp_icu_new.c
deleted file mode 100644
index d69ab0f..0000000
--- a/lib/cmp_icu_new.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/**
- * @file   icu_cmp.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 software compression library
- * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
- */
-
-
-#include <stdint.h>
-
-#include "cmp_debug.h"
-
-
-/* return code if the bitstream buffer is too small to store the whole bitstream */
-#define CMP_ERROR_SAMLL_BUF -2
-
-/* pointer to a code word generation function */
-typedef uint32_t (*generate_cw_pt)(uint32_t value, uint32_t encoder_par1,
-				   uint32_t encoder_par2, uint32_t *cw);
-
-/* typedef uint32_t (*next_model_f_pt)(uint32_t model_mode_val, uint32_t diff_model_var); */
-
-struct encoder_setupt {
-	/* unsigned int lossy_par; */
-	/* next_model_f_pt *next_model_f; */
-	generate_cw_pt generate_cw; /* pointer to the code word generation function */
-	/* uint32_t updated_model; */
-	uint32_t encoder_par1;
-	uint32_t encoder_par2;
-	uint32_t outlier_par;
-	uint32_t model_value;
-	uint32_t max_value_bits; /* how many bits are needed to represent the highest possible value */
-	uint32_t max_bit_len; /* maximum length of the bitstream/icu_output_buf in bits */
-	uint32_t *bitstream_adr;
-};
-
-
-/**
- * @brief map a signed value into a positive value range
- *
- * @param value_to_map		signed value to map
- * @param max_value_bits	how many bits are needed to represent the
- *				highest possible value
- *
- * @returns the positive mapped value
- */
-
-static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_value_bits)
-{
-	uint32_t mask = (~0U >> (32 - max_value_bits)); /* mask the used bits */
-
-	value_to_map &= mask;
-	if (value_to_map >> (max_value_bits - 1)) { /* check the leading signed bit */
-		value_to_map |= ~mask; /* convert to 32-bit signed integer */
-		/* map negative values to uneven numbers */
-		return (-value_to_map) * 2 - 1; /* possible integer overflow is intended */
-	} else {
-		/* map positive values to even numbers */
-		return value_to_map * 2; /* possible integer overflow is intended */
-	}
-}
-
-
-/**
- * @brief put the value of up to 32 bits into a bitstream accessed as 32-bit
- *	RAM in big-endian
- *
- * @param value		the value to put
- * @param n_bits	number of bits to put in the bitstream
- * @param bit_offset	bit index where the bits will be put, seen from the very
- *			beginning of the bitstream
- * @param bitstream_adr	this is the pointer to the beginning of the bitstream
- *			(can be NULL)
- * @param max_bit_len	maximum length of the bitstream in bits; is ignored if
- *			bitstream_adr is NULL
- *
- * @returns length in bits of the generated bitstream on success; returns
- *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
- *          the bitstream buffer is too small to put the value in the bitstream
- */
-
-static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
-			uint32_t *bitstream_adr, unsigned int max_bit_len)
-{
-	uint32_t *local_adr;
-	uint32_t mask;
-	unsigned int shiftRight, shiftLeft, bitsLeft, bitsRight;
-	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
-
-	/* leave in case of erroneous input */
-	if (bit_offset < 0)
-		return -1;
-
-	if (n_bits == 0)
-		return stream_len;
-
-	if (n_bits > 32)
-		return -1;
-
-	/* Do we need to write data to the bitstream? */
-	if (!bitstream_adr)
-		return stream_len;
-
-	/* Check if bitstream buffer is large enough */
-	if ((unsigned int)stream_len > max_bit_len) {
-		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
-		return CMP_ERROR_SAMLL_BUF;
-	}
-
-	/* (M) is the n_bits parameter large enough to cover all value bits; the
-	 * calculations can be re-used in the unsegmented code, so we have no overhead
-	 */
-	shiftRight = 32 - n_bits;
-	mask = 0xFFFFFFFFU >> shiftRight;
-	value &= mask;
-
-	/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
-	local_adr = bitstream_adr + (bit_offset >> 5);
-	bitsLeft = bit_offset & 0x1F;
-
-	/* Calculate the bitsRight for the unsegmented case. If bitsRight is
-	 * negative we need to split the value over two words
-	 */
-	bitsRight = shiftRight - bitsLeft;
-
-	if ((int)bitsRight >= 0) {
-		/*         UNSEGMENTED
-		 *
-		 *|-----------|XXXXX|----------------|
-		 *   bitsLeft    n       bitsRight
-		 *
-		 *  -> to get the mask:
-		 *  shiftRight = bitsLeft + bitsRight = 32 - n
-		 *  shiftLeft = bitsRight = 32 - n - bitsLeft = shiftRight - bitsLeft
-		 */
-
-		shiftLeft = bitsRight;
-
-		/* generate the mask, the bits for the values will be true
-		 * shiftRight = 32 - n_bits; see (M) above!
-		 * mask = (0XFFFFFFFF >> shiftRight) << shiftLeft; see (M) above!
-		 */
-		mask <<= shiftLeft;
-		value <<= shiftLeft;
-
-		/* clear the destination with inverse mask */
-		*(local_adr) &= ~mask;
-
-		/* assign the value */
-		*(local_adr) |= value;
-
-	} else {
-		/*                             SEGMENTED
-		 *
-		 *|-----------------------------|XXX| |XX|------------------------------|
-		 *          bitsLeft              n1   n2          bitsRight
-		 *
-		 *  -> to get the mask part 1:
-		 *  shiftRight = bitsLeft
-		 *  n1 = n - (bitsLeft + n - 32) = 32 - bitsLeft
-		 *
-		 *  -> to get the mask part 2:
-		 *  n2 = bitsLeft + n - 32 = -(32 - n - bitsLeft) = -(bitsRight_UNSEGMENTED)
-		 *  shiftLeft = 32 - n2 = 32 - (bitsLeft + n - 32) = 64 - bitsLeft - n
-		 *
-		 */
-
-		unsigned int n2 = -bitsRight;
-
-		/* part 1: */
-		shiftRight = bitsLeft;
-		mask = 0XFFFFFFFFU >> shiftRight;
-
-		/* clear the destination with inverse mask */
-		*(local_adr) &= ~mask;
-
-		/* assign the value part 1 */
-		*(local_adr) |= (value >> n2);
-
-		/* part 2: */
-		/* adjust address */
-		local_adr += 1;
-		shiftLeft = 32 - n2;
-		mask = 0XFFFFFFFFU << shiftLeft;
-
-		/* clear the destination with inverse mask */
-		*(local_adr) &= ~mask;
-
-		/* assign the value part 2 */
-		*(local_adr) |= (value << shiftLeft);
-	}
-	return stream_len;
-}
-
-
-/**
- * @brief forms the codeword according to the Rice code
- *
- * @param value		value to be encoded
- * @param m		Golomb parameter, only m's which are power of 2 are allowed
- * @param log2_m	Rice parameter, is log_2(m) calculate outside function
- *			for better performance
- * @param cw		address were the encode code word is stored
- *
- * @returns the length of the formed code word in bits
- * @note no check if the generated code word is not longer than 32 bits.
- */
-
-static uint32_t Rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
-				 uint32_t *cw)
-{
-	uint32_t g;  /* quotient of value/m */
-	uint32_t q;  /* quotient code without ending zero */
-	uint32_t r;  /* remainder of value/m */
-	uint32_t rl; /* remainder length */
-
-	g = value >> log2_m; /* quotient, number of leading bits */
-	q = (1U << g) - 1;   /* prepare the quotient code without ending zero */
-
-	r = value & (m-1);   /* calculate the remainder */
-	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the quotient code) */
-	*cw = (q << rl) | r; /* put the quotient and remainder code together */
-	/*
-	 * NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined
-	 * behavior. However, in this case, a valid code with a maximum of 32
-	 * bits can only be formed if q = 0. Any shift with 0 << x always
-	 * results in 0, which forms the correct codeword in this case. For
-	 * performance reasons, this undefined behaviour is not caught.
-	 */
-
-	return rl + g;	      /* calculate the length of the code word */
-}
-
-
-/**
- * @brief forms a codeword according to the Golomb code
- *
- * @param value		value to be encoded
- * @param m		Golomb parameter (have to be bigger than 0)
- * @param log2_m	is log_2(m) calculate outside function for better
- *			performance
- * @param cw		address were the formed code word is stored
- *
- * @returns the length of the formed code word in bits
- */
-
-static uint32_t Golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
-				   uint32_t *cw)
-{
-	uint32_t len0, b, g, q, lg;
-	uint32_t len;
-	uint32_t cutoff;
-
-	len0 = log2_m + 1;                 /* codeword length in group 0 */
-	cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */
-
-	if (value < cutoff) { /* group 0 */
-		*cw = value;
-		len = len0;
-	} else { /* other groups */
-		g = (value-cutoff) / m; /* this group is which one  */
-		b = cutoff << 1;        /* form the base codeword */
-		lg = len0 + g;          /* it has lg remainder bits */
-		q = (1U << g) - 1;      /* prepare the left side in unary */
-		*cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */
-		len = lg + 1;           /* length of the codeword */
-	}
-	return len;
-}
-
-
-/**
- * @brief generate a code word without a outlier mechanism and put in the
- *	bitstream
- *
- * @param value		value to encode in the bitstream
- * @param stream_len	length of the bitstream in bits
- * @param setup		pointer to the encoder setup
- *
- * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error
- */
-
-static int encode_normal(uint32_t value, int stream_len,
-			 struct encoder_setupt *setup)
-{
-	uint32_t code_word, cw_len;
-
-	cw_len = setup->generate_cw(value, setup->encoder_par1,
-				    setup->encoder_par2, &code_word);
-
-	return put_n_bits32(code_word, cw_len, stream_len, setup->bitstream_adr,
-			    setup->max_bit_len);
-}
-
-
-/**
- * @brief subtract the model from the data, encode the result and put it into
- *	bitstream, for encodeing outlier use the zero escape symbol mechanism
- *
- * @param data		data to encode
- * @param model		model of the data (0 if not used)
- * @param stream_len	length of the bitstream in bits
- * @param setup		pointer to the encoder setup
- *
- * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
- *	is too small to put the value in the bitstream
- *
- * @note no check if data or model are in the allowed range
- * @note no check if the setup->outlier_par is in the allowed range
- */
-
-static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
-			     struct encoder_setupt *setup)
-{
-	data -= model;
-
-	data = map_to_pos(data, setup->max_value_bits);
-
-	/* For performance reasons, we check to see if there is an outlier
-	 * before adding one, rather than the other way around:
-	 * data++;
-	 * if (data < setup->outlier_par && data != 0)
-	 *	return ...
-	 */
-	if (data < (setup->outlier_par - 1)) { /* detect r */
-		data++; /* add 1 to every value so we can use 0 as escape symbol */
-		return encode_normal(data, stream_len, setup);
-	}
-
-	data++; /* add 1 to every value so we can use 0 as escape symbol */
-
-	/* use zero as escape symbol */
-	stream_len = encode_normal(0, stream_len, setup);
-	if (stream_len <= 0)
-		return stream_len;
-
-	/* put the data unencoded in the bitstream */
-	stream_len = put_n_bits32(data, setup->max_value_bits, stream_len,
-				  setup->bitstream_adr, setup->max_bit_len);
-
-	return stream_len;
-
-}
-
-
-/**
- * @brief subtract the model from the data, encode the result and put it into
- *	bitstream, for encoding outlier use the multi escape symbol mechanism
- *
- * @param data		data to encode
- * @param model		model of the data (0 if not used)
- * @param stream_len	length of the bitstream in bits
- * @param setup		pointer to the encoder setup
- *
- * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
- *	is too small to put the value in the bitstream
- *
- * @note no check if data or model are in the allowed range
- * @note no check if the setup->outlier_par is in the allowed ragne
- */
-
-static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
-			      struct encoder_setupt *setup)
-{
-	uint32_t unencoded_data;
-	unsigned int unencoded_data_len;
-	uint32_t escape_sym, escape_sym_offset;
-
-	data -= model; /* possible underflow is intended */
-
-	data = map_to_pos(data, setup->max_value_bits);
-
-	if (data < setup->outlier_par) /* detect non-outlier */
-		return  encode_normal(data, stream_len, setup);
-
-	/*
-	 * In this mode we put the difference between the data and the spillover
-	 * threshold value (unencoded_data) after a encoded escape symbol, which
-	 * indicate that the next codeword is unencoded.
-	 * We use different escape symbol depended on the size the needed bit of
-	 * unencoded data:
-	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is outlier_par + 0
-	 * 3, 4 bits needed for unencoded data -> escape symbol is outlier_par + 1
-	 * 5, 6 bits needed for unencoded data -> escape symbol is outlier_par + 2
-	 * and so on
-	 */
-	unencoded_data = data - setup->outlier_par;
-
-	if (!unencoded_data) /* catch __builtin_clz(0) because the result is undefined.*/
-		escape_sym_offset = 0;
-	else
-		escape_sym_offset = (31U - (uint32_t)__builtin_clz(unencoded_data)) >> 1;
-
-	escape_sym = setup->outlier_par + escape_sym_offset;
-	unencoded_data_len = (escape_sym_offset + 1U) << 1;
-
-	/* put the escape symbol in the bitstream */
-	stream_len = encode_normal(escape_sym, stream_len, setup);
-	if (stream_len <= 0)
-		return stream_len;
-
-	/* put the unencoded data in the bitstream */
-	stream_len = put_n_bits32(unencoded_data, unencoded_data_len, stream_len,
-				  setup->bitstream_adr, setup->max_bit_len);
-
-	return stream_len;
-}
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 7c00d56..99e80c6 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -32,6 +32,38 @@
 #include "cmp_data_types.h"
 
 
+/* directory to convert from data_type to string */
+static const struct {
+	enum cmp_data_type data_type;
+	const char *str;
+} data_type_string_table[] = {
+	{DATA_TYPE_IMAGETTE, "DATA_TYPE_IMAGETTE"},
+	{DATA_TYPE_IMAGETTE_ADAPTIVE, "DATA_TYPE_IMAGETTE_ADAPTIVE"},
+	{DATA_TYPE_SAT_IMAGETTE, "DATA_TYPE_SAT_IMAGETTE"},
+	{DATA_TYPE_SAT_IMAGETTE_ADAPTIVE, "DATA_TYPE_SAT_IMAGETTE_ADAPTIVE"},
+	{DATA_TYPE_OFFSET, "DATA_TYPE_OFFSET"},
+	{DATA_TYPE_BACKGROUND, "DATA_TYPE_BACKGROUND"},
+	{DATA_TYPE_SMEARING, "DATA_TYPE_SMEARING"},
+	{DATA_TYPE_S_FX, "DATA_TYPE_S_FX"},
+	{DATA_TYPE_S_FX_DFX, "DATA_TYPE_S_FX_DFX"},
+	{DATA_TYPE_S_FX_NCOB, "DATA_TYPE_S_FX_NCOB"},
+	{DATA_TYPE_S_FX_DFX_NCOB_ECOB, "DATA_TYPE_S_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_L_FX, "DATA_TYPE_L_FX"},
+	{DATA_TYPE_L_FX_DFX, "DATA_TYPE_L_FX_DFX"},
+	{DATA_TYPE_L_FX_NCOB, "DATA_TYPE_L_FX_NCOB"},
+	{DATA_TYPE_L_FX_DFX_NCOB_ECOB, "DATA_TYPE_L_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_F_FX, "DATA_TYPE_F_FX"},
+	{DATA_TYPE_F_FX_DFX, "DATA_TYPE_F_FX_DFX"},
+	{DATA_TYPE_F_FX_NCOB, "DATA_TYPE_F_FX_NCOB"},
+	{DATA_TYPE_F_FX_DFX_NCOB_ECOB, "DATA_TYPE_F_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_F_CAM_IMAGETTE, "DATA_TYPE_F_CAM_IMAGETTE"},
+	{DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE, "DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE"},
+	{DATA_TYPE_F_CAM_OFFSET, "DATA_TYPE_F_CAM_OFFSET"},
+	{DATA_TYPE_F_CAM_BACKGROUND, "DATA_TYPE_F_CAM_BACKGROUND"},
+	{DATA_TYPE_UNKOWN, "DATA_TYPE_UNKOWN"}
+};
+
+
 /**
  * @brief print help information
  *
@@ -114,31 +146,34 @@ static FILE *open_file(const char *dirname, const char *filename)
 
 
 /**
- * @brief write a uint16_t buffer to an output file
- *
- * @param buf		the buffer to write a file
- * @param buf_len	length of the buffer
+ * @brief write uncompressed input data to an output file
  *
+ * @param data		the data to write a file
+ * @param data_size	size of the data in bytes
  * @param output_prefix  file name without file extension
  * @param name_extension file extension (with leading point character)
- *
  * @param verbose	print verbose output if not zero
  *
  * @returns 0 on success, error otherwise
  */
 
-int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
-		    *output_prefix, const char *name_extension, int verbose)
+int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type data_type,
+			     const char *output_prefix, const char *name_extension, int verbose)
 {
-	uint32_t i;
+	uint32_t i = 0;
 	FILE *fp;
+	uint8_t *tmp_buf;
+	size_t sample_size = size_of_a_sample(data_type);
 
-	if (!buf)
+	if (!data)
 		abort();
 
-	if (buf_len == 0)
+	if (data_size == 0)
 		return 0;
 
+	if (!sample_size)
+		return -1;
+
 	fp = open_file(output_prefix, name_extension);
 	if (fp == NULL) {
 		fprintf(stderr, "%s: %s%s: %s\n", PROGRAM_NAME, output_prefix,
@@ -146,8 +181,12 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 		return -1;
 	}
 
-	for (i = 0; i < buf_len; i++) {
-		fprintf(fp, "%02X %02X", buf[i] >> 8, buf[i] & 0xFF);
+	tmp_buf = malloc(data_size);
+	memcpy(tmp_buf, data, data_size);
+	cmp_input_big_to_cpu_endianness(tmp_buf, data_size, data_type);
+
+	for (i = 0 ; i < data_size; i++) {
+		fprintf(fp, "%02X",  tmp_buf[i]);
 		if ((i + 1) % 16 == 0)
 			fprintf(fp, "\n");
 		else
@@ -159,8 +198,8 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 
 	if (verbose) {
 		printf("\n\n");
-			for (i = 0; i < buf_len; i++) {
-				printf("%02X %02X", buf[i] >> 8, buf[i] & 0xFF);
+			for (i = 0; i < data_size; i++) {
+				printf("%02X ", tmp_buf[i]);
 			if ((i + 1) % 16 == 0)
 				printf("\n");
 			else
@@ -170,6 +209,7 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 		printf("\n\n");
 	}
 
+	free(tmp_buf);
 	return 0;
 }
 
@@ -356,6 +396,67 @@ int atoui32(const char *dep_str, const char *val_str, uint32_t *red_val)
 }
 
 
+/**
+ * @brief parse a compression data_type string to a data_type
+ * @note string can be either a number or the name of the compression data type
+ *
+ * @param data_type_str	string containing the compression data type to parse
+ *
+ * @returns data type on success, DATA_TYPE_UNKOWN on error
+ */
+
+enum cmp_data_type string2data_type(const char *data_type_str)
+{
+	enum cmp_data_type data_type = DATA_TYPE_UNKOWN;
+
+	if (data_type_str) {
+		if (isalpha(data_type_str[0])) {  /* check if mode is given as text */
+			size_t j;
+
+			for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
+				if (!strcmp(data_type_str, data_type_string_table[j].str)) {
+					data_type = data_type_string_table[j].data_type;
+					break;
+				}
+			}
+		} else {
+			uint32_t read_val;
+
+			if (!atoui32("Compression Data Type", data_type_str, &read_val)) {
+				data_type = read_val;
+				if (!cmp_data_type_valid(data_type))
+					data_type = DATA_TYPE_UNKOWN;
+			}
+		}
+	}
+	return data_type;
+}
+
+/**
+ * @brief parse a compression data_type string to a data_type
+ * @note string can be either a number or the name of the compression data type
+ *
+ * @param data_type compression data type to convert in string
+ *
+ * @returns data type on success, DATA_TYPE_UNKOWN on error
+ */
+
+const char *data_type2string(enum cmp_data_type data_type)
+{
+	size_t j;
+	const char *string = "DATA_TYPE_UNKOWN";
+
+	for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
+		if (data_type == data_type_string_table[j].data_type) {
+			string = data_type_string_table[j].str;
+			break;
+		}
+	}
+
+	return string;
+}
+
+
 /**
  * @brief parse a compression mode vale string to an integer
  * @note string can be either a number or the name of the compression mode
@@ -373,11 +474,16 @@ int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
 		uint32_t  cmp_mode;
 		const char *str;
 	} conversion[] = {
-		{MODE_RAW, "MODE_RAW"},
-		{MODE_MODEL_ZERO, "MODE_MODEL_ZERO"},
-		{MODE_DIFF_ZERO, "MODE_DIFF_ZERO"},
-		{MODE_MODEL_MULTI, "MODE_MODEL_MULTI"},
-		{MODE_DIFF_MULTI, "MODE_DIFF_MULTI"},
+		{CMP_MODE_RAW, "MODE_RAW"},
+		{CMP_MODE_MODEL_ZERO, "MODE_MODEL_ZERO"},
+		{CMP_MODE_DIFF_ZERO, "MODE_DIFF_ZERO"},
+		{CMP_MODE_MODEL_MULTI, "MODE_MODEL_MULTI"},
+		{CMP_MODE_DIFF_MULTI, "MODE_DIFF_MULTI"},
+		{CMP_MODE_RAW, "CMP_MODE_RAW"},
+		{CMP_MODE_MODEL_ZERO, "CMP_MODE_MODEL_ZERO"},
+		{CMP_MODE_DIFF_ZERO, "CMP_MODE_DIFF_ZERO"},
+		{CMP_MODE_MODEL_MULTI, "CMP_MODE_MODEL_MULTI"},
+		{CMP_MODE_DIFF_MULTI, "CMP_MODE_DIFF_MULTI"},
 	};
 
 	if (!cmp_mode_str)
@@ -398,7 +504,7 @@ int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
 			return -1;
 	}
 
-	if (!cmp_mode_available(*cmp_mode))
+	if (!cmp_mode_is_supported(*cmp_mode))
 		return -1;
 
 	return 0;
@@ -450,9 +556,16 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 			continue;
 
 
+		if (!strcmp(token1, "data_type")) {
+			cfg->data_type = string2data_type(token2);
+			if (cfg->data_type == DATA_TYPE_UNKOWN)
+				return -1;
+			continue;
+		}
 		if (!strcmp(token1, "cmp_mode")) {
 			must_read_items[CMP_MODE] = 1;
 			if (isalpha(*token2)) { /* check if mode is given as text or val*/
+				/* TODO: use conversion function for this: */
 				if (!strcmp(token2, "MODE_RAW")) {
 					cfg->cmp_mode = 0;
 					continue;
@@ -645,12 +758,6 @@ int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 		printf("\n");
 	}
 
-	if (cfg->buffer_length < cfg->samples/2) {
-		fprintf(stderr,
-			"%s: warning: buffer_length: %u is relative small to the chosen samples parameter of %u.\n",
-			PROGRAM_NAME, cfg->buffer_length, cfg->samples);
-	}
-
 	return 0;
 }
 
@@ -705,6 +812,7 @@ static int parse_info(FILE *fp, struct cmp_info *info)
 		if (!strcmp(token1, "cmp_mode_used")) {
 			must_read_items[CMP_MODE_USED] = 1;
 			if (isalpha(*token2)) { /* check if mode is given as text or val*/
+				/* TODO: use conversion function for this: */
 				if (!strcmp(token2, "MODE_RAW")) {
 					info->cmp_mode_used = 0;
 					continue;
@@ -1013,7 +1121,7 @@ static uint8_t str_to_uint8(const char *str, char **str_end)
 
 
 /**
- * @brief reads n_word words of a hex-encoded string to a uint8_t buffer
+ * @brief reads buf_size words of a hex-encoded string to a uint8_t buffer
  *
  * @note A whitespace (space (0x20), form feed (0x0c), line feed (0x0a), carriage
  *	return (0x0d), horizontal tab (0x09), or vertical tab (0x0b) or several in a
@@ -1026,14 +1134,14 @@ static uint8_t str_to_uint8(const char *str, char **str_end)
  *
  * @param str		pointer to the null-terminated byte string to be interpreted
  * @param data		buffer to write the interpreted content (can be NULL)
- * @param n_word	number of uint8_t data words to read in
+ * @param buf_size	number of uint8_t data words to read in
  * @param file_name	file name for better error output (can be NULL)
  * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the string content; negative on error
  */
 
-static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
+static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t buf_size,
 			     const char *file_name, int verbose_en)
 {
 	const char *nptr = str;
@@ -1043,12 +1151,12 @@ static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
 	errno = 0;
 
 	if (!data)
-		n_word = ~0;
+		buf_size = ~0;
 
 	if (!file_name)
 		file_name = "unknown file name";
 
-	for (i = 0; i < n_word; ) {
+	for (i = 0; i < buf_size; ) {
 		uint8_t read_val;
 		unsigned char c = *nptr;
 
@@ -1118,8 +1226,7 @@ static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
 
 
 /**
- * @brief reads n_word words of a hex-encoded uint8_t data form a file to a
- *	buffer
+ * @brief reads hex-encoded uint8_t data form a file to a buffer
  *
  * @note A whitespace (space (0x20), form feed (0x0c), line feed (0x0a), carriage
  *	return (0x0d), horizontal tab (0x09), or vertical tab (0x0b) or several in a
@@ -1132,13 +1239,13 @@ static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
  *
  * @param file_name	data/model file name
  * @param buf		buffer to write the file content (can be NULL)
- * @param n_word	number of uint8_t data words to read in
+ * @param buf_size	number of uint8_t data words to read in
  * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the file content; negative on error
  */
 
-ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int verbose_en)
+ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t buf_size, int verbose_en)
 {
 	FILE *fp;
 	char *file_cpy = NULL;
@@ -1165,6 +1272,10 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int ver
 		fclose(fp);
 		return 0;
 	}
+	if (file_size < buf_size) {
+		fprintf(stderr, "%s: %s: Error: The files do not contain enough data as requested.\n", PROGRAM_NAME, file_name);
+		goto fail;
+	}
 	/* reset the file position indicator to the beginning of the file */
 	if (fseek(fp, 0L, SEEK_SET) != 0)
 		goto fail;
@@ -1188,7 +1299,7 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int ver
 	fclose(fp);
 	fp = NULL;
 
-	size = str2uint8_arr(file_cpy, buf, n_word, file_name, verbose_en);
+	size = str2uint8_arr(file_cpy, buf, buf_size, file_name, verbose_en);
 
 	free(file_cpy);
 	file_cpy = NULL;
@@ -1206,75 +1317,38 @@ fail:
 
 
 /**
- * @brief reads the number of uint16_t samples of a hex-encoded data (or model)
- *	file into a buffer
+ * @brief reads hex-encoded data from a file into a buffer
  *
  * @param file_name	data/model file name
+ * @param data_type	compression data type used for the data
  * @param buf		buffer to write the file content (can be NULL)
- * @param samples	amount of uint16_t data samples to read in
+ * @param buf_size	size in bytes of the buffer
  * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the file content; negative on error
  */
 
-ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples,
-		    int verbose_en)
+ssize_t read_file_data(const char *file_name, enum cmp_data_type data_type,
+		       void *buf, uint32_t buf_size, int verbose_en)
 {
-	ssize_t size = read_file8(file_name, (uint8_t *)buf,
-				  samples*sizeof(uint16_t), verbose_en);
+	ssize_t size;
+	int samples, err;
+
+	size = read_file8(file_name, (uint8_t *)buf, buf_size, verbose_en);
 
 	if (size < 0)
 		return size;
 
-	if (size & 0x1) {
-		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 2 hex words.\n",
+	samples = cmp_input_size_to_samples(size, data_type);
+	if (samples < 0) {
+		fprintf(stderr, "%s: %s: Error: The data are not correct formatted for the used compression data type.\n",
 				PROGRAM_NAME, file_name);
 		return -1;
 	}
 
-	if (buf) {
-		size_t i;
-		for (i = 0; i < samples; i++)
-			be16_to_cpus(&buf[i]);
-	}
-
-
-	return size;
-}
-
-
-/**
- * @brief reads the number of uint32_t samples of a hex-encoded data (or model)
- *	file into a buffer
- *
- * @param file_name	data/model file name
- * @param buf		buffer to write the file content (can be NULL)
- * @param samples	amount of uint32_t data samples to read in
- * @param verbose_en	print verbose output if not zero
- *
- * @returns the size in bytes to store the file content; negative on error
- */
-
-ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
-		    int verbose_en)
-{
-	ssize_t size = read_file8(file_name, (uint8_t *)buf,
-				  samples*sizeof(uint32_t), verbose_en);
-
-	if (size < 0)
-		return -1;
-
-	if (size & 0x3) {
-		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 4 hex words.\n",
-				PROGRAM_NAME, file_name);
+	err = cmp_input_big_to_cpu_endianness(buf, size, data_type);
+	if (err)
 		return -1;
-	}
-
-	if (buf) {
-		size_t i;
-		for (i = 0; i < samples; i++)
-			be32_to_cpus(&buf[i]);
-	}
 
 	return size;
 }
@@ -1292,7 +1366,7 @@ ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
  */
 
 ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
-			   uint32_t ent_size, int verbose_en)
+			     uint32_t ent_size, int verbose_en)
 {
 	ssize_t size;
 
@@ -1307,9 +1381,9 @@ ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 	}
 
 	if (ent) {
-		enum cmp_ent_data_type data_type = cmp_ent_get_data_type(ent);
+		enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
 
-		if (!cmp_ent_data_type_valid(data_type)) {
+		if (data_type == DATA_TYPE_UNKOWN) {
 			fprintf(stderr, "%s: %s: Error: Compression data type is not supported.\n",
 				PROGRAM_NAME, file_name);
 			return -1;
@@ -1328,6 +1402,41 @@ ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 }
 
 
+/**
+ * @brief reads hex-encoded uint32_t samples from a file into a buffer
+ *
+ * @param file_name	data/model file name
+ * @param buf		buffer to write the file content (can be NULL)
+ * @param buf_size	size of the buf buffer in bytes
+ * @param verbose_en	print verbose output if not zero
+ *
+ * @returns the size in bytes to store the file content; negative on error
+ */
+
+ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_size,
+		    int verbose_en)
+{
+	ssize_t size = read_file8(file_name, (uint8_t *)buf, buf_size, verbose_en);
+
+	if (size < 0)
+		return -1;
+
+	if (size & 0x3) {
+		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 4 hex words.\n",
+				PROGRAM_NAME, file_name);
+		return -1;
+	}
+
+	if (buf) {
+		size_t i;
+		for (i = 0; i < buf_size/sizeof(uint32_t); i++)
+			be32_to_cpus(&buf[i]);
+	}
+
+	return size;
+}
+
+
 /*
  * @brief generate from the cmp_tool version string a version_id for the
  * compression entity header
@@ -1371,7 +1480,7 @@ uint32_t cmp_tool_gen_version_id(const char *version)
 
 	version_id |= n;
 
-	return version_id |= CMP_TOOL_VERSION_ID_BIT;
+	return version_id | CMP_TOOL_VERSION_ID_BIT;
 }
 
 
@@ -1389,6 +1498,10 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg, int rdcu_cfg
 	fprintf(fp, "#-------------------------------------------------------------------------------\n");
 	fprintf(fp, "# Default Configuration File\n");
 	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Selected compression data type\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "data_type = %u\n", cfg->data_type);
+	fprintf(fp, "\n");
 	fprintf(fp, "# Selected compression mode\n");
 	fprintf(fp, "# 0: raw mode\n");
 	fprintf(fp, "# 1: model mode with zero escape symbol mechanism\n");
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index c24ebed..34606f4 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -15,21 +15,36 @@
  *
  * @brief hardware compressor control library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
+ *
+ * To compress data, first create a compression configuration with the
+ * rdcu_cfg_create() function.
+ * Then set the different data buffers with the data to compressed, the model
+ * data and the RDCU SRAM addresses with the rdcu_cfg_buffers() function.
+ * Then set the imagette compression parameters with the rdcu_cfg_imagette()
+ * function.
+ * Finally, you can compress the data with the RDCU using the
+ * rdcu_compress_data() function.
  */
 
 #include <stdint.h>
 #include <stdio.h>
 
-#include "../include/rdcu_cmd.h"
-#include "../include/cmp_support.h"
-#include "../include/rdcu_ctrl.h"
-#include "../include/rdcu_rmap.h"
+#include "rdcu_cmd.h"
+#include "cmp_support.h"
+#include "cmp_data_types.h"
+#include "rdcu_ctrl.h"
+#include "rdcu_rmap.h"
+#include "cmp_debug.h"
+
 
+#define IMA_SAM2BYT                                                            \
+	2 /* imagette sample to byte conversion factor; one imagette samples has 16 bits (2 bytes) */
 
 #define RDCU_INTR_SIG_ENA 1 /* RDCU interrupt signal enabled */
 #define RDCU_INTR_SIG_DIS 0 /* RDCU interrupt signal disable */
-#define RDCU_INTR_SIG_DEFAULT RDCU_INTR_SIG_ENA /* default start value for RDCU
-						   interrupt signal */
+#define RDCU_INTR_SIG_DEFAULT RDCU_INTR_SIG_ENA /* default start value for RDCU interrupt signal */
+
+
 /* RDCU interrupt signal status */
 static int interrupt_signal_enabled = RDCU_INTR_SIG_DEFAULT;
 
@@ -48,6 +63,7 @@ static void sync(void)
 	not needed for packed generation
 
 	int cnt = 0;
+
 	printf("syncing...");
 	while (rdcu_rmap_sync_status()) {
 		printf("pending: %d\n", rdcu_rmap_sync_status());
@@ -63,6 +79,84 @@ static void sync(void)
 }
 
 
+/**
+ * @brief check if the compression data product type, compression mode, model
+ *	value and the lossy rounding parameters are valid for a RDCU compression
+ *
+ * @param cfg	pointer to a compression configuration containing the compression
+ *	data product type, compression mode, model value and the rounding parameters
+ *
+ * @returns 0 if the compression data type, compression mode, model value and
+ *	the lossy rounding parameters are valid for a RDCU compression, non-zero
+ *	if parameters are invalid
+ */
+
+static int rdcu_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cfg)
+		return -1;
+
+	if (!cmp_imagette_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The selected compression data type is not supported for RDCU compression");
+		cfg_invalid++;
+	}
+
+	if (cfg->cmp_mode > MAX_RDCU_CMP_MODE) {
+		debug_print("Error: selected cmp_mode: %u is not supported. Largest supported mode is: %u.\n",
+			    cfg->cmp_mode, MAX_RDCU_CMP_MODE);
+		cfg_invalid++;
+	}
+
+	if (cfg->model_value > MAX_MODEL_VALUE) {
+		debug_print("Error: selected model_value: %u is invalid. Largest supported value is: %u.\n",
+			    cfg->model_value, MAX_MODEL_VALUE);
+		cfg_invalid++;
+	}
+
+	if (cfg->round > MAX_RDCU_ROUND) {
+		debug_print("Error: selected round parameter: %u is not supported. Largest supported value is: %u.\n",
+			    cfg->round, MAX_RDCU_ROUND);
+		cfg_invalid++;
+	}
+
+#ifdef SKIP_CMP_PAR_CHECK
+	return 0;
+#endif
+
+	return -cfg_invalid;
+}
+
+
+/**
+ * @brief create a RDCU compression configuration
+ *
+ * @param data_type	compression data product types
+ * @param cmp_mode	compression mode
+ * @param model_value	model weighting parameter (only need for model compression mode)
+ * @param lossy_par	lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
+ *
+ * @returns compression configuration containing the chosen parameters;
+ *	on error the data_type record is set to DATA_TYPE_UNKOWN
+ */
+
+struct cmp_cfg rdcu_cfg_create(enum cmp_ent_data_type data_type, enum cmp_mode cmp_mode,
+			       uint32_t model_value, uint32_t lossy_par)
+{
+	struct cmp_cfg cfg = {0};
+
+	cfg.data_type = data_type;
+	cfg.cmp_mode = cmp_mode;
+	cfg.model_value = model_value;
+	cfg.round = lossy_par;
+
+	if (rdcu_cfg_gen_par_is_invalid(&cfg))
+		cfg.data_type = DATA_TYPE_UNKOWN;
+
+	return cfg;
+}
+
 /**
  * @brief check if a buffer is in inside the RDCU SRAM
  *
@@ -99,6 +193,7 @@ static int in_sram_range(uint32_t addr, uint32_t size)
  * @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)
 {
@@ -110,302 +205,373 @@ static int buffers_overlap(uint32_t start_a, uint32_t end_a, uint32_t start_b,
 
 
 /**
- * @brief check if the compressor configuration is valid for a RDCU compression,
- * see the user manual for more information (PLATO-UVIE-PL-UM-0001).
+ * @brief check if RDCU buffer settings are invalid
  *
- * @param cfg	configuration contains all parameters required for compression
+ * @param cfg	a pointer to a compression configuration
  *
- * @returns  >= 0 on success, error otherwise
+ * @returns 0 if buffers configuration is valid, otherwise the configuration is
+ *	invalid
  */
 
-int rdcu_cmp_cfg_valid(const struct cmp_cfg *cfg)
+static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
-	int cfg_warning = 0;
-
-	if (cfg == NULL)
-		return -1;
-
-	if (cfg->cmp_mode > MAX_RDCU_CMP_MODE) {
-		printf("Error: selected cmp_mode: %u is not supported. "
-		       "Largest supported mode is: %lu.\n", cfg->cmp_mode,
-		       MAX_RDCU_CMP_MODE);
-		cfg_invalid++;
-	}
-
-	if (cfg->model_value > MAX_MODEL_VALUE) {
-		printf("Error: selected model_value: %u is invalid. "
-		       "Largest supported value is: %lu.\n", cfg->model_value,
-		       MAX_MODEL_VALUE);
-		cfg_invalid++;
-	}
-
-	if (cfg->golomb_par < MIN_RDCU_GOLOMB_PAR||
-	    cfg->golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		printf("Error: The selected Golomb parameter: %u is not supported. "
-		       "The Golomb parameter has to  be between [%lu, %lu].\n",
-		       cfg->golomb_par, MIN_RDCU_GOLOMB_PAR,
-		       MAX_RDCU_GOLOMB_PAR);
-		cfg_invalid++;
-	}
-
-	if (cfg->ap1_golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->ap1_golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		printf("Error: The selected adaptive 1 Golomb parameter: %u is not supported. "
-		       "The Golomb parameter has to  be between [%lu, %lu].\n",
-		       cfg->ap1_golomb_par, MIN_RDCU_GOLOMB_PAR,
-		       MAX_RDCU_GOLOMB_PAR);
-		cfg_invalid++;
-	}
 
-	if (cfg->ap2_golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->ap2_golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		printf("Error: The selected adaptive 2 Golomb parameter: %u is not supported. "
-		       "The Golomb parameter has to be between [%lu, %lu].\n",
-		       cfg->ap2_golomb_par, MIN_RDCU_GOLOMB_PAR,
-		       MAX_RDCU_GOLOMB_PAR);
-		cfg_invalid++;
-	}
-
-	if (cfg->spill < MIN_RDCU_SPILL) {
-		printf("Error: The selected spillover threshold value: %u is too small. "
-		       "Smallest possible spillover value is: %lu.\n",
-		       cfg->spill, MIN_RDCU_SPILL);
-		cfg_invalid++;
-	}
-
-	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->cmp_mode)) {
-		printf("Error: The selected spillover threshold value: %u is "
-		       "too large for the selected Golomb parameter: %u, the "
-		       "largest possible spillover value is: %u.\n",
-		       cfg->spill, cfg->golomb_par,
-		       get_max_spill(cfg->golomb_par, cfg->cmp_mode));
-		cfg_invalid++;
-	}
-
-	if (cfg->ap1_spill < MIN_RDCU_SPILL) {
-		printf("Error: The selected adaptive 1 spillover threshold "
-		       "value: %u is too small. "
-		       "Smallest possible spillover value is: %lu.\n",
-		       cfg->ap1_spill, MIN_RDCU_SPILL);
-		cfg_invalid++;
-	}
-
-	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->cmp_mode)) {
-		printf("Error: The selected adaptive 1 spillover threshold "
-		       "value: %u is too large for the selected adaptive 1 "
-		       "Golomb parameter: %u, the largest possible adaptive 1 "
-		       "spillover value is: %u.\n",
-		       cfg->ap1_spill, cfg->ap1_golomb_par,
-		       get_max_spill(cfg->ap1_golomb_par, cfg->cmp_mode));
-		cfg_invalid++;
-	}
-
-	if (cfg->ap2_spill < MIN_RDCU_SPILL) {
-		printf("Error: The selected adaptive 2 spillover threshold "
-		       "value: %u is too small."
-		       "Smallest possible spillover value is: %lu.\n",
-		       cfg->ap2_spill, MIN_RDCU_SPILL);
-		cfg_invalid++;
-	}
-
-	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->cmp_mode)) {
-		printf("Error: The selected adaptive 2 spillover threshold "
-		       "value: %u is too large for the selected adaptive 2 "
-		       "Golomb parameter: %u, the largest possible adaptive 2 "
-		       "spillover value is: %u.\n",
-		       cfg->ap2_spill, cfg->ap2_golomb_par,
-		       get_max_spill(cfg->ap2_golomb_par, cfg->cmp_mode));
-		cfg_invalid++;
-	}
-
-	if (cfg->round > MAX_RDCU_ROUND) {
-		printf("Error: selected round parameter: %u is not supported. "
-		       "Largest supported value is: %lu.\n",
-		       cfg->round, MAX_RDCU_ROUND);
-		cfg_invalid++;
-	}
-
-	if (cfg->samples == 0) {
-		printf("Warning: The samples parameter is set to 0. No data will be compressed.\n");
-		cfg_warning++;
-	}
-
-	if (cfg->buffer_length == 0) {
-		printf("Error: The buffer_length is set to 0. There is no place "
-		       "to store the compressed data.\n");
-		cfg_invalid++;
-	}
-
-	if (cfg->cmp_mode == MODE_RAW) {
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
 		if (cfg->buffer_length < cfg->samples) {
-			printf("buffer_length is smaller than samples parameter. "
-			       "There is not enough space to copy the data in "
-			       "RAW mode.\n");
+			debug_print("rdcu_buffer_length is smaller than samples parameter. There is not enough space to copy the data in RAW mode.\n");
 			cfg_invalid++;
 		}
 	}
 
-	if (!cfg->input_buf) {
-		printf("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");
-		cfg_warning++;
-	}
-
 	if (cfg->rdcu_data_adr & 0x3) {
-		printf("Error: The RDCU data to compress start address is not 4-Byte aligned.\n");
+		debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned.\n");
 		cfg_invalid++;
 	}
 
 	if (cfg->rdcu_buffer_adr & 0x3) {
-		printf("Error: The RDCU compressed data start address is not 4-Byte aligned.\n");
+		debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned.\n");
 		cfg_invalid++;
 	}
 
-	if (!in_sram_range(cfg->rdcu_data_adr, cfg->samples * SAM2BYT)) {
-		printf("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.\n");
+	if (!in_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 (!in_sram_range(cfg->rdcu_buffer_adr, cfg->buffer_length * SAM2BYT)) {
-		printf("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.\n");
+	if (!in_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 * SAM2BYT,
+			    cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT,
 			    cfg->rdcu_buffer_adr,
-			    cfg->rdcu_buffer_adr + cfg->buffer_length * SAM2BYT)) {
-		printf("Error: The RDCU data to compress buffer and the RDCU "
-		       "compressed data buffer are overlapping.\n");
+			    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->input_buf) {
-			printf("Error: The model buffer (model_buf) and the data "
-			       "to be compressed (input_buf) are equal.");
+		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.");
 			cfg_invalid++;
 		}
 
-		if (!cfg->model_buf) {
-			printf("Warning: The model buffer is set to NULL. No "
-			       "model data will be transferred to the "
-			       "rdcu_model_adr in the RDCU-SRAM.\n");
-			cfg_warning++;
-		}
-
 		if (cfg->rdcu_model_adr & 0x3) {
-			printf("Error: The RDCU model start address is not 4-Byte aligned.\n");
+			debug_print("Error: The RDCU model start address is not 4-Byte aligned.\n");
 			cfg_invalid++;
 		}
 
-		if (!in_sram_range(cfg->rdcu_model_adr, cfg->samples * SAM2BYT)) {
-			printf("Error: The RDCU model buffer is outside the RDCU SRAM address space.\n");
+		if (!in_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 * SAM2BYT,
+			    cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT,
 			    cfg->rdcu_data_adr,
-			    cfg->rdcu_data_adr + cfg->samples * SAM2BYT)) {
-			printf("Error: The model buffer and the data to compress buffer are overlapping.\n");
+			    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 * SAM2BYT,
+			cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT,
 			cfg->rdcu_buffer_adr,
-			cfg->rdcu_buffer_adr + cfg->buffer_length * SAM2BYT)
-		    ){
-			printf("Error: The model buffer and the compressed data buffer are overlapping.\n");
+			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) {
-				printf("Error: The RDCU updated model start address "
-				       "(rdcu_new_model_adr) is not 4-Byte aligned.\n");
+				debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned.\n");
 				cfg_invalid++;
 			}
 
 			if (!in_sram_range(cfg->rdcu_new_model_adr,
-					   cfg->samples * SAM2BYT)) {
-				printf("Error: The RDCU updated model buffer is "
-				       "outside the RDCU SRAM address space.\n");
+					   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 * SAM2BYT,
+				cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT,
 				cfg->rdcu_data_adr,
-				cfg->rdcu_data_adr + cfg->samples * SAM2BYT)
-			    ){
-				printf("Error: The updated model buffer and the data to "
-				       "compress buffer are overlapping.\n");
+				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 * SAM2BYT,
+				cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT,
 				cfg->rdcu_buffer_adr,
-				cfg->rdcu_buffer_adr + cfg->buffer_length * SAM2BYT)
-			    ){
-				printf("Error: The updated model buffer and the compressed "
-				       "data buffer are overlapping.\n");
+				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 * SAM2BYT,
+				cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT,
 				cfg->rdcu_model_adr,
-				cfg->rdcu_model_adr + cfg->samples * SAM2BYT)
-			    ){
-				printf("Error: The updated model buffer and the "
-				       "model buffer are overlapping.\n");
+				cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT)
+			    ) {
+				debug_print("Error: The updated model buffer and the model buffer are overlapping.\n");
 				cfg_invalid++;
 			}
 		}
 	}
 
-	if (cfg->icu_new_model_buf) {
-		printf("Warning: ICU updated model buffer is set. This "
-		       "buffer is not used for an RDCU compression.\n");
-		cfg_warning++;
+	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");
+
+#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 multi entity 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 data to compress start address, the first
+ *				data address in the RDCU SRAM
+ * @param rdcu_model_adr	RDCU model start address, the first model address
+ *				in the RDCU SRAM (only need for model compression mode)
+ * @param rdcu_new_model_adr	RDCU 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 compressed data start address, the first
+ *				output data address in the RDCU SRAM
+ * @param rdcu_buffer_lenght	length of the RDCU compressed data SRAM buffer
+ *				in number of 16-bit 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;
 	}
 
-	if (cfg->icu_output_buf) {
-		printf("Warning: ICU compressed data buffer is set. This "
-		       "buffer is not used for an RDCU compression.\n");
-		cfg_warning++;
+	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;
+
+	if (rdcu_cfg_buffers_is_invalid(cfg))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the Golomb and spillover threshold parameter combination is
+ *	invalid for a RDCU compression
+ * @note also checked the adaptive Golomb and spillover threshold parameter combinations
+ *
+ * @param cfg	a pointer to a compression configuration
+ *
+ * @returns 0 if (adaptive) Golomb spill threshold parameter combinations are
+ *	valid, otherwise the configuration is invalid
+ */
+
+static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (cfg->golomb_par < MIN_RDCU_GOLOMB_PAR ||
+	    cfg->golomb_par > MAX_RDCU_GOLOMB_PAR) {
+		debug_print("Error: The selected Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%u, %u].\n",
+			    cfg->golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap1_golomb_par < MIN_RDCU_GOLOMB_PAR ||
+	    cfg->ap1_golomb_par > MAX_RDCU_GOLOMB_PAR) {
+		debug_print("Error: The selected adaptive 1 Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%u, %u].\n",
+			    cfg->ap1_golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap2_golomb_par < MIN_RDCU_GOLOMB_PAR ||
+	    cfg->ap2_golomb_par > MAX_RDCU_GOLOMB_PAR) {
+		debug_print("Error: The selected adaptive 2 Golomb parameter: %u is not supported. The Golomb parameter has to be between [%u, %u].\n",
+			    cfg->ap2_golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg_invalid++;
+	}
+
+	if (cfg->spill < MIN_RDCU_SPILL) {
+		debug_print("Error: The selected spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+			    cfg->spill, MIN_RDCU_SPILL);
+		cfg_invalid++;
+	}
+
+	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->data_type)) {
+		debug_print("Error: The selected spillover threshold value: %u is too large for the selected Golomb parameter: %u, the largest possible spillover value is: %u.\n",
+			    cfg->spill, cfg->golomb_par, get_max_spill(cfg->golomb_par, cfg->data_type));
+		cfg_invalid++;
+	}
+
+	if (cfg->ap1_spill < MIN_RDCU_SPILL) {
+		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+			    cfg->ap1_spill, MIN_RDCU_SPILL);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->data_type)) {
+		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too large for the selected adaptive 1 Golomb parameter: %u, the largest possible adaptive 1 spillover value is: %u.\n",
+			    cfg->ap1_spill, cfg->ap1_golomb_par, get_max_spill(cfg->ap1_golomb_par, cfg->data_type));
+		cfg_invalid++;
+	}
+
+	if (cfg->ap2_spill < MIN_RDCU_SPILL) {
+		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+			    cfg->ap2_spill, MIN_RDCU_SPILL);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->data_type)) {
+		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too large for the selected adaptive 2 Golomb parameter: %u, the largest possible adaptive 2 spillover value is: %u.\n",
+			    cfg->ap2_spill, cfg->ap2_golomb_par, get_max_spill(cfg->ap2_golomb_par, cfg->data_type));
+		cfg_invalid++;
 	}
 
 #ifdef SKIP_CMP_PAR_CHECK
 	return 0;
 #endif
-	if (cfg_invalid)
-		return -cfg_invalid;
-	else
-		return cfg_warning;
+
+	return -cfg_invalid;
+}
+
+
+/**
+ * @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 (Golomb parameter)
+ * @param spillover_par		imagette spillover threshold parameter
+ * @param ap1_golomb_par	adaptive 1 imagette compression parameter (ap1_golomb parameter)
+ * @param ap1_spillover_par	adaptive 1 imagette spillover threshold parameter
+ * @param ap2_golomb_par	adaptive 2 imagette compression parameter (ap2_golomb parameter)
+ * @param ap2_spillover_par	adaptive 1 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;
+
+	if (rdcu_cfg_imagette_is_invalid(cfg))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the compressor configuration is invalid for a 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->input_buf && cfg->samples == 0)
+		debug_print("Warning: The samples parameter is set to 0. No data will be compressed.\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++;
+	}
+
+	if (rdcu_cfg_gen_par_is_invalid(cfg))
+		cfg_invalid++;
+	if (rdcu_cfg_buffers_is_invalid(cfg))
+		cfg_invalid++;
+	if (rdcu_cfg_imagette_is_invalid(cfg))
+		cfg_invalid++;
+
+	return -cfg_invalid;
 }
 
 
 /**
  * @brief set up RDCU compression register
  *
- * @param cfg  configuration contains all parameters required for compression
+ * @param cfg  pointer to a compression configuration contains all parameters
+ *	required for compression
  *
  * @returns 0 on success, error otherwise
  */
 
 int rdcu_set_compression_register(const struct cmp_cfg *cfg)
 {
-	if (rdcu_cmp_cfg_valid(cfg) < 0)
+	if (rdcu_cmp_cfg_is_invalid(cfg))
 		return -1;
 
 	/* first, set compression parameters in local mirror registers */
@@ -509,8 +675,6 @@ int rdcu_start_compression(void)
  *
  * @note when using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
  *      the model parameters (model_value, model_buf, rdcu_model_adr) are ignored
- * @note the icu_output_buf will not be used for the RDCU compression
- * @note the overlapping of the different rdcu buffers is not checked
  * @note the validity of the cfg structure is checked before the compression is
  *	 started
  *
@@ -700,7 +864,7 @@ int rdcu_read_model(const struct cmp_info *info, void *model_buf)
 		return -1;
 
 	/* calculate the need bytes for the model */
-	s = cmp_cal_size_of_data(info->samples_used, info->cmp_mode_used);
+	s = info->samples_used * IMA_SAM2BYT;
 
 	if (model_buf == NULL)
 		return (int)s;
@@ -790,19 +954,17 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 	if (last_info->cmp_err)
 		return -1;
 
-	/* TODO: check read write buffer overlapping */
-
 	rdcu_set_compression_register(cfg);
 
 	/* round up needed size must be a multiple of 4 bytes */
-	samples_4byte = (cfg->samples * SAM2BYT + 3) & ~3U;
+	samples_4byte = (cfg->samples * IMA_SAM2BYT + 3) & ~3U;
 
 	if (cfg->input_buf != NULL) {
 		uint32_t cmp_size_4byte;
 
 		/* now set the data in the local mirror... */
 		if (rdcu_write_sram_16(cfg->input_buf, cfg->rdcu_data_adr,
-				       cfg->samples * SAM2BYT) < 0)
+				       cfg->samples * IMA_SAM2BYT) < 0)
 			return -1;
 
 		/* calculate the need bytes for the bitstream */
@@ -823,7 +985,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 				return -1;
 		}
 	} else {
-		printf("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the sram\n");
+		debug_print("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the SRAM\n");
 	}
 
 	/* read model and write model in parallel */
@@ -832,10 +994,10 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 
 		/* set the model in the local mirror... */
 		if (rdcu_write_sram_16(cfg->model_buf, cfg->rdcu_model_adr,
-				       cfg->samples * SAM2BYT) < 0)
+				       cfg->samples * IMA_SAM2BYT) < 0)
 			return -1;
 
-		new_model_size_4byte = last_info->samples_used * SAM2BYT ;
+		new_model_size_4byte = last_info->samples_used * IMA_SAM2BYT;
 		if (rdcu_sync_sram_mirror_parallel(last_info->rdcu_new_model_adr_used,
 						   (new_model_size_4byte+3) & ~0x3U,
 						   cfg->rdcu_model_adr,
@@ -853,7 +1015,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 	} else if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode)) {
 		/* set the model in the local mirror... */
 		if (rdcu_write_sram_16(cfg->model_buf, cfg->rdcu_model_adr,
-				       cfg->samples * SAM2BYT) < 0)
+				       cfg->samples * IMA_SAM2BYT) < 0)
 			return -1;
 
 		if (rdcu_sync_mirror_to_sram(cfg->rdcu_model_adr, samples_4byte,
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index 93db7b6..a02e897 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -18,75 +18,15 @@
  */
 
 
-#include "../include/cmp_support.h"
-#include "../include/cmp_data_types.h"
-#include "../include/cmp_debug.h"
-
-
-/**
- * @brief Default configuration of the Compressor in model imagette mode.
- * @warning All ICU buffers are set to NULL. Samples and buffer_length are set to 0
- * @note see PLATO-IWF-PL-RS-0005 V1.1
- */
-
-
-const struct cmp_cfg DEFAULT_CFG_MODEL = {
-	MODE_MODEL_MULTI, /* cmp_mode */
-	4, /* golomb_par */
-	48, /* spill */
-	8, /* model_value */
-	0, /* round */
-	3, /* ap1_golomb_par */
-	35, /* ap1_spill */
-	5, /* ap2_golomb_par */
-	60, /* ap2_spill */
-	NULL, /* *input_buf */
-	0x000000, /* rdcu_data_adr */
-	NULL, /* *model_buf */
-	0x200000, /* rdcu_model_adr */
-	NULL, /* *icu_new_model_buf */
-	0x400000, /* rdcu_up_model_adr */
-	0, /* samples */
-	NULL, /* *icu_output_buf */
-	0x600000, /* rdcu_buffer_adr */
-	0x0 /* buffer_length */
-};
-
-
-/**
- * @brief Default configuration of the Compressor in 1d-differencing imagette mode.
- * @warning All ICU buffers are set to NULL. Samples and buffer_length are set to 0
- * @note see PLATO-IWF-PL-RS-0005 V1.1
- */
-
-const struct cmp_cfg DEFAULT_CFG_DIFF = {
-	MODE_DIFF_ZERO, /* cmp_mode */
-	7, /* golomb_par */
-	60, /* spill */
-	8, /* model_value */
-	0, /* round */
-	6, /* ap1_golomb_par */
-	48, /* ap1_spill */
-	8, /* ap2_golomb_par */
-	72, /* ap2_spill */
-	NULL, /* *input_buf */
-	0x000000, /* rdcu_data_adr */
-	NULL, /* *model_buf */
-	0x000000, /* rdcu_model_adr */
-	NULL, /* *icu_new_model_buf */
-	0x000000, /* rdcu_up_model_adr */
-	0, /* samples */
-	NULL, /* *icu_output_buf */
-	0x600000, /* rdcu_buffer_adr */
-	0x0 /* buffer_length */
-};
+#include "cmp_support.h"
+#include "cmp_debug.h"
 
 
 /**
  * @brief implementation of the logarithm base of floor(log2(x)) for integers
  * @note ilog_2(0) = -1 defined
  *
- * @param x input parameter
+ * @param x	input parameter
  *
  * @returns the result of floor(log2(x))
  */
@@ -101,10 +41,10 @@ int ilog_2(uint32_t x)
 
 
 /**
- * @brief Determining if an integer is a power of 2
+ * @brief determining if an integer is a power of 2
  * @note 0 is incorrectly considered a power of 2 here
  *
- * @param v we want to see if v is a power of 2
+ * @param v	we want to see if v is a power of 2
  *
  * @returns 1 if v is a power of 2, otherwise 0
  *
@@ -117,231 +57,278 @@ int is_a_pow_of_2(unsigned int v)
 }
 
 
+/**
+ * @brief check if the compression entity data product type is supported
+ *
+ * @param data_type	compression entity data product type to check
+ *
+ * @returns zero if data_type is invalid; non-zero if data_type is valid
+ */
+
+int cmp_data_type_valid(enum cmp_data_type data_type)
+{
+	if (data_type <= DATA_TYPE_UNKOWN || data_type > DATA_TYPE_F_CAM_OFFSET)
+		return 0;
+
+	return 1;
+}
+
+
 /**
  * @brief check if a model mode is selected
  *
- * @param cmp_mode compression mode
+ * @param cmp_mode	compression mode
  *
- * @returns 1 when model mode is set, otherwise 0
+ * @returns 1 when the model mode is used, otherwise 0
  */
 
-int model_mode_is_used(unsigned int cmp_mode)
+int model_mode_is_used(enum cmp_mode cmp_mode)
 {
-	switch (cmp_mode) {
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
+	if (cmp_mode == CMP_MODE_MODEL_ZERO ||
+	    cmp_mode == CMP_MODE_MODEL_MULTI)
 		return 1;
-		break;
-	default:
-		return 0;
-		break;
-	}
+
+	return 0;
 }
 
 
 /**
  * @brief check if a 1d-differencing mode is selected
  *
- * @param cmp_mode compression mode
+ * @param cmp_mode	compression mode
  *
- * @returns 1 when 1d-differencing mode is set, otherwise 0
+ * @returns 1 when the 1d-differencing mode is used, otherwise 0
  */
 
-int diff_mode_is_used(unsigned int cmp_mode)
+int diff_mode_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_DIFF_ZERO ||
+	    cmp_mode == CMP_MODE_DIFF_MULTI)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the raw mode is selected
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when the raw mode is used, otherwise 0
+ */
+
+int raw_mode_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_RAW)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the compression mode is supported by the RDCU compressor
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when the compression mode is supported by the RDCU, otherwise 0
+ */
+
+int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode)
 {
 	switch (cmp_mode) {
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI:
-	case MODE_DIFF_MULTI_S_FX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
+	case CMP_MODE_RAW:
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_DIFF_ZERO:
+	case CMP_MODE_MODEL_MULTI:
+	case CMP_MODE_DIFF_MULTI:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
+
 }
 
 
 /**
- * @brief check if the raw mode is selected
+ * @brief check if the data product data type is supported by the RDCU compressor
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data product types
  *
- * @returns 1 when raw mode is set, otherwise 0
+ * @returns 1 when the data type is supported by the RDCU, otherwise 0
  */
 
-int raw_mode_is_used(unsigned int cmp_mode)
+int rdcu_supported_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-	case MODE_RAW_32:
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
 }
 
 
 /**
- * @brief check if the mode is supported by the RDCU compressor
+ * @brief check if the compression mode is supported for an ICU compression
  *
- * @param cmp_mode compression mode
+ * @param cmp_mode	compression mode
  *
- * @returns 1 when mode is supported by the RDCU, otherwise 0
+ * @returns 1 when the compression mode is supported, otherwise 0
  */
 
-int rdcu_supported_mode_is_used(unsigned int cmp_mode)
+int cmp_mode_is_supported(enum cmp_mode cmp_mode)
 {
 	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
+	case CMP_MODE_RAW:
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_DIFF_ZERO:
+	case CMP_MODE_MODEL_MULTI:
+	case CMP_MODE_DIFF_MULTI:
+	case CMP_MODE_STUFF:
+		return 1;
+	}
+	return 0;
+}
+
+
+/**
+ * @brief check if zero escape symbol mechanism mode is used
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when zero escape symbol mechanism is set, otherwise 0
+ */
+
+int zero_escape_mech_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_MODEL_ZERO ||
+	    cmp_mode == CMP_MODE_DIFF_ZERO)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if multi escape symbol mechanism mode is used
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when multi escape symbol mechanism is set, otherwise 0
+ */
+
+int multi_escape_mech_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_MODEL_MULTI ||
+	    cmp_mode == CMP_MODE_DIFF_MULTI)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if an imagette compression data type is used
+ * @note adaptive imagette compression data types included
+ *
+ * @param data_type	compression data type
+ *
+ * @returns 1 when data_type is an imagette data type, otherwise 0
+ */
+
+int cmp_imagette_data_type_is_used(enum cmp_data_type data_type)
+{
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
 }
 
 
 /**
- * @brief check if the mode is available
+ * @brief check if an adaptive imagette compression data type is used
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data type
  *
- * @returns 1 when mode is available, otherwise 0
+ * @returns 1 when data_type is an adaptive imagette data type, otherwise 0
  */
 
-int cmp_mode_available(unsigned int cmp_mode)
+int cmp_ap_imagette_data_type_is_used(enum cmp_data_type data_type)
 {
-	if (diff_mode_is_used(cmp_mode) ||
-	    model_mode_is_used(cmp_mode) ||
-	    raw_mode_is_used(cmp_mode))
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return 1;
-	else
+	default:
 		return 0;
-
+	}
 }
 
 
 /**
- * @brief check if zero escape symbol mechanism mode is used
+ * @brief check if a flux/center of brightness compression data type is used
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data type
  *
- * @returns 1 when zero escape symbol mechanism is set, otherwise 0
+ * @returns 1 when data_type is a flux/center of brightness data type, otherwise 0
  */
 
-int zero_escape_mech_is_used(unsigned int cmp_mode)
+int cmp_fx_cob_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (cmp_mode) {
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_32:
-	case MODE_DIFF_ZERO_32:
+	switch (data_type) {
+	case DATA_TYPE_S_FX:
+	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_NCOB:
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX:
+	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_NCOB:
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX:
+	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_NCOB:
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
-
 }
 
 
 /**
- * @brief check if multi escape symbol mechanism mode is used
+ * @brief check if an auxiliary science compression data type is used
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data type
  *
- * @returns 1 when multi escape symbol mechanism is set, otherwise 0
+ * @returns 1 when data_type is an auxiliary science data type, otherwise 0
  */
 
-int multi_escape_mech_is_used(unsigned int cmp_mode)
+int cmp_aux_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (cmp_mode) {
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_MULTI_32:
+	switch (data_type) {
+	case DATA_TYPE_OFFSET:
+	case DATA_TYPE_BACKGROUND:
+	case DATA_TYPE_SMEARING:
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
 }
 
@@ -349,8 +336,8 @@ int multi_escape_mech_is_used(unsigned int cmp_mode)
 /**
  * @brief method for lossy rounding
  *
- * @param value value to round
- * @param round round parameter
+ * @param value	the value to round
+ * @param round	rounding parameter
  *
  * @return rounded value
  */
@@ -364,8 +351,8 @@ unsigned int round_fwd(unsigned int value, unsigned int round)
 /**
  * @brief inverse method for lossy rounding
  *
- * @param value value to round back
- * @param round round parameter
+ * @param value	the value to round back
+ * @param round	rounding parameter
  *
  * @return back rounded value
  */
@@ -378,9 +365,8 @@ unsigned int round_inv(unsigned int value, unsigned int round)
 
 /**
  * @brief implantation of the model update equation
- *
  * @note check before that model_value is not greater than MAX_MODEL_VALUE
-
+ *
  * @param data		data to process
  * @param model		(current) model of the data to process
  * @param model_value	model weighting parameter
@@ -388,9 +374,14 @@ unsigned int round_inv(unsigned int value, unsigned int round)
  * @returns (new) updated model
  */
 
-unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
-			  model_value)
+unsigned int cmp_up_model(unsigned int data, unsigned int model,
+			  unsigned int model_value, unsigned int round)
+
 {
+	/* round and round back input because for decompression the accurate
+	 * data values are not available
+	 */
+	data = round_inv(round_fwd(data, round), round);
 	/* cast uint64_t to prevent overflow in the multiplication */
 	uint64_t weighted_model = (uint64_t)model * model_value;
 	uint64_t weighted_data = (uint64_t)data * (MAX_MODEL_VALUE - model_value);
@@ -402,13 +393,13 @@ unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
 /**
  * @brief get the maximum valid spill threshold value for a given golomb_par
  *
- * @param golomb_par Golomb parameter
- * @param cmp_mode   compression mode
+ * @param golomb_par	Golomb parameter
+ * @param data_type	compression data type
  *
  * @returns the highest still valid spill threshold value
  */
 
-uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode)
+uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type data_type)
 {
 	const uint32_t LUT_MAX_RDCU[MAX_RDCU_GOLOMB_PAR+1] = { 0, 8, 22, 35, 48,
 		60, 72, 84, 96, 107, 118, 129, 140, 151, 162, 173, 184, 194,
@@ -420,208 +411,447 @@ uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode)
 	if (golomb_par == 0)
 		return 0;
 
-	if (rdcu_supported_mode_is_used(cmp_mode)) {
+	/* the RDCU can only generate 16 bit long code words -> lower max spill needed */
+	if (rdcu_supported_data_type_is_used(data_type)) {
 		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
 			return 0;
 
 		return LUT_MAX_RDCU[golomb_par];
+	}
+
+	if (golomb_par > MAX_ICU_GOLOMB_PAR) {
+		return 0;
 	} else {
-		if (golomb_par > MAX_ICU_GOLOMB_PAR) {
-			return 0;
-		} else {
-			/* the ICU compressor can generate code words with a length of
-			 * maximal 32 bits.  */
-			unsigned int max_cw_bits = 32;
-			unsigned int cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
-			unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
-			return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
-				max_n_sym_offset - 1;
+		/* the ICU compressor can generate code words with a length of
+		 * maximal 32 bits.
+		 */
+		unsigned int max_cw_bits = 32;
+		unsigned int cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
+		unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
+
+		return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
+			max_n_sym_offset - 1;
+	}
+}
+
+
+/**
+ * @brief calculate the need bytes to hold a bitstream
+ *
+ * @param cmp_size_bit	compressed data size, measured in bits
+ *
+ * @returns the size in bytes to store the hole bitstream
+ * @note we round up the result to multiples of 4 bytes
+ */
+
+unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
+{
+	return (((cmp_size_bit + 7) / 8) + 3) & ~0x3UL;
+}
+
+
+/**
+ * @brief check if the compression data type, compression mode, model value and
+ *	the lossy rounding parameters are valid for a ICU compression
+ *
+ * @param cfg	pointer to the compressor configuration
+ *
+ * @returns 1 if generic compression parameters are valid, otherwise 0
+ */
+
+int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cmp_data_type_valid(cfg->data_type)) {
+		debug_print("Error: selected compression data type is not supported.\n");
+		cfg_invalid++;
+	}
+
+	if (cfg->cmp_mode > CMP_MODE_STUFF) {
+		debug_print("Error: selected cmp_mode: %u is not supported\n.", cfg->cmp_mode);
+		cfg_invalid++;
+	}
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->model_value > MAX_MODEL_VALUE) {
+			debug_print("Error: selected model_value: %u is invalid. Largest supported value is: %u.\n",
+				    cfg->model_value, MAX_MODEL_VALUE);
+			cfg_invalid++;
 		}
 	}
+
+	if (cfg->round > MAX_ICU_ROUND) {
+		debug_print("Error: selected lossy parameter: %u is not supported. Largest supported value is: %u.\n",
+			    cfg->round, MAX_ICU_ROUND);
+		cfg_invalid++;
+	}
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief get a good spill threshold parameter for the selected Golomb parameter
- *	and compression mode
+ * @brief check if the buffer parameters are valid
  *
- * @param golomb_par Golomb parameter
- * @param cmp_mode compression mode
+ * @param cfg	pointer to the compressor configuration
  *
- * @returns a good spill parameter (optimal for zero escape mechanism)
- * @warning icu compression not support yet!
+ * @returns 1 if the buffer parameters are valid, otherwise 0
  */
 
-uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode)
+int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
 {
-	const uint32_t LUT_RDCU_MULIT[MAX_RDCU_GOLOMB_PAR+1] = {0, 8, 16, 23,
-		30, 36, 44, 51, 58, 64, 71, 77, 84, 90, 97, 108, 115, 121, 128,
-		135, 141, 148, 155, 161, 168, 175, 181, 188, 194, 201, 207, 214,
-		229, 236, 242, 250, 256, 263, 269, 276, 283, 290, 296, 303, 310,
-		317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397,
-		405, 411, 418, 424, 431, 452 };
+	int cfg_invalid = 0;
 
-	if (zero_escape_mech_is_used(cmp_mode))
-		return get_max_spill(golomb_par, cmp_mode);
+	if (!cfg)
+		return 0;
 
-	if (cmp_mode == MODE_MODEL_MULTI) {
-		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
-			return 0;
-		else
-			return LUT_RDCU_MULIT[golomb_par];
+	if (cfg->input_buf == NULL) {
+		debug_print("Error: The data_to_compress buffer for the data to be compressed is NULL.\n");
+		cfg_invalid++;
 	}
 
-	if (cmp_mode == MODE_DIFF_MULTI)
-		return CMP_GOOD_SPILL_DIFF_MULTI;
+	if (cfg->samples == 0)
+		debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
 
-	return 0;
+	if (cfg->icu_output_buf && cfg->buffer_length == 0 && cfg->samples != 0) {
+		debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n");
+		cfg_invalid++;
+	}
+
+	if (cfg->icu_output_buf == cfg->input_buf) {
+		debug_print("Error: The compressed_data buffer is the same as the data_to_compress buffer.\n");
+		cfg_invalid++;
+	}
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->model_buf == NULL) {
+			debug_print("Error: The model_of_data buffer for the model data is NULL.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->model_buf == cfg->input_buf) {
+			debug_print("Error: The model_of_data buffer is the same as the data_to_compress buffer.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->model_buf == cfg->icu_output_buf) {
+			debug_print("Error: The model_of_data buffer is the same as the compressed_data buffer.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->icu_new_model_buf) {
+			if (cfg->icu_new_model_buf == cfg->input_buf) {
+				debug_print("Error: The updated_model buffer is the same as the data_to_compress buffer.\n");
+				cfg_invalid++;
+			}
+
+			if (cfg->icu_new_model_buf == cfg->icu_output_buf) {
+				debug_print("Error: The compressed_data buffer is the same as the compressed_data buffer.\n");
+				cfg_invalid++;
+			}
+		}
+	}
+
+	if (raw_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->buffer_length < cfg->samples) {
+			debug_print("Error: The compressed_data_len_samples is to small to hold the data form the data_to_compress.\n");
+			cfg_invalid++;
+		}
+	} else {
+		if (cfg->samples < cfg->buffer_length/3)
+			debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended.This is probably unintended.\n");
+	}
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculate the size of a sample for the different compression modes
+ * @brief check if the combination of the different compression parameters is valid
  *
- * @param cmp_mode compression mode
+ * @param cmp_par	compression parameter
+ * @param spill		spillover threshold parameter
+ * @param cmp_mode	compression mode
+ * @param data_type	compression data type
+ * @param par_name	string describing the use of the compression par. for
+ *			debug messages (can be NULL)
  *
- * @returns the size of a data sample in bytes for the selected compression
- *	mode;
+ * @returns 1 if the parameter combination is valid, otherwise 0
  */
 
-size_t size_of_a_sample(unsigned int cmp_mode)
+static int cmp_pars_are_valid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cmp_mode,
+			      enum cmp_data_type data_type, char *par_name)
 {
-	size_t sample_len;
+	int cfg_invalid = 0;
+
+	if (!par_name)
+		par_name = "";
 
 	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		sample_len = sizeof(uint16_t);
-		break;
-	case MODE_RAW_S_FX:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		sample_len = sizeof(struct S_FX);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		sample_len = sizeof(struct S_FX_NCOB);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		sample_len = sizeof(struct S_FX_EFX_NCOB_ECOB);
+	case CMP_MODE_RAW:
+		/* no checks needed */
 		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		sample_len = sizeof(struct F_FX);
-		break;
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-		sample_len = sizeof(struct F_FX_EFX);
-		break;
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-		sample_len = sizeof(struct F_FX_NCOB);
-		break;
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-		sample_len = sizeof(struct F_FX_EFX_NCOB_ECOB);
+	case CMP_MODE_STUFF:
+		if (cmp_par > MAX_STUFF_CMP_PAR) {
+			debug_print("Error: The selected %s stuff mode compression parameter: %u is too large, the largest possible value in the selected compression mode is: %u.\n",
+				    par_name, cmp_par, MAX_STUFF_CMP_PAR);
+			cfg_invalid++;
+		}
 		break;
-	case MODE_RAW_32:
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-		sample_len = sizeof(uint32_t);
+	case CMP_MODE_DIFF_ZERO:
+	case CMP_MODE_DIFF_MULTI:
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_MODEL_MULTI:
+		if (cmp_par < MIN_ICU_GOLOMB_PAR ||
+		    cmp_par > MAX_ICU_GOLOMB_PAR) {
+			debug_print("Error: The selected %s compression parameter: %u is not supported. The compression parameter has to be between [%u, %u].\n",
+				    par_name, cmp_par, MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+			cfg_invalid++;
+		}
+		if (spill < MIN_ICU_SPILL) {
+			debug_print("Error: The selected %s spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+				    par_name, spill, MIN_ICU_SPILL);
+			cfg_invalid++;
+		}
+		if (spill > get_max_spill(cmp_par, data_type)) {
+			debug_print("Error: The selected %s spillover threshold value: %u is too large for the selected %s compression parameter: %u, the largest possible spillover value in the selected compression mode is: %u.\n",
+				    par_name, spill, par_name, cmp_par, get_max_spill(cmp_par, data_type));
+			cfg_invalid++;
+		}
+
 		break;
 	default:
-		debug_print("Error: Compression mode not supported.\n");
-		return 0;
+		debug_print("Error: The compression mode is not supported.\n");
+		cfg_invalid++;
 		break;
 	}
-	return sample_len;
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculates the number of samples for a given data size for the
- *	different compression modes
+ * @brief check if the imagette specific compression parameters are valid
  *
- * @param size		size of the data me
- * @param cmp_mode	compression mode
+ * @param cfg	pointer to the compressor configuration
  *
- * @returns the number samples for the given compression mode; negative on error
+ * @returns 1 if the imagette specific parameters are valid, otherwise 0
  */
 
-int cmp_input_size_to_samples(unsigned int size, unsigned int cmp_mode)
+int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg)
 {
-	unsigned int samples_size = size_of_a_sample(cmp_mode);
+	int cfg_invalid = 0;
 
-	if (!samples_size)
-		return -1;
+	if (!cfg)
+		return 0;
 
-	if (!rdcu_supported_mode_is_used(cmp_mode)) {
-		if (size < N_DPU_ICU_MULTI_ENTRY_HDR_SIZE)
-			return -1;
-		size -= N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+	if (!cmp_imagette_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The compression data type is not an imagette compression data type.!\n");
+		cfg_invalid++;
 	}
 
-	if (size % samples_size)
-		return -1;
+	if (!cmp_pars_are_valid(cfg->golomb_par, cfg->spill, cfg->cmp_mode,
+				cfg->data_type, "imagette"))
+		cfg_invalid++;
+
+	if (cmp_ap_imagette_data_type_is_used(cfg->data_type)) {
+		if (!cmp_pars_are_valid(cfg->ap1_golomb_par, cfg->ap1_spill,
+					cfg->cmp_mode, cfg->data_type, "adaptive 1 imagette"))
+			cfg_invalid++;
+		if (!cmp_pars_are_valid(cfg->ap2_golomb_par, cfg->ap2_spill,
+					cfg->cmp_mode, cfg->data_type, "adaptive 2 imagette"))
+			cfg_invalid++;
+	}
 
-	return size/samples_size;
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculate the need bytes to hold a bitstream
+ * @brief check if the flux/center of brightness specific compression parameters are valid
  *
- * @param cmp_size_bit compressed data size, measured in bits
+ * @param cfg	pointer to the compressor configuration
  *
- * @returns the size in bytes to store the hole bitstream
- * @note we round up the result to multiples of 4 bytes
+ * @returns 1 if the flux/center of brightness specific parameters are valid, otherwise 0
  */
 
-unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
+int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 {
-	return (((cmp_size_bit + 7) / 8) + 3) & ~0x3UL;
+	int cfg_invalid = 0;
+	int check_exp_flags = 0, check_ncob = 0, check_efx = 0, check_ecob = 0, check_var = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cmp_fx_cob_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The compression data type is not a flux/center of brightness compression data type.!\n");
+		cfg_invalid++;
+	}
+	/* flux parameter is needed for every fx_cob data_type */
+	if (!cmp_pars_are_valid(cfg->cmp_par_fx, cfg->spill_fx, cfg->cmp_mode, cfg->data_type, "flux"))
+		cfg_invalid++;
+
+	switch (cfg->data_type) {
+	case DATA_TYPE_S_FX:
+		check_exp_flags = 1;
+		break;
+	case DATA_TYPE_S_FX_DFX:
+		check_exp_flags = 1;
+		check_efx = 1;
+		break;
+	case DATA_TYPE_S_FX_NCOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		break;
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		check_efx = 1;
+		check_ecob = 1;
+		break;
+	case DATA_TYPE_L_FX:
+		check_exp_flags = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_L_FX_DFX:
+		check_exp_flags = 1;
+		check_efx = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		check_efx = 1;
+		check_ecob = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_F_FX:
+		break;
+	case DATA_TYPE_F_FX_DFX:
+		check_efx = 1;
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		check_ncob = 1;
+		break;
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		check_ncob = 1;
+		check_efx = 1;
+		check_ecob = 1;
+		break;
+	default:
+		cfg_invalid++;
+		break;
+	}
+
+	if (check_exp_flags && !cmp_pars_are_valid(cfg->cmp_par_exp_flags, cfg->spill_exp_flags, cfg->cmp_mode, cfg->data_type, "exposure flags"))
+		cfg_invalid++;
+	if (check_ncob && !cmp_pars_are_valid(cfg->cmp_par_ncob, cfg->spill_ncob, cfg->cmp_mode, cfg->data_type, "center of brightness"))
+		cfg_invalid++;
+	if (check_efx && !cmp_pars_are_valid(cfg->cmp_par_efx, cfg->spill_efx, cfg->cmp_mode, cfg->data_type, "extended flux"))
+		cfg_invalid++;
+	if (check_ecob && !cmp_pars_are_valid(cfg->cmp_par_ecob, cfg->spill_ecob, cfg->cmp_mode, cfg->data_type, "extended center of brightness"))
+		cfg_invalid++;
+	if (check_var && !cmp_pars_are_valid(cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, cfg->cmp_mode, cfg->data_type, "flux COB varianc"))
+		cfg_invalid++;
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculate the need bytes for the data
+ * @brief check if the auxiliary science specific compression parameters are valid
  *
- * @param samples number of data samples
- * @param cmp_mode used compression mode
+ * @param cfg	pointer to the compressor configuration
  *
- * @note for non RDCU modes the N_DPU ICU multi entry header size is added
+ * @returns 1 if the auxiliary science specific parameters are valid, otherwise 0
+ */
+
+int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cmp_aux_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The compression data type is not an auxiliary science compression data type.!\n");
+		cfg_invalid++;
+	}
+
+	if (!cmp_pars_are_valid(cfg->cmp_par_mean, cfg->spill_mean, cfg->cmp_mode, cfg->data_type, "mean"))
+		cfg_invalid++;
+	if (!cmp_pars_are_valid(cfg->cmp_par_variance, cfg->spill_variance, cfg->cmp_mode, cfg->data_type, "variance"))
+		cfg_invalid++;
+	if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET)
+		if (!cmp_pars_are_valid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error, cfg->cmp_mode, cfg->data_type, "outlier pixls num"))
+			cfg_invalid++;
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
+}
+
+
+/**
+ * @brief check if a compression configuration is valid
  *
- * @returns the size in bytes to store the data sample
+ * @param cfg	pointer to the compressor configuration
+ *
+ * @returns 1 if the compression configuration is valid, otherwise 0
  */
 
-unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode)
+int cmp_cfg_is_valid(const struct cmp_cfg *cfg)
 {
-	unsigned int s = samples * size_of_a_sample(cmp_mode);
+	int cfg_invalid = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cmp_cfg_icu_gen_par_is_valid(cfg))
+		cfg_invalid++;
+
+	if (!cmp_cfg_icu_buffers_is_valid(cfg))
+		cfg_invalid++;
+
+	if (cmp_imagette_data_type_is_used(cfg->data_type)) {
+		if (!cmp_cfg_imagette_is_valid(cfg))
+			cfg_invalid++;
+	} else if (cmp_fx_cob_data_type_is_used(cfg->data_type)) {
+		if (!cmp_cfg_fx_cob_is_valid(cfg))
+			cfg_invalid++;
+	} else if (cmp_aux_data_type_is_used(cfg->data_type)) {
+		if (!cmp_cfg_aux_is_valid(cfg))
+			cfg_invalid++;
+	} else {
+		cfg_invalid++;
+	}
 
-	if (!rdcu_supported_mode_is_used(cmp_mode))
-		s += N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+	if (cfg_invalid)
+		return 0;
 
-	return s;
+	return 1;
 }
 
 
@@ -630,7 +860,6 @@ unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode)
  *
  * @param cfg	compressor configuration contains all parameters required for
  *		compression
- *
  */
 
 void print_cmp_cfg(const struct cmp_cfg *cfg)
diff --git a/lib/decmp.c b/lib/decmp.c
index 4953f5d..c22e5e4 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -4,823 +4,43 @@
 #include <limits.h>
 #include <string.h>
 
-#include "../include/cmp_support.h"
-#include "../include/cmp_icu.h"
-#include "../include/cmp_data_types.h"
-#include "../include/byteorder.h"
-#include "../include/cmp_debug.h"
+#include "byteorder.h"
+#include "cmp_debug.h"
+#include "cmp_support.h"
+#include "cmp_data_types.h"
+#include "cmp_entity.h"
 
+#define CMP_ERROR_SAMLL_BUF -2
 
-double get_compression_ratio(const struct cmp_info *info)
-{
-	unsigned long orign_len_bits = info->samples_used * size_of_a_sample(info->cmp_mode_used) * CHAR_BIT;
-
-	return (double)orign_len_bits/(double)info->cmp_size;
-}
-
-
-void *malloc_decompressed_data(const struct cmp_info *info)
-{
-	size_t sample_len;
-
-	if (!info)
-		return NULL;
-
-	if (info->samples_used == 0)
-		return NULL;
-
-	sample_len = size_of_a_sample(info->cmp_mode_used);
-
-	return malloc(info->samples_used * sample_len);
-}
-
-
-/**
- * @brief decompression data pre-processing in RAW mode
- *
- * @note in RAW mode the data are uncompressed no pre_processing needed
- *
- * @param  cmp_mode_used used compression mode
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_raw_pre_process(uint8_t cmp_mode_used)
-{
-	if (!raw_mode_is_used(cmp_mode_used))
-		return -1;
-
-	return 0;
-}
-
-
-/**
- * @brief model decompression pre-processing
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the data to process
- * @param model_buf	pointer to the model of the data to process
- * @param samples_used	the size of the data and model buffer in 16 bit units
- * @param model_value_used used model weighting parameter
- * @param round_used	used number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_model_16(uint16_t *data_buf, uint16_t *model_buf, uint32_t
-		       samples_used, uint8_t model_value_used, uint8_t
-		       round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (!model_buf)
-		return -1;
-
-	if (model_value_used > MAX_MODEL_VALUE)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		/* overflow is intended */
-		data_buf[i] = (uint16_t)(data_buf[i] + round_fwd(model_buf[i],
-								  round_used));
-	}
-
-	err = de_lossy_rounding_16(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		model_buf[i] = (uint16_t)cal_up_model(data_buf[i], model_buf[i],
-						      model_value_used);
-	}
-	return 0;
-}
-
-
-static int de_model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf, uint32_t
-		       samples_used, uint8_t model_value_used, uint8_t
-		       round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (!model_buf)
-		return -1;
-
-	if (model_value_used > MAX_MODEL_VALUE)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		/* overflow is intended */
-		struct S_FX round_model = model_buf[i];
-
-		lossy_rounding_S_FX(&round_model, 1, round_used);
-		data_buf[i] = add_S_FX(data_buf[i], model_buf[i]);
-	}
-
-	err = de_lossy_rounding_S_FX(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	for (i = 0; i < samples_used; i++)
-		model_buf[i] = cal_up_model_S_FX(data_buf[i], model_buf[i],
-						 model_value_used);
-
-	return 0;
-}
-
-
-/**
- * @brief 1d-differencing decompression per-processing
- *
- * @param data_buf	pointer to the data to process
- * @param samples_used	the size of the data and model buffer in 16 bit units
- * @param round_used	used number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_diff_16(uint16_t *data_buf, uint32_t samples_used, uint8_t
-		      round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = data_buf[i] + data_buf[i-1];
-	}
-
-	err = de_lossy_rounding_16(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_32(uint32_t *data_buf, uint32_t samples_used, uint8_t
-		      round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = data_buf[i] + data_buf[i-1];
-	}
-
-	err = de_lossy_rounding_32(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX(struct S_FX *data_buf, uint32_t samples_used, uint8_t
-			round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX_EFX(struct S_FX_EFX *data_buf, uint32_t samples_used,
-			    uint8_t round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX_EFX(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX_EFX(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX_NCOB(struct S_FX_NCOB *data_buf, uint32_t samples_used,
-			     uint8_t round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX_NCOB(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX_NCOB(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-				      uint32_t samples_used, uint8_t round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX_EFX_NCOB_ECOB(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX_EFX_NCOB_ECOB(data_buf, samples_used,
-						   round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_pre_process(void *decoded_data, void *de_model_buf,
-			  const struct cmp_info *info)
-{
-	if (!decoded_data)
-		return -1;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
-
-	switch (info->cmp_mode_used) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return de_raw_pre_process(info->cmp_mode_used);
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-		return de_model_16((uint16_t *)decoded_data,
-				   (uint16_t *)de_model_buf, info->samples_used,
-				   info->model_value_used, info->round_used);
-		break;
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return de_diff_16((uint16_t *)decoded_data, info->samples_used,
-				  info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-		return de_model_S_FX((struct S_FX *)decoded_data,
-				   (struct S_FX *)de_model_buf,
-				   info->samples_used, info->model_value_used,
-				   info->round_used);
-		break;
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return de_diff_S_FX((struct S_FX *)decoded_data,
-				    info->samples_used, info->round_used);
-		break;
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return de_diff_S_FX_EFX((struct S_FX_EFX *)decoded_data,
-					info->samples_used, info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-		return -1;
-		break;
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return de_diff_S_FX_NCOB((struct S_FX_NCOB *)decoded_data,
-					 info->samples_used, info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-		return -1;
-		break;
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return de_diff_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)
-						  decoded_data,
-						  info->samples_used,
-						  info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-		return -1;
-		break;
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return de_diff_32((uint32_t *)decoded_data, info->samples_used,
-				  info->round_used);
-		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-		return -1;
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
-	}
-
-	return -1;
-}
-
-
-static uint8_t de_map_to_pos_alg_8(uint8_t value_to_unmap)
-{
-	if (value_to_unmap & 0x1) /* if uneven */
-		return (value_to_unmap + 1) / -2;
-	else
-		return value_to_unmap / 2;
-}
-
-
-static uint16_t de_map_to_pos_alg_16(uint16_t value_to_unmap)
-{
-	if (value_to_unmap & 0x1) /* if uneven */
-		return (value_to_unmap + 1) / -2;
-	else
-		return value_to_unmap / 2;
-}
-
-
-static uint32_t de_map_to_pos_alg_32(uint32_t value_to_unmap)
-{
-
-	if (value_to_unmap & 0x1) /* if uneven */
-		return ((int64_t)value_to_unmap + 1) / -2; /* typecast to prevent overflow */
-	else
-		return value_to_unmap / 2;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	16-bit buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_16(uint16_t *data_buf, uint32_t samples_used, int
-			    zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used)
-			data_buf[i] -= 1;
-
-		data_buf[i] = (uint16_t)de_map_to_pos_alg_16(data_buf[i]);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	32-bit buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_32(uint32_t *data_buf, uint32_t samples_used, int
-			    zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used)
-			data_buf[i] -= 1;
-
-		data_buf[i] = (uint32_t)de_map_to_pos_alg_32(data_buf[i]);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX(struct S_FX *data_buf, uint32_t samples_used, int
-			      zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX_EFX buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX_EFX data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX_EFX(struct S_FX_EFX *data_buf, uint32_t
-				  samples_used, int zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-			data_buf[i].EFX -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].EFX = de_map_to_pos_alg_32(data_buf[i].EFX);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX_NCOB buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX_NCOB data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX_NCOB(struct S_FX_NCOB *data_buf, uint32_t
-				   samples_used, int zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-			data_buf[i].NCOB_X -= 1;
-			data_buf[i].NCOB_Y -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = de_map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = de_map_to_pos_alg_32(data_buf[i].NCOB_Y);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX_EFX_NCOB_ECOB buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX_EFX_NCOB_ECOB data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					    uint32_t samples_used,
-					    int zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-			data_buf[i].NCOB_X -= 1;
-			data_buf[i].NCOB_Y -= 1;
-			data_buf[i].EFX -= 1;
-			data_buf[i].ECOB_X -= 1;
-			data_buf[i].ECOB_Y -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = de_map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = de_map_to_pos_alg_32(data_buf[i].NCOB_Y);
-		data_buf[i].EFX = de_map_to_pos_alg_32(data_buf[i].EFX);
-		data_buf[i].ECOB_X = de_map_to_pos_alg_32(data_buf[i].ECOB_X);
-		data_buf[i].ECOB_Y = de_map_to_pos_alg_32(data_buf[i].ECOB_Y);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	F_FX buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the F_FX data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_F_FX(uint32_t *data_buf, uint32_t samples_used, int
-			      zero_mode_used)
-{
-	return de_map_to_pos_32(data_buf, samples_used, zero_mode_used);
-}
 
+/* structure to hold a setup to encode a value */
+typedef unsigned int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
+struct decoder_setup {
+	/* generate_cw_f_pt generate_cw_f; /1* pointer to the code word generation function *1/ */
+	decoder_ptr decode_cw_f;
+	int (*encode_method_f)(uint32_t *decoded_value, int stream_pos,
+			       const struct decoder_setup *setup); /* pointer to the decoding function */
+	uint32_t *bitstream_adr; /* start address of the compressed data bitstream */
+	uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */
+	uint32_t max_cw_len;
+	uint32_t encoder_par1; /* encoding parameter 1 */
+	uint32_t encoder_par2; /* encoding parameter 2 */
+	uint32_t outlier_par; /* outlier parameter */
+	uint32_t lossy_par; /* lossy compression parameter */
+	uint32_t model_value; /* model value parameter */
+	uint32_t max_data_bits; /* how many bits are needed to represent the highest possible value */
+};
 
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range
- *
- * @note change the data_buf in-place
- *
- * @param decompressed_data	pointer to the data to process
- * @param info			compressor information contains information of
- *				an executed compression
- *
- * @returns 0 on success, error otherwise
- */
 
-static int de_map_to_pos(void *decompressed_data, const struct cmp_info *info)
+double get_compression_ratio(uint32_t samples, uint32_t cmp_size_bits,
+			     enum cmp_data_type data_type)
 {
-	int zero_mode_used;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
-
-	if (!decompressed_data)
-		return -1;
+	double orign_len_bits = (double)cmp_cal_size_of_data(samples, data_type) * CHAR_BIT;
 
-	zero_mode_used = zero_escape_mech_is_used(info->cmp_mode_used);
-
-	switch (info->cmp_mode_used) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return 0; /* in raw mode no mapping is necessary */
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return de_map_to_pos_16((uint16_t *)decompressed_data,
-					info->samples_used, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return de_map_to_pos_S_FX((struct S_FX *)decompressed_data,
-					  info->samples_used, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return de_map_to_pos_S_FX_EFX((struct S_FX_EFX *)
-					      decompressed_data,
-					      info->samples_used,
-					      zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return de_map_to_pos_S_FX_NCOB((struct S_FX_NCOB *)
-					       decompressed_data,
-					       info->samples_used,
-					       zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return de_map_to_pos_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)
-							decompressed_data,
-							info->samples_used,
-							zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return de_map_to_pos_F_FX((uint32_t *)decompressed_data,
-					  info->samples_used, zero_mode_used);
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
-	}
-	return -1;
+	return orign_len_bits/(double)cmp_size_bits;
 }
 
 
-static unsigned int get_n_bits32(uint32_t *p_value, unsigned int bitOffset,
-				unsigned int nBits, const unsigned int *srcAddr,
-				size_t src_len_bit)
-{
-	const unsigned int *localAddr;
-	unsigned int bitsLeft, bitsRight, localEndPos;
-	unsigned int mask;
-	/*leave in case of erroneous input */
-	if (nBits == 0)
-		return 0;
-	if (nBits > 32)
-		return 0;
-	if (!srcAddr)
-		return 0;
-	if (!p_value)
-		return 0;
-	if ((bitOffset + nBits) > src_len_bit) {
-		debug_print("Error: Buffer overflow detected.\n");
-		return 0;
-	}
-	/* separate the bitOffset into word offset (set localAddr pointer) and
-	 * local bit offset (bitsLeft)
-	 */
-
-	localAddr = srcAddr + (bitOffset >> 5);
-	bitsLeft = bitOffset & 0x1f;
-
-	localEndPos = bitsLeft + nBits;
-
-	if (localEndPos <= 32) {
-		unsigned int shiftRight = 32 - nBits;
-
-		bitsRight = shiftRight - bitsLeft;
-
-		*(p_value) = *(localAddr) >> bitsRight;
-
-		mask = (0xffffffff >> shiftRight);
-
-		*(p_value) &= mask;
-	} else {
-		unsigned int n1 = 32 - bitsLeft;
-		unsigned int n2 = nBits - n1;
-		/* part 1 ; */
-		mask = 0xffffffff >> bitsLeft;
-		*(p_value) = (*localAddr) & mask;
-		*(p_value) <<= n2;
-		/*part 2: */
-		/* adjust address*/
-		localAddr += 1;
-
-		bitsRight = 32 - n2;
-		*(p_value) |= *(localAddr) >> bitsRight;
-	}
-	return nBits;
-}
-
 static unsigned int count_leading_ones(unsigned int value)
 {
 	unsigned int n_ones = 0; /* number of leading 1s */
@@ -831,16 +51,15 @@ static unsigned int count_leading_ones(unsigned int value)
 		leading_bit = value & 0x80000000;
 		if (!leading_bit)
 			break;
-		else {
-			n_ones++;
-			value <<= 1;
-		}
+
+		n_ones++;
+		value <<= 1;
 	}
 	return n_ones;
 }
 
 
-static unsigned int Rice_decoder(uint32_t code_word, unsigned int m,
+static unsigned int rice_decoder(uint32_t code_word, unsigned int m,
 				 unsigned int log2_m, unsigned int *decoded_cw)
 {
 	unsigned int q; /* quotient code */
@@ -863,7 +82,7 @@ static unsigned int Rice_decoder(uint32_t code_word, unsigned int m,
 
 	code_word = code_word << ql;  /* shift quotient code out */
 
-	/* Right shifting an integer by a number of bits equal orgreater than
+	/* Right shifting an integer by a number of bits equal or greater than
 	 * its size is undefined behavior
 	 */
 	if (rl == 0)
@@ -877,7 +96,7 @@ static unsigned int Rice_decoder(uint32_t code_word, unsigned int m,
 }
 
 
-static unsigned int Golomb_decoder(unsigned int code_word, unsigned int m,
+static unsigned int golomb_decoder(unsigned int code_word, unsigned int m,
 				   unsigned int log2_m, unsigned int
 				   *decoded_cw)
 {
@@ -915,608 +134,382 @@ static unsigned int Golomb_decoder(unsigned int code_word, unsigned int m,
 }
 
 
-typedef unsigned int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
-
 static decoder_ptr select_decoder(unsigned int golomb_par)
 {
 	if (!golomb_par)
 		return NULL;
 
 	if (is_a_pow_of_2(golomb_par))
-		return &Rice_decoder;
+		return &rice_decoder;
 	else
-		return &Golomb_decoder;
+		return &golomb_decoder;
 }
 
 
-static int decode_raw(const void *compressed_data, const struct cmp_info
-			*info, void *const decompressed_data)
-{
-	if (!info)
-		return -1;
-	if (info->samples_used == 0)
-		return 0;
-	if (!compressed_data)
-		return -1;
-	if (!decompressed_data)
-		return -1;
-
-	if (info->samples_used*size_of_a_sample(info->cmp_mode_used)*CHAR_BIT
-	    != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
-	memcpy(decompressed_data, compressed_data, info->cmp_size/CHAR_BIT);
-
-	return 0;
-}
+/**
+ * @brief read a value of up to 32 bits from a bitstream
+ *
+ * @param p_value		pointer to the read value
+ * @param n_bits		number of bits to read from the bitstream
+ * @param bit_offset		bit index where the bits will be read, seen from
+ *				the very beginning of the bitstream
+ * @param bitstream_adr		this is the pointer to the beginning of the
+ *				bitstream (can be NULL)
+ * @param max_stream_len	maximum length of the bitstream in bits; is
+ *				ignored if bitstream_adr is NULL
+ *
+ * @returns length in bits of the generated bitstream on success; returns
+ *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
+ *          the bitstream buffer is too small to read the value from the bitstream
+ */
 
-static int decode_raw_16(const void *compressed_data, const struct cmp_info
-			*info, uint16_t *const decompressed_data)
+static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
+			uint32_t *bitstream_adr, unsigned int max_stream_len)
 {
-	size_t i;
-	uint16_t *p = decompressed_data;
-	uint32_t read_pos = 0;
-	unsigned int read_bits;
-	uint32_t read_val;
+	const unsigned int *local_adr;
+	unsigned int bitsLeft, bitsRight, localEndPos;
+	unsigned int mask;
+	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
 
-	if (!info)
-		return -1;
-	if (info->samples_used == 0)
-		return 0;
-	if (!compressed_data)
-		return -1;
-	if (!decompressed_data)
+	/*leave in case of erroneous input */
+	if (bit_offset < 0)
 		return -1;
 
-	for (i = 0; i < info->samples_used; ++i) {
-		read_bits = get_n_bits32(&read_val, read_pos, 16,
-					 compressed_data, info->cmp_size);
-		if (!read_bits)
-			return -1;
-		read_pos += 16;
-		p[i] =read_val;
-	}
-	return 0;
-}
-
-
-static int decode_raw_S_FX(const void *compressed_data, const struct cmp_info
-			   *info, struct S_FX *const decompressed_data)
-{
-	int err = decode_raw(compressed_data, info, decompressed_data);
-	if (err)
-		return err;
+	if (n_bits == 0)
+		return stream_len;
 
-#if defined(LITTLE_ENDIAN)
-	{
-		size_t i;
-		for (i = 0; i < info->samples_used; i++) {
-			decompressed_data[i].FX = cpu_to_be32(decompressed_data[i].FX);
-		}
-	}
-#endif
-	return 0;
-}
+	if (n_bits > 32)
+		return -1;
 
-static unsigned int decode_normal(const void *compressed_data,
-				  const struct cmp_info *info,
-				  unsigned int read_pos,
-				  unsigned int max_cw_len,
-				  uint32_t *const decoded_val)
-{
-	decoder_ptr decoder;
-	unsigned int n_read_bits;
-	uint32_t read_val;
-	unsigned int n_bits;
-	unsigned int read_bits;
-	unsigned int log2_g;
+	if (!bitstream_adr)
+		return stream_len;
 
-	if (!compressed_data)
-		return -1U;
+	if (!p_value)
+		return stream_len;
 
-	if (!info)
-		return -1U;
+	/* Check if bitstream buffer is large enough */
+	if ((unsigned int)stream_len > max_stream_len) {
+		debug_print("Error: Buffer overflow detected.\n");
+		return CMP_ERROR_SAMLL_BUF;
 
-	if (!decoded_val)
-		return -1U;
+	}
 
-	if (read_pos > info->cmp_size)
-		return -1U;
+	/* separate the bit_offset into word offset (set local_adr pointer) and
+	 * local bit offset (bitsLeft)
+	 */
+	local_adr = bitstream_adr + (bit_offset >> 5);
+	bitsLeft = bit_offset & 0x1f;
 
-	if (max_cw_len > 32)
-		return -1U;
+	localEndPos = bitsLeft + n_bits;
 
-	if (max_cw_len == 0)
-		return read_pos;
+	if (localEndPos <= 32) {
+		unsigned int shiftRight = 32 - n_bits;
 
-	decoder = select_decoder(info->golomb_par_used);
-	if (!decoder)
-		return -1U;
+		bitsRight = shiftRight - bitsLeft;
 
-	if (read_pos + max_cw_len > info->cmp_size)   /* check buffer overflow */
-		n_read_bits = info->cmp_size - read_pos;
-	else
-		n_read_bits = max_cw_len;
+		*(p_value) = cpu_to_be32(*(local_adr)) >> bitsRight;
 
-	read_bits = get_n_bits32(&read_val, read_pos, n_read_bits,
-				 compressed_data, info->cmp_size);
-	if (!read_bits)
-		return -1U;
+		mask = (0xffffffff >> shiftRight);
 
-	read_val = read_val << (32 - n_read_bits);
+		*(p_value) &= mask;
+	} else {
+		unsigned int n1 = 32 - bitsLeft;
+		unsigned int n2 = n_bits - n1;
+		/* part 1 ; */
+		mask = 0xffffffff >> bitsLeft;
+		*(p_value) = cpu_to_be32(*(local_adr)) & mask;
+		*(p_value) <<= n2;
+		/*part 2: */
+		/* adjust address*/
+		local_adr += 1;
 
-	log2_g = ilog_2(info->golomb_par_used);
-	n_bits = decoder(read_val, info->golomb_par_used, log2_g, decoded_val);
+		bitsRight = 32 - n2;
+		*(p_value) |= cpu_to_be32(*(local_adr)) >> bitsRight;
+	}
 
-	return read_pos + n_bits;
+	return stream_len;
 }
 
 
-static unsigned int decode_zero(const void *compressed_data,
-				const struct cmp_info *info,
-				unsigned int read_pos, unsigned int max_cw_len,
-				uint32_t *const decoded_val)
+static int decode_normal(uint32_t *decoded_value, int stream_pos, const struct decoder_setup *setup)
 {
-	if (!info)
-		return -1U;
-
-	if (info->samples_used == 0)
-		return read_pos;
-
-	if (!compressed_data)
-		return -1U;
-
-	if (!decoded_val)
-		return -1U;
-
-	if (read_pos > info->cmp_size)
-		return -1U;
-
-	if (max_cw_len > 32)
-		return -1U;
+	uint32_t read_val = ~0U;
+	int n_read_bits, cw_len, n_bits;
 
-	if (max_cw_len == 0)
-		return read_pos;
+	if (stream_pos + setup->max_cw_len > setup->max_stream_len)   /* check buffer overflow */
+		n_read_bits = setup->max_stream_len - stream_pos;
+	else
+		n_read_bits = setup->max_cw_len;
+	if (n_read_bits >= 32 || n_read_bits == 0)
+		return -1;
 
-	read_pos = decode_normal(compressed_data, info, read_pos, max_cw_len,
-				 decoded_val);
-	if (read_pos == -1U)
-		return -1U;
-	if (*decoded_val >= info->spill_used) /* consistency check */
-		return -1U;
+	n_bits = get_n_bits32(&read_val, n_read_bits, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+	if (n_bits <= 0)
+		return -1;
 
-	if (*decoded_val == 0) {/* escape symbol mechanism was used; read unencoded value */
-		unsigned int n_bits;
-		uint32_t unencoded_val;
+	read_val = read_val << (32 - n_read_bits);
 
-		n_bits = get_n_bits32(&unencoded_val, read_pos, max_cw_len,
-				      compressed_data, info->cmp_size);
-		if (!n_bits)
-			return -1U;
-		if (unencoded_val < info->spill_used && unencoded_val != 0) /* consistency check */
-			return -1U;
+	cw_len = setup->decode_cw_f(read_val, setup->encoder_par1, setup->encoder_par2, decoded_value);
+	if (cw_len < 0)
+		return -1;
 
-		*decoded_val = unencoded_val;
-		read_pos += n_bits;
-	}
-	return read_pos;
+	return stream_pos + cw_len;
 }
 
 
-static unsigned int decode_multi(const void *compressed_data,
-				 const struct cmp_info *info,
-				 unsigned int read_pos, unsigned int max_cw_len,
-				 uint32_t *const decoded_val)
+static int decode_multi(uint32_t *decoded_value, int stream_pos,
+			    const struct decoder_setup *setup)
 {
-	if (!info)
-		return -1U;
-
-	if (info->samples_used == 0)
-		return read_pos;
+	stream_pos = decode_normal(decoded_value, stream_pos, setup);
+	if (stream_pos < 0)
+		return stream_pos;
 
-	if (!compressed_data)
-		return -1U;
-
-	if (!decoded_val)
-		return -1U;
-
-	if (read_pos > info->cmp_size)
-		return -1U;
-
-	if (max_cw_len > 32)
-		return -1U;
-
-	if (max_cw_len == 0)
-		return read_pos;
-
-	read_pos = decode_normal(compressed_data, info, read_pos, max_cw_len,
-				 decoded_val);
-	if (read_pos == -1U)
-		return -1U;
-
-	if (*decoded_val >= info->spill_used) {
+	if (*decoded_value >= setup->outlier_par) {
 		/* escape symbol mechanism was used; read unencoded value */
-		unsigned int n_bits;
-		uint32_t unencoded_val;
+		int n_bits;
+		uint32_t unencoded_val = 0;
 		unsigned int unencoded_len;
 
-		unencoded_len = (*decoded_val - info->spill_used + 1) * 2;
-		if (unencoded_len > max_cw_len) /* consistency check */
-			return -1U;
+		unencoded_len = (*decoded_value - setup->outlier_par + 1) * 2;
 
-		/* check buffer overflow */
-		if ((read_pos + unencoded_len) > info->cmp_size) {
-			/*TODO: debug message */
-			return -1U;
-		}
-		n_bits = get_n_bits32(&unencoded_val, read_pos, unencoded_len,
-				      compressed_data, info->cmp_size);
-		if (!n_bits)
-			return -1U;
+		n_bits = get_n_bits32(&unencoded_val, unencoded_len, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+		if (n_bits <= 0)
+			return -1;
 
-		*decoded_val = unencoded_val + info->spill_used;
-		read_pos += n_bits;
+		*decoded_value = unencoded_val + setup->outlier_par;
+		stream_pos += unencoded_len;
 	}
-	return read_pos;
-}
-
-
-static unsigned int decode_value(const void *compressed_data,
-				 const struct cmp_info *info,
-				 unsigned int read_pos,
-				 unsigned int max_cw_len, uint32_t *decoded_val)
-{
-	if (multi_escape_mech_is_used(info->cmp_mode_used))
-		return decode_multi(compressed_data, info, read_pos, max_cw_len,
-				    decoded_val);
-
-	if (zero_escape_mech_is_used(info->cmp_mode_used))
-		return decode_zero(compressed_data, info, read_pos, max_cw_len,
-				   decoded_val);
-	return -1U;
+	return stream_pos;
 }
 
 
-static int decode_16(const void *compressed_data, const struct cmp_info *info,
-		     uint16_t *decoded_data)
+static int decode_zero(uint32_t *decoded_value, int stream_pos,
+			   const struct decoder_setup *setup)
 {
-	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
-		return -1;
+	stream_pos = decode_normal(decoded_value, stream_pos, setup);
 
-	if (info->samples_used == 0)
-		return 0;
+	if (stream_pos <= 0)
+		return stream_pos;
 
-	if (!decoded_data)
+	if (*decoded_value > setup->outlier_par) /* consistency check */
 		return -1;
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
+	if (*decoded_value == 0) {/* escape symbol mechanism was used; read unencoded value */
+		int n_bits;
+		uint32_t unencoded_val = 0;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 16,
-					&decoded_val);
-		if (read_pos == -1U) {
-			debug_print("Error: Compressed values could not be decoded.\n");
+		n_bits = get_n_bits32(&unencoded_val, setup->max_data_bits, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+		if (n_bits <= 0)
 			return -1;
-		}
-
-		if (decoded_val > UINT16_MAX)
+		if (unencoded_val < setup->outlier_par && unencoded_val != 0) /* consistency check */
 			return -1;
 
-		decoded_data[i] = (uint16_t)decoded_val;
+		*decoded_value = unencoded_val;
+		stream_pos += setup->max_data_bits;
 	}
-
-	if (read_pos != info->cmp_size &&
-	    cmp_bit_to_4byte(read_pos) != cmp_bit_to_4byte(info->cmp_size)) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
-	return 0;
+	(*decoded_value)--;
+	if (*decoded_value == 0xFFFFFFFF) /* catch underflow */
+		(*decoded_value) = (*decoded_value) >> (32-setup->max_data_bits);
+	return stream_pos;
 }
 
 
-static int decode_S_FX(const void *compressed_data, const struct cmp_info *info,
-		       struct S_FX *decoded_data)
-{
-	size_t i;
-	unsigned int read_pos = 0;
-	struct cmp_info info_exp_flag;
+/**
+ * @brief remap a unsigned value back to a signed value
+ * @note this is the reverse function of map_to_pos()
+ *
+ * @param value_to_unmap	unsigned value to remap
+ *
+ * @returns the signed remapped value
+ */
 
-	info_exp_flag.golomb_par_used = GOLOMB_PAR_EXPOSURE_FLAGS;
+static uint32_t re_map_to_pos(uint32_t value_to_unmap)
+{
+	if (value_to_unmap & 0x1) { /* if uneven */
+		if (value_to_unmap == 0xFFFFFFFF) /* catch overflow */
+			return 0x80000000;
+		return -((value_to_unmap + 1) / 2);
+	} else
+		return value_to_unmap / 2;
+}
 
-	if (!info)
-		return -1;
 
-	if (info->samples_used == 0)
-		return 0;
+static int decode_value(uint32_t *decoded_value, uint32_t model,
+			int stream_pos, const struct decoder_setup *setup)
+{
+	uint32_t mask = (~0U >> (32 - setup->max_data_bits)); /* mask the used bits */
 
-	if (!decoded_data)
-		return -1;
+	stream_pos = setup->encode_method_f(decoded_value, stream_pos, setup);
+	if (stream_pos <= 0)
+		return stream_pos;
 
-	info_exp_flag = *info;
+	*decoded_value = re_map_to_pos(*decoded_value); //, setup->max_used_bits);
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
+	*decoded_value += round_fwd(model, setup->lossy_par);
 
-		/* read_pos = decode_value(compressed_data, &info_exp_flag, read_pos, 8, */
-		/* 			&decoded_val); */
-		read_pos = decode_normal(compressed_data, &info_exp_flag, read_pos, 8,
-					 &decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
+	*decoded_value &= mask;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].FX = decoded_val;
-	}
+	*decoded_value = round_inv(*decoded_value, setup->lossy_par);
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.");
-		return 1;
-	}
-	return 0;
+	return stream_pos;
 }
 
 
-static int decode_S_FX_EFX(const void *compressed_data, const struct cmp_info
-			   *info, struct S_FX_EFX *decoded_data)
+static int configure_decoder_setup(struct decoder_setup *setup,
+				   uint32_t cmp_par, uint32_t spill,
+				   uint32_t lossy_par, uint32_t max_data_bits,
+				   const struct cmp_cfg *cfg)
 {
-	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
+	if (multi_escape_mech_is_used(cfg->cmp_mode))
+		setup->encode_method_f = &decode_multi;
+	else if (zero_escape_mech_is_used(cfg->cmp_mode))
+		setup->encode_method_f = &decode_zero;
+	else {
+		debug_print("Error: Compression mode not supported.\n");
 		return -1;
+	}
 
-	if (info->samples_used == 0)
-		return 0;
-
-	if (!decoded_data)
+	setup->bitstream_adr = cfg->icu_output_buf; /* start address of the compressed data bitstream */
+	if (cfg->buffer_length & 0x3) {
+		debug_print("Error: The length of the compressed data is not a multiple of 4 bytes.");
 		return -1;
-
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 8,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].FX = decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].EFX = decoded_val;
 	}
+	setup->max_stream_len = (cfg->buffer_length) * CHAR_BIT;  /* maximum length of the bitstream/icu_output_buf in bits */
+	if (rdcu_supported_data_type_is_used(cfg->data_type))
+		setup->max_cw_len = 16;
+	else
+		setup->max_cw_len = 32;
+	setup->encoder_par1 = cmp_par; /* encoding parameter 1 */
+	setup->encoder_par2 = ilog_2(cmp_par); /* encoding parameter 2 */
+	setup->outlier_par = spill; /* outlier parameter */
+	setup->lossy_par = lossy_par; /* lossy compression parameter */
+	setup->model_value = cfg->model_value; /* model value parameter */
+	setup->max_data_bits = max_data_bits; /* how many bits are needed to represent the highest possible value */
+	setup->decode_cw_f = select_decoder(cmp_par);
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
 	return 0;
 }
 
 
-static int decode_S_FX_NCOB(const void *compressed_data, const struct cmp_info
-			    *info, struct S_FX_NCOB *decoded_data)
+static int decompress_imagette(struct cmp_cfg *cfg)
 {
 	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
+	int stream_pos = 0;
+	struct decoder_setup setup;
+	uint16_t *decompressed_data = cfg->input_buf;
+	uint16_t *model_buf = cfg->model_buf;
+	uint16_t *up_model_buf = cfg->icu_new_model_buf;
+	uint32_t decoded_value = 0;
+	uint16_t model;
+	int err;
 
-	if (!decoded_data)
+	err = configure_decoder_setup(&setup, cfg->golomb_par, cfg->spill,
+				      cfg->round, 16, cfg);
+	if (err)
 		return -1;
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 8,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].FX = decoded_val;
+	for (i = 0; i < cfg->samples; i++) {
+		if (model_mode_is_used(cfg->cmp_mode))
+			model = model_buf[i];
+		else
+			model = decoded_value;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].NCOB_X = decoded_val;
+		stream_pos = decode_value(&decoded_value, model, stream_pos, &setup);
+		if (stream_pos <= 0)
+			return stream_pos;
+		decompressed_data[i] = decoded_value;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].NCOB_Y = decoded_val;
+		if (up_model_buf) {
+			up_model_buf[i] = cmp_up_model(decoded_value, model,
+						       cfg->model_value, setup.lossy_par);
+		}
 	}
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
-	return 0;
+	return stream_pos;
 }
 
-
-static int decode_S_FX_EFX_NCOB_ECOB(const void *compressed_data,
-				     const struct cmp_info *info,
-				     struct S_FX_EFX_NCOB_ECOB *decoded_data)
+static int decompressed_data_internal(struct cmp_cfg *cfg)
 {
-	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
+	int data_size, strem_len_bit = -1;
 
-	if (!decoded_data)
+	if (!cfg)
+		return 0; /* or -1? */
+	if (!cfg->icu_output_buf)
 		return -1;
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 8,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
+	data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+	if (!cfg->input_buf || !data_size)
+		return data_size;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
+	if (model_mode_is_used(cfg->cmp_mode))
+		if (!cfg->model_buf)
 			return -1;
-		decoded_data[i].FX = decoded_val;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].NCOB_X = decoded_val;
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
+		if ((unsigned int)data_size < cfg->buffer_length/CHAR_BIT)
 			return -1;
-		decoded_data[i].NCOB_Y = decoded_val;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].EFX = decoded_val;
+		if (cfg->input_buf) {
+			memcpy(cfg->input_buf, cfg->icu_output_buf, data_size);
+			if (cmp_input_big_to_cpu_endianness(cfg->input_buf, data_size, cfg->data_type))
+				return -1;
+			strem_len_bit = data_size * CHAR_BIT;
+		}
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].ECOB_X = decoded_val;
+	} else {
+		switch (cfg->data_type) {
+		case DATA_TYPE_IMAGETTE:
+			strem_len_bit = decompress_imagette(cfg);
+			break;
+		default:
+			strem_len_bit = -1;
+			debug_print("Error: Compressed data type not supported.\n");
+			break;
+		}
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].ECOB_Y = decoded_val;
 	}
+	/* TODO: is this usefull? if (strem_len_bit != data_size * CHAR_BIT) { */
+	if (strem_len_bit <= 0)
+		return -1;
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.");
-		return 1;
-	}
-	return 0;
+
+	return data_size;
 }
 
 
-static int decode_data(const void *compressed_data, const struct cmp_info *info,
-		       void *decompressed_data)
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+			 void *up_model_buf, void *decompressed_data)
 {
-	if (!info)
-		return -1;
+	int err;
+	struct cmp_cfg cfg = {0};
 
-	if (info->samples_used == 0)
-		return 0;
+	cfg.model_buf = model_buf;
+	cfg.icu_new_model_buf = up_model_buf;
+	cfg.input_buf = decompressed_data;
 
-	if (!compressed_data)
+	if (!ent)
 		return -1;
 
-	if (!decompressed_data)
+	err = cmp_ent_read_header(ent, &cfg);
+	if (err)
 		return -1;
 
-	switch (info->cmp_mode_used) {
-	case MODE_RAW:
-		return decode_raw_16(compressed_data, info, decompressed_data);
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
-		return decode_16(compressed_data, info,
-				 (uint16_t *)decompressed_data);
-		break;
-	case MODE_RAW_S_FX:
-		return decode_raw_S_FX(compressed_data, info, decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return decode_S_FX(compressed_data, info,
-				   (struct S_FX *)decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return decode_S_FX_EFX(compressed_data, info,
-				       (struct S_FX_EFX *)decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return decode_S_FX_NCOB(compressed_data, info,
-					(struct S_FX_NCOB *)decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return decode_S_FX_EFX_NCOB_ECOB(compressed_data, info,
-						 (struct S_FX_EFX_NCOB_ECOB *)
-						 decompressed_data);
-		break;
-#if 0
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		break;
-#endif
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
-
-	}
-	return -1;
+	return decompressed_data_internal(&cfg);
 }
 
-/* model buffer is overwritten with updated model*/
 
-int decompress_data(const void *compressed_data, void *de_model_buf, const
-		    struct cmp_info *info, void *decompressed_data)
+/* model buffer is overwritten with updated model */
+
+int decompress_data(uint32_t *compressed_data, void *de_model_buf,
+		    const struct cmp_info *info, void *decompressed_data)
 {
-	int err;
+	int size_decomp_data;
+	struct cmp_cfg cfg = {0};
 
 	if (!compressed_data)
 		return -1;
@@ -1535,18 +528,22 @@ int decompress_data(const void *compressed_data, void *de_model_buf, const
 	if (!decompressed_data)
 		return -1;
 
+	/* cfg.data_type = info->data_type_used; */
+	cfg.cmp_mode = info->cmp_mode_used;
+	cfg.model_value = info->model_value_used;
+	cfg.round = info->round_used;
+	cfg.spill = info->spill_used;
+	cfg.golomb_par = info->golomb_par_used;
+	cfg.samples = info->samples_used;
+	cfg.icu_output_buf = compressed_data;
+	cfg.buffer_length = cmp_bit_to_4byte(info->cmp_size);
+	cfg.input_buf = decompressed_data;
+	cfg.model_buf = de_model_buf;
+	size_decomp_data = decompressed_data_internal(&cfg);
+	if (size_decomp_data <= 0)
+		return -1;
+	else
+		return 0;
 
-	err = decode_data(compressed_data, info, decompressed_data);
-	if (err)
-		return err;
-
-	err = de_map_to_pos(decompressed_data, info);
-	if (err)
-		return err;
-
-	err = de_pre_process(decompressed_data, de_model_buf, info);
-	if (err)
-		return err;
 
-	return 0;
 }
diff --git a/lib/meson.build b/lib/meson.build
index 21f72ad..f072ce4 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -17,6 +17,6 @@ cmplib_sources = files([
 cmp_lib = static_library('cmp_lib',
   sources : cmplib_sources,
   include_directories : incdir,
-  c_args : ['-DDEBUGLEVEL=1'], 
-  install : 'true' # linking under windows mingw only works if this is set
+  c_args : ['-DDEBUGLEVEL=1'],
+#  install : 'true' # linking under windows mingw only works if this is set
 )
diff --git a/lib/rdcu_pkt_to_file.c b/lib/rdcu_pkt_to_file.c
index 83074d7..0c71c8e 100644
--- a/lib/rdcu_pkt_to_file.c
+++ b/lib/rdcu_pkt_to_file.c
@@ -28,11 +28,11 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#include "../include/rdcu_pkt_to_file.h"
-#include "../include/cmp_rdcu_extended.h"
-#include "../include/rdcu_rmap.h"
-#include "../include/rdcu_ctrl.h"
-#include "../include/rdcu_cmd.h"
+#include "rdcu_pkt_to_file.h"
+#include "cmp_rdcu_extended.h"
+#include "rdcu_rmap.h"
+#include "rdcu_ctrl.h"
+#include "rdcu_cmd.h"
 
 /* Name of directory were the RMAP packages are stored */
 static char tc_folder_dir[MAX_TC_FOLDER_DIR_LEN] = "TC_FILES";
@@ -52,7 +52,6 @@ void set_tc_folder_dir(const char *dir_name)
 	strncpy(tc_folder_dir, dir_name, sizeof(tc_folder_dir));
 	/*  Ensure null-termination. */
 	tc_folder_dir[sizeof(tc_folder_dir) - 1] = '\0';
-	return;
 }
 
 
@@ -292,8 +291,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
 	if (read_all < 0x7)
 		return -1;
 
-	printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %d for the "
-	       "RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
+	printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %d for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
 
 	return 0;
 }
diff --git a/meson.build b/meson.build
index d300c11..6757167 100644
--- a/meson.build
+++ b/meson.build
@@ -5,6 +5,8 @@ project('cmp_tool', 'c',
   default_options : ['warning_level=3', 'c_std=gnu99']
 )
 
+add_project_arguments('-DDEBUGLEVEL=1', language : 'c')
+
 if host_machine.system() == 'windows' and meson.get_compiler('c').get_id() == 'gcc'
   # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)),
   # you need to add -mno-ms-bitfields to make it work as expected.
diff --git a/test/cmp_icu/meson.build b/test/cmp_icu/meson.build
index 80c3e27..405d376 100644
--- a/test/cmp_icu/meson.build
+++ b/test/cmp_icu/meson.build
@@ -1,14 +1,26 @@
-test_cmp_icu_files = files ([
-  'test_cmp_icu.c'
-])
+test_case = files('test_cmp_icu.c')
+test_runner = test_runner_generator.process(test_case)
 
 test_cmp_icu = executable('test_cmp_icu',
-   test_cmp_icu_files,
+   test_case, test_runner,
    include_directories : incdir,
    link_with : cmp_lib,
-   # c_args : ['-DMAIN']
-   dependencies : cunit_dep,
+   dependencies : unity_dep,
    build_by_default : false
 )
 
-test('cmp_icu unit test', test_cmp_icu)
+test('cmp_icu Unit Tests', test_cmp_icu)
+
+
+test_case = files('test_decmp.c')
+test_runner = test_runner_generator.process(test_case)
+
+test_cmp_decomp = executable('test_cmp_decomp',
+   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_decomp)
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index 8bf30d6..35f938a 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -1,128 +1,1388 @@
-/*
- *  Simple example of a CUnit unit test.
- *
- *  This program (crudely) demonstrates a very simple "black box"
- *  test of the standard library functions fprintf() and fread().
- *  It uses suite initialization and cleanup functions to open
- *  and close a common temporary file used by the test functions.
- *  The test functions then write to and read from the temporary
- *  file in the course of testing the library functions.
- *
- *  The 2 test functions are added to a single CUnit suite, and
- *  then run using the CUnit Basic interface.  The output of the
- *  program (on CUnit version 2.0-2) is:
- *
- *           CUnit : A Unit testing framework for C.
- *           http://cunit.sourceforge.net/
- *
- *       Suite: Suite_1
- *         Test: test of fprintf() ... passed
- *         Test: test of fread() ... passed
- *
- *       --Run Summary: Type      Total     Ran  Passed  Failed
- *                      suites        1       1     n/a       0
- *                      tests         2       2       2       0
- *                      asserts       5       5       5       0
+#include <string.h>
+#include <stdlib.h>
+
+#include "unity.h"
+
+#include "cmp_support.h"
+/* this is a hack to test static functions */
+#include "../lib/cmp_icu.c"
+
+
+/**
+ * @test map_to_pos
  */
 
-#include <stdio.h>
-#include <string.h>
-#include "CUnit/Basic.h"
+void test_map_to_pos(void)
+{
+	uint32_t value_to_map;
+	uint32_t max_data_bits;
+	uint32_t mapped_value;
+
+	/* test mapping 32 bits values */
+	max_data_bits = 32;
+
+	value_to_map = 0;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(0, mapped_value);
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 1;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(2, mapped_value);
+
+	value_to_map = 42;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(84, mapped_value);
+
+	value_to_map = INT32_MAX;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value);
+
+	value_to_map = INT32_MIN;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value);
+
+	/* test mapping 16 bits values */
+	max_data_bits = 16;
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	/* test mapping 6 bits values */
+	max_data_bits = 6;
 
-/* Pointer to the file used by the tests. */
-static FILE* temp_file = NULL;
+	value_to_map = 0;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(0, mapped_value);
 
-/* The suite initialization function.
- * Opens the temporary file used by the tests.
- * Returns zero on success, non-zero otherwise.
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = UINT32_MAX;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = -1U & 0x3FU;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 63;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 1;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(2, mapped_value);
+
+	value_to_map = 31;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(62, mapped_value);
+
+	value_to_map = -33U; /* aka 31 */
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(62, mapped_value);
+
+	value_to_map = -32U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(63, mapped_value);
+
+	value_to_map = 32;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(63, mapped_value);
+}
+
+
+/**
+ * @test put_n_bits32
  */
-int init_suite1(void)
+
+#define SDP_PB_N 3
+
+
+static void init_PB32_arrays(uint32_t *z, uint32_t *o)
 {
-	if (NULL == (temp_file = fopen("temp.txt", "w+"))) {
-		return -1;
-	}
-	else {
-		return 0;
+	uint32_t i;
+
+	/* init testarray with all 0 and all 1 */
+	for (i = 0; i < SDP_PB_N; i++) {
+		z[i] = 0;
+		o[i] = 0xffffffff;
 	}
 }
 
-/* The suite cleanup function.
- * Closes the temporary file used by the tests.
- * Returns zero on success, non-zero otherwise.
+
+void test_put_n_bits32(void)
+{
+	uint32_t v, n;
+	int o, rval; /* return value */
+	uint32_t testarray0[SDP_PB_N];
+	uint32_t testarray1[SDP_PB_N];
+	const uint32_t l = sizeof(testarray0) * CHAR_BIT;
+
+	/* hereafter, the value is v,
+	 * the number of bits to write is n,
+	 * the offset of the bit is o,
+	 * the max length the bitstream in bits is l
+	 */
+
+	init_PB32_arrays(testarray0, testarray1);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+
+	/*** n=0 ***/
+
+	/* do not write, left border */
+	v = 0; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+
+	v = 0xffffffff; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+
+	/* do not write, right border */
+	v = 0; n = 0; o = l;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+
+	/* test value = 0xffffffff; N = 0 */
+	v = 0xffffffff; n = 0; o = l;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+
+	/*** n=1 ***/
+
+	/* left border, write 0 */
+	v = 0; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray1[0] == 0x7fffffff);
+
+	/* left border, write 1 */
+	v = 1; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray0[0] == 0x80000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/* left border, write 32 */
+	v = 0xf0f0abcd; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 2 bits */
+	v = 3; n = 2; o = 29;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 31);
+	TEST_ASSERT(testarray0[0] == 0x6);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT_EQUAL_INT(rval, 31);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/*** n=5, unsegmented ***/
+
+	/* left border, write 0 */
+	v = 0; n = 5; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT(testarray1[0] == 0x07ffffff);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* left border, write 11111 */
+	v = 0x1f; n = 5; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray0[0] == 0xf8000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 0 */
+	v = 0; n = 5; o = 7;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray1[0] == 0xfe0fffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 11111 */
+	v = 0x1f; n = 5; o = 7;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray0[0] == 0x01f00000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* right, write 0 */
+	v = 0; n = 5; o = 91;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffe0);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* right, write 11111 */
+	v = 0x1f; n = 5; o = 91;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0x0000001f);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write 0 */
+	v = 0; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0x00000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0x00000000);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write -1 */
+	v = 0xffffffff; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* SEGMENTED cases */
+	/* 5 bit, write 0 */
+	v = 0; n = 5; o = 62;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xfffffffc);
+	TEST_ASSERT(testarray1[2] == 0x1fffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 5 bit, write 1f */
+	v = 0x1f; n = 5; o = 62;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 3);
+	TEST_ASSERT(testarray0[2] == 0xe0000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write 0 */
+	v = 0; n = 32; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray0[0] == 0x00000000);
+	TEST_ASSERT(testarray0[1] == 0x00000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray1[0] == 0x80000000);
+	TEST_ASSERT(testarray1[1] == 0x7fffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write -1 */
+	v = 0xffffffff; n = 32; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray0[0] == 0x7fffffff);
+	TEST_ASSERT(testarray0[1] == 0x80000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* test NULL buffer */
+	v = 0; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 0);
+
+	v = 0; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 1);
+
+	v = 0; n = 5; o = 31;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 36);
+
+	v = 0; n = 2; o = 95;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
+
+	/* value larger than n allows */
+	v = 0x7f; n = 6; o = 10;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray0[0] == 0x003f0000);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	v = 0xffffffff; n = 6; o = 10;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray0[0] == 0x003f0000);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/*** error cases ***/
+	/* n too large */
+	v = 0x0; n = 33; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
+
+	/* try to put too much in the bitstream */
+	v = 0x1; n = 1; o = 96;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+
+	/* this should work (if bitstream=NULL no length check) */
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(97, rval);
+
+	/* offset lager than max_stream_len(l) */
+	v = 0x0; n = 32; o = INT32_MAX;
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT(rval < 0);
+
+	/* negative offset */
+	v = 0x0; n = 0; o = -1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+
+	v = 0x0; n = 0; o = -2;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+}
+
+
+/**
+ * @test rice_encoder
  */
-int clean_suite1(void)
+
+void test_rice_encoder(void)
 {
-	if (0 != fclose(temp_file)) {
-		return -1;
-	}
-	else {
-		temp_file = NULL;
-		return 0;
-	}
+	uint32_t value, g_par, log2_g_par, cw, cw_len;
+
+	/* test minimum Golomb parameter */
+	value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(1, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 31;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
+
+	/* test some arbitrary values */
+	value = 0; log2_g_par = 4; g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 42;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(7, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
+
+	value = 446;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
+
+	value = 447;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
+
+	/* test maximum Golomb parameter for rice_encoder */
+	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 0x7FFFFFFE;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
+
+	value = 0x7FFFFFFF;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
 }
 
-/* Simple test of fprintf().
- * Writes test data to the temporary file and checks
- * whether the expected number of bytes were written.
+
+/**
+ * @test golomb_encoder
  */
-void testFPRINTF(void)
+
+void test_Golomb_encoder(void)
 {
-	int i1 = 10;
+	uint32_t value, g_par, log2_g_par, cw, cw_len;
 
-	if (NULL != temp_file) {
-		CU_ASSERT(0 == fprintf(temp_file, ""));
-		CU_ASSERT(2 == fprintf(temp_file, "Q\n"));
-		CU_ASSERT(7 == fprintf(temp_file, "i1 = %d", i1));
-	}
+	/* test minimum Golomb parameter */
+	value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(1, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 31;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
+
+
+	/* test some arbitrary values with g_par = 16 */
+	value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 42;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(7, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
+
+	value = 446;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
+
+	value = 447;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
+
+
+	/* test some arbitrary values with g_par = 3 */
+	value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(2, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(3, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x2, cw);
+
+	value = 42;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(16, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFC, cw);
+
+	value = 44;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(17, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1FFFB, cw);
+
+	value = 88;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFA, cw);
+
+	value = 89;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw);
+
+
+	/* test maximum Golomb parameter for golomb_encoder */
+	value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 0x7FFFFFFE;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
+
+	value = 0x7FFFFFFF;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
 }
 
-/* Simple test of fread().
- * Reads the data previously written by testFPRINTF()
- * and checks whether the expected characters are present.
- * Must be run after testFPRINTF().
+
+/**
+ * @test encode_value_zero
  */
-void testFREAD(void)
+
+void test_encode_value_zero(void)
 {
-	unsigned char buffer[20];
+	uint32_t data, model;
+	int stream_len;
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[3] = {0};
 
-	if (NULL != temp_file) {
-		rewind(temp_file);
-		CU_ASSERT(9 == fread(buffer, sizeof(unsigned char), 20, temp_file));
-		CU_ASSERT(0 == strncmp(buffer, "Q\ni1 = 10", 9));
-	}
+	/* setup the setup */
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
+	setup.spillover_par = 32;
+	setup.max_data_bits = 32;
+	setup.generate_cw_f = rice_encoder;
+	setup.bitstream_adr = bitstream;
+	setup.max_stream_len = sizeof(bitstream) * CHAR_BIT;
+
+	stream_len = 0;
+
+	data = 0; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(2, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	data = 5; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(14, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	data = 2; model = 7;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(25, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* zero escape mechanism */
+	data = 100; model = 42;
+	/* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(58, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* test overflow */
+	data = INT32_MIN; model = 0;
+	/* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(91, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* small buffer error */
+	data = 23; model = 26;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+
+	/* reset bitstream to all bits set */
+	bitstream[0] = ~0U;
+	bitstream[1] = ~0U;
+	bitstream[2] = ~0U;
+	stream_len = 0;
+
+	/* we use now values with maximum 6 bits */
+	setup.max_data_bits = 6;
+
+	/* lowest value before zero encoding */
+	data = 53; model = 38;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(32, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* lowest value with zero encoding */
+	data = 0; model = 16;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(39, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* maximum positive value to encode */
+	data = 31; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(46, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* maximum negative value to encode */
+	data = 0; model = 32;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(53, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* small buffer error when creating the zero escape symbol*/
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	bitstream[2] = 0;
+	stream_len = 32;
+	setup.max_stream_len = 32;
+	data = 31; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
 }
 
-/* The main() function for setting up and running the tests.
- * Returns a CUE_SUCCESS on successful running, another
- * CUnit error code on failure.
+
+/**
+ * @test encode_value_multi
  */
-int main()
+
+void test_encode_value_multi(void)
 {
-	CU_pSuite pSuite = NULL;
+	uint32_t data, model;
+	int stream_len;
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[4] = {0};
 
-	/* initialize the CUnit test registry */
-	if (CUE_SUCCESS != CU_initialize_registry())
-		return CU_get_error();
+	/* setup the setup */
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
+	setup.spillover_par = 16;
+	setup.max_data_bits = 32;
+	setup.generate_cw_f = golomb_encoder;
+	setup.bitstream_adr = bitstream;
+	setup.max_stream_len = sizeof(bitstream) * CHAR_BIT;
 
-	/* add a suite to the registry */
-	pSuite = CU_add_suite("Suite_1", init_suite1, clean_suite1);
-	if (NULL == pSuite) {
-		CU_cleanup_registry();
-		return CU_get_error();
-	}
+	stream_len = 0;
+
+	data = 0; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(1, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	data = 0; model = 1;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(3, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x40000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	data = 1+23; model = 0+23;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(6, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x58000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* highest value without multi outlier encoding */
+	data = 0+42; model = 8+42;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(22, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFF800, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* lowest value with multi outlier encoding */
+	data = 8+42; model = 0+42;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(41, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFC000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* highest value with multi outlier encoding */
+	data = INT32_MIN; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(105, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0xF7800000, bitstream[3]);
+
+	/* small buffer error */
+	data = 0; model = 38;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+
+	/* small buffer error when creating the multi escape symbol*/
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	setup.max_stream_len = 32;
+
+	stream_len = 32;
+	data = 31; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+}
+
+
+/**
+ * @test encode_value
+ */
+
+void test_encode_value(void)
+{
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[4] = {0};
+	uint32_t data, model;
+	int cmp_size;
+
+	setup.encode_method_f = encode_value_none;
+	setup.bitstream_adr = bitstream;
+	setup.max_stream_len = 128;
+	cmp_size = 0;
+
+	/* test 32 bit input */
+	setup.encoder_par1 = 32;
+	setup.max_data_bits = 32;
+	setup.lossy_par = 0;
+
+	data = 0; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(32, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	data = UINT32_MAX; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(64, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	/* test rounding */
+	setup.lossy_par = 1;
+	data = UINT32_MAX; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(96, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	setup.lossy_par = 2;
+	data = 0x3; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(128, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* small buffer error bitstream can not hold more data*/
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+
+	/* reset bitstream */
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	bitstream[2] = 0;
+	bitstream[3] = 0;
+	cmp_size = 0;
+
+	/* test 31 bit input */
+	setup.encoder_par1 = 31;
+	setup.max_data_bits = 31;
+	setup.lossy_par = 0;
+
+	data = 0; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(31, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	data = 0x7FFFFFFF; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(62, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0x00000001, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFC, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	/* round = 1 */
+	setup.lossy_par = 1;
+	data = UINT32_MAX; model = UINT32_MAX;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(93, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0x00000001, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFF8, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	/* data are bigger than max_data_bits */
+	setup.lossy_par = 0;
+	data = UINT32_MAX; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_size);
+
+	/* model are bigger than max_data_bits */
+	setup.lossy_par = 0;
+	cmp_size = 93;
+	data = 0; model = UINT32_MAX;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_size);
+}
+
+
+/**
+ * @test cmp_get_max_used_bits
+ */
+
+void test_cmp_get_max_used_bits(void)
+{
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_imagette, MAX_USED_NC_IMAGETTE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.saturated_imagette, MAX_USED_SATURATED_IMAGETTE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_imagette, MAX_USED_FC_IMAGETTE_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_fx, MAX_USED_F_FX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_efx, MAX_USED_F_EFX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_ncob, MAX_USED_F_NCOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_ecob, MAX_USED_F_ECOB_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_exp_flags, MAX_USED_S_FX_EXPOSURE_FLAGS_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_fx, MAX_USED_S_FX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_efx, MAX_USED_S_EFX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_ncob, MAX_USED_S_NCOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_ecob, MAX_USED_S_ECOB_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_fx_variance, MAX_USED_L_FX_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_efx, MAX_USED_L_EFX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_ncob, MAX_USED_L_NCOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_ecob, MAX_USED_L_ECOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_cob_variance, MAX_USED_L_COB_VARIANCE_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_offset_mean, MAX_USED_NC_OFFSET_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_offset_variance, MAX_USED_NC_OFFSET_VARIANCE_BITS);
 
-	/* add the tests to the suite */
-	/* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */
-	if ((NULL == CU_add_test(pSuite, "test of fprintf()", testFPRINTF)) ||
-	    (NULL == CU_add_test(pSuite, "test of fread()", testFREAD)))
-	{
-		CU_cleanup_registry();
-		return CU_get_error();
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_mean, MAX_USED_NC_BACKGROUND_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_variance, MAX_USED_NC_BACKGROUND_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_outlier_pixels, MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smeating_mean, MAX_USED_SMEARING_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smeating_variance_mean, MAX_USED_SMEARING_VARIANCE_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smearing_outlier_pixels, MAX_USED_SMEARING_OUTLIER_PIXELS_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_mean, MAX_USED_FC_OFFSET_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_variance, MAX_USED_FC_OFFSET_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_pixel_in_error, MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_background_mean, MAX_USED_FC_BACKGROUND_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_background_variance, MAX_USED_FC_BACKGROUND_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_background_outlier_pixels, MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS);
+}
+
+
+void test_compress_imagette_diff(void)
+{
+	uint16_t data[] = {0xFFFF, 1, 0, 42, 0x8000, 0x7FFF, 0xFFFF};
+	uint32_t output_buf[3] = {0xFFFF, 0xFFFF, 0xFFFF};
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.golomb_par = 1;
+	cfg.spill = 8;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 7;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(66, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0xDF6002AB, be32_to_cpu(output_buf[0]));
+	TEST_ASSERT_EQUAL_HEX(0xFEB70000, be32_to_cpu(output_buf[1]));
+	TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(output_buf[2]));
+}
+
+void test_compress_imagette_model(void)
+{
+	uint16_t data[]  = {0x0000, 0x0001, 0x0042, 0x8000, 0x7FFF, 0xFFFF, 0xFFFF};
+	uint16_t model[] = {0x0000, 0xFFFF, 0xF301, 0x8FFF, 0x0000, 0xFFFF, 0x0000};
+	uint16_t model_up[7] = {0};
+	uint32_t output_buf[3] = {0xFFFF, 0xFFFF, 0xFFFF};
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.icu_new_model_buf = model_up;
+	cfg.samples = 7;
+	cfg.golomb_par = 3;
+	cfg.spill = 8;
+	cfg.model_value = 8;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 8;
+
+	cmp_size = icu_compress_data(&cfg);
+
+	TEST_ASSERT_EQUAL_INT(76, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0x2BDB4F5E, be32_to_cpu(output_buf[0]));
+	TEST_ASSERT_EQUAL_HEX(0xDFF5F9FF, be32_to_cpu(output_buf[1]));
+	TEST_ASSERT_EQUAL_HEX(0xEC200000, be32_to_cpu(output_buf[2]));
+
+	TEST_ASSERT_EQUAL_HEX(0x0000, model_up[0]);
+	TEST_ASSERT_EQUAL_HEX(0x8000, model_up[1]);
+	TEST_ASSERT_EQUAL_HEX(0x79A1, model_up[2]);
+	TEST_ASSERT_EQUAL_HEX(0x87FF, model_up[3]);
+	TEST_ASSERT_EQUAL_HEX(0x3FFF, model_up[4]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFF, model_up[5]);
+	TEST_ASSERT_EQUAL_HEX(0x7FFF, model_up[6]);
+}
+
+
+void test_compress_imagette_stuff(void)
+{
+	uint16_t data[] = {0x0, 0x1, 0x23, 0x42, 0x8000, 0x7FFF, 0xFFFF};
+	uint32_t output_buf[4] = {0};
+	struct cmp_cfg cfg = {0};
+
+	int cmp_size;
+	uint8_t output_buf_exp[] = {
+		0x00, 0x00, 0x00, 0x01,
+		0x00, 0x23, 0x00, 0x42,
+		0x80, 0x00, 0x7F, 0xFF,
+		0xFF, 0xFF, 0x00, 0x00};
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_STUFF;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 8;
+	cfg.golomb_par = 16; /* how many used bits has the maximum data value */
+
+	cmp_size = icu_compress_data(&cfg);
+
+	uint32_t *output_buf_exp_32 = (uint32_t *)output_buf_exp;
+	TEST_ASSERT_EQUAL_INT(7*16, cmp_size);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[0], output_buf[0]);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[1], output_buf[1]);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[2], output_buf[2]);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[3], output_buf[3]);
+}
+
+
+void test_compress_imagette_raw(void)
+{
+	uint16_t data[] = {0x0, 0x1, 0x23, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX};
+	uint16_t output_buf[7] = {0};
+	struct cmp_cfg cfg = {0};
+
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.model_buf = NULL;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 7;
+
+
+	cmp_size = icu_compress_data(&cfg);
+
+	TEST_ASSERT_EQUAL_INT(7*16, cmp_size);
+	TEST_ASSERT_EQUAL_HEX16(0x0, be16_to_cpu(output_buf[0]));
+	TEST_ASSERT_EQUAL_HEX16(0x1, be16_to_cpu(output_buf[1]));
+	TEST_ASSERT_EQUAL_HEX16(0x23, be16_to_cpu(output_buf[2]));
+	TEST_ASSERT_EQUAL_HEX16(0x42, be16_to_cpu(output_buf[3]));
+	TEST_ASSERT_EQUAL_HEX16(INT16_MIN, be16_to_cpu(output_buf[4]));
+	TEST_ASSERT_EQUAL_HEX16(INT16_MAX, be16_to_cpu(output_buf[5]));
+	TEST_ASSERT_EQUAL_HEX16(UINT16_MAX, be16_to_cpu(output_buf[6]));
+}
+
+
+void test_compress_s_fx_raw(void)
+{
+	struct s_fx data[7];
+	struct cmp_cfg cfg = {0};
+	int cmp_size, cmp_size_exp;
+	size_t i;
+
+	cfg.data_type = DATA_TYPE_S_FX;
+	cfg.model_buf = NULL;
+	cfg.samples = 7;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	cfg.buffer_length = 7;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[4].exp_flags = 0x0;
+	data[4].fx = INT32_MIN;
+	data[5].exp_flags = 0x3;
+	data[5].fx = INT32_MAX;
+	data[6].exp_flags = 0x1;
+	data[6].fx = UINT32_MAX;
+
+	struct multi_entry_hdr *hdr = cfg.input_buf;
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	memcpy(hdr->entry, data, sizeof(data));
+
+	cmp_size = icu_compress_data(&cfg);
+
+	cmp_size_exp = (sizeof(data) + sizeof(struct multi_entry_hdr)) * CHAR_BIT;
+	TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size);
+
+	for (i = 0; i < ARRAY_SIZE(data); i++) {
+		hdr = (struct multi_entry_hdr *)cfg.icu_output_buf;
+		struct s_fx *p = (struct s_fx *)hdr->entry;
+
+		TEST_ASSERT_EQUAL_HEX(data[i].exp_flags, p[i].exp_flags);
+		TEST_ASSERT_EQUAL_HEX(data[i].fx, cpu_to_be32(p[i].fx));
 	}
+}
+
+
+void test_compress_s_fx_staff(void)
+{
+	struct s_fx data[5];
+	struct cmp_cfg cfg = {0};
+	int cmp_size, cmp_size_exp;
+	struct multi_entry_hdr *hdr;
+	uint32_t *cmp_data;
+
+	/* setup configuration */
+	cfg.data_type = DATA_TYPE_S_FX;
+	cfg.cmp_mode = CMP_MODE_STUFF;
+	cfg.samples = 5;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+	cfg.buffer_length = 5;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	cfg.cmp_par_exp_flags = 2;
+	cfg.cmp_par_fx = 21;
+
+	/* generate input data */
+	hdr = cfg.input_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[4].exp_flags = 0x0;
+	data[4].fx = 0x001FFFFF;
+	memcpy(hdr->entry, data, sizeof(data));
+
+	cmp_size = icu_compress_data(&cfg);
 
-	/* Run all tests using the CUnit Basic interface */
-	CU_basic_set_mode(CU_BRM_VERBOSE);
-	CU_basic_run_tests();
-	CU_cleanup_registry();
-	return CU_get_error();
+	cmp_size_exp = 5 * (2 + 21) + MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
+	TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size);
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	hdr = (void *)cfg.icu_output_buf;
+	cmp_data = (uint32_t *)hdr->entry;
+	TEST_ASSERT_EQUAL_HEX(0x00000080, be32_to_cpu(cmp_data[0]));
+	TEST_ASSERT_EQUAL_HEX(0x00060001, be32_to_cpu(cmp_data[1]));
+	TEST_ASSERT_EQUAL_HEX(0x1E000423, be32_to_cpu(cmp_data[2]));
+	TEST_ASSERT_EQUAL_HEX(0xFFFFE000, be32_to_cpu(cmp_data[3]));
+
+	free(cfg.input_buf);
+	free(cfg.icu_output_buf);
+}
+
+
+void test_compress_s_fx_model_multi(void)
+{
+	struct s_fx data[6], model[6];
+	struct s_fx *up_model_buf;
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+	struct multi_entry_hdr *hdr;
+	uint32_t *cmp_data;
+	struct cmp_max_used_bits max_used_bits;
+
+	/* setup configuration */
+	cfg.data_type = DATA_TYPE_S_FX;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.model_value = 11;
+	cfg.samples = 6;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+	cfg.model_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.model_buf);
+	cfg.icu_new_model_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_new_model_buf);
+	cfg.buffer_length = 6;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	cfg.cmp_par_exp_flags = 1;
+	cfg.spill_exp_flags = 8;
+	cfg.cmp_par_fx = 3;
+	cfg.spill_fx = 35;
+
+
+	/* generate input data */
+	hdr = cfg.input_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[4].exp_flags = 0x0;
+	data[4].fx = 0x001FFFFF;
+	data[5].exp_flags = 0x0;
+	data[5].fx = 0x0;
+	memcpy(hdr->entry, data, sizeof(data));
+
+	/* generate model data */
+	hdr = cfg.model_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x41, sizeof(struct multi_entry_hdr));
+	model[0].exp_flags = 0x0;
+	model[0].fx = 0x0;
+	model[1].exp_flags = 0x3;
+	model[1].fx = 0x1;
+	model[2].exp_flags = 0x0;
+	model[2].fx = 0x42;
+	model[3].exp_flags = 0x0;
+	model[3].fx = 0x23;
+	model[4].exp_flags = 0x3;
+	model[4].fx = 0x0;
+	model[5].exp_flags = 0x2;
+	model[5].fx = 0x001FFFFF;
+	memcpy(hdr->entry, model, sizeof(model));
+
+	max_used_bits = cmp_get_max_used_bits();
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cmp_size = icu_compress_data(&cfg);
+
+	TEST_ASSERT_EQUAL_INT(166, cmp_size);
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	cmp_data = &cfg.icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
+	TEST_ASSERT_EQUAL_HEX(0x1C77FFA6, be32_to_cpu(cmp_data[0]));
+	TEST_ASSERT_EQUAL_HEX(0xAFFF4DE5, be32_to_cpu(cmp_data[1]));
+	TEST_ASSERT_EQUAL_HEX(0xCC000000, be32_to_cpu(cmp_data[2]));
+
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	hdr = cfg.icu_new_model_buf;
+	up_model_buf = (struct s_fx *)hdr->entry;
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].fx);
+	TEST_ASSERT_EQUAL_HEX(0x2, up_model_buf[1].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x1, up_model_buf[1].fx);
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[2].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x38, up_model_buf[2].fx);
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[3].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x2C, up_model_buf[3].fx);
+	TEST_ASSERT_EQUAL_HEX(0x2, up_model_buf[4].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x9FFFF, up_model_buf[4].fx);
+	TEST_ASSERT_EQUAL_HEX(0x1, up_model_buf[5].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x15FFFF, up_model_buf[5].fx);
+
+	free(cfg.input_buf);
+	free(cfg.model_buf);
+	free(cfg.icu_new_model_buf);
+	free(cfg.icu_output_buf);
 }
+
+
diff --git a/test/cmp_icu/test_cmp_icu_new.c b/test/cmp_icu/test_cmp_icu_new.c
deleted file mode 100644
index a0d9109..0000000
--- a/test/cmp_icu/test_cmp_icu_new.c
+++ /dev/null
@@ -1,894 +0,0 @@
-#include <string.h>
-
-#include "unity.h"
-
-#include "cmp_support.h"
-/* this is a hack to test static functions */
-#include "../lib/cmp_icu_new.c"
-
-
-/**
- * @test map_to_pos
- */
-
-void test_map_to_pos(void)
-{
-	uint32_t value_to_map;
-	uint32_t max_value_bits;
-	uint32_t mapped_value;
-
-	/* test mapping 32 bits values */
-	max_value_bits = 32;
-
-	value_to_map = 0;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(0, mapped_value);
-
-	value_to_map = -1U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = 1;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(2, mapped_value);
-
-	value_to_map = 42;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(84, mapped_value);
-
-	value_to_map = INT32_MAX;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value);
-
-	value_to_map = INT32_MIN;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value);
-
-	/* test mapping 16 bits values */
-	max_value_bits = 16;
-
-	value_to_map = -1U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	/* test mapping 6 bits values */
-	max_value_bits = 6;
-
-	value_to_map = 0;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(0, mapped_value);
-
-	value_to_map = -1U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = UINT32_MAX;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = -1U & 0x3FU;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = 63;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = 1;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(2, mapped_value);
-
-	value_to_map = 31;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(62, mapped_value);
-
-	value_to_map = -33U; /* aka 31 */
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(62, mapped_value);
-
-	value_to_map = -32U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(63, mapped_value);
-
-	value_to_map = 32;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(63, mapped_value);
-}
-
-
-/**
- * @test put_n_bits32
- */
-
-#define SDP_PB_N 3
-
-
-static void init_PB32_arrays(uint32_t *z, uint32_t *o)
-{
-	uint32_t i;
-
-	/* init testarray with all 0 and all 1 */
-	for (i = 0; i < SDP_PB_N; i++) {
-		z[i] = 0;
-		o[i] = 0xffffffff;
-	}
-}
-
-
-void test_put_n_bits32(void)
-{
-	uint32_t v, n;
-	int o, rval; /* return value */
-	uint32_t testarray0[SDP_PB_N];
-	uint32_t testarray1[SDP_PB_N];
-	const uint32_t l = sizeof(testarray0) * CHAR_BIT;
-
-	/* hereafter, the value is v,
-	 * the number of bits to write is n,
-	 * the offset of the bit is o,
-	 * the max length the bitstream in bits is l
-	 */
-
-	init_PB32_arrays(testarray0, testarray1);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-
-	/*** n=0 ***/
-
-	/* do not write, left border */
-	v = 0; n = 0; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-
-	v = 0xffffffff; n = 0; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-
-	/* do not write, right border */
-	v = 0; n = 0; o = l;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-
-	/* test value = 0xffffffff; N = 0 */
-	v = 0xffffffff; n = 0; o = l;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-
-	/*** n=1 ***/
-
-	/* left border, write 0 */
-	v = 0; n = 1; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray1[0] == 0x7fffffff);
-
-	/* left border, write 1 */
-	v = 1; n = 1; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray0[0] == 0x80000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	/* left border, write 32 */
-	v = 0xf0f0abcd; n = 32; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* middle, write 2 bits */
-	v = 3; n = 2; o = 29;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 31);
-	TEST_ASSERT(testarray0[0] == 0x6);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT_EQUAL_INT(rval, 31);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/*** n=5, unsegmented ***/
-
-	/* left border, write 0 */
-	v = 0; n = 5; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT(testarray1[0] == 0x07ffffff);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* left border, write 11111 */
-	v = 0x1f; n = 5; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	TEST_ASSERT(testarray0[0] == 0xf8000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* middle, write 0 */
-	v = 0; n = 5; o = 7;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray1[0] == 0xfe0fffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* middle, write 11111 */
-	v = 0x1f; n = 5; o = 7;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray0[0] == 0x01f00000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* right, write 0 */
-	v = 0; n = 5; o = 91;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffe0);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* right, write 11111 */
-	v = 0x1f; n = 5; o = 91;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0x0000001f);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write 0 */
-	v = 0; n = 32; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray0[0] == 0x00000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray1[0] == 0x00000000);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write -1 */
-	v = 0xffffffff; n = 32; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray0[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* SEGMENTED cases */
-	/* 5 bit, write 0 */
-	v = 0; n = 5; o = 62;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xfffffffc);
-	TEST_ASSERT(testarray1[2] == 0x1fffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 5 bit, write 1f */
-	v = 0x1f; n = 5; o = 62;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 3);
-	TEST_ASSERT(testarray0[2] == 0xe0000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write 0 */
-	v = 0; n = 32; o = 1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray0[0] == 0x00000000);
-	TEST_ASSERT(testarray0[1] == 0x00000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray1[0] == 0x80000000);
-	TEST_ASSERT(testarray1[1] == 0x7fffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write -1 */
-	v = 0xffffffff; n = 32; o = 1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray0[0] == 0x7fffffff);
-	TEST_ASSERT(testarray0[1] == 0x80000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* test NULL buffer */
-	v = 0; n = 0; o = 0;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 0);
-
-	v = 0; n = 1; o = 0;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 1);
-
-	v = 0; n = 5; o = 31;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 36);
-
-	v = 0; n = 2; o = 95;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
-
-	/* value larger than n allows */
-	v = 0x7f; n = 6; o = 10;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray0[0] == 0x003f0000);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	v = 0xffffffff; n = 6; o = 10;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray0[0] == 0x003f0000);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/*** error cases ***/
-	/* n too large */
-	v = 0x0; n = 33; o = 1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, -1);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, -1);
-
-	/* try to put too much in the bitstream */
-	v = 0x1; n = 1; o = 96;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0);
-
-	/* this should work (if bitstream=NULL no length check) */
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(97, rval);
-
-	/* offset lager than max_bit_len(l) */
-	v = 0x0; n = 32; o = INT32_MAX;
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT(rval < 0);
-
-	/* negative offset */
-	v = 0x0; n = 0; o = -1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-
-	v = 0x0; n = 0; o = -2;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-}
-
-
-/**
- * @test Rice_encoder
- */
-
-void test_Rice_encoder(void)
-{
-	uint32_t value, g_par, log2_g_par, cw, cw_len;
-
-	/* test minimum Golomb parameter */
-	value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(1, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 31;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
-
-	/* test some arbitrary values */
-	value = 0; log2_g_par = 4; g_par = 1U << log2_g_par; cw = ~0U;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 42;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(7, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
-
-	value = 446;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
-
-	value = 447;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
-
-	/* test maximum Golomb parameter for Rice_encoder */
-	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 0x7FFFFFFE;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
-
-	value = 0x7FFFFFFF;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
-}
-
-
-/**
- * @test Golomb_encoder
- */
-
-void test_Golomb_encoder(void)
-{
-	uint32_t value, g_par, log2_g_par, cw, cw_len;
-
-	/* test minimum Golomb parameter */
-	value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(1, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 31;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
-
-
-	/* test some arbitrary values with g_par = 16 */
-	value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 42;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(7, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
-
-	value = 446;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
-
-	value = 447;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
-
-
-	/* test some arbitrary values with g_par = 3 */
-	value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(2, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(3, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x2, cw);
-
-	value = 42;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(16, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFC, cw);
-
-	value = 44;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(17, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1FFFB, cw);
-
-	value = 88;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFA, cw);
-
-	value = 89;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw);
-
-
-	/* test maximum Golomb parameter for Golomb_encoder */
-	value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 0x7FFFFFFE;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
-
-	value = 0x7FFFFFFF;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
-}
-
-
-/**
- * @test encode_value_zero
- */
-
-void test_encode_value_zero(void)
-{
-	uint32_t data, model;
-	int stream_len;
-	struct encoder_setupt setup = {0};
-	uint32_t bitstream[3] = {0};
-
-	/* setup the setup */
-	setup.encoder_par1 = 1;
-	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
-	setup.outlier_par = 32;
-	setup.max_value_bits = 32;
-	setup.generate_cw = Rice_encoder;
-	setup.bitstream_adr = bitstream;
-	setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
-
-	stream_len = 0;
-
-	data = 0; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(2, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	data = 5; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(14, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	data = 2; model = 7;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(25, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	/* zero escape mechanism */
-	data = 100; model = 42;
-	/* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(58, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	/* test overflow */
-	data = INT32_MIN; model = 0;
-	/* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(91, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	/* small buffer error */
-	data = 23; model = 26;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-
-	/* reset bitstream to all bits set */
-	bitstream[0] = ~0U;
-	bitstream[1] = ~0U;
-	bitstream[2] = ~0U;
-	stream_len = 0;
-
-	/* we use now values with maximum 6 bits */
-	setup.max_value_bits = 6;
-
-	/* lowest value before zero encoding */
-	data = 53; model = 38;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(32, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* lowest value with zero encoding */
-	data = 0; model = 16;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(39, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* maximum positive value to encode */
-	data = 31; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(46, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* maximum negative value to encode */
-	data = 0; model = 32;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(53, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* small buffer error when creating the zero escape symbol*/
-	bitstream[0] = 0;
-	bitstream[1] = 0;
-	bitstream[2] = 0;
-	stream_len = 32;
-	setup.max_bit_len = 32;
-	data = 31; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
-}
-
-
-/**
- * @test encode_value_multi
- */
-
-void test_encode_value_multi(void)
-{
-	uint32_t data, model;
-	int stream_len;
-	struct encoder_setupt setup = {0};
-	uint32_t bitstream[4] = {0};
-
-	/* setup the setup */
-	setup.encoder_par1 = 1;
-	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
-	setup.outlier_par = 16;
-	setup.max_value_bits = 32;
-	setup.generate_cw = Rice_encoder;
-	setup.bitstream_adr = bitstream;
-	setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
-
-	stream_len = 0;
-
-	data = 0; model = 0;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(1, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	data = 0; model = 1;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(3, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x40000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	data = 1+23; model = 0+23;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(6, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x58000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	/* highest value without multi outlier encoding */
-	data = 0+42; model = 8+42;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(22, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x5BFFF800, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	/* lowest value with multi outlier encoding */
-	data = 8+42; model = 0+42;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(41, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0xFC000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	/* highest value with multi outlier encoding */
-	data = INT32_MIN; model = 0;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(105, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0xF7800000, bitstream[3]);
-
-	/* small buffer error */
-	data = 0; model = 38;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-
-	/* small buffer error when creating the multi escape symbol*/
-	bitstream[0] = 0;
-	bitstream[1] = 0;
-	setup.max_bit_len = 32;
-
-	stream_len = 32;
-	data = 31; model = 0;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
-}
diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c
new file mode 100644
index 0000000..523b64f
--- /dev/null
+++ b/test/cmp_icu/test_decmp.c
@@ -0,0 +1,442 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "unity.h"
+
+#include "compiler.h"
+#include "cmp_debug.h"
+#include "cmp_entity.h"
+#include "../../lib/cmp_icu.c" /* .c file included to test static functions */
+#include "../../lib/decmp.c" /* .c file included to test static functions */
+
+
+/* returns the needed size of the compression entry header plus the max size of the
+ * compressed data if ent ==  NULL if ent is set the size of the compression
+ * entry */
+size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cfg)
+{
+	size_t s, hdr_size;
+	struct cmp_cfg cfg_cpy;
+	int cmp_size_bits;
+
+	if (!cfg)
+		return 0;
+
+	if (cfg->icu_output_buf)
+		debug_print("Warning the set buffer for the compressed data is ignored! The compressed data are write to the compression entry.");
+
+	if (!ent) {
+		s = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type);
+		if (!s)
+			return 0;
+
+		hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW);
+		if (!hdr_size)
+			return 0;
+
+		return s + hdr_size;
+	}
+
+	cfg_cpy = *cfg;
+	cfg_cpy.icu_output_buf = cmp_ent_get_data_buf(ent);
+
+	cmp_size_bits = icu_compress_data(&cfg_cpy);
+	if (cmp_size_bits < 0)
+		return 0;
+
+	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW,
+					 cmp_bit_to_4byte(cmp_size_bits));
+	if (!s)
+		return 0;
+
+	if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits))
+		return 0;
+
+	return s;
+}
+
+
+void test_cmp_decmp_n_imagette_raw(void)
+{
+	int cmp_size;
+	size_t s, i;
+	struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 0, CMP_LOSSLESS);
+	uint16_t data[] = {0, 1, 2, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX};
+	uint32_t *compressed_data;
+	uint16_t *decompressed_data;
+	struct cmp_entity *ent;
+
+	s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL,
+				NULL, ARRAY_SIZE(data));
+	TEST_ASSERT_TRUE(s);
+	compressed_data = malloc(s);
+	TEST_ASSERT_TRUE(compressed_data);
+	s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL,
+				compressed_data, ARRAY_SIZE(data));
+	TEST_ASSERT_TRUE(s);
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(sizeof(data)*CHAR_BIT, cmp_size);
+
+	s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_bit_to_4byte(cmp_size));
+	TEST_ASSERT_TRUE(s);
+	ent = malloc(s);
+	TEST_ASSERT_TRUE(ent);
+	s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_bit_to_4byte(cmp_size));
+	TEST_ASSERT_TRUE(s);
+	memcpy(cmp_ent_get_data_buf(ent), compressed_data, (cmp_size+7)/8);
+
+	s = decompress_cmp_entiy(ent, NULL, NULL, NULL);
+	TEST_ASSERT_EQUAL_INT(sizeof(data), s);
+	decompressed_data = malloc(s);
+	TEST_ASSERT_TRUE(decompressed_data);
+	s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(sizeof(data), s);
+
+	for (i = 0; i < ARRAY_SIZE(data); ++i) {
+		TEST_ASSERT_EQUAL_INT(data[i], decompressed_data[i]);
+
+	}
+
+	free(compressed_data);
+	free(ent);
+	free(decompressed_data);
+}
+
+
+/*
+ * @test re_map_to_pos
+ */
+
+void test_re_map_to_pos(void)
+{
+	int j;
+	uint32_t input, result;
+	unsigned int max_value_bits;
+
+	input = INT32_MIN;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = INT32_MAX;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = -1;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = 0;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = 1; max_value_bits = 6;
+	result = re_map_to_pos(map_to_pos(input, max_value_bits));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	for (j = -16; j < 15; j++) {
+		uint32_t map_val =  map_to_pos(j, 16) & 0x3F;
+		result = re_map_to_pos(map_val);
+		TEST_ASSERT_EQUAL_INT32(j, result);
+	}
+
+	for (j = INT16_MIN; j < INT16_MAX; j++) {
+		uint32_t map_val =  map_to_pos(j, 16) & 0xFFFF;
+		result = re_map_to_pos(map_val);
+		TEST_ASSERT_EQUAL_INT32(j, result);
+	}
+#if 0
+	for (j = INT32_MIN; j < INT32_MAX; j++) {
+		result = re_map_to_pos(map_to_pos(j, 32));
+		TEST_ASSERT_EQUAL_INT32(j, result);
+	}
+#endif
+}
+
+
+void test_decode_normal(void)
+{
+	uint32_t decoded_value;
+	int stream_pos, sample;
+	 /* compressed data from 0 to 6; */
+	uint32_t cmp_data[] = {0x5BBDF7E0};
+	struct decoder_setup setup = {0};
+
+	cpu_to_be32s(cmp_data);
+
+	setup.decode_cw_f = rice_decoder;
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = ilog_2(setup.encoder_par1);
+	setup.bitstream_adr = cmp_data;
+	setup.max_stream_len = 32;
+	setup.max_cw_len = 16;
+
+	stream_pos = 0;
+	for (sample = 0; sample < 7; sample++) {
+		stream_pos = decode_normal(&decoded_value, stream_pos, &setup);
+		TEST_ASSERT_EQUAL_HEX(sample, decoded_value);
+	}
+
+	 /* TODO error case: negativ stream_pos */
+}
+
+
+void test_decode_zero(void)
+{
+	uint32_t decoded_value;
+	int stream_pos;
+	uint32_t cmp_data[] = {0x88449FE0};
+	struct decoder_setup setup = {0};
+	struct cmp_cfg cfg = {0};
+
+	cpu_to_be32s(cmp_data);
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.icu_output_buf = cmp_data;
+	cfg.buffer_length = 4;
+
+	int err = configure_decoder_setup(&setup, 1, 8, CMP_LOSSLESS, 16, &cfg);
+	TEST_ASSERT_FALSE(err);
+
+	stream_pos = 0;
+
+	stream_pos = decode_zero(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0, decoded_value);
+	stream_pos = decode_zero(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value);
+	stream_pos = decode_zero(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(7, decoded_value);
+	TEST_ASSERT_EQUAL_INT(28, stream_pos);
+
+	 /* TODO error case: negativ stream_pos */
+}
+
+void test_decode_multi(void)
+{
+	uint32_t decoded_value;
+	int stream_pos;
+	uint32_t cmp_data[] = {0x16B66DF8, 0x84360000};
+	struct decoder_setup setup = {0};
+	struct cmp_cfg cfg = {0};
+
+	cpu_to_be32s(&cmp_data[0]);
+	cpu_to_be32s(&cmp_data[1]);
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_MULTI;
+	cfg.icu_output_buf = cmp_data;
+	cfg.buffer_length = 8;
+
+	int err = configure_decoder_setup(&setup, 3, 8, CMP_LOSSLESS, 16, &cfg);
+	TEST_ASSERT_FALSE(err);
+
+	stream_pos = 0;
+
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(1, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(7, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(8, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(9, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value);
+	TEST_ASSERT_EQUAL_INT(47, stream_pos);
+
+}
+
+
+void test_decompress_imagette_model(void)
+{
+	uint16_t data[5]  = {0};
+	uint16_t model[5] = {0, 1, 2, 3, 4};
+	uint16_t up_model[5]  = {0};
+	uint32_t cmp_data[] = {0};
+	struct cmp_cfg cfg = {0};
+	int stream_pos;
+
+	cmp_data[0] = cpu_to_be32(0x49240000);
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.icu_new_model_buf = up_model;
+	cfg.icu_output_buf = cmp_data;
+	cfg.buffer_length = 4;
+	cfg.samples = 5;
+	cfg.model_value = 16;
+	cfg.golomb_par = 4;
+	cfg.spill = 48;
+
+	stream_pos = decompress_imagette(&cfg);
+	TEST_ASSERT_EQUAL_INT(15, stream_pos);
+	TEST_ASSERT_EQUAL_HEX(1, data[0]);
+	TEST_ASSERT_EQUAL_HEX(2, data[1]);
+	TEST_ASSERT_EQUAL_HEX(3, data[2]);
+	TEST_ASSERT_EQUAL_HEX(4, data[3]);
+	TEST_ASSERT_EQUAL_HEX(5, data[4]);
+
+	TEST_ASSERT_EQUAL_HEX(0, up_model[0]);
+	TEST_ASSERT_EQUAL_HEX(1, up_model[1]);
+	TEST_ASSERT_EQUAL_HEX(2, up_model[2]);
+	TEST_ASSERT_EQUAL_HEX(3, up_model[3]);
+	TEST_ASSERT_EQUAL_HEX(4, up_model[4]);
+}
+
+int my_random(unsigned int min, unsigned int max)
+{
+	if (max-min > RAND_MAX)
+		TEST_ASSERT(0);
+	if (min > max)
+		TEST_ASSERT(0);
+	return min + rand() / (RAND_MAX / (max - min + 1) + 1);
+}
+
+/* #include <cmp_io.h> */
+/* void test_imagette_1(void) */
+/* { */
+/* 	size_t i; */
+
+/* 	enum cmp_mode cmp_mode = 1; */
+/* 	uint16_t model_value = 10; */
+/* 	struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, cmp_mode, model_value, CMP_LOSSLESS); */
+/* 	unsigned int samples = 1; */
+/* 	uint16_t data[1] = {0x8000}; */
+/* 	uint16_t model[1] = {0}; */
+/* 	uint16_t up_model[1] = {0}; */
+/* 	uint16_t de_up_model[1] = {0}; */
+/* 	uint32_t compressed_data[1]; */
+
+/* 	size_t s = cmp_cfg_buffers(&cfg, data, samples, model, up_model, */
+/* 			      compressed_data, 2*samples); */
+/* 	TEST_ASSERT(s > 0); */
+
+/* 	uint32_t golomb_par = 9; */
+/* 	uint32_t spill = 44; */
+
+/* 	cfg.spill = spill; */
+/* 	cfg.golomb_par = golomb_par; */
+/* 	/1* print_cfg(&cfg, 0); *1/ */
+/* 	int cmp_size = icu_compress_data(&cfg, NULL); */
+/* 	TEST_ASSERT(cmp_size > 0); */
+
+
+/* 	s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_size); */
+/* 	TEST_ASSERT_TRUE(s); */
+/* 	struct cmp_entity *ent = malloc(s); */
+/* 	TEST_ASSERT_TRUE(ent); */
+/* 	s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_size); */
+/* 	TEST_ASSERT_TRUE(s); */
+/* 	memcpy(cmp_ent_get_data_buf(ent), compressed_data, cmp_bit_to_4byte(cmp_size)); */
+
+/* 	s = decompress_cmp_entiy(ent, model, de_up_model, NULL); */
+/* 	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); */
+/* 	uint16_t *decompressed_data = malloc(s); */
+/* 	TEST_ASSERT_TRUE(decompressed_data); */
+/* 	s = decompress_cmp_entiy(ent, model, de_up_model, decompressed_data); */
+/* 	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); */
+
+/* 	for (i = 0; i < samples; ++i) { */
+/* 		if (data[i] != decompressed_data[i]) */
+/* 			TEST_ASSERT(0); */
+/* 		/1* TEST_ASSERT_EQUAL_HEX16(data[i], decompressed_data[i]); *1/ */
+/* 		/1* TEST_ASSERT_EQUAL_HEX16(up_model[i], de_up_model[i]); *1/ */
+/* 	} */
+
+
+/* 	free(ent); */
+/* 	free(decompressed_data); */
+/* } */
+
+#include <unistd.h>
+#include "cmp_io.h"
+
+void test_imagette_random(void)
+{
+	unsigned int seed = time(NULL) * getpid();
+	size_t i, s, cmp_data_size;
+	int error;
+	struct cmp_cfg cfg;
+	struct cmp_entity *ent;
+
+	enum cmp_mode cmp_mode = my_random(0, 4);
+	enum cmp_data_type data_type = DATA_TYPE_IMAGETTE;
+	uint16_t model_value = my_random(0, MAX_MODEL_VALUE);
+	uint32_t round = my_random(0, 3);
+	uint32_t samples, compressed_data_len_samples;
+	uint16_t *data, *model = NULL, *up_model = NULL, *de_up_model = NULL;
+
+	/* Seeds the pseudo-random number generator used by rand() */
+	srand(seed);
+	printf("seed: %u\n", seed);
+
+	/* create random test _data */
+	samples = my_random(1, 100000);
+	s = cmp_cal_size_of_data(samples, data_type);
+	data = malloc(s); TEST_ASSERT_TRUE(data);
+	for (i = 0; i < samples; ++i) {
+		data[i] = my_random(0, UINT16_MAX);
+	}
+	if (model_mode_is_used(cmp_mode)) {
+		model = malloc(s); TEST_ASSERT_TRUE(model);
+		up_model = malloc(s); TEST_ASSERT_TRUE(up_model);
+		de_up_model = malloc(s); TEST_ASSERT(de_up_model);
+		for (i = 0; i < samples; ++i) {
+			model[i] = my_random(0, UINT16_MAX);
+		}
+	}
+	compressed_data_len_samples = 6*samples;
+
+	/* create a compression configuration */
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, round);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKOWN);
+
+
+	cmp_data_size = cmp_cfg_icu_buffers(&cfg, data, samples, model, up_model,
+					    NULL, compressed_data_len_samples);
+	TEST_ASSERT_TRUE(cmp_data_size);
+
+	uint32_t golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+	uint32_t max_spill = get_max_spill(golomb_par, data_type);
+	TEST_ASSERT(max_spill > 1);
+	uint32_t spill = my_random(2, max_spill);
+
+	error = cmp_cfg_icu_imagette(&cfg, golomb_par, spill);
+	TEST_ASSERT_FALSE(error);
+
+	print_cfg(&cfg, 0);
+	s = icu_compress_data_entity(NULL, &cfg);
+	TEST_ASSERT_TRUE(s);
+	ent = malloc(s); TEST_ASSERT_TRUE(ent);
+	s = icu_compress_data_entity(ent, &cfg);
+	TEST_ASSERT_TRUE(s);
+
+	s = decompress_cmp_entiy(ent, model, de_up_model, NULL);
+	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s);
+	uint16_t *decompressed_data = malloc(s);
+	TEST_ASSERT_TRUE(decompressed_data);
+	s = decompress_cmp_entiy(ent, model, de_up_model, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s);
+
+	for (i = 0; i < samples; ++i) {
+		printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round);
+		uint32_t mask = ~0U << round;
+		if ((data[i]&mask) != (decompressed_data[i]&mask))
+			TEST_ASSERT(0);
+		if (model_mode_is_used(cmp_mode))
+			if (up_model[i] != de_up_model[i])
+				TEST_ASSERT(0);
+	}
+
+	free(data);
+	free(model);
+	free(up_model);
+	free(de_up_model);
+	free(ent);
+	free(decompressed_data);
+}
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
index 9804d41..aac8b0b 100755
--- a/test/cmp_tool/cmp_tool_integration_test.py
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -14,6 +14,7 @@ PATH_CMP_TOOL = "./cmp_tool"
 EXIT_FAILURE = 1
 EXIT_SUCCESS = 0
 
+DATA_TYPE_IMAGETTE  = 1
 
 GENERIC_HEADER_SIZE = 32
 IMAGETTE_HEADER_SIZE = GENERIC_HEADER_SIZE+4
@@ -409,14 +410,13 @@ def test_compression_diff():
                     assert(info['cmp_size'] == '20')
                     assert(info['cmp_err'] == '0')
                 else:
-                    # import pdb; pdb.set_trace()
                     header = read_in_cmp_header(f.read())
                     assert(header['asw_version_id']['value'] == VERSION)
                     assert(header['cmp_ent_size']['value'] == IMAGETTE_HEADER_SIZE+4)
                     assert(header['original_size']['value'] == 10)
                     # todo
                     assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow()))
-                    #todo
+                    # todo
                     assert(header['end_timestamp']['value'] < cuc_timestamp(datetime.utcnow()))
                     assert(header['data_type']['value'] == 1)
                     assert(header['cmp_mode_used']['value'] == 2)
@@ -428,7 +428,7 @@ def test_compression_diff():
                     assert(header['golomb_par_used']['value'] == 7)
                     assert(header['compressed_data']['value'] == "44444000")
 
-                # decompression
+            # decompression
             if add_arg == " --no_header":
                 returncode, stdout, stderr = call_cmp_tool(
                     " -i "+output_prefix+".info -d "+output_prefix+".cmp -o "+output_prefix)
@@ -441,8 +441,8 @@ def test_compression_diff():
                    "%s" % ((lambda arg : "Importing decompression information file %s.info ... DONE\n" % (output_prefix)
                             if "--no_header" in arg else "")(add_arg)) +
                    "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix) +
-                   "%s" % ((lambda arg : "Parse the compression entity header ... DONE\n"
-                            if not "--no_header" in arg else "")(add_arg)) +
+                   # "%s" % ((lambda arg : "Parse the compression entity header ... DONE\n"
+                   #          if not "--no_header" in arg else "")(add_arg)) +
                    "Decompress data ... DONE\n" +
                    "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix))
 
@@ -459,7 +459,7 @@ def test_compression_diff():
         del_file(output_prefix+'.dat')
 
 
-def test_model_compression_no_header():
+def test_model_compression():
     # generate test data
     data = '00 01 00 02 00 03 00 04 00 05 \n'
     model = '00 00 00 01 00 02 00 03 00 04 \n'
@@ -481,62 +481,93 @@ def test_model_compression_no_header():
             assert(stderr == "")
             cfg = parse_key_value(stdout)
             cfg['cmp_mode'] = 'MODE_MODEL_MULTI'
+            cfg['model_value'] = '16'
             cfg["samples"] = '5'
             cfg["buffer_length"] = '2'
             for key, value in cfg.items():
                 f.write(key + ' = ' + str(value) + '\n')
 
-        # compression
-        returncode, stdout, stderr = call_cmp_tool(
-            " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix1+" --no_header")
+        add_args = [" --no_header", ""]
+        for add_arg in add_args:
+            print("Remove this", add_arg)
+            # compression
+            returncode, stdout, stderr = call_cmp_tool(
+                " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix1+ add_arg)
 
-        # check compression results
-        assert(returncode == EXIT_SUCCESS)
-        assert(stderr == "")
-        assert(stdout == CMP_START_STR_CMP +
-               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
-               "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Importing model file %s ... DONE\n" % (model_file_name) +
-               "Compress data ... DONE\n" +
-               "Write compressed data to file %s.cmp ... DONE\n" % (output_prefix1) +
-               "Write decompression information to file %s.info ... DONE\n" % (output_prefix1) +
-               "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix1))
-        # check compressed data
-        with open(output_prefix1+".cmp", encoding='utf-8') as f:
-            assert(f.read() == "49 24 00 00 \n")
-        # check info file
-        with open(output_prefix1+".info", encoding='utf-8') as f:
-            info = parse_key_value(f.read())
-        assert(info['cmp_mode_used'] == '3')
-        assert(info['model_value_used'] == cfg['model_value'])
-        assert(info['round_used'] == cfg['round'])
-        assert(info['spill_used'] == cfg['spill'])
-        assert(info['golomb_par_used'] == cfg['golomb_par'])
-        assert(info['samples_used'] == cfg['samples'])
-        assert(info['cmp_size'] == '15')
-        assert(info['cmp_err'] == '0')
-
-        # decompression
-        returncode, stdout, stderr = call_cmp_tool(
-            " -i "+output_prefix1+".info -d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
-        assert(returncode == EXIT_SUCCESS)
-        assert(stdout == CMP_START_STR_DECMP +
-               "Importing decompression information file %s.info ... DONE\n" % (output_prefix1) +
-               "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix1) +
-               "Importing model file %s ... DONE\n" % (model_file_name) +
-               "Decompress data ... DONE\n" +
-               "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix2) +
-               "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix2))
-        assert(stderr == "")
-        # check compressed data
+            # check compression results
+            assert(stderr == "")
+            assert(stdout == CMP_START_STR_CMP +
+                   "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+                   "Importing data file %s ... DONE\n" % (data_file_name) +
+                   "Importing model file %s ... DONE\n" % (model_file_name) +
+                   "Compress data ... DONE\n" +
+                   "Write compressed data to file %s.cmp ... DONE\n" % (output_prefix1) +
+                   "%s" % ((lambda arg : "Write decompression information to file %s.info ... DONE\n" % (output_prefix1)
+                            if arg == " --no_header" else "")(add_arg)) +
+                   "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix1)
+            )
+            assert(returncode == EXIT_SUCCESS)
+
+            if add_arg == " --no_header":
+                # check compressed data
+                with open(output_prefix1+".cmp", encoding='utf-8') as f:
+                    assert(f.read() == "49 24 00 00 \n")
+                # check info file
+                with open(output_prefix1+".info", encoding='utf-8') as f:
+                    info = parse_key_value(f.read())
+                assert(info['cmp_mode_used'] == '3')
+                assert(info['model_value_used'] == cfg['model_value'])
+                assert(info['round_used'] == cfg['round'])
+                assert(info['spill_used'] == cfg['spill'])
+                assert(info['golomb_par_used'] == cfg['golomb_par'])
+                assert(info['samples_used'] == cfg['samples'])
+                assert(info['cmp_size'] == '15')
+                assert(info['cmp_err'] == '0')
+            else:
+                with open(output_prefix1+".cmp", encoding='utf-8') as f:
+                    header = read_in_cmp_header(f.read())
+                assert(header['asw_version_id']['value'] == VERSION)
+                assert(header['cmp_ent_size']['value'] == IMAGETTE_HEADER_SIZE+4)
+                assert(header['original_size']['value'] == 10)
+                # todo
+                assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow()))
+                #todo
+                assert(header['end_timestamp']['value'] < cuc_timestamp(datetime.utcnow()))
+                assert(header['data_type']['value'] == DATA_TYPE_IMAGETTE)
+                assert(header['cmp_mode_used']['value'] == 3)
+                assert(header['model_value_used']['value'] == int(cfg['model_value']))
+                assert(header['model_id']['value'] == 53264)
+                assert(header['model_counter']['value'] == 1)
+                assert(header['lossy_cmp_par_used']['value'] == int(cfg['round']))
+                assert(header['spill_used']['value'] == int(cfg['spill']))
+                assert(header['golomb_par_used']['value'] == int(cfg['golomb_par']))
+                assert(header['compressed_data']['value'] == "49240000")
+
+            # decompression
+            if add_arg == " --no_header":
+                returncode, stdout, stderr = call_cmp_tool(
+                    " -i "+output_prefix1+".info -d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
+            else:
+                returncode, stdout, stderr = call_cmp_tool("-d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
+            assert(stderr == "")
+            assert(stdout == CMP_START_STR_DECMP +
+                   "%s" % ((lambda arg : "Importing decompression information file %s.info ... DONE\n" % (output_prefix1)
+                            if "--no_header" in arg else "")(add_arg)) +
+                   "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix1) +
+                   "Importing model file %s ... DONE\n" % (model_file_name) +
+                   "Decompress data ... DONE\n" +
+                   "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix2) +
+                   "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix2))
+            assert(returncode == EXIT_SUCCESS)
+            # check compressed data
 
-        with open(output_prefix2+".dat", encoding='utf-8') as f:
-            assert(f.read() == data)
+            with open(output_prefix2+".dat", encoding='utf-8') as f:
+                assert(f.read() == data)
 
-        with open(output_prefix1+"_upmodel.dat", encoding='utf-8') as f1:
-            with open(output_prefix2+"_upmodel.dat", encoding='utf-8') as f2:
-                assert(f1.read() == f2.read() ==
-                       '00 00 00 01 00 02 00 03 00 04 \n')
+            with open(output_prefix1+"_upmodel.dat", encoding='utf-8') as f1:
+                with open(output_prefix2+"_upmodel.dat", encoding='utf-8') as f2:
+                    assert(f1.read() == f2.read() ==
+                           '00 00 00 01 00 02 00 03 00 04 \n')
     # clean up
     finally:
         del_file(data_file_name)
@@ -582,7 +613,7 @@ def test_raw_mode_compression():
             with open(output_prefix+".cmp", encoding='utf-8') as f:
                 if "--no_header" in arg:
                     # check compressed data file
-                    assert(f.read() == data[:-1]+"00 00 \n")
+                    assert(f.read() == data)#[:-1]+"00 00 \n")
                     # check info file
                     with open(output_prefix+".info", encoding='utf-8') as f:
                         info = parse_key_value(f.read())
@@ -627,8 +658,6 @@ def test_raw_mode_compression():
                    "%s" % ((lambda arg : "Importing decompression information file %s.info ... DONE\n" % (output_prefix)
                             if "--no_header" in arg else "")(arg)) +
                    "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix) +
-                   "%s" % ((lambda arg : "Parse the compression entity header ... DONE\n"
-                            if not "--no_header" in arg else "")(arg)) +
                    "Decompress data ... DONE\n" +
                    "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix))
             assert(returncode == EXIT_SUCCESS)
@@ -979,11 +1008,9 @@ def test_sample_used_is_to_big():
             else:
                 assert(stdout == CMP_START_STR_DECMP +
                        "Importing compressed data file %s ... DONE\n" % (cmp_file_name) +
-                       "Parse the compression entity header ... DONE\n" +
                        "Decompress data ... FAILED\n")
 
-            assert(stderr == "Error: Buffer overflow detected.\n" +
-                   "Error: Compressed values could not be decoded.\n")
+            assert(stderr == "Error: Buffer overflow detected.\n")
 
             assert(returncode == EXIT_FAILURE)
     finally:
@@ -1009,6 +1036,7 @@ def test_header_wrong_formatted():
     finally:
         del_file(cmp_file_name)
 
+
 def test_header_read_in():
     cmp_file_name = 'test_header_read_in.cmp'
 
@@ -1081,7 +1109,7 @@ def test_header_read_in():
         assert(returncode == EXIT_FAILURE)
         assert(stdout == CMP_START_STR_DECMP +
                "Importing compressed data file %s ... DONE\n" % (cmp_file_name) +
-               "Parse the compression entity header ... FAILED\n" )
+               "Decompress data ... FAILED\n" )
         assert(stderr == "Error: Compression mode not supported.\n")
 
     finally:
@@ -1106,25 +1134,27 @@ def test_model_fiel_erros():
             f.write(cfg)
 
         # no -m option in model mode
-        returncode, stdout, stderr = call_cmp_tool(
-            " -c "+cfg_file_name+" -d "+data_file_name + " -o "+output_prefix+" --no_header")
-        assert(returncode == EXIT_FAILURE)
-        assert(stdout == CMP_START_STR_CMP +
-               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
-               "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Importing model file  ... FAILED\n" )
-        assert(stderr == "cmp_tool: No model file (-m option) specified.\n")
+        add_args = [" --no_header", ""]
+        for add_arg in add_args:
+            returncode, stdout, stderr = call_cmp_tool(
+                " -c "+cfg_file_name+" -d "+data_file_name + " -o "+output_prefix+add_arg)
+            assert(returncode == EXIT_FAILURE)
+            assert(stdout == CMP_START_STR_CMP +
+                   "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+                   "Importing data file %s ... DONE\n" % (data_file_name) +
+                   "Importing model file  ... FAILED\n" )
+            assert(stderr == "cmp_tool: No model file (-m option) specified.\n")
 
-        # model file to small
-        with open(model_file_name, 'w', encoding='utf-8') as f:
-            f.write(model)
-        returncode, stdout, stderr = call_cmp_tool(
-            " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix)
-        assert(returncode == EXIT_FAILURE)
-        assert(stdout == CMP_START_STR_CMP +
-               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
-               "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Importing model file %s ... FAILED\n" % (model_file_name) )
+            # model file to small
+            with open(model_file_name, 'w', encoding='utf-8') as f:
+                f.write(model)
+            returncode, stdout, stderr = call_cmp_tool(
+                " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix)
+            assert(returncode == EXIT_FAILURE)
+            assert(stdout == CMP_START_STR_CMP +
+                   "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+                   "Importing data file %s ... DONE\n" % (data_file_name) +
+                   "Importing model file %s ... FAILED\n" % (model_file_name) )
         assert(stderr == "cmp_tool: %s: Error: The files do not contain enough data as requested.\n" % (model_file_name))
 
         # updated model can not write
diff --git a/test/meson.build b/test/meson.build
index b843e00..4743653 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -34,10 +34,6 @@ subdir('tools')
 
 subdir('cmp_tool')
 
-cunit_dep = dependency('cunit', required : false)
-
 unity_dep = dependency('unity', fallback : ['unity', 'unity_dep'])
-# unity_proj = subproject('unity')
-# unity_dep = unity_proj.get_variable('unity_dep')
 
 subdir('cmp_icu')
-- 
GitLab