You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.7 KiB
167 lines
5.7 KiB
/* |
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
/// |
|
/// @file AP_Common.h |
|
/// @brief Common definitions and utility routines for the ArduPilot |
|
/// libraries. |
|
/// |
|
|
|
#pragma once |
|
|
|
#include <stdint.h> |
|
#include <stdlib.h> |
|
#include <type_traits> |
|
|
|
// used to pack structures |
|
#define PACKED __attribute__((__packed__)) |
|
|
|
// used to weaken symbols |
|
#define WEAK __attribute__((__weak__)) |
|
|
|
// used to mark a function that may be unused in some builds |
|
#define UNUSED_FUNCTION __attribute__((unused)) |
|
|
|
// this can be used to optimize individual functions |
|
#define OPTIMIZE(level) __attribute__((optimize(level))) |
|
|
|
// sometimes we need to prevent inlining to prevent large stack usage |
|
#define NOINLINE __attribute__((noinline)) |
|
|
|
// used to ignore results for functions marked as warn unused |
|
#define IGNORE_RETURN(x) do {if (x) {}} while(0) |
|
|
|
#define FMT_PRINTF(a,b) __attribute__((format(printf, a, b))) |
|
#define FMT_SCANF(a,b) __attribute__((format(scanf, a, b))) |
|
|
|
// used to forbid copy of objects |
|
#define CLASS_NO_COPY(c) c(const c &other) = delete; c &operator=(const c&) = delete |
|
|
|
#ifdef __has_cpp_attribute |
|
# if __has_cpp_attribute(fallthrough) |
|
# define FALLTHROUGH [[fallthrough]] |
|
# elif __has_cpp_attribute(gnu::fallthrough) |
|
# define FALLTHROUGH [[gnu::fallthrough]] |
|
# endif |
|
#endif |
|
#ifndef FALLTHROUGH |
|
# define FALLTHROUGH |
|
#endif |
|
|
|
#ifdef __GNUC__ |
|
#define WARN_IF_UNUSED __attribute__ ((warn_unused_result)) |
|
#else |
|
#define WARN_IF_UNUSED |
|
#endif |
|
|
|
#define NORETURN __attribute__ ((noreturn)) |
|
|
|
#define ToRad(x) radians(x) // *pi/180 |
|
#define ToDeg(x) degrees(x) // *180/pi |
|
|
|
/* Declare and implement const and non-const versions of the array subscript |
|
* operator. The object is treated as an array of type_ values. */ |
|
#define DEFINE_BYTE_ARRAY_METHODS \ |
|
inline uint8_t &operator[](size_t i) { return reinterpret_cast<uint8_t *>(this)[i]; } \ |
|
inline uint8_t operator[](size_t i) const { return reinterpret_cast<const uint8_t *>(this)[i]; } |
|
|
|
/* |
|
check if bit bitnumber is set in value, returned as a |
|
bool. Bitnumber starts at 0 for the first bit |
|
*/ |
|
#define BIT_IS_SET(value, bitnumber) (((value) & (1U<<(bitnumber))) != 0) |
|
|
|
// get high or low bytes from 2 byte integer |
|
#define LOWBYTE(i) ((uint8_t)(i)) |
|
#define HIGHBYTE(i) ((uint8_t)(((uint16_t)(i))>>8)) |
|
|
|
#define ARRAY_SIZE(_arr) (sizeof(_arr) / sizeof(_arr[0])) |
|
|
|
#define UINT16_VALUE(hbyte, lbyte) (static_cast<uint16_t>(((hbyte)<<8)|(lbyte))) |
|
#define UINT32_VALUE(b3, b2, b1, b0) (static_cast<uint32_t>(((b3)<<24)|((b2)<<16)|((b1)<<8)|(b0))) |
|
|
|
/* |
|
* See UNUSED_RESULT. The difference is that it receives @uniq_ as the name to |
|
* be used for its internal variable. |
|
* |
|
* @uniq_: a unique name to use for variable name |
|
* @expr_: the expression to be evaluated |
|
*/ |
|
#define _UNUSED_RESULT(uniq_, expr_) \ |
|
do { \ |
|
decltype(expr_) uniq_ __attribute__((unused)); \ |
|
uniq_ = expr_; \ |
|
} while (0) |
|
|
|
/* |
|
* Allow to call a function annotated with warn_unused_result attribute |
|
* without getting a warning, because sometimes this is what we want to do. |
|
* |
|
* @expr_: the expression to be evaluated |
|
*/ |
|
#define UNUSED_RESULT(expr_) _UNUSED_RESULT(__unique_name_##__COUNTER__, expr_) |
|
|
|
// @} |
|
|
|
|
|
// assert_storage_size template: assert that the memory used to store an |
|
// item is of a specific size. |
|
// example invocation: |
|
// assert_storage_size<class Location, 16> _assert_storage_size_Location; |
|
// templates are used for this because the compiler's output will |
|
// usually contain details of the template instantiation so you can |
|
// see how the actual size differs from the expected size. |
|
template<typename s, size_t s_size, size_t t> struct _assert_storage_size { |
|
static_assert(s_size == t, "wrong size"); |
|
}; |
|
template<typename s, size_t t> struct assert_storage_size { |
|
_assert_storage_size<s, sizeof(s), t> _member; |
|
}; |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
/// @name Conversions |
|
/// |
|
/// Conversion macros and factors. |
|
/// |
|
//@{ |
|
|
|
/* |
|
Return true if value is between lower and upper bound inclusive. |
|
False otherwise. |
|
*/ |
|
bool is_bounded_int32(int32_t value, int32_t lower_bound, int32_t upper_bound); |
|
|
|
bool hex_to_uint8(uint8_t a, uint8_t &res); // return the uint8 value of an ascii hex character |
|
|
|
/* |
|
strncpy without the warning for not leaving room for nul termination |
|
*/ |
|
void strncpy_noterm(char *dest, const char *src, size_t n); |
|
|
|
// return the numeric value of an ascii hex character |
|
int16_t char_to_hex(char a); |
|
|
|
/* |
|
Bit manipulation |
|
*/ |
|
//#define BIT_SET(value, bitnumber) ((value) |= (((typeof(value))1U) << (bitnumber))) |
|
template <typename T> void BIT_SET (T& value, uint8_t bitnumber) noexcept { |
|
static_assert(std::is_integral<T>::value, "Integral required."); |
|
((value) |= ((T)(1U) << (bitnumber))); |
|
} |
|
//#define BIT_CLEAR(value, bitnumber) ((value) &= ~(((typeof(value))1U) << (bitnumber))) |
|
template <typename T> void BIT_CLEAR (T& value, uint8_t bitnumber) noexcept { |
|
static_assert(std::is_integral<T>::value, "Integral required."); |
|
((value) &= ~((T)(1U) << (bitnumber))); |
|
}
|
|
|