yokesha 3 months ago
parent
commit
7a9bf4e350
100 changed files with 23861 additions and 0 deletions
  1. 11 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/.project
  2. 91 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/Makefile
  3. 181 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/Makefile.def
  4. 11 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/build_all.sh
  5. 12 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/build_adcs_intf_lib.sh
  6. 1396 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/adcs_bsk.h
  7. 1168 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/adcs_common.h
  8. 262 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/bootloader.h
  9. 4568 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/cubeacp.h
  10. 36 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/types.h
  11. 94 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/makefile
  12. 2180 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/adcs_bsk.c
  13. 143 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/bootloader.c
  14. 721 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/common.c
  15. 5318 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/cubeacp.c
  16. 89 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/Makefile
  17. 35 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/build_lib.sh
  18. 15 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/build_csp_lib.sh
  19. 153 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/basic.rst
  20. 61 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/example.rst
  21. 21 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/history.rst
  22. 21 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/libcsp.rst
  23. 16 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/memory.rst
  24. 19 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/mtu.rst
  25. 61 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/protocolstack.rst
  26. 29 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/structure.rst
  27. 27 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/topology.rst
  28. 52 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/buildall.py
  29. 159 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/csp_arch.c
  30. 316 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/csp_server_client.c
  31. 63 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/python_bindings_example_client.py
  32. 74 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/python_bindings_example_server.py
  33. 115 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/zmqproxy.c
  34. 70 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_clock.h
  35. 60 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_malloc.h
  36. 126 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_queue.h
  37. 206 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_semaphore.h
  38. 135 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_system.h
  39. 133 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_thread.h
  40. 73 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_time.h
  41. 59 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/posix/csp_system.h
  42. 114 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/posix/pthread_queue.h
  43. 82 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/crypto/csp_hmac.h
  44. 89 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/crypto/csp_sha1.h
  45. 78 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/crypto/csp_xtea.h
  46. 504 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp.h
  47. 94 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_buffer.h
  48. 214 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_cmp.h
  49. 117 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_comms.h
  50. 62 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_crc32.h
  51. 226 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_debug.h
  52. 39 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_dedup.h
  53. 148 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_endian.h
  54. 60 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_error.h
  55. 76 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_iflist.h
  56. 95 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_interface.h
  57. 77 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_perf.h
  58. 72 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_platform.h
  59. 64 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_promisc.h
  60. 161 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_rtable.h
  61. 111 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_sfp.h
  62. 294 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_types.h
  63. 73 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/drivers/can_socketcan.h
  64. 121 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/drivers/usart.h
  65. 18 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if.h
  66. 178 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_can.h
  67. 118 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_i2c.h
  68. 116 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_kiss.h
  69. 49 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_lo.h
  70. 54 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_mcast.h
  71. 34 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_slgnd.h
  72. 34 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_slgnd_tcp.h
  73. 118 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_zmqhub.h
  74. 43 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/makefile
  75. 23 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/csp_system.c
  76. 21 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/csp_time.c
  77. 32 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_clock.c
  78. 42 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_malloc.c
  79. 60 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_queue.c
  80. 84 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_semaphore.c
  81. 88 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_system.c
  82. 48 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_thread.c
  83. 40 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_time.c
  84. 22 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_clock.c
  85. 22 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_malloc.c
  86. 22 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_queue.c
  87. 85 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_semaphore.c
  88. 87 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_system.c
  89. 55 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_thread.c
  90. 22 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_time.c
  91. 178 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/pthread_queue.c
  92. 45 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_clock.c
  93. 36 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_malloc.c
  94. 60 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_queue.c
  95. 155 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_semaphore.c
  96. 135 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_system.c
  97. 72 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_thread.c
  98. 57 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_time.c
  99. 239 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/pthread_queue.c
  100. 18 0
      tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/windows/README

+ 11 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/.project

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>gs_ps_simu</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+	</natures>
+</projectDescription>

+ 91 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/Makefile

@@ -0,0 +1,91 @@
+#
+#   @copyright Copyright 2022 Antaris, Inc.
+#
+
+TOP_DIR=./
+include $(TOP_DIR)Makefile.def
+
+##############################################################################
+# All variables here intensionally set to empty, User should not modify here
+
+SRC =
+SRC_DIR =
+SUBDIR =
+
+##############################################################################
+# List of include file directories required for compilation
+INCLUDES =
+
+##############################################################################
+#Current Folder target name, usually current folder name
+#TARGET_LIB = target_name
+
+# List of source files required for compilation using SRC
+# mention the directory path where all C files to be compiled usig SRC_DIR
+# Mention Sub director makefile compilation using SUBDIR
+
+SUBDIR += lib
+SUBDIR += sample_apps
+
+##############################################################################
+
+ifeq ($(TARGET_LIB),)
+TARGET_LIB := $(shell basename `pwd`)
+endif
+
+ifneq ($(SRC_DIR),)
+    SOURCES = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
+endif
+
+SOURCES += $(SRC)
+
+OBJS = $(foreach dir,$(patsubst %.c, %.o, $(SOURCES)), $(OBJ_DIR)/$(dir))
+
+ifneq ($(SUBDIR),)
+SUB_DIR_LIBS = $(foreach dir,$(SUBDIR), $(dir)/$(OBJ_DIR)/$(shell basename $(dir)).a)
+endif
+
+#$(info selective source files List : $(SRC))
+#$(info source file directory       : $(SRC_DIR))
+#$(info All source file list        : $(SOURCES))
+#$(info All target object files     : $(OBJS))
+#$(info All target lib files        : $(SUB_DIR_LIBS))
+
+
+DEPS = $(OBJS:.o=.d)
+
+# Command to invoke compilation in sub-directories
+subdir_clean:
+	$(HIDE)for i in $(SUBDIR); do \
+	    $(MAKE) clean -C $$i;\
+	    done
+
+top_obj_dirs:
+	$(HIDE)$(MKDIR) $(TOP_DIR)/$(OBJ_DIR)
+
+# Command to invoke compilation in sub-directories
+subdir_all:
+	$(HIDE)for i in $(SUBDIR); do \
+	    $(MAKE) all -C $$i;\
+	    done
+lib: subdir_all
+	$(HIDE)$(MKDIR) $(OBJ_DIR)
+	$(HIDE)$(AR) $(OBJ_DIR)/$(TARGET_LIB).a $(SUB_DIR_LIBS)
+
+# Command to compile source files to intermediate object files
+all: top_obj_dirs $(OBJS)
+	$(HIDE)$(MKDIR) $(TOP_DIR)/$(OBJ_DIR)
+#	$(HIDE)$(RM) $(TOP_DIR)/$(OBJ_DIR)/*.o
+ifneq ($(SUBDIR),)
+	$(HIDE)$(MAKE) subdir_all
+endif
+
+# Command to delete intermediate object files
+clean:
+ifneq ($(SUBDIR),)
+	$(HIDE)$(MAKE) subdir_clean
+endif
+	$(HIDE)$(RM) $(OBJ_DIR)
+	@echo Cleaning done !
+
+-include $(DEPS)

+ 181 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/Makefile.def

@@ -0,0 +1,181 @@
+#
+#   @copyright Copyright 2022 Antaris, Inc.
+#
+
+#############################################################
+# 0 - CUBE ADCS
+# 1 - BSK Simulation
+
+ADCS_BSK_SIM =0
+#############################################################
+# 0 - UDP Socket Communication
+# 1 - TCP Socket Communication
+
+GS_OBC_SKT_TYPE=0
+#############################################################
+# 0 - SBAND SRS4 with csp
+# 1 - IQS SBAND without csp
+
+IQS_SBAND_SIM=0
+#############################################################
+# 0 - Disabld Backdoor Socket SIM
+# 1 - Enabled Backdoor Socket SIM
+
+BACKDOOR_SOCKET_SIM=1
+#############################################################
+# 0 - SBAND SRS4 with csp
+# 1 - UHF with csp
+
+UHF_SIM=0
+#############################################################
+# 1 - To enable MFCC for HYB setup validation
+
+UHF_GS_SIM=0
+#############################################################
+# 1 - Backdoor Socket enabled - CSP header and data
+# 0 - Backdoor Socket disabled
+
+SRS4_SBAND_SIM=0
+#############################################################
+
+# 0 - Disabled JANUS 2 EPS configuration
+# 1 - Enabled JANUS 2 EPS configuration
+
+EPS_BRD_CFG =1
+############################################################
+#
+# 0 - Disable test layer
+# 1 - Enable test layer
+
+TEST_LAYER=0
+#############################################################
+
+# 0 - Disable Encryption for IPCC
+# 1 - Enable Encryption for IPCC
+
+ENABLE_ENCRPT_IPCC=0
+
+#############################################################
+# 0 - Disable the eps simu TC
+# 1 - Enable the eps simu TC
+
+EPS_SIMU_TC_EN=0
+#############################################################
+# 0 - Disable the eps drishti
+# 1 - Enable the eps drishti
+
+EPS_DRISHTI_EN=0
+#############################################################
+
+
+# Clear All previous CFLAGS settings
+CFLAGS :=
+
+# Decide whether the commands will be shwon or not
+#VERBOSE =TRUE
+VERBOSE =FALSE
+
+# Hide or not the calls depending of VERBOSE
+ifeq ($(VERBOSE),TRUE)
+    HIDE =  
+    MAKE_FLAGS =
+else
+    HIDE = @
+    MAKE_FLAGS = --no-print-directory --silent
+endif
+
+MKDIR = mkdir -p
+RM    = rm -rf
+RMDIR = rm -rf
+
+# Toolchain path
+AR   = ar
+CC   = gcc
+OC   = objcopy
+OD   = objdump
+SIZE = size
+LD   = ld
+
+ifeq ($(ADCS_BSK_SIM),1)
+    CFLAGS += -DADCS_BSK_SIM
+endif
+
+ifeq ($(GS_OBC_SKT_TYPE),1)
+    CFLAGS += -DGS_OBC_TCP
+endif
+
+ifeq ($(IQS_SBAND_SIM),1)
+    CFLAGS += -DIQS_S_SIM
+endif
+
+ifeq ($(UHF_SIM),1)
+    CFLAGS += -DUHF_SIM
+endif
+
+ifeq ($(UHF_GS_SIM),1)
+    CFLAGS += -DUHF_GS_SIM
+endif
+
+ifeq ($(BACKDOOR_SOCKET_SIM),1)
+    CFLAGS += -DBACKDOOR_SOCK_SIM
+endif
+
+ifeq ($(SRS4_SBAND_SIM),1)
+    CFLAGS += -DSBAND_SIM
+endif
+
+ifeq ($(EPS_BRD_CFG),1)
+    CFLAGS += -DEPS_BRD_J2
+endif
+
+ifeq ($(TEST_LAYER),1)
+    CFLAGS += -DTEST_LAYER
+endif
+
+ifeq ($(ENABLE_ENCRPT_IPCC),1)
+    CFLAGS += -DIPCC_ENCRPT=0x20
+else
+    CFLAGS += -DIPCC_ENCRPT=0x00
+endif
+
+ifeq ($(EPS_SIMU_TC_EN),1)
+    CFLAGS += -DEPS_SIMU_EN
+endif
+
+ifeq ($(EPS_DRISHTI_EN),1)
+    CFLAGS += -DDRISHTI_EN
+endif
+
+# Additional compilation flags that could be enabled
+CFLAGS += -g3 $(OPT) -pthread -Wall -Werror -Wno-address-of-packed-member -DDEBUG -DFT_OBC -DFT_SAT -I$(TOP_DIR)/includes -I$(TOP_DIR) -DCSP_POSIX=1 -std=gnu99
+
+# Libraries to be linked are updated here
+LDFLAGS = -L lib/ipcc/\
+	  -L lib/security/libcrc-2.0/obj/\
+	  -L lib/security/hmac/obj/\
+	  -L lib/security/mbedtls/library/obj/\
+
+LIBS = -lc -lm
+
+LIBS += -lpthread -lipcc_lib -lcrc -lhmac -lmbedcrypto
+
+MAKE = make $(MAKE_FLAGS)
+
+#MAKE += -j4
+
+OBJ_DIR := obj
+
+$(OBJ_DIR)/%.o : %.s
+	echo Building $@
+	$(HIDE)$(MKDIR) $(dir $@)
+	$(HIDE)$(CC) $(CFLAGS) -c $(INCLUDES) -o $@ $< -MMD
+	$(HIDE)$(MKDIR) $(TOP_DIR)/$(OBJ_DIR)
+	$(HIDE)$(OC) $@ $(TOP_DIR)/$(OBJ_DIR)/$(notdir $@)
+
+$(OBJ_DIR)/%.o : %.c
+	echo Building $@
+	$(HIDE)$(MKDIR) $(dir $@)
+	$(HIDE)$(CC) $(CFLAGS) -c $(INCLUDES) -o $@ $< -MMD
+	$(HIDE)$(MKDIR) $(TOP_DIR)/$(OBJ_DIR)
+	$(HIDE)$(OC) $@ $(TOP_DIR)/$(OBJ_DIR)/$(notdir $@)
+

+ 11 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/build_all.sh

@@ -0,0 +1,11 @@
+
+# ********* Building IPCC Library ******
+cd lib
+./build_lib.sh $1
+cd ..
+
+# ******** Building sample apps **********
+cd sample_apps
+./build_sample_apps.sh $1
+cd ..
+

+ 12 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/build_adcs_intf_lib.sh

@@ -0,0 +1,12 @@
+# *********** Building ADCS interface library **********
+
+if [ $1 == "clean" ]
+then
+    echo "Cleaning ADCS library"
+    make clean
+
+else
+    echo "Building ADCS library"
+    make clean
+    make all
+fi

+ 1396 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/adcs_bsk.h

@@ -0,0 +1,1396 @@
+/**
+ * @file adcs_bsk.h
+ *
+ * @brief # This file contains abstraction functions, structures, enum for
+ *          ADCS simulation.
+ *
+ * @copyright Copyright 2023 Antaris, Inc.
+ */
+
+#ifndef ADCS_BSK_H_
+#define ADCS_BSK_H_
+
+#include "stdint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Adcs sensors
+typedef enum 
+{
+    ADCS_MAG = 0,            ///< Magnetometer
+    ADCS_RED_MAG = 1,        ///< Redundant Magnetometer
+    ADCS_MEMS_RATE,          ///< MEMS Rate sensor
+    ADCS_COARSE_SUN,         ///< Coarse momentum sensor
+    ADCS_FINE_SUN,           ///< Fine momentum sensor
+    ADCS_NADIR_SENS,         ///< Nadir pointing sensor
+    ADCS_GPS,                ///< GPS sensor
+    ADCS_STAR_SENS           ///< Star tracking sensor
+}e_adcs_sensor_type;
+
+/// Adcs actuators
+typedef enum 
+{
+    ADCS_MAG_TORQUER = 0,   ///< Magnetorquer
+    ADCS_WHEEL = 1,         ///< Reaction wheel
+    ADCS_THRUSTER           ///< Thruster
+}e_adcs_actuator_type;
+
+/// Rest Cause enumeration
+typedef enum
+{
+    ADCS_RESET_CAUSE_POR = 0,       ///< Power on reset
+    ADCS_RESET_CAUSE_BOR = 1,       ///< Brownout reset
+    ADCS_RESET_CAUSE_WDG = 2        ///< Watchdog reset
+}e_adcs_reset_cause;
+
+/// Boot cause enumeration
+typedef enum
+{
+    ADCS_BOOTCAUSE_UNEXPECTED = 0,  ///< Unexpected
+    ADCS_BOOTCAUSE_NORMAL = 1,      ///< Normal
+    ADCS_BOOTCAUSE_ERROR = 2        ///< Error
+}e_adcs_boot_cause;
+
+/// Magnetometer mode value enumeration
+typedef enum
+{
+    ADCS_MAGMTR_MODE_1 = 0,         ///< Magnetometer mode 1
+    ADCS_MAGMTR_MODE_2 = 1,         ///< Magnetometer mode 2
+    ADCS_MAGMTR_MODE_3 = 2          ///< Magnetometer mode 3
+}e_adcs_magmtr_mode_val;
+
+/// GPS type enumeration
+typedef enum
+{
+    ADCS_GPS_SELECT_NONE = 0        ///< GPS type none
+}e_adcs_gps_type;
+
+/// Star Tracker mode enumeration
+typedef enum 
+{
+    ADCS_STAR_MODE_TRACKING = 0,    ///< Tracking Mode
+    ADCS_STAR_MODE_LOST = 1         ///< Lost
+}e_adcs_star_mode;
+
+/// Capture result enumeration
+typedef enum
+{
+    ADCS_CAPTURE_STARTUP = 0,       ///< Capture Startup
+    ADCS_CAPTURE_PENDING = 1,       ///< Capture Pending
+    ADCS_CAPTURE_SUCCESS = 2,       ///< Capture Success
+    ADCS_CAPTURE_SUCCESS_HIFT = 3,  ///< Capture Success HIFT
+    ADCS_CAPTURE_TIMEOUT = 4,       ///< Capture Time out
+    ADCS_CAPTURE_SRAM_ERR = 5       ///< Capture SRAM error
+}e_adcs_capture_result;
+
+/// Detect result enumeration
+typedef enum
+{
+    ADCS_DETECT_STRATUP = 0,        ///< Detect Startup
+    ADCS_DETECT_NO_DETECT = 1,      ///< No Detect
+    ADCS_DETECT_PENDING = 2,        ///< Detect Pending
+    ADCS_DETECT_TOO_MANY_EDGES = 3, ///< Detect too many edges
+    ADCS_DETECT_TOO_FEW_EDGES = 4,  ///< Detect too few edges
+    ADCS_DETECT_BAD_FIT = 5,        ///< Detect bad fit
+    ADCS_DETECT_SUN_NOT_FOUND = 6,  ///< Detect sun not found
+    ADCS_DETECT_SUCCESS = 7         ///< Detect success
+}e_adcs_detect_result;
+
+/// GPS solution status enumeration
+typedef enum
+{
+    ADCS_GPS_SOL_COMPUTED = 0,          ///< GPS solution computed
+    ADCS_GPS_SOL_INSUFFICIENT_OBS = 1,  ///< GPS solution insufficient
+    ADCS_GPS_SOL_NO_CONVERGENCE = 2,    ///< GPS solution no convergence
+    ADCS_GPS_SOL_SINGULARITY = 3,       ///< GPS solution singularity
+    ADCS_GPS_SOL_COVTRACE = 4,          ///< GPS solution covtrace
+    ADCS_GPS_SOL_COLD_START = 5,        ///< GPS solution cold start
+    ADCS_GPS_SOL_VH_LIMIT = 6,          ///< GPS solution VH limit
+    ADCS_GPS_SOL_VARIANCE = 7,          ///< GPS solution variance
+    ADCS_GPS_SOL_INTEGRITY_WARNING = 8, ///< GPS solution integrity warning
+    ADCS_GPS_SOL_PENDING = 9,           ///< GPS solution pending
+    ADCS_GPS_SOL_INVALID_FIX = 10,      ///< GPS solution invalid fix
+    ADCS_GPS_SOL_UNAUTHORIZED = 11      ///< GPS solution unauthorized
+}e_adcs_gps_sol_sts;
+
+/// AxisSelect enumeration
+typedef enum
+{
+    ADCS_AXIS_SELECT_POSX = 0,          ///< Positive X
+    ADCS_AXIS_SELECT_NEGX = 1,          ///< Negative X
+    ADCS_AXIS_SELECT_POSY = 2,          ///< Positive Y
+    ADCS_AXIS_SELECT_NEGY = 3,          ///< Negative Y
+    ADCS_AXIS_SELECT_POSZ = 4,          ///< Positive Z
+    ADCS_AXIS_SELECT_NEGZ = 5,          ///< Negative Z
+    ADCS_AXIS_SELECT_NOTUSED = 6,       ///< Not Used
+    ADCS_AXIS_SELECT_POSXPOSY45DEG = 7  ///< Positive X/Y 45 degree
+}e_adcs_axis_select;
+
+/// Estimation mode enumeration
+typedef enum
+{
+    ADCS_EST_NONE = 0,                  ///< Estimation mode none
+    ADCS_EST_MEMS_RATE = 1,             ///< Estimation mode MEMS rate
+    ADCS_EST_GYRO_EKF = 2               ///< Estimation mode Gyro EKF
+}e_adcs_est_mode;
+
+/// ADCS States
+typedef enum
+{
+    ADCS_STATE_NONE = 0                 ///< ADCS none state
+}e_adcs_state;
+
+/// Attitude control mode enumeration
+typedef enum 
+{
+    ADCS_CTRL_MODE_NONE = 0,                    ///< No control mode
+    ADCS_CTRL_MODE_DETUMBLING = 1,              ///< Detumbling control mode
+    ADCS_CTRL_MODE_Y_SPIN_STABILIZATION = 2,    ///< Y Spin Stabilization
+    ADCS_CTRL_MODE_Z_SPIN_STABILIZATION = 3,    ///< Z Spin Stabilization
+    ADCS_CTRL_MODE_THREE_AXIS = 4,              ///< 3axis stabilization
+    ADCS_CTRL_MODE_SUN_POINTING = 5,            ///< Sun pointing
+    ADCS_CTRL_MODE_NADIR_POINTING = 6,          ///< Nadir pointing
+    ADCS_CTRL_MODE_TARGET_TRACKING = 7,         ///< Target tracking
+    ADCS_CTRL_MODE_CUSTOM = 8                   ///< Custom control mode
+}e_adcs_att_ctrl_mode;
+
+/// TC TM ID
+typedef enum
+{
+    API_REQ_RESET = 1,          ///< Reset command
+    API_REQ_UTC,                ///< UTC Set command
+    API_REQ_CLEAR_ERROR,        ///< Clear Error
+    API_REQ_SAVE_ORBIT,         ///< Save orbit parameters
+    API_REQ_TLE,                ///< TLE Set command
+    API_REQ_MOI,                ///< Set moment of intertia
+    API_REQ_PWR,                ///< Set Power configuration
+    API_REQ_MAGMTR_MODE_OPER,   ///< Set magnetometer operation mode
+    API_REQ_GYRO_CFG,           ///< Set gyro configuration
+    API_REQ_CSS_CFG,            ///< Set coarse sun sensor configuration
+    API_REQ_STAR_TRAC_CFG,      ///< Set star tracker configuration
+    API_REQ_MAGMTR_CFG,         ///< Set Magnetometer configuration
+    API_REQ_REDUN_MAGMTR_CFG,   ///< Set Redudent magnetometer
+                                ///< configuration
+    API_REQ_MAG_BOOM,           ///< Set Magnetometer boom
+    API_REQ_MGNTRQR_OUT,        ///< Set Magnetorquer output
+    API_REQ_RW_SPEED,           ///< Set Reaction wheel speed
+    API_REQ_MGNTRQR_CFG,        ///< Set Magnetorquer configuration
+    API_REQ_RW_CFG,             ///< Set Reaction wheel configuration
+    API_REQ_CTRL_MODE,          ///< Set Control mode configuration
+    API_REQ_DETUMBLE_CTRL,      ///< Set Detumble control parameters
+    API_REQ_Y_RW_CTRL,          ///< Set Y axis Reaction wheel control
+                                ///< parameter
+    API_REQ_Z_RW_CTRL,          ///< Set Z axis Reaction wheel control
+                                ///< parameter
+    API_REQ_RW_CTRL,            ///< Set Reaction wheel control
+    API_REQ_TRCK_CTRL_GAIN,     ///< Set tracking control gain
+    API_REQ_ATTITUDE_ANGL,      ///< Set attitude angle parameters
+    API_REQ_TRCK_TARGET,        ///< Set target tracking parameters
+    API_REQ_INRTL_REF,          ///< Set inertial reference
+    API_REQ_EST_MODE,           ///< Set estimation mode
+    API_REQ_EST_PARAM,          ///< Set estimation parameters
+    API_REQ_SENSORS_CFG,        ///< Set Sensor configuration
+    API_REQ_ACTUATORS_CFG,      ///< Set Acruator configuration
+    API_REQ_FSS_CFG,            ///< Set Fine sun sensor configuration
+    API_REQ_NADIR_CFG,          ///< Set Nadir configuration
+    API_RESP_ID = 128,          ///< Get Identification
+    API_RESP_STATE,             ///< Get ADCS state
+    API_RESP_TLE,               ///< Get TLE
+    API_RESP_MOI,               ///< Get moment of inetria
+    API_RESP_PWR,               ///< Get power configuration
+    API_RESP_MAG_FIELD_VEC,     ///< Get magnetic field vector
+    API_RESP_CSS_VEC,           ///< Get CSS vector
+    API_RESP_FSS_VEC,           ///< Get FSS vector
+    API_RESP_NADIR_VEC,         ///< Get nadir vector
+    API_RESP_SENSOR_RATE,       ///< Get sensor rate
+    API_RESP_STAR_TRKR_BVEC,    ///< Get star tracker body vector
+    API_RESP_STAR_TRKR_OVEC,    ///< Get star trackere orbit vector
+    API_RESP_RAW_NADIR_SEN,     ///< Get raw nadir sensor meaurement
+    API_RESP_RAW_FSS_SEN,       ///< Get raw fine sun sensor measurement
+    API_RESP_RAW_MAGMTR,        ///< Get raw magnetometer measurement
+    API_RESP_RAW_GPS_STS,       ///< Get raw GPS staus
+    API_RESP_RAW_GPS_TIME,      ///< Get raw GPS time
+    API_RESP_RAW_GPS_X,         ///< Get raw GPS X axis
+    API_RESP_RAW_GPS_Y,         ///< Get raw GPS Y axis
+    API_RESP_RAW_GPS_Z,         ///< Get raw GPS Z axis
+    API_RESP_STAR_MAG,          ///< Get star magnitude
+    API_RESP_STAR_PERFORM,      ///< Get star performance
+    API_RESP_STAR_TIMING,       ///< Get star timing
+    API_RESP_RAW_SENS,          ///< Get raw sensor measurement
+    API_RESP_RAW_GPS,           ///< Get raw GPS measurement
+    API_RESP_RAW_STAR_TRAC,     ///< Get raw star tracker measurement
+    API_RESP_STAR_RDATA,        ///< Get raw star tracker data
+    API_RESP_RAW_SEC_MAGMTR,    ///< Get raw secondary magnetometer
+                                ///< measurement
+    API_RESP_RAW_SENS_RATE,     ///< Get raw sensor rates
+    API_RESP_STAR_EST_RATE,     ///< Get star tracker estimation rate
+    API_RESP_SENS_CUR,          ///< Get sensor current
+    API_RESP_CON_CUR,           ///< Get adcs consumed current measurement
+    API_RESP_RW_CUR,            ///< Get reaction wheel current
+    API_RESP_TEMP,              ///< Get adcs temperature
+    API_RESP_SENS_RATE_TEMP,    ///< Get rate sensor temperature
+    API_RESP_POW_TEMP,          ///< Get power and temperature measurement
+    API_RESP_GYRO_CFG,          ///< Get gyro configuration
+    API_RESP_STAR_TRAC_CFG,     ///< Get star tracker configuration
+    API_RESP_MAGMTR_CFG,        ///< Get magnetometer configuration
+    API_RESP_CSS_CFG,           ///< Get CSS configuration
+    API_RESP_FSS_CFG,           ///< Get FSS configuration
+    API_RESP_NADIR_CFG,         ///< Get Nadir configuration
+    API_RESP_RED_MAGMTR_CFG,    ///< Get Redudant magnetometer
+                                ///< configuration
+    API_RESP_MGNTRQR_CFG,       ///< Get magnetorquer configuration
+    API_RESP_RW_CFG,            ///< Get reaction wheel configuration
+    API_RESP_DETUMBLE_CTRL,     ///< Get detumble parameters
+    API_RESP_Y_RW_CTRL,         ///< Get Y reaction wheel control
+    API_RESP_RW_CTRL,           ///< Get reaction wheel control
+    API_RESP_TRCK_CTRL_GAIN,    ///< Get tracking control gain
+    API_RESP_ATTITUDE_ANGL,     ///< Get attitude angle
+    API_RESP_TRCK_TARGET,       ///< Get target tracking parameters
+    API_RESP_INRTL_REF,         ///< Get inertial reference
+    API_RESP_EST_PARAM,         ///< Get estimation paremeters
+    API_RESP_POS_ECI,           ///< Get sattelite position ECI
+    API_RESP_VEL,               ///< Get sattelite velocity
+    API_RESP_POS_LLH,           ///< Get sattelte position LLH
+    API_RESP_EST_RATE,          ///< Get estimation rates
+    API_RESP_EST_QUTRN,         ///< Get estimated quaternion
+    API_RESP_ECEF_POS,          ///< Get ECEF sattelite position
+    API_RESP_MODL_MAG,          ///< Get moduled magnetic field vector
+    API_RESP_MODL_SUN,          ///< Get moduled sun vector
+    API_RESP_EST_GYRO,          ///< Get estimated gyro measurement
+    API_RESP_EST_INNOVN,        ///< Get estimation innovation
+    API_RESP_QUTR_ERROR,        ///< Get quaternion error vector
+    API_RESP_QUTR_COVR,         ///< Get quaternion covariance
+    API_RESP_ANGL_COVR,         ///< Get angular rate covariance
+    API_RESP_CTRL_MODE,         ///< Get Control mode
+    API_RESP_RW_SPEED,          ///< Get Reaction wheel commanded speed
+    API_RESP_RW_SPEED_MEASURE   ///< Get Reaction wheel measurement
+}e_api_req_id;
+
+/// API Response Id
+typedef enum
+{
+    API_RESP_OK=1,                    ///< Responce ID OK
+    API_RESP_ERROR                    ///< Responce Error
+}e_api_resp_id;
+
+
+/// API Error
+typedef enum
+{
+    API_ERR_INVALID_REQ=1,            ///< Invalid Request Id received
+    API_ERR_FRAME_ERR,                ///< Frame Error (SOF/EOF)
+    API_ERR_CRC_ERR,                  ///< Checksum Error
+    API_ERR_DATA_INVALID              ///< Invalid Data Error
+}e_api_error;
+
+
+/**
+ * @brief This structure repersent the ADCS context 
+ * will be updated in future
+ */
+typedef struct
+{
+    uint32_t magic;  /*!< Always equals to 0XAE */
+}__attribute__ ((__packed__))s_adcs_ctx;
+
+/**
+ * @brief Power command structure power sorce can either be sensor or actuator.
+ *        Supports upto 32 Power Sources. Each source will be internally mapped
+ *        inside the Basilisk Tool
+ */
+typedef struct
+{
+    uint32_t pwr_source;            /*!< 1 - Power On/ 0 - Power Off Each Bit 
+                                        can be mapped to each source*/
+}__attribute__ ((__packed__))s_adcs_pwr_cmd;
+
+/**
+ * @brief Reset command structure
+ */
+typedef struct
+{
+    uint8_t magic;           /*!< Identification byte which always 
+                                equals to 0x5A */
+}__attribute__ ((__packed__))s_adcs_reset;
+
+/**
+ * @brief Identification command
+ */
+typedef struct
+{
+    uint32_t id;             /*!< Identification element */
+}__attribute__ ((__packed__))s_adcs_id;
+
+/**
+ * @brief ADCS current state
+ */
+typedef struct
+{
+    uint8_t state; /*!< ADCS State */
+}__attribute__ ((__packed__))s_adcs_state;
+
+/**
+ * @brief TLE configuration structure
+ */
+typedef struct
+{
+    double inclination;        /*!< Inclination */
+    double eccentricity;       /*!< Eccenticity */
+    double raan;               /*!< Right-ascension of the Ascending Node */
+    double arg_perigee;        /*!< Argument of Perigee */
+    double b_star;             /*!< B-Star drag term */
+    double mean_motion;        /*!< Mean Motion */
+    double mean_anomaly;       /*!< Mean Anomaly */
+    double epoch;              /*!< Epoch Time */
+}__attribute__ ((__packed__))s_adcs_tle;
+
+/**
+ * @brief Moment of inertia matrix
+ */
+typedef struct
+{
+    float mom_iner_xx;        /*!< Moment Of Inertia - Ixx. (Unit [kg.m^2]) */
+    float mom_iner_yy;        /*!< Moment Of Inertia - Iyy. (Unit [kg.m^2]) */
+    float mom_iner_zz;        /*!< Moment Of Inertia - Izz. (Unit [kg.m^2]) */
+    float prod_iner_xy;       /*!< Product Of Inertia - Ixy. (Unit [kg.m^2]) */
+    float prod_iner_xz;       /*!< Product Of Inertia - Ixz. (Unit [kg.m^2]) */
+    float prod_iner_yz;       /*!< Product Of Inertia - Iyz. (Unit [kg.m^2]) */
+}__attribute__ ((__packed__))s_adcs_moi;
+
+/**
+ * @brief Current Unix Time
+ */
+typedef struct
+{
+    uint32_t utc_time;           /*!< Time in s since 01/01/1970,00:00.
+                                    (Unit [s]) */
+    uint16_t milli_sec;          /*!< Current millisecond count. (Unit [ms]) */
+}__attribute__ ((__packed__))s_adcs_time;
+
+/**
+ * @brief Magnetometer configuration
+ */
+typedef struct
+{
+    double angle_1;            /*!< Magnetometer Mounting Transform Alpha Angle
+                                (Uint [deg])*/
+    double angle_2;            /*!< Magnetometer Mounting Transform Beta Angle
+                                (Uint [deg])*/
+    double angle_3;            /*!< Magnetometer Mounting Transform Gamma Angle
+                                (Uint [deg])*/
+    double offset_1;           /*!< Magnetometer Channel 1 Offset */
+    double offset_2;           /*!< Magnetometer Channel 2 Offset */
+    double offset_3;           /*!< Magnetometer Channel 3 Offset */
+    double sens_11;            /*!< Magnetometer Sensitivity Matrix S11 */
+    double sens_12;            /*!< Magnetometer Sensitivity Matrix S12 */
+    double sens_13;            /*!< Magnetometer Sensitivity Matrix S13 */
+    double sens_21;            /*!< Magnetometer Sensitivity Matrix S21 */
+    double sens_22;            /*!< Magnetometer Sensitivity Matrix S22 */
+    double sens_23;            /*!< Magnetometer Sensitivity Matrix S23 */
+    double sens_31;            /*!< Magnetometer Sensitivity Matrix S31 */
+    double sens_32;            /*!< Magnetometer Sensitivity Matrix S32 */
+    double sens_33;            /*!< Magnetometer Sensitivity Matrix S33 */
+}__attribute__ ((__packed__))s_adcs_mgmtr_cfg;
+
+/**
+ * @brief Raw Magnetometer
+ */
+typedef struct
+{
+    int16_t mag_raw_x;          /*!< Raw magnetometer X measuremen */
+    int16_t mag_raw_y;          /*!< Raw magnetometer Y measurement */
+    int16_t mag_raw_z;          /*!< Raw magnetometer Z measurement */
+}__attribute__ ((__packed__))s_adcs_raw_mgmtr;
+
+/**
+ * @brief Deploy magnetometer boom
+ */
+typedef struct
+{
+    uint8_t time_out;   /*!< Deployment actuation timeout value.(Unit [s]) */
+}__attribute__ ((__packed__))s_adcs_mgmtr_boom;
+
+/**
+ * @brief CSS pointing direction and scale factor
+ */
+typedef struct
+{
+    uint8_t css_conf;                   /*!< CSS Axis configuration */
+    double css_scale;                   /*!< CSS Relative Scaling Factor */
+    uint8_t css_min;                    /*!< CSS Minimum Threshold */
+}__attribute__ ((__packed__))s_adcs_css_cfg;
+
+/**
+ * @brief FSS pointing direction and scale factor
+ */
+typedef struct
+{
+    uint8_t fss_conf;                   /*!< FSS Axis configuration */
+    double fss_scale;                   /*!< FSS Relative Scaling Factor */
+    uint8_t fss_min;                    /*!< FSS Minimum Threshold */
+}__attribute__ ((__packed__))s_adcs_fss_cfg;
+
+/**
+ * @brief Nadir sensor configuration
+ */
+typedef struct
+{
+    uint8_t max_deviation_pct;          /*!< Nadir Max Deviation Percentage */
+    uint8_t max_bad_edges;              /*!< Nadir Max Bad Edges */
+    uint8_t max_radius;                 /*!< Maximum Radius. (Unit [°]) */
+    uint8_t min_radius;                 /*!< Minimum Radius. (Unit [°]) */
+}__attribute__ ((__packed__))s_adcs_nadir_cfg;
+
+/**
+ * @brief Nadir sensor measurement
+ */
+typedef struct
+{
+    int16_t nadir_raw_x;                /*!< Nadir sensor raw X angle */
+    int16_t nadir_raw_y;                /*!< Nadir sensor raw Y angle */
+    uint8_t nadir_busy;                 /*!< Nadir sensor capture status */
+    uint8_t nadir_result;               /*!< Nadir sensor detection result */
+}__attribute__ ((__packed__))s_adcs_nadir_sens;
+
+/**
+ * @brief FSS measurement
+ */
+typedef struct
+{
+    int16_t fss_raw_x;                  /*!< FSS raw X angle */
+    int16_t fss_raw_y;                  /*!< FSS raw Y angle */
+    uint8_t fss_busy;                   /*!< FSS capture status */
+    uint8_t fss_result;                 /*!< FSS detection result */
+}__attribute__ ((__packed__))s_adcs_fss_sens;
+
+/**
+ * @brief Gyro configuration
+ */
+typedef struct
+{
+    uint8_t gyro_conf;                  /*!< Gyro axis configuration */
+    double x_rate_offset;               /*!< X-Rate Sensor Offset */
+    double y_rate_offset;               /*!< Y-Rate Sensor Offse */
+    double z_rate_offset;               /*!< Z-Rate Sensor Offse */
+    uint8_t rate_sensor_mult;           /*!< Multiplier of rate sensor 
+                                            measurement */
+}__attribute__ ((__packed__))s_adcs_gyro_cfg;
+
+/**
+ * @brief Star Tracker configuration
+ */
+typedef struct
+{
+    double angle_1;                     /*!< StarTracker Mounting Transform 
+                                        Alpha Angle */
+    double angle_2;                     /*!< StarTracker Mounting Transform 
+                                        Beta Angle */
+    double angle_3;                     /*!< StarTracker Mounting Transform 
+                                        Gamma Angle */
+    uint16_t exposure;                  /*!< StarTracker exposure time */
+    uint16_t gain;                      /*!< StarTracker analog gain */
+    uint8_t detection_threshold;        /*!< StarTracker detection threshold */
+    uint8_t threshold;                  /*!< StarTracker star threshold */
+    uint8_t max_star_matched;           /*!< Maximum Star Matched */
+    uint16_t timeout_time;              /*!< Detection Timeout duration */
+    uint8_t max_star_pixel;             /*!< Maximum Star Pixel */
+    uint8_t min_star_pixel;             /*!< Minimum Star Pixel */
+    double error_margin;                /*!< Star Tracker Error Margin */
+    uint16_t delay_time;                /*!< Star Tracker Delay Time */
+    float cent_x;                       /*!< Star Tracker Centroid X */
+    float cent_y;                       /*!< Star Tracker Centroid Y */
+    float focal;                        /*!< Star Tracker Focal Length */
+    float lens_k1;                      /*!< K1 radial distortion coefficient */
+    float lens_k2;                      /*!< K2 radial distortion coefficient */
+    float lens_p1;                      /*!< P1 tangential distortion 
+                                            coefficient */
+    float lens_p2;                      /*!< P2 tangential distortion 
+                                            coefficient */
+    uint8_t window_width;               /*!< Star tracking window width */
+    double tracking_margin;             /*!< Star Tracking Margin */
+    double validation_margin;           /*!< Star Validation Margin */
+    uint8_t module_enable;              /*!< Star Tracking Module Enable */
+    uint8_t location_prediction_enable; /*!< Star Tracking Location Prediction 
+                                        Enable */
+    double search_width;                /*!< Star Tracking Search Width */
+}__attribute__ ((__packed__))s_adcs_star_trkr_cfg;
+
+/**
+ * @brief Star Tracker magnitude of identified
+ */
+typedef struct
+{
+    uint16_t mag_star_1;             /*!< Instrument magnitude of star 1 */
+    uint16_t mag_star_2;             /*!< Instrument magnitude of star 2 */
+    uint16_t mag_star_3;             /*!< Instrument magnitude of star 3 */
+}__attribute__ ((__packed__))s_adcs_star_trkr_mag;
+
+/**
+ * @brief Star Tracker performance
+ */
+typedef struct
+{
+    uint8_t num_stars_detected;          /*!< Number of stars detected */
+    uint8_t star_image_noise;            /*!< Star image noise */
+    uint8_t invalid_stars;               /*!< Invalid Star */
+    uint8_t num_stars_id;                /*!< Number of star identified */
+    uint8_t id_mode;                     /*!< Identification mode */
+    uint8_t image_dark_value;            /*!< Image dark value  The average 
+                                            value of center line in image */
+}__attribute__ ((__packed__))s_adcs_star_trkr_perform;
+
+/**
+ * @brief Timing information of star measurement
+ */
+typedef struct
+{
+    uint16_t capture;            /*!< Capture */
+    uint16_t detection;          /*!< Detection */
+    uint16_t id;                 /*!< Identification */
+}__attribute__ ((__packed__))s_adcs_star_trkr_timing;
+
+/**
+ * @brief Star Tracker raw measurement
+ */
+typedef struct
+{
+    uint8_t num_stars_detected;         /*!< Number of stars detected */
+    uint8_t star_image_noise;           /*!< Star image noise */
+    uint8_t invalid_stars;              /*!< Invalid Star */
+    uint8_t num_stars_id;               /*!< Number of star identified */
+    uint8_t id_mode;                    /*!< Identification mode */
+    uint8_t image_dark_value;           /*!< Image dark value  The average 
+                                           value of center line in image */
+    uint8_t image_capture_success;      /*!< Image Capture Success */
+    uint8_t detection_success;          /*!< Detection Success */
+    uint8_t id_success;                 /*!< Identification Success*/
+    uint8_t attitude_success;           /*!< Attitude Success */
+    uint8_t processing_time_error;      /*!< Processing Time Error */
+    uint8_t tracking_module_enabled;    /*!< Tracking module enabled */
+    uint8_t prediction_enabled;         /*!< Prediction enabled */
+    uint8_t comms_error;                /*!< Comms error */
+    uint8_t s1_conf;                    /*!< Star 1 confidence.
+                                            (Unit[percentage]) */
+    uint8_t s2_conf;                    /*!< Star 2 confidence.
+                                            (Unit[percentage]) */
+    uint8_t s3_conf;                    /*!< Star 3 confidence.
+                                            (Unit[percentage]) */
+    uint16_t mag_star_1;                /*!< Instrument magnitude of star 1 */
+    uint16_t mag_star_2;                /*!< Instrument magnitude of star 2 */
+    uint16_t mag_star_3;                /*!< Instrument magnitude of star 3 */
+    uint16_t capture;                   /*!< Capture */
+    uint16_t detection;                 /*!< Detection */
+    uint16_t id;                        /*!< Identification */
+    double rate_x;                      /*!< Estimated Rate X-axis */
+    double rate_y;                      /*!< Estimated Rate Y-axis */
+    double rate_z;                      /*!< Estimated Rate Z-axis */
+    double est_attitude_q1;             /*!< Estimated attitude Q1 */
+    double est_attitude_q2;             /*!< Estimated attitude Q2 */
+    double est_attitude_q3;             /*!< Estimated attitude Q3 */
+}__attribute__ ((__packed__))s_adcs_raw_star_trkr;
+
+/**
+ * @brief Star Tracker body vector for xyz axis
+ */
+typedef struct
+{
+    int16_t star_b_x;               /*!< Star body X-vector */
+    int16_t star_b_y;               /*!< Star body Y-vector */
+    int16_t star_b_z;               /*!< Star body Z-vector */
+}__attribute__ ((__packed__))s_adcs_star_trkr_body;
+
+/**
+ * @brief Star Tracker Orbit vector for xyz axis
+ */
+typedef struct
+{
+    int16_t star_o_x;               /*!< Star orbit X-vector */
+    int16_t star_o_y;               /*!< Star orbit Y-vector */
+    int16_t star_o_z;               /*!< Star orbit Z-vector */
+}__attribute__ ((__packed__))s_adcs_star_trkr_orbit;
+
+/**
+ *@brief generic sensor configration union.
+ */
+typedef union
+{
+    s_adcs_mgmtr_cfg magetometer_config;        /*!< Magnetometer config  */
+    s_adcs_mgmtr_cfg red_magetometer_config;    /*!< Retudent Magnetometer 
+                                                    config */
+    s_adcs_css_cfg corase_config;               /*!< Coarse configuration */
+    s_adcs_fss_cfg fss_config;                  /*!< Fss configuration */
+    s_adcs_nadir_cfg nadir_config;              /*!< Nadir configuration */
+    s_adcs_star_trkr_cfg star_trkr_config;      /*!< Star tracker 
+                                                    configuration */
+}u_adcs_sensor_config;
+
+/**
+ *@brief generic sensor configration parameter.
+ */
+typedef struct
+{
+    uint8_t sensor_type;                        /*!< Sesnor type */
+    uint8_t sensor_id;                          /*!< Sensor Id */
+    u_adcs_sensor_config sensor_cfg;            /*!< Sensor Configuration 
+                                                    parameters */
+}__attribute__ ((__packed__))s_adcs_sensor_cfg;
+
+/**
+ * @brief Tracking Controller Gain Parameters
+ */
+typedef struct
+{
+    float prop_gain;                        /*!< Tracking Proportional Gain */
+    float derv_gain;                        /*!< Tracking Derivative Gain */
+    float integ_gain;                       /*!< Tracking Integral Gain */
+    uint8_t target_Track_Facet;             /*!< Target-tracking Facet */
+}__attribute__ ((__packed__))s_adcs_trck_ctrl_gain;
+
+/**
+ * @brief Magnetorquer configuration
+ */
+typedef struct
+{
+    uint8_t mgntrqr_axis;           /*!< Magnetorquer axis configuration */
+}__attribute__ ((__packed__))s_adcs_mgntrqr_cfg;
+
+/*
+ * @brief Magnetorquer output
+ */
+typedef struct
+{
+    int16_t torquer_cmd_x;          /*!< Commanded X Magnetorquer duty cycle */
+    int16_t torquer_cmd_y;          /*!< Commanded y Magnetorquer duty cycle */
+    int16_t torquer_cmd_z;          /*!< Commanded Z Magnetorquer duty cycle */
+}__attribute__ ((__packed__))s_adcs_mgntrqr_out;
+
+/**
+ * @brief Reaction Wheel configuration
+ */
+typedef struct
+{
+    uint8_t rw_conf;       /*!< Reaction wheel axis configuration */
+}__attribute__ ((__packed__))s_adcs_rw_cfg;
+
+/**
+ * @brief Reaction Wheel Speed
+ */
+typedef struct
+{
+    int16_t rw_speed;       /*!< Command wheel speed */
+}__attribute__ ((__packed__))s_adcs_rw_speed;
+
+/**
+ *@brief generic Actuator configration Union.
+ */
+typedef union
+{
+    s_adcs_rw_cfg rwheel_config;           /*!< Reactionwheel config */
+    s_adcs_mgntrqr_cfg magnotorque_config; /*!< Magnetorquer config  */
+}u_adcs_acutator_config;
+
+/**
+ *@brief generic Actuator configration parameter.
+ */
+typedef struct
+{
+    uint8_t actuator_type;                  /*!< Actuator type */
+    uint8_t actuator_id;                    /*!< Actuator Id */
+    u_adcs_acutator_config actuator_cfg;    /*!< Actuator configurtion 
+                                                parameters */
+}__attribute__ ((__packed__))s_adcs_actuators_cfg;
+
+/**
+ * @brief Y-Wheel Control Parameters
+ */
+typedef struct
+{
+    float ctrl_gain;              /*!< Y-Momentum Control Gain */
+    float nutation_damp_gain;     /*!< Y-momentum Nutation Damping Gain */
+    float prop_gain;              /*!< Y-momentum Proportional Gain */
+    float derv_gain;              /*!< Y-momentum Derivative Gain */
+    float ref_rw_mom;             /*!< Reference Wheel Momentum */
+}__attribute__ ((__packed__))s_adcs_y_rw_ctrl;
+
+/**
+ * @brief Z-Wheel Control Parameters
+ */
+typedef struct
+{
+    float ctrl_gain;              /*!< Z-Momentum Control Gain */
+    float nutation_damp_gain;     /*!< Z-momentum Nutation Damping Gain */
+    float prop_gain;              /*!< Z-momentum Proportional Gain */
+    float derv_gain;              /*!< Z-momentum Derivative Gain */
+    float ref_rw_mom;             /*!< Reference Wheel Momentum */
+}__attribute__ ((__packed__))s_adcs_z_rw_ctrl;
+
+/**
+ * @brief Reaction wheel Control Parameters
+ */
+typedef struct
+{
+    float rw_prop_gain;                   /*!< RWheel Proportional Gain */
+    float rw_derv_gain;                   /*!< RWheel Derivative Gain */
+    float y_rw_bias;                      /*!< Y-Wheel Bias Momentum */
+    uint8_t sun_point_facet;              /*!< Sun-pointing Facet */
+    uint8_t rw_error_handling;            /*!< Automatic Control Transition 
+                                            due to Wheel Errors */
+}__attribute__ ((__packed__))s_adcs_rw_ctrl;
+
+/**
+ * @brief Reaction wheel Current parameter
+ */
+typedef struct
+{
+    double rw_current;        /*!< Reaction wheel current */
+}__attribute__ ((__packed__))s_adcs_rw_cur;
+
+/**
+ * @brief Raw sensor measurement
+ */
+typedef struct
+{
+    int16_t nadir_raw_x;                /*!< Nadir sensor raw X angle */
+    int16_t nadir_raw_y;                /*!< Nadir sensor raw Y angle */
+    uint8_t nadir_busy;                 /*!< Nadir sensor capture status */
+    uint8_t nadir_result;               /*!< Nadir sensor detection result */
+    int16_t fss_raw_x;                  /*!< FSS raw X angle */
+    int16_t fss_raw_y;                  /*!< FSS raw Y angle */
+    uint8_t fss_busy;                   /*!< FSS capture status */
+    uint8_t fss_result;                 /*!< FSS detection result */
+    uint8_t css_raw;                    /*!< CSS Raw measurement */
+    int16_t mag_raw_x;                  /*!< Raw magnetometer X measurement */
+    int16_t mag_raw_y;                  /*!< Raw magnetometer Y measurement */
+    int16_t mag_raw_z;                  /*!< Raw magnetometer Z measurement */
+    int16_t raw_rate_x;                 /*!< Raw Angular rate X axis */
+    int16_t raw_rate_y;                 /*!< Raw Angular rate Y axis */
+    int16_t raw_rate_z;                 /*!< Raw Angular rate Z axis */
+}__attribute__ ((__packed__))s_adcs_raw_sensor;
+
+/**
+ * @brief Control mode configuration
+ */
+typedef struct
+{
+    uint8_t ctrl_mode;                  /*!< Control mode */
+    uint16_t time_out;                  /*!< Timeout value for assigned 
+                                            control mode */
+}__attribute__ ((__packed__))s_adcs_ctrl_mode;
+
+/**
+ * @brief Control mode configuration
+ */
+typedef struct
+{
+    float spin_gain;            /*!< Detumbling spin gain */
+    float damping_gain;         /*!< Detumbling Damping Gain */
+    double rw_ref_spin_rate;    /*!< Reference spin rate */
+    float f_bdot_gain;          /*!< Fast BDot Detumbling Gain */
+}__attribute__ ((__packed__))s_adcs_detumble_ctrl;
+
+/**
+ * @brief Rate sensor xyz axis measurement
+ */
+typedef struct
+{
+    double rate_x;         /*!< X axis rate sensor measurement value */
+    double rate_y;         /*!< Y axis rate sensor measurement value */
+    double rate_z;         /*!< Z axis rate sensor measurement value */
+}__attribute__ ((__packed__))s_adcs_rate_sens;
+
+/**
+ * @brief Rate sensor raw measurement
+ */
+typedef struct
+{
+    int16_t raw_rate_x;     /*!< X axis raw rate sensor measurement */
+    int16_t raw_rate_y;     /*!< Y axis raw rate sensor measurement */
+    int16_t raw_rate_z;     /*!< Z axis raw rate sensor measurement */
+}__attribute__ ((__packed__))s_adcs_raw_rate_sens;
+
+/**
+ * @brief Attitude Angle
+ */
+typedef struct
+{
+    double roll;           /*!< Command Roll Angle */
+    double pitch;          /*!< Command Pitch Angle */
+    double yaw;            /*!< Command Yaw Angle */
+}__attribute__ ((__packed__))s_adcs_attitude_angl;
+
+/**
+ * @brief Target tarcking parameter
+ */
+typedef struct
+{
+    float long_ref;       /*!< Geocentric longitude of target */
+    float lat_ref;        /*!< Geocentric latitude of target */
+    float alt_ref;        /*!< Geocentric altitude of target */
+}__attribute__ ((__packed__))s_adcs_trck_target;
+
+/**
+ * @brief Inertial Pointing Reference Vector
+ */
+typedef struct
+{
+    int16_t iner_ref_x;     /*!< Inertial Reference X */
+    int16_t iner_ref_y;     /*!< Inertial Reference Y */
+    int16_t iner_ref_z;     /*!< Inertial Reference Z */
+}__attribute__ ((__packed__))s_adcs_inrt_ref;
+
+/**
+ * @brief generic control mode configuration parameter.
+ */
+typedef union
+{
+    s_adcs_attitude_angl attitude_ctrl;     /*!< Attitude control parameters */
+    s_adcs_trck_target target_track_ctrl;   /*!< Traget tracking parameters */
+    uint32_t nadir_point_mode;              /*!< Nadir pointing mode */
+}__attribute__ ((__packed__))u_control_mode_param;
+
+/**
+ * @brief Estimated star tracker rates
+ */
+typedef struct
+{
+    int16_t x_axis_rate;    /*!< Estimated X axis rate measurement */
+    int16_t y_axis_rate;    /*!< Estimated Y axis rate measurement */
+    int16_t z_axis_rate;    /*!< Estimated Z axis rate measurement */
+}__attribute__ ((__packed__))s_adcs_star_est_rate;
+
+/**
+ * @brief GPS and Sattelite tracker structure
+ */
+typedef struct
+{
+    uint8_t gps_sol_sts;            /*!< Gps Solution Status */
+    uint8_t gps_num_sats_tracked;   /*!< Number of tracked GPS satellites */
+    uint8_t gps_num_sats_sol;       /*!< Number of GPS satellites used 
+                                        in solution */
+    uint8_t gps_xyz_log_ctr;        /*!< Counter for XYZ Lof from GPS */
+    uint8_t gps_range_log_ctr;      /*!< Counter for RANGE log from GPS */
+    uint8_t gps_response;           /*!< Response Message for GPS log setup */
+}__attribute__ ((__packed__))s_adcs_gps_s;
+
+/**
+ * @brief GPS time format
+ */
+typedef struct
+{
+    uint16_t gps_week;               /*!< GPS Reference Week */
+    uint32_t gps_time_ms;            /*!< GPS Time Milliseconds */
+}__attribute__ ((__packed__))s_adcs_gps_time;
+
+/**
+ * @brief Position and velocity in ECEF format for X axis
+ */
+typedef struct
+{
+    int32_t ecef_pos_x;             /*!< ECEF Position X */
+    int16_t ecef_vel_x;             /*!< ECEF Velocity X */
+}__attribute__ ((__packed__))s_adcs_gps_x;
+
+/**
+ * @brief Position and velocity in ECEF format for Y axis
+ */
+typedef struct
+{
+    int32_t ecef_pos_y;             /*!< ECEF Position Y */
+    int16_t ecef_vel_y;             /*!< ECEF Velocity Y */
+}__attribute__ ((__packed__))s_adcs_gps_y;
+
+/**
+ * @brief Position and velocity in ECEF format for Z axis
+ */
+typedef struct
+{
+    int32_t ecef_pos_z;             /*!< ECEF Position Z */
+    int16_t ecef_vel_z;             /*!< ECEF Velocity Z */
+}__attribute__ ((__packed__))s_adcs_gps_z;
+
+/**
+ * @brief Raw GPS measurement
+ */
+typedef struct
+{
+    uint8_t gps_sol_sts;            /*!< Gps Solution Status */
+    uint8_t gps_num_sats_tracked;   /*!< Number of tracked GPS satellites */
+    uint8_t gps_num_sats_sol;       /*!< Number of GPS satellites used 
+                                        in solution */
+    uint8_t gps_xyz_log_ctr;        /*!< Counter for XYZ Lof from GPS */
+    uint8_t gps_range_log_ctr;      /*!< Counter for RANGE log from GPS */
+    uint8_t gps_response;           /*!< Response Message for GPS log setup */
+    uint16_t gps_week;              /*!< GPS Reference Week */
+    uint32_t gps_time_ms;           /*!< GPS Time Milliseconds */
+    int32_t ecef_pos_x;             /*!< ECEF Position X */
+    int16_t ecef_vel_x;             /*!< ECEF Velocity X */
+    int32_t ecef_pos_y;             /*!< ECEF Position Y */
+    int16_t ecef_vel_y;             /*!< ECEF Velocity Y */
+    int32_t ecef_pos_z;             /*!< ECEF Position Z */
+    int16_t ecef_vel_z;             /*!< ECEF Velocity Z */
+    double std_dev_pos_x;           /*!< X-pos Standard Deviation */
+    double std_dev_pos_y;           /*!< Y-pos Standard Deviation */
+    double std_dev_pos_z;           /*!< Z-pos Standard Deviation */
+    uint8_t std_dev_vel_x;          /*!< X-vel Standard Deviation */
+    uint8_t std_dev_vel_y;          /*!< Y-vel Standard Deviation */
+    uint8_t std_dev_vel_z;          /*!< Z-vel Standard Deviation */
+}__attribute__ ((__packed__))s_adcs_raw_gps;
+
+/**
+ * @brief Estimation mode configuration
+ */
+typedef struct
+{
+    uint8_t est_mode;               /*!< Estimation mode */
+}__attribute__ ((__packed__))s_adcs_est_mode;
+
+/**
+ * @brief Estimation parameter
+ */
+typedef struct
+{
+    float mag_rate_noise;               /*!< Magnetometer Rate Filter System 
+                                            Noise */
+    float ekf_sys_noise;                /*!< EKF System Noise */
+    float css_noise;                    /*!< CSS Measurement Noise */
+    float sun_noise;                    /*!< Sun Sensor Measurement Noise */
+    float nadir_noise;                  /*!< Nadir Sensor Measurement Noise */
+    float mag_noise;                    /*!< Magnetometer Measurement Noise */
+    float star_noise;                   /*!< Star Tracker Measurement Noise */
+    uint8_t use_sun_est;                /*!< Use Sun Sensor in EKF */
+    uint8_t use_nadir_est;              /*!< Use Nadir Sensor in EKF */
+    uint8_t use_css_est;                /*!< Use CSS measurement in EKF */
+    uint8_t use_star_est;               /*!< Use Star Tracker measurement in 
+                                            EKF */
+    uint8_t nadir_terminator_check;     /*!< Nadir sensor terminator test */
+    uint8_t mag_mode;                   /*!< Magnetometer Mode */
+}__attribute__ ((__packed__))s_adcs_est_param;
+
+/**
+ * @brief ECI position of the sattlite
+ */
+typedef struct
+{
+    int16_t position_x;         /*!< ECI referenced X coordinate */
+    int16_t position_y;         /*!< ECI referenced Y coordinate */
+    int16_t position_z;         /*!< ECI referenced Z coordinate */
+}__attribute__ ((__packed__))s_adcs_eci_position;
+
+/**
+ * @brief ECI velocity of the Sattelite
+ */
+typedef struct
+{
+    int16_t velocity_x;             /*!< ECI referenced X velocity */
+    int16_t velocity_y;             /*!< ECI referenced Y velocity */
+    int16_t velocity_z;             /*!< ECI referenced Z velocity */
+}__attribute__ ((__packed__))s_adcs_eci_velocity;
+
+/**
+ * @brief Estimated angular rates
+ */
+typedef struct
+{
+    int16_t est_x_angular_rate;     /*!< Estimated X Angular Rate */
+    int16_t est_y_angular_rate;     /*!< Estimated Y Angular Rate */
+    int16_t est_z_angular_rate;     /*!< Estimated Z Angular Rate */
+}__attribute__ ((__packed__))s_adcs_est_rate;
+
+/**
+ * @brief Estimated quaternion
+ */
+typedef struct
+{
+    int16_t est_qutrn_1;            /*!< Star tracker estimated attitude Q1 */
+    int16_t est_qutrn_2;            /*!< Star tracker estimated attitude Q2 */
+    int16_t est_qutrn_3;            /*!< Star tracker estimated attitude Q3 */
+}__attribute__ ((__packed__))s_adcs_est_qutrn;
+
+/**
+ * @brief Estimation innovation vector
+ */
+typedef struct
+{
+    int16_t innovn_vec_x;       /*!< Innovation Vector X */
+    int16_t innovn_vec_y;       /*!< Innovation Vector Y */
+    int16_t innovn_vec_z;       /*!< Innovation Vector Z */
+}__attribute__ ((__packed__))s_adcs_est_innovn;
+
+/**
+ * @brief Estimation gyro measurement
+ */
+typedef struct
+{
+    int16_t est_gyro_x;         /*!< Estimated X-gyro Bias */
+    int16_t est_gyro_y;         /*!< Estimated Y-gyro Bias */
+    int16_t est_gyro_z;         /*!< Estimated Z-gyro Bias */
+}__attribute__ ((__packed__))s_adcs_est_gyro;
+
+/**
+ * @brief Quaternion error vector
+ */
+typedef struct
+{
+    int16_t qutr_error_q1;      /*!< Quaternion Error -Q1 */
+    int16_t qutr_error_q2;      /*!< Quaternion Error -Q2 */
+    int16_t qutr_error_q3;      /*!< Quaternion Error -Q3 */
+}__attribute__ ((__packed__))s_adcs_qutr_error;
+
+/**
+ * @brief Quaternion covariance
+ */
+typedef struct
+{
+    int16_t qutr_covr_q1;      /*!< Quaternion Covariance - Q1 RMS */
+    int16_t qutr_covr_q2;      /*!< Quaternion Covariance - Q2 RMS */
+    int16_t qutr_covr_q3;      /*!< Quaternion Covariance - Q3 RMS */
+}__attribute__ ((__packed__))s_adcs_qutr_covr;
+
+/**
+ * @brief Angular rate covariance
+ */
+typedef struct
+{
+    int16_t covr_ang_rate_x;    /*!< X Angular Rate Covariance */
+    int16_t covr_ang_rate_y;    /*!< Y Angular Rate Covariance */
+    int16_t covr_ang_rate_z;    /*!< Z Angular Rate Covariance */
+}__attribute__ ((__packed__))s_adcs_angl_rate_covr;
+
+/**
+ * @brief Magnetic filed vector measurement
+ */
+typedef struct
+{
+    int16_t mag_filed_x;        /*!< X axis magnetic field vector */
+    int16_t mag_filed_y;        /*!< Y axis magnetic field vector */
+    int16_t mag_filed_z;        /*!< Z axis magnetic field vector */
+}__attribute__ ((__packed__))s_adcs_mag_vector;
+
+/**
+ * @brief Sun Vector measurement
+ */
+typedef struct
+{
+    int16_t sun_x;              /*!< X axis Sun vector */
+    int16_t sun_y;              /*!< Y axis Sun vector */
+    int16_t sun_z;              /*!< Z axis Sun vector */
+}__attribute__ ((__packed__))s_adcs_sun_vector;
+
+/**
+ * @brief Nadir Vector measurement
+ */
+typedef struct
+{
+    int16_t nadir_x;              /*!< X axis Nadir vector */
+    int16_t nadir_y;              /*!< Y axis Nadir vector */
+    int16_t nadir_z;              /*!< Z axis Nadir vector */
+}__attribute__ ((__packed__))s_adcs_nadir_vector;
+
+/**
+ * @brief Current measurement
+ */
+typedef struct
+{
+    uint16_t current_3v3;        /*!< Current value measured in 3.3V */
+    uint16_t current_5v;         /*!< Current value measured in 5V */
+}__attribute__ ((__packed__))s_adcs_current;
+
+/**
+ * @brief Current measurement
+ */
+typedef struct
+{
+    int16_t mcu_temperature;            /*!< MCU temperature value */
+    int16_t mgmtr_temperature;          /*!< Magnetometer temperature value */
+    int16_t rate_sensor_temperature;    /*!< Rate sensor temperature value */
+}__attribute__ ((__packed__))s_adcs_temperature;
+
+/**
+ * @brief Rate sensor temeprature measurement
+ */
+typedef struct
+{
+    int16_t x_rate_temp;        /*!< X axis Rate sensor temeprature value */
+    int16_t y_rate_temp;        /*!< Y axis Rate sensor temeprature value */
+    int16_t z_rate_temp;        /*!< Z axis Rate sensor temeprature value */
+}__attribute__ ((__packed__))s_adcs_rate_temperature;
+
+/**
+ * @brief Sensors Current measurement
+ */
+typedef struct
+{
+    double nadir_current;       /*!< Nadir Sensor current measurement */
+    double fss_current;         /*!< Fine Sun Sensor current measurement */
+    double css_current;         /*!< Coarse Sun Sensor current measurement */
+}__attribute__ ((__packed__))s_adcs_sens_cur;
+
+/**
+ * @brief ADCS Current and Temperature
+ */
+typedef struct
+{
+    s_adcs_temperature adcs_temp;   /*!< ADCS Temperature */
+    s_adcs_current adcs_current;    /*!< ADCS Curreent */
+}__attribute__ ((__packed__))s_adcs_cur_temp;
+
+/**
+ * @brief Health Metrics Structure - Measured Fine Sun Sensor Vector
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    int16_t sun_x;              /*!< X-Axis Sun Vector */
+    int16_t sun_y;              /*!< Y-Axis Sun Vector */
+    int16_t sun_z;              /*!< Z-Axis Sun Vector */
+}__attribute__ ((__packed__))s_adcs_hm_fss_vec;
+
+/**
+ * @brief Health Metrics Structure - Estimated Angular Rates
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    int16_t est_rate_x;         /*!< Estimated X Angular Rate */
+    int16_t est_rate_y;         /*!< Estimated Y Angular Rate */
+    int16_t est_rate_z;         /*!< Estimated Z Angular Rate */
+}__attribute__ ((__packed__))s_adcs_hm_est_rates_sns;
+
+/**
+ * @brief Health Metrics Structure - ADCS Misc Current Measurement
+ */
+typedef struct
+{
+    uint8_t status;           /*!< Operation Status */
+    uint64_t time;            /*!< Epoch Time */
+    double cubestar_cur;      /*!< CubeStar Current Measurement */
+    double mgntqr_cur;        /*!< Magnetorquer Current Measurement */
+    double cubestar_mcu_temp; /*!< CubeStar MCU Temperature */
+}__attribute__ ((__packed__))s_adcs_hm_misc_cur;
+
+/**
+ * @brief Health Metrics Structure - ADCS Temperature
+ */
+typedef struct
+{
+    uint8_t status;         /*!< Operation Status */
+    uint64_t time;          /*!< Epoch Time */
+    int16_t mcu_temp;       /*!< MCU Temperature */
+    double mgntr_temp;      /*!< Magnetometer Temperature */
+    double re_mgntr_temp;   /*!< Redundant Magnetometer Temperature */
+}__attribute__ ((__packed__))s_adcs_hm_temp;
+
+/**
+ * @brief Health Metrics Structure - Estimated Rate Sensor Temperature
+ */
+typedef struct
+{
+    uint8_t status;         /*!< Operation Status */
+    uint64_t time;          /*!< Epoch Time */
+    int16_t x_rate_sns;     /*!< X Rate Sensor Temperature */
+    int16_t y_rate_sns;     /*!< Y Rate Sensor Temperature */
+    int16_t z_rate_sns;     /*!< Z Rate Sensor Temperature */
+}__attribute__ ((__packed__))s_adcs_hm_est_rate_sns_temp;
+
+
+/**
+ * @brief Health Metrics Structure - Current ADCS State
+ */
+typedef struct
+{
+    uint8_t status;                 /*!< Operation Status */
+    uint64_t time;                  /*!< Epoch Time */
+    uint8_t att_est_mode;           /*!< Attitude Estimation Mode */
+    uint8_t ctrl_mode;              /*!< Control Mode */
+    uint8_t run_mode : 2;           /*!< ADCS Run mode */
+    uint8_t asgp4_mode : 2;         /*!< ASGP4 Mode */
+    uint8_t ctrl_sig_en :1;         /*!< Cube Control Signal Enabled */
+    uint8_t ctrl_motor_en : 1;      /*!< Cube Control Motor Enabled */
+    uint8_t cubesense1_en : 1;      /*!< Cubesense1 Enabled */
+    uint8_t cubesense2_en : 1;      /*!< Cubesense2 Enabled */
+    uint8_t rw1_en : 1;             /*!< Cube Wheel 1 Enabled */
+    uint8_t rw2_en : 1;             /*!< Cube Wheel 2 Enabled */
+    uint8_t rw3_en : 1;             /*!< Cube Wheel 3 Enabled */
+    uint8_t star_en : 1;            /*!< Cube Star Enabled */
+    uint8_t gps_recv_en : 1;        /*!< GPS Receiver Enabled */
+    uint8_t gps_lna_pwr_en : 1;     /*!< GPS LNA Power Enabled */
+    uint8_t motor_driver_en : 1;    /*!< Motor Driver Enabled */
+    uint8_t sun_above_horizon : 1;  /*!< Sun is Above Local Horizon */
+    uint8_t cubesens1_comm_err : 1; /*!< Cubesense1 Communications Error */
+    uint8_t cubesens2_comm_err : 1; /*!< Cubesense2 Communications Error */
+    uint8_t ctrl_sig_comm_err : 1;  /*!< CubeControl Signal Communications
+                                       Error */
+    uint8_t ctrl_motor_comm_err : 1; /*!< CubeControl Motor Communications
+                                       Error */
+    uint8_t rw1_comm_err : 1;        /*!< Cube Wheel1 Communications Error */
+    uint8_t rw2_comm_err : 1;         /*!< Cube Wheel2 Communications Error */
+    uint8_t rw3_comm_err : 1;        /*!< Cube Wheel3 Communications Error */
+    uint8_t star_comm_err : 1;       /*!< Cube Star Communications Error */
+    uint8_t mgntr_range_err : 1;     /*!< Magnetometer Range Error */
+    uint8_t cam1_sram_ocur : 1;      /*!< Cam1 SRAM Overcurrent Detected */
+    uint8_t cam1_3v3_ocur : 1;        /*!< Cam1 3v3 Overcurrent Detected */
+    uint8_t cam1_sns_busy_err : 1;   /*!< Cam1 Sensor Busy Error */
+    uint8_t cam1_sns_err : 1;        /*!< Cam1 Sensor Detection Error */
+    uint8_t sun_sns_range_err : 1;   /*!< Sun Sensor Range Error */
+    uint8_t cam2_sram_ocur : 1;      /*!< Cam2 SRAM Overcurrent Detected */
+    uint8_t cam2_3v3_ocur : 1;       /*!< Cam2 3v3 Overcurrent Detected */
+    uint8_t cam2_sns_busy_err : 1;   /*!< Cam2 Sensor Busy Error */
+    uint8_t cam2_sns_err : 1;        /*!< Cam2 Sensor Detection Error */
+    uint8_t nadir_sns_range_err : 1; /*!< Nadir Sensor Range Error */
+    uint8_t rate_sns_range_err : 1;  /*!< Rate Sensor Range Error */
+    uint8_t rw_spd_range_err : 1;    /*!< Wheel Speed Range Error */
+    uint8_t css_err : 1;             /*!< Coarse Sun Sensor Error */
+    uint8_t star_trckr_match_err : 1;/*!< Star Tracker Match Error */
+    uint8_t star_trckr_ocur : 1;     /*!< Star Tracker Overcurrent Detected*/
+    uint8_t orbit_param_invalid : 1;   /*!< Orbit Parameters are Invalid */
+    uint8_t cfg_invalid : 1;           /*!< Configuration is Invalid */
+    uint8_t ctrl_mode_chg_not_alwd : 1;/*!< Control Mode Change is not
+                                            allowed */
+    uint8_t est_chg_not_alwd : 1;      /*!< Estimator Change is not allowed */
+    uint8_t cur_mgntr_mode : 2;        /*!<Current Magnetometer Sampling Mode*/
+    uint8_t magfield_model_err : 1;    /*!< Modelled and measured magnetic
+                                          field differs in size */
+    uint8_t node_reco_err : 1;         /*!< Node Recovery Error */
+    uint8_t cubesense1_runt_err : 1;   /*!< CubeSense1 Runtime Error */
+    uint8_t cubesense2_runt_err : 1;   /*!< CubeSense2 Runtime Error */
+    uint8_t cubectrl_sig_runt_err : 1; /*!< CubeControl Signal Runtime Error */
+    uint8_t cubectrl_m_runt_err : 1;   /*!< CubeControl Motor Runtime Error */
+    uint8_t rw1_runt_err : 1;          /*!< CubeWheel1 Runtime Error */
+    uint8_t rw2_runt_err : 1;          /*!< CubeWheel2 Runtime Error */
+    uint8_t rw3_runt_err : 1;          /*!< CubeWheel3 Runtime Error */
+    uint8_t star_runt_err : 1;         /*!< CubeStar Runtime Error */
+    uint8_t mgntr_err : 1;             /*!< Magnetometer Error */
+    uint8_t rate_sns_fail : 1;         /*!< Rate Sensor Failure */
+
+}__attribute__ ((__packed__))s_adcs_hm_crnt_state;
+
+// Health Metrics Id Enumeration
+typedef enum
+{
+    ADCS_HM_SESNOR_CURRENT,         ///< Sensor Current Consumption
+    ADCS_HM_CONS_CURRENT,           ///< Controller Current Consumption
+    ADCS_HM_RW_CURRENT,             ///< Reaction Wheel Current Measure
+    ADCS_HM_CSS_VECTOR,             ///< Coarse Sun Sensor Vector
+    ADCS_HM_EST_ATTITUDE_ANGLE,     ///< Estimated Attitude Angle
+    ADCS_HM_RAW_MAG_MEASURE,        ///< Raw Magnetometer Measurement
+    ADCS_HM_RAW_RATE_SENSOR_MEASURE,///< Raw Rate Sensor Sensor Measurement
+    ADCS_HM_RATE_SENSOR_MEASURE,    ///< Rate Sensor Measurement
+    ADCS_HM_FSS_VECTOR,             ///< Fine Sun Sensor Vector
+    ADCS_HM_EST_RATES,              ///< Estimated Angular rates
+    ADCS_HM_MISC_CURRENT,           ///< ADCS Misc Current Measurement
+    ADCS_HM_TEMPERATURE,            ///< ADCS Temperature
+    ADCS_HM_RATE_SENSOR_TEMPERATURE,///< Rate Sensor Temperature
+    ADCS_HM_CURRENT_STATE,          ///< Current ADCS State
+    ADCS_HM_MAX                     ///< Health metrics Maximum
+}e_adcs_health_metrics_id;
+
+/**
+ * @brief Health Metrics Structure - Sensors Current measurement
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    double nadir_3v3_current;   /*!< Nadir Sensor 3V3 current measurement */
+    double fss_3v3_current;     /*!< FSS 3V3 current measurement */
+    double nadir_sram_current;  /*!< Nadir Sensor SRAM current measurement */
+    double fss_sram_current;    /*!< FSS SRAM current measurement */
+}__attribute__ ((__packed__))s_adcs_hm_sen_cur;
+
+/**
+ * @brief Health Metrics Structure - Consumed Current measurement
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    double current_3v3;         /*!< Current value measured in 3.3V */
+    double current_5v;          /*!< Current value measured in 5V */
+    double current_vbat;        /*!< Vbat current value */
+}__attribute__ ((__packed__))s_adcs_hm_cons_cur;
+
+/**
+ * @brief Health Metrics Structure - Reaction wheel Current measurement
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    double rw1_current;         /*!< Reaction wheel current 1 */
+    double rw2_current;         /*!< Reaction wheel current 2 */
+    double rw3_current;         /*!< Reaction wheel current 3 */
+}__attribute__ ((__packed__))s_adcs_hm_rw_cur;
+
+/**
+ * @brief Health Metrics Structure - CSS Vector
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    int16_t sun_x;              /*!< X axis Sun vector */
+    int16_t sun_y;              /*!< Y axis Sun vector */
+    int16_t sun_z;              /*!< Z axis Sun vector */
+}__attribute__ ((__packed__))s_adcs_hm_css_vector;
+
+/**
+ * @brief Health Metrics Structure - Estimated Attitude Angles
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    double roll;                /*!< Estimated Roll Angle */
+    double pitch;               /*!< Estimated Pitch Angle */
+    double yaw;                 /*!< Estimated Yaw Angle */
+}__attribute__ ((__packed__))s_adcs_hm_est_att_angl;
+
+/**
+ * @brief Health Metrics Structure - Raw Magnetometer Measurement
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    int16_t mag_raw_x;          /*!< Raw magnetometer X measurement */
+    int16_t mag_raw_y;          /*!< Raw magnetometer Y measurement */
+    int16_t mag_raw_z;          /*!< Raw magnetometer Z measurement */
+}__attribute__ ((__packed__))s_adcs_hm_raw_mag_measure;
+
+/**
+ * @brief Health Metrics Structure - Raw Rate Sensor Measurement
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    int16_t raw_rate_x;         /*!< X axis raw rate sensor measurement */
+    int16_t raw_rate_y;         /*!< Y axis raw rate sensor measurement */
+    int16_t raw_rate_z;         /*!< Z axis raw rate sensor measurement */
+}__attribute__ ((__packed__))s_adcs_hm_raw_rates;
+
+/**
+ * @brief Health Metrics Structure - Measured Angular Rates
+ */
+typedef struct
+{
+    uint8_t status;             /*!< Operation Status */
+    uint64_t time;              /*!< Epoch Time */
+    double rate_x;              /*!< Measured X axis Rates */
+    double rate_y;              /*!< Measured Y axis Rates */
+    double rate_z;              /*!< Measured Z axis Rates */
+}__attribute__ ((__packed__))s_adcs_hm_meas_rates;
+
+/**
+ * @brief This function extract the telemetry data based on telemetry id.
+ */
+void unfied_tlm_data_extract(uint8_t *data,uint16_t pld_len,uint8_t id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ADCS_BSK_H_ */

+ 1168 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/adcs_common.h

@@ -0,0 +1,1168 @@
+/************************************************************************************
+ * This file was auto-generated by CIDEA                           .                *
+ * Please do not modify the contents of this file manually.                         *
+ ***********************************************************************************/
+
+#ifndef __COMMON2_H
+#define __COMMON2_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* @addtogroup CubeComponents
+* @{
+******************************************************************************/
+
+/***************************************************************************//**
+* @addtogroup CubeComputer4Common
+* @brief CubeComputer4 Commmon Interface API
+* @{
+******************************************************************************/
+
+/// CubeComputer4Common Telemetry enumeration
+typedef enum {
+    BlockChecksum = 246, ///< File upload Block CRC16 Checksum
+    BootIndexStatus = 130, ///< Current selected boot index and status of last boot
+    Cache = 131, ///< Cache enabled state
+    CommsStatus = 144, ///< Communication status - includes command and telemetry counters and error flags
+    DownloadBlockReady = 242, ///< Status about download block preparation
+    EdacErrors = 143, ///< EDAC Error Counters
+    ExtendedIdentification = 129, ///< Boot And Running Program Status
+    FileDownload = 241, ///< File Download buffer 20-byte packet
+    FileInfo = 243, ///< File Information
+    HoleMap1 = 247, ///< File Upload Hole Map 1
+    HoleMap2 = 248, ///< File Upload Hole Map 2
+    HoleMap3 = 249, ///< File Upload Hole Map 3
+    HoleMap4 = 250, ///< File Upload Hole Map 4
+    HoleMap5 = 251, ///< File Upload Hole Map 5
+    HoleMap6 = 252, ///< File Upload Hole Map 6
+    HoleMap7 = 253, ///< File Upload Hole Map 7
+    HoleMap8 = 254, ///< File Upload Hole Map 8
+    Identification = 128, ///< Identification information for this node
+    InitializeUploadComplete = 244, ///< Initialize Upload Complete
+    LastLogEvent = 141, ///< Last Logged Event (relative to pointer - adjusted via Advance and Reset TCs (3 & 4)
+    LatchupErrors = 142, ///< SRAM Latchup counters
+    SdProgress = 234, ///< SD card format or erase progress
+    SramScrubSettings = 134, ///< SRAM scrubbing size
+    TelecommandAcknowledge = 240, ///< Telemetry frame with acknowledge status of the previously sent command
+    UnixTime = 140, ///< Current Unix Time
+    UnixTimeSave = 145, ///< Configuration settings for Unix time flash memory persistence
+    UploadBlockComplete = 245, ///< Finalize Upload Block Complete
+} COMMON_Telemetry_t; 
+
+/// BootCause enumeration
+typedef enum {
+    BootCause_Unexpected = 0, ///< Unexpected reset
+    BootCause_TrxuvI2cError = 1, ///< Not Used
+    BootCause_CommsTimeout = 2, ///< Timeout due to lack of communications
+    BootCause_CommandedMcuReset = 3, ///< Software commanded MCU reset
+    BootCause_CommandedEpsReset = 4, ///< Not Used
+    BootCause_SramLatchup = 5, ///< Latchup detected in SRAM
+} COMMON_BootCause_t;
+
+/// BootProgramsList enumeration
+typedef enum {
+    BootProgramsList_RunInternalFlashProgram = 1, ///< Internal Flash Program
+    BootProgramsList_RunBootloader = 2, ///< Bootloader
+} COMMON_BootProgramsList_t;
+
+/// BootStatus enumeration
+typedef enum {
+    BootStatus_BootNew = 0, ///< New Selection
+    BootStatus_BootSuccess = 1, ///< Boot Success
+    BootStatus_BootTry1 = 2, ///< 1 Failed boot attempt
+    BootStatus_BootTry2 = 3, ///< 2 Failed boot attempts
+    BootStatus_BootFail = 4, ///< 3 Failed boot attempts
+} COMMON_BootStatus_t;
+
+/// FileType enumeration
+typedef enum {
+    FileType_TlmLog = 2, ///< Telemetry Log File
+    FileType_JpgImg = 3, ///< JPG Image File
+    FileType_BmpImg = 4, ///< BMP Image File
+    FileType_IndexFile = 15, ///< Index File
+} COMMON_FileType_t;
+
+/// FileUploadDestination enumeration
+typedef enum {
+    FileUploadDestination_UlEeprom = 2, ///< EEPROM
+    FileUploadDestination_UlFlash1 = 3, ///< Flash program 1
+    FileUploadDestination_UlFlash2 = 4, ///< Flash program 2
+    FileUploadDestination_UlFlash3 = 5, ///< Flash program 3
+    FileUploadDestination_UlFlash4 = 6, ///< Flash program 4
+    FileUploadDestination_UlFlash5 = 7, ///< Flash program 5
+    FileUploadDestination_UlFlash6 = 8, ///< Flash program 6
+    FileUploadDestination_UlFlash7 = 9, ///< Flash program 7
+    FileUploadDestination_UlSdUser1 = 10, ///< SD User file 1
+    FileUploadDestination_UlSdUser2 = 11, ///< SD User file 2
+    FileUploadDestination_UlSdUser3 = 12, ///< SD User file 3
+    FileUploadDestination_UlSdUser4 = 13, ///< SD User file 4
+    FileUploadDestination_UlSdUser5 = 14, ///< SD User file 5
+    FileUploadDestination_UlSdUser6 = 15, ///< SD User file 6
+    FileUploadDestination_UlSdUser7 = 16, ///< SD User file 7
+    FileUploadDestination_UlSdUser8 = 17, ///< SD User file 8
+} COMMON_FileUploadDestination_t;
+
+/// ResetCause enumeration
+typedef enum {
+    ResetCause_PowerOnReset = 0, ///< Power-On Reset
+    ResetCause_BrownOutRegulated = 1, ///< Brown-Out Detected on Regulated Power
+    ResetCause_BrownOutUnregulated = 2, ///< Brown-Out Detected on Unregulated Power
+    ResetCause_ExternalWatchdog = 3, ///< External Watchdog Reset
+    ResetCause_ExternalReset = 4, ///< External Reset
+    ResetCause_WatchdogReset = 5, ///< Watchdog Reset
+    ResetCause_LockupSystemReset = 6, ///< Lockup System Reset
+    ResetCause_LockupReset = 7, ///< Lockup Reset
+    ResetCause_SystemReqReset = 8, ///< System Request Reset
+    ResetCause_BackupBrownOut = 9, ///< Backup domain brown-out reset
+    ResetCause_BackupModeRst = 10, ///< Backup mode reset
+    ResetCause_BackupModeRST_BackupBrownOutVddRegulated = 11, ///< Backup Mode reset and Backup domain brown-out on VDD regulated
+    ResetCause_BackupModeRST_BackupBrownOutVddRegulated_BrownOutRegulated = 12, ///< Backup Mode reset and Backup domain brown-out on VDD regulated and brown out on regulated
+    ResetCause_BackupModeRST_WatchdogReset = 13, ///< Backup mode reset and Watchdog reset
+    ResetCause_BackupBrownOutBuvin_SystemReqReset = 14, ///< Backup Domain brown-out on BUVIN and System request reset.
+    ResetCause_Unknown = 15, ///< Unkown Reset Cause
+} COMMON_ResetCause_t;
+
+/// SramBank enumeration
+typedef enum {
+    SramBank_Sram1 = 1, ///< SRAM bank 1
+    SramBank_Sram2 = 2, ///< SRAM bank 2
+} COMMON_SramBank_t;
+
+/// TcErrorReason enumeration
+typedef enum {
+    TcErrorReason_NoError = 0, ///< No error
+    TcErrorReason_InvalidTc = 1, ///< Invalid telecommand ID
+    TcErrorReason_IncorrectLen = 2, ///< Incorrect TC parameter length
+    TcErrorReason_IncorrectParams = 3, ///< Incorrect TC parameter value
+    TcErrorReason_CrcError = 4, ///< CRC check failed
+} COMMON_TcErrorReason_t;
+
+/*******************************************************************************
+ *******************************   STRUCTS   ***********************************
+ ******************************************************************************/
+
+/**
+ * @brief NodeDef Information Structure
+ * @details Contains NodeDef-specific Information
+ */
+typedef struct  {
+    U8 nodeTypeId;
+    U8 interfaceVersion;
+} COMMON_NodeDefInfo_t;
+
+/**
+ * @brief Boot Index and Status message structure
+ * @details Current selected boot index and status of last boot
+ */
+typedef struct  {
+    COMMON_BootProgramsList_t programIndex;    /**< Program Index  */
+    COMMON_BootStatus_t bootStatus;            /**< Boot Status  */
+} COMMON_BootIndexStatus_t;
+
+/**
+ * @brief Communication Status message structure
+ * @details Communication status - includes command and telemetry counters and error flags
+ */
+typedef struct  {
+    U16 tcCounter;                /**< No. of telecommands received  */
+    U16 tlmCounter;               /**< No. of telemetry requests received  */
+    Boolean uartBufferOverrun;    /**< TC buffer was overrun while receiving a telecommand  */
+    Boolean uartProtocolError;    /**< UART protocol error occurred  */
+    Boolean uartMsgIncomplete;    /**< UART start-of-message identifier was received without a preceding end-of-message  */
+    Boolean i2CTelemetryError;    /**< Number of data clocked out was more than telemetry package  */
+    Boolean i2CBufferError;       /**< Telecommand sent exceeds buffer size  */
+    Boolean cANBufferError;       /**< Telecommand sent exceeds buffer size  */
+} COMMON_CommsStatus_t;
+
+/**
+ * @brief Download Block Ready message structure
+ * @details Status about download block preparation
+ */
+typedef struct  {
+    Boolean ready;             /**< Ready  */
+    Boolean parameterError;    /**< The combination of message length and hole map resulted in invalid array lengths  */
+    U16 checksum;              /**< Block CRC16 Checksum  */
+    U16 length;                /**< Block length  */
+} COMMON_DownloadBlockReady_t;
+
+/**
+ * @brief Initiate Download Burst message structure
+ * @details Initiate Download Burst
+ */
+typedef struct  {
+    U8 messageLength;         /**< Message Length  */
+    Boolean ignoreHoleMap;    /**< Ignore Hole Map  */
+} COMMON_DownloadBurst_t;
+
+/**
+ * @brief EDAC Error Counters message structure
+ * @details EDAC Error Counters
+ */
+typedef struct  {
+    U16 singleSRAMSEUs;    /**< The number of single SRAM upsets (per byte) detected  */
+    U16 doubleSRAMSEUs;    /**< The number of double SRAM upsets (per byte) detected  */
+    U16 multiSRAMSEUs;     /**< The number of multiple SRAM upsets (per byte) detected  */
+} COMMON_EdacErrors_t;
+
+/**
+ * @brief Erase File message structure
+ * @details Erase File
+ */
+typedef struct  {
+    COMMON_FileType_t fileType;    /**< File Type  */
+    U8 fileCtr;                    /**< File Counter  */
+    Boolean eraseAll;              /**< Erase All  */
+} COMMON_EraseFile_t;
+
+/**
+ * @brief Boot And Running Program Status message structure
+ * @details Boot And Running Program Status
+ */
+typedef struct  {
+    COMMON_ResetCause_t mcuResetCause;                /**< Cause of MCU reset  */
+    COMMON_BootCause_t bootCause;                     /**< Cause of last reboot  */
+    U16 bootCounter;                                  /**< Number of times CubeComputer has booted  */
+    COMMON_BootProgramsList_t runningProgramIndex;    /**< Location of program that is currently running  */
+    U8 firmwareMajorVersion;                          /**< Firmware version (Major)  */
+    U8 firmwareMinorVersion;                          /**< Firmware version (Minor)  */
+} COMMON_ExtendedIdentification_t;
+
+/**
+ * @brief File Download Buffer with File Contents message structure
+ * @details File Download buffer 20-byte packet
+ */
+typedef struct  {
+    U16 packetNo;        /**< Packet counter of this file download packet  */
+    U8 fileBytes[20];    /**< File 20-byte packet  */
+} COMMON_FileDownload_t;
+
+/**
+ * @brief File Information message structure
+ * @details File Information
+ */
+typedef struct  {
+    COMMON_FileType_t fileType;    /**< File Type  */
+    Boolean busyUpdating;          /**< Busy Updating  */
+    U8 fileCtr;                    /**< File Counter  */
+    U32 size;                      /**< File Size  */
+    U32 unixTime;                  /**< File Date and Time (in MS-DOS format)  (measurment unit is [s]) */
+    U16 checksum;                  /**< File CRC16 Checksum  */
+} COMMON_FileInfo_t;
+
+/**
+ * @brief File Upload Packet message structure
+ * @details File Upload Packet
+ */
+typedef struct  {
+    U16 packetNo;        /**< Packet Number  */
+    U8 fileBytes[20];    /**< File Bytes  */
+} COMMON_FileUpload_t;
+
+/**
+ * @brief Finalize Upload Block message structure
+ * @details Finalize Uploaded File Block
+ */
+typedef struct  {
+    COMMON_FileUploadDestination_t destination;    /**< Destination  */
+    U32 offset;                                    /**< Offset into file  */
+    U16 blockLen;                                  /**< Length of block   */
+} COMMON_FinalizeUploadBlock_t;
+
+/**
+ * @brief Identification message structure
+ * @details Identification information for this node
+ */
+typedef struct  {
+    U8 nodeType;                /**< Node type identifier.  */
+    U8 interfaceVersion;        /**< Interface version. This field should have a value of 1  */
+    U8 firmwareMajorVersion;    /**< Firmware version (Major)  */
+    U8 firmwareMinorVersion;    /**< Firmware version (Minor)  */
+    U16 runtimeSeconds;         /**< Number of seconds since processor start-up  */
+    U16 runtimeMilliseconds;    /**< Number of milliseconds (after the integer second) since processor start-up  */
+} COMMON_Identification_t;
+
+/**
+ * @brief Initiate File Upload message structure
+ * @details Initiate File Upload
+ */
+typedef struct  {
+    COMMON_FileUploadDestination_t destination;    /**< Destination  */
+    U8 blockSize;                                  /**< Block Size  */
+} COMMON_InitiateFileUpload_t;
+
+/**
+ * @brief Last Logged Event message structure
+ * @details Last Logged Event (relative to pointer - adjusted via Advance and Reset TCs (3 & 4)
+ */
+typedef struct  {
+    U32 unixTime;     /**< Time of Event  */
+    U8 eventId;       /**< Event ID  */
+    U8 eventParam;    /**< Event Parameter  */
+} COMMON_LastLogEvent_t;
+
+/**
+ * @brief SRAM Latchup counters message structure
+ * @details SRAM Latchup counters
+ */
+typedef struct  {
+    U16 sRAM1SELs;    /**< The number of SRAM1 latchups detected  */
+    U16 sRAM2SELs;    /**< The number of SRAM2 latchups detected  */
+} COMMON_LatchupErrors_t;
+
+/**
+ * @brief Load File Download Block message structure
+ * @details Fill download buffer with file contents
+ */
+typedef struct  {
+    COMMON_FileType_t fileType;    /**< File Type  */
+    U8 counter;                    /**< Counter  */
+    U32 offset;                    /**< Offset  */
+    U16 length;                    /**< Block Length  */
+} COMMON_LoadDownloadBlock_t;
+
+/**
+ * @brief SD card format/erase progress message structure
+ * @details SD card format or erase progress
+ */
+typedef struct  {
+    Boolean formatBusy;      /**< Busy formatting SD card  */
+    Boolean eraseAllBusy;    /**< Busy formatting erasing all SD files  */
+} COMMON_SdProgress_t;
+
+/**
+ * @brief Telecommand Acknowledge message structure
+ * @details Telemetry frame with acknowledge status of the previously sent command
+ */
+typedef struct  {
+    U8 lastTCID;                              /**< ID of last received TC  */
+    Boolean processedFlag;                    /**< Flag to indicate if the last TC has been processed.  */
+    COMMON_TcErrorReason_t tCerrorStatus ;    /**< Status of last processed telecommand  */
+    U8 tCParameterErrorIndex;                 /**< Index of incorrect TC parameter  */
+} COMMON_TelecommandAcknowledge_t;
+
+/**
+ * @brief Current Unix Time message structure
+ * @details Current Unix Time
+ */
+typedef struct  {
+    U32 time;        /**< Time in s since 01/01/1970, 00:00  (measurment unit is [s]) */
+    U16 milliSec;    /**< Current millisecond count  (measurment unit is [ms]) */
+} COMMON_UnixTime_t;
+
+/**
+ * @brief Unix Time Save to Flash message structure
+ * @details Configuration settings for Unix time flash memory persistence
+ */
+typedef struct  {
+    Boolean saveNow;         /**< Save current Unix time to flash memory  */
+    Boolean saveOnUpdate;    /**< Save Unix time to flash memory whenever there is a command to update the Unix time  */
+    Boolean savePeriodic;    /**< Save Unix time to flash memory periodically  */
+    U8 period;               /**< Interval at which to save Unix time to flash memory  (measurment unit is [s]) */
+} COMMON_UnixTimeSave_t;
+
+/**
+ * @brief Upload Block Complete message structure
+ * @details Finalize Upload Block Complete
+ */
+typedef struct  {
+    Boolean busy;     /**< Busy with block finalization  */
+    Boolean error;    /**< Error in block finalization  */
+} COMMON_UploadBlockComplete_t;
+
+
+/*******************************************************************************
+ *****************************   PROTOTYPES   **********************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+Return the expected length of a telemetry frame
+ *
+ * @param[in] tlm
+ *   Enumeration of specified telemetry request
+ * @return
+ *   Returns the length of the telemetry frame in bytes
+ ******************************************************************************/
+uint16_t COMMON_GetTlmLen(COMMON_Telemetry_t tlm);
+
+/***************************************************************************//**
+ * Decode a Block  Checksum telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] checksum
+ *   Pointer to a U16 in which the Checksum will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, checksum, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractBlockChecksumTlm(uint8_t* rxBuffer, U16* checksum);
+
+/***************************************************************************//**
+ * Decode a Boot Index and Status telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_BootIndexStatus_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractBootIndexStatusTlm(uint8_t* rxBuffer, COMMON_BootIndexStatus_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Cache enabled state telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] enabled
+ *   Pointer to a Boolean in which the Enabled state will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, enabled, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractCacheTlm(uint8_t* rxBuffer, Boolean* enabled);
+
+/***************************************************************************//**
+ * Decode a Communication Status telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_CommsStatus_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractCommsStatusTlm(uint8_t* rxBuffer, COMMON_CommsStatus_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Download Block Ready telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_DownloadBlockReady_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractDownloadBlockReadyTlm(uint8_t* rxBuffer, COMMON_DownloadBlockReady_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a EDAC Error Counters telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_EdacErrors_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractEdacErrorsTlm(uint8_t* rxBuffer, COMMON_EdacErrors_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Boot And Running Program Status telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_ExtendedIdentification_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractExtendedIdentificationTlm(uint8_t* rxBuffer, COMMON_ExtendedIdentification_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a File Download Buffer with File Contents telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_FileDownload_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractFileDownloadTlm(uint8_t* rxBuffer, COMMON_FileDownload_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a File Information telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_FileInfo_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractFileInfoTlm(uint8_t* rxBuffer, COMMON_FileInfo_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Hole Map 1 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap1Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 2 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap2Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 3 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap3Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 4 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap4Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 5 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap5Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 6 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap6Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 7 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap7Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Hole Map 8 telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] holeMap
+ *   Pointer to a byte array in which the Hole Map will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, holeMap, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractHoleMap8Tlm(uint8_t* rxBuffer, uint8_t* holeMap);
+
+/***************************************************************************//**
+ * Decode a Identification telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_Identification_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractIdentificationTlm(uint8_t* rxBuffer, COMMON_Identification_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Initialize Upload Complete telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] busy
+ *   Pointer to a Boolean in which the Busy will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, busy, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractInitializeUploadCompleteTlm(uint8_t* rxBuffer, Boolean* busy);
+
+/***************************************************************************//**
+ * Decode a Last Logged Event telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_LastLogEvent_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractLastLogEventTlm(uint8_t* rxBuffer, COMMON_LastLogEvent_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a SRAM Latchup counters telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_LatchupErrors_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractLatchupErrorsTlm(uint8_t* rxBuffer, COMMON_LatchupErrors_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a SD card format/erase progress telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_SdProgress_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractSdProgressTlm(uint8_t* rxBuffer, COMMON_SdProgress_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a SRAM Scrub Parameters telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] scrubSize
+ *   Pointer to a U16 in which the Scrub Size will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, scrubSize, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractSramScrubSettingsTlm(uint8_t* rxBuffer, U16* scrubSize);
+
+/***************************************************************************//**
+ * Decode a Telecommand Acknowledge telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_TelecommandAcknowledge_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractTelecommandAcknowledgeTlm(uint8_t* rxBuffer, COMMON_TelecommandAcknowledge_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Current Unix Time telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_UnixTime_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractUnixTimeTlm(uint8_t* rxBuffer, COMMON_UnixTime_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Unix Time Save to Flash telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_UnixTimeSave_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractUnixTimeSaveTlm(uint8_t* rxBuffer, COMMON_UnixTimeSave_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Upload Block Complete telemetry frame from the CubeComputer4 Commmon
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a COMMON_UploadBlockComplete_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t COMMON_ExtractUploadBlockCompleteTlm(uint8_t* rxBuffer, COMMON_UploadBlockComplete_t* returnVal);
+
+/***************************************************************************//**
+ * Send a Advance File List Read Pointer command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatAdvanceFileListPtrCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Advance Log Pointer command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatAdvanceLogPtrCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Cache enabled state command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] enabled
+ *   Enabled state
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatCacheCmd(uint8_t* tcBuffer, Boolean enabled);
+
+/***************************************************************************//**
+ * Send a Initiate Download Burst command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] messageLength
+ *   Message Length
+ * @param[in] ignoreHoleMap
+ *   Ignore Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatDownloadBurstCmd(uint8_t* tcBuffer, U8 messageLength, Boolean ignoreHoleMap);
+
+/***************************************************************************//**
+ * Send a Erase File command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] fileType
+ *   File Type
+ * @param[in] fileCtr
+ *   File Counter
+ * @param[in] eraseAll
+ *   Erase All
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, fileType, was not a valid COMMON_FileType_t enumeration
+ ******************************************************************************/
+uint16_t COMMON_FormatEraseFileCmd(uint8_t* tcBuffer, COMMON_FileType_t fileType, U8 fileCtr, Boolean eraseAll);
+
+/***************************************************************************//**
+ * Send a File Upload Packet command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] packetNo
+ *   Packet Number
+ * @param[in] fileBytes
+ *   File Bytes
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatFileUploadCmd(uint8_t* tcBuffer, U16 packetNo, U8* fileBytes);
+
+/***************************************************************************//**
+ * Send a Finalize Upload Block command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] destination
+ *   Destination
+ * @param[in] offset
+ *   Offset into file
+ * @param[in] blockLen
+ *   Length of block 
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, destination, was not a valid COMMON_FileUploadDestination_t enumeration
+ ******************************************************************************/
+uint16_t COMMON_FormatFinalizeUploadBlockCmd(uint8_t* tcBuffer, COMMON_FileUploadDestination_t destination, U32 offset, U16 blockLen);
+
+/***************************************************************************//**
+ * Send a Format SD card command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] formatMagic
+ *   Magic number to prevent against accidental format. Has to be set to 90(0x5A)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatFormatSdCmd(uint8_t* tcBuffer, U8 formatMagic);
+
+/***************************************************************************//**
+ * Send a Hole Map 1 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap1Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 2 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap2Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 3 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap3Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 4 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap4Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 5 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap5Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 6 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap6Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 7 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap7Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Hole Map 8 command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] holeMap
+ *   Hole Map
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatHoleMap8Cmd(uint8_t* tcBuffer, U8* holeMap);
+
+/***************************************************************************//**
+ * Send a Initiate File Upload command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] destination
+ *   Destination
+ * @param[in] blockSize
+ *   Block Size
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, destination, was not a valid COMMON_FileUploadDestination_t enumeration
+ ******************************************************************************/
+uint16_t COMMON_FormatInitiateFileUploadCmd(uint8_t* tcBuffer, COMMON_FileUploadDestination_t destination, U8 blockSize);
+
+/***************************************************************************//**
+ * Send a Load File Download Block command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] fileType
+ *   File Type
+ * @param[in] counter
+ *   Counter
+ * @param[in] offset
+ *   Offset
+ * @param[in] length
+ *   Block Length
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, fileType, was not a valid COMMON_FileType_t enumeration
+ ******************************************************************************/
+uint16_t COMMON_FormatLoadDownloadBlockCmd(uint8_t* tcBuffer, COMMON_FileType_t fileType, U8 counter, U32 offset, U16 length);
+
+/***************************************************************************//**
+ * Send a Reset command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] magic
+ *   Magic number to make sure it is a valid reset command. Should equal 0x5A
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatResetCmd(uint8_t* tcBuffer, U8 magic);
+
+/***************************************************************************//**
+ * Send a Reset Boot Registers command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatResetBootRegistersCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Reset File List Read Pointer command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatResetFileListPtrCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Reset Log Pointer command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatResetLogPtrCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Reset Upload Block command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatResetUploadBlockCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a SRAM Scrub Parameters command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] scrubSize
+ *   Scrub Size
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatSramScrubSettingsCmd(uint8_t* tcBuffer, U16 scrubSize);
+
+/***************************************************************************//**
+ * Send a Current Unix Time command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] time
+ *   Time in s since 01/01/1970, 00:00
+ *   (in [s] units)
+ * @param[in] milliSec
+ *   Current millisecond count
+ *   (in [ms] units)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatUnixTimeCmd(uint8_t* tcBuffer, U32 time, U16 milliSec);
+
+/***************************************************************************//**
+ * Send a Unix Time Save to Flash command to the CubeComputer4 Commmon
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] saveNow
+ *   Save current Unix time to flash memory
+ * @param[in] saveOnUpdate
+ *   Save Unix time to flash memory whenever there is a command to update the Unix time
+ * @param[in] savePeriodic
+ *   Save Unix time to flash memory periodically
+ * @param[in] reserved
+ *   
+ * @param[in] period
+ *   Interval at which to save Unix time to flash memory
+ *   (in [s] units)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t COMMON_FormatUnixTimeSaveCmd(uint8_t* tcBuffer, Boolean saveNow, Boolean saveOnUpdate, Boolean savePeriodic, U8 period);
+
+
+void print_array(uint8_t* data, uint16_t size);
+void mfcc_adcs_tc_send(uint32_t tc_id, uint8_t *adcs_data, uint16_t tc_len);
+void health_metric_print(uint8_t hm_id, uint8_t hm_buffer_cnt, uint8_t *hm_data);
+#endif  // define __CUBECOMPUTER4COMMON2_H

+ 262 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/bootloader.h

@@ -0,0 +1,262 @@
+/************************************************************************************
+ * This file was auto-generated by CIDEA                           .                *
+ * Please do not modify the contents of this file manually.                         *
+ ***********************************************************************************/
+
+#ifndef __BOOTLOADER3_H
+#define __BOOTLOADER3_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* @addtogroup CubeComponents
+* @{
+******************************************************************************/
+
+/***************************************************************************//**
+* @addtogroup CubeComputer4FlashBootLoader
+* @brief Flash Bootloader Interface API
+* @{
+******************************************************************************/
+
+/// CubeComputer4FlashBootLoader Telemetry enumeration
+typedef enum {
+    CopyToIntFlashProgress = 233, ///< Progress of copy to internal flash operation
+    ProgramInfo = 232, ///< Program information including file size and CRC
+    State = 132, ///< Status flags for bootloader
+} BOOTLOADER_Telemetry_t; 
+
+/// BootSetProgramsList enumeration
+typedef enum {
+    BootSetProgramsList_RunInternalFlashProgram = 1, ///< Internal Flash Program
+} BOOTLOADER_BootSetProgramsList_t;
+
+/// IntFlashCopyState enumeration
+typedef enum {
+    IntFlashCopyState_WaitingDma = 0, ///< Waiting for DMA
+    IntFlashCopyState_WaitingMcuStatus = 1, ///< Waiting for MCU Status
+} BOOTLOADER_IntFlashCopyState_t;
+
+/// ProgramsList enumeration
+typedef enum {
+    ProgramsList_Bootloader = 0, ///< Bootloader
+    ProgramsList_InternalFlash = 1, ///< Internal Flash Program
+    ProgramsList_Eeprom = 2, ///< EEPROM
+    ProgramsList_ExtFlash1 = 3, ///< External Flash Program 1
+    ProgramsList_ExtFlash2 = 4, ///< External Flash Program 2
+    ProgramsList_ExtFlash3 = 5, ///< External Flash Program 3
+    ProgramsList_ExtFlash4 = 6, ///< External Flash Program 4
+    ProgramsList_ExtFlash5 = 7, ///< External Flash Program 5
+    ProgramsList_ExtFlash6 = 8, ///< External Flash Program 6
+    ProgramsList_ExtFlash7 = 9, ///< External Flash Program 7
+    ProgramsList_SdUser1 = 10, ///< SD User file 1
+    ProgramsList_SdUser2 = 11, ///< SD User file 2
+    ProgramsList_SdUser3 = 12, ///< SD User file 3
+    ProgramsList_SdUser4 = 13, ///< SD User file 4
+    ProgramsList_SdUser5 = 14, ///< SD User file 5
+    ProgramsList_SdUser6 = 15, ///< SD User file 6
+    ProgramsList_SdUser7 = 16, ///< SD User file 7
+    ProgramsList_SdUser8 = 17, ///< SD User file 8
+} BOOTLOADER_ProgramsList_t;
+
+/*******************************************************************************
+ *******************************   STRUCTS   ***********************************
+ ******************************************************************************/
+
+/**
+ * @brief NodeDef Information Structure
+ * @details Contains NodeDef-specific Information
+ */
+typedef struct  {
+    U8 nodeTypeId;
+    U8 interfaceVersion;
+} BOOTLOADER_NodeDefInfo_t;
+
+/**
+ * @brief Copy Program to Internal Flash message structure
+ * @details Copy Program to Internal Flash
+ */
+typedef struct  {
+    BOOTLOADER_ProgramsList_t srcIndex;    /**< Source Program Index  */
+    U8 bootloaderOverwrite;                /**< Bootloader overwrite flag. Set to 0x5A to overwrite the boot segment. USE WITH CAUTION!  */
+} BOOTLOADER_CopyToInternalFlash_t;
+
+/**
+ * @brief Copy To Internal Flash Progress message structure
+ * @details Progress of copy to internal flash operation
+ */
+typedef struct  {
+    Boolean busy;     /**< Busy  */
+    Boolean error;    /**< Error  */
+} BOOTLOADER_CopyToIntFlashProgress_t;
+
+/**
+ * @brief Program Information message structure
+ * @details Program information including file size and CRC
+ */
+typedef struct  {
+    BOOTLOADER_ProgramsList_t programIndex;    /**< Program Index  */
+    Boolean busy;                              /**< Busy reading  */
+    U32 fileSize;                              /**< File Size (bytes)  */
+    U16 crc16;                                 /**< CRC16 Checksum  */
+} BOOTLOADER_ProgramInfo_t;
+
+/**
+ * @brief Bootloader State message structure
+ * @details Status flags for bootloader
+ */
+typedef struct  {
+    U16 runtime;                     /**< Uptime  (measurment unit is [s]) */
+    Boolean sram1Enabled;            /**< SRAM1 is enabled  */
+    Boolean sram2Enabled;            /**< SRAM2 is enabled  */
+    Boolean sramLatchup;             /**< SRAM Latch-up Error occurred and could not be recovered  */
+    Boolean sramLatchupRecovered;    /**< SRAM Latch-up Occurred but recovered after power cycle  */
+    Boolean sdInitError;             /**< Flag to indicate that the SD card failed to initialise  */
+    Boolean sdReadError;             /**< Flag to indicate that a read operation from the SD card failed  */
+    Boolean sdWriteError;            /**< Flag to indicate that a write operation to the SD card failed  */
+    Boolean extFlashError;           /**< External Flash Erase/write error occurred  */
+    Boolean intFlashError;           /**< Internal Flash Erase/write error occurred  */
+    Boolean eepromError;             /**< EEPROM Write error occurred  */
+    Boolean bootRegCorrupt;          /**< Boot Register contained invalid data  */
+    Boolean radioCommsError;         /**< Communications Error with Radio  */
+} BOOTLOADER_State_t;
+
+
+/*******************************************************************************
+ *****************************   PROTOTYPES   **********************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+Return the expected length of a telemetry frame
+ *
+ * @param[in] tlm
+ *   Enumeration of specified telemetry request
+ * @return
+ *   Returns the length of the telemetry frame in bytes
+ ******************************************************************************/
+uint16_t BOOTLOADER_GetTlmLen(BOOTLOADER_Telemetry_t tlm);
+
+/***************************************************************************//**
+ * Decode a Copy To Internal Flash Progress telemetry frame from the Flash Bootloader
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a BOOTLOADER_CopyToIntFlashProgress_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t BOOTLOADER_ExtractCopyToIntFlashProgressTlm(uint8_t* rxBuffer, BOOTLOADER_CopyToIntFlashProgress_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Program Information telemetry frame from the Flash Bootloader
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a BOOTLOADER_ProgramInfo_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t BOOTLOADER_ExtractProgramInfoTlm(uint8_t* rxBuffer, BOOTLOADER_ProgramInfo_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Bootloader State telemetry frame from the Flash Bootloader
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a BOOTLOADER_State_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t BOOTLOADER_ExtractStateTlm(uint8_t* rxBuffer, BOOTLOADER_State_t* returnVal);
+
+/***************************************************************************//**
+ * Send a Set Boot Index command to the Flash Bootloader
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] programIndex
+ *   Program Index
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, programIndex, was not a valid BOOTLOADER_BootSetProgramsList_t enumeration
+ ******************************************************************************/
+uint16_t BOOTLOADER_FormatBootIndexCmd(uint8_t* tcBuffer, BOOTLOADER_BootSetProgramsList_t programIndex);
+
+/***************************************************************************//**
+ * Send a Clear Error Flags command to the Flash Bootloader
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t BOOTLOADER_FormatClearErrorsCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Copy Program to Internal Flash command to the Flash Bootloader
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] srcIndex
+ *   Source Program Index
+ * @param[in] bootloaderOverwrite
+ *   Bootloader overwrite flag. Set to 0x5A to overwrite the boot segment. USE WITH CAUTION!
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, srcIndex, was not a valid BOOTLOADER_ProgramsList_t enumeration
+ ******************************************************************************/
+uint16_t BOOTLOADER_FormatCopyToInternalFlashCmd(uint8_t* tcBuffer, BOOTLOADER_ProgramsList_t srcIndex, U8 bootloaderOverwrite);
+
+/***************************************************************************//**
+ * Send a Read Program Information command to the Flash Bootloader
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] programIndex
+ *   Program Index
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, programIndex, was not a valid BOOTLOADER_ProgramsList_t enumeration
+ ******************************************************************************/
+uint16_t BOOTLOADER_FormatReadProgramInfoCmd(uint8_t* tcBuffer, BOOTLOADER_ProgramsList_t programIndex);
+
+/***************************************************************************//**
+ * Send a Run Selected Program command to the Flash Bootloader
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t BOOTLOADER_FormatRunSelectedProgramCmd(uint8_t* tcBuffer);
+
+
+#endif  // define __CUBECOMPUTER4FLASHBOOTLOADER3_H

+ 4568 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/cubeacp.h

@@ -0,0 +1,4568 @@
+/************************************************************************************
+ * This file was auto-generated by CIDEA                           .                *
+ * Please do not modify the contents of this file manually.                         *
+ ***********************************************************************************/
+
+#ifndef __CUBEACP7_H
+#define __CUBEACP7_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* @addtogroup CubeComponents
+* @{
+******************************************************************************/
+
+/***************************************************************************//**
+* @addtogroup CubeComputer4ControlProgram
+* @brief CubeACP Interface API
+* @{
+******************************************************************************/
+
+/// CubeComputer4ControlProgram Telemetry enumeration
+typedef enum {
+    AcpLoopState = 220, ///< Returns information about the ACP loop
+    ActuatorCmd = 192, ///< Actuator commands
+    AdcsConfig = 206, ///< Current configuration
+    AdcsExecTimes = 196, ///< Returns information about execution times of ACP functions
+    AdcsMeasure = 191, ///< Calibrated sensor measurements
+    AdcsMiscCurrents = 198, ///< CubeStar and Torquer current and temperature measurements
+    AdcsPower = 197, ///< Control power to selected components
+    AdcsPowerMeasure = 195, ///< Power and temperature measurements
+    AdcsState = 190, ///< Current ADCS state
+    AdcsSystemConfig = 225, ///< Current hard-coded system configuration
+    AdcsTemperatures1 = 174, ///< Magnetometer + MCU temperature measurements
+    AdcsTemperatures2 = 175, ///< Rate sensor temperatures
+    Asgp4KepTle = 228, ///< ASGP4 TLEs generated
+    ASgp4Params = 227, ///< Settings for GPS augmented SGP4
+    CmdAttitude = 199, ///< Commanded attitude angles
+    CmdTrackingTarget = 200, ///< Target reference for tracking control mode
+    CoarseSunVec = 152, ///< Measured coarse sun vector
+    ConversionProgress = 133, ///< Conversion progress
+    CssConfig = 139, ///< Photodiode pointing directions and scale factors
+    CubeACPState = 135, ///< Contains flags regarding the state of the ACP
+    CubeControlCurrents = 172, ///< CubeControl current measurements
+    CubeSense1Currents = 171, ///< CubeSense1 current measurements
+    CubeSense2Currents = 232, ///< CubeSense2 current measurements
+    CubeSenseConfig = 203, ///< CubeSense configuration parameters
+    CurrentAdcsState = 132, ///< Current state of the Attitude Control Processor - frame 1
+    CurrentAdcsState2 = 224, ///< Current state of the Attitude Control Processor - frame 2
+    DetumbleParams = 208, ///< Set controller gains and reference values for Detumbling control mode
+    EstimAttitude = 146, ///< Estimated attitude angles
+    EstimData = 193, ///< Estimation meta-data
+    EstimGyroBias = 161, ///< Estimated rate sensor bias
+    EstimParams = 223, ///< Estimation noise covariance and sensor mask
+    EstimQuaternion = 218, ///< Estimated quaternion set
+    EstimRates = 147, ///< Estimated angular rates relative to orbit reference frame
+    FineEstimRates = 201, ///< High resolution estimated angular rates relative to orbit reference frame
+    FineSunVec = 153, ///< Measured fine sun vector
+    GyroConfig = 138, ///< Set rate gyro configuration parameters
+    ImageSaveStatus = 233, ///< Status of Image Capture and Save Operation
+    InertialPointReference = 238, ///< Reference unit vector for inertial pointing control mode
+    InnovationVec = 162, ///< Estimation innovation vector
+    LogSdConfig1 = 235, ///< Log selection and period for LOG1
+    LogSdConfig2 = 236, ///< Log selection and period for LOG2
+    LogUartConfig = 237, ///< Log selection and period for UART (unsolicited TLM)
+    MagConfig = 204, ///< Magnetometer configuration parameters
+    MagField = 151, ///< Measured magnetic field vector
+    MagRaw2 = 215, ///< Secondary Magnetometer raw measurements
+    MagtorqConfig = 136, ///< Set magnetorquer configuration parameters
+    MagTorquerCmd = 157, ///< Magnetorquer commands
+    ModelMagVec = 159, ///< IGRF modelled magnetic field vector (orbit frame referenced)
+    ModelSunVec = 160, ///< Modelled sun vector (orbit frame referenced)
+    MoI = 222, ///< Satellite moment of inertia matrix
+    NadirVec = 154, ///< Measured nadir vector
+    OrbitParameters = 207, ///< SGP4 Orbit Parameters
+    PositionECEF = 219, ///< Satellite position in ECEF coordinates
+    PositionECI = 148, ///< Satellite position in ECI frame
+    PositionLLH = 150, ///< Satellite position in WGS-84 coordinate frame
+    QuaternionCovar = 164, ///< Quaternion covariance
+    QuaternionErrVec = 163, ///< Quaternion error vector
+    RateCovar = 165, ///< Angular rate covariance
+    RateSensor = 155, ///< Rate sensor measurements
+    RawCam1Sens = 167, ///< Cam1 sensor capture and detection result
+    RawCam2Sens = 166, ///< Cam2 sensor capture and detection result
+    RawCss1 = 168, ///< Raw CSS measurements 1 to 6
+    RawCss2 = 169, ///< Raw CSS measurements 7 to 10
+    RawGPS = 210, ///< Raw GPS measurements
+    RawGpsStatus = 176, ///< Raw GPS status
+    RawGpsTime = 177, ///< Raw GPS time
+    RawGpsX = 178, ///< Raw GPS X position and velocity (ECI referenced)
+    RawGpsY = 179, ///< Raw GPS Y position and velocity (ECI referenced)
+    RawGpsZ = 180, ///< Raw GPS Z position and velocity (ECI referenced)
+    RawMagnetometer = 170, ///< Raw magnetometer measurements
+    RawRate = 216, ///< Raw rate sensor measurements
+    RawSensor = 194, ///< Raw sensor measurements
+    RawStarTracker = 211, ///< Raw Star Tracker Measurement
+    RedMagConfig = 205, ///< Redundant magnetometer configuration parameters
+    RWheelParams = 217, ///< Set controller gains and reference value for reaction wheel control mode
+    SpeedCmd = 158, ///< Wheel speed commands
+    Star1Body = 181, ///< Star 1 Body Vector
+    Star1Orbit = 184, ///< Star 1 Orbit Vector
+    Star1Raw = 212, ///< Catalogue index and detected coordinates for star 1
+    Star2Body = 182, ///< Star 2 Body Vector
+    Star2Orbit = 185, ///< Star 2 Orbit Vector
+    Star2Raw = 213, ///< Catalogue index and detected coordinates for star 2
+    Star3Body = 183, ///< Star 3 Body Vector
+    Star3Orbit = 186, ///< Star 3 Orbit Vector
+    Star3Raw = 214, ///< Catalogue index and detected coordinates for star 3
+    StarConfig = 202, ///< Set configurations of CubeStar
+    StarEstimQ = 230, ///< Attitude quaternion estimated by CubeStar
+    StarEstimRate = 229, ///< Angular rates estimated by CubeStar
+    StarMagnitude = 187, ///< Instrument magnitude of identified stars
+    StarPerformance1 = 188, ///< Performance parameters of star measurement
+    StarPerformance2 = 231, ///< Performance parameters of star measurement
+    StarTiming = 189, ///< Timing information of star measurement
+    TrackingParams = 221, ///< Set controller gains for tracking control mode
+    UserConEstParams = 226, ///< Settings for user-coded estimation and control modes
+    VelocityECI = 149, ///< Satellite velocity in ECI frame
+    WheelConfig = 137, ///< Set  wheel configuration parameters
+    WheelCurrents = 173, ///< XYZ Wheel current measurement
+    WheelSpeed = 156, ///< Wheel speed measurement
+    YWheelParams = 209, ///< Set controller gains and reference value for Y-wheel control mode
+} CUBEACP_Telemetry_t; 
+
+/// AcpProgramType enumeration
+typedef enum {
+    AcpProgramType_Acp3Axis = 0, ///< 3-Axis ACP
+    AcpProgramType_AcpYMom = 1, ///< Y-Momentum ACP
+} CUBEACP_AcpProgramType_t;
+
+/// AdcsRunMode enumeration
+typedef enum {
+    AdcsRunMode_AdcsOff = 0, ///< ADCS loop is inactive
+    AdcsRunMode_AdcsEnabled = 1, ///< ADCS 1Hz loop is active
+    AdcsRunMode_AdcsTriggered = 2, ///< ADCS will execute control loop only when triggered
+    AdcsRunMode_AdcsSimulation = 3, ///< ADCS is in simulation mode
+} CUBEACP_AdcsRunMode_t;
+
+/// Asgp4Error enumeration
+typedef enum {
+    Asgp4Error_Asgp4None = 0, ///< No error
+    Asgp4Error_Asgp4UnixTime = 1, ///< Error due to time
+    Asgp4Error_Asgp4LargePositionError = 2, ///< Error due to position error exceeding threshold
+    Asgp4Error_Asgp4Overflow = 3, ///< Error overflow
+} CUBEACP_Asgp4Error_t;
+
+/// Asgp4ModeSelect enumeration
+typedef enum {
+    Asgp4ModeSelect_Asgp4Off = 0, ///< ASGP4 is inactive
+    Asgp4ModeSelect_Asgp4Trigger = 1, ///< ASGP4 is active but waiting for trigger TC
+    Asgp4ModeSelect_Asgp4Background = 2, ///< ASGP4 runs asynchronously with GPS data received, TLEs updated internal to asgp4 module but not used
+    Asgp4ModeSelect_Asgp4Augment = 3, ///< ASGP4 runs in background but when processing of data is complete, TLEs used by orbit model is updated with asgp4 estimated TLEs
+} CUBEACP_Asgp4ModeSelect_t;
+
+/// AsgpFilter enumeration
+typedef enum {
+    AsgpFilter_Asgp4Lpf = 0, ///< Use LPF
+    AsgpFilter_Asgp4Average = 1, ///< Use averaging filter
+} CUBEACP_AsgpFilter_t;
+
+/// AxisSelect enumeration
+typedef enum {
+    AxisSelect_PosX = 0, ///< Positive X
+    AxisSelect_NegX = 1, ///< Negative X
+    AxisSelect_PosY = 2, ///< Positive Y
+    AxisSelect_NegY = 3, ///< Negative Y
+    AxisSelect_PosZ = 4, ///< Positive Z
+    AxisSelect_NegZ = 5, ///< Negative Z
+    AxisSelect_NotUsed = 6, ///< Not Used
+    AxisSelect_PosXPosY45deg = 7, ///< Positive X/Y 45 degree
+} CUBEACP_AxisSelect_t;
+
+/// CamSelect enumeration
+typedef enum {
+    CamSelect_CamCam1 = 0, ///< Cam1 camera
+    CamSelect_CamCam2 = 1, ///< Cam2 camera
+    CamSelect_CamStar = 2, ///< Star camera
+} CUBEACP_CamSelect_t;
+
+/// CaptureResult enumeration
+typedef enum {
+    CaptureResult_CaptureStartup = 0, ///< Start-up
+    CaptureResult_CapturePending = 1, ///< Capture pending
+    CaptureResult_CaptureSuccess = 2, ///< Successfully captured
+    CaptureResult_CaptureSuccessShift = 3, ///< Successfully captured on other SRAM (only applicable to CubeSense V2 hardware)
+    CaptureResult_CaptureTimeout = 4, ///< Camera timeout
+    CaptureResult_CaptureSRAMErr = 5, ///< SRAM overcurrent
+} CUBEACP_CaptureResult_t;
+
+/// ConModeSelect enumeration
+typedef enum {
+    ConModeSelect_ConNone = 0, ///< No control
+    ConModeSelect_ConBdot = 1, ///< Detumbling control
+    ConModeSelect_ConYspin = 2, ///< Y-Thomson spin
+    ConModeSelect_ConYwheelInit = 3, ///< Y-Wheel momentum stabilized - Initial Pitch Acquisition
+    ConModeSelect_ConYwheel = 4, ///< Y-Wheel momentum stabilized - Steady State
+    ConModeSelect_ConXYZwheel = 5, ///< XYZ-Wheel control
+    ConModeSelect_ConRWSunTrack = 6, ///< Rwheel sun tracking control
+    ConModeSelect_ConRWTargetTrack = 7, ///< Rwheel target tracking control
+    ConModeSelect_ConVeryFastDetumbling = 8, ///< 10Hz Detumbling control within CubeControl
+    ConModeSelect_ConFastDetumbling = 9, ///< Fast Detumbling control
+    ConModeSelect_ConSpecial1 = 10, ///< User defined, or custom control mode 1
+    ConModeSelect_ConSpecial2 = 11, ///< User defined, or custom control mode 2
+    ConModeSelect_ConStopRW = 12, ///< Stop all R-wheels
+    ConModeSelect_ConUser = 13, ///< User coded control mode
+    ConModeSelect_ConRWSunRollYawSteer = 14, ///< Yaw-only or roll-only sun tracking mode.
+    ConModeSelect_ConRWTargetYawSteer = 15, ///< Yaw-only wheel control to align selected facet to ground target
+} CUBEACP_ConModeSelect_t;
+
+/// CsCamType enumeration
+typedef enum {
+    CsCamType_CamTypeSun = 0, ///< Sun Sensor
+    CsCamType_CamTypeNadir = 1, ///< Nadir Sensor
+} CUBEACP_CsCamType_t;
+
+/// DetectResult enumeration
+typedef enum {
+    DetectResult_DetectStartup = 0, ///< Start-up
+    DetectResult_DetectNoDetect = 1, ///< No detection scheduled
+    DetectResult_DetectPending = 2, ///< Detection pending
+    DetectResult_DetectTooManyEdges = 3, ///< Nadir error - too many detected edges
+    DetectResult_DetectTooFewEdges = 4, ///< Nadir error - not enough edges detected
+    DetectResult_DetectBadFit = 5, ///< Nadir error - bad fit
+    DetectResult_DetectSunNotFound = 6, ///< Sun error - sun not found
+    DetectResult_DetectSuccess = 7, ///< Successful detection
+} CUBEACP_DetectResult_t;
+
+/// EstimModeSelect enumeration
+typedef enum {
+    EstimModeSelect_EstNone = 0, ///< No attitude estimation
+    EstimModeSelect_EstMemsRate = 1, ///< MEMS rate sensing
+    EstimModeSelect_EstMagRkf = 2, ///< Magnetometer rate filter
+    EstimModeSelect_EstPitchRkf = 3, ///< Magnetometer rate filter with pitch estimation
+    EstimModeSelect_EstTriad = 4, ///< Magnetometer and Fine-sun TRIAD algorithm
+    EstimModeSelect_EstFullEkf = 5, ///< Full-state EKF
+    EstimModeSelect_EstGyroEkf = 6, ///< MEMS gyro EKF
+    EstimModeSelect_EstUser = 7, ///< User coded estimation mode
+} CUBEACP_EstimModeSelect_t;
+
+/// ExecutionWaypoints enumeration
+typedef enum {
+    ExecutionWaypoints_Init = 0, ///< Busy with initialization
+    ExecutionWaypoints_Idle = 1, ///< Idle
+    ExecutionWaypoints_SensorActuatorComms = 2, ///< Sensor/Actuator Communications
+    ExecutionWaypoints_AdcsUpdate = 3, ///< ADCS Estimation & Control Update
+    ExecutionWaypoints_PeripheralPowerSet = 4, ///< Perhipheral Power commands (over I2C)
+    ExecutionWaypoints_SampleTemperature = 5, ///< CPU Temperature Sampling
+    ExecutionWaypoints_ImageDownload = 6, ///< Image Download
+    ExecutionWaypoints_ImageCompression = 7, ///< Image Compression
+    ExecutionWaypoints_ImageSaveToSd = 8, ///< Saving Image to SD Card
+    ExecutionWaypoints_Logging = 9, ///< Logging
+    ExecutionWaypoints_LogCompression = 10, ///< Log File Compression
+    ExecutionWaypoints_LogSaveToSd = 11, ///< Saving Log to SD Card
+    ExecutionWaypoints_WritingToFlash = 12, ///< Writing to flash memory
+} CUBEACP_ExecutionWaypoints_t;
+
+/// GpioPort enumeration
+typedef enum {
+    GpioPort_PortA = 0, ///< Port A
+    GpioPort_PortB = 1, ///< Port B
+    GpioPort_PortC = 2, ///< Port C
+    GpioPort_PortD = 3, ///< Port D
+    GpioPort_PortE = 4, ///< Port E
+    GpioPort_PortF = 5, ///< Port F
+} CUBEACP_GpioPort_t;
+
+/// GpioPortPin enumeration
+typedef enum {
+    GpioPortPin_PortPin0 = 0, ///< Pin 0
+    GpioPortPin_PortPin1 = 1, ///< Pin 1
+    GpioPortPin_PortPin2 = 2, ///< Pin 2
+    GpioPortPin_PortPin3 = 3, ///< Pin 3
+    GpioPortPin_PortPin4 = 4, ///< Pin 4
+    GpioPortPin_PortPin5 = 5, ///< Pin 5
+    GpioPortPin_PortPin6 = 6, ///< Pin 6
+    GpioPortPin_PortPin7 = 7, ///< Pin 7
+    GpioPortPin_PortPin8 = 8, ///< Pin 8
+    GpioPortPin_PortPin9 = 9, ///< Pin 9
+    GpioPortPin_PortPin10 = 10, ///< Pin 10
+    GpioPortPin_PortPin11 = 11, ///< Pin 11
+    GpioPortPin_PortPin12 = 12, ///< Pin 12
+    GpioPortPin_PortPin13 = 13, ///< Pin 13
+    GpioPortPin_PortPin14 = 14, ///< Pin 14
+    GpioPortPin_PortPin15 = 15, ///< Pin 15
+} CUBEACP_GpioPortPin_t;
+
+/// GpsSelect enumeration
+typedef enum {
+    GpsSelect_GpsNone = 0, ///< No GPS support
+    GpsSelect_GpsNovatel = 1, ///< Novatel GPS
+    GpsSelect_GpsSkyfox = 2, ///< Skyfox GPS
+} CUBEACP_GpsSelect_t;
+
+/// GpsSolutionStatus enumeration
+typedef enum {
+    GpsSolutionStatus_SolutionComputed = 0, ///< Solution computed
+    GpsSolutionStatus_InsufficientObs = 1, ///< Insufficient observations
+    GpsSolutionStatus_NoConvergence = 2, ///< No convergence
+    GpsSolutionStatus_Singularity = 3, ///< Singularity at parameters matrix
+    GpsSolutionStatus_CovTrace = 4, ///< Covariance trace exceeds maximum
+    GpsSolutionStatus_ColdStart = 5, ///< Not yet converged from cold start
+    GpsSolutionStatus_VhLimit = 6, ///< Height or velocity limits exceeded
+    GpsSolutionStatus_Variance = 7, ///< Variance exceeds limits
+    GpsSolutionStatus_IntegrityWarning = 8, ///< Large residuals make position unreliable
+    GpsSolutionStatus_Pending = 9, ///< Calculating comparison to user provided
+    GpsSolutionStatus_InvalidFix = 10, ///< The fixed position is invalid
+    GpsSolutionStatus_Unauthorized = 11, ///< Position type is unauthorized
+} CUBEACP_GpsSolutionStatus_t;
+
+/// ImSaveStatus enumeration
+typedef enum {
+    ImSaveStatus_ImgSaveNoError = 0, ///< No Error
+    ImSaveStatus_CameraTimeout = 1, ///< Timeout waiting for sensor to become available
+    ImSaveStatus_DownloadTimeout = 2, ///< Timeout waiting for next frame to become ready
+    ImSaveStatus_DownloadChecksum = 3, ///< Checksum mismatch between downloaded frame and unit frame
+    ImSaveStatus_SdCardError = 4, ///< Error writing to SD card
+} CUBEACP_ImSaveStatus_t;
+
+/// ImSize enumeration
+typedef enum {
+    ImSize_Size0 = 0, ///< 1024 x 1024 pixels
+    ImSize_Size1 = 1, ///< 512 x 512 pixels
+    ImSize_Size2 = 2, ///< 256 x 256 pixels
+    ImSize_Size3 = 3, ///< 128 x 128 pixels
+    ImSize_Size4 = 4, ///< 64 x 64 pixels
+} CUBEACP_ImSize_t;
+
+/// JpgConvertResult enumeration
+typedef enum {
+    JpgConvertResult_NoConversion = 0, ///< Nothing Converted Yet
+    JpgConvertResult_ConvertOk = 1, ///< Success
+    JpgConvertResult_FileLoadError = 2, ///< File Load Error
+    JpgConvertResult_BusyConverting = 3, ///< Busy
+} CUBEACP_JpgConvertResult_t;
+
+/// MagModeVal enumeration
+typedef enum {
+    MagModeVal_SigMainMag = 0, ///< Main magnetometer, sampled through signal microcontroller
+    MagModeVal_SigRedMag = 1, ///< Redundant magnetometer, sampled through signal microcontroller
+    MagModeVal_MotorMainMag = 2, ///< Main magnetometer, sampled through motor microcontroller
+    MagModeVal_None = 3, ///< None
+} CUBEACP_MagModeVal_t;
+
+/// NadirResult enumeration
+typedef enum {
+    NadirResult_NadirNoError = 0, ///< No Error
+    NadirResult_NadirTimeout = 1, ///< Camera timeout
+    NadirResult_NadirOvercurrent = 4, ///< Nadir SRAM Overcurrent detected
+    NadirResult_NadirTooManyEdges = 10, ///< Too many edges
+    NadirResult_NadirNotEnoughEdges = 11, ///< Not enough edges
+    NadirResult_NadirMatrixErr = 12, ///< Matrix Inversion Error
+    NadirResult_NadirBadFit = 13, ///< Bad Horizon Fit
+    NadirResult_NadirNoDetect = 255, ///< No detection performed
+} CUBEACP_NadirResult_t;
+
+/// PowerSelect enumeration
+typedef enum {
+    PowerSelect_PowOff = 0, ///< Off
+    PowerSelect_PowOn = 1, ///< On
+    PowerSelect_PowNoChange = 2, ///< Power state kept the same
+} CUBEACP_PowerSelect_t;
+
+/// PowerSelectCubeSense enumeration
+typedef enum {
+    PowerSelectCubeSense_PowCsOff = 0, ///< Off
+    PowerSelectCubeSense_PowCsOn = 1, ///< On
+    PowerSelectCubeSense_PowCsNoChange = 2, ///< Power state kept the same
+    PowerSelectCubeSense_PowCsAuto = 3, ///< Power state automatically managed
+} CUBEACP_PowerSelectCubeSense_t;
+
+/// SdLogSelect enumeration
+typedef enum {
+    SdLogSelect_SdLogPrimary = 0, ///< Use Primary (on-board) SD card for log file
+    SdLogSelect_SdLogSecondary = 1, ///< Use Secondary SD card for log file
+} CUBEACP_SdLogSelect_t;
+
+/// SpecialConSelect enumeration
+typedef enum {
+    SpecialConSelect_SpecConNone = 0, ///< None
+    SpecialConSelect_SpecConZSunPoint = 1, ///< Z-axis Sun pointing
+    SpecialConSelect_SpecConGeoTracking = 2, ///< GEO Tracking
+    SpecialConSelect_SpecConECITracking = 3, ///< Inertial pointing
+    SpecialConSelect_SpecConYSunPoint = 4, ///< Y-axis Sun pointing
+} CUBEACP_SpecialConSelect_t;
+
+/// StarIDModeVal enumeration
+typedef enum {
+    StarIDModeVal_Tracking = 0, ///< Tracking Mode
+    StarIDModeVal_Lost = 1, ///< Lost Mode
+} CUBEACP_StarIDModeVal_t;
+
+/// Stars enumeration
+typedef enum {
+    Stars_Zero = 0, ///< Zero
+    Stars_One = 1, ///< One
+    Stars_Two = 2, ///< Two
+} CUBEACP_Stars_t;
+
+/// SunResult enumeration
+typedef enum {
+    SunResult_SunNoError = 0, ///< No Error
+    SunResult_SunTimeout = 1, ///< Camera timeout
+    SunResult_SunOvercurrent = 4, ///< Sun SRAM Overcurrent detected
+    SunResult_SunNotFound = 20, ///< Sun not found
+    SunResult_SunNoDetect = 255, ///< No detection performed
+} CUBEACP_SunResult_t;
+
+/*******************************************************************************
+ *******************************   STRUCTS   ***********************************
+ ******************************************************************************/
+
+/**
+ * @brief NodeDef Information Structure
+ * @details Contains NodeDef-specific Information
+ */
+typedef struct  {
+    U8 nodeTypeId;
+    U8 interfaceVersion;
+} CUBEACP_NodeDefInfo_t;
+
+/**
+ * @brief ACP Execution State message structure
+ * @details Returns information about the ACP loop
+ */
+typedef struct  {
+    U16 timeSinceLoopStart;                                /**< Time since the start of the current loop iteration  (measurment unit is [ms]) */
+    CUBEACP_ExecutionWaypoints_t currentExecutionPoint;    /**< Indicates which part of the loop is currently executing  */
+} CUBEACP_AcpLoopState_t;
+
+/**
+ * @brief Actuator Commands message structure
+ * @details Actuator commands
+ */
+typedef struct  {
+    S16 torquerCmdX;    /**< X Magnetorquer Commanded on-time  (measurment unit is [10ms units]) */
+    S16 torquerCmdY;    /**< Y Magnetorquer Commanded on-time  (measurment unit is [10ms units]) */
+    S16 torquerCmdZ;    /**< Z Magnetorquer Commanded on-time  (measurment unit is [10ms units]) */
+    S16 speedCmdX;      /**< X Wheel Speed  (measurment unit is [rpm]) */
+    S16 speedCmdY;      /**< Y Wheel Speed  (measurment unit is [rpm]) */
+    S16 speedCmdZ;      /**< Z Wheel Speed  (measurment unit is [rpm]) */
+} CUBEACP_ActuatorCmd_t;
+
+/**
+ * @brief ADCS Configuration message structure
+ * @details Current configuration
+ */
+typedef struct  {
+    CUBEACP_AxisSelect_t magtorq1;               /**< Magnetorquer 1 Configuration  */
+    CUBEACP_AxisSelect_t magtorq2;               /**< Magnetorquer 2 Configuration  */
+    CUBEACP_AxisSelect_t magtorq3;               /**< Magnetorquer 3 Configuration  */
+    CUBEACP_AxisSelect_t rW1Conf;                /**< RW1 Configuration  */
+    CUBEACP_AxisSelect_t rW2Conf;                /**< RW2 Configuration  */
+    CUBEACP_AxisSelect_t rW3Conf;                /**< RW3 Configuration  */
+    CUBEACP_AxisSelect_t rW4Conf;                /**< RW4 or Momentum wheel Configuration  */
+    CUBEACP_AxisSelect_t gyro1Conf;              /**< Gyro1 Configuration  */
+    CUBEACP_AxisSelect_t gyro2Conf;              /**< Gyro2 Configuration  */
+    CUBEACP_AxisSelect_t gyro3Conf;              /**< Gyro3 Configuration  */
+    F64 xRateOffset;                             /**< X-Rate Sensor Offset  (measurment unit is [deg/s]) */
+    F64 yRateOffset;                             /**< Y-Rate Sensor Offset  (measurment unit is [deg/s]) */
+    F64 zRateOffset;                             /**< Z-Rate Sensor Offset  (measurment unit is [deg/s]) */
+    U8 rateSensorMult;                           /**< Multiplier of rate sensor measurement  */
+    CUBEACP_AxisSelect_t css1Conf;               /**< CSS1 Configuration  */
+    CUBEACP_AxisSelect_t css2Conf;               /**< CSS2 Configuration  */
+    CUBEACP_AxisSelect_t css3Conf;               /**< CSS3 Configuration  */
+    CUBEACP_AxisSelect_t css4Conf;               /**< CSS4 Configuration  */
+    CUBEACP_AxisSelect_t css5Conf;               /**< CSS5 Configuration  */
+    CUBEACP_AxisSelect_t css6Conf;               /**< CSS6 Configuration  */
+    CUBEACP_AxisSelect_t css7Conf;               /**< CSS7 Configuration  */
+    CUBEACP_AxisSelect_t css8Conf;               /**< CSS8 Configuration  */
+    CUBEACP_AxisSelect_t css9Conf;               /**< CSS9 Configuration  */
+    CUBEACP_AxisSelect_t css10Conf;              /**< CSS10 Configuration  */
+    F64 css1Scale;                               /**< CSS1 Relative Scaling Factor  */
+    F64 css2Scale;                               /**< CSS2 Relative Scaling Factor  */
+    F64 css3Scale;                               /**< CSS3 Relative Scaling Factor  */
+    F64 css4Scale;                               /**< CSS4 Relative Scaling Factor  */
+    F64 css5Scale;                               /**< CSS5 Relative Scaling Factor  */
+    F64 css6Scale;                               /**< CSS6 Relative Scaling Factor  */
+    F64 css7Scale;                               /**< CSS7 Relative Scaling Factor  */
+    F64 css8Scale;                               /**< CSS8 Relative Scaling Factor  */
+    F64 css9Scale;                               /**< CSS9 Relative Scaling Factor  */
+    F64 css10Scale;                              /**< CSS10 Relative Scaling Factor  */
+    U8 cssMinimum;                               /**< CSS Threshold  */
+    F64 cam1Angle1;                              /**< Cam1 Sensor Mounting Transform Alpha Angle  (measurment unit is [deg]) */
+    F64 cam1Angle2;                              /**< Cam1 Sensor Mounting Transform Beta Angle  (measurment unit is [deg]) */
+    F64 cam1Angle3;                              /**< Cam1 Sensor Mounting Transform Gamma Angle  (measurment unit is [deg]) */
+    U8 cam1Threshold;                            /**< Cam1 detection threshold  */
+    Boolean cam1AutoAdj;                         /**< 0 = disabled and 1 = enabled  */
+    U16 cam1Exposure;                            /**< exposure time register value  */
+    F64 cam1BoreX;                               /**< X Pixel location of Cam1 boresight  (measurment unit is [pixels]) */
+    F64 cam1BoreY;                               /**< Y Pixel location of Cam1 boresight  (measurment unit is [pixels]) */
+    F64 cam2Angle1;                              /**< Cam2 Sensor Mounting Transform Alpha Angle  (measurment unit is [deg]) */
+    F64 cam2Angle2;                              /**< Cam2 Sensor Mounting Transform Beta Angle  (measurment unit is [deg]) */
+    F64 cam2Angle3;                              /**< Cam2 Sensor Mounting Transform Gamma Angle  (measurment unit is [deg]) */
+    U8 cam2Threshold;                            /**< Cam2 detection threshold  */
+    Boolean cam2AutoAdj;                         /**< 0 = disabled and 1 = enabled  */
+    U16 cam2Exposure;                            /**< exposure time register value  */
+    F64 cam2BoreX;                               /**< X Pixel location of Cam2 boresight  (measurment unit is [pixels]) */
+    F64 cam2BoreY;                               /**< Y Pixel location of Cam2 boresight  (measurment unit is [pixels]) */
+    U8 nadirMaxDeviationPercentage;              /**< Percentage of measured angular radius as edge's maximum allowable deviation  */
+    U8 nadirMaxBadEdges;                         /**< Maximum amount of edges allowed outside maximum deviation (>50 to disable)  */
+    U8 nadirMaxRadius;                           /**< Maximum Radius  (measurment unit is [°]) */
+    U8 nadirMinRadius;                           /**< Minimum Radius  (measurment unit is [°]) */
+    U16 cam1MaskArea1Xmin;                       /**< Cam 1 Minimum X of Area 1  */
+    U16 cam1MaskArea1Xmax;                       /**< Cam 1 Maximum X of Area 1  */
+    U16 cam1MaskArea1Ymin;                       /**< Cam 1 Minimum Y of Area 1  */
+    U16 cam1MaskArea1Ymax;                       /**< Cam 1 Maximum Y of Area 1  */
+    U16 cam1MaskArea2Xmin;                       /**< Cam 1 Minimum X of Area 2  */
+    U16 cam1MaskArea2Xmax;                       /**< Cam 1 Maximum X of Area 2  */
+    U16 cam1MaskArea2Ymin;                       /**< Cam 1 Minimum Y of Area 2  */
+    U16 cam1MaskArea2Ymax;                       /**< Cam 1 Maximum Y of Area 2  */
+    U16 cam1MaskArea3Xmin;                       /**< Cam 1 Minimum X of Area 3  */
+    U16 cam1MaskArea3Xmax;                       /**< Cam 1 Maximum X of Area 3  */
+    U16 cam1MaskArea3Ymin;                       /**< Cam 1 Minimum Y of Area 3  */
+    U16 cam1MaskArea3Ymax;                       /**< Cam 1 Maximum Y of Area 3  */
+    U16 cam1MaskArea4Xmin;                       /**< Cam 1 Minimum X of Area 4  */
+    U16 cam1MaskArea4Xmax;                       /**< Cam 1 Maximum X of Area 4  */
+    U16 cam1MaskArea4Ymin;                       /**< Cam 1 Minimum Y of Area 4  */
+    U16 cam1MaskArea4Ymax;                       /**< Cam 1 Maximum Y of Area 4  */
+    U16 cam1MaskArea5Xmin;                       /**< Cam 1 Minimum X of Area 5  */
+    U16 cam1MaskArea5Xmax;                       /**< Cam 1 Maximum X of Area 5  */
+    U16 cam1MaskArea5Ymin;                       /**< Cam 1 Minimum Y of Area 5  */
+    U16 cam1MaskArea5Ymax;                       /**< Cam 1 Maximum Y of Area 5  */
+    U16 cam2MaskArea1Xmin;                       /**< Cam 2 Minimum X of Area 1  */
+    U16 cam2MaskArea1Xmax;                       /**< Cam 2 Maximum X of Area 1  */
+    U16 cam2MaskArea1Ymin;                       /**< Cam 2 Minimum Y of Area 1  */
+    U16 cam2MaskArea1Ymax;                       /**< Cam 2 Maximum Y of Area 1  */
+    U16 cam2MaskArea2Xmin;                       /**< Cam 2 Minimum X of Area 2  */
+    U16 cam2MaskArea2Xmax;                       /**< Cam 2 Maximum X of Area 2  */
+    U16 cam2MaskArea2Ymin;                       /**< Cam 2 Minimum Y of Area 2  */
+    U16 cam2MaskArea2Ymax;                       /**< Cam 2 Maximum Y of Area 2  */
+    U16 cam2MaskArea3Xmin;                       /**< Cam 2 Minimum X of Area 3  */
+    U16 cam2MaskArea3Xmax;                       /**< Cam 2 Maximum X of Area 3  */
+    U16 cam2MaskArea3Ymin;                       /**< Cam 2 Minimum Y of Area 3  */
+    U16 cam2MaskArea3Ymax;                       /**< Cam 2 Maximum Y of Area 3  */
+    U16 cam2MaskArea4Xmin;                       /**< Cam 2 Minimum X of Area 4  */
+    U16 cam2MaskArea4Xmax;                       /**< Cam 2 Maximum X of Area 4  */
+    U16 cam2MaskArea4Ymin;                       /**< Cam 2 Minimum Y of Area 4  */
+    U16 cam2MaskArea4Ymax;                       /**< Cam 2 Maximum Y of Area 4  */
+    U16 cam2MaskArea5Xmin;                       /**< Cam 2 Minimum X of Area 5  */
+    U16 cam2MaskArea5Xmax;                       /**< Cam 2 Maximum X of Area 5  */
+    U16 cam2MaskArea5Ymin;                       /**< Cam 2 Minimum Y of Area 5  */
+    U16 cam2MaskArea5Ymax;                       /**< Cam 2 Maximum Y of Area 5  */
+    F64 magmAngle1;                              /**< Magnetometer Mounting Transform Alpha Angle  (measurment unit is [deg]) */
+    F64 magmAngle2;                              /**< Magnetometer Mounting Transform Beta Angle  (measurment unit is [deg]) */
+    F64 magmAngle3;                              /**< Magnetometer Mounting Transform Gamma Angle  (measurment unit is [deg]) */
+    F64 magmOffset1;                             /**< Magnetometer Channel 1 Offset  */
+    F64 magmOffset2;                             /**< Magnetometer Channel 2 Offset  */
+    F64 magmOffset3;                             /**< Magnetometer Channel 3 Offset  */
+    F64 magmSens11;                              /**< Magnetometer Sensitivity Matrix S11  */
+    F64 magmSens22;                              /**< Magnetometer Sensitivity Matrix S22  */
+    F64 magmSens33;                              /**< Magnetometer Sensitivity Matrix S33  */
+    F64 magmSens12;                              /**< Magnetometer Sensitivity Matrix S12  */
+    F64 magmSens13;                              /**< Magnetometer Sensitivity Matrix S13  */
+    F64 magmSens21;                              /**< Magnetometer Sensitivity Matrix S21  */
+    F64 magmSens23;                              /**< Magnetometer Sensitivity Matrix S23  */
+    F64 magmSens31;                              /**< Magnetometer Sensitivity Matrix S31  */
+    F64 magmSens32;                              /**< Magnetometer Sensitivity Matrix S32  */
+    F64 mredAngle1;                              /**< Redundant Magnetometer Mounting Transform Alpha Angle  (measurment unit is [deg]) */
+    F64 mredAngle2;                              /**< Redundant Magnetometer Mounting Transform Beta Angle  (measurment unit is [deg]) */
+    F64 mredAngle3;                              /**< Redundant Magnetometer Mounting Transform Gamma Angle  (measurment unit is [deg]) */
+    F64 mredOffset1;                             /**< Redundant Magnetometer Channel 1 Offset  */
+    F64 mredOffset2;                             /**< Redundant Magnetometer Channel 2 Offset  */
+    F64 mredOffset3;                             /**< Redundant Magnetometer Channel 3 Offset  */
+    F64 mredSens11;                              /**< Redundant Magnetometer Sensitivity Matrix S11  */
+    F64 mredSens22;                              /**< Redundant Magnetometer Sensitivity Matrix S22  */
+    F64 mredSens33;                              /**< Redundant Magnetometer Sensitivity Matrix S33  */
+    F64 mredSens12;                              /**< Redundant Magnetometer Sensitivity Matrix S12  */
+    F64 mredSens13;                              /**< Redundant Magnetometer Sensitivity Matrix S13  */
+    F64 mredSens21;                              /**< Redundant Magnetometer Sensitivity Matrix S21  */
+    F64 mredSens23;                              /**< Redundant Magnetometer Sensitivity Matrix S23  */
+    F64 mredSens31;                              /**< Redundant Magnetometer Sensitivity Matrix S31  */
+    F64 mredSens32;                              /**< Redundant Magnetometer Sensitivity Matrix S32  */
+    F64 starAngle1;                              /**< StarTracker Mounting Transform Alpha Angle  (measurment unit is [deg]) */
+    F64 starAngle2;                              /**< StarTracker Mounting Transform Beta Angle  (measurment unit is [deg]) */
+    F64 starAngle3;                              /**< StarTracker Mounting Transform Gamma Angle  (measurment unit is [deg]) */
+    U16 starExposure;                            /**< exposure time register value  */
+    U16 starGain;                                /**< analog gain register value  */
+    U8 detectionThreshold;                       /**< StarTracker detection threshold  */
+    U8 starThreshold;                            /**< StarTracker star threshold  */
+    U8 maxStarMatched;                           /**< Maximum of stars that the star tracker will match  */
+    U16 starTimeoutTime;                         /**< Time allowed for detection  */
+    U8 maxStarPixel;                             /**< Maximum pixels in a star  */
+    U8 minStarPixel;                             /**< Minimum pixels in a star  */
+    F64 starErrorMargin;                         /**< % Error margin of the star identification  (measurment unit is [%]) */
+    U16 starDelayTime;                           /**< Delay Time  (measurment unit is [milliseconds]) */
+    F32 starCentX;                               /**< Pixel centroid X  (valid range is between -5000  and 5000 ) */
+    F32 starCentY;                               /**< Pixel centroid Y  (valid range is between -5000  and 5000 ) */
+    F32 starFocal;                               /**< Star Tracker Focal Length  (measurment unit is [mm]. valid range is between 5 mm and 7 mm) */
+    F32 starLensK1;                              /**< First radial distortion coefficient  (measurment unit is [gain]. valid range is between -1 gain and 1 gain) */
+    F32 starLensK2;                              /**< Second radial distortion coefficient  (measurment unit is [gain]. valid range is between -1 gain and 1 gain) */
+    F32 starLensP1;                              /**< First tangential distortion coefficient  (measurment unit is [gain]. valid range is between -1 gain and 1 gain) */
+    F32 starLensP2;                              /**< Second tangential distortion coefficients  (measurment unit is [gain]. valid range is between -1 gain and 1 gain) */
+    U8 starWindowWidth;                          /**< Window width  */
+    F64 starTrackingMargin;                      /**< Tracking Margin  */
+    F64 starValidationMargin;                    /**< Validation Margin  */
+    Boolean starModuleEnable;                    /**< Module Enable  */
+    Boolean starLocationPredictionEnable;        /**< LocationPredictionEnable  */
+    F64 starSearchWidth;                         /**< Search Width  */
+    F32 ks;                                      /**< Detumbling Spin Gain (Ks)  (valid range is between 0  and 10000 ) */
+    F32 kd;                                      /**< Detumbling Damping Gain (Kd)  (valid range is between 0  and 10000 ) */
+    F64 wy_ref;                                  /**< Reference spin rate (wy-ref). Must always be smaller than 0 for Y-spin  (measurment unit is [deg/s]. valid range is between -32000 deg/s and 32000 deg/s) */
+    F32 kdf;                                     /**< Fast BDot Detumbling Gain (Kdf)  (valid range is between 0  and 100 ) */
+    F32 kh;                                      /**< Y-Momentum Control Gain (Kh)  (valid range is between 0  and 10000 ) */
+    F32 kn;                                      /**< Y-momentum Nutation Damping Gain (Kn)  (valid range is between 0  and 10000 ) */
+    F32 kp1;                                     /**< Y-momentum Proportional Gain (Kp1)  (valid range is between 0  and 100 ) */
+    F32 kd1;                                     /**< Y-momentum Derivative Gain (Kd1)  (valid range is between 0  and 100 ) */
+    F32 h_ref;                                   /**< Reference Wheel Momentum (H-ref). Must always be smaller than 0  (measurment unit is [Nms]. valid range is between -10 Nms and 0 Nms) */
+    F32 kp2;                                     /**< RWheel Proportional Gain (Kp2)  (valid range is between 0  and 100 ) */
+    F32 kd2;                                     /**< RWheel Derivative Gain (Kd2)  (valid range is between 0  and 100 ) */
+    F32 h_bias;                                  /**< Y-Wheel Bias Momentum (H-bias)  (measurment unit is [Nms]. valid range is between -10 Nms and 10 Nms) */
+    CUBEACP_AxisSelect_t sunPointFacet;          /**< Satellite body axis that will align with sun vector  */
+    Boolean wheelErrorHandling;                  /**< Enable/disable automatic transition from wheel control modes to Y-Thomson mode in case of wheel error  */
+    F32 kp3;                                     /**< Tracking Proportional Gain (Kp3)  (valid range is between 0  and 100 ) */
+    F32 kd3;                                     /**< Tracking Derivative Gain (Kd3)  (valid range is between 0  and 100 ) */
+    F32 ki3;                                     /**< Tracking Integral Gain (Ki3)  (valid range is between 0  and 100 ) */
+    CUBEACP_AxisSelect_t targetTrackFacet;       /**< Satellite body axis that will point to target  */
+    F32 ixx;                                     /**< Moment Of Inertia - Ixx  (measurment unit is [kg.m^2]. valid range is between 0 kg.m^2 and 10 kg.m^2) */
+    F32 iyy;                                     /**< Moment Of Inertia - Iyy  (measurment unit is [kg.m^2]. valid range is between 0 kg.m^2 and 10 kg.m^2) */
+    F32 izz;                                     /**< Moment Of Inertia - Izz  (measurment unit is [kg.m^2]. valid range is between 0 kg.m^2 and 10 kg.m^2) */
+    F32 ixy;                                     /**< Product Of Inertia - Ixy  (measurment unit is [kg.m^2]. valid range is between -10 kg.m^2 and 10 kg.m^2) */
+    F32 ixz;                                     /**< Product Of Inertia - Ixz  (measurment unit is [kg.m^2]. valid range is between -10 kg.m^2 and 10 kg.m^2) */
+    F32 iyz;                                     /**< Product Of Inertia - Iyz  (measurment unit is [kg.m^2]. valid range is between -10 kg.m^2 and 10 kg.m^2) */
+    F32 magRateNoise;                            /**< Magnetometer Rate Filter System Noise  (valid range is between 0  and 100 ) */
+    F32 ekfSysNoise;                             /**< EKF System Noise  (valid range is between 0  and 100 ) */
+    F32 cssNoise;                                /**< CSS Measurement Noise  (valid range is between 0  and 100 ) */
+    F32 sunNoise;                                /**< Sun Sensor Measurement Noise  (valid range is between 0  and 100 ) */
+    F32 nadirNoise;                              /**< Nadir Sensor Measurement Noise  (valid range is between 0  and 100 ) */
+    F32 magNoise;                                /**< Magnetometer Measurement Noise  (valid range is between 0  and 100 ) */
+    F32 starNoise;                               /**< Star Tracker Measurement Noise  (valid range is between 0  and 100 ) */
+    Boolean useSunEst;                           /**< Use Sun Sensor measurement in EKF  */
+    Boolean useNadirEst;                         /**< Use Nadir Sensor measurement in EKF  */
+    Boolean useCssEst;                           /**< Use CSS measurement in EKF  */
+    Boolean useStarEst;                          /**< Use Star Tracker measurement in EKF  */
+    Boolean terminatorCheck;                     /**< Select to ignore Nadir sensor measurements when terminator is in FOV  */
+    Boolean autoRecoverMtm;                      /**< Select whether automatic switch to redundant magnetometer should occur in case of failure  */
+    CUBEACP_MagModeVal_t magMode;                /**< Mode describing which magnetometer is used for estimation and control  */
+    CUBEACP_MagModeVal_t magRawTlm2Selection;    /**< Select which magnetometer and sampling to use for 2nd raw magnetometer tlm frame  */
+    Boolean rateSensorErrorHandling;             /**< Enable/disable automatic transition from MEMS rate estimation mode to RKF in case of rate sensor error  */
+    Boolean wheelPowerOn30sDelay;                /**< Delay wheel communications for 30s after power-cycle  */
+    U8 cam1Cam2Period;                           /**< Cam1 and Cam2 sensor sampling period. Lower four bits are Cam1 period and upper four bits the Cam2 period. Setting period to zero for sensor will disable sampling of sensor.  (measurment unit is [s]) */
+    F64 aInclCoeff;                              /**< Inclination filter coefficient  */
+    F64 aRaanCoeff;                              /**< RAAN filter coefficient  */
+    F64 aEccCoeff;                               /**< Eccentricity filter coefficient  */
+    F64 aArgPerCoeff;                            /**< Argument of perigee filter coefficient  */
+    F64 aTimeCoeff;                              /**< Time filter coefficient  */
+    F64 aPosCoeff;                               /**< Position filter coefficient  */
+    F64 asgp4MaxPosError;                        /**< Maximum position error for asgp4 to continue working  */
+    CUBEACP_AsgpFilter_t asgp4Filter;            /**< The type of filter asgp4 is using  */
+    F64 asgp4Xp;                                 /**< Polar coefficient xp  */
+    F64 asgp4Yp;                                 /**< Polar coefficient yp  */
+    U8 asgp4GpsRollover;                         /**< GPS roll over number  */
+    F64 asgp4PosSdTh;                            /**< Maximum position standard deviation for asgp4 to operate  */
+    F64 asgp4VelSdTh;                            /**< Maximum velocity standard deviation for asgp4 to operate  */
+    U8 asgp4MinSat;                              /**< Minimum satellites for asgp4 to operate  */
+    F64 asgp4TimeGain;                           /**< Time offset compensation gain  */
+    F64 asgp4MaxLag;                             /**< Maximum lagged timestamp measurements to incorporate  */
+    U16 asgp4MinSamples;                         /**< Minimum samples to use for asgp4 process  */
+    U8 userConSettings[48];                      /**< Settings for user coded control mode(s)  */
+    U8 userEstSettings[48];                      /**< Settings for user coded estimation mode(s)  */
+} CUBEACP_AdcsConfig_t;
+
+/**
+ * @brief Adcs Execution Times message structure
+ * @details Returns information about execution times of ACP functions
+ */
+typedef struct  {
+    U16 timeAdcsUpdate;             /**< Time to perform complete ADCS Update function  (measurment unit is [ms]) */
+    U16 timeSensorActuatorComms;    /**< Time to perform Sensor/actuator communications  (measurment unit is [ms]) */
+    U16 timeSgp4;                   /**< Time to execute SGP4 propagator  (measurment unit is [ms]) */
+    U16 timeIgrf;                   /**< Time to execute IGRF computation  (measurment unit is [ms]) */
+} CUBEACP_AdcsExecTimes_t;
+
+/**
+ * @brief ADCS Measurements message structure
+ * @details Calibrated sensor measurements
+ */
+typedef struct  {
+    F64 magX;       /**< Magnetic Field X  (measurment unit is [uT]) */
+    F64 magY;       /**< Magnetic Field Y  (measurment unit is [uT]) */
+    F64 magZ;       /**< Magnetic Field Z  (measurment unit is [uT]) */
+    F64 cssX;       /**< Coarse Sun X  */
+    F64 cssY;       /**< Coarse Sun Y  */
+    F64 cssZ;       /**< Coarse Sun Z  */
+    F64 sunX;       /**< Sun X  */
+    F64 sunY;       /**< Sun Y  */
+    F64 sunZ;       /**< Sun Z  */
+    F64 nadirX;     /**< Nadir X  */
+    F64 nadirY;     /**< Nadir Y  */
+    F64 nadirZ;     /**< Nadir Z  */
+    F64 rateX;      /**< X Angular Rate  (measurment unit is [deg/s]) */
+    F64 rateY;      /**< Y Angular Rate  (measurment unit is [deg/s]) */
+    F64 rateZ;      /**< Z Angular Rate  (measurment unit is [deg/s]) */
+    S16 speedX;     /**< X Wheel Speed  (measurment unit is [rpm]) */
+    S16 speedY;     /**< Y Wheel Speed  (measurment unit is [rpm]) */
+    S16 speedZ;     /**< Z Wheel Speed  (measurment unit is [rpm]) */
+    F64 star1BX;    /**< Star1 body X-vector  */
+    F64 star1BY;    /**< Star1 body Y-vector  */
+    F64 star1BZ;    /**< Star1 body Z-vector  */
+    F64 star1OX;    /**< Star1 orbit X-vector  */
+    F64 star1OY;    /**< Star1 orbit Y-vector  */
+    F64 star1OZ;    /**< Star1 orbit Z-vector  */
+    F64 star2BX;    /**< Star2 body X-vector  */
+    F64 star2BY;    /**< Star2 body Y-vector  */
+    F64 star2BZ;    /**< Star2 body Z-vector  */
+    F64 star2OX;    /**< Star2 orbit X-vector  */
+    F64 star2OY;    /**< Star2 orbit Y-vector  */
+    F64 star2OZ;    /**< Star2 orbit Z-vector  */
+    F64 star3BX;    /**< Star3 body X-vector  */
+    F64 star3BY;    /**< Star3 body Y-vector  */
+    F64 star3BZ;    /**< Star3 body Z-vector  */
+    F64 star3OX;    /**< Star3 orbit X-vector  */
+    F64 star3OY;    /**< Star3 orbit Y-vector  */
+    F64 star3OZ;    /**< Star3 orbit Z-vector  */
+} CUBEACP_AdcsMeasure_t;
+
+/**
+ * @brief ADCS Power Control message structure
+ * @details Control power to selected components
+ */
+typedef struct  {
+    CUBEACP_PowerSelect_t cubeControlSignalPower;      /**< Control power to electronics of CubeControl Signal PIC  */
+    CUBEACP_PowerSelect_t cubeControlMotorPower;       /**< Control power to electronics of CubeControl Motor PIC  */
+    CUBEACP_PowerSelectCubeSense_t cubeSense1Power;    /**< Control power to the CubeSense1  */
+    CUBEACP_PowerSelectCubeSense_t cubeSense2Power;    /**< Control power to the CubeSense2  */
+    CUBEACP_PowerSelect_t cubeStarPower;               /**< Control power to the CubeStar  */
+    CUBEACP_PowerSelect_t cubeWheel1Power;             /**< Control power to the CubeWheel1  */
+    CUBEACP_PowerSelect_t cubeWheel2Power;             /**< Control power to the CubeWheel2  */
+    CUBEACP_PowerSelect_t cubeWheel3Power;             /**< Control power to the CubeWheel3  */
+    CUBEACP_PowerSelect_t motorPower;                  /**< Control power to Motor electronics  */
+    CUBEACP_PowerSelect_t gpsLnaPower;                 /**< Control power to GPS LNA  */
+} CUBEACP_AdcsPower_t;
+
+/**
+ * @brief Power and Temperature Measurements message structure
+ * @details Power and temperature measurements
+ */
+typedef struct  {
+    F64 cubeSense1_3V3Current;        /**< CubeSense1 3V3 Current  (measurment unit is [mA]) */
+    F64 cubeSense1_CamCurrent;        /**< CubeSense1 Cam SRAM Current  (measurment unit is [mA]) */
+    F64 cubeSense2_3V3Current;        /**< CubeSense2 3V3 Current  (measurment unit is [mA]) */
+    F64 cubeSense2_CamCurrent;        /**< CubeSense2 Cam SRAM Current  (measurment unit is [mA]) */
+    F64 cubeControl3V3Current;        /**< CubeControl 3V3 Current  (measurment unit is [mA]) */
+    F64 cubeControl5VCurrent;         /**< CubeControl 5V Current  (measurment unit is [mA]) */
+    F64 cubeControlBatCurrent;        /**< CubeControl Vbat Current  (measurment unit is [mA]) */
+    F64 wheel1Current;                /**< Wheel1 Current  (measurment unit is [mA]) */
+    F64 wheel2Current;                /**< Wheel2 Current  (measurment unit is [mA]) */
+    F64 wheel3Current;                /**< Wheel3 Current  (measurment unit is [mA]) */
+    F64 cubeStarCurrent;              /**< CubeStar Current  (measurment unit is [mA]) */
+    F64 magtorqCurrent;               /**< Magnetorquer Current  (measurment unit is [mA]) */
+    F64 cubeStarTemp;                 /**< CubeStar MCU temperature  (measurment unit is [C]) */
+    S16 mCUTemp;                      /**< MCU Temperature  (measurment unit is [C]) */
+    F64 magnetometerTemp;             /**< Magnetometer Temperature  (measurment unit is [C]) */
+    F64 redundentMagnetometerTemp;    /**< Redundant Magnetometer Temperature  (measurment unit is [C]) */
+    S16 xRateTemp;                    /**< X-Rate sensor Temperature  (measurment unit is [C]) */
+    S16 yRateTemp;                    /**< Y-Rate sensor Temperature  (measurment unit is [C]) */
+    S16 zRateTemp;                    /**< Z-Rate sensor Temperature  (measurment unit is [C]) */
+} CUBEACP_AdcsPowerMeasure_t;
+
+/**
+ * @brief ADCS State message structure
+ * @details Current ADCS state
+ */
+typedef struct  {
+    CUBEACP_EstimModeSelect_t estimMode;      /**< Current attitude estimation mode  */
+    CUBEACP_ConModeSelect_t controlMode;      /**< Current attitude control mode  */
+    CUBEACP_AdcsRunMode_t adcsRunMode;        /**< Current ADCS Running mode  */
+    CUBEACP_Asgp4ModeSelect_t asgp4Mode;      /**< ASGP4 enabled state  */
+    Boolean cubeControlSignalPower;           /**< CubeControl Signal electronics enabled status  */
+    Boolean cubeControlMotorPower;            /**< CubeControl Motor electronics enabled status  */
+    Boolean cubeSense1Power;                  /**< CubeSense1 enabled status  */
+    Boolean cubeSense2Power;                  /**< CubeSense2 enabled status  */
+    Boolean cubeWheel1Power;                  /**< CubeWheel1 enabled status  */
+    Boolean cubeWheel2Power;                  /**< CubeWheel2 enabled status  */
+    Boolean cubeWheel3Power;                  /**< CubeWheel3 enabled status  */
+    Boolean cubeStarPower;                    /**< CubeStar enabled status  */
+    Boolean gpsReceiverPower;                 /**< GPS Receiver enabled status  */
+    Boolean gpsLnaPower;                      /**< GPS Antenna LNA enabled status  */
+    Boolean motorDriverPower;                 /**< Motor Driver Electronics enabled status  */
+    Boolean sunAboveHorizon;                  /**< Sun is above the local horizon (elevation > 0)  */
+    Boolean cubeSense1CommsError;             /**< Communication error occurred with the CubeSense1  */
+    Boolean cubeSense2CommsError;             /**< Communication error occurred with the CubeSense2  */
+    Boolean cubeControlSignalCommsError;      /**< Communication error occurred with the CubeControl Signal MCU  */
+    Boolean cubeControlMotorCommsError;       /**< Communication error occurred with the CubeControl Motor MCU  */
+    Boolean cubeWheel1CommsError;             /**< Communication error occurred with the CubeWheel1  */
+    Boolean cubeWheel2CommsError;             /**< Communication error occurred with the CubeWheel2  */
+    Boolean cubeWheel3CommsError;             /**< Communication error occurred with the CubeWheel3  */
+    Boolean cubeStarCommsError;               /**< Communication error occurred with the CubeStar  */
+    Boolean magRangeError;                    /**< Magnetometer measured magnetic field with size <15 uT or >65 uT  */
+    Boolean cam1OvercurrentSram;              /**< Cam1 SRAM overcurrent detected  */
+    Boolean cam1Overcurrent3V3;               /**< Cam1 3V3 overcurrent detected  */
+    Boolean cam1SensNotIdle;                  /**< Cam1 sensor was not idle at the start of ADCS loop  */
+    Boolean cam1SensDetectError;              /**< Cam1 sensor was unable to compute angles (could be not in FOV)  */
+    Boolean sunSensRangeError;                /**< Detected sun angles were outside of +/- 90 deg  */
+    Boolean cam2OvercurrentSram;              /**< Cam2 SRAM overcurrent detected  */
+    Boolean cam2Overcurrent3V3;               /**< Cam2 3V3 overcurrent detected  */
+    Boolean cam2SensNotIdle;                  /**< Cam2 sensor was not idle at the start of ADCS loop  */
+    Boolean cam2SensDetectError;              /**< Cam2 sensor was unable to compute angles (could be not in FOV)  */
+    Boolean nadirSensRangeError;              /**< Detected nadir angles were outside of +/- 60 deg  */
+    Boolean rateSensRangeError;               /**< Measured XYZ-body rate is outside of the range +/-20 deg/s  */
+    Boolean wheelSpeedRangeError;             /**< Wheel XYZ speed measurement was outside the range +/-8500 rpm  */
+    Boolean cssError;                         /**< Unable to compute Coarse Sun vector (could be not in FOV)  */
+    Boolean starMatchError;                   /**< Unable to obtain enough matched stars  */
+    Boolean starTrackOvercurrent;             /**< Star tracker overcurrent detected  */
+    Boolean orbitParamsInvalidError;          /**< Orbit Parameters are not in allowed bounds (angle exceeding limits etc.). Failed to initialize SGP4 propagator using supplied parameters  */
+    Boolean configInvalidError;               /**< Magnetorquer Configuration or CSS in invalid. Each principle axis should have a torquer output (1,2, or 3) assigned. At least one CSS per principle axis needed  */
+    Boolean controlModeNotAllowed;            /**< Attempt was made to select control mode without appropriate estimator, or command to set Y-momentum mode while not in steady-state Y-Thomson  */
+    Boolean estimatorNotAllowed;              /**< Attempt was made to change to an estimation mode that would be inappropriate for the current control mode  */
+    CUBEACP_MagModeVal_t curMagMode;          /**< Current magnetometer sampling mode  */
+    Boolean magfieldModelError;               /**< Modelled and measured magnetic field differs in size by more than 5000 nT  */
+    Boolean nodeRecoveryError;                /**< Failed to Recover an ADCS Node by successive resets  */
+    Boolean cubeSense1RuntimeError;           /**< Runtime error occurred with the CubeSense1  */
+    Boolean cubeSense2RuntimeError;           /**< Runtime error occurred with the CubeSense2  */
+    Boolean cubeControlSignalRuntimeError;    /**< Runtime error occurred with the CubeControl Signal MCU  */
+    Boolean cubeControlMotorRuntimeError;     /**< Runtime error occurred with the CubeControl Motor MCU  */
+    Boolean cubeWheel1RuntimeError;           /**< Runtime error occurred with the CubeWheel1  */
+    Boolean cubeWheel2RuntimeError;           /**< Runtime error occurred with the CubeWheel2  */
+    Boolean cubeWheel3RuntimeError;           /**< Runtime error occurred with the CubeWheel3  */
+    Boolean cubeStarRuntimeError;             /**< Runtime error occurred with the CubeStar  */
+    Boolean magnetometerError;                /**< Magnetometer failure occurred  */
+    Boolean rateSensorFailure;                /**< Rate sensor failure occurred  */
+    F64 roll;                                 /**< Estimated roll angle  (measurment unit is [deg]) */
+    F64 pitch;                                /**< Estimated pitch angle  (measurment unit is [deg]) */
+    F64 yaw;                                  /**< Estimated yaw angle  (measurment unit is [deg]) */
+    S16 q1;                                   /**< Estimated q1  */
+    S16 q2;                                   /**< Estimated q2  */
+    S16 q3;                                   /**< Estimated q3  */
+    F64 rateX;                                /**< Estimated X angular rate  (measurment unit is [deg/s]) */
+    F64 rateY;                                /**< Estimated Y angular rate  (measurment unit is [deg/s]) */
+    F64 rateZ;                                /**< Estimated Z angular rate  (measurment unit is [deg/s]) */
+    F64 positionX;                            /**< ECI referenced X coordinate  (measurment unit is [km]) */
+    F64 positionY;                            /**< ECI referenced Y coordinate  (measurment unit is [km]) */
+    F64 positionZ;                            /**< ECI referenced Z coordinate  (measurment unit is [km]) */
+    F64 velocityX;                            /**< ECI referenced X velocity  (measurment unit is [m/s]) */
+    F64 velocityY;                            /**< ECI referenced Y velocity  (measurment unit is [m/s]) */
+    F64 velocityZ;                            /**< ECI referenced Z velocity  (measurment unit is [m/s]) */
+    F64 latitude;                             /**< WGS-84 Latitude angle  (measurment unit is [deg]) */
+    F64 longitude;                            /**< Longitude angle  (measurment unit is [deg]) */
+    F64 altitude;                             /**< WGS-84 altitude  (measurment unit is [km]) */
+    S16 posEcefX;                             /**< ECEF Position X  (measurment unit is [m]) */
+    S16 posEcefY;                             /**< ECEF Position Y  (measurment unit is [m]) */
+    S16 posEcefZ;                             /**< ECEF Position Z  (measurment unit is [m]) */
+} CUBEACP_AdcsState_t;
+
+/**
+ * @brief ADCS System Configuration message structure
+ * @details Current hard-coded system configuration
+ */
+typedef struct  {
+    CUBEACP_AcpProgramType_t acpType;             /**< ACP Type  */
+    CUBEACP_SpecialConSelect_t specialControl;    /**< Special Control Selection  */
+    U8 ccSignalVer;                               /**< CubeControl Signal Version  */
+    U8 ccMotorVer;                                /**< CubeControl Motor Version  */
+    U8 cs1Ver;                                    /**< CubeSense1 Version  */
+    U8 cs2Ver;                                    /**< CubeSense2 Version  */
+    CUBEACP_CsCamType_t csCam1Type;               /**< CubeSense1 Camera Type  */
+    CUBEACP_CsCamType_t csCam2Type;               /**< CubeSense2 Camera Type  */
+    U8 cubeStarVer;                               /**< CubeStar Version  */
+    CUBEACP_GpsSelect_t gpsType;                  /**< GPS Type  */
+    Boolean hasRedMag;                            /**< Redundant MTM Included  */
+    F32 mqx;                                      /**< Magnetorquer-X Max Dipole  (measurment unit is [A.m^2]. valid range is between 0 A.m^2 and 2 A.m^2) */
+    F32 mqy;                                      /**< Magnetorquer-Y Max Dipole  (measurment unit is [A.m^2]. valid range is between 0 A.m^2 and 2 A.m^2) */
+    F32 mqz;                                      /**< Magnetorquer-Z Max Dipole  (measurment unit is [A.m^2]. valid range is between 0 A.m^2 and 2 A.m^2) */
+    F32 mtTmin;                                   /**< Magnetorquer On-time Resolution  (measurment unit is [s]. valid range is between 0 s and 1 s) */
+    F32 mtTmax;                                   /**< Magnetorquer Maximum On-time  (measurment unit is [s]. valid range is between 0 s and 1 s) */
+    F32 nSatX;                                    /**< RW-X Maximum Torque  (measurment unit is [N.m]. valid range is between 0 N.m and 0.1 N.m) */
+    F32 nSatY;                                    /**< RW-Y Maximum Torque  (measurment unit is [N.m]. valid range is between 0 N.m and 0.1 N.m) */
+    F32 nSatZ;                                    /**< RW-Z Maximum Torque  (measurment unit is [N.m]. valid range is between 0 N.m and 0.1 N.m) */
+    F32 hSatX;                                    /**< RW-X Maximum Momentum  (measurment unit is [Nms]. valid range is between 0 Nms and 0.1 Nms) */
+    F32 hSatY;                                    /**< RW-Y Maximum Momentum  (measurment unit is [Nms]. valid range is between 0 Nms and 0.1 Nms) */
+    F32 hSatZ;                                    /**< RW-Z Maximum Momentum  (measurment unit is [Nms]. valid range is between 0 Nms and 0.1 Nms) */
+    F32 iwx;                                      /**< RW-X Inertia  (measurment unit is [kg.m^2]. valid range is between 0 kg.m^2 and 0.001 kg.m^2) */
+    F32 iwy;                                      /**< RW-Y Inertia  (measurment unit is [kg.m^2]. valid range is between 0 kg.m^2 and 0.001 kg.m^2) */
+    F32 iwz;                                      /**< RW-Z Inertia  (measurment unit is [kg.m^2]. valid range is between 0 kg.m^2 and 0.001 kg.m^2) */
+    F32 ndel;                                     /**< RW Torque Increment  (measurment unit is [N.m]. valid range is between 0 N.m and 0.1 N.m) */
+    F32 biasX_d1;                                 /**< Primary MTM X-Bias d1  (valid range is between -10  and 10 ) */
+    F32 biasY_d1;                                 /**< Primary MTM Y-Bias d1  (valid range is between -10  and 10 ) */
+    F32 biasZ_d1;                                 /**< Primary MTM Z-Bias d1  (valid range is between -10  and 10 ) */
+    F32 biasX_d2;                                 /**< Primary MTM X-Bias d2  (valid range is between -10000  and 10000 ) */
+    F32 biasY_d2;                                 /**< Primary MTM Y-Bias d2  (valid range is between -10000  and 10000 ) */
+    F32 biasZ_d2;                                 /**< Primary MTM Z-Bias d2  (valid range is between -10000  and 10000 ) */
+    F32 sensX_s1;                                 /**< Primary MTM X-Sens s1  (valid range is between -1  and 1 ) */
+    F32 sensY_s1;                                 /**< Primary MTM Y-Sens s1  (valid range is between -1  and 1 ) */
+    F32 sensZ_s1;                                 /**< Primary MTM Z-Sens s1  (valid range is between -1  and 1 ) */
+    F32 sensX_s2;                                 /**< Primary MTM X-Sens s2  (valid range is between -10  and 10 ) */
+    F32 sensY_s2;                                 /**< Primary MTM Y-Sens s2  (valid range is between -10  and 10 ) */
+    F32 sensZ_s2;                                 /**< Primary MTM Z-Sens s2  (valid range is between -10  and 10 ) */
+    F32 red_BiasX_d1;                             /**< Redundant MTM X-Bias d1  (valid range is between -10  and 10 ) */
+    F32 red_BiasY_d1;                             /**< Redundant MTM Y-Bias d1  (valid range is between -10  and 10 ) */
+    F32 red_BiasZ_d1;                             /**< Redundant MTM Z-Bias d1  (valid range is between -10  and 10 ) */
+    F32 red_BiasX_d2;                             /**< Redundant MTM X-Bias d2  (valid range is between -10000  and 10000 ) */
+    F32 red_BiasY_d2;                             /**< Redundant MTM Y-Bias d2  (valid range is between -10000  and 10000 ) */
+    F32 red_BiasZ_d2;                             /**< Redundant MTM Z-Bias d2  (valid range is between -10000  and 10000 ) */
+    F32 red_SensX_s1;                             /**< Redundant MTM X-Sens s1  (valid range is between -1  and 1 ) */
+    F32 red_SensY_s1;                             /**< Redundant MTM Y-Sens s1  (valid range is between -1  and 1 ) */
+    F32 red_SensZ_s1;                             /**< Redundant MTM Z-Sens s1  (valid range is between -1  and 1 ) */
+    F32 red_SensX_s2;                             /**< Redundant MTM X-Sens s2  (valid range is between -10  and 10 ) */
+    F32 red_SensY_s2;                             /**< Redundant MTM Y-Sens s2  (valid range is between -10  and 10 ) */
+    F32 red_SensZ_s2;                             /**< Redundant MTM Z-Sens s2  (valid range is between -10  and 10 ) */
+    CUBEACP_GpioPort_t ccsEnablePort;             /**< CC Signal Enable GPIO port  */
+    CUBEACP_GpioPortPin_t ccsEnablePin;           /**< CC Signal Enable GPIO port pin  */
+    CUBEACP_GpioPort_t ccmEnablePort;             /**< CC Motor Enable GPIO port  */
+    CUBEACP_GpioPortPin_t ccmEnablePin;           /**< CC Motor Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cccEnablePort;             /**< CC Common Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cccEnablePin;           /**< CC Common Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cSense1EnablePort;         /**< CubeSense1 Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cSense1EnablePin;       /**< CubeSense1 Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cSense2EnablePort;         /**< CubeSense2 Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cSense2EnablePin;       /**< CubeSense2 Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cStarEnablePort;           /**< CubeStar Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cStarEnablePin;         /**< CubeStar Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cW1EnablePort;             /**< CubeWheel1 Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cW1EnablePin;           /**< CubeWheel1 Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cW2EnablePort;             /**< CubeWheel2 Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cW2EnablePin;           /**< CubeWheel2 Enable GPIO port pin  */
+    CUBEACP_GpioPort_t cW3EnablePort;             /**< CubeWheel3 Enable GPIO port  */
+    CUBEACP_GpioPortPin_t cW3EnablePin;           /**< CubeWheel3 Enable GPIO port pin  */
+} CUBEACP_AdcsSystemConfig_t;
+
+/**
+ * @brief ASGP4 TLEs message structure
+ * @details ASGP4 TLEs generated
+ */
+typedef struct  {
+    Boolean asgp4Complete;           /**< Is ASGP4 process complete  */
+    CUBEACP_Asgp4Error_t asgpErr;    /**< The error state that the asgp4 module is in  */
+    F32 asgp4Epoch;                  /**< Epoch from asgp4  */
+    F32 asgp4Incli;                  /**< Inclination from asgp4  */
+    F32 asgp4Raan;                   /**< RAAN from asgp4  */
+    F32 asgp4Ecc;                    /**< Eccentricity from asgp4  */
+    F32 asgp4Aop;                    /**< AOP from asgp4  */
+    F32 asgp4Ma;                     /**< MA from asgp4  */
+    F32 asgp4Mm;                     /**< MM from asgp4  */
+    F32 asgp4Bstar;                  /**< BStar from asgp4  */
+} CUBEACP_Asgp4KepTle_t;
+
+/**
+ * @brief Clear Errors message structure
+ * @details Clear Latched Error Flags
+ */
+typedef struct  {
+    Boolean aDCSErrors;    /**< Clear ADCS error flags  */
+    Boolean hKErrors;      /**< Clear HK Error flags  */
+} CUBEACP_ClearErrors_t;
+
+/**
+ * @brief Commanded Attitude Angles message structure
+ * @details Commanded attitude angles
+ */
+typedef struct  {
+    F64 roll;     /**< Commanded roll angle  (measurment unit is [deg]. valid range is between -9000 deg and 9000 deg) */
+    F64 pitch;    /**< Commanded pitch angle  (measurment unit is [deg]. valid range is between -18000 deg and 18000 deg) */
+    F64 yaw;      /**< Commanded yaw angle  (measurment unit is [deg]. valid range is between -18000 deg and 18000 deg) */
+} CUBEACP_CmdAttitude_t;
+
+/**
+ * @brief Tracking Controller Target Reference message structure
+ * @details Target reference for tracking control mode
+ */
+typedef struct  {
+    F32 longRef;    /**< Geocentric longitude of target  (measurment unit is [deg]. valid range is between 0 deg and 360 deg) */
+    F32 latRef;     /**< Geocentric latitude of target  (measurment unit is [deg]. valid range is between -90 deg and 90 deg) */
+    F32 altRef;     /**< Geocentric altitude of target  (measurment unit is [meter]. valid range is between -20000 meter and 40000000 meter) */
+} CUBEACP_CmdTrackingTarget_t;
+
+/**
+ * @brief Set Attitude Control Mode message structure
+ * @details Set attitude control mode
+ */
+typedef struct  {
+    CUBEACP_ConModeSelect_t controlModeSelection;    /**< Attitude control mode  */
+    U16 timeout;                                     /**< Control timeout duration. Control will revert to None when timer reaches zero. 0xFFFF for infinite timeout  (measurment unit is [s]) */
+} CUBEACP_ControlMode_t;
+
+/**
+ * @brief JPG Conversion Progress message structure
+ * @details Conversion progress
+ */
+typedef struct  {
+    U8 progress;                                    /**< Progress %  */
+    CUBEACP_JpgConvertResult_t conversionResult;    /**< JPG Conversion Result  */
+    U8 outFileCounter;                              /**< Output File Counter  */
+} CUBEACP_ConversionProgress_t;
+
+/**
+ * @brief Convert to JPG file message structure
+ * @details Convert raw or bmp files to JPG
+ */
+typedef struct  {
+    U8 srcFileCtr;       /**< Source File Counter  */
+    U8 qualityFactor;    /**< Quality Factor  */
+    U8 whiteBalance;     /**< White Balance  */
+} CUBEACP_Convert_t;
+
+/**
+ * @brief CubeACP State message structure
+ * @details Contains flags regarding the state of the ACP
+ */
+typedef struct  {
+    Boolean adcsConfigLoadError;      /**< Flag to indicate that the ADCS configuartion was not read successfully out of flash  */
+    Boolean orbitParamsLoadError;     /**< Flag to indicate that the Orbit parameters were not read successfully out of flash  */
+    Boolean systemConfigLoadError;    /**< Flag to indicate that the System Configuration was not read successfully out of flash  */
+    Boolean sdInitError;              /**< Flag to indicate that the SD card failed to initialise  */
+    Boolean sdReadError;              /**< Flag to indicate that a read operation from the SD card failed  */
+    Boolean sdWriteError;             /**< Flag to indicate that a write operation to the SD card failed  */
+} CUBEACP_CubeACPState_t;
+
+/**
+ * @brief Estimation Data message structure
+ * @details Estimation meta-data
+ */
+typedef struct  {
+    F64 igrfMagX;          /**< IGRF Modelled Magnetic Field X  (measurment unit is [uT]) */
+    F64 igrfMagY;          /**< IGRF Modelled Magnetic Field Y  (measurment unit is [uT]) */
+    F64 igrfMagZ;          /**< IGRF Modelled Magnetic Field Z  (measurment unit is [uT]) */
+    F64 modelSunX;         /**< Modelled Sun Vector X  */
+    F64 modelSunY;         /**< Modelled Sun Vector Y  */
+    F64 modelSunZ;         /**< Modelled Sun Vector Z  */
+    F64 estimGyroBiasX;    /**< Estimated X-gyro Bias  (measurment unit is [deg/s]) */
+    F64 estimGyroBiasY;    /**< Estimated Y-gyro Bias  (measurment unit is [deg/s]) */
+    F64 estimGyroBiasZ;    /**< Estimated Z-gyro Bias  (measurment unit is [deg/s]) */
+    F64 innovX;            /**< Innovation Vector X  */
+    F64 innovY;            /**< Innovation Vector Y  */
+    F64 innovZ;            /**< Innovation Vector Z  */
+    F64 qError1;           /**< Quaternion Error - Q1  */
+    F64 qError2;           /**< Quaternion Error - Q2  */
+    F64 qError3;           /**< Quaternion Error - Q3  */
+    F64 qCovar1;           /**< Quaternion Covariance - Q1 RMS  */
+    F64 qCovar2;           /**< Quaternion Covariance - Q2 RMS  */
+    F64 qCovar3;           /**< Quaternion Covariance - Q3 RMS  */
+    F64 rateCovarX;        /**< X Angular Rate Covariance  */
+    F64 rateCovarY;        /**< Y Angular Rate Covariance  */
+    F64 rateCovarZ;        /**< Z Angular Rate Covariance  */
+} CUBEACP_EstimData_t;
+
+/**
+ * @brief Fine Estimated Angular Rates message structure
+ * @details High resolution estimated angular rates relative to orbit reference frame
+ */
+typedef struct  {
+    F64 rateX;    /**< Estimated X angular rate  (measurment unit is [deg/s]) */
+    F64 rateY;    /**< Estimated Y angular rate  (measurment unit is [deg/s]) */
+    F64 rateZ;    /**< Estimated Z angular rate  (measurment unit is [deg/s]) */
+} CUBEACP_FineEstimRates_t;
+
+/**
+ * @brief Status of Image Capture and Save Operation message structure
+ * @details Status of Image Capture and Save Operation
+ */
+typedef struct  {
+    U8 percentageComplete;            /**< Current progress of operation  (measurment unit is [%]) */
+    CUBEACP_ImSaveStatus_t status;    /**< Current status of operation  */
+} CUBEACP_ImageSaveStatus_t;
+
+/**
+ * @brief Inertial Pointing Reference Vector message structure
+ * @details Reference unit vector for inertial pointing control mode
+ */
+typedef struct  {
+    F64 inertialRefX;    /**< Inertial Reference X  */
+    F64 inertialRefY;    /**< Inertial Reference Y  */
+    F64 inertialRefZ;    /**< Inertial Reference Z  */
+} CUBEACP_InertialPointReference_t;
+
+/**
+ * @brief SD Log1 Configuration message structure
+ * @details Log selection and period for LOG1
+ */
+typedef struct  {
+    U8 logSelection[10];                  /**< Log Selection - up to 80 flags indicating which telemetry frames should be logged  */
+    U16 period;                           /**< Log period. Set to 0 to disable logging  */
+    CUBEACP_SdLogSelect_t destination;    /**< Which SD card to use to store log file  */
+} CUBEACP_LogSdConfig1_t;
+
+/**
+ * @brief SD Log2 Configuration message structure
+ * @details Log selection and period for LOG2
+ */
+typedef struct  {
+    U8 logSelection[10];                  /**< Log Selection - up to 80 flags indicating which telemetry frames should be logged  */
+    U16 period;                           /**< Log period. Set to 0 to disable logging  */
+    CUBEACP_SdLogSelect_t destination;    /**< Which SD card to use to store log file  */
+} CUBEACP_LogSdConfig2_t;
+
+/**
+ * @brief UART Log Configuration message structure
+ * @details Log selection and period for UART (unsolicited TLM)
+ */
+typedef struct  {
+    U8 selection[10];    /**< Log Selection - up to 80 flags indicating which telemetry frames should be logged  */
+    U16 period;          /**< Log period. Set to 0 to disable logging  */
+} CUBEACP_LogUartConfig_t;
+
+/**
+ * @brief Secondary Magnetometer Raw Measurements message structure
+ * @details Secondary Magnetometer raw measurements
+ */
+typedef struct  {
+    S16 magRawX;    /**< sampled A/D value  */
+    S16 magRawY;    /**< sampled A/D value  */
+    S16 magRawZ;    /**< sampled A/D value  */
+} CUBEACP_MagRaw2_t;
+
+/**
+ * @brief SGP4 Orbit Parameters message structure
+ * @details SGP4 Orbit Parameters
+ */
+typedef struct  {
+    F64 inclination;     /**< Inclination  (measurment unit is [deg]. valid range is between 0 deg and 180 deg) */
+    F64 eccentricity;    /**< Eccentricity  (valid range is between 0  and 1 ) */
+    F64 raan;            /**< Right-ascension of the Ascending Node  (measurment unit is [deg]. valid range is between 0 deg and 360 deg) */
+    F64 argPerigee;      /**< Argument of Perigee  (measurment unit is [deg]. valid range is between 0 deg and 360 deg) */
+    F64 bstar;           /**< B-Star drag term  (valid range is between 0  and 1 ) */
+    F64 meanMotion;      /**< Mean Motion  (measurment unit is [orbits/day]. valid range is between 0 orbits/day and 20 orbits/day) */
+    F64 meanAnomaly;     /**< Mean Anomaly  (measurment unit is [deg]. valid range is between 0 deg and 360 deg) */
+    F64 epoch;           /**< Epoch (year.day)  (measurment unit is [year.day]. valid range is between 0 year.day and 100000 year.day) */
+} CUBEACP_OrbitParameters_t;
+
+/**
+ * @brief Raw GPS Measurements message structure
+ * @details Raw GPS measurements
+ */
+typedef struct  {
+    CUBEACP_GpsSolutionStatus_t gpsSolutionStatus;    /**< GPS Solution Status  */
+    U8 gpsNumSatsTracked;                             /**< Number of tracked GPS satellites  */
+    U8 gpsNumSatsSolution;                            /**< Number of GPS satellites used in solution  */
+    U8 gpsXYZLogCtr;                                  /**< Counter for XYZ Lof from GPS  */
+    U8 gpsRangeLogCtr;                                /**< Counter for RANGE log from GPS  */
+    U8 gpsResponse;                                   /**< Response Message for GPS log setup - p656 of OEMV615 reference manual  */
+    U16 gpsWeek;                                      /**< GPS Reference Week  */
+    U32 gpsTimeMs;                                    /**< GPS Time Milliseconds  (measurment unit is [ms]) */
+    S32 posEcefX;                                     /**< ECEF Position X  (measurment unit is [m]) */
+    S16 velEcefX;                                     /**< ECEF Velocity X  (measurment unit is [m/s]) */
+    S32 posEcefY;                                     /**< ECEF Position Y  (measurment unit is [m]) */
+    S16 velEcefY;                                     /**< ECEF Velocity Y  (measurment unit is [m/s]) */
+    S32 posEcefZ;                                     /**< ECEF Position Z  (measurment unit is [m]) */
+    S16 velEcefZ;                                     /**< ECEF Velocity Z  (measurment unit is [m/s]) */
+    F64 stdDevPosX;                                   /**< X-pos Standard Deviation  (measurment unit is [m]) */
+    F64 stdDevPosY;                                   /**< Y-pos Standard Deviation  (measurment unit is [m]) */
+    F64 stdDevPosZ;                                   /**< Z-pos Standard Deviation  (measurment unit is [m]) */
+    U8 stdDevVelX;                                    /**< X-vel Standard Deviation  (measurment unit is [m/s]) */
+    U8 stdDevVelY;                                    /**< Y-vel Standard Deviation  (measurment unit is [m/s]) */
+    U8 stdDevVelZ;                                    /**< Z-vel Standard Deviation  (measurment unit is [m/s]) */
+} CUBEACP_RawGPS_t;
+
+/**
+ * @brief Raw Sensor Measurements message structure
+ * @details Raw sensor measurements
+ */
+typedef struct  {
+    S16 cam2RawX;                         /**< Cam2 azimuth angle  */
+    S16 cam2RawY;                         /**< Cam2 elevation angle  */
+    CUBEACP_CaptureResult_t cam2Busy;     /**< Cam2 capture status  */
+    CUBEACP_DetectResult_t cam2Result;    /**< Cam2 detection result  */
+    S16 cam1RawX;                         /**< Cam1 azimuth angle  */
+    S16 cam1RawY;                         /**< Cam1 elevation angle  */
+    CUBEACP_CaptureResult_t cam1Busy;     /**< Cam1 capture status  */
+    CUBEACP_DetectResult_t cam1Result;    /**< Cam1 detection result  */
+    U8 cssRaw1;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw2;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw3;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw4;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw5;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw6;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw7;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw8;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw9;                           /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    U8 cssRaw10;                          /**< sampled A/D value - corresponds to COS(sun_angle)  */
+    S16 magRawX;                          /**< sampled A/D value  */
+    S16 magRawY;                          /**< sampled A/D value  */
+    S16 magRawZ;                          /**< sampled A/D value  */
+    S16 rawRateX;                         /**< sampled A/D value  */
+    S16 rawRateY;                         /**< sampled A/D value  */
+    S16 rawRateZ;                         /**< sampled A/D value  */
+} CUBEACP_RawSensor_t;
+
+/**
+ * @brief Raw Star Tracker message structure
+ * @details Raw Star Tracker Measurement
+ */
+typedef struct  {
+    U8 numStarsDetected;               /**< Number of stars detected  (measurment unit is [stars]) */
+    U8 starImageNoise;                 /**< Star image noise  (measurment unit is [noise]) */
+    U8 invalidStars;                   /**< Number of invalid stars detected  (measurment unit is [Invalid stars]) */
+    U8 numberOfStarsID;                /**< Number of stars identified  (measurment unit is [stars]) */
+    CUBEACP_StarIDModeVal_t iDmode;    /**< Identification mode  (measurment unit is [ID mode]) */
+    U8 imageDarkValue;                 /**< The average value of center line in image  (measurment unit is [8-bit pixel value]) */
+    Boolean imageCaptureSuccess;       /**< Image Capture Success  (measurment unit is [flag]) */
+    Boolean detectionSuccess;          /**< Detection Success  (measurment unit is [flag]) */
+    Boolean identificationSuccess;     /**< Identification Success  (measurment unit is [flag]) */
+    Boolean attitudeSuccess;           /**< Attitude Success  (measurment unit is [flag]) */
+    Boolean processingTimeError;       /**< Processing time Error  (measurment unit is [flag]) */
+    Boolean trackingModuleEnabled;     /**< Tracking Module Enabled  (measurment unit is [flag]) */
+    Boolean predictionEnabled;         /**< Prediction Enabled  (measurment unit is [flag]) */
+    Boolean commsError;                /**< Comms error  (measurment unit is [flag]) */
+    U16 deltaT;                        /**< Sample Period  */
+    U8 s1Conf;                         /**< Star 1 confidence  (measurment unit is [percentage]) */
+    U8 s2Conf;                         /**< Star 2 confidence  (measurment unit is [percentage]) */
+    U8 s3Conf;                         /**< Star 3 confidence  (measurment unit is [percentage]) */
+    U16 magStar1;                      /**< Instrument magnitude of star 1  */
+    U16 magStar2;                      /**< Instrument magnitude of star 2  */
+    U16 magStar3;                      /**< Instrument magnitude of star 3  */
+    U16 catStar1;                      /**< Catalogue number of star 1  */
+    S16 centXStar1;                    /**< X centroid of star 1  */
+    S16 centYStar1;                    /**< Y centroid of star 1  */
+    U16 catStar2;                      /**< Catalogue number of star 2  */
+    S16 centXStar2;                    /**< X centroid of star 2  */
+    S16 centYStar2;                    /**< Y centroid of star 2  */
+    U16 catStar3;                      /**< Catalogue number of star 3  */
+    S16 centXStar3;                    /**< X centroid of star 3  */
+    S16 centYStar3;                    /**< Y centroid of star 3  */
+    U16 capture;                       /**< Capture  (measurment unit is [ms]) */
+    U16 detection;                     /**< Detection  (measurment unit is [ms]) */
+    U16 identification;                /**< Identification  (measurment unit is [ms]) */
+    F64 starRateX;                     /**< Estimated Rate around CubeStar X-axis  */
+    F64 starRateY;                     /**< Estimated Rate around CubeStar Y-axis  */
+    F64 starRateZ;                     /**< Estimated Rate around CubeStar Z-axis  */
+    F64 starQbar0;                     /**< CubeStar estimated attitude Q1  */
+    F64 starQbar1;                     /**< CubeStar estimated attitude Q2  */
+    F64 starQbar2;                     /**< CubeStar estimated attitude Q3  */
+} CUBEACP_RawStarTracker_t;
+
+/**
+ * @brief Save Image message structure
+ * @details Save and capture image from one of CubeSense cameras or CubeStar camera to SD card
+ */
+typedef struct  {
+    CUBEACP_CamSelect_t cameraSelect;    /**< Camera Selection  (measurment unit is [s]) */
+    CUBEACP_ImSize_t imageSize;          /**< Image size selection  (measurment unit is [s]) */
+} CUBEACP_SaveImage_t;
+
+/**
+ * @brief Set Magnetorquer Output message structure
+ * @details Set magnetorquer output (only valid if Control Mode is None)
+ */
+typedef struct  {
+    F64 torquerX;    /**< Commanded X-torquer duty cycle  (valid range is between -800  and 800 ) */
+    F64 torquerY;    /**< Commanded Y-torquer duty cycle  (valid range is between -800  and 800 ) */
+    F64 torquerZ;    /**< Commanded Z-torquer duty cycle  (valid range is between -800  and 800 ) */
+} CUBEACP_TorquerCmd_t;
+
+/**
+ * @brief Trigger ADCS Loop with Simulated Sensor Data message structure
+ * @details Trigger ADCS to perform one iteration of the control loop (only valid when ADCS Run Mode is Triggered)
+ */
+typedef struct  {
+    U32 unixTime;                                     /**< Unix time for iteration  (measurment unit is [s]) */
+    U16 cssRaw1;                                      /**< CSS1 raw measurement  */
+    U16 cssRaw2;                                      /**< CSS2 raw measurement  */
+    U16 cssRaw3;                                      /**< CSS3 raw measurement  */
+    U16 cssRaw4;                                      /**< CSS4 raw measurement  */
+    U16 cssRaw5;                                      /**< CSS5 raw measurement  */
+    U16 cssRaw6;                                      /**< CSS6 raw measurement  */
+    U16 cssRaw7;                                      /**< CSS7 raw measurement  */
+    U16 cssRaw8;                                      /**< CSS8 raw measurement  */
+    U16 cssRaw9;                                      /**< CSS9 raw measurement  */
+    U16 cssRaw10;                                     /**< CSS10 raw measurement  */
+    S16 cam1RawX;                                     /**< Cam1 sensor raw X angle  */
+    S16 cam1RawY;                                     /**< Cam1 sensor raw Y angle  */
+    U8 cam1Busy;                                      /**< Cam1 sensor capture status  */
+    U8 cam1Result;                                    /**< Cam1 sensor detection result  */
+    S16 cam2RawX;                                     /**< Cam2 sensor raw X angle  */
+    S16 cam2RawY;                                     /**< Cam2 sensor raw Y angle  */
+    U8 cam2Busy;                                      /**< Cam2 sensor capture status  */
+    U8 cam2Result;                                    /**< Cam2 sensor detection result  */
+    S16 magRawX;                                      /**< Raw magnetometer X measurement  */
+    S16 magRawY;                                      /**< Raw magnetometer Y measurement  */
+    S16 magRawZ;                                      /**< Raw magnetometer Z measurement  */
+    S32 rateRawX;                                     /**< Raw X rate sensor measurement  */
+    S32 rateRawY;                                     /**< Raw Y rate sensor measurement  */
+    S32 rateRawZ;                                     /**< Raw Z rate sensor measurement  */
+    S16 wheelRawX;                                    /**< Raw X wheel speed measurement  (measurment unit is [rpm]) */
+    S16 wheelRawY;                                    /**< Raw Y wheel speed measurement  (measurment unit is [rpm]) */
+    S16 wheelRawZ;                                    /**< Raw Z wheel speed measurement  (measurment unit is [rpm]) */
+    S16 star1CameraX;                                 /**< Star1 camera X-vector  */
+    S16 star1CameraY;                                 /**< Star1 camera Y-vector  */
+    S16 star1CameraZ;                                 /**< Star1 camera Z-vector  */
+    S16 star1InertialX;                               /**< Star1 inertial X-vector  */
+    S16 star1InertialY;                               /**< Star1 inertial Y-vector  */
+    S16 star1InertialZ;                               /**< Star1 inertial Z-vector  */
+    S16 star2CameraX;                                 /**< Star2 camera X-vector  */
+    S16 star2CameraY;                                 /**< Star2 camera Y-vector  */
+    S16 star2CameraZ;                                 /**< Star2 camera Z-vector  */
+    S16 star2InertialX;                               /**< Star2 inertial X-vector  */
+    S16 star2InertialY;                               /**< Star2 inertial Y-vector  */
+    S16 star2InertialZ;                               /**< Star2 inertial Z-vector  */
+    S16 star3CameraX;                                 /**< Star3 camera X-vector  */
+    S16 star3CameraY;                                 /**< Star3 camera Y-vector  */
+    S16 star3CameraZ;                                 /**< Star3 camera Z-vector  */
+    S16 star3InertialX;                               /**< Star3 inertial X-vector  */
+    S16 star3InertialY;                               /**< Star3 inertial Y-vector  */
+    S16 star3InertialZ;                               /**< Star3 inertial Z-vector  */
+    CUBEACP_GpsSolutionStatus_t gpsSolutionStatus;    /**< GPS Solution Status  */
+    U16 gpsWeek;                                      /**< GPS Reference Week  */
+    U32 gpsTimeMs;                                    /**< GPS Time Milliseconds  (measurment unit is [ms]) */
+    S32 posEcefX;                                     /**< ECEF Position X  (measurment unit is [m]) */
+    S16 velEcefX;                                     /**< ECEF Velocity X  (measurment unit is [m/s]) */
+    S32 posEcefY;                                     /**< ECEF Position Y  (measurment unit is [m]) */
+    S16 velEcefY;                                     /**< ECEF Velocity Y  (measurment unit is [m/s]) */
+    S32 posEcefZ;                                     /**< ECEF Position Z  (measurment unit is [m]) */
+    S16 velEcefZ;                                     /**< ECEF Velocity Z  (measurment unit is [m/s]) */
+    F64 stdDevPosX;                                   /**< X-pos Standard Deviation  (measurment unit is [m]) */
+    F64 stdDevPosY;                                   /**< Y-pos Standard Deviation  (measurment unit is [m]) */
+    F64 stdDevPosZ;                                   /**< Z-pos Standard Deviation  (measurment unit is [m]) */
+    U8 stdDevVelX;                                    /**< X-vel Standard Deviation  (measurment unit is [m/s]) */
+    U8 stdDevVelY;                                    /**< Y-vel Standard Deviation  (measurment unit is [m/s]) */
+    U8 stdDevVelZ;                                    /**< Z-vel Standard Deviation  (measurment unit is [m/s]) */
+} CUBEACP_TriggerAdcsSensor_t;
+
+/**
+ * @brief Set Wheel Speed message structure
+ * @details Set wheel speed (only valid if Control Mode is None)
+ */
+typedef struct  {
+    S16 wheelX;    /**< Commanded X-wheel speed  (measurment unit is [rpm]. valid range is between -8000 rpm and 8000 rpm) */
+    S16 wheelY;    /**< Commanded Y-wheel speed  (measurment unit is [rpm]. valid range is between -8000 rpm and 8000 rpm) */
+    S16 wheelZ;    /**< Commanded Z-wheel speed  (measurment unit is [rpm]. valid range is between -8000 rpm and 8000 rpm) */
+} CUBEACP_WheelSpeedCmd_t;
+
+
+/*******************************************************************************
+ *****************************   PROTOTYPES   **********************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+Return the expected length of a telemetry frame
+ *
+ * @param[in] tlm
+ *   Enumeration of specified telemetry request
+ * @return
+ *   Returns the length of the telemetry frame in bytes
+ ******************************************************************************/
+uint16_t CUBEACP_GetTlmLen(CUBEACP_Telemetry_t tlm);
+
+/***************************************************************************//**
+ * Decode a ACP Execution State telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AcpLoopState_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAcpLoopStateTlm(uint8_t* rxBuffer, CUBEACP_AcpLoopState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Actuator Commands telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_ActuatorCmd_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractActuatorCmdTlm(uint8_t* rxBuffer, CUBEACP_ActuatorCmd_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ *      TlmRangeError if the Star Tracker Centroid X telemetry value was outside of the range -5000  to 5000 
+ *      TlmRangeError if the Star Tracker Centroid Y telemetry value was outside of the range -5000  to 5000 
+ *      TlmRangeError if the Star Tracker Focal Length telemetry value was outside of the range 5 mm to 7 mm
+ *      TlmRangeError if the K1 radial distortion coefficient telemetry value was outside of the range -1 gain to 1 gain
+ *      TlmRangeError if the K2 radial distortion coefficient telemetry value was outside of the range -1 gain to 1 gain
+ *      TlmRangeError if the P1 tangential distortion coefficient telemetry value was outside of the range -1 gain to 1 gain
+ *      TlmRangeError if the P2 tangential distortion coefficient telemetry value was outside of the range -1 gain to 1 gain
+ *      TlmRangeError if the Detumbling Spin Gain telemetry value was outside of the range 0  to 10000 
+ *      TlmRangeError if the Detumbling Damping Gain telemetry value was outside of the range 0  to 10000 
+ *      TlmRangeError if the Reference spin rate telemetry value was outside of the range -32000 deg/s to 32000 deg/s
+ *      TlmRangeError if the Fast BDot Detumbling Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Y-Momentum Control Gain telemetry value was outside of the range 0  to 10000 
+ *      TlmRangeError if the Y-momentum Nutation Damping Gain telemetry value was outside of the range 0  to 10000 
+ *      TlmRangeError if the Y-momentum Proportional Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Y-momentum Derivative Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Reference Wheel Momentum telemetry value was outside of the range -10 Nms to 0 Nms
+ *      TlmRangeError if the RWheel Proportional Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the RWheel Derivative Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Y-Wheel Bias Momentum telemetry value was outside of the range -10 Nms to 10 Nms
+ *      TlmRangeError if the Tracking Proportional Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Tracking Derivative Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Tracking Integral Gain telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Moment Of Inertia - Ixx telemetry value was outside of the range 0 kg.m^2 to 10 kg.m^2
+ *      TlmRangeError if the Moment Of Inertia - Iyy telemetry value was outside of the range 0 kg.m^2 to 10 kg.m^2
+ *      TlmRangeError if the Moment Of Inertia - Izz telemetry value was outside of the range 0 kg.m^2 to 10 kg.m^2
+ *      TlmRangeError if the Product Of Inertia - Ixy telemetry value was outside of the range -10 kg.m^2 to 10 kg.m^2
+ *      TlmRangeError if the Product Of Inertia - Ixz telemetry value was outside of the range -10 kg.m^2 to 10 kg.m^2
+ *      TlmRangeError if the Product Of Inertia - Iyz telemetry value was outside of the range -10 kg.m^2 to 10 kg.m^2
+ *      TlmRangeError if the Magnetometer Rate Filter System Noise telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the EKF System Noise telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the CSS Measurement Noise telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Sun Sensor Measurement Noise telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Nadir Sensor Measurement Noise telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Magnetometer Measurement Noise telemetry value was outside of the range 0  to 100 
+ *      TlmRangeError if the Star Tracker Measurement Noise telemetry value was outside of the range 0  to 100 
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Adcs Execution Times telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsExecTimes_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsExecTimesTlm(uint8_t* rxBuffer, CUBEACP_AdcsExecTimes_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsMeasure_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsMeasureTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS Misc Current Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsMiscCurrents_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsMiscCurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS Power Control telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsPower_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsPowerTlm(uint8_t* rxBuffer, CUBEACP_AdcsPower_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Power and Temperature Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsPowerMeasure_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsPowerMeasureTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS State telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsState_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsStateTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS System Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsSystemConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ *      TlmRangeError if the Magnetorquer-X Max Dipole telemetry value was outside of the range 0 A.m^2 to 2 A.m^2
+ *      TlmRangeError if the Magnetorquer-Y Max Dipole telemetry value was outside of the range 0 A.m^2 to 2 A.m^2
+ *      TlmRangeError if the Magnetorquer-Z Max Dipole telemetry value was outside of the range 0 A.m^2 to 2 A.m^2
+ *      TlmRangeError if the Magnetorquer On-time Resolution telemetry value was outside of the range 0 s to 1 s
+ *      TlmRangeError if the Magnetorquer Maximum On-time telemetry value was outside of the range 0 s to 1 s
+ *      TlmRangeError if the RW-X Maximum Torque telemetry value was outside of the range 0 N.m to 0.1 N.m
+ *      TlmRangeError if the RW-Y Maximum Torque telemetry value was outside of the range 0 N.m to 0.1 N.m
+ *      TlmRangeError if the RW-Z Maximum Torque telemetry value was outside of the range 0 N.m to 0.1 N.m
+ *      TlmRangeError if the RW-X Maximum Momentum telemetry value was outside of the range 0 Nms to 0.1 Nms
+ *      TlmRangeError if the RW-Y Maximum Momentum telemetry value was outside of the range 0 Nms to 0.1 Nms
+ *      TlmRangeError if the RW-Z Maximum Momentum telemetry value was outside of the range 0 Nms to 0.1 Nms
+ *      TlmRangeError if the RW-X Inertia telemetry value was outside of the range 0 kg.m^2 to 0.001 kg.m^2
+ *      TlmRangeError if the RW-Y Inertia telemetry value was outside of the range 0 kg.m^2 to 0.001 kg.m^2
+ *      TlmRangeError if the RW-Z Inertia telemetry value was outside of the range 0 kg.m^2 to 0.001 kg.m^2
+ *      TlmRangeError if the RW Torque Increment telemetry value was outside of the range 0 N.m to 0.1 N.m
+ *      TlmRangeError if the Primary MTM X-Bias d1 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Primary MTM Y-Bias d1 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Primary MTM Z-Bias d1 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Primary MTM X-Bias d2 telemetry value was outside of the range -10000  to 10000 
+ *      TlmRangeError if the Primary MTM Y-Bias d2 telemetry value was outside of the range -10000  to 10000 
+ *      TlmRangeError if the Primary MTM Z-Bias d2 telemetry value was outside of the range -10000  to 10000 
+ *      TlmRangeError if the Primary MTM X-Sens s1 telemetry value was outside of the range -1  to 1 
+ *      TlmRangeError if the Primary MTM Y-Sens s1 telemetry value was outside of the range -1  to 1 
+ *      TlmRangeError if the Primary MTM Z-Sens s1 telemetry value was outside of the range -1  to 1 
+ *      TlmRangeError if the Primary MTM X-Sens s2 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Primary MTM Y-Sens s2 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Primary MTM Z-Sens s2 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Redundant MTM X-Bias d1 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Redundant MTM Y-Bias d1 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Redundant MTM Z-Bias d1 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Redundant MTM X-Bias d2 telemetry value was outside of the range -10000  to 10000 
+ *      TlmRangeError if the Redundant MTM Y-Bias d2 telemetry value was outside of the range -10000  to 10000 
+ *      TlmRangeError if the Redundant MTM Z-Bias d2 telemetry value was outside of the range -10000  to 10000 
+ *      TlmRangeError if the Redundant MTM X-Sens s1 telemetry value was outside of the range -1  to 1 
+ *      TlmRangeError if the Redundant MTM Y-Sens s1 telemetry value was outside of the range -1  to 1 
+ *      TlmRangeError if the Redundant MTM Z-Sens s1 telemetry value was outside of the range -1  to 1 
+ *      TlmRangeError if the Redundant MTM X-Sens s2 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Redundant MTM Y-Sens s2 telemetry value was outside of the range -10  to 10 
+ *      TlmRangeError if the Redundant MTM Z-Sens s2 telemetry value was outside of the range -10  to 10 
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsSystemConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsSystemConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ADCS Temperatures telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsTemperatures1_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsTemperatures1Tlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Rate sensor temperatures telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_AdcsTemperatures2_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAdcsTemperatures2Tlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ASGP4 TLEs telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Asgp4KepTle_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractAsgp4KepTleTlm(uint8_t* rxBuffer, CUBEACP_Asgp4KepTle_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Augmented-SGP4 Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_ASgp4Params_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractASgp4ParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Commanded Attitude Angles telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CmdAttitude_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ *      TlmRangeError if the Commanded Roll Angle telemetry value was outside of the range -9000 deg to 9000 deg
+ *      TlmRangeError if the Commanded Pitch Angle telemetry value was outside of the range -18000 deg to 18000 deg
+ *      TlmRangeError if the Commanded Yaw Angle telemetry value was outside of the range -18000 deg to 18000 deg
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCmdAttitudeTlm(uint8_t* rxBuffer, CUBEACP_CmdAttitude_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Tracking Controller Target Reference telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CmdTrackingTarget_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ *      TlmRangeError if the Geocentric longitude of target telemetry value was outside of the range 0 deg to 360 deg
+ *      TlmRangeError if the Geocentric latitude of target telemetry value was outside of the range -90 deg to 90 deg
+ *      TlmRangeError if the Geocentric altitude of target telemetry value was outside of the range -20000 meter to 40000000 meter
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCmdTrackingTargetTlm(uint8_t* rxBuffer, CUBEACP_CmdTrackingTarget_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Coarse Sun Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CoarseSunVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCoarseSunVecTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a JPG Conversion Progress telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_ConversionProgress_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractConversionProgressTlm(uint8_t* rxBuffer, CUBEACP_ConversionProgress_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CSS Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CssConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCssConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeACP State telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CubeACPState_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCubeACPStateTlm(uint8_t* rxBuffer, CUBEACP_CubeACPState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeControl Current Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CubeControlCurrents_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCubeControlCurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeSense1 Current Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CubeSense1Currents_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCubeSense1CurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeSense2 Current Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CubeSense2Currents_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCubeSense2CurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeSense Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CubeSenseConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCubeSenseConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Current ADCS State telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CurrentAdcsState_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCurrentAdcsStateTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Current ADCS State 2 telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_CurrentAdcsState2_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractCurrentAdcsState2Tlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Detumbling Control Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_DetumbleParams_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractDetumbleParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimated Attitude Angles telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_EstimAttitude_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractEstimAttitudeTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimation Data telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_EstimData_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractEstimDataTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimated Gyro Bias telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_EstimGyroBias_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractEstimGyroBiasTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimation Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_EstimParams_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractEstimParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimated Quaternion telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_EstimQuaternion_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractEstimQuaternionTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimated Angular Rates telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_EstimRates_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractEstimRatesTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Fine Estimated Angular Rates telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_FineEstimRates_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractFineEstimRatesTlm(uint8_t* rxBuffer, CUBEACP_FineEstimRates_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Fine Sun Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_FineSunVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractFineSunVecTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Rate Gyro Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_GyroConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractGyroConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Status of Image Capture and Save Operation telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_ImageSaveStatus_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractImageSaveStatusTlm(uint8_t* rxBuffer, CUBEACP_ImageSaveStatus_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Inertial Pointing Reference Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_InertialPointReference_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractInertialPointReferenceTlm(uint8_t* rxBuffer, CUBEACP_InertialPointReference_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Estimation Innovation Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_InnovationVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractInnovationVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a SD Log1 Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_LogSdConfig1_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractLogSdConfig1Tlm(uint8_t* rxBuffer, CUBEACP_LogSdConfig1_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a SD Log2 Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_LogSdConfig2_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractLogSdConfig2Tlm(uint8_t* rxBuffer, CUBEACP_LogSdConfig2_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a UART Log Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_LogUartConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractLogUartConfigTlm(uint8_t* rxBuffer, CUBEACP_LogUartConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Magnetometer Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_MagConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractMagConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Magnetic Field Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_MagField_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractMagFieldTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Secondary Magnetometer Raw Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_MagRaw2_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractMagRaw2Tlm(uint8_t* rxBuffer, CUBEACP_MagRaw2_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Magnetorquer Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_MagtorqConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractMagtorqConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Magnetorquer Command telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_MagTorquerCmd_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractMagTorquerCmdTlm(uint8_t* rxBuffer, CUBEACP_ActuatorCmd_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a IGRF Modelled Magnetic Field Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_ModelMagVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractModelMagVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Modelled Sun Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_ModelSunVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractModelSunVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Moment of Inertia Matrix telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_MoI_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractMoITlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Nadir Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_NadirVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractNadirVecTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a SGP4 Orbit Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_OrbitParameters_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ *      TlmRangeError if the Inclination telemetry value was outside of the range 0 deg to 180 deg
+ *      TlmRangeError if the Eccentricity telemetry value was outside of the range 0  to 1 
+ *      TlmRangeError if the Right-ascension of the Ascending Node telemetry value was outside of the range 0 deg to 360 deg
+ *      TlmRangeError if the Argument of Perigee telemetry value was outside of the range 0 deg to 360 deg
+ *      TlmRangeError if the B-Star drag term telemetry value was outside of the range 0  to 1 
+ *      TlmRangeError if the Mean Motion telemetry value was outside of the range 0 orbits/day to 20 orbits/day
+ *      TlmRangeError if the Mean Anomaly telemetry value was outside of the range 0 deg to 360 deg
+ *      TlmRangeError if the Epoch telemetry value was outside of the range 0 year.day to 100000 year.day
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractOrbitParametersTlm(uint8_t* rxBuffer, CUBEACP_OrbitParameters_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a ECEF Position telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_PositionECEF_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractPositionECEFTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Satellite Position (ECI) telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_PositionECI_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractPositionECITlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Satellite Position (LLH) telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_PositionLLH_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractPositionLLHTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Quaternion Covariance telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_QuaternionCovar_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractQuaternionCovarTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Quaternion Error Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_QuaternionErrVec_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractQuaternionErrVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Angular Rate Covariance telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RateCovar_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRateCovarTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Rate Sensor Rates telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RateSensor_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRateSensorTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw Cam1 Sensor telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawCam1Sens_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawCam1SensTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw Cam2 Sensor telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawCam2Sens_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawCam2SensTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw CSS 1 to 6 telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawCss1_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawCss1Tlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw CSS 7 to 10 telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawCss2_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawCss2Tlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw GPS Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawGPS_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawGPSTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw GPS Status telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawGpsStatus_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsStatusTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw GPS Time telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawGpsTime_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsTimeTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw GPS X telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawGpsX_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsXTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw GPS Y telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawGpsY_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsYTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw GPS Z telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawGpsZ_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsZTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw Magnetometer telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawMagnetometer_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawMagnetometerTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw Rate Sensor telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawRate_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawRateTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw Sensor Measurements telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawSensor_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawSensorTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Raw Star Tracker telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RawStarTracker_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRawStarTrackerTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Redundant Magnetometer Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RedMagConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRedMagConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Reaction Wheel Control Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_RWheelParams_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractRWheelParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Wheel Speed Commands telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_SpeedCmd_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractSpeedCmdTlm(uint8_t* rxBuffer, CUBEACP_ActuatorCmd_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 1 Body Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star1Body_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar1BodyTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 1 Orbit Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star1Orbit_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar1OrbitTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 1 Raw Data telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star1Raw_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar1RawTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 2 Body Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star2Body_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar2BodyTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 2 Orbit Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star2Orbit_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar2OrbitTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 2 Raw Data telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star2Raw_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar2RawTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 3 Body Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star3Body_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar3BodyTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 3 Orbit Vector telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star3Orbit_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar3OrbitTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star 3 Raw Data telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_Star3Raw_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStar3RawTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Star Tracker Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeStar Estimated Quaternion telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarEstimQ_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarEstimQTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a CubeStar Estimated Rates telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarEstimRate_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarEstimRateTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star Magnitude telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarMagnitude_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarMagnitudeTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star Performance1 telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarPerformance1_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarPerformance1Tlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star Performance2 telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarPerformance2_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarPerformance2Tlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Star Timing telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_StarTiming_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractStarTimingTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Tracking Controller Gain Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_TrackingParams_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractTrackingParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a User-coded Controller and Estimator Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_UserConEstParams_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractUserConEstParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Satellite Velocity (ECI) telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_VelocityECI_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractVelocityECITlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Wheel Configuration telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_WheelConfig_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractWheelConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Wheel Currents telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_WheelCurrents_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractWheelCurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Wheel Speed telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_WheelSpeed_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractWheelSpeedTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal);
+
+/***************************************************************************//**
+ * Decode a Set Y-Wheel Control Parameters telemetry frame from the CubeACP
+ *
+ * @param[in] rxBuffer
+ *   Buffer containing raw bytes
+ * @param[in] returnVal
+ *   Pointer to a CUBEACP_YWheelParams_t struct in which the telemetry will be returned.
+ * @return
+ *   Returns a value from the CUBEADCS_Result_t enumeration:
+ *      CubeLibOk if the telemetry was decoded without error
+ *      PointerIsNull if the input parameter, returnVal, was NULL
+ ******************************************************************************/
+CUBEADCS_Result_t CUBEACP_ExtractYWheelParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal);
+
+/***************************************************************************//**
+ * Send a ADCS Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] magtorq1
+ *   Magnetorquer 1 Configuration
+ * @param[in] magtorq2
+ *   Magnetorquer 2 Configuration
+ * @param[in] magtorq3
+ *   Magnetorquer 3 Configuration
+ * @param[in] rW1Conf
+ *   RW1 Configuration
+ * @param[in] rW2Conf
+ *   RW2 Configuration
+ * @param[in] rW3Conf
+ *   RW3 Configuration
+ * @param[in] rW4Conf
+ *   RW4 or Momentum wheel Configuration
+ * @param[in] gyro1Conf
+ *   Gyro1 Configuration
+ * @param[in] gyro2Conf
+ *   Gyro2 Configuration
+ * @param[in] gyro3Conf
+ *   Gyro3 Configuration
+ * @param[in] xRateOffset
+ *   X-Rate Sensor Offset
+ *   (in [deg/s] units)
+ * @param[in] yRateOffset
+ *   Y-Rate Sensor Offset
+ *   (in [deg/s] units)
+ * @param[in] zRateOffset
+ *   Z-Rate Sensor Offset
+ *   (in [deg/s] units)
+ * @param[in] rateSensorMult
+ *   Multiplier of rate sensor measurement
+ * @param[in] css1Conf
+ *   CSS1 Configuration
+ * @param[in] css2Conf
+ *   CSS2 Configuration
+ * @param[in] css3Conf
+ *   CSS3 Configuration
+ * @param[in] css4Conf
+ *   CSS4 Configuration
+ * @param[in] css5Conf
+ *   CSS5 Configuration
+ * @param[in] css6Conf
+ *   CSS6 Configuration
+ * @param[in] css7Conf
+ *   CSS7 Configuration
+ * @param[in] css8Conf
+ *   CSS8 Configuration
+ * @param[in] css9Conf
+ *   CSS9 Configuration
+ * @param[in] css10Conf
+ *   CSS10 Configuration
+ * @param[in] css1Scale
+ *   CSS1 Relative Scaling Factor
+ * @param[in] css2Scale
+ *   CSS2 Relative Scaling Factor
+ * @param[in] css3Scale
+ *   CSS3 Relative Scaling Factor
+ * @param[in] css4Scale
+ *   CSS4 Relative Scaling Factor
+ * @param[in] css5Scale
+ *   CSS5 Relative Scaling Factor
+ * @param[in] css6Scale
+ *   CSS6 Relative Scaling Factor
+ * @param[in] css7Scale
+ *   CSS7 Relative Scaling Factor
+ * @param[in] css8Scale
+ *   CSS8 Relative Scaling Factor
+ * @param[in] css9Scale
+ *   CSS9 Relative Scaling Factor
+ * @param[in] css10Scale
+ *   CSS10 Relative Scaling Factor
+ * @param[in] cssMinimum
+ *   CSS Threshold
+ * @param[in] cam1Angle1
+ *   Cam1 Sensor Mounting Transform Alpha Angle
+ *   (in [deg] units)
+ * @param[in] cam1Angle2
+ *   Cam1 Sensor Mounting Transform Beta Angle
+ *   (in [deg] units)
+ * @param[in] cam1Angle3
+ *   Cam1 Sensor Mounting Transform Gamma Angle
+ *   (in [deg] units)
+ * @param[in] cam1Threshold
+ *   Cam1 detection threshold
+ * @param[in] cam1AutoAdj
+ *   0 = disabled and 1 = enabled
+ * @param[in] reserved
+ *   
+ * @param[in] cam1Exposure
+ *   exposure time register value
+ * @param[in] cam1BoreX
+ *   X Pixel location of Cam1 boresight
+ *   (in [pixels] units)
+ * @param[in] cam1BoreY
+ *   Y Pixel location of Cam1 boresight
+ *   (in [pixels] units)
+ * @param[in] cam2Angle1
+ *   Cam2 Sensor Mounting Transform Alpha Angle
+ *   (in [deg] units)
+ * @param[in] cam2Angle2
+ *   Cam2 Sensor Mounting Transform Beta Angle
+ *   (in [deg] units)
+ * @param[in] cam2Angle3
+ *   Cam2 Sensor Mounting Transform Gamma Angle
+ *   (in [deg] units)
+ * @param[in] cam2Threshold
+ *   Cam2 detection threshold
+ * @param[in] cam2AutoAdj
+ *   0 = disabled and 1 = enabled
+ * @param[in] reserved
+ *   
+ * @param[in] cam2Exposure
+ *   exposure time register value
+ * @param[in] cam2BoreX
+ *   X Pixel location of Cam2 boresight
+ *   (in [pixels] units)
+ * @param[in] cam2BoreY
+ *   Y Pixel location of Cam2 boresight
+ *   (in [pixels] units)
+ * @param[in] nadirMaxDeviationPercentage
+ *   Percentage of measured angular radius as edge's maximum allowable deviation
+ * @param[in] nadirMaxBadEdges
+ *   Maximum amount of edges allowed outside maximum deviation (>50 to disable)
+ * @param[in] nadirMaxRadius
+ *   Maximum Radius
+ *   (in [°] units)
+ * @param[in] nadirMinRadius
+ *   Minimum Radius
+ *   (in [°] units)
+ * @param[in] cam1MaskArea1Xmin
+ *   Cam 1 Minimum X of Area 1
+ * @param[in] cam1MaskArea1Xmax
+ *   Cam 1 Maximum X of Area 1
+ * @param[in] cam1MaskArea1Ymin
+ *   Cam 1 Minimum Y of Area 1
+ * @param[in] cam1MaskArea1Ymax
+ *   Cam 1 Maximum Y of Area 1
+ * @param[in] cam1MaskArea2Xmin
+ *   Cam 1 Minimum X of Area 2
+ * @param[in] cam1MaskArea2Xmax
+ *   Cam 1 Maximum X of Area 2
+ * @param[in] cam1MaskArea2Ymin
+ *   Cam 1 Minimum Y of Area 2
+ * @param[in] cam1MaskArea2Ymax
+ *   Cam 1 Maximum Y of Area 2
+ * @param[in] cam1MaskArea3Xmin
+ *   Cam 1 Minimum X of Area 3
+ * @param[in] cam1MaskArea3Xmax
+ *   Cam 1 Maximum X of Area 3
+ * @param[in] cam1MaskArea3Ymin
+ *   Cam 1 Minimum Y of Area 3
+ * @param[in] cam1MaskArea3Ymax
+ *   Cam 1 Maximum Y of Area 3
+ * @param[in] cam1MaskArea4Xmin
+ *   Cam 1 Minimum X of Area 4
+ * @param[in] cam1MaskArea4Xmax
+ *   Cam 1 Maximum X of Area 4
+ * @param[in] cam1MaskArea4Ymin
+ *   Cam 1 Minimum Y of Area 4
+ * @param[in] cam1MaskArea4Ymax
+ *   Cam 1 Maximum Y of Area 4
+ * @param[in] cam1MaskArea5Xmin
+ *   Cam 1 Minimum X of Area 5
+ * @param[in] cam1MaskArea5Xmax
+ *   Cam 1 Maximum X of Area 5
+ * @param[in] cam1MaskArea5Ymin
+ *   Cam 1 Minimum Y of Area 5
+ * @param[in] cam1MaskArea5Ymax
+ *   Cam 1 Maximum Y of Area 5
+ * @param[in] cam2MaskArea1Xmin
+ *   Cam 2 Minimum X of Area 1
+ * @param[in] cam2MaskArea1Xmax
+ *   Cam 2 Maximum X of Area 1
+ * @param[in] cam2MaskArea1Ymin
+ *   Cam 2 Minimum Y of Area 1
+ * @param[in] cam2MaskArea1Ymax
+ *   Cam 2 Maximum Y of Area 1
+ * @param[in] cam2MaskArea2Xmin
+ *   Cam 2 Minimum X of Area 2
+ * @param[in] cam2MaskArea2Xmax
+ *   Cam 2 Maximum X of Area 2
+ * @param[in] cam2MaskArea2Ymin
+ *   Cam 2 Minimum Y of Area 2
+ * @param[in] cam2MaskArea2Ymax
+ *   Cam 2 Maximum Y of Area 2
+ * @param[in] cam2MaskArea3Xmin
+ *   Cam 2 Minimum X of Area 3
+ * @param[in] cam2MaskArea3Xmax
+ *   Cam 2 Maximum X of Area 3
+ * @param[in] cam2MaskArea3Ymin
+ *   Cam 2 Minimum Y of Area 3
+ * @param[in] cam2MaskArea3Ymax
+ *   Cam 2 Maximum Y of Area 3
+ * @param[in] cam2MaskArea4Xmin
+ *   Cam 2 Minimum X of Area 4
+ * @param[in] cam2MaskArea4Xmax
+ *   Cam 2 Maximum X of Area 4
+ * @param[in] cam2MaskArea4Ymin
+ *   Cam 2 Minimum Y of Area 4
+ * @param[in] cam2MaskArea4Ymax
+ *   Cam 2 Maximum Y of Area 4
+ * @param[in] cam2MaskArea5Xmin
+ *   Cam 2 Minimum X of Area 5
+ * @param[in] cam2MaskArea5Xmax
+ *   Cam 2 Maximum X of Area 5
+ * @param[in] cam2MaskArea5Ymin
+ *   Cam 2 Minimum Y of Area 5
+ * @param[in] cam2MaskArea5Ymax
+ *   Cam 2 Maximum Y of Area 5
+ * @param[in] magmAngle1
+ *   Magnetometer Mounting Transform Alpha Angle
+ *   (in [deg] units)
+ * @param[in] magmAngle2
+ *   Magnetometer Mounting Transform Beta Angle
+ *   (in [deg] units)
+ * @param[in] magmAngle3
+ *   Magnetometer Mounting Transform Gamma Angle
+ *   (in [deg] units)
+ * @param[in] magmOffset1
+ *   Magnetometer Channel 1 Offset
+ * @param[in] magmOffset2
+ *   Magnetometer Channel 2 Offset
+ * @param[in] magmOffset3
+ *   Magnetometer Channel 3 Offset
+ * @param[in] magmSens11
+ *   Magnetometer Sensitivity Matrix S11
+ * @param[in] magmSens22
+ *   Magnetometer Sensitivity Matrix S22
+ * @param[in] magmSens33
+ *   Magnetometer Sensitivity Matrix S33
+ * @param[in] magmSens12
+ *   Magnetometer Sensitivity Matrix S12
+ * @param[in] magmSens13
+ *   Magnetometer Sensitivity Matrix S13
+ * @param[in] magmSens21
+ *   Magnetometer Sensitivity Matrix S21
+ * @param[in] magmSens23
+ *   Magnetometer Sensitivity Matrix S23
+ * @param[in] magmSens31
+ *   Magnetometer Sensitivity Matrix S31
+ * @param[in] magmSens32
+ *   Magnetometer Sensitivity Matrix S32
+ * @param[in] mredAngle1
+ *   Redundant Magnetometer Mounting Transform Alpha Angle
+ *   (in [deg] units)
+ * @param[in] mredAngle2
+ *   Redundant Magnetometer Mounting Transform Beta Angle
+ *   (in [deg] units)
+ * @param[in] mredAngle3
+ *   Redundant Magnetometer Mounting Transform Gamma Angle
+ *   (in [deg] units)
+ * @param[in] mredOffset1
+ *   Redundant Magnetometer Channel 1 Offset
+ * @param[in] mredOffset2
+ *   Redundant Magnetometer Channel 2 Offset
+ * @param[in] mredOffset3
+ *   Redundant Magnetometer Channel 3 Offset
+ * @param[in] mredSens11
+ *   Redundant Magnetometer Sensitivity Matrix S11
+ * @param[in] mredSens22
+ *   Redundant Magnetometer Sensitivity Matrix S22
+ * @param[in] mredSens33
+ *   Redundant Magnetometer Sensitivity Matrix S33
+ * @param[in] mredSens12
+ *   Redundant Magnetometer Sensitivity Matrix S12
+ * @param[in] mredSens13
+ *   Redundant Magnetometer Sensitivity Matrix S13
+ * @param[in] mredSens21
+ *   Redundant Magnetometer Sensitivity Matrix S21
+ * @param[in] mredSens23
+ *   Redundant Magnetometer Sensitivity Matrix S23
+ * @param[in] mredSens31
+ *   Redundant Magnetometer Sensitivity Matrix S31
+ * @param[in] mredSens32
+ *   Redundant Magnetometer Sensitivity Matrix S32
+ * @param[in] starAngle1
+ *   StarTracker Mounting Transform Alpha Angle
+ *   (in [deg] units)
+ * @param[in] starAngle2
+ *   StarTracker Mounting Transform Beta Angle
+ *   (in [deg] units)
+ * @param[in] starAngle3
+ *   StarTracker Mounting Transform Gamma Angle
+ *   (in [deg] units)
+ * @param[in] starExposure
+ *   exposure time register value
+ * @param[in] starGain
+ *   analog gain register value
+ * @param[in] detectionThreshold
+ *   StarTracker detection threshold
+ * @param[in] starThreshold
+ *   StarTracker star threshold
+ * @param[in] maxStarMatched
+ *   Maximum of stars that the star tracker will match
+ * @param[in] starTimeoutTime
+ *   Time allowed for detection
+ * @param[in] maxStarPixel
+ *   Maximum pixels in a star
+ * @param[in] minStarPixel
+ *   Minimum pixels in a star
+ * @param[in] starErrorMargin
+ *   % Error margin of the star identification
+ *   (in [%] units)
+ * @param[in] starDelayTime
+ *   Delay Time
+ *   (in [milliseconds] units)
+ * @param[in] starCentX
+ *   Pixel centroid X
+ *   (valid range is between -5000  and 5000 )
+ * @param[in] starCentY
+ *   Pixel centroid Y
+ *   (valid range is between -5000  and 5000 )
+ * @param[in] starFocal
+ *   Star Tracker Focal Length
+ *   (in [mm] units)
+ *   (valid range is between 5 mm and 7 mm)
+ * @param[in] starLensK1
+ *   First radial distortion coefficient
+ *   (in [gain] units)
+ *   (valid range is between -1 gain and 1 gain)
+ * @param[in] starLensK2
+ *   Second radial distortion coefficient
+ *   (in [gain] units)
+ *   (valid range is between -1 gain and 1 gain)
+ * @param[in] starLensP1
+ *   First tangential distortion coefficient
+ *   (in [gain] units)
+ *   (valid range is between -1 gain and 1 gain)
+ * @param[in] starLensP2
+ *   Second tangential distortion coefficients
+ *   (in [gain] units)
+ *   (valid range is between -1 gain and 1 gain)
+ * @param[in] starWindowWidth
+ *   Window width
+ * @param[in] starTrackingMargin
+ *   Tracking Margin
+ * @param[in] starValidationMargin
+ *   Validation Margin
+ * @param[in] starModuleEnable
+ *   Module Enable
+ * @param[in] starLocationPredictionEnable
+ *   LocationPredictionEnable
+ * @param[in] reserved
+ *   
+ * @param[in] starSearchWidth
+ *   Search Width
+ * @param[in] ks
+ *   Detumbling Spin Gain (Ks)
+ *   (valid range is between 0  and 10000 )
+ * @param[in] kd
+ *   Detumbling Damping Gain (Kd)
+ *   (valid range is between 0  and 10000 )
+ * @param[in] wy_ref
+ *   Reference spin rate (wy-ref). Must always be smaller than 0 for Y-spin
+ *   (in [deg/s] units)
+ *   (valid range is between -32000 deg/s and 32000 deg/s)
+ * @param[in] kdf
+ *   Fast BDot Detumbling Gain (Kdf)
+ *   (valid range is between 0  and 100 )
+ * @param[in] kh
+ *   Y-Momentum Control Gain (Kh)
+ *   (valid range is between 0  and 10000 )
+ * @param[in] kn
+ *   Y-momentum Nutation Damping Gain (Kn)
+ *   (valid range is between 0  and 10000 )
+ * @param[in] kp1
+ *   Y-momentum Proportional Gain (Kp1)
+ *   (valid range is between 0  and 100 )
+ * @param[in] kd1
+ *   Y-momentum Derivative Gain (Kd1)
+ *   (valid range is between 0  and 100 )
+ * @param[in] h_ref
+ *   Reference Wheel Momentum (H-ref). Must always be smaller than 0
+ *   (in [Nms] units)
+ *   (valid range is between -10 Nms and 0 Nms)
+ * @param[in] kp2
+ *   RWheel Proportional Gain (Kp2)
+ *   (valid range is between 0  and 100 )
+ * @param[in] kd2
+ *   RWheel Derivative Gain (Kd2)
+ *   (valid range is between 0  and 100 )
+ * @param[in] h_bias
+ *   Y-Wheel Bias Momentum (H-bias)
+ *   (in [Nms] units)
+ *   (valid range is between -10 Nms and 10 Nms)
+ * @param[in] sunPointFacet
+ *   Satellite body axis that will align with sun vector
+ * @param[in] wheelErrorHandling
+ *   Enable/disable automatic transition from wheel control modes to Y-Thomson mode in case of wheel error
+ * @param[in] kp3
+ *   Tracking Proportional Gain (Kp3)
+ *   (valid range is between 0  and 100 )
+ * @param[in] kd3
+ *   Tracking Derivative Gain (Kd3)
+ *   (valid range is between 0  and 100 )
+ * @param[in] ki3
+ *   Tracking Integral Gain (Ki3)
+ *   (valid range is between 0  and 100 )
+ * @param[in] targetTrackFacet
+ *   Satellite body axis that will point to target
+ * @param[in] ixx
+ *   Moment Of Inertia - Ixx
+ *   (in [kg.m^2] units)
+ *   (valid range is between 0 kg.m^2 and 10 kg.m^2)
+ * @param[in] iyy
+ *   Moment Of Inertia - Iyy
+ *   (in [kg.m^2] units)
+ *   (valid range is between 0 kg.m^2 and 10 kg.m^2)
+ * @param[in] izz
+ *   Moment Of Inertia - Izz
+ *   (in [kg.m^2] units)
+ *   (valid range is between 0 kg.m^2 and 10 kg.m^2)
+ * @param[in] ixy
+ *   Product Of Inertia - Ixy
+ *   (in [kg.m^2] units)
+ *   (valid range is between -10 kg.m^2 and 10 kg.m^2)
+ * @param[in] ixz
+ *   Product Of Inertia - Ixz
+ *   (in [kg.m^2] units)
+ *   (valid range is between -10 kg.m^2 and 10 kg.m^2)
+ * @param[in] iyz
+ *   Product Of Inertia - Iyz
+ *   (in [kg.m^2] units)
+ *   (valid range is between -10 kg.m^2 and 10 kg.m^2)
+ * @param[in] magRateNoise
+ *   Magnetometer Rate Filter System Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] ekfSysNoise
+ *   EKF System Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] cssNoise
+ *   CSS Measurement Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] sunNoise
+ *   Sun Sensor Measurement Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] nadirNoise
+ *   Nadir Sensor Measurement Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] magNoise
+ *   Magnetometer Measurement Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] starNoise
+ *   Star Tracker Measurement Noise
+ *   (valid range is between 0  and 100 )
+ * @param[in] useSunEst
+ *   Use Sun Sensor measurement in EKF
+ * @param[in] useNadirEst
+ *   Use Nadir Sensor measurement in EKF
+ * @param[in] useCssEst
+ *   Use CSS measurement in EKF
+ * @param[in] useStarEst
+ *   Use Star Tracker measurement in EKF
+ * @param[in] terminatorCheck
+ *   Select to ignore Nadir sensor measurements when terminator is in FOV
+ * @param[in] autoRecoverMtm
+ *   Select whether automatic switch to redundant magnetometer should occur in case of failure
+ * @param[in] magMode
+ *   Mode describing which magnetometer is used for estimation and control
+ * @param[in] magRawTlm2Selection
+ *   Select which magnetometer and sampling to use for 2nd raw magnetometer tlm frame
+ * @param[in] rateSensorErrorHandling
+ *   Enable/disable automatic transition from MEMS rate estimation mode to RKF in case of rate sensor error
+ * @param[in] wheelPowerOn30sDelay
+ *   Delay wheel communications for 30s after power-cycle
+ * @param[in] reserved
+ *   
+ * @param[in] cam1Cam2Period
+ *   Cam1 and Cam2 sensor sampling period. Lower four bits are Cam1 period and upper four bits the Cam2 period. Setting period to zero for sensor will disable sampling of sensor.
+ *   (in [s] units)
+ * @param[in] aInclCoeff
+ *   Inclination filter coefficient
+ * @param[in] aRaanCoeff
+ *   RAAN filter coefficient
+ * @param[in] aEccCoeff
+ *   Eccentricity filter coefficient
+ * @param[in] aArgPerCoeff
+ *   Argument of perigee filter coefficient
+ * @param[in] aTimeCoeff
+ *   Time filter coefficient
+ * @param[in] aPosCoeff
+ *   Position filter coefficient
+ * @param[in] asgp4MaxPosError
+ *   Maximum position error for asgp4 to continue working
+ * @param[in] asgp4Filter
+ *   The type of filter asgp4 is using
+ * @param[in] asgp4Xp
+ *   Polar coefficient xp
+ * @param[in] asgp4Yp
+ *   Polar coefficient yp
+ * @param[in] asgp4GpsRollover
+ *   GPS roll over number
+ * @param[in] asgp4PosSdTh
+ *   Maximum position standard deviation for asgp4 to operate
+ * @param[in] asgp4VelSdTh
+ *   Maximum velocity standard deviation for asgp4 to operate
+ * @param[in] asgp4MinSat
+ *   Minimum satellites for asgp4 to operate
+ * @param[in] asgp4TimeGain
+ *   Time offset compensation gain
+ * @param[in] asgp4MaxLag
+ *   Maximum lagged timestamp measurements to incorporate
+ * @param[in] asgp4MinSamples
+ *   Minimum samples to use for asgp4 process
+ * @param[in] userConSettings
+ *   Settings for user coded control mode(s)
+ * @param[in] userEstSettings
+ *   Settings for user coded estimation mode(s)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, magtorq1, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, magtorq2, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, magtorq3, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, rW1Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, rW2Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, rW3Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, rW4Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, gyro1Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, gyro2Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, gyro3Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css1Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css2Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css3Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css4Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css5Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css6Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css7Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css8Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css9Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, css10Conf, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, starCentX, was outside of the range -5000  to 5000 
+ *      TcInvalidParam if the input parameter, starCentY, was outside of the range -5000  to 5000 
+ *      TcInvalidParam if the input parameter, starFocal, was outside of the range 5 mm to 7 mm
+ *      TcInvalidParam if the input parameter, starLensK1, was outside of the range -1 gain to 1 gain
+ *      TcInvalidParam if the input parameter, starLensK2, was outside of the range -1 gain to 1 gain
+ *      TcInvalidParam if the input parameter, starLensP1, was outside of the range -1 gain to 1 gain
+ *      TcInvalidParam if the input parameter, starLensP2, was outside of the range -1 gain to 1 gain
+ *      TcInvalidParam if the input parameter, ks, was outside of the range 0  to 10000 
+ *      TcInvalidParam if the input parameter, kd, was outside of the range 0  to 10000 
+ *      TcInvalidParam if the input parameter, wy_ref, was outside of the range -32000 deg/s to 32000 deg/s
+ *      TcInvalidParam if the input parameter, kdf, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, kh, was outside of the range 0  to 10000 
+ *      TcInvalidParam if the input parameter, kn, was outside of the range 0  to 10000 
+ *      TcInvalidParam if the input parameter, kp1, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, kd1, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, h_ref, was outside of the range -10 Nms to 0 Nms
+ *      TcInvalidParam if the input parameter, kp2, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, kd2, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, h_bias, was outside of the range -10 Nms to 10 Nms
+ *      TcInvalidParam if the input parameter, sunPointFacet, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, kp3, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, kd3, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, ki3, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, targetTrackFacet, was not a valid CUBEACP_AxisSelect_t enumeration
+ *      TcInvalidParam if the input parameter, ixx, was outside of the range 0 kg.m^2 to 10 kg.m^2
+ *      TcInvalidParam if the input parameter, iyy, was outside of the range 0 kg.m^2 to 10 kg.m^2
+ *      TcInvalidParam if the input parameter, izz, was outside of the range 0 kg.m^2 to 10 kg.m^2
+ *      TcInvalidParam if the input parameter, ixy, was outside of the range -10 kg.m^2 to 10 kg.m^2
+ *      TcInvalidParam if the input parameter, ixz, was outside of the range -10 kg.m^2 to 10 kg.m^2
+ *      TcInvalidParam if the input parameter, iyz, was outside of the range -10 kg.m^2 to 10 kg.m^2
+ *      TcInvalidParam if the input parameter, magRateNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, ekfSysNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, cssNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, sunNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, nadirNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, magNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, starNoise, was outside of the range 0  to 100 
+ *      TcInvalidParam if the input parameter, magMode, was not a valid CUBEACP_MagModeVal_t enumeration
+ *      TcInvalidParam if the input parameter, magRawTlm2Selection, was not a valid CUBEACP_MagModeVal_t enumeration
+ *      TcInvalidParam if the input parameter, asgp4Filter, was not a valid CUBEACP_AsgpFilter_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatAdcsConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a ADCS Run Mode command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] enabled
+ *   Set ADCS enabled state. When disabled the CubeACP will not use the ADCS I2C bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, enabled, was not a valid CUBEACP_AdcsRunMode_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatAdcsEnabledCmd(uint8_t* tcBuffer, CUBEACP_AdcsRunMode_t enabled);
+
+/***************************************************************************//**
+ * Send a ADCS Power Control command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] cubeControlSignalPower
+ *   Control power to electronics of CubeControl Signal PIC
+ * @param[in] cubeControlMotorPower
+ *   Control power to electronics of CubeControl Motor PIC
+ * @param[in] cubeSense1Power
+ *   Control power to the CubeSense1
+ * @param[in] cubeSense2Power
+ *   Control power to the CubeSense2
+ * @param[in] cubeStarPower
+ *   Control power to the CubeStar
+ * @param[in] cubeWheel1Power
+ *   Control power to the CubeWheel1
+ * @param[in] cubeWheel2Power
+ *   Control power to the CubeWheel2
+ * @param[in] cubeWheel3Power
+ *   Control power to the CubeWheel3
+ * @param[in] motorPower
+ *   Control power to Motor electronics
+ * @param[in] gpsLnaPower
+ *   Control power to GPS LNA
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, cubeControlSignalPower, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, cubeControlMotorPower, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, cubeSense1Power, was not a valid CUBEACP_PowerSelectCubeSense_t enumeration
+ *      TcInvalidParam if the input parameter, cubeSense2Power, was not a valid CUBEACP_PowerSelectCubeSense_t enumeration
+ *      TcInvalidParam if the input parameter, cubeStarPower, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, cubeWheel1Power, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, cubeWheel2Power, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, cubeWheel3Power, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, motorPower, was not a valid CUBEACP_PowerSelect_t enumeration
+ *      TcInvalidParam if the input parameter, gpsLnaPower, was not a valid CUBEACP_PowerSelect_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatAdcsPowerCmd(uint8_t* tcBuffer, CUBEACP_AdcsPower_t* setVal);
+
+/***************************************************************************//**
+ * Send a ADCS System Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] acpType
+ *   ACP Type
+ * @param[in] specialControl
+ *   Special Control Selection
+ * @param[in] ccSignalVer
+ *   CubeControl Signal Version
+ * @param[in] ccMotorVer
+ *   CubeControl Motor Version
+ * @param[in] cs1Ver
+ *   CubeSense1 Version
+ * @param[in] cs2Ver
+ *   CubeSense2 Version
+ * @param[in] csCam1Type
+ *   CubeSense1 Camera Type
+ * @param[in] csCam2Type
+ *   CubeSense2 Camera Type
+ * @param[in] cubeStarVer
+ *   CubeStar Version
+ * @param[in] gpsType
+ *   GPS Type
+ * @param[in] hasRedMag
+ *   Redundant MTM Included
+ * @param[in] reserved
+ *   
+ * @param[in] mqx
+ *   Magnetorquer-X Max Dipole
+ *   (in [A.m^2] units)
+ *   (valid range is between 0 A.m^2 and 2 A.m^2)
+ * @param[in] mqy
+ *   Magnetorquer-Y Max Dipole
+ *   (in [A.m^2] units)
+ *   (valid range is between 0 A.m^2 and 2 A.m^2)
+ * @param[in] mqz
+ *   Magnetorquer-Z Max Dipole
+ *   (in [A.m^2] units)
+ *   (valid range is between 0 A.m^2 and 2 A.m^2)
+ * @param[in] mtTmin
+ *   Magnetorquer On-time Resolution
+ *   (in [s] units)
+ *   (valid range is between 0 s and 1 s)
+ * @param[in] mtTmax
+ *   Magnetorquer Maximum On-time
+ *   (in [s] units)
+ *   (valid range is between 0 s and 1 s)
+ * @param[in] nSatX
+ *   RW-X Maximum Torque
+ *   (in [N.m] units)
+ *   (valid range is between 0 N.m and 0.1 N.m)
+ * @param[in] nSatY
+ *   RW-Y Maximum Torque
+ *   (in [N.m] units)
+ *   (valid range is between 0 N.m and 0.1 N.m)
+ * @param[in] nSatZ
+ *   RW-Z Maximum Torque
+ *   (in [N.m] units)
+ *   (valid range is between 0 N.m and 0.1 N.m)
+ * @param[in] hSatX
+ *   RW-X Maximum Momentum
+ *   (in [Nms] units)
+ *   (valid range is between 0 Nms and 0.1 Nms)
+ * @param[in] hSatY
+ *   RW-Y Maximum Momentum
+ *   (in [Nms] units)
+ *   (valid range is between 0 Nms and 0.1 Nms)
+ * @param[in] hSatZ
+ *   RW-Z Maximum Momentum
+ *   (in [Nms] units)
+ *   (valid range is between 0 Nms and 0.1 Nms)
+ * @param[in] iwx
+ *   RW-X Inertia
+ *   (in [kg.m^2] units)
+ *   (valid range is between 0 kg.m^2 and 0.001 kg.m^2)
+ * @param[in] iwy
+ *   RW-Y Inertia
+ *   (in [kg.m^2] units)
+ *   (valid range is between 0 kg.m^2 and 0.001 kg.m^2)
+ * @param[in] iwz
+ *   RW-Z Inertia
+ *   (in [kg.m^2] units)
+ *   (valid range is between 0 kg.m^2 and 0.001 kg.m^2)
+ * @param[in] ndel
+ *   RW Torque Increment
+ *   (in [N.m] units)
+ *   (valid range is between 0 N.m and 0.1 N.m)
+ * @param[in] biasX_d1
+ *   Primary MTM X-Bias d1
+ *   (valid range is between -10  and 10 )
+ * @param[in] biasY_d1
+ *   Primary MTM Y-Bias d1
+ *   (valid range is between -10  and 10 )
+ * @param[in] biasZ_d1
+ *   Primary MTM Z-Bias d1
+ *   (valid range is between -10  and 10 )
+ * @param[in] biasX_d2
+ *   Primary MTM X-Bias d2
+ *   (valid range is between -10000  and 10000 )
+ * @param[in] biasY_d2
+ *   Primary MTM Y-Bias d2
+ *   (valid range is between -10000  and 10000 )
+ * @param[in] biasZ_d2
+ *   Primary MTM Z-Bias d2
+ *   (valid range is between -10000  and 10000 )
+ * @param[in] sensX_s1
+ *   Primary MTM X-Sens s1
+ *   (valid range is between -1  and 1 )
+ * @param[in] sensY_s1
+ *   Primary MTM Y-Sens s1
+ *   (valid range is between -1  and 1 )
+ * @param[in] sensZ_s1
+ *   Primary MTM Z-Sens s1
+ *   (valid range is between -1  and 1 )
+ * @param[in] sensX_s2
+ *   Primary MTM X-Sens s2
+ *   (valid range is between -10  and 10 )
+ * @param[in] sensY_s2
+ *   Primary MTM Y-Sens s2
+ *   (valid range is between -10  and 10 )
+ * @param[in] sensZ_s2
+ *   Primary MTM Z-Sens s2
+ *   (valid range is between -10  and 10 )
+ * @param[in] red_BiasX_d1
+ *   Redundant MTM X-Bias d1
+ *   (valid range is between -10  and 10 )
+ * @param[in] red_BiasY_d1
+ *   Redundant MTM Y-Bias d1
+ *   (valid range is between -10  and 10 )
+ * @param[in] red_BiasZ_d1
+ *   Redundant MTM Z-Bias d1
+ *   (valid range is between -10  and 10 )
+ * @param[in] red_BiasX_d2
+ *   Redundant MTM X-Bias d2
+ *   (valid range is between -10000  and 10000 )
+ * @param[in] red_BiasY_d2
+ *   Redundant MTM Y-Bias d2
+ *   (valid range is between -10000  and 10000 )
+ * @param[in] red_BiasZ_d2
+ *   Redundant MTM Z-Bias d2
+ *   (valid range is between -10000  and 10000 )
+ * @param[in] red_SensX_s1
+ *   Redundant MTM X-Sens s1
+ *   (valid range is between -1  and 1 )
+ * @param[in] red_SensY_s1
+ *   Redundant MTM Y-Sens s1
+ *   (valid range is between -1  and 1 )
+ * @param[in] red_SensZ_s1
+ *   Redundant MTM Z-Sens s1
+ *   (valid range is between -1  and 1 )
+ * @param[in] red_SensX_s2
+ *   Redundant MTM X-Sens s2
+ *   (valid range is between -10  and 10 )
+ * @param[in] red_SensY_s2
+ *   Redundant MTM Y-Sens s2
+ *   (valid range is between -10  and 10 )
+ * @param[in] red_SensZ_s2
+ *   Redundant MTM Z-Sens s2
+ *   (valid range is between -10  and 10 )
+ * @param[in] ccsEnablePort
+ *   CC Signal Enable GPIO port
+ * @param[in] ccsEnablePin
+ *   CC Signal Enable GPIO port pin
+ * @param[in] ccmEnablePort
+ *   CC Motor Enable GPIO port
+ * @param[in] ccmEnablePin
+ *   CC Motor Enable GPIO port pin
+ * @param[in] cccEnablePort
+ *   CC Common Enable GPIO port
+ * @param[in] cccEnablePin
+ *   CC Common Enable GPIO port pin
+ * @param[in] cSense1EnablePort
+ *   CubeSense1 Enable GPIO port
+ * @param[in] cSense1EnablePin
+ *   CubeSense1 Enable GPIO port pin
+ * @param[in] cSense2EnablePort
+ *   CubeSense2 Enable GPIO port
+ * @param[in] cSense2EnablePin
+ *   CubeSense2 Enable GPIO port pin
+ * @param[in] cStarEnablePort
+ *   CubeStar Enable GPIO port
+ * @param[in] cStarEnablePin
+ *   CubeStar Enable GPIO port pin
+ * @param[in] cW1EnablePort
+ *   CubeWheel1 Enable GPIO port
+ * @param[in] cW1EnablePin
+ *   CubeWheel1 Enable GPIO port pin
+ * @param[in] cW2EnablePort
+ *   CubeWheel2 Enable GPIO port
+ * @param[in] cW2EnablePin
+ *   CubeWheel2 Enable GPIO port pin
+ * @param[in] cW3EnablePort
+ *   CubeWheel3 Enable GPIO port
+ * @param[in] cW3EnablePin
+ *   CubeWheel3 Enable GPIO port pin
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, acpType, was not a valid CUBEACP_AcpProgramType_t enumeration
+ *      TcInvalidParam if the input parameter, specialControl, was not a valid CUBEACP_SpecialConSelect_t enumeration
+ *      TcInvalidParam if the input parameter, csCam1Type, was not a valid CUBEACP_CsCamType_t enumeration
+ *      TcInvalidParam if the input parameter, csCam2Type, was not a valid CUBEACP_CsCamType_t enumeration
+ *      TcInvalidParam if the input parameter, gpsType, was not a valid CUBEACP_GpsSelect_t enumeration
+ *      TcInvalidParam if the input parameter, mqx, was outside of the range 0 A.m^2 to 2 A.m^2
+ *      TcInvalidParam if the input parameter, mqy, was outside of the range 0 A.m^2 to 2 A.m^2
+ *      TcInvalidParam if the input parameter, mqz, was outside of the range 0 A.m^2 to 2 A.m^2
+ *      TcInvalidParam if the input parameter, mtTmin, was outside of the range 0 s to 1 s
+ *      TcInvalidParam if the input parameter, mtTmax, was outside of the range 0 s to 1 s
+ *      TcInvalidParam if the input parameter, nSatX, was outside of the range 0 N.m to 0.1 N.m
+ *      TcInvalidParam if the input parameter, nSatY, was outside of the range 0 N.m to 0.1 N.m
+ *      TcInvalidParam if the input parameter, nSatZ, was outside of the range 0 N.m to 0.1 N.m
+ *      TcInvalidParam if the input parameter, hSatX, was outside of the range 0 Nms to 0.1 Nms
+ *      TcInvalidParam if the input parameter, hSatY, was outside of the range 0 Nms to 0.1 Nms
+ *      TcInvalidParam if the input parameter, hSatZ, was outside of the range 0 Nms to 0.1 Nms
+ *      TcInvalidParam if the input parameter, iwx, was outside of the range 0 kg.m^2 to 0.001 kg.m^2
+ *      TcInvalidParam if the input parameter, iwy, was outside of the range 0 kg.m^2 to 0.001 kg.m^2
+ *      TcInvalidParam if the input parameter, iwz, was outside of the range 0 kg.m^2 to 0.001 kg.m^2
+ *      TcInvalidParam if the input parameter, ndel, was outside of the range 0 N.m to 0.1 N.m
+ *      TcInvalidParam if the input parameter, biasX_d1, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, biasY_d1, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, biasZ_d1, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, biasX_d2, was outside of the range -10000  to 10000 
+ *      TcInvalidParam if the input parameter, biasY_d2, was outside of the range -10000  to 10000 
+ *      TcInvalidParam if the input parameter, biasZ_d2, was outside of the range -10000  to 10000 
+ *      TcInvalidParam if the input parameter, sensX_s1, was outside of the range -1  to 1 
+ *      TcInvalidParam if the input parameter, sensY_s1, was outside of the range -1  to 1 
+ *      TcInvalidParam if the input parameter, sensZ_s1, was outside of the range -1  to 1 
+ *      TcInvalidParam if the input parameter, sensX_s2, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, sensY_s2, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, sensZ_s2, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, red_BiasX_d1, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, red_BiasY_d1, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, red_BiasZ_d1, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, red_BiasX_d2, was outside of the range -10000  to 10000 
+ *      TcInvalidParam if the input parameter, red_BiasY_d2, was outside of the range -10000  to 10000 
+ *      TcInvalidParam if the input parameter, red_BiasZ_d2, was outside of the range -10000  to 10000 
+ *      TcInvalidParam if the input parameter, red_SensX_s1, was outside of the range -1  to 1 
+ *      TcInvalidParam if the input parameter, red_SensY_s1, was outside of the range -1  to 1 
+ *      TcInvalidParam if the input parameter, red_SensZ_s1, was outside of the range -1  to 1 
+ *      TcInvalidParam if the input parameter, red_SensX_s2, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, red_SensY_s2, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, red_SensZ_s2, was outside of the range -10  to 10 
+ *      TcInvalidParam if the input parameter, ccsEnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, ccsEnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, ccmEnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, ccmEnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cccEnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cccEnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cSense1EnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cSense1EnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cSense2EnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cSense2EnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cStarEnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cStarEnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cW1EnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cW1EnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cW2EnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cW2EnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ *      TcInvalidParam if the input parameter, cW3EnablePort, was not a valid CUBEACP_GpioPort_t enumeration
+ *      TcInvalidParam if the input parameter, cW3EnablePin, was not a valid CUBEACP_GpioPortPin_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatAdcsSystemConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsSystemConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a ASGP4 Run Mode command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] asgp4ModeSelection
+ *   ASGP4 enabled state
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, asgp4ModeSelection, was not a valid CUBEACP_Asgp4ModeSelect_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatAsgp4ModeCmd(uint8_t* tcBuffer, CUBEACP_Asgp4ModeSelect_t asgp4ModeSelection);
+
+/***************************************************************************//**
+ * Send a Augmented-SGP4 Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatASgp4ParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a ASGP4 Trigger command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatAsgp4TriggerCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Clear Errors command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] aDCSErrors
+ *   Clear ADCS error flags
+ * @param[in] hKErrors
+ *   Clear HK Error flags
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatClearErrorsCmd(uint8_t* tcBuffer, CUBEACP_ClearErrors_t* setVal);
+
+/***************************************************************************//**
+ * Send a Commanded Attitude Angles command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] roll
+ *   Commanded roll angle
+ *   (in [deg] units)
+ *   (valid range is between -9000 deg and 9000 deg)
+ * @param[in] pitch
+ *   Commanded pitch angle
+ *   (in [deg] units)
+ *   (valid range is between -18000 deg and 18000 deg)
+ * @param[in] yaw
+ *   Commanded yaw angle
+ *   (in [deg] units)
+ *   (valid range is between -18000 deg and 18000 deg)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, roll, was outside of the range -9000 deg to 9000 deg
+ *      TcInvalidParam if the input parameter, pitch, was outside of the range -18000 deg to 18000 deg
+ *      TcInvalidParam if the input parameter, yaw, was outside of the range -18000 deg to 18000 deg
+ ******************************************************************************/
+uint16_t CUBEACP_FormatCmdAttitudeCmd(uint8_t* tcBuffer, CUBEACP_CmdAttitude_t* setVal);
+
+/***************************************************************************//**
+ * Send a Tracking Controller Target Reference command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] longRef
+ *   Geocentric longitude of target
+ *   (in [deg] units)
+ *   (valid range is between 0 deg and 360 deg)
+ * @param[in] latRef
+ *   Geocentric latitude of target
+ *   (in [deg] units)
+ *   (valid range is between -90 deg and 90 deg)
+ * @param[in] altRef
+ *   Geocentric altitude of target
+ *   (in [meter] units)
+ *   (valid range is between -20000 meter and 40000000 meter)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, longRef, was outside of the range 0 deg to 360 deg
+ *      TcInvalidParam if the input parameter, latRef, was outside of the range -90 deg to 90 deg
+ *      TcInvalidParam if the input parameter, altRef, was outside of the range -20000 meter to 40000000 meter
+ ******************************************************************************/
+uint16_t CUBEACP_FormatCmdTrackingTargetCmd(uint8_t* tcBuffer, F32 longRef, F32 latRef, F32 altRef);
+
+/***************************************************************************//**
+ * Send a Set Attitude Control Mode command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] controlModeSelection
+ *   Attitude control mode
+ * @param[in] timeout
+ *   Control timeout duration. Control will revert to None when timer reaches zero. 0xFFFF for infinite timeout
+ *   (in [s] units)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, controlModeSelection, was not a valid CUBEACP_ConModeSelect_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatControlModeCmd(uint8_t* tcBuffer, CUBEACP_ControlMode_t* setVal);
+
+/***************************************************************************//**
+ * Send a Convert to JPG file command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] srcFileCtr
+ *   Source File Counter
+ * @param[in] qualityFactor
+ *   Quality Factor
+ * @param[in] whiteBalance
+ *   White Balance
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatConvertCmd(uint8_t* tcBuffer, U8 srcFileCtr, U8 qualityFactor, U8 whiteBalance);
+
+/***************************************************************************//**
+ * Send a CSS Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatCssConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a CubeSense Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatCubeSenseConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Deploy Magnetometer Boom command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] timeout
+ *   Deployment actuation timeout value
+ *   (in [s] units)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatDeployMagnetometerCmd(uint8_t* tcBuffer, U8 timeout);
+
+/***************************************************************************//**
+ * Send a Set Detumbling Control Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatDetumbleParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Attitude Estimation Mode command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] estimModeSelection
+ *   Attitude estimation mode
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, estimModeSelection, was not a valid CUBEACP_EstimModeSelect_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatEstimModeCmd(uint8_t* tcBuffer, CUBEACP_EstimModeSelect_t estimModeSelection);
+
+/***************************************************************************//**
+ * Send a Estimation Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatEstimParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Rate Gyro Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatGyroConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Inertial Pointing Reference Vector command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] inertialRefX
+ *   Inertial Reference X
+ * @param[in] inertialRefY
+ *   Inertial Reference Y
+ * @param[in] inertialRefZ
+ *   Inertial Reference Z
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatInertialPointReferenceCmd(uint8_t* tcBuffer, F64 inertialRefX, F64 inertialRefY, F64 inertialRefZ);
+
+/***************************************************************************//**
+ * Send a SD Log1 Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] logSelection
+ *   Log Selection - up to 80 flags indicating which telemetry frames should be logged
+ * @param[in] period
+ *   Log period. Set to 0 to disable logging
+ * @param[in] destination
+ *   Which SD card to use to store log file
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, destination, was not a valid CUBEACP_SdLogSelect_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatLogSdConfig1Cmd(uint8_t* tcBuffer, U8* logSelection, U16 period, CUBEACP_SdLogSelect_t destination);
+
+/***************************************************************************//**
+ * Send a SD Log2 Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] logSelection
+ *   Log Selection - up to 80 flags indicating which telemetry frames should be logged
+ * @param[in] period
+ *   Log period. Set to 0 to disable logging
+ * @param[in] destination
+ *   Which SD card to use to store log file
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, destination, was not a valid CUBEACP_SdLogSelect_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatLogSdConfig2Cmd(uint8_t* tcBuffer, U8* logSelection, U16 period, CUBEACP_SdLogSelect_t destination);
+
+/***************************************************************************//**
+ * Send a UART Log Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] selection
+ *   Log Selection - up to 80 flags indicating which telemetry frames should be logged
+ * @param[in] period
+ *   Log period. Set to 0 to disable logging
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatLogUartConfigCmd(uint8_t* tcBuffer, U8* selection, U16 period);
+
+/***************************************************************************//**
+ * Send a Magnetometer Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatMagConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Mode of Magnetometer Operation command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] modeSetting
+ *   Mode describing which magnetometer is used for estimation and control
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, modeSetting, was not a valid CUBEACP_MagModeVal_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatMagModeCmd(uint8_t* tcBuffer, CUBEACP_MagModeVal_t modeSetting);
+
+/***************************************************************************//**
+ * Send a Set Magnetorquer Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatMagtorqConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Moment of Inertia Matrix command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatMoICmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit Argument of Perigee command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitArgPerCmd(uint8_t* tcBuffer, F64 argPerigee);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit B-Star Drag term command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitBStarCmd(uint8_t* tcBuffer, F64 bstar);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit Eccentricity command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitEccentricityCmd(uint8_t* tcBuffer, F64 eccentricity);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit Epoch command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitEpochCmd(uint8_t* tcBuffer, F64 epoch);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit Inclination command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitInclinationCmd(uint8_t* tcBuffer, F64 inclination);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit Mean Anomaly command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitMeanAnomCmd(uint8_t* tcBuffer, F64 meanAnomaly);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit Mean Motion command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitMeanMotCmd(uint8_t* tcBuffer, F64 meanMotion);
+
+/***************************************************************************//**
+ * Send a SGP4 Orbit Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] inclination
+ *   Inclination
+ *   (in [deg] units)
+ *   (valid range is between 0 deg and 180 deg)
+ * @param[in] eccentricity
+ *   Eccentricity
+ *   (valid range is between 0  and 1 )
+ * @param[in] raan
+ *   Right-ascension of the Ascending Node
+ *   (in [deg] units)
+ *   (valid range is between 0 deg and 360 deg)
+ * @param[in] argPerigee
+ *   Argument of Perigee
+ *   (in [deg] units)
+ *   (valid range is between 0 deg and 360 deg)
+ * @param[in] bstar
+ *   B-Star drag term
+ *   (valid range is between 0  and 1 )
+ * @param[in] meanMotion
+ *   Mean Motion
+ *   (in [orbits/day] units)
+ *   (valid range is between 0 orbits/day and 20 orbits/day)
+ * @param[in] meanAnomaly
+ *   Mean Anomaly
+ *   (in [deg] units)
+ *   (valid range is between 0 deg and 360 deg)
+ * @param[in] epoch
+ *   Epoch (year.day)
+ *   (in [year.day] units)
+ *   (valid range is between 0 year.day and 100000 year.day)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, inclination, was outside of the range 0 deg to 180 deg
+ *      TcInvalidParam if the input parameter, eccentricity, was outside of the range 0  to 1 
+ *      TcInvalidParam if the input parameter, raan, was outside of the range 0 deg to 360 deg
+ *      TcInvalidParam if the input parameter, argPerigee, was outside of the range 0 deg to 360 deg
+ *      TcInvalidParam if the input parameter, bstar, was outside of the range 0  to 1 
+ *      TcInvalidParam if the input parameter, meanMotion, was outside of the range 0 orbits/day to 20 orbits/day
+ *      TcInvalidParam if the input parameter, meanAnomaly, was outside of the range 0 deg to 360 deg
+ *      TcInvalidParam if the input parameter, epoch, was outside of the range 0 year.day to 100000 year.day
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitParametersCmd(uint8_t* tcBuffer, CUBEACP_OrbitParameters_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set SGP4 Orbit RAAN command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatOrbitRaanCmd(uint8_t* tcBuffer, F64 raan);
+
+/***************************************************************************//**
+ * Send a Redundant Magnetometer Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatRedMagConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Reaction Wheel Control Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatRWheelParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Save Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatSaveConfigCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Save Image command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] cameraSelect
+ *   Camera Selection
+ *   (in [s] units)
+ * @param[in] imageSize
+ *   Image size selection
+ *   (in [s] units)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, cameraSelect, was not a valid CUBEACP_CamSelect_t enumeration
+ *      TcInvalidParam if the input parameter, imageSize, was not a valid CUBEACP_ImSize_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatSaveImageCmd(uint8_t* tcBuffer, CUBEACP_SaveImage_t* setVal);
+
+/***************************************************************************//**
+ * Send a Save Orbit Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatSaveOrbitParamsCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Set Star Tracker Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatStarConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Magnetorquer Output command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] torquerX
+ *   Commanded X-torquer duty cycle
+ *   (valid range is between -800  and 800 )
+ * @param[in] torquerY
+ *   Commanded Y-torquer duty cycle
+ *   (valid range is between -800  and 800 )
+ * @param[in] torquerZ
+ *   Commanded Z-torquer duty cycle
+ *   (valid range is between -800  and 800 )
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, torquerX, was outside of the range -800  to 800 
+ *      TcInvalidParam if the input parameter, torquerY, was outside of the range -800  to 800 
+ *      TcInvalidParam if the input parameter, torquerZ, was outside of the range -800  to 800 
+ ******************************************************************************/
+uint16_t CUBEACP_FormatTorquerCmdCmd(uint8_t* tcBuffer, CUBEACP_TorquerCmd_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Tracking Controller Gain Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatTrackingParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Trigger ADCS Loop command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatTriggerAdcsCmd(uint8_t* tcBuffer);
+
+/***************************************************************************//**
+ * Send a Trigger ADCS Loop with Simulated Sensor Data command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] unixTime
+ *   Unix time for iteration
+ *   (in [s] units)
+ * @param[in] cssRaw1
+ *   CSS1 raw measurement
+ * @param[in] cssRaw2
+ *   CSS2 raw measurement
+ * @param[in] cssRaw3
+ *   CSS3 raw measurement
+ * @param[in] cssRaw4
+ *   CSS4 raw measurement
+ * @param[in] cssRaw5
+ *   CSS5 raw measurement
+ * @param[in] cssRaw6
+ *   CSS6 raw measurement
+ * @param[in] cssRaw7
+ *   CSS7 raw measurement
+ * @param[in] cssRaw8
+ *   CSS8 raw measurement
+ * @param[in] cssRaw9
+ *   CSS9 raw measurement
+ * @param[in] cssRaw10
+ *   CSS10 raw measurement
+ * @param[in] cam1RawX
+ *   Cam1 sensor raw X angle
+ * @param[in] cam1RawY
+ *   Cam1 sensor raw Y angle
+ * @param[in] cam1Busy
+ *   Cam1 sensor capture status
+ * @param[in] cam1Result
+ *   Cam1 sensor detection result
+ * @param[in] cam2RawX
+ *   Cam2 sensor raw X angle
+ * @param[in] cam2RawY
+ *   Cam2 sensor raw Y angle
+ * @param[in] cam2Busy
+ *   Cam2 sensor capture status
+ * @param[in] cam2Result
+ *   Cam2 sensor detection result
+ * @param[in] magRawX
+ *   Raw magnetometer X measurement
+ * @param[in] magRawY
+ *   Raw magnetometer Y measurement
+ * @param[in] magRawZ
+ *   Raw magnetometer Z measurement
+ * @param[in] rateRawX
+ *   Raw X rate sensor measurement
+ * @param[in] rateRawY
+ *   Raw Y rate sensor measurement
+ * @param[in] rateRawZ
+ *   Raw Z rate sensor measurement
+ * @param[in] wheelRawX
+ *   Raw X wheel speed measurement
+ *   (in [rpm] units)
+ * @param[in] wheelRawY
+ *   Raw Y wheel speed measurement
+ *   (in [rpm] units)
+ * @param[in] wheelRawZ
+ *   Raw Z wheel speed measurement
+ *   (in [rpm] units)
+ * @param[in] star1CameraX
+ *   Star1 camera X-vector
+ * @param[in] star1CameraY
+ *   Star1 camera Y-vector
+ * @param[in] star1CameraZ
+ *   Star1 camera Z-vector
+ * @param[in] star1InertialX
+ *   Star1 inertial X-vector
+ * @param[in] star1InertialY
+ *   Star1 inertial Y-vector
+ * @param[in] star1InertialZ
+ *   Star1 inertial Z-vector
+ * @param[in] star2CameraX
+ *   Star2 camera X-vector
+ * @param[in] star2CameraY
+ *   Star2 camera Y-vector
+ * @param[in] star2CameraZ
+ *   Star2 camera Z-vector
+ * @param[in] star2InertialX
+ *   Star2 inertial X-vector
+ * @param[in] star2InertialY
+ *   Star2 inertial Y-vector
+ * @param[in] star2InertialZ
+ *   Star2 inertial Z-vector
+ * @param[in] star3CameraX
+ *   Star3 camera X-vector
+ * @param[in] star3CameraY
+ *   Star3 camera Y-vector
+ * @param[in] star3CameraZ
+ *   Star3 camera Z-vector
+ * @param[in] star3InertialX
+ *   Star3 inertial X-vector
+ * @param[in] star3InertialY
+ *   Star3 inertial Y-vector
+ * @param[in] star3InertialZ
+ *   Star3 inertial Z-vector
+ * @param[in] gpsSolutionStatus
+ *   GPS Solution Status
+ * @param[in] gpsWeek
+ *   GPS Reference Week
+ * @param[in] gpsTimeMs
+ *   GPS Time Milliseconds
+ *   (in [ms] units)
+ * @param[in] posEcefX
+ *   ECEF Position X
+ *   (in [m] units)
+ * @param[in] velEcefX
+ *   ECEF Velocity X
+ *   (in [m/s] units)
+ * @param[in] posEcefY
+ *   ECEF Position Y
+ *   (in [m] units)
+ * @param[in] velEcefY
+ *   ECEF Velocity Y
+ *   (in [m/s] units)
+ * @param[in] posEcefZ
+ *   ECEF Position Z
+ *   (in [m] units)
+ * @param[in] velEcefZ
+ *   ECEF Velocity Z
+ *   (in [m/s] units)
+ * @param[in] stdDevPosX
+ *   X-pos Standard Deviation
+ *   (in [m] units)
+ * @param[in] stdDevPosY
+ *   Y-pos Standard Deviation
+ *   (in [m] units)
+ * @param[in] stdDevPosZ
+ *   Z-pos Standard Deviation
+ *   (in [m] units)
+ * @param[in] stdDevVelX
+ *   X-vel Standard Deviation
+ *   (in [m/s] units)
+ * @param[in] stdDevVelY
+ *   Y-vel Standard Deviation
+ *   (in [m/s] units)
+ * @param[in] stdDevVelZ
+ *   Z-vel Standard Deviation
+ *   (in [m/s] units)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, gpsSolutionStatus, was not a valid CUBEACP_GpsSolutionStatus_t enumeration
+ ******************************************************************************/
+uint16_t CUBEACP_FormatTriggerAdcsSensorCmd(uint8_t* tcBuffer, CUBEACP_TriggerAdcsSensor_t* setVal);
+
+/***************************************************************************//**
+ * Send a User-coded Controller and Estimator Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatUserConEstParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Wheel Configuration command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatWheelConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Wheel Speed command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @param[in] wheelX
+ *   Commanded X-wheel speed
+ *   (in [rpm] units)
+ *   (valid range is between -8000 rpm and 8000 rpm)
+ * @param[in] wheelY
+ *   Commanded Y-wheel speed
+ *   (in [rpm] units)
+ *   (valid range is between -8000 rpm and 8000 rpm)
+ * @param[in] wheelZ
+ *   Commanded Z-wheel speed
+ *   (in [rpm] units)
+ *   (valid range is between -8000 rpm and 8000 rpm)
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ *      TcInvalidParam if the input parameter, wheelX, was outside of the range -8000 rpm to 8000 rpm
+ *      TcInvalidParam if the input parameter, wheelY, was outside of the range -8000 rpm to 8000 rpm
+ *      TcInvalidParam if the input parameter, wheelZ, was outside of the range -8000 rpm to 8000 rpm
+ ******************************************************************************/
+uint16_t CUBEACP_FormatWheelSpeedCmdCmd(uint8_t* tcBuffer, CUBEACP_WheelSpeedCmd_t* setVal);
+
+/***************************************************************************//**
+ * Send a Set Y-Wheel Control Parameters command to the CubeACP
+ *
+ * @param[in] nodeid
+ *   identifier of the node on the communications bus
+ * @return
+ *   Returns a value from the uint16_t enumeration:
+ *      CubeLibOk if the command was sent without error
+ *      One of the I2C enumeration values in case of I2C communications error
+ ******************************************************************************/
+uint16_t CUBEACP_FormatYWheelParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal);
+
+
+#endif  // define __CUBECOMPUTER4CONTROLPROGRAM7_H

+ 36 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/inc/types.h

@@ -0,0 +1,36 @@
+
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef _Bool Boolean;
+
+#define FALSE ((Boolean)0U)
+#define TRUE  ((Boolean)1U)
+
+typedef uint8_t U8;
+typedef int8_t S8;
+typedef uint16_t U16;
+typedef int16_t S16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+typedef int64_t S64;
+typedef float F32;
+typedef double F64;
+typedef char Text;
+
+/// Sensor/actuator interface function result enumeration
+typedef enum
+{
+	CubeLibOk             = 0,
+	PointerIsNull         = 1,
+	TcInvalidParam        = 2,
+	TlmRangeError         = 3,
+	TcAckTimeout          = 4
+} CUBEADCS_Result_t;
+
+#endif /* _TYPES_H_ */

+ 94 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/makefile

@@ -0,0 +1,94 @@
+#
+#   @copyright Copyright 2022 Antaris, Inc.
+#
+TOP_DIR=../../
+include $(TOP_DIR)Makefile.def
+
+##############################################################################
+# All variables here intensionally set to empty, User should not modify here
+
+SRC =
+SRC_DIR =
+SUBDIR =
+
+##############################################################################
+# List of include file directories required for compilation
+INCLUDES = -I inc/\
+	   -I ../security/mbedtls/include/\
+	   -I ../security/hmac/src/\
+	   -I ../security/libcrc-2.0/include\
+
+
+##############################################################################
+#Current Folder target name, usually current folder name
+#TARGET_LIB = target_name
+
+# List of source files required for compilation using SRC
+# mention the directory path where all C files to be compiled usig SRC_DIR
+# Mention Sub director makefile compilation using SUBDIR
+
+SRC += src/bootloader.c
+SRC += src/common.c
+SRC += src/cubeacp.c
+SRC += src/adcs_bsk.c
+
+##############################################################################
+
+ifeq ($(TARGET_LIB),)
+TARGET_LIB := $(shell basename `pwd`)
+endif
+
+ifneq ($(SRC_DIR),)
+    SOURCES = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
+endif
+
+SOURCES += $(SRC)
+
+OBJS = $(foreach dir,$(patsubst %.c, %.o, $(SOURCES)), $(OBJ_DIR)/$(dir))
+
+ifneq ($(SUBDIR),)
+SUB_DIR_LIBS = $(foreach dir,$(SUBDIR), $(dir)/$(OBJ_DIR)/$(shell basename $(dir)).a)
+endif
+
+#$(info selective source files List : $(SRC))
+#$(info source file directory       : $(SRC_DIR))
+#$(info All source file list        : $(SOURCES))
+#$(info All target object files     : $(OBJS))
+#$(info All target lib files        : $(SUB_DIR_LIBS))
+
+DEPS = $(OBJS:.o=.d)
+
+# Command to invoke compilation in sub-directories
+subdir_clean:
+	$(HIDE)for i in $(SUBDIR); do \
+	    $(MAKE) clean -C $$i;\
+	    done
+# Command to invoke compilation in sub-directories
+subdir_all:
+	$(HIDE)for i in $(SUBDIR); do \
+	    $(MAKE) all -C $$i;\
+	    done
+lib: subdir_all
+	$(HIDE)$(MKDIR) $(OBJ_DIR)
+	$(HIDE)$(AR) $(OBJ_DIR)/$(TARGET_LIB).a $(SUB_DIR_LIBS)
+
+# Command to compile source files to intermediate object files
+all:$(OBJS)
+	$(HIDE)$(MKDIR) $(OBJ_DIR)
+	ar rcs libadcs_intf.a obj/src/*.o
+	rm -f obj/src/*.o
+ifneq ($(SUBDIR),)
+	$(HIDE)$(MAKE) subdir_all
+endif
+#	$(HIDE)$(AR) $(OBJ_DIR)/$(TARGET_LIB).a $^ $(SUB_DIR_LIBS)
+
+# Command to delete intermediate object files
+clean:
+	rm -f obj/src/*.o
+	rm -f ./*.a
+ifneq ($(SUBDIR),)
+	$(HIDE)$(MAKE) subdir_clean
+endif
+	$(HIDE)$(RM) $(OBJ_DIR)
+
+-include $(DEPS)

+ 2180 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/adcs_bsk.c

@@ -0,0 +1,2180 @@
+/**
+ * @file adcs_bsk.c
+ *
+ * @brief This file contains basilisk telemetry extract functionalities.
+ *
+ * @copyright Copyright 2023 Antaris, Inc.
+ */
+/*********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "adcs_bsk.h"
+
+/**
+ * @brief This function extract the Identification Command
+ */
+uint16_t adcs_bsk_ext_tlm_id(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_id id_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_id);
+
+    // Copy data to tc buffer
+    memcpy(&id_param,&data[0],len);
+
+    // Debug print
+    printf("Id:- %d\n",id_param.id);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the ADCS state
+ */
+uint16_t adcs_bsk_ext_tlm_state(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_state state = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_state);
+
+    // Copy data to tc buffer
+    memcpy(&state,&data[0],len);
+
+    // Debug print
+    printf("State:- %d\n",state.state);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the TLE configuration
+ */
+uint16_t adcs_bsk_ext_tlm_tle(uint8_t *data)
+{
+    printf("TLE Configuration\n");
+    // Variable decleration
+    uint16_t len;
+    s_adcs_tle tle_cfg = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_tle);
+
+    // Copy data to tc buffer
+    memcpy(&tle_cfg,&data[0],len);
+
+    // Debug print
+    printf("inclination:- %lf\n",tle_cfg.inclination);
+    printf("eccentricity:- %lf\n",tle_cfg.eccentricity);
+    printf("raan:- %lf\n",tle_cfg.raan);
+    printf("arg_perigee:- %lf\n",tle_cfg.arg_perigee);
+    printf("b_star:- %lf\n",tle_cfg.b_star);
+    printf("mean_motion:- %lf\n",tle_cfg.mean_motion);
+    printf("mean_anomaly:- %lf\n",tle_cfg.mean_anomaly);
+    printf("epoch:- %lf\n",tle_cfg.epoch);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Moment of inertia matrix
+ */
+uint16_t adcs_bsk_ext_tlm_moi(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_moi moi_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_moi);
+
+    // Copy data to tc buffer
+    memcpy(&moi_param,&data[0],len);
+
+    // Debug print
+    printf("Mom In XX:- %lf\n",moi_param.mom_iner_xx);
+    printf("Mom In YY:- %lf\n",moi_param.mom_iner_yy);
+    printf("Mom In ZZ:- %lf\n",moi_param.mom_iner_zz);
+    printf("Prod In xy:- %lf\n",moi_param.prod_iner_xy);
+    printf("Prod In xz:- %lf\n",moi_param.prod_iner_xz);
+    printf("Prod In yz:- %fl\n",moi_param.prod_iner_yz);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Power configuration
+ */
+uint16_t adcs_bsk_ext_tlm_power(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_pwr_cmd power_sts_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_pwr_cmd);
+
+    // Copy data to tc buffer
+    memcpy(&power_sts_param,&data[0],len);
+
+    // Debug print
+    printf("Power value:- %d\n",power_sts_param.pwr_source);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Magnetic field vector
+ */
+uint16_t adcs_bsk_ext_tlm_mag_vector(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_mag_vector magnetic_vector = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_mag_vector);
+
+    // Copy data to tc buffer
+    memcpy(&magnetic_vector,&data[0],len);
+
+    // Debug print
+    printf("Magnetic field X:- %d\n",magnetic_vector.mag_filed_x);
+    printf("Magnetic field Y:- %d\n",magnetic_vector.mag_filed_y);
+    printf("Magnetic field Z:- %d\n",magnetic_vector.mag_filed_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the CSS vector
+ */
+uint16_t adcs_bsk_ext_tlm_css_sun_vector(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_sun_vector css_vector = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_sun_vector);
+
+    // Copy data to tc buffer
+    memcpy(&css_vector,&data[0],len);
+
+    // Debug print
+    printf("CSS Vector X:- %d\n",css_vector.sun_x);
+    printf("CSS Vector Y:- %d\n",css_vector.sun_y);
+    printf("CSS Vector Z:- %d\n",css_vector.sun_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the FSS vector
+ */
+uint16_t adcs_bsk_ext_tlm_fss_sun_vector(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_sun_vector fss_vector = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_sun_vector);
+
+    // Copy data to tc buffer
+    memcpy(&fss_vector,&data[0],len);
+
+    // Debug print
+    printf("FSS Vector X:- %d\n",fss_vector.sun_x);
+    printf("FSS Vector Y:- %d\n",fss_vector.sun_y);
+    printf("FSS Vector Z:- %d\n",fss_vector.sun_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Nadir vector
+ */
+uint16_t adcs_bsk_ext_tlm_nadir_vector(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_nadir_vector nadir_vector = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_nadir_vector);
+
+    // Copy data to tc buffer
+    memcpy(&nadir_vector,&data[0],len);
+
+    // Debug print
+    printf("Nadir Vector X:- %d\n",nadir_vector.nadir_x);
+    printf("Nadir Vector Y:- %d\n",nadir_vector.nadir_y);
+    printf("Nadir Vector Z:- %d\n",nadir_vector.nadir_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Rate sensor rates
+ */
+uint16_t adcs_bsk_ext_tlm_sensor_rate(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_rate_sens rates = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_rate_sens);
+
+    // Copy data to tc buffer
+    memcpy(&rates,&data[0],len);
+
+    // Debug print
+    printf("Rate Sensor X:- %lf\n",rates.rate_x);
+    printf("Rate Sensor Y:- %lf\n",rates.rate_y);
+    printf("Rate Sensor Z:- %lf\n",rates.rate_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker body vector for xyz axis
+ */
+uint16_t adcs_bsk_ext_tlm_star_body(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_trkr_body star_body = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_trkr_body);
+
+    // Copy data to tc buffer
+    memcpy(&star_body,&data[0],len);
+
+    // Debug print
+    printf("Star Tracker body X:- %d\n",star_body.star_b_x);
+    printf("Star Tracker body Y:- %d\n",star_body.star_b_y);
+    printf("Star Tracker body Z:- %d\n",star_body.star_b_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker Orbit vector for xyz axis
+ */
+uint16_t adcs_bsk_ext_tlm_star_orbit(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_trkr_orbit star_orbit = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_trkr_orbit);
+
+    // Copy data to tc buffer
+    memcpy(&star_orbit,&data[0],len);
+
+    // Debug print
+    printf("Star Tracker Orbit X:- %d\n",star_orbit.star_o_x);
+    printf("Star Tracker Orbit Y:- %d\n",star_orbit.star_o_y);
+    printf("Star Tracker Orbit Z:- %d\n",star_orbit.star_o_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw Nadir sensor measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_nadir(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_nadir_sens nadir_sens = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_nadir_sens);
+
+    // Copy data to tc buffer
+    memcpy(&nadir_sens,&data[0],len);
+
+    // Debug print
+    printf("Nadir Raw X:- %d\n",nadir_sens.nadir_raw_x);
+    printf("Nadir Raw Y:- %d\n",nadir_sens.nadir_raw_y);
+    printf("Nadir Capture result:- %d\n",nadir_sens.nadir_busy);
+    printf("Nadir Detect result:- %d\n",nadir_sens.nadir_result);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw FSS measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_fss(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_fss_sens fss_sens = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_fss_sens);
+
+    // Copy data to tc buffer
+    memcpy(&fss_sens,&data[0],len);
+
+    // Debug print
+    printf("FSS Raw X:- %d\n",fss_sens.fss_raw_x);
+    printf("FSS Raw Y:- %d\n",fss_sens.fss_raw_y);
+    printf("FSS Capture result:- %d\n",fss_sens.fss_busy);
+    printf("FSS Detect result:- %d\n",fss_sens.fss_result);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw Magnetometer measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_magmtr(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_mgmtr raw_mgmtr = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_mgmtr);
+
+    // Copy data to tc buffer
+    memcpy(&raw_mgmtr,&data[0],len);
+
+    // Debug print
+    printf("Raw Magnetometer X:- %d\n",raw_mgmtr.mag_raw_x);
+    printf("Raw Magnetometer Y:- %d\n",raw_mgmtr.mag_raw_y);
+    printf("Raw Magnetometer Z:- %d\n",raw_mgmtr.mag_raw_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw GPS and Sattelite tracker structure
+ */
+uint16_t adcs_bsk_ext_tlm_raw_gps_status(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_gps_s gps_param  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_gps_s);
+
+    // Copy data to tc buffer
+    memcpy(&gps_param,&data[0],len);
+
+    // Debug print
+    printf("GPS Solution Status:- %d\n",gps_param.gps_sol_sts);
+    printf("GPS Number of satellite used in solution:- %d\n",\
+    gps_param.gps_num_sats_tracked);
+    printf("Counter for XYZ Lof from GPS:- %d\n",gps_param.gps_xyz_log_ctr);
+    printf("Counter for RANGE log from GPS:- %d\n",\
+    gps_param.gps_range_log_ctr);
+    printf("Response Message for GPS log setup:- %d\n",gps_param.gps_response);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw GPS time format
+ */
+uint16_t adcs_bsk_ext_tlm_raw_gps_time(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_gps_time gps_time  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_gps_time);
+
+    // Copy data to tc buffer
+    memcpy(&gps_time,&data[0],len);
+
+    // Debug print
+    printf("GPS Week:- %d\n",gps_time.gps_week);
+    printf("GPS Time MS:- %d\n",gps_time.gps_time_ms);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw Position and velocity in ECEF format for X axis
+ */
+uint16_t adcs_bsk_ext_tlm_raw_gps_x(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_gps_x gps_x  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_gps_x);
+
+    // Copy data to tc buffer
+    memcpy(&gps_x,&data[0],len);
+
+    // Debug print
+    printf("Position X:- %d\n",gps_x.ecef_pos_x);
+    printf("Velocity X:- %d\n",gps_x.ecef_vel_x);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw Position and velocity in ECEF format for Y axis
+ */
+uint16_t adcs_bsk_ext_tlm_raw_gps_y(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_gps_y gps_y  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_gps_y);
+
+    // Copy data to tc buffer
+    memcpy(&gps_y,&data[0],len);
+
+    // Debug print
+    printf("Position Y:- %d\n",gps_y.ecef_pos_y);
+    printf("Velocity Y:- %d\n",gps_y.ecef_vel_y);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the raw Position and velocity in ECEF format for Z axis
+ */
+uint16_t adcs_bsk_ext_tlm_raw_gps_z(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_gps_z gps_z  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_gps_z);
+
+    // Copy data to tc buffer
+    memcpy(&gps_z,&data[0],len);
+
+    // Debug print
+    printf("Position Z:- %d\n",gps_z.ecef_pos_z);
+    printf("Velocity Z:- %d\n",gps_z.ecef_vel_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker magnitude of identified
+ */
+uint16_t adcs_bsk_ext_tlm_star_magnitude(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_trkr_mag star_mag  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_trkr_mag);
+
+    // Copy data to tc buffer
+    memcpy(&star_mag,&data[0],len);
+
+    // Debug print
+    printf("Star 1:- %d\n",star_mag.mag_star_1);
+    printf("Star 2:- %d\n",star_mag.mag_star_2);
+    printf("Star 3:- %d\n",star_mag.mag_star_3);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker performance
+ */
+uint16_t adcs_bsk_ext_tlm_star_performance(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_trkr_perform star_perform  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_trkr_perform);
+
+    // Copy data to tc buffer
+    memcpy(&star_perform,&data[0],len);
+
+    // Debug print
+    printf("Number Star detected:- %d\n",star_perform.num_stars_detected);
+    printf("Star Image Noise:- %d\n",star_perform.star_image_noise);
+    printf("Invalid Star:- %d\n",star_perform.invalid_stars);
+    printf("Number of star identified:- %d\n",star_perform.num_stars_id);
+    printf("Identification mode:- %d\n",star_perform.id_mode);
+    printf("Image Dark value:- %d\n",star_perform.image_dark_value);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Timing information of star measurement
+ */
+uint16_t adcs_bsk_ext_tlm_star_timing(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_trkr_timing star_timing  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_trkr_timing);
+
+    // Copy data to tc buffer
+    memcpy(&star_timing,&data[0],len);
+
+    // Debug print
+    printf("Capture:- %d\n",star_timing.capture);
+    printf("Detection:- %d\n",star_timing.detection);
+    printf("Identification:- %d\n",star_timing.id);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Raw sensor measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_sensor_measure(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_sensor raw_sensor  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_sensor);
+
+    // Copy data to tc buffer
+    memcpy(&raw_sensor,&data[0],len);
+
+    // Debug print
+    printf("Raw Nadir X:- %d\n",raw_sensor.nadir_raw_x);
+    printf("Raw Nadir Y:- %d\n",raw_sensor.nadir_raw_y);
+    printf("Raw Nadir Capture Status:- %d\n",raw_sensor.nadir_busy);
+    printf("Raw Nadir Detect Status:- %d\n",raw_sensor.nadir_result);
+    printf("Raw FSS X:- %d\n",raw_sensor.fss_raw_x);
+    printf("Raw FSS Y:- %d\n",raw_sensor.fss_raw_y);
+    printf("Raw FSS Capture Status:- %d\n",raw_sensor.fss_busy);
+    printf("Raw CSS:- %d\n",raw_sensor.css_raw);
+    printf("Raw Magnetometer X:- %d\n",raw_sensor.mag_raw_x);
+    printf("Raw Magnetometer Y:- %d\n",raw_sensor.mag_raw_y);
+    printf("Raw Magnetometer Z:- %d\n",raw_sensor.mag_raw_z);
+    printf("Raw Angular Rate X:- %d\n",raw_sensor.raw_rate_x);
+    printf("Raw Angular Rate Y:- %d\n",raw_sensor.raw_rate_y);
+    printf("Raw Angular Rate Z:- %d\n",raw_sensor.raw_rate_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Raw GPS measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_gps_measure(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_gps raw_gps  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_gps);
+
+    // Copy data to tc buffer
+    memcpy(&raw_gps,&data[0],len);
+
+    // Debug print
+    printf("Raw GPS Solution Staus:- %d\n",raw_gps.gps_sol_sts);
+    printf("Raw Number of satellite tracked:- %d\n",\
+    raw_gps.gps_num_sats_tracked);
+    printf("Raw Number of satellite in solution:- %d\n",\
+    raw_gps.gps_num_sats_sol);
+    printf("Raw gps_xyz_log_ctr:- %d\n",raw_gps.gps_xyz_log_ctr);
+    printf("Raw gps_range_log_ctr:- %d\n",raw_gps.gps_range_log_ctr);
+    printf("Raw gps_response:- %d\n",raw_gps.gps_response);
+    printf("Raw gps_week:- %d\n",raw_gps.gps_week);
+    printf("Raw gps_time_ms:- %d\n",raw_gps.gps_time_ms);
+    printf("Raw ecef_pos_x:- %d\n",raw_gps.ecef_pos_x);
+    printf("Raw ecef_vel_x:- %d\n",raw_gps.ecef_vel_x);
+    printf("Raw ecef_pos_y:- %d\n",raw_gps.ecef_pos_y);
+    printf("Raw ecef_vel_y:- %d\n",raw_gps.ecef_vel_y);
+    printf("Raw ecef_pos_z:- %d\n",raw_gps.ecef_pos_z);
+    printf("Raw ecef_vel_z:- %d\n",raw_gps.ecef_vel_z);
+    printf("Raw std_dev_pos_x:- %lf\n",raw_gps.std_dev_pos_x);
+    printf("Raw std_dev_pos_y:- %lf\n",raw_gps.std_dev_pos_y);
+    printf("Raw std_dev_pos_z:- %lf\n",raw_gps.std_dev_pos_z);
+    printf("Raw std_dev_vel_x:- %d\n",raw_gps.std_dev_vel_x);
+    printf("Raw std_dev_vel_y:- %d\n",raw_gps.std_dev_vel_y);
+    printf("Raw std_dev_vel_z:- %d\n",raw_gps.std_dev_vel_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker raw measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_star_measure(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_star_trkr raw_star_trkr  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_star_trkr);
+
+    // Copy data to tc buffer
+    memcpy(&raw_star_trkr,&data[0],len);
+
+    // Debug print
+    printf("Raw num_stars_detected:- %d\n",raw_star_trkr.num_stars_detected);
+    printf("Raw star_image_noise:- %d\n",raw_star_trkr.star_image_noise);
+    printf("Raw invalid_stars:- %d\n",raw_star_trkr.invalid_stars);
+    printf("Raw num_stars_id:- %d\n",raw_star_trkr.num_stars_id);
+    printf("Raw id_mode:- %d\n",raw_star_trkr.id_mode);
+    printf("Raw image_dark_value:- %d\n",raw_star_trkr.image_dark_value);
+    printf("Raw image_capture_success:- %d\n",\
+    raw_star_trkr.image_capture_success);
+    printf("Raw detection_success:- %d\n",raw_star_trkr.detection_success);
+    printf("Raw id_success:- %d\n",raw_star_trkr.id_success);
+    printf("Raw attitude_success:- %d\n",raw_star_trkr.attitude_success);
+    printf("Raw processing_time_error:- %d\n",\
+    raw_star_trkr.processing_time_error);
+    printf("Raw tracking_module_enabled:- %d\n",\
+    raw_star_trkr.tracking_module_enabled);
+    printf("Raw prediction_enabled:- %d\n",raw_star_trkr.prediction_enabled);
+    printf("Raw comms_error:- %d\n",raw_star_trkr.comms_error);
+    printf("Raw s1_conf:- %d\n",raw_star_trkr.s1_conf);
+    printf("Raw s2_conf:- %d\n",raw_star_trkr.s2_conf);
+    printf("Raw s3_conf:- %d\n",raw_star_trkr.s3_conf);
+    printf("Raw mag_star_1:- %d\n",raw_star_trkr.mag_star_1);
+    printf("Raw mag_star_2:- %d\n",raw_star_trkr.mag_star_2);
+    printf("Raw mag_star_3:- %d\n",raw_star_trkr.mag_star_3);
+    printf("Raw capture:- %d\n",raw_star_trkr.capture);
+    printf("Raw detection:- %d\n",raw_star_trkr.detection);
+    printf("Raw id:- %d\n",raw_star_trkr.id);
+    printf("Raw rate_x:- %lf\n",raw_star_trkr.rate_x);
+    printf("Raw rate_y:- %lf\n",raw_star_trkr.rate_y);
+    printf("Raw rate_z:- %lf\n",raw_star_trkr.rate_z);
+    printf("Raw est_attitude_q1:- %lf\n",raw_star_trkr.est_attitude_q1);
+    printf("Raw est_attitude_q2:- %lf\n",raw_star_trkr.est_attitude_q2);
+    printf("Raw est_attitude_q3:- %lf\n",raw_star_trkr.est_attitude_q3);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker raw data
+ */
+uint16_t adcs_bsk_ext_tlm_raw_star_data(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_star_trkr raw_star_trkr  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_star_trkr);
+
+    // Copy data to tc buffer
+    memcpy(&raw_star_trkr,&data[0],len);
+
+    // Debug print
+    printf("Raw num_stars_detected:- %d\n",raw_star_trkr.num_stars_detected);
+    printf("Raw star_image_noise:- %d\n",raw_star_trkr.star_image_noise);
+    printf("Raw invalid_stars:- %d\n",raw_star_trkr.invalid_stars);
+    printf("Raw num_stars_id:- %d\n",raw_star_trkr.num_stars_id);
+    printf("Raw id_mode:- %d\n",raw_star_trkr.id_mode);
+    printf("Raw image_dark_value:- %d\n",raw_star_trkr.image_dark_value);
+    printf("Raw image_capture_success:- %d\n",\
+    raw_star_trkr.image_capture_success);
+    printf("Raw detection_success:- %d\n",raw_star_trkr.detection_success);
+    printf("Raw id_success:- %d\n",raw_star_trkr.id_success);
+    printf("Raw attitude_success:- %d\n",raw_star_trkr.attitude_success);
+    printf("Raw processing_time_error:- %d\n",\
+    raw_star_trkr.processing_time_error);
+    printf("Raw tracking_module_enabled:- %d\n",\
+    raw_star_trkr.tracking_module_enabled);
+    printf("Raw prediction_enabled:- %d\n",raw_star_trkr.prediction_enabled);
+    printf("Raw comms_error:- %d\n",raw_star_trkr.comms_error);
+    printf("Raw s1_conf:- %d\n",raw_star_trkr.s1_conf);
+    printf("Raw s2_conf:- %d\n",raw_star_trkr.s2_conf);
+    printf("Raw s3_conf:- %d\n",raw_star_trkr.s3_conf);
+    printf("Raw mag_star_1:- %d\n",raw_star_trkr.mag_star_1);
+    printf("Raw mag_star_2:- %d\n",raw_star_trkr.mag_star_2);
+    printf("Raw mag_star_3:- %d\n",raw_star_trkr.mag_star_3);
+    printf("Raw capture:- %d\n",raw_star_trkr.capture);
+    printf("Raw detection:- %d\n",raw_star_trkr.detection);
+    printf("Raw id:- %d\n",raw_star_trkr.id);
+    printf("Raw rate_x:- %lf\n",raw_star_trkr.rate_x);
+    printf("Raw rate_y:- %lf\n",raw_star_trkr.rate_y);
+    printf("Raw rate_z:- %lf\n",raw_star_trkr.rate_z);
+    printf("Raw est_attitude_q1:- %lf\n",raw_star_trkr.est_attitude_q1);
+    printf("Raw est_attitude_q2:- %lf\n",raw_star_trkr.est_attitude_q2);
+    printf("Raw est_attitude_q3:- %lf\n",raw_star_trkr.est_attitude_q3);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Raw Magnetometer
+ */
+uint16_t adcs_bsk_ext_tlm_sec_raw_magmtr_measure(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_mgmtr raw_mgmtr  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_mgmtr);
+
+    // Copy data to tc buffer
+    memcpy(&raw_mgmtr,&data[0],len);
+
+    // Debug print
+    printf("Raw magnetometer X:- %d\n",raw_mgmtr.mag_raw_x);
+    printf("Raw magnetometer Y:- %d\n",raw_mgmtr.mag_raw_y);
+    printf("Raw magnetometer Z:- %d\n",raw_mgmtr.mag_raw_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Rate sensor raw measurement
+ */
+uint16_t adcs_bsk_ext_tlm_raw_rates(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_raw_rate_sens raw_rate  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_raw_rate_sens);
+
+    // Copy data to tc buffer
+    memcpy(&raw_rate,&data[0],len);
+
+    // Debug print
+    printf("X axis raw rate sensor:- %d\n",raw_rate.raw_rate_x);
+    printf("Y axis raw rate sensor:- %d\n",raw_rate.raw_rate_y);
+    printf("Z axis raw rate sensor:- %d\n",raw_rate.raw_rate_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Estimated star tracker rates
+ */
+uint16_t adcs_bsk_ext_tlm_star_est_rate(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_est_rate star_est_rate  = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_est_rate);
+
+    // Copy data to tc buffer
+    memcpy(&star_est_rate,&data[0],len);
+
+    // Debug print
+    printf("Estimated X Rate measurement:- %d\n",star_est_rate.x_axis_rate);
+    printf("Estimated Y Rate measurement:- %d\n",star_est_rate.x_axis_rate);
+    printf("Estimated Z Rate measurement:- %d\n",star_est_rate.x_axis_rate);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Sensors Current measurement
+ */
+uint16_t adcs_bsk_ext_tlm_sensor_current(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_sens_cur sens_current = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_sens_cur);
+
+    // Copy data to tc buffer
+    memcpy(&sens_current,&data[0],len);
+
+    // Debug print
+    printf("Nadir Current:- %lf\n",sens_current.nadir_current);
+    printf("CSS Current:- %lf\n",sens_current.css_current);
+    printf("FSS Current:- %lf\n",sens_current.fss_current);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Current measurement
+ */
+uint16_t adcs_bsk_ext_tlm_con_current_measure(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_current current_mesr = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_current);
+
+    // Copy data to tc buffer
+    memcpy(&current_mesr,&data[0],len);
+
+    // Debug print
+    printf("Current in 3.3V:- %d\n",current_mesr.current_3v3);
+    printf("Current in 5V:- %d\n",current_mesr.current_5v);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Reaction wheel Current parameter
+ */
+uint16_t adcs_bsk_ext_tlm_rw_current(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len = 0;
+    s_adcs_rw_cur *rw_current = {0};
+
+    // Assign payload data to the pointer
+    rw_current = (s_adcs_rw_cur*)&data[1];
+
+    printf("Reaction wheel count:- %d\n", data[0]);
+    for(int i = 0; i < data[0]; i++)
+    {
+        // Debug print
+        printf("Reaction Wheel %d Current:- %lf\n",i + 1, rw_current[i].rw_current);
+    }
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Temperature measurement
+ */
+uint16_t adcs_bsk_ext_tlm_temperature(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_temperature temp_msr = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_temperature);
+
+    // Copy data to tc buffer
+    memcpy(&temp_msr,&data[0],len);
+
+    // Debug print
+    printf("MCU Temperature:- %d\n",temp_msr.mcu_temperature);
+    printf("Magnetometer Temperature:- %d\n",temp_msr.mgmtr_temperature);
+    printf("Rate Sensor Temperature:- %d\n",temp_msr.rate_sensor_temperature);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Rate sensor temeprature measurement
+ */
+uint16_t adcs_bsk_ext_tlm_rate_sensor_temperature(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_rate_temperature rate_temp = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_rate_temperature);
+
+    // Copy data to tc buffer
+    memcpy(&rate_temp,&data[0],len);
+
+    // Debug print
+    printf("Rate Sensor X Temperature:- %d\n",rate_temp.x_rate_temp);
+    printf("Rate Sensor Y Temperature:- %d\n",rate_temp.y_rate_temp);
+    printf("Rate Sensor Z Temperature:- %d\n",rate_temp.z_rate_temp);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the ADCS Current and Temperature
+ */
+uint16_t adcs_bsk_ext_tlm_power_temperature(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_cur_temp cur_temp;
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_cur_temp);
+
+    // Copy data to tc buffer
+    memcpy(&cur_temp,&data[0],len);
+
+    // Debug print
+    printf("Current in 3.3V:- %d\n",cur_temp.adcs_current.current_3v3);
+    printf("Current in 5V:- %d\n",cur_temp.adcs_current.current_5v);
+    printf("MCU Temperature:- %d\n",cur_temp.adcs_temp.mcu_temperature);
+    printf("Magnetometer Temperature:- %d\n",\
+    cur_temp.adcs_temp.mgmtr_temperature);
+    printf("Rate Sensor Temperature:- %d\n",\
+    cur_temp.adcs_temp.rate_sensor_temperature);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Gyro configuration
+ */
+uint16_t adcs_bsk_ext_tlm_gyro_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_gyro_cfg gyro_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_gyro_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&gyro_param,&data[0],len);
+
+    // Debug print
+    printf("gyro config:- %d\n",gyro_param.gyro_conf);
+    printf("x_rate_offset:- %f\n",gyro_param.x_rate_offset);
+    printf("y_rate_offset:- %f\n",gyro_param.y_rate_offset);
+    printf("z_rate_offset:- %f\n",gyro_param.z_rate_offset);
+    printf("rate_sensor_mult:- %d\n",gyro_param.rate_sensor_mult);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Star Tracker configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_star_trkr_cgf(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_star_trkr_cfg star_trkr_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_star_trkr_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&star_trkr_param,&data[0],len);
+
+    // Debug print
+    printf("angle_1:- %lf\n",star_trkr_param.angle_1);
+    printf("angle_2:- %lf\n",star_trkr_param.angle_2);
+    printf("angle_3:- %lf\n",star_trkr_param.angle_3);
+    printf("exposure:- %d\n",star_trkr_param.exposure);
+    printf("gain:- %d\n",star_trkr_param.gain);
+    printf("detection_threshold:- %d\n",star_trkr_param.detection_threshold);
+    printf("threshold:- %d\n",star_trkr_param.threshold);
+    printf("max_star_matched:- %d\n",star_trkr_param.max_star_matched);
+    printf("timeout_time:- %d\n",star_trkr_param.timeout_time);
+    printf("max_star_pixel:- %d\n",star_trkr_param.max_star_pixel);
+    printf("min_star_pixel:- %d\n",star_trkr_param.min_star_pixel);
+    printf("error_margin:- %lf\n",star_trkr_param.error_margin);
+    printf("delay_time:- %d\n",star_trkr_param.delay_time);
+    printf("cent_x:- %f\n",star_trkr_param.cent_x);
+    printf("cent_y:- %f\n",star_trkr_param.cent_y);
+    printf("focal:- %f\n",star_trkr_param.focal);
+    printf("lens_k1:- %f\n",star_trkr_param.lens_k1);
+    printf("lens_k2:- %f\n",star_trkr_param.lens_k2);
+    printf("lens_p1:- %f\n",star_trkr_param.lens_p1);
+    printf("lens_p2:- %f\n",star_trkr_param.lens_p2);
+    printf("window_width:- %d\n",star_trkr_param.window_width);
+    printf("tracking_margin:- %lf\n",star_trkr_param.tracking_margin);
+    printf("validation_margin:- %lf\n",star_trkr_param.validation_margin);
+    printf("module_enable:- %d\n",star_trkr_param.module_enable);
+    printf("location_prediction_enable:- %d\n",\
+    star_trkr_param.location_prediction_enable);
+    printf("search_width:- %lf\n",star_trkr_param.search_width);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Magnetometer configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_mgmtr_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_mgmtr_cfg mgmtr_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_mgmtr_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&mgmtr_param,&data[0],len);
+
+    // Debug print
+    printf("angle_1:- %lf\n",mgmtr_param.angle_1);
+    printf("angle_2:- %lf\n",mgmtr_param.angle_2);
+    printf("angle_3:- %lf\n",mgmtr_param.angle_3);
+    printf("offset_1:- %lf\n",mgmtr_param.offset_1);
+    printf("offset_2:- %lf\n",mgmtr_param.offset_2);
+    printf("offset_3:- %lf\n",mgmtr_param.offset_3);
+    printf("sens_11:- %lf\n",mgmtr_param.sens_11);
+    printf("sens_12:- %lf\n",mgmtr_param.sens_12);
+    printf("sens_13:- %lf\n",mgmtr_param.sens_13);
+    printf("sens_21:- %lf\n",mgmtr_param.sens_21);
+    printf("sens_22:- %lf\n",mgmtr_param.sens_22);
+    printf("sens_23:- %lf\n",mgmtr_param.sens_23);
+    printf("sens_31:- %lf\n",mgmtr_param.sens_31);
+    printf("sens_32:- %lf\n",mgmtr_param.sens_32);
+    printf("sens_33:- %lf\n",mgmtr_param.sens_33);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Coarse Sun Sensor configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_css_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_css_cfg css_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_css_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&css_param,&data[0],len);
+
+    // Debug print
+    printf("Css config:- %d\n",css_param.css_conf);
+    printf("css_scale:- %lf\n",css_param.css_scale);
+    printf("css_min:- %d\n",css_param.css_min);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Fine Sun Sensor configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_fss_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_fss_cfg fss_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_fss_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&fss_param,&data[0],len);
+
+    // Debug print
+    printf("fss config:- %d\n",fss_param.fss_conf);
+    printf("fss_scale:- %lf\n",fss_param.fss_scale);
+    printf("fss_min:- %d\n",fss_param.fss_min);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Nadir configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_nadir_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_nadir_cfg nadir_cfg_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_nadir_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&nadir_cfg_param,&data[0],len);
+
+    // Debug print
+    printf("max_deviation_pct:- %d\n",nadir_cfg_param.max_deviation_pct);
+    printf("max_bad_edges:- %d\n",nadir_cfg_param.max_bad_edges);
+    printf("max_radius:- %d\n",nadir_cfg_param.max_radius);
+    printf("min_radius:- %d\n",nadir_cfg_param.min_radius);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Redundant  Magnetometer configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_red_mgmtr_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_mgmtr_cfg red_mgmtr_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_mgmtr_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&red_mgmtr_param,&data[0],len);
+
+    // Debug print
+    printf("angle_1:- %lf\n",red_mgmtr_param.angle_1);
+    printf("angle_2:- %lf\n",red_mgmtr_param.angle_2);
+    printf("angle_3:- %lf\n",red_mgmtr_param.angle_3);
+    printf("offset_1:- %lf\n",red_mgmtr_param.offset_1);
+    printf("offset_2:- %lf\n",red_mgmtr_param.offset_2);
+    printf("offset_3:- %lf\n",red_mgmtr_param.offset_3);
+    printf("sens_11:- %lf\n",red_mgmtr_param.sens_11);
+    printf("sens_12:- %lf\n",red_mgmtr_param.sens_12);
+    printf("sens_13:- %lf\n",red_mgmtr_param.sens_13);
+    printf("sens_21:- %lf\n",red_mgmtr_param.sens_21);
+    printf("sens_22:- %lf\n",red_mgmtr_param.sens_22);
+    printf("sens_23:- %lf\n",red_mgmtr_param.sens_23);
+    printf("sens_31:- %lf\n",red_mgmtr_param.sens_31);
+    printf("sens_32:- %lf\n",red_mgmtr_param.sens_32);
+    printf("sens_33:- %lf\n",red_mgmtr_param.sens_33);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Magnetorquer configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_mgntrqr_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_mgntrqr_cfg mgntrqr_config_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_mgntrqr_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&mgntrqr_config_param,&data[0],len);
+
+    // Debug print
+    printf("Magnetoquer Axis:- %d\n",mgntrqr_config_param.mgntrqr_axis);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Reaction Wheel configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_rw_cfg(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_rw_cfg rw_cfg_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_rw_cfg);
+
+    // Copy data to tc buffer
+    memcpy(&rw_cfg_param,&data[0],len);
+
+    // Debug print
+    printf("RW 1 Axis:- %d\n",rw_cfg_param.rw_conf);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Detumble control configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_detumble_param(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_detumble_ctrl detumble_ctrl_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_detumble_ctrl);
+
+    // Copy data to tc buffer
+    memcpy(&detumble_ctrl_param,&data[0],len);
+
+    // Debug print
+    printf("spin_gain:- %f\n",detumble_ctrl_param.spin_gain);
+    printf("damping_gain:- %f\n",detumble_ctrl_param.damping_gain);
+    printf("rw_ref_spin_rate:- %lf\n",detumble_ctrl_param.rw_ref_spin_rate);
+    printf("f_bdot_gain:- %f\n",detumble_ctrl_param.f_bdot_gain);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Y axis reaction wheel control configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_y_rw_ctrl(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_y_rw_ctrl y_rw_ctrl_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_y_rw_ctrl);
+
+    // Copy data to tc buffer
+    memcpy(&y_rw_ctrl_param,&data[0],len);
+
+    // Debug print
+    printf("Y ctrl_gain:- %f\n",y_rw_ctrl_param.ctrl_gain);
+    printf("Y nutation_damp_gain:- %f\n",y_rw_ctrl_param.nutation_damp_gain);
+    printf("Y prop_gain:- %lf\n",y_rw_ctrl_param.prop_gain);
+    printf("Y derv_gain:- %f\n",y_rw_ctrl_param.derv_gain);
+    printf("Y ref_rw_mom:- %f\n",y_rw_ctrl_param.ref_rw_mom);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Reaction wheel control configuration parameters
+ */
+uint16_t adcs_bsk_ext_tlm_rw_ctrl(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_rw_ctrl rw_ctrl_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_rw_ctrl);
+
+    // Copy data to tc buffer
+    memcpy(&rw_ctrl_param,&data[0],len);
+
+    // Debug print
+    printf("spin_gain:- %f\n",rw_ctrl_param.rw_prop_gain);
+    printf("nutation_damp_gain:- %f\n",rw_ctrl_param.rw_derv_gain);
+    printf("prop_gain:- %lf\n",rw_ctrl_param.y_rw_bias);
+    printf("sun_point_facet:- %d\n",rw_ctrl_param.sun_point_facet);
+    printf("rw_error_handling:- %d\n",rw_ctrl_param.rw_error_handling);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Tracking control gain parameters
+ */
+uint16_t adcs_bsk_ext_tlm_trck_ctrl_gain(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_trck_ctrl_gain trck_ctrl_gain = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_trck_ctrl_gain);
+
+    // Copy data to tc buffer
+    memcpy(&trck_ctrl_gain,&data[0],len);
+
+    // Debug print
+    printf("prop_gain:- %f\n",trck_ctrl_gain.prop_gain);
+    printf("derv_gain:- %f\n",trck_ctrl_gain.derv_gain);
+    printf("integ_gain:- %f\n",trck_ctrl_gain.integ_gain);
+    printf("target_Track_Facet:- %d\n",trck_ctrl_gain.target_Track_Facet);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Attitude Angle gain parameters
+ */
+uint16_t adcs_bsk_ext_tlm_attitude(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_attitude_angl attitude_angle = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_attitude_angl);
+
+    // Copy data to tc buffer
+    memcpy(&attitude_angle,&data[0],len);
+
+    // Debug print
+    printf("roll:- %lf\n",attitude_angle.roll);
+    printf("pitch:- %lf\n",attitude_angle.pitch);
+    printf("yaw:- %lf\n",attitude_angle.yaw);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Target Tarcking parameters
+ */
+uint16_t adcs_bsk_ext_tlm_target_track(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_trck_target trck_target_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_trck_target);
+
+    // Copy data to tc buffer
+    memcpy(&trck_target_param,&data[0],len);
+
+    // Debug print
+    printf("lat_ref:- %lf\n",trck_target_param.lat_ref);
+    printf("long_ref:- %lf\n",trck_target_param.long_ref);
+    printf("alt_ref:- %lf\n",trck_target_param.alt_ref);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Interial reference
+ */
+uint16_t adcs_bsk_ext_tlm_inertial_ref(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_inrt_ref inrt_ref = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_inrt_ref);
+
+    // Copy data to tc buffer
+    memcpy(&inrt_ref,&data[0],len);
+
+    // Debug print
+    printf("iner_ref_x:- %d\n",inrt_ref.iner_ref_x);
+    printf("iner_ref_y:- %d\n",inrt_ref.iner_ref_y);
+    printf("iner_ref_z:- %d\n",inrt_ref.iner_ref_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Estimation parameters
+ */
+uint16_t adcs_bsk_ext_tlm_est_param(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_est_param est_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_est_param);
+
+    // Copy data to tc buffer
+    memcpy(&est_param,&data[0],len);
+
+    // Debug print
+    printf("mag_rate_noise:- %f\n",est_param.mag_rate_noise);
+    printf("ekf_sys_noise:- %f\n",est_param.ekf_sys_noise);
+    printf("css_noise:- %f\n",est_param.css_noise);
+    printf("sun_noise:- %f\n",est_param.sun_noise);
+    printf("nadir_noise:- %f\n",est_param.nadir_noise);
+    printf("mag_noise:- %f\n",est_param.mag_noise);
+    printf("star_noise:- %f\n",est_param.star_noise);
+    printf("use_sun_est:- %d\n",est_param.use_sun_est);
+    printf("use_nadir_est:- %d\n",est_param.use_nadir_est);
+    printf("use_css_est:- %d\n",est_param.use_css_est);
+    printf("use_star_est:- %d\n",est_param.use_star_est);
+    printf("nadir_terminator_check:- %d\n",est_param.nadir_terminator_check);
+    printf("mag_mode:- %d\n",est_param.mag_mode);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the ECI position of the sattlite
+ */
+uint16_t adcs_bsk_ext_tlm_eci_postition(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_eci_position eci_position = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_eci_position);
+
+    // Copy data to tc buffer
+    memcpy(&eci_position,&data[0],len);
+
+    // Debug print
+    printf("Position X:- %d\n",eci_position.position_x);
+    printf("Position Y:- %d\n",eci_position.position_y);
+    printf("Position Z:- %d\n",eci_position.position_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the ECI velocity of the Sattelite
+ */
+uint16_t adcs_bsk_ext_tlm_sat_velocity(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_eci_velocity eci_velocity = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_eci_velocity);
+
+    // Copy data to tc buffer
+    memcpy(&eci_velocity,&data[0],len);
+
+    // Debug print
+    printf("Velocity X:- %d\n",eci_velocity.velocity_x);
+    printf("Velocity Y:- %d\n",eci_velocity.velocity_y);
+    printf("Velocity Z:- %d\n",eci_velocity.velocity_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Position LLH
+ */
+uint16_t adcs_bsk_ext_tlm_llh_psition(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_trck_target trck_target_param = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_trck_target);
+
+    // Copy data to tc buffer
+    memcpy(&trck_target_param,&data[0],len);
+
+    // Debug print
+    printf("lat_ref:- %lf\n",trck_target_param.lat_ref);
+    printf("long_ref:- %lf\n",trck_target_param.long_ref);
+    printf("alt_ref:- %lf\n",trck_target_param.alt_ref);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Estimated angular rates
+ */
+uint16_t adcs_bsk_ext_tlm_est_rate(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_est_rate est_rate = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_est_rate);
+
+    // Copy data to tc buffer
+    memcpy(&est_rate,&data[0],len);
+
+    // Debug print
+    printf("Est X Angular Rate:- %d\n",est_rate.est_x_angular_rate);
+    printf("Est Y Angular Rate:- %d\n",est_rate.est_y_angular_rate);
+    printf("Est Z Angular Rate:- %d\n",est_rate.est_z_angular_rate);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Estimated quaternion
+ */
+uint16_t adcs_bsk_ext_tlm_est_qutrn(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_est_qutrn est_qutrn = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_est_qutrn);
+
+    // Copy data to tc buffer
+    memcpy(&est_qutrn,&data[0],len);
+
+    // Debug print
+    printf("Est Quaternion 1:- %d\n",est_qutrn.est_qutrn_1);
+    printf("Est Quaternion 2:- %d\n",est_qutrn.est_qutrn_2);
+    printf("Est Quaternion 3:- %d\n",est_qutrn.est_qutrn_3);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the ECEF position of the sattlite
+ */
+uint16_t adcs_bsk_ext_tlm_ecef_position(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_eci_position ecef_position = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_eci_position);
+
+    // Copy data to tc buffer
+    memcpy(&ecef_position,&data[0],len);
+
+    // Debug print
+    printf("Position X:- %d\n",ecef_position.position_x);
+    printf("Position Y:- %d\n",ecef_position.position_y);
+    printf("Position Z:- %d\n",ecef_position.position_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Magnetic filed vector measurement
+ */
+uint16_t adcs_bsk_ext_tlm_mod_mag_vector(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_mag_vector mag_vec = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_mag_vector);
+
+    // Copy data to tc buffer
+    memcpy(&mag_vec,&data[0],len);
+
+    // Debug print
+    printf("Magnetic Vector X:- %d\n",mag_vec.mag_filed_x);
+    printf("Magnetic Vector Y:- %d\n",mag_vec.mag_filed_y);
+    printf("Magnetic Vector Z:- %d\n",mag_vec.mag_filed_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Sun Vector measurement
+ */
+uint16_t adcs_bsk_ext_tlm_mod_sun_vector(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_sun_vector sun_vec = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_sun_vector);
+
+    // Copy data to tc buffer
+    memcpy(&sun_vec,&data[0],len);
+
+    // Debug print
+    printf("Sun Vector X:- %d\n",sun_vec.sun_x);
+    printf("Sun Vector Y:- %d\n",sun_vec.sun_y);
+    printf("Sun Vector Z:- %d\n",sun_vec.sun_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Estimation gyro measurement
+ */
+uint16_t adcs_bsk_ext_tlm_est_gyro_measure(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_est_gyro est_gyro = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_est_gyro);
+
+    // Copy data to tc buffer
+    memcpy(&est_gyro,&data[0],len);
+
+    // Debug print
+    printf("Estimated X-gyro Bias:- %d\n",est_gyro.est_gyro_x);
+    printf("Estimated Y-gyro Bias:- %d\n",est_gyro.est_gyro_y);
+    printf("Estimated Z-gyro Bias:- %d\n",est_gyro.est_gyro_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Estimation innovation vector
+ */
+uint16_t adcs_bsk_ext_tlm_est_innovation(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_est_innovn est_innovn = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_est_innovn);
+
+    // Copy data to tc buffer
+    memcpy(&est_innovn,&data[0],len);
+
+    // Debug print
+    printf("Innovation Vector X:- %d\n",est_innovn.innovn_vec_x);
+    printf("Innovation Vector Y:- %d\n",est_innovn.innovn_vec_y);
+    printf("Innovation Vector Z:- %d\n",est_innovn.innovn_vec_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Quaternion error vector
+ */
+uint16_t adcs_bsk_ext_tlm_qutrn_error(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_qutr_error qutr_error = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_qutr_error);
+
+    // Copy data to tc buffer
+    memcpy(&qutr_error,&data[0],len);
+
+    // Debug print
+    printf("Quaternion Error -Q1:- %d\n",qutr_error.qutr_error_q1);
+    printf("Quaternion Error -Q2:- %d\n",qutr_error.qutr_error_q2);
+    printf("Quaternion Error -Q3:- %d\n",qutr_error.qutr_error_q3);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Quaternion covariance
+ */
+uint16_t adcs_bsk_ext_tlm_qutrn_covr(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_qutr_covr qutr_covr = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_qutr_covr);
+
+    // Copy data to tc buffer
+    memcpy(&qutr_covr,&data[0],len);
+
+    // Debug print
+    printf("Quaternion Covariance - Q1:- %d\n",qutr_covr.qutr_covr_q1);
+    printf("Quaternion Covariance - Q2:- %d\n",qutr_covr.qutr_covr_q2);
+    printf("Quaternion Covariance - Q3:- %d\n",qutr_covr.qutr_covr_q3);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Angular rate covariance
+ */
+uint16_t adcs_bsk_ext_tlm_ang_rate_covr(uint8_t *data)
+{
+    // Variable decleration
+    uint16_t len;
+    s_adcs_angl_rate_covr rate_covr = {0};
+
+    // Value assignment to variable
+    len = sizeof(s_adcs_angl_rate_covr);
+
+    // Copy data to tc buffer
+    memcpy(&rate_covr,&data[0],len);
+
+    // Debug print
+    printf("X Angular Rate Covariance:- %d\n",rate_covr.covr_ang_rate_x);
+    printf("Y Angular Rate Covariance:- %d\n",rate_covr.covr_ang_rate_y);
+    printf("Z Angular Rate Covariance:- %d\n",rate_covr.covr_ang_rate_z);
+
+    return len;
+}
+
+/**
+ * @brief This function extract the Control mode configuration
+ */
+void adcs_bsk_ext_tlm_ctrl_mode(uint8_t *data)
+{
+    // Variable decleration
+    s_adcs_ctrl_mode cntrl_mode = {0};
+    u_control_mode_param control_param;
+
+    // Copy data to tc buffer
+    cntrl_mode.ctrl_mode = data[0];
+
+    printf("Crtl Mode :- %d\n",cntrl_mode.ctrl_mode);
+
+    // Select control mode
+    switch(cntrl_mode.ctrl_mode)
+    {
+        case ADCS_CTRL_MODE_THREE_AXIS:             // 3axis stabilization
+        {
+            // Copy data to local variable
+            memcpy(&control_param.attitude_ctrl, &data[1],
+                    sizeof(s_adcs_attitude_angl));
+            printf("Roll %lf Pitch %lf Yaw %lf\n",\
+                    control_param.attitude_ctrl.roll,\
+                    control_param.attitude_ctrl.pitch,\
+                    control_param.attitude_ctrl.yaw);
+        }
+        break;
+        case ADCS_CTRL_MODE_TARGET_TRACKING:        // Target tracking
+        {
+            printf("Target Tracking\n");
+
+            // Copy data to local variable
+            memcpy(&control_param.target_track_ctrl, &data[1],
+                    sizeof(s_adcs_trck_target));
+            printf("Longtitude %f Latitude %f Altitude %f\n",\
+                    control_param.target_track_ctrl.long_ref,\
+                    control_param.target_track_ctrl.lat_ref,\
+                    control_param.target_track_ctrl.alt_ref);
+        }
+        break;
+        case ADCS_CTRL_MODE_SUN_POINTING:           // Sun pointing
+        {
+            printf("Sun Tracking\n");
+        }
+        break;
+        case ADCS_CTRL_MODE_NADIR_POINTING:         // Nadir pointing
+        {
+            // Copy data to local variable
+            memcpy(&control_param.nadir_point_mode, &data[1], 4);
+            printf("Nadir Pointing Mode:- %d\n",\
+            control_param.nadir_point_mode);
+        }
+        break;
+        case ADCS_CTRL_MODE_NONE:                   // No control mode
+        {
+            printf("Control mode none\n");
+        }
+        break;
+        case ADCS_CTRL_MODE_DETUMBLING:             // Detumbling control mode
+        {
+            printf("Control mode detumbling\n");
+        }
+        break;
+        case ADCS_CTRL_MODE_Y_SPIN_STABILIZATION:   // Y Spin Stabilization
+        {
+            printf("Control mode Y Spin\n");
+        }
+        break;
+        case ADCS_CTRL_MODE_Z_SPIN_STABILIZATION:   // Z Spin Stabilization
+        {
+            printf("Control mode Z Spin\n");
+        }
+        break;
+        case ADCS_CTRL_MODE_CUSTOM:                 // Custom control mode
+        {
+            printf("Control Custom mode\n");
+        }
+        break;
+        default:
+        {
+            printf("CTRL Default Case\n");
+            //data = 1;
+        }
+        break;
+    }
+}
+
+/**
+ * @brief This function extract the Reaction wheel speed command
+ */
+void adcs_bsk_ext_tlm_rw_speed_cmd(uint8_t *data)
+{
+    // Variable decleration
+    s_adcs_rw_speed *rw_speed = {0};
+
+    // Assign payload data to the pointer
+    rw_speed = (s_adcs_rw_speed*)&data[1];
+
+    printf("Reaction wheel count:- %d\n", data[0]);
+    for(int i = 0; i < data[0]; i++)
+    {
+        // Debug print
+        printf("Commanded Wheel %d Speed:- %d\n",i + 1, rw_speed[i].rw_speed);
+    }
+}
+
+/**
+ * @brief This function extract the Reaction wheel speed measurement
+ */
+void adcs_bsk_ext_tlm_rw_speed_measure(uint8_t *data)
+{
+    // Variable decleration
+    s_adcs_rw_speed *rw_speed = {0};
+
+    // Assign payload data to the pointer
+    rw_speed = (s_adcs_rw_speed*)&data[1];
+
+    printf("Reaction wheel count:- %d\n", data[0]);
+    for(int i = 0; i < data[0]; i++)
+    {
+        // Debug print
+        printf("Measured Wheel %d Speed:- %d\n",i + 1, rw_speed[i].rw_speed);
+    }
+}
+
+/**
+ * @brief This function extract the telemetry data based on telemetry id.
+ */
+void unfied_tlm_data_extract(uint8_t *data,uint16_t pld_len,uint8_t id)
+{
+    if(id >= API_RESP_ID)
+    {
+        switch(id)
+        {
+            case API_RESP_ID:                // Get Identification
+            {
+                adcs_bsk_ext_tlm_id(data);
+            }
+            break;
+            case API_RESP_STATE:             // Get ADCS state
+            {
+                adcs_bsk_ext_tlm_state(data);
+            }
+            break;
+            case API_RESP_TLE:               // Get TLE
+            {
+                adcs_bsk_ext_tlm_tle(data);
+            }
+            break;
+            case API_RESP_MOI:               // Get moment of inetria
+            {
+                adcs_bsk_ext_tlm_moi(data);
+            }
+            break;
+            case API_RESP_PWR:               // Get power configuration
+            {
+                adcs_bsk_ext_tlm_power(data);
+            }
+            break;
+            case API_RESP_MAG_FIELD_VEC:     // Get magnetic field vector
+            {
+                adcs_bsk_ext_tlm_mag_vector(data);
+            }
+            break;
+            case API_RESP_CSS_VEC:           // Get CSS vector
+            {
+                adcs_bsk_ext_tlm_css_sun_vector(data);
+            }
+            break;
+            case API_RESP_FSS_VEC:           // Get FSS vector
+            {
+                adcs_bsk_ext_tlm_fss_sun_vector(data);
+            }
+            break;
+            case API_RESP_NADIR_VEC:         // Get nadir vector
+            {
+                adcs_bsk_ext_tlm_nadir_vector(data);
+            }
+            break;
+            case API_RESP_SENSOR_RATE:       // Get sensor rate
+            {
+                adcs_bsk_ext_tlm_sensor_rate(data);
+            }
+            break;
+            case API_RESP_STAR_TRKR_BVEC:    // Get star tracker body vector
+            {
+                adcs_bsk_ext_tlm_star_body(data);
+            }
+            break;
+            case API_RESP_STAR_TRKR_OVEC:    // Get star trackere orbit vector
+            {
+                adcs_bsk_ext_tlm_star_orbit(data);
+            }
+            break;
+            case API_RESP_RAW_NADIR_SEN:     // Get raw nadir sensor meaurement
+            {
+                adcs_bsk_ext_tlm_raw_nadir(data);
+            }
+            break;
+            case API_RESP_RAW_FSS_SEN:  // Get raw fine sun sensor measurement
+            {
+                adcs_bsk_ext_tlm_raw_fss(data);
+            }
+            break;
+            case API_RESP_RAW_MAGMTR:   // Get raw magnetometer measurement
+            {
+                adcs_bsk_ext_tlm_raw_magmtr(data);
+            }
+            break;
+            case API_RESP_RAW_GPS_STS:       // Get raw GPS staus
+            {
+                adcs_bsk_ext_tlm_raw_gps_status(data);
+            }
+            break;
+            case API_RESP_RAW_GPS_TIME:      // Get raw GPS time
+            {
+                adcs_bsk_ext_tlm_raw_gps_time(data);
+            }
+            break;
+            case API_RESP_RAW_GPS_X:         // Get raw GPS X axis
+            {
+                adcs_bsk_ext_tlm_raw_gps_x(data);
+            }
+            break;
+            case API_RESP_RAW_GPS_Y:         // Get raw GPS Y axis
+            {
+                adcs_bsk_ext_tlm_raw_gps_y(data);
+            }
+            break;
+            case API_RESP_RAW_GPS_Z:         // Get raw GPS Z axis
+            {
+                adcs_bsk_ext_tlm_raw_gps_z(data);
+            }
+            break;
+            case API_RESP_STAR_MAG:          // Get star magnitude
+            {
+                adcs_bsk_ext_tlm_star_magnitude(data);
+            }
+            break;
+            case API_RESP_STAR_PERFORM:      // Get star performance
+            {
+                adcs_bsk_ext_tlm_star_performance(data);
+            }
+            break;
+            case API_RESP_STAR_TIMING:       // Get star timing
+            {
+                adcs_bsk_ext_tlm_star_timing(data);
+            }
+            break;
+            case API_RESP_RAW_SENS:          // Get raw sensor measurement
+            {
+                adcs_bsk_ext_tlm_raw_sensor_measure(data);
+            }
+            break;
+            case API_RESP_RAW_GPS:           // Get raw GPS measurement
+            {
+                adcs_bsk_ext_tlm_raw_gps_measure(data);
+            }
+            break;
+            case API_RESP_RAW_STAR_TRAC:    // Get raw star tracker measurement
+            {
+                adcs_bsk_ext_tlm_raw_star_measure(data);
+            }
+            break;
+            case API_RESP_STAR_RDATA:        // Get raw star tracker data
+            {
+                adcs_bsk_ext_tlm_raw_star_data(data);
+            }
+            break;
+            case API_RESP_RAW_SEC_MAGMTR:    // Get raw secondary magnetometer
+            {
+                adcs_bsk_ext_tlm_sec_raw_magmtr_measure(data);
+            }
+            break;
+            case API_RESP_RAW_SENS_RATE:     // Get raw sensor rates
+            {
+                adcs_bsk_ext_tlm_raw_rates(data);
+            }
+            break;
+            case API_RESP_STAR_EST_RATE:    // Get star tracker estimation rate
+            {
+                adcs_bsk_ext_tlm_star_est_rate(data);
+            }
+            break;
+            case API_RESP_SENS_CUR:          // Get sensor current
+            {
+                adcs_bsk_ext_tlm_sensor_current(data);
+            }
+            break;
+            case API_RESP_CON_CUR:  // Get adcs consumed current measurement
+            {
+                adcs_bsk_ext_tlm_con_current_measure(data);
+            }
+            break;
+            case API_RESP_RW_CUR:            // Get reaction wheel current
+            {
+                adcs_bsk_ext_tlm_rw_current(data);
+            }
+            break;
+            case API_RESP_TEMP:              // Get adcs temperature
+            {
+                adcs_bsk_ext_tlm_temperature(data);
+            }
+            break;
+            case API_RESP_SENS_RATE_TEMP:    // Get rate sensor temperature
+            {
+                adcs_bsk_ext_tlm_rate_sensor_temperature(data);
+            }
+            break;
+            case API_RESP_POW_TEMP:    // Get power and temperature measurement
+            {
+                adcs_bsk_ext_tlm_power_temperature(data);
+            }
+            break;
+            case API_RESP_GYRO_CFG:          // Get gyro configuration
+            {
+                adcs_bsk_ext_tlm_gyro_cfg(data);
+            }
+            break;
+            case API_RESP_STAR_TRAC_CFG:     // Get star tracker configuration
+            {
+                adcs_bsk_ext_tlm_star_trkr_cgf(data);
+            }
+            break;
+            case API_RESP_MAGMTR_CFG:        // Get magnetometer configuration
+            {
+                adcs_bsk_ext_tlm_mgmtr_cfg(data);
+            }
+            break;
+            case API_RESP_CSS_CFG:           // Get CSS configuration
+            {
+                adcs_bsk_ext_tlm_css_cfg(data);
+            }
+            break;
+            case API_RESP_FSS_CFG:           // Get FSS configuration
+            {
+                adcs_bsk_ext_tlm_fss_cfg(data);
+            }
+            break;
+            case API_RESP_NADIR_CFG:         // Get Nadir configuration
+            {
+                adcs_bsk_ext_tlm_nadir_cfg(data);
+            }
+            break;
+            case API_RESP_RED_MAGMTR_CFG:    // Get Redudant magnetometer
+            {
+                adcs_bsk_ext_tlm_red_mgmtr_cfg(data);
+            }
+            break;
+            case API_RESP_MGNTRQR_CFG:       // Get magnetorquer configuration
+            {
+                adcs_bsk_ext_tlm_mgntrqr_cfg(data);
+            }
+            break;
+            case API_RESP_RW_CFG:           // Get reaction wheel configuration
+            {
+                adcs_bsk_ext_tlm_rw_cfg(data);
+            }
+            break;
+            case API_RESP_DETUMBLE_CTRL:     // Get detumble parameters
+            {
+                adcs_bsk_ext_tlm_detumble_param(data);
+            }
+            break;
+            case API_RESP_Y_RW_CTRL:         // Get Y reaction wheel control
+            {
+                adcs_bsk_ext_tlm_y_rw_ctrl(data);
+            }
+            break;
+            case API_RESP_RW_CTRL:           // Get reaction wheel control
+            {
+                adcs_bsk_ext_tlm_rw_ctrl(data);
+            }
+            break;
+            case API_RESP_TRCK_CTRL_GAIN:    // Get tracking control gain
+            {
+                adcs_bsk_ext_tlm_trck_ctrl_gain(data);
+            }
+            break;
+            case API_RESP_ATTITUDE_ANGL:     // Get attitude angle
+            {
+                adcs_bsk_ext_tlm_attitude(data);
+            }
+            break;
+            case API_RESP_TRCK_TARGET:       // Get target tracking parameters
+            {
+                adcs_bsk_ext_tlm_target_track(data);
+            }
+            break;
+            case API_RESP_INRTL_REF:         // Get inertial reference
+            {
+                adcs_bsk_ext_tlm_inertial_ref(data);
+            }
+            break;
+            case API_RESP_EST_PARAM:         // Get estimation paremeters
+            {
+                adcs_bsk_ext_tlm_est_param(data);
+            }
+            break;
+            case API_RESP_POS_ECI:           // Get sattelite position ECI
+            {
+                adcs_bsk_ext_tlm_eci_postition(data);
+            }
+            break;
+            case API_RESP_VEL:               // Get sattelite velocity
+            {
+                adcs_bsk_ext_tlm_sat_velocity(data);
+            }
+            break;
+            case API_RESP_POS_LLH:           // Get sattelte position LLH
+            {
+                adcs_bsk_ext_tlm_llh_psition(data);
+            }
+            break;
+            case API_RESP_EST_RATE:          // Get estimation rates
+            {
+                adcs_bsk_ext_tlm_est_rate(data);
+            }
+            break;
+            case API_RESP_EST_QUTRN:         // Get estimated quaternion
+            {
+                adcs_bsk_ext_tlm_est_qutrn(data);
+            }
+            break;
+            case API_RESP_ECEF_POS:          // Get ECEF sattelite position
+            {
+                adcs_bsk_ext_tlm_ecef_position(data);
+            }
+            break;
+            case API_RESP_MODL_MAG:     // Get moduled magnetic field vector
+            {
+                adcs_bsk_ext_tlm_mod_mag_vector(data);
+            }
+            break;
+            case API_RESP_MODL_SUN:          // Get moduled sun vector
+            {
+                adcs_bsk_ext_tlm_mod_sun_vector(data);
+            }
+            break;
+            case API_RESP_EST_GYRO:          // Get estimated gyro measurement
+            {
+                adcs_bsk_ext_tlm_est_gyro_measure(data);
+            }
+            break;
+            case API_RESP_EST_INNOVN:        // Get estimation innovation
+            {
+                adcs_bsk_ext_tlm_est_innovation(data);
+            }
+            break;
+            case API_RESP_QUTR_ERROR:        // Get quaternion error vector
+            {
+                adcs_bsk_ext_tlm_qutrn_error(data);
+            }
+            break;
+            case API_RESP_QUTR_COVR:         // Get quaternion covariance
+            {
+                adcs_bsk_ext_tlm_qutrn_covr(data);
+            }
+            break;
+            case API_RESP_ANGL_COVR:         // Get angular rate covariance
+            {
+                adcs_bsk_ext_tlm_ang_rate_covr(data);
+            }
+            break;
+            case API_RESP_CTRL_MODE:
+            {
+                adcs_bsk_ext_tlm_ctrl_mode(data);
+            }
+            break;
+            case API_RESP_RW_SPEED:
+            {
+                adcs_bsk_ext_tlm_rw_speed_cmd(data);
+            }
+            break;
+            case API_RESP_RW_SPEED_MEASURE:
+            {
+                adcs_bsk_ext_tlm_rw_speed_measure(data);
+            }
+            break;
+            default:
+            {
+                printf("ADCS: Decoding Function not available for this TM Id:- %u\n",id);
+            }
+            break;
+        }
+    }
+}

+ 143 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/bootloader.c

@@ -0,0 +1,143 @@
+/************************************************************************************
+ * This file was auto-generated by CIDEA                           .                *
+ * Please do not modify the contents of this file manually.                         *
+ ***********************************************************************************/
+
+
+#include "bootloader.h"
+
+uint16_t BOOTLOADER_GetTlmLen(BOOTLOADER_Telemetry_t tlm)
+{
+    switch(tlm)
+    {
+        case CopyToIntFlashProgress:
+            return 1;
+        case ProgramInfo:
+            return 8;
+        case State:
+            return 6;
+        default:
+            return -1;
+    }
+}
+CUBEADCS_Result_t BOOTLOADER_ExtractCopyToIntFlashProgressTlm(uint8_t* rxBuffer, BOOTLOADER_CopyToIntFlashProgress_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->busy = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->error = (rxBuffer[0] & 0x02) >> 1;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t BOOTLOADER_ExtractProgramInfoTlm(uint8_t* rxBuffer, BOOTLOADER_ProgramInfo_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->programIndex = (BOOTLOADER_ProgramsList_t) enumVal;
+
+    returnVal->busy = (rxBuffer[1] & 0x01) >> 0;
+
+
+    returnVal->fileSize = *( (U32*) (rxBuffer + 2) );
+
+    returnVal->crc16 = *( (U16*) (rxBuffer + 6) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t BOOTLOADER_ExtractStateTlm(uint8_t* rxBuffer, BOOTLOADER_State_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->runtime = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->sram1Enabled = (rxBuffer[2] & 0x01) >> 0;
+
+    returnVal->sram2Enabled = (rxBuffer[2] & 0x02) >> 1;
+
+    returnVal->sramLatchup = (rxBuffer[2] & 0x04) >> 2;
+
+    returnVal->sramLatchupRecovered = (rxBuffer[2] & 0x08) >> 3;
+
+    returnVal->sdInitError = (rxBuffer[2] & 0x10) >> 4;
+
+    returnVal->sdReadError = (rxBuffer[2] & 0x20) >> 5;
+
+    returnVal->sdWriteError = (rxBuffer[2] & 0x40) >> 6;
+
+    returnVal->extFlashError = (rxBuffer[2] & 0x80) >> 7;
+
+    returnVal->intFlashError = (rxBuffer[3] & 0x01) >> 0;
+
+    returnVal->eepromError = (rxBuffer[3] & 0x02) >> 1;
+
+    returnVal->bootRegCorrupt = (rxBuffer[3] & 0x04) >> 2;
+
+    returnVal->radioCommsError = (rxBuffer[3] & 0x08) >> 3;
+
+
+    return CubeLibOk;
+}
+
+
+uint16_t BOOTLOADER_FormatBootIndexCmd(uint8_t* tcBuffer, BOOTLOADER_BootSetProgramsList_t programIndex)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 100;
+
+    tcBuffer[1] = 
+        (programIndex << 0);
+
+    return 2;
+}
+
+uint16_t BOOTLOADER_FormatClearErrorsCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 7;
+
+
+    return 1;
+}
+
+uint16_t BOOTLOADER_FormatCopyToInternalFlashCmd(uint8_t* tcBuffer, BOOTLOADER_ProgramsList_t srcIndex, U8 bootloaderOverwrite)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 103;
+
+    tcBuffer[1] = 
+        (srcIndex << 0);
+    *( (U8*)(tcBuffer + 2) ) = bootloaderOverwrite;
+
+    return 3;
+}
+
+uint16_t BOOTLOADER_FormatReadProgramInfoCmd(uint8_t* tcBuffer, BOOTLOADER_ProgramsList_t programIndex)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 102;
+
+    tcBuffer[1] = 
+        (programIndex << 0);
+
+    return 2;
+}
+
+uint16_t BOOTLOADER_FormatRunSelectedProgramCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 101;
+
+
+    return 1;
+}
+
+

+ 721 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/common.c

@@ -0,0 +1,721 @@
+/************************************************************************************
+ * This file was auto-generated by CIDEA                           .                *
+ * Please do not modify the contents of this file manually.                         *
+ ***********************************************************************************/
+
+
+#include "adcs_common.h"
+
+uint16_t COMMON_GetTlmLen(COMMON_Telemetry_t tlm)
+{
+    switch(tlm)
+    {
+        case BlockChecksum:
+            return 2;
+        case BootIndexStatus:
+            return 2;
+        case Cache:
+            return 1;
+        case CommsStatus:
+            return 6;
+        case DownloadBlockReady:
+            return 5;
+        case EdacErrors:
+            return 6;
+        case ExtendedIdentification:
+            return 6;
+        case FileDownload:
+            return 22;
+        case FileInfo:
+            return 12;
+        case HoleMap1:
+            return 16;
+        case HoleMap2:
+            return 16;
+        case HoleMap3:
+            return 16;
+        case HoleMap4:
+            return 16;
+        case HoleMap5:
+            return 16;
+        case HoleMap6:
+            return 16;
+        case HoleMap7:
+            return 16;
+        case HoleMap8:
+            return 16;
+        case Identification:
+            return 8;
+        case InitializeUploadComplete:
+            return 1;
+        case LastLogEvent:
+            return 6;
+        case LatchupErrors:
+            return 6;
+        case SdProgress:
+            return 1;
+        case SramScrubSettings:
+            return 2;
+        case TelecommandAcknowledge:
+            return 4;
+        case UnixTime:
+            return 6;
+        case UnixTimeSave:
+            return 2;
+        case UploadBlockComplete:
+            return 1;
+        default:
+            return -1;
+    }
+}
+CUBEADCS_Result_t COMMON_ExtractBlockChecksumTlm(uint8_t* rxBuffer, U16* checksum)
+{
+    if (checksum == 0)
+        return PointerIsNull;
+
+    *checksum = *( (U16*) (rxBuffer + 0) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractBootIndexStatusTlm(uint8_t* rxBuffer, COMMON_BootIndexStatus_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->programIndex = (COMMON_BootProgramsList_t) enumVal;
+
+    enumVal = rxBuffer[1];
+    returnVal->bootStatus = (COMMON_BootStatus_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractCacheTlm(uint8_t* rxBuffer, Boolean* enabled)
+{
+    if (enabled == 0)
+        return PointerIsNull;
+
+    *enabled = (rxBuffer[0] & 0x01) >> 0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractCommsStatusTlm(uint8_t* rxBuffer, COMMON_CommsStatus_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->tcCounter = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->tlmCounter = *( (U16*) (rxBuffer + 2) );
+
+    returnVal->uartBufferOverrun = (rxBuffer[4] & 0x01) >> 0;
+
+    returnVal->uartProtocolError = (rxBuffer[4] & 0x02) >> 1;
+
+    returnVal->uartMsgIncomplete = (rxBuffer[4] & 0x04) >> 2;
+
+    returnVal->i2CTelemetryError = (rxBuffer[4] & 0x08) >> 3;
+
+    returnVal->i2CBufferError = (rxBuffer[4] & 0x10) >> 4;
+
+    returnVal->cANBufferError = (rxBuffer[4] & 0x20) >> 5;
+
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractDownloadBlockReadyTlm(uint8_t* rxBuffer, COMMON_DownloadBlockReady_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->ready = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->parameterError = (rxBuffer[0] & 0x02) >> 1;
+
+
+    returnVal->checksum = *( (U16*) (rxBuffer + 1) );
+
+    returnVal->length = *( (U16*) (rxBuffer + 3) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractEdacErrorsTlm(uint8_t* rxBuffer, COMMON_EdacErrors_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->singleSRAMSEUs = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->doubleSRAMSEUs = *( (U16*) (rxBuffer + 2) );
+
+    returnVal->multiSRAMSEUs = *( (U16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractExtendedIdentificationTlm(uint8_t* rxBuffer, COMMON_ExtendedIdentification_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = (rxBuffer[0] >> 0) & 15;
+    returnVal->mcuResetCause = (COMMON_ResetCause_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 4) & 15;
+    returnVal->bootCause = (COMMON_BootCause_t) enumVal;
+
+    returnVal->bootCounter = *( (U16*) (rxBuffer + 1) );
+
+    enumVal = rxBuffer[3];
+    returnVal->runningProgramIndex = (COMMON_BootProgramsList_t) enumVal;
+
+    returnVal->firmwareMajorVersion = *( (U8*) (rxBuffer + 4) );
+
+    returnVal->firmwareMinorVersion = *( (U8*) (rxBuffer + 5) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractFileDownloadTlm(uint8_t* rxBuffer, COMMON_FileDownload_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->packetNo = *( (U16*) (rxBuffer + 0) );
+
+    memcpy(returnVal->fileBytes, rxBuffer + 2, 20);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractFileInfoTlm(uint8_t* rxBuffer, COMMON_FileInfo_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = (rxBuffer[0] >> 0) & 15;
+    returnVal->fileType = (COMMON_FileType_t) enumVal;
+
+    returnVal->busyUpdating = (rxBuffer[0] & 0x10) >> 4;
+
+
+    returnVal->fileCtr = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->size = *( (U32*) (rxBuffer + 2) );
+
+    returnVal->unixTime = *( (U32*) (rxBuffer + 6) );
+
+    returnVal->checksum = *( (U16*) (rxBuffer + 10) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap1Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap2Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap3Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap4Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap5Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap6Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap7Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractHoleMap8Tlm(uint8_t* rxBuffer, uint8_t* holeMap)
+{
+    if (holeMap == 0)
+        return PointerIsNull;
+
+    memcpy(holeMap, rxBuffer + 0, 16);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractIdentificationTlm(uint8_t* rxBuffer, COMMON_Identification_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->nodeType = *( (U8*) (rxBuffer + 0) );
+
+    returnVal->interfaceVersion = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->firmwareMajorVersion = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->firmwareMinorVersion = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->runtimeSeconds = *( (U16*) (rxBuffer + 4) );
+
+    returnVal->runtimeMilliseconds = *( (U16*) (rxBuffer + 6) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractInitializeUploadCompleteTlm(uint8_t* rxBuffer, Boolean* busy)
+{
+    if (busy == 0)
+        return PointerIsNull;
+
+    *busy = (rxBuffer[0] & 0x01) >> 0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractLastLogEventTlm(uint8_t* rxBuffer, COMMON_LastLogEvent_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->unixTime = *( (U32*) (rxBuffer + 0) );
+
+    returnVal->eventId = *( (U8*) (rxBuffer + 4) );
+
+    returnVal->eventParam = *( (U8*) (rxBuffer + 5) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractLatchupErrorsTlm(uint8_t* rxBuffer, COMMON_LatchupErrors_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->sRAM1SELs = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->sRAM2SELs = *( (U16*) (rxBuffer + 2) );
+
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractSdProgressTlm(uint8_t* rxBuffer, COMMON_SdProgress_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->formatBusy = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->eraseAllBusy = (rxBuffer[0] & 0x02) >> 1;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractSramScrubSettingsTlm(uint8_t* rxBuffer, U16* scrubSize)
+{
+    if (scrubSize == 0)
+        return PointerIsNull;
+
+    *scrubSize = *( (U16*) (rxBuffer + 0) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractTelecommandAcknowledgeTlm(uint8_t* rxBuffer, COMMON_TelecommandAcknowledge_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->lastTCID = *( (U8*) (rxBuffer + 0) );
+
+    returnVal->processedFlag = (rxBuffer[1] & 0x01) >> 0;
+
+
+    enumVal = rxBuffer[2];
+    returnVal->tCerrorStatus  = (COMMON_TcErrorReason_t) enumVal;
+
+    returnVal->tCParameterErrorIndex = *( (U8*) (rxBuffer + 3) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractUnixTimeTlm(uint8_t* rxBuffer, COMMON_UnixTime_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->time = *( (U32*) (rxBuffer + 0) );
+
+    returnVal->milliSec = *( (U16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractUnixTimeSaveTlm(uint8_t* rxBuffer, COMMON_UnixTimeSave_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->saveNow = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->saveOnUpdate = (rxBuffer[0] & 0x02) >> 1;
+
+    returnVal->savePeriodic = (rxBuffer[0] & 0x04) >> 2;
+
+
+    returnVal->period = *( (U8*) (rxBuffer + 1) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t COMMON_ExtractUploadBlockCompleteTlm(uint8_t* rxBuffer, COMMON_UploadBlockComplete_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->busy = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->error = (rxBuffer[0] & 0x02) >> 1;
+
+    return CubeLibOk;
+}
+
+
+uint16_t COMMON_FormatAdvanceFileListPtrCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 113;
+
+
+    return 1;
+}
+
+uint16_t COMMON_FormatAdvanceLogPtrCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 5;
+
+
+    return 1;
+}
+
+uint16_t COMMON_FormatCacheCmd(uint8_t* tcBuffer, Boolean enabled)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 3;
+
+    tcBuffer[1] = 
+        (enabled << 0);
+
+    return 2;
+}
+
+uint16_t COMMON_FormatDownloadBurstCmd(uint8_t* tcBuffer, U8 messageLength, Boolean ignoreHoleMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 119;
+
+    tcBuffer[2] = 
+        (ignoreHoleMap << 0);
+    *( (U8*)(tcBuffer + 1) ) = messageLength;
+
+    return 3;
+}
+
+uint16_t COMMON_FormatEraseFileCmd(uint8_t* tcBuffer, COMMON_FileType_t fileType, U8 fileCtr, Boolean eraseAll)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 108;
+
+    tcBuffer[1] = 
+        (fileType << 0);
+    tcBuffer[3] = 
+        (eraseAll << 0);
+    *( (U8*)(tcBuffer + 2) ) = fileCtr;
+
+    return 4;
+}
+
+uint16_t COMMON_FormatFileUploadCmd(uint8_t* tcBuffer, U16 packetNo, U8* fileBytes)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 115;
+
+    *( (U16*)(tcBuffer + 1) ) = packetNo;
+    memcpy(tcBuffer + 3,fileBytes,20);
+
+    return 23;
+}
+
+uint16_t COMMON_FormatFinalizeUploadBlockCmd(uint8_t* tcBuffer, COMMON_FileUploadDestination_t destination, U32 offset, U16 blockLen)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 116;
+
+    tcBuffer[1] = 
+        (destination << 0);
+    *( (U32*)(tcBuffer + 2) ) = offset;
+    *( (U16*)(tcBuffer + 6) ) = blockLen;
+
+    return 8;
+}
+
+uint16_t COMMON_FormatFormatSdCmd(uint8_t* tcBuffer, U8 formatMagic)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 33;
+
+    *( (U8*)(tcBuffer + 1) ) = formatMagic;
+
+    return 2;
+}
+
+uint16_t COMMON_FormatHoleMap1Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 120;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap2Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 121;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap3Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 122;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap4Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 123;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap5Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 124;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap6Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 125;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap7Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 126;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatHoleMap8Cmd(uint8_t* tcBuffer, U8* holeMap)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 127;
+
+    memcpy(tcBuffer + 1,holeMap,16);
+
+    return 17;
+}
+
+uint16_t COMMON_FormatInitiateFileUploadCmd(uint8_t* tcBuffer, COMMON_FileUploadDestination_t destination, U8 blockSize)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 114;
+
+    tcBuffer[1] = 
+        (destination << 0);
+    *( (U8*)(tcBuffer + 2) ) = blockSize;
+
+    return 3;
+}
+
+uint16_t COMMON_FormatLoadDownloadBlockCmd(uint8_t* tcBuffer, COMMON_FileType_t fileType, U8 counter, U32 offset, U16 length)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 112;
+
+    tcBuffer[1] = 
+        (fileType << 0);
+    *( (U8*)(tcBuffer + 2) ) = counter;
+    *( (U32*)(tcBuffer + 3) ) = offset;
+    *( (U16*)(tcBuffer + 7) ) = length;
+
+    return 9;
+}
+
+uint16_t COMMON_FormatResetCmd(uint8_t* tcBuffer, U8 magic)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 1;
+
+    *( (U8*)(tcBuffer + 1) ) = magic;
+
+    return 2;
+}
+
+uint16_t COMMON_FormatResetBootRegistersCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 6;
+
+
+    return 1;
+}
+
+uint16_t COMMON_FormatResetFileListPtrCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 118;
+
+
+    return 1;
+}
+
+uint16_t COMMON_FormatResetLogPtrCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 4;
+
+
+    return 1;
+}
+
+uint16_t COMMON_FormatResetUploadBlockCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 117;
+
+
+    return 1;
+}
+
+uint16_t COMMON_FormatSramScrubSettingsCmd(uint8_t* tcBuffer, U16 scrubSize)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 8;
+
+    *( (U16*)(tcBuffer + 1) ) = scrubSize;
+
+    return 3;
+}
+
+uint16_t COMMON_FormatUnixTimeCmd(uint8_t* tcBuffer, U32 time, U16 milliSec)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 2;
+
+    *( (U32*)(tcBuffer + 1) ) = time;
+    *( (U16*)(tcBuffer + 5) ) = milliSec;
+
+    return 7;
+}
+
+uint16_t COMMON_FormatUnixTimeSaveCmd(uint8_t* tcBuffer, Boolean saveNow, Boolean saveOnUpdate, Boolean savePeriodic, U8 period)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 9;
+
+    tcBuffer[1] = 
+        (saveNow << 0) + 
+        (saveOnUpdate << 1) + 
+        (savePeriodic << 2);
+    *( (U8*)(tcBuffer + 2) ) = period;
+
+    return 3;
+}
+
+

+ 5318 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/AdcsInterfaceLib/src/cubeacp.c

@@ -0,0 +1,5318 @@
+/************************************************************************************
+ * This file was auto-generated by CIDEA                           .                *
+ * Please do not modify the contents of this file manually.                         *
+ ***********************************************************************************/
+
+
+#include "cubeacp.h"
+
+uint16_t CUBEACP_GetTlmLen(CUBEACP_Telemetry_t tlm)
+{
+    switch(tlm)
+    {
+        case AcpLoopState:
+            return 3;
+        case ActuatorCmd:
+            return 12;
+        case AdcsConfig:
+            return 504;
+        case AdcsExecTimes:
+            return 8;
+        case AdcsMeasure:
+            return 72;
+        case AdcsMiscCurrents:
+            return 6;
+        case AdcsPower:
+            return 3;
+        case AdcsPowerMeasure:
+            return 38;
+        case AdcsState:
+            return 54;
+        case AdcsSystemConfig:
+            return 173;
+        case AdcsTemperatures1:
+            return 6;
+        case AdcsTemperatures2:
+            return 6;
+        case Asgp4KepTle:
+            return 33;
+        case ASgp4Params:
+            return 30;
+        case CmdAttitude:
+            return 6;
+        case CmdTrackingTarget:
+            return 12;
+        case CoarseSunVec:
+            return 6;
+        case ConversionProgress:
+            return 3;
+        case CssConfig:
+            return 21;
+        case CubeACPState:
+            return 1;
+        case CubeControlCurrents:
+            return 6;
+        case CubeSense1Currents:
+            return 4;
+        case CubeSense2Currents:
+            return 4;
+        case CubeSenseConfig:
+            return 112;
+        case CurrentAdcsState:
+            return 6;
+        case CurrentAdcsState2:
+            return 6;
+        case DetumbleParams:
+            return 14;
+        case EstimAttitude:
+            return 6;
+        case EstimData:
+            return 42;
+        case EstimGyroBias:
+            return 6;
+        case EstimParams:
+            return 31;
+        case EstimQuaternion:
+            return 6;
+        case EstimRates:
+            return 6;
+        case FineEstimRates:
+            return 6;
+        case FineSunVec:
+            return 6;
+        case GyroConfig:
+            return 10;
+        case ImageSaveStatus:
+            return 2;
+        case InertialPointReference:
+            return 6;
+        case InnovationVec:
+            return 6;
+        case LogSdConfig1:
+            return 13;
+        case LogSdConfig2:
+            return 13;
+        case LogUartConfig:
+            return 12;
+        case MagConfig:
+            return 30;
+        case MagField:
+            return 6;
+        case MagRaw2:
+            return 6;
+        case MagtorqConfig:
+            return 3;
+        case MagTorquerCmd:
+            return 6;
+        case ModelMagVec:
+            return 6;
+        case ModelSunVec:
+            return 6;
+        case MoI:
+            return 24;
+        case NadirVec:
+            return 6;
+        case OrbitParameters:
+            return 64;
+        case PositionECEF:
+            return 6;
+        case PositionECI:
+            return 6;
+        case PositionLLH:
+            return 6;
+        case QuaternionCovar:
+            return 6;
+        case QuaternionErrVec:
+            return 6;
+        case RateCovar:
+            return 6;
+        case RateSensor:
+            return 6;
+        case RawCam1Sens:
+            return 6;
+        case RawCam2Sens:
+            return 6;
+        case RawCss1:
+            return 6;
+        case RawCss2:
+            return 6;
+        case RawGPS:
+            return 36;
+        case RawGpsStatus:
+            return 6;
+        case RawGpsTime:
+            return 6;
+        case RawGpsX:
+            return 6;
+        case RawGpsY:
+            return 6;
+        case RawGpsZ:
+            return 6;
+        case RawMagnetometer:
+            return 6;
+        case RawRate:
+            return 6;
+        case RawSensor:
+            return 34;
+        case RawStarTracker:
+            return 54;
+        case RedMagConfig:
+            return 30;
+        case RWheelParams:
+            return 13;
+        case SpeedCmd:
+            return 6;
+        case Star1Body:
+            return 6;
+        case Star1Orbit:
+            return 6;
+        case Star1Raw:
+            return 6;
+        case Star2Body:
+            return 6;
+        case Star2Orbit:
+            return 6;
+        case Star2Raw:
+            return 6;
+        case Star3Body:
+            return 6;
+        case Star3Orbit:
+            return 6;
+        case Star3Raw:
+            return 6;
+        case StarConfig:
+            return 53;
+        case StarEstimQ:
+            return 6;
+        case StarEstimRate:
+            return 6;
+        case StarMagnitude:
+            return 6;
+        case StarPerformance1:
+            return 6;
+        case StarPerformance2:
+            return 6;
+        case StarTiming:
+            return 6;
+        case TrackingParams:
+            return 13;
+        case UserConEstParams:
+            return 96;
+        case VelocityECI:
+            return 6;
+        case WheelConfig:
+            return 4;
+        case WheelCurrents:
+            return 6;
+        case WheelSpeed:
+            return 6;
+        case YWheelParams:
+            return 20;
+        default:
+            return -1;
+    }
+}
+CUBEADCS_Result_t CUBEACP_ExtractAcpLoopStateTlm(uint8_t* rxBuffer, CUBEACP_AcpLoopState_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->timeSinceLoopStart = *( (U16*) (rxBuffer + 0) );
+
+    enumVal = rxBuffer[2];
+    returnVal->currentExecutionPoint = (CUBEACP_ExecutionWaypoints_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractActuatorCmdTlm(uint8_t* rxBuffer, CUBEACP_ActuatorCmd_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->torquerCmdX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->torquerCmdY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->torquerCmdZ = *( (S16*) (rxBuffer + 4) );
+
+    returnVal->speedCmdX = *( (S16*) (rxBuffer + 6) );
+
+    returnVal->speedCmdY = *( (S16*) (rxBuffer + 8) );
+
+    returnVal->speedCmdZ = *( (S16*) (rxBuffer + 10) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawXRateOffset;
+    S16 rawYRateOffset;
+    S16 rawZRateOffset;
+    U8 rawCss1Scale;
+    U8 rawCss2Scale;
+    U8 rawCss3Scale;
+    U8 rawCss4Scale;
+    U8 rawCss5Scale;
+    U8 rawCss6Scale;
+    U8 rawCss7Scale;
+    U8 rawCss8Scale;
+    U8 rawCss9Scale;
+    U8 rawCss10Scale;
+    S16 rawCam1Angle1;
+    S16 rawCam1Angle2;
+    S16 rawCam1Angle3;
+    U16 rawCam1BoreX;
+    U16 rawCam1BoreY;
+    S16 rawCam2Angle1;
+    S16 rawCam2Angle2;
+    S16 rawCam2Angle3;
+    U16 rawCam2BoreX;
+    U16 rawCam2BoreY;
+    S16 rawMagmAngle1;
+    S16 rawMagmAngle2;
+    S16 rawMagmAngle3;
+    S16 rawMagmOffset1;
+    S16 rawMagmOffset2;
+    S16 rawMagmOffset3;
+    S16 rawMagmSens11;
+    S16 rawMagmSens22;
+    S16 rawMagmSens33;
+    S16 rawMagmSens12;
+    S16 rawMagmSens13;
+    S16 rawMagmSens21;
+    S16 rawMagmSens23;
+    S16 rawMagmSens31;
+    S16 rawMagmSens32;
+    S16 rawMredAngle1;
+    S16 rawMredAngle2;
+    S16 rawMredAngle3;
+    S16 rawMredOffset1;
+    S16 rawMredOffset2;
+    S16 rawMredOffset3;
+    S16 rawMredSens11;
+    S16 rawMredSens22;
+    S16 rawMredSens33;
+    S16 rawMredSens12;
+    S16 rawMredSens13;
+    S16 rawMredSens21;
+    S16 rawMredSens23;
+    S16 rawMredSens31;
+    S16 rawMredSens32;
+    S16 rawStarAngle1;
+    S16 rawStarAngle2;
+    S16 rawStarAngle3;
+    U8 rawStarErrorMargin;
+    U8 rawStarTrackingMargin;
+    U8 rawStarValidationMargin;
+    U8 rawStarSearchWidth;
+    S16 rawwy_ref;
+    U16 rawAInclCoeff;
+    U16 rawARaanCoeff;
+    U16 rawAEccCoeff;
+    U16 rawAArgPerCoeff;
+    U16 rawATimeCoeff;
+    U16 rawAPosCoeff;
+    U8 rawAsgp4MaxPosError;
+    S32 rawAsgp4Xp;
+    S32 rawAsgp4Yp;
+    U8 rawAsgp4PosSdTh;
+    U8 rawAsgp4VelSdTh;
+    U8 rawAsgp4TimeGain;
+    U8 rawAsgp4MaxLag;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->magtorq1 = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[1];
+    returnVal->magtorq2 = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[2];
+    returnVal->magtorq3 = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[3];
+    returnVal->rW1Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[4];
+    returnVal->rW2Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[5];
+    returnVal->rW3Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[6];
+    returnVal->rW4Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[7];
+    returnVal->gyro1Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[8];
+    returnVal->gyro2Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[9];
+    returnVal->gyro3Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    rawXRateOffset = *( (S16*) (rxBuffer + 10) );
+    returnVal->xRateOffset = rawXRateOffset*0.001;
+
+    rawYRateOffset = *( (S16*) (rxBuffer + 12) );
+    returnVal->yRateOffset = rawYRateOffset*0.001;
+
+    rawZRateOffset = *( (S16*) (rxBuffer + 14) );
+    returnVal->zRateOffset = rawZRateOffset*0.001;
+
+    returnVal->rateSensorMult = *( (U8*) (rxBuffer + 16) );
+
+    enumVal = rxBuffer[17];
+    returnVal->css1Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[18];
+    returnVal->css2Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[19];
+    returnVal->css3Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[20];
+    returnVal->css4Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[21];
+    returnVal->css5Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[22];
+    returnVal->css6Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[23];
+    returnVal->css7Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[24];
+    returnVal->css8Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[25];
+    returnVal->css9Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[26];
+    returnVal->css10Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    rawCss1Scale = *( (U8*) (rxBuffer + 27) );
+    returnVal->css1Scale = rawCss1Scale*0.01;
+
+    rawCss2Scale = *( (U8*) (rxBuffer + 28) );
+    returnVal->css2Scale = rawCss2Scale*0.01;
+
+    rawCss3Scale = *( (U8*) (rxBuffer + 29) );
+    returnVal->css3Scale = rawCss3Scale*0.01;
+
+    rawCss4Scale = *( (U8*) (rxBuffer + 30) );
+    returnVal->css4Scale = rawCss4Scale*0.01;
+
+    rawCss5Scale = *( (U8*) (rxBuffer + 31) );
+    returnVal->css5Scale = rawCss5Scale*0.01;
+
+    rawCss6Scale = *( (U8*) (rxBuffer + 32) );
+    returnVal->css6Scale = rawCss6Scale*0.01;
+
+    rawCss7Scale = *( (U8*) (rxBuffer + 33) );
+    returnVal->css7Scale = rawCss7Scale*0.01;
+
+    rawCss8Scale = *( (U8*) (rxBuffer + 34) );
+    returnVal->css8Scale = rawCss8Scale*0.01;
+
+    rawCss9Scale = *( (U8*) (rxBuffer + 35) );
+    returnVal->css9Scale = rawCss9Scale*0.01;
+
+    rawCss10Scale = *( (U8*) (rxBuffer + 36) );
+    returnVal->css10Scale = rawCss10Scale*0.01;
+
+    returnVal->cssMinimum = *( (U8*) (rxBuffer + 37) );
+
+    rawCam1Angle1 = *( (S16*) (rxBuffer + 38) );
+    returnVal->cam1Angle1 = rawCam1Angle1*0.01;
+
+    rawCam1Angle2 = *( (S16*) (rxBuffer + 40) );
+    returnVal->cam1Angle2 = rawCam1Angle2*0.01;
+
+    rawCam1Angle3 = *( (S16*) (rxBuffer + 42) );
+    returnVal->cam1Angle3 = rawCam1Angle3*0.01;
+
+    returnVal->cam1Threshold = *( (U8*) (rxBuffer + 44) );
+
+    returnVal->cam1AutoAdj = (rxBuffer[45] & 0x01) >> 0;
+
+
+    returnVal->cam1Exposure = *( (U16*) (rxBuffer + 46) );
+
+    rawCam1BoreX = *( (U16*) (rxBuffer + 48) );
+    returnVal->cam1BoreX = rawCam1BoreX*0.01;
+
+    rawCam1BoreY = *( (U16*) (rxBuffer + 50) );
+    returnVal->cam1BoreY = rawCam1BoreY*0.01;
+
+    rawCam2Angle1 = *( (S16*) (rxBuffer + 52) );
+    returnVal->cam2Angle1 = rawCam2Angle1*0.01;
+
+    rawCam2Angle2 = *( (S16*) (rxBuffer + 54) );
+    returnVal->cam2Angle2 = rawCam2Angle2*0.01;
+
+    rawCam2Angle3 = *( (S16*) (rxBuffer + 56) );
+    returnVal->cam2Angle3 = rawCam2Angle3*0.01;
+
+    returnVal->cam2Threshold = *( (U8*) (rxBuffer + 58) );
+
+    returnVal->cam2AutoAdj = (rxBuffer[59] & 0x01) >> 0;
+
+
+    returnVal->cam2Exposure = *( (U16*) (rxBuffer + 60) );
+
+    rawCam2BoreX = *( (U16*) (rxBuffer + 62) );
+    returnVal->cam2BoreX = rawCam2BoreX*0.01;
+
+    rawCam2BoreY = *( (U16*) (rxBuffer + 64) );
+    returnVal->cam2BoreY = rawCam2BoreY*0.01;
+
+    returnVal->nadirMaxDeviationPercentage = *( (U8*) (rxBuffer + 66) );
+
+    returnVal->nadirMaxBadEdges = *( (U8*) (rxBuffer + 67) );
+
+    returnVal->nadirMaxRadius = *( (U8*) (rxBuffer + 68) );
+
+    returnVal->nadirMinRadius = *( (U8*) (rxBuffer + 69) );
+
+    returnVal->cam1MaskArea1Xmin = *( (U16*) (rxBuffer + 70) );
+
+    returnVal->cam1MaskArea1Xmax = *( (U16*) (rxBuffer + 72) );
+
+    returnVal->cam1MaskArea1Ymin = *( (U16*) (rxBuffer + 74) );
+
+    returnVal->cam1MaskArea1Ymax = *( (U16*) (rxBuffer + 76) );
+
+    returnVal->cam1MaskArea2Xmin = *( (U16*) (rxBuffer + 78) );
+
+    returnVal->cam1MaskArea2Xmax = *( (U16*) (rxBuffer + 80) );
+
+    returnVal->cam1MaskArea2Ymin = *( (U16*) (rxBuffer + 82) );
+
+    returnVal->cam1MaskArea2Ymax = *( (U16*) (rxBuffer + 84) );
+
+    returnVal->cam1MaskArea3Xmin = *( (U16*) (rxBuffer + 86) );
+
+    returnVal->cam1MaskArea3Xmax = *( (U16*) (rxBuffer + 88) );
+
+    returnVal->cam1MaskArea3Ymin = *( (U16*) (rxBuffer + 90) );
+
+    returnVal->cam1MaskArea3Ymax = *( (U16*) (rxBuffer + 92) );
+
+    returnVal->cam1MaskArea4Xmin = *( (U16*) (rxBuffer + 94) );
+
+    returnVal->cam1MaskArea4Xmax = *( (U16*) (rxBuffer + 96) );
+
+    returnVal->cam1MaskArea4Ymin = *( (U16*) (rxBuffer + 98) );
+
+    returnVal->cam1MaskArea4Ymax = *( (U16*) (rxBuffer + 100) );
+
+    returnVal->cam1MaskArea5Xmin = *( (U16*) (rxBuffer + 102) );
+
+    returnVal->cam1MaskArea5Xmax = *( (U16*) (rxBuffer + 104) );
+
+    returnVal->cam1MaskArea5Ymin = *( (U16*) (rxBuffer + 106) );
+
+    returnVal->cam1MaskArea5Ymax = *( (U16*) (rxBuffer + 108) );
+
+    returnVal->cam2MaskArea1Xmin = *( (U16*) (rxBuffer + 110) );
+
+    returnVal->cam2MaskArea1Xmax = *( (U16*) (rxBuffer + 112) );
+
+    returnVal->cam2MaskArea1Ymin = *( (U16*) (rxBuffer + 114) );
+
+    returnVal->cam2MaskArea1Ymax = *( (U16*) (rxBuffer + 116) );
+
+    returnVal->cam2MaskArea2Xmin = *( (U16*) (rxBuffer + 118) );
+
+    returnVal->cam2MaskArea2Xmax = *( (U16*) (rxBuffer + 120) );
+
+    returnVal->cam2MaskArea2Ymin = *( (U16*) (rxBuffer + 122) );
+
+    returnVal->cam2MaskArea2Ymax = *( (U16*) (rxBuffer + 124) );
+
+    returnVal->cam2MaskArea3Xmin = *( (U16*) (rxBuffer + 126) );
+
+    returnVal->cam2MaskArea3Xmax = *( (U16*) (rxBuffer + 128) );
+
+    returnVal->cam2MaskArea3Ymin = *( (U16*) (rxBuffer + 130) );
+
+    returnVal->cam2MaskArea3Ymax = *( (U16*) (rxBuffer + 132) );
+
+    returnVal->cam2MaskArea4Xmin = *( (U16*) (rxBuffer + 134) );
+
+    returnVal->cam2MaskArea4Xmax = *( (U16*) (rxBuffer + 136) );
+
+    returnVal->cam2MaskArea4Ymin = *( (U16*) (rxBuffer + 138) );
+
+    returnVal->cam2MaskArea4Ymax = *( (U16*) (rxBuffer + 140) );
+
+    returnVal->cam2MaskArea5Xmin = *( (U16*) (rxBuffer + 142) );
+
+    returnVal->cam2MaskArea5Xmax = *( (U16*) (rxBuffer + 144) );
+
+    returnVal->cam2MaskArea5Ymin = *( (U16*) (rxBuffer + 146) );
+
+    returnVal->cam2MaskArea5Ymax = *( (U16*) (rxBuffer + 148) );
+
+    rawMagmAngle1 = *( (S16*) (rxBuffer + 150) );
+    returnVal->magmAngle1 = rawMagmAngle1*0.01;
+
+    rawMagmAngle2 = *( (S16*) (rxBuffer + 152) );
+    returnVal->magmAngle2 = rawMagmAngle2*0.01;
+
+    rawMagmAngle3 = *( (S16*) (rxBuffer + 154) );
+    returnVal->magmAngle3 = rawMagmAngle3*0.01;
+
+    rawMagmOffset1 = *( (S16*) (rxBuffer + 156) );
+    returnVal->magmOffset1 = rawMagmOffset1*0.001;
+
+    rawMagmOffset2 = *( (S16*) (rxBuffer + 158) );
+    returnVal->magmOffset2 = rawMagmOffset2*0.001;
+
+    rawMagmOffset3 = *( (S16*) (rxBuffer + 160) );
+    returnVal->magmOffset3 = rawMagmOffset3*0.001;
+
+    rawMagmSens11 = *( (S16*) (rxBuffer + 162) );
+    returnVal->magmSens11 = rawMagmSens11*0.001;
+
+    rawMagmSens22 = *( (S16*) (rxBuffer + 164) );
+    returnVal->magmSens22 = rawMagmSens22*0.001;
+
+    rawMagmSens33 = *( (S16*) (rxBuffer + 166) );
+    returnVal->magmSens33 = rawMagmSens33*0.001;
+
+    rawMagmSens12 = *( (S16*) (rxBuffer + 168) );
+    returnVal->magmSens12 = rawMagmSens12*0.001;
+
+    rawMagmSens13 = *( (S16*) (rxBuffer + 170) );
+    returnVal->magmSens13 = rawMagmSens13*0.001;
+
+    rawMagmSens21 = *( (S16*) (rxBuffer + 172) );
+    returnVal->magmSens21 = rawMagmSens21*0.001;
+
+    rawMagmSens23 = *( (S16*) (rxBuffer + 174) );
+    returnVal->magmSens23 = rawMagmSens23*0.001;
+
+    rawMagmSens31 = *( (S16*) (rxBuffer + 176) );
+    returnVal->magmSens31 = rawMagmSens31*0.001;
+
+    rawMagmSens32 = *( (S16*) (rxBuffer + 178) );
+    returnVal->magmSens32 = rawMagmSens32*0.001;
+
+    rawMredAngle1 = *( (S16*) (rxBuffer + 180) );
+    returnVal->mredAngle1 = rawMredAngle1*0.01;
+
+    rawMredAngle2 = *( (S16*) (rxBuffer + 182) );
+    returnVal->mredAngle2 = rawMredAngle2*0.01;
+
+    rawMredAngle3 = *( (S16*) (rxBuffer + 184) );
+    returnVal->mredAngle3 = rawMredAngle3*0.01;
+
+    rawMredOffset1 = *( (S16*) (rxBuffer + 186) );
+    returnVal->mredOffset1 = rawMredOffset1*0.001;
+
+    rawMredOffset2 = *( (S16*) (rxBuffer + 188) );
+    returnVal->mredOffset2 = rawMredOffset2*0.001;
+
+    rawMredOffset3 = *( (S16*) (rxBuffer + 190) );
+    returnVal->mredOffset3 = rawMredOffset3*0.001;
+
+    rawMredSens11 = *( (S16*) (rxBuffer + 192) );
+    returnVal->mredSens11 = rawMredSens11*0.001;
+
+    rawMredSens22 = *( (S16*) (rxBuffer + 194) );
+    returnVal->mredSens22 = rawMredSens22*0.001;
+
+    rawMredSens33 = *( (S16*) (rxBuffer + 196) );
+    returnVal->mredSens33 = rawMredSens33*0.001;
+
+    rawMredSens12 = *( (S16*) (rxBuffer + 198) );
+    returnVal->mredSens12 = rawMredSens12*0.001;
+
+    rawMredSens13 = *( (S16*) (rxBuffer + 200) );
+    returnVal->mredSens13 = rawMredSens13*0.001;
+
+    rawMredSens21 = *( (S16*) (rxBuffer + 202) );
+    returnVal->mredSens21 = rawMredSens21*0.001;
+
+    rawMredSens23 = *( (S16*) (rxBuffer + 204) );
+    returnVal->mredSens23 = rawMredSens23*0.001;
+
+    rawMredSens31 = *( (S16*) (rxBuffer + 206) );
+    returnVal->mredSens31 = rawMredSens31*0.001;
+
+    rawMredSens32 = *( (S16*) (rxBuffer + 208) );
+    returnVal->mredSens32 = rawMredSens32*0.001;
+
+    rawStarAngle1 = *( (S16*) (rxBuffer + 210) );
+    returnVal->starAngle1 = rawStarAngle1*0.01;
+
+    rawStarAngle2 = *( (S16*) (rxBuffer + 212) );
+    returnVal->starAngle2 = rawStarAngle2*0.01;
+
+    rawStarAngle3 = *( (S16*) (rxBuffer + 214) );
+    returnVal->starAngle3 = rawStarAngle3*0.01;
+
+    returnVal->starExposure = *( (U16*) (rxBuffer + 216) );
+
+    returnVal->starGain = *( (U16*) (rxBuffer + 218) );
+
+    returnVal->detectionThreshold = *( (U8*) (rxBuffer + 220) );
+
+    returnVal->starThreshold = *( (U8*) (rxBuffer + 221) );
+
+    returnVal->maxStarMatched = *( (U8*) (rxBuffer + 222) );
+
+    returnVal->starTimeoutTime = *( (U16*) (rxBuffer + 223) );
+
+    returnVal->maxStarPixel = *( (U8*) (rxBuffer + 225) );
+
+    returnVal->minStarPixel = *( (U8*) (rxBuffer + 226) );
+
+    rawStarErrorMargin = *( (U8*) (rxBuffer + 227) );
+    returnVal->starErrorMargin = rawStarErrorMargin*0.01;
+
+    returnVal->starDelayTime = *( (U16*) (rxBuffer + 228) );
+
+    returnVal->starCentX = *((F32*)(rxBuffer + 230));
+
+    returnVal->starCentY = *((F32*)(rxBuffer + 234));
+
+    returnVal->starFocal = *((F32*)(rxBuffer + 238));
+
+    returnVal->starLensK1 = *((F32*)(rxBuffer + 242));
+
+    returnVal->starLensK2 = *((F32*)(rxBuffer + 246));
+
+    returnVal->starLensP1 = *((F32*)(rxBuffer + 250));
+
+    returnVal->starLensP2 = *((F32*)(rxBuffer + 254));
+
+    returnVal->starWindowWidth = *( (U8*) (rxBuffer + 258) );
+
+    rawStarTrackingMargin = *( (U8*) (rxBuffer + 259) );
+    returnVal->starTrackingMargin = rawStarTrackingMargin/100.0;
+
+    rawStarValidationMargin = *( (U8*) (rxBuffer + 260) );
+    returnVal->starValidationMargin = rawStarValidationMargin/100.0;
+
+    returnVal->starModuleEnable = (rxBuffer[261] & 0x01) >> 0;
+
+    returnVal->starLocationPredictionEnable = (rxBuffer[261] & 0x02) >> 1;
+
+
+    rawStarSearchWidth = *( (U8*) (rxBuffer + 262) );
+    returnVal->starSearchWidth = rawStarSearchWidth/5.0;
+
+    returnVal->ks = *((F32*)(rxBuffer + 263));
+
+    returnVal->kd = *((F32*)(rxBuffer + 267));
+
+    rawwy_ref = *( (S16*) (rxBuffer + 271) );
+    returnVal->wy_ref = rawwy_ref*0.001;
+
+    returnVal->kdf = *((F32*)(rxBuffer + 273));
+
+    returnVal->kh = *((F32*)(rxBuffer + 277));
+
+    returnVal->kn = *((F32*)(rxBuffer + 281));
+
+    returnVal->kp1 = *((F32*)(rxBuffer + 285));
+
+    returnVal->kd1 = *((F32*)(rxBuffer + 289));
+
+    returnVal->h_ref = *((F32*)(rxBuffer + 293));
+
+    returnVal->kp2 = *((F32*)(rxBuffer + 297));
+
+    returnVal->kd2 = *((F32*)(rxBuffer + 301));
+
+    returnVal->h_bias = *((F32*)(rxBuffer + 305));
+
+    enumVal = (rxBuffer[309] >> 0) & 127;
+    returnVal->sunPointFacet = (CUBEACP_AxisSelect_t) enumVal;
+
+    returnVal->wheelErrorHandling = (rxBuffer[309] & 0x80) >> 7;
+
+    returnVal->kp3 = *((F32*)(rxBuffer + 310));
+
+    returnVal->kd3 = *((F32*)(rxBuffer + 314));
+
+    returnVal->ki3 = *((F32*)(rxBuffer + 318));
+
+    enumVal = rxBuffer[322];
+    returnVal->targetTrackFacet = (CUBEACP_AxisSelect_t) enumVal;
+
+    returnVal->ixx = *((F32*)(rxBuffer + 323));
+
+    returnVal->iyy = *((F32*)(rxBuffer + 327));
+
+    returnVal->izz = *((F32*)(rxBuffer + 331));
+
+    returnVal->ixy = *((F32*)(rxBuffer + 335));
+
+    returnVal->ixz = *((F32*)(rxBuffer + 339));
+
+    returnVal->iyz = *((F32*)(rxBuffer + 343));
+
+    returnVal->magRateNoise = *((F32*)(rxBuffer + 347));
+
+    returnVal->ekfSysNoise = *((F32*)(rxBuffer + 351));
+
+    returnVal->cssNoise = *((F32*)(rxBuffer + 355));
+
+    returnVal->sunNoise = *((F32*)(rxBuffer + 359));
+
+    returnVal->nadirNoise = *((F32*)(rxBuffer + 363));
+
+    returnVal->magNoise = *((F32*)(rxBuffer + 367));
+
+    returnVal->starNoise = *((F32*)(rxBuffer + 371));
+
+    returnVal->useSunEst = (rxBuffer[375] & 0x01) >> 0;
+
+    returnVal->useNadirEst = (rxBuffer[375] & 0x02) >> 1;
+
+    returnVal->useCssEst = (rxBuffer[375] & 0x04) >> 2;
+
+    returnVal->useStarEst = (rxBuffer[375] & 0x08) >> 3;
+
+    returnVal->terminatorCheck = (rxBuffer[375] & 0x10) >> 4;
+
+    returnVal->autoRecoverMtm = (rxBuffer[375] & 0x20) >> 5;
+
+    enumVal = (rxBuffer[375] >> 6) & 3;
+    returnVal->magMode = (CUBEACP_MagModeVal_t) enumVal;
+
+    enumVal = (rxBuffer[376] >> 0) & 3;
+    returnVal->magRawTlm2Selection = (CUBEACP_MagModeVal_t) enumVal;
+
+    returnVal->rateSensorErrorHandling = (rxBuffer[376] & 0x04) >> 2;
+
+    returnVal->wheelPowerOn30sDelay = (rxBuffer[376] & 0x08) >> 3;
+
+
+    returnVal->cam1Cam2Period = *( (U8*) (rxBuffer + 377) );
+
+    rawAInclCoeff = *( (U16*) (rxBuffer + 378) );
+    returnVal->aInclCoeff = rawAInclCoeff*0.001;
+
+    rawARaanCoeff = *( (U16*) (rxBuffer + 380) );
+    returnVal->aRaanCoeff = rawARaanCoeff*0.001;
+
+    rawAEccCoeff = *( (U16*) (rxBuffer + 382) );
+    returnVal->aEccCoeff = rawAEccCoeff*0.001;
+
+    rawAArgPerCoeff = *( (U16*) (rxBuffer + 384) );
+    returnVal->aArgPerCoeff = rawAArgPerCoeff*0.001;
+
+    rawATimeCoeff = *( (U16*) (rxBuffer + 386) );
+    returnVal->aTimeCoeff = rawATimeCoeff*0.001;
+
+    rawAPosCoeff = *( (U16*) (rxBuffer + 388) );
+    returnVal->aPosCoeff = rawAPosCoeff*0.001;
+
+    rawAsgp4MaxPosError = *( (U8*) (rxBuffer + 390) );
+    returnVal->asgp4MaxPosError = rawAsgp4MaxPosError*0.1;
+
+    enumVal = rxBuffer[391];
+    returnVal->asgp4Filter = (CUBEACP_AsgpFilter_t) enumVal;
+
+    rawAsgp4Xp = *( (S32*) (rxBuffer + 392) );
+    returnVal->asgp4Xp = rawAsgp4Xp*0.0000001;
+
+    rawAsgp4Yp = *( (S32*) (rxBuffer + 396) );
+    returnVal->asgp4Yp = rawAsgp4Yp*0.0000001;
+
+    returnVal->asgp4GpsRollover = *( (U8*) (rxBuffer + 400) );
+
+    rawAsgp4PosSdTh = *( (U8*) (rxBuffer + 401) );
+    returnVal->asgp4PosSdTh = rawAsgp4PosSdTh*0.1;
+
+    rawAsgp4VelSdTh = *( (U8*) (rxBuffer + 402) );
+    returnVal->asgp4VelSdTh = rawAsgp4VelSdTh*0.01;
+
+    returnVal->asgp4MinSat = *( (U8*) (rxBuffer + 403) );
+
+    rawAsgp4TimeGain = *( (U8*) (rxBuffer + 404) );
+    returnVal->asgp4TimeGain = rawAsgp4TimeGain*0.01;
+
+    rawAsgp4MaxLag = *( (U8*) (rxBuffer + 405) );
+    returnVal->asgp4MaxLag = rawAsgp4MaxLag*0.01;
+
+    returnVal->asgp4MinSamples = *( (U16*) (rxBuffer + 406) );
+
+    memcpy(returnVal->userConSettings, rxBuffer + 408, 48);
+
+    memcpy(returnVal->userEstSettings, rxBuffer + 456, 48);
+
+    if ((returnVal->starCentX < -5000) || (returnVal->starCentX > 5000))
+        return TlmRangeError;
+
+    if ((returnVal->starCentY < -5000) || (returnVal->starCentY > 5000))
+        return TlmRangeError;
+
+    if ((returnVal->starFocal < 5) || (returnVal->starFocal > 7))
+        return TlmRangeError;
+
+    if ((returnVal->starLensK1 < -1) || (returnVal->starLensK1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->starLensK2 < -1) || (returnVal->starLensK2 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->starLensP1 < -1) || (returnVal->starLensP1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->starLensP2 < -1) || (returnVal->starLensP2 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->ks < 0) || (returnVal->ks > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->kd < 0) || (returnVal->kd > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->wy_ref < -32000) || (returnVal->wy_ref > 32000))
+        return TlmRangeError;
+
+    if ((returnVal->kdf < 0) || (returnVal->kdf > 100))
+        return TlmRangeError;
+
+    if ((returnVal->kh < 0) || (returnVal->kh > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->kn < 0) || (returnVal->kn > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->kp1 < 0) || (returnVal->kp1 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->kd1 < 0) || (returnVal->kd1 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->h_ref < -10) || (returnVal->h_ref > 0))
+        return TlmRangeError;
+
+    if ((returnVal->kp2 < 0) || (returnVal->kp2 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->kd2 < 0) || (returnVal->kd2 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->h_bias < -10) || (returnVal->h_bias > 10))
+        return TlmRangeError;
+
+    if ((returnVal->kp3 < 0) || (returnVal->kp3 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->kd3 < 0) || (returnVal->kd3 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->ki3 < 0) || (returnVal->ki3 > 100))
+        return TlmRangeError;
+
+    if ((returnVal->ixx < 0) || (returnVal->ixx > 10))
+        return TlmRangeError;
+
+    if ((returnVal->iyy < 0) || (returnVal->iyy > 10))
+        return TlmRangeError;
+
+    if ((returnVal->izz < 0) || (returnVal->izz > 10))
+        return TlmRangeError;
+
+    if ((returnVal->ixy < -10) || (returnVal->ixy > 10))
+        return TlmRangeError;
+
+    if ((returnVal->ixz < -10) || (returnVal->ixz > 10))
+        return TlmRangeError;
+
+    if ((returnVal->iyz < -10) || (returnVal->iyz > 10))
+        return TlmRangeError;
+
+    if ((returnVal->magRateNoise < 0) || (returnVal->magRateNoise > 100))
+        return TlmRangeError;
+
+    if ((returnVal->ekfSysNoise < 0) || (returnVal->ekfSysNoise > 100))
+        return TlmRangeError;
+
+    if ((returnVal->cssNoise < 0) || (returnVal->cssNoise > 100))
+        return TlmRangeError;
+
+    if ((returnVal->sunNoise < 0) || (returnVal->sunNoise > 100))
+        return TlmRangeError;
+
+    if ((returnVal->nadirNoise < 0) || (returnVal->nadirNoise > 100))
+        return TlmRangeError;
+
+    if ((returnVal->magNoise < 0) || (returnVal->magNoise > 100))
+        return TlmRangeError;
+
+    if ((returnVal->starNoise < 0) || (returnVal->starNoise > 100))
+        return TlmRangeError;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsExecTimesTlm(uint8_t* rxBuffer, CUBEACP_AdcsExecTimes_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->timeAdcsUpdate = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->timeSensorActuatorComms = *( (U16*) (rxBuffer + 2) );
+
+    returnVal->timeSgp4 = *( (U16*) (rxBuffer + 4) );
+
+    returnVal->timeIgrf = *( (U16*) (rxBuffer + 6) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsMeasureTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawMagX;
+    S16 rawMagY;
+    S16 rawMagZ;
+    S16 rawCssX;
+    S16 rawCssY;
+    S16 rawCssZ;
+    S16 rawSunX;
+    S16 rawSunY;
+    S16 rawSunZ;
+    S16 rawNadirX;
+    S16 rawNadirY;
+    S16 rawNadirZ;
+    S16 rawRateX;
+    S16 rawRateY;
+    S16 rawRateZ;
+    S16 rawStar1BX;
+    S16 rawStar1BY;
+    S16 rawStar1BZ;
+    S16 rawStar1OX;
+    S16 rawStar1OY;
+    S16 rawStar1OZ;
+    S16 rawStar2BX;
+    S16 rawStar2BY;
+    S16 rawStar2BZ;
+    S16 rawStar2OX;
+    S16 rawStar2OY;
+    S16 rawStar2OZ;
+    S16 rawStar3BX;
+    S16 rawStar3BY;
+    S16 rawStar3BZ;
+    S16 rawStar3OX;
+    S16 rawStar3OY;
+    S16 rawStar3OZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawMagX = *( (S16*) (rxBuffer + 0) );
+    returnVal->magX = rawMagX*0.01;
+
+    rawMagY = *( (S16*) (rxBuffer + 2) );
+    returnVal->magY = rawMagY*0.01;
+
+    rawMagZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->magZ = rawMagZ*0.01;
+
+    rawCssX = *( (S16*) (rxBuffer + 6) );
+    returnVal->cssX = rawCssX/10000.0;
+
+    rawCssY = *( (S16*) (rxBuffer + 8) );
+    returnVal->cssY = rawCssY/10000.0;
+
+    rawCssZ = *( (S16*) (rxBuffer + 10) );
+    returnVal->cssZ = rawCssZ/10000.0;
+
+    rawSunX = *( (S16*) (rxBuffer + 12) );
+    returnVal->sunX = rawSunX/10000.0;
+
+    rawSunY = *( (S16*) (rxBuffer + 14) );
+    returnVal->sunY = rawSunY/10000.0;
+
+    rawSunZ = *( (S16*) (rxBuffer + 16) );
+    returnVal->sunZ = rawSunZ/10000.0;
+
+    rawNadirX = *( (S16*) (rxBuffer + 18) );
+    returnVal->nadirX = rawNadirX/10000.0;
+
+    rawNadirY = *( (S16*) (rxBuffer + 20) );
+    returnVal->nadirY = rawNadirY/10000.0;
+
+    rawNadirZ = *( (S16*) (rxBuffer + 22) );
+    returnVal->nadirZ = rawNadirZ/10000.0;
+
+    rawRateX = *( (S16*) (rxBuffer + 24) );
+    returnVal->rateX = rawRateX*0.01;
+
+    rawRateY = *( (S16*) (rxBuffer + 26) );
+    returnVal->rateY = rawRateY*0.01;
+
+    rawRateZ = *( (S16*) (rxBuffer + 28) );
+    returnVal->rateZ = rawRateZ*0.01;
+
+    returnVal->speedX = *( (S16*) (rxBuffer + 30) );
+
+    returnVal->speedY = *( (S16*) (rxBuffer + 32) );
+
+    returnVal->speedZ = *( (S16*) (rxBuffer + 34) );
+
+    rawStar1BX = *( (S16*) (rxBuffer + 36) );
+    returnVal->star1BX = rawStar1BX/10000.0;
+
+    rawStar1BY = *( (S16*) (rxBuffer + 38) );
+    returnVal->star1BY = rawStar1BY/10000.0;
+
+    rawStar1BZ = *( (S16*) (rxBuffer + 40) );
+    returnVal->star1BZ = rawStar1BZ/10000.0;
+
+    rawStar1OX = *( (S16*) (rxBuffer + 42) );
+    returnVal->star1OX = rawStar1OX/10000.0;
+
+    rawStar1OY = *( (S16*) (rxBuffer + 44) );
+    returnVal->star1OY = rawStar1OY/10000.0;
+
+    rawStar1OZ = *( (S16*) (rxBuffer + 46) );
+    returnVal->star1OZ = rawStar1OZ/10000.0;
+
+    rawStar2BX = *( (S16*) (rxBuffer + 48) );
+    returnVal->star2BX = rawStar2BX/10000.0;
+
+    rawStar2BY = *( (S16*) (rxBuffer + 50) );
+    returnVal->star2BY = rawStar2BY/10000.0;
+
+    rawStar2BZ = *( (S16*) (rxBuffer + 52) );
+    returnVal->star2BZ = rawStar2BZ/10000.0;
+
+    rawStar2OX = *( (S16*) (rxBuffer + 54) );
+    returnVal->star2OX = rawStar2OX/10000.0;
+
+    rawStar2OY = *( (S16*) (rxBuffer + 56) );
+    returnVal->star2OY = rawStar2OY/10000.0;
+
+    rawStar2OZ = *( (S16*) (rxBuffer + 58) );
+    returnVal->star2OZ = rawStar2OZ/10000.0;
+
+    rawStar3BX = *( (S16*) (rxBuffer + 60) );
+    returnVal->star3BX = rawStar3BX/10000.0;
+
+    rawStar3BY = *( (S16*) (rxBuffer + 62) );
+    returnVal->star3BY = rawStar3BY/10000.0;
+
+    rawStar3BZ = *( (S16*) (rxBuffer + 64) );
+    returnVal->star3BZ = rawStar3BZ/10000.0;
+
+    rawStar3OX = *( (S16*) (rxBuffer + 66) );
+    returnVal->star3OX = rawStar3OX/10000.0;
+
+    rawStar3OY = *( (S16*) (rxBuffer + 68) );
+    returnVal->star3OY = rawStar3OY/10000.0;
+
+    rawStar3OZ = *( (S16*) (rxBuffer + 70) );
+    returnVal->star3OZ = rawStar3OZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsMiscCurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    U16 rawCubeStarCurrent;
+    U16 rawMagtorqCurrent;
+    S16 rawCubeStarTemp;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCubeStarCurrent = *( (U16*) (rxBuffer + 0) );
+    returnVal->cubeStarCurrent = rawCubeStarCurrent*0.01;
+
+    rawMagtorqCurrent = *( (U16*) (rxBuffer + 2) );
+    returnVal->magtorqCurrent = rawMagtorqCurrent*0.1;
+
+    rawCubeStarTemp = *( (S16*) (rxBuffer + 4) );
+    returnVal->cubeStarTemp = rawCubeStarTemp/100.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsPowerTlm(uint8_t* rxBuffer, CUBEACP_AdcsPower_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = (rxBuffer[0] >> 0) & 3;
+    returnVal->cubeControlSignalPower = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 2) & 3;
+    returnVal->cubeControlMotorPower = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 4) & 3;
+    returnVal->cubeSense1Power = (CUBEACP_PowerSelectCubeSense_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 6) & 3;
+    returnVal->cubeSense2Power = (CUBEACP_PowerSelectCubeSense_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 0) & 3;
+    returnVal->cubeStarPower = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 2) & 3;
+    returnVal->cubeWheel1Power = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 4) & 3;
+    returnVal->cubeWheel2Power = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 6) & 3;
+    returnVal->cubeWheel3Power = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[2] >> 0) & 3;
+    returnVal->motorPower = (CUBEACP_PowerSelect_t) enumVal;
+
+    enumVal = (rxBuffer[2] >> 2) & 3;
+    returnVal->gpsLnaPower = (CUBEACP_PowerSelect_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsPowerMeasureTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    U16 rawCubeSense1_3V3Current;
+    U16 rawCubeSense1_CamCurrent;
+    U16 rawCubeSense2_3V3Current;
+    U16 rawCubeSense2_CamCurrent;
+    U16 rawCubeControl3V3Current;
+    U16 rawCubeControl5VCurrent;
+    U16 rawCubeControlBatCurrent;
+    U16 rawWheel1Current;
+    U16 rawWheel2Current;
+    U16 rawWheel3Current;
+    U16 rawCubeStarCurrent;
+    U16 rawMagtorqCurrent;
+    S16 rawCubeStarTemp;
+    S16 rawMagnetometerTemp;
+    S16 rawRedundentMagnetometerTemp;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCubeSense1_3V3Current = *( (U16*) (rxBuffer + 0) );
+    returnVal->cubeSense1_3V3Current = rawCubeSense1_3V3Current*0.1;
+
+    rawCubeSense1_CamCurrent = *( (U16*) (rxBuffer + 2) );
+    returnVal->cubeSense1_CamCurrent = rawCubeSense1_CamCurrent*0.1;
+
+    rawCubeSense2_3V3Current = *( (U16*) (rxBuffer + 4) );
+    returnVal->cubeSense2_3V3Current = rawCubeSense2_3V3Current*0.1;
+
+    rawCubeSense2_CamCurrent = *( (U16*) (rxBuffer + 6) );
+    returnVal->cubeSense2_CamCurrent = rawCubeSense2_CamCurrent*0.1;
+
+    rawCubeControl3V3Current = *( (U16*) (rxBuffer + 8) );
+    returnVal->cubeControl3V3Current = rawCubeControl3V3Current*0.48828125;
+
+    rawCubeControl5VCurrent = *( (U16*) (rxBuffer + 10) );
+    returnVal->cubeControl5VCurrent = rawCubeControl5VCurrent*0.48828125;
+
+    rawCubeControlBatCurrent = *( (U16*) (rxBuffer + 12) );
+    returnVal->cubeControlBatCurrent = rawCubeControlBatCurrent*0.48828125;
+
+    rawWheel1Current = *( (U16*) (rxBuffer + 14) );
+    returnVal->wheel1Current = rawWheel1Current*0.01;
+
+    rawWheel2Current = *( (U16*) (rxBuffer + 16) );
+    returnVal->wheel2Current = rawWheel2Current*0.01;
+
+    rawWheel3Current = *( (U16*) (rxBuffer + 18) );
+    returnVal->wheel3Current = rawWheel3Current*0.01;
+
+    rawCubeStarCurrent = *( (U16*) (rxBuffer + 20) );
+    returnVal->cubeStarCurrent = rawCubeStarCurrent*0.01;
+
+    rawMagtorqCurrent = *( (U16*) (rxBuffer + 22) );
+    returnVal->magtorqCurrent = rawMagtorqCurrent*0.1;
+
+    rawCubeStarTemp = *( (S16*) (rxBuffer + 24) );
+    returnVal->cubeStarTemp = rawCubeStarTemp/100.0;
+
+    returnVal->mCUTemp = *( (S16*) (rxBuffer + 26) );
+
+    rawMagnetometerTemp = *( (S16*) (rxBuffer + 28) );
+    returnVal->magnetometerTemp = rawMagnetometerTemp/10.0;
+
+    rawRedundentMagnetometerTemp = *( (S16*) (rxBuffer + 30) );
+    returnVal->redundentMagnetometerTemp = rawRedundentMagnetometerTemp/10.0;
+
+    returnVal->xRateTemp = *( (S16*) (rxBuffer + 32) );
+
+    returnVal->yRateTemp = *( (S16*) (rxBuffer + 34) );
+
+    returnVal->zRateTemp = *( (S16*) (rxBuffer + 36) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsStateTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    S16 rawRoll;
+    S16 rawPitch;
+    S16 rawYaw;
+    S16 rawRateX;
+    S16 rawRateY;
+    S16 rawRateZ;
+    S16 rawPositionX;
+    S16 rawPositionY;
+    S16 rawPositionZ;
+    S16 rawVelocityX;
+    S16 rawVelocityY;
+    S16 rawVelocityZ;
+    S16 rawLatitude;
+    S16 rawLongitude;
+    U16 rawAltitude;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = (rxBuffer[0] >> 0) & 15;
+    returnVal->estimMode = (CUBEACP_EstimModeSelect_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 4) & 15;
+    returnVal->controlMode = (CUBEACP_ConModeSelect_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 0) & 3;
+    returnVal->adcsRunMode = (CUBEACP_AdcsRunMode_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 2) & 3;
+    returnVal->asgp4Mode = (CUBEACP_Asgp4ModeSelect_t) enumVal;
+
+    returnVal->cubeControlSignalPower = (rxBuffer[1] & 0x10) >> 4;
+
+    returnVal->cubeControlMotorPower = (rxBuffer[1] & 0x20) >> 5;
+
+    returnVal->cubeSense1Power = (rxBuffer[1] & 0x40) >> 6;
+
+    returnVal->cubeSense2Power = (rxBuffer[1] & 0x80) >> 7;
+
+    returnVal->cubeWheel1Power = (rxBuffer[2] & 0x01) >> 0;
+
+    returnVal->cubeWheel2Power = (rxBuffer[2] & 0x02) >> 1;
+
+    returnVal->cubeWheel3Power = (rxBuffer[2] & 0x04) >> 2;
+
+    returnVal->cubeStarPower = (rxBuffer[2] & 0x08) >> 3;
+
+    returnVal->gpsReceiverPower = (rxBuffer[2] & 0x10) >> 4;
+
+    returnVal->gpsLnaPower = (rxBuffer[2] & 0x20) >> 5;
+
+    returnVal->motorDriverPower = (rxBuffer[2] & 0x40) >> 6;
+
+    returnVal->sunAboveHorizon = (rxBuffer[2] & 0x80) >> 7;
+
+    returnVal->cubeSense1CommsError = (rxBuffer[3] & 0x01) >> 0;
+
+    returnVal->cubeSense2CommsError = (rxBuffer[3] & 0x02) >> 1;
+
+    returnVal->cubeControlSignalCommsError = (rxBuffer[3] & 0x04) >> 2;
+
+    returnVal->cubeControlMotorCommsError = (rxBuffer[3] & 0x08) >> 3;
+
+    returnVal->cubeWheel1CommsError = (rxBuffer[3] & 0x10) >> 4;
+
+    returnVal->cubeWheel2CommsError = (rxBuffer[3] & 0x20) >> 5;
+
+    returnVal->cubeWheel3CommsError = (rxBuffer[3] & 0x40) >> 6;
+
+    returnVal->cubeStarCommsError = (rxBuffer[3] & 0x80) >> 7;
+
+    returnVal->magRangeError = (rxBuffer[4] & 0x01) >> 0;
+
+    returnVal->cam1OvercurrentSram = (rxBuffer[4] & 0x02) >> 1;
+
+    returnVal->cam1Overcurrent3V3 = (rxBuffer[4] & 0x04) >> 2;
+
+    returnVal->cam1SensNotIdle = (rxBuffer[4] & 0x08) >> 3;
+
+    returnVal->cam1SensDetectError = (rxBuffer[4] & 0x10) >> 4;
+
+    returnVal->sunSensRangeError = (rxBuffer[4] & 0x20) >> 5;
+
+    returnVal->cam2OvercurrentSram = (rxBuffer[4] & 0x40) >> 6;
+
+    returnVal->cam2Overcurrent3V3 = (rxBuffer[4] & 0x80) >> 7;
+
+    returnVal->cam2SensNotIdle = (rxBuffer[5] & 0x01) >> 0;
+
+    returnVal->cam2SensDetectError = (rxBuffer[5] & 0x02) >> 1;
+
+    returnVal->nadirSensRangeError = (rxBuffer[5] & 0x04) >> 2;
+
+    returnVal->rateSensRangeError = (rxBuffer[5] & 0x08) >> 3;
+
+    returnVal->wheelSpeedRangeError = (rxBuffer[5] & 0x10) >> 4;
+
+    returnVal->cssError = (rxBuffer[5] & 0x20) >> 5;
+
+    returnVal->starMatchError = (rxBuffer[5] & 0x40) >> 6;
+
+    returnVal->starTrackOvercurrent = (rxBuffer[5] & 0x80) >> 7;
+
+    returnVal->orbitParamsInvalidError = (rxBuffer[6] & 0x01) >> 0;
+
+    returnVal->configInvalidError = (rxBuffer[6] & 0x02) >> 1;
+
+    returnVal->controlModeNotAllowed = (rxBuffer[6] & 0x04) >> 2;
+
+    returnVal->estimatorNotAllowed = (rxBuffer[6] & 0x08) >> 3;
+
+    enumVal = (rxBuffer[6] >> 4) & 3;
+    returnVal->curMagMode = (CUBEACP_MagModeVal_t) enumVal;
+
+    returnVal->magfieldModelError = (rxBuffer[6] & 0x40) >> 6;
+
+    returnVal->nodeRecoveryError = (rxBuffer[6] & 0x80) >> 7;
+
+    returnVal->cubeSense1RuntimeError = (rxBuffer[7] & 0x01) >> 0;
+
+    returnVal->cubeSense2RuntimeError = (rxBuffer[7] & 0x02) >> 1;
+
+    returnVal->cubeControlSignalRuntimeError = (rxBuffer[7] & 0x04) >> 2;
+
+    returnVal->cubeControlMotorRuntimeError = (rxBuffer[7] & 0x08) >> 3;
+
+    returnVal->cubeWheel1RuntimeError = (rxBuffer[7] & 0x10) >> 4;
+
+    returnVal->cubeWheel2RuntimeError = (rxBuffer[7] & 0x20) >> 5;
+
+    returnVal->cubeWheel3RuntimeError = (rxBuffer[7] & 0x40) >> 6;
+
+    returnVal->cubeStarRuntimeError = (rxBuffer[7] & 0x80) >> 7;
+
+    returnVal->magnetometerError = (rxBuffer[8] & 0x01) >> 0;
+
+    returnVal->rateSensorFailure = (rxBuffer[8] & 0x02) >> 1;
+
+
+    rawRoll = *( (S16*) (rxBuffer + 12) );
+    returnVal->roll = rawRoll*0.01;
+
+    rawPitch = *( (S16*) (rxBuffer + 14) );
+    returnVal->pitch = rawPitch*0.01;
+
+    rawYaw = *( (S16*) (rxBuffer + 16) );
+    returnVal->yaw = rawYaw*0.01;
+
+    returnVal->q1 = *( (S16*) (rxBuffer + 18) );
+
+    returnVal->q2 = *( (S16*) (rxBuffer + 20) );
+
+    returnVal->q3 = *( (S16*) (rxBuffer + 22) );
+
+    rawRateX = *( (S16*) (rxBuffer + 24) );
+    returnVal->rateX = rawRateX*0.01;
+
+    rawRateY = *( (S16*) (rxBuffer + 26) );
+    returnVal->rateY = rawRateY*0.01;
+
+    rawRateZ = *( (S16*) (rxBuffer + 28) );
+    returnVal->rateZ = rawRateZ*0.01;
+
+    rawPositionX = *( (S16*) (rxBuffer + 30) );
+    returnVal->positionX = rawPositionX*0.25;
+
+    rawPositionY = *( (S16*) (rxBuffer + 32) );
+    returnVal->positionY = rawPositionY*0.25;
+
+    rawPositionZ = *( (S16*) (rxBuffer + 34) );
+    returnVal->positionZ = rawPositionZ*0.25;
+
+    rawVelocityX = *( (S16*) (rxBuffer + 36) );
+    returnVal->velocityX = rawVelocityX*0.25;
+
+    rawVelocityY = *( (S16*) (rxBuffer + 38) );
+    returnVal->velocityY = rawVelocityY*0.25;
+
+    rawVelocityZ = *( (S16*) (rxBuffer + 40) );
+    returnVal->velocityZ = rawVelocityZ*0.25;
+
+    rawLatitude = *( (S16*) (rxBuffer + 42) );
+    returnVal->latitude = rawLatitude*0.01;
+
+    rawLongitude = *( (S16*) (rxBuffer + 44) );
+    returnVal->longitude = rawLongitude*0.01;
+
+    rawAltitude = *( (U16*) (rxBuffer + 46) );
+    returnVal->altitude = rawAltitude*0.01;
+
+    returnVal->posEcefX = *( (S16*) (rxBuffer + 48) );
+
+    returnVal->posEcefY = *( (S16*) (rxBuffer + 50) );
+
+    returnVal->posEcefZ = *( (S16*) (rxBuffer + 52) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsSystemConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsSystemConfig_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = (rxBuffer[0] >> 0) & 15;
+    returnVal->acpType = (CUBEACP_AcpProgramType_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 4) & 15;
+    returnVal->specialControl = (CUBEACP_SpecialConSelect_t) enumVal;
+
+    returnVal->ccSignalVer = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->ccMotorVer = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->cs1Ver = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->cs2Ver = *( (U8*) (rxBuffer + 4) );
+
+    enumVal = (rxBuffer[5] >> 0) & 15;
+    returnVal->csCam1Type = (CUBEACP_CsCamType_t) enumVal;
+
+    enumVal = (rxBuffer[5] >> 4) & 15;
+    returnVal->csCam2Type = (CUBEACP_CsCamType_t) enumVal;
+
+    returnVal->cubeStarVer = *( (U8*) (rxBuffer + 6) );
+
+    enumVal = (rxBuffer[7] >> 0) & 15;
+    returnVal->gpsType = (CUBEACP_GpsSelect_t) enumVal;
+
+    returnVal->hasRedMag = (rxBuffer[7] & 0x10) >> 4;
+
+
+    returnVal->mqx = *((F32*)(rxBuffer + 8));
+
+    returnVal->mqy = *((F32*)(rxBuffer + 12));
+
+    returnVal->mqz = *((F32*)(rxBuffer + 16));
+
+    returnVal->mtTmin = *((F32*)(rxBuffer + 20));
+
+    returnVal->mtTmax = *((F32*)(rxBuffer + 24));
+
+    returnVal->nSatX = *((F32*)(rxBuffer + 28));
+
+    returnVal->nSatY = *((F32*)(rxBuffer + 32));
+
+    returnVal->nSatZ = *((F32*)(rxBuffer + 36));
+
+    returnVal->hSatX = *((F32*)(rxBuffer + 40));
+
+    returnVal->hSatY = *((F32*)(rxBuffer + 44));
+
+    returnVal->hSatZ = *((F32*)(rxBuffer + 48));
+
+    returnVal->iwx = *((F32*)(rxBuffer + 52));
+
+    returnVal->iwy = *((F32*)(rxBuffer + 56));
+
+    returnVal->iwz = *((F32*)(rxBuffer + 60));
+
+    returnVal->ndel = *((F32*)(rxBuffer + 64));
+
+    returnVal->biasX_d1 = *((F32*)(rxBuffer + 68));
+
+    returnVal->biasY_d1 = *((F32*)(rxBuffer + 72));
+
+    returnVal->biasZ_d1 = *((F32*)(rxBuffer + 76));
+
+    returnVal->biasX_d2 = *((F32*)(rxBuffer + 80));
+
+    returnVal->biasY_d2 = *((F32*)(rxBuffer + 84));
+
+    returnVal->biasZ_d2 = *((F32*)(rxBuffer + 88));
+
+    returnVal->sensX_s1 = *((F32*)(rxBuffer + 92));
+
+    returnVal->sensY_s1 = *((F32*)(rxBuffer + 96));
+
+    returnVal->sensZ_s1 = *((F32*)(rxBuffer + 100));
+
+    returnVal->sensX_s2 = *((F32*)(rxBuffer + 104));
+
+    returnVal->sensY_s2 = *((F32*)(rxBuffer + 108));
+
+    returnVal->sensZ_s2 = *((F32*)(rxBuffer + 112));
+
+    returnVal->red_BiasX_d1 = *((F32*)(rxBuffer + 116));
+
+    returnVal->red_BiasY_d1 = *((F32*)(rxBuffer + 120));
+
+    returnVal->red_BiasZ_d1 = *((F32*)(rxBuffer + 124));
+
+    returnVal->red_BiasX_d2 = *((F32*)(rxBuffer + 128));
+
+    returnVal->red_BiasY_d2 = *((F32*)(rxBuffer + 132));
+
+    returnVal->red_BiasZ_d2 = *((F32*)(rxBuffer + 136));
+
+    returnVal->red_SensX_s1 = *((F32*)(rxBuffer + 140));
+
+    returnVal->red_SensY_s1 = *((F32*)(rxBuffer + 144));
+
+    returnVal->red_SensZ_s1 = *((F32*)(rxBuffer + 148));
+
+    returnVal->red_SensX_s2 = *((F32*)(rxBuffer + 152));
+
+    returnVal->red_SensY_s2 = *((F32*)(rxBuffer + 156));
+
+    returnVal->red_SensZ_s2 = *((F32*)(rxBuffer + 160));
+
+    enumVal = (rxBuffer[164] >> 0) & 15;
+    returnVal->ccsEnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[164] >> 4) & 15;
+    returnVal->ccsEnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[165] >> 0) & 15;
+    returnVal->ccmEnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[165] >> 4) & 15;
+    returnVal->ccmEnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[166] >> 0) & 15;
+    returnVal->cccEnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[166] >> 4) & 15;
+    returnVal->cccEnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[167] >> 0) & 15;
+    returnVal->cSense1EnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[167] >> 4) & 15;
+    returnVal->cSense1EnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[168] >> 0) & 15;
+    returnVal->cSense2EnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[168] >> 4) & 15;
+    returnVal->cSense2EnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[169] >> 0) & 15;
+    returnVal->cStarEnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[169] >> 4) & 15;
+    returnVal->cStarEnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[170] >> 0) & 15;
+    returnVal->cW1EnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[170] >> 4) & 15;
+    returnVal->cW1EnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[171] >> 0) & 15;
+    returnVal->cW2EnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[171] >> 4) & 15;
+    returnVal->cW2EnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    enumVal = (rxBuffer[172] >> 0) & 15;
+    returnVal->cW3EnablePort = (CUBEACP_GpioPort_t) enumVal;
+
+    enumVal = (rxBuffer[172] >> 4) & 15;
+    returnVal->cW3EnablePin = (CUBEACP_GpioPortPin_t) enumVal;
+
+    if ((returnVal->mqx < 0) || (returnVal->mqx > 2))
+        return TlmRangeError;
+
+    if ((returnVal->mqy < 0) || (returnVal->mqy > 2))
+        return TlmRangeError;
+
+    if ((returnVal->mqz < 0) || (returnVal->mqz > 2))
+        return TlmRangeError;
+
+    if ((returnVal->mtTmin < 0) || (returnVal->mtTmin > 1))
+        return TlmRangeError;
+
+    if ((returnVal->mtTmax < 0) || (returnVal->mtTmax > 1))
+        return TlmRangeError;
+
+    if ((returnVal->nSatX < 0) || (returnVal->nSatX > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->nSatY < 0) || (returnVal->nSatY > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->nSatZ < 0) || (returnVal->nSatZ > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->hSatX < 0) || (returnVal->hSatX > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->hSatY < 0) || (returnVal->hSatY > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->hSatZ < 0) || (returnVal->hSatZ > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->iwx < 0) || (returnVal->iwx > 0.001))
+        return TlmRangeError;
+
+    if ((returnVal->iwy < 0) || (returnVal->iwy > 0.001))
+        return TlmRangeError;
+
+    if ((returnVal->iwz < 0) || (returnVal->iwz > 0.001))
+        return TlmRangeError;
+
+    if ((returnVal->ndel < 0) || (returnVal->ndel > 0.1))
+        return TlmRangeError;
+
+    if ((returnVal->biasX_d1 < -10) || (returnVal->biasX_d1 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->biasY_d1 < -10) || (returnVal->biasY_d1 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->biasZ_d1 < -10) || (returnVal->biasZ_d1 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->biasX_d2 < -10000) || (returnVal->biasX_d2 > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->biasY_d2 < -10000) || (returnVal->biasY_d2 > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->biasZ_d2 < -10000) || (returnVal->biasZ_d2 > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->sensX_s1 < -1) || (returnVal->sensX_s1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->sensY_s1 < -1) || (returnVal->sensY_s1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->sensZ_s1 < -1) || (returnVal->sensZ_s1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->sensX_s2 < -10) || (returnVal->sensX_s2 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->sensY_s2 < -10) || (returnVal->sensY_s2 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->sensZ_s2 < -10) || (returnVal->sensZ_s2 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->red_BiasX_d1 < -10) || (returnVal->red_BiasX_d1 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->red_BiasY_d1 < -10) || (returnVal->red_BiasY_d1 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->red_BiasZ_d1 < -10) || (returnVal->red_BiasZ_d1 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->red_BiasX_d2 < -10000) || (returnVal->red_BiasX_d2 > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->red_BiasY_d2 < -10000) || (returnVal->red_BiasY_d2 > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->red_BiasZ_d2 < -10000) || (returnVal->red_BiasZ_d2 > 10000))
+        return TlmRangeError;
+
+    if ((returnVal->red_SensX_s1 < -1) || (returnVal->red_SensX_s1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->red_SensY_s1 < -1) || (returnVal->red_SensY_s1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->red_SensZ_s1 < -1) || (returnVal->red_SensZ_s1 > 1))
+        return TlmRangeError;
+
+    if ((returnVal->red_SensX_s2 < -10) || (returnVal->red_SensX_s2 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->red_SensY_s2 < -10) || (returnVal->red_SensY_s2 > 10))
+        return TlmRangeError;
+
+    if ((returnVal->red_SensZ_s2 < -10) || (returnVal->red_SensZ_s2 > 10))
+        return TlmRangeError;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsTemperatures1Tlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    S16 rawMagnetometerTemp;
+    S16 rawRedundentMagnetometerTemp;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->mCUTemp = *( (S16*) (rxBuffer + 0) );
+
+    rawMagnetometerTemp = *( (S16*) (rxBuffer + 2) );
+    returnVal->magnetometerTemp = rawMagnetometerTemp/10.0;
+
+    rawRedundentMagnetometerTemp = *( (S16*) (rxBuffer + 4) );
+    returnVal->redundentMagnetometerTemp = rawRedundentMagnetometerTemp/10.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAdcsTemperatures2Tlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->xRateTemp = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->yRateTemp = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->zRateTemp = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractAsgp4KepTleTlm(uint8_t* rxBuffer, CUBEACP_Asgp4KepTle_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->asgp4Complete = (rxBuffer[0] & 0x01) >> 0;
+
+    enumVal = (rxBuffer[0] >> 1) & 127;
+    returnVal->asgpErr = (CUBEACP_Asgp4Error_t) enumVal;
+
+    returnVal->asgp4Epoch = *((F32*)(rxBuffer + 1));
+
+    returnVal->asgp4Incli = *((F32*)(rxBuffer + 5));
+
+    returnVal->asgp4Raan = *((F32*)(rxBuffer + 9));
+
+    returnVal->asgp4Ecc = *((F32*)(rxBuffer + 13));
+
+    returnVal->asgp4Aop = *((F32*)(rxBuffer + 17));
+
+    returnVal->asgp4Ma = *((F32*)(rxBuffer + 21));
+
+    returnVal->asgp4Mm = *((F32*)(rxBuffer + 25));
+
+    returnVal->asgp4Bstar = *((F32*)(rxBuffer + 29));
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractASgp4ParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    U16 rawAInclCoeff;
+    U16 rawARaanCoeff;
+    U16 rawAEccCoeff;
+    U16 rawAArgPerCoeff;
+    U16 rawATimeCoeff;
+    U16 rawAPosCoeff;
+    U8 rawAsgp4MaxPosError;
+    S32 rawAsgp4Xp;
+    S32 rawAsgp4Yp;
+    U8 rawAsgp4PosSdTh;
+    U8 rawAsgp4VelSdTh;
+    U8 rawAsgp4TimeGain;
+    U8 rawAsgp4MaxLag;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawAInclCoeff = *( (U16*) (rxBuffer + 0) );
+    returnVal->aInclCoeff = rawAInclCoeff*0.001;
+
+    rawARaanCoeff = *( (U16*) (rxBuffer + 2) );
+    returnVal->aRaanCoeff = rawARaanCoeff*0.001;
+
+    rawAEccCoeff = *( (U16*) (rxBuffer + 4) );
+    returnVal->aEccCoeff = rawAEccCoeff*0.001;
+
+    rawAArgPerCoeff = *( (U16*) (rxBuffer + 6) );
+    returnVal->aArgPerCoeff = rawAArgPerCoeff*0.001;
+
+    rawATimeCoeff = *( (U16*) (rxBuffer + 8) );
+    returnVal->aTimeCoeff = rawATimeCoeff*0.001;
+
+    rawAPosCoeff = *( (U16*) (rxBuffer + 10) );
+    returnVal->aPosCoeff = rawAPosCoeff*0.001;
+
+    rawAsgp4MaxPosError = *( (U8*) (rxBuffer + 12) );
+    returnVal->asgp4MaxPosError = rawAsgp4MaxPosError*0.1;
+
+    enumVal = rxBuffer[13];
+    returnVal->asgp4Filter = (CUBEACP_AsgpFilter_t) enumVal;
+
+    rawAsgp4Xp = *( (S32*) (rxBuffer + 14) );
+    returnVal->asgp4Xp = rawAsgp4Xp*0.0000001;
+
+    rawAsgp4Yp = *( (S32*) (rxBuffer + 18) );
+    returnVal->asgp4Yp = rawAsgp4Yp*0.0000001;
+
+    returnVal->asgp4GpsRollover = *( (U8*) (rxBuffer + 22) );
+
+    rawAsgp4PosSdTh = *( (U8*) (rxBuffer + 23) );
+    returnVal->asgp4PosSdTh = rawAsgp4PosSdTh*0.1;
+
+    rawAsgp4VelSdTh = *( (U8*) (rxBuffer + 24) );
+    returnVal->asgp4VelSdTh = rawAsgp4VelSdTh*0.01;
+
+    returnVal->asgp4MinSat = *( (U8*) (rxBuffer + 25) );
+
+    rawAsgp4TimeGain = *( (U8*) (rxBuffer + 26) );
+    returnVal->asgp4TimeGain = rawAsgp4TimeGain*0.01;
+
+    rawAsgp4MaxLag = *( (U8*) (rxBuffer + 27) );
+    returnVal->asgp4MaxLag = rawAsgp4MaxLag*0.01;
+
+    returnVal->asgp4MinSamples = *( (U16*) (rxBuffer + 28) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCmdAttitudeTlm(uint8_t* rxBuffer, CUBEACP_CmdAttitude_t* returnVal)
+{
+    S16 rawRoll;
+    S16 rawPitch;
+    S16 rawYaw;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawRoll = *( (S16*) (rxBuffer + 0) );
+    returnVal->roll = rawRoll*0.01;
+
+    rawPitch = *( (S16*) (rxBuffer + 2) );
+    returnVal->pitch = rawPitch*0.01;
+
+    rawYaw = *( (S16*) (rxBuffer + 4) );
+    returnVal->yaw = rawYaw*0.01;
+
+    if ((returnVal->roll < -9000) || (returnVal->roll > 9000))
+        return TlmRangeError;
+
+    if ((returnVal->pitch < -18000) || (returnVal->pitch > 18000))
+        return TlmRangeError;
+
+    if ((returnVal->yaw < -18000) || (returnVal->yaw > 18000))
+        return TlmRangeError;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCmdTrackingTargetTlm(uint8_t* rxBuffer, CUBEACP_CmdTrackingTarget_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->longRef = *((F32*)(rxBuffer + 0));
+
+    returnVal->latRef = *((F32*)(rxBuffer + 4));
+
+    returnVal->altRef = *((F32*)(rxBuffer + 8));
+
+    if ((returnVal->longRef < 0) || (returnVal->longRef > 360))
+        return TlmRangeError;
+
+    if ((returnVal->latRef < -90) || (returnVal->latRef > 90))
+        return TlmRangeError;
+
+    if ((returnVal->altRef < -20000) || (returnVal->altRef > 40000000))
+        return TlmRangeError;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCoarseSunVecTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawCssX;
+    S16 rawCssY;
+    S16 rawCssZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCssX = *( (S16*) (rxBuffer + 0) );
+    returnVal->cssX = rawCssX/10000.0;
+
+    rawCssY = *( (S16*) (rxBuffer + 2) );
+    returnVal->cssY = rawCssY/10000.0;
+
+    rawCssZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->cssZ = rawCssZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractConversionProgressTlm(uint8_t* rxBuffer, CUBEACP_ConversionProgress_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->progress = *( (U8*) (rxBuffer + 0) );
+
+    enumVal = rxBuffer[1];
+    returnVal->conversionResult = (CUBEACP_JpgConvertResult_t) enumVal;
+
+    returnVal->outFileCounter = *( (U8*) (rxBuffer + 2) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCssConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    U8 rawCss1Scale;
+    U8 rawCss2Scale;
+    U8 rawCss3Scale;
+    U8 rawCss4Scale;
+    U8 rawCss5Scale;
+    U8 rawCss6Scale;
+    U8 rawCss7Scale;
+    U8 rawCss8Scale;
+    U8 rawCss9Scale;
+    U8 rawCss10Scale;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->css1Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[1];
+    returnVal->css2Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[2];
+    returnVal->css3Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[3];
+    returnVal->css4Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[4];
+    returnVal->css5Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[5];
+    returnVal->css6Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[6];
+    returnVal->css7Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[7];
+    returnVal->css8Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[8];
+    returnVal->css9Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[9];
+    returnVal->css10Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    rawCss1Scale = *( (U8*) (rxBuffer + 10) );
+    returnVal->css1Scale = rawCss1Scale*0.01;
+
+    rawCss2Scale = *( (U8*) (rxBuffer + 11) );
+    returnVal->css2Scale = rawCss2Scale*0.01;
+
+    rawCss3Scale = *( (U8*) (rxBuffer + 12) );
+    returnVal->css3Scale = rawCss3Scale*0.01;
+
+    rawCss4Scale = *( (U8*) (rxBuffer + 13) );
+    returnVal->css4Scale = rawCss4Scale*0.01;
+
+    rawCss5Scale = *( (U8*) (rxBuffer + 14) );
+    returnVal->css5Scale = rawCss5Scale*0.01;
+
+    rawCss6Scale = *( (U8*) (rxBuffer + 15) );
+    returnVal->css6Scale = rawCss6Scale*0.01;
+
+    rawCss7Scale = *( (U8*) (rxBuffer + 16) );
+    returnVal->css7Scale = rawCss7Scale*0.01;
+
+    rawCss8Scale = *( (U8*) (rxBuffer + 17) );
+    returnVal->css8Scale = rawCss8Scale*0.01;
+
+    rawCss9Scale = *( (U8*) (rxBuffer + 18) );
+    returnVal->css9Scale = rawCss9Scale*0.01;
+
+    rawCss10Scale = *( (U8*) (rxBuffer + 19) );
+    returnVal->css10Scale = rawCss10Scale*0.01;
+
+    returnVal->cssMinimum = *( (U8*) (rxBuffer + 20) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCubeACPStateTlm(uint8_t* rxBuffer, CUBEACP_CubeACPState_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->adcsConfigLoadError = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->orbitParamsLoadError = (rxBuffer[0] & 0x02) >> 1;
+
+    returnVal->systemConfigLoadError = (rxBuffer[0] & 0x04) >> 2;
+
+    returnVal->sdInitError = (rxBuffer[0] & 0x08) >> 3;
+
+    returnVal->sdReadError = (rxBuffer[0] & 0x10) >> 4;
+
+    returnVal->sdWriteError = (rxBuffer[0] & 0x20) >> 5;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCubeControlCurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    U16 rawCubeControl3V3Current;
+    U16 rawCubeControl5VCurrent;
+    U16 rawCubeControlBatCurrent;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCubeControl3V3Current = *( (U16*) (rxBuffer + 0) );
+    returnVal->cubeControl3V3Current = rawCubeControl3V3Current*0.48828125;
+
+    rawCubeControl5VCurrent = *( (U16*) (rxBuffer + 2) );
+    returnVal->cubeControl5VCurrent = rawCubeControl5VCurrent*0.48828125;
+
+    rawCubeControlBatCurrent = *( (U16*) (rxBuffer + 4) );
+    returnVal->cubeControlBatCurrent = rawCubeControlBatCurrent*0.48828125;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCubeSense1CurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    U16 rawCubeSense1_3V3Current;
+    U16 rawCubeSense1_CamCurrent;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCubeSense1_3V3Current = *( (U16*) (rxBuffer + 0) );
+    returnVal->cubeSense1_3V3Current = rawCubeSense1_3V3Current*0.1;
+
+    rawCubeSense1_CamCurrent = *( (U16*) (rxBuffer + 2) );
+    returnVal->cubeSense1_CamCurrent = rawCubeSense1_CamCurrent*0.1;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCubeSense2CurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    U16 rawCubeSense2_3V3Current;
+    U16 rawCubeSense2_CamCurrent;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCubeSense2_3V3Current = *( (U16*) (rxBuffer + 0) );
+    returnVal->cubeSense2_3V3Current = rawCubeSense2_3V3Current*0.1;
+
+    rawCubeSense2_CamCurrent = *( (U16*) (rxBuffer + 2) );
+    returnVal->cubeSense2_CamCurrent = rawCubeSense2_CamCurrent*0.1;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCubeSenseConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawCam1Angle1;
+    S16 rawCam1Angle2;
+    S16 rawCam1Angle3;
+    U16 rawCam1BoreX;
+    U16 rawCam1BoreY;
+    S16 rawCam2Angle1;
+    S16 rawCam2Angle2;
+    S16 rawCam2Angle3;
+    U16 rawCam2BoreX;
+    U16 rawCam2BoreY;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawCam1Angle1 = *( (S16*) (rxBuffer + 0) );
+    returnVal->cam1Angle1 = rawCam1Angle1*0.01;
+
+    rawCam1Angle2 = *( (S16*) (rxBuffer + 2) );
+    returnVal->cam1Angle2 = rawCam1Angle2*0.01;
+
+    rawCam1Angle3 = *( (S16*) (rxBuffer + 4) );
+    returnVal->cam1Angle3 = rawCam1Angle3*0.01;
+
+    returnVal->cam1Threshold = *( (U8*) (rxBuffer + 6) );
+
+    returnVal->cam1AutoAdj = (rxBuffer[7] & 0x01) >> 0;
+
+
+    returnVal->cam1Exposure = *( (U16*) (rxBuffer + 8) );
+
+    rawCam1BoreX = *( (U16*) (rxBuffer + 10) );
+    returnVal->cam1BoreX = rawCam1BoreX*0.01;
+
+    rawCam1BoreY = *( (U16*) (rxBuffer + 12) );
+    returnVal->cam1BoreY = rawCam1BoreY*0.01;
+
+    rawCam2Angle1 = *( (S16*) (rxBuffer + 14) );
+    returnVal->cam2Angle1 = rawCam2Angle1*0.01;
+
+    rawCam2Angle2 = *( (S16*) (rxBuffer + 16) );
+    returnVal->cam2Angle2 = rawCam2Angle2*0.01;
+
+    rawCam2Angle3 = *( (S16*) (rxBuffer + 18) );
+    returnVal->cam2Angle3 = rawCam2Angle3*0.01;
+
+    returnVal->cam2Threshold = *( (U8*) (rxBuffer + 20) );
+
+    returnVal->cam2AutoAdj = (rxBuffer[21] & 0x01) >> 0;
+
+
+    returnVal->cam2Exposure = *( (U16*) (rxBuffer + 22) );
+
+    rawCam2BoreX = *( (U16*) (rxBuffer + 24) );
+    returnVal->cam2BoreX = rawCam2BoreX*0.01;
+
+    rawCam2BoreY = *( (U16*) (rxBuffer + 26) );
+    returnVal->cam2BoreY = rawCam2BoreY*0.01;
+
+    returnVal->nadirMaxDeviationPercentage = *( (U8*) (rxBuffer + 28) );
+
+    returnVal->nadirMaxBadEdges = *( (U8*) (rxBuffer + 29) );
+
+    returnVal->nadirMaxRadius = *( (U8*) (rxBuffer + 30) );
+
+    returnVal->nadirMinRadius = *( (U8*) (rxBuffer + 31) );
+
+    returnVal->cam1MaskArea1Xmin = *( (U16*) (rxBuffer + 32) );
+
+    returnVal->cam1MaskArea1Xmax = *( (U16*) (rxBuffer + 34) );
+
+    returnVal->cam1MaskArea1Ymin = *( (U16*) (rxBuffer + 36) );
+
+    returnVal->cam1MaskArea1Ymax = *( (U16*) (rxBuffer + 38) );
+
+    returnVal->cam1MaskArea2Xmin = *( (U16*) (rxBuffer + 40) );
+
+    returnVal->cam1MaskArea2Xmax = *( (U16*) (rxBuffer + 42) );
+
+    returnVal->cam1MaskArea2Ymin = *( (U16*) (rxBuffer + 44) );
+
+    returnVal->cam1MaskArea2Ymax = *( (U16*) (rxBuffer + 46) );
+
+    returnVal->cam1MaskArea3Xmin = *( (U16*) (rxBuffer + 48) );
+
+    returnVal->cam1MaskArea3Xmax = *( (U16*) (rxBuffer + 50) );
+
+    returnVal->cam1MaskArea3Ymin = *( (U16*) (rxBuffer + 52) );
+
+    returnVal->cam1MaskArea3Ymax = *( (U16*) (rxBuffer + 54) );
+
+    returnVal->cam1MaskArea4Xmin = *( (U16*) (rxBuffer + 56) );
+
+    returnVal->cam1MaskArea4Xmax = *( (U16*) (rxBuffer + 58) );
+
+    returnVal->cam1MaskArea4Ymin = *( (U16*) (rxBuffer + 60) );
+
+    returnVal->cam1MaskArea4Ymax = *( (U16*) (rxBuffer + 62) );
+
+    returnVal->cam1MaskArea5Xmin = *( (U16*) (rxBuffer + 64) );
+
+    returnVal->cam1MaskArea5Xmax = *( (U16*) (rxBuffer + 66) );
+
+    returnVal->cam1MaskArea5Ymin = *( (U16*) (rxBuffer + 68) );
+
+    returnVal->cam1MaskArea5Ymax = *( (U16*) (rxBuffer + 70) );
+
+    returnVal->cam2MaskArea1Xmin = *( (U16*) (rxBuffer + 72) );
+
+    returnVal->cam2MaskArea1Xmax = *( (U16*) (rxBuffer + 74) );
+
+    returnVal->cam2MaskArea1Ymin = *( (U16*) (rxBuffer + 76) );
+
+    returnVal->cam2MaskArea1Ymax = *( (U16*) (rxBuffer + 78) );
+
+    returnVal->cam2MaskArea2Xmin = *( (U16*) (rxBuffer + 80) );
+
+    returnVal->cam2MaskArea2Xmax = *( (U16*) (rxBuffer + 82) );
+
+    returnVal->cam2MaskArea2Ymin = *( (U16*) (rxBuffer + 84) );
+
+    returnVal->cam2MaskArea2Ymax = *( (U16*) (rxBuffer + 86) );
+
+    returnVal->cam2MaskArea3Xmin = *( (U16*) (rxBuffer + 88) );
+
+    returnVal->cam2MaskArea3Xmax = *( (U16*) (rxBuffer + 90) );
+
+    returnVal->cam2MaskArea3Ymin = *( (U16*) (rxBuffer + 92) );
+
+    returnVal->cam2MaskArea3Ymax = *( (U16*) (rxBuffer + 94) );
+
+    returnVal->cam2MaskArea4Xmin = *( (U16*) (rxBuffer + 96) );
+
+    returnVal->cam2MaskArea4Xmax = *( (U16*) (rxBuffer + 98) );
+
+    returnVal->cam2MaskArea4Ymin = *( (U16*) (rxBuffer + 100) );
+
+    returnVal->cam2MaskArea4Ymax = *( (U16*) (rxBuffer + 102) );
+
+    returnVal->cam2MaskArea5Xmin = *( (U16*) (rxBuffer + 104) );
+
+    returnVal->cam2MaskArea5Xmax = *( (U16*) (rxBuffer + 106) );
+
+    returnVal->cam2MaskArea5Ymin = *( (U16*) (rxBuffer + 108) );
+
+    returnVal->cam2MaskArea5Ymax = *( (U16*) (rxBuffer + 110) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCurrentAdcsStateTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = (rxBuffer[0] >> 0) & 15;
+    returnVal->estimMode = (CUBEACP_EstimModeSelect_t) enumVal;
+
+    enumVal = (rxBuffer[0] >> 4) & 15;
+    returnVal->controlMode = (CUBEACP_ConModeSelect_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 0) & 3;
+    returnVal->adcsRunMode = (CUBEACP_AdcsRunMode_t) enumVal;
+
+    enumVal = (rxBuffer[1] >> 2) & 3;
+    returnVal->asgp4Mode = (CUBEACP_Asgp4ModeSelect_t) enumVal;
+
+    returnVal->cubeControlSignalPower = (rxBuffer[1] & 0x10) >> 4;
+
+    returnVal->cubeControlMotorPower = (rxBuffer[1] & 0x20) >> 5;
+
+    returnVal->cubeSense1Power = (rxBuffer[1] & 0x40) >> 6;
+
+    returnVal->cubeSense2Power = (rxBuffer[1] & 0x80) >> 7;
+
+    returnVal->cubeWheel1Power = (rxBuffer[2] & 0x01) >> 0;
+
+    returnVal->cubeWheel2Power = (rxBuffer[2] & 0x02) >> 1;
+
+    returnVal->cubeWheel3Power = (rxBuffer[2] & 0x04) >> 2;
+
+    returnVal->cubeStarPower = (rxBuffer[2] & 0x08) >> 3;
+
+    returnVal->gpsReceiverPower = (rxBuffer[2] & 0x10) >> 4;
+
+    returnVal->gpsLnaPower = (rxBuffer[2] & 0x20) >> 5;
+
+    returnVal->motorDriverPower = (rxBuffer[2] & 0x40) >> 6;
+
+    returnVal->sunAboveHorizon = (rxBuffer[2] & 0x80) >> 7;
+
+    returnVal->cubeSense1CommsError = (rxBuffer[3] & 0x01) >> 0;
+
+    returnVal->cubeSense2CommsError = (rxBuffer[3] & 0x02) >> 1;
+
+    returnVal->cubeControlSignalCommsError = (rxBuffer[3] & 0x04) >> 2;
+
+    returnVal->cubeControlMotorCommsError = (rxBuffer[3] & 0x08) >> 3;
+
+    returnVal->cubeWheel1CommsError = (rxBuffer[3] & 0x10) >> 4;
+
+    returnVal->cubeWheel2CommsError = (rxBuffer[3] & 0x20) >> 5;
+
+    returnVal->cubeWheel3CommsError = (rxBuffer[3] & 0x40) >> 6;
+
+    returnVal->cubeStarCommsError = (rxBuffer[3] & 0x80) >> 7;
+
+    returnVal->magRangeError = (rxBuffer[4] & 0x01) >> 0;
+
+    returnVal->cam1OvercurrentSram = (rxBuffer[4] & 0x02) >> 1;
+
+    returnVal->cam1Overcurrent3V3 = (rxBuffer[4] & 0x04) >> 2;
+
+    returnVal->cam1SensNotIdle = (rxBuffer[4] & 0x08) >> 3;
+
+    returnVal->cam1SensDetectError = (rxBuffer[4] & 0x10) >> 4;
+
+    returnVal->sunSensRangeError = (rxBuffer[4] & 0x20) >> 5;
+
+    returnVal->cam2OvercurrentSram = (rxBuffer[4] & 0x40) >> 6;
+
+    returnVal->cam2Overcurrent3V3 = (rxBuffer[4] & 0x80) >> 7;
+
+    returnVal->cam2SensNotIdle = (rxBuffer[5] & 0x01) >> 0;
+
+    returnVal->cam2SensDetectError = (rxBuffer[5] & 0x02) >> 1;
+
+    returnVal->nadirSensRangeError = (rxBuffer[5] & 0x04) >> 2;
+
+    returnVal->rateSensRangeError = (rxBuffer[5] & 0x08) >> 3;
+
+    returnVal->wheelSpeedRangeError = (rxBuffer[5] & 0x10) >> 4;
+
+    returnVal->cssError = (rxBuffer[5] & 0x20) >> 5;
+
+    returnVal->starMatchError = (rxBuffer[5] & 0x40) >> 6;
+
+    returnVal->starTrackOvercurrent = (rxBuffer[5] & 0x80) >> 7;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractCurrentAdcsState2Tlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->orbitParamsInvalidError = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->configInvalidError = (rxBuffer[0] & 0x02) >> 1;
+
+    returnVal->controlModeNotAllowed = (rxBuffer[0] & 0x04) >> 2;
+
+    returnVal->estimatorNotAllowed = (rxBuffer[0] & 0x08) >> 3;
+
+    enumVal = (rxBuffer[0] >> 4) & 3;
+    returnVal->curMagMode = (CUBEACP_MagModeVal_t) enumVal;
+
+    returnVal->magfieldModelError = (rxBuffer[0] & 0x40) >> 6;
+
+    returnVal->nodeRecoveryError = (rxBuffer[0] & 0x80) >> 7;
+
+    returnVal->cubeSense1RuntimeError = (rxBuffer[1] & 0x01) >> 0;
+
+    returnVal->cubeSense2RuntimeError = (rxBuffer[1] & 0x02) >> 1;
+
+    returnVal->cubeControlSignalRuntimeError = (rxBuffer[1] & 0x04) >> 2;
+
+    returnVal->cubeControlMotorRuntimeError = (rxBuffer[1] & 0x08) >> 3;
+
+    returnVal->cubeWheel1RuntimeError = (rxBuffer[1] & 0x10) >> 4;
+
+    returnVal->cubeWheel2RuntimeError = (rxBuffer[1] & 0x20) >> 5;
+
+    returnVal->cubeWheel3RuntimeError = (rxBuffer[1] & 0x40) >> 6;
+
+    returnVal->cubeStarRuntimeError = (rxBuffer[1] & 0x80) >> 7;
+
+    returnVal->magnetometerError = (rxBuffer[2] & 0x01) >> 0;
+
+    returnVal->rateSensorFailure = (rxBuffer[2] & 0x02) >> 1;
+
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractDetumbleParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawwy_ref;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->ks = *((F32*)(rxBuffer + 0));
+
+    returnVal->kd = *((F32*)(rxBuffer + 4));
+
+    rawwy_ref = *( (S16*) (rxBuffer + 8) );
+    returnVal->wy_ref = rawwy_ref*0.001;
+
+    returnVal->kdf = *((F32*)(rxBuffer + 10));
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractEstimAttitudeTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    S16 rawRoll;
+    S16 rawPitch;
+    S16 rawYaw;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawRoll = *( (S16*) (rxBuffer + 0) );
+    returnVal->roll = rawRoll*0.01;
+
+    rawPitch = *( (S16*) (rxBuffer + 2) );
+    returnVal->pitch = rawPitch*0.01;
+
+    rawYaw = *( (S16*) (rxBuffer + 4) );
+    returnVal->yaw = rawYaw*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractEstimDataTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawIgrfMagX;
+    S16 rawIgrfMagY;
+    S16 rawIgrfMagZ;
+    S16 rawModelSunX;
+    S16 rawModelSunY;
+    S16 rawModelSunZ;
+    S16 rawEstimGyroBiasX;
+    S16 rawEstimGyroBiasY;
+    S16 rawEstimGyroBiasZ;
+    S16 rawInnovX;
+    S16 rawInnovY;
+    S16 rawInnovZ;
+    S16 rawQError1;
+    S16 rawQError2;
+    S16 rawQError3;
+    S16 rawQCovar1;
+    S16 rawQCovar2;
+    S16 rawQCovar3;
+    S16 rawRateCovarX;
+    S16 rawRateCovarY;
+    S16 rawRateCovarZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawIgrfMagX = *( (S16*) (rxBuffer + 0) );
+    returnVal->igrfMagX = rawIgrfMagX*0.01;
+
+    rawIgrfMagY = *( (S16*) (rxBuffer + 2) );
+    returnVal->igrfMagY = rawIgrfMagY*0.01;
+
+    rawIgrfMagZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->igrfMagZ = rawIgrfMagZ*0.01;
+
+    rawModelSunX = *( (S16*) (rxBuffer + 6) );
+    returnVal->modelSunX = rawModelSunX/10000.0;
+
+    rawModelSunY = *( (S16*) (rxBuffer + 8) );
+    returnVal->modelSunY = rawModelSunY/10000.0;
+
+    rawModelSunZ = *( (S16*) (rxBuffer + 10) );
+    returnVal->modelSunZ = rawModelSunZ/10000.0;
+
+    rawEstimGyroBiasX = *( (S16*) (rxBuffer + 12) );
+    returnVal->estimGyroBiasX = rawEstimGyroBiasX*0.001;
+
+    rawEstimGyroBiasY = *( (S16*) (rxBuffer + 14) );
+    returnVal->estimGyroBiasY = rawEstimGyroBiasY*0.001;
+
+    rawEstimGyroBiasZ = *( (S16*) (rxBuffer + 16) );
+    returnVal->estimGyroBiasZ = rawEstimGyroBiasZ*0.001;
+
+    rawInnovX = *( (S16*) (rxBuffer + 18) );
+    returnVal->innovX = rawInnovX*0.0001;
+
+    rawInnovY = *( (S16*) (rxBuffer + 20) );
+    returnVal->innovY = rawInnovY*0.0001;
+
+    rawInnovZ = *( (S16*) (rxBuffer + 22) );
+    returnVal->innovZ = rawInnovZ*0.0001;
+
+    rawQError1 = *( (S16*) (rxBuffer + 24) );
+    returnVal->qError1 = rawQError1*0.0001;
+
+    rawQError2 = *( (S16*) (rxBuffer + 26) );
+    returnVal->qError2 = rawQError2*0.0001;
+
+    rawQError3 = *( (S16*) (rxBuffer + 28) );
+    returnVal->qError3 = rawQError3*0.0001;
+
+    rawQCovar1 = *( (S16*) (rxBuffer + 30) );
+    returnVal->qCovar1 = rawQCovar1*0.001;
+
+    rawQCovar2 = *( (S16*) (rxBuffer + 32) );
+    returnVal->qCovar2 = rawQCovar2*0.001;
+
+    rawQCovar3 = *( (S16*) (rxBuffer + 34) );
+    returnVal->qCovar3 = rawQCovar3*0.001;
+
+    rawRateCovarX = *( (S16*) (rxBuffer + 36) );
+    returnVal->rateCovarX = rawRateCovarX*0.001;
+
+    rawRateCovarY = *( (S16*) (rxBuffer + 38) );
+    returnVal->rateCovarY = rawRateCovarY*0.001;
+
+    rawRateCovarZ = *( (S16*) (rxBuffer + 40) );
+    returnVal->rateCovarZ = rawRateCovarZ*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractEstimGyroBiasTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawEstimGyroBiasX;
+    S16 rawEstimGyroBiasY;
+    S16 rawEstimGyroBiasZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawEstimGyroBiasX = *( (S16*) (rxBuffer + 0) );
+    returnVal->estimGyroBiasX = rawEstimGyroBiasX*0.001;
+
+    rawEstimGyroBiasY = *( (S16*) (rxBuffer + 2) );
+    returnVal->estimGyroBiasY = rawEstimGyroBiasY*0.001;
+
+    rawEstimGyroBiasZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->estimGyroBiasZ = rawEstimGyroBiasZ*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractEstimParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->magRateNoise = *((F32*)(rxBuffer + 0));
+
+    returnVal->ekfSysNoise = *((F32*)(rxBuffer + 4));
+
+    returnVal->cssNoise = *((F32*)(rxBuffer + 8));
+
+    returnVal->sunNoise = *((F32*)(rxBuffer + 12));
+
+    returnVal->nadirNoise = *((F32*)(rxBuffer + 16));
+
+    returnVal->magNoise = *((F32*)(rxBuffer + 20));
+
+    returnVal->starNoise = *((F32*)(rxBuffer + 24));
+
+    returnVal->useSunEst = (rxBuffer[28] & 0x01) >> 0;
+
+    returnVal->useNadirEst = (rxBuffer[28] & 0x02) >> 1;
+
+    returnVal->useCssEst = (rxBuffer[28] & 0x04) >> 2;
+
+    returnVal->useStarEst = (rxBuffer[28] & 0x08) >> 3;
+
+    returnVal->terminatorCheck = (rxBuffer[28] & 0x10) >> 4;
+
+    returnVal->autoRecoverMtm = (rxBuffer[28] & 0x20) >> 5;
+
+    enumVal = (rxBuffer[28] >> 6) & 3;
+    returnVal->magMode = (CUBEACP_MagModeVal_t) enumVal;
+
+    enumVal = (rxBuffer[29] >> 0) & 3;
+    returnVal->magRawTlm2Selection = (CUBEACP_MagModeVal_t) enumVal;
+
+    returnVal->rateSensorErrorHandling = (rxBuffer[29] & 0x04) >> 2;
+
+    returnVal->wheelPowerOn30sDelay = (rxBuffer[29] & 0x08) >> 3;
+
+
+    returnVal->cam1Cam2Period = *( (U8*) (rxBuffer + 30) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractEstimQuaternionTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->q1 = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->q2 = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->q3 = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractEstimRatesTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    S16 rawRateX;
+    S16 rawRateY;
+    S16 rawRateZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawRateX = *( (S16*) (rxBuffer + 0) );
+    returnVal->rateX = rawRateX*0.01;
+
+    rawRateY = *( (S16*) (rxBuffer + 2) );
+    returnVal->rateY = rawRateY*0.01;
+
+    rawRateZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->rateZ = rawRateZ*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractFineEstimRatesTlm(uint8_t* rxBuffer, CUBEACP_FineEstimRates_t* returnVal)
+{
+    S16 rawRateX;
+    S16 rawRateY;
+    S16 rawRateZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawRateX = *( (S16*) (rxBuffer + 0) );
+    returnVal->rateX = rawRateX*0.001;
+
+    rawRateY = *( (S16*) (rxBuffer + 2) );
+    returnVal->rateY = rawRateY*0.001;
+
+    rawRateZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->rateZ = rawRateZ*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractFineSunVecTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawSunX;
+    S16 rawSunY;
+    S16 rawSunZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawSunX = *( (S16*) (rxBuffer + 0) );
+    returnVal->sunX = rawSunX/10000.0;
+
+    rawSunY = *( (S16*) (rxBuffer + 2) );
+    returnVal->sunY = rawSunY/10000.0;
+
+    rawSunZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->sunZ = rawSunZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractGyroConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawXRateOffset;
+    S16 rawYRateOffset;
+    S16 rawZRateOffset;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->gyro1Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[1];
+    returnVal->gyro2Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[2];
+    returnVal->gyro3Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    rawXRateOffset = *( (S16*) (rxBuffer + 3) );
+    returnVal->xRateOffset = rawXRateOffset*0.001;
+
+    rawYRateOffset = *( (S16*) (rxBuffer + 5) );
+    returnVal->yRateOffset = rawYRateOffset*0.001;
+
+    rawZRateOffset = *( (S16*) (rxBuffer + 7) );
+    returnVal->zRateOffset = rawZRateOffset*0.001;
+
+    returnVal->rateSensorMult = *( (U8*) (rxBuffer + 9) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractImageSaveStatusTlm(uint8_t* rxBuffer, CUBEACP_ImageSaveStatus_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->percentageComplete = *( (U8*) (rxBuffer + 0) );
+
+    enumVal = rxBuffer[1];
+    returnVal->status = (CUBEACP_ImSaveStatus_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractInertialPointReferenceTlm(uint8_t* rxBuffer, CUBEACP_InertialPointReference_t* returnVal)
+{
+    S16 rawInertialRefX;
+    S16 rawInertialRefY;
+    S16 rawInertialRefZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawInertialRefX = *( (S16*) (rxBuffer + 0) );
+    returnVal->inertialRefX = rawInertialRefX/10000.0;
+
+    rawInertialRefY = *( (S16*) (rxBuffer + 2) );
+    returnVal->inertialRefY = rawInertialRefY/10000.0;
+
+    rawInertialRefZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->inertialRefZ = rawInertialRefZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractInnovationVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawInnovX;
+    S16 rawInnovY;
+    S16 rawInnovZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawInnovX = *( (S16*) (rxBuffer + 0) );
+    returnVal->innovX = rawInnovX*0.0001;
+
+    rawInnovY = *( (S16*) (rxBuffer + 2) );
+    returnVal->innovY = rawInnovY*0.0001;
+
+    rawInnovZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->innovZ = rawInnovZ*0.0001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractLogSdConfig1Tlm(uint8_t* rxBuffer, CUBEACP_LogSdConfig1_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    memcpy(returnVal->logSelection, rxBuffer + 0, 10);
+
+    returnVal->period = *( (U16*) (rxBuffer + 10) );
+
+    enumVal = rxBuffer[12];
+    returnVal->destination = (CUBEACP_SdLogSelect_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractLogSdConfig2Tlm(uint8_t* rxBuffer, CUBEACP_LogSdConfig2_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    memcpy(returnVal->logSelection, rxBuffer + 0, 10);
+
+    returnVal->period = *( (U16*) (rxBuffer + 10) );
+
+    enumVal = rxBuffer[12];
+    returnVal->destination = (CUBEACP_SdLogSelect_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractLogUartConfigTlm(uint8_t* rxBuffer, CUBEACP_LogUartConfig_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    memcpy(returnVal->selection, rxBuffer + 0, 10);
+
+    returnVal->period = *( (U16*) (rxBuffer + 10) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractMagConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawMagmAngle1;
+    S16 rawMagmAngle2;
+    S16 rawMagmAngle3;
+    S16 rawMagmOffset1;
+    S16 rawMagmOffset2;
+    S16 rawMagmOffset3;
+    S16 rawMagmSens11;
+    S16 rawMagmSens22;
+    S16 rawMagmSens33;
+    S16 rawMagmSens12;
+    S16 rawMagmSens13;
+    S16 rawMagmSens21;
+    S16 rawMagmSens23;
+    S16 rawMagmSens31;
+    S16 rawMagmSens32;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawMagmAngle1 = *( (S16*) (rxBuffer + 0) );
+    returnVal->magmAngle1 = rawMagmAngle1*0.01;
+
+    rawMagmAngle2 = *( (S16*) (rxBuffer + 2) );
+    returnVal->magmAngle2 = rawMagmAngle2*0.01;
+
+    rawMagmAngle3 = *( (S16*) (rxBuffer + 4) );
+    returnVal->magmAngle3 = rawMagmAngle3*0.01;
+
+    rawMagmOffset1 = *( (S16*) (rxBuffer + 6) );
+    returnVal->magmOffset1 = rawMagmOffset1*0.001;
+
+    rawMagmOffset2 = *( (S16*) (rxBuffer + 8) );
+    returnVal->magmOffset2 = rawMagmOffset2*0.001;
+
+    rawMagmOffset3 = *( (S16*) (rxBuffer + 10) );
+    returnVal->magmOffset3 = rawMagmOffset3*0.001;
+
+    rawMagmSens11 = *( (S16*) (rxBuffer + 12) );
+    returnVal->magmSens11 = rawMagmSens11*0.001;
+
+    rawMagmSens22 = *( (S16*) (rxBuffer + 14) );
+    returnVal->magmSens22 = rawMagmSens22*0.001;
+
+    rawMagmSens33 = *( (S16*) (rxBuffer + 16) );
+    returnVal->magmSens33 = rawMagmSens33*0.001;
+
+    rawMagmSens12 = *( (S16*) (rxBuffer + 18) );
+    returnVal->magmSens12 = rawMagmSens12*0.001;
+
+    rawMagmSens13 = *( (S16*) (rxBuffer + 20) );
+    returnVal->magmSens13 = rawMagmSens13*0.001;
+
+    rawMagmSens21 = *( (S16*) (rxBuffer + 22) );
+    returnVal->magmSens21 = rawMagmSens21*0.001;
+
+    rawMagmSens23 = *( (S16*) (rxBuffer + 24) );
+    returnVal->magmSens23 = rawMagmSens23*0.001;
+
+    rawMagmSens31 = *( (S16*) (rxBuffer + 26) );
+    returnVal->magmSens31 = rawMagmSens31*0.001;
+
+    rawMagmSens32 = *( (S16*) (rxBuffer + 28) );
+    returnVal->magmSens32 = rawMagmSens32*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractMagFieldTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawMagX;
+    S16 rawMagY;
+    S16 rawMagZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawMagX = *( (S16*) (rxBuffer + 0) );
+    returnVal->magX = rawMagX*0.01;
+
+    rawMagY = *( (S16*) (rxBuffer + 2) );
+    returnVal->magY = rawMagY*0.01;
+
+    rawMagZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->magZ = rawMagZ*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractMagRaw2Tlm(uint8_t* rxBuffer, CUBEACP_MagRaw2_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->magRawX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->magRawY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->magRawZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractMagtorqConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->magtorq1 = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[1];
+    returnVal->magtorq2 = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[2];
+    returnVal->magtorq3 = (CUBEACP_AxisSelect_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractMagTorquerCmdTlm(uint8_t* rxBuffer, CUBEACP_ActuatorCmd_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->torquerCmdX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->torquerCmdY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->torquerCmdZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractModelMagVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawIgrfMagX;
+    S16 rawIgrfMagY;
+    S16 rawIgrfMagZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawIgrfMagX = *( (S16*) (rxBuffer + 0) );
+    returnVal->igrfMagX = rawIgrfMagX*0.01;
+
+    rawIgrfMagY = *( (S16*) (rxBuffer + 2) );
+    returnVal->igrfMagY = rawIgrfMagY*0.01;
+
+    rawIgrfMagZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->igrfMagZ = rawIgrfMagZ*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractModelSunVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawModelSunX;
+    S16 rawModelSunY;
+    S16 rawModelSunZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawModelSunX = *( (S16*) (rxBuffer + 0) );
+    returnVal->modelSunX = rawModelSunX/10000.0;
+
+    rawModelSunY = *( (S16*) (rxBuffer + 2) );
+    returnVal->modelSunY = rawModelSunY/10000.0;
+
+    rawModelSunZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->modelSunZ = rawModelSunZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractMoITlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->ixx = *((F32*)(rxBuffer + 0));
+
+    returnVal->iyy = *((F32*)(rxBuffer + 4));
+
+    returnVal->izz = *((F32*)(rxBuffer + 8));
+
+    returnVal->ixy = *((F32*)(rxBuffer + 12));
+
+    returnVal->ixz = *((F32*)(rxBuffer + 16));
+
+    returnVal->iyz = *((F32*)(rxBuffer + 20));
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractNadirVecTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawNadirX;
+    S16 rawNadirY;
+    S16 rawNadirZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawNadirX = *( (S16*) (rxBuffer + 0) );
+    returnVal->nadirX = rawNadirX/10000.0;
+
+    rawNadirY = *( (S16*) (rxBuffer + 2) );
+    returnVal->nadirY = rawNadirY/10000.0;
+
+    rawNadirZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->nadirZ = rawNadirZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractOrbitParametersTlm(uint8_t* rxBuffer, CUBEACP_OrbitParameters_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    memcpy(&returnVal->inclination, rxBuffer + 0, 8);
+
+    memcpy(&returnVal->eccentricity, rxBuffer + 8, 8);
+
+    memcpy(&returnVal->raan, rxBuffer + 16, 8);
+
+    memcpy(&returnVal->argPerigee, rxBuffer + 24, 8);
+
+    memcpy(&returnVal->bstar, rxBuffer + 32, 8);
+
+    memcpy(&returnVal->meanMotion, rxBuffer + 40, 8);
+
+    memcpy(&returnVal->meanAnomaly, rxBuffer + 48, 8);
+
+    memcpy(&returnVal->epoch, rxBuffer + 56, 8);
+
+    if ((returnVal->inclination < 0) || (returnVal->inclination > 180))
+        return TlmRangeError;
+
+    if ((returnVal->eccentricity < 0) || (returnVal->eccentricity > 1))
+        return TlmRangeError;
+
+    if ((returnVal->raan < 0) || (returnVal->raan > 360))
+        return TlmRangeError;
+
+    if ((returnVal->argPerigee < 0) || (returnVal->argPerigee > 360))
+        return TlmRangeError;
+
+    if ((returnVal->bstar < 0) || (returnVal->bstar > 1))
+        return TlmRangeError;
+
+    if ((returnVal->meanMotion < 0) || (returnVal->meanMotion > 20))
+        return TlmRangeError;
+
+    if ((returnVal->meanAnomaly < 0) || (returnVal->meanAnomaly > 360))
+        return TlmRangeError;
+
+    if ((returnVal->epoch < 0) || (returnVal->epoch > 100000))
+        return TlmRangeError;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractPositionECEFTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->posEcefX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->posEcefY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->posEcefZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractPositionECITlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    S16 rawPositionX;
+    S16 rawPositionY;
+    S16 rawPositionZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawPositionX = *( (S16*) (rxBuffer + 0) );
+    returnVal->positionX = rawPositionX*0.25;
+
+    rawPositionY = *( (S16*) (rxBuffer + 2) );
+    returnVal->positionY = rawPositionY*0.25;
+
+    rawPositionZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->positionZ = rawPositionZ*0.25;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractPositionLLHTlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    S16 rawLatitude;
+    S16 rawLongitude;
+    U16 rawAltitude;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawLatitude = *( (S16*) (rxBuffer + 0) );
+    returnVal->latitude = rawLatitude*0.01;
+
+    rawLongitude = *( (S16*) (rxBuffer + 2) );
+    returnVal->longitude = rawLongitude*0.01;
+
+    rawAltitude = *( (U16*) (rxBuffer + 4) );
+    returnVal->altitude = rawAltitude*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractQuaternionCovarTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawQCovar1;
+    S16 rawQCovar2;
+    S16 rawQCovar3;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawQCovar1 = *( (S16*) (rxBuffer + 0) );
+    returnVal->qCovar1 = rawQCovar1*0.001;
+
+    rawQCovar2 = *( (S16*) (rxBuffer + 2) );
+    returnVal->qCovar2 = rawQCovar2*0.001;
+
+    rawQCovar3 = *( (S16*) (rxBuffer + 4) );
+    returnVal->qCovar3 = rawQCovar3*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractQuaternionErrVecTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawQError1;
+    S16 rawQError2;
+    S16 rawQError3;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawQError1 = *( (S16*) (rxBuffer + 0) );
+    returnVal->qError1 = rawQError1*0.0001;
+
+    rawQError2 = *( (S16*) (rxBuffer + 2) );
+    returnVal->qError2 = rawQError2*0.0001;
+
+    rawQError3 = *( (S16*) (rxBuffer + 4) );
+    returnVal->qError3 = rawQError3*0.0001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRateCovarTlm(uint8_t* rxBuffer, CUBEACP_EstimData_t* returnVal)
+{
+    S16 rawRateCovarX;
+    S16 rawRateCovarY;
+    S16 rawRateCovarZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawRateCovarX = *( (S16*) (rxBuffer + 0) );
+    returnVal->rateCovarX = rawRateCovarX*0.001;
+
+    rawRateCovarY = *( (S16*) (rxBuffer + 2) );
+    returnVal->rateCovarY = rawRateCovarY*0.001;
+
+    rawRateCovarZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->rateCovarZ = rawRateCovarZ*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRateSensorTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawRateX;
+    S16 rawRateY;
+    S16 rawRateZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawRateX = *( (S16*) (rxBuffer + 0) );
+    returnVal->rateX = rawRateX*0.01;
+
+    rawRateY = *( (S16*) (rxBuffer + 2) );
+    returnVal->rateY = rawRateY*0.01;
+
+    rawRateZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->rateZ = rawRateZ*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawCam1SensTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->cam1RawX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->cam1RawY = *( (S16*) (rxBuffer + 2) );
+
+    enumVal = rxBuffer[4];
+    returnVal->cam1Busy = (CUBEACP_CaptureResult_t) enumVal;
+
+    enumVal = rxBuffer[5];
+    returnVal->cam1Result = (CUBEACP_DetectResult_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawCam2SensTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->cam2RawX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->cam2RawY = *( (S16*) (rxBuffer + 2) );
+
+    enumVal = rxBuffer[4];
+    returnVal->cam2Busy = (CUBEACP_CaptureResult_t) enumVal;
+
+    enumVal = rxBuffer[5];
+    returnVal->cam2Result = (CUBEACP_DetectResult_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawCss1Tlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->cssRaw1 = *( (U8*) (rxBuffer + 0) );
+
+    returnVal->cssRaw2 = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->cssRaw3 = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->cssRaw4 = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->cssRaw5 = *( (U8*) (rxBuffer + 4) );
+
+    returnVal->cssRaw6 = *( (U8*) (rxBuffer + 5) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawCss2Tlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->cssRaw7 = *( (U8*) (rxBuffer + 0) );
+
+    returnVal->cssRaw8 = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->cssRaw9 = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->cssRaw10 = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->magRawX = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawGPSTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal)
+{
+    U8 rawStdDevPosX;
+    U8 rawStdDevPosY;
+    U8 rawStdDevPosZ;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->gpsSolutionStatus = (CUBEACP_GpsSolutionStatus_t) enumVal;
+
+    returnVal->gpsNumSatsTracked = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->gpsNumSatsSolution = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->gpsXYZLogCtr = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->gpsRangeLogCtr = *( (U8*) (rxBuffer + 4) );
+
+    returnVal->gpsResponse = *( (U8*) (rxBuffer + 5) );
+
+    returnVal->gpsWeek = *( (U16*) (rxBuffer + 6) );
+
+    returnVal->gpsTimeMs = *( (U32*) (rxBuffer + 8) );
+
+    returnVal->posEcefX = *( (S32*) (rxBuffer + 12) );
+
+    returnVal->velEcefX = *( (S16*) (rxBuffer + 16) );
+
+    returnVal->posEcefY = *( (S32*) (rxBuffer + 18) );
+
+    returnVal->velEcefY = *( (S16*) (rxBuffer + 22) );
+
+    returnVal->posEcefZ = *( (S32*) (rxBuffer + 24) );
+
+    returnVal->velEcefZ = *( (S16*) (rxBuffer + 28) );
+
+    rawStdDevPosX = *( (U8*) (rxBuffer + 30) );
+    returnVal->stdDevPosX = rawStdDevPosX*0.1;
+
+    rawStdDevPosY = *( (U8*) (rxBuffer + 31) );
+    returnVal->stdDevPosY = rawStdDevPosY*0.1;
+
+    rawStdDevPosZ = *( (U8*) (rxBuffer + 32) );
+    returnVal->stdDevPosZ = rawStdDevPosZ*0.1;
+
+    returnVal->stdDevVelX = *( (U8*) (rxBuffer + 33) );
+
+    returnVal->stdDevVelY = *( (U8*) (rxBuffer + 34) );
+
+    returnVal->stdDevVelZ = *( (U8*) (rxBuffer + 35) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsStatusTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->gpsSolutionStatus = (CUBEACP_GpsSolutionStatus_t) enumVal;
+
+    returnVal->gpsNumSatsTracked = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->gpsNumSatsSolution = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->gpsXYZLogCtr = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->gpsRangeLogCtr = *( (U8*) (rxBuffer + 4) );
+
+    returnVal->gpsResponse = *( (U8*) (rxBuffer + 5) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsTimeTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->gpsWeek = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->gpsTimeMs = *( (U32*) (rxBuffer + 2) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsXTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->posEcefX = *( (S32*) (rxBuffer + 0) );
+
+    returnVal->velEcefX = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsYTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->posEcefY = *( (S32*) (rxBuffer + 0) );
+
+    returnVal->velEcefY = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawGpsZTlm(uint8_t* rxBuffer, CUBEACP_RawGPS_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->posEcefZ = *( (S32*) (rxBuffer + 0) );
+
+    returnVal->velEcefZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawMagnetometerTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->magRawX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->magRawY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->magRawZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawRateTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->rawRateX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->rawRateY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->rawRateZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawSensorTlm(uint8_t* rxBuffer, CUBEACP_RawSensor_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->cam2RawX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->cam2RawY = *( (S16*) (rxBuffer + 2) );
+
+    enumVal = rxBuffer[4];
+    returnVal->cam2Busy = (CUBEACP_CaptureResult_t) enumVal;
+
+    enumVal = rxBuffer[5];
+    returnVal->cam2Result = (CUBEACP_DetectResult_t) enumVal;
+
+    returnVal->cam1RawX = *( (S16*) (rxBuffer + 6) );
+
+    returnVal->cam1RawY = *( (S16*) (rxBuffer + 8) );
+
+    enumVal = rxBuffer[10];
+    returnVal->cam1Busy = (CUBEACP_CaptureResult_t) enumVal;
+
+    enumVal = rxBuffer[11];
+    returnVal->cam1Result = (CUBEACP_DetectResult_t) enumVal;
+
+    returnVal->cssRaw1 = *( (U8*) (rxBuffer + 12) );
+
+    returnVal->cssRaw2 = *( (U8*) (rxBuffer + 13) );
+
+    returnVal->cssRaw3 = *( (U8*) (rxBuffer + 14) );
+
+    returnVal->cssRaw4 = *( (U8*) (rxBuffer + 15) );
+
+    returnVal->cssRaw5 = *( (U8*) (rxBuffer + 16) );
+
+    returnVal->cssRaw6 = *( (U8*) (rxBuffer + 17) );
+
+    returnVal->cssRaw7 = *( (U8*) (rxBuffer + 18) );
+
+    returnVal->cssRaw8 = *( (U8*) (rxBuffer + 19) );
+
+    returnVal->cssRaw9 = *( (U8*) (rxBuffer + 20) );
+
+    returnVal->cssRaw10 = *( (U8*) (rxBuffer + 21) );
+
+    returnVal->magRawX = *( (S16*) (rxBuffer + 22) );
+
+    returnVal->magRawY = *( (S16*) (rxBuffer + 24) );
+
+    returnVal->magRawZ = *( (S16*) (rxBuffer + 26) );
+
+    returnVal->rawRateX = *( (S16*) (rxBuffer + 28) );
+
+    returnVal->rawRateY = *( (S16*) (rxBuffer + 30) );
+
+    returnVal->rawRateZ = *( (S16*) (rxBuffer + 32) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRawStarTrackerTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    S16 rawStarRateX;
+    S16 rawStarRateY;
+    S16 rawStarRateZ;
+    S16 rawStarQbar0;
+    S16 rawStarQbar1;
+    S16 rawStarQbar2;
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->numStarsDetected = *( (U8*) (rxBuffer + 0) );
+
+    returnVal->starImageNoise = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->invalidStars = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->numberOfStarsID = *( (U8*) (rxBuffer + 3) );
+
+    enumVal = rxBuffer[4];
+    returnVal->iDmode = (CUBEACP_StarIDModeVal_t) enumVal;
+
+    returnVal->imageDarkValue = *( (U8*) (rxBuffer + 5) );
+
+    returnVal->imageCaptureSuccess = (rxBuffer[6] & 0x01) >> 0;
+
+    returnVal->detectionSuccess = (rxBuffer[6] & 0x02) >> 1;
+
+    returnVal->identificationSuccess = (rxBuffer[6] & 0x04) >> 2;
+
+    returnVal->attitudeSuccess = (rxBuffer[6] & 0x08) >> 3;
+
+    returnVal->processingTimeError = (rxBuffer[6] & 0x10) >> 4;
+
+    returnVal->trackingModuleEnabled = (rxBuffer[6] & 0x20) >> 5;
+
+    returnVal->predictionEnabled = (rxBuffer[6] & 0x40) >> 6;
+
+    returnVal->commsError = (rxBuffer[6] & 0x80) >> 7;
+
+    returnVal->deltaT = *( (U16*) (rxBuffer + 7) );
+
+    returnVal->s1Conf = *( (U8*) (rxBuffer + 9) );
+
+    returnVal->s2Conf = *( (U8*) (rxBuffer + 10) );
+
+    returnVal->s3Conf = *( (U8*) (rxBuffer + 11) );
+
+    returnVal->magStar1 = *( (U16*) (rxBuffer + 12) );
+
+    returnVal->magStar2 = *( (U16*) (rxBuffer + 14) );
+
+    returnVal->magStar3 = *( (U16*) (rxBuffer + 16) );
+
+    returnVal->catStar1 = *( (U16*) (rxBuffer + 18) );
+
+    returnVal->centXStar1 = *( (S16*) (rxBuffer + 20) );
+
+    returnVal->centYStar1 = *( (S16*) (rxBuffer + 22) );
+
+    returnVal->catStar2 = *( (U16*) (rxBuffer + 24) );
+
+    returnVal->centXStar2 = *( (S16*) (rxBuffer + 26) );
+
+    returnVal->centYStar2 = *( (S16*) (rxBuffer + 28) );
+
+    returnVal->catStar3 = *( (U16*) (rxBuffer + 30) );
+
+    returnVal->centXStar3 = *( (S16*) (rxBuffer + 32) );
+
+    returnVal->centYStar3 = *( (S16*) (rxBuffer + 34) );
+
+    returnVal->capture = *( (U16*) (rxBuffer + 36) );
+
+    returnVal->detection = *( (U16*) (rxBuffer + 38) );
+
+    returnVal->identification = *( (U16*) (rxBuffer + 40) );
+
+    rawStarRateX = *( (S16*) (rxBuffer + 42) );
+    returnVal->starRateX = rawStarRateX/10000.0;
+
+    rawStarRateY = *( (S16*) (rxBuffer + 44) );
+    returnVal->starRateY = rawStarRateY/10000.0;
+
+    rawStarRateZ = *( (S16*) (rxBuffer + 46) );
+    returnVal->starRateZ = rawStarRateZ/10000.0;
+
+    rawStarQbar0 = *( (S16*) (rxBuffer + 48) );
+    returnVal->starQbar0 = rawStarQbar0/10000.0;
+
+    rawStarQbar1 = *( (S16*) (rxBuffer + 50) );
+    returnVal->starQbar1 = rawStarQbar1/10000.0;
+
+    rawStarQbar2 = *( (S16*) (rxBuffer + 52) );
+    returnVal->starQbar2 = rawStarQbar2/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRedMagConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawMredAngle1;
+    S16 rawMredAngle2;
+    S16 rawMredAngle3;
+    S16 rawMredOffset1;
+    S16 rawMredOffset2;
+    S16 rawMredOffset3;
+    S16 rawMredSens11;
+    S16 rawMredSens22;
+    S16 rawMredSens33;
+    S16 rawMredSens12;
+    S16 rawMredSens13;
+    S16 rawMredSens21;
+    S16 rawMredSens23;
+    S16 rawMredSens31;
+    S16 rawMredSens32;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawMredAngle1 = *( (S16*) (rxBuffer + 0) );
+    returnVal->mredAngle1 = rawMredAngle1*0.01;
+
+    rawMredAngle2 = *( (S16*) (rxBuffer + 2) );
+    returnVal->mredAngle2 = rawMredAngle2*0.01;
+
+    rawMredAngle3 = *( (S16*) (rxBuffer + 4) );
+    returnVal->mredAngle3 = rawMredAngle3*0.01;
+
+    rawMredOffset1 = *( (S16*) (rxBuffer + 6) );
+    returnVal->mredOffset1 = rawMredOffset1*0.001;
+
+    rawMredOffset2 = *( (S16*) (rxBuffer + 8) );
+    returnVal->mredOffset2 = rawMredOffset2*0.001;
+
+    rawMredOffset3 = *( (S16*) (rxBuffer + 10) );
+    returnVal->mredOffset3 = rawMredOffset3*0.001;
+
+    rawMredSens11 = *( (S16*) (rxBuffer + 12) );
+    returnVal->mredSens11 = rawMredSens11*0.001;
+
+    rawMredSens22 = *( (S16*) (rxBuffer + 14) );
+    returnVal->mredSens22 = rawMredSens22*0.001;
+
+    rawMredSens33 = *( (S16*) (rxBuffer + 16) );
+    returnVal->mredSens33 = rawMredSens33*0.001;
+
+    rawMredSens12 = *( (S16*) (rxBuffer + 18) );
+    returnVal->mredSens12 = rawMredSens12*0.001;
+
+    rawMredSens13 = *( (S16*) (rxBuffer + 20) );
+    returnVal->mredSens13 = rawMredSens13*0.001;
+
+    rawMredSens21 = *( (S16*) (rxBuffer + 22) );
+    returnVal->mredSens21 = rawMredSens21*0.001;
+
+    rawMredSens23 = *( (S16*) (rxBuffer + 24) );
+    returnVal->mredSens23 = rawMredSens23*0.001;
+
+    rawMredSens31 = *( (S16*) (rxBuffer + 26) );
+    returnVal->mredSens31 = rawMredSens31*0.001;
+
+    rawMredSens32 = *( (S16*) (rxBuffer + 28) );
+    returnVal->mredSens32 = rawMredSens32*0.001;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractRWheelParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->kp2 = *((F32*)(rxBuffer + 0));
+
+    returnVal->kd2 = *((F32*)(rxBuffer + 4));
+
+    returnVal->h_bias = *((F32*)(rxBuffer + 8));
+
+    enumVal = (rxBuffer[12] >> 0) & 127;
+    returnVal->sunPointFacet = (CUBEACP_AxisSelect_t) enumVal;
+
+    returnVal->wheelErrorHandling = (rxBuffer[12] & 0x80) >> 7;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractSpeedCmdTlm(uint8_t* rxBuffer, CUBEACP_ActuatorCmd_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->speedCmdX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->speedCmdY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->speedCmdZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar1BodyTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawStar1BX;
+    S16 rawStar1BY;
+    S16 rawStar1BZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStar1BX = *( (S16*) (rxBuffer + 0) );
+    returnVal->star1BX = rawStar1BX/10000.0;
+
+    rawStar1BY = *( (S16*) (rxBuffer + 2) );
+    returnVal->star1BY = rawStar1BY/10000.0;
+
+    rawStar1BZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->star1BZ = rawStar1BZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar1OrbitTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawStar1OX;
+    S16 rawStar1OY;
+    S16 rawStar1OZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStar1OX = *( (S16*) (rxBuffer + 0) );
+    returnVal->star1OX = rawStar1OX/10000.0;
+
+    rawStar1OY = *( (S16*) (rxBuffer + 2) );
+    returnVal->star1OY = rawStar1OY/10000.0;
+
+    rawStar1OZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->star1OZ = rawStar1OZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar1RawTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->catStar1 = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->centXStar1 = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->centYStar1 = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar2BodyTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawStar2BX;
+    S16 rawStar2BY;
+    S16 rawStar2BZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStar2BX = *( (S16*) (rxBuffer + 0) );
+    returnVal->star2BX = rawStar2BX/10000.0;
+
+    rawStar2BY = *( (S16*) (rxBuffer + 2) );
+    returnVal->star2BY = rawStar2BY/10000.0;
+
+    rawStar2BZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->star2BZ = rawStar2BZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar2OrbitTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawStar2OX;
+    S16 rawStar2OY;
+    S16 rawStar2OZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStar2OX = *( (S16*) (rxBuffer + 0) );
+    returnVal->star2OX = rawStar2OX/10000.0;
+
+    rawStar2OY = *( (S16*) (rxBuffer + 2) );
+    returnVal->star2OY = rawStar2OY/10000.0;
+
+    rawStar2OZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->star2OZ = rawStar2OZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar2RawTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->catStar2 = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->centXStar2 = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->centYStar2 = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar3BodyTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawStar3BX;
+    S16 rawStar3BY;
+    S16 rawStar3BZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStar3BX = *( (S16*) (rxBuffer + 0) );
+    returnVal->star3BX = rawStar3BX/10000.0;
+
+    rawStar3BY = *( (S16*) (rxBuffer + 2) );
+    returnVal->star3BY = rawStar3BY/10000.0;
+
+    rawStar3BZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->star3BZ = rawStar3BZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar3OrbitTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    S16 rawStar3OX;
+    S16 rawStar3OY;
+    S16 rawStar3OZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStar3OX = *( (S16*) (rxBuffer + 0) );
+    returnVal->star3OX = rawStar3OX/10000.0;
+
+    rawStar3OY = *( (S16*) (rxBuffer + 2) );
+    returnVal->star3OY = rawStar3OY/10000.0;
+
+    rawStar3OZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->star3OZ = rawStar3OZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStar3RawTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->catStar3 = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->centXStar3 = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->centYStar3 = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    S16 rawStarAngle1;
+    S16 rawStarAngle2;
+    S16 rawStarAngle3;
+    U8 rawStarErrorMargin;
+    U8 rawStarTrackingMargin;
+    U8 rawStarValidationMargin;
+    U8 rawStarSearchWidth;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStarAngle1 = *( (S16*) (rxBuffer + 0) );
+    returnVal->starAngle1 = rawStarAngle1*0.01;
+
+    rawStarAngle2 = *( (S16*) (rxBuffer + 2) );
+    returnVal->starAngle2 = rawStarAngle2*0.01;
+
+    rawStarAngle3 = *( (S16*) (rxBuffer + 4) );
+    returnVal->starAngle3 = rawStarAngle3*0.01;
+
+    returnVal->starExposure = *( (U16*) (rxBuffer + 6) );
+
+    returnVal->starGain = *( (U16*) (rxBuffer + 8) );
+
+    returnVal->detectionThreshold = *( (U8*) (rxBuffer + 10) );
+
+    returnVal->starThreshold = *( (U8*) (rxBuffer + 11) );
+
+    returnVal->maxStarMatched = *( (U8*) (rxBuffer + 12) );
+
+    returnVal->starTimeoutTime = *( (U16*) (rxBuffer + 13) );
+
+    returnVal->maxStarPixel = *( (U8*) (rxBuffer + 15) );
+
+    returnVal->minStarPixel = *( (U8*) (rxBuffer + 16) );
+
+    rawStarErrorMargin = *( (U8*) (rxBuffer + 17) );
+    returnVal->starErrorMargin = rawStarErrorMargin*0.01;
+
+    returnVal->starDelayTime = *( (U16*) (rxBuffer + 18) );
+
+    returnVal->starCentX = *((F32*)(rxBuffer + 20));
+
+    returnVal->starCentY = *((F32*)(rxBuffer + 24));
+
+    returnVal->starFocal = *((F32*)(rxBuffer + 28));
+
+    returnVal->starLensK1 = *((F32*)(rxBuffer + 32));
+
+    returnVal->starLensK2 = *((F32*)(rxBuffer + 36));
+
+    returnVal->starLensP1 = *((F32*)(rxBuffer + 40));
+
+    returnVal->starLensP2 = *((F32*)(rxBuffer + 44));
+
+    returnVal->starWindowWidth = *( (U8*) (rxBuffer + 48) );
+
+    rawStarTrackingMargin = *( (U8*) (rxBuffer + 49) );
+    returnVal->starTrackingMargin = rawStarTrackingMargin/100.0;
+
+    rawStarValidationMargin = *( (U8*) (rxBuffer + 50) );
+    returnVal->starValidationMargin = rawStarValidationMargin/100.0;
+
+    returnVal->starModuleEnable = (rxBuffer[51] & 0x01) >> 0;
+
+    returnVal->starLocationPredictionEnable = (rxBuffer[51] & 0x02) >> 1;
+
+
+    rawStarSearchWidth = *( (U8*) (rxBuffer + 52) );
+    returnVal->starSearchWidth = rawStarSearchWidth/5.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarEstimQTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    S16 rawStarQbar0;
+    S16 rawStarQbar1;
+    S16 rawStarQbar2;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStarQbar0 = *( (S16*) (rxBuffer + 0) );
+    returnVal->starQbar0 = rawStarQbar0/10000.0;
+
+    rawStarQbar1 = *( (S16*) (rxBuffer + 2) );
+    returnVal->starQbar1 = rawStarQbar1/10000.0;
+
+    rawStarQbar2 = *( (S16*) (rxBuffer + 4) );
+    returnVal->starQbar2 = rawStarQbar2/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarEstimRateTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    S16 rawStarRateX;
+    S16 rawStarRateY;
+    S16 rawStarRateZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawStarRateX = *( (S16*) (rxBuffer + 0) );
+    returnVal->starRateX = rawStarRateX/10000.0;
+
+    rawStarRateY = *( (S16*) (rxBuffer + 2) );
+    returnVal->starRateY = rawStarRateY/10000.0;
+
+    rawStarRateZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->starRateZ = rawStarRateZ/10000.0;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarMagnitudeTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->magStar1 = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->magStar2 = *( (U16*) (rxBuffer + 2) );
+
+    returnVal->magStar3 = *( (U16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarPerformance1Tlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->numStarsDetected = *( (U8*) (rxBuffer + 0) );
+
+    returnVal->starImageNoise = *( (U8*) (rxBuffer + 1) );
+
+    returnVal->invalidStars = *( (U8*) (rxBuffer + 2) );
+
+    returnVal->numberOfStarsID = *( (U8*) (rxBuffer + 3) );
+
+    enumVal = rxBuffer[4];
+    returnVal->iDmode = (CUBEACP_StarIDModeVal_t) enumVal;
+
+    returnVal->imageDarkValue = *( (U8*) (rxBuffer + 5) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarPerformance2Tlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->imageCaptureSuccess = (rxBuffer[0] & 0x01) >> 0;
+
+    returnVal->detectionSuccess = (rxBuffer[0] & 0x02) >> 1;
+
+    returnVal->identificationSuccess = (rxBuffer[0] & 0x04) >> 2;
+
+    returnVal->attitudeSuccess = (rxBuffer[0] & 0x08) >> 3;
+
+    returnVal->processingTimeError = (rxBuffer[0] & 0x10) >> 4;
+
+    returnVal->trackingModuleEnabled = (rxBuffer[0] & 0x20) >> 5;
+
+    returnVal->predictionEnabled = (rxBuffer[0] & 0x40) >> 6;
+
+    returnVal->commsError = (rxBuffer[0] & 0x80) >> 7;
+
+    returnVal->deltaT = *( (U16*) (rxBuffer + 1) );
+
+    returnVal->s1Conf = *( (U8*) (rxBuffer + 3) );
+
+    returnVal->s2Conf = *( (U8*) (rxBuffer + 4) );
+
+    returnVal->s3Conf = *( (U8*) (rxBuffer + 5) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractStarTimingTlm(uint8_t* rxBuffer, CUBEACP_RawStarTracker_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->capture = *( (U16*) (rxBuffer + 0) );
+
+    returnVal->detection = *( (U16*) (rxBuffer + 2) );
+
+    returnVal->identification = *( (U16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractTrackingParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->kp3 = *((F32*)(rxBuffer + 0));
+
+    returnVal->kd3 = *((F32*)(rxBuffer + 4));
+
+    returnVal->ki3 = *((F32*)(rxBuffer + 8));
+
+    enumVal = rxBuffer[12];
+    returnVal->targetTrackFacet = (CUBEACP_AxisSelect_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractUserConEstParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    memcpy(returnVal->userConSettings, rxBuffer + 0, 48);
+
+    memcpy(returnVal->userEstSettings, rxBuffer + 48, 48);
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractVelocityECITlm(uint8_t* rxBuffer, CUBEACP_AdcsState_t* returnVal)
+{
+    S16 rawVelocityX;
+    S16 rawVelocityY;
+    S16 rawVelocityZ;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawVelocityX = *( (S16*) (rxBuffer + 0) );
+    returnVal->velocityX = rawVelocityX*0.25;
+
+    rawVelocityY = *( (S16*) (rxBuffer + 2) );
+    returnVal->velocityY = rawVelocityY*0.25;
+
+    rawVelocityZ = *( (S16*) (rxBuffer + 4) );
+    returnVal->velocityZ = rawVelocityZ*0.25;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractWheelConfigTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    uint8_t enumVal;
+
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    enumVal = rxBuffer[0];
+    returnVal->rW1Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[1];
+    returnVal->rW2Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[2];
+    returnVal->rW3Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    enumVal = rxBuffer[3];
+    returnVal->rW4Conf = (CUBEACP_AxisSelect_t) enumVal;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractWheelCurrentsTlm(uint8_t* rxBuffer, CUBEACP_AdcsPowerMeasure_t* returnVal)
+{
+    U16 rawWheel1Current;
+    U16 rawWheel2Current;
+    U16 rawWheel3Current;
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    rawWheel1Current = *( (U16*) (rxBuffer + 0) );
+    returnVal->wheel1Current = rawWheel1Current*0.01;
+
+    rawWheel2Current = *( (U16*) (rxBuffer + 2) );
+    returnVal->wheel2Current = rawWheel2Current*0.01;
+
+    rawWheel3Current = *( (U16*) (rxBuffer + 4) );
+    returnVal->wheel3Current = rawWheel3Current*0.01;
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractWheelSpeedTlm(uint8_t* rxBuffer, CUBEACP_AdcsMeasure_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->speedX = *( (S16*) (rxBuffer + 0) );
+
+    returnVal->speedY = *( (S16*) (rxBuffer + 2) );
+
+    returnVal->speedZ = *( (S16*) (rxBuffer + 4) );
+
+    return CubeLibOk;
+}
+
+CUBEADCS_Result_t CUBEACP_ExtractYWheelParamsTlm(uint8_t* rxBuffer, CUBEACP_AdcsConfig_t* returnVal)
+{
+    if (returnVal == 0)
+        return PointerIsNull;
+
+    returnVal->kh = *((F32*)(rxBuffer + 0));
+
+    returnVal->kn = *((F32*)(rxBuffer + 4));
+
+    returnVal->kp1 = *((F32*)(rxBuffer + 8));
+
+    returnVal->kd1 = *((F32*)(rxBuffer + 12));
+
+    returnVal->h_ref = *((F32*)(rxBuffer + 16));
+
+    return CubeLibOk;
+}
+
+
+uint16_t CUBEACP_FormatAdcsConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 20;
+
+    tcBuffer[1] = 
+        (setVal->magtorq1 << 0);
+    tcBuffer[2] = 
+        (setVal->magtorq2 << 0);
+    tcBuffer[3] = 
+        (setVal->magtorq3 << 0);
+    tcBuffer[4] = 
+        (setVal->rW1Conf << 0);
+    tcBuffer[5] = 
+        (setVal->rW2Conf << 0);
+    tcBuffer[6] = 
+        (setVal->rW3Conf << 0);
+    tcBuffer[7] = 
+        (setVal->rW4Conf << 0);
+    tcBuffer[8] = 
+        (setVal->gyro1Conf << 0);
+    tcBuffer[9] = 
+        (setVal->gyro2Conf << 0);
+    tcBuffer[10] = 
+        (setVal->gyro3Conf << 0);
+    tcBuffer[18] = 
+        (setVal->css1Conf << 0);
+    tcBuffer[19] = 
+        (setVal->css2Conf << 0);
+    tcBuffer[20] = 
+        (setVal->css3Conf << 0);
+    tcBuffer[21] = 
+        (setVal->css4Conf << 0);
+    tcBuffer[22] = 
+        (setVal->css5Conf << 0);
+    tcBuffer[23] = 
+        (setVal->css6Conf << 0);
+    tcBuffer[24] = 
+        (setVal->css7Conf << 0);
+    tcBuffer[25] = 
+        (setVal->css8Conf << 0);
+    tcBuffer[26] = 
+        (setVal->css9Conf << 0);
+    tcBuffer[27] = 
+        (setVal->css10Conf << 0);
+    tcBuffer[46] = 
+        (setVal->cam1AutoAdj << 0);
+    tcBuffer[60] = 
+        (setVal->cam2AutoAdj << 0);
+    tcBuffer[262] = 
+        (setVal->starModuleEnable << 0) + 
+        (setVal->starLocationPredictionEnable << 1);
+    tcBuffer[310] = 
+        (setVal->sunPointFacet << 0) + 
+        (setVal->wheelErrorHandling << 7);
+    tcBuffer[323] = 
+        (setVal->targetTrackFacet << 0);
+    tcBuffer[376] = 
+        (setVal->useSunEst << 0) + 
+        (setVal->useNadirEst << 1) + 
+        (setVal->useCssEst << 2) + 
+        (setVal->useStarEst << 3) + 
+        (setVal->terminatorCheck << 4) + 
+        (setVal->autoRecoverMtm << 5) + 
+        (setVal->magMode << 6);
+    tcBuffer[377] = 
+        (setVal->magRawTlm2Selection << 0) + 
+        (setVal->rateSensorErrorHandling << 2) + 
+        (setVal->wheelPowerOn30sDelay << 3);
+    tcBuffer[392] = 
+        (setVal->asgp4Filter << 0);
+    *( (S16*)(tcBuffer + 11) ) = (S16) round(setVal->xRateOffset*1000.0);
+    *( (S16*)(tcBuffer + 13) ) = (S16) round(setVal->yRateOffset*1000.0);
+    *( (S16*)(tcBuffer + 15) ) = (S16) round(setVal->zRateOffset*1000.0);
+    *( (U8*)(tcBuffer + 17) ) = setVal->rateSensorMult;
+    *( (U8*)(tcBuffer + 28) ) = (U8) round(setVal->css1Scale*100.0);
+    *( (U8*)(tcBuffer + 29) ) = (U8) round(setVal->css2Scale*100.0);
+    *( (U8*)(tcBuffer + 30) ) = (U8) round(setVal->css3Scale*100.0);
+    *( (U8*)(tcBuffer + 31) ) = (U8) round(setVal->css4Scale*100.0);
+    *( (U8*)(tcBuffer + 32) ) = (U8) round(setVal->css5Scale*100.0);
+    *( (U8*)(tcBuffer + 33) ) = (U8) round(setVal->css6Scale*100.0);
+    *( (U8*)(tcBuffer + 34) ) = (U8) round(setVal->css7Scale*100.0);
+    *( (U8*)(tcBuffer + 35) ) = (U8) round(setVal->css8Scale*100.0);
+    *( (U8*)(tcBuffer + 36) ) = (U8) round(setVal->css9Scale*100.0);
+    *( (U8*)(tcBuffer + 37) ) = (U8) round(setVal->css10Scale*100.0);
+    *( (U8*)(tcBuffer + 38) ) = setVal->cssMinimum;
+    *( (S16*)(tcBuffer + 39) ) = (S16) round(setVal->cam1Angle1*100.0);
+    *( (S16*)(tcBuffer + 41) ) = (S16) round(setVal->cam1Angle2*100.0);
+    *( (S16*)(tcBuffer + 43) ) = (S16) round(setVal->cam1Angle3*100.0);
+    *( (U8*)(tcBuffer + 45) ) = setVal->cam1Threshold;
+    *( (U16*)(tcBuffer + 47) ) = setVal->cam1Exposure;
+    *( (U16*)(tcBuffer + 49) ) = (U16) round(setVal->cam1BoreX*100.0);
+    *( (U16*)(tcBuffer + 51) ) = (U16) round(setVal->cam1BoreY*100.0);
+    *( (S16*)(tcBuffer + 53) ) = (S16) round(setVal->cam2Angle1*100.0);
+    *( (S16*)(tcBuffer + 55) ) = (S16) round(setVal->cam2Angle2*100.0);
+    *( (S16*)(tcBuffer + 57) ) = (S16) round(setVal->cam2Angle3*100.0);
+    *( (U8*)(tcBuffer + 59) ) = setVal->cam2Threshold;
+    *( (U16*)(tcBuffer + 61) ) = setVal->cam2Exposure;
+    *( (U16*)(tcBuffer + 63) ) = (U16) round(setVal->cam2BoreX*100.0);
+    *( (U16*)(tcBuffer + 65) ) = (U16) round(setVal->cam2BoreY*100.0);
+    *( (U8*)(tcBuffer + 67) ) = setVal->nadirMaxDeviationPercentage;
+    *( (U8*)(tcBuffer + 68) ) = setVal->nadirMaxBadEdges;
+    *( (U8*)(tcBuffer + 69) ) = setVal->nadirMaxRadius;
+    *( (U8*)(tcBuffer + 70) ) = setVal->nadirMinRadius;
+    *( (U16*)(tcBuffer + 71) ) = setVal->cam1MaskArea1Xmin;
+    *( (U16*)(tcBuffer + 73) ) = setVal->cam1MaskArea1Xmax;
+    *( (U16*)(tcBuffer + 75) ) = setVal->cam1MaskArea1Ymin;
+    *( (U16*)(tcBuffer + 77) ) = setVal->cam1MaskArea1Ymax;
+    *( (U16*)(tcBuffer + 79) ) = setVal->cam1MaskArea2Xmin;
+    *( (U16*)(tcBuffer + 81) ) = setVal->cam1MaskArea2Xmax;
+    *( (U16*)(tcBuffer + 83) ) = setVal->cam1MaskArea2Ymin;
+    *( (U16*)(tcBuffer + 85) ) = setVal->cam1MaskArea2Ymax;
+    *( (U16*)(tcBuffer + 87) ) = setVal->cam1MaskArea3Xmin;
+    *( (U16*)(tcBuffer + 89) ) = setVal->cam1MaskArea3Xmax;
+    *( (U16*)(tcBuffer + 91) ) = setVal->cam1MaskArea3Ymin;
+    *( (U16*)(tcBuffer + 93) ) = setVal->cam1MaskArea3Ymax;
+    *( (U16*)(tcBuffer + 95) ) = setVal->cam1MaskArea4Xmin;
+    *( (U16*)(tcBuffer + 97) ) = setVal->cam1MaskArea4Xmax;
+    *( (U16*)(tcBuffer + 99) ) = setVal->cam1MaskArea4Ymin;
+    *( (U16*)(tcBuffer + 101) ) = setVal->cam1MaskArea4Ymax;
+    *( (U16*)(tcBuffer + 103) ) = setVal->cam1MaskArea5Xmin;
+    *( (U16*)(tcBuffer + 105) ) = setVal->cam1MaskArea5Xmax;
+    *( (U16*)(tcBuffer + 107) ) = setVal->cam1MaskArea5Ymin;
+    *( (U16*)(tcBuffer + 109) ) = setVal->cam1MaskArea5Ymax;
+    *( (U16*)(tcBuffer + 111) ) = setVal->cam2MaskArea1Xmin;
+    *( (U16*)(tcBuffer + 113) ) = setVal->cam2MaskArea1Xmax;
+    *( (U16*)(tcBuffer + 115) ) = setVal->cam2MaskArea1Ymin;
+    *( (U16*)(tcBuffer + 117) ) = setVal->cam2MaskArea1Ymax;
+    *( (U16*)(tcBuffer + 119) ) = setVal->cam2MaskArea2Xmin;
+    *( (U16*)(tcBuffer + 121) ) = setVal->cam2MaskArea2Xmax;
+    *( (U16*)(tcBuffer + 123) ) = setVal->cam2MaskArea2Ymin;
+    *( (U16*)(tcBuffer + 125) ) = setVal->cam2MaskArea2Ymax;
+    *( (U16*)(tcBuffer + 127) ) = setVal->cam2MaskArea3Xmin;
+    *( (U16*)(tcBuffer + 129) ) = setVal->cam2MaskArea3Xmax;
+    *( (U16*)(tcBuffer + 131) ) = setVal->cam2MaskArea3Ymin;
+    *( (U16*)(tcBuffer + 133) ) = setVal->cam2MaskArea3Ymax;
+    *( (U16*)(tcBuffer + 135) ) = setVal->cam2MaskArea4Xmin;
+    *( (U16*)(tcBuffer + 137) ) = setVal->cam2MaskArea4Xmax;
+    *( (U16*)(tcBuffer + 139) ) = setVal->cam2MaskArea4Ymin;
+    *( (U16*)(tcBuffer + 141) ) = setVal->cam2MaskArea4Ymax;
+    *( (U16*)(tcBuffer + 143) ) = setVal->cam2MaskArea5Xmin;
+    *( (U16*)(tcBuffer + 145) ) = setVal->cam2MaskArea5Xmax;
+    *( (U16*)(tcBuffer + 147) ) = setVal->cam2MaskArea5Ymin;
+    *( (U16*)(tcBuffer + 149) ) = setVal->cam2MaskArea5Ymax;
+    *( (S16*)(tcBuffer + 151) ) = (S16) round(setVal->magmAngle1*100.0);
+    *( (S16*)(tcBuffer + 153) ) = (S16) round(setVal->magmAngle2*100.0);
+    *( (S16*)(tcBuffer + 155) ) = (S16) round(setVal->magmAngle3*100.0);
+    *( (S16*)(tcBuffer + 157) ) = (S16) round(setVal->magmOffset1*1000.0);
+    *( (S16*)(tcBuffer + 159) ) = (S16) round(setVal->magmOffset2*1000.0);
+    *( (S16*)(tcBuffer + 161) ) = (S16) round(setVal->magmOffset3*1000.0);
+    *( (S16*)(tcBuffer + 163) ) = (S16) round(setVal->magmSens11*1000.0);
+    *( (S16*)(tcBuffer + 165) ) = (S16) round(setVal->magmSens22*1000.0);
+    *( (S16*)(tcBuffer + 167) ) = (S16) round(setVal->magmSens33*1000.0);
+    *( (S16*)(tcBuffer + 169) ) = (S16) round(setVal->magmSens12*1000.0);
+    *( (S16*)(tcBuffer + 171) ) = (S16) round(setVal->magmSens13*1000.0);
+    *( (S16*)(tcBuffer + 173) ) = (S16) round(setVal->magmSens21*1000.0);
+    *( (S16*)(tcBuffer + 175) ) = (S16) round(setVal->magmSens23*1000.0);
+    *( (S16*)(tcBuffer + 177) ) = (S16) round(setVal->magmSens31*1000.0);
+    *( (S16*)(tcBuffer + 179) ) = (S16) round(setVal->magmSens32*1000.0);
+    *( (S16*)(tcBuffer + 181) ) = (S16) round(setVal->mredAngle1*100.0);
+    *( (S16*)(tcBuffer + 183) ) = (S16) round(setVal->mredAngle2*100.0);
+    *( (S16*)(tcBuffer + 185) ) = (S16) round(setVal->mredAngle3*100.0);
+    *( (S16*)(tcBuffer + 187) ) = (S16) round(setVal->mredOffset1*1000.0);
+    *( (S16*)(tcBuffer + 189) ) = (S16) round(setVal->mredOffset2*1000.0);
+    *( (S16*)(tcBuffer + 191) ) = (S16) round(setVal->mredOffset3*1000.0);
+    *( (S16*)(tcBuffer + 193) ) = (S16) round(setVal->mredSens11*1000.0);
+    *( (S16*)(tcBuffer + 195) ) = (S16) round(setVal->mredSens22*1000.0);
+    *( (S16*)(tcBuffer + 197) ) = (S16) round(setVal->mredSens33*1000.0);
+    *( (S16*)(tcBuffer + 199) ) = (S16) round(setVal->mredSens12*1000.0);
+    *( (S16*)(tcBuffer + 201) ) = (S16) round(setVal->mredSens13*1000.0);
+    *( (S16*)(tcBuffer + 203) ) = (S16) round(setVal->mredSens21*1000.0);
+    *( (S16*)(tcBuffer + 205) ) = (S16) round(setVal->mredSens23*1000.0);
+    *( (S16*)(tcBuffer + 207) ) = (S16) round(setVal->mredSens31*1000.0);
+    *( (S16*)(tcBuffer + 209) ) = (S16) round(setVal->mredSens32*1000.0);
+    *( (S16*)(tcBuffer + 211) ) = (S16) round(setVal->starAngle1*100.0);
+    *( (S16*)(tcBuffer + 213) ) = (S16) round(setVal->starAngle2*100.0);
+    *( (S16*)(tcBuffer + 215) ) = (S16) round(setVal->starAngle3*100.0);
+    *( (U16*)(tcBuffer + 217) ) = setVal->starExposure;
+    *( (U16*)(tcBuffer + 219) ) = setVal->starGain;
+    *( (U8*)(tcBuffer + 221) ) = setVal->detectionThreshold;
+    *( (U8*)(tcBuffer + 222) ) = setVal->starThreshold;
+    *( (U8*)(tcBuffer + 223) ) = setVal->maxStarMatched;
+    *( (U16*)(tcBuffer + 224) ) = setVal->starTimeoutTime;
+    *( (U8*)(tcBuffer + 226) ) = setVal->maxStarPixel;
+    *( (U8*)(tcBuffer + 227) ) = setVal->minStarPixel;
+    *( (U8*)(tcBuffer + 228) ) = (U8) round(setVal->starErrorMargin*100.0);
+    *( (U16*)(tcBuffer + 229) ) = setVal->starDelayTime;
+    *( (F32*)(tcBuffer + 231) ) = setVal->starCentX;
+    *( (F32*)(tcBuffer + 235) ) = setVal->starCentY;
+    *( (F32*)(tcBuffer + 239) ) = setVal->starFocal;
+    *( (F32*)(tcBuffer + 243) ) = setVal->starLensK1;
+    *( (F32*)(tcBuffer + 247) ) = setVal->starLensK2;
+    *( (F32*)(tcBuffer + 251) ) = setVal->starLensP1;
+    *( (F32*)(tcBuffer + 255) ) = setVal->starLensP2;
+    *( (U8*)(tcBuffer + 259) ) = setVal->starWindowWidth;
+    *( (U8*)(tcBuffer + 260) ) = (U8) round(setVal->starTrackingMargin*100.0);
+    *( (U8*)(tcBuffer + 261) ) = (U8) round(setVal->starValidationMargin*100.0);
+    *( (U8*)(tcBuffer + 263) ) = (U8) round(setVal->starSearchWidth*5.0);
+    *( (F32*)(tcBuffer + 264) ) = setVal->ks;
+    *( (F32*)(tcBuffer + 268) ) = setVal->kd;
+    *( (S16*)(tcBuffer + 272) ) = (S16) round(setVal->wy_ref*1000.0);
+    *( (F32*)(tcBuffer + 274) ) = setVal->kdf;
+    *( (F32*)(tcBuffer + 278) ) = setVal->kh;
+    *( (F32*)(tcBuffer + 282) ) = setVal->kn;
+    *( (F32*)(tcBuffer + 286) ) = setVal->kp1;
+    *( (F32*)(tcBuffer + 290) ) = setVal->kd1;
+    *( (F32*)(tcBuffer + 294) ) = setVal->h_ref;
+    *( (F32*)(tcBuffer + 298) ) = setVal->kp2;
+    *( (F32*)(tcBuffer + 302) ) = setVal->kd2;
+    *( (F32*)(tcBuffer + 306) ) = setVal->h_bias;
+    *( (F32*)(tcBuffer + 311) ) = setVal->kp3;
+    *( (F32*)(tcBuffer + 315) ) = setVal->kd3;
+    *( (F32*)(tcBuffer + 319) ) = setVal->ki3;
+    *( (F32*)(tcBuffer + 324) ) = setVal->ixx;
+    *( (F32*)(tcBuffer + 328) ) = setVal->iyy;
+    *( (F32*)(tcBuffer + 332) ) = setVal->izz;
+    *( (F32*)(tcBuffer + 336) ) = setVal->ixy;
+    *( (F32*)(tcBuffer + 340) ) = setVal->ixz;
+    *( (F32*)(tcBuffer + 344) ) = setVal->iyz;
+    *( (F32*)(tcBuffer + 348) ) = setVal->magRateNoise;
+    *( (F32*)(tcBuffer + 352) ) = setVal->ekfSysNoise;
+    *( (F32*)(tcBuffer + 356) ) = setVal->cssNoise;
+    *( (F32*)(tcBuffer + 360) ) = setVal->sunNoise;
+    *( (F32*)(tcBuffer + 364) ) = setVal->nadirNoise;
+    *( (F32*)(tcBuffer + 368) ) = setVal->magNoise;
+    *( (F32*)(tcBuffer + 372) ) = setVal->starNoise;
+    *( (U8*)(tcBuffer + 378) ) = setVal->cam1Cam2Period;
+    *( (U16*)(tcBuffer + 379) ) = (U16) round(setVal->aInclCoeff*1000.0);
+    *( (U16*)(tcBuffer + 381) ) = (U16) round(setVal->aRaanCoeff*1000.0);
+    *( (U16*)(tcBuffer + 383) ) = (U16) round(setVal->aEccCoeff*1000.0);
+    *( (U16*)(tcBuffer + 385) ) = (U16) round(setVal->aArgPerCoeff*1000.0);
+    *( (U16*)(tcBuffer + 387) ) = (U16) round(setVal->aTimeCoeff*1000.0);
+    *( (U16*)(tcBuffer + 389) ) = (U16) round(setVal->aPosCoeff*1000.0);
+    *( (U8*)(tcBuffer + 391) ) = (U8) round(setVal->asgp4MaxPosError*10.0);
+    *( (S32*)(tcBuffer + 393) ) = (S32) round(setVal->asgp4Xp*1E7);
+    *( (S32*)(tcBuffer + 397) ) = (S32) round(setVal->asgp4Yp*1E7);
+    *( (U8*)(tcBuffer + 401) ) = setVal->asgp4GpsRollover;
+    *( (U8*)(tcBuffer + 402) ) = (U8) round(setVal->asgp4PosSdTh*10.0);
+    *( (U8*)(tcBuffer + 403) ) = (U8) round(setVal->asgp4VelSdTh*100.0);
+    *( (U8*)(tcBuffer + 404) ) = setVal->asgp4MinSat;
+    *( (U8*)(tcBuffer + 405) ) = (U8) round(setVal->asgp4TimeGain*100.0);
+    *( (U8*)(tcBuffer + 406) ) = (U8) round(setVal->asgp4MaxLag*100.0);
+    *( (U16*)(tcBuffer + 407) ) = setVal->asgp4MinSamples;
+    memcpy(tcBuffer + 409,setVal->userConSettings,48);
+    memcpy(tcBuffer + 457,setVal->userEstSettings,48);
+
+    return 505;
+}
+
+uint16_t CUBEACP_FormatAdcsEnabledCmd(uint8_t* tcBuffer, CUBEACP_AdcsRunMode_t enabled)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 10;
+
+    tcBuffer[1] = 
+        (enabled << 0);
+
+    return 2;
+}
+
+uint16_t CUBEACP_FormatAdcsPowerCmd(uint8_t* tcBuffer, CUBEACP_AdcsPower_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 11;
+
+    tcBuffer[1] = 
+        (setVal->cubeControlSignalPower << 0) + 
+        (setVal->cubeControlMotorPower << 2) + 
+        (setVal->cubeSense1Power << 4) + 
+        (setVal->cubeSense2Power << 6);
+    tcBuffer[2] = 
+        (setVal->cubeStarPower << 0) + 
+        (setVal->cubeWheel1Power << 2) + 
+        (setVal->cubeWheel2Power << 4) + 
+        (setVal->cubeWheel3Power << 6);
+    tcBuffer[3] = 
+        (setVal->motorPower << 0) + 
+        (setVal->gpsLnaPower << 2);
+
+    return 4;
+}
+
+uint16_t CUBEACP_FormatAdcsSystemConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsSystemConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 30;
+
+    tcBuffer[1] = 
+        (setVal->acpType << 0) + 
+        (setVal->specialControl << 4);
+    tcBuffer[6] = 
+        (setVal->csCam1Type << 0) + 
+        (setVal->csCam2Type << 4);
+    tcBuffer[8] = 
+        (setVal->gpsType << 0) + 
+        (setVal->hasRedMag << 4);
+    tcBuffer[165] = 
+        (setVal->ccsEnablePort << 0) + 
+        (setVal->ccsEnablePin << 4);
+    tcBuffer[166] = 
+        (setVal->ccmEnablePort << 0) + 
+        (setVal->ccmEnablePin << 4);
+    tcBuffer[167] = 
+        (setVal->cccEnablePort << 0) + 
+        (setVal->cccEnablePin << 4);
+    tcBuffer[168] = 
+        (setVal->cSense1EnablePort << 0) + 
+        (setVal->cSense1EnablePin << 4);
+    tcBuffer[169] = 
+        (setVal->cSense2EnablePort << 0) + 
+        (setVal->cSense2EnablePin << 4);
+    tcBuffer[170] = 
+        (setVal->cStarEnablePort << 0) + 
+        (setVal->cStarEnablePin << 4);
+    tcBuffer[171] = 
+        (setVal->cW1EnablePort << 0) + 
+        (setVal->cW1EnablePin << 4);
+    tcBuffer[172] = 
+        (setVal->cW2EnablePort << 0) + 
+        (setVal->cW2EnablePin << 4);
+    tcBuffer[173] = 
+        (setVal->cW3EnablePort << 0) + 
+        (setVal->cW3EnablePin << 4);
+    *( (U8*)(tcBuffer + 2) ) = setVal->ccSignalVer;
+    *( (U8*)(tcBuffer + 3) ) = setVal->ccMotorVer;
+    *( (U8*)(tcBuffer + 4) ) = setVal->cs1Ver;
+    *( (U8*)(tcBuffer + 5) ) = setVal->cs2Ver;
+    *( (U8*)(tcBuffer + 7) ) = setVal->cubeStarVer;
+    *( (F32*)(tcBuffer + 9) ) = setVal->mqx;
+    *( (F32*)(tcBuffer + 13) ) = setVal->mqy;
+    *( (F32*)(tcBuffer + 17) ) = setVal->mqz;
+    *( (F32*)(tcBuffer + 21) ) = setVal->mtTmin;
+    *( (F32*)(tcBuffer + 25) ) = setVal->mtTmax;
+    *( (F32*)(tcBuffer + 29) ) = setVal->nSatX;
+    *( (F32*)(tcBuffer + 33) ) = setVal->nSatY;
+    *( (F32*)(tcBuffer + 37) ) = setVal->nSatZ;
+    *( (F32*)(tcBuffer + 41) ) = setVal->hSatX;
+    *( (F32*)(tcBuffer + 45) ) = setVal->hSatY;
+    *( (F32*)(tcBuffer + 49) ) = setVal->hSatZ;
+    *( (F32*)(tcBuffer + 53) ) = setVal->iwx;
+    *( (F32*)(tcBuffer + 57) ) = setVal->iwy;
+    *( (F32*)(tcBuffer + 61) ) = setVal->iwz;
+    *( (F32*)(tcBuffer + 65) ) = setVal->ndel;
+    *( (F32*)(tcBuffer + 69) ) = setVal->biasX_d1;
+    *( (F32*)(tcBuffer + 73) ) = setVal->biasY_d1;
+    *( (F32*)(tcBuffer + 77) ) = setVal->biasZ_d1;
+    *( (F32*)(tcBuffer + 81) ) = setVal->biasX_d2;
+    *( (F32*)(tcBuffer + 85) ) = setVal->biasY_d2;
+    *( (F32*)(tcBuffer + 89) ) = setVal->biasZ_d2;
+    *( (F32*)(tcBuffer + 93) ) = setVal->sensX_s1;
+    *( (F32*)(tcBuffer + 97) ) = setVal->sensY_s1;
+    *( (F32*)(tcBuffer + 101) ) = setVal->sensZ_s1;
+    *( (F32*)(tcBuffer + 105) ) = setVal->sensX_s2;
+    *( (F32*)(tcBuffer + 109) ) = setVal->sensY_s2;
+    *( (F32*)(tcBuffer + 113) ) = setVal->sensZ_s2;
+    *( (F32*)(tcBuffer + 117) ) = setVal->red_BiasX_d1;
+    *( (F32*)(tcBuffer + 121) ) = setVal->red_BiasY_d1;
+    *( (F32*)(tcBuffer + 125) ) = setVal->red_BiasZ_d1;
+    *( (F32*)(tcBuffer + 129) ) = setVal->red_BiasX_d2;
+    *( (F32*)(tcBuffer + 133) ) = setVal->red_BiasY_d2;
+    *( (F32*)(tcBuffer + 137) ) = setVal->red_BiasZ_d2;
+    *( (F32*)(tcBuffer + 141) ) = setVal->red_SensX_s1;
+    *( (F32*)(tcBuffer + 145) ) = setVal->red_SensY_s1;
+    *( (F32*)(tcBuffer + 149) ) = setVal->red_SensZ_s1;
+    *( (F32*)(tcBuffer + 153) ) = setVal->red_SensX_s2;
+    *( (F32*)(tcBuffer + 157) ) = setVal->red_SensY_s2;
+    *( (F32*)(tcBuffer + 161) ) = setVal->red_SensZ_s2;
+
+    return 174;
+}
+
+uint16_t CUBEACP_FormatAsgp4ModeCmd(uint8_t* tcBuffer, CUBEACP_Asgp4ModeSelect_t asgp4ModeSelection)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 31;
+
+    tcBuffer[1] = 
+        (asgp4ModeSelection << 0);
+
+    return 2;
+}
+
+uint16_t CUBEACP_FormatASgp4ParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 28;
+
+    *( (U16*)(tcBuffer + 1) ) = (U16) round(setVal->aInclCoeff*1000.0);
+    *( (U16*)(tcBuffer + 3) ) = (U16) round(setVal->aRaanCoeff*1000.0);
+    *( (U16*)(tcBuffer + 5) ) = (U16) round(setVal->aEccCoeff*1000.0);
+    *( (U16*)(tcBuffer + 7) ) = (U16) round(setVal->aArgPerCoeff*1000.0);
+    *( (U16*)(tcBuffer + 9) ) = (U16) round(setVal->aTimeCoeff*1000.0);
+    *( (U16*)(tcBuffer + 11) ) = (U16) round(setVal->aPosCoeff*1000.0);
+    *( (U8*)(tcBuffer + 13) ) = (U8) round(setVal->asgp4MaxPosError*10.0);
+    *( (S32*)(tcBuffer + 15) ) = (S32) round(setVal->asgp4Xp*1E7);
+    *( (S32*)(tcBuffer + 19) ) = (S32) round(setVal->asgp4Yp*1E7);
+    *( (U8*)(tcBuffer + 23) ) = setVal->asgp4GpsRollover;
+    *( (U8*)(tcBuffer + 24) ) = (U8) round(setVal->asgp4PosSdTh*10.0);
+    *( (U8*)(tcBuffer + 25) ) = (U8) round(setVal->asgp4VelSdTh*100.0);
+    *( (U8*)(tcBuffer + 26) ) = setVal->asgp4MinSat;
+    *( (U8*)(tcBuffer + 27) ) = (U8) round(setVal->asgp4TimeGain*100.0);
+    *( (U8*)(tcBuffer + 28) ) = (U8) round(setVal->asgp4MaxLag*100.0);
+    *( (U16*)(tcBuffer + 29) ) = setVal->asgp4MinSamples;
+
+    return 31;
+}
+
+uint16_t CUBEACP_FormatAsgp4TriggerCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 32;
+
+
+    return 1;
+}
+
+uint16_t CUBEACP_FormatClearErrorsCmd(uint8_t* tcBuffer, CUBEACP_ClearErrors_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 12;
+
+    tcBuffer[1] = 
+        (setVal->aDCSErrors << 0) + 
+        (setVal->hKErrors << 1);
+
+    return 2;
+}
+
+uint16_t CUBEACP_FormatCmdAttitudeCmd(uint8_t* tcBuffer, CUBEACP_CmdAttitude_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 15;
+
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(setVal->roll*100.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(setVal->pitch*100.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(setVal->yaw*100.0);
+
+    return 7;
+}
+
+uint16_t CUBEACP_FormatCmdTrackingTargetCmd(uint8_t* tcBuffer, F32 longRef, F32 latRef, F32 altRef)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 55;
+
+    *( (F32*)(tcBuffer + 1) ) = longRef;
+    *( (F32*)(tcBuffer + 5) ) = latRef;
+    *( (F32*)(tcBuffer + 9) ) = altRef;
+
+    return 13;
+}
+
+uint16_t CUBEACP_FormatControlModeCmd(uint8_t* tcBuffer, CUBEACP_ControlMode_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 13;
+
+    tcBuffer[1] = 
+        (setVal->controlModeSelection << 0);
+    *( (U16*)(tcBuffer + 2) ) = setVal->timeout;
+
+    return 4;
+}
+
+uint16_t CUBEACP_FormatConvertCmd(uint8_t* tcBuffer, U8 srcFileCtr, U8 qualityFactor, U8 whiteBalance)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 57;
+
+    *( (U8*)(tcBuffer + 1) ) = srcFileCtr;
+    *( (U8*)(tcBuffer + 2) ) = qualityFactor;
+    *( (U8*)(tcBuffer + 3) ) = whiteBalance;
+
+    return 4;
+}
+
+uint16_t CUBEACP_FormatCssConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 24;
+
+    tcBuffer[1] = 
+        (setVal->css1Conf << 0);
+    tcBuffer[2] = 
+        (setVal->css2Conf << 0);
+    tcBuffer[3] = 
+        (setVal->css3Conf << 0);
+    tcBuffer[4] = 
+        (setVal->css4Conf << 0);
+    *( (U8*)(tcBuffer + 11) ) = (U8) round(setVal->css1Scale*100.0);
+    *( (U8*)(tcBuffer + 12) ) = (U8) round(setVal->css2Scale*100.0);
+    *( (U8*)(tcBuffer + 13) ) = (U8) round(setVal->css3Scale*100.0);
+    *( (U8*)(tcBuffer + 14) ) = (U8) round(setVal->css4Scale*100.0);
+    *( (U8*)(tcBuffer + 15) ) = (U8) round(setVal->css5Scale*100.0);
+    *( (U8*)(tcBuffer + 16) ) = (U8) round(setVal->css6Scale*100.0);
+    *( (U8*)(tcBuffer + 17) ) = (U8) round(setVal->css7Scale*100.0);
+    *( (U8*)(tcBuffer + 18) ) = (U8) round(setVal->css8Scale*100.0);
+    *( (U8*)(tcBuffer + 19) ) = (U8) round(setVal->css9Scale*100.0);
+    *( (U8*)(tcBuffer + 20) ) = (U8) round(setVal->css10Scale*100.0);
+    *( (U8*)(tcBuffer + 21) ) = setVal->cssMinimum;
+
+    return 22;
+}
+
+uint16_t CUBEACP_FormatCubeSenseConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 25;
+
+    tcBuffer[8] = 
+        (setVal->cam1AutoAdj << 0);
+    tcBuffer[22] = 
+        (setVal->cam2AutoAdj << 0);
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(setVal->cam1Angle1*100.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(setVal->cam1Angle2*100.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(setVal->cam1Angle3*100.0);
+    *( (U8*)(tcBuffer + 7) ) = setVal->cam1Threshold;
+    *( (U16*)(tcBuffer + 9) ) = setVal->cam1Exposure;
+    *( (U16*)(tcBuffer + 11) ) = (U16) round(setVal->cam1BoreX*100.0);
+    *( (U16*)(tcBuffer + 13) ) = (U16) round(setVal->cam1BoreY*100.0);
+    *( (S16*)(tcBuffer + 15) ) = (S16) round(setVal->cam2Angle1*100.0);
+    *( (S16*)(tcBuffer + 17) ) = (S16) round(setVal->cam2Angle2*100.0);
+    *( (S16*)(tcBuffer + 19) ) = (S16) round(setVal->cam2Angle3*100.0);
+    *( (U8*)(tcBuffer + 21) ) = setVal->cam2Threshold;
+    *( (U16*)(tcBuffer + 23) ) = setVal->cam2Exposure;
+    *( (U16*)(tcBuffer + 25) ) = (U16) round(setVal->cam2BoreX*100.0);
+    *( (U16*)(tcBuffer + 27) ) = (U16) round(setVal->cam2BoreY*100.0);
+    *( (U8*)(tcBuffer + 29) ) = setVal->nadirMaxDeviationPercentage;
+    *( (U8*)(tcBuffer + 30) ) = setVal->nadirMaxBadEdges;
+    *( (U8*)(tcBuffer + 31) ) = setVal->nadirMaxRadius;
+    *( (U8*)(tcBuffer + 32) ) = setVal->nadirMinRadius;
+    *( (U16*)(tcBuffer + 33) ) = setVal->cam1MaskArea1Xmin;
+    *( (U16*)(tcBuffer + 35) ) = setVal->cam1MaskArea1Xmax;
+    *( (U16*)(tcBuffer + 37) ) = setVal->cam1MaskArea1Ymin;
+    *( (U16*)(tcBuffer + 39) ) = setVal->cam1MaskArea1Ymax;
+    *( (U16*)(tcBuffer + 41) ) = setVal->cam1MaskArea2Xmin;
+    *( (U16*)(tcBuffer + 43) ) = setVal->cam1MaskArea2Xmax;
+    *( (U16*)(tcBuffer + 45) ) = setVal->cam1MaskArea2Ymin;
+    *( (U16*)(tcBuffer + 47) ) = setVal->cam1MaskArea2Ymax;
+    *( (U16*)(tcBuffer + 49) ) = setVal->cam1MaskArea3Xmin;
+    *( (U16*)(tcBuffer + 51) ) = setVal->cam1MaskArea3Xmax;
+    *( (U16*)(tcBuffer + 53) ) = setVal->cam1MaskArea3Ymin;
+    *( (U16*)(tcBuffer + 55) ) = setVal->cam1MaskArea3Ymax;
+    *( (U16*)(tcBuffer + 57) ) = setVal->cam1MaskArea4Xmin;
+    *( (U16*)(tcBuffer + 59) ) = setVal->cam1MaskArea4Xmax;
+    *( (U16*)(tcBuffer + 61) ) = setVal->cam1MaskArea4Ymin;
+    *( (U16*)(tcBuffer + 63) ) = setVal->cam1MaskArea4Ymax;
+    *( (U16*)(tcBuffer + 65) ) = setVal->cam1MaskArea5Xmin;
+    *( (U16*)(tcBuffer + 67) ) = setVal->cam1MaskArea5Xmax;
+    *( (U16*)(tcBuffer + 69) ) = setVal->cam1MaskArea5Ymin;
+    *( (U16*)(tcBuffer + 71) ) = setVal->cam1MaskArea5Ymax;
+    *( (U16*)(tcBuffer + 73) ) = setVal->cam2MaskArea1Xmin;
+    *( (U16*)(tcBuffer + 75) ) = setVal->cam2MaskArea1Xmax;
+    *( (U16*)(tcBuffer + 77) ) = setVal->cam2MaskArea1Ymin;
+    *( (U16*)(tcBuffer + 79) ) = setVal->cam2MaskArea1Ymax;
+    *( (U16*)(tcBuffer + 81) ) = setVal->cam2MaskArea2Xmin;
+    *( (U16*)(tcBuffer + 83) ) = setVal->cam2MaskArea2Xmax;
+    *( (U16*)(tcBuffer + 85) ) = setVal->cam2MaskArea2Ymin;
+    *( (U16*)(tcBuffer + 87) ) = setVal->cam2MaskArea2Ymax;
+    *( (U16*)(tcBuffer + 89) ) = setVal->cam2MaskArea3Xmin;
+    *( (U16*)(tcBuffer + 91) ) = setVal->cam2MaskArea3Xmax;
+    *( (U16*)(tcBuffer + 93) ) = setVal->cam2MaskArea3Ymin;
+    *( (U16*)(tcBuffer + 95) ) = setVal->cam2MaskArea3Ymax;
+    *( (U16*)(tcBuffer + 97) ) = setVal->cam2MaskArea4Xmin;
+    *( (U16*)(tcBuffer + 99) ) = setVal->cam2MaskArea4Xmax;
+    *( (U16*)(tcBuffer + 101) ) = setVal->cam2MaskArea4Ymin;
+    *( (U16*)(tcBuffer + 103) ) = setVal->cam2MaskArea4Ymax;
+    *( (U16*)(tcBuffer + 105) ) = setVal->cam2MaskArea5Xmin;
+    *( (U16*)(tcBuffer + 107) ) = setVal->cam2MaskArea5Xmax;
+    *( (U16*)(tcBuffer + 109) ) = setVal->cam2MaskArea5Ymin;
+    *( (U16*)(tcBuffer + 111) ) = setVal->cam2MaskArea5Ymax;
+
+    return 113;
+}
+
+uint16_t CUBEACP_FormatDeployMagnetometerCmd(uint8_t* tcBuffer, U8 timeout)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 7;
+
+    *( (U8*)(tcBuffer + 1) ) = timeout;
+
+    return 2;
+}
+
+uint16_t CUBEACP_FormatDetumbleParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 38;
+
+    *( (F32*)(tcBuffer + 1) ) = setVal->ks;
+    *( (F32*)(tcBuffer + 5) ) = setVal->kd;
+    *( (S16*)(tcBuffer + 9) ) = (S16) round(setVal->wy_ref*1000.0);
+    *( (F32*)(tcBuffer + 11) ) = setVal->kdf;
+
+    return 15;
+}
+
+uint16_t CUBEACP_FormatEstimModeCmd(uint8_t* tcBuffer, CUBEACP_EstimModeSelect_t estimModeSelection)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 14;
+
+    tcBuffer[1] = 
+        (estimModeSelection << 0);
+
+    return 2;
+}
+
+uint16_t CUBEACP_FormatEstimParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 27;
+
+    *( (F32*)(tcBuffer + 1) ) = setVal->magRateNoise;
+    *( (F32*)(tcBuffer + 5) ) = setVal->ekfSysNoise;
+    *( (F32*)(tcBuffer + 9) ) = setVal->cssNoise;
+    *( (F32*)(tcBuffer + 13) ) = setVal->sunNoise;
+    *( (F32*)(tcBuffer + 17) ) = setVal->nadirNoise;
+    *( (F32*)(tcBuffer + 21) ) = setVal->magNoise;
+    *( (F32*)(tcBuffer + 25) ) = setVal->starNoise;
+    *( (U8*)(tcBuffer + 31) ) = setVal->cam1Cam2Period;
+
+    return 32;
+}
+
+uint16_t CUBEACP_FormatGyroConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 23;
+
+    tcBuffer[1] = 
+        (setVal->gyro1Conf << 0);
+    tcBuffer[2] = 
+        (setVal->gyro2Conf << 0);
+    tcBuffer[3] = 
+        (setVal->gyro3Conf << 0);
+    *( (S16*)(tcBuffer + 4) ) = (S16) round(setVal->xRateOffset*1000.0);
+    *( (S16*)(tcBuffer + 6) ) = (S16) round(setVal->yRateOffset*1000.0);
+    *( (S16*)(tcBuffer + 8) ) = (S16) round(setVal->zRateOffset*1000.0);
+    *( (U8*)(tcBuffer + 10) ) = setVal->rateSensorMult;
+
+    return 11;
+}
+
+uint16_t CUBEACP_FormatInertialPointReferenceCmd(uint8_t* tcBuffer, F64 inertialRefX, F64 inertialRefY, F64 inertialRefZ)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 34;
+
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(inertialRefX*10000.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(inertialRefY*10000.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(inertialRefZ*10000.0);
+
+    return 7;
+}
+
+uint16_t CUBEACP_FormatLogSdConfig1Cmd(uint8_t* tcBuffer, U8* logSelection, U16 period, CUBEACP_SdLogSelect_t destination)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 104;
+
+    tcBuffer[13] = 
+        (destination << 0);
+    memcpy(tcBuffer + 1,logSelection,10);
+    *( (U16*)(tcBuffer + 11) ) = period;
+
+    return 14;
+}
+
+uint16_t CUBEACP_FormatLogSdConfig2Cmd(uint8_t* tcBuffer, U8* logSelection, U16 period, CUBEACP_SdLogSelect_t destination)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 105;
+
+    tcBuffer[13] = 
+        (destination << 0);
+    memcpy(tcBuffer + 1,logSelection,10);
+    *( (U16*)(tcBuffer + 11) ) = period;
+
+    return 14;
+}
+
+uint16_t CUBEACP_FormatLogUartConfigCmd(uint8_t* tcBuffer, U8* selection, U16 period)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 106;
+
+    memcpy(tcBuffer + 1,selection,10);
+    *( (U16*)(tcBuffer + 11) ) = period;
+
+    return 13;
+}
+
+uint16_t CUBEACP_FormatMagConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 26;
+
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(setVal->magmAngle1*100.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(setVal->magmAngle2*100.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(setVal->magmAngle3*100.0);
+    *( (S16*)(tcBuffer + 7) ) = (S16) round(setVal->magmOffset1*1000.0);
+    *( (S16*)(tcBuffer + 9) ) = (S16) round(setVal->magmOffset2*1000.0);
+    *( (S16*)(tcBuffer + 11) ) = (S16) round(setVal->magmOffset3*1000.0);
+    *( (S16*)(tcBuffer + 13) ) = (S16) round(setVal->magmSens11*1000.0);
+    *( (S16*)(tcBuffer + 15) ) = (S16) round(setVal->magmSens22*1000.0);
+    *( (S16*)(tcBuffer + 17) ) = (S16) round(setVal->magmSens33*1000.0);
+    *( (S16*)(tcBuffer + 19) ) = (S16) round(setVal->magmSens12*1000.0);
+    *( (S16*)(tcBuffer + 21) ) = (S16) round(setVal->magmSens13*1000.0);
+    *( (S16*)(tcBuffer + 23) ) = (S16) round(setVal->magmSens21*1000.0);
+    *( (S16*)(tcBuffer + 25) ) = (S16) round(setVal->magmSens23*1000.0);
+    *( (S16*)(tcBuffer + 27) ) = (S16) round(setVal->magmSens31*1000.0);
+    *( (S16*)(tcBuffer + 29) ) = (S16) round(setVal->magmSens32*1000.0);
+
+    return 31;
+}
+
+uint16_t CUBEACP_FormatMagModeCmd(uint8_t* tcBuffer, CUBEACP_MagModeVal_t modeSetting)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 56;
+
+    tcBuffer[1] = 
+        (modeSetting << 0);
+
+    return 2;
+}
+
+uint16_t CUBEACP_FormatMagtorqConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 21;
+
+    tcBuffer[1] = 
+        (setVal->magtorq1 << 0);
+    tcBuffer[2] = 
+        (setVal->magtorq2 << 0);
+    tcBuffer[3] = 
+        (setVal->magtorq3 << 0);
+
+    return 4;
+}
+
+uint16_t CUBEACP_FormatMoICmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 41;
+
+    *( (F32*)(tcBuffer + 1) ) = setVal->ixx;
+    *( (F32*)(tcBuffer + 5) ) = setVal->iyy;
+    *( (F32*)(tcBuffer + 9) ) = setVal->izz;
+    *( (F32*)(tcBuffer + 13) ) = setVal->ixy;
+    *( (F32*)(tcBuffer + 17) ) = setVal->ixz;
+    *( (F32*)(tcBuffer + 21) ) = setVal->iyz;
+
+    return 25;
+}
+
+uint16_t CUBEACP_FormatOrbitArgPerCmd(uint8_t* tcBuffer, F64 argPerigee)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 49;
+
+    memcpy(tcBuffer + 1, &argPerigee, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitBStarCmd(uint8_t* tcBuffer, F64 bstar)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 50;
+
+    memcpy(tcBuffer + 1, &bstar, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitEccentricityCmd(uint8_t* tcBuffer, F64 eccentricity)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 47;
+
+    memcpy(tcBuffer + 1, &eccentricity, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitEpochCmd(uint8_t* tcBuffer, F64 epoch)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 53;
+
+    memcpy(tcBuffer + 1, &epoch, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitInclinationCmd(uint8_t* tcBuffer, F64 inclination)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 46;
+
+    memcpy(tcBuffer + 1, &inclination, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitMeanAnomCmd(uint8_t* tcBuffer, F64 meanAnomaly)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 52;
+
+    memcpy(tcBuffer + 1, &meanAnomaly, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitMeanMotCmd(uint8_t* tcBuffer, F64 meanMotion)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 51;
+
+    memcpy(tcBuffer + 1, &meanMotion, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatOrbitParametersCmd(uint8_t* tcBuffer, CUBEACP_OrbitParameters_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 45;
+
+    memcpy(tcBuffer + 1, &setVal->inclination, 8);
+    memcpy(tcBuffer + 9, &setVal->eccentricity, 8);
+    memcpy(tcBuffer + 17, &setVal->raan, 8);
+    memcpy(tcBuffer + 25, &setVal->argPerigee, 8);
+    memcpy(tcBuffer + 33, &setVal->bstar, 8);
+    memcpy(tcBuffer + 41, &setVal->meanMotion, 8);
+    memcpy(tcBuffer + 49, &setVal->meanAnomaly, 8);
+    memcpy(tcBuffer + 57, &setVal->epoch, 8);
+
+    return 65;
+}
+
+uint16_t CUBEACP_FormatOrbitRaanCmd(uint8_t* tcBuffer, F64 raan)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 48;
+
+    memcpy(tcBuffer + 1, &raan, 8);
+
+    return 9;
+}
+
+uint16_t CUBEACP_FormatRedMagConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 36;
+
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(setVal->mredAngle1*100.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(setVal->mredAngle2*100.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(setVal->mredAngle3*100.0);
+    *( (S16*)(tcBuffer + 7) ) = (S16) round(setVal->mredOffset1*1000.0);
+    *( (S16*)(tcBuffer + 9) ) = (S16) round(setVal->mredOffset2*1000.0);
+    *( (S16*)(tcBuffer + 11) ) = (S16) round(setVal->mredOffset3*1000.0);
+    *( (S16*)(tcBuffer + 13) ) = (S16) round(setVal->mredSens11*1000.0);
+    *( (S16*)(tcBuffer + 15) ) = (S16) round(setVal->mredSens22*1000.0);
+    *( (S16*)(tcBuffer + 17) ) = (S16) round(setVal->mredSens33*1000.0);
+    *( (S16*)(tcBuffer + 19) ) = (S16) round(setVal->mredSens12*1000.0);
+    *( (S16*)(tcBuffer + 21) ) = (S16) round(setVal->mredSens13*1000.0);
+    *( (S16*)(tcBuffer + 23) ) = (S16) round(setVal->mredSens21*1000.0);
+    *( (S16*)(tcBuffer + 25) ) = (S16) round(setVal->mredSens23*1000.0);
+    *( (S16*)(tcBuffer + 27) ) = (S16) round(setVal->mredSens31*1000.0);
+    *( (S16*)(tcBuffer + 29) ) = (S16) round(setVal->mredSens32*1000.0);
+
+    return 31;
+}
+
+uint16_t CUBEACP_FormatRWheelParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 40;
+
+    *( (F32*)(tcBuffer + 1) ) = setVal->kp2;
+    *( (F32*)(tcBuffer + 5) ) = setVal->kd2;
+    *( (F32*)(tcBuffer + 9) ) = setVal->h_bias;
+
+    return 14;
+}
+
+uint16_t CUBEACP_FormatSaveConfigCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 63;
+
+
+    return 1;
+}
+
+uint16_t CUBEACP_FormatSaveImageCmd(uint8_t* tcBuffer, CUBEACP_SaveImage_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 80;
+
+    tcBuffer[1] = 
+        (setVal->cameraSelect << 0);
+    tcBuffer[2] = 
+        (setVal->imageSize << 0);
+
+    return 3;
+}
+
+uint16_t CUBEACP_FormatSaveOrbitParamsCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 64;
+
+
+    return 1;
+}
+
+uint16_t CUBEACP_FormatStarConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 37;
+
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(setVal->starAngle1*100.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(setVal->starAngle2*100.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(setVal->starAngle3*100.0);
+    *( (U16*)(tcBuffer + 7) ) = setVal->starExposure;
+    *( (U16*)(tcBuffer + 9) ) = setVal->starGain;
+    *( (U8*)(tcBuffer + 11) ) = setVal->detectionThreshold;
+    *( (U8*)(tcBuffer + 12) ) = setVal->starThreshold;
+    *( (U8*)(tcBuffer + 13) ) = setVal->maxStarMatched;
+    *( (U16*)(tcBuffer + 14) ) = setVal->starTimeoutTime;
+    *( (U8*)(tcBuffer + 16) ) = setVal->maxStarPixel;
+    *( (U8*)(tcBuffer + 17) ) = setVal->minStarPixel;
+    *( (U8*)(tcBuffer + 18) ) = (U8) round(setVal->starErrorMargin*100.0);
+    *( (U16*)(tcBuffer + 19) ) = setVal->starDelayTime;
+    *( (F32*)(tcBuffer + 21) ) = setVal->starCentX;
+    *( (F32*)(tcBuffer + 25) ) = setVal->starCentY;
+    *( (F32*)(tcBuffer + 29) ) = setVal->starFocal;
+    *( (F32*)(tcBuffer + 33) ) = setVal->starLensK1;
+    *( (F32*)(tcBuffer + 37) ) = setVal->starLensK2;
+    *( (F32*)(tcBuffer + 41) ) = setVal->starLensP1;
+    *( (F32*)(tcBuffer + 45) ) = setVal->starLensP2;
+    *( (U8*)(tcBuffer + 49) ) = setVal->starWindowWidth;
+    *( (U8*)(tcBuffer + 50) ) = (U8) round(setVal->starTrackingMargin*100.0);
+    *( (U8*)(tcBuffer + 51) ) = (U8) round(setVal->starValidationMargin*100.0);
+    *( (U8*)(tcBuffer + 53) ) = (U8) round(setVal->starSearchWidth*5.0);
+
+    return 54;
+}
+
+uint16_t CUBEACP_FormatTorquerCmdCmd(uint8_t* tcBuffer, CUBEACP_TorquerCmd_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 16;
+
+    *( (S16*)(tcBuffer + 1) ) = (S16) round(setVal->torquerX*1000.0);
+    *( (S16*)(tcBuffer + 3) ) = (S16) round(setVal->torquerY*1000.0);
+    *( (S16*)(tcBuffer + 5) ) = (S16) round(setVal->torquerZ*1000.0);
+
+    return 7;
+}
+
+uint16_t CUBEACP_FormatTrackingParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 54;
+
+    *( (F32*)(tcBuffer + 1) ) = setVal->kp3;
+    *( (F32*)(tcBuffer + 5) ) = setVal->kd3;
+    *( (F32*)(tcBuffer + 9) ) = setVal->ki3;
+
+    return 14;
+}
+
+uint16_t CUBEACP_FormatTriggerAdcsCmd(uint8_t* tcBuffer)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 18;
+
+
+    return 1;
+}
+
+uint16_t CUBEACP_FormatTriggerAdcsSensorCmd(uint8_t* tcBuffer, CUBEACP_TriggerAdcsSensor_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 19;
+
+    tcBuffer[97] = 
+        (setVal->gpsSolutionStatus << 0);
+    *( (U32*)(tcBuffer + 1) ) = setVal->unixTime;
+    *( (U16*)(tcBuffer + 5) ) = setVal->cssRaw1;
+    *( (U16*)(tcBuffer + 7) ) = setVal->cssRaw2;
+    *( (U16*)(tcBuffer + 9) ) = setVal->cssRaw3;
+    *( (U16*)(tcBuffer + 11) ) = setVal->cssRaw4;
+    *( (U16*)(tcBuffer + 13) ) = setVal->cssRaw5;
+    *( (U16*)(tcBuffer + 15) ) = setVal->cssRaw6;
+    *( (U16*)(tcBuffer + 17) ) = setVal->cssRaw7;
+    *( (U16*)(tcBuffer + 19) ) = setVal->cssRaw8;
+    *( (U16*)(tcBuffer + 21) ) = setVal->cssRaw9;
+    *( (U16*)(tcBuffer + 23) ) = setVal->cssRaw10;
+    *( (S16*)(tcBuffer + 25) ) = setVal->cam1RawX;
+    *( (S16*)(tcBuffer + 27) ) = setVal->cam1RawY;
+    *( (U8*)(tcBuffer + 29) ) = setVal->cam1Busy;
+    *( (U8*)(tcBuffer + 30) ) = setVal->cam1Result;
+    *( (S16*)(tcBuffer + 31) ) = setVal->cam2RawX;
+    *( (S16*)(tcBuffer + 33) ) = setVal->cam2RawY;
+    *( (U8*)(tcBuffer + 35) ) = setVal->cam2Busy;
+    *( (U8*)(tcBuffer + 36) ) = setVal->cam2Result;
+    *( (S16*)(tcBuffer + 37) ) = setVal->magRawX;
+    *( (S16*)(tcBuffer + 39) ) = setVal->magRawY;
+    *( (S16*)(tcBuffer + 41) ) = setVal->magRawZ;
+    *( (S32*)(tcBuffer + 43) ) = setVal->rateRawX;
+    *( (S32*)(tcBuffer + 47) ) = setVal->rateRawY;
+    *( (S32*)(tcBuffer + 51) ) = setVal->rateRawZ;
+    *( (S16*)(tcBuffer + 55) ) = setVal->wheelRawX;
+    *( (S16*)(tcBuffer + 57) ) = setVal->wheelRawY;
+    *( (S16*)(tcBuffer + 59) ) = setVal->wheelRawZ;
+    *( (S16*)(tcBuffer + 61) ) = setVal->star1CameraX;
+    *( (S16*)(tcBuffer + 63) ) = setVal->star1CameraY;
+    *( (S16*)(tcBuffer + 65) ) = setVal->star1CameraZ;
+    *( (S16*)(tcBuffer + 67) ) = setVal->star1InertialX;
+    *( (S16*)(tcBuffer + 69) ) = setVal->star1InertialY;
+    *( (S16*)(tcBuffer + 71) ) = setVal->star1InertialZ;
+    *( (S16*)(tcBuffer + 73) ) = setVal->star2CameraX;
+    *( (S16*)(tcBuffer + 75) ) = setVal->star2CameraY;
+    *( (S16*)(tcBuffer + 77) ) = setVal->star2CameraZ;
+    *( (S16*)(tcBuffer + 79) ) = setVal->star2InertialX;
+    *( (S16*)(tcBuffer + 81) ) = setVal->star2InertialY;
+    *( (S16*)(tcBuffer + 83) ) = setVal->star2InertialZ;
+    *( (S16*)(tcBuffer + 85) ) = setVal->star3CameraX;
+    *( (S16*)(tcBuffer + 87) ) = setVal->star3CameraY;
+    *( (S16*)(tcBuffer + 89) ) = setVal->star3CameraZ;
+    *( (S16*)(tcBuffer + 91) ) = setVal->star3InertialX;
+    *( (S16*)(tcBuffer + 93) ) = setVal->star3InertialY;
+    *( (S16*)(tcBuffer + 95) ) = setVal->star3InertialZ;
+    *( (U16*)(tcBuffer + 98) ) = setVal->gpsWeek;
+    *( (U32*)(tcBuffer + 100) ) = setVal->gpsTimeMs;
+    *( (S32*)(tcBuffer + 104) ) = setVal->posEcefX;
+    *( (S16*)(tcBuffer + 108) ) = setVal->velEcefX;
+    *( (S32*)(tcBuffer + 110) ) = setVal->posEcefY;
+    *( (S16*)(tcBuffer + 114) ) = setVal->velEcefY;
+    *( (S32*)(tcBuffer + 116) ) = setVal->posEcefZ;
+    *( (S16*)(tcBuffer + 120) ) = setVal->velEcefZ;
+    *( (U8*)(tcBuffer + 122) ) = (U8) round(setVal->stdDevPosX*10.0);
+    *( (U8*)(tcBuffer + 123) ) = (U8) round(setVal->stdDevPosY*10.0);
+    *( (U8*)(tcBuffer + 124) ) = (U8) round(setVal->stdDevPosZ*10.0);
+    *( (U8*)(tcBuffer + 125) ) = setVal->stdDevVelX;
+    *( (U8*)(tcBuffer + 126) ) = setVal->stdDevVelY;
+    *( (U8*)(tcBuffer + 127) ) = setVal->stdDevVelZ;
+
+    return 128;
+}
+
+uint16_t CUBEACP_FormatUserConEstParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 29;
+
+    memcpy(tcBuffer + 1,setVal->userConSettings,48);
+    memcpy(tcBuffer + 49,setVal->userEstSettings,48);
+
+    return 97;
+}
+
+uint16_t CUBEACP_FormatWheelConfigCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 22;
+
+    tcBuffer[1] = 
+        (setVal->rW1Conf << 0);
+
+    return 5;
+}
+
+uint16_t CUBEACP_FormatWheelSpeedCmdCmd(uint8_t* tcBuffer, CUBEACP_WheelSpeedCmd_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 17;
+
+    *( (S16*)(tcBuffer + 1) ) = setVal->wheelX;
+    *( (S16*)(tcBuffer + 3) ) = setVal->wheelY;
+    *( (S16*)(tcBuffer + 5) ) = setVal->wheelZ;
+
+    return 7;
+}
+
+uint16_t CUBEACP_FormatYWheelParamsCmd(uint8_t* tcBuffer, CUBEACP_AdcsConfig_t* setVal)
+{
+    // write TtcMessage ID to first element in buffer
+    tcBuffer[0] = 39;
+
+    *( (F32*)(tcBuffer + 1) ) = setVal->kh;
+    *( (F32*)(tcBuffer + 5) ) = setVal->kn;
+    *( (F32*)(tcBuffer + 9) ) = setVal->kp1;
+    *( (F32*)(tcBuffer + 13) ) = setVal->kd1;
+    *( (F32*)(tcBuffer + 17) ) = setVal->h_ref;
+
+    return 21;
+}
+
+

+ 89 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/Makefile

@@ -0,0 +1,89 @@
+#
+#   @copyright Copyright 2022 Antaris, Inc.
+#
+TOP_DIR=../
+include $(TOP_DIR)Makefile.def
+
+##############################################################################
+# All variables here intensionally set to empty, User should not modify here
+
+SRC =
+SRC_DIR =
+SUBDIR =
+
+##############################################################################
+# List of include file directories required for compilation
+INCLUDES =
+
+##############################################################################
+#Current Folder target name, usually current folder name
+#TARGET_LIB = target_name
+
+# List of source files required for compilation using SRC
+# mention the directory path where all C files to be compiled usig SRC_DIR
+# Mention Sub director makefile compilation using SUBDIR
+
+SUBDIR += AdcsInterfaceLib
+SUBDIR += csp
+SUBDIR += file_transfer
+SUBDIR += ipcc
+SUBDIR += security
+SUBDIR += tc_tm
+SUBDIR += timer 
+
+##############################################################################
+
+ifeq ($(TARGET_LIB),)
+TARGET_LIB := $(shell basename `pwd`)
+endif
+
+ifneq ($(SRC_DIR),)
+    SOURCES = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
+endif
+
+SOURCES += $(SRC)
+
+OBJS = $(foreach dir,$(patsubst %.c, %.o, $(SOURCES)), $(OBJ_DIR)/$(dir))
+
+ifneq ($(SUBDIR),)
+SUB_DIR_LIBS = $(foreach dir,$(SUBDIR), $(dir)/$(OBJ_DIR)/$(shell basename $(dir)).a)
+endif
+
+#$(info selective source files List : $(SRC))
+#$(info source file directory       : $(SRC_DIR))
+#$(info All source file list        : $(SOURCES))
+#$(info All target object files     : $(OBJS))
+#$(info All target lib files        : $(SUB_DIR_LIBS))
+
+DEPS = $(OBJS:.o=.d)
+
+# Command to invoke compilation in sub-directories
+subdir_clean:
+	$(HIDE)for i in $(SUBDIR); do \
+	    $(MAKE) clean -C $$i;\
+	    done
+# Command to invoke compilation in sub-directories
+subdir_all:
+	$(HIDE)for i in $(SUBDIR); do \
+	    $(MAKE) all -C $$i;\
+	    done
+lib: subdir_all
+	$(HIDE)$(MKDIR) $(OBJ_DIR)
+	$(HIDE)$(AR) $(OBJ_DIR)/$(TARGET_LIB).a $(SUB_DIR_LIBS)
+
+# Command to compile source files to intermediate object files
+all:$(OBJS)
+	$(HIDE)$(MKDIR) $(OBJ_DIR)
+ifneq ($(SUBDIR),)
+	$(HIDE)$(MAKE) subdir_all
+endif
+#	$(HIDE)$(AR) $(OBJ_DIR)/$(TARGET_LIB).a $^ $(SUB_DIR_LIBS)
+
+# Command to delete intermediate object files
+clean:
+ifneq ($(SUBDIR),)
+	$(HIDE)$(MAKE) subdir_clean
+endif
+	$(HIDE)$(RM) $(OBJ_DIR)
+
+-include $(DEPS)

+ 35 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/build_lib.sh

@@ -0,0 +1,35 @@
+# *********** Building security libraries **********
+echo "Building security libraries"
+cd security
+./build.sh $1
+cd ..
+
+echo "Building IPCC libraries"
+cd ipcc
+./build_ipcc_lib.sh $1
+cd ..
+
+echo "Building TC TM libraries"
+cd tc_tm
+./build_tctm_lib.sh $1
+cd ..
+
+echo "Building File transfer libraries"
+cd file_transfer
+./build_ft_lib.sh $1
+cd ..
+
+echo "Building CSP libraries"
+cd csp
+./build_csp_lib.sh $1
+cd ..
+
+echo "Building ADCS interface library"
+cd AdcsInterfaceLib
+./build_adcs_intf_lib.sh $1
+cd ..
+
+echo "Building Timer libraries"
+cd timer
+./build_timer.sh $1
+cd ..

+ 15 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/build_csp_lib.sh

@@ -0,0 +1,15 @@
+# *********** Building CSP libraries **********
+echo "Building CSP libraries"
+cd ../csp
+
+if [ $1 == "clean" ]
+then
+    echo "Cleaning CSP library"
+    rm -rf docs
+    make clean
+
+else
+    echo "Building CSP library"
+    make clean
+    make all
+fi

+ 153 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/basic.rst

@@ -0,0 +1,153 @@
+The basics of CSP
+=================
+
+The following diagram shows a conceptual overview of the different blocks in CSP. The shown inferface is CAN (src/interfaces/csp_if_can.c, driver: src/drivers/can/can_socketcan.c).
+
+.. code-block:: none
+
+           buffer                  connection   send   read/accept
+              ^                         |         |         ^
+              |                         |         v         |
+              |   +-----------------+   |     +----------------+    +-------------------+
+              |   | connection pool |   |     |    CSP Core    |    | csp_task_router() |
+              |   |  csp_conn.c     |<--+---->| * routing      |<---|    csp_route.c    |
+              |   +-----------------+         | * crypt        |    +-------------------+
+              |                               | * UDP/RDP      |              ^
+              |                  csp_route_t  | * CRC32        |              |
+              v                 +------------>|                |     +----------------+
+       +--------------+         |             |                |     | incoming queue |
+       | buffer pool  |         |             |                |     |     qfifo.c    |
+       | csp_buffer.c |  +-------------+      +----------------+     +----------------+
+       +--------------+  |routing table|            |                         ^
+              ^          |  rtable.c   |            v                         |
+              |          +-------------+      +------------------------------------+
+              |                               |  (next_hop)                        |
+              |                               |    CAN interface (csp_if_can.c)    |
+              +------------------------------>|                      csp_can_rx()  |
+                                              +------------------------------------+
+                                                    |   CAN frame (8 bytes)   ^
+                                                    v                         |
+                                            csp_can_tx_frame()       socketcan_rx_thread()
+					            (drivers/can/can_socketcan.c)
+
+
+Buffer
+------
+
+All buffers are allocated once during initialization of CSP, after this the buffer system is entirely self-contained. All allocated elements are of the same size, so the buffer size must be chosen to be able to handle the maximum possible packet length. The buffer pool uses a queue to store pointers to free buffer elements. First of all, this gives a very quick method to get the next free element since the dequeue is an O(1) operation. Furthermore, since the queue is a protected operating system primitive, it can be accessed from both task-context and interrupt-context. The `csp_buffer_get()` version is for task-context and `csp_buffer_get_isr()` is for interrupt-context. Using fixed size buffer elements that are preallocated is again a question of speed and safety.
+
+Definition of a buffer element `csp_packet_t`:
+
+.. literalinclude:: ../include/csp/csp_types.h
+   :language: c
+   :start-after: //doc-begin:csp_packet_t
+   :end-before: //doc-end:csp_packet_t
+
+A basic concept in the buffer system is called Zero-Copy. This means that from userspace to the kernel-driver, the buffer is never copied from one buffer to another. This is a big deal for a small microprocessor, where a call to `memcpy()` can be very expensive.
+This is achieved by a number of `padding` bytes in the buffer, allowing for a header to be prepended at the lower layers without copying the actual payload. This also means that there is a strict contract between the layers, which data can be modified and where.
+
+The padding bytes are used by the I2C interface, where the `csp_packet_t` will be casted to a `csp_i2c_frame_t`, when the interface calls the driver Tx function `csp_i2c_driver_tx_t`:
+
+.. literalinclude:: ../include/csp/interfaces/csp_if_i2c.h
+   :language: c
+   :start-after: //doc-begin:csp_i2c_frame_t
+   :end-before: //doc-end:csp_i2c_frame_t
+
+
+Connection
+----------
+
+CSP supports both connection-less and connection-oriented connections. See more about protocols in :ref:`layer4`.
+
+During initialization libcsp allocates the configured number of connections. The required number of connections depends on the application. Here is a list functions, that will allocate a connection from the connection pool:
+
+  - client connection, call to `csp_connect()`
+  - server socket for listening `csp_socket()`
+  - server accepting an incmoing connection `csp_accept()`
+
+An applications receive queue is located on the connection and is also allocated once during initialization. The length of the queue is the same for all queues, and specified in the configuration.
+
+
+Send
+----
+
+The data flow from the application to the driver, can basically be broken down into following steps:
+
+   1. if using connection-oriented communication, establish a connection> `csp_connect()`, `csp_accept()`
+   2. get packet from the buffer pool: `csp_buffer_get()`
+   3. add payload data to the packet
+   4. send packet, e.g. `csp_send()`, `csp_sendto()`
+   5. CSP looks up the destination route, using the routing table, and calls `nexthop()` on the resolved interface.
+   6. The interface (in this case the CAN interface), splits the packet into a number of CAN frames (8 bytes) and forwards them to the driver.
+
+
+Receive
+-------
+
+The data flow from the driver to the application, can basically be broken down into following steps:
+
+   1. the driver layer forwards the raw data frames to the interface, in this case CAN frames
+   2. the interface will aquire a free buffer (e.g. `csp_buffer_get_isr()`) for assembling the CAN frames into a complete packet
+   3. once the interface has successfully assembled a packet, the packet is queued for routing - primarily to decouple the interface, e.g. if the interfacec/drivers uses interrupt (ISR).
+   4. the router picks up the packet from the incoming queue and routes it on - this can either to a local destination, or another interface.
+   5. the application waits for new packets at its Rx queue, by calling `csp_read()` or `csp_accept` in case it is a server socket.
+   6. the application can now process the packet, and either send it using e.g. `csp_send()`, or free the packet using `csp_buffer_free()`.
+
+
+Routing table
+-------------
+
+When a packet is routed, the destination address is looked up in the routing table, which results in a `csp_route_t` record. The record contains the inteface (`csp_iface_t`) the packet is to be send on, and an optional `via` address. The `via` address is used, when the sender cannot direcly reach the receiver on one of its connected networks, e.g. sending a packet from the satellite to the ground - the radio will be the `via` address.
+
+CSP comes with 2 routing table implementations (selected at compile time).
+
+ - static: supports a one-to-one mapping, meaning routes must be configured per destination address or a single `default` address. The `default` address is used, in case there are no routes set for the specific destination address.
+   The `static` routing table has the fastest lookup, but requires more setup.
+
+ - cidr (Classless Inter-Domain Routing): supports a one-to-many mapping, meaning routes can be configued for a range of destianation addresses.
+   The `cidr` is a bit slower for lookup, but simple to setup.
+
+Routes can be configured using text strings in the format:
+
+   <address>[/mask] <interface name> [via]
+
+   * address: is the destination address, the routing table will match it against the CSP header destination.
+   * mask (optional): determines how many MSB bits of address are to be matched. mask = 1 will only match the MSB bit, mask = 2 will match 2 MSB bits. Mask values different from 0 and 5, is only supported by the cidr rtable.
+   * interface name: name of the interface to route the packet on
+   * via (optional) address: if different from 255, route the packet to the `via` address, instead of the address in the CSP header.
+
+Here are some examples:
+
+ - "10 I2C" route destination address 10 to the "I2C" interface and send it to address 10 (no `via`).
+ - "10 I2C 30" route destination address 10 to the "I2C" interface and send it to address 30 (`via`). The original destination address 10 is not changed in the CSP header of the packet.
+ - "16/1 CAN 4" (CIDR only) route all destinations addresses 16-31 to address 4 on the CAN interface.
+ - "0/0 CAN" default route, if no other matching route is found, route packet onto the CAN interface.
+
+
+Interface
+---------
+
+The interface typically implements :ref:`layer2`, and uses drivers from :ref:`layer1` to send/receive data.
+The interface is a generic struct, with no knowledge of any specific interface , protocol or driver:
+
+.. literalinclude:: ../include/csp/csp_interface.h
+   :language: c
+   :start-after: //doc-begin:csp_iface_s
+   :end-before: //doc-end:csp_iface_s
+
+If an interface implementation needs to store data, e.g. state information (KISS), it can use the pointer `interface_data` to reference any data structure needed. The driver implementation can use the pointer `driver_data` for storing data, e.g. device number.
+
+See function `csp_can_socketcan_open_and_add_interface()` in `src/drivers/can/can_socketcan.c` for an example of how to implement a CAN driver and hooking it into CSP, using the CSP standard CAN interface.
+
+Send
+^^^^
+
+When CSP needs to send a packet, it calls `nexthop` on the interface returned by route lookup.
+If the interface succeeds in sending the packet, it must free the packet.
+In case of failure, the packet must not be freed by the interface. The original idea was, that the packet could be retried later on, without having to re-create the packet again. However, the current implementation does not yet fully support this as some interfaces modifies header (endian conversion) or data (adding CRC32).
+
+Receive
+^^^^^^^
+
+When receiving data, the driver calls into the interface with the received data, e.g. `csp_can_rx()`. The interface will convert/copy the data into a packet (e.g. by assembling all CAN frames). Once a complete packet is received, the packet is  queued for later CSP processing, by calling `csp_qfifo_write()`.
+

+ 61 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/example.rst

@@ -0,0 +1,61 @@
+Client and server example
+=========================
+
+The example in `example/csp_server_client.c` provides a simple server/client setup, where the client sends a request to the server and receives a reply. The code can be compiled to an executable using `./examples/buildall.py`.
+
+The example supports the drivers and interfaces in CSP:
+
+ - ZMQHUB: -z <host name|ip>
+
+   Requires no extra hardware, as it uses standard network. The zmqproxy will need to be started.
+
+ - CAN: -c <can device>
+
+   Requires a physical CAN interface. There are several CAN dongles on the market, for example https://www.peak-system.com/PCAN-USB.199.0.html.
+
+   To achieve best performance and stabilty, following options can be set on the CAN device:
+
+      .. code-block:: none
+
+	 linux: sudo ip link set dev can0 down
+	 linux: sudo ip link set dev can0 up type can bitrate 1000000 restart-ms 100
+	 linux: sudo ip link set dev can0 txqueuelen 100
+
+ - KISS: -k <serial device>
+
+   Requires a serial interface, e.g. USB dongle.
+
+
+Running the example
+^^^^^^^^^^^^^^^^^^^
+If the example is started without any interfaces, it will use the loopback interface for communication between client and server::
+
+  ubuntu-18:~/libcsp$ ./build/csp_server_client 
+  1586816581.410181 Initialising CSP
+  Connection table
+  [00 0x55a00f7adee0] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [01 0x55a00f7adf68] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [02 0x55a00f7adff0] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [03 0x55a00f7ae078] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [04 0x55a00f7ae100] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [05 0x55a00f7ae188] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [06 0x55a00f7ae210] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [07 0x55a00f7ae298] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [08 0x55a00f7ae320] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  [09 0x55a00f7ae3a8] S:0, 0 -> 0, 0 -> 0, sock: (nil)
+  Interfaces
+  LOOP       tx: 00000 rx: 00000 txe: 00000 rxe: 00000
+             drop: 00000 autherr: 00000 frame: 00000
+             txb: 0 (0.0B) rxb: 0 (0.0B) MTU: 0
+
+  Route table
+  1/5 LOOP
+  0/0 LOOP
+  1586816581.410405 Server task started
+  1586816581.410453 Binding socket 0x55a00f7adf68 to port 25
+  1586816581.410543 Client task started
+  1586816582.410983 SERVICE: Ping received
+  1586816582.411135 Ping address: 1, result 0 [mS]
+  1586816582.411174 reboot system request sent to address: 1
+  1586816582.461341 csp_sys_reboot not supported - no user function set
+  1586816582.512532 Packet received on MY_SERVER_PORT: Hello World (1)

+ 21 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/history.rst

@@ -0,0 +1,21 @@
+History
+=======
+
+The idea was developed by a group of students from Aalborg University in 2008. In 2009 the main developer started working for GomSpace, and CSP became integrated into the GomSpace products.
+
+The three letter acronym CSP was originally an abbreviation for CAN Space Protocol because the first MAC-layer driver was written for CAN-bus. Now the physical layer has extended to include SpaceWire, I2C and RS232, the name was therefore extended to the more general CubeSat Space Protocol without changing the abbreviation.
+
+Satellites using CSP
+--------------------
+
+Here is a list of some of the known satellites or organisations, that uses CSP:
+
+ * GomSpace GATOSS GOMX-1
+ * AAUSAT-3
+ * EgyCubeSat
+ * EuroLuna
+ * NUTS
+ * Hawaiian Space Flight Laboratory
+ * GomSpace GOMX-3, GOMX-4 A & B
+
+See list of libcsp fork's here: https://github.com/libcsp/libcsp/network/members

+ 21 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/libcsp.rst

@@ -0,0 +1,21 @@
+.. CSP Documentation master file.
+
+.. _libcsp:
+   
+**********************
+CubeSat Space Protocol
+**********************
+
+.. toctree::
+   :maxdepth: 3
+   
+   ../README
+   history
+   structure
+   basic
+   memory
+   protocolstack
+   topology
+   mtu
+   example
+   

+ 16 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/memory.rst

@@ -0,0 +1,16 @@
+How CSP uses memory
+===================
+
+CSP has been written for small microprocessor systems. The way memory is handled is therefore a tradeoff between the amount used and the code efficiency.
+
+The current libcsp implementation primarily uses dynamic memory allocation during initialization, where all structures are allocated: port tables, connection pools, buffer pools, message queues, semaphores, tasks, etc.
+
+Once the initiallization is complete, there are only a few functions that uses dynamic allocation, such as:
+
+ * csp_sfp_recv() - sending larger memory chuncks than can fit into a single CSP message.
+ * csp_rtable (cidr only) - adding new elements may allocate memory.
+
+This means that there are no `alloc/free` after initialization, possibly causing fragmented memory which especially can be a problem on small systems with limited memory.
+It also allows for a very simple memory allocator (implementation of `csp_malloc()`), as `free` can be avoided.
+
+Future versions of libcsp may provide a `pure` static memory layout, since newer FreeRTOS versions allows for specifying memory for queues, semaphores, tasks, etc.

+ 19 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/mtu.rst

@@ -0,0 +1,19 @@
+Maximum Transfer Unit
+=====================
+
+There are two things limiting the MTU of CSP.
+
+  1. The pre-allocated buffer pool’s allocation size
+  2. The link layer protocol.
+
+So let’s assume that you have made a protocol called KISS with a MTU of 256. The 256 is the total amount of data that you can put into the CSP-packet. However, you need to take the overhead of the link layer into account. Typically this could consist of a length field and/or a start/stop flag. So the actual frame size on the link layer would for example be 256 bytes of data + 2 bytes sync flag + 2 bytes length field.
+
+This requires a buffer allocation of at lest 256 + 2 + 2. However, the CSP packet itself has some reserved bytes in the beginning of the packet (which you can see in csp.h) - so the recommended buffer allocation size is MAX MTU + 16 bytes. In this case the max MTU would be 256.
+
+If you try to pass data which is longer than the MTU, the chance is that you will also make a buffer overflow in the CSP buffer pool. However, lets assume that you have two interfaces one with an MTU of 200 bytes and another with an MTU of 100 bytes. In this case you might successfully transfer 150 bytes over the first interface, but the packet will be rejected once it comes to the second interface.
+
+If you want to increase your MTU of a specific link layer, it is up to the link layer protocol to implement its own fragmentation protocol. A good example is CAN-bus which only allows a frame size of 8 bytes. libcsp have a small protocol for this called the “CAN fragmentation protocol" or CFP for short. This allows data of much larger size to be transferred over the CAN bus.
+
+Okay, but what if you want to transfer 1000 bytes, and the network maximum MTU is 256? Well, since CSP does not include streaming sockets, only packet’s. Somebody will have to split that data up into chunks. It might be that your application have special knowledge about the datatype you are transmitting, and that it makes sense to split the 1000 byte content into 10 chunks of 100 byte status messages. This, application layer delimitation might be good if you have a situation with packet loss, because your receiver could still make good usage of the partially delivered chunks.
+
+But, what if you just want 1000 bytes transmitted, and you don’t care about the fragmentation unit, and also don’t want the hassle of writing the fragmentation code yourself? - In this case, libcsp provides SFP (small fragmentation protocol), designed to work on the application layer. For this purpose you will not use csp_send and csp_recv, but csp_sfp_send and csp_sfp_recv. This will split your data into chunks of a certain size, enumerate them and transfer over a given connection. If a chunk is missing the SFP client will abort the reception, because SFP does not provide retransmission. If you wish to also have retransmission and orderly delivery you will have to open an RDP connection and send your SFP message to that connection.

+ 61 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/protocolstack.rst

@@ -0,0 +1,61 @@
+The Protocol Stack
+==================
+
+The CSP protocol stack includes functionality on all layers of the TCP/IP model:
+
+.. _layer1:
+
+Layer 1: Drivers
+----------------
+
+CSP is not designed for any specific processor or hardware peripheral, but yet these drivers are required in order to work. The intention of LibCSP is not to provide CAN, I2C or UART drivers for all platforms, however some drivers has only been included for some specific platforms. If you do not find your driver supported, it is quite simple to add a driver that conforms to the CSP interface.
+For good stability and performance interrupt driven drivers are preferred in favor of polled drivers. Where applicable also DMA usage is recommended.
+
+.. _layer2:
+
+Layer 2: MAC interfaces
+-----------------------
+
+CSP has interfaces for I2C, CAN, RS232 (KISS) and Loopback. The layer 2 protocol software defines a frame-format that is suitable for the media. CSP can be easily extended with implementations for even more links. For example a radio-link and IP-networks. The file `csp_interface.h` declares the rx and tx functions needed in order to define a network interface in CSP. During initialisation of CSP each interface will be inserted into a linked list of interfaces that is available to the router. In cases where link-layer addresses are required, such as I2C, the routing table supports specifying a `via` link-layer address directly. This avoids the need to implement an address resolution protocol to translate CSP addresses to I2C addresses.
+
+Layer 3: Network Router
+-----------------------
+
+The router core is the backbone of the CSP implementation. The router works by looking at a 32-bit CSP header which contains the destination and source address together with port numbers for the connection. The router supports both local destination and forwarding to an external destination. Messages will never exit the router on the same interface that they arrives at, this concept is called split horizon, and helps prevent routing loops.
+
+The main purpose of the router is to accept incoming packets and deliver them to the right message queue. Therefore, in order to listen on a port-number on the network, a task must create a socket and call the accept() call. This will make the task block and wait for incoming traffic, just like a web-server or similar. When an incoming connection is opened, the task is woken. Depending on the task-priority, the task can even preempt another task and start execution immediately.
+
+There is no routing protocol for automatic route discovery, all routing tables are pre-programmed into the subsystems. The table itself contains a separate route to each of the possible 32 nodes in the network and the additional default route. This means that the overall topology must be decided before putting sub-systems together, as explained in the :ref:`topology` section. However CSP has an extension on port zero CMP (CSP management protocol), which allows for over-the-network routing table configuration. This has the advantage that default routes could be changed if for example the primary radio fails, and the secondary should be used instead.
+
+.. _layer4:
+
+Layer 4: Transport Layer
+------------------------
+
+LibCSP implements two different Transport Layer protocols, they are called UDP (unreliable datagram protocol) and RDP (reliable datagram protocol). The name UDP has not been chosen to be an exact replica of the UDP (user datagram protocol) known from the TCP/IP model, but they have certain similarities.
+
+The most important thing to notice is that CSP is entirely a datagram service. There is no stream based service like TCP. A datagram is a defined block of data with a specified size and structure. This block enters the transport layer as a single datagram and exits the transport layer in the other end as a single datagram. CSP preserves this structure all the way to the physical layer for I2C, KISS and Loopback interfaces. The CAN-bus interface has to fragment the datagram into CAN-frames of 8 bytes, however only a fully completed datagram will arrive at the receiver.
+
+UDP
+^^^
+
+UDP uses a simple transmission model without implicit hand-shaking dialogues for guaranteeing reliability, ordering, or data integrity. Thus, UDP provides an unreliable service and datagrams may arrive out of order, appear duplicated, or go missing without notice. UDP assumes that error checking and correction is either not necessary or performed in the application, avoiding the overhead of such processing at the network interface level. Time-sensitive applications often use UDP because dropping packets is preferable to waiting for delayed packets, which may not be an option in a real-time system.
+
+UDP is very practical to implement request/reply based communication where a single packet forms the request and a single packet forms the reply. In this case a typical request and wait protocol is used between the client and server, which will simply return an error if a reply is not received within a specified time limit. An error would normally lead to a retransmission of the request from the user or operator which sent the request.
+
+While UDP is very simple, it also has some limitations. Normally a human in the loop is a good thing when operating the satellite over UDP. But when it comes to larger file transfers, the human becomes the bottleneck. When a high-speed file transfer is initiated data acknowledgment should be done automatically in order to speed up the transfer. This is where the RDP protocol can help.
+
+RDP
+^^^
+CSP provides a transport layer extension called RDP (reliable datagram protocol) which is an implementation of RFC908 and RFC1151. RDP provides a few additional features:
+
+ * Three-way handshake
+ * Flow Control
+ * Data-buffering
+ * Packet re-ordering
+ * Retransmission
+ * Windowing
+ * Extended Acknowledgment
+
+For more information on this, please refer to RFC908 and RFC1151.
+

+ 29 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/structure.rst

@@ -0,0 +1,29 @@
+Structure
+=========
+The Cubesat Space Protocol library is structured as shown in the following table:
+
+=============================  =========================================================================
+**Folder**                     **Description**
+=============================  =========================================================================
+libcsp/include/csp             Public header files
+libcsp/include/csp/arch         Architecture (platform)
+libcsp/include/csp/interfaces   Interfaces
+libcsp/include/csp/drivers      Drivers
+libcsp/src                     Source modules and internal header files
+libcsp/src/arch                 Architecture (platform) specific code
+libcsp/src/arch/freertos        FreeRTOS
+libcsp/src/arch/macosx          Mac OS X
+libcsp/src/arch/posix           Posix (Linux)
+libcsp/src/arch/windows         Windows
+libcsp/src/bindings/python      Python3 wrapper for libcsp
+libcsp/src/crypto               HMAC, SHA and XTEA.
+libcsp/src/drivers              Drivers, mostly platform specific (Linux)
+libcsp/src/drivers/can          CAN
+libcsp/src/drivers/usart        USART
+libcsp/src/interfaces           Interfaces, CAN, I2C, KISS, LOOPBACK and ZMQHUB
+libcsp/src/rtable               Routing tables
+libcsp/src/transport            Transport layer: UDP, RDP
+libcsp/utils                   Utilities, Python scripts for decoding CSP headers.
+libcsp/examples                CSP examples, C/Python, zmqproxy
+libcsp/doc                     RST based documention (this documentation)
+=============================  =========================================================================

+ 27 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/doc/topology.rst

@@ -0,0 +1,27 @@
+
+.. _topology:
+
+Network Topology
+================
+
+CSP uses a network oriented terminology similar to what is known from the Internet and the TCP/IP model. A CSP network can be configured for several different topologies. The most common topology is to create two segments, one for the Satellite and one for the Ground-Station. 
+
+.. code-block:: none
+
+     +-------+-------+-------+-------+       bus: I2C, CAN, KISS
+     |       |       |       |       |
+   +---+   +---+   +---+   +---+   +---+
+   |OBC|   |COM|   |EPS|   |PL1|   |PL2|     Nodes 0 - 15 (Space segment)
+   +---+   +---+   +---+   +---+   +---+
+             ^
+             |  Radio
+             v
+           +---+          +----+
+           |TNC|          | PC |             Nodes 16 - 31 (Ground segment)
+           +---+          +----+
+             |               |
+             +---------------+               bus: KISS, ZMQ
+
+The address range, from 0 to 31, has been segmented into two equal size segments. This allows for easy routing in the network. All addresses starting with binary 1 is on the ground-segment, and all addresses starting with 0 is on the space segment.
+
+The network is configured using static routes initialised at boot-up of each sub-system. This means that the basic routing table must be assigned compile-time of each subsystem. However each node supports assigning an individual route to every single node in the network and can be changed run-time. This means that the network topology can be easily reconfigured after startup.

+ 52 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/buildall.py

@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+import subprocess
+import sys
+
+
+os = 'posix'  # default OS
+options = sys.argv[1:]
+if (len(options) > 0) and not options[0].startswith('--'):
+    os = options[0]
+    options = options[1:]
+
+options += [
+    '--with-os=' + os,
+    '--enable-rdp',
+    '--enable-promisc',
+    '--enable-crc32',
+    '--enable-hmac',
+    '--enable-xtea',
+    '--enable-dedup',
+    '--with-loglevel=debug',
+    '--enable-debug-timestamp'
+]
+
+waf = ['./waf']
+if os in ['posix']:
+    options += [
+        '--enable-python3-bindings',
+        '--enable-can-socketcan',
+        '--with-driver-usart=linux',
+        '--enable-if-zmqhub',
+        '--enable-shlib'
+    ]
+
+if os in ['macosx']:
+    options += [
+        '--with-driver-usart=linux',
+    ]
+
+if os in ['windows']:
+    options += [
+        '--with-driver-usart=windows',
+    ]
+    waf = ['python', '-x', 'waf']
+
+# Build
+waf += ['distclean', 'configure', 'build']
+print("Waf build command:", waf)
+subprocess.check_call(waf + options +
+                      ['--enable-qos', '--with-rtable=cidr', '--disable-stlib', '--disable-output'])
+subprocess.check_call(waf + options + ['--enable-examples'])

+ 159 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/csp_arch.c

@@ -0,0 +1,159 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#define CSP_USE_ASSERT 1  // always enable CSP assert
+
+#include <csp/csp_debug.h>
+#include <csp/arch/csp_thread.h>
+#include <csp/arch/csp_clock.h>
+#include <csp/arch/csp_time.h>
+#include <csp/arch/csp_malloc.h>
+#include <csp/arch/csp_queue.h>
+#include <csp/arch/csp_semaphore.h>
+
+#include <stdlib.h>
+
+static bool thread_executed = false;
+
+void csp_assert_fail_action(const char *assertion, const char *file, int line) {
+    printf("assertion: [%s], file: %s:%d\r\n", assertion, file, line);
+    exit(1);
+}
+
+CSP_DEFINE_TASK(thread_func) {
+    csp_log_info("Thread started");
+    thread_executed = true;
+    csp_sleep_ms(10000); // safty - ensure process terminates
+    exit(1);
+    return CSP_TASK_RETURN;
+}
+
+int main(int argc, char * argv[]) {
+
+    // debug/log - enable all levels
+    for (int i = 0; i <= CSP_LOCK; ++i) {
+        csp_debug_set_level(i, true);
+    }
+    csp_log_error("csp_log_error(...), level: %d", CSP_ERROR);
+    csp_log_warn("csp_log_warn(...), level: %d", CSP_WARN);
+    csp_log_info("csp_log_info((...), level: %d", CSP_INFO);
+    csp_log_buffer("csp_log_buffer(...), level: %d", CSP_BUFFER);
+    csp_log_packet("csp_log_packet(...), level: %d", CSP_PACKET);
+    csp_log_protocol("csp_log_protocol(...), level: %d", CSP_PROTOCOL);
+    csp_log_lock("csp_log_lock(...), level: %d", CSP_LOCK);
+
+    // create a thread - csp_thread doesn't support join
+    csp_thread_handle_t thread = 0;
+    int res = csp_thread_create(thread_func, "thread", 0, NULL, 0, &thread);
+    csp_assert(res == CSP_ERR_NONE);
+    csp_assert(thread != 0);
+
+    // clock
+    csp_timestamp_t csp_clock = {};
+    csp_clock_get_time(&csp_clock);
+    csp_assert(csp_clock.tv_sec != 0);
+    csp_log_info("csp_clock_get_time(..) -> sec:nsec = %"PRIu32":%"PRIu32, csp_clock.tv_sec, csp_clock.tv_nsec);
+
+    // relative time
+    const uint32_t msec1 = csp_get_ms();
+    const uint32_t msec2 = csp_get_ms_isr();
+    const uint32_t sec1 = csp_get_s();
+    const uint32_t sec2 = csp_get_s_isr();
+    csp_sleep_ms(2000);
+    csp_assert(csp_get_ms() >= (msec1 + 500));
+    csp_assert(csp_get_ms_isr() >= (msec2 + 500));
+    csp_assert(csp_get_s() >= (sec1 + 1));
+    csp_assert(csp_get_s_isr() >= (sec2 + 1));
+
+    // malloc
+    uint32_t * ptr = csp_malloc(sizeof(*ptr));
+    csp_assert(ptr != NULL);
+    ptr[0] = 10;
+    csp_free(ptr);
+    ptr = csp_calloc(1, sizeof(*ptr));
+    csp_assert(ptr != NULL);
+    csp_assert(*ptr == 0);
+    ptr[0] = 20;
+    csp_free(ptr);
+    
+    // check thread actually executed
+    csp_assert(thread_executed != false);
+
+    // queue handling
+    uint32_t value;
+    csp_queue_handle_t q = csp_queue_create(3, sizeof(value));
+    csp_assert(csp_queue_size(q) == 0);
+    csp_assert(csp_queue_size_isr(q) == 0);
+    csp_assert(csp_queue_dequeue(q, &value, 0) == CSP_QUEUE_ERROR);
+    csp_assert(csp_queue_dequeue(q, &value, 200) == CSP_QUEUE_ERROR);
+    csp_assert(csp_queue_dequeue_isr(q, &value, NULL) == CSP_QUEUE_ERROR);
+    value = 1;
+    csp_assert(csp_queue_enqueue(q, &value, 0) == CSP_QUEUE_OK);
+    value = 2;
+    csp_assert(csp_queue_enqueue(q, &value, 200) == CSP_QUEUE_OK);
+    value = 3;
+    csp_assert(csp_queue_enqueue_isr(q, &value, NULL) == CSP_QUEUE_OK);
+    csp_assert(csp_queue_size(q) == 3);
+    csp_assert(csp_queue_size_isr(q) == 3);
+    value = 10;
+    csp_assert(csp_queue_enqueue(q, &value, 0) == CSP_QUEUE_ERROR);
+    value = 20;
+    csp_assert(csp_queue_enqueue(q, &value, 200) == CSP_QUEUE_ERROR);
+    value = 30;
+    csp_assert(csp_queue_enqueue_isr(q, &value, NULL) == CSP_QUEUE_ERROR);
+    value = 100;
+    csp_assert(csp_queue_dequeue(q, &value, 0) == CSP_QUEUE_OK);
+    csp_assert(value == 1);
+    csp_assert(csp_queue_dequeue(q, &value, 200) == CSP_QUEUE_OK);
+    csp_assert(value == 2);
+    csp_assert(csp_queue_dequeue_isr(q, &value, NULL) == CSP_QUEUE_OK);
+    csp_assert(value == 3);
+    csp_queue_remove(q);
+
+    // mutex - the actual mutex lock can't be tested from a single thread
+    csp_mutex_t m;
+    csp_assert(csp_mutex_create(&m) == CSP_MUTEX_OK);
+    csp_assert(csp_mutex_lock(&m, 0) == CSP_MUTEX_OK);
+#if (CSP_WINDOWS) // implementations differ in return value if already locked
+    csp_assert(csp_mutex_lock(&m, 200) == CSP_MUTEX_OK);
+#else
+    csp_assert(csp_mutex_lock(&m, 200) == CSP_MUTEX_ERROR);
+#endif
+    csp_assert(csp_mutex_unlock(&m) == CSP_MUTEX_OK);
+    csp_assert(csp_mutex_lock(&m, 200) == CSP_MUTEX_OK);
+    csp_assert(csp_mutex_unlock(&m) == CSP_MUTEX_OK);
+    csp_assert(csp_mutex_remove(&m) == CSP_MUTEX_OK);
+
+    // semaphore
+    csp_bin_sem_handle_t s;
+    csp_assert(csp_bin_sem_create(&s) == CSP_SEMAPHORE_OK);
+    csp_assert(csp_bin_sem_wait(&s, 0) == CSP_SEMAPHORE_OK);
+    csp_assert(csp_bin_sem_post(&s) == CSP_SEMAPHORE_OK);
+#if (CSP_POSIX) // implementations differ in return value if already posted/signaled
+    csp_assert(csp_bin_sem_post_isr(&s, NULL) == CSP_SEMAPHORE_OK);
+#else
+    csp_assert(csp_bin_sem_post_isr(&s, NULL) == CSP_SEMAPHORE_ERROR);
+#endif
+    csp_assert(csp_bin_sem_wait(&s, 200) == CSP_SEMAPHORE_OK);
+    csp_assert(csp_bin_sem_wait(&s, 200) == CSP_SEMAPHORE_ERROR);
+    csp_assert(csp_bin_sem_remove(&s) == CSP_SEMAPHORE_OK);
+
+    return 0;
+}

+ 316 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/csp_server_client.c

@@ -0,0 +1,316 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <csp/csp.h>
+#include <csp/arch/csp_thread.h>
+#include <csp/drivers/usart.h>
+#include <csp/drivers/can_socketcan.h>
+#include <csp/interfaces/csp_if_zmqhub.h>
+
+/* Server port, the port the server listens on for incoming connections from the client. */
+#define MY_SERVER_PORT		10
+
+/* Commandline options */
+static uint8_t server_address = 255;
+
+/* test mode, used for verifying that host & client can exchange packets over the loopback interface */
+static bool test_mode = false;
+static unsigned int server_received = 0;
+
+/* Server task - handles requests from clients */
+CSP_DEFINE_TASK(task_server) {
+
+	csp_log_info("Server task started");
+
+	/* Create socket with no specific socket options, e.g. accepts CRC32, HMAC, XTEA, etc. if enabled during compilation */
+	csp_socket_t *sock = csp_socket(CSP_SO_NONE);
+
+	/* Bind socket to all ports, e.g. all incoming connections will be handled here */
+	csp_bind(sock, CSP_ANY);
+
+	/* Create a backlog of 10 connections, i.e. up to 10 new connections can be queued */
+	csp_listen(sock, 10);
+
+	/* Wait for connections and then process packets on the connection */
+	while (1) {
+
+		/* Wait for a new connection, 10000 mS timeout */
+		csp_conn_t *conn;
+		if ((conn = csp_accept(sock, 10000)) == NULL) {
+			/* timeout */
+			continue;
+		}
+
+		/* Read packets on connection, timout is 100 mS */
+		csp_packet_t *packet;
+		while ((packet = csp_read(conn, 50)) != NULL) {
+			switch (csp_conn_dport(conn)) {
+			case MY_SERVER_PORT:
+				/* Process packet here */
+				csp_log_info("Packet received on MY_SERVER_PORT: %s", (char *) packet->data);
+				csp_buffer_free(packet);
+				++server_received;
+				break;
+
+			default:
+				/* Call the default CSP service handler, handle pings, buffer use, etc. */
+				csp_service_handler(conn, packet);
+				break;
+			}
+		}
+
+		/* Close current connection */
+		csp_close(conn);
+
+	}
+
+	return CSP_TASK_RETURN;
+
+}
+/* End of server task */
+
+/* Client task sending requests to server task */
+CSP_DEFINE_TASK(task_client) {
+
+	csp_log_info("Client task started");
+
+	unsigned int count = 0;
+
+	while (1) {
+
+		csp_sleep_ms(test_mode ? 200 : 1000);
+
+		/* Send ping to server, timeout 1000 mS, ping size 100 bytes */
+		int result = csp_ping(server_address, 1000, 100, CSP_O_NONE);
+		csp_log_info("Ping address: %u, result %d [mS]", server_address, result);
+
+		/* Send reboot request to server, the server has no actual implementation of csp_sys_reboot() and fails to reboot */
+		csp_reboot(server_address);
+		csp_log_info("reboot system request sent to address: %u", server_address);
+
+		/* Send data packet (string) to server */
+
+		/* 1. Connect to host on 'server_address', port MY_SERVER_PORT with regular UDP-like protocol and 1000 ms timeout */
+		csp_conn_t * conn = csp_connect(CSP_PRIO_NORM, server_address, MY_SERVER_PORT, 1000, CSP_O_NONE);
+		if (conn == NULL) {
+			/* Connect failed */
+			csp_log_error("Connection failed");
+			return CSP_TASK_RETURN;
+		}
+
+		/* 2. Get packet buffer for message/data */
+		csp_packet_t * packet = csp_buffer_get(100);
+		if (packet == NULL) {
+			/* Could not get buffer element */
+			csp_log_error("Failed to get CSP buffer");
+			return CSP_TASK_RETURN;
+		}
+
+		/* 3. Copy data to packet */
+		snprintf((char *) packet->data, csp_buffer_data_size(), "Hello World (%u)", ++count);
+
+		/* 4. Set packet length */
+		packet->length = (strlen((char *) packet->data) + 1); /* include the 0 termination */
+
+		/* 5. Send packet */
+		if (!csp_send(conn, packet, 1000)) {
+			/* Send failed */
+			csp_log_error("Send failed");
+			csp_buffer_free(packet);
+		}
+
+		/* 6. Close connection */
+		csp_close(conn);
+	}
+
+	return CSP_TASK_RETURN;
+}
+/* End of client task */
+
+/* main - initialization of CSP and start of server/client tasks */
+int main(int argc, char * argv[]) {
+
+    uint8_t address = 1;
+    csp_debug_level_t debug_level = CSP_INFO;
+#if (CSP_HAVE_LIBSOCKETCAN)
+    const char * can_device = NULL;
+#endif
+    const char * kiss_device = NULL;
+#if (CSP_HAVE_LIBZMQ)
+    const char * zmq_device = NULL;
+#endif
+    const char * rtable = NULL;
+    int opt;
+    while ((opt = getopt(argc, argv, "a:d:r:c:k:z:tR:h")) != -1) {
+        switch (opt) {
+            case 'a':
+                address = atoi(optarg);
+                break;
+            case 'd':
+                debug_level = atoi(optarg);
+                break;
+            case 'r':
+                server_address = atoi(optarg);
+                break;
+#if (CSP_HAVE_LIBSOCKETCAN)
+            case 'c':
+                can_device = optarg;
+                break;
+#endif
+            case 'k':
+                kiss_device = optarg;
+                break;
+#if (CSP_HAVE_LIBZMQ)
+            case 'z':
+                zmq_device = optarg;
+                break;
+#endif
+            case 't':
+                test_mode = true;
+                break;
+            case 'R':
+                rtable = optarg;
+                break;
+            default:
+                printf("Usage:\n"
+                       " -a <address>     local CSP address\n"
+                       " -d <debug-level> debug level, 0 - 6\n"
+                       " -r <address>     run client against server address\n"
+                       " -c <can-device>  add CAN device\n"
+                       " -k <kiss-device> add KISS device (serial)\n"
+                       " -z <zmq-device>  add ZMQ device, e.g. \"localhost\"\n"
+                       " -R <rtable>      set routing table\n"
+                       " -t               enable test mode\n");
+                exit(1);
+                break;
+        }
+    }
+
+    /* enable/disable debug levels */
+    for (csp_debug_level_t i = 0; i <= CSP_LOCK; ++i) {
+        csp_debug_set_level(i, (i <= debug_level) ? true : false);
+    }
+
+    csp_log_info("Initialising CSP");
+
+    /* Init CSP with address and default settings */
+    csp_conf_t csp_conf;
+    csp_conf_get_defaults(&csp_conf);
+    csp_conf.address = address;
+    int error = csp_init(&csp_conf);
+    if (error != CSP_ERR_NONE) {
+        csp_log_error("csp_init() failed, error: %d", error);
+        exit(1);
+    }
+
+    /* Start router task with 10000 bytes of stack (priority is only supported on FreeRTOS) */
+    csp_route_start_task(500, 0);
+
+    /* Add interface(s) */
+    csp_iface_t * default_iface = NULL;
+    if (kiss_device) {
+        csp_usart_conf_t conf = {
+            .device = kiss_device,
+            .baudrate = 115200, /* supported on all platforms */
+            .databits = 8,
+            .stopbits = 1,
+            .paritysetting = 0,
+            .checkparity = 0};
+        error = csp_usart_open_and_add_kiss_interface(&conf, CSP_IF_KISS_DEFAULT_NAME,  &default_iface);
+        if (error != CSP_ERR_NONE) {
+            csp_log_error("failed to add KISS interface [%s], error: %d", kiss_device, error);
+            exit(1);
+        }
+    }
+#if (CSP_HAVE_LIBSOCKETCAN)
+    if (can_device) {
+        error = csp_can_socketcan_open_and_add_interface(can_device, CSP_IF_CAN_DEFAULT_NAME, 0, false, &default_iface);
+        if (error != CSP_ERR_NONE) {
+            csp_log_error("failed to add CAN interface [%s], error: %d", can_device, error);
+            exit(1);
+        }
+    }
+#endif
+#if (CSP_HAVE_LIBZMQ)
+    if (zmq_device) {
+        error = csp_zmqhub_init(csp_get_address(), zmq_device, 0, &default_iface);
+        if (error != CSP_ERR_NONE) {
+            csp_log_error("failed to add ZMQ interface [%s], error: %d", zmq_device, error);
+            exit(1);
+        }
+    }
+#endif
+
+    if (rtable) {
+        error = csp_rtable_load(rtable);
+        if (error < 1) {
+            csp_log_error("csp_rtable_load(%s) failed, error: %d", rtable, error);
+            exit(1);
+        }
+    } else if (default_iface) {
+        csp_rtable_set(CSP_DEFAULT_ROUTE, 0, default_iface, CSP_NO_VIA_ADDRESS);
+    } else {
+        /* no interfaces configured - run server and client in process, using loopback interface */
+        server_address = address;
+    }
+
+    printf("Connection table\r\n");
+    csp_conn_print_table();
+
+    printf("Interfaces\r\n");
+    csp_route_print_interfaces();
+
+    printf("Route table\r\n");
+    csp_route_print_table();
+
+    /* Start server thread */
+    if ((server_address == 255) ||  /* no server address specified, I must be server */
+        (default_iface == NULL)) {  /* no interfaces specified -> run server & client via loopback */
+        csp_thread_create(task_server, "SERVER", 1000, NULL, 0, NULL);
+    }
+
+    /* Start client thread */
+    if ((server_address != 255) ||  /* server address specified, I must be client */
+        (default_iface == NULL)) {  /* no interfaces specified -> run server & client via loopback */
+        csp_thread_create(task_client, "CLIENT", 1000, NULL, 0, NULL);
+    }
+
+    /* Wait for execution to end (ctrl+c) */
+    while(1) {
+        csp_sleep_ms(3000);
+
+        if (test_mode) {
+            /* Test mode is intended for checking that host & client can exchange packets over loopback */
+            if (server_received < 5) {
+                csp_log_error("Server received %u packets", server_received);
+                exit(1);
+            }
+            csp_log_info("Server received %u packets", server_received);
+            exit(0);
+        }
+    }
+
+    return 0;
+}

+ 63 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/python_bindings_example_client.py

@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+
+# Build required code:
+# $ ./examples/buildall.py
+#
+# Start zmqproxy (only one instance)
+# $ ./build/zmqproxy
+#
+# Run client against server using ZMQ:
+# $ LD_LIBRARY_PATH=build PYTHONPATH=build python3 examples/python_bindings_example_client.py -z localhost
+#
+
+import os
+import time
+import sys
+import argparse
+
+import csp
+
+
+def getOptions():
+    parser = argparse.ArgumentParser(description="Parses command.")
+    parser.add_argument("-a", "--address", type=int, default=10, help="Local CSP address")
+    parser.add_argument("-c", "--can", help="Add CAN interface")
+    parser.add_argument("-z", "--zmq", help="Add ZMQ interface")
+    parser.add_argument("-s", "--server-address", type=int, default=27, help="Server address")
+    parser.add_argument("-R", "--routing-table", help="Routing table")
+    return parser.parse_args(sys.argv[1:])
+
+
+if __name__ == "__main__":
+
+    options = getOptions()
+
+    csp.init(options.address, "host", "model", "1.2.3", 10, 300)
+
+    if options.can:
+        csp.can_socketcan_init(options.can)
+    if options.zmq:
+        csp.zmqhub_init(options.address, options.zmq)
+        csp.rtable_load("0/0 ZMQHUB")
+    if options.routing_table:
+        csp.rtable_load(options.routing_table)
+
+    csp.route_start_task()
+    time.sleep(0.2)  # allow router task startup
+
+    print("Connections:")
+    csp.print_connections()
+
+    print("Routes:")
+    csp.print_routes()
+
+    print("CMP ident:", csp.cmp_ident(options.server_address))
+
+    print("Ping: %d mS" % csp.ping(options.server_address))
+
+    # transaction
+    outbuf = bytearray().fromhex('01')
+    inbuf = bytearray(1)
+    print ("Exchange data with server using csp_transaction ...")
+    csp.transaction(0, options.server_address, 10, 1000, outbuf, inbuf)
+    print ("  got reply from server [%s]" % (''.join('{:02x}'.format(x) for x in inbuf)))

+ 74 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/python_bindings_example_server.py

@@ -0,0 +1,74 @@
+#!/usr/bin/python3
+
+# Build required code:
+# $ ./examples/buildall.py
+#
+# Start zmqproxy (only one instance)
+# $ ./build/zmqproxy
+#
+# Run server, default enabling ZMQ interface:
+# $ LD_LIBRARY_PATH=build PYTHONPATH=build python3 examples/python_bindings_example_server.py
+#
+
+import os
+import time
+import sys
+import threading
+
+import csp
+
+
+def csp_server():
+    sock = csp.socket()
+    csp.bind(sock, csp.CSP_ANY)
+    csp.listen(sock, 5)
+    while True:
+        # wait for incoming connection
+        conn = csp.accept(sock, csp.CSP_MAX_TIMEOUT)
+        if not conn:
+            continue
+
+        print ("connection: source=%i:%i, dest=%i:%i" % (csp.conn_src(conn),
+                                                         csp.conn_sport(conn),
+                                                         csp.conn_dst(conn),
+                                                         csp.conn_dport(conn)))
+
+        while True:
+            # Read all packets on the connection
+            packet = csp.read(conn, 100)
+            if packet is None:
+                break
+
+            if csp.conn_dport(conn) == 10:
+                # print request
+                data = bytearray(csp.packet_get_data(packet))
+                length = csp.packet_get_length(packet)
+                print ("got packet, len=" + str(length) + ", data=" + ''.join('{:02x}'.format(x) for x in data))
+                # send reply
+                data[0] = data[0] + 1
+                reply = csp.buffer_get(1)
+                csp.packet_set_data(reply, data)
+                csp.sendto_reply(packet, reply, csp.CSP_O_NONE)
+
+            else:
+                # pass request on to service handler
+                csp.service_handler(conn, packet)
+
+
+if __name__ == "__main__":
+
+    # init csp
+    csp.init(27, "test_service", "bindings", "1.2.3", 10, 300)
+    csp.zmqhub_init(27, "localhost")
+    csp.rtable_set(0, 0, "ZMQHUB")
+    csp.route_start_task()
+
+    print("Hostname: %s" % csp.get_hostname())
+    print("Model:    %s" % csp.get_model())
+    print("Revision: %s" % csp.get_revision())
+
+    print("Routes:")
+    csp.print_routes()
+
+    # start CSP server
+    threading.Thread(target=csp_server).start()

+ 115 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/examples/zmqproxy.c

@@ -0,0 +1,115 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <zmq.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include <csp/csp.h>
+
+static void * task_capture(void *ctx) {
+
+    /* Subscriber (RX) */
+    void *subscriber = zmq_socket(ctx, ZMQ_SUB);
+    assert(zmq_connect(subscriber, "tcp://localhost:7000") == 0);
+    assert(zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0) == 0);
+
+    /* Allocated 'raw' CSP packet */
+    csp_packet_t * packet = malloc(1024);
+    assert(packet != NULL);
+
+    while (1) {
+    	zmq_msg_t msg;
+        zmq_msg_init_size(&msg, 1024);
+
+        /* Receive data */
+        if (zmq_msg_recv(&msg, subscriber, 0) < 0) {
+            zmq_msg_close(&msg);
+            csp_log_error("ZMQ: %s\r\n", zmq_strerror(zmq_errno()));
+            continue;
+        }
+
+        int datalen = zmq_msg_size(&msg);
+        if (datalen < 5) {
+            csp_log_warn("ZMQ: Too short datalen: %u\r\n", datalen);
+            while(zmq_msg_recv(&msg, subscriber, ZMQ_NOBLOCK) > 0)
+                zmq_msg_close(&msg);
+            continue;
+        }
+
+        /* Copy the data from zmq to csp */
+        char * satidptr = ((char *) &packet->id) - 1;
+        memcpy(satidptr, zmq_msg_data(&msg), datalen);
+        packet->length = datalen - sizeof(packet->id) - 1;
+
+        csp_log_packet("Input: Src %u, Dst %u, Dport %u, Sport %u, Pri %u, Flags 0x%02X, Size %"PRIu16,
+                       packet->id.src, packet->id.dst, packet->id.dport,
+                       packet->id.sport, packet->id.pri, packet->id.flags, packet->length);
+
+        zmq_msg_close(&msg);
+    }
+}
+
+int main(int argc, char ** argv) {
+
+    csp_debug_level_t debug_level = CSP_PACKET;
+    int opt;
+    while ((opt = getopt(argc, argv, "d:h")) != -1) {
+        switch (opt) {
+            case 'd':
+                debug_level = atoi(optarg);
+                break;
+            default:
+                printf("Usage:\n"
+                       " -d <debug-level> debug level, 0 - 6\n");
+                exit(1);
+                break;
+        }
+    }
+
+    /* enable/disable debug levels */
+    for (csp_debug_level_t i = 0; i <= CSP_LOCK; ++i) {
+        csp_debug_set_level(i, (i <= debug_level) ? true : false);
+    }
+
+    void * ctx = zmq_ctx_new();
+    assert(ctx);
+
+    void *frontend = zmq_socket(ctx, ZMQ_XSUB);
+    assert(frontend);
+    assert(zmq_bind (frontend, "tcp://*:6000") == 0);
+
+    void *backend = zmq_socket(ctx, ZMQ_XPUB);
+    assert(backend);
+    assert(zmq_bind(backend, "tcp://*:7000") == 0);
+
+    pthread_t capworker;
+    pthread_create(&capworker, NULL, task_capture, ctx);
+
+    csp_log_info("Starting ZMQproxy");
+    zmq_proxy(frontend, backend, NULL);
+
+    csp_log_info("Closing ZMQproxy");
+    zmq_ctx_destroy(ctx);
+
+    return 0;
+}

+ 70 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_clock.h

@@ -0,0 +1,70 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_ARCH_CLOCK_H_
+#define _CSP_ARCH_CLOCK_H_
+
+/**
+   @file
+
+   Clock interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Timestamp (cross platform).
+*/
+typedef struct {
+        //! Seconds
+	uint32_t tv_sec;
+        //! Nano-seconds.
+	uint32_t tv_nsec;
+} csp_timestamp_t;
+
+/**
+   Get time.
+
+   This function is 'weak' in libcsp, providing a working implementation for following OS's: POSIX, Windows and Macosx.
+   This function is expected to be equivalent to standard POSIX clock_gettime(CLOCK_REALTIME, ...).
+
+   @param[out] time current time.
+*/
+void csp_clock_get_time(csp_timestamp_t * time);
+
+/**
+   Set time.
+
+   This function is 'weak' in libcsp, providing a working implementation for following OS's: POSIX, Windows and Macosx.
+   This function is expected to be equivalent to standard POSIX clock_settime(CLOCK_REALTIME, ...).
+
+   @param[in] time time to set.
+   @return #CSP_ERR_NONE on success.
+*/
+int csp_clock_set_time(const csp_timestamp_t * time);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 60 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_malloc.h

@@ -0,0 +1,60 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_MALLOC_H_
+#define _CSP_MALLOC_H_
+
+/**
+   @file
+
+   Memory interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Allocate chunk of memory (POSIX).
+   @param[in] size size of memory chunk (bytes).
+   @return Pointer to allocated memory, or NULL on failure.
+*/
+void * csp_malloc(size_t size);
+
+/**
+   Allocate chunk of memory and set it to zero (POSIX).
+   @param[in] nmemb number of members/chunks to allocate.
+   @param[in] size size of memory chunk (bytes).
+   @return Pointer to allocated memory, or NULL on failure.
+*/
+void * csp_calloc(size_t nmemb, size_t size);
+
+/**
+   Free allocated memory (POSIX).
+   @param[in] ptr memory to free. NULL pointer is ignored.
+*/
+void csp_free(void * ptr);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 126 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_queue.h

@@ -0,0 +1,126 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_ARCH_QUEUE_H_
+#define _CSP_ARCH_QUEUE_H_
+
+/**
+   @file
+
+   Queue interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   No error.
+   @note Value is 1!
+*/
+#define CSP_QUEUE_OK 1
+
+/**
+   Queue full.
+   @note Value is 0!
+*/
+#define CSP_QUEUE_FULL 0
+
+/**
+   Queue error.
+   @note Value is 0!
+*/
+#define CSP_QUEUE_ERROR 0
+
+/**
+   Queue handle.
+*/
+typedef void * csp_queue_handle_t;
+
+/**
+   Create queue.
+   @param[in] length max length of queue, number of elements.
+   @param[in] item_size size of queue elements (bytes).
+   @return Create queue on success, otherwise NULL.
+*/
+csp_queue_handle_t csp_queue_create(int length, size_t item_size);
+
+/**
+   Remove/delete queue.
+   @param[in] queue queue.
+*/
+void csp_queue_remove(csp_queue_handle_t queue);
+
+/**
+   Enqueue (back) value.
+   @param[in] handle queue.
+   @param[in] value value to add (by copy)
+   @param[in] timeout timeout, time to wait for free space
+   @return #CSP_QUEUE_OK on success, otherwise a queue error code.
+*/
+int csp_queue_enqueue(csp_queue_handle_t handle, const void *value, uint32_t timeout);
+
+/**
+   Enqueue (back) value from ISR.
+   @param[in] handle queue.
+   @param[in] value value to add (by copy)
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+   @return #CSP_QUEUE_OK on success, otherwise a queue error code.
+*/
+int csp_queue_enqueue_isr(csp_queue_handle_t handle, const void * value, CSP_BASE_TYPE * pxTaskWoken);
+
+/**
+   Dequeue value (front).
+   @param[in] handle queue.
+   @param[out] buf extracted element (by copy).
+   @param[in] timeout timeout, time to wait for element in queue.
+   @return #CSP_QUEUE_OK on success, otherwise a queue error code.
+*/
+int csp_queue_dequeue(csp_queue_handle_t handle, void *buf, uint32_t timeout);
+
+/**
+   Dequeue value (front) from ISR.
+   @param[in] handle queue.
+   @param[out] buf extracted element (by copy).
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+   @return #CSP_QUEUE_OK on success, otherwise a queue error code.
+*/
+int csp_queue_dequeue_isr(csp_queue_handle_t handle, void * buf, CSP_BASE_TYPE * pxTaskWoken);
+
+/**
+   Queue size.
+   @param[in] handle queue.
+   @return Number of elements in the queue.
+*/
+int csp_queue_size(csp_queue_handle_t handle);
+
+/**
+   Queue size from ISR.
+   @param[in] handle queue.
+   @return Number of elements in the queue.
+*/
+int csp_queue_size_isr(csp_queue_handle_t handle);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 206 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_semaphore.h

@@ -0,0 +1,206 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_SEMAPHORE_H_
+#define _CSP_SEMAPHORE_H_
+
+/**
+   @file
+
+   Semaphore and Mutex interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POSIX interface */
+#if (CSP_POSIX || __DOXYGEN__)
+
+#include <pthread.h>
+#include <semaphore.h>
+
+/**
+   Semaphore (or mutex) call OK.
+
+   @note Platform specific (this is Posix) and differs from standard CSP error codes.
+*/
+#define CSP_SEMAPHORE_OK 	1
+/**
+   Semaphore (or mutex) call failed.
+
+   @note Platform specific (this is Posix) and differs from standard CSP error codes.
+*/
+#define CSP_SEMAPHORE_ERROR	2
+
+/**
+   Semaphore handle.
+
+   @note Platform specific (this is Posix)
+*/
+typedef sem_t csp_bin_sem_handle_t;
+/**
+   Mutex handle.
+
+   @note Platform specific (this is Posix)
+*/
+typedef pthread_mutex_t csp_mutex_t;
+
+#endif // CSP_POSIX
+
+/* MAC OS X interface */
+#if (CSP_MACOSX)
+
+#include <pthread.h>
+#include "posix/pthread_queue.h"
+
+#define CSP_SEMAPHORE_OK 	PTHREAD_QUEUE_OK
+#define CSP_SEMAPHORE_ERROR 	PTHREAD_QUEUE_EMPTY
+
+typedef pthread_queue_t * csp_bin_sem_handle_t;
+typedef pthread_queue_t * csp_mutex_t;
+
+#endif // CSP_MACOSX
+
+#if (CSP_WINDOWS)
+
+#include <Windows.h>
+
+#define CSP_SEMAPHORE_OK 	1
+#define CSP_SEMAPHORE_ERROR	2
+
+typedef HANDLE csp_bin_sem_handle_t;
+typedef HANDLE csp_mutex_t;
+
+#endif // CSP_WINDOWS
+
+/* FreeRTOS interface */
+#if (CSP_FREERTOS)
+
+#include <FreeRTOS.h>
+#include <semphr.h>
+
+#define CSP_SEMAPHORE_OK 	pdPASS
+#define CSP_SEMAPHORE_ERROR	pdFAIL
+
+typedef xSemaphoreHandle csp_bin_sem_handle_t;
+typedef xSemaphoreHandle csp_mutex_t;
+
+#endif // CSP_FREERTOS
+
+/**
+   Mutex call OK.
+
+   @note Value is different from standard CSP error codes, see #CSP_SEMAPHORE_OK
+*/
+#define CSP_MUTEX_OK 		CSP_SEMAPHORE_OK
+
+/**
+   Mutex call failed.
+
+   @note Value is different from standard CSP error codes, see #CSP_SEMAPHORE_ERROR
+*/
+#define CSP_MUTEX_ERROR		CSP_SEMAPHORE_ERROR
+
+/**
+   Create/initialize a mutex.
+
+   @param[in] mutex mutex.
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR
+*/
+int csp_mutex_create(csp_mutex_t * mutex);
+
+/**
+   Free a mutex.
+
+   @param[in] mutex mutex.
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR
+*/
+int csp_mutex_remove(csp_mutex_t * mutex);
+
+/**
+   Lock mutex.
+
+   @param[in] mutex mutex
+   @param[in] timeout timeout in mS. Use #CSP_MAX_TIMEOUT for no timeout, e.g. wait forever until locked.
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR
+*/
+int csp_mutex_lock(csp_mutex_t * mutex, uint32_t timeout);
+
+/**
+   Unlock mutex.
+
+   @param[in] mutex mutex
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR
+*/
+int csp_mutex_unlock(csp_mutex_t * mutex);
+
+/**
+   Create/initialize a binary semaphore.
+
+   The semaphore is created in state \a unlocked (value 1).
+
+   On platforms supporting max values, the semaphore is created with a max value of 1, hence the naming \a binary.
+
+   @param[in] sem semaphore
+   @return #CSP_SEMAPHORE_OK on success, otherwise #CSP_SEMAPHORE_ERROR
+*/
+int csp_bin_sem_create(csp_bin_sem_handle_t * sem);
+
+/**
+   Free a semaphore.
+
+   @param[in] sem semaphore.
+   @return #CSP_SEMAPHORE_OK on success, otherwise #CSP_SEMAPHORE_ERROR
+*/
+int csp_bin_sem_remove(csp_bin_sem_handle_t * sem);
+
+/**
+   Wait/lock semaphore.
+
+   @param[in] sem semaphore
+   @param[in] timeout timeout in mS. Use #CSP_MAX_TIMEOUT for no timeout, e.g. wait forever until locked.
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR
+*/
+int csp_bin_sem_wait(csp_bin_sem_handle_t * sem, uint32_t timeout);
+
+/**
+   Signal/unlock semaphore.
+
+   @param[in] sem semaphore
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR
+*/
+int csp_bin_sem_post(csp_bin_sem_handle_t * sem);
+
+/**
+   Signal/unlock semaphore from an ISR context.
+
+   @param[in] sem semaphore
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+   @return #CSP_MUTEX_OK on success, otherwise #CSP_MUTEX_ERROR*
+*/
+int csp_bin_sem_post_isr(csp_bin_sem_handle_t * sem, CSP_BASE_TYPE * pxTaskWoken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 135 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_system.h

@@ -0,0 +1,135 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_SYSTEM_H_
+#define _CSP_SYSTEM_H_
+
+/**
+   @file
+
+   System interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Color mask */
+#define COLOR_MASK_COLOR 	0x0F
+/** Color modifier mask */
+#define COLOR_MASK_MODIFIER	0xF0
+
+/**
+   Color and color modifiers.
+*/
+typedef enum {
+	/* Colors */
+	COLOR_RESET		= 0xF0,
+	COLOR_BLACK		= 0x01,
+	COLOR_RED		= 0x02,
+	COLOR_GREEN		= 0x03,
+	COLOR_YELLOW		= 0x04,
+	COLOR_BLUE		= 0x05,
+	COLOR_MAGENTA		= 0x06,
+	COLOR_CYAN		= 0x07,
+	COLOR_WHITE		= 0x08,
+	/* Modifiers */
+	COLOR_NORMAL		= 0x0F,
+	COLOR_BOLD		= 0x10,
+	COLOR_UNDERLINE		= 0x20,
+	COLOR_BLINK		= 0x30,
+	COLOR_HIDE		= 0x40,
+} csp_color_t;
+
+/**
+   Get task list.
+   Write task list into a pre-allocate buffer. The buffer must be at least the size returned by csp_sys_tasklist_size().
+   @param[out] out pre-allocate buffer for returning task.
+   @return #CSP_ERR_NONE on success.
+*/
+int csp_sys_tasklist(char * out);
+
+/**
+   Get size of task buffer.
+   @return Size of task list buffer to allocate for the csp_sys_tasklist().
+*/
+int csp_sys_tasklist_size(void);
+
+/**
+   Free system memory.
+
+   @return Free system memory (bytes)
+*/
+uint32_t csp_sys_memfree(void);
+
+/**
+   Callback function for system reboot request.
+   @return #CSP_ERR_NONE on success (if function returns at all), or error code.
+*/
+typedef int (*csp_sys_reboot_t)(void);
+
+/**
+   Set system reboot/reset function.
+   Function will be called by csp_sys_reboot().
+   @param[in] reboot callback.
+   @see csp_sys_reboot_using_system(), csp_sys_reboot_using_reboot()
+*/
+void csp_sys_set_reboot(csp_sys_reboot_t reboot);
+
+/**
+   Reboot/reset system.
+   Reboot/resets the system by calling the function set by csp_sys_set_reboot().
+   @return #CSP_ERR_NONE on success (if function returns at all), or error code.
+*/
+int csp_sys_reboot(void);
+
+/**
+   Callback function for system shutdown request.
+   @return #CSP_ERR_NONE on success (if function returns at all), or error code.
+*/
+typedef int (*csp_sys_shutdown_t)(void);
+
+/**
+   Set system shutdown function.
+   Function will be called by csp_sys_shutdown().
+   @param[in] shutdown callback.
+   @see csp_sys_shutdown_using_system(), csp_sys_shutdown_using_reboot()
+*/
+void csp_sys_set_shutdown(csp_sys_shutdown_t shutdown);
+
+/**
+   Shutdown system.
+   Shuts down the system by calling the function set by csp_sys_set_shutdown().
+   @return #CSP_ERR_NONE on success (if function returns at all), or error code.
+*/
+int csp_sys_shutdown(void);
+
+/**
+   Set color on stdout.
+   @param[in] color color.
+*/
+void csp_sys_set_color(csp_color_t color);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 133 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_thread.h

@@ -0,0 +1,133 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_THREAD_H_
+#define _CSP_THREAD_H_
+
+/**
+   @file
+
+   Thread (task) interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  POSIX interface
+*/
+#if (CSP_POSIX || CSP_MACOSX || __DOXYGEN__)
+
+#include <pthread.h>
+
+/**
+   Platform specific thread handle.
+*/
+typedef pthread_t csp_thread_handle_t;
+
+/**
+   Platform specific thread return type.
+*/
+typedef void * csp_thread_return_t;
+
+/**
+   Platform specific thread function.
+   @param[in] parameter parameter to thread function #csp_thread_return_t.
+*/
+typedef csp_thread_return_t (* csp_thread_func_t)(void * parameter);
+
+/**
+   Macro for creating a thread.
+*/
+#define CSP_DEFINE_TASK(task_name) csp_thread_return_t task_name(void * param)
+
+/**
+   Return value for a thread function.
+   Can be used as argument for normal return, eg "return CSP_TASK_RETURN";
+*/
+#define CSP_TASK_RETURN NULL
+
+#endif // CSP_POSIX
+
+/*
+  Windows interface
+*/
+#if (CSP_WINDOWS)
+
+#include <Windows.h>
+
+typedef HANDLE csp_thread_handle_t;
+typedef unsigned int csp_thread_return_t;
+typedef csp_thread_return_t (* csp_thread_func_t)(void *) __attribute__((stdcall));
+
+#define CSP_DEFINE_TASK(task_name) csp_thread_return_t __attribute__((stdcall)) task_name(void * param) 
+#define CSP_TASK_RETURN 0
+
+#endif // CSP_WINDOWS
+
+/*
+  FreeRTOS interface
+*/
+#if (CSP_FREERTOS)
+
+#include <FreeRTOS.h>
+#include <task.h>
+
+typedef xTaskHandle csp_thread_handle_t;
+typedef void csp_thread_return_t;
+typedef csp_thread_return_t (* csp_thread_func_t)(void *);
+
+#define CSP_DEFINE_TASK(task_name) csp_thread_return_t task_name(void * param)
+#define CSP_TASK_RETURN
+
+#endif // CSP_FREERTOS
+
+/**
+   Create thread (task).
+
+   @param[in] func thread function
+   @param[in] name name of thread, supported on: FreeRTOS.
+   @param[in] stack_size stack size, supported on: posix (bytes), FreeRTOS (words, word = 4 bytes).
+   @param[in] parameter parameter for thread function.
+   @param[in] priority thread priority, supported on: FreeRTOS.
+   @param[out] handle reference to created thread.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_thread_create(csp_thread_func_t func, const char * const name, unsigned int stack_size, void * parameter, unsigned int priority, csp_thread_handle_t * handle);
+
+/**
+   Exit current thread.
+   @note Not supported on all platforms.
+*/
+void csp_thread_exit(void);
+
+/**
+   Sleep X mS.
+   @param[in] time_ms mS to sleep.
+*/
+void csp_sleep_ms(unsigned int time_ms);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 73 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/csp_time.h

@@ -0,0 +1,73 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_TIME_H_
+#define _CSP_TIME_H_
+
+/**
+   @file
+
+   Relative time interface.
+
+   @note The returned values will eventually wrap.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Return uptime in seconds.
+   The function uses csp_get_s() for relative time. First time the function is called (by csp_init()), it saves an offset
+   in case the platform doesn't start from 0, e.g. Linux.
+   @return uptime in seconds.
+*/
+uint32_t csp_get_uptime_s(void);
+
+/**
+   Return current time in mS.
+   @return mS.
+*/
+uint32_t csp_get_ms(void);
+
+/**
+   Return current time in mS (from ISR).
+   @return mS.
+*/
+uint32_t csp_get_ms_isr(void);
+
+/**
+   Return current time in seconds.
+   @return seconds.
+*/
+uint32_t csp_get_s(void);
+
+/**
+   Return current time in seconds (from ISR).
+   @return seconds.
+*/
+uint32_t csp_get_s_isr(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 59 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/posix/csp_system.h

@@ -0,0 +1,59 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_ARCH_POSIX_CSP_SYSTEM_H_
+#define _CSP_ARCH_POSIX_CSP_SYSTEM_H_
+
+/**
+   @file
+
+   Posix extension to system interface.
+*/
+
+#include <csp/arch/csp_system.h>
+
+#ifdef __cplusplus
+yextern "C" {
+#endif
+
+/**
+   Executes 'system("reboot")' for system reboot.
+*/
+int csp_sys_reboot_using_system(void);
+
+/**
+   Executes 'sync() and reboot(LINUX_REBOOT_CMD_RESTART)' for system reboot.
+*/
+int csp_sys_reboot_using_reboot(void);
+
+/**
+   Executes 'system("halt")' for system shutdown.
+*/
+int csp_sys_shutdown_using_system(void);
+
+/**
+   Executes 'sync() and reboot(LINUX_REBOOT_CMD_HALT)' for system shutdown.
+*/
+int csp_sys_shutdown_using_reboot(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 114 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/arch/posix/pthread_queue.h

@@ -0,0 +1,114 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PTHREAD_QUEUE_H_
+#define _PTHREAD_QUEUE_H_
+
+/**
+   @file
+
+   Queue implemented using pthread locks and conds.
+
+   Inspired by c-pthread-queue by Matthew Dickinson: http://code.google.com/p/c-pthread-queue/
+*/
+
+#include <pthread.h>
+
+#include <csp/arch/csp_queue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Queue error codes.
+   @{
+*/
+/**
+   General error code - something went wrong.
+*/
+#define PTHREAD_QUEUE_ERROR CSP_QUEUE_ERROR
+/**
+   Queue is empty - cannot extract element.
+*/
+#define PTHREAD_QUEUE_EMPTY CSP_QUEUE_ERROR
+/**
+   Queue is full - cannot insert element.
+*/
+#define PTHREAD_QUEUE_FULL CSP_QUEUE_ERROR
+/**
+   Ok - no error.
+*/
+#define PTHREAD_QUEUE_OK CSP_QUEUE_OK
+/** @{ */
+
+/**
+   Queue handle.
+*/
+typedef struct pthread_queue_s {
+    //! Memory area.
+    void * buffer;
+    //! Memory size.
+    int size;
+    //! Item/element size.
+    int item_size;
+    //! Items/elements in queue.
+    int items;
+    //! Insert point.
+    int in;
+    //! Extract point.
+    int out;
+    //! Lock.
+    pthread_mutex_t mutex;
+    //! Wait because queue is full (insert).
+    pthread_cond_t cond_full;
+    //! Wait because queue is empty (extract).
+    pthread_cond_t cond_empty;
+} pthread_queue_t;
+
+/**
+   Create queue.
+*/
+pthread_queue_t * pthread_queue_create(int length, size_t item_size);
+
+/**
+   Delete queue.
+*/
+void pthread_queue_delete(pthread_queue_t * q);
+
+/**
+   Enqueue/insert element.
+*/
+int pthread_queue_enqueue(pthread_queue_t * queue, const void * value, uint32_t timeout);
+
+/**
+   Dequeue/extract element.
+*/
+int pthread_queue_dequeue(pthread_queue_t * queue, void * buf, uint32_t timeout);
+
+/**
+   Return number of elements in the queue.
+*/
+int pthread_queue_items(pthread_queue_t * queue);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 82 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/crypto/csp_hmac.h

@@ -0,0 +1,82 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_CRYPTO_HMAC_H_
+#define _CSP_CRYPTO_HMAC_H_
+
+/**
+   @file
+   HMAC support.
+
+   Hash-based Message Authentication Code - based on code from libtom.org.
+*/
+
+#include <csp/crypto/csp_sha1.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Number of bytes from the HMAC calculation, that is appended to the CSP message.
+*/
+#define CSP_HMAC_LENGTH	4
+
+/**
+ * Append HMAC to packet
+ * @param packet CSP packet, must be valid.
+ * @param include_header use header in hmac calculation (this will not modify the flags field)
+ * @return #CSP_ERR_NONE on success, otherwise an error code.
+ */
+int csp_hmac_append(csp_packet_t * packet, bool include_header);
+
+/**
+ * Verify HMAC of packet
+ * @param packet CSP packet, must be valid.
+ * @param include_header use header in hmac calculation (this will not modify the flags field)
+ * @return #CSP_ERR_NONE on success, otherwise an error code.
+ */
+int csp_hmac_verify(csp_packet_t * packet, bool include_header);
+
+/**
+ * Calculate HMAC on buffer
+ *
+ * This function is used by append/verify but cal also be called separately.
+ * @param key HMAC key
+ * @param keylen HMAC key length
+ * @param data pointer to data
+ * @param datalen lehgth of data
+ * @param[out] hmac calculated HMAC hash, minimum #CSP_SHA1_DIGESTSIZE bytes.
+ * @return #CSP_ERR_NONE on success, otherwise an error code.
+ */
+int csp_hmac_memory(const void * key, uint32_t keylen, const void * data, uint32_t datalen, uint8_t * hmac);
+
+/**
+ * Save a copy of the key string for use by the append/verify functions
+ * @param key HMAC key
+ * @param keylen HMAC key length
+ * @return #CSP_ERR_NONE on success, otherwise an error code.
+ */
+int csp_hmac_set_key(const void * key, uint32_t keylen);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 89 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/crypto/csp_sha1.h

@@ -0,0 +1,89 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_CRYPTO_SHA1_H_
+#define _CSP_CRYPTO_SHA1_H_
+
+/**
+   @file
+   SHA1 support.
+
+   Code originally from Python's SHA1 Module, who based it on libtom.org.
+*/
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** The SHA1 block size in bytes */
+#define CSP_SHA1_BLOCKSIZE	64
+
+/** The SHA1 digest (hash) size in bytes */
+#define CSP_SHA1_DIGESTSIZE	20
+
+/**
+   SHA1 state.
+*/
+typedef struct {
+        //! Internal SHA1 state.
+	uint64_t length;
+        //! Internal SHA1 state.
+	uint32_t state[5];
+        //! Internal SHA1 state.
+	uint32_t curlen;
+        //! Internal SHA1 state.
+	uint8_t  buf[CSP_SHA1_BLOCKSIZE];
+} csp_sha1_state_t;
+
+/**
+   Initialize the hash state
+   @param[in] state hash state.
+*/
+void csp_sha1_init(csp_sha1_state_t * state);
+
+/**
+   Process a block of memory through the hash.
+   @param[in] state hash state
+   @param[in] data data.
+   @param[in] length length of \a data.
+*/
+void csp_sha1_process(csp_sha1_state_t * state, const void * data, uint32_t length);
+
+/**
+   Terminate the hash calculation and get the SHA1.
+   @param[in] state hash state
+   @param[out] sha1 user supplied buffer of minimum #CSP_SHA1_DIGESTSIZE bytes.
+*/
+void csp_sha1_done(csp_sha1_state_t * state, uint8_t * sha1);
+
+/**
+   Calculate SHA1 hash of block of memory.
+   @param[in] data data.
+   @param[in] length length of \a data.
+   @param[out] sha1 user supplied buffer of minimum #CSP_SHA1_DIGESTSIZE bytes.
+*/
+void csp_sha1_memory(const void * data, uint32_t length, uint8_t * sha1);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 78 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/crypto/csp_xtea.h

@@ -0,0 +1,78 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_CRYPTO_XTEA_H_
+#define _CSP_CRYPTO_XTEA_H_
+
+/**
+   @file
+   XTEA support.
+*/
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Set XTEA key
+   @param[in] key XTEA key
+   @param[in] keylen length of key
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_xtea_set_key(const void * key, uint32_t keylen);
+
+/**
+   XTEA encrypt byte array
+   @param[in] data data to be encrypted.
+   @param[in] len Length of \a data.
+   @param[in] iv Initialization vector
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_xtea_encrypt(void * data, uint32_t len, uint32_t iv[2]);
+
+/**
+   XTEA encrypt message.
+   @param packet CSP packet, must be valid.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_xtea_encrypt_packet(csp_packet_t * packet);
+
+/**
+   Decrypt XTEA encrypted byte array.
+   @param[in,out] encrypted data be decrypted.
+   @param[in] len length of \a encrypted data.
+   @param[in] iv Initialization vector.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_xtea_decrypt(void * encrypted, uint32_t len, uint32_t iv[2]);
+
+/**
+   XTEA decrypt message.
+   @param packet CSP packet, must be valid.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_xtea_decrypt_packet(csp_packet_t * packet);
+    
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 504 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp.h

@@ -0,0 +1,504 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_H_
+#define _CSP_H_
+
+/**
+   @file
+   CSP.
+*/
+
+#include <csp/csp_platform.h>
+#include <csp/csp_error.h>
+#include <csp/csp_debug.h>
+#include <csp/csp_buffer.h>
+#include <csp/csp_rtable.h>
+#include <csp/csp_iflist.h>
+#include <csp/csp_sfp.h>
+#include <csp/csp_promisc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   CSP configuration.
+   @see csp_init()
+*/
+typedef struct csp_conf_s {
+
+	uint8_t address;		/**< CSP address of the system */
+
+	const char *hostname;		/**< Host name, returned by the #CSP_CMP_IDENT request */
+	const char *model;		/**< Model, returned by the #CSP_CMP_IDENT request */
+	const char *revision;		/**< Revision, returned by the #CSP_CMP_IDENT request */
+	const char *date;		/**< Build date, returned by the #CSP_CMP_IDENT request */
+	const char *time;		/**< Build time, returned by the #CSP_CMP_IDENT request */
+
+	uint16_t conn_max;		/**< Max number of connections. A fixed connection array is allocated by csp_init() */
+	uint16_t conn_queue_length;	/**< Max queue length (max queued Rx messages). */
+	uint16_t fifo_length;		/**< Length of incoming message queue, used for handover to router task. */
+	uint8_t port_max_bind;		/**< Max/highest port for use with csp_bind() */
+	uint8_t rdp_max_window;		/**< Max RDP window size */
+	uint16_t buffers;		/**< Number of CSP buffers */
+	uint16_t buffer_data_size;	/**< Data size of a CSP buffer. Total size will be sizeof(#csp_packet_t) + data_size. */
+	uint32_t conn_dfl_so;		/**< Default connection options. Options will always be or'ed onto new connections, see csp_connect() */
+} csp_conf_t;
+
+/**
+   Get default CSP configuration.
+*/
+static inline void csp_conf_get_defaults(csp_conf_t * conf) {
+	conf->address = 10;
+	conf->hostname = "hostname";
+	conf->model = "model";
+	conf->revision = "revision";
+	conf->date = __DATE__;
+	conf->time = __TIME__;
+	conf->conn_max = 600;
+	conf->conn_queue_length = 600;
+	conf->fifo_length = 600;
+	conf->port_max_bind = 50;
+	conf->rdp_max_window = 20;
+	conf->buffers = 600;
+	conf->buffer_data_size = 213*8;
+	conf->conn_dfl_so = CSP_O_NONE;
+}
+
+/**
+   Initialize CSP.
+   This will configure/allocate basic structures.
+   @param[in] conf configuration. A shallow copy will be done of the provided configuration, i.e. only copy references to strings/structers.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_init(const csp_conf_t * conf);
+
+/**
+   Free allocated resorces in CSP.
+   This is intended for testing of CSP, in order to be able re-initialize CSP by calling csp_init() again.
+*/
+void csp_free_resources(void);
+
+/**
+   Get a \a read-only reference to the active CSP configuration.
+   @return Active CSP configuration (read-only).
+*/
+const csp_conf_t * csp_get_conf(void);
+
+/**
+   Get the system's own address.
+   @return system's own address
+*/
+uint8_t csp_get_address(void);
+
+/**
+   Create a CSP socket endpoint.
+   @param[in] opts socket options, see @ref CSP_SOCKET_OPTIONS.
+   @return Socket on success, NULL on failure
+*/
+csp_socket_t *csp_socket(uint32_t opts);
+
+/**
+   Wait/accept a new connection.
+   @param[in] socket socket to accept connections on, created by calling csp_socket().
+   @param[in] timeout timeout in mS to wait for a connection, use #CSP_MAX_TIMEOUT for infinite timeout.
+   @return New connection on success, NULL on failure or timeout.
+*/
+csp_conn_t *csp_accept(csp_socket_t *socket, uint32_t timeout);
+
+/**
+   Read packet from a connection.
+   This fuction will wait on the connection's RX queue for the specified timeout.
+   @param[in] conn connection
+   @param[in] timeout timeout in mS to wait for a packet, use #CSP_MAX_TIMEOUT for infinite timeout.
+   @return Packet or NULL in case of failure or timeout.
+*/
+csp_packet_t *csp_read(csp_conn_t *conn, uint32_t timeout);
+
+/**
+   Send packet on a connection.
+   @param[in] conn connection
+   @param[in] packet packet to send
+   @param[in] timeout unused as of CSP version 1.6
+   @return 1 on success, 0 on failure and the packet must be freed by calling csp_buffer_free()
+*/
+int csp_send(csp_conn_t *conn, csp_packet_t *packet, uint32_t timeout);
+
+/**
+   Send a packet on an already established connection, but free it if transmission fails.
+   @param[in] conn connection
+   @param[in] packet packet to send
+   @param[in] timeout unused as of CSP version 1.6
+   @return returns 1 if successful and 0 otherwise. The packet MUST not be accessed after calling this function.
+ */
+int csp_send_free(csp_conn_t *conn, csp_packet_t *packet, uint32_t timeout);
+
+/**
+   Change the default priority of the connection and send a packet.
+   @note The priority of the connection will be changed. If you need to change it back, call csp_send_prio() again.
+
+   @param[in] prio priority to set on the connection
+   @param[in] conn connection
+   @param[in] packet packet to send
+   @param[in] timeout unused as of CSP version 1.6
+   @return 1 on success, 0 on failure and the packet must be freed by calling csp_buffer_free()
+ */
+int csp_send_prio(uint8_t prio, csp_conn_t *conn, csp_packet_t *packet, uint32_t timeout);
+
+/**
+   Perform an entire request & reply transaction.
+   Creates a connection, send \a outbuf, wait for reply, copy reply to \a inbuf and close the connection.
+   @param[in] prio priority, see #csp_prio_t
+   @param[in] dst destination address
+   @param[in] dst_port destination port
+   @param[in] timeout timeout in mS to wait for a reply
+   @param[in] outbuf outgoing data (request)
+   @param[in] outlen length of data in \a outbuf (request)
+   @param[out] inbuf user provided buffer for receiving data (reply)
+   @param[in] inlen length of expected reply, -1 for unknown size (inbuf MUST be large enough), 0 for no reply.
+   @param[in] opts connection options, see @ref CSP_CONNECTION_OPTIONS.
+   @return 1 or reply size on success, 0 on failure (error, incoming length does not match, timeout)
+*/
+int csp_transaction_w_opts(uint8_t prio, uint8_t dst, uint8_t dst_port, uint32_t timeout, void *outbuf, int outlen, void *inbuf, int inlen, uint32_t opts);
+
+/**
+   Perform an entire request & reply transaction.
+   Creates a connection, send \a outbuf, wait for reply, copy reply to \a inbuf and close the connection.
+   @param[in] prio priority, see #csp_prio_t
+   @param[in] dest destination address
+   @param[in] port destination port
+   @param[in] timeout timeout in mS to wait for a reply
+   @param[in] outbuf outgoing data (request)
+   @param[in] outlen length of data in \a outbuf (request)
+   @param[out] inbuf user provided buffer for receiving data (reply)
+   @param[in] inlen length of expected reply, -1 for unknown size (inbuf MUST be large enough), 0 for no reply.
+   @return 1 or reply size on success, 0 on failure (error, incoming length does not match, timeout)
+*/
+static inline int csp_transaction(uint8_t prio, uint8_t dest, uint8_t port, uint32_t timeout, void * outbuf, int outlen, void * inbuf, int inlen) {
+	return csp_transaction_w_opts(prio, dest, port, timeout, outbuf, outlen, inbuf, inlen, 0);
+}
+
+/**
+   Perform an entire request & reply transaction on an existing connection.
+   Send \a outbuf, wait for reply and copy reply to \a inbuf.
+   @param[in] conn connection
+   @param[in] timeout timeout in mS to wait for a reply
+   @param[in] outbuf outgoing data (request)
+   @param[in] outlen length of data in \a outbuf (request)
+   @param[out] inbuf user provided buffer for receiving data (reply)
+   @param[in] inlen length of expected reply, -1 for unknown size (inbuf MUST be large enough), 0 for no reply.
+   @return 1 or reply size on success, 0 on failure (error, incoming length does not match, timeout)
+*/
+int csp_transaction_persistent(csp_conn_t *conn, uint32_t timeout, void *outbuf, int outlen, void *inbuf, int inlen);
+
+/**
+   Read data from a connection-less server socket.
+   @param[in] socket connection-less socket.
+   @param[in] timeout timeout in mS to wait for a packet, use #CSP_MAX_TIMEOUT for infinite timeout.
+   @return Packet on success, or NULL on failure or timeout.
+*/
+csp_packet_t *csp_recvfrom(csp_socket_t *socket, uint32_t timeout);
+
+/**
+   Send a packet (without connection).
+   @param[in] prio packet priority, see #csp_prio_t
+   @param[in] dst destination address
+   @param[in] dst_port destination port
+   @param[in] src_port source port
+   @param[in] opts connection options, see @ref CSP_CONNECTION_OPTIONS.
+   @param[in] packet packet to send
+   @param[in] timeout unused as of CSP version 1.6
+   @return #CSP_ERR_NONE on success, otherwise an error code and the packet must be freed by calling csp_buffer_free().
+*/
+int csp_sendto(uint8_t prio, uint8_t dst, uint8_t dst_port, uint8_t src_port, uint32_t opts, csp_packet_t *packet, uint32_t timeout);
+
+/**
+   Send a packet as a reply to a request (without a connection).
+   Calls csp_sendto() with the source address and port from the request.
+   @param[in] request incoming request
+   @param[in] reply reply packet
+   @param[in] opts connection options, see @ref CSP_CONNECTION_OPTIONS.
+   @param[in] timeout unused as of CSP version 1.6
+   @return #CSP_ERR_NONE on success, otherwise an error code and the reply must be freed by calling csp_buffer_free().
+*/
+int csp_sendto_reply(const csp_packet_t * request, csp_packet_t * reply, uint32_t opts, uint32_t timeout);
+
+/**
+   Establish outgoing connection.
+   The call will return immediately, unless it is a RDP connection (#CSP_O_RDP) in which case it will wait until the other
+   end acknowleges the connection (timeout is determined by the current connection timeout set by csp_rdp_set_opt()).
+   @param[in] prio priority, see #csp_prio_t
+   @param[in] dst Destination address
+   @param[in] dst_port Destination port
+   @param[in] timeout unused.
+   @param[in] opts connection options, see @ref CSP_CONNECTION_OPTIONS.
+   @return Established connection or NULL on failure (no free connections, timeout).
+*/
+csp_conn_t *csp_connect(uint8_t prio, uint8_t dst, uint8_t dst_port, uint32_t timeout, uint32_t opts);
+
+/**
+   Close an open connection.
+   Any packets in the RX queue will be freed.
+   @param[in] conn connection. Closing a NULL connection is acceptable.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_close(csp_conn_t *conn);
+
+/**
+   Return destination port of connection.
+   @param[in] conn connection
+   @return destination port of an incoming connection
+*/
+int csp_conn_dport(csp_conn_t *conn);
+
+/**
+   Return source port of connection.
+   @param conn connection
+   @return source port of an incoming connection
+*/
+int csp_conn_sport(csp_conn_t *conn);
+
+/**
+   Return destination address of connection.
+   @param[in] conn connection
+   @return destination address of an incoming connection
+*/
+int csp_conn_dst(csp_conn_t *conn);
+
+/**
+   Return source address of connection.
+   @param conn connection
+   @return source address of an incoming connection
+*/
+int csp_conn_src(csp_conn_t *conn);
+
+/**
+   Return flags of connection.
+   @param[in] conn connection
+   @return flags of an incoming connection, see @ref CSP_HEADER_FLAGS
+*/
+int csp_conn_flags(csp_conn_t *conn);
+
+/**
+   Set socket to listen for incoming connections.
+   @param[in] socket socket
+   @param[in] backlog max length of backlog queue. The backlog queue holds incoming connections, waiting to be returned by call to csp_accept().
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_listen(csp_socket_t *socket, size_t backlog);
+
+/**
+   Bind port to socket.
+   @param[in] socket socket to bind port to
+   @param[in] port port number to bind, use #CSP_ANY for all ports. Bindnig to a specific will take precedence over #CSP_ANY.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_bind(csp_socket_t *socket, uint8_t port);
+
+/**
+   Start the router task.
+   The router task calls csp_route_work() to do the actual work.
+   @param[in] task_stack_size stack size for the task, see csp_thread_create() for details on the stack size parameter.
+   @param[in] task_priority priority for the task, see csp_thread_create() for details on the stack size parameter.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_route_start_task(unsigned int task_stack_size, unsigned int task_priority);
+
+/**
+   Route packet from the incoming router queue and check RDP timeouts.
+   In order for incoming packets to routed and RDP timeouts to be checked, this function must be called reguarly.
+   If the router task is started by calling csp_route_start_task(), there function should not be called.
+   @param[in] timeout timeout in mS to wait for an incoming packet.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_route_work(uint32_t timeout);
+
+/**
+   Start the bridge task.
+   The bridge will copy packets between interfaces, i.e. packets received on A will be sent on B, and vice versa.
+   @param[in] task_stack_size stack size for the task, see csp_thread_create() for details on the stack size parameter.
+   @param[in] task_priority priority for the task, see csp_thread_create() for details on the stack size parameter.
+   @param[in] if_a interface/side A
+   @param[in] if_b interface/side B
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_bridge_start(unsigned int task_stack_size, unsigned int task_priority, csp_iface_t * if_a, csp_iface_t * if_b);
+
+/**
+   Handle CSP service request.
+   If the given packet is a service-request (the destination port matches one of CSP service ports #csp_service_port_t),
+   the packet will be processed by the specific CSP service handler.
+   The packet will either process it or free it, so this function is typically called in the last "default" clause of
+   a switch/case statement in a CSP listener task.
+   In order to listen to csp service ports, bind your listener to the specific services ports #csp_service_port_t or
+   use #CSP_ANY to all ports.
+   @param[in] conn connection
+   @param[in] packet first packet, obtained by using csp_read()
+*/
+void csp_service_handler(csp_conn_t *conn, csp_packet_t *packet);
+
+/**
+   Send a single ping/echo packet.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in ms to wait for reply.
+   @param[in] size payload size in bytes.
+   @param[in] opts connection options, see @ref CSP_CONNECTION_OPTIONS.
+   @return >0 = echo time in mS on success, otherwise -1 for error.
+*/
+int csp_ping(uint8_t node, uint32_t timeout, unsigned int size, uint8_t opts);
+
+/**
+   Send a single ping/echo packet without waiting for reply.
+   Payload is 1 byte.
+   @param[in] node address of subsystem.
+*/
+void csp_ping_noreply(uint8_t node);
+
+/**
+   Request process list.
+   @note This is currently only supported on FreeRTOS systems.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for replies. The function will not return until the timeout occurrs.
+*/
+void csp_ps(uint8_t node, uint32_t timeout);
+
+/**
+   Request free memory.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply.
+   @param[out] size free memory on subsystem.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_get_memfree(uint8_t node, uint32_t timeout, uint32_t * size);
+
+/**
+   Request free memory and print to stdout.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply.
+*/
+void csp_memfree(uint8_t node, uint32_t timeout);
+
+/**
+   Request free buffers.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply.
+   @param[out] size free buffers.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_get_buf_free(uint8_t node, uint32_t timeout, uint32_t * size);
+
+/**
+   Request free buffers and print to stdout.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply.
+*/
+void csp_buf_free(uint8_t node, uint32_t timeout);
+
+/**
+   Reboot subsystem.
+   If handled by the standard CSP service handler, the reboot handler set by csp_sys_set_reboot() on the subsystem, will be invoked.
+   @param[in] node address of subsystem.
+*/
+void csp_reboot(uint8_t node);
+
+/**
+   Shutdown subsystem.
+   If handled by the standard CSP service handler, the shutdown handler set by csp_sys_set_shutdown() on the subsystem, will be invoked.
+   @param[in] node address of subsystem.
+*/
+void csp_shutdown(uint8_t node);
+
+/**
+   Request uptime and print to stdout.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply.
+*/
+void csp_uptime(uint8_t node, uint32_t timeout);
+
+/**
+   Request uptime
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply.
+   @param[out] uptime uptime in seconds.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_get_uptime(uint8_t node, uint32_t timeout, uint32_t * uptime);
+
+/**
+   Set RDP options.
+   The RDP options are used from the connecting/client side. When a RDP connection is established, the client tranmits the options to the server.
+   @param[in] window_size window size
+   @param[in] conn_timeout_ms connection timeout in mS
+   @param[in] packet_timeout_ms packet timeout in mS.
+   @param[in] delayed_acks enable/disable delayed acknowledgements.
+   @param[in] ack_timeout acknowledgement timeout when delayed ACKs is enabled
+   @param[in] ack_delay_count send acknowledgement for every ack_delay_count packets.
+*/
+void csp_rdp_set_opt(unsigned int window_size, unsigned int conn_timeout_ms,
+		unsigned int packet_timeout_ms, unsigned int delayed_acks,
+		unsigned int ack_timeout, unsigned int ack_delay_count);
+
+/**
+   Get RDP options.
+   @see csp_rdp_set_opt()
+   @param[out] window_size Window size
+   @param[out] conn_timeout_ms connection timeout in ms
+   @param[out] packet_timeout_ms packet timeout in ms
+   @param[out] delayed_acks enable/disable delayed acknowledgements
+   @param[out] ack_timeout acknowledgement timeout when delayed ACKs is enabled
+   @param[out] ack_delay_count send acknowledgement for every ack_delay_count packets
+*/
+void csp_rdp_get_opt(unsigned int *window_size, unsigned int *conn_timeout_ms,
+		unsigned int *packet_timeout_ms, unsigned int *delayed_acks,
+		unsigned int *ack_timeout, unsigned int *ack_delay_count);
+
+/**
+   Print connection table to stdout.
+*/
+void csp_conn_print_table(void);
+
+/**
+   Print connection table to string.
+*/
+int csp_conn_print_table_str(char * str_buf, int str_size);
+
+/**
+   Print buffer usage table to stdout.
+*/
+void csp_buffer_print_table(void);
+
+/**
+   Hex dump memory to stdout.
+   @param[in] desc description printed on first line.
+   @param[in] addr memory address.
+   @param[in] len number of bytes to dump, starting from \a addr.
+*/
+void csp_hex_dump(const char *desc, void *addr, int len);
+
+/**
+   Set platform specific memory copy function.
+*/
+void csp_cmp_set_memcpy(csp_memcpy_fnc_t fnc);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 94 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_buffer.h

@@ -0,0 +1,94 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_BUFFER_H_
+#define _CSP_BUFFER_H_
+
+/**
+   @file
+   Message buffer.
+*/
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Get free buffer (from task context).
+
+   @param[in] data_size minimum data size of requested buffer.
+   @return Buffer (pointer to #csp_packet_t) or NULL if no buffers available or size too big.
+*/
+void * csp_buffer_get(size_t data_size);
+
+/**
+   Get free buffer (from ISR context).
+
+   @param[in] data_size minimum data size of requested buffer.
+   @return Buffer (pointer to #csp_packet_t) or NULL if no buffers available or size too big.
+*/
+void * csp_buffer_get_isr(size_t data_size);
+
+/**
+   Free buffer (from task context).
+   @param[in] buffer buffer to free. NULL is handled gracefully.
+*/
+void csp_buffer_free(void *buffer);
+
+/**
+   Free buffer (from ISR context).
+   @param[in] buffer buffer to free. NULL is handled gracefully.
+*/
+void csp_buffer_free_isr(void *buffer);
+
+/**
+   Clone an existing buffer.
+   The existing \a buffer content is copied to the new buffer.
+   @param[in] buffer buffer to clone.
+   @return cloned buffer on success, or NULL on failure.
+*/
+void * csp_buffer_clone(void *buffer);
+
+/**
+   Return number of remaining/free buffers.
+   The number of buffers is set by csp_init().
+   @return number of remaining/free buffers
+*/
+int csp_buffer_remaining(void);
+
+/**
+   Return the size of a CSP buffer.
+   @return size of a CSP buffer, sizeof(#csp_packet_t) + data_size.
+*/
+size_t csp_buffer_size(void);
+
+/**
+   Return the data size of a CSP buffer.
+   The data size is set by csp_init().
+   @return data size of a CSP buffer
+*/
+size_t csp_buffer_data_size(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 214 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_cmp.h

@@ -0,0 +1,214 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_CMP_H_
+#define _CSP_CMP_H_
+
+/**
+   @file
+   CSP Management Protocol (CMP).
+*/
+
+#include <csp/csp.h>
+#include <csp/arch/csp_clock.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   CMP type.
+   @{
+*/
+/**
+   CMP request.
+*/
+#define CSP_CMP_REQUEST 0x00
+/**
+   CMP reply.
+*/
+#define CSP_CMP_REPLY   0xff
+/**@}*/
+
+/**
+   CMP requests.
+   @{
+*/
+/**
+   CMP request codes.
+*/
+/**
+   Request identification, compile time, revision, hostname and model.
+*/
+#define CSP_CMP_IDENT 1
+/**
+   Set/configure routing.
+*/
+#define CSP_CMP_ROUTE_SET 2
+/**
+   Request interface statistics.
+*/
+#define CSP_CMP_IF_STATS 3
+/**
+   Peek/read data from memory.
+*/
+#define CSP_CMP_PEEK 4
+/**
+   Poke/write data from memory.
+*/
+#define CSP_CMP_POKE 5
+/**
+   Get/set clock.
+*/
+#define CSP_CMP_CLOCK 6
+/**@}*/
+
+/**
+   CMP identification - max revision length.
+*/
+#define CSP_CMP_IDENT_REV_LEN  20
+/**
+   CMP identification - max date length.
+*/
+#define CSP_CMP_IDENT_DATE_LEN 12
+/**
+   CMP identification - max time length.
+*/
+#define CSP_CMP_IDENT_TIME_LEN 9
+
+/**
+   CMP interface statistics - max interface name length.
+*/
+#define CSP_CMP_ROUTE_IFACE_LEN 11
+
+/**
+   CMP peek/read memeory - max read length.
+*/
+#define CSP_CMP_PEEK_MAX_LEN 200
+
+/**
+   CMP poke/write memeory - max write length.
+*/
+#define CSP_CMP_POKE_MAX_LEN 200
+
+/**
+   CSP management protocol description.
+*/
+struct csp_cmp_message {
+        //! CMP request type.
+        uint8_t type;
+        //! CMP request code.
+        uint8_t code;
+	union {
+		struct {
+			char hostname[CSP_HOSTNAME_LEN];
+			char model[CSP_MODEL_LEN];
+			char revision[CSP_CMP_IDENT_REV_LEN];
+			char date[CSP_CMP_IDENT_DATE_LEN];
+			char time[CSP_CMP_IDENT_TIME_LEN];
+		} ident;
+		struct {
+			uint8_t dest_node;
+			uint8_t next_hop_via;
+			char interface[CSP_CMP_ROUTE_IFACE_LEN];
+		} route_set;
+		struct __attribute__((__packed__)) {
+			char interface[CSP_CMP_ROUTE_IFACE_LEN];
+			uint32_t tx;
+			uint32_t rx;
+			uint32_t tx_error;
+			uint32_t rx_error;
+			uint32_t drop;
+			uint32_t autherr;
+			uint32_t frame;
+			uint32_t txbytes;
+			uint32_t rxbytes;
+			uint32_t irq;
+		} if_stats;
+		struct {
+			uint32_t addr;
+			uint8_t len;
+			char data[CSP_CMP_PEEK_MAX_LEN];
+		} peek;
+		struct {
+			uint32_t addr;
+			uint8_t len;
+			char data[CSP_CMP_POKE_MAX_LEN];
+		} poke;
+		csp_timestamp_t clock;
+	};
+} __attribute__ ((packed));
+
+/**
+   Macro for calculating total size of management message.
+*/
+#define CMP_SIZE(_memb) (sizeof(((struct csp_cmp_message *)0)->type) + sizeof(((struct csp_cmp_message *)0)->code) + sizeof(((struct csp_cmp_message *)0)->_memb))
+
+/**
+   Generic send management message request.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply..
+   @param[in] code request code.
+   @param[in] msg_size size of \a msg.
+   @param[in,out] msg data.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_cmp(uint8_t node, uint32_t timeout, uint8_t code, int msg_size, struct csp_cmp_message *msg);
+
+/**
+   Macro for defining management handling function.
+*/
+#define CMP_MESSAGE(_code, _memb) \
+static inline int csp_cmp_##_memb(uint8_t node, uint32_t timeout, struct csp_cmp_message *msg) { \
+	return csp_cmp(node, timeout, _code, CMP_SIZE(_memb), msg); \
+}
+
+CMP_MESSAGE(CSP_CMP_IDENT, ident)
+CMP_MESSAGE(CSP_CMP_ROUTE_SET, route_set)
+CMP_MESSAGE(CSP_CMP_IF_STATS, if_stats)
+CMP_MESSAGE(CSP_CMP_CLOCK, clock)
+
+/**
+   Peek (read) memory on remote node.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply..
+   @param[in] msg memory address and number of bytes to peek.
+   @param[out] msg peeked/read memory.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+static inline int csp_cmp_peek(uint8_t node, uint32_t timeout, struct csp_cmp_message *msg) {
+    return csp_cmp(node, timeout, CSP_CMP_PEEK, CMP_SIZE(peek) - sizeof(msg->peek.data) + msg->peek.len, msg);
+}
+
+/**
+   Poke (write) memory on remote node.
+   @param[in] node address of subsystem.
+   @param[in] timeout timeout in mS to wait for reply..
+   @param[in] msg memory address, number of bytes and the actual bytes to poke/write.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+static inline int csp_cmp_poke(uint8_t node, uint32_t timeout, struct csp_cmp_message *msg) {
+    return csp_cmp(node, timeout, CSP_CMP_POKE, CMP_SIZE(poke) - sizeof(msg->poke.data) + msg->poke.len, msg);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 117 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_comms.h

@@ -0,0 +1,117 @@
+/**
+ * @file csp_comms.h
+ *
+ * @brief This file contains function prototypes and types that is used
+ *        for sending and receiving data through can interface
+ *
+ * @copyright Copyright 2023 Antaris, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CSP_COMMS_H_
+#define CSP_COMMS_H_
+
+#include <stdint.h>
+#include <errno.h>
+
+#define UHF_UART_MTU 245
+
+#define UHF_DEFAULT_TIMEOUT 1000
+#define UHF_START_BYTE_0     0x22           /** First start byte  */
+#define UHF_START_BYTE_1     0x69           /** Second start byte  */
+#define UHF_HEADER_SIZE      6
+#define UHF_MAX_PAYLOAD      251
+#define UHF_ADC_NUM_CHANNELS 10
+
+/**
+ *   * @brief Socket option for comms
+ *     */
+typedef enum
+{
+    S1_SBAND_HWIL_GS1,
+    S2_DEFAULT_SBAND_GS2,
+    S3_UHF_HWIL_GS3
+}e_comms_uhf_param_opt_sts;
+
+typedef enum {
+    bootloader_msg_ping        = 0x00,
+    bootloader_msg_ack         = 0x01,
+    bootloader_msg_write_page  = 0x02,
+    bootloader_msg_erase       = 0x0c,
+    bootloader_msg_nack        = 0x0f,
+    cmn_msg_ack                = 0x10,
+    cmn_msg_ascii              = 0x11,
+    radio_msg_reboot           = 0x12,
+    radio_msg_get_time         = 0x13,
+    radio_msg_set_time         = 0x14,
+    radio_msg_ranging          = 0x15,
+    radio_msg_ranging_ack      = 0x16,
+    radio_msg_get_telem        = 0x17,
+    radio_msg_telem            = 0x18,
+    radio_msg_get_callsign     = 0x19,
+    radio_msg_set_callsign     = 0x1a,
+    radio_msg_callsign         = 0x1b,
+    cmn_msg_nack               = 0xff
+}e_comms_uhf_msg_no;
+
+typedef struct __attribute__((packed))
+{
+    uint8_t sync1;
+    uint8_t sync2;
+    uint8_t length;
+    uint16_t hwid;
+    uint16_t seqnum;
+    uint8_t system;
+    uint8_t command;
+}s_comms_uhf_header;
+
+typedef struct __attribute__((packed))
+{
+    s_comms_uhf_header header;
+    uint8_t data[UHF_MAX_PAYLOAD - sizeof(s_comms_uhf_header)];
+}s_comms_uhf_data;
+
+typedef union command_buffer
+{
+    uint8_t msg[UHF_MAX_PAYLOAD];
+    s_comms_uhf_data cmd;
+}u_comms_uhf_command_buffer_t;
+
+typedef struct
+{
+    uint8_t reserved;
+    uint32_t uptime;
+    uint32_t uart0_rx_count;
+    uint32_t uart1_rx_count;
+    uint8_t  rx_mode;
+    uint8_t  tx_mode;
+    int16_t  adc[UHF_ADC_NUM_CHANNELS];
+    int8_t   last_rssi;
+    uint8_t  last_lqi;
+    int8_t   last_freqest;
+    uint32_t packets_sent;
+    uint32_t cs_count;
+    uint32_t packets_good;
+    uint32_t packets_rejected_checksum;
+    uint32_t packets_rejected_reserved;
+    uint32_t packets_rejected_other;
+    uint32_t reserved0;
+    uint32_t reserved1;
+    uint32_t custom0;
+    uint32_t custom1;
+
+}s_comms_uhf_tm_prop;
+
+#endif /* CSP_COMMS_H_ */
+

+ 62 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_crc32.h

@@ -0,0 +1,62 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_CRC32_H_
+#define _CSP_CRC32_H_
+
+/**
+   @file
+   CRC32 support.
+*/
+
+#include <csp/csp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Append CRC32 checksum to packet
+   @param[in] packet CSP packet, must be valid.
+   @param[in] include_header include the CSP header in the CRC32, otherwise just the data part.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_crc32_append(csp_packet_t * packet, bool include_header);
+
+/**
+   Verify CRC32 checksum on packet.
+   @param[in] packet CSP packet, must be valid.
+   @param[in] include_header include the CSP header in the CRC32, otherwise just the data part.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_crc32_verify(csp_packet_t * packet, bool include_header);
+
+/**
+   Calculate checksum for a given memory area.
+   @param[in] addr memory address
+   @param[in] length length of memory to do checksum on
+   @return checksum
+*/
+uint32_t csp_crc32_memory(const uint8_t * addr, uint32_t length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 226 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_debug.h

@@ -0,0 +1,226 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_DEBUG_H_
+#define _CSP_DEBUG_H_
+
+/**
+   @file
+   Debug and log.
+*/
+
+#include <inttypes.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <csp/csp_types.h>
+
+#if (CSP_USE_EXTERNAL_DEBUG)
+/* Use external csp_debug API */
+#include <csp/external/csp_debug.h>
+
+#else 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Debug levels.
+*/
+typedef enum {
+	CSP_ERROR	= 0, //!< Error
+	CSP_WARN	= 1, //!< Warning
+	CSP_INFO	= 2, //!< Informational
+	CSP_BUFFER	= 3, //!< Buffer, e.g. csp_packet get/free
+	CSP_PACKET	= 4, //!< Packet routing
+	CSP_PROTOCOL	= 5, //!< Protocol, i.e. RDP
+	CSP_LOCK	= 6, //!< Locking, i.e. semaphore
+} csp_debug_level_t;
+
+/**
+   Debug level enabled/disabled.
+*/
+extern bool csp_debug_level_enabled[];
+
+/**
+   Extract filename component from path
+*/
+#define BASENAME(_file) ((strrchr(_file, '/') ? : (strrchr(_file, '\\') ? : _file)) + 1)
+
+/**
+   Implement csp_assert_fail_action to override default failure action
+*/
+extern void __attribute__((weak)) csp_assert_fail_action(const char *assertion, const char *file, int line);
+
+/**
+   CSP assert.
+*/
+#if (!defined(NDEBUG) || CSP_USE_ASSERT)
+#define csp_assert(exp) {                                       				        \
+		if (!(exp)) {										\
+			const char *assertion = #exp;							\
+			const char *file = BASENAME(__FILE__);						\
+			int line = __LINE__;								\
+			printf("\E[1;31mAssertion \'%s\' failed in %s:%d\E[0m\r\n",			\
+			       assertion, file, line);							\
+			if (csp_assert_fail_action)							\
+				csp_assert_fail_action(assertion, file, line);				\
+		}											\
+	}
+#else
+#define csp_assert(...) {}
+#endif
+
+#if !(__DOXYGEN__)
+/* Ensure defines are 'defined' */
+#if !defined(CSP_DEBUG)
+#define CSP_DEBUG 1
+#endif
+
+#if !defined(CSP_LOG_LEVEL_DEBUG)
+#define CSP_LOG_LEVEL_DEBUG 1
+#endif
+
+#if !defined(CSP_LOG_LEVEL_INFO)
+#define CSP_LOG_LEVEL_INFO 0
+#endif
+
+#if !defined(CSP_LOG_LEVEL_WARN)
+#define CSP_LOG_LEVEL_WARN 1
+#endif
+
+#if !defined(CSP_LOG_LEVEL_ERROR)
+#define CSP_LOG_LEVEL_ERROR 1
+#endif
+#endif // __DOXYGEN__
+
+#ifdef __AVR__
+        #include <stdio.h>
+	#include <avr/pgmspace.h>
+	#define CONSTSTR(data) PSTR(data)
+	#undef printf
+	#undef sscanf
+	#undef scanf
+	#undef sprintf
+	#undef snprintf
+	#define printf(s, ...) printf_P(PSTR(s), ## __VA_ARGS__)
+	#define sscanf(buf, s, ...) sscanf_P(buf, PSTR(s), ## __VA_ARGS__)
+	#define scanf(s, ...) scanf_P(PSTR(s), ## __VA_ARGS__)
+	#define sprintf(buf, s, ...) sprintf_P(buf, PSTR(s), ## __VA_ARGS__)
+	#define snprintf(buf, size, s, ...) snprintf_P(buf, size, PSTR(s), ## __VA_ARGS__)
+#define csp_debug(level, format, ...) { if (CSP_DEBUG && csp_debug_level_enabled[level]) do_csp_debug(level, PSTR(format), ##__VA_ARGS__); }
+#else
+/**
+ * Log message with specific level.
+ * @param level log level
+ * @param format log message, printf syntax.
+ */
+#define csp_debug(level, format, ...) { if (CSP_DEBUG && csp_debug_level_enabled[level]) do_csp_debug(level, format, ##__VA_ARGS__); }
+#endif
+
+/**
+ * Log message with level #CSP_ERROR.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_error(format, ...)    { if (CSP_LOG_LEVEL_ERROR) csp_debug(CSP_ERROR, format, ##__VA_ARGS__); }
+
+/**
+ * Log message with level #CSP_WARN.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_warn(format, ...)     { if (CSP_LOG_LEVEL_WARN) csp_debug(CSP_WARN, format, ##__VA_ARGS__); }
+
+/**
+ * Log message with level #CSP_INFO.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_info(format, ...)     { if (CSP_LOG_LEVEL_INFO) csp_debug(CSP_INFO, format, ##__VA_ARGS__); }
+
+/**
+ * Log message with level #CSP_BUFFER.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_buffer(format, ...)   { if (CSP_LOG_LEVEL_DEBUG) csp_debug(CSP_BUFFER, format, ##__VA_ARGS__); }
+
+/**
+ * Log message with level #CSP_PACKET.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_packet(format, ...)   { if (CSP_LOG_LEVEL_DEBUG) csp_debug(CSP_PACKET, format, ##__VA_ARGS__); }
+
+/**
+ * Log message with level #CSP_PROTOCOL.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_protocol(format, ...) { if (CSP_LOG_LEVEL_DEBUG) csp_debug(CSP_PROTOCOL, format, ##__VA_ARGS__); }
+
+/**
+ * Log message with level #CSP_LOCK.
+ * @param format log message, printf syntax.
+ */
+#define csp_log_lock(format, ...)     { if (CSP_LOG_LEVEL_DEBUG) csp_debug(CSP_LOCK, format, ##__VA_ARGS__); }
+
+/**
+ * Do the actual logging (don't use directly).
+ * @note Use the csp_log_<level>() macros instead.
+ * @param level log level
+ * @param format log message, printf syntax.
+ */
+void do_csp_debug(csp_debug_level_t level, const char *format, ...) __attribute__ ((format (__printf__, 2, 3)));
+
+/**
+ * Toggle debug level on/off
+ * @param level Level to toggle
+ */
+void csp_debug_toggle_level(csp_debug_level_t level);
+
+/**
+ * Set debug level
+ * @param level Level to set
+ * @param value New level value
+ */
+void csp_debug_set_level(csp_debug_level_t level, bool value);
+
+/**
+ * Get current debug level value
+ * @param level Level to get
+ * @return Level value
+ */
+int csp_debug_get_level(csp_debug_level_t level);
+
+/**
+ * Debug hook function.
+ */
+typedef void (*csp_debug_hook_func_t)(csp_debug_level_t level, const char *format, va_list args);
+
+/**
+ * Set debug/log hook function.
+ */
+void csp_debug_hook_set(csp_debug_hook_func_t f);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CSP_USE_EXTERNAL_DEBUG
+
+#endif // _CSP_DEBUG_H_

+ 39 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_dedup.h

@@ -0,0 +1,39 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_DEDUP_H_
+#define CSP_DEDUP_H_
+
+#include <csp/csp_types.h>
+ 
+/**
+ * Enable or disable deduplication
+ * @param enable enable deduplication if true
+ */
+void csp_dedup_enable(bool enable);
+
+/**
+ * Check for a duplicate packet
+ * @param packet pointer to packet
+ * @return false if not a duplicate, true if duplicate
+ */
+bool csp_dedup_is_duplicate(csp_packet_t *packet);
+
+#endif /* CSP_DEDUP_H_ */

+ 148 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_endian.h

@@ -0,0 +1,148 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_ENDIAN_H_
+#define _CSP_ENDIAN_H_
+
+/**
+   @file
+   Endian support.
+*/
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Convert from host order to network order.
+*/
+uint16_t csp_hton16(uint16_t h16);
+
+/**
+   Convert from network order to host order.
+*/
+uint16_t csp_ntoh16(uint16_t n16);
+
+/**
+   Convert from host order to network order.
+*/
+uint32_t csp_hton32(uint32_t h32);
+
+/**
+   Convert from network order to host order.
+*/
+uint32_t csp_ntoh32(uint32_t n32);
+
+/**
+   Convert from host order to network order.
+*/
+uint64_t csp_hton64(uint64_t h64);
+
+/**
+   Convert from network order to host order.
+*/
+uint64_t csp_ntoh64(uint64_t n64);
+
+/**
+   Convert from host order to big endian.
+*/
+uint16_t csp_htobe16(uint16_t h16);
+
+/**
+   Convert from host order to little endian.
+*/
+uint16_t csp_htole16(uint16_t h16);
+
+/**
+   Convert from big endian to host order.
+*/
+uint16_t csp_betoh16(uint16_t be16);
+
+/**
+   Convert from little endian to host order.
+*/
+uint16_t csp_letoh16(uint16_t le16);
+
+/**
+   Convert from host order to big endian.
+ */
+uint32_t csp_htobe32(uint32_t h32);
+
+/**
+   Convert from host order to little endian.
+*/
+uint32_t csp_htole32(uint32_t h32);
+
+/**
+   Convert from big endian to host order.
+*/
+uint32_t csp_betoh32(uint32_t be32);
+
+/**
+   Convert from little endian to host order.
+*/
+uint32_t csp_letoh32(uint32_t le32);
+
+/**
+   Convert from host order to big endian.
+*/
+uint64_t csp_htobe64(uint64_t h64);
+
+/**
+   Convert from host order to little endian.
+*/
+uint64_t csp_htole64(uint64_t h64);
+
+/**
+   Convert from big endian to host order.
+*/
+uint64_t csp_betoh64(uint64_t be64);
+
+/**
+   Convert from little endian to host order.
+*/
+uint64_t csp_letoh64(uint64_t le64);
+
+/**
+   Convert from host order to network order.
+*/
+float csp_htonflt(float f);
+
+/**
+   Convert from network order to host order.
+*/
+float csp_ntohflt(float f);
+
+/**
+   Convert from host order to network order.
+*/
+double csp_htondbl(double d);
+
+/**
+   Convert from network order to host order.
+*/
+double csp_ntohdbl(double d);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // _CSP_ENDIAN_H_

+ 60 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_error.h

@@ -0,0 +1,60 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_ERROR_H_
+#define _CSP_ERROR_H_
+
+/**
+   @file
+
+   Error codes.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   @defgroup CSP_ERR CSP error codes.
+   @{
+*/
+#define CSP_ERR_NONE		 0		/**< No error */
+#define CSP_ERR_NOMEM		-1		/**< Not enough memory */
+#define CSP_ERR_INVAL		-2		/**< Invalid argument */
+#define CSP_ERR_TIMEDOUT	-3		/**< Operation timed out */
+#define CSP_ERR_USED		-4		/**< Resource already in use */
+#define CSP_ERR_NOTSUP		-5		/**< Operation not supported */
+#define CSP_ERR_BUSY		-6		/**< Device or resource busy */
+#define CSP_ERR_ALREADY		-7		/**< Connection already in progress */
+#define CSP_ERR_RESET		-8		/**< Connection reset */
+#define CSP_ERR_NOBUFS		-9		/**< No more buffer space available */
+#define CSP_ERR_TX		-10		/**< Transmission failed */
+#define CSP_ERR_DRIVER		-11		/**< Error in driver layer */
+#define CSP_ERR_AGAIN		-12		/**< Resource temporarily unavailable */
+#define CSP_ERR_HMAC		-100		/**< HMAC failed */
+#define CSP_ERR_XTEA		-101		/**< XTEA failed */
+#define CSP_ERR_CRC32		-102		/**< CRC32 failed */
+#define CSP_ERR_SFP		-103		/**< SFP protocol error or inconsistency */
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 76 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_iflist.h

@@ -0,0 +1,76 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_IFLIST_H_
+#define CSP_IFLIST_H_
+
+/**
+   @file
+
+   Interface list.
+
+   Linked-list of interfaces in the system.
+
+   This API is not thread-safe.
+*/
+
+#include <csp/csp_interface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Add interface to the list.
+
+   @param[in] iface interface. The interface must remain valid as long as the application is running.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_iflist_add(csp_iface_t * iface);
+
+/**
+   Get interface by name.
+
+   @param[in] name interface name.
+   @return Interface or NULL if not found.
+*/
+csp_iface_t * csp_iflist_get_by_name(const char *name);
+
+/**
+   Print list of interfaces to stdout.
+*/
+void csp_iflist_print(void);
+
+/**
+   Return list of interfaces.
+
+   @return First interface or NULL, if no interfaces added.
+*/
+csp_iface_t * csp_iflist_get(void);
+
+/**
+   Convert bytes to readable string.
+*/
+int csp_bytesize(char *buffer, int buffer_len, unsigned long int bytes);
+    
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 95 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_interface.h

@@ -0,0 +1,95 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_INTERFACE_H_
+#define _CSP_INTERFACE_H_
+
+/**
+   @file
+   Interface.
+*/
+
+#include <csp/csp_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Max unique length of interface name, when matching names.
+*/
+#define CSP_IFLIST_NAME_MAX    10
+
+/**
+   Interface Tx function.
+
+   @param[in] ifroute contains the interface and the \a mac adddress.
+   @param[in] packet CSP packet to send. On success, the packet must be freed using csp_buffer_free().
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+typedef int (*nexthop_t)(const csp_route_t * ifroute, csp_packet_t *packet);
+
+//doc-begin:csp_iface_s
+/**
+   CSP interface.
+*/
+struct csp_iface_s {
+    const char *name;          //!< Name, max compare length is #CSP_IFLIST_NAME_MAX
+    void * interface_data;     //!< Interface data, only known/used by the interface layer, e.g. state information.
+    void * driver_data;        //!< Driver data, only known/used by the driver layer, e.g. device/channel references.
+    nexthop_t nexthop;         //!< Next hop (Tx) function
+    uint16_t mtu;              //!< Maximum Transmission Unit of interface
+    uint8_t split_horizon_off; //!< Disable the route-loop prevention
+    uint32_t tx;               //!< Successfully transmitted packets
+    uint32_t rx;               //!< Successfully received packets
+    uint32_t tx_error;         //!< Transmit errors (packets)
+    uint32_t rx_error;         //!< Receive errors, e.g. too large message
+    uint32_t drop;             //!< Dropped packets
+    uint32_t autherr;          //!< Authentication errors (packets)
+    uint32_t frame;            //!< Frame format errors (packets)
+    uint32_t txbytes;          //!< Transmitted bytes
+    uint32_t rxbytes;          //!< Received bytes
+    uint32_t irq;              //!< Interrupts
+    struct csp_iface_s *next;  //!< Internal, interfaces are stored in a linked list
+};
+//doc-end:csp_iface_s
+
+/**
+   Inputs a new packet into the system.
+
+   This function can be called from interface drivers (ISR) or tasks, to route and accept packets.
+
+   @note EXTREMELY IMPORTANT: \a pxTaskWoken must ALWAYS be NULL if called from task, and ALWAYS
+   be NON NULL if called from ISR. If this condition is met, this call is completely thread-safe
+
+   This function is fire and forget, it returns void, meaning that the \a packet will always be
+   either accepted or dropped, so the memory will always be freed.
+
+   @param[in] packet A pointer to the incoming packet
+   @param[in] iface A pointer to the incoming interface TX function.
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+*/
+void csp_qfifo_write(csp_packet_t *packet, csp_iface_t *iface, CSP_BASE_TYPE *pxTaskWoken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+

+ 77 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_perf.h

@@ -0,0 +1,77 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2017 CSP Contributors (http://www.libcsp.org) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_PERF_H_
+#define _CSP_PERF_H_
+
+#include <stdint.h>
+
+#include <csp/csp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct csp_perf_config;
+typedef int (*csp_perf_cb_t)(struct csp_perf_config *conf, void *arg);
+
+struct csp_perf_config {
+	uint8_t port;
+	uint8_t server;
+	uint8_t flags;
+
+	unsigned int timeout_ms;
+	unsigned int data_size;
+	unsigned int runtime;
+	unsigned int max_frames;
+	unsigned int bandwidth;
+	unsigned int update_interval;
+
+	bool should_stop;
+
+	csp_perf_cb_t cb;
+	void *cb_arg;
+};
+
+static inline void csp_perf_set_defaults(struct csp_perf_config *conf)
+{
+	memset(conf, 0, sizeof(*conf));
+	conf->timeout_ms = 1000;
+	conf->data_size = 100;
+	conf->runtime = 10;
+	conf->max_frames = 0;
+	conf->bandwidth = 1000000; /* bits/s */
+	conf->update_interval = 1;
+	conf->port = 11;
+}
+
+static inline void csp_perf_stop(struct csp_perf_config *conf)
+{
+	conf->should_stop = true;
+}
+
+int csp_perf_server(struct csp_perf_config *conf);
+
+int csp_perf_client(struct csp_perf_config *conf);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _CSP_PERF_H_ */

+ 72 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_platform.h

@@ -0,0 +1,72 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_PLATFORM_H_
+#define _CSP_PLATFORM_H_
+
+/**
+   @file
+   Platform support.
+*/
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CSP_POSIX 1
+
+/* Set OS */
+#if (CSP_POSIX || CSP_WINDOWS || CSP_MACOSX || __DOXYGEN__)
+	/** Base type. Mainly used for FreeRTOS calls to trigger task re-scheduling. */
+	#define CSP_BASE_TYPE int
+	/** Max timeout time. On platforms supporting no timeouts (e.g. Linux), the timeout will be converted to \a forever. */
+	#define CSP_MAX_TIMEOUT (UINT32_MAX)
+	/** Declare critical lock. */
+	#define CSP_DEFINE_CRITICAL(lock) static csp_bin_sem_handle_t lock
+	/** Initialize critical lock. */
+	#define CSP_INIT_CRITICAL(lock) ({(csp_bin_sem_create(&lock) == CSP_SEMAPHORE_OK) ? CSP_ERR_NONE : CSP_ERR_NOMEM;})
+	/** Enter/take critical lock. */
+	#define CSP_ENTER_CRITICAL(lock) do { csp_bin_sem_wait(&lock, CSP_MAX_DELAY); } while(0)
+	/** Exit/release critical lock. */
+	#define CSP_EXIT_CRITICAL(lock) do { csp_bin_sem_post(&lock); } while(0)
+#elif (CSP_FREERTOS)
+	#include "FreeRTOS.h"
+	#define CSP_BASE_TYPE portBASE_TYPE
+	#define CSP_MAX_TIMEOUT portMAX_DELAY
+	#define CSP_DEFINE_CRITICAL(lock)
+	#define CSP_INIT_CRITICAL(lock) ({CSP_ERR_NONE;})
+	#define CSP_ENTER_CRITICAL(lock) do { portENTER_CRITICAL(); } while (0)
+	#define CSP_EXIT_CRITICAL(lock) do { portEXIT_CRITICAL(); } while (0)
+#else
+	#error "OS must be either CSP_POSIX, CSP_MACOSX, CSP_FREERTOS or CSP_WINDOWS"
+#endif
+
+/** Legacy definition for #CSP_MAX_TIMEOUT. */
+#define CSP_MAX_DELAY CSP_MAX_TIMEOUT
+
+/** Legacy definition for #CSP_MAX_TIMEOUT. */
+#define CSP_INFINITY CSP_MAX_TIMEOUT
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 64 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_promisc.h

@@ -0,0 +1,64 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_CSP_PROMISC_H_
+#define _CSP_CSP_PROMISC_H_
+
+/**
+   #file
+
+   Promiscuous packet queue.
+
+   This function is used to enable promiscuous mode for incoming packets, e.g. router, bridge.
+   If enabled, a copy of all incoming packets are cloned (using csp_buffer_clone()) and placed in a
+   FIFO queue, that can be read using csp_promisc_read().
+*/
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Enable promiscuous packet queue.
+   @param[in] queue_size Size (max length) of queue for incoming packets.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+ */
+int csp_promisc_enable(unsigned int queue_size);
+
+/**
+   Disable promiscuous mode.
+*/
+void csp_promisc_disable(void);
+
+/**
+   Get/dequeue packet from promiscuous packet queue.
+
+   Returns the first packet from the promiscuous packet queue.
+   @param[in] timeout Timeout in ms to wait for a packet.
+   @return Packet (free with csp_buffer_free() or re-use packet), NULL on error or timeout.
+*/
+csp_packet_t *csp_promisc_read(uint32_t timeout);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 161 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_rtable.h

@@ -0,0 +1,161 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_RTABLE_H_
+#define CSP_RTABLE_H_
+
+/**
+   @file
+
+   Routing table.
+
+   The routing table maps a CSP destination address to an interface (and optional a via address).
+
+   Normal routing: If the route's via address is set to #CSP_NO_VIA_ADDRESS, the packet will be sent directly to the destination address
+   specified in the CSP header, otherwise the packet will be sent the to the route's via address.
+*/
+
+#include <csp/csp_iflist.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   No via address specified for the route, use CSP header destination.
+*/
+#define CSP_NO_VIA_ADDRESS	0xFF
+
+/**
+   Legacy definition for #CSP_NO_VIA_ADDRESS.
+*/
+#define CSP_NODE_MAC	CSP_NO_VIA_ADDRESS
+    
+/**
+   Route entry.
+   @see csp_rtable_find_route().
+*/
+struct csp_route_s {
+    /** Which interface to route packet on */
+    csp_iface_t * iface;
+    /** If different from #CSP_NO_VIA_ADDRESS, send packet to this address, instead of the destination address in the CSP header. */
+    uint8_t via;
+};
+
+/**
+   Find route to address/node.
+   @param[in] dest_address destination address.
+   @return Route or NULL if no route found.
+*/
+const csp_route_t * csp_rtable_find_route(uint8_t dest_address);
+
+/**
+   Set route to destination address/node.
+   @param[in] dest_address destination address.
+   @param[in] mask number of bits in netmask
+   @param[in] ifc interface.
+   @param[in] via assosicated via address.
+   @return #CSP_ERR_NONE on success, or an error code.
+*/
+int csp_rtable_set(uint8_t dest_address, uint8_t mask, csp_iface_t *ifc, uint8_t via);
+
+/**
+   Save routing table as a string (readable format).
+   @see csp_rtable_load() for additional information, e.g. format.
+   @param[out] buffer user supplied buffer.
+   @param[in] buffer_size size of \a buffer.
+   @return #CSP_ERR_NONE on success, or an error code.
+*/
+int csp_rtable_save(char * buffer, size_t buffer_size);
+
+/**
+   Load routing table from a string.
+   Table will be loaded on-top of existing routes, possibly overwriting existing entries.
+   Format: \<address\>[/mask] \<interface\> [via][, next entry]
+   Example: "0/0 CAN, 8 KISS, 10 I2C 10", same as "0/0 CAN, 8/5 KISS, 10/5 I2C 10".
+   @see csp_rtable_save(), csp_rtable_clear(), csp_rtable_free()
+   @param[in] rtable routing table (nul terminated)
+   @return @ref CSP_ERR or number of entries.
+*/
+int csp_rtable_load(const char * rtable);
+
+/**
+   Check string for valid routing elements.
+   @param[in] rtable routing table (nul terminated)
+   @return @ref CSP_ERR or number of entries.
+*/
+int csp_rtable_check(const char * rtable);
+
+/**
+   Clear routing table and add loopback route.
+   @see csp_rtable_free()
+*/
+void csp_rtable_clear(void);
+
+/**
+   Clear/free all entries in the routing table.
+*/
+void csp_rtable_free(void);
+
+/**
+   Print routing table
+*/
+void csp_rtable_print(void);
+
+/** Iterator for looping through the routing table. */
+typedef bool (*csp_rtable_iterator_t)(void * ctx, uint8_t address, uint8_t mask, const csp_route_t * route);
+
+/**
+   Iterate routing table.
+*/
+void csp_rtable_iterate(csp_rtable_iterator_t iter, void * ctx);
+
+/**
+   Set route to destination address/node.
+   @deprecated Use csp_rtable_set() instead.
+   @param[in] dest_address destination address.
+   @param[in] ifc interface.
+   @param[in] via assosicated via address.
+   @return #CSP_ERR_NONE on success, or an error code.
+*/
+static inline int csp_route_set(uint8_t dest_address, csp_iface_t *ifc, uint8_t via) {
+    return csp_rtable_set(dest_address, CSP_ID_HOST_SIZE, ifc, via);
+}
+
+/**
+   Print routing table.
+   @deprecated Use csp_rtable_print() instead.
+*/
+static inline void csp_route_print_table(void) {
+    csp_rtable_print();
+}
+
+/**
+   Print list of interfaces.
+   @deprecated Use csp_iflist_print() instead.
+*/
+static inline void csp_route_print_interfaces(void) {
+    csp_iflist_print();
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 111 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_sfp.h

@@ -0,0 +1,111 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_SFP_H_
+#define _CSP_SFP_H_
+
+/**
+   @file
+
+   Simple Fragmentation Protocol (SFP).
+
+   The SFP API can transfer a blob of data across an established CSP connection, by chopping the data into smaller chuncks of data, that
+   can fit into a single CSP message.
+
+   SFP will add a small header to each packet, containing information about the transfer.
+   SFP is usually sent over a RDP connection (which also adds a header),
+*/
+
+#include <string.h> // memcpy()
+
+#include <csp/csp_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Send data over a CSP connection.
+
+   Data will be send in chunks of \a mtu bytes. The MTU must be small enough to fit into a CSP packat + SFP header + other transport headers.
+
+   csp_sfp_recv() or csp_sfp_recv_fp() can be used at the other end to receive data.
+
+   This is usefull if you wish to send data stored in flash memory or another location, where standard memcpy() doesn't work.
+
+   @param[in] conn established connection for sending SFP packets.
+   @param[in] data data to send
+   @param[in] datasize size of \a data
+   @param[in] mtu maximum transfer unit (bytes), max data chunk to send.
+   @param[in] timeout unused as of CSP version 1.6
+   @param[in] memcpyfcn memory copy function.
+   @return #CSP_ERR_NONE on success, otherwise an error.
+*/
+int csp_sfp_send_own_memcpy(csp_conn_t * conn, const void * data, unsigned int datasize, unsigned int mtu, uint32_t timeout, csp_memcpy_fnc_t memcpyfcn);
+
+/**
+   Send data over a CSP connection.
+
+   Uses csp_sfp_send_own_memcpy() with standard memcpy().
+
+   @param[in] conn established connection for sending SFP packets.
+   @param[in] data data to send
+   @param[in] datasize size of \a data
+   @param[in] mtu maximum transfer unit (bytes), max data chunk to send.
+   @param[in] timeout unused as of CSP version 1.6
+   @return #CSP_ERR_NONE on success, otherwise an error.
+*/
+static inline int csp_sfp_send(csp_conn_t * conn, const void * data, unsigned int datasize, unsigned int mtu, uint32_t timeout) {
+    return csp_sfp_send_own_memcpy(conn, data, datasize, mtu, timeout, (csp_memcpy_fnc_t) &memcpy);
+}
+    
+/**
+   Receive data over a CSP connection.
+
+   This is the counterpart to the csp_sfp_send() and csp_sfp_send_own_memcpy().
+
+   @param[in] conn established connection for receiving SFP packets.
+   @param[out] dataout received data on success. Allocated with csp_malloc(), so should be freed with csp_free(). The pointer will be NULL on failure.
+   @param[out] datasize size of received data.
+   @param[in] timeout timeout in ms to wait for csp_read()
+   @param[in] first_packet First packet of a SFP transfer. Use NULL to receive first packet on the connection.
+   @return #CSP_ERR_NONE on success, otherwise an error.
+*/
+int csp_sfp_recv_fp(csp_conn_t * conn, void ** dataout, int * datasize, uint32_t timeout, csp_packet_t * first_packet);
+
+/**
+   Receive data over a CSP connection.
+
+   This is the counterpart to the csp_sfp_send() and csp_sfp_send_own_memcpy().
+
+   @param[in] conn established connection for receiving SFP packets.
+   @param[out] dataout received data on success. Allocated with csp_malloc(), so should be freed with csp_free(). The pointer will be NULL on failure.
+   @param[out] datasize size of received data.
+   @param[in] timeout timeout in ms to wait for csp_read()
+   @return #CSP_ERR_NONE on success, otherwise an error.
+*/
+static inline int csp_sfp_recv(csp_conn_t * conn, void ** dataout, int * datasize, uint32_t timeout) {
+    return csp_sfp_recv_fp(conn, dataout, datasize, timeout, NULL);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 294 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/csp_types.h

@@ -0,0 +1,294 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_TYPES_H_
+#define CSP_TYPES_H_
+
+/**
+   @file
+   Basic types.
+*/
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+//#include <csp/csp_autoconfig.h> // -> CSP_X defines (compile configuration)
+#include <csp/csp_error.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CSP_LITTLE_ENDIAN 1
+
+#if (CSP_BIG_ENDIAN && CSP_LITTLE_ENDIAN)
+#error "Only define/set either CSP_BIG_ENDIAN or CSP_LITTLE_ENDIAN"
+#endif
+
+/**
+   Reserved ports for CSP services.
+*/
+typedef enum {
+	CSP_CMP				= 0,   //!< CSP management, e.g. memory, routes, stats
+	CSP_PING			= 1,   //!< Ping - return ping
+	CSP_PS				= 2,   //!< Current process list
+	CSP_MEMFREE			= 3,   //!< Free memory
+	CSP_REBOOT			= 4,   //!< Reboot, see #CSP_REBOOT_MAGIC and #CSP_REBOOT_SHUTDOWN_MAGIC
+	CSP_BUF_FREE			= 5,   //!< Free CSP buffers
+	CSP_UPTIME			= 6,   //!< Uptime
+} csp_service_port_t;
+
+/** Listen on all ports, primarily used with csp_bind() */
+#define CSP_ANY				255
+    
+/**
+   Message priority.
+*/
+typedef enum {
+	CSP_PRIO_CRITICAL		= 0, //!< Critical
+	CSP_PRIO_HIGH			= 1, //!< High
+	CSP_PRIO_NORM			= 2, //!< Normal (default)
+	CSP_PRIO_LOW			= 3, //!< Low
+} csp_prio_t;
+
+#define CSP_PRIORITIES			(1 << CSP_ID_PRIO_SIZE) //!< Number of CSP message priorities.
+
+#if (CSP_USE_QOS || __DOXYGEN__)
+#define CSP_ROUTE_FIFOS			CSP_PRIORITIES //!< Number of fifos for incoming messages (handover to router)
+#define CSP_RX_QUEUES			CSP_PRIORITIES //!< Number of fifos for incoming message per message-queue
+#else
+#define CSP_ROUTE_FIFOS			1
+#define CSP_RX_QUEUES			1
+#endif
+
+/**
+   @defgroup CSP_HEADER_DEF CSP header definition.
+   @{
+*/
+#define CSP_ID_PRIO_SIZE		2 //!< Bits for priority, see #csp_prio_t
+#define CSP_ID_HOST_SIZE		5 //!< Bits for host (destination/source address)
+#define CSP_ID_PORT_SIZE		6 //!< Bits for port (destination/source port)
+#define CSP_ID_FLAGS_SIZE		8 //!< Bits for flags, see @ref CSP_HEADER_FLAGS
+
+/** Number of bits in CSP header */
+#define CSP_HEADER_BITS			(CSP_ID_PRIO_SIZE + (2 * CSP_ID_HOST_SIZE) + (2 * CSP_ID_PORT_SIZE) + CSP_ID_FLAGS_SIZE)
+/** CSP header size in bytes */
+#define CSP_HEADER_LENGTH		(CSP_HEADER_BITS / 8)
+
+#if CSP_HEADER_BITS != 32 && __GNUC__
+#error "Header length must be 32 bits"
+#endif
+
+#define CSP_ID_PRIO_MAX			((1 << (CSP_ID_PRIO_SIZE)) - 1)  //!< Max priority value in header
+#define CSP_ID_HOST_MAX			((1 << (CSP_ID_HOST_SIZE)) - 1)  //!< Max host value in header
+#define CSP_ID_PORT_MAX			((1 << (CSP_ID_PORT_SIZE)) - 1)  //!< Max port value in header
+#define CSP_ID_FLAGS_MAX		((1 << (CSP_ID_FLAGS_SIZE)) - 1) //!< Max flag(s) value in header
+
+/** CSP identifier/header - priority mask */
+#define CSP_ID_PRIO_MASK		((uint32_t) CSP_ID_PRIO_MAX  << (CSP_ID_FLAGS_SIZE + (2 * CSP_ID_PORT_SIZE) + (2 * CSP_ID_HOST_SIZE)))
+/** CSP identifier/header - source address mask */
+#define CSP_ID_SRC_MASK	 		((uint32_t) CSP_ID_HOST_MAX  << (CSP_ID_FLAGS_SIZE + (2 * CSP_ID_PORT_SIZE) + (1 * CSP_ID_HOST_SIZE)))
+/** CSP identifier/header - destination address mask */
+#define CSP_ID_DST_MASK	 		((uint32_t) CSP_ID_HOST_MAX  << (CSP_ID_FLAGS_SIZE + (2 * CSP_ID_PORT_SIZE)))
+/** CSP identifier/header - destination port mask */
+#define CSP_ID_DPORT_MASK   		((uint32_t) CSP_ID_PORT_MAX  << (CSP_ID_FLAGS_SIZE + (1 * CSP_ID_PORT_SIZE)))
+/** CSP identifier/header - source port mask */
+#define CSP_ID_SPORT_MASK   		((uint32_t) CSP_ID_PORT_MAX  << (CSP_ID_FLAGS_SIZE))
+/** CSP identifier/header - flag mask */
+#define CSP_ID_FLAGS_MASK		((uint32_t) CSP_ID_FLAGS_MAX << (0))
+/** CSP identifier/header - connection mask (source & destination address + source & destination ports) */
+#define CSP_ID_CONN_MASK		(CSP_ID_SRC_MASK | CSP_ID_DST_MASK | CSP_ID_DPORT_MASK | CSP_ID_SPORT_MASK)
+/**@}*/
+
+/**
+   CSP identifier/header.
+   This union is sent directly on the wire, hence the big/little endian definitions
+*/
+typedef union {
+    /** Entire identifier. */
+    uint32_t ext;
+    /** Individual fields. */
+    struct __attribute__((__packed__)) {
+#if (CSP_BIG_ENDIAN || __DOXYGEN__)
+        unsigned int pri   : CSP_ID_PRIO_SIZE;  //!< Priority
+        unsigned int src   : CSP_ID_HOST_SIZE;  //!< Source address
+        unsigned int dst   : CSP_ID_HOST_SIZE;  //!< Destination address
+        unsigned int dport : CSP_ID_PORT_SIZE;  //!< Destination port
+        unsigned int sport : CSP_ID_PORT_SIZE;  //!< Source port
+        unsigned int flags : CSP_ID_FLAGS_SIZE; //!< Flags, see @ref CSP_HEADER_FLAGS
+#elif (CSP_LITTLE_ENDIAN)
+        unsigned int flags : CSP_ID_FLAGS_SIZE;
+        unsigned int sport : CSP_ID_PORT_SIZE;
+        unsigned int dport : CSP_ID_PORT_SIZE;
+        unsigned int dst   : CSP_ID_HOST_SIZE;
+        unsigned int src   : CSP_ID_HOST_SIZE;
+        unsigned int pri   : CSP_ID_PRIO_SIZE;
+#endif
+    };
+} csp_id_t;
+
+/** Broadcast address */
+#define CSP_BROADCAST_ADDR		CSP_ID_HOST_MAX
+
+/** Default routing address */
+#define CSP_DEFAULT_ROUTE		(CSP_ID_HOST_MAX + 1)
+
+/**
+   @defgroup CSP_HEADER_FLAGS CSP header flags.
+   @{
+*/
+#define CSP_FRES1			0x80 //!< Reserved for future use
+#define CSP_FRES2			0x40 //!< Reserved for future use
+#define CSP_FRES3			0x20 //!< Reserved for future use
+#define CSP_FFRAG			0x10 //!< Use fragmentation
+#define CSP_FHMAC			0x08 //!< Use HMAC verification
+#define CSP_FXTEA			0x04 //!< Use XTEA encryption
+#define CSP_FRDP			0x02 //!< Use RDP protocol
+#define CSP_FCRC32			0x01 //!< Use CRC32 checksum
+/**@}*/
+
+/**
+   @defgroup CSP_SOCKET_OPTIONS CSP Socket options.
+   @{
+*/
+#define CSP_SO_NONE			0x0000 //!< No socket options
+#define CSP_SO_RDPREQ			0x0001 //!< Require RDP
+#define CSP_SO_RDPPROHIB		0x0002 //!< Prohibit RDP
+#define CSP_SO_HMACREQ			0x0004 //!< Require HMAC
+#define CSP_SO_HMACPROHIB		0x0008 //!< Prohibit HMAC
+#define CSP_SO_XTEAREQ			0x0010 //!< Require XTEA
+#define CSP_SO_XTEAPROHIB		0x0020 //!< Prohibit HMAC
+#define CSP_SO_CRC32REQ			0x0040 //!< Require CRC32
+#define CSP_SO_CRC32PROHIB		0x0080 //!< Prohibit CRC32
+#define CSP_SO_CONN_LESS		0x0100 //!< Enable Connection Less mode
+#define CSP_SO_INTERNAL_LISTEN          0x1000 //!< Internal flag: listen called on socket
+/**@}*/
+
+/**
+   @defgroup CSP_CONNECTION_OPTIONS CSP Connect options.
+   @{
+*/
+#define CSP_O_NONE			CSP_SO_NONE        //!< No connection options
+#define CSP_O_RDP			CSP_SO_RDPREQ      //!< Enable RDP
+#define CSP_O_NORDP			CSP_SO_RDPPROHIB   //!< Disable RDP
+#define CSP_O_HMAC			CSP_SO_HMACREQ     //!< Enable HMAC
+#define CSP_O_NOHMAC			CSP_SO_HMACPROHIB  //!< Disable HMAC
+#define CSP_O_XTEA			CSP_SO_XTEAREQ     //!< Enable XTEA
+#define CSP_O_NOXTEA			CSP_SO_XTEAPROHIB  //!< Disable XTEA
+#define CSP_O_CRC32			CSP_SO_CRC32REQ    //!< Enable CRC32
+#define CSP_O_NOCRC32			CSP_SO_CRC32PROHIB //!< Disable CRC32
+/**@}*/
+
+/**
+   Padding size in #csp_packet_t.
+   10 bytes ensure correct aligned \a id and \a data in #csp_packet_t.
+*/
+#define CSP_PADDING_BYTES		10
+
+//doc-begin:csp_packet_t
+/**
+   CSP Packet.
+
+   This structure is constructed to fit with all interface and protocols to prevent the
+   need to copy data (zero copy).
+
+   @note In most cases a CSP packet cannot be reused in case of send failure, because the
+   lower layers may add additional data causing increased length (e.g. CRC32), convert
+   the CSP id to different endian (e.g. I2C), etc.
+*/
+typedef struct {
+	/**
+           Padding. These bytes are intended for use by protocols, which want to prepend
+           data before sending it, without having to copy/reorganize the entire message.
+        */
+        uint8_t padding[CSP_PADDING_BYTES];
+        /** Data length. Must be just before CSP ID.*/
+	uint16_t length;
+	/** CSP id. Must be just before data, as it allows the interface to id and data
+            in a single operation. */
+	csp_id_t id;
+	/**
+           Data part of packet.
+           When using the csp_buffer API, the size of the data part is set by
+           csp_buffer_init(), and can later be accessed by csp_buffer_data_size()
+        */
+	union {
+		/** Access data as uint8_t. */
+		uint8_t data[0];
+		/** Access data as uint16_t */
+		uint16_t data16[0];
+		/** Access data as uint32_t */
+		uint32_t data32[0];
+	};
+} csp_packet_t;
+//doc-end:csp_packet_t
+
+/**
+   Size of the packet overhead in #csp_packet_t.
+   The overhead is the difference between the total buffer size (returned by csp_buffer_size()) and the data part
+   of the #csp_packet_t (returned by csp_buffer_data_size()).
+*/
+#define CSP_BUFFER_PACKET_OVERHEAD      (sizeof(csp_packet_t) - sizeof(((csp_packet_t *)0)->data))
+
+/** Forward declaration of CSP interface, see #csp_iface_s for details. */
+typedef struct csp_iface_s csp_iface_t;
+/** Forward declaration of outgoing CSP route, see #csp_route_s for details. */
+typedef struct csp_route_s csp_route_t;
+
+/** Forward declaration of socket structure */
+typedef struct csp_conn_s csp_socket_t;
+/** Forward declaration of connection structure */
+typedef struct csp_conn_s csp_conn_t;
+
+/** Max length of host name - including zero termination */
+#define CSP_HOSTNAME_LEN	20
+/** Max length of model name - including zero termination */
+#define CSP_MODEL_LEN		30
+
+/** Magic number for reboot request, for service-code #CSP_REBOOT */
+#define CSP_REBOOT_MAGIC		0x80078007
+/** Magic number for shutdown request, for service-code #CSP_REBOOT */
+#define CSP_REBOOT_SHUTDOWN_MAGIC	0xD1E5529A
+
+#ifdef __AVR__
+typedef uint32_t csp_memptr_t;
+typedef const uint32_t csp_const_memptr_t;
+#else
+/** Memory pointer */
+typedef void * csp_memptr_t;
+/** Const memory pointer */
+typedef const void * csp_const_memptr_t;
+#endif
+
+/**
+   Platform specific memory copy function.
+*/
+typedef csp_memptr_t (*csp_memcpy_fnc_t)(csp_memptr_t, csp_const_memptr_t, size_t);
+
+/**
+   Compile check/asserts.
+*/
+#define CSP_STATIC_ASSERT(condition, name)   typedef char name[(condition) ? 1 : -1]
+    
+#ifdef __cplusplus
+}
+#endif
+#endif /* CSP_TYPES_H_ */

+ 73 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/drivers/can_socketcan.h

@@ -0,0 +1,73 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef LIB_CSP_INCLUDE_CSP_DRIVERS_CAN_SOCKETCAN_H_
+#define LIB_CSP_INCLUDE_CSP_DRIVERS_CAN_SOCKETCAN_H_
+
+/**
+   @file
+
+   Socket CAN driver (Linux).
+
+   This driver requires the libsocketcan library.
+*/
+
+#include <csp/interfaces/csp_if_can.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Open CAN socket and add CSP interface.
+
+   @param[in] device CAN device name (Linux device).
+   @param[in] ifname CSP interface name, use #CSP_IF_CAN_DEFAULT_NAME for default name.
+   @param[in] bitrate if different from 0, it will be attempted to change the bitrate on the CAN device - this may require increased OS privileges.
+   @param[in] promisc if \a true, receive all CAN frames. If \a false a filter is set on the CAN device, using csp_get_address().
+   @param[out] return_iface the added interface.
+   @return The added interface, or NULL in case of failure.
+*/
+int csp_can_socketcan_open_and_add_interface(const char * device, const char * ifname, int bitrate, bool promisc, csp_iface_t ** return_iface);
+
+/**
+   Initialize socketcan and add CSP interface.
+
+   @deprecated version 1.6, use csp_can_socketcan_open_and_add_interface()
+   @param[in] device CAN device name (Linux device).
+   @param[in] bitrate if different from 0, it will be attempted to change the bitrate on the CAN device - this may require increased OS privileges.
+   @param[in] promisc if \a true, receive all CAN frames. If \a false a filter is set on the CAN device, using csp_get_address().
+   @return The added interface, or NULL in case of failure.
+*/
+csp_iface_t * csp_can_socketcan_init(const char * device, int bitrate, bool promisc);
+
+/**
+   Stop the Rx thread and free resources (testing).
+
+   @note This will invalidate CSP, because an interface can't be removed. This is primarily for testing.
+
+   @param[in] iface interface to stop.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_can_socketcan_stop(csp_iface_t * iface);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 121 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/drivers/usart.h

@@ -0,0 +1,121 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_DRIVERS_USART_H
+#define CSP_DRIVERS_USART_H
+
+/**
+   @file
+
+   USART driver.
+
+   @note This interface implementation only support ONE open UART connection.
+*/
+
+#include <csp/interfaces/csp_if_kiss.h>
+
+#if (CSP_WINDOWS)
+#include <Windows.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   OS file handle.
+*/
+#if (CSP_WINDOWS)
+    typedef HANDLE csp_usart_fd_t;
+#else
+    typedef int csp_usart_fd_t;
+#endif
+
+/**
+   Usart configuration.
+   @see csp_usart_open()
+*/
+typedef struct csp_usart_conf {
+    //! USART device.
+    const char *device;
+    //! bits per second.
+    uint32_t baudrate;
+    //! Number of data bits.
+    uint8_t databits;
+    //! Number of stop bits.
+    uint8_t stopbits;
+    //! Parity setting.
+    uint8_t paritysetting;
+    //! Enable parity checking (Windows only).
+    uint8_t checkparity;
+} csp_usart_conf_t;
+
+/**
+   Callback for returning data to application.
+
+   @param[in] buf data received.
+   @param[in] len data length (number of bytes in \a buf).
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+*/
+typedef void (*csp_usart_callback_t) (void * user_data, uint8_t *buf, size_t len, void *pxTaskWoken);
+
+/**
+   Opens an UART device.
+
+   Opens the UART device and creates a thread for reading/returning data to the application.
+
+   @note On read failure, exit() will be called - terminating the process.
+
+   @param[in] conf UART configuration.
+   @param[in] rx_callback receive data callback.
+   @param[in] user_data reference forwarded to the \a rx_callback function.
+   @param[out] fd the opened file descriptor.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_usart_open(const csp_usart_conf_t *conf, csp_usart_callback_t rx_callback, void * user_data, csp_usart_fd_t * fd);
+
+/**
+   Write data on open UART.
+
+   @param[in] fd file descriptor.
+   @param[in] data data to write.
+   @param[in] data_length length of \a data.
+   @return number of bytes written on success, a negative value on failure.
+*/
+int csp_usart_write(csp_usart_fd_t fd, const void * data, size_t data_length);
+
+/**
+   Opens UART device and add KISS interface.
+
+   This is a convience function for opening an UART device and adding it as an interface with a given name.
+
+   @note On read failures, exit() will be called - terminating the process.
+
+   @param[in] conf UART configuration.
+   @param[in] ifname internface name (will be copied), or use NULL for default name.
+   @param[out] return_iface the added interface.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_usart_open_and_add_kiss_interface(const csp_usart_conf_t *conf, const char * ifname, csp_iface_t ** return_iface);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 18 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if.h

@@ -0,0 +1,18 @@
+/*
+ * csp_if.h
+ *
+ *  Created on: 29-Aug-2022
+ *      Author: Build_usr
+ */
+
+#ifndef EXO_STACK_LIBCSP_INCLUDE_CSP_INTERFACES_CSP_IF_H_
+#define EXO_STACK_LIBCSP_INCLUDE_CSP_INTERFACES_CSP_IF_H_
+
+#include "csp_types.h"
+#include "csp.h"
+//#include "csp_init.h"
+//#include "csp_conn.h"
+#include "csp_thread.h"
+
+
+#endif /* EXO_STACK_LIBCSP_INCLUDE_CSP_INTERFACES_CSP_IF_H_ */

+ 178 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_can.h

@@ -0,0 +1,178 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_INTERFACES_CSP_IF_CAN_H
+#define CSP_INTERFACES_CSP_IF_CAN_H
+
+/**
+   @file
+
+   CAN interface.
+
+   CAN frames contains at most 8 bytes of data, so in order to transmit CSP 
+   packets larger than this, a fragmentation protocol is required.
+   The CAN Fragmentation Protocol (CFP) is based on CAN2.0B, using all 29 bits of the
+   identifier. The CAN identifier is divided into these fields:
+
+   - Source:       5 bits
+   - Destination:  5 bits
+   - Type:         1 bit
+   - Remain:       8 bits
+   - Identifier:   10 bits
+
+   The \b Source and \b Destination fields must match the source and destiantion addressses in the CSP packet.
+   The \b Type field is used to distinguish the first and subsequent frames in a fragmented CSP
+   packet. Type is BEGIN (0) for the first fragment and MORE (1) for all other fragments.
+   The \b Remain field indicates number of remaining fragments, and must be decremented by one for each fragment sent.
+   The \b identifier field serves the same purpose as in the Internet Protocol, and should be an auto incrementing
+   integer to uniquely separate sessions.
+
+   Other CAN communication using a standard 11 bit identifier, can co-exist on the wire.
+*/
+
+#include <csp/csp_interface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   @defgroup CFP_SIZE CAN message id field size.
+   @{
+*/
+/** Host - source/destination address. */
+#define CFP_HOST_SIZE		5
+/** Type - \a begin fragment or \a more fragments. */
+#define CFP_TYPE_SIZE		1
+/** Remaining fragments */
+#define CFP_REMAIN_SIZE		8
+/** CFP identification. */
+#define CFP_ID_SIZE		10
+/** @} */
+
+/**
+   @defgroup CFP_FIELDS Macros for extracting fields from CAN message id.
+   @{
+*/
+/** Helper macro */
+#define CFP_FIELD(id,rsiz,fsiz) ((uint32_t)((uint32_t)((id) >> (rsiz)) & (uint32_t)((1 << (fsiz)) - 1)))
+/** Extract source address */
+#define CFP_SRC(id)		CFP_FIELD(id, CFP_HOST_SIZE + CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE)
+/** Extract destination address */
+#define CFP_DST(id)		CFP_FIELD(id, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE)
+/** Extract type (begin or more) */
+#define CFP_TYPE(id)		CFP_FIELD(id, CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_TYPE_SIZE)
+/** Extract remaining fragments */
+#define CFP_REMAIN(id)		CFP_FIELD(id, CFP_ID_SIZE, CFP_REMAIN_SIZE)
+/** Extract CFP identification */
+#define CFP_ID(id)		CFP_FIELD(id, 0, CFP_ID_SIZE)
+/** @} */
+
+/**
+   @defgroup CFP_MAKE Macros for building CAN message id.
+   @{
+*/
+/** Helper macro */
+#define CFP_MAKE_FIELD(id,fsiz,rsiz) ((uint32_t)(((id) & (uint32_t)((uint32_t)(1 << (fsiz)) - 1)) << (rsiz)))
+/** Make source */
+#define CFP_MAKE_SRC(id)	CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_HOST_SIZE + CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE)
+/** Make destination */
+#define CFP_MAKE_DST(id)	CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE)
+/** Make type */
+#define CFP_MAKE_TYPE(id)	CFP_MAKE_FIELD(id, CFP_TYPE_SIZE, CFP_REMAIN_SIZE + CFP_ID_SIZE)
+/** Make remaining fragments */
+#define CFP_MAKE_REMAIN(id)	CFP_MAKE_FIELD(id, CFP_REMAIN_SIZE, CFP_ID_SIZE)
+/** Make CFP id */
+#define CFP_MAKE_ID(id)		CFP_MAKE_FIELD(id, CFP_ID_SIZE, 0)
+/** @} */
+
+/** Mask to uniquely separate connections */
+#define CFP_ID_CONN_MASK	(CFP_MAKE_SRC((uint32_t)(1 << CFP_HOST_SIZE) - 1) | \
+				 CFP_MAKE_DST((uint32_t)(1 << CFP_HOST_SIZE) - 1) | \
+				 CFP_MAKE_ID((uint32_t)(1 << CFP_ID_SIZE) - 1))
+
+/**
+   Default interface name.
+*/
+#define CSP_IF_CAN_DEFAULT_NAME "CAN"
+
+/**
+   Send CAN frame (implemented by driver).
+
+   Used by csp_can_tx() to send CAN frames.
+
+   @param[in] driver_data driver data from #csp_iface_t
+   @param[in] id CAM message id.
+   @param[in] data CAN data 
+   @param[in] dlc data length of \a data.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+typedef int (*csp_can_driver_tx_t)(void * driver_data, uint32_t id, const uint8_t * data, uint8_t dlc);
+
+/**
+   Interface data (state information).
+*/
+typedef struct {
+    /** CFP Identification number - same number on all fragments from same CSP packet. */
+    uint32_t cfp_frame_id;
+    /** Tx function */
+    csp_can_driver_tx_t tx_func;
+} csp_can_interface_data_t;
+
+/**
+   Add interface.
+
+   If the MTU is not set, it will be set to the maximum value of 2042 bytes (max length when using CFP).
+
+   @param[in] iface CSP interface, initialized with name and inteface_data pointing to a valid #csp_can_interface_data_t structure.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_can_add_interface(csp_iface_t * iface);
+
+/**
+   Send CSP packet over CAN (nexthop).
+
+   This function will split the CSP packet into several fragments and call csp_can_tx_fram() for sending each fragment.
+
+   @param[in] ifroute route.
+   @param[in] packet CSP packet to send.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_can_tx(const csp_route_t * ifroute, csp_packet_t *packet);
+
+/**
+   Process received CAN frame.
+
+   Called from driver when a single CAN frame (up to 8 bytes) has been received. The function will gather the fragments into a single
+   CSP packet and route it on when complete.
+
+   @param[in] iface incoming interface.
+   @param[in] id received CAN message identifier.
+   @param[in] data received CAN data.
+   @param[in] dlc length of received \a data.
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_can_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t dlc, CSP_BASE_TYPE *pxTaskWoken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 118 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_i2c.h

@@ -0,0 +1,118 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_IF_I2C_H_
+#define _CSP_IF_I2C_H_
+
+/**
+   @file
+
+   I2C interface.
+*/
+
+#include <csp/csp_interface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Default name of I2C interface.
+*/
+#define CSP_IF_I2C_DEFAULT_NAME "I2C"
+
+//doc-begin:csp_i2c_frame_t
+/**
+   I2C frame.
+   This struct fits on top of a #csp_packet_t, removing the need for copying data.
+*/
+typedef struct i2c_frame_s {
+    //! Not used  (-> csp_packet_t.padding)
+    uint8_t padding[3];
+    //! Cleared before Tx  (-> csp_packet_t.padding)
+    uint8_t retries;
+    //! Not used  (-> csp_packet_t.padding)
+    uint32_t reserved;
+    //! Destination address  (-> csp_packet_t.padding)
+    uint8_t dest;
+    //! Cleared before Tx  (-> csp_packet_t.padding)
+    uint8_t len_rx;
+    //! Length of \a data part  (-> csp_packet_t.length)
+    uint16_t len;
+    //! CSP id + data  (-> csp_packet_t.id)
+    uint8_t data[0];
+} csp_i2c_frame_t;
+//doc-end:csp_i2c_frame_t
+
+/**
+   Send I2C frame (implemented by driver).
+
+   Used by csp_i2c_tx() to send a frame.
+
+   The function must free the frame/packet using csp_buffer_free(), if the send succeeds (returning #CSP_ERR_NONE).
+
+   @param[in] driver_data driver data from #csp_iface_t
+   @param[in] frame destination, length and data. This is actually a #csp_packet_t buffer, casted to #csp_i2c_frame_t.
+   @return #CSP_ERR_NONE on success, or an error code.
+*/
+typedef int (*csp_i2c_driver_tx_t)(void * driver_data, csp_i2c_frame_t * frame);
+
+/**
+   Interface data (state information).
+*/
+typedef struct {
+    /** Tx function */
+    csp_i2c_driver_tx_t tx_func;
+} csp_i2c_interface_data_t;
+
+/**
+   Add interface.
+
+   @param[in] iface CSP interface, initialized with name and inteface_data pointing to a valid #csp_i2c_interface_data_t.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_i2c_add_interface(csp_iface_t * iface);
+
+/**
+   Send CSP packet over I2C (nexthop).
+
+   @param[in] ifroute route.
+   @param[in] packet CSP packet to send.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_i2c_tx(const csp_route_t * ifroute, csp_packet_t * packet);
+
+/**
+   Process received I2C frame.
+
+   @note The received #csp_i2c_frame_t must actually be pointing to an #csp_packet_t.
+
+   Called from driver, when a frame has been received.
+
+   @param[in] iface incoming interface.
+   @param[in] frame received data, routed on as a #csp_packet_t.
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+*/
+void csp_i2c_rx(csp_iface_t * iface, csp_i2c_frame_t * frame, void * pxTaskWoken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 116 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_kiss.h

@@ -0,0 +1,116 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CSP_INTERFACES_CSP_IF_KISS_H
+#define CSP_INTERFACES_CSP_IF_KISS_H
+
+/**
+   @file
+
+   KISS interface (serial).
+*/
+
+#include <csp/csp_interface.h>
+#include <csp/arch/csp_semaphore.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Default name of KISS interface.
+*/
+#define CSP_IF_KISS_DEFAULT_NAME "KISS"
+
+/**
+   Send KISS frame (implemented by driver).
+
+   @param[in] driver_data driver data from #csp_iface_t
+   @param[in] data data to send
+   @param[in] len length of \a data.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+typedef int (*csp_kiss_driver_tx_t)(void *driver_data, const uint8_t * data, size_t len);
+
+/**
+   KISS Rx mode/state.
+*/
+typedef enum {
+	KISS_MODE_NOT_STARTED,  //!< No start detected
+	KISS_MODE_STARTED,      //!< Started on a KISS frame
+	KISS_MODE_ESCAPED,      //!< Rx escape character 
+	KISS_MODE_SKIP_FRAME,   //!< Skip remaining frame, wait for end character
+} csp_kiss_mode_t;
+
+/**
+   KISS interface data (state information).
+*/
+typedef struct {
+	/** Max Rx length */
+	unsigned int max_rx_length;
+	/** Tx function */
+	csp_kiss_driver_tx_t tx_func;
+	/** Tx lock. Current implementation doesn't transfer data to driver in a single 'write', hence locking is necessary. */
+	csp_mutex_t lock;
+	/** Rx mode/state. */
+	csp_kiss_mode_t rx_mode;
+	/** Rx length */
+	unsigned int rx_length;
+	/** Rx first - if set, waiting for first character (== TNC_DATA) after start */
+	bool rx_first;
+	/** CSP packet for storing Rx data. */
+	csp_packet_t * rx_packet;
+} csp_kiss_interface_data_t;
+
+/**
+   Add interface.
+
+   If the MTU is not set, it will be set to the csp_buffer_data_size() - sizeof(uint32_t), to make room for the CRC32 added to the packet.
+
+   @param[in] iface CSP interface, initialized with name and inteface_data pointing to a valid #csp_kiss_interface_data_t.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_kiss_add_interface(csp_iface_t * iface);
+
+/**
+   Send CSP packet over KISS (nexthop).
+
+   @param[in] ifroute route.
+   @param[in] packet CSP packet to send.
+   @return #CSP_ERR_NONE on success, otherwise an error code.
+*/
+int csp_kiss_tx(const csp_route_t * ifroute, csp_packet_t * packet);
+
+/**
+   Process received CAN frame.
+
+   Called from driver when a chunk of data has been received. Once a complete frame has been received, the CSP packet will be routed on.
+
+   @param[in] iface incoming interface.
+   @param[in] buf reveived data.
+   @param[in] len length of \a buf.
+   @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
+*/
+void csp_kiss_rx(csp_iface_t * iface, const uint8_t * buf, size_t len, void * pxTaskWoken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 49 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_lo.h

@@ -0,0 +1,49 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CSP_IF_LO_H_
+#define _CSP_IF_LO_H_
+
+/**
+   @file
+
+   Loopback interface.
+*/
+
+#include <csp/csp_interface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Name of loopback interface.
+*/
+#define CSP_IF_LOOPBACK_NAME "LOOP"
+
+/**
+   Loopback interface.
+*/
+extern csp_iface_t csp_if_lo;
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 54 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_mcast.h

@@ -0,0 +1,54 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2016 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2016 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+ * Multicast UDP interface for CSP
+ * Copyright (C) 2016 Satlab ApS (http://www.satlab.com) 
+ */
+
+#ifndef _CSP_IF_MCAST_H_
+#define _CSP_IF_MCAST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <csp/csp.h>
+#include <csp/csp_interface.h>
+
+/**
+   Default MCAST interface name.
+*/
+#define CSP_IF_MCAST_DEFAULT_NAME	"MCAST"
+
+/**
+   Setup multicast interface.
+   @param[in] device IP Interface to bind to for multicast traffic, NULL for any
+   @param[in] ifname Name of CSP interface, use NULL for default name #CSP_IF_MCAST_DEFAULT_NAME.
+   @param[out] ifc created CSP interface.
+   @return #CSP_ERR_NONE on succcess - else assert.
+*/
+int csp_mcast_init(const char *device, const char *ifname, csp_iface_t **ifc);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _CSP_IF_MCAST_H_ */

+ 34 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_slgnd.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 Satlab A/S (https://www.satlab.com)
+ *
+ * This file is part of CSP. See COPYING for details.
+ */
+
+#ifndef _CSP_IF_SLGND_H_
+#define _CSP_IF_SLGND_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <csp/csp_interface.h>
+
+/**
+   Default name of SLGND interface.
+*/
+#define CSP_IF_SLGND_DEFAULT_NAME	"SLGND"
+
+/**
+   Setup SLGND interface.
+   @param[in] radio_host Hostname or IP address of radio host. Append :port to change from the default port.
+   @param[in] ifname Name of CSP interface, use NULL for default name #CSP_IF_SLGND_DEFAULT_NAME.
+   @param[out] ifc Created CSP interface.
+   @return #CSP_ERR_NONE on succcess - else assert.
+*/
+int csp_slgnd_init(const char *radio_host, const char *ifname, csp_iface_t **ifc);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _CSP_IF_SLGND_H_ */

+ 34 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_slgnd_tcp.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 Satlab A/S (https://www.satlab.com)
+ *
+ * This file is part of CSP. See COPYING for details.
+ */
+
+#ifndef _CSP_IF_SLGND_H_
+#define _CSP_IF_SLGND_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <csp/csp_interface.h>
+
+/**
+   Default name of SLGND interface.
+*/
+#define CSP_IF_SLGND_DEFAULT_NAME	"SLGND"
+
+/**
+   Setup SLGND interface.
+   @param[in] radio_host Hostname or IP address of radio host. Append :port to change from the default port.
+   @param[in] ifname Name of CSP interface, use NULL for default name #CSP_IF_SLGND_DEFAULT_NAME.
+   @param[out] ifc Created CSP interface.
+   @return #CSP_ERR_NONE on succcess - else assert.
+*/
+int csp_slgnd_init_tcp(const char *radio_host, const char *radio_addr,const char *ifname, csp_iface_t **ifc);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _CSP_IF_SLGND_H_ */

+ 118 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/include/csp/interfaces/csp_if_zmqhub.h

@@ -0,0 +1,118 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 GomSpace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef CSP_IF_ZMQHUB_H_
+#define CSP_IF_ZMQHUB_H_
+
+/**
+   @file
+
+   ZMQ (ZeroMQ) interface.
+
+   The ZMQ interface is designed to connect to a ZMQ hub, also refered to as \a zmqproxy. The zmqproxy can be found under examples,
+   and is based on zmq_proxy() - provided by the ZMQ API.
+
+   For further details on ZMQ, see http://www.zeromq.org.
+*/
+
+#include <csp/csp_interface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   zmqproxy default subscribe (rx) port.
+   The client must connect it's publish endpoint to the zmqproxy's subscribe port.
+*/
+#define CSP_ZMQPROXY_SUBSCRIBE_PORT   6000
+
+/**
+   zmqproxy default publish (tx) port.
+   The client must connect it's subscribe endpoint to the zmqproxy's publish port.
+*/
+#define CSP_ZMQPROXY_PUBLISH_PORT     7000
+
+/**
+   Default ZMQ interface name.
+*/
+#define CSP_ZMQHUB_IF_NAME            "ZMQHUB"
+
+/**
+   Format endpoint connection string for ZMQ.
+
+   @param[in] host host name of IP.
+   @param[in] port IP port.
+   @param[out] buf user allocated buffer for receiving formatted string.
+   @param[in] buf_size size of \a buf.
+   @return #CSP_ERR_NONE on succcess.
+   @return #CSP_ERR_NOMEM if supplied buffer too small.
+*/
+int csp_zmqhub_make_endpoint(const char * host, uint16_t port, char * buf, size_t buf_size);
+
+/**
+   Setup ZMQ interface.
+   @param[in] addr only receive messages matching this address (255 means all). This is set as \a rx_filter in call to 
+   @param[in] host host name or IP of zmqproxy host. Endpoints are created using the \a host and the default subscribe/publish ports.
+   @param[in] flags flags for controlling features on the connection.
+   @param[out] return_interface created CSP interface.
+   @return #CSP_ERR_NONE on succcess - else assert.
+*/
+int csp_zmqhub_init(uint8_t addr,
+                    const char * host,
+                    uint32_t flags,
+                    csp_iface_t ** return_interface);
+
+/**
+   Setup ZMQ interface.
+   @param[in] addr only receive messages matching this address (255 means all). This is set as a \a rx_filter.
+   @param[in] publish_endpoint publish (tx) endpoint -> connect to zmqproxy's subscribe port #CSP_ZMQPROXY_SUBSCRIBE_PORT.
+   @param[in] subscribe_endpoint subscribe (rx) endpoint -> connect to zmqproxy's publish port #CSP_ZMQPROXY_PUBLISH_PORT.
+   @param[in] flags flags for controlling features on the connection.
+   @param[out] return_interface created CSP interface.
+   @return #CSP_ERR_NONE on succcess - else assert.
+*/
+int csp_zmqhub_init_w_endpoints(uint8_t addr,
+                                const char * publish_endpoint,
+                                const char * subscribe_endpoint,
+                                uint32_t flags,
+                                csp_iface_t ** return_interface);
+
+/**
+   Setup ZMQ interface.
+   @param[in] ifname Name of CSP interface, use NULL for default name #CSP_ZMQHUB_IF_NAME.
+   @param[in] rx_filter Rx filters, use NULL for no filters - receive all messages.
+   @param[in] rx_filter_count Number of Rx filters in \a rx_filter.
+   @param[in] publish_endpoint publish (tx) endpoint -> connect to zmqproxy's subscribe port #CSP_ZMQPROXY_SUBSCRIBE_PORT.
+   @param[in] subscribe_endpoint subscribe (rx) endpoint -> connect to zmqproxy's publish port #CSP_ZMQPROXY_PUBLISH_PORT.
+   @param[in] flags flags for controlling features on the connection.
+   @param[out] return_interface created CSP interface.
+   @return #CSP_ERR_NONE on succcess - else assert.
+*/
+int csp_zmqhub_init_w_name_endpoints_rxfilter(const char * ifname,
+                                              const uint8_t rx_filter[], unsigned int rx_filter_count,
+                                              const char * publish_endpoint,
+                                              const char * subscribe_endpoint,
+                                              uint32_t flags,
+                                              csp_iface_t ** return_interface);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 43 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/makefile

@@ -0,0 +1,43 @@
+
+include ../../Makefile.def
+
+##############################################################################
+# List of include file directories required for compilation
+INCLUDES = -Iinclude/\
+	   -Iinclude/csp/\
+	   -Iinclude/csp/interfaces/\
+	   -Iinclude/csp/drivers/\
+	   -Iinclude/csp/crypto/\
+	   -Iinclude/csp/arch/\
+	   -Iinclude/csp/arch/posix\
+	   -Isrc/\
+	   -Isrc/transport\
+	   -Isrc/rtable\
+	   -Isrc/interfaces\
+	   -Isrc/arch\
+	   -Isrc/arch/posix\
+
+##############################################################################
+# List of source files required for compilation using SRC
+# mention the directory path where all C files to be compiled usig SRC_DIR
+# Mention Sub director makefile compilation using SUBDIR
+
+SRC = src/*.c\
+      src/transport/*.c\
+      src/rtable/*.c\
+      src/interfaces/*.c\
+      src/crypto/*.c\
+      src/arch/*.c\
+      src/arch/posix/*.c\
+
+##############################################################################
+# Command to compile source files to intermediate object files
+all:
+	$(CC) $(CFLAGS) -c $(SRC) $(INCLUDES)
+	ar rcs libcsp_lib.a ./*.o
+	rm -f ./*.o
+
+# Command to delete intermediate object files
+clean:
+	rm -f ./*.o
+	rm -f ./*.a

+ 23 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/csp_system.c

@@ -0,0 +1,23 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_system.h>
+
+#include <csp/csp_debug.h>

+ 21 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/csp_time.c

@@ -0,0 +1,21 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_time.h>

+ 32 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_clock.c

@@ -0,0 +1,32 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_clock.h>
+#include <csp/csp_debug.h>
+
+__attribute__((weak)) void csp_clock_get_time(csp_timestamp_t * time) {
+    time->tv_sec = 0;
+    time->tv_nsec = 0;
+}
+
+__attribute__((weak)) int csp_clock_set_time(const csp_timestamp_t * time) {
+    csp_log_warn("csp_clock_set_time() not supported");
+    return CSP_ERR_NOTSUP;
+}

+ 42 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_malloc.c

@@ -0,0 +1,42 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_malloc.h>
+
+#include <string.h>
+
+#include <FreeRTOS.h>
+
+void * csp_malloc(size_t size) {
+	return pvPortMalloc(size);
+}
+
+void * csp_calloc(size_t nmemb, size_t size) {
+	size = (nmemb * size); 
+	void * ptr = csp_malloc(size);
+	if (ptr) {
+		memset(ptr, 0, size);
+	}
+	return ptr;
+}
+
+void csp_free(void *ptr) {
+	vPortFree(ptr);
+}

+ 60 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_queue.c

@@ -0,0 +1,60 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_queue.h>
+
+#include <FreeRTOS.h>
+#include <queue.h> // FreeRTOS
+
+csp_queue_handle_t csp_queue_create(int length, size_t item_size) {
+	return xQueueCreate(length, item_size);
+}
+
+void csp_queue_remove(csp_queue_handle_t queue) {
+	vQueueDelete(queue);
+}
+
+int csp_queue_enqueue(csp_queue_handle_t handle, const void * value, uint32_t timeout) {
+	if (timeout != CSP_MAX_TIMEOUT)
+		timeout = timeout / portTICK_RATE_MS;
+	return xQueueSendToBack(handle, value, timeout);
+}
+
+int csp_queue_enqueue_isr(csp_queue_handle_t handle, const void * value, CSP_BASE_TYPE * task_woken) {
+	return xQueueSendToBackFromISR(handle, value, task_woken);
+}
+
+int csp_queue_dequeue(csp_queue_handle_t handle, void * buf, uint32_t timeout) {
+	if (timeout != CSP_MAX_TIMEOUT)
+		timeout = timeout / portTICK_RATE_MS;
+	return xQueueReceive(handle, buf, timeout);
+}
+
+int csp_queue_dequeue_isr(csp_queue_handle_t handle, void * buf, CSP_BASE_TYPE * task_woken) {
+	return xQueueReceiveFromISR(handle, buf, task_woken);
+}
+
+int csp_queue_size(csp_queue_handle_t handle) {
+	return uxQueueMessagesWaiting(handle);
+}
+
+int csp_queue_size_isr(csp_queue_handle_t handle) {
+	return uxQueueMessagesWaitingFromISR(handle);
+}

+ 84 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_semaphore.c

@@ -0,0 +1,84 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_semaphore.h>
+#include <csp/csp_debug.h>
+
+int csp_mutex_create(csp_mutex_t * mutex) {
+	*mutex = xSemaphoreCreateMutex();
+	if (*mutex) {
+		return CSP_SEMAPHORE_OK;
+	} else {
+		return CSP_SEMAPHORE_ERROR;
+	}
+}
+
+int csp_mutex_remove(csp_mutex_t * mutex) {
+	return csp_bin_sem_remove(mutex);
+}
+
+int csp_mutex_lock(csp_mutex_t * mutex, uint32_t timeout) {
+	return csp_bin_sem_wait(mutex, timeout);
+}
+
+int csp_mutex_unlock(csp_mutex_t * mutex) {
+	return csp_bin_sem_post(mutex);
+}
+
+int csp_bin_sem_create(csp_bin_sem_handle_t * sem) {
+	vSemaphoreCreateBinary(*sem);
+	return CSP_SEMAPHORE_OK;
+}
+
+int csp_bin_sem_remove(csp_bin_sem_handle_t * sem) {
+	if ((sem != NULL) && (*sem != NULL)) {
+		vSemaphoreDelete(*sem);
+	}
+	return CSP_SEMAPHORE_OK;
+}
+
+int csp_bin_sem_wait(csp_bin_sem_handle_t * sem, uint32_t timeout) {
+	csp_log_lock("Wait: %p", sem);
+	if (timeout != CSP_MAX_TIMEOUT) {
+		timeout = timeout / portTICK_RATE_MS;
+	}
+	if (xSemaphoreTake(*sem, timeout) == pdPASS) {
+		return CSP_SEMAPHORE_OK;
+	}
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_bin_sem_post(csp_bin_sem_handle_t * sem) {
+	csp_log_lock("Post: %p", sem);
+	if (xSemaphoreGive(*sem) == pdPASS) {
+		return CSP_SEMAPHORE_OK;
+	}
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_bin_sem_post_isr(csp_bin_sem_handle_t * sem, CSP_BASE_TYPE * pxTaskWoken) {
+	csp_log_lock("Post: %p", sem);
+	if (xSemaphoreGiveFromISR(*sem, pxTaskWoken) == pdPASS) {
+		return CSP_SEMAPHORE_OK;
+	} else {
+		return CSP_SEMAPHORE_ERROR;
+	}
+}
+

+ 88 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_system.c

@@ -0,0 +1,88 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_system.h>
+
+#include <FreeRTOS.h>
+#include <task.h> // FreeRTOS
+
+#include <csp/csp_debug.h>
+
+int csp_sys_tasklist(char * out) {
+#if (tskKERNEL_VERSION_MAJOR < 8)
+	vTaskList((signed portCHAR *) out);
+#else
+	vTaskList(out);
+#endif
+	return CSP_ERR_NONE;
+}
+
+int csp_sys_tasklist_size(void) {
+
+	return 40 * uxTaskGetNumberOfTasks();
+}
+
+uint32_t csp_sys_memfree(void) {
+
+	return (uint32_t) xPortGetFreeHeapSize();
+
+}
+
+void csp_sys_set_color(csp_color_t color) {
+
+	unsigned int color_code, modifier_code;
+	switch (color & COLOR_MASK_COLOR) {
+		case COLOR_BLACK:
+			color_code = 30; break;
+		case COLOR_RED:
+			color_code = 31; break;
+		case COLOR_GREEN:
+			color_code = 32; break;
+		case COLOR_YELLOW:
+			color_code = 33; break;
+		case COLOR_BLUE:
+			color_code = 34; break;
+		case COLOR_MAGENTA:
+			color_code = 35; break;
+		case COLOR_CYAN:
+			color_code = 36; break;
+		case COLOR_WHITE:
+			color_code = 37; break;
+		case COLOR_RESET:
+		default:
+			color_code = 0; break;
+	}
+	
+	switch (color & COLOR_MASK_MODIFIER) {
+		case COLOR_BOLD:
+			modifier_code = 1; break;
+		case COLOR_UNDERLINE:
+			modifier_code = 2; break;
+		case COLOR_BLINK:
+			modifier_code = 3; break;
+		case COLOR_HIDE:
+			modifier_code = 4; break;
+		case COLOR_NORMAL:
+		default:
+			modifier_code = 0; break;
+	}
+
+	printf("\033[%u;%um", modifier_code, color_code);
+}

+ 48 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_thread.c

@@ -0,0 +1,48 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_thread.h>
+
+int csp_thread_create(csp_thread_func_t routine, const char * const thread_name, unsigned int stack_size, void * parameters, unsigned int priority, csp_thread_handle_t * return_handle) {
+
+	csp_thread_handle_t handle;
+#if (tskKERNEL_VERSION_MAJOR >= 8)
+	portBASE_TYPE ret = xTaskCreate(routine, thread_name, stack_size, parameters, priority, &handle);
+#else
+	portBASE_TYPE ret = xTaskCreate(routine, (signed char *) thread_name, stack_size, parameters, priority, &handle);
+#endif
+	if (ret != pdTRUE) {
+		return CSP_ERR_NOMEM;
+	}
+	if (return_handle) {
+		*return_handle = handle;
+	}
+	return CSP_ERR_NONE;
+}
+
+void csp_thread_exit(void) {
+
+	vTaskDelete(NULL);  // Function must exist, otherwise code wont behave the same on all platforms.
+}
+
+void csp_sleep_ms(unsigned int time_ms) {
+
+	vTaskDelay(time_ms / portTICK_RATE_MS);
+}

+ 40 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/freertos/csp_time.c

@@ -0,0 +1,40 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_time.h>
+
+#include <FreeRTOS.h>
+#include <task.h> // FreeRTOS
+
+uint32_t csp_get_ms(void) {
+	return (uint32_t)(xTaskGetTickCount() * (1000/configTICK_RATE_HZ));
+}
+
+uint32_t csp_get_ms_isr(void) {
+	return (uint32_t)(xTaskGetTickCountFromISR() * (1000/configTICK_RATE_HZ));
+}
+
+uint32_t csp_get_s(void) {
+	return (uint32_t)(xTaskGetTickCount()/configTICK_RATE_HZ);
+}
+
+uint32_t csp_get_s_isr(void) {
+	return (uint32_t)(xTaskGetTickCountFromISR()/configTICK_RATE_HZ);
+}

+ 22 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_clock.c

@@ -0,0 +1,22 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Use POSIX implementation
+#include "../posix/csp_clock.c"

+ 22 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_malloc.c

@@ -0,0 +1,22 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Use POSIX implementation
+#include "../posix/csp_malloc.c"

+ 22 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_queue.c

@@ -0,0 +1,22 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Use POSIX implementation
+#include "../posix/csp_queue.c"

+ 85 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_semaphore.c

@@ -0,0 +1,85 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_semaphore.h>
+
+#include <sys/time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <csp/csp_debug.h>
+
+int csp_mutex_create(csp_mutex_t * mutex) {
+	csp_log_lock("Mutex init: %p", mutex);
+	*mutex = pthread_queue_create(1, sizeof(int));
+	if (*mutex) {
+		int dummy = 0;
+		pthread_queue_enqueue(*mutex, &dummy, 0);
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_mutex_remove(csp_mutex_t * mutex) {
+	pthread_queue_delete(*mutex);
+	return CSP_SEMAPHORE_OK;
+}
+
+int csp_mutex_lock(csp_mutex_t * mutex, uint32_t timeout) {
+
+	csp_log_lock("Wait: %p timeout %"PRIu32, mutex, timeout);
+
+	int dummy = 0;
+	if (pthread_queue_dequeue(*mutex, &dummy, timeout) == PTHREAD_QUEUE_OK) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_mutex_unlock(csp_mutex_t * mutex) {
+	int dummy = 0;
+	if (pthread_queue_enqueue(*mutex, &dummy, 0) == PTHREAD_QUEUE_OK) {
+		return CSP_SEMAPHORE_OK;
+	}
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_bin_sem_create(csp_bin_sem_handle_t * sem) {
+	return csp_mutex_create(sem);
+}
+
+int csp_bin_sem_remove(csp_bin_sem_handle_t * sem) {
+	return csp_mutex_remove(sem);
+}
+
+int csp_bin_sem_wait(csp_bin_sem_handle_t * sem, uint32_t timeout) {
+	return csp_mutex_lock(sem, timeout);
+}
+
+int csp_bin_sem_post(csp_bin_sem_handle_t * sem) {
+	return csp_mutex_unlock(sem);
+}
+
+int csp_bin_sem_post_isr(csp_bin_sem_handle_t * sem, CSP_BASE_TYPE * task_woken) {
+	return csp_mutex_unlock(sem);
+}

+ 87 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_system.c

@@ -0,0 +1,87 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_system.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <csp/csp.h>
+
+int csp_sys_tasklist(char * out) {
+
+	strcpy(out, "Tasklist not available on OSX");
+	return CSP_ERR_NONE;
+
+}
+
+int csp_sys_tasklist_size(void) {
+
+        return 100;
+
+}
+
+uint32_t csp_sys_memfree(void) {
+
+	return 0; // not implemented
+
+}
+
+void csp_sys_set_color(csp_color_t color) {
+
+	unsigned int color_code, modifier_code;
+	switch (color & COLOR_MASK_COLOR) {
+		case COLOR_BLACK:
+			color_code = 30; break;
+		case COLOR_RED:
+			color_code = 31; break;
+		case COLOR_GREEN:
+			color_code = 32; break;
+		case COLOR_YELLOW:
+			color_code = 33; break;
+		case COLOR_BLUE:
+			color_code = 34; break;
+		case COLOR_MAGENTA:
+			color_code = 35; break;
+		case COLOR_CYAN:
+			color_code = 36; break;
+		case COLOR_WHITE:
+			color_code = 37; break;
+		case COLOR_RESET:
+		default:
+			color_code = 0; break;
+	}
+	
+	switch (color & COLOR_MASK_MODIFIER) {
+		case COLOR_BOLD:
+			modifier_code = 1; break;
+		case COLOR_UNDERLINE:
+			modifier_code = 2; break;
+		case COLOR_BLINK:
+			modifier_code = 3; break;
+		case COLOR_HIDE:
+			modifier_code = 4; break;
+		case COLOR_NORMAL:
+		default:
+			modifier_code = 0; break;
+	}
+
+	printf("\033[%u;%um", modifier_code, color_code);
+}

+ 55 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_thread.c

@@ -0,0 +1,55 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_thread.h>
+
+#include <time.h>
+#include <errno.h>
+
+int csp_thread_create(csp_thread_func_t routine, const char * const thread_name, unsigned int stack_size, void * parameters, unsigned int priority, csp_thread_handle_t * return_handle) {
+
+	pthread_t handle;
+	int res = pthread_create(&handle, NULL, routine, parameters);
+	if (res) {
+		return CSP_ERR_NOMEM;
+	}
+	if (return_handle) {
+		*return_handle = handle;
+	}
+
+	return CSP_ERR_NONE;
+}
+
+void csp_thread_exit(void) {
+
+	pthread_exit(CSP_TASK_RETURN);
+}
+
+void csp_sleep_ms(unsigned int time_ms) {
+
+
+	struct timespec req, rem;
+	req.tv_sec = (time_ms / 1000U);
+	req.tv_nsec = ((time_ms % 1000U) * 1000000U);
+
+	while ((nanosleep(&req, &rem) < 0) && (errno == EINTR)) {
+		req = rem;
+	}
+}

+ 22 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/csp_time.c

@@ -0,0 +1,22 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Use POSIX implementation
+#include "../posix/csp_time.c"

+ 178 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/macosx/pthread_queue.c

@@ -0,0 +1,178 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Inspired by c-pthread-queue by Matthew Dickinson
+http://code.google.com/p/c-pthread-queue/
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <mach/clock.h>
+#include <mach/mach.h>
+
+#include <csp/arch/posix/pthread_queue.h>
+
+pthread_queue_t * pthread_queue_create(int length, size_t item_size) {
+
+	pthread_queue_t * q = malloc(sizeof(pthread_queue_t));
+
+	if (q != NULL) {
+		q->buffer = malloc(length*item_size);
+		if (q->buffer != NULL) {
+			q->size = length;
+			q->item_size = item_size;
+			q->items = 0;
+			q->in = 0;
+			q->out = 0;
+			if (pthread_mutex_init(&(q->mutex), NULL) || pthread_cond_init(&(q->cond_full), NULL) || pthread_cond_init(&(q->cond_empty), NULL)) {
+				free(q->buffer);
+				free(q);
+				q = NULL;
+			}
+		} else {
+			free(q);
+			q = NULL;
+		}
+	}
+
+	return q;
+
+}
+
+void pthread_queue_delete(pthread_queue_t * q) {
+
+	if (q == NULL)
+		return;
+
+	free(q->buffer);
+	free(q);
+
+	return;
+
+}
+
+int pthread_queue_enqueue(pthread_queue_t * queue, const void * value, uint32_t timeout) {
+
+	int ret;
+
+	/* Calculate timeout */
+	struct timespec ts;
+
+	clock_serv_t cclock;
+	mach_timespec_t mts;
+	host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+	clock_get_time(cclock, &mts);
+	mach_port_deallocate(mach_task_self(), cclock);
+	ts.tv_sec = mts.tv_sec;
+	ts.tv_nsec = mts.tv_nsec;
+
+	uint32_t sec = timeout / 1000;
+	uint32_t nsec = (timeout - 1000 * sec) * 1000000;
+
+	ts.tv_sec += sec;
+
+	if (ts.tv_nsec + nsec > 1000000000)
+		ts.tv_sec++;
+
+	ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
+
+	/* Get queue lock */
+	pthread_mutex_lock(&(queue->mutex));
+	while (queue->items == queue->size) {
+		ret = pthread_cond_timedwait(&(queue->cond_full), &(queue->mutex), &ts);
+		if (ret != 0) {
+			pthread_mutex_unlock(&(queue->mutex));
+			return PTHREAD_QUEUE_FULL;
+		}
+	}
+
+	/* Copy object from input buffer */
+	memcpy(queue->buffer+(queue->in * queue->item_size), value, queue->item_size);
+	queue->items++;
+	queue->in = (queue->in + 1) % queue->size;
+	pthread_mutex_unlock(&(queue->mutex));
+
+	/* Nofify blocked threads */
+	pthread_cond_broadcast(&(queue->cond_empty));
+
+	return PTHREAD_QUEUE_OK;
+
+}
+
+int pthread_queue_dequeue(pthread_queue_t * queue, void * buf, uint32_t timeout) {
+
+	int ret;
+
+	/* Calculate timeout */
+	struct timespec ts;
+	clock_serv_t cclock;
+	mach_timespec_t mts;
+	host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+	clock_get_time(cclock, &mts);
+	mach_port_deallocate(mach_task_self(), cclock);
+	ts.tv_sec = mts.tv_sec;
+	ts.tv_nsec = mts.tv_nsec;
+
+	uint32_t sec = timeout / 1000;
+	uint32_t nsec = (timeout - 1000 * sec) * 1000000;
+
+	ts.tv_sec += sec;
+
+	if (ts.tv_nsec + nsec > 1000000000)
+		ts.tv_sec++;
+
+	ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
+
+	/* Get queue lock */
+	pthread_mutex_lock(&(queue->mutex));
+	while (queue->items == 0) {
+		ret = pthread_cond_timedwait(&(queue->cond_empty), &(queue->mutex), &ts);
+		if (ret != 0) {
+			pthread_mutex_unlock(&(queue->mutex));
+			return PTHREAD_QUEUE_EMPTY;
+		}
+	}
+
+	/* Copy object to output buffer */
+	memcpy(buf, queue->buffer+(queue->out * queue->item_size), queue->item_size);
+	queue->items--;
+	queue->out = (queue->out + 1) % queue->size;
+	pthread_mutex_unlock(&(queue->mutex));
+
+	/* Nofify blocked threads */
+	pthread_cond_broadcast(&(queue->cond_full));
+
+	return PTHREAD_QUEUE_OK;
+
+}
+
+int pthread_queue_items(pthread_queue_t * queue) {
+
+	pthread_mutex_lock(&(queue->mutex));
+	int items = queue->items;
+	pthread_mutex_unlock(&(queue->mutex));
+
+	return items;
+
+}

+ 45 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_clock.c

@@ -0,0 +1,45 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_clock.h>
+
+#include <time.h>
+
+__attribute__((weak)) void csp_clock_get_time(csp_timestamp_t * time) {
+
+	struct timespec ts;
+	if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
+		time->tv_sec = ts.tv_sec;
+		time->tv_nsec = ts.tv_nsec;
+	} else {
+		time->tv_sec = 0;
+		time->tv_nsec = 0;
+	}
+}
+
+__attribute__((weak)) int csp_clock_set_time(const csp_timestamp_t * time) {
+
+	struct timespec ts = {.tv_sec = time->tv_sec, .tv_nsec = time->tv_nsec};
+	if (clock_settime(CLOCK_REALTIME, &ts) == 0) {
+		return CSP_ERR_NONE;
+	}
+	return CSP_ERR_INVAL; // CSP doesn't have any matching error codes
+
+}

+ 36 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_malloc.c

@@ -0,0 +1,36 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_malloc.h>
+
+#include <stdlib.h>
+
+void * csp_malloc(size_t size) {
+	return malloc(size);
+}
+
+void * csp_calloc(size_t nmemb, size_t size) {
+	return calloc(nmemb, size);
+}
+
+void csp_free(void *ptr) {
+	free(ptr);
+}
+

+ 60 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_queue.c

@@ -0,0 +1,60 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_queue.h>
+#include <csp/arch/posix/pthread_queue.h>
+
+csp_queue_handle_t csp_queue_create(int length, size_t item_size) {
+	return pthread_queue_create(length, item_size);
+}
+
+void csp_queue_remove(csp_queue_handle_t queue) {
+	return pthread_queue_delete(queue);
+}
+
+int csp_queue_enqueue(csp_queue_handle_t handle, const void *value, uint32_t timeout) {
+	return pthread_queue_enqueue(handle, value, timeout);
+}
+
+int csp_queue_enqueue_isr(csp_queue_handle_t handle, const void * value, CSP_BASE_TYPE * task_woken) {
+	if (task_woken != NULL) {
+		*task_woken = 0;
+	}
+	return csp_queue_enqueue(handle, value, 0);
+}
+
+int csp_queue_dequeue(csp_queue_handle_t handle, void *buf, uint32_t timeout) {
+	return pthread_queue_dequeue(handle, buf, timeout);
+}
+
+int csp_queue_dequeue_isr(csp_queue_handle_t handle, void *buf, CSP_BASE_TYPE * task_woken) {
+	if (task_woken != NULL) {
+		*task_woken = 0;
+	}
+	return csp_queue_dequeue(handle, buf, 0);
+}
+
+int csp_queue_size(csp_queue_handle_t handle) {
+	return pthread_queue_items(handle);
+}
+
+int csp_queue_size_isr(csp_queue_handle_t handle) {
+	return pthread_queue_items(handle);
+}

+ 155 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_semaphore.c

@@ -0,0 +1,155 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_semaphore.h>
+#include <csp/csp_debug.h>
+
+int csp_mutex_create(csp_mutex_t * mutex) {
+	csp_log_lock("Mutex init: %p", mutex);
+	if (pthread_mutex_init(mutex, NULL) == 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_mutex_remove(csp_mutex_t * mutex) {
+	if (pthread_mutex_destroy(mutex) == 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_mutex_lock(csp_mutex_t * mutex, uint32_t timeout) {
+
+	int ret;
+
+	csp_log_lock("Wait: %p timeout %"PRIu32, mutex, timeout);
+
+	if (timeout == CSP_MAX_TIMEOUT) {
+		ret = pthread_mutex_lock(mutex);
+	} else {
+		struct timespec ts;
+		if (clock_gettime(CLOCK_REALTIME, &ts)) {
+			return CSP_SEMAPHORE_ERROR;
+		}
+
+		uint32_t sec = timeout / 1000;
+		uint32_t nsec = (timeout - 1000 * sec) * 1000000;
+
+		ts.tv_sec += sec;
+
+		if (ts.tv_nsec + nsec >= 1000000000) {
+			ts.tv_sec++;
+		}
+
+		ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
+
+		ret = pthread_mutex_timedlock(mutex, &ts);
+	}
+
+	if (ret != 0)
+		return CSP_SEMAPHORE_ERROR;
+
+	return CSP_SEMAPHORE_OK;
+}
+
+int csp_mutex_unlock(csp_mutex_t * mutex) {
+	if (pthread_mutex_unlock(mutex) == 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_bin_sem_create(csp_bin_sem_handle_t * sem) {
+	csp_log_lock("Semaphore init: %p", sem);
+	if (sem_init(sem, 0, 1) == 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_bin_sem_remove(csp_bin_sem_handle_t * sem) {
+	if (sem_destroy(sem) == 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}
+
+int csp_bin_sem_wait(csp_bin_sem_handle_t * sem, uint32_t timeout) {
+
+	int ret;
+
+	csp_log_lock("Wait: %p timeout %"PRIu32, sem, timeout);
+
+	if (timeout == CSP_MAX_TIMEOUT) {
+		ret = sem_wait(sem);
+	} else {
+		struct timespec ts;
+		if (clock_gettime(CLOCK_REALTIME, &ts)) {
+			return CSP_SEMAPHORE_ERROR;
+		}
+
+		uint32_t sec = timeout / 1000;
+		uint32_t nsec = (timeout - 1000 * sec) * 1000000;
+
+		ts.tv_sec += sec;
+
+		if (ts.tv_nsec + nsec >= 1000000000) {
+			ts.tv_sec++;
+		}
+
+		ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
+
+		ret = sem_timedwait(sem, &ts);
+	}
+
+	if (ret != 0)
+		return CSP_SEMAPHORE_ERROR;
+
+	return CSP_SEMAPHORE_OK;
+}
+
+int csp_bin_sem_post_isr(csp_bin_sem_handle_t * sem, CSP_BASE_TYPE * task_woken) {
+	if (task_woken) {
+		*task_woken = 0;
+	}
+	return csp_bin_sem_post(sem);
+}
+
+int csp_bin_sem_post(csp_bin_sem_handle_t * sem) {
+	csp_log_lock("Post: %p", sem);
+
+	int value;
+	sem_getvalue(sem, &value);
+	if (value > 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	if (sem_post(sem) == 0) {
+		return CSP_SEMAPHORE_OK;
+	}
+
+	return CSP_SEMAPHORE_ERROR;
+}

+ 135 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_system.c

@@ -0,0 +1,135 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/posix/csp_system.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/sysinfo.h>
+#include <sys/reboot.h>
+#include <linux/reboot.h>
+
+#include <csp/csp_debug.h>
+
+int csp_sys_tasklist(char * out) {
+
+	strcpy(out, "Tasklist not available on POSIX");
+	return CSP_ERR_NONE;
+
+}
+
+int csp_sys_tasklist_size(void) {
+
+	return 100;
+
+}
+
+uint32_t csp_sys_memfree(void) {
+
+	uint32_t total = 0;
+	struct sysinfo info;
+	sysinfo(&info);
+	total = info.freeram * info.mem_unit;
+	return total;
+
+}
+
+// helper for doing log and mapping result to CSP_ERR
+static int csp_sys_log_and_return(const char * function, int res) {
+
+	if (res != 0) {
+		csp_log_warn("%s: failed to execute, returned error: %d, errno: %d", function, res, errno);
+		return CSP_ERR_INVAL; // no real suitable error code
+	}
+	csp_log_info("%s: executed", function);
+	return CSP_ERR_NONE;
+
+}
+
+int csp_sys_reboot_using_system(void) {
+
+	return csp_sys_log_and_return(__FUNCTION__, system("reboot"));
+
+}
+
+int csp_sys_reboot_using_reboot(void) {
+
+	sync(); // Sync filesystem
+	return csp_sys_log_and_return(__FUNCTION__, reboot(LINUX_REBOOT_CMD_RESTART));
+
+}
+
+int csp_sys_shutdown_using_system(void) {
+
+	return csp_sys_log_and_return(__FUNCTION__, system("halt"));
+
+}
+
+int csp_sys_shutdown_using_reboot(void) {
+
+	sync(); // Sync filesystem
+	return csp_sys_log_and_return(__FUNCTION__, reboot(LINUX_REBOOT_CMD_HALT));
+
+}
+
+void csp_sys_set_color(csp_color_t color) {
+
+	unsigned int color_code, modifier_code;
+	switch (color & COLOR_MASK_COLOR) {
+		case COLOR_BLACK:
+			color_code = 30; break;
+		case COLOR_RED:
+			color_code = 31; break;
+		case COLOR_GREEN:
+			color_code = 32; break;
+		case COLOR_YELLOW:
+			color_code = 33; break;
+		case COLOR_BLUE:
+			color_code = 34; break;
+		case COLOR_MAGENTA:
+			color_code = 35; break;
+		case COLOR_CYAN:
+			color_code = 36; break;
+		case COLOR_WHITE:
+			color_code = 37; break;
+		case COLOR_RESET:
+		default:
+			color_code = 0; break;
+	}
+
+	switch (color & COLOR_MASK_MODIFIER) {
+		case COLOR_BOLD:
+			modifier_code = 1; break;
+		case COLOR_UNDERLINE:
+			modifier_code = 2; break;
+		case COLOR_BLINK:
+			modifier_code = 3; break;
+		case COLOR_HIDE:
+			modifier_code = 4; break;
+		case COLOR_NORMAL:
+		default:
+			modifier_code = 0; break;
+	}
+
+	printf("\033[%u;%um", modifier_code, color_code);
+}

+ 72 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_thread.c

@@ -0,0 +1,72 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_thread.h>
+
+#include <limits.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+
+int csp_thread_create(csp_thread_func_t routine, const char * const thread_name, unsigned int stack_size, void * parameters, unsigned int priority, csp_thread_handle_t * return_handle) {
+
+	pthread_attr_t attributes;
+	if (pthread_attr_init(&attributes) != 0) {
+		return CSP_ERR_NOMEM;
+	}
+	// if stack size is 0, use default stack size
+	if (stack_size) {
+		unsigned int min_stack_size = PTHREAD_STACK_MIN;// use at least one memory
+		while (min_stack_size < stack_size) { // must reach at least the provided size
+			min_stack_size += PTHREAD_STACK_MIN;// keep memory page boundary (some systems may fail otherwise))
+		}
+		pthread_attr_setstacksize(&attributes, min_stack_size);
+	}
+	pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);// no need to join with thread to free its resources
+
+	pthread_t handle;
+	int return_code = pthread_create(&handle, &attributes, routine, parameters);
+	pthread_attr_destroy(&attributes);
+
+	if (return_code != 0) {
+		return CSP_ERR_NOMEM;
+	}
+	if (return_handle) {
+		*return_handle = handle;
+	}
+
+	return CSP_ERR_NONE;
+}
+
+void csp_thread_exit(void) {
+
+	pthread_exit(CSP_TASK_RETURN);
+}
+
+void csp_sleep_ms(unsigned int time_ms) {
+
+	struct timespec req, rem;
+	req.tv_sec = (time_ms / 1000U);
+	req.tv_nsec = ((time_ms % 1000U) * 1000000U);
+
+	while ((nanosleep(&req, &rem) < 0) && (errno == EINTR)) {
+		req = rem;
+	}
+}

+ 57 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/csp_time.c

@@ -0,0 +1,57 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <csp/arch/csp_time.h>
+
+#include <time.h>
+#include <sys/time.h>
+#include <limits.h>
+
+uint32_t csp_get_ms(void) {
+
+	struct timespec ts;
+	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+		return (uint32_t)((ts.tv_sec*1000) + (ts.tv_nsec/1000000));
+	}
+	return 0;
+
+}
+
+uint32_t csp_get_ms_isr(void) {
+
+	return csp_get_ms();
+
+}
+
+uint32_t csp_get_s(void) {
+
+	struct timespec ts;
+	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+		return (uint32_t)ts.tv_sec;
+	}
+	return 0;
+
+}
+
+uint32_t csp_get_s_isr(void) {
+
+	return csp_get_s();
+
+}

+ 239 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/posix/pthread_queue.c

@@ -0,0 +1,239 @@
+/*
+Cubesat Space Protocol - A small network-layer protocol designed for Cubesats
+Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com)
+Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) 
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Inspired by c-pthread-queue by Matthew Dickinson
+http://code.google.com/p/c-pthread-queue/
+*/
+
+#include <csp/arch/posix/pthread_queue.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <csp/arch/csp_malloc.h>
+
+static inline int get_deadline(struct timespec *ts, uint32_t timeout_ms)
+{
+	int ret = clock_gettime(CLOCK_MONOTONIC, ts);
+
+	if (ret < 0) {
+		return ret;
+	}
+
+	uint32_t sec = timeout_ms / 1000;
+	uint32_t nsec = (timeout_ms - 1000 * sec) * 1000000;
+
+	ts->tv_sec += sec;
+
+	if (ts->tv_nsec + nsec >= 1000000000) {
+		ts->tv_sec++;
+	}
+
+	ts->tv_nsec = (ts->tv_nsec + nsec) % 1000000000;
+
+	return ret;
+}
+
+static inline int init_cond_clock_monotonic(pthread_cond_t * cond)
+{
+
+	int ret;
+	pthread_condattr_t attr;
+
+	pthread_condattr_init(&attr);
+	ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+
+	if (ret == 0) {
+		ret = pthread_cond_init(cond, &attr);
+	}
+
+	pthread_condattr_destroy(&attr);
+	return ret;
+
+}
+
+pthread_queue_t * pthread_queue_create(int length, size_t item_size) {
+	
+	pthread_queue_t * q = csp_malloc(sizeof(pthread_queue_t));
+	
+	if (q != NULL) {
+		q->buffer = csp_malloc(length*item_size);
+		if (q->buffer != NULL) {
+			q->size = length;
+			q->item_size = item_size;
+			q->items = 0;
+			q->in = 0;
+			q->out = 0;
+			if (pthread_mutex_init(&(q->mutex), NULL) || init_cond_clock_monotonic(&(q->cond_full)) || init_cond_clock_monotonic(&(q->cond_empty))) {
+				csp_free(q->buffer);
+				csp_free(q);
+				q = NULL;
+			}
+		} else {
+			csp_free(q);
+			q = NULL;
+		}
+	}
+
+	return q;
+	
+}
+
+void pthread_queue_delete(pthread_queue_t * q) {
+
+	if (q == NULL)
+		return;
+
+	csp_free(q->buffer);
+	csp_free(q);
+
+	return;
+
+}
+	
+
+static inline int wait_slot_available(pthread_queue_t * queue, struct timespec *ts) {
+
+	int ret;
+
+	while (queue->items == queue->size) {
+
+		if (ts != NULL) {
+			ret = pthread_cond_timedwait(&(queue->cond_full), &(queue->mutex), ts);
+		} else {
+			ret = pthread_cond_wait(&(queue->cond_full), &(queue->mutex));
+		}
+
+		if (ret != 0 && errno != EINTR) {
+			return PTHREAD_QUEUE_FULL; //Timeout
+		}
+	}
+
+	return PTHREAD_QUEUE_OK;
+
+}
+
+int pthread_queue_enqueue(pthread_queue_t * queue, const void * value, uint32_t timeout) {
+
+	int ret;
+	struct timespec ts;
+	struct timespec *pts = NULL;
+
+	/* Calculate timeout */
+	if (timeout != CSP_MAX_TIMEOUT) {
+		if (get_deadline(&ts, timeout) != 0) {
+			return PTHREAD_QUEUE_ERROR;
+		}
+		pts = &ts;
+	} else {
+		pts = NULL;
+	}
+
+	/* Get queue lock */
+	pthread_mutex_lock(&(queue->mutex));
+
+	ret = wait_slot_available(queue, pts);
+	if (ret == PTHREAD_QUEUE_OK) {
+		/* Copy object from input buffer */
+		memcpy(queue->buffer+(queue->in * queue->item_size), value, queue->item_size);
+		queue->items++;
+		queue->in = (queue->in + 1) % queue->size;
+	}
+
+	pthread_mutex_unlock(&(queue->mutex));
+
+	if (ret == PTHREAD_QUEUE_OK) {
+		/* Nofify blocked threads */
+		pthread_cond_broadcast(&(queue->cond_empty));
+	}
+
+	return ret;
+
+}
+
+static inline int wait_item_available(pthread_queue_t * queue, struct timespec *ts) {
+
+	int ret;
+
+	while (queue->items == 0) {
+
+		if (ts != NULL) {
+			ret = pthread_cond_timedwait(&(queue->cond_empty), &(queue->mutex), ts);
+		} else {
+			ret = pthread_cond_wait(&(queue->cond_empty), &(queue->mutex));
+		}
+
+		if (ret != 0 && errno != EINTR) {
+			return PTHREAD_QUEUE_EMPTY; //Timeout
+		}
+	}
+
+	return PTHREAD_QUEUE_OK;
+
+}
+
+int pthread_queue_dequeue(pthread_queue_t * queue, void * buf, uint32_t timeout) {
+
+	int ret;
+	struct timespec ts;
+	struct timespec *pts;
+
+	/* Calculate timeout */
+	if (timeout != CSP_MAX_TIMEOUT) {
+		if (get_deadline(&ts, timeout) != 0) {
+			return PTHREAD_QUEUE_ERROR;
+		}
+		pts = &ts;
+	} else {
+		pts = NULL;
+	}
+
+	/* Get queue lock */
+	pthread_mutex_lock(&(queue->mutex));
+
+	ret = wait_item_available(queue, pts);
+	if (ret == PTHREAD_QUEUE_OK) {
+		/* Coby object to output buffer */
+		memcpy(buf, queue->buffer+(queue->out * queue->item_size), queue->item_size);
+		queue->items--;
+		queue->out = (queue->out + 1) % queue->size;
+	}
+
+	pthread_mutex_unlock(&(queue->mutex));
+
+	if (ret == PTHREAD_QUEUE_OK) {
+		/* Nofify blocked threads */
+		pthread_cond_broadcast(&(queue->cond_full));
+	}
+
+	return ret;
+
+}
+
+int pthread_queue_items(pthread_queue_t * queue) {
+
+	pthread_mutex_lock(&(queue->mutex));
+	int items = queue->items;
+	pthread_mutex_unlock(&(queue->mutex));
+	
+	return items;
+	
+}

+ 18 - 0
tc_tm_gen2_board_bringup_sw/gs_ps_simu/lib/csp/src/arch/windows/README

@@ -0,0 +1,18 @@
+This directory contains files specific to the windows port of libcsp.
+
+To compile and create a static library, execute:
+
+  python waf configure --with-os=windows build
+
+from the root of this project. Note python must be in PATH.
+
+The build requirements are:
+    * Windows Vista SP1
+    * A recent version of MinGW _or_ MinGW-w64
+    * Windows API headers
+    * cPython 2.5 or newer
+
+What provides the Windows API headers depends on the development environment:
+Using MinGW: Headers provided by w32api package. windows_glue.h header is needed because these headers do not declare condition variables.
+Using MinGW-w64: Headers should be available in the default configuration. You may have to compile the distribution from source. windows_glue.h should not be needed.
+

Some files were not shown because too many files changed in this diff