Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

300 wiersze
9.2 KiB

  1. #include "plsr_profile.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. static int TestFailures;
  5. static int TestChecks;
  6. #define CHECK(condition) \
  7. do \
  8. { \
  9. TestChecks++; \
  10. if (!(condition)) \
  11. { \
  12. TestFailures++; \
  13. (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
  14. } \
  15. } while (0)
  16. /* 跑完一段曲线,返回实际脉冲数与峰值频率。 */
  17. static void RunProfile(const PLSR_PROFILE_REQUEST *request,
  18. int64_t pulses,
  19. uint32_t refreshHz,
  20. uint32_t retargetHz,
  21. uint32_t retargetAfterSteps,
  22. int64_t *actualPulses,
  23. uint32_t *peakHz,
  24. int64_t *steps)
  25. {
  26. PLSR_PROFILE_STATE state;
  27. uint32_t frequency = 0U;
  28. uint8_t completed = 0U;
  29. int64_t stepCount = 0;
  30. uint32_t peak = 0U;
  31. CHECK(PlsrProfileStart(&state, request, pulses, refreshHz)
  32. == PLSR_RESULT_OK);
  33. while ((completed == 0U) && (stepCount < 5000000))
  34. {
  35. (void)PlsrProfileStep(&state, &frequency, &completed);
  36. if (frequency > peak)
  37. {
  38. peak = frequency;
  39. }
  40. stepCount++;
  41. if ((retargetHz != 0U) && (stepCount == retargetAfterSteps))
  42. {
  43. CHECK(PlsrProfileRetarget(&state, retargetHz) == PLSR_RESULT_OK);
  44. }
  45. }
  46. CHECK(completed != 0U);
  47. *actualPulses = (int64_t)(state.emittedPulsesQ32 >> 32U);
  48. *peakHz = peak;
  49. *steps = stepCount;
  50. }
  51. static PLSR_PROFILE_REQUEST MakeRequest(uint32_t targetHz,
  52. uint32_t startHz,
  53. uint32_t stopHz,
  54. uint32_t accelSlope,
  55. uint32_t decelSlope,
  56. uint8_t curveMode)
  57. {
  58. PLSR_PROFILE_REQUEST request;
  59. (void)memset(&request, 0, sizeof(request));
  60. request.targetFrequencyHz = targetHz;
  61. request.startFrequencyHz = startHz;
  62. request.stopFrequencyHz = stopHz;
  63. request.maxFrequencyHz = 100000UL;
  64. request.accelSlopeHzPerMs = accelSlope;
  65. request.decelSlopeHzPerMs = decelSlope;
  66. request.curveMode = curveMode;
  67. return request;
  68. }
  69. static void TestTrapezoid(void)
  70. {
  71. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
  72. int64_t pulses;
  73. uint32_t peak;
  74. int64_t steps;
  75. RunProfile(&request, 20000, 1000U, 0U, 0, &pulses, &peak, &steps);
  76. CHECK(pulses == 20000);
  77. CHECK(peak == 10000U);
  78. CHECK(steps > 2000);
  79. }
  80. static void TestTriangle(void)
  81. {
  82. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
  83. int64_t pulses;
  84. uint32_t peak;
  85. int64_t steps;
  86. /* 脉冲太少:永远到不了目标频率,三角曲线。 */
  87. RunProfile(&request, 100, 1000U, 0U, 0, &pulses, &peak, &steps);
  88. CHECK(pulses == 100);
  89. CHECK(peak < 10000U);
  90. CHECK(peak > 0U);
  91. }
  92. static void TestStartStopSpeed(void)
  93. {
  94. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 1000U, 500U,
  95. 100U, 80U, 0U);
  96. int64_t pulses;
  97. uint32_t peak;
  98. int64_t steps;
  99. RunProfile(&request, 50000, 1000U, 0U, 0, &pulses, &peak, &steps);
  100. CHECK(pulses == 50000);
  101. CHECK(peak == 10000U);
  102. }
  103. static void TestSCurve(void)
  104. {
  105. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 1U);
  106. int64_t pulses;
  107. uint32_t peak;
  108. int64_t steps;
  109. RunProfile(&request, 20000, 1000U, 0U, 0, &pulses, &peak, &steps);
  110. CHECK(pulses == 20000);
  111. CHECK(peak == 10000U);
  112. CHECK(steps > 2000);
  113. }
  114. static void TestSine(void)
  115. {
  116. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 2U);
  117. int64_t pulses;
  118. uint32_t peak;
  119. int64_t steps;
  120. RunProfile(&request, 20000, 1000U, 0U, 0, &pulses, &peak, &steps);
  121. CHECK(pulses == 20000);
  122. CHECK(peak == 10000U);
  123. }
  124. static void TestRetargetUp(void)
  125. {
  126. PLSR_PROFILE_REQUEST request = MakeRequest(5000U, 0U, 0U, 100U, 100U, 0U);
  127. int64_t pulses;
  128. uint32_t peak;
  129. int64_t steps;
  130. /* 运行中升频到 10000:平滑过渡且总脉冲精确。 */
  131. RunProfile(&request, 30000, 1000U, 10000U, 500, &pulses, &peak, &steps);
  132. CHECK(pulses == 30000);
  133. CHECK(peak == 10000U);
  134. }
  135. static void TestRetargetDown(void)
  136. {
  137. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
  138. int64_t pulses;
  139. uint32_t peak;
  140. int64_t steps;
  141. /* 运行中降频到 3000:先减速到新目标再匀速,总脉冲精确。 */
  142. RunProfile(&request, 30000, 1000U, 3000U, 500, &pulses, &peak, &steps);
  143. CHECK(pulses == 30000);
  144. CHECK(peak == 10000U);
  145. CHECK(steps > 600);
  146. }
  147. static void TestNoAccel(void)
  148. {
  149. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 0U, 0U, 0U);
  150. int64_t pulses;
  151. uint32_t peak;
  152. int64_t steps;
  153. RunProfile(&request, 5000, 1000U, 0U, 0, &pulses, &peak, &steps);
  154. CHECK(pulses == 5000);
  155. CHECK(peak == 10000U);
  156. CHECK(steps == 500);
  157. }
  158. static void TestSubMillisecondRefresh(void)
  159. {
  160. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
  161. int64_t pulses;
  162. uint32_t peak;
  163. int64_t steps;
  164. /* 0.1ms 刷新:精度更高,步数是 1ms 的约 10 倍。 */
  165. RunProfile(&request, 20000, 10000U, 0U, 0, &pulses, &peak, &steps);
  166. CHECK(pulses == 20000);
  167. CHECK(peak == 10000U);
  168. CHECK(steps > 20000);
  169. }
  170. static void TestSinglePulse(void)
  171. {
  172. PLSR_PROFILE_REQUEST request = MakeRequest(1000U, 0U, 0U, 100U, 100U, 0U);
  173. int64_t pulses;
  174. uint32_t peak;
  175. int64_t steps;
  176. RunProfile(&request, 1, 1000U, 0U, 0, &pulses, &peak, &steps);
  177. CHECK(pulses == 1);
  178. CHECK(peak <= 1000U);
  179. }
  180. static void TestHighFrequency(void)
  181. {
  182. PLSR_PROFILE_REQUEST request = MakeRequest(100000U, 0U, 0U,
  183. 10000U, 10000U, 0U);
  184. int64_t pulses;
  185. uint32_t peak;
  186. int64_t steps;
  187. RunProfile(&request, 1000000, 1000U, 0U, 0, &pulses, &peak, &steps);
  188. CHECK(pulses == 1000000);
  189. CHECK(peak == 100000U);
  190. }
  191. static void TestArgumentValidation(void)
  192. {
  193. PLSR_PROFILE_STATE state;
  194. PLSR_PROFILE_REQUEST request = MakeRequest(1000U, 0U, 0U, 100U, 100U, 0U);
  195. uint32_t frequency;
  196. uint8_t completed;
  197. CHECK(PlsrProfileStart(NULL, &request, 100, 1000U)
  198. == PLSR_RESULT_INVALID_ARGUMENT);
  199. CHECK(PlsrProfileStart(&state, NULL, 100, 1000U)
  200. == PLSR_RESULT_INVALID_ARGUMENT);
  201. CHECK(PlsrProfileStart(&state, &request, 0, 1000U)
  202. == PLSR_RESULT_INVALID_ARGUMENT);
  203. CHECK(PlsrProfileStart(&state, &request, 100, 0U)
  204. == PLSR_RESULT_INVALID_ARGUMENT);
  205. request.targetFrequencyHz = 0U;
  206. CHECK(PlsrProfileStart(&state, &request, 100, 1000U)
  207. == PLSR_RESULT_INVALID_ARGUMENT);
  208. request.targetFrequencyHz = 1000U;
  209. CHECK(PlsrProfileStep(NULL, &frequency, &completed)
  210. == PLSR_RESULT_INVALID_ARGUMENT);
  211. CHECK(PlsrProfileStep(&state, NULL, &completed)
  212. == PLSR_RESULT_INVALID_ARGUMENT);
  213. CHECK(PlsrProfileStep(&state, &frequency, NULL)
  214. == PLSR_RESULT_INVALID_ARGUMENT);
  215. CHECK(PlsrProfileRetarget(NULL, 2000U) == PLSR_RESULT_INVALID_ARGUMENT);
  216. CHECK(PlsrProfileRetarget(&state, 0U) == PLSR_RESULT_INVALID_ARGUMENT);
  217. }
  218. static void TestPlan(void)
  219. {
  220. PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
  221. PLSR_PROFILE_PLAN plan;
  222. PLSR_PROFILE_REQUEST triangleRequest =
  223. MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
  224. CHECK(PlsrProfilePlan(&request, 20000, &plan) == PLSR_RESULT_OK);
  225. CHECK(plan.accelTimeMs == 100U);
  226. CHECK(plan.decelTimeMs == 100U);
  227. CHECK(plan.triangular == 0U);
  228. CHECK(plan.peakFrequencyHz == 10000U);
  229. CHECK(plan.cruiseTimeMs > 0U);
  230. CHECK(PlsrProfilePlan(&triangleRequest, 100, &plan) == PLSR_RESULT_OK);
  231. CHECK(plan.triangular != 0U);
  232. CHECK(plan.peakFrequencyHz < 10000U);
  233. CHECK(plan.accelTimeMs > 0U);
  234. CHECK(PlsrProfilePlan(NULL, 100, &plan) == PLSR_RESULT_INVALID_ARGUMENT);
  235. CHECK(PlsrProfilePlan(&request, 0, &plan) == PLSR_RESULT_INVALID_ARGUMENT);
  236. CHECK(PlsrProfilePlan(&request, 100, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
  237. }
  238. int main(void)
  239. {
  240. TestTrapezoid();
  241. TestTriangle();
  242. TestStartStopSpeed();
  243. TestSCurve();
  244. TestSine();
  245. TestRetargetUp();
  246. TestRetargetDown();
  247. TestNoAccel();
  248. TestSubMillisecondRefresh();
  249. TestSinglePulse();
  250. TestHighFrequency();
  251. TestArgumentValidation();
  252. TestPlan();
  253. if (TestFailures != 0)
  254. {
  255. (void)printf("FAIL: %d of %d PLSR profile checks failed\n",
  256. TestFailures,
  257. TestChecks);
  258. return 1;
  259. }
  260. (void)printf("PASS: %d PLSR profile checks\n", TestChecks);
  261. return 0;
  262. }