util.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #ifndef MY_UTIL_H_
  2. #define MY_UTIL_H_
  3. #ifndef F_CPU
  4. # warning "F_CPU not defined"
  5. #endif
  6. #include <util/delay.h>
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <avr/interrupt.h>
  10. #include <avr/pgmspace.h>
  11. #include <avr/cpufunc.h>
  12. /* Return the smaller value of 'a' and 'b'. */
  13. #define min(a, b) ({ \
  14. __typeof__(a) __a = (a); \
  15. __typeof__(b) __b = (b); \
  16. __a < __b ? __a : __b; \
  17. })
  18. /* Return the bigger value of 'a' and 'b'. */
  19. #define max(a, b) ({ \
  20. __typeof__(a) __a = (a); \
  21. __typeof__(b) __b = (b); \
  22. __a > __b ? __a : __b; \
  23. })
  24. /* Return 'value' clamped inbetween 'min_val' and 'max_val'. */
  25. #define clamp(value, min_val, max_val) \
  26. max(min(value, max_val), min_val)
  27. /* Return the absolute value of 'val' */
  28. #undef abs
  29. #define abs(val) ({ \
  30. __typeof__(val) __val = (val); \
  31. __val >= 0 ? __val : -__val; \
  32. })
  33. /* Round an integer 'n' up to a multiple of 's'. */
  34. #define round_up(n, s) ((((n) + (s) - 1) / (s)) * (s))
  35. /* Perform a ceiling division of 'x' / 'd'. */
  36. #define div_round_up(x, d) ({ \
  37. __typeof__(x) __x = (x); \
  38. __typeof__(d) __d = (d); \
  39. (__x + __d - 1) / __d; \
  40. })
  41. /* Divide unsigned integer x by unsigned integer d and
  42. * round to the closest result. */
  43. #define div_round(x, d) ({ \
  44. __typeof__(x) __x = (x); \
  45. __typeof__(d) __d = (d); \
  46. (__x + (__d / 2)) / __d; \
  47. })
  48. /* Swap values 'a' and 'b' in place.
  49. * Also checks whether 'a' and 'b' are of the same type. */
  50. #define swap_values(a, b) do { \
  51. __typeof__(a) __a = (a); \
  52. __typeof__(b) __b = (b); \
  53. __typeof__(a) __tmp = __a; \
  54. (void)((&__a) == (&__b)); \
  55. (a) = __b; \
  56. (b) = __tmp; \
  57. } while (0)
  58. /* Helper to efficiently convert a bit number to
  59. * the corresponding bit mask.
  60. * Resolves at compile-time, if bitnr is a compile-time constant.
  61. * Uses an efficient table lookup otherwise.
  62. */
  63. extern const uint8_t PROGMEM _bit_to_mask8[8];
  64. #define BITMASK8(bitnr) ( \
  65. __builtin_constant_p(bitnr) ? \
  66. (1 << (bitnr)) : \
  67. pgm_read_byte(&_bit_to_mask8[(bitnr)]) \
  68. )
  69. /* Return the number of elements in a C array. */
  70. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  71. /* Progmem pointer annotation. */
  72. #define PROGPTR /* progmem pointer */
  73. /* Memory barrier. */
  74. #define mb() __asm__ __volatile__("" : : : "memory")
  75. /* Do-not-inline function attribute. */
  76. #define noinline __attribute__((__noinline__))
  77. /* Pure-function attribute. */
  78. #define pure_fn __attribute__((__pure__))
  79. /* Const-function attribute. */
  80. #define const_fn __attribute__((__const__))
  81. /* Data structure packing attribute. */
  82. #define _packed __attribute__((__packed__))
  83. /* Build-time assertion.
  84. * 'cond' must be a compile-time constant.
  85. * Build will fail, if 'cond' is false.
  86. */
  87. #define build_assert(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
  88. /* Code flow attributes */
  89. #define noreturn __attribute__((__noreturn__))
  90. #define _mainfunc __attribute__((__OS_main__))
  91. #if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 5
  92. # define unreachable() __builtin_unreachable()
  93. #else
  94. # define unreachable() while (1)
  95. #endif
  96. /* Boolean type. */
  97. typedef _Bool bool;
  98. void reboot(void) noreturn;
  99. void panic(void) noreturn;
  100. #define PANIC_ON(condition) do { if (condition) panic(); } while (0)
  101. void eeprom_read_block_wdtsafe(void *_dst, const void *_src, size_t n);
  102. void eeprom_update_block_wdtsafe(const void *_src, void *dst, size_t n);
  103. /* Disable interrupts globally. */
  104. static inline void irq_disable(void)
  105. {
  106. cli();
  107. mb();
  108. }
  109. /* Enable interrupts globally. */
  110. static inline void irq_enable(void)
  111. {
  112. mb();
  113. sei();
  114. }
  115. /* Save flags and disable interrupts globally. */
  116. static inline uint8_t irq_disable_save(void)
  117. {
  118. uint8_t sreg = SREG;
  119. cli();
  120. mb();
  121. return sreg;
  122. }
  123. /* Restore interrupt flags. */
  124. static inline void irq_restore(uint8_t sreg_flags)
  125. {
  126. mb();
  127. SREG = sreg_flags;
  128. }
  129. /* Check whether the interrupt-enable flag is set in 'sreg_flags' */
  130. static inline bool __irqs_enabled(uint8_t sreg_flags)
  131. {
  132. return !!(sreg_flags & (1 << SREG_I));
  133. }
  134. /* Check whether interrupts are enabled globally. */
  135. static inline bool irqs_enabled(void)
  136. {
  137. return __irqs_enabled(SREG);
  138. }
  139. #endif /* MY_UTIL_H_ */