PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

3 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* FreqMeasure Library, for measuring relatively low frequencies
  2. * http://www.pjrc.com/teensy/td_libs_FreqMeasure.html
  3. * Copyright (c) 2011 PJRC.COM, LLC - Paul Stoffregen <paul@pjrc.com>
  4. *
  5. * Version 1.1
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include "FreqMeasure.h"
  26. #include "util/FreqMeasureCapture.h"
  27. #define FREQMEASURE_BUFFER_LEN 12
  28. static volatile uint32_t buffer_value[FREQMEASURE_BUFFER_LEN];
  29. static volatile uint8_t buffer_head;
  30. static volatile uint8_t buffer_tail;
  31. static uint16_t capture_msw;
  32. static uint32_t capture_previous;
  33. void FreqMeasureClass::begin(void)
  34. {
  35. capture_init();
  36. capture_msw = 0;
  37. capture_previous = 0;
  38. buffer_head = 0;
  39. buffer_tail = 0;
  40. capture_start();
  41. }
  42. uint8_t FreqMeasureClass::available(void)
  43. {
  44. uint8_t head, tail;
  45. head = buffer_head;
  46. tail = buffer_tail;
  47. if (head >= tail) return head - tail;
  48. return FREQMEASURE_BUFFER_LEN + head - tail;
  49. }
  50. uint32_t FreqMeasureClass::read(void)
  51. {
  52. uint8_t head, tail;
  53. uint32_t value;
  54. head = buffer_head;
  55. tail = buffer_tail;
  56. if (head == tail) return 0xFFFFFFFF;
  57. tail = tail + 1;
  58. if (tail >= FREQMEASURE_BUFFER_LEN) tail = 0;
  59. value = buffer_value[tail];
  60. buffer_tail = tail;
  61. return value;
  62. }
  63. float FreqMeasureClass::countToFrequency(uint32_t count)
  64. {
  65. #if defined(__AVR__)
  66. return (float)F_CPU / (float)count;
  67. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  68. return (float)F_BUS / (float)count;
  69. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  70. return (float)(F_PLL/2) / (float)count;
  71. #elif defined(__arm__) && defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))
  72. return (float)F_BUS_ACTUAL / (float)count;
  73. #endif
  74. }
  75. float FreqMeasureClass::countToNanoseconds(uint32_t count)
  76. {
  77. #if defined(__AVR__)
  78. return (float)count * (1000000000.0f / (float)F_CPU);
  79. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  80. return (float)count * (1000000000.0f / (float)F_BUS);
  81. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  82. return (float)count * (2000000000.0f / (float)F_PLL);
  83. #elif defined(__arm__) && defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))
  84. return (float)count * 1000000000.0f / (float)F_BUS_ACTUAL;
  85. #else
  86. return 0.0;
  87. #endif
  88. }
  89. void FreqMeasureClass::end(void)
  90. {
  91. capture_shutdown();
  92. }
  93. #if defined(__AVR__)
  94. ISR(TIMER_OVERFLOW_VECTOR)
  95. {
  96. capture_msw++;
  97. }
  98. ISR(TIMER_CAPTURE_VECTOR)
  99. {
  100. uint16_t capture_lsw;
  101. uint32_t capture, period;
  102. uint8_t i;
  103. // get the timer capture
  104. capture_lsw = capture_read();
  105. // Handle the case where but capture and overflow interrupts were pending
  106. // (eg, interrupts were disabled for a while), or where the overflow occurred
  107. // while this ISR was starting up. However, if we read a 16 bit number that
  108. // is very close to overflow, then ignore any overflow since it probably
  109. // just happened.
  110. if (capture_overflow() && capture_lsw < 0xFF00) {
  111. capture_overflow_reset();
  112. capture_msw++;
  113. }
  114. // compute the waveform period
  115. capture = ((uint32_t)capture_msw << 16) | capture_lsw;
  116. period = capture - capture_previous;
  117. capture_previous = capture;
  118. // store it into the buffer
  119. i = buffer_head + 1;
  120. if (i >= FREQMEASURE_BUFFER_LEN) i = 0;
  121. if (i != buffer_tail) {
  122. buffer_value[i] = period;
  123. buffer_head = i;
  124. }
  125. }
  126. #elif defined(__arm__) && defined(TEENSYDUINO)
  127. void FTM_ISR_NAME (void)
  128. {
  129. uint32_t capture, period, i;
  130. bool inc = false;
  131. if (capture_overflow()) {
  132. capture_overflow_reset();
  133. capture_msw++;
  134. inc = true;
  135. }
  136. if (capture_event()) {
  137. capture = capture_read();
  138. if (capture <= 0xE000 || !inc) {
  139. capture |= (capture_msw << 16);
  140. } else {
  141. capture |= ((capture_msw - 1) << 16);
  142. }
  143. // compute the waveform period
  144. period = capture - capture_previous;
  145. capture_previous = capture;
  146. // store it into the buffer
  147. i = buffer_head + 1;
  148. if (i >= FREQMEASURE_BUFFER_LEN) i = 0;
  149. if (i != buffer_tail) {
  150. buffer_value[i] = period;
  151. buffer_head = i;
  152. }
  153. }
  154. }
  155. #endif
  156. FreqMeasureClass FreqMeasure;