PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

fastled_delay.h 4.6KB

3 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #ifndef __INC_FL_DELAY_H
  2. #define __INC_FL_DELAY_H
  3. #include "FastLED.h"
  4. ///@file fastled_delay.h
  5. ///Utility functions and classes for managing delaycycles
  6. FASTLED_NAMESPACE_BEGIN
  7. /// Class to ensure that a minimum amount of time has kicked since the last time run - and delay if not enough time has passed yet
  8. /// this should make sure that chipsets that have
  9. template<int WAIT> class CMinWait {
  10. uint16_t mLastMicros;
  11. public:
  12. CMinWait() { mLastMicros = 0; }
  13. void wait() {
  14. uint16_t diff;
  15. do {
  16. diff = (micros() & 0xFFFF) - mLastMicros;
  17. } while(diff < WAIT);
  18. }
  19. void mark() { mLastMicros = micros() & 0xFFFF; }
  20. };
  21. ////////////////////////////////////////////////////////////////////////////////////////////
  22. //
  23. // Clock cycle counted delay loop
  24. //
  25. ////////////////////////////////////////////////////////////////////////////////////////////
  26. // Default is now just 'nop', with special case for AVR
  27. // ESP32 core has it's own definition of NOP, so undef it first
  28. #ifdef ESP32
  29. #undef NOP
  30. #undef NOP2
  31. #endif
  32. #if defined(__AVR__)
  33. # define FL_NOP __asm__ __volatile__ ("cp r0,r0\n");
  34. # define FL_NOP2 __asm__ __volatile__ ("rjmp .+0");
  35. #else
  36. # define FL_NOP __asm__ __volatile__ ("nop\n");
  37. # define FL_NOP2 __asm__ __volatile__ ("nop\n\t nop\n");
  38. #endif
  39. // predeclaration to not upset the compiler
  40. template<int CYCLES> inline void delaycycles();
  41. template<int CYCLES> inline void delaycycles_min1() {
  42. delaycycles<1>();
  43. delaycycles<CYCLES-1>();
  44. }
  45. // TODO: ARM version of _delaycycles_
  46. // usable definition
  47. #if defined(FASTLED_AVR)
  48. // worker template - this will nop for LOOP * 3 + PAD cycles total
  49. template<int LOOP, int PAD> inline void _delaycycles_AVR() {
  50. delaycycles<PAD>();
  51. // the loop below is 3 cycles * LOOP. the LDI is one cycle,
  52. // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and
  53. // 1 if not (the LDI balances out the BRNE being 1 cycle on exit)
  54. __asm__ __volatile__ (
  55. " LDI R16, %0\n"
  56. "L_%=: DEC R16\n"
  57. " BRNE L_%=\n"
  58. : /* no outputs */
  59. : "M" (LOOP)
  60. : "r16"
  61. );
  62. }
  63. template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() {
  64. _delaycycles_AVR<CYCLES / 3, CYCLES % 3>();
  65. }
  66. #else
  67. // template<int LOOP, int PAD> inline void _delaycycles_ARM() {
  68. // delaycycles<PAD>();
  69. // // the loop below is 3 cycles * LOOP. the LDI is one cycle,
  70. // // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and
  71. // // 1 if not (the LDI balances out the BRNE being 1 cycle on exit)
  72. // __asm__ __volatile__ (
  73. // " mov.w r9, %0\n"
  74. // "L_%=: subs.w r9, r9, #1\n"
  75. // " bne.n L_%=\n"
  76. // : /* no outputs */
  77. // : "M" (LOOP)
  78. // : "r9"
  79. // );
  80. // }
  81. template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() {
  82. // _delaycycles_ARM<CYCLES / 3, CYCLES % 3>();
  83. FL_NOP; delaycycles<CYCLES-1>();
  84. }
  85. #endif
  86. // pre-instantiations for values small enough to not need the loop, as well as sanity holders
  87. // for some negative values.
  88. template<> __attribute__((always_inline)) inline void delaycycles<-10>() {}
  89. template<> __attribute__((always_inline)) inline void delaycycles<-9>() {}
  90. template<> __attribute__((always_inline)) inline void delaycycles<-8>() {}
  91. template<> __attribute__((always_inline)) inline void delaycycles<-7>() {}
  92. template<> __attribute__((always_inline)) inline void delaycycles<-6>() {}
  93. template<> __attribute__((always_inline)) inline void delaycycles<-5>() {}
  94. template<> __attribute__((always_inline)) inline void delaycycles<-4>() {}
  95. template<> __attribute__((always_inline)) inline void delaycycles<-3>() {}
  96. template<> __attribute__((always_inline)) inline void delaycycles<-2>() {}
  97. template<> __attribute__((always_inline)) inline void delaycycles<-1>() {}
  98. template<> __attribute__((always_inline)) inline void delaycycles<0>() {}
  99. template<> __attribute__((always_inline)) inline void delaycycles<1>() {FL_NOP;}
  100. template<> __attribute__((always_inline)) inline void delaycycles<2>() {FL_NOP2;}
  101. template<> __attribute__((always_inline)) inline void delaycycles<3>() {FL_NOP;FL_NOP2;}
  102. template<> __attribute__((always_inline)) inline void delaycycles<4>() {FL_NOP2;FL_NOP2;}
  103. template<> __attribute__((always_inline)) inline void delaycycles<5>() {FL_NOP2;FL_NOP2;FL_NOP;}
  104. // Some timing related macros/definitions
  105. // Macro to convert from nano-seconds to clocks and clocks to nano-seconds
  106. // #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))
  107. #define F_CPU_MHZ (F_CPU / 1000000L)
  108. // #define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000
  109. #define NS(_NS) (((_NS * F_CPU_MHZ) + 999) / 1000)
  110. #define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 1000000L)
  111. // Macro for making sure there's enough time available
  112. #define NO_TIME(A, B, C) (NS(A) < 3 || NS(B) < 3 || NS(C) < 6)
  113. FASTLED_NAMESPACE_END
  114. #endif