Skip to content

Instantly share code, notes, and snippets.

@hraftery
Created October 12, 2023 01:05
Show Gist options
  • Save hraftery/902504b51316d6c4871ddcfbcf4825f3 to your computer and use it in GitHub Desktop.
Save hraftery/902504b51316d6c4871ddcfbcf4825f3 to your computer and use it in GitHub Desktop.
Project wide includes, macros and types.
/**
* \file
*
* \brief General utility functions
*
* \author Heath Raftery
* \date July, 2016
*/
#ifndef __COMMON_H__
#define __COMMON_H__
//=====================
// INCLUDES
//=====================
/** All modules should be using these utils. */
#include "util/assert.h"
#include "util/fault.h"
//=====================
// TYPES
//=====================
/** Use the std bool and ints (uint32_t et al.) liberally */
#include <stdbool.h>
#include <stdint.h>
/**
* A date/time value, as the number of seconds since 00:00 hours, Jan 1, 1970 UTC.
* Compatible with the Unix timestamp, and most time_t implementations.
*/
typedef uint32_t tDatetime;
//=====================
// DEFINES
//=====================
/** Get the number of elements in a statically defined array */
#define NUM_ELEMS(x) (sizeof(x) / sizeof((x)[0]))
/**
* Get n rounded up to a multiple of m. Eg ROUND_UP(12,5) = 15, ROUND_UP(4,4) = 4.
* Only intended for positive integers.
* \see http://stackoverflow.com/questions/3407012/
*/
#define ROUND_UP(n,m) ( (n)==0 ? (n) : ( ((n)+(m)-1) - (((n)-1)%(m)) ) )
/**
* Get n rounded down to a multiple of m. Eg ROUND_DOWN(12,5) = 10, ROUND_DOWN(4,4) = 4, ROUND_DOWN(-1,4) = -4.
* Works with negative integers for the first argument.
* \see https://gist.github.com/aslakhellesoy/1134482
*/
#define ROUND_DOWN(n,m) ( (n) >= 0 ? ((n) / (m)) * (m) : (((n) - (m) + 1) / (m)) * (m) )
/**
* Perform integer division n/d but round to nearest integer instead of truncating by adding d/2 first.
* Only intended for positive integers. See \ref DIV_ROUND_INT for signed integers support.
* \see http://stackoverflow.com/questions/2422712/c-rounding-integer-division-instead-of-truncating
*/
#define DIV_ROUND(n,d) ((((n) + (d)/2)/(d)))
/**
* Perform integer division n/d but round to nearest integer instead of truncating.
* Works with positive or negative integers.
* \see http://stackoverflow.com/questions/2422712/c-rounding-integer-division-instead-of-truncating
*/
#define DIV_ROUND_INT(n,d) ((((n) < 0) ^ ((d) < 0)) ? (((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d)))
/**
* Return -1, 0 or 1 depending on whether x is negative, zero or positive.
* \see http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
*/
#define SIGN(x) ((x > 0) - (x < 0))
/**
* Get the number of wordSize words required to wholly contain numBytes.
* Eg. NUM_WORDS_FOR_BYTES(12,5) = 3, NUM_WORDS_FOR_BYTES(4,4) = 1.
* Only intended for positive integers. Could do with a better name.
*/
#define NUM_WORDS_FOR_BYTES(numBytes, wordSize) (((numBytes)+(wordSize)-1)/(wordSize))
/** Get the sizeof a member of a struct type. */
#define SIZEOF_MEMBER(type, member) sizeof(((type *)0)->member)
/** Turn a define into a string by wrapping it in double quotes */
#define STRINGIFY(s) STRINGIFY_HELPER(s)
#define STRINGIFY_HELPER(s) #s /* two macro levels required, as per https://gcc.gnu.org/onlinedocs/cpp/Stringification.html */
/** Simple linear interpolation macro, without the overhead of std::lerp
* Returns the linear interpolation of x on the line (x0,y0) to (x1,y1) */
#define LERP(x, x0, x1, y0, y1) (y0 + ((y1-y0)/(x1-x0)) * (x-x0))
/** Stop the current task. Interrupts can still fire so context switches can still occur. */
#define HALT() while(1) __asm volatile( "NOP" );
#include "config/FreeRTOSConfig.h"
/**
* All interrupts that we enable should have priority >= configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
* so we are free to call *FromISR FreeRTOS functions from the ISR. See the "Inverse Relationship Between
* Numeric Priority Value and the Logical Priority Setting" section of
* http://www.freertos.org/RTOS-Cortex-M3-M4.html for details.
*/
#define INTERRUPT_PRIORITY configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
/**
* This is a replacement for the retarded irq_register_handler in interrupt_sam_nvic.h. The documentation
* for irq_register_handler is so bad as to be considered dangerous. This version does what it says.
* In SAM4E, IRQ handlers are already assigned in the vector table (see startup_sam4e.c) so all one needs
* to do to enable an interrupt is call this define and provide a definition of the corresponding
* handler (see exceptions.c). irq_num must be of type IRQn_Type (see sam4e16e.h).
*/
#define irq_enable(irq_num) \
do { \
NVIC_ClearPendingIRQ(irq_num); \
NVIC_SetPriority(irq_num, INTERRUPT_PRIORITY); \
NVIC_EnableIRQ(irq_num); \
}while(0) /* user to supply ';' */
//=====================
// DEBUG
//=====================
#ifdef _DEBUG
//In debug mode, try to print out the error message to stdout. Note printf is not thread safe, isn't guaranteed
//to be available and occasionally hard faults, but generally if you have a terminal session attached to the
//USB port the error message is useful debugging information. See serial_comms for the stdio setup.
#include <stdio_serial.h>
#define DEBUG_PRINT(...) printf(__VA_ARGS__)
#else
#define DEBUG_PRINT(...)
#endif
//=====================
// PROFILING
//=====================
/** #include this at top of the file of a function you wish to profile. */
#define PROFILE_INCLUDE <stdio.h>
/** Place at the start of a function you wish to profile. */
#define PROFILE_START \
TickType_t endTick, startTick = xTaskGetTickCount();
/** Place any number of times between \ref PROFILE_START and \ref PROFILE_END to get a profiling update. */
#define PROFILE_PROGRESS \
endTick = xTaskGetTickCount(); \
DEBUG_PRINT("time = %lu, ", endTick-startTick); \
startTick = xTaskGetTickCount();
/** Place at the end of a function you wish to profile. */
#define PROFILE_END \
endTick = xTaskGetTickCount(); \
DEBUG_PRINT("time = %lu.\n", endTick-startTick);
//=====================
// CALIBRATION
//=====================
/**
* Uncomment to enable calibration mode, where various calibration values are printed to the console,
* displayed on the home screen and configurable in the settings screen. See TT-PRO-0001 Assembly
* Instructions for details.
*
* Note that the preferred way to enable CALIBRATION_MODE is to build using the "Calibration" configuration.
* It is the same as "Debug", but defines CALIBRATION_MODE as well. It was created so we can have a normal
* Debug build without having to manually edit this file back and forth.
*/
//#define CALIBRATION_MODE
#ifdef CALIBRATION_MODE
#ifdef NDEBUG
#error Cannot use calibration mode in Release build because Release build requires a Flash erase to overwrite, which deletes the calibration.
#endif
/** In cal mode, start with a fresh set of settings on boot so we don't launch with invalid values. */
#define RESET_TO_FACTORY_DEFAULTS
#endif
#endif //__COMMON_H__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment