summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--movement/filesystem.c1
-rw-r--r--movement/lib/chirpy_tx/chirpy_tx.c179
-rw-r--r--movement/lib/chirpy_tx/chirpy_tx.h98
-rw-r--r--movement/lib/chirpy_tx/test/test_main.c160
-rw-r--r--movement/lib/chirpy_tx/test/unity.c2466
-rw-r--r--movement/lib/chirpy_tx/test/unity.h687
-rw-r--r--movement/lib/chirpy_tx/test/unity_internals.h1145
-rw-r--r--movement/make/Makefile8
-rw-r--r--movement/movement_faces.h6
-rw-r--r--movement/watch_faces/clock/repetition_minute_face.c231
-rw-r--r--movement/watch_faces/clock/repetition_minute_face.h83
-rw-r--r--movement/watch_faces/complication/activity_face.c725
-rw-r--r--movement/watch_faces/complication/activity_face.h89
-rw-r--r--movement/watch_faces/complication/day_one_face.c2
-rw-r--r--movement/watch_faces/complication/discgolf_face.c326
-rw-r--r--movement/watch_faces/complication/discgolf_face.h95
-rw-r--r--movement/watch_faces/complication/interval_face.c18
-rw-r--r--movement/watch_faces/complication/invaders_face.c434
-rw-r--r--movement/watch_faces/complication/invaders_face.h82
-rw-r--r--movement/watch_faces/complication/timer_face.c366
-rw-r--r--movement/watch_faces/complication/timer_face.h103
-rw-r--r--movement/watch_faces/demo/chirpy_demo_face.c335
-rw-r--r--movement/watch_faces/demo/chirpy_demo_face.h70
23 files changed, 7699 insertions, 10 deletions
diff --git a/movement/filesystem.c b/movement/filesystem.c
index 2b345eda..97e35455 100644
--- a/movement/filesystem.c
+++ b/movement/filesystem.c
@@ -196,6 +196,7 @@ static void filesystem_cat(char *filename) {
if (info.size > 0) {
char *buf = malloc(info.size + 1);
filesystem_read_file(filename, buf, info.size);
+ buf[info.size] = '\0';
printf("%s\n", buf);
free(buf);
} else {
diff --git a/movement/lib/chirpy_tx/chirpy_tx.c b/movement/lib/chirpy_tx/chirpy_tx.c
new file mode 100644
index 00000000..41a42a58
--- /dev/null
+++ b/movement/lib/chirpy_tx/chirpy_tx.c
@@ -0,0 +1,179 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Gabor L Ugray
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include "chirpy_tx.h"
+
+static const uint32_t chirpy_min_freq = 2500;
+static const uint32_t cirpy_freq_step = 250;
+
+// This many bytes are followed by a CRC and block separator
+// It's a multiple of 3 so no bits are wasted (a tone encodes 3 bits)
+// Last block can be shorter
+static const uint8_t chirpy_default_block_size = 15;
+
+// The dedicated control tone. This is the highest tone index.
+static const uint8_t chirpy_control_tone = 8;
+
+// Pre-computed tone periods. This is allocated and populated on-demand.
+static uint32_t *chirpy_tone_periods = NULL;
+
+uint8_t chirpy_crc8(const uint8_t *addr, uint16_t len) {
+ uint8_t crc = 0;
+ for (uint16_t i = 0; i < len; i++)
+ crc = chirpy_update_crc8(addr[i], crc);
+ return crc;
+}
+
+uint8_t chirpy_update_crc8(uint8_t next_byte, uint8_t crc) {
+ for (uint8_t j = 0; j < 8; j++) {
+ uint8_t mix = (crc ^ next_byte) & 0x01;
+ crc >>= 1;
+ if (mix)
+ crc ^= 0x8C;
+ next_byte >>= 1;
+ }
+ return crc;
+}
+
+static void _chirpy_append_tone(chirpy_encoder_state_t *ces, uint8_t tone) {
+ // This is BAD and should never happen. But if it does, we'd rather
+ // create a corrupt transmission than corrupt memory #$^@
+ if (ces->tone_count == CHIRPY_TONE_BUF_SIZE)
+ return;
+ ces->tone_buf[ces->tone_count] = tone;
+ ++ces->tone_count;
+}
+
+void chirpy_init_encoder(chirpy_encoder_state_t *ces, chirpy_get_next_byte_t get_next_byte) {
+ memset(ces, 0, sizeof(chirpy_encoder_state_t));
+ ces->block_size = chirpy_default_block_size;
+ ces->get_next_byte = get_next_byte;
+ _chirpy_append_tone(ces, 8);
+ _chirpy_append_tone(ces, 0);
+ _chirpy_append_tone(ces, 8);
+ _chirpy_append_tone(ces, 0);
+}
+
+static uint8_t _chirpy_retrieve_next_tone(chirpy_encoder_state_t *ces) {
+ if (ces->tone_pos == ces->tone_count)
+ return 255;
+
+ uint8_t res = ces->tone_buf[ces->tone_pos];
+ ++ces->tone_pos;
+ if (ces->tone_pos == ces->tone_count) {
+ // End of buffer: reset buffer
+ ces->tone_pos = 0;
+ ces->tone_count = 0;
+ }
+ return res;
+}
+
+static void _chirpy_encode_bits(chirpy_encoder_state_t *ces, uint8_t force_partial) {
+ while (ces->bit_count > 0) {
+ if (ces->bit_count < 3 && !force_partial) break;
+ uint8_t tone = (uint8_t)(ces->bits >> 13);
+ _chirpy_append_tone(ces, tone);
+ if (ces->bit_count >= 3) {
+ ces->bits <<= 3;
+ ces->bit_count -= 3;
+ } else {
+ ces->bits = 0;
+ ces->bit_count = 0;
+ }
+ }
+}
+
+static void _chirpy_finish_block(chirpy_encoder_state_t *ces) {
+ _chirpy_append_tone(ces, chirpy_control_tone);
+ ces->bits = ces->crc;
+ ces->bits <<= 8;
+ ces->bit_count = 8;
+ _chirpy_encode_bits(ces, 1);
+ ces->bit_count = 0;
+ ces->crc = 0;
+ ces->block_len = 0;
+ _chirpy_append_tone(ces, chirpy_control_tone);
+}
+
+static void _chirpy_finish_transmission(chirpy_encoder_state_t *ces) {
+ _chirpy_append_tone(ces, chirpy_control_tone);
+ _chirpy_append_tone(ces, chirpy_control_tone);
+}
+
+uint8_t chirpy_get_next_tone(chirpy_encoder_state_t *ces) {
+ // If there are tones left in the buffer, keep sending those
+ if (ces->tone_pos < ces->tone_count)
+ return _chirpy_retrieve_next_tone(ces);
+
+ // We know data is over: that means we've wrapped up transmission
+ // Just drain tone buffer, and then keep sendig EOB
+ if (ces->get_next_byte == 0)
+ return _chirpy_retrieve_next_tone(ces);
+
+ // Fetch next byte
+ uint8_t next_byte;
+ uint8_t got_more = ces->get_next_byte(&next_byte);
+
+ // Data over: write CRC if we sent a partial buffer; send end signal
+ if (got_more == 0) {
+ ces->get_next_byte = 0;
+ if (ces->bit_count > 0) _chirpy_encode_bits(ces, 1);
+ if (ces->block_len > 0) _chirpy_finish_block(ces);
+ _chirpy_finish_transmission(ces);
+ return _chirpy_retrieve_next_tone(ces);
+ }
+
+ // Got more data: add to bits; convert
+ uint16_t msk = next_byte;
+ msk <<= (8 - ces->bit_count);
+ ces->bits |= msk;
+ ces->bit_count += 8;
+ _chirpy_encode_bits(ces, 0);
+ ++ces->block_len;
+ ces->crc = chirpy_update_crc8(next_byte, ces->crc);
+ if (ces->block_len == ces->block_size)
+ _chirpy_finish_block(ces);
+
+ return _chirpy_retrieve_next_tone(ces);
+}
+
+uint16_t chirpy_get_tone_period(uint8_t tone) {
+ // Create pre-computed tone periods array on first use
+ if (chirpy_tone_periods == NULL) {
+ chirpy_tone_periods = malloc((chirpy_control_tone + 1) * sizeof(uint32_t));
+ for (uint8_t i = 0; i < chirpy_control_tone + 1; ++i) {
+ uint32_t freq = chirpy_min_freq + i * cirpy_freq_step;
+ uint16_t period = 1000000 / freq;
+ chirpy_tone_periods[i] = period;
+ }
+ }
+ // Return pre-computed value, but be paranoid about indexing into array
+ if (tone > chirpy_control_tone)
+ tone = chirpy_control_tone;
+ return chirpy_tone_periods[tone];
+}
diff --git a/movement/lib/chirpy_tx/chirpy_tx.h b/movement/lib/chirpy_tx/chirpy_tx.h
new file mode 100644
index 00000000..092d05c7
--- /dev/null
+++ b/movement/lib/chirpy_tx/chirpy_tx.h
@@ -0,0 +1,98 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Gabor L Ugray
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIRPY_TX_H
+#define CHIRPY_TX_H
+
+/** @brief Calculates the CRC of a byte sequence.
+ */
+uint8_t chirpy_crc8(const uint8_t *addr, uint16_t len);
+
+/** @brief Updates a CRC value with the next byte of input.
+ */
+uint8_t chirpy_update_crc8(uint8_t next_byte, uint8_t crc);
+
+/** @brief Function to return next byte to be encoded.
+ * @param next_byte Pointer where implementor must write next byte (if available).
+ * @return 1 if there is a next byte, or 0 if no more data to encode.
+ */
+typedef uint8_t (*chirpy_get_next_byte_t)(uint8_t *next_byte);
+
+#define CHIRPY_TONE_BUF_SIZE 16
+
+// Holds state used by the encoder. Do not manipulate directly.
+typedef struct {
+ uint8_t tone_buf[CHIRPY_TONE_BUF_SIZE];
+ uint8_t tone_pos;
+ uint8_t tone_count;
+ uint8_t block_len;
+ uint8_t block_size;
+ uint8_t crc;
+ uint16_t bits;
+ uint8_t bit_count;
+ chirpy_get_next_byte_t get_next_byte;
+} chirpy_encoder_state_t;
+
+/** @brief Iniitializes the encoder state to be used during the transmission.
+ * @param ces Pointer to encoder state object to be initialized.
+ * @param get_next_byte Pointer to function that the encoder will call to fetch data byte by byte.
+ */
+void chirpy_init_encoder(chirpy_encoder_state_t *ces, chirpy_get_next_byte_t get_next_byte);
+
+/** @brief Returns the next tone to be transmitted.
+ * @details This function will call the get_next_byte function stored in the encoder state to
+ * retrieve the next byte to be transmitted as needed. As a single byte is encoded as several tones,
+ * and because the transmission also includes periodic CRC values, not every call to this function
+ * will result in a callback for the next data byte.
+ * @param ced Pointer to the encoder state object.
+ * @return A tone index from 0 to N (where N is the largest tone index), or 255 if the transmission is over.
+ */
+uint8_t chirpy_get_next_tone(chirpy_encoder_state_t *ces);
+
+/** @brief Returns the period value for buzzing out a tone.
+ * @param tone The tone index, 0 thru 8.
+ * @return The period for the tone's frequency, i.e., 1_000_000 / freq.
+ */
+uint16_t chirpy_get_tone_period(uint8_t tone);
+
+/** @brief Typedef for a tick handler function.
+ */
+typedef void (*chirpy_tick_fun_t)(void *context);
+
+/** @brief Creature-comfort struct for use in your chirping code.
+ * @details The idea is to handle a tick that happens 64 times per second at the outermost level.
+ * To get to the desired ~20 tones per second, increment a counter and call the actual
+ * transmission ticker when tick_counter reaches tick_compare, with a compare value of 3.
+ * seq_pos is for use by the transmission function to keep track of where it is in the data.
+ * The current transmission function is stored in tick_fun. You can have multiple phases
+ * by switching to a different function. E.g., intro countdown first, followed by data chirping.
+ */
+typedef struct {
+ uint8_t tick_count;
+ uint8_t tick_compare;
+ uint16_t seq_pos;
+ chirpy_tick_fun_t tick_fun;
+} chirpy_tick_state_t;
+
+#endif
diff --git a/movement/lib/chirpy_tx/test/test_main.c b/movement/lib/chirpy_tx/test/test_main.c
new file mode 100644
index 00000000..c76a3f3c
--- /dev/null
+++ b/movement/lib/chirpy_tx/test/test_main.c
@@ -0,0 +1,160 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Gabor L Ugray
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include "../src/lib/chirpy_tx.h"
+#include "unity.h"
+
+
+void setUp(void) {
+}
+
+void tearDown(void) {
+}
+
+const char *crc_test_str0 = "";
+const char *crc_test_str1 = "h";
+const char *crc_test_str2 = "he";
+const char *crc_test_str3 = "hen";
+const char *crc_test_str4 = "henl";
+const char *crc_test_str5 = "henlO";
+
+#define CRC_VAL_COUNT 5
+const uint8_t crc_vals[] = {167, 118, 95, 92, 127};
+
+void test_crc8() {
+ TEST_ASSERT_EQUAL_UINT8(0, chirpy_crc8((const uint8_t *)crc_test_str0, 0));
+ TEST_ASSERT_EQUAL_UINT8(167, chirpy_crc8((const uint8_t *)crc_test_str1, strlen(crc_test_str1)));
+ TEST_ASSERT_EQUAL_UINT8(118, chirpy_crc8((const uint8_t *)crc_test_str2, strlen(crc_test_str2)));
+ TEST_ASSERT_EQUAL_UINT8(95, chirpy_crc8((const uint8_t *)crc_test_str3, strlen(crc_test_str3)));
+ TEST_ASSERT_EQUAL_UINT8(92, chirpy_crc8((const uint8_t *)crc_test_str4, strlen(crc_test_str4)));
+ TEST_ASSERT_EQUAL_UINT8(127, chirpy_crc8((const uint8_t *)crc_test_str5, strlen(crc_test_str5)));
+
+ uint8_t crc = 0;
+ for (uint16_t i = 0; i < CRC_VAL_COUNT; ++i) {
+ uint8_t next_byte = crc_test_str5[i];
+ crc = chirpy_update_crc8(next_byte, crc);
+ TEST_ASSERT_EQUAL_UINT8(crc_vals[i], crc);
+ }
+
+ crc = chirpy_update_crc8(0, 0);
+ TEST_ASSERT_EQUAL(0, crc);
+
+ crc = chirpy_update_crc8(0x4f, 0);
+ TEST_ASSERT_EQUAL(7, crc);
+}
+
+const uint16_t data_len_01 = 0;
+const uint8_t data_01[] = {};
+const uint16_t tones_len_01 = 6;
+const uint8_t tones_01[] = {8, 0, 8, 0, 8, 8};
+
+const uint16_t data_len_02 = 1;
+const uint8_t data_02[] = {0};
+const uint16_t tones_len_02 = 14;
+const uint8_t tones_02[] = {8, 0, 8, 0, 0, 0, 0, 8, 0, 0, 0, 8, 8, 8};
+
+const uint16_t data_len_03 = 1;
+const uint8_t data_03[] = {0x68};
+const uint16_t tones_len_03 = 14;
+const uint8_t tones_03[] = {8, 0, 8, 0, 3, 2, 0, 8, 5, 1, 6, 8, 8, 8};
+
+const uint16_t data_len_04 = 3;
+const uint8_t data_04[] = {0x68, 0x65, 0x6e};
+const uint16_t tones_len_04 = 19;
+const uint8_t tones_04[] = {8, 0, 8, 0, 3, 2, 0, 6, 2, 5, 5, 6, 8, 2, 7, 6, 8, 8, 8};
+
+const uint16_t data_len_05 = 4;
+const uint8_t data_05[] = {0x68, 0x65, 0x6e, 0x4f};
+const uint16_t tones_len_05 = 27;
+const uint8_t tones_05[] = {
+ 8, 0, 8, 0, 3, 2, 0, 6, 2, 5, 5, 6, 8, 2, 7, 6, 8,
+ 2, 3, 6, 8, 0, 1, 6, 8, 8, 8};
+
+uint8_t curr_data_pos;
+uint8_t curr_data_len;
+const uint8_t *curr_data;
+
+uint8_t get_next_byte(uint8_t *next_byte) {
+ if (curr_data_pos < curr_data_len) {
+ *next_byte = curr_data[curr_data_pos];
+ ++curr_data_pos;
+ return 1;
+ }
+ return 0;
+}
+
+void test_encoder_one(const uint8_t *data, uint16_t data_len, const uint8_t *tones, uint16_t tones_len) {
+ curr_data = data;
+ curr_data_len = data_len;
+ curr_data_pos = 0;
+ chirpy_encoder_state_t ces;
+ chirpy_init_encoder(&ces, get_next_byte);
+ ces.block_size = 3;
+
+ uint8_t got_tones[2048] = {0};
+ uint16_t got_tone_pos = 0;
+ while (got_tone_pos < 2048) {
+ uint8_t tone = chirpy_get_next_tone(&ces);
+ got_tones[got_tone_pos] = tone;
+ if (tone == 255) break;
+ ++got_tone_pos;
+ }
+ char buf1[65536];
+ char bufx[256];
+ memset(buf1, 0, 65536);
+ for (uint16_t i = 0; i < got_tone_pos; ++i) {
+ if (i == 0)
+ sprintf(bufx, "%d", got_tones[i]);
+ else
+ sprintf(bufx, ", %d", got_tones[i]);
+ strcat(buf1, bufx);
+ }
+ TEST_MESSAGE(buf1);
+ TEST_ASSERT_EQUAL(tones_len, got_tone_pos);
+ uint16_t smaller_len = tones_len < got_tone_pos ? tones_len : got_tone_pos;
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(tones, got_tones, smaller_len);
+}
+
+void test_encoder() {
+ TEST_MESSAGE("Testing encoder with dataset 01");
+ test_encoder_one(data_01, data_len_01, tones_01, tones_len_01);
+ TEST_MESSAGE("Testing encoder with dataset 02");
+ test_encoder_one(data_02, data_len_02, tones_02, tones_len_02);
+ TEST_MESSAGE("Testing encoder with dataset 03");
+ test_encoder_one(data_03, data_len_03, tones_03, tones_len_03);
+ TEST_MESSAGE("Testing encoder with dataset 04");
+ test_encoder_one(data_04, data_len_04, tones_04, tones_len_04);
+ TEST_MESSAGE("Testing encoder with dataset 05");
+ test_encoder_one(data_05, data_len_05, tones_05, tones_len_05);
+}
+
+int main(void) {
+ UNITY_BEGIN();
+ RUN_TEST(test_crc8);
+ RUN_TEST(test_encoder);
+ return UNITY_END();
+}
diff --git a/movement/lib/chirpy_tx/test/unity.c b/movement/lib/chirpy_tx/test/unity.c
new file mode 100644
index 00000000..3e4bc04d
--- /dev/null
+++ b/movement/lib/chirpy_tx/test/unity.c
@@ -0,0 +1,2466 @@
+/* =========================================================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+============================================================================ */
+
+#include "unity.h"
+
+#ifndef UNITY_PROGMEM
+#define UNITY_PROGMEM
+#endif
+
+/* If omitted from header, declare overrideable prototypes here so they're ready for use */
+#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
+void UNITY_OUTPUT_CHAR(int);
+#endif
+
+/* Helpful macros for us to use here in Assert functions */
+#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0)
+#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0)
+#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0)
+
+struct UNITY_STORAGE_T Unity;
+
+#ifdef UNITY_OUTPUT_COLOR
+const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m";
+const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m";
+const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m";
+const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m";
+#else
+const char UNITY_PROGMEM UnityStrOk[] = "OK";
+const char UNITY_PROGMEM UnityStrPass[] = "PASS";
+const char UNITY_PROGMEM UnityStrFail[] = "FAIL";
+const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE";
+#endif
+static const char UNITY_PROGMEM UnityStrNull[] = "NULL";
+static const char UNITY_PROGMEM UnityStrSpacer[] = ". ";
+static const char UNITY_PROGMEM UnityStrExpected[] = " Expected ";
+static const char UNITY_PROGMEM UnityStrWas[] = " Was ";
+static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than ";
+static const char UNITY_PROGMEM UnityStrLt[] = " to be less than ";
+static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to ";
+static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to ";
+static const char UNITY_PROGMEM UnityStrElement[] = " Element ";
+static const char UNITY_PROGMEM UnityStrByte[] = " Byte ";
+static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch.";
+static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta ";
+static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless.";
+static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL";
+static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL";
+#ifndef UNITY_EXCLUDE_FLOAT
+static const char UNITY_PROGMEM UnityStrNot[] = "Not ";
+static const char UNITY_PROGMEM UnityStrInf[] = "Infinity";
+static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity";
+static const char UNITY_PROGMEM UnityStrNaN[] = "NaN";
+static const char UNITY_PROGMEM UnityStrDet[] = "Determinate";
+static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait";
+#endif
+const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled";
+const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled";
+const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled";
+const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled";
+static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------";
+static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests ";
+static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures ";
+static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored ";
+#ifndef UNITY_EXCLUDE_DETAILS
+static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " ";
+static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " ";
+#endif
+/*-----------------------------------------------
+ * Pretty Printers & Test Result Output Handlers
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+/* Local helper function to print characters. */
+static void UnityPrintChar(const char* pch)
+{
+ /* printable characters plus CR & LF are printed */
+ if ((*pch <= 126) && (*pch >= 32))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ }
+ /* write escaped carriage returns */
+ else if (*pch == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (*pch == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)*pch, 2);
+ }
+}
+
+/*-----------------------------------------------*/
+/* Local helper function to print ANSI escape strings e.g. "\033[42m". */
+#ifdef UNITY_OUTPUT_COLOR
+static UNITY_UINT UnityPrintAnsiEscapeString(const char* string)
+{
+ const char* pch = string;
+ UNITY_UINT count = 0;
+
+ while (*pch && (*pch != 'm'))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ pch++;
+ count++;
+ }
+ UNITY_OUTPUT_CHAR('m');
+ count++;
+
+ return count;
+}
+#endif
+
+/*-----------------------------------------------*/
+void UnityPrint(const char* string)
+{
+ const char* pch = string;
+
+ if (pch != NULL)
+ {
+ while (*pch)
+ {
+#ifdef UNITY_OUTPUT_COLOR
+ /* print ANSI escape code */
+ if ((*pch == 27) && (*(pch + 1) == '['))
+ {
+ pch += UnityPrintAnsiEscapeString(pch);
+ continue;
+ }
+#endif
+ UnityPrintChar(pch);
+ pch++;
+ }
+ }
+}
+/*-----------------------------------------------*/
+void UnityPrintLen(const char* string, const UNITY_UINT32 length)
+{
+ const char* pch = string;
+
+ if (pch != NULL)
+ {
+ while (*pch && ((UNITY_UINT32)(pch - string) < length))
+ {
+ /* printable characters plus CR & LF are printed */
+ if ((*pch <= 126) && (*pch >= 32))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ }
+ /* write escaped carriage returns */
+ else if (*pch == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (*pch == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)*pch, 2);
+ }
+ pch++;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style)
+{
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (style == UNITY_DISPLAY_STYLE_CHAR)
+ {
+ /* printable characters plus CR & LF are printed */
+ UNITY_OUTPUT_CHAR('\'');
+ if ((number <= 126) && (number >= 32))
+ {
+ UNITY_OUTPUT_CHAR((int)number);
+ }
+ /* write escaped carriage returns */
+ else if (number == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (number == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, 2);
+ }
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrintNumber(number);
+ }
+ }
+ else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT)
+ {
+ UnityPrintNumberUnsigned((UNITY_UINT)number);
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2));
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumber(const UNITY_INT number_to_print)
+{
+ UNITY_UINT number = (UNITY_UINT)number_to_print;
+
+ if (number_to_print < 0)
+ {
+ /* A negative number, including MIN negative */
+ UNITY_OUTPUT_CHAR('-');
+ number = (~number) + 1;
+ }
+ UnityPrintNumberUnsigned(number);
+}
+
+/*-----------------------------------------------
+ * basically do an itoa using as little ram as possible */
+void UnityPrintNumberUnsigned(const UNITY_UINT number)
+{
+ UNITY_UINT divisor = 1;
+
+ /* figure out initial divisor */
+ while (number / divisor > 9)
+ {
+ divisor *= 10;
+ }
+
+ /* now mod and print, then divide divisor */
+ do
+ {
+ UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
+ divisor /= 10;
+ } while (divisor > 0);
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print)
+{
+ int nibble;
+ char nibbles = nibbles_to_print;
+
+ if ((unsigned)nibbles > UNITY_MAX_NIBBLES)
+ {
+ nibbles = UNITY_MAX_NIBBLES;
+ }
+
+ while (nibbles > 0)
+ {
+ nibbles--;
+ nibble = (int)(number >> (nibbles * 4)) & 0x0F;
+ if (nibble <= 9)
+ {
+ UNITY_OUTPUT_CHAR((char)('0' + nibble));
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble));
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
+{
+ UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1);
+ UNITY_INT32 i;
+
+ for (i = 0; i < UNITY_INT_WIDTH; i++)
+ {
+ if (current_bit & mask)
+ {
+ if (current_bit & number)
+ {
+ UNITY_OUTPUT_CHAR('1');
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('0');
+ }
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('X');
+ }
+ current_bit = current_bit >> 1;
+ }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+/*
+ * This function prints a floating-point value in a format similar to
+ * printf("%.7g") on a single-precision machine or printf("%.9g") on a
+ * double-precision machine. The 7th digit won't always be totally correct
+ * in single-precision operation (for that level of accuracy, a more
+ * complicated algorithm would be needed).
+ */
+void UnityPrintFloat(const UNITY_DOUBLE input_number)
+{
+#ifdef UNITY_INCLUDE_DOUBLE
+ static const int sig_digits = 9;
+ static const UNITY_INT32 min_scaled = 100000000;
+ static const UNITY_INT32 max_scaled = 1000000000;
+#else
+ static const int sig_digits = 7;
+ static const UNITY_INT32 min_scaled = 1000000;
+ static const UNITY_INT32 max_scaled = 10000000;
+#endif
+
+ UNITY_DOUBLE number = input_number;
+
+ /* print minus sign (does not handle negative zero) */
+ if (number < 0.0f)
+ {
+ UNITY_OUTPUT_CHAR('-');
+ number = -number;
+ }
+
+ /* handle zero, NaN, and +/- infinity */
+ if (number == 0.0f)
+ {
+ UnityPrint("0");
+ }
+ else if (isnan(number))
+ {
+ UnityPrint("nan");
+ }
+ else if (isinf(number))
+ {
+ UnityPrint("inf");
+ }
+ else
+ {
+ UNITY_INT32 n_int = 0;
+ UNITY_INT32 n;
+ int exponent = 0;
+ int decimals;
+ int digits;
+ char buf[16] = {0};
+
+ /*
+ * Scale up or down by powers of 10. To minimize rounding error,
+ * start with a factor/divisor of 10^10, which is the largest
+ * power of 10 that can be represented exactly. Finally, compute
+ * (exactly) the remaining power of 10 and perform one more
+ * multiplication or division.
+ */
+ if (number < 1.0f)
+ {
+ UNITY_DOUBLE factor = 1.0f;
+
+ while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; }
+ while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; }
+
+ number *= factor;
+ }
+ else if (number > (UNITY_DOUBLE)max_scaled)
+ {
+ UNITY_DOUBLE divisor = 1.0f;
+
+ while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; }
+ while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; }
+
+ number /= divisor;
+ }
+ else
+ {
+ /*
+ * In this range, we can split off the integer part before
+ * doing any multiplications. This reduces rounding error by
+ * freeing up significant bits in the fractional part.
+ */
+ UNITY_DOUBLE factor = 1.0f;
+ n_int = (UNITY_INT32)number;
+ number -= (UNITY_DOUBLE)n_int;
+
+ while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; }
+
+ number *= factor;
+ }
+
+ /* round to nearest integer */
+ n = ((UNITY_INT32)(number + number) + 1) / 2;
+
+#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO
+ /* round to even if exactly between two integers */
+ if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f))
+ n--;
+#endif
+
+ n += n_int;
+
+ if (n >= max_scaled)
+ {
+ n = min_scaled;
+ exponent++;
+ }
+
+ /* determine where to place decimal point */
+ decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1);
+ exponent += decimals;
+
+ /* truncate trailing zeroes after decimal point */
+ while ((decimals > 0) && ((n % 10) == 0))
+ {
+ n /= 10;
+ decimals--;
+ }
+
+ /* build up buffer in reverse order */
+ digits = 0;
+ while ((n != 0) || (digits <= decimals))
+ {
+ buf[digits++] = (char)('0' + n % 10);
+ n /= 10;
+ }
+
+ /* print out buffer (backwards) */
+ while (digits > 0)
+ {
+ if (digits == decimals)
+ {
+ UNITY_OUTPUT_CHAR('.');
+ }
+ UNITY_OUTPUT_CHAR(buf[--digits]);
+ }
+
+ /* print exponent if needed */
+ if (exponent != 0)
+ {
+ UNITY_OUTPUT_CHAR('e');
+
+ if (exponent < 0)
+ {
+ UNITY_OUTPUT_CHAR('-');
+ exponent = -exponent;
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('+');
+ }
+
+ digits = 0;
+ while ((exponent != 0) || (digits < 2))
+ {
+ buf[digits++] = (char)('0' + exponent % 10);
+ exponent /= 10;
+ }
+ while (digits > 0)
+ {
+ UNITY_OUTPUT_CHAR(buf[--digits]);
+ }
+ }
+ }
+}
+#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */
+
+/*-----------------------------------------------*/
+static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line)
+{
+#ifdef UNITY_OUTPUT_FOR_ECLIPSE
+ UNITY_OUTPUT_CHAR('(');
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(')');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+#else
+#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH
+ UnityPrint("<SRCREF line=");
+ UnityPrintNumber((UNITY_INT)line);
+ UnityPrint(" file=\"");
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR('"');
+ UNITY_OUTPUT_CHAR('>');
+ UnityPrint(Unity.CurrentTestName);
+ UnityPrint("</SRCREF> ");
+#else
+#ifdef UNITY_OUTPUT_FOR_QT_CREATOR
+ UnityPrint("file://");
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+#else
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+#endif
+#endif
+#endif
+}
+
+/*-----------------------------------------------*/
+static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
+{
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrFail);
+ UNITY_OUTPUT_CHAR(':');
+}
+
+/*-----------------------------------------------*/
+void UnityConcludeTest(void)
+{
+ if (Unity.CurrentTestIgnored)
+ {
+ Unity.TestIgnores++;
+ }
+ else if (!Unity.CurrentTestFailed)
+ {
+ UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber);
+ UnityPrint(UnityStrPass);
+ }
+ else
+ {
+ Unity.TestFailures++;
+ }
+
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+ UNITY_PRINT_EXEC_TIME();
+ UNITY_PRINT_EOL();
+ UNITY_FLUSH_CALL();
+}
+
+/*-----------------------------------------------*/
+static void UnityAddMsgIfSpecified(const char* msg)
+{
+#ifdef UNITY_PRINT_TEST_CONTEXT
+ UnityPrint(UnityStrSpacer);
+ UNITY_PRINT_TEST_CONTEXT();
+#endif
+#ifndef UNITY_EXCLUDE_DETAILS
+ if (Unity.CurrentDetail1)
+ {
+ UnityPrint(UnityStrSpacer);
+ UnityPrint(UnityStrDetail1Name);
+ UnityPrint(Unity.CurrentDetail1);
+ if (Unity.CurrentDetail2)
+ {
+ UnityPrint(UnityStrDetail2Name);
+ UnityPrint(Unity.CurrentDetail2);
+ }
+ }
+#endif
+ if (msg)
+ {
+ UnityPrint(UnityStrSpacer);
+ UnityPrint(msg);
+ }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual)
+{
+ UnityPrint(UnityStrExpected);
+ if (expected != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrint(expected);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+ UnityPrint(UnityStrWas);
+ if (actual != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrint(actual);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStringsLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length)
+{
+ UnityPrint(UnityStrExpected);
+ if (expected != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrintLen(expected, length);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+ UnityPrint(UnityStrWas);
+ if (actual != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrintLen(actual, length);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+}
+
+/*-----------------------------------------------
+ * Assertion & Control Helpers
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_LINE_TYPE lineNumber,
+ const char* msg)
+{
+ /* Both are NULL or same pointer */
+ if (expected == actual) { return 0; }
+
+ /* print and return true if just expected is NULL */
+ if (expected == NULL)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrNullPointerForExpected);
+ UnityAddMsgIfSpecified(msg);
+ return 1;
+ }
+
+ /* print and return true if just actual is NULL */
+ if (actual == NULL)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrNullPointerForActual);
+ UnityAddMsgIfSpecified(msg);
+ return 1;
+ }
+
+ return 0; /* return false if neither is NULL */
+}
+
+/*-----------------------------------------------
+ * Assertion Functions
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+void UnityAssertBits(const UNITY_INT mask,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((mask & expected) != (mask & actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected);
+ UnityPrint(UnityStrWas);
+ UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualNumber(const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (expected != actual)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expected, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
+ const UNITY_INT actual,
+ const UNITY_COMPARISON_T compare,
+ const char *msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ int failed = 0;
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; }
+ if ((threshold == actual)) { failed = 1; }
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; }
+ if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; }
+ }
+ else /* UINT or HEX */
+ {
+ if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; }
+ if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; }
+ }
+
+ if (failed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(actual, style);
+ if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); }
+ if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); }
+ if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); }
+ if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); }
+ UnityPrintNumberByStyle(threshold, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#define UnityPrintPointlessAndBail() \
+do { \
+ UnityTestResultsFailBegin(lineNumber); \
+ UnityPrint(UnityStrPointless); \
+ UnityAddMsgIfSpecified(msg); \
+ UNITY_FAIL_AND_BAIL; \
+} while (0)
+
+/*-----------------------------------------------*/
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ unsigned int length = style & 0xF;
+ unsigned int increment = 0;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (num_elements == 0)
+ {
+#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY
+ UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg);
+#else
+ UnityPrintPointlessAndBail();
+#endif
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while ((elements > 0) && (elements--))
+ {
+ UNITY_INT expect_val;
+ UNITY_INT actual_val;
+
+ switch (length)
+ {
+ case 1:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual;
+ if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX))
+ {
+ expect_val &= 0x000000FF;
+ actual_val &= 0x000000FF;
+ }
+ increment = sizeof(UNITY_INT8);
+ break;
+
+ case 2:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual;
+ if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX))
+ {
+ expect_val &= 0x0000FFFF;
+ actual_val &= 0x0000FFFF;
+ }
+ increment = sizeof(UNITY_INT16);
+ break;
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual;
+ increment = sizeof(UNITY_INT64);
+ break;
+#endif
+
+ default: /* default is length 4 bytes */
+ case 4:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual;
+#ifdef UNITY_SUPPORT_64
+ if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX))
+ {
+ expect_val &= 0x00000000FFFFFFFF;
+ actual_val &= 0x00000000FFFFFFFF;
+ }
+#endif
+ increment = sizeof(UNITY_INT32);
+ length = 4;
+ break;
+ }
+
+ if (expect_val != actual_val)
+ {
+ if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8)))
+ { /* For UINT, remove sign extension (padding 1's) from signed type casts above */
+ UNITY_INT mask = 1;
+ mask = (mask << 8 * length) - 1;
+ expect_val &= mask;
+ actual_val &= mask;
+ }
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expect_val, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual_val, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ /* Walk through array by incrementing the pointers */
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment);
+ }
+ actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment);
+ }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT
+/* Wrap this define in a function with variable types as float or double */
+#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \
+ if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \
+ if (UNITY_NAN_CHECK) return 1; \
+ (diff) = (actual) - (expected); \
+ if ((diff) < 0) (diff) = -(diff); \
+ if ((delta) < 0) (delta) = -(delta); \
+ return !(isnan(diff) || isinf(diff) || ((diff) > (delta)))
+ /* This first part of this condition will catch any NaN or Infinite values */
+#ifndef UNITY_NAN_NOT_EQUAL_NAN
+ #define UNITY_NAN_CHECK isnan(expected) && isnan(actual)
+#else
+ #define UNITY_NAN_CHECK 0
+#endif
+
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
+ do { \
+ UnityPrint(UnityStrExpected); \
+ UnityPrintFloat(expected); \
+ UnityPrint(UnityStrWas); \
+ UnityPrintFloat(actual); \
+ } while (0)
+#else
+ #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
+ UnityPrint(UnityStrDelta)
+#endif /* UNITY_EXCLUDE_FLOAT_PRINT */
+
+/*-----------------------------------------------*/
+static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
+{
+ UNITY_FLOAT diff;
+ UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertWithinFloatArray(const UNITY_FLOAT delta,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected;
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual;
+ UNITY_FLOAT in_delta = delta;
+ UNITY_FLOAT current_element_delta = delta;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY
+ UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg);
+#else
+ UnityPrintPointlessAndBail();
+#endif
+ }
+
+ if (isinf(in_delta))
+ {
+ return; /* Arrays will be force equal with infinite delta */
+ }
+
+ if (isnan(in_delta))
+ {
+ /* Delta must be correct number */
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ /* fix delta sign if need */
+ if (in_delta < 0)
+ {
+ in_delta = -in_delta;
+ }
+
+ while (elements--)
+ {
+ current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION;
+
+ if (current_element_delta < 0)
+ {
+ /* fix delta sign for correct calculations */
+ current_element_delta = -current_element_delta;
+ }
+
+ if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ ptr_expected++;
+ }
+ ptr_actual++;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+
+ if (!UnityFloatsWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (UnityFloatsWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintFloat((UNITY_DOUBLE)expected);
+ UnityPrint(UnityStrNotEqual);
+ UnityPrintFloat((UNITY_DOUBLE)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold,
+ const UNITY_FLOAT actual,
+ const UNITY_COMPARISON_T compare,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ int failed;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ failed = 0;
+
+ /* Checking for "not success" rather than failure to get the right result for NaN */
+ if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; }
+ if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; }
+
+ if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; }
+
+ if (failed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintFloat(actual);
+ if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); }
+ if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); }
+ if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); }
+ UnityPrintFloat(threshold);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style)
+{
+ const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
+ UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
+ UNITY_INT is_trait = !should_be_trait;
+ UNITY_INT trait_index = (UNITY_INT)(style >> 1);
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ switch (style)
+ {
+ case UNITY_FLOAT_IS_INF:
+ case UNITY_FLOAT_IS_NOT_INF:
+ is_trait = isinf(actual) && (actual > 0);
+ break;
+ case UNITY_FLOAT_IS_NEG_INF:
+ case UNITY_FLOAT_IS_NOT_NEG_INF:
+ is_trait = isinf(actual) && (actual < 0);
+ break;
+
+ case UNITY_FLOAT_IS_NAN:
+ case UNITY_FLOAT_IS_NOT_NAN:
+ is_trait = isnan(actual) ? 1 : 0;
+ break;
+
+ case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
+ case UNITY_FLOAT_IS_NOT_DET:
+ is_trait = !isinf(actual) && !isnan(actual);
+ break;
+
+ default: /* including UNITY_FLOAT_INVALID_TRAIT */
+ trait_index = 0;
+ trait_names[0] = UnityStrInvalidFloatTrait;
+ break;
+ }
+
+ if (is_trait != should_be_trait)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ if (!should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+ UnityPrint(UnityStrWas);
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ UnityPrintFloat((UNITY_DOUBLE)actual);
+#else
+ if (should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+#endif
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#endif /* not UNITY_EXCLUDE_FLOAT */
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_DOUBLE
+static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual)
+{
+ UNITY_DOUBLE diff;
+ UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected;
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual;
+ UNITY_DOUBLE in_delta = delta;
+ UNITY_DOUBLE current_element_delta = delta;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY
+ UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg);
+#else
+ UnityPrintPointlessAndBail();
+#endif
+ }
+
+ if (isinf(in_delta))
+ {
+ return; /* Arrays will be force equal with infinite delta */
+ }
+
+ if (isnan(in_delta))
+ {
+ /* Delta must be correct number */
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ /* fix delta sign if need */
+ if (in_delta < 0)
+ {
+ in_delta = -in_delta;
+ }
+
+ while (elements--)
+ {
+ current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION;
+
+ if (current_element_delta < 0)
+ {
+ /* fix delta sign for correct calculations */
+ current_element_delta = -current_element_delta;
+ }
+
+ if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ ptr_expected++;
+ }
+ ptr_actual++;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (!UnityDoublesWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (UnityDoublesWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintFloat((UNITY_DOUBLE)expected);
+ UnityPrint(UnityStrNotEqual);
+ UnityPrintFloat((UNITY_DOUBLE)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold,
+ const UNITY_DOUBLE actual,
+ const UNITY_COMPARISON_T compare,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ int failed;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ failed = 0;
+
+ /* Checking for "not success" rather than failure to get the right result for NaN */
+ if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; }
+ if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; }
+
+ if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; }
+
+ if (failed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintFloat(actual);
+ if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); }
+ if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); }
+ if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); }
+ UnityPrintFloat(threshold);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style)
+{
+ const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
+ UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
+ UNITY_INT is_trait = !should_be_trait;
+ UNITY_INT trait_index = (UNITY_INT)(style >> 1);
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ switch (style)
+ {
+ case UNITY_FLOAT_IS_INF:
+ case UNITY_FLOAT_IS_NOT_INF:
+ is_trait = isinf(actual) && (actual > 0);
+ break;
+ case UNITY_FLOAT_IS_NEG_INF:
+ case UNITY_FLOAT_IS_NOT_NEG_INF:
+ is_trait = isinf(actual) && (actual < 0);
+ break;
+
+ case UNITY_FLOAT_IS_NAN:
+ case UNITY_FLOAT_IS_NOT_NAN:
+ is_trait = isnan(actual) ? 1 : 0;
+ break;
+
+ case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
+ case UNITY_FLOAT_IS_NOT_DET:
+ is_trait = !isinf(actual) && !isnan(actual);
+ break;
+
+ default: /* including UNITY_FLOAT_INVALID_TRAIT */
+ trait_index = 0;
+ trait_names[0] = UnityStrInvalidFloatTrait;
+ break;
+ }
+
+ if (is_trait != should_be_trait)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ if (!should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+ UnityPrint(UnityStrWas);
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ UnityPrintFloat(actual);
+#else
+ if (should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+#endif
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#endif /* not UNITY_EXCLUDE_DOUBLE */
+
+/*-----------------------------------------------*/
+void UnityAssertNumbersWithin(const UNITY_UINT delta,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (actual > expected)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta);
+ }
+ }
+ else
+ {
+ if ((UNITY_UINT)actual > (UNITY_UINT)expected)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta);
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrDelta);
+ UnityPrintNumberByStyle((UNITY_INT)delta, style);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expected, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertNumbersArrayWithin(const UNITY_UINT delta,
+ UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ unsigned int length = style & 0xF;
+ unsigned int increment = 0;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (num_elements == 0)
+ {
+#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY
+ UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg);
+#else
+ UnityPrintPointlessAndBail();
+#endif
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while ((elements > 0) && (elements--))
+ {
+ UNITY_INT expect_val;
+ UNITY_INT actual_val;
+
+ switch (length)
+ {
+ case 1:
+ /* fixing problems with signed overflow on unsigned numbers */
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual;
+ increment = sizeof(UNITY_INT8);
+ }
+ else
+ {
+ expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected;
+ actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual;
+ increment = sizeof(UNITY_UINT8);
+ }
+ break;
+
+ case 2:
+ /* fixing problems with signed overflow on unsigned numbers */
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual;
+ increment = sizeof(UNITY_INT16);
+ }
+ else
+ {
+ expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected;
+ actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual;
+ increment = sizeof(UNITY_UINT16);
+ }
+ break;
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ /* fixing problems with signed overflow on unsigned numbers */
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual;
+ increment = sizeof(UNITY_INT64);
+ }
+ else
+ {
+ expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected;
+ actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual;
+ increment = sizeof(UNITY_UINT64);
+ }
+ break;
+#endif
+
+ default: /* default is length 4 bytes */
+ case 4:
+ /* fixing problems with signed overflow on unsigned numbers */
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual;
+ increment = sizeof(UNITY_INT32);
+ }
+ else
+ {
+ expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected;
+ actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual;
+ increment = sizeof(UNITY_UINT32);
+ }
+ length = 4;
+ break;
+ }
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (actual_val > expect_val)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta);
+ }
+ }
+ else
+ {
+ if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta);
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8)))
+ { /* For UINT, remove sign extension (padding 1's) from signed type casts above */
+ UNITY_INT mask = 1;
+ mask = (mask << 8 * length) - 1;
+ expect_val &= mask;
+ actual_val &= mask;
+ }
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrDelta);
+ UnityPrintNumberByStyle((UNITY_INT)delta, style);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expect_val, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual_val, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ /* Walk through array by incrementing the pointers */
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment);
+ }
+ actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment);
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualString(const char* expected,
+ const char* actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ UNITY_UINT32 i;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if both pointers not null compare the strings */
+ if (expected && actual)
+ {
+ for (i = 0; expected[i] || actual[i]; i++)
+ {
+ if (expected[i] != actual[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expected != actual)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrintExpectedAndActualStrings(expected, actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ UNITY_UINT32 i;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if both pointers not null compare the strings */
+ if (expected && actual)
+ {
+ for (i = 0; (i < length) && (expected[i] || actual[i]); i++)
+ {
+ if (expected[i] != actual[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expected != actual)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrintExpectedAndActualStringsLen(expected, actual, length);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
+ const char** actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 i = 0;
+ UNITY_UINT32 j = 0;
+ const char* expd = NULL;
+ const char* act = NULL;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if no elements, it's an error */
+ if (num_elements == 0)
+ {
+#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY
+ UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg);
+#else
+ UnityPrintPointlessAndBail();
+#endif
+ }
+
+ if ((const void*)expected == (const void*)actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ if (flags != UNITY_ARRAY_TO_ARRAY)
+ {
+ expd = (const char*)expected;
+ }
+
+ do
+ {
+ act = actual[j];
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expd = ((const char* const*)expected)[j];
+ }
+
+ /* if both pointers not null compare the strings */
+ if (expd && act)
+ {
+ for (i = 0; expd[i] || act[i]; i++)
+ {
+ if (expd[i] != act[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expd != act)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ if (num_elements > 1)
+ {
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(j);
+ }
+ UnityPrintExpectedAndActualStrings(expd, act);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ } while (++j < num_elements);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 length,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+ UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual;
+ UNITY_UINT32 elements = num_elements;
+ UNITY_UINT32 bytes;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY
+ UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg);
+#else
+ UnityPrintPointlessAndBail();
+#endif
+ }
+ if (length == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while (elements--)
+ {
+ bytes = length;
+ while (bytes--)
+ {
+ if (*ptr_exp != *ptr_act)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrMemory);
+ if (num_elements > 1)
+ {
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ }
+ UnityPrint(UnityStrByte);
+ UnityPrintNumberUnsigned(length - bytes - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ ptr_exp++;
+ ptr_act++;
+ }
+ if (flags == UNITY_ARRAY_TO_VAL)
+ {
+ ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+
+static union
+{
+ UNITY_INT8 i8;
+ UNITY_INT16 i16;
+ UNITY_INT32 i32;
+#ifdef UNITY_SUPPORT_64
+ UNITY_INT64 i64;
+#endif
+#ifndef UNITY_EXCLUDE_FLOAT
+ float f;
+#endif
+#ifndef UNITY_EXCLUDE_DOUBLE
+ double d;
+#endif
+} UnityQuickCompare;
+
+UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size)
+{
+ switch(size)
+ {
+ case 1:
+ UnityQuickCompare.i8 = (UNITY_INT8)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8);
+
+ case 2:
+ UnityQuickCompare.i16 = (UNITY_INT16)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16);
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ UnityQuickCompare.i64 = (UNITY_INT64)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64);
+#endif
+
+ default: /* 4 bytes */
+ UnityQuickCompare.i32 = (UNITY_INT32)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32);
+ }
+}
+
+#ifndef UNITY_EXCLUDE_FLOAT
+/*-----------------------------------------------*/
+UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
+{
+ UnityQuickCompare.f = num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f);
+}
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+/*-----------------------------------------------*/
+UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
+{
+ UnityQuickCompare.d = num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d);
+}
+#endif
+
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+
+/*-----------------------------------------------
+ * printf length modifier helpers
+ *-----------------------------------------------*/
+
+enum UnityLengthModifier {
+ UNITY_LENGTH_MODIFIER_NONE,
+ UNITY_LENGTH_MODIFIER_LONG_LONG,
+ UNITY_LENGTH_MODIFIER_LONG,
+};
+
+#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \
+do { \
+ switch (LENGTH_MOD) \
+ { \
+ case UNITY_LENGTH_MODIFIER_LONG_LONG: \
+ { \
+ NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \
+ break; \
+ } \
+ case UNITY_LENGTH_MODIFIER_LONG: \
+ { \
+ NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \
+ break; \
+ } \
+ case UNITY_LENGTH_MODIFIER_NONE: \
+ default: \
+ { \
+ NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \
+ break; \
+ } \
+ } \
+} while (0)
+
+static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length)
+{
+ enum UnityLengthModifier length_mod;
+ switch (pch[0])
+ {
+ case 'l':
+ {
+ if (pch[1] == 'l')
+ {
+ *length = 2;
+ length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG;
+ }
+ else
+ {
+ *length = 1;
+ length_mod = UNITY_LENGTH_MODIFIER_LONG;
+ }
+ break;
+ }
+ case 'h':
+ {
+ // short and char are converted to int
+ length_mod = UNITY_LENGTH_MODIFIER_NONE;
+ if (pch[1] == 'h')
+ {
+ *length = 2;
+ }
+ else
+ {
+ *length = 1;
+ }
+ break;
+ }
+ case 'j':
+ case 'z':
+ case 't':
+ case 'L':
+ {
+ // Not supported, but should gobble up the length specifier anyway
+ length_mod = UNITY_LENGTH_MODIFIER_NONE;
+ *length = 1;
+ break;
+ }
+ default:
+ {
+ length_mod = UNITY_LENGTH_MODIFIER_NONE;
+ *length = 0;
+ }
+ }
+ return length_mod;
+}
+
+/*-----------------------------------------------
+ * printf helper function
+ *-----------------------------------------------*/
+static void UnityPrintFVA(const char* format, va_list va)
+{
+ const char* pch = format;
+ if (pch != NULL)
+ {
+ while (*pch)
+ {
+ /* format identification character */
+ if (*pch == '%')
+ {
+ pch++;
+
+ if (pch != NULL)
+ {
+ int length_mod_size;
+ enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size);
+ pch += length_mod_size;
+
+ switch (*pch)
+ {
+ case 'd':
+ case 'i':
+ {
+ UNITY_INT number;
+ UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int);
+ UnityPrintNumber((UNITY_INT)number);
+ break;
+ }
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ case 'f':
+ case 'g':
+ {
+ const double number = va_arg(va, double);
+ UnityPrintFloat((UNITY_DOUBLE)number);
+ break;
+ }
+#endif
+ case 'u':
+ {
+ UNITY_UINT number;
+ UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
+ UnityPrintNumberUnsigned(number);
+ break;
+ }
+ case 'b':
+ {
+ UNITY_UINT number;
+ UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
+ const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1;
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('b');
+ UnityPrintMask(mask, number);
+ break;
+ }
+ case 'x':
+ case 'X':
+ {
+ UNITY_UINT number;
+ UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex(number, 8);
+ break;
+ }
+ case 'p':
+ {
+ const unsigned int number = va_arg(va, unsigned int);
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, 8);
+ break;
+ }
+ case 'c':
+ {
+ const int ch = va_arg(va, int);
+ UnityPrintChar((const char *)&ch);
+ break;
+ }
+ case 's':
+ {
+ const char * string = va_arg(va, const char *);
+ UnityPrint(string);
+ break;
+ }
+ case '%':
+ {
+ UnityPrintChar(pch);
+ break;
+ }
+ default:
+ {
+ /* print the unknown format character */
+ UNITY_OUTPUT_CHAR('%');
+ UnityPrintChar(pch);
+ break;
+ }
+ }
+ }
+ }
+#ifdef UNITY_OUTPUT_COLOR
+ /* print ANSI escape code */
+ else if ((*pch == 27) && (*(pch + 1) == '['))
+ {
+ pch += UnityPrintAnsiEscapeString(pch);
+ continue;
+ }
+#endif
+ else if (*pch == '\n')
+ {
+ UNITY_PRINT_EOL();
+ }
+ else
+ {
+ UnityPrintChar(pch);
+ }
+
+ pch++;
+ }
+ }
+}
+
+void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...)
+{
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint("INFO");
+ if(format != NULL)
+ {
+ UnityPrint(": ");
+ va_list va;
+ va_start(va, format);
+ UnityPrintFVA(format, va);
+ va_end(va);
+ }
+ UNITY_PRINT_EOL();
+}
+#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */
+
+
+/*-----------------------------------------------
+ * Control Functions
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrFail);
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+
+#ifdef UNITY_PRINT_TEST_CONTEXT
+ UNITY_PRINT_TEST_CONTEXT();
+#endif
+#ifndef UNITY_EXCLUDE_DETAILS
+ if (Unity.CurrentDetail1)
+ {
+ UnityPrint(UnityStrDetail1Name);
+ UnityPrint(Unity.CurrentDetail1);
+ if (Unity.CurrentDetail2)
+ {
+ UnityPrint(UnityStrDetail2Name);
+ UnityPrint(Unity.CurrentDetail2);
+ }
+ UnityPrint(UnityStrSpacer);
+ }
+#endif
+ if (msg[0] != ' ')
+ {
+ UNITY_OUTPUT_CHAR(' ');
+ }
+ UnityPrint(msg);
+ }
+
+ UNITY_FAIL_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrIgnore);
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(msg);
+ }
+ UNITY_IGNORE_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityMessage(const char* msg, const UNITY_LINE_TYPE line)
+{
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint("INFO");
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(msg);
+ }
+ UNITY_PRINT_EOL();
+}
+
+/*-----------------------------------------------*/
+/* If we have not defined our own test runner, then include our default test runner to make life easier */
+#ifndef UNITY_SKIP_DEFAULT_RUNNER
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum)
+{
+ Unity.CurrentTestName = FuncName;
+ Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum;
+ Unity.NumberOfTests++;
+ UNITY_CLR_DETAILS();
+ UNITY_EXEC_TIME_START();
+ if (TEST_PROTECT())
+ {
+ setUp();
+ Func();
+ }
+ if (TEST_PROTECT())
+ {
+ tearDown();
+ }
+ UNITY_EXEC_TIME_STOP();
+ UnityConcludeTest();
+}
+#endif
+
+/*-----------------------------------------------*/
+void UnitySetTestFile(const char* filename)
+{
+ Unity.TestFile = filename;
+}
+
+/*-----------------------------------------------*/
+void UnityBegin(const char* filename)
+{
+ Unity.TestFile = filename;
+ Unity.CurrentTestName = NULL;
+ Unity.CurrentTestLineNumber = 0;
+ Unity.NumberOfTests = 0;
+ Unity.TestFailures = 0;
+ Unity.TestIgnores = 0;
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+
+ UNITY_CLR_DETAILS();
+ UNITY_OUTPUT_START();
+}
+
+/*-----------------------------------------------*/
+int UnityEnd(void)
+{
+ UNITY_PRINT_EOL();
+ UnityPrint(UnityStrBreaker);
+ UNITY_PRINT_EOL();
+ UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests));
+ UnityPrint(UnityStrResultsTests);
+ UnityPrintNumber((UNITY_INT)(Unity.TestFailures));
+ UnityPrint(UnityStrResultsFailures);
+ UnityPrintNumber((UNITY_INT)(Unity.TestIgnores));
+ UnityPrint(UnityStrResultsIgnored);
+ UNITY_PRINT_EOL();
+ if (Unity.TestFailures == 0U)
+ {
+ UnityPrint(UnityStrOk);
+ }
+ else
+ {
+ UnityPrint(UnityStrFail);
+#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL
+ UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D');
+#endif
+ }
+ UNITY_PRINT_EOL();
+ UNITY_FLUSH_CALL();
+ UNITY_OUTPUT_COMPLETE();
+ return (int)(Unity.TestFailures);
+}
+
+/*-----------------------------------------------
+ * Command Line Argument Support
+ *-----------------------------------------------*/
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+
+char* UnityOptionIncludeNamed = NULL;
+char* UnityOptionExcludeNamed = NULL;
+int UnityVerbosity = 1;
+
+/*-----------------------------------------------*/
+int UnityParseOptions(int argc, char** argv)
+{
+ int i;
+ UnityOptionIncludeNamed = NULL;
+ UnityOptionExcludeNamed = NULL;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'l': /* list tests */
+ return -1;
+ case 'n': /* include tests with name including this string */
+ case 'f': /* an alias for -n */
+ if (argv[i][2] == '=')
+ {
+ UnityOptionIncludeNamed = &argv[i][3];
+ }
+ else if (++i < argc)
+ {
+ UnityOptionIncludeNamed = argv[i];
+ }
+ else
+ {
+ UnityPrint("ERROR: No Test String to Include Matches For");
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ break;
+ case 'q': /* quiet */
+ UnityVerbosity = 0;
+ break;
+ case 'v': /* verbose */
+ UnityVerbosity = 2;
+ break;
+ case 'x': /* exclude tests with name including this string */
+ if (argv[i][2] == '=')
+ {
+ UnityOptionExcludeNamed = &argv[i][3];
+ }
+ else if (++i < argc)
+ {
+ UnityOptionExcludeNamed = argv[i];
+ }
+ else
+ {
+ UnityPrint("ERROR: No Test String to Exclude Matches For");
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ break;
+ default:
+ UnityPrint("ERROR: Unknown Option ");
+ UNITY_OUTPUT_CHAR(argv[i][1]);
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------*/
+int IsStringInBiggerString(const char* longstring, const char* shortstring)
+{
+ const char* lptr = longstring;
+ const char* sptr = shortstring;
+ const char* lnext = lptr;
+
+ if (*sptr == '*')
+ {
+ return 1;
+ }
+
+ while (*lptr)
+ {
+ lnext = lptr + 1;
+
+ /* If they current bytes match, go on to the next bytes */
+ while (*lptr && *sptr && (*lptr == *sptr))
+ {
+ lptr++;
+ sptr++;
+
+ /* We're done if we match the entire string or up to a wildcard */
+ if (*sptr == '*')
+ return 1;
+ if (*sptr == ',')
+ return 1;
+ if (*sptr == '"')
+ return 1;
+ if (*sptr == '\'')
+ return 1;
+ if (*sptr == ':')
+ return 2;
+ if (*sptr == 0)
+ return 1;
+ }
+
+ /* Otherwise we start in the long pointer 1 character further and try again */
+ lptr = lnext;
+ sptr = shortstring;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------*/
+int UnityStringArgumentMatches(const char* str)
+{
+ int retval;
+ const char* ptr1;
+ const char* ptr2;
+ const char* ptrf;
+
+ /* Go through the options and get the substrings for matching one at a time */
+ ptr1 = str;
+ while (ptr1[0] != 0)
+ {
+ if ((ptr1[0] == '"') || (ptr1[0] == '\''))
+ {
+ ptr1++;
+ }
+
+ /* look for the start of the next partial */
+ ptr2 = ptr1;
+ ptrf = 0;
+ do
+ {
+ ptr2++;
+ if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','))
+ {
+ ptrf = &ptr2[1];
+ }
+ } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','));
+
+ while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ',')))
+ {
+ ptr2++;
+ }
+
+ /* done if complete filename match */
+ retval = IsStringInBiggerString(Unity.TestFile, ptr1);
+ if (retval == 1)
+ {
+ return retval;
+ }
+
+ /* done if testname match after filename partial match */
+ if ((retval == 2) && (ptrf != 0))
+ {
+ if (IsStringInBiggerString(Unity.CurrentTestName, ptrf))
+ {
+ return 1;
+ }
+ }
+
+ /* done if complete testname match */
+ if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1)
+ {
+ return 1;
+ }
+
+ ptr1 = ptr2;
+ }
+
+ /* we couldn't find a match for any substrings */
+ return 0;
+}
+
+/*-----------------------------------------------*/
+int UnityTestMatches(void)
+{
+ /* Check if this test name matches the included test pattern */
+ int retval;
+ if (UnityOptionIncludeNamed)
+ {
+ retval = UnityStringArgumentMatches(UnityOptionIncludeNamed);
+ }
+ else
+ {
+ retval = 1;
+ }
+
+ /* Check if this test name matches the excluded test pattern */
+ if (UnityOptionExcludeNamed)
+ {
+ if (UnityStringArgumentMatches(UnityOptionExcludeNamed))
+ {
+ retval = 0;
+ }
+ }
+
+ return retval;
+}
+
+#endif /* UNITY_USE_COMMAND_LINE_ARGS */
+/*-----------------------------------------------*/
diff --git a/movement/lib/chirpy_tx/test/unity.h b/movement/lib/chirpy_tx/test/unity.h
new file mode 100644
index 00000000..e321a1da
--- /dev/null
+++ b/movement/lib/chirpy_tx/test/unity.h
@@ -0,0 +1,687 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FRAMEWORK_H
+#define UNITY_FRAMEWORK_H
+#define UNITY
+
+#define UNITY_VERSION_MAJOR 2
+#define UNITY_VERSION_MINOR 5
+#define UNITY_VERSION_BUILD 4
+#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "unity_internals.h"
+
+/*-------------------------------------------------------
+ * Test Setup / Teardown
+ *-------------------------------------------------------*/
+
+/* These functions are intended to be called before and after each test.
+ * If using unity directly, these will need to be provided for each test
+ * executable built. If you are using the test runner generator and/or
+ * Ceedling, these are optional. */
+void setUp(void);
+void tearDown(void);
+
+/* These functions are intended to be called at the beginning and end of an
+ * entire test suite. suiteTearDown() is passed the number of tests that
+ * failed, and its return value becomes the exit code of main(). If using
+ * Unity directly, you're in charge of calling these if they are desired.
+ * If using Ceedling or the test runner generator, these will be called
+ * automatically if they exist. */
+void suiteSetUp(void);
+int suiteTearDown(int num_failures);
+
+/*-------------------------------------------------------
+ * Test Reset and Verify
+ *-------------------------------------------------------*/
+
+/* These functions are intended to be called before during tests in order
+ * to support complex test loops, etc. Both are NOT built into Unity. Instead
+ * the test runner generator will create them. resetTest will run teardown and
+ * setup again, verifying any end-of-test needs between. verifyTest will only
+ * run the verification. */
+void resetTest(void);
+void verifyTest(void);
+
+/*-------------------------------------------------------
+ * Configuration Options
+ *-------------------------------------------------------
+ * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
+
+ * Integers/longs/pointers
+ * - Unity attempts to automatically discover your integer sizes
+ * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
+ * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
+ * - If you cannot use the automatic methods above, you can force Unity by using these options:
+ * - define UNITY_SUPPORT_64
+ * - set UNITY_INT_WIDTH
+ * - set UNITY_LONG_WIDTH
+ * - set UNITY_POINTER_WIDTH
+
+ * Floats
+ * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
+ * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
+ * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
+ * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
+ * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
+ * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
+ * - define UNITY_DOUBLE_TYPE to specify something other than double
+ * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
+
+ * Output
+ * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
+ * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
+
+ * Optimization
+ * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
+ * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
+
+ * Test Cases
+ * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
+
+ * Parameterized Tests
+ * - you'll want to create a define of TEST_CASE(...) and/or TEST_RANGE(...) which basically evaluates to nothing
+
+ * Tests with Arguments
+ * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
+
+ *-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
+#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
+#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
+#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
+#define TEST_MESSAGE(message) UnityMessage((message), __LINE__)
+#define TEST_ONLY()
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), __VA_ARGS__)
+#endif
+
+/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
+ * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
+#define TEST_PASS() TEST_ABORT()
+#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0)
+
+/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
+ * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */
+#define TEST_FILE(a)
+
+/*-------------------------------------------------------
+ * Test Asserts (simple)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
+#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
+#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
+#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
+#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
+#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
+#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty")
+#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty")
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL)
+
+/* Integer Not Equal To (of all sizes) */
+#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
+
+/* Integer Greater Than/ Less Than (of all sizes) */
+#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+
+/* Integer Array Ranges (of all sizes) */
+#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+
+/* Arrays Compared To Single Value */
+#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL)
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/* Shorthand */
+#ifdef UNITY_SHORTHAND_AS_OLD
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
+#endif
+#ifdef UNITY_SHORTHAND_AS_INT
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_MEM
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_RAW
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal")
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
+#endif
+#ifdef UNITY_SHORTHAND_AS_NONE
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+
+/*-------------------------------------------------------
+ * Test Asserts (with additional messages)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
+#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
+#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
+#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
+#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
+#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
+#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message))
+#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message))
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message))
+
+/* Integer Not Equal To (of all sizes) */
+#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
+
+
+/* Integer Greater Than/ Less Than (of all sizes) */
+#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message))
+
+/* Integer Array Ranges (of all sizes) */
+#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+
+/* Arrays Compared To Single Value*/
+#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message))
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* Shorthand */
+#ifdef UNITY_SHORTHAND_AS_OLD
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
+#endif
+#ifdef UNITY_SHORTHAND_AS_INT
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_MEM
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_RAW
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message)
+#endif
+#ifdef UNITY_SHORTHAND_AS_NONE
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+
+/* end of UNITY_FRAMEWORK_H */
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/movement/lib/chirpy_tx/test/unity_internals.h b/movement/lib/chirpy_tx/test/unity_internals.h
new file mode 100644
index 00000000..47bd370d
--- /dev/null
+++ b/movement/lib/chirpy_tx/test/unity_internals.h
@@ -0,0 +1,1145 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_INTERNALS_H
+#define UNITY_INTERNALS_H
+
+#ifdef UNITY_INCLUDE_CONFIG_H
+#include "unity_config.h"
+#endif
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_MATH_H
+#include <math.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+#include <stdarg.h>
+#endif
+
+/* Unity Attempts to Auto-Detect Integer Types
+ * Attempt 1: UINT_MAX, ULONG_MAX in <limits.h>, or default to 32 bits
+ * Attempt 2: UINTPTR_MAX in <stdint.h>, or default to same size as long
+ * The user may override any of these derived constants:
+ * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */
+#ifndef UNITY_EXCLUDE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_LIMITS_H
+#include <limits.h>
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+ #define UNITY_FUNCTION_ATTR(a) __attribute__((a))
+#else
+ #define UNITY_FUNCTION_ATTR(a) /* ignore */
+#endif
+
+#ifndef UNITY_NORETURN
+ #if defined(__cplusplus)
+ #if __cplusplus >= 201103L
+ #define UNITY_NORETURN [[ noreturn ]]
+ #endif
+ #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+ #if defined(_WIN32) && defined(_MSC_VER)
+ /* We are using MSVC compiler on Windows platform. */
+ /* Not all Windows SDKs supports <stdnoreturn.h>, but compiler can support C11: */
+ /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */
+ /* Not sure, that Mingw compilers has Windows SDK headers at all. */
+ #include <sdkddkver.h>
+ #endif
+
+ /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */
+ /* Mingw GCC should work without that fixes. */
+ /* Based on: */
+ /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */
+ /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */
+ #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE)
+ /* Based on tests and: */
+ /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */
+ /* https://en.cppreference.com/w/c/language/_Noreturn */
+ #define UNITY_NORETURN _Noreturn
+ #else /* Using newer Windows SDK or not MSVC compiler */
+ #include <stdnoreturn.h>
+ #define UNITY_NORETURN noreturn
+ #endif
+ #endif
+#endif
+#ifndef UNITY_NORETURN
+ #define UNITY_NORETURN UNITY_FUNCTION_ATTR(noreturn)
+#endif
+
+/*-------------------------------------------------------
+ * Guess Widths If Not Specified
+ *-------------------------------------------------------*/
+
+/* Determine the size of an int, if not already specified.
+ * We cannot use sizeof(int), because it is not yet defined
+ * at this stage in the translation of the C program.
+ * Also sizeof(int) does return the size in addressable units on all platforms,
+ * which may not necessarily be the size in bytes.
+ * Therefore, infer it from UINT_MAX if possible. */
+#ifndef UNITY_INT_WIDTH
+ #ifdef UINT_MAX
+ #if (UINT_MAX == 0xFFFF)
+ #define UNITY_INT_WIDTH (16)
+ #elif (UINT_MAX == 0xFFFFFFFF)
+ #define UNITY_INT_WIDTH (32)
+ #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_INT_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_INT_WIDTH (32)
+ #endif /* UINT_MAX */
+#endif
+
+/* Determine the size of a long, if not already specified. */
+#ifndef UNITY_LONG_WIDTH
+ #ifdef ULONG_MAX
+ #if (ULONG_MAX == 0xFFFF)
+ #define UNITY_LONG_WIDTH (16)
+ #elif (ULONG_MAX == 0xFFFFFFFF)
+ #define UNITY_LONG_WIDTH (32)
+ #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_LONG_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_LONG_WIDTH (32)
+ #endif /* ULONG_MAX */
+#endif
+
+/* Determine the size of a pointer, if not already specified. */
+#ifndef UNITY_POINTER_WIDTH
+ #ifdef UINTPTR_MAX
+ #if (UINTPTR_MAX <= 0xFFFF)
+ #define UNITY_POINTER_WIDTH (16)
+ #elif (UINTPTR_MAX <= 0xFFFFFFFF)
+ #define UNITY_POINTER_WIDTH (32)
+ #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_POINTER_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH
+ #endif /* UINTPTR_MAX */
+#endif
+
+/*-------------------------------------------------------
+ * Int Support (Define types based on detected sizes)
+ *-------------------------------------------------------*/
+
+#if (UNITY_INT_WIDTH == 32)
+ typedef unsigned char UNITY_UINT8;
+ typedef unsigned short UNITY_UINT16;
+ typedef unsigned int UNITY_UINT32;
+ typedef signed char UNITY_INT8;
+ typedef signed short UNITY_INT16;
+ typedef signed int UNITY_INT32;
+#elif (UNITY_INT_WIDTH == 16)
+ typedef unsigned char UNITY_UINT8;
+ typedef unsigned int UNITY_UINT16;
+ typedef unsigned long UNITY_UINT32;
+ typedef signed char UNITY_INT8;
+ typedef signed int UNITY_INT16;
+ typedef signed long UNITY_INT32;
+#else
+ #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
+#endif
+
+/*-------------------------------------------------------
+ * 64-bit Support
+ *-------------------------------------------------------*/
+
+/* Auto-detect 64 Bit Support */
+#ifndef UNITY_SUPPORT_64
+ #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64
+ #define UNITY_SUPPORT_64
+ #endif
+#endif
+
+/* 64-Bit Support Dependent Configuration */
+#ifndef UNITY_SUPPORT_64
+ /* No 64-bit Support */
+ typedef UNITY_UINT32 UNITY_UINT;
+ typedef UNITY_INT32 UNITY_INT;
+ #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */
+#else
+ /* 64-bit Support */
+ #if (UNITY_LONG_WIDTH == 32)
+ typedef unsigned long long UNITY_UINT64;
+ typedef signed long long UNITY_INT64;
+ #elif (UNITY_LONG_WIDTH == 64)
+ typedef unsigned long UNITY_UINT64;
+ typedef signed long UNITY_INT64;
+ #else
+ #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
+ #endif
+ typedef UNITY_UINT64 UNITY_UINT;
+ typedef UNITY_INT64 UNITY_INT;
+ #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */
+#endif
+
+/*-------------------------------------------------------
+ * Pointer Support
+ *-------------------------------------------------------*/
+
+#if (UNITY_POINTER_WIDTH == 32)
+ #define UNITY_PTR_TO_INT UNITY_INT32
+ #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
+#elif (UNITY_POINTER_WIDTH == 64)
+ #define UNITY_PTR_TO_INT UNITY_INT64
+ #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
+#elif (UNITY_POINTER_WIDTH == 16)
+ #define UNITY_PTR_TO_INT UNITY_INT16
+ #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
+#else
+ #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
+#endif
+
+#ifndef UNITY_PTR_ATTRIBUTE
+ #define UNITY_PTR_ATTRIBUTE
+#endif
+
+#ifndef UNITY_INTERNAL_PTR
+ #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void*
+#endif
+
+/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */
+
+/*-------------------------------------------------------
+ * Float Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_FLOAT
+
+/* No Floating Point Support */
+#ifndef UNITY_EXCLUDE_DOUBLE
+#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */
+#endif
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+#define UNITY_EXCLUDE_FLOAT_PRINT
+#endif
+
+#else
+
+/* Floating Point Support */
+#ifndef UNITY_FLOAT_PRECISION
+#define UNITY_FLOAT_PRECISION (0.00001f)
+#endif
+#ifndef UNITY_FLOAT_TYPE
+#define UNITY_FLOAT_TYPE float
+#endif
+typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
+
+/* isinf & isnan macros should be provided by math.h */
+#ifndef isinf
+/* The value of Inf - Inf is NaN */
+#define isinf(n) (isnan((n) - (n)) && !isnan(n))
+#endif
+
+#ifndef isnan
+/* NaN is the only floating point value that does NOT equal itself.
+ * Therefore if n != n, then it is NaN. */
+#define isnan(n) ((n != n) ? 1 : 0)
+#endif
+
+#endif
+
+/*-------------------------------------------------------
+ * Double Float Support
+ *-------------------------------------------------------*/
+
+/* unlike float, we DON'T include by default */
+#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE)
+
+ /* No Floating Point Support */
+ #ifndef UNITY_EXCLUDE_DOUBLE
+ #define UNITY_EXCLUDE_DOUBLE
+ #else
+ #undef UNITY_INCLUDE_DOUBLE
+ #endif
+
+ #ifndef UNITY_EXCLUDE_FLOAT
+ #ifndef UNITY_DOUBLE_TYPE
+ #define UNITY_DOUBLE_TYPE double
+ #endif
+ typedef UNITY_FLOAT UNITY_DOUBLE;
+ /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */
+ #endif
+
+#else
+
+ /* Double Floating Point Support */
+ #ifndef UNITY_DOUBLE_PRECISION
+ #define UNITY_DOUBLE_PRECISION (1e-12)
+ #endif
+
+ #ifndef UNITY_DOUBLE_TYPE
+ #define UNITY_DOUBLE_TYPE double
+ #endif
+ typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE;
+
+#endif
+
+/*-------------------------------------------------------
+ * Output Method: stdout (DEFAULT)
+ *-------------------------------------------------------*/
+#ifndef UNITY_OUTPUT_CHAR
+ /* Default to using putchar, which is defined in stdio.h */
+ #include <stdio.h>
+ #define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
+#else
+ /* If defined as something else, make sure we declare it here so it's ready for use */
+ #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION
+ extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION;
+ #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+ #ifdef UNITY_USE_FLUSH_STDOUT
+ /* We want to use the stdout flush utility */
+ #include <stdio.h>
+ #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout)
+ #else
+ /* We've specified nothing, therefore flush should just be ignored */
+ #define UNITY_OUTPUT_FLUSH() (void)0
+ #endif
+#else
+ /* If defined as something else, make sure we declare it here so it's ready for use */
+ #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION
+ extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION;
+ #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+#define UNITY_FLUSH_CALL()
+#else
+#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH()
+#endif
+
+#ifndef UNITY_PRINT_EOL
+#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n')
+#endif
+
+#ifndef UNITY_OUTPUT_START
+#define UNITY_OUTPUT_START()
+#endif
+
+#ifndef UNITY_OUTPUT_COMPLETE
+#define UNITY_OUTPUT_COMPLETE()
+#endif
+
+#ifdef UNITY_INCLUDE_EXEC_TIME
+ #if !defined(UNITY_EXEC_TIME_START) && \
+ !defined(UNITY_EXEC_TIME_STOP) && \
+ !defined(UNITY_PRINT_EXEC_TIME) && \
+ !defined(UNITY_TIME_TYPE)
+ /* If none any of these macros are defined then try to provide a default implementation */
+
+ #if defined(UNITY_CLOCK_MS)
+ /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */
+ #define UNITY_TIME_TYPE UNITY_UINT
+ #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS()
+ #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS()
+ #define UNITY_PRINT_EXEC_TIME() { \
+ UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \
+ UnityPrint(" ("); \
+ UnityPrintNumberUnsigned(execTimeMs); \
+ UnityPrint(" ms)"); \
+ }
+ #elif defined(_WIN32)
+ #include <time.h>
+ #define UNITY_TIME_TYPE clock_t
+ #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC)
+ #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime)
+ #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime)
+ #define UNITY_PRINT_EXEC_TIME() { \
+ UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \
+ UnityPrint(" ("); \
+ UnityPrintNumberUnsigned(execTimeMs); \
+ UnityPrint(" ms)"); \
+ }
+ #elif defined(__unix__) || defined(__APPLE__)
+ #include <time.h>
+ #define UNITY_TIME_TYPE struct timespec
+ #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t)
+ #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime)
+ #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime)
+ #define UNITY_PRINT_EXEC_TIME() { \
+ UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \
+ execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \
+ UnityPrint(" ("); \
+ UnityPrintNumberUnsigned(execTimeMs); \
+ UnityPrint(" ms)"); \
+ }
+ #endif
+ #endif
+#endif
+
+#ifndef UNITY_EXEC_TIME_START
+#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0)
+#endif
+
+#ifndef UNITY_EXEC_TIME_STOP
+#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0)
+#endif
+
+#ifndef UNITY_TIME_TYPE
+#define UNITY_TIME_TYPE UNITY_UINT
+#endif
+
+#ifndef UNITY_PRINT_EXEC_TIME
+#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0)
+#endif
+
+/*-------------------------------------------------------
+ * Footprint
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_LINE_TYPE
+#define UNITY_LINE_TYPE UNITY_UINT
+#endif
+
+#ifndef UNITY_COUNTER_TYPE
+#define UNITY_COUNTER_TYPE UNITY_UINT
+#endif
+
+/*-------------------------------------------------------
+ * Internal Structs Needed
+ *-------------------------------------------------------*/
+
+typedef void (*UnityTestFunction)(void);
+
+#define UNITY_DISPLAY_RANGE_INT (0x10)
+#define UNITY_DISPLAY_RANGE_UINT (0x20)
+#define UNITY_DISPLAY_RANGE_HEX (0x40)
+#define UNITY_DISPLAY_RANGE_CHAR (0x80)
+
+typedef enum
+{
+ UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT,
+#endif
+
+ UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT,
+#endif
+
+ UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX,
+ UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX,
+ UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX,
+#endif
+
+ UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT,
+
+ UNITY_DISPLAY_STYLE_UNKNOWN
+} UNITY_DISPLAY_STYLE_T;
+
+typedef enum
+{
+ UNITY_WITHIN = 0x0,
+ UNITY_EQUAL_TO = 0x1,
+ UNITY_GREATER_THAN = 0x2,
+ UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO,
+ UNITY_SMALLER_THAN = 0x4,
+ UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO,
+ UNITY_NOT_EQUAL = 0x0,
+ UNITY_UNKNOWN
+} UNITY_COMPARISON_T;
+
+#ifndef UNITY_EXCLUDE_FLOAT
+typedef enum UNITY_FLOAT_TRAIT
+{
+ UNITY_FLOAT_IS_NOT_INF = 0,
+ UNITY_FLOAT_IS_INF,
+ UNITY_FLOAT_IS_NOT_NEG_INF,
+ UNITY_FLOAT_IS_NEG_INF,
+ UNITY_FLOAT_IS_NOT_NAN,
+ UNITY_FLOAT_IS_NAN,
+ UNITY_FLOAT_IS_NOT_DET,
+ UNITY_FLOAT_IS_DET,
+ UNITY_FLOAT_INVALID_TRAIT
+} UNITY_FLOAT_TRAIT_T;
+#endif
+
+typedef enum
+{
+ UNITY_ARRAY_TO_VAL = 0,
+ UNITY_ARRAY_TO_ARRAY,
+ UNITY_ARRAY_UNKNOWN
+} UNITY_FLAGS_T;
+
+struct UNITY_STORAGE_T
+{
+ const char* TestFile;
+ const char* CurrentTestName;
+#ifndef UNITY_EXCLUDE_DETAILS
+ const char* CurrentDetail1;
+ const char* CurrentDetail2;
+#endif
+ UNITY_LINE_TYPE CurrentTestLineNumber;
+ UNITY_COUNTER_TYPE NumberOfTests;
+ UNITY_COUNTER_TYPE TestFailures;
+ UNITY_COUNTER_TYPE TestIgnores;
+ UNITY_COUNTER_TYPE CurrentTestFailed;
+ UNITY_COUNTER_TYPE CurrentTestIgnored;
+#ifdef UNITY_INCLUDE_EXEC_TIME
+ UNITY_TIME_TYPE CurrentTestStartTime;
+ UNITY_TIME_TYPE CurrentTestStopTime;
+#endif
+#ifndef UNITY_EXCLUDE_SETJMP_H
+ jmp_buf AbortFrame;
+#endif
+};
+
+extern struct UNITY_STORAGE_T Unity;
+
+/*-------------------------------------------------------
+ * Test Suite Management
+ *-------------------------------------------------------*/
+
+void UnityBegin(const char* filename);
+int UnityEnd(void);
+void UnitySetTestFile(const char* filename);
+void UnityConcludeTest(void);
+
+#ifndef RUN_TEST
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
+#else
+#define UNITY_SKIP_DEFAULT_RUNNER
+#endif
+
+/*-------------------------------------------------------
+ * Details Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_DETAILS
+#define UNITY_CLR_DETAILS()
+#define UNITY_SET_DETAIL(d1)
+#define UNITY_SET_DETAILS(d1,d2)
+#else
+#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0)
+#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0)
+#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0)
+
+#ifndef UNITY_DETAIL1_NAME
+#define UNITY_DETAIL1_NAME "Function"
+#endif
+
+#ifndef UNITY_DETAIL2_NAME
+#define UNITY_DETAIL2_NAME "Argument"
+#endif
+#endif
+
+#ifdef UNITY_PRINT_TEST_CONTEXT
+void UNITY_PRINT_TEST_CONTEXT(void);
+#endif
+
+/*-------------------------------------------------------
+ * Test Output
+ *-------------------------------------------------------*/
+
+void UnityPrint(const char* string);
+
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...);
+#endif
+
+void UnityPrintLen(const char* string, const UNITY_UINT32 length);
+void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number);
+void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style);
+void UnityPrintNumber(const UNITY_INT number_to_print);
+void UnityPrintNumberUnsigned(const UNITY_UINT number);
+void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print);
+
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+void UnityPrintFloat(const UNITY_DOUBLE input_number);
+#endif
+
+/*-------------------------------------------------------
+ * Test Assertion Functions
+ *-------------------------------------------------------
+ * Use the macros below this section instead of calling
+ * these directly. The macros have a consistent naming
+ * convention and will pull in file and line information
+ * for you. */
+
+void UnityAssertEqualNumber(const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
+ const UNITY_INT actual,
+ const UNITY_COMPARISON_T compare,
+ const char *msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertBits(const UNITY_INT mask,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualString(const char* expected,
+ const char* actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected,
+ const char** actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 length,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertNumbersWithin(const UNITY_UINT delta,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertNumbersArrayWithin(const UNITY_UINT delta,
+ UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags);
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line);
+UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
+#else
+void UnityFail(const char* message, const UNITY_LINE_TYPE line);
+void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
+#endif
+
+void UnityMessage(const char* message, const UNITY_LINE_TYPE line);
+
+#ifndef UNITY_EXCLUDE_FLOAT
+void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold,
+ const UNITY_FLOAT actual,
+ const UNITY_COMPARISON_T compare,
+ const char* msg,
+ const UNITY_LINE_TYPE linenumber);
+
+void UnityAssertWithinFloatArray(const UNITY_FLOAT delta,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold,
+ const UNITY_DOUBLE actual,
+ const UNITY_COMPARISON_T compare,
+ const char* msg,
+ const UNITY_LINE_TYPE linenumber);
+
+void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+/*-------------------------------------------------------
+ * Helpers
+ *-------------------------------------------------------*/
+
+UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size);
+#ifndef UNITY_EXCLUDE_FLOAT
+UNITY_INTERNAL_PTR UnityFloatToPtr(const float num);
+#endif
+#ifndef UNITY_EXCLUDE_DOUBLE
+UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num);
+#endif
+
+/*-------------------------------------------------------
+ * Error Strings We Might Need
+ *-------------------------------------------------------*/
+
+extern const char UnityStrOk[];
+extern const char UnityStrPass[];
+extern const char UnityStrFail[];
+extern const char UnityStrIgnore[];
+
+extern const char UnityStrErrFloat[];
+extern const char UnityStrErrDouble[];
+extern const char UnityStrErr64[];
+extern const char UnityStrErrShorthand[];
+
+/*-------------------------------------------------------
+ * Test Running Macros
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
+#define TEST_ABORT() longjmp(Unity.AbortFrame, 1)
+#else
+#define TEST_PROTECT() 1
+#define TEST_ABORT() return
+#endif
+
+/* Automatically enable variadic macros support, if it not enabled before */
+#ifndef UNITY_SUPPORT_VARIADIC_MACROS
+ #ifdef __STDC_VERSION__
+ #if __STDC_VERSION__ >= 199901L
+ #define UNITY_SUPPORT_VARIADIC_MACROS
+ #endif
+ #endif
+#endif
+
+/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */
+#ifndef RUN_TEST
+#ifdef UNITY_SUPPORT_VARIADIC_MACROS
+#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway)
+#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line)
+#endif
+#endif
+
+/* Enable default macros for masking param tests test cases */
+#ifdef UNITY_SUPPORT_TEST_CASES
+ #ifdef UNITY_SUPPORT_VARIADIC_MACROS
+ #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE)
+ #define TEST_CASE(...)
+ #endif
+ #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE)
+ #define TEST_RANGE(...)
+ #endif
+ #endif
+#endif
+
+/* If we can't do the tricky version, we'll just have to require them to always include the line number */
+#ifndef RUN_TEST
+#ifdef CMOCK
+#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num)
+#else
+#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__)
+#endif
+#endif
+
+#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
+#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
+#define UNITY_NEW_TEST(a) \
+ Unity.CurrentTestName = (a); \
+ Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \
+ Unity.NumberOfTests++;
+
+#ifndef UNITY_BEGIN
+#define UNITY_BEGIN() UnityBegin(__FILE__)
+#endif
+
+#ifndef UNITY_END
+#define UNITY_END() UnityEnd()
+#endif
+
+#ifndef UNITY_SHORTHAND_AS_INT
+#ifndef UNITY_SHORTHAND_AS_MEM
+#ifndef UNITY_SHORTHAND_AS_NONE
+#ifndef UNITY_SHORTHAND_AS_RAW
+#define UNITY_SHORTHAND_AS_OLD
+#endif
+#endif
+#endif
+#endif
+
+/*-----------------------------------------------
+ * Command Line Argument Support
+ *-----------------------------------------------*/
+
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+int UnityParseOptions(int argc, char** argv);
+int UnityTestMatches(void);
+#endif
+
+/*-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line))
+
+/*-------------------------------------------------------
+ * Test Asserts
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message)); } } while (0)
+#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (UNITY_LINE_TYPE)(line), (message))
+
+#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line))
+
+#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY)
+
+
+#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
+#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+
+#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY)
+
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL)
+
+#ifdef UNITY_SUPPORT_64
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY)
+#else
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#endif
+
+#ifdef UNITY_EXCLUDE_FLOAT
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#else
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+#ifdef UNITY_EXCLUDE_DOUBLE
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#else
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+/* End of UNITY_INTERNALS_H */
+#endif
diff --git a/movement/make/Makefile b/movement/make/Makefile
index 6865960c..dec3ffab 100644
--- a/movement/make/Makefile
+++ b/movement/make/Makefile
@@ -17,6 +17,7 @@ INCLUDES += \
-I../watch_faces/sensor/ \
-I../watch_faces/demo/ \
-I../../littlefs/ \
+ -I../lib/chirpy_tx/ \
-I../lib/TOTP/ \
-I../lib/base32/ \
-I../lib/sunriset/ \
@@ -31,6 +32,7 @@ INCLUDES += \
# ../drivers/lis2dh.c \
# ../watch_faces/fitness/step_count_face.c
SRCS += \
+ ../lib/chirpy_tx/chirpy_tx.c \
../lib/TOTP/sha1.c \
../lib/TOTP/sha256.c \
../lib/TOTP/sha512.c \
@@ -95,8 +97,14 @@ SRCS += \
../watch_faces/complication/tarot_face.c \
../watch_faces/complication/morsecalc_face.c \
../watch_faces/complication/rpn_calculator_face.c \
+ ../watch_faces/complication/activity_face.c \
+ ../watch_faces/demo/chirpy_demo_face.c \
../watch_faces/complication/ships_bell_face.c \
+ ../watch_faces/complication/discgolf_face.c \
../watch_faces/complication/habit_face.c \
+ ../watch_faces/clock/repetition_minute_face.c \
+ ../watch_faces/complication/timer_face.c \
+ ../watch_faces/complication/invaders_face.c \
# New watch faces go above this line.
# Leave this line at the bottom of the file; it has all the targets for making your project.
diff --git a/movement/movement_faces.h b/movement/movement_faces.h
index 901260eb..50b084d3 100644
--- a/movement/movement_faces.h
+++ b/movement/movement_faces.h
@@ -73,8 +73,14 @@
#include "interval_face.h"
#include "morsecalc_face.h"
#include "rpn_calculator_face.h"
+#include "activity_face.h"
+#include "chirpy_demo_face.h"
#include "ships_bell_face.h"
+#include "discgolf_face.h"
#include "habit_face.h"
+#include "repetition_minute_face.h"
+#include "timer_face.h"
+#include "invaders_face.h"
// New includes go above this line.
#endif // MOVEMENT_FACES_H_
diff --git a/movement/watch_faces/clock/repetition_minute_face.c b/movement/watch_faces/clock/repetition_minute_face.c
new file mode 100644
index 00000000..a0fbe077
--- /dev/null
+++ b/movement/watch_faces/clock/repetition_minute_face.c
@@ -0,0 +1,231 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Jonas Termeau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include "repetition_minute_face.h"
+#include "watch.h"
+#include "watch_utility.h"
+#include "watch_private_display.h"
+
+void play_hour_chime(void) {
+ watch_buzzer_play_note(BUZZER_NOTE_C6, 75);
+ watch_buzzer_play_note(BUZZER_NOTE_REST, 500);
+}
+
+void play_quarter_chime(void) {
+ watch_buzzer_play_note(BUZZER_NOTE_E6, 75);
+ watch_buzzer_play_note(BUZZER_NOTE_REST, 150);
+ watch_buzzer_play_note(BUZZER_NOTE_C6, 75);
+ watch_buzzer_play_note(BUZZER_NOTE_REST, 750);
+}
+
+void play_minute_chime(void) {
+ watch_buzzer_play_note(BUZZER_NOTE_E6, 75);
+ watch_buzzer_play_note(BUZZER_NOTE_REST, 500);
+}
+
+static void _update_alarm_indicator(bool settings_alarm_enabled, repetition_minute_state_t *state) {
+ state->alarm_enabled = settings_alarm_enabled;
+ if (state->alarm_enabled) watch_set_indicator(WATCH_INDICATOR_SIGNAL);
+ else watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
+}
+
+void repetition_minute_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
+ (void) settings;
+ (void) watch_face_index;
+
+ if (*context_ptr == NULL) {
+ *context_ptr = malloc(sizeof(repetition_minute_state_t));
+ repetition_minute_state_t *state = (repetition_minute_state_t *)*context_ptr;
+ state->signal_enabled = false;
+ state->watch_face_index = watch_face_index;
+ }
+}
+
+void repetition_minute_face_activate(movement_settings_t *settings, void *context) {
+ repetition_minute_state_t *state = (repetition_minute_state_t *)context;
+
+ if (watch_tick_animation_is_running()) watch_stop_tick_animation();
+
+ if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H);
+
+ // handle chime indicator
+ if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_BELL);
+ else watch_clear_indicator(WATCH_INDICATOR_BELL);
+
+ // show alarm indicator if there is an active alarm
+ _update_alarm_indicator(settings->bit.alarm_enabled, state);
+
+ watch_set_colon();
+
+ // this ensures that none of the timestamp fields will match, so we can re-render them all.
+ state->previous_date_time = 0xFFFFFFFF;
+}
+
+bool repetition_minute_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
+ repetition_minute_state_t *state = (repetition_minute_state_t *)context;
+ char buf[11];
+ uint8_t pos;
+
+ watch_date_time date_time;
+ uint32_t previous_date_time;
+ switch (event.event_type) {
+ case EVENT_ACTIVATE:
+ case EVENT_TICK:
+ case EVENT_LOW_ENERGY_UPDATE:
+ date_time = watch_rtc_get_date_time();
+ previous_date_time = state->previous_date_time;
+ state->previous_date_time = date_time.reg;
+
+ // check the battery voltage once a day...
+ if (date_time.unit.day != state->last_battery_check) {
+ state->last_battery_check = date_time.unit.day;
+ watch_enable_adc();
+ uint16_t voltage = watch_get_vcc_voltage();
+ watch_disable_adc();
+ // 2.2 volts will happen when the battery has maybe 5-10% remaining?
+ // we can refine this later.
+ state->battery_low = (voltage < 2200);
+ }
+
+ // ...and set the LAP indicator if low.
+ if (state->battery_low) watch_set_indicator(WATCH_INDICATOR_LAP);
+
+ if ((date_time.reg >> 6) == (previous_date_time >> 6) && event.event_type != EVENT_LOW_ENERGY_UPDATE) {
+ // everything before seconds is the same, don't waste cycles setting those segments.
+ watch_display_character_lp_seconds('0' + date_time.unit.second / 10, 8);
+ watch_display_character_lp_seconds('0' + date_time.unit.second % 10, 9);
+ break;
+ } else if ((date_time.reg >> 12) == (previous_date_time >> 12) && event.event_type != EVENT_LOW_ENERGY_UPDATE) {
+ // everything before minutes is the same.
+ pos = 6;
+ sprintf(buf, "%02d%02d", date_time.unit.minute, date_time.unit.second);
+ } else {
+ // other stuff changed; let's do it all.
+ if (!settings->bit.clock_mode_24h) {
+ // if we are in 12 hour mode, do some cleanup.
+ if (date_time.unit.hour < 12) {
+ watch_clear_indicator(WATCH_INDICATOR_PM);
+ } else {
+ watch_set_indicator(WATCH_INDICATOR_PM);
+ }
+ date_time.unit.hour %= 12;
+ if (date_time.unit.hour == 0) date_time.unit.hour = 12;
+ }
+ pos = 0;
+ if (event.event_type == EVENT_LOW_ENERGY_UPDATE) {
+ if (!watch_tick_animation_is_running()) watch_start_tick_animation(500);
+ sprintf(buf, "%s%2d%2d%02d ", watch_utility_get_weekday(date_time), date_time.unit.day, date_time.unit.hour, date_time.unit.minute);
+ } else {
+ sprintf(buf, "%s%2d%2d%02d%02d", watch_utility_get_weekday(date_time), date_time.unit.day, date_time.unit.hour, date_time.unit.minute, date_time.unit.second);
+ }
+ }
+ watch_display_string(buf, pos);
+ // handle alarm indicator
+ if (state->alarm_enabled != settings->bit.alarm_enabled) _update_alarm_indicator(settings->bit.alarm_enabled, state);
+ break;
+ case EVENT_ALARM_LONG_PRESS:
+ state->signal_enabled = !state->signal_enabled;
+ if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_BELL);
+ else watch_clear_indicator(WATCH_INDICATOR_BELL);
+ break;
+ case EVENT_BACKGROUND_TASK:
+ // uncomment this line to snap back to the clock face when the hour signal sounds:
+ // movement_move_to_face(state->watch_face_index);
+ if (watch_is_buzzer_or_led_enabled()) {
+ // if we are in the foreground, we can just beep.
+ movement_play_signal();
+ } else {
+ // if we were in the background, we need to enable the buzzer peripheral first,
+ watch_enable_buzzer();
+ // beep quickly (this call blocks for 275 ms),
+ movement_play_signal();
+ // and then turn the buzzer peripheral off again.
+ watch_disable_buzzer();
+ }
+ break;
+ case EVENT_LIGHT_LONG_UP:
+ /*
+ * Howdy neighbors, this is the actual complication. Like an actual
+ * (very expensive) watch with a repetition minute complication it's
+ * boring at 00:00 or 1:00 and very quite musical at 23:59 or 12:59.
+ */
+
+ date_time = watch_rtc_get_date_time();
+
+
+ int hours = date_time.unit.hour;
+ int quarters = date_time.unit.minute / 15;
+ int minutes = date_time.unit.minute % 15;
+
+ // chiming hours
+ if (!settings->bit.clock_mode_24h) {
+ hours = date_time.unit.hour % 12;
+ if (hours == 0) hours = 12;
+ }
+ if (hours > 0) {
+ int count = 0;
+ for(count = hours; count > 0; --count) {
+ play_hour_chime();
+ }
+ }
+
+ // chiming quarters (if needed)
+ if (quarters > 0) {
+ int count = 0;
+ for(count = quarters; count > 0; --count) {
+ play_quarter_chime();
+ }
+ }
+
+ // chiming minutes (if needed)
+ if (minutes > 0) {
+ int count = 0;
+ for(count = minutes; count > 0; --count) {
+ play_minute_chime();
+ }
+ }
+
+ break;
+ default:
+ return movement_default_loop_handler(event, settings);
+ }
+
+ return true;
+}
+
+void repetition_minute_face_resign(movement_settings_t *settings, void *context) {
+ (void) settings;
+ (void) context;
+}
+
+bool repetition_minute_face_wants_background_task(movement_settings_t *settings, void *context) {
+ (void) settings;
+ repetition_minute_state_t *state = (repetition_minute_state_t *)context;
+ if (!state->signal_enabled) return false;
+
+ watch_date_time date_time = watch_rtc_get_date_time();
+
+ return date_time.unit.minute == 0;
+}
diff --git a/movement/watch_faces/clock/repetition_minute_face.h b/movement/watch_faces/clock/repetition_minute_face.h
new file mode 100644
index 00000000..5a897bc1
--- /dev/null
+++ b/movement/watch_faces/clock/repetition_minute_face.h
@@ -0,0 +1,83 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Jonas Termeau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef REPETITION_MINUTE_FACE_H_
+#define REPETITION_MINUTE_FACE_H_
+
+#include "movement.h"
+
+/*
+ * A hopefully useful complication for friendly neighbors in the dark
+ *
+ * Originating from 1676 from reverend and mechanician Edward Barlow, and
+ * perfected in 1820 by neighbor Abraham Breguet, a minute repeater or
+ * "repetition minute" is a complication in a mechanical watch or clock that
+ * chimes the hours and often minutes at the press of a button. There are many
+ * types of repeater, from the simple repeater which merely strikes the number
+ * of hours, to the minute repeater which chimes the time down to the minute,
+ * using separate tones for hours, quarter hours, and minutes. They originated
+ * before widespread artificial illumination, to allow the time to be determined
+ * in the dark, and were also used by the visually impaired.
+ *
+ *
+ * How to use it :
+ *
+ * Long press the light button to get an auditive reading of the time like so :
+ * 0..23 (1..12 if 24-hours format isn't enabled) low beep(s) for the hours
+ * 0..3 low-high couple pitched beeps for the quarters
+ * 0..14 high pitched beep(s) for the remaining minutes
+ *
+ * Prerequisite : a watch with a working buzzer
+ *
+ * ~ Only in the darkness can you see the stars. - Martin Luther King ~
+ *
+ */
+
+typedef struct {
+ uint32_t previous_date_time;
+ uint8_t last_battery_check;
+ uint8_t watch_face_index;
+ bool signal_enabled;
+ bool battery_low;
+ bool alarm_enabled;
+} repetition_minute_state_t;
+
+void play_hour_chime(void);
+void play_quarter_chime(void);
+void play_minute_chime(void);
+void repetition_minute_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
+void repetition_minute_face_activate(movement_settings_t *settings, void *context);
+bool repetition_minute_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
+void repetition_minute_face_resign(movement_settings_t *settings, void *context);
+bool repetition_minute_face_wants_background_task(movement_settings_t *settings, void *context);
+
+#define repetition_minute_face ((const watch_face_t){ \
+ repetition_minute_face_setup, \
+ repetition_minute_face_activate, \
+ repetition_minute_face_loop, \
+ repetition_minute_face_resign, \
+ repetition_minute_face_wants_background_task, \
+})
+
+#endif // REPETITION_MINUTE_FACE_H_
diff --git a/movement/watch_faces/complication/activity_face.c b/movement/watch_faces/complication/activity_face.c
new file mode 100644
index 00000000..f92984cd
--- /dev/null
+++ b/movement/watch_faces/complication/activity_face.c
@@ -0,0 +1,725 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Gabor L Ugray
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* ** TODO
+ * ===================
+ * -- Additional power-saving optimizations
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "activity_face.h"
+#include "chirpy_tx.h"
+#include "watch.h"
+#include "watch_utility.h"
+
+// ===========================================================================
+// This part is configurable: you can edit values here to customize you activity face
+// In particular, with num_enabled_activities and enabled_activities you can choose a subset of the
+// activities that you want to see in your watch.
+// You can also add new items to activity_names, but don't redefine or remove existing ones.
+
+// If a logged activity is shorter than this, then it won't be added to log when it ends.
+// This way scarce log slots are not taken up by aborted events that weren't real activities.
+static const uint16_t activity_min_length_sec = 60;
+
+// Supported activities. ID of activity is index in this buffer
+// W e should never change order or redefine items, only add new items when needed.
+static const char activity_names[][7] = {
+ " bIKE ",
+ "uuaLK ",
+ " rUn ",
+ "DAnCE ",
+ " yOgA ",
+ "CrOSS ",
+ "Suuinn",
+ "ELLIP ",
+ " gYnn",
+ " rOuu",
+ "SOCCEr",
+ " FOOTb",
+ " bALL ",
+ " SKI ",
+};
+
+// Currently enabled activities. This makes picking on first subface easier: why show activities you personally never do.
+static const uint8_t enabled_activities[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
+
+// Number of currently enabled activities (size of enabled_activities).
+static const uint8_t num_enabled_activities = sizeof(enabled_activities) / sizeof(uint8_t);
+
+// End configurable section
+// ===========================================================================
+
+// One logged activity
+typedef struct __attribute__((__packed__)) {
+ // Activity's start time
+ watch_date_time start_time;
+
+ // Total duration of activity, including time spend in paus
+ uint16_t total_sec;
+
+ // Number of seconds the activity was paused
+ uint16_t pause_sec;
+
+ // Type of activity (index in activity_names)
+ uint8_t activity_type;
+
+} activity_item_t;
+
+#define MAX_ACTIVITY_SECONDS 28800 // 8 hours = 28800 sec
+
+// Size of (fixed) buffer to log activites. Takes up x9 bytes in SRAM if face is installed.
+#define ACTIVITY_LOG_SZ 99
+
+// Number of activities in buffer.
+static uint8_t activity_log_count = 0;
+
+// Buffer with all logged activities.
+static activity_item_t activity_log_buffer[ACTIVITY_LOG_SZ];
+
+#define CHIRPY_PREFIX_LEN 2
+// First two bytes chirped out, to identify transmission as from the activity face
+static const uint8_t activity_chirpy_prefix[CHIRPY_PREFIX_LEN] = {0x27, 0x00};
+
+// The face's different UI modes (views).
+typedef enum {
+ ACTM_CHOOSE = 0,
+ ACTM_LOGGING,
+ ACTM_PAUSED,
+ ACTM_DONE,
+ ACTM_LOGSIZE,
+ ACTM_CHIRP,
+ ACTM_CHIRPING,
+ ACTM_CLEAR,
+ ACTM_CLEAR_CONFIRM,
+ ACTM_CLEAR_DONE,
+} activity_mode_t;
+
+// The full state of the activity face
+typedef struct {
+ // Current mode (which secondary face, or ongoing operation like logging)
+ activity_mode_t mode;
+
+ // Index of currently selected activity in enabled_activities
+ uint8_t type_ix;
+
+ // Used for different things depending on mode
+ // In ACTM_DONE: countdown for animation, before returning to start face
+ // In ACTM_LOGGING and ACTM_PAUSED: drives blinking colon and alternating time display
+ // In ACTM_LOGSIZE, ACTM_CLEAR: enables timeout return to choose screen
+ uint16_t counter;
+
+ // Start of currently logged activity, if any
+ watch_date_time start_time;
+
+ // Total seconds elapsed since logging started
+ uint16_t curr_total_sec;
+
+ // Total paused seconds in current log
+ uint16_t curr_pause_sec;
+
+ // Helps us handle 1/64 ticks during transmission; including countdown timer
+ chirpy_tick_state_t chirpy_tick_state;
+
+ // Used by chirpy encoder during transmission
+ chirpy_encoder_state_t chirpy_encoder_state;
+
+ // 0: Running normally
+ // 1: In LE mode
+ // 2: Just woke up from LE mode. Will go to 0 after ignoring ALARM_BUTTON_UP.
+ uint8_t le_state;
+
+} activity_state_t;
+
+#define ACTIVITY_BUF_SZ 14
+
+// Temp buffer used for sprintf'ing content for the display.
+char activity_buf[ACTIVITY_BUF_SZ];
+
+// Needed by _activity_get_next_byte to keep track of where we are in transmission
+uint16_t *activity_seq_pos;
+
+static void _activity_clear_buffers() {
+ // Clear activity buffer; 0xcd is good for diagnostics
+ memset(activity_log_buffer, 0xcd, ACTIVITY_LOG_SZ * sizeof(activity_item_t));
+ // Clear display buffer
+ memset(activity_buf, 0, ACTIVITY_BUF_SZ);
+}
+
+static void _activity_display_choice(activity_state_t *state);
+static void _activity_update_logging_screen(movement_settings_t *settings, activity_state_t *state);
+static uint8_t _activity_get_next_byte(uint8_t *next_byte);
+
+void activity_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void **context_ptr) {
+ (void)settings;
+ (void)watch_face_index;
+ if (*context_ptr == NULL) {
+ *context_ptr = malloc(sizeof(activity_state_t));
+ memset(*context_ptr, 0, sizeof(activity_state_t));
+ // This happens only at boot
+ _activity_clear_buffers();
+ }
+ // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep.
+}
+
+void activity_face_activate(movement_settings_t *settings, void *context) {
+ (void)settings;
+ (void)context;
+
+ // Not using this function. Calling _activity_activate from the event handler.
+ // That is what we get both when the face is shown upon navigation by MODE,
+ // and when waking from low energy state.
+}
+
+// Called from the ACTIVATE event handler in the loop
+static void _activity_activate(movement_settings_t *settings, activity_state_t *state) {
+ // If waking from low-energy state and currently logging: update seconds values
+ // Those are not up-to-date because ticks have not been coming
+ if (state->le_state != 0 && state->mode == ACTM_LOGGING) {
+ state->le_state = 2;
+ watch_date_time now = watch_rtc_get_date_time();
+ uint32_t now_timestamp = watch_utility_date_time_to_unix_time(now, 0);
+ uint32_t start_timestamp = watch_utility_date_time_to_unix_time(state->start_time, 0);
+ uint32_t total_seconds = now_timestamp - start_timestamp;
+ state->curr_total_sec = total_seconds;
+ _activity_update_logging_screen(settings, state);
+ }
+ // Regular activation: start from defaults
+ else {
+ state->le_state = 0;
+ state->mode = 0;
+ state->type_ix = 0;
+ _activity_display_choice(state);
+ }
+}
+
+static void _activity_display_choice(activity_state_t *state) {
+ watch_display_string("AC", 0);
+ // If buffer is full: We say "FULL"
+ if (activity_log_count >= ACTIVITY_LOG_SZ) {
+ watch_display_string(" FULL ", 4);
+ }
+ // Otherwise, we show currently activity
+ else {
+ uint8_t activity_ix = enabled_activities[state->type_ix];
+ const char *name = activity_names[activity_ix];
+ watch_display_string((char *)name, 4);
+ }
+}
+
+const uint8_t activity_anim_pixels[][2] = {
+ {1, 4}, // TL
+ {0, 5}, // BL
+ {0, 6}, // BOT
+ {1, 6}, // BR
+ {2, 5}, // TR
+ {2, 4}, // TOP
+ // {2, 4}, // MID
+};
+
+static void _activity_update_logging_screen(movement_settings_t *settings, activity_state_t *state) {
+ watch_duration_t duration;
+
+ watch_display_string("AC ", 0);
+
+ // If we're in LE state: per-minute update is special
+ if (state->le_state == 1) {
+ watch_date_time now = watch_rtc_get_date_time();
+ uint32_t now_timestamp = watch_utility_date_time_to_unix_time(now, 0);
+ uint32_t start_timestamp = watch_utility_date_time_to_unix_time(state->start_time, 0);
+ uint32_t total_seconds = now_timestamp - start_timestamp;
+ duration = watch_utility_seconds_to_duration(total_seconds);
+ sprintf(activity_buf, " %d%02d ", duration.hours, duration.minutes);
+ watch_display_string(activity_buf, 4);
+ watch_set_colon();
+ watch_set_indicator(WATCH_INDICATOR_LAP);
+ watch_clear_indicator(WATCH_INDICATOR_PM);
+ watch_clear_indicator(WATCH_INDICATOR_24H);
+ return;
+ }
+
+ // Show elapsed time, or PAUSE
+ if ((state->counter % 5) < 3) {
+ watch_set_indicator(WATCH_INDICATOR_LAP);
+ watch_clear_indicator(WATCH_INDICATOR_PM);
+ watch_clear_indicator(WATCH_INDICATOR_24H);
+ if (state->mode == ACTM_PAUSED) {
+ watch_display_string(" PAUSE", 4);
+ watch_clear_colon();
+ } else {
+ duration = watch_utility_seconds_to_duration(state->curr_total_sec);
+ // Under 10 minutes: M:SS
+ if (state->curr_total_sec < 600) {
+ sprintf(activity_buf, " %01d%02d", duration.minutes, duration.seconds);
+ watch_display_string(activity_buf, 4);
+ watch_clear_colon();
+ }
+ // Under an hour: MM:SS
+ else if (state->curr_total_sec < 3600) {
+ sprintf(activity_buf, " %02d%02d", duration.minutes, duration.seconds);
+ watch_display_string(activity_buf, 4);
+ watch_clear_colon();
+ }
+ // Over an hour: H:MM:SS
+ // (We never go to two-digit hours; stop at 8)
+ else {
+ sprintf(activity_buf, " %d%02d%02d", duration.hours, duration.minutes, duration.seconds);
+ watch_display_string(activity_buf, 4);
+ watch_set_colon();
+ }
+ }
+ }
+ // Briefly, show time without seconds
+ else {
+ watch_clear_indicator(WATCH_INDICATOR_LAP);
+ watch_date_time now = watch_rtc_get_date_time();
+ uint8_t hour = now.unit.hour;
+ if (!settings->bit.clock_mode_24h) {
+ watch_clear_indicator(WATCH_INDICATOR_24H);
+ if (hour < 12)
+ watch_clear_indicator(WATCH_INDICATOR_PM);
+ else
+ watch_set_indicator(WATCH_INDICATOR_PM);
+ hour %= 12;
+ if (hour == 0) hour = 12;
+ }
+ else {
+ watch_set_indicator(WATCH_INDICATOR_24H);
+ watch_clear_indicator(WATCH_INDICATOR_PM);
+ }
+ sprintf(activity_buf, "%2d%02d ", hour, now.unit.minute);
+ watch_set_colon();
+ watch_display_string(activity_buf, 4);
+ }
+}
+
+static void _activity_quit_chirping() {
+ watch_clear_indicator(WATCH_INDICATOR_BELL);
+ watch_set_buzzer_off();
+ movement_request_tick_frequency(1);
+}
+
+static void _activity_chirp_tick_transmit(void *context) {
+ activity_state_t *state = (activity_state_t *)context;
+
+ uint8_t tone = chirpy_get_next_tone(&state->chirpy_encoder_state);
+ // Transmission over?
+ if (tone == 255) {
+ _activity_quit_chirping();
+ state->mode = ACTM_CHIRP;
+ state->counter = 0;
+ watch_display_string("AC CHIRP ", 0);
+ return;
+ }
+ uint16_t period = chirpy_get_tone_period(tone);
+ watch_set_buzzer_period(period);
+ watch_set_buzzer_on();
+}
+
+static void _activity_chirp_tick_countdown(void *context) {
+ activity_state_t *state = (activity_state_t *)context;
+
+ // Countdown over: start actual broadcast
+ if (state->chirpy_tick_state.seq_pos == 8 * 3) {
+ state->chirpy_tick_state.tick_compare = 3;
+ state->chirpy_tick_state.tick_count = 2; // tick_compare - 1, so it starts immediately
+ state->chirpy_tick_state.seq_pos = 0;
+ state->chirpy_tick_state.tick_fun = _activity_chirp_tick_transmit;
+ return;
+ }
+ // Sound or turn off buzzer
+ if ((state->chirpy_tick_state.seq_pos % 8) == 0) {
+ watch_set_buzzer_period(NotePeriods[BUZZER_NOTE_A5]);
+ watch_set_buzzer_on();
+ if (state->chirpy_tick_state.seq_pos == 0) {
+ watch_display_string(" --- ", 4);
+ } else if (state->chirpy_tick_state.seq_pos == 8) {
+ watch_display_string(" --", 5);
+ } else if (state->chirpy_tick_state.seq_pos == 16) {
+ watch_display_string(" -", 5);
+ }
+ } else if ((state->chirpy_tick_state.seq_pos % 8) == 1) {
+ watch_set_buzzer_off();
+ }
+ ++state->chirpy_tick_state.seq_pos;
+}
+
+static uint8_t _activity_get_next_byte(uint8_t *next_byte) {
+ uint16_t num_bytes = 2 + activity_log_count * sizeof(activity_item_t);
+ uint16_t pos = *activity_seq_pos;
+
+ // Init counter
+ if (pos == 0) {
+ sprintf(activity_buf, "%3d", activity_log_count);
+ watch_display_string(activity_buf, 5);
+ }
+
+ if (pos == num_bytes) {
+ return 0;
+ }
+ // Two-byte prefix
+ if (pos < 2) {
+ (*next_byte) = activity_chirpy_prefix[pos];
+ }
+ // Data
+ else {
+ pos -= 2;
+ uint16_t ix = pos / sizeof(activity_item_t);
+ const activity_item_t *itm = &activity_log_buffer[ix];
+ uint16_t ofs = pos % sizeof(activity_item_t);
+
+ // Update counter when starting new item
+ if (ofs == 0) {
+ sprintf(activity_buf, "%3d", activity_log_count - ix);
+ watch_display_string(activity_buf, 5);
+ }
+
+ // Do this the hard way, byte by byte, to avoid high/low endedness issues
+ // Higher order bytes first, is our serialization format
+ uint8_t val;
+ // watch_date_time start_time;
+ // uint16_t total_sec;
+ // uint16_t pause_sec;
+ // uint8_t activity_type;
+ if (ofs == 0)
+ val = (itm->start_time.reg & 0xff000000) >> 24;
+ else if (ofs == 1)
+ val = (itm->start_time.reg & 0x00ff0000) >> 16;
+ else if (ofs == 2)
+ val = (itm->start_time.reg & 0x0000ff00) >> 8;
+ else if (ofs == 3)
+ val = (itm->start_time.reg & 0x000000ff);
+ else if (ofs == 4)
+ val = (itm->total_sec & 0xff00) >> 8;
+ else if (ofs == 5)
+ val = (itm->total_sec & 0x00ff);
+ else if (ofs == 6)
+ val = (itm->pause_sec & 0xff00) >> 8;
+ else if (ofs == 7)
+ val = (itm->pause_sec & 0x00ff);
+ else
+ val = itm->activity_type;
+ (*next_byte) = val;
+ }
+ ++(*activity_seq_pos);
+ return 1;
+}
+
+static void _activity_finish_logging(activity_state_t *state) {
+ // Save this activity
+ // If shorter than minimum for log: don't save
+ // Sanity check about buffer length. This should never happen, but also we never want to overrun by error
+ if (state->curr_total_sec >= activity_min_length_sec && activity_log_count + 1 < ACTIVITY_LOG_SZ) {
+ activity_item_t *itm = &activity_log_buffer[activity_log_count];
+ itm->start_time = state->start_time;
+ itm->total_sec = state->curr_total_sec;
+ itm->pause_sec = state->curr_pause_sec;
+ itm->activity_type = state->type_ix;
+ ++activity_log_count;
+ }
+
+ // Go to DONE animation
+ // TODO: Not in LE mode
+ state->mode = ACTM_DONE;
+ watch_clear_indicator(WATCH_INDICATOR_LAP);
+ movement_request_tick_frequency(2);
+ state->counter = 6 * 1;
+ watch_clear_display();
+ watch_display_string("AC dONE ", 0);
+}
+
+static void _activity_handle_tick(movement_settings_t *settings, activity_state_t *state) {
+ // Display stopwatch-like duration while logging, alternating with time
+ if (state->mode == ACTM_LOGGING || state->mode == ACTM_PAUSED) {
+ ++state->counter;
+ ++state->curr_total_sec;
+ if (state->mode == ACTM_PAUSED)
+ ++state->curr_pause_sec;
+ // If we've reached max activity length: finish logging
+ if (state->curr_total_sec == MAX_ACTIVITY_SECONDS) {
+ _activity_finish_logging(state);
+ }
+ // Still logging: refresh display
+ else {
+ _activity_update_logging_screen(settings, state);
+ }
+ }
+ // Display countown animation, and exit face when down
+ else if (state->mode == ACTM_DONE) {
+ if (state->counter == 0) {
+ movement_move_to_face(0);
+ movement_request_tick_frequency(1);
+ }
+ else {
+ uint8_t cd = state->counter % 6;
+ watch_clear_pixel(activity_anim_pixels[cd][0], activity_anim_pixels[cd][1]);
+ --state->counter;
+ cd = state->counter % 6;
+ watch_set_pixel(activity_anim_pixels[cd][0], activity_anim_pixels[cd][1]);
+ }
+ }
+ // Log size, chirp, clear: return to choose after some time
+ else if (state->mode == ACTM_LOGSIZE || state->mode == ACTM_CHIRP || state->mode == ACTM_CLEAR) {
+ ++state->counter;
+ // Leave Log Size after 20 seconds
+ // Leave Clear after only 10: this is danger zone, we don't like hanging around here
+ // Leave Chirp after 2 minutes: most likely need to the time to fiddle with mic & Chirpy RX on the computer
+ uint16_t timeout = 20;
+ if (state->mode == ACTM_CLEAR) timeout = 10;
+ else if (state->mode == ACTM_CHIRP) timeout = 120;
+ if (state->counter > timeout) {
+ state->mode = ACTM_CHOOSE;
+ _activity_display_choice(state);
+ }
+ }
+ // Chirping
+ else if (state->mode == ACTM_CHIRPING) {
+ ++state->chirpy_tick_state.tick_count;
+ if (state->chirpy_tick_state.tick_count == state->chirpy_tick_state.tick_compare) {
+ state->chirpy_tick_state.tick_count = 0;
+ state->chirpy_tick_state.tick_fun(state);
+ }
+ }
+ // Clear confirm: blink CLEAR
+ else if (state->mode == ACTM_CLEAR_CONFIRM) {
+ ++state->counter;
+ if ((state->counter % 2) == 0)
+ watch_display_string("CLEAR ", 4);
+ else
+ watch_display_string(" ", 4);
+ if (state->counter > 12) {
+ state->mode = ACTM_CHOOSE;
+ _activity_display_choice(state);
+ movement_request_tick_frequency(1);
+ }
+ }
+ // Clear done: fill up zeroes, then return to choose screen
+ else if (state->mode == ACTM_CLEAR_DONE) {
+ ++state->counter;
+ // Animation done
+ if (state->counter == 7) {
+ state->mode = ACTM_CHOOSE;
+ _activity_display_choice(state);
+ movement_request_tick_frequency(1);
+ return;
+ }
+ // Display current state of animation
+ sprintf(activity_buf, " ");
+ uint8_t nZeros = state->counter + 1;
+ if (nZeros > 6) nZeros = 6;
+ for (uint8_t i = 0; i < nZeros; ++i) {
+ activity_buf[i] = '0';
+ }
+ watch_display_string(activity_buf, 4);
+ }
+}
+
+static void _activity_alarm_long(movement_settings_t *settings, activity_state_t *state) {
+ // On choose face: start logging activity
+ if (state->mode == ACTM_CHOOSE) {
+ // If buffer is full: Ignore this long press
+ if (activity_log_count >= ACTIVITY_LOG_SZ)
+ return;
+ // OK, we go ahead and start logging
+ state->start_time = watch_rtc_get_date_time();
+ state->curr_total_sec = 0;
+ state->curr_pause_sec = 0;
+ state->counter = -1;
+ state->mode = ACTM_LOGGING;
+ watch_set_indicator(WATCH_INDICATOR_LAP);
+ _activity_update_logging_screen(settings, state);
+ }
+ // If logging or paused: end logging
+ else if (state->mode == ACTM_LOGGING || state->mode == ACTM_PAUSED) {
+ _activity_finish_logging(state);
+ }
+ // If chirp: kick off chirping
+ else if (state->mode == ACTM_CHIRP) {
+ // Set up our tick handling for countdown beeps
+ activity_seq_pos = &state->chirpy_tick_state.seq_pos;
+ state->chirpy_tick_state.tick_compare = 8;
+ state->chirpy_tick_state.tick_count = 7; // tick_compare - 1, so it starts immediately
+ state->chirpy_tick_state.seq_pos = 0;
+ state->chirpy_tick_state.tick_fun = _activity_chirp_tick_countdown;
+ // Set up chirpy encoder
+ chirpy_init_encoder(&state->chirpy_encoder_state, _activity_get_next_byte);
+ // Show bell; switch to 64/sec ticks
+ watch_set_indicator(WATCH_INDICATOR_BELL);
+ movement_request_tick_frequency(64);
+ state->mode = ACTM_CHIRPING;
+ }
+ // If clear: confirm (unless empty)
+ else if (state->mode == ACTM_CLEAR) {
+ if (activity_log_count == 0)
+ return;
+ state->mode = ACTM_CLEAR_CONFIRM;
+ state->counter = -1;
+ movement_request_tick_frequency(4);
+ }
+ // If clear confirm: do clear.
+ else if (state->mode == ACTM_CLEAR_CONFIRM) {
+ _activity_clear_buffers();
+ activity_log_count = 0;
+ state->mode = ACTM_CLEAR_DONE;
+ state->counter = -1;
+ watch_display_string("0 ", 4);
+ movement_request_tick_frequency(2);
+ }
+}
+
+static void _activity_alarm_short(movement_settings_t *settings, activity_state_t *state) {
+ // In the choose face, short ALARM cycles through activities
+ if (state->mode == ACTM_CHOOSE) {
+ state->type_ix = (state->type_ix + 1) % num_enabled_activities;
+ _activity_display_choice(state);
+ }
+ // If logging: pause
+ else if (state->mode == ACTM_LOGGING) {
+ state->mode = ACTM_PAUSED;
+ state->counter = 0;
+ _activity_update_logging_screen(settings, state);
+ }
+ // If paused: Update paused seconds count and return to logging
+ else if (state->mode == ACTM_PAUSED) {
+ state->mode = ACTM_LOGGING;
+ state->counter = 0;
+ _activity_update_logging_screen(settings, state);
+ }
+ // If chirping: stoppit
+ else if (state->mode == ACTM_CHIRPING) {
+ _activity_quit_chirping();
+ state->mode = ACTM_CHIRP;
+ state->counter = 0;
+ watch_display_string("AC CHIRP ", 0);
+ }
+}
+
+static void _activity_light_short(activity_state_t *state) {
+ // If choose face: move to log size
+ if (state->mode == ACTM_CHOOSE) {
+ state->mode = ACTM_LOGSIZE;
+ state->counter = 0;
+ sprintf(activity_buf, "AC L#g%3d", activity_log_count);
+ watch_display_string(activity_buf, 0);
+ }
+ // If log size face: move to chirp
+ else if (state->mode == ACTM_LOGSIZE) {
+ state->mode = ACTM_CHIRP;
+ state->counter = 0;
+ watch_display_string("AC CHIRP ", 0);
+ }
+ // If chirp face: move to clear
+ else if (state->mode == ACTM_CHIRP) {
+ state->mode = ACTM_CLEAR;
+ state->counter = 0;
+ watch_display_string("AC CLEAR ", 0);
+ }
+ // If clear face: return to choose face
+ else if (state->mode == ACTM_CLEAR || state->mode == ACTM_CLEAR_CONFIRM) {
+ state->mode = ACTM_CHOOSE;
+ _activity_display_choice(state);
+ movement_request_tick_frequency(1);
+ }
+ // While logging or paused, light is light
+ else if (state->mode == ACTM_LOGGING || state->mode == ACTM_PAUSED) {
+ movement_illuminate_led();
+ }
+ // Otherwise, we don't do light.
+}
+
+bool activity_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
+ activity_state_t *state = (activity_state_t *)context;
+
+ switch (event.event_type) {
+ case EVENT_ACTIVATE:
+ _activity_activate(settings, state);
+ break;
+ case EVENT_TICK:
+ _activity_handle_tick(settings, state);
+ break;
+ case EVENT_MODE_BUTTON_UP:
+ if (state->mode != ACTM_LOGGING && state->mode != ACTM_PAUSED && state->mode != ACTM_CHIRPING) {
+ movement_request_tick_frequency(1);
+ movement_move_to_next_face();
+ }
+ break;
+ case EVENT_LIGHT_BUTTON_UP:
+ _activity_light_short(state);
+ break;
+ case EVENT_ALARM_BUTTON_UP:
+ // We also receive ALARM press that woke us up from LE state
+ // Don't want to act on that as if it were a real button press for us
+ if (state->le_state != 2)
+ _activity_alarm_short(settings, state);
+ else
+ state->le_state = 0;
+ break;
+ case EVENT_ALARM_LONG_PRESS:
+ _activity_alarm_long(settings, state);
+ break;
+ case EVENT_TIMEOUT:
+ if (state->mode != ACTM_LOGGING && state->mode != ACTM_PAUSED &&
+ state->mode != ACTM_CHIRP && state->mode != ACTM_CHIRPING) {
+ movement_request_tick_frequency(1);
+ movement_move_to_face(0);
+ }
+ break;
+ case EVENT_LOW_ENERGY_UPDATE:
+ state->le_state = 1;
+ // If we're in paused logging mode: let's lose this activity. Pause is not meant for over an hour.
+ if (state->mode == ACTM_PAUSED) {
+ // When waking, face will revert to default screen
+ state->mode = ACTM_CHOOSE;
+ watch_display_string("AC SLEEP ", 0);
+ watch_clear_colon();
+ watch_clear_indicator(WATCH_INDICATOR_LAP);
+ watch_clear_indicator(WATCH_INDICATOR_PM);
+ }
+ else {
+ _activity_update_logging_screen(settings, state);
+ watch_start_tick_animation(500);
+ }
+ break;
+ default:
+ movement_default_loop_handler(event, settings);
+ break;
+ }
+
+ // Return true if the watch can enter standby mode. False needed when chirping.
+ if (state->mode == ACTM_CHIRPING)
+ return false;
+ else
+ return true;
+}
+
+void activity_face_resign(movement_settings_t *settings, void *context) {
+ (void)settings;
+ (void)context;
+
+ // Face should only ever temporarily request a higher frequency, so by the time we're resigning,
+ // this should not be needed. But we don't want an error to create a situation that drains the battery.
+ // Rather do this defensively here.
+ movement_request_tick_frequency(1);
+}
diff --git a/movement/watch_faces/complication/activity_face.h b/movement/watch_faces/complication/activity_face.h
new file mode 100644
index 00000000..c72f7099
--- /dev/null
+++ b/movement/watch_faces/complication/activity_face.h
@@ -0,0 +1,89 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Gabor L Ugray
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef ACTIVITY_FACE_H_
+#define ACTIVITY_FACE_H_
+
+#include "movement.h"
+
+/*
+ * ACTIVITY WATCH FACE
+ *
+ * The Activity face lets you record activities like you would do with a fitness watch.
+ * It supports different activities like running, biking, rowing etc., and for each recorded activity
+ * it stores when it started and how long it was.
+ *
+ * You can save up to 99 activities this way. Every once in a while you can chirp them out
+ * using the watch's piezo buzzer as a modem, then clear the log in the watch.
+ * To record and decode a chirpy transmission on your computer, you can use the web app here:
+ * https://jealousmarkup.xyz/off/chirpy/rx/
+ *
+ * Using the face
+ *
+ * When you activate the face, it starts with the first screen to select the activity you want to log.
+ * ALARM cycles through the list of activities.
+ * LONG ALARM starts logging.
+ * While logging is in progress, the face alternates between the elapsed time and the current time.
+ * You can press ALARM to pause (e.g., while you hop in to the baker's for a croissant during your jog).
+ * Pressing ALARM again resumes the activity.
+ * LONG ALARM stops logging and saves the activity.
+ *
+ * When you're not loggin, you can press LIGHT to access the secondary faces.
+ * LIGHT #1 => Shows the size of the log (how many activities have been recorded).
+ * LIGHT #2 => The screen to chirp out the data. Press LONG ALARM to start chirping.
+ * LIGHT #3 => The screen to clear the log in the watch. Press LONG ALARM twice to clear data.
+ *
+ * Quirky details
+ *
+ * The face will discard short activities (less than a minute) when you press LONG ALARM to finish logging.
+ * These were probably logged by mistake, and it's better to save slots and chirping battery power for
+ * stuff that really matters.
+ *
+ * The face will continue to record an activity past the normal one-hour mark, when the watch
+ * enters low energy mode. However, it will always stop at 8 hours. If an activity takes that long,
+ * you probably just forgot to stop logging.
+ *
+ * The log is stored in regular memory. It will be lost when you remove the battery, so make
+ * sure you chirp it out before taking the watch apart.
+ *
+ * See the top of activity_face.c for some customization options. What you most likely want to do
+ * is reduce the list of activities shown on the first screen to the ones you are regularly doing.
+ *
+ */
+
+void activity_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
+void activity_face_activate(movement_settings_t *settings, void *context);
+bool activity_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
+void activity_face_resign(movement_settings_t *settings, void *context);
+
+#define activity_face ((const watch_face_t){ \
+ activity_face_setup, \
+ activity_face_activate, \
+ activity_face_loop, \
+ activity_face_resign, \
+ NULL, \
+})
+
+#endif // ACTIVITY_FACE_H_
+
diff --git a/movement/watch_faces/complication/day_one_face.c b/movement/watch_faces/complication/day_one_face.c
index 7ce43bfa..25ce1c23 100644
--- a/movement/watch_faces/complication/day_one_face.c
+++ b/movement/watch_faces/complication/day_one_face.c
@@ -33,7 +33,7 @@ static uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16
}
static void _day_one_face_update(day_one_state_t state) {
- char buf[14];
+ char buf[15];
watch_date_time date_time = watch_rtc_get_date_time();
uint32_t julian_date = _day_one_face_juliandaynum(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day);
uint32_t julian_birthdate = _day_one_face_juliandaynum(state.birth_year, state.birth_month, state.birth_day);
diff --git a/movement/watch_faces/complication/discgolf_face.c b/movement/watch_faces/complication/discgolf_face.c
new file mode 100644
index 00000000..0852bf1f
--- /dev/null
+++ b/movement/watch_faces/complication/discgolf_face.c
@@ -0,0 +1,326 @@
+#include <stdlib.h>
+#include <string.h>
+#include "discgolf_face.h"
+#include "watch.h" // Remember to change number of courses in this file
+#include "watch_utility.h"
+
+/*
+ * Keep track of scores in discgolf or golf!
+ * The watch face operates in three different modes:
+ *
+ * - dg_setting: Select a course
+ * Enter this mode by holding down the light button. The screen will display
+ * the label for the hole and the lowest score since last boot.
+ * Press alarm to loop through the holes. Press the light button to make a
+ * selection. This will reset all scores and start a new game in dg_idle mode.
+ *
+ * -dg_idle: We're playing a hole
+ * This either shows your current score relative to par, or the score for a
+ * particular hole.
+ * At the start of a game, press alarm to loop through the holes and leave it
+ * your starting hole. For optimal experience, play the course linearly after that
+ * If you're viewing the hole you're supposed to be playing, the watch face will
+ * display your score relative to par.
+ * Use the alarm button to view other holes than the one you're playing, in which
+ * case the input score for that hole will be displayed, in case it needs changing.
+ * Long press the alarm button to snap back to currently playing hole.
+ * To input scores for a hole in this mode, press the light button.
+ *
+ * -dg_scoring: Input score for a hole
+ * In this mode, if the score is 0 (hasn't been entered during this round),
+ * it will blink, indicating we're in scoring mode. Press the alarm button
+ * to increment the score up until 15, in which case it loops back to 0.
+ * Press the light button to save the score for that hole, advance one hole
+ * if you're not editing an already input score, and returning to idle mode.
+ *
+ * When all scores have been entered, the LAP indicator turns on. At that point, if we enter
+ * dg_setting to select a course, the score for that round is evaluated against the current
+ * lowest score for that course, and saved if it is better.
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////
+// Enter course data
+/* Initialize lowest scores with a high number */
+int8_t best[courses];
+
+static const uint8_t pars[][18] = {
+ { 3, 3, 4, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, // Grafarholt
+ { 3, 4, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3 }, // Gufunes
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Vífilsstaðir
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Dalvegur
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Laugardalur
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Guðmundarlundur
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Víðistaðatún
+ { 3, 3, 3, 4, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Fossvogur
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // KlambratĂşn
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Seljahverfi
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Fella- og HĂłla
+};
+static const uint8_t holes[] = { // Number of holes on each course
+ 18,
+ 18,
+ 10,
+ 10,
+ 10,
+ 10,
+ 9,
+ 9,
+ 9,
+ 9,
+ 9
+};
+/* Two-letter descriptive labels, second field can only be A, B, C, D, E, F, H, I, J, L, N, O, R, T, U and X. */
+static const char labels[][2] = {
+ { 'G', 'H' },
+ { 'G', 'N' },
+ { 'V', 'I' },
+ { 'D', 'V' },
+ { 'L', 'A' },
+ { 'G', 'L' },
+ { 'V', 'T' },
+ { 'F', 'V' },
+ { 'K', 'T' },
+ { 'S', 'E' },
+ { 'F', 'H' }
+};
+
+// End of course data
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/* Beep function */
+static inline void beep(movement_settings_t *settings) {
+ if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_C7, 50);
+}
+
+/* Prep for a new round */
+static inline void reset(discgolf_state_t *state) {
+ for (int i = 0; i < holes[state->course]; i++) {
+ state->scores[i] = 0;
+ }
+ state->hole = 1;
+ watch_clear_indicator(WATCH_INDICATOR_LAP);
+ return;
+}
+
+/* Total number of throws so far */
+static inline uint8_t score_sum(discgolf_state_t *state) {
+ uint8_t sum = 0;
+ for (int i = 0; i < holes[state->course]; i++) {
+ sum = sum + state->scores[i];
+ }
+ return sum;
+}
+
+/* Count how many holes have been played */
+static inline uint8_t count_played(discgolf_state_t *state) {
+ uint8_t holes_played = 0;
+ for (int i = 0; i < holes[state->course]; i++) {
+ if (state->scores[i] > 0) holes_played++;
+ }
+ return holes_played;
+}
+
+
+/* Calculate the current score relative to par */
+static inline int8_t calculate_score(discgolf_state_t *state) {
+ uint8_t par_sum = 0;
+ uint8_t score_sum = 0;
+
+ for (int i = 0; i < holes[state->course]; i++) {
+ if (state->scores[i] > 0) {
+ par_sum = par_sum + pars[state->course][i];
+ score_sum = score_sum + state->scores[i];
+ }
+ }
+ return score_sum - par_sum;
+}
+
+/* Store score if it's the best so far */
+static inline void store_best(discgolf_state_t *state) {
+ uint8_t played = count_played(state);
+ if ( played == holes[state->course] ) {
+ int8_t high_score = calculate_score(state);
+ if (high_score < best[state->course] ) {
+ best[state->course] = high_score;
+ }
+ }
+}
+
+/* Configuration at boot, the high score array can be initialized with your high scores if they're known */
+void discgolf_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
+ (void) settings;
+ (void) watch_face_index;
+
+ if (*context_ptr == NULL) {
+ *context_ptr = malloc(sizeof(discgolf_state_t));
+ discgolf_state_t *state = (discgolf_state_t *)*context_ptr;
+ memset(*context_ptr, 0, sizeof(discgolf_state_t));
+ state->hole = 1;
+ state->course = 0;
+ state->playing = holes[state->course] + 1;
+ for (int i = 0; i < courses; i++) best[i] = 99;
+ state->mode = dg_setting;
+ }
+}
+
+void discgolf_face_activate(movement_settings_t *settings, void *context) {
+ (void) settings;
+ watch_clear_colon();
+ discgolf_state_t *state = (discgolf_state_t *)context;
+
+ /* If we were playing, go to current hole */
+ if (state->playing <= holes[0]) {
+ state->hole = state->playing;
+ }
+ /* Set LAP if round finished */
+ if (count_played(state) == holes[state->course] ) {
+ watch_set_indicator(WATCH_INDICATOR_LAP);
+ }
+ movement_request_tick_frequency(4);
+}
+
+bool discgolf_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
+ (void) settings;
+
+ discgolf_state_t *state = (discgolf_state_t *)context;
+
+ switch (event.event_type) {
+ case EVENT_TIMEOUT:
+ /* Snap to first screen if we're not playing*/
+ if ( count_played(state) == holes[state->course] || state->mode == dg_setting) {
+ movement_move_to_face(0);
+ }
+ /* Cancel scoring if timed out */
+ if (state->mode == dg_scoring) {
+ state->scores[state->hole] = 0;
+ state->mode = dg_idle;
+ }
+ break;
+ /* Advance if not scoring */
+ case EVENT_MODE_BUTTON_UP:
+ if ( state->mode != dg_scoring ) {
+ movement_move_to_next_face();
+ }
+ break;
+ /* Go to default face if not scoring */
+ case EVENT_MODE_LONG_PRESS:
+ if ( state->mode != dg_scoring ) {
+ movement_move_to_face(0);
+ }
+ break;
+ case EVENT_LIGHT_BUTTON_UP:
+ switch ( state->mode ) {
+ case dg_idle:
+ /* Check if selected hole is the first one */
+ if ( score_sum(state) == 0 ) {
+ state->playing = state->hole;
+ }
+ /* Enter scoring mode */
+ state->mode = dg_scoring;
+ break;
+ case dg_scoring:
+ /* Set the LAP indicator if all scores are entered */
+ if (count_played(state) == holes[state->course] ) {
+ watch_set_indicator(WATCH_INDICATOR_LAP);
+ }
+ /* Advance to next hole if not editing previously set score */
+ if ( state->hole == state->playing ) {
+ if (state->hole < holes[state->course]) state->hole++;
+ else state->hole = 1;
+ if (state->playing < holes[state->course]) state->playing++;
+ else state->playing = 1;
+ }
+ /* Return to idle */
+ state->mode = dg_idle;
+ break;
+ case dg_setting:
+ /* Return to idle */
+ state->playing = holes[state->course] + 1;
+ state->mode = dg_idle;
+ break;
+ }
+ beep(settings);
+ break;
+ case EVENT_ALARM_BUTTON_UP:
+ switch (state->mode) {
+ /* Setting, loop through courses */
+ case dg_setting:
+ state->course = (state->course + 1) % courses;
+ break;
+ /* Scoring, increment score for current hole */
+ case dg_scoring:
+ state->scores[state->hole - 1] = (state->scores[state->hole - 1] + 1) % 16; // Loop around at 15
+ break;
+ /* Idle, loop through holes */
+ case dg_idle:
+ if (state->hole < holes[state->course]) {
+ state->hole++;
+ } else { state->hole = 1; }
+ break;
+ }
+ break;
+ case EVENT_LIGHT_LONG_PRESS:
+ /* Enter setting mode, reset state */
+ if ( state->mode == dg_idle ) {
+ state->mode = dg_setting;
+ store_best(state);
+ reset(state);
+ beep(settings);
+ }
+ break;
+ case EVENT_ALARM_LONG_PRESS:
+ /* Snap back to currently playing hole if we've established one*/
+ if ( (state->mode == dg_idle) && (state->hole != state->playing) && (state->playing <= holes[state->course]) ) {
+ state->hole = state->playing;
+ beep(settings);
+ }
+ break;
+ default:
+ break;
+ }
+
+ char buf[21];
+ char prefix;
+ int8_t diff;
+
+ switch (state->mode) {
+ /* Setting mode, display course label and high score */
+ case dg_setting:
+ if ( best[state->course] < 0 ) {
+ prefix = '-';
+ } else { prefix = ' '; }
+ sprintf(buf, "%c%c %c%2d ", labels[state->course][0], labels[state->course][1], prefix, abs(best[state->course]));
+ break;
+ /* Idle, show relative or input score */
+ case dg_idle:
+ if (state->hole == state->playing) {
+ diff = calculate_score(state);
+ if ( diff < 0 ) {
+ prefix = '-';
+ } else { prefix = ' '; }
+ sprintf(buf, "%c%c%2d %c%2d ", labels[state->course][0], labels[state->course][1], state->hole, prefix, abs(diff));
+ } else {
+ sprintf(buf, "%c%c%2d %2d ", labels[state->course][0], labels[state->course][1], state->hole, state->scores[state->hole - 1]);
+ }
+ break;
+ /* Scoring, show set score */
+ case dg_scoring:
+ sprintf(buf, "%c%c%2d %2d ", labels[state->course][0], labels[state->course][1], state->hole, state->scores[state->hole - 1]);
+ break;
+ }
+
+ /* Blink during scoring */
+ if (event.subsecond % 2 && state->mode == dg_scoring) {
+ buf[6] = buf[7] = ' ';
+ }
+
+ /* Draw screen */
+ watch_display_string(buf, 0);
+
+ return true;
+}
+
+void discgolf_face_resign(movement_settings_t *settings, void *context) {
+ (void) settings;
+ (void) context;
+ watch_clear_indicator(WATCH_INDICATOR_LAP);
+}
diff --git a/movement/watch_faces/complication/discgolf_face.h b/movement/watch_faces/complication/discgolf_face.h
new file mode 100644
index 00000000..5e8068e0
--- /dev/null
+++ b/movement/watch_faces/complication/discgolf_face.h
@@ -0,0 +1,95 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Ăžorsteinn JĂłn Gautason
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Keep track of scores in discgolf or golf!
+ * The watch face operates in three different modes:
+ *
+ * - dg_setting: Select a course
+ * Enter this mode by holding down the light button. The screen will display
+ * the label for the hole and the lowest score since last boot.
+ * Press alarm to loop through the holes. Press the light button to make a
+ * selection. This will reset all scores and start a new game in dg_idle mode.
+ *
+ * -dg_idle: We're playing a hole
+ * This either shows your current score relative to par, or the score for a
+ * particular hole.
+ * At the start of a game, press alarm to loop through the holes and leave it
+ * your starting hole. For optimal experience, play the course linearly after that
+ * If you're viewing the hole you're supposed to be playing, the watch face will
+ * display your score relative to par.
+ * Use the alarm button to view other holes than the one you're playing, in which
+ * case the input score for that hole will be displayed, in case it needs changing.
+ * Long press the alarm button to snap back to currently playing hole.
+ * To input scores for a hole in this mode, press the light button.
+ *
+ * -dg_scoring: Input score for a hole
+ * In this mode, if the score is 0 (hasn't been entered during this round),
+ * it will blink, indicating we're in scoring mode. Press the alarm button
+ * to increment the score up until 15, in which case it loops back to 0.
+ * Press the light button to save the score for that hole, advance one hole
+ * if you're not editing an already input score, and returning to idle mode.
+ *
+ * When all scores have been entered, the LAP indicator turns on. At that point, if we enter
+ * dg_setting to select a course, the score for that round is evaluated against the current
+ * lowest score for that course, and saved if it is better.
+*/
+
+
+#ifndef DISCGOLF_FACE_H_
+#define DISCGOLF_FACE_H_
+
+#include "movement.h"
+#define courses 11
+
+typedef enum {
+ dg_setting, // We are selecting a course
+ dg_scoring, // We are inputting our score
+ dg_idle, // We have input our score and are playing a hole
+} discgolf_mode_t;
+
+typedef struct {
+ uint8_t course; // Index for course selection, from 0
+ uint8_t hole; // Index for current hole, from 1
+ uint8_t playing; // Current hole
+ int scores[18]; // Scores for each played hole
+ discgolf_mode_t mode; // Watch face mode
+} discgolf_state_t;
+
+void discgolf_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
+void discgolf_face_activate(movement_settings_t *settings, void *context);
+bool discgolf_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
+void discgolf_face_resign(movement_settings_t *settings, void *context);
+
+#define discgolf_face ((const watch_face_t){ \
+ discgolf_face_setup, \
+ discgolf_face_activate, \
+ discgolf_face_loop, \
+ discgolf_face_resign, \
+ NULL, \
+})
+
+#endif // DISCGOLF_FACE_H_
diff --git a/movement/watch_faces/complication/interval_face.c b/movement/watch_faces/complication/interval_face.c
index e8ebe321..dabc6b1e 100644
--- a/movement/watch_faces/complication/interval_face.c
+++ b/movement/watch_faces/complication/interval_face.c
@@ -129,15 +129,15 @@ static const int8_t _sound_seq_break[] = {BUZZER_NOTE_B6, 15, BUZZER_NOTE_REST,
static const int8_t _sound_seq_cooldown[] = {BUZZER_NOTE_C7, 15, BUZZER_NOTE_REST, 1, -2, 1, BUZZER_NOTE_C7, 24, 0};
static const int8_t _sound_seq_finish[] = {BUZZER_NOTE_C7, 6, BUZZER_NOTE_E7, 6, BUZZER_NOTE_G7, 6, BUZZER_NOTE_C8, 18, 0};
-interval_setting_idx_t _setting_idx;
-int8_t _ticks;
-bool _erase_timer_flag;
-uint32_t _target_ts;
-uint32_t _now_ts;
-uint32_t _paused_ts;
-uint8_t _timer_work_round;
-uint8_t _timer_full_round;
-uint8_t _timer_run_state;
+static interval_setting_idx_t _setting_idx;
+static int8_t _ticks;
+static bool _erase_timer_flag;
+static uint32_t _target_ts;
+static uint32_t _now_ts;
+static uint32_t _paused_ts;
+static uint8_t _timer_work_round;
+static uint8_t _timer_full_round;
+static uint8_t _timer_run_state;
static inline void _inc_uint8(uint8_t *value, uint8_t step, uint8_t max) {
*value += step;
diff --git a/movement/watch_faces/complication/invaders_face.c b/movement/watch_faces/complication/invaders_face.c
new file mode 100644
index 00000000..c3b13c68
--- /dev/null
+++ b/movement/watch_faces/complication/invaders_face.c
@@ -0,0 +1,434 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Andreas Nebinger
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+// Emulator only: need time() to seed the random number generator
+#if __EMSCRIPTEN__
+#include <time.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "watch_private_display.h"
+#include "invaders_face.h"
+
+#define INVADERS_FACE_WAVES_PER_STAGE 9 // number of waves per stage (there are two stages)
+#define INVADERS_FACE_WAVE_INVADERS 16 // number of invaders attacking per wave
+
+static const uint8_t _defense_lines_segdata[3][2] = {{2, 12}, {2, 11}, {0, 11}};
+static const uint8_t _bonus_points_segdata[4][2] = {{2, 7}, {2, 8}, {2, 9}, {0, 10}};
+static const uint8_t _bonus_points_helper[] = {1, 5, 9, 11, 15, 19, 21, 25, 29};
+
+static const int8_t _sound_seq_game_start[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 1, BUZZER_NOTE_REST, 10, BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 1, 0};
+static const int8_t _sound_seq_shot_hit[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 2, 0};
+static const int8_t _sound_seq_shot_miss[] = {BUZZER_NOTE_A7, 1, 0};
+static const int8_t _sound_seq_ufo_hit[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 2, -2, 1, 0};
+static const int8_t _sound_seq_def_gone[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 3, BUZZER_NOTE_REST, 40, BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 4, 0};
+static const int8_t _sound_seq_next_wave[] = {BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, BUZZER_NOTE_REST, 8, BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, -2, 1,
+ BUZZER_NOTE_REST, 32,
+ BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, BUZZER_NOTE_REST, 8, BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, -2, 1, 0};
+static const int8_t _sound_seq_game_over[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 11, 0};
+
+typedef enum {
+ invaders_state_activated,
+ invaders_state_pre_game,
+ invaders_state_playing,
+ invaders_state_in_wave_break,
+ invaders_state_pre_next_wave,
+ invaders_state_next_wave,
+ invaders_state_game_over
+} invaders_current_state_t;
+
+typedef struct {
+ bool ufo_next : 1; // indicates whether next invader is a ufo
+ bool inv_checking : 1; // flag to indicate whether we are currently moving invaders (to prevent race conditions)
+ bool suspend_buttons : 1; // used while playing the game over sequence to prevent involuntary immediate restarts
+} invaders_signals_t;
+
+static int8_t _invaders[6]; // array of current invaders values (-1 = empty, 10 = ufo)
+static uint8_t _wave_invaders[INVADERS_FACE_WAVE_INVADERS]; // all invaders for the current wave. (Predefined to save cpu cycles when playing.)
+static invaders_current_state_t _current_state;
+static uint8_t _defense_lines; // number of defense lines which have been broken in the current wave
+static uint8_t _aim; // current "aim" digit
+static uint8_t _invader_idx; // index of next invader attacking in current wave (0 to 15)
+static uint8_t _wave_position; // current position of first invader. When > 6 the defense is broken
+static uint8_t _wave_tick_freq; // number of ticks passing until the next invader is inserted
+static uint8_t _ticks; // counts the ticks
+static uint8_t _bonus_countdown; // ticks countdown until the bonus point indicator is cleared
+static uint8_t _waves; // counts the waves (_wave_tick_freq decreases slowly depending on _wave value)
+static uint8_t _shots_in_wave; // number of shots in current wave. If 30 is reached, the game is over
+static uint8_t _invaders_shot; // number of sucessfully shot invaders in current wave
+static uint8_t _invaders_shot_sum; // current sum of invader digits shot (needed to determine if a ufo is coming)
+static invaders_signals_t _signals; // holds severals flags
+static uint16_t _score; // score of the current game
+
+/// @brief return a random number. 0 <= return_value < num_values
+static inline uint8_t _get_rand_num(uint8_t num_values) {
+#if __EMSCRIPTEN__
+ return rand() % num_values;
+#else
+ return arc4random_uniform(num_values);
+#endif
+}
+
+/// @brief callback function to re-enable light and alarm buttons after playing a sound sequence
+static inline void _resume_buttons() {
+ _signals.suspend_buttons = false;
+}
+
+/// @brief play a sound sequence if the game is in beepy mode
+static inline void _play_sequence(invaders_state_t *state, int8_t *sequence) {
+ if (state->sound_on) watch_buzzer_play_sequence((int8_t *)sequence, NULL);
+}
+
+/// @brief draw the remaining defense lines
+static void _display_defense_lines() {
+ watch_display_character(' ', 1);
+ for (uint8_t i = 0; i < 3 - _defense_lines; i++) watch_set_pixel(_defense_lines_segdata[i][0], _defense_lines_segdata[i][1]);
+}
+
+/** @brief draw label followed by the given score value
+ * @param label string displayed in the upper left corner
+ * @param score score to display
+ */
+static void _display_score(char *label, uint16_t score) {
+ watch_display_character(label[0], 0);
+ watch_display_character(label[1], 1);
+ char buf[10];
+ sprintf(buf, " %06d", (score * 10));
+ watch_display_string(buf, 2);
+}
+
+/// @brief draw an invader at the given position
+static inline void _display_invader(int8_t invader, uint8_t position) {
+ switch (invader) {
+ case 10:
+ watch_display_character('n', position);
+ break;
+ case -1:
+ watch_display_character(' ', position);
+ break;
+ default:
+ watch_display_character(invader + 48, position);
+ break;
+ }
+}
+
+/// @brief game over: show score and set state
+static void _game_over(invaders_state_t *state) {
+ _display_score("GO", _score);
+ _current_state = invaders_state_game_over;
+ movement_request_tick_frequency(1);
+ _signals.suspend_buttons = true;
+ if (state->sound_on) watch_buzzer_play_sequence((int8_t *)_sound_seq_game_over, _resume_buttons);
+ // save current score to highscore, if applicable
+ if (_score > state->highscore) state->highscore = _score;
+}
+
+/// @brief initialize the current wave
+static void _init_wave() {
+ uint8_t i;
+ if (_current_state == invaders_state_in_wave_break) {
+ _invader_idx = _invaders_shot;
+ } else {
+ _invader_idx = _invaders_shot = _invaders_shot_sum = _defense_lines = _shots_in_wave = 0;
+ }
+ // pre-fill invaders
+ for (i = _invader_idx; i < INVADERS_FACE_WAVE_INVADERS; i++) _wave_invaders[i] = _get_rand_num(10);
+ // init invaders field
+ for (i = 1; i < 6; i++) _invaders[i] = -1;
+ _invaders[0] = _wave_invaders[_invader_idx];
+ _wave_position = _aim = _bonus_countdown = 0;
+ _signals.ufo_next = _signals.inv_checking = _signals.suspend_buttons = false;
+ _current_state = invaders_state_playing;
+ // determine wave speed
+ _wave_tick_freq = 6 - ((_waves % INVADERS_FACE_WAVES_PER_STAGE) + 1) / 2;
+ if (_waves >= INVADERS_FACE_WAVES_PER_STAGE) _wave_tick_freq--;
+ // clear display
+ watch_display_string(" ", 2);
+ watch_display_character('0', 0);
+ _display_defense_lines();
+ // draw first invader
+ watch_display_character(_wave_invaders[_invader_idx] + 48, 9);
+}
+
+/** @brief move invaders and add a new one, if necessary
+ * @returns true, if invaders have reached position 6, false otherwise
+ */
+static bool _move_invaders() {
+ if (_wave_position == 5) return true;
+ _signals.inv_checking = true;
+ if (_invaders[_wave_position] >= 0) _wave_position++;
+ int8_t i;
+ // move invaders
+ for (i = _wave_position; i > 0; i--) _invaders[i] = _invaders[i - 1];
+ if (_invader_idx < INVADERS_FACE_WAVE_INVADERS - 1) {
+ // add invader
+ _invader_idx++;
+ if (_signals.ufo_next) {
+ _invaders[0] = 10;
+ _signals.ufo_next = false;
+ } else {
+ _invaders[0] = _wave_invaders[_invader_idx];
+ }
+ } else {
+ // just add an empty invader slot
+ _invaders[0] = -1;
+ }
+ // update display
+ for (i = 0; i <= _wave_position; i++) {
+ _display_invader(_invaders[i], 9 - i);
+ }
+ _signals.inv_checking = false;
+ return false;
+}
+
+void invaders_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
+ (void) settings;
+ (void) watch_face_index;
+ if (*context_ptr == NULL) {
+ *context_ptr = malloc(sizeof(invaders_state_t));
+ memset(*context_ptr, 0, sizeof(invaders_state_t));
+ invaders_state_t *state = (invaders_state_t *)*context_ptr;
+ // default: sound on
+ state->sound_on = true;
+ }
+#if __EMSCRIPTEN__
+ // simulator only: seed the randon number generator
+ time_t t;
+ srand((unsigned) time(&t));
+#endif
+}
+
+void invaders_face_activate(movement_settings_t *settings, void *context) {
+ (void) settings;
+ (void) context;
+ _current_state = invaders_state_activated;
+ _signals.suspend_buttons = false;
+}
+
+bool invaders_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
+ invaders_state_t *state = (invaders_state_t *)context;
+
+ switch (event.event_type) {
+ case EVENT_ACTIVATE:
+ // show highscore
+ _display_score("GA", state->highscore);
+ break;
+ case EVENT_TICK:
+ _ticks++;
+ switch (_current_state) {
+ case invaders_state_in_wave_break:
+ case invaders_state_pre_game:
+ case invaders_state_next_wave:
+ // wait 2 secs to start the first round
+ if (_ticks >= 2) {
+ _ticks = 0;
+ _init_wave();
+ _current_state = invaders_state_playing;
+ movement_request_tick_frequency(4);
+ }
+ break;
+ case invaders_state_playing:
+ // game is playing
+ if (_ticks >= _wave_tick_freq) {
+ _ticks = 0;
+ if (_move_invaders()) {
+ // invaders broke through
+ if (_defense_lines < 2) {
+ // start current wave over
+ _defense_lines++;
+ _display_defense_lines();
+ _display_score("GA", _score);
+ _current_state = invaders_state_in_wave_break;
+ movement_request_tick_frequency(1);
+ _play_sequence(state, (int8_t *)_sound_seq_def_gone);
+ } else {
+ // game over
+ _game_over(state);
+ }
+ }
+ }
+ // handle bonus points indicators
+ if (_bonus_countdown) {
+ _bonus_countdown--;
+ if (!_bonus_countdown) {
+ watch_display_character(' ', 2);
+ watch_display_character(' ', 3);
+ }
+ }
+ break;
+ case invaders_state_pre_next_wave:
+ if (_ticks >= 3) {
+ // switch to next wave
+ _ticks = 0;
+ movement_request_tick_frequency(1);
+ _display_score("GA", _score);
+ watch_set_pixel(1, 9);
+ watch_display_character((_waves % INVADERS_FACE_WAVES_PER_STAGE) + 49, 3);
+ _current_state = invaders_state_next_wave;
+ _waves++;
+ if (_waves == INVADERS_FACE_WAVES_PER_STAGE * 2) _waves = 0;
+ _play_sequence(state, (int8_t *)_sound_seq_next_wave);
+ }
+ default:
+ break;
+ }
+ break;
+ case EVENT_LIGHT_BUTTON_DOWN:
+ if (!_signals.suspend_buttons) {
+ if (_current_state == invaders_state_playing) {
+ // cycle the aim
+ _aim = (_aim + 1) % 11;
+ _display_invader(_aim, 0);
+ } else if (_current_state == invaders_state_activated || _current_state == invaders_state_game_over) {
+ // just illuminate the LED
+ movement_illuminate_led();
+ }
+ }
+ break;
+ case EVENT_LIGHT_LONG_PRESS:
+ if ((_current_state == invaders_state_activated || _current_state == invaders_state_game_over) && !_signals.suspend_buttons) {
+ // switch between beepy and silent mode
+ state->sound_on = !state->sound_on;
+ watch_buzzer_play_note(BUZZER_NOTE_A7, state->sound_on ? 65 : 25);
+ }
+ break;
+ case EVENT_ALARM_BUTTON_DOWN:
+ if (!_signals.suspend_buttons) {
+ switch (_current_state) {
+ case invaders_state_game_over:
+ case invaders_state_activated:
+ // initialize the game
+ _waves = 0;
+ _score = 0;
+ movement_request_tick_frequency(1);
+ _ticks = 0;
+ _current_state = invaders_state_pre_game;
+ _play_sequence(state, (int8_t *)_sound_seq_game_start);
+ break;
+ case invaders_state_playing: {
+ // "shoot"
+ _shots_in_wave++;
+ if (_shots_in_wave == 30) {
+ // max number of shots reached: game over
+ _game_over(state);
+ } else {
+ // wait if we are currently deleting an invader
+ while (_signals.inv_checking);
+ // proceed
+ _signals.inv_checking = true;
+ bool skip = false;
+ for (int8_t i = _wave_position; i >= 0 && !skip; i--) {
+ // if (_invaders[i] == -1) break;
+ if (_invaders[i] == _aim) {
+ // invader is shot
+ skip = true;
+ _invaders_shot++;
+ _play_sequence(state, _aim == 10 ? (int8_t *)_sound_seq_ufo_hit : (int8_t *)_sound_seq_shot_hit);
+ if (_invaders_shot == INVADERS_FACE_WAVE_INVADERS) {
+ // last invader shot: wave sucessfully completed
+ watch_display_character(' ', 9 - _wave_position);
+ _ticks = 0;
+ _current_state = invaders_state_pre_next_wave;
+ _signals.inv_checking = false;
+ } else {
+ // check for ufo appearance
+ if (_aim && _aim < 10) {
+ _invaders_shot_sum = (_invaders_shot_sum + _aim) % 10;
+ if (_invaders_shot_sum == 0) _signals.ufo_next = true;
+ }
+ // remove invader
+ if (_wave_position == 0 || i == 5) {
+ _invaders[i] = -1;
+ } else {
+ for (uint8_t j = i; j < _wave_position; j++) {
+ _invaders[j] = _invaders[j + 1];
+ _display_invader(_invaders[j], 9 - j);
+ }
+ }
+ watch_display_character(' ', 9 - _wave_position);
+ if (_wave_position) _wave_position--;
+ // update score
+ if (_aim == 10) {
+ // ufo shot. The original game uses a ridiculously complicated scoring system here...
+ uint8_t bonus_points = 0;
+ uint8_t j;
+ for (j = 0; j < sizeof(_bonus_points_helper) && !bonus_points; j++) {
+ if (_shots_in_wave == _bonus_points_helper[j]) {
+ bonus_points = 30;
+ } else if (_shots_in_wave - 1 == _bonus_points_helper[j]) {
+ bonus_points = 20;
+ }
+ }
+ if (!bonus_points) bonus_points = 10;
+ bonus_points += (6 - i);
+ if ((_waves >= INVADERS_FACE_WAVES_PER_STAGE) && i) bonus_points += (6 - i);
+ _score += bonus_points;
+ // represent bonus points by bars
+ for (j = 0; j < (bonus_points / 10); j++) watch_set_pixel(_bonus_points_segdata[j][0], _bonus_points_segdata[j][1]);
+ _bonus_countdown = 9;
+ } else {
+ // regular invader
+ _score += (6 - _wave_position) * (_waves >= INVADERS_FACE_WAVES_PER_STAGE ? 2 : 1);
+ }
+ }
+ }
+ }
+ if (!skip) _play_sequence(state, (int8_t *)_sound_seq_shot_miss);
+ _signals.inv_checking = false;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ break;
+ case EVENT_TIMEOUT:
+ movement_move_to_face(0);
+ break;
+ default:
+ // Movement's default loop handler will step in for any cases you don't handle above:
+ // * EVENT_LIGHT_BUTTON_DOWN lights the LED
+ // * EVENT_MODE_BUTTON_UP moves to the next watch face in the list
+ // * EVENT_MODE_LONG_PRESS returns to the first watch face (or skips to the secondary watch face, if configured)
+ // You can override any of these behaviors by adding a case for these events to this switch statement.
+ return movement_default_loop_handler(event, settings);
+ }
+
+ // return true if the watch can enter standby mode. Generally speaking, you should always return true.
+ // Exceptions:
+ // * If you are displaying a color using the low-level watch_set_led_color function, you should return false.
+ // * If you are sounding the buzzer using the low-level watch_set_buzzer_on function, you should return false.
+ // Note that if you are driving the LED or buzzer using Movement functions like movement_illuminate_led or
+ // movement_play_alarm, you can still return true. This guidance only applies to the low-level watch_ functions.
+ return true;
+}
+
+void invaders_face_resign(movement_settings_t *settings, void *context) {
+ (void) settings;
+ (void) context;
+ _current_state = invaders_state_game_over;
+}
+
diff --git a/movement/watch_faces/complication/invaders_face.h b/movement/watch_faces/complication/invaders_face.h
new file mode 100644
index 00000000..59126dd5
--- /dev/null
+++ b/movement/watch_faces/complication/invaders_face.h
@@ -0,0 +1,82 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Andreas Nebinger
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef INVADERS_FACE_H_
+#define INVADERS_FACE_H_
+
+#include "movement.h"
+
+/*
+ * Remake of the "famous" Casio Number Invaders Game
+ *
+ * This is an authentic remake of the invaders game, found on the Casio
+ * calculator wristwatch CA-85 or CA-851. There were also some calculators
+ * sold with this game, like MG-880.
+ *
+ * How to play:
+ *
+ * Press the alarm button to start the game.
+ * "Invaders" (just digits, tbh) will start coming in from the right hand side.
+ * Press the light button to "aim". The digit on the top of the display cycles
+ * from 0 to 9. If your aiming digit is identical to one of the invaders,
+ * press the alarm button to "shoot". The corresponding invader will disappear.
+ * If the invaders reach beneath the very first position, you loose one defense
+ * line. When all three defense lines are gone, the game is over.
+ * Also: If you shoot more than 29 times per round, you loose the game.
+ * Good to know: There are 16 invaders per wave. There is a short break between
+ * waves.
+ *
+ * What are the "n" invaders? Ufos!
+ *
+ * Whenever the sum of all invaders shot is divisible by 10 the next invader
+ * will be an ufo, represented by the n-symbol. Shooting a ufo gets you extra
+ * points. Example: shoot 2, 5, 3 --> ufo next
+ *
+ * As for points: the earlier you shoot an invader, the more points you get.
+ *
+ * Anything else? Long pressing the light button toggles sound on or off. (Not
+ * while playing.)
+ *
+ */
+
+typedef struct {
+ uint16_t highscore;
+ bool sound_on;
+} invaders_state_t;
+
+void invaders_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
+void invaders_face_activate(movement_settings_t *settings, void *context);
+bool invaders_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
+void invaders_face_resign(movement_settings_t *settings, void *context);
+
+#define invaders_face ((const watch_face_t){ \
+ invaders_face_setup, \
+ invaders_face_activate, \
+ invaders_face_loop, \
+ invaders_face_resign, \
+ NULL, \
+})
+
+#endif // INVADERS_FACE_H_
+
diff --git a/movement/watch_faces/complication/timer_face.c b/movement/watch_faces/complication/timer_face.c
new file mode 100644
index 00000000..4b0b70b1
--- /dev/null
+++ b/movement/watch_faces/complication/timer_face.c
@@ -0,0 +1,366 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2022 Andreas Nebinger, building on Wesley Ellis’ countdown_face.c
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+#include "timer_face.h"
+#include "watch.h"
+#include "watch_utility.h"
+
+static const uint16_t _default_timer_values[] = {0x200, 0x500, 0xA00, 0x1400, 0x2D02}; // default timers: 2 min, 5 min, 10 min, 20 min, 2 h 45 min
+
+// sound sequence for a single beeping sequence
+static const int8_t _sound_seq_beep[] = {BUZZER_NOTE_C8, 3, BUZZER_NOTE_REST, 3, -2, 2, BUZZER_NOTE_C8, 5, BUZZER_NOTE_REST, 25, 0};
+static const int8_t _sound_seq_start[] = {BUZZER_NOTE_C8, 2, 0};
+
+static uint8_t _beeps_to_play; // temporary counter for ring signals playing
+
+static inline int32_t _get_tz_offset(movement_settings_t *settings) {
+ return movement_timezone_offsets[settings->bit.time_zone] * 60;
+}
+
+static void _signal_callback() {
+ if (_beeps_to_play) {
+ _beeps_to_play--;
+ watch_buzzer_play_sequence((int8_t *)_sound_seq_beep, _signal_callback);
+ }
+}
+
+static void _start(timer_state_t *state, movement_settings_t *settings, bool with_beep) {
+ if (state->timers[state->current_timer].value == 0) return;
+ watch_date_time now = watch_rtc_get_date_time();
+ state->now_ts = watch_utility_date_time_to_unix_time(now, _get_tz_offset(settings));
+ if (state->mode == pausing)
+ state->target_ts = state->now_ts + state->paused_left;
+ else
+ state->target_ts = watch_utility_offset_timestamp(state->now_ts,
+ state->timers[state->current_timer].unit.hours,
+ state->timers[state->current_timer].unit.minutes,
+ state->timers[state->current_timer].unit.seconds);
+ watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, _get_tz_offset(settings));
+ state->mode = running;
+ movement_schedule_background_task(target_dt);
+ watch_set_indicator(WATCH_INDICATOR_BELL);
+ if (settings->bit.button_should_sound && with_beep) watch_buzzer_play_sequence((int8_t *)_sound_seq_start, NULL);
+}
+
+static void _draw(timer_state_t *state, uint8_t subsecond) {
+ char buf[14];
+ uint32_t delta;
+ div_t result;
+ uint8_t h, min, sec;
+
+ switch (state->mode) {
+ case pausing:
+ if (state->pausing_seconds % 2)
+ watch_clear_indicator(WATCH_INDICATOR_BELL);
+ else
+ watch_set_indicator(WATCH_INDICATOR_BELL);
+ if (state->pausing_seconds != 1)
+ // not 1st iteration (or 256th): do not write anything
+ return;
+ // fall through
+ case running:
+ delta = state->target_ts - state->now_ts;
+ result = div(delta, 60);
+ sec = result.rem;
+ result = div(result.quot, 60);
+ min = result.rem;
+ h = result.quot;
+ sprintf(buf, " %02u%02u%02u", h, min, sec);
+ break;
+ case setting:
+ if (state->settings_state == 1) {
+ // ask it the current timer shall be erased
+ sprintf(buf, " CLEAR%c", state->erase_timer_flag ? 'y' : 'n');
+ watch_clear_colon();
+ } else if (state->settings_state == 5) {
+ sprintf(buf, " LOOP%c", state->timers[state->current_timer].unit.repeat ? 'y' : 'n');
+ watch_clear_colon();
+ } else {
+ sprintf(buf, " %02u%02u%02u", state->timers[state->current_timer].unit.hours,
+ state->timers[state->current_timer].unit.minutes,
+ state->timers[state->current_timer].unit.seconds);
+ watch_set_colon();
+ }
+ break;
+ case waiting:
+ sprintf(buf, " %02u%02u%02u", state->timers[state->current_timer].unit.hours,
+ state->timers[state->current_timer].unit.minutes,
+ state->timers[state->current_timer].unit.seconds);
+ break;
+ }
+ buf[0] = 49 + state->current_timer;
+ if (state->mode == setting && subsecond % 2) {
+ // blink the current settings value
+ if (state->settings_state == 0) buf[0] = ' ';
+ else if (state->settings_state == 1 || state->settings_state == 5) buf[6] = ' ';
+ else buf[(state->settings_state - 1) * 2 - 1] = buf[(state->settings_state - 1) * 2] = ' ';
+ }
+ watch_display_string(buf, 3);
+ // set lap indicator when we have a looping timer
+ if (state->timers[state->current_timer].unit.repeat) watch_set_indicator(WATCH_INDICATOR_LAP);
+ else watch_clear_indicator(WATCH_INDICATOR_LAP);
+}
+
+static void _reset(timer_state_t *state) {
+ state->mode = waiting;
+ movement_cancel_background_task();
+ watch_clear_indicator(WATCH_INDICATOR_BELL);
+}
+
+static void _set_next_valid_timer(timer_state_t *state) {
+ if ((state->timers[state->current_timer].value & 0xFFFFFF) == 0) {
+ uint8_t i = state->current_timer;
+ do {
+ i = (i + 1) % TIMER_SLOTS;
+ } while ((state->timers[i].value & 0xFFFFFF) == 0 && i != state->current_timer);
+ state->current_timer = i;
+ }
+}
+
+static void _resume_setting(timer_state_t *state) {
+ state->settings_state = 0;
+ state->mode = waiting;
+ movement_request_tick_frequency(1);
+ _set_next_valid_timer(state);
+}
+
+static void _settings_increment(timer_state_t *state) {
+ switch(state->settings_state) {
+ case 0:
+ state->current_timer = (state->current_timer + 1) % TIMER_SLOTS;
+ break;
+ case 1:
+ state->erase_timer_flag ^= 1;
+ break;
+ case 2:
+ state->timers[state->current_timer].unit.hours = (state->timers[state->current_timer].unit.hours + 1) % 24;
+ break;
+ case 3:
+ state->timers[state->current_timer].unit.minutes = (state->timers[state->current_timer].unit.minutes + 1) % 60;
+ break;
+ case 4:
+ state->timers[state->current_timer].unit.seconds = (state->timers[state->current_timer].unit.seconds + 1) % 60;
+ break;
+ case 5:
+ state->timers[state->current_timer].unit.repeat ^= 1;
+ break;
+ default:
+ // should never happen
+ break;
+ }
+ return;
+}
+
+static void _abort_quick_cycle(timer_state_t *state) {
+ if (state->quick_cycle) {
+ state->quick_cycle = false;
+ movement_request_tick_frequency(4);
+ }
+}
+
+static inline bool _check_for_signal() {
+ if (_beeps_to_play) {
+ _beeps_to_play = 0;
+ return true;
+ }
+ return false;
+}
+
+void timer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
+ (void) settings;
+ (void) watch_face_index;
+
+ if (*context_ptr == NULL) {
+ *context_ptr = malloc(sizeof(timer_state_t));
+ timer_state_t *state = (timer_state_t *)*context_ptr;
+ memset(*context_ptr, 0, sizeof(timer_state_t));
+ for (uint8_t i = 0; i < sizeof(_default_timer_values) / sizeof(uint16_t); i++) {
+ state->timers[i].value = _default_timer_values[i];
+ }
+ }
+}
+
+void timer_face_activate(movement_settings_t *settings, void *context) {
+ (void) settings;
+ timer_state_t *state = (timer_state_t *)context;
+ watch_display_string("TR", 0);
+ watch_set_colon();
+ if(state->mode == running) {
+ watch_date_time now = watch_rtc_get_date_time();
+ state->now_ts = watch_utility_date_time_to_unix_time(now, _get_tz_offset(settings));
+ watch_set_indicator(WATCH_INDICATOR_BELL);
+ } else {
+ state->pausing_seconds = 1;
+ _beeps_to_play = 0;
+ }
+}
+
+bool timer_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
+ (void) settings;
+ timer_state_t *state = (timer_state_t *)context;
+ uint8_t subsecond = event.subsecond;
+
+ switch (event.event_type) {
+ case EVENT_ACTIVATE:
+ _draw(state, event.subsecond);
+ break;
+ case EVENT_TICK:
+ if (state->mode == running) state->now_ts++;
+ else if (state->mode == pausing) state->pausing_seconds++;
+ else if (state->quick_cycle) {
+ if (watch_get_pin_level(BTN_ALARM)) {
+ _settings_increment(state);
+ subsecond = 0;
+ } else _abort_quick_cycle(state);
+ }
+ _draw(state, subsecond);
+ break;
+ case EVENT_LIGHT_BUTTON_DOWN:
+ switch (state->mode) {
+ case pausing:
+ case running:
+ movement_illuminate_led();
+ break;
+ case setting:
+ if (state->erase_timer_flag) {
+ state->timers[state->current_timer].value = 0;
+ state->erase_timer_flag = false;
+ }
+ state->settings_state = (state->settings_state + 1) % 6;
+ if (state->settings_state == 1 && state->timers[state->current_timer].value == 0) state->settings_state = 2;
+ else if (state->settings_state == 5 && (state->timers[state->current_timer].value & 0xFFFFFF) == 0) state->settings_state = 0;
+ break;
+ default:
+ break;
+ }
+ _draw(state, event.subsecond);
+ break;
+ case EVENT_LIGHT_BUTTON_UP:
+ if (state->mode == waiting) movement_illuminate_led();
+ break;
+ case EVENT_ALARM_BUTTON_UP:
+ _abort_quick_cycle(state);
+ if (_check_for_signal()) break;;
+ switch (state->mode) {
+ case running:
+ state->mode = pausing;
+ state->pausing_seconds = 0;
+ state->paused_left = state->target_ts - state->now_ts;
+ movement_cancel_background_task();
+ break;
+ case pausing:
+ _start(state, settings, false);
+ break;
+ case waiting: {
+ uint8_t last_timer = state->current_timer;
+ state->current_timer = (state->current_timer + 1) % TIMER_SLOTS;
+ _set_next_valid_timer(state);
+ // start the time immediately if there is only one valid timer slot
+ if (last_timer == state->current_timer) _start(state, settings, true);
+ break;
+ }
+ case setting:
+ _settings_increment(state);
+ subsecond = 0;
+ break;
+ }
+ _draw(state, subsecond);
+ break;
+ case EVENT_LIGHT_LONG_PRESS:
+ if (state->mode == waiting) {
+ // initiate settings
+ state->mode = setting;
+ state->settings_state = 0;
+ state->erase_timer_flag = false;
+ movement_request_tick_frequency(4);
+ } else if (state->mode == setting) {
+ _resume_setting(state);
+ }
+ _draw(state, event.subsecond);
+ break;
+ case EVENT_BACKGROUND_TASK:
+ // play the alarm
+ _beeps_to_play = 4;
+ watch_buzzer_play_sequence((int8_t *)_sound_seq_beep, _signal_callback);
+ _reset(state);
+ if (state->timers[state->current_timer].unit.repeat) _start(state, settings, false);
+ break;
+ case EVENT_ALARM_LONG_PRESS:
+ switch(state->mode) {
+ case setting:
+ switch (state->settings_state) {
+ case 0:
+ state->current_timer = 0;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ state->quick_cycle = true;
+ movement_request_tick_frequency(8);
+ break;
+ default:
+ break;
+ }
+ break;
+ case waiting:
+ _start(state, settings, true);
+ break;
+ case pausing:
+ case running:
+ _reset(state);
+ if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_C7, 50);
+ break;
+ default:
+ break;
+ }
+ _draw(state, event.subsecond);
+ break;
+ case EVENT_ALARM_LONG_UP:
+ _abort_quick_cycle(state);
+ break;
+ case EVENT_MODE_LONG_PRESS:
+ case EVENT_TIMEOUT:
+ _abort_quick_cycle(state);
+ movement_move_to_face(0);
+ break;
+ default:
+ movement_default_loop_handler(event, settings);
+ break;
+ }
+
+ return true;
+}
+
+void timer_face_resign(movement_settings_t *settings, void *context) {
+ (void) settings;
+ timer_state_t *state = (timer_state_t *)context;
+ if (state->mode == setting) {
+ state->settings_state = 0;
+ state->mode = waiting;
+ }
+}
diff --git a/movement/watch_faces/complication/timer_face.h b/movement/watch_faces/complication/timer_face.h
new file mode 100644
index 00000000..293f6524
--- /dev/null
+++ b/movement/watch_faces/complication/timer_face.h
@@ -0,0 +1,103 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2022 Andreas Nebinger, based on Wesley Ellis’ countdown face.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+//-----------------------------------------------------------------------------
+
+#ifndef TIMER_FACE_H_
+#define TIMER_FACE_H_
+
+#include "movement.h"
+
+/*
+ * Advanced timer/countdown face with pre-set timer lengths
+ *
+ * This watch face provides the functionality of starting a countdown by choosing
+ * one out of nine programmable timer presets. A timer/countdown can be 23 hours,
+ * 59 minutes, and 59 seconds max. A timer can also be set to auto-repeat, which
+ * is indicated by the lap indicator.
+ *
+ * How to use in NORMAL mode:
+ * - Short-pressing the alarm button cycles through all pre-set timer lengths.
+ * Find the current timer slot number in the upper right-hand corner.
+ * - Long-pressing the alarm button starts the timer.
+ * - Long-pressing the light button initiates settings mode.
+ *
+ * How to use in SETTINGS mode:
+ * - There are up to nine slots for storing a timer setting. The current slot is
+ * indicated by the number in the upper right-hand corner.
+ * - Short-pressing the light button cycles through the settings values of each
+ * timer slot in the following order: hours - minutes - seconds - timer repeat
+ * - Short-pressing the alarm button alters the current settings value.
+ * - Long-pressing the light button resumes to normal mode.
+ *
+ */
+
+#define TIMER_SLOTS 9 // offer 9 timer slots
+
+typedef enum {
+ waiting,
+ running,
+ setting,
+ pausing
+} timer_mode_t;
+
+typedef union {
+ struct {
+ uint8_t hours;
+ uint8_t minutes;
+ uint8_t seconds;
+ bool repeat;
+ } unit;
+ uint32_t value;
+} timer_setting_t;
+
+typedef struct {
+ uint32_t target_ts;
+ uint32_t now_ts;
+ uint16_t paused_left;
+ uint8_t pausing_seconds;
+ timer_setting_t timers[TIMER_SLOTS];
+ uint8_t settings_state : 4;
+ uint8_t current_timer : 4;
+ uint8_t set_timers : 4;
+ bool erase_timer_flag : 1;
+ timer_mode_t mode : 3;
+ bool quick_cycle : 1;
+} timer_state_t;
+
+void timer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
+void timer_face_activate(movement_settings_t *settings, void *context);
+bool timer_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
+void timer_face_resign(movement_settings_t *settings, void *context);
+
+#define timer_face ((const watch_face_t){ \
+ timer_face_setup, \
+ timer_face_activate, \
+ timer_face_loop, \
+ timer_face_resign, \
+ NULL, \
+})
+
+
+#endif // TIMER_FACE_H_
diff --git a/movement/watch_faces/demo/chirpy_demo_face.c b/movement/watch_faces/demo/chirpy_demo_face.c
new file mode 100644
index 00000000..ee3e5b41
--- /dev/null
+++ b/movement/watch_faces/demo/chirpy_demo_face.c
@@ -0,0 +1,335 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Gabor L Ugray
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "chirpy_demo_face.h"
+#include "chirpy_tx.h"
+#include "filesystem.h"
+
+typedef enum {
+ CDM_CHOOSE = 0,
+ CDM_CHIRPING,
+} chirpy_demo_mode_t;
+
+typedef enum {
+ CDP_SCALE = 0,
+ CDP_INFO_SHORT,
+ CDP_INFO_LONG,
+ CDP_INFO_NANOSEC,
+} chirpy_demo_program_t;
+
+typedef struct {
+ // Current mode
+ chirpy_demo_mode_t mode;
+
+ // Selected program
+ chirpy_demo_program_t program;
+
+ // Helps us handle 1/64 ticks during transmission; including countdown timer
+ chirpy_tick_state_t tick_state;
+
+ // Used by chirpy encoder during transmission
+ chirpy_encoder_state_t encoder_state;
+
+} chirpy_demo_state_t;
+
+static uint8_t long_data_str[] =
+ "There once was a ship that put to sea\n"
+ "The name of the ship was the Billy of Tea\n"
+ "The winds blew up, her bow dipped down\n"
+ "O blow, my bully boys, blow (huh)\n"
+ "\n"
+ "Soon may the Wellerman come\n"
+ "To bring us sugar and tea and rum\n"
+ "One day, when the tonguin' is done\n"
+ "We'll take our leave and go\n";
+
+static uint16_t short_data_len = 20;
+
+static uint8_t short_data[] = {
+ 0x27,
+ 0x00,
+ 0x0c,
+ 0x42,
+ 0xa3,
+ 0xd4,
+ 0x06,
+ 0x54,
+ 0x00,
+ 0x00,
+ 0x02,
+ 0x0c,
+ 0x6b,
+ 0x05,
+ 0x5a,
+ 0x09,
+ 0xd8,
+ 0x00,
+ 0xf5,
+ 0x00,
+};
+
+#define NANOSEC_INI_FILE_NAME "nanosec.ini"
+
+static uint8_t *nanosec_buffer = 0;
+static uint16_t nanosec_buffer_size = 0;
+
+void chirpy_demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void **context_ptr) {
+ (void)settings;
+ (void)watch_face_index;
+ if (*context_ptr == NULL) {
+ *context_ptr = malloc(sizeof(chirpy_demo_state_t));
+ memset(*context_ptr, 0, sizeof(chirpy_demo_state_t));
+ // Do any one-time tasks in here; the inside of this conditional happens only at boot.
+ }
+ // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep.
+}
+
+void chirpy_demo_face_activate(movement_settings_t *settings, void *context) {
+ (void)settings;
+ chirpy_demo_state_t *state = (chirpy_demo_state_t *)context;
+
+ memset(context, 0, sizeof(chirpy_demo_state_t));
+ state->mode = CDM_CHOOSE;
+ state->program = CDP_SCALE;
+
+ // Do we have nanosec data? Load it.
+ int32_t sz = filesystem_get_file_size(NANOSEC_INI_FILE_NAME);
+ if (sz > 0) {
+ // We will free this in resign.
+ // I don't like any kind of dynamic allocation in long-running embedded software...
+ // But there's no way around it here; I don't want to hard-wire (and squat) any fixed size structure
+ // Nanosec data may change in the future too
+ nanosec_buffer_size = sz + 2;
+ nanosec_buffer = malloc(nanosec_buffer_size);
+ // First two bytes of prefix, so Chirpy RX can recognize this data type
+ nanosec_buffer[0] = 0xc0;
+ nanosec_buffer[1] = 0x00;
+ // Read file
+ filesystem_read_file(NANOSEC_INI_FILE_NAME, (char*)&nanosec_buffer[2], sz);
+ }
+}
+
+// To create / check test file in emulator:
+// echo TestData > nanosec.ini
+// cat nanosec.ini
+
+static void _cdf_update_lcd(chirpy_demo_state_t *state) {
+ watch_display_string("CH", 0);
+ if (state->program == CDP_SCALE)
+ watch_display_string(" SCALE", 4);
+ else if (state->program == CDP_INFO_SHORT)
+ watch_display_string("SHORT ", 4);
+ else if (state->program == CDP_INFO_LONG)
+ watch_display_string(" LOng ", 4);
+ else if (state->program == CDP_INFO_NANOSEC)
+ watch_display_string("nAnO ", 4);
+ else
+ watch_display_string("---- ", 4);
+}
+
+static void _cdf_quit_chirping(chirpy_demo_state_t *state) {
+ state->mode = CDM_CHOOSE;
+ watch_set_buzzer_off();
+ watch_clear_indicator(WATCH_INDICATOR_BELL);
+ movement_request_tick_frequency(1);
+}
+
+static void _cdf_scale_tick(void *context) {
+ chirpy_demo_state_t *state = (chirpy_demo_state_t *)context;
+ chirpy_tick_state_t *tick_state = &state->tick_state;
+
+ // Scale goes in 200Hz increments from 700 Hz to 12.3 kHz -> 58 steps
+ if (tick_state->seq_pos == 58) {
+ _cdf_quit_chirping(state);
+ return;
+ }
+ uint32_t freq = 700 + tick_state->seq_pos * 200;
+ uint32_t period = 1000000 / freq;
+ watch_set_buzzer_period(period);
+ watch_set_buzzer_on();
+ ++tick_state->seq_pos;
+}
+
+static void _cdf_data_tick(void *context) {
+ chirpy_demo_state_t *state = (chirpy_demo_state_t *)context;
+
+ uint8_t tone = chirpy_get_next_tone(&state->encoder_state);
+ // Transmission over?
+ if (tone == 255) {
+ _cdf_quit_chirping(state);
+ return;
+ }
+ uint16_t period = chirpy_get_tone_period(tone);
+ watch_set_buzzer_period(period);
+ watch_set_buzzer_on();
+}
+
+static uint8_t *curr_data_ptr;
+static uint16_t curr_data_ix;
+static uint16_t curr_data_len;
+
+static uint8_t _cdf_get_next_byte(uint8_t *next_byte) {
+ if (curr_data_ix == curr_data_len)
+ return 0;
+ *next_byte = curr_data_ptr[curr_data_ix];
+ ++curr_data_ix;
+ return 1;
+}
+
+static void _cdf_countdown_tick(void *context) {
+ chirpy_demo_state_t *state = (chirpy_demo_state_t *)context;
+ chirpy_tick_state_t *tick_state = &state->tick_state;
+
+ // Countdown over: start actual broadcast
+ if (tick_state->seq_pos == 8 * 3) {
+ tick_state->tick_compare = 3;
+ tick_state->tick_count = -1;
+ tick_state->seq_pos = 0;
+ // We'll be chirping out a scale
+ if (state->program == CDP_SCALE) {
+ tick_state->tick_fun = _cdf_scale_tick;
+ }
+ // We'll be chirping out data
+ else {
+ // Set up the encoder
+ chirpy_init_encoder(&state->encoder_state, _cdf_get_next_byte);
+ tick_state->tick_fun = _cdf_data_tick;
+ // Set up the data
+ curr_data_ix = 0;
+ if (state->program == CDP_INFO_SHORT) {
+ curr_data_ptr = short_data;
+ curr_data_len = short_data_len;
+ } else if (state->program == CDP_INFO_LONG) {
+ curr_data_ptr = long_data_str;
+ curr_data_len = strlen((const char *)long_data_str);
+ } else if (state->program == CDP_INFO_NANOSEC) {
+ curr_data_ptr = nanosec_buffer;
+ curr_data_len = nanosec_buffer_size;
+ }
+ }
+ return;
+ }
+ // Sound or turn off buzzer
+ if ((tick_state->seq_pos % 8) == 0) {
+ watch_set_buzzer_period(NotePeriods[BUZZER_NOTE_A5]);
+ watch_set_buzzer_on();
+ } else if ((tick_state->seq_pos % 8) == 1) {
+ watch_set_buzzer_off();
+ }
+ ++tick_state->seq_pos;
+}
+
+static void _cdm_setup_chirp(chirpy_demo_state_t *state) {
+ // We want frequent callbacks from now on
+ movement_request_tick_frequency(64);
+ watch_set_indicator(WATCH_INDICATOR_BELL);
+ state->mode = CDM_CHIRPING;
+ // Set up tick state; start with countdown
+ state->tick_state.tick_count = -1;
+ state->tick_state.tick_compare = 8;
+ state->tick_state.seq_pos = 0;
+ state->tick_state.tick_fun = _cdf_countdown_tick;
+}
+
+bool chirpy_demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
+ (void)settings;
+ chirpy_demo_state_t *state = (chirpy_demo_state_t *)context;
+
+ switch (event.event_type) {
+ case EVENT_ACTIVATE:
+ _cdf_update_lcd(state);
+ break;
+ case EVENT_MODE_BUTTON_UP:
+ // Do not exit face while we're chirping
+ if (state->mode != CDM_CHIRPING) {
+ movement_move_to_next_face();
+ }
+ break;
+ case EVENT_LIGHT_BUTTON_UP:
+ // We don't do light.
+ break;
+ case EVENT_ALARM_BUTTON_UP:
+ // If in choose mode: select next program
+ if (state->mode == CDM_CHOOSE) {
+ if (state->program == CDP_SCALE)
+ state->program = CDP_INFO_SHORT;
+ else if (state->program == CDP_INFO_SHORT)
+ state->program = CDP_INFO_LONG;
+ else if (state->program == CDP_INFO_LONG) {
+ if (nanosec_buffer_size > 0)
+ state->program = CDP_INFO_NANOSEC;
+ else
+ state->program = CDP_SCALE;
+ } else if (state->program == CDP_INFO_NANOSEC)
+ state->program = CDP_SCALE;
+ _cdf_update_lcd(state);
+ }
+ // If chirping: stoppit
+ else if (state->mode == CDM_CHIRPING) {
+ _cdf_quit_chirping(state);
+ }
+ break;
+ case EVENT_ALARM_LONG_PRESS:
+ // If in choose mode: start chirping
+ if (state->mode == CDM_CHOOSE) {
+ _cdm_setup_chirp(state);
+ }
+ break;
+ case EVENT_TICK:
+ if (state->mode == CDM_CHIRPING) {
+ ++state->tick_state.tick_count;
+ if (state->tick_state.tick_count == state->tick_state.tick_compare) {
+ state->tick_state.tick_count = 0;
+ state->tick_state.tick_fun(context);
+ }
+ }
+ break;
+ case EVENT_TIMEOUT:
+ // Do not time out while we're chirping
+ if (state->mode != CDM_CHIRPING) {
+ movement_move_to_face(0);
+ }
+ default:
+ break;
+ }
+
+ // Return true if the watch can enter standby mode. False needed when chirping.
+ if (state->mode == CDM_CHIRPING)
+ return false;
+ else
+ return true;
+}
+
+void chirpy_demo_face_resign(movement_settings_t *settings, void *context) {
+ (void)settings;
+ (void)context;
+
+ if (nanosec_buffer != 0) {
+ free(nanosec_buffer);
+ nanosec_buffer = 0;
+ nanosec_buffer_size = 0;
+ }
+}
diff --git a/movement/watch_faces/demo/chirpy_demo_face.h b/movement/watch_faces/demo/chirpy_demo_face.h
new file mode 100644
index 00000000..2d34107a
--- /dev/null
+++ b/movement/watch_faces/demo/chirpy_demo_face.h
@@ -0,0 +1,70 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 <#author_name#>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIRPY_DEMO_FACE_H_
+#define CHIRPY_DEMO_FACE_H_
+
+#include "movement.h"
+
+/*
+ * CHIRPY DEMO FACE
+ *
+ * This face demonstrates the chirpy-tx library. It is intended to help you
+ * include chirpy-tx in your own watch faces that need to transmit data out
+ * of the watch.
+ *
+ * The face's first screen lets you select from a few built-in transmissions:
+ *
+ * SCALE cycles through frequencies in fixed increments. This is intended to
+ * collect and analyze audio samples from different watches. With this info
+ * it may be possible to improve chirpy-tx's parameters like the frequencies
+ * it uses to make the method more robust.
+ *
+ * SHORT is a small transmission that contains data taked from the activity_face.
+ *
+ * LONG is a longer transmission that contains the first two strophes of a
+ * famous sea shanty.
+ *
+ * Select the transmission you want with ALARM, the press LONG ALARM to chirp.
+ *
+ * To record and decode a chirpy transmission on your computer, you can use the web app here:
+ * https://jealousmarkup.xyz/off/chirpy/rx/
+ *
+ */
+
+void chirpy_demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
+void chirpy_demo_face_activate(movement_settings_t *settings, void *context);
+bool chirpy_demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
+void chirpy_demo_face_resign(movement_settings_t *settings, void *context);
+
+#define chirpy_demo_face ((const watch_face_t){ \
+ chirpy_demo_face_setup, \
+ chirpy_demo_face_activate, \
+ chirpy_demo_face_loop, \
+ chirpy_demo_face_resign, \
+ NULL, \
+})
+
+#endif // CHIRPY_DEMO_FACE_H_
+