summaryrefslogtreecommitdiff
path: root/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest
diff options
context:
space:
mode:
Diffstat (limited to 'fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest')
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/arr_desc/arr_desc.h220
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest.h17
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_cycle.h65
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_define.h37
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_fw.h253
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group.h66
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_call.h126
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_define.h87
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_pf.h85
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_systick.h93
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test.h100
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_call.h121
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_define.h133
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_ret.h17
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_util.h27
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/opt_arg.h15
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/pp_narg.h25
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/splice.h8
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/util/util.h52
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_cycle.c9
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_dump_str_segments.c36
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_fw.c9
-rw-r--r--fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_trigger_action.c37
23 files changed, 1638 insertions, 0 deletions
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/arr_desc/arr_desc.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/arr_desc/arr_desc.h
new file mode 100644
index 0000000..effab26
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/arr_desc/arr_desc.h
@@ -0,0 +1,220 @@
+#ifndef _ARR_DESC_H_
+#define _ARR_DESC_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <string.h> /* memset() */
+#include "../util/util.h" /* CONCAT() */
+
+/*--------------------------------------------------------------------------------*/
+/* Type Definitions */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Array-descriptor struct.
+ */
+typedef struct ARR_DESC_struct
+{
+ void * data_ptr; /* Pointer to the array contents. */
+ int32_t element_count; /* Number of current elements. */
+ int32_t element_size; /* Size of current elements in bytes. */
+ int32_t underlying_size; /* Size of underlying array in bytes. */
+} ARR_DESC_t;
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Prefix of the array variable's name when creating an array and an array
+ * descriptor at the same time.
+ */
+#define ARR_DESC_ARR_PREFIX ARR_DESC_ARR_
+
+/**
+ * Evaluate to the array variable's name when creating an array and an array
+ * descriptor at the same time.
+ */
+#define ARR_DESC_ARR_NAME(name) \
+ CONCAT(ARR_DESC_ARR_PREFIX, name)
+
+/**
+ * Define an #ARR_DESC_t by itself.
+ *
+ * @note The user must supply an array to store the data used by the
+ * #ARR_DESC_t.
+ */
+#define ARR_DESC_INTERNAL_DEFINE(name, data_ptr, \
+ element_count, element_size) \
+ ARR_DESC_t name = { \
+ data_ptr, \
+ element_count, \
+ element_size, \
+ element_count * element_size \
+ } \
+
+/**
+ * Define both an array and an #ARR_DESC_t that describes it.
+ *
+ * @note Use the #CURLY() macro for the content field; it provides the curly
+ * braces necessary for an array initialization.
+ */
+#define ARR_DESC_DEFINE(type, name, element_count, content) \
+ type ARR_DESC_ARR_NAME(name)[element_count] = content; \
+ ARR_DESC_INTERNAL_DEFINE(name, \
+ &ARR_DESC_ARR_NAME(name), \
+ element_count, \
+ sizeof(type)) /* Note the lacking semicolon */
+
+/**
+ * Create a #ARR_DESC_t which refers to a subset of the data in another.
+ *
+ * The new #ARR_DESC_t shares the same underlying array as the aliased
+ * #ARR_DESC_t, but only describes a subset of the originals values.
+ */
+#define ARR_DESC_DEFINE_SUBSET(name, original, element_cnt) \
+ ARR_DESC_INTERNAL_DEFINE(name, \
+ &ARR_DESC_ARR_NAME(original), \
+ element_cnt, \
+ sizeof(ARR_DESC_ARR_NAME(original)[0]) \
+ ) /* Note the lacking semicolon */
+
+/**
+ * Creat an #ARR_DESC_t which points to the data in an existing array.
+ *
+ * @param start_idx Offset in array_ptr of first element.
+ * @param element_cnt Number of elements to include in the #ARR_DESC_t.
+ *
+ * @example
+ *
+ * float my_floats[4] = {0.0f, 1.0f, 2.0f, 3.0f};
+ *
+ * ARR_DESC_DEFINE_USING_ARR(my_arr_desc, my_floats, 1, 3);
+ *
+ * printf("Element 0: %f\n", ARR_DESC_ELT(float, 0, &my_arr_desc));
+ * printf("Element 1: %f\n", ARR_DESC_ELT(float, 1, &my_arr_desc));
+ *
+ * Outputs:
+ *
+ * Element 0: 1.000000
+ * Element 1: 2.000000
+ *
+ * @warning There are no checks in place to catch invalid start indices; This
+ * is left to the user.
+ */
+#define ARR_DESC_DEFINE_USING_ARR(type, name, array_ptr, start_idx, element_cnt) \
+ ARR_DESC_INTERNAL_DEFINE( \
+ name, \
+ (type *) (array_ptr + start_idx), \
+ element_cnt, \
+ sizeof(type) \
+ ) /* Note the lacking semicolon*/
+
+/**
+ * Declare an #ARR_DESC_t object.
+ */
+#define ARR_DESC_DECLARE(name) \
+ extern ARR_DESC_t name /* Note the lacking semicolon */
+
+/**
+ * Evaluate to the number of bytes stored in the #ARR_DESC_t.
+ */
+#define ARR_DESC_BYTES(arr_desc_ptr) \
+ ((arr_desc_ptr)->element_count * (arr_desc_ptr)->element_size)
+
+/**
+ * Set the contents of #ARR_DESC_t to value.
+ */
+#define ARR_DESC_MEMSET(arr_desc_ptr, value, bytes) \
+ do \
+ { \
+ memset((arr_desc_ptr)->data_ptr, \
+ value, \
+ BOUND(0, \
+ (arr_desc_ptr)->underlying_size, \
+ bytes) \
+ ); \
+ } while (0)
+
+/**
+ * Perform a memcpy of 'bytes' bytes from the source #ARR_DESC_t to the
+ * destination #ARR_DESC_t.
+ */
+#define ARR_DESC_MEMCPY(arr_desc_dest_ptr, arr_desc_src_ptr, bytes) \
+ do \
+ { \
+ memcpy((arr_desc_dest_ptr)->data_ptr, \
+ (arr_desc_src_ptr)->data_ptr, \
+ BOUND(0, \
+ (arr_desc_dest_ptr)->underlying_size, \
+ bytes)); \
+ } while (0)
+
+/**
+ * Evaluate to true if the source #ARR_DESC_t contents will fit into the
+ * destination #ARR_DESC_t and false otherwise.
+ */
+#define ARR_DESC_COPYABLE(arr_desc_dest_ptr, arr_desc_src_ptr) \
+ (ARR_DESC_BYTES(arr_desc_src_ptr) <= \
+ (arr_desc_dest_ptr)->underlying_size)
+
+/**
+ * Copy all the data from the source #ARR_DESC_t to the destination
+ * #ARR_DESC_t.
+ *
+ * @note If the destination #ARR_DESC_t is too small to fit the source data the
+ * copy is aborted and nothing happens.
+ */
+#define ARR_DESC_COPY(arr_desc_dest_ptr, arr_desc_src_ptr) \
+ do \
+ { \
+ if (ARR_DESC_COPYABLE(arr_desc_dest_ptr, \
+ arr_desc_src_ptr)) \
+ { \
+ ARR_DESC_MEMCPY(arr_desc_dest_ptr, \
+ arr_desc_src_ptr, \
+ ARR_DESC_BYTES(arr_desc_src_ptr)); \
+ /* Update the properties*/ \
+ (arr_desc_dest_ptr)->element_count = \
+ (arr_desc_src_ptr)->element_count; \
+ (arr_desc_dest_ptr)->element_size = \
+ (arr_desc_src_ptr)->element_size; \
+ } \
+ } while (0)
+
+/**
+ * Compare the data in two #ARR_DESC_t structs for the specified number of
+ * bytes.
+ */
+#define ARR_DESC_MEMCMP(arr_desc_ptr_a, arr_desc_ptr_b, bytes) \
+ memcmp((arr_desc_ptr_a)->data_ptr, \
+ (arr_desc_ptr_b)->data_ptr, \
+ bytes) /* Note the lacking semicolon */ \
+
+/**
+ * Zero out the contents of the #ARR_DESC_t.
+ */
+#define ARR_DESC_ZERO(arr_desc_ptr) \
+ ARR_DESC_MEMSET(arr_desc_ptr, \
+ 0, \
+ (arr_desc_ptr)->underlying_size)
+
+/**
+ * Evaluate to the data address in #ARR_DESC_t at offset.
+ */
+#define ARR_DESC_DATA_ADDR(type, arr_desc_ptr, offset) \
+ ((void*)(((type *) \
+ ((arr_desc_ptr)->data_ptr)) \
+ + offset))
+
+/**
+ * Evaluate to the element in #ARR_DESC_t with type at idx.
+ */
+#define ARR_DESC_ELT(type, idx, arr_desc_ptr) \
+ (*((type *) ARR_DESC_DATA_ADDR(type, \
+ arr_desc_ptr, \
+ idx)))
+
+#endif /* _ARR_DESC_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest.h
new file mode 100644
index 0000000..9d0af06
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest.h
@@ -0,0 +1,17 @@
+#ifndef _JTEST_H_
+#define _JTEST_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "jtest_fw.h"
+#include "jtest_test.h"
+#include "jtest_test_define.h"
+#include "jtest_test_call.h"
+#include "jtest_group.h"
+#include "jtest_group_define.h"
+#include "jtest_group_call.h"
+#include "jtest_cycle.h"
+
+#endif /* _JTEST_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_cycle.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_cycle.h
new file mode 100644
index 0000000..1934af8
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_cycle.h
@@ -0,0 +1,65 @@
+#ifndef _JTEST_CYCLE_H_
+#define _JTEST_CYCLE_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "jtest_fw.h" /* JTEST_DUMP_STRF() */
+#include "jtest_systick.h"
+#include "jtest_util.h" /* STR() */
+
+/*--------------------------------------------------------------------------------*/
+/* Declare Module Variables */
+/*--------------------------------------------------------------------------------*/
+extern const char * JTEST_CYCLE_STRF;
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Wrap the function call, fn_call, to count execution cycles and display the
+ * results.
+ */
+/* skipp function name + param
+#define JTEST_COUNT_CYCLES(fn_call) \
+ do \
+ { \
+ uint32_t __jtest_cycle_end_count; \
+ \
+ JTEST_SYSTICK_RESET(SysTick); \
+ JTEST_SYSTICK_START(SysTick); \
+ \
+ fn_call; \
+ \
+ __jtest_cycle_end_count = \
+ JTEST_SYSTICK_VALUE(SysTick); \
+ \
+ JTEST_SYSTICK_RESET(SysTick); \
+ JTEST_DUMP_STRF(JTEST_CYCLE_STRF, \
+ STR(fn_call), \
+ (JTEST_SYSTICK_INITIAL_VALUE - \
+ __jtest_cycle_end_count)); \
+ } while (0)
+*/
+#define JTEST_COUNT_CYCLES(fn_call) \
+ do \
+ { \
+ uint32_t __jtest_cycle_end_count; \
+ \
+ JTEST_SYSTICK_RESET(SysTick); \
+ JTEST_SYSTICK_START(SysTick); \
+ \
+ fn_call; \
+ \
+ __jtest_cycle_end_count = \
+ JTEST_SYSTICK_VALUE(SysTick); \
+ \
+ JTEST_SYSTICK_RESET(SysTick); \
+ JTEST_DUMP_STRF(JTEST_CYCLE_STRF, \
+ (JTEST_SYSTICK_INITIAL_VALUE - \
+ __jtest_cycle_end_count)); \
+ } while (0)
+
+#endif /* _JTEST_CYCLE_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_define.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_define.h
new file mode 100644
index 0000000..cbec329
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_define.h
@@ -0,0 +1,37 @@
+#ifndef _JTEST_DEFINE_H_
+#define _JTEST_DEFINE_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Makes a symbol for use as a struct name. Names made this way have two parts;
+ * the first parts is a prefix common to all structs of that class. The second
+ * is a specifier which differs for each instance of that struct type.
+ */
+#define JTEST_STRUCT_NAME(prefix, specifier) \
+ CONCAT(prefix, specifier)
+
+/**
+ * Define a struct with type with a name generated by #JTEST_STRUCT_NAME().
+ */
+#define JTEST_DEFINE_STRUCT(type, struct_name) \
+ type struct_name
+
+/**
+ * Declare a struct with type with a name generated by #JTEST_STRUCT_NAME().
+ */
+#define JTEST_DECLARE_STRUCT(struct_definition) \
+ extern struct_definition
+
+/**
+ * Define and initialize a struct (created with JTEST_DEFINE_STRUCT()) and
+ * initialize it with init_values.
+ */
+#define JTEST_INIT_STRUCT(struct_definition, init_values) \
+ struct_definition = { \
+ init_values \
+ }
+
+#endif /* _JTEST_DEFINE_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_fw.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_fw.h
new file mode 100644
index 0000000..13b015d
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_fw.h
@@ -0,0 +1,253 @@
+#ifndef _JTEST_FW_H_
+#define _JTEST_FW_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include <stdint.h> /* int32_t */
+#include <string.h> /* strcpy() */
+#include <stdio.h> /* sprintf() */
+#include "jtest_pf.h" /* Extend JTEST_FW_t with Pass/Fail data */
+#include "jtest_group.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Type Definitions */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * A struct used to interface with the Keil Debugger.
+ */
+typedef struct JTEST_FW_struct
+{
+ /* Action Triggers: The Keil debugger monitors these values for changes. In
+ * response to a change, the debugger executes code on the host. */
+ volatile int32_t test_start;
+ volatile int32_t test_end;
+ volatile int32_t group_start;
+ volatile int32_t group_end;
+ volatile int32_t dump_str;
+ volatile int32_t dump_data;
+ volatile int32_t exit_fw;
+
+ JTEST_GROUP_t * current_group_ptr;
+
+ /* Buffers: The C-code cannot send strings and data directly to the
+ * debugging framework. Instead, the debugger can be told to read 128 byte
+ * (by default) chunks of memory. Data received in this manner requires
+ * post-processing to be legible.*/
+ char * str_buffer;
+ char * data_buffer;
+
+ /* Pass/Fail Data */
+ JTEST_PF_MEMBERS;
+
+} JTEST_FW_t;
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Default name for the JTEST_FW struct.
+ *
+ * Define your own if you want the variable containing the #JTEST_FW_t to have
+ * a different name.
+ */
+#ifndef JTEST_FW
+#define JTEST_FW JTEST_FW
+#endif
+
+/**
+ * Default name for the JTEST_FW_STR_BUFFER.
+ *
+ * Define your own if you want the variable containing the char buffer to have
+ * a different name.
+ */
+#ifndef JTEST_FW_STR_BUFFER
+#define JTEST_FW_STR_BUFFER JTEST_FW_STR_BUFFER
+#endif
+
+/**
+ * Size of the #JTEST_FW_t, output string-buffer.
+ *
+ * If you change this value, make sure the "dump_str_fn" and "dump_data_fn"
+ * functions in jtest_fns.ini uses the same size. If you aren't sure, read the
+ * documentation Keil Debugger Command 'DISPLAY'.
+ */
+#define JTEST_BUF_SIZE 256
+
+
+/**
+ * The maximum number of bytes output at once using #JTEST_DUMP_STRF().
+ */
+#define JTEST_STR_MAX_OUTPUT_SIZE 128
+
+/**
+ * The maximum number of block transimissions needed to send a string from a
+ * buffer with JTEST_BUF_SIZE.
+ */
+#define JTEST_STR_MAX_OUTPUT_SEGMENTS \
+ (JTEST_BUF_SIZE / JTEST_STR_MAX_OUTPUT_SIZE)
+
+/**
+ * Initialize the JTEST framework.
+ */
+#define JTEST_INIT() \
+ do \
+ { \
+ JTEST_FW.str_buffer = JTEST_FW_STR_BUFFER; \
+ } while (0)
+
+/* Debugger Action-triggering Macros */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Dispatch macro to trigger various actions in the Keil Debugger.
+ */
+#define JTEST_TRIGGER_ACTION(action_name) \
+ do \
+ { \
+ action_name(); \
+ } while (0)
+
+/**
+ * Trigger the "Test Start" action in the Keil Debugger.
+ */
+#define JTEST_ACT_TEST_START() \
+ JTEST_TRIGGER_ACTION(test_start)
+
+/**
+ * Trigger the "Test End" action in the Keil Debugger.
+ */
+#define JTEST_ACT_TEST_END() \
+ JTEST_TRIGGER_ACTION(test_end)
+
+
+/**
+ * Trigger the "Group Start" action in the Keil Debugger.
+ */
+#define JTEST_ACT_GROUP_START() \
+ JTEST_TRIGGER_ACTION(group_start)
+
+/**
+ * Trigger the "Group End" action in the Keil Debugger.
+ */
+#define JTEST_ACT_GROUP_END() \
+ JTEST_TRIGGER_ACTION(group_end)
+
+
+/**
+ * Fill the buffer named buf_name with value and dump it to the Keil debugger
+ * using action.
+ */
+#define JTEST_ACT_DUMP(action, buf_name, value) \
+ do \
+ { \
+ JTEST_CLEAR_BUFFER(buf_name); \
+ strcpy(JTEST_FW.buf_name, (value)); \
+ JTEST_TRIGGER_ACTION(action); \
+ } while (0)
+
+/**
+ * Trigger the "Exit Framework" action in the Keil Debugger.
+ */
+#define JTEST_ACT_EXIT_FW() \
+ do \
+ { \
+ JTEST_TRIGGER_ACTION(exit_fw); \
+ } while (0)
+
+
+/* Buffer Manipulation Macros */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Clear the JTEST_FW buffer with name buf_name.
+ */
+#define JTEST_CLEAR_BUFFER(buf_name) \
+ do \
+ { \
+ memset(JTEST_FW.buf_name, 0, JTEST_BUF_SIZE); \
+ } while (0)
+
+/**
+ * Clear the memory needed for the JTEST_FW's string buffer.
+ */
+#define JTEST_CLEAR_STR_BUFFER() \
+ JTEST_CLEAR_BUFFER(str_buffer)
+
+/**
+ * Clear the memory needed for the JTEST_FW's data buffer.
+ */
+#define JTEST_CLEAR_DATA_BUFFER() \
+ JTEST_CLEAR_BUFFER(data_buffer)
+
+/**
+ * Dump the given string to the Keil Debugger.
+ */
+#define JTEST_DUMP_STR(string) \
+ JTEST_ACT_DUMP(dump_str, str_buffer, string)
+
+/**
+ * Dump a formatted string to the Keil Debugger.
+ */
+#define JTEST_DUMP_STRF(format_str, ... ) \
+ do \
+ { \
+ JTEST_CLEAR_STR_BUFFER(); \
+ sprintf(JTEST_FW.str_buffer,format_str, __VA_ARGS__); \
+ jtest_dump_str_segments(); \
+ } while (0)
+
+/* Pass/Fail Macros */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Increment the number of passed tests in #JTEST_FW.
+ */
+#define JTEST_FW_INC_PASSED(amount) \
+ JTEST_PF_INC_PASSED(&JTEST_FW, amount)
+
+/**
+ * Increment the number of passed tests in #JTEST_FW.
+ */
+#define JTEST_FW_INC_FAILED(amount) \
+ JTEST_PF_INC_FAILED(&JTEST_FW, amount)
+
+/* Manipulating the Current Group */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Evaluate to the current_group_ptr in #JTEST_FW.
+ */
+#define JTEST_CURRENT_GROUP_PTR() \
+ (JTEST_FW.current_group_ptr)
+
+#define JTEST_SET_CURRENT_GROUP(group_ptr) \
+ do \
+ { \
+ JTEST_CURRENT_GROUP_PTR() = group_ptr; \
+ } while (0)
+
+/*--------------------------------------------------------------------------------*/
+/* Declare Global Variables */
+/*--------------------------------------------------------------------------------*/
+extern char JTEST_FW_STR_BUFFER[JTEST_BUF_SIZE];
+extern volatile JTEST_FW_t JTEST_FW;
+
+/*--------------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*--------------------------------------------------------------------------------*/
+void jtest_dump_str_segments(void);
+
+void test_start (void);
+void test_end (void);
+void group_start (void);
+void group_end (void);
+void dump_str (void);
+void dump_data (void);
+void exit_fw (void);
+
+
+#endif /* _JTEST_FW_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group.h
new file mode 100644
index 0000000..3b37ae4
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group.h
@@ -0,0 +1,66 @@
+#ifndef _JTEST_GROUP_H_
+#define _JTEST_GROUP_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "jtest_pf.h"
+#include "jtest_util.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Type Definitions */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * A struct which represents a group of #JTEST_TEST_t structs. This struct is
+ * used to run the group of tests, and report on their outcomes.
+ */
+typedef struct JTEST_GROUP_struct
+{
+ void (* group_fn_ptr) (void); /**< Pointer to the test group */
+ char * name_str; /**< Name of the group */
+
+ /* Extend the #JTEST_GROUP_t with Pass/Fail information.*/
+ JTEST_PF_MEMBERS;
+} JTEST_GROUP_t;
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Set the name of JTEST_GROUP_t.
+ */
+#define JTEST_GROUP_SET_NAME(group_ptr, name) \
+ JTEST_SET_STRUCT_ATTRIBUTE(group_ptr, name_str, name)
+
+#define JTEST_GROUP_SET_FN(group_ptr, fn_ptr) \
+ JTEST_SET_STRUCT_ATTRIBUTE(group_ptr, group_fn_ptr, fn_ptr)
+
+/**
+ * Increment the number of tests passed in the JTEST_GROUP_t pointed to by
+ * group_ptr.
+ */
+#define JTEST_GROUP_INC_PASSED(group_ptr, amount) \
+ JTEST_PF_INC_PASSED(group_ptr, amount)
+
+/**
+ * Increment the number of tests failed in the JTEST_GROUP_t pointed to by
+ * group_ptr.
+ */
+#define JTEST_GROUP_INC_FAILED(group_ptr, amount) \
+ JTEST_PF_INC_FAILED(group_ptr, amount)
+
+/**
+ * Reset the pass/fail information of the #JTEST_GROUP_t pointed to by
+ * group_ptr.
+ */
+#define JTEST_GROUP_RESET_PF(group_ptr) \
+ do \
+ { \
+ JTEST_PF_RESET_PASSED(group_ptr); \
+ JTEST_PF_RESET_FAILED(group_ptr); \
+ } while (0)
+
+#endif /* _JTEST_GROUP_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_call.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_call.h
new file mode 100644
index 0000000..d565a4c
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_call.h
@@ -0,0 +1,126 @@
+#ifndef _JTEST_GROUP_CALL_H_
+#define _JTEST_GROUP_CALL_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "jtest_fw.h"
+#include <inttypes.h>
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Execute the test in the #JTEST_GROUP_t struct associated witht he identifier
+ * group_fn.
+ */
+#define JTEST_GROUP_RUN(group_fn) \
+ do \
+ { \
+ JTEST_DUMP_STR("Group Name:\n"); \
+ JTEST_DUMP_STR(JTEST_GROUP_STRUCT_NAME(group_fn).name_str); \
+ JTEST_GROUP_STRUCT_NAME(group_fn).group_fn_ptr(); \
+ } while (0)
+
+
+/**
+ * Update the enclosing #JTEST_GROUP_t's pass/fail information using the
+ * current #JTEST_GROUP_t's.
+ *
+ * @param group_ptr Pointer to the current #JTEST_GROUP_t.
+ * @param parent_ptr Pointer to the enclosing #JTEST_GROUP_t.
+ *
+ * @warning Only run this if the current #JTEST_GROUP_t is being called within
+ * the context of another #JTEST_GROUP_t.
+ */
+#define JTEST_GROUP_UPDATE_PARENT_GROUP_PF(group_ptr, parent_group_ptr) \
+ do \
+ { \
+ JTEST_GROUP_INC_PASSED(parent_group_ptr, \
+ (group_ptr)->passed); \
+ JTEST_GROUP_INC_FAILED(parent_group_ptr, \
+ (group_ptr)->failed); \
+ } while (0)
+
+/**
+ * Update the #JTEST_FW's pass/fail information using the current
+ * #JTEST_GROUP_t's.
+ */
+#define JTEST_GROUP_UPDATE_FW_PF(group_ptr) \
+ do \
+ { \
+ JTEST_FW_INC_PASSED((group_ptr)->passed); \
+ JTEST_FW_INC_FAILED((group_ptr)->failed); \
+ } while (0)
+
+/**
+ * Update the enclosing context with the current #JTEST_GROUP_t's pass/fail
+ * information. If this group isn't in an enclosing group, it updates the
+ * #JTEST_FW's pass/fail info by default.
+ */
+#define JTEST_GROUP_UPDATE_PARENT_GROUP_OR_FW_PF(group_ptr, \
+ parent_group_ptr) \
+ do \
+ { \
+ /* Update the pass fail counts in the parent group */ \
+ if (parent_group_ptr /* Null implies Top*/) \
+ { \
+ JTEST_GROUP_UPDATE_PARENT_GROUP_PF( \
+ group_ptr, \
+ parent_group_ptr); \
+ } else { \
+ JTEST_GROUP_UPDATE_FW_PF( \
+ group_ptr); \
+ } \
+ } while (0)
+
+/**
+ * Dump the results of running the #JTEST_GROUP_t to the Keil Debugger.
+ */
+#define JTEST_GROUP_DUMP_RESULTS(group_ptr) \
+ do \
+ { \
+ JTEST_DUMP_STRF( \
+ "Tests Run: %" PRIu32 "\n" \
+ "----------\n" \
+ " Passed: %" PRIu32 "\n" \
+ " Failed: %" PRIu32 "\n", \
+ (group_ptr)->passed + (group_ptr)->failed, \
+ (group_ptr)->passed, \
+ (group_ptr)->failed); \
+ } while (0)
+
+/**
+ * Call the #JTEST_GROUP_t associated with the identifier group_fn.
+ */
+#define JTEST_GROUP_CALL(group_fn) \
+ do \
+ { /* Save the current group from JTEST_FW_t before swapping */ \
+ /* it to this group (in order to restore it later )*/ \
+ JTEST_GROUP_t * __jtest_temp_group_ptr = \
+ JTEST_CURRENT_GROUP_PTR(); \
+ JTEST_SET_CURRENT_GROUP(&JTEST_GROUP_STRUCT_NAME(group_fn)); \
+ \
+ /* Reset this group's pass/fail count. Each group */ \
+ /* should only remember counts for its last execution. */ \
+ JTEST_GROUP_RESET_PF(JTEST_CURRENT_GROUP_PTR()); \
+ \
+ /* Run the current group */ \
+ JTEST_ACT_GROUP_START(); \
+ JTEST_GROUP_RUN(group_fn); \
+ JTEST_ACT_GROUP_END(); \
+ \
+ /* Update the pass fail counts in the parent group (or FW) */ \
+ JTEST_GROUP_UPDATE_PARENT_GROUP_OR_FW_PF( \
+ JTEST_CURRENT_GROUP_PTR(), \
+ __jtest_temp_group_ptr); \
+ \
+ JTEST_GROUP_DUMP_RESULTS(JTEST_CURRENT_GROUP_PTR()); \
+ \
+ /* Restore the previously current group */ \
+ JTEST_SET_CURRENT_GROUP(__jtest_temp_group_ptr); \
+ } while (0)
+
+#endif /* _JTEST_GROUP_CALL_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_define.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_define.h
new file mode 100644
index 0000000..b3a86c0
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_group_define.h
@@ -0,0 +1,87 @@
+#ifndef _JTEST_GROUP_DEFINE_H_
+#define _JTEST_GROUP_DEFINE_H_
+
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "jtest_util.h"
+#include "jtest_define.h"
+#include "jtest_group.h"
+
+/* For defining macros with optional arguments */
+#include "opt_arg/opt_arg.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Prefix for all #JTEST_GROUP_t structs.
+ */
+#define JTEST_GROUP_STRUCT_NAME_PREFIX G_JTEST_GROUP_STRUCT_
+
+/**
+ * Define test template used by #JTEST_GROUP_t tests.
+ */
+#define JTEST_GROUP_FN_TEMPLATE(group_fn) \
+ void group_fn(void)
+
+#define JTEST_GROUP_FN_PROTOTYPE JTEST_GROUP_FN_TEMPLATE /**< Alias for
+ #JTEST_GROUP_FN_TEMPLATE. */
+
+/**
+ * Evaluate to the name of the #JTEST_GROUP_t struct associated with group_fn.
+ */
+#define JTEST_GROUP_STRUCT_NAME(group_fn) \
+ JTEST_STRUCT_NAME(JTEST_GROUP_STRUCT_NAME_PREFIX, group_fn)
+
+/**
+ * Define a #JTEST_GROUP_t struct based on the given group_fn.
+ */
+#define JTEST_GROUP_DEFINE_STRUCT(group_fn) \
+ JTEST_DEFINE_STRUCT(JTEST_GROUP_t, \
+ JTEST_GROUP_STRUCT_NAME(group_fn))
+
+/**
+ * Declare a #JTEST_GROUP_t struct based on the given group_fn.
+ */
+#define JTEST_GROUP_DECLARE_STRUCT(group_fn) \
+ JTEST_DECLARE_STRUCT(JTEST_GROUP_DEFINE_STRUCT(group_fn))
+
+/**
+ * Contents needed to initialize a JTEST_GROUP_t struct.
+ */
+#define JTEST_GROUP_STRUCT_INIT(group_fn) \
+ group_fn, \
+ STR_NL(group_fn), \
+ JTEST_PF_MEMBER_INIT
+
+/**
+ * Initialize the contents of a #JTEST_GROUP_t struct.
+ */
+#define JTEST_GROUP_INIT(group_fn) \
+ JTEST_GROUP_DEFINE_STRUCT(group_fn) = { \
+ JTEST_GROUP_STRUCT_INIT(group_fn) \
+ }
+
+/* Test Definition Macro */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Define a #JTEST_GROUP_t object and a test function.
+ */
+#define JTEST_DEFINE_GROUP(group_fn) \
+ JTEST_GROUP_FN_PROTOTYPE(group_fn); \
+ JTEST_GROUP_INIT(group_fn); \
+ JTEST_GROUP_FN_PROTOTYPE(group_fn) /* Notice the lacking semicolon */
+
+/**
+ * Declare a #JTEST_GROUP_t object and a test function prototype.
+ */
+#define JTEST_DECLARE_GROUP(group_fn) \
+ JTEST_GROUP_FN_PROTOTYPE(group_fn); \
+ JTEST_GROUP_DECLARE_STRUCT(group_fn) /* Note the lacking semicolon */
+
+#endif /* _JTEST_GROUP_DEFINE_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_pf.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_pf.h
new file mode 100644
index 0000000..2b005b6
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_pf.h
@@ -0,0 +1,85 @@
+#ifndef _JTEST_PF_H_
+#define _JTEST_PF_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Purpose */
+/*--------------------------------------------------------------------------------*/
+/* jtest_pf.h Contains macros useful for capturing pass/fail data. */
+
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Members that can be added to other structs to extend them pass/fail data and
+ * corresponding functionality.
+ */
+#define JTEST_PF_MEMBERS \
+ uint32_t passed; \
+ uint32_t failed /* Note the lacking semicolon*/ \
+
+/**
+ * Used for initializing JTEST_PF_MEMBERS in a struct declaration.
+ */
+#define JTEST_PF_MEMBER_INIT \
+ 0, \
+ 0
+
+/* Member-Incrementing Macros */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Dispatch macro for incrementing #JTEST_PF_MEMBERS.
+ *
+ * @param xxx Values: 'passed', 'failed'
+ */
+#define JTEST_PF_INC_XXX(xxx, struct_pf_ptr, amount) \
+ do \
+ { \
+ ((struct_pf_ptr)->xxx) += (amount); \
+ } while (0)
+
+/**
+ * Specialization of the #JTEST_PF_INC_XXX macro to increment the passed
+ * member.
+ */
+#define JTEST_PF_INC_PASSED(struct_pf_ptr, amount) \
+ JTEST_PF_INC_XXX(passed, struct_pf_ptr, amount)
+
+
+/**
+ * Specialization of the #JTEST_PF_INC_XXX macro to increment the failed
+ * member.
+ */
+#define JTEST_PF_INC_FAILED(struct_pf_ptr, amount) \
+ JTEST_PF_INC_XXX(failed, struct_pf_ptr, amount)
+
+
+/* Member-Resetting Macros */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Dispatch macro for setting #JTEST_PF_MEMBERS to zero.
+ *
+ * @param xxx Values: 'passed', 'failed'
+ */
+#define JTEST_PF_RESET_XXX(xxx, struct_pf_ptr) \
+ do \
+ { \
+ ((struct_pf_ptr)->xxx) = UINT32_C(0); \
+ } while (0)
+
+/**
+ * Specialization of #JTEST_PF_RESET_XXX for the 'passed' member.
+ */
+#define JTEST_PF_RESET_PASSED(struct_pf_ptr) \
+ JTEST_PF_RESET_XXX(passed, struct_pf_ptr)
+
+/**
+ * Specialization of #JTEST_PF_RESET_XXX for the 'failed' member.
+ */
+#define JTEST_PF_RESET_FAILED(struct_pf_ptr) \
+ JTEST_PF_RESET_XXX(failed, struct_pf_ptr)
+
+#endif /* _JTEST_PF_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_systick.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_systick.h
new file mode 100644
index 0000000..339ecf2
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_systick.h
@@ -0,0 +1,93 @@
+#ifndef _JTEST_SYSTICK_H_
+#define _JTEST_SYSTICK_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+/* Get access to the SysTick structure. */
+#if defined ARMCM0
+ #include "ARMCM0.h"
+#elif defined ARMCM0P
+ #include "ARMCM0plus.h"
+#elif defined ARMCM3
+ #include "ARMCM3.h"
+#elif defined ARMCM4
+ #include "ARMCM4.h"
+#elif defined ARMCM4_FP
+ #include "ARMCM4_FP.h"
+#elif defined ARMCM7
+ #include "ARMCM7.h"
+#elif defined ARMCM7_SP
+ #include "ARMCM7_SP.h"
+#elif defined ARMCM7_DP
+ #include "ARMCM7_DP.h"
+#elif defined ARMSC000
+ #include "ARMSC000.h"
+#elif defined ARMSC300
+ #include "ARMSC300.h"
+#elif defined ARMv8MBL
+ #include "ARMv8MBL.h"
+#elif defined ARMv8MML
+ #include "ARMv8MML.h"
+#elif defined ARMv8MML_DSP
+ #include "ARMv8MML_DSP.h"
+#elif defined ARMv8MML_SP
+ #include "ARMv8MML_SP.h"
+#elif defined ARMv8MML_DSP_SP
+ #include "ARMv8MML_DSP_SP.h"
+#elif defined ARMv8MML_DP
+ #include "ARMv8MML_DP.h"
+#elif defined ARMv8MML_DSP_DP
+ #include "ARMv8MML_DSP_DP.h"
+
+#else
+ #warning "no appropriate header file found!"
+#endif
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Initial value for the SysTick module.
+ *
+ * @note This is also the maximum value, important as SysTick is a decrementing
+ * counter.
+ */
+#define JTEST_SYSTICK_INITIAL_VALUE 0xFFFFFF
+
+/**
+ * Reset the SysTick, decrementing timer to it's maximum value and disable it.
+ *
+ * This macro should leave the SysTick timer in a state that's ready for cycle
+ * counting.
+ */
+#define JTEST_SYSTICK_RESET(systick_ptr) \
+ do \
+ { \
+ (systick_ptr)->LOAD = JTEST_SYSTICK_INITIAL_VALUE; \
+ (systick_ptr)->VAL = 1; \
+ \
+ /* Disable the SysTick module. */ \
+ (systick_ptr)->CTRL = UINT32_C(0x000000); \
+ } while (0)
+
+/**
+ * Start the SysTick timer, sourced by the processor clock.
+ */
+#define JTEST_SYSTICK_START(systick_ptr) \
+ do \
+ { \
+ (systick_ptr)->CTRL = \
+ SysTick_CTRL_ENABLE_Msk | \
+ SysTick_CTRL_CLKSOURCE_Msk; /* Internal clk*/ \
+ } while (0)
+
+/**
+ * Evaluate to the current value of the SysTick timer.
+ */
+#define JTEST_SYSTICK_VALUE(systick_ptr) \
+ ((systick_ptr)->VAL)
+
+#endif /* _JTEST_SYSTICK_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test.h
new file mode 100644
index 0000000..023145f
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test.h
@@ -0,0 +1,100 @@
+#ifndef _JTEST_TEST_H_
+#define _JTEST_TEST_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include <stdint.h>
+#include "jtest_util.h"
+#include "jtest_test_ret.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Type Definitions */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * A struct which represents a Test in the JTEST framework. This struct is
+ * used to enable, run, and describe the test it represents.
+ */
+typedef struct JTEST_TEST_struct
+{
+ JTEST_TEST_RET_t ( * test_fn_ptr)(void); /**< Pointer to the test function. */
+ char * test_fn_str; /**< Name of the test function */
+ char * fut_str; /**< Name of the function under test. */
+
+ /**
+ * Flags that govern how the #JTEST_TEST_t behaves.
+ */
+ union {
+ struct {
+ unsigned enabled : 1;
+ unsigned unused : 7;
+ } bits;
+ uint8_t byte; /* Access all flags at once. */
+ } flags;
+
+} JTEST_TEST_t;
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Assign a test function to the #JTEST_TEST_t struct.
+ */
+#define JTEST_TEST_SET_FN(jtest_test_ptr, fn_ptr) \
+ JTEST_SET_STRUCT_ATTRIBUTE(jtest_test_ptr, test_fn_ptr, fn_ptr)
+
+/**
+ * Specify a function under test (FUT) for the #JTEST_TEST_t struct.
+ */
+#define JTEST_TEST_SET_FUT(jtest_test_ptr, str) \
+ JTEST_SET_STRUCT_ATTRIBUTE(jtest_test_ptr, fut_str, str)
+
+/* Macros concerning JTEST_TEST_t flags */
+/*--------------------------------------------------------------------------------*/
+
+#define JTEST_TEST_FLAG_SET 1 /**< Value of a set #JTEST_TEST_t flag. */
+#define JTEST_TEST_FLAG_CLR 0 /**< Value of a cleared #JTEST_TEST_t flag. */
+
+/**
+ * Evaluate to the flag in #JTEST_TEST_t having flag_name.
+ */
+#define JTEST_TEST_FLAG(jtest_test_ptr, flag_name) \
+ ((jtest_test_ptr)->flags.bits.flag_name)
+
+/**
+ * Dispatch macro for setting and clearing #JTEST_TEST_t flags.
+ *
+ * @param jtest_test_ptr Pointer to a #JTEST_TEST_t struct.
+ * @param flag_name Name of the flag to set in #JTEST_TEST_t.flags.bits
+ * @param xxx Vaid values: "SET" or "CLR"
+ *
+ * @note This function depends on JTEST_TEST_FLAG_SET and JTEST_TEST_FLAG_CLR.
+ */
+#define JTEST_TEST_XXX_FLAG(jtest_test_ptr, flag_name, xxx) \
+ do \
+ { \
+ JTEST_TEST_FLAG(jtest_test_ptr, flag_name) = JTEST_TEST_FLAG_##xxx ; \
+ } while (0)
+
+/**
+ * Specification of #JTEST_TEST_XXX_FLAG to set #JTEST_TEST_t flags.
+ */
+#define JTEST_TEST_SET_FLAG(jtest_test_ptr, flag_name) \
+ JTEST_TEST_XXX_FLAG(jtest_test_ptr, flag_name, SET)
+
+/**
+ * Specification of #JTEST_TEST_XXX_FLAG to clear #JTEST_TEST_t flags.
+ */
+#define JTEST_TEST_CLR_FLAG(jtest_test_ptr, flag_name) \
+ JTEST_TEST_XXX_FLAG(jtest_test_ptr, flag_name, CLR)
+
+/**
+ * Evaluate to true if the #JTEST_TEST_t is enabled.
+ */
+#define JTEST_TEST_IS_ENABLED(jtest_test_ptr) \
+ (JTEST_TEST_FLAG(jtest_test_ptr, enabled) == JTEST_TEST_FLAG_SET)
+
+#endif /* _JTEST_TEST_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_call.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_call.h
new file mode 100644
index 0000000..9325185
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_call.h
@@ -0,0 +1,121 @@
+#ifndef _JTEST_TEST_CALL_H_
+#define _JTEST_TEST_CALL_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+#include "jtest_test.h"
+#include "jtest_test_define.h"
+#include "jtest_fw.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Exectute the test in the #JTEST_TEST_t struct associated with the identifier
+ * test_fn and store the result in retval.
+ */
+#define JTEST_TEST_RUN(retval, test_fn) \
+ do \
+ { \
+ JTEST_DUMP_STR("Test Name:\n"); \
+ JTEST_DUMP_STR(JTEST_TEST_STRUCT_NAME(test_fn).test_fn_str); \
+ JTEST_DUMP_STR("Function Under Test:\n"); \
+ JTEST_DUMP_STR(JTEST_TEST_STRUCT_NAME(test_fn).fut_str); \
+ retval = JTEST_TEST_STRUCT_NAME(test_fn).test_fn_ptr(); \
+ } while (0)
+
+/**
+ * Update the enclosing #JTEST_GROUP_t's pass/fail information based on
+ * test_retval.
+ *
+ * @param test_retval A #JTEST_TEST_RET_enum for the current test.
+ *
+ * @warning Only use if #JTEST_TEST_t is called in the context of a
+ * #JTEST_GROUP_t.
+ */
+#define JTEST_TEST_UPDATE_PARENT_GROUP_PF(test_retval) \
+ do \
+ { \
+ /* Update enclosing JTEST_GROUP_t with pass/fail info */ \
+ if (test_retval == JTEST_TEST_PASSED) \
+ { \
+ JTEST_GROUP_INC_PASSED(JTEST_CURRENT_GROUP_PTR(), 1); \
+ } else { \
+ JTEST_GROUP_INC_FAILED(JTEST_CURRENT_GROUP_PTR(), 1); \
+ } \
+ } while (0)
+
+/**
+ * Update the #JTEST_FW with pass/fail information based on test_retval.
+ *
+ * @param test_retval A #JTEST_TEST_RET_enum for the current test.
+ */
+#define JTEST_TEST_UPDATE_FW_PF(test_retval) \
+ do \
+ { \
+ /* Update the JTEST_FW with pass/fail info */ \
+ if (test_retval == JTEST_TEST_PASSED) \
+ { \
+ JTEST_FW_INC_PASSED( 1); \
+ } else { \
+ JTEST_FW_INC_FAILED(1); \
+ } \
+ } while (0)
+
+/**
+ * Update the enclosing JTEST_GROUP_t's pass/fail information, or the
+ * #JTEST_FW's if this test has no enclosing #JTEST_GROUP_t.
+ *
+ * @param test_retval A #JTEST_TEST_RET_enum for the current test.
+ */
+#define JTEST_TEST_UPDATE_PARENT_GROUP_OR_FW_PF(test_retval) \
+ do \
+ { \
+ /* Update pass-fail information */ \
+ if (JTEST_CURRENT_GROUP_PTR() /* Non-null */) \
+ { \
+ JTEST_TEST_UPDATE_PARENT_GROUP_PF(test_retval); \
+ } else { \
+ JTEST_TEST_UPDATE_FW_PF(test_retval); \
+ } \
+ } while (0)
+
+/**
+ * Dump the results of the test to the Keil Debugger.
+ */
+#define JTEST_TEST_DUMP_RESULTS(test_retval) \
+ do \
+ { \
+ if (test_retval == JTEST_TEST_PASSED) \
+ { \
+ JTEST_DUMP_STR("Test Passed\n"); \
+ } else { \
+ JTEST_DUMP_STR("Test Failed\n"); \
+ } \
+ } while (0)
+
+/**
+ * Call the #JTEST_TEST_t assocaited with the identifier test_fn.
+ */
+#define JTEST_TEST_CALL(test_fn) \
+ do \
+ { \
+ if (JTEST_TEST_IS_ENABLED(&JTEST_TEST_STRUCT_NAME(test_fn))) \
+ { \
+ /* Default to failure */ \
+ JTEST_TEST_RET_t __jtest_test_ret = JTEST_TEST_FAILED; \
+ \
+ JTEST_ACT_TEST_START(); \
+ JTEST_TEST_RUN(__jtest_test_ret, test_fn); \
+ \
+ /* Update pass-fail information */ \
+ JTEST_TEST_UPDATE_PARENT_GROUP_OR_FW_PF(__jtest_test_ret); \
+ \
+ JTEST_TEST_DUMP_RESULTS(__jtest_test_ret); \
+ JTEST_ACT_TEST_END(); \
+ } \
+ } while (0)
+
+#endif /* _JTEST_TEST_CALL_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_define.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_define.h
new file mode 100644
index 0000000..1447dd0
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_define.h
@@ -0,0 +1,133 @@
+#ifndef _JTEST_TEST_DEFINE_H_
+#define _JTEST_TEST_DEFINE_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "jtest_util.h"
+#include "jtest_define.h"
+#include "jtest_test.h"
+
+/* For defining macros with optional arguments */
+#include "opt_arg/opt_arg.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Prefix for all #JTEST_TEST_t structs.
+ */
+#define JTEST_TEST_STRUCT_NAME_PREFIX G_JTEST_TEST_STRUCT_
+
+/**
+ * Define test template used by #JTEST_TEST_t tests.
+ */
+#define JTEST_TEST_FN_TEMPLATE(test_fn) \
+ JTEST_TEST_RET_t test_fn(void)
+
+#define JTEST_TEST_FN_PROTOTYPE JTEST_TEST_FN_TEMPLATE /**< Alias for
+ * #JTEST_TEST_FN_TEMPLATE. */
+
+/**
+ * Evaluate to the name of the #JTEST_TEST_t struct associated with test_fn.
+ */
+#define JTEST_TEST_STRUCT_NAME(test_fn) \
+ JTEST_STRUCT_NAME(JTEST_TEST_STRUCT_NAME_PREFIX, test_fn)
+
+/**
+ * Define a #JTEST_TEST_t struct based on the given test_fn.
+ */
+#define JTEST_TEST_DEFINE_STRUCT(test_fn) \
+ JTEST_DEFINE_STRUCT(JTEST_TEST_t, \
+ JTEST_TEST_STRUCT_NAME(test_fn))
+
+/**
+ * Declare a #JTEST_TEST_t struct based on the given test_fn.
+ */
+#define JTEST_TEST_DECLARE_STRUCT(test_fn) \
+ JTEST_DECLARE_STRUCT(JTEST_TEST_DEFINE_STRUCT(test_fn))
+
+/**
+ * Contents needed to initialize a JTEST_TEST_t struct.
+ */
+#define JTEST_TEST_STRUCT_INIT(test_fn, fut, enable) \
+ test_fn, \
+ STR_NL(test_fn), \
+ STR_NL(fut), \
+ { \
+ { \
+ enable, \
+ 0 \
+ } \
+ } \
+
+
+/**
+ * Initialize the contents of a #JTEST_TEST_t struct.
+ */
+#define JTEST_TEST_INIT(test_fn, fut, enable) \
+ JTEST_TEST_DEFINE_STRUCT(test_fn) = { \
+ JTEST_TEST_STRUCT_INIT(test_fn, fut, enable) \
+ }
+
+/* Test Definition Macro */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Define a #JTEST_TEST_t object and a test function.
+ */
+#define _JTEST_DEFINE_TEST(test_fn, fut, enable) \
+ JTEST_TEST_FN_PROTOTYPE(test_fn); \
+ JTEST_TEST_INIT(test_fn, fut, enable); \
+ JTEST_TEST_FN_PROTOTYPE(test_fn) /* Notice the lacking semicolon */
+
+/**
+ * Declare a #JTEST_TEST_t object and a test function prototype.
+ */
+#define JTEST_DECLARE_TEST(test_fn) \
+ JTEST_TEST_FN_PROTOTYPE(test_fn); \
+ JTEST_TEST_DECLARE_STRUCT(test_fn) /* Note the lacking semicolon */
+
+/*--------------------------------------------------------------------------------*/
+/* Macros with optional arguments */
+/*--------------------------------------------------------------------------------*/
+
+/* Top-level Interface */
+#define JTEST_DEFINE_TEST(...) \
+ JTEST_DEFINE_TEST_(PP_NARG(__VA_ARGS__), ##__VA_ARGS__)
+
+/* Dispatch Macro*/
+#define JTEST_DEFINE_TEST_(N, ...) \
+ SPLICE(JTEST_DEFINE_TEST_, N)(__VA_ARGS__)
+
+/* Default Arguments */
+#define JTEST_DEFINE_TEST_DEFAULT_FUT /* Blank */
+#define JTEST_DEFINE_TEST_DEFAULT_ENABLE \
+ JTEST_TRUE /* Tests enabled by
+ * default. */
+
+/* Dispatch Cases*/
+#define JTEST_DEFINE_TEST_1(_1) \
+ _JTEST_DEFINE_TEST( \
+ _1, \
+ JTEST_DEFINE_TEST_DEFAULT_FUT, \
+ JTEST_DEFINE_TEST_DEFAULT_ENABLE \
+ )
+
+#define JTEST_DEFINE_TEST_2(_1, _2) \
+ _JTEST_DEFINE_TEST( \
+ _1, \
+ _2, \
+ JTEST_DEFINE_TEST_DEFAULT_ENABLE \
+ )
+
+#define JTEST_DEFINE_TEST_3(_1, _2, _3) \
+ _JTEST_DEFINE_TEST( \
+ _1, \
+ _2, \
+ _3 \
+ )
+
+#endif /* _JTEST_TEST_DEFINE_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_ret.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_ret.h
new file mode 100644
index 0000000..c3176e5
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_test_ret.h
@@ -0,0 +1,17 @@
+#ifndef _JTEST_TEST_RET_H_
+#define _JTEST_TEST_RET_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Type Definitions */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Values a #JTEST_TEST_t can return.
+ */
+typedef enum JTEST_TEST_RET_enum
+{
+ JTEST_TEST_PASSED,
+ JTEST_TEST_FAILED
+} JTEST_TEST_RET_t;
+
+#endif /* _JTEST_TEST_RET_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_util.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_util.h
new file mode 100644
index 0000000..3e07d2e
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/jtest_util.h
@@ -0,0 +1,27 @@
+#ifndef _JTEST_UTIL_H_
+#define _JTEST_UTIL_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "util/util.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/* Define boolean values for the framework. */
+#define JTEST_TRUE 1 /**< Value used for TRUE in JTEST. */
+#define JTEST_FALSE 0 /**< Value used for FALSE in JTEST. */
+
+/**
+ * Set the value of the attribute in the struct to by struct_ptr to value.
+ */
+#define JTEST_SET_STRUCT_ATTRIBUTE(struct_ptr, attribute, value) \
+ do \
+ { \
+ (struct_ptr)->attribute = (value); \
+ } while (0)
+
+#endif /* _JTEST_UTIL_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/opt_arg.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/opt_arg.h
new file mode 100644
index 0000000..683be1d
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/opt_arg.h
@@ -0,0 +1,15 @@
+#ifndef _OPT_ARG_H_
+#define _OPT_ARG_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------------*/
+
+#include "pp_narg.h"
+#include "splice.h"
+
+/* If you are Joseph Jaoudi, you have a snippet which expands into an
+ example. If you are not Joseph, but possess his code, study the examples. If
+ you have no examples, turn back contact Joseph. */
+
+#endif /* _OPT_ARG_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/pp_narg.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/pp_narg.h
new file mode 100644
index 0000000..d3248f4
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/pp_narg.h
@@ -0,0 +1,25 @@
+#ifndef _PP_NARG_H_
+#define _PP_NARG_H_
+
+#define PP_NARG(...) \
+ PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
+#define PP_NARG_(...) \
+ PP_ARG_N(__VA_ARGS__)
+#define PP_ARG_N( \
+ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+ _61,_62,_63,N,...) N
+#define PP_RSEQ_N() \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9,8,7,6,5,4,3,2,1,0
+
+#endif /* _PP_NARG_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/splice.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/splice.h
new file mode 100644
index 0000000..ec9142b
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/opt_arg/splice.h
@@ -0,0 +1,8 @@
+#ifndef _SPLICE_H_
+#define _SPLICE_H_
+
+#define SPLICE(a,b) SPLICE_1(a,b)
+#define SPLICE_1(a,b) SPLICE_2(a,b)
+#define SPLICE_2(a,b) a##b
+
+#endif /* _SPLICE_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/util/util.h b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/util/util.h
new file mode 100644
index 0000000..f56e0e6
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/inc/util/util.h
@@ -0,0 +1,52 @@
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+/*--------------------------------------------------------------------------------*/
+/* Macros and Defines */
+/*--------------------------------------------------------------------------------*/
+
+/**
+ * Convert a symbol to a string and add a 'NewLine'.
+ */
+#define STR_NL(x) STR1_NL(x)
+#define STR1_NL(x) (STR2_NL(x)"\n")
+#define STR2_NL(x) #x
+
+/**
+ * Convert a symbol to a string.
+ */
+#define STR(x) STR1(x)
+#define STR1(x) STR2(x)
+#define STR2(x) #x
+
+/**
+ * Concatenate two symbols.
+ */
+#define CONCAT(a, b) CONCAT1(a, b)
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a##b
+
+
+/**
+ * Place curly braces around a varaible number of macro arguments.
+ */
+#define CURLY(...) {__VA_ARGS__}
+
+/**
+ * Place parenthesis around a variable number of macro arguments.
+ */
+#define PAREN(...) (__VA_ARGS__)
+
+/* Standard min/max macros. */
+#define MIN(x,y) (((x) < (y)) ? (x) : (y) )
+#define MAX(x,y) (((x) > (y)) ? (x) : (y) )
+
+/**
+ * Bound value using low and high limits.
+ *
+ * Evaluate to a number in the range, endpoint inclusive.
+ */
+#define BOUND(low, high, value) \
+ MAX(MIN(high, value), low)
+
+#endif /* _UTIL_H_ */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_cycle.c b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_cycle.c
new file mode 100644
index 0000000..24d552d
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_cycle.c
@@ -0,0 +1,9 @@
+#include "../inc/jtest_cycle.h"
+#include <inttypes.h>
+
+/*--------------------------------------------------------------------------------*/
+/* Define Module Variables */
+/*--------------------------------------------------------------------------------*/
+
+/* const char * JTEST_CYCLE_STRF = "Running: %s\nCycles: %" PRIu32 "\n"; */
+const char * JTEST_CYCLE_STRF = "Cycles: %" PRIu32 "\n"; /* function name + parameter string skipped */
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_dump_str_segments.c b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_dump_str_segments.c
new file mode 100644
index 0000000..c3a9bf8
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_dump_str_segments.c
@@ -0,0 +1,36 @@
+#include "jtest_fw.h"
+
+/**
+ * Dump the JTEST_FW.str_buffer the Keil framework in pieces.
+ *
+ * The JTEST_FW.str_buffer contains more characters than the Keil framework can
+ * dump at once. This function dumps them in blocks.
+ */
+void jtest_dump_str_segments(void)
+{
+ uint32_t seg_idx = 0;
+ uint32_t memmove_idx = 0;
+ uint32_t seg_cnt =
+ (strlen(JTEST_FW.str_buffer) / JTEST_STR_MAX_OUTPUT_SIZE) + 1;
+
+ for( seg_idx = 0; seg_idx < seg_cnt; ++seg_idx)
+ {
+ JTEST_TRIGGER_ACTION(dump_str);
+
+ if (seg_idx < JTEST_STR_MAX_OUTPUT_SEGMENTS)
+ {
+ memmove_idx = 0;
+ while (memmove_idx < (seg_cnt - seg_idx -1) )
+ {
+ memmove(
+ JTEST_FW.str_buffer+
+ (memmove_idx* JTEST_STR_MAX_OUTPUT_SIZE),
+ JTEST_FW.str_buffer+
+ ((memmove_idx+1)*JTEST_STR_MAX_OUTPUT_SIZE),
+ JTEST_BUF_SIZE);
+ ++memmove_idx;
+ }
+ }
+ }
+ return;
+}
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_fw.c b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_fw.c
new file mode 100644
index 0000000..69d7a63
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_fw.c
@@ -0,0 +1,9 @@
+#include "../inc/jtest.h"
+
+/*--------------------------------------------------------------------------------*/
+/* Define Global Variables */
+/*--------------------------------------------------------------------------------*/
+
+char JTEST_FW_STR_BUFFER[JTEST_BUF_SIZE] = {0};
+
+volatile JTEST_FW_t JTEST_FW = {0};
diff --git a/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_trigger_action.c b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_trigger_action.c
new file mode 100644
index 0000000..a3901da
--- /dev/null
+++ b/fw/hid-dials/Drivers/CMSIS/DSP/DSP_Lib_TestSuite/Common/JTest/src/jtest_trigger_action.c
@@ -0,0 +1,37 @@
+
+#include "jtest_fw.h"
+
+void test_start (void) {
+// ;
+ JTEST_FW.test_start++;
+}
+
+void test_end (void) {
+// ;
+ JTEST_FW.test_end++;
+}
+
+void group_start (void) {
+// ;
+ JTEST_FW.group_start++;
+}
+
+void group_end (void) {
+// ;
+ JTEST_FW.group_end++;
+}
+
+void dump_str (void) {
+// ;
+ JTEST_FW.dump_str++;
+}
+
+void dump_data (void) {
+// ;
+ JTEST_FW.dump_data++;
+}
+
+void exit_fw (void) {
+// ;
+ JTEST_FW.exit_fw++;
+}