|
- #include "plsr_profile.h"
- #include <stdio.h>
- #include <string.h>
-
- static int TestFailures;
- static int TestChecks;
-
- #define CHECK(condition) \
- do \
- { \
- TestChecks++; \
- if (!(condition)) \
- { \
- TestFailures++; \
- (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
- } \
- } while (0)
-
- /* 跑完一段曲线,返回实际脉冲数与峰值频率。 */
- static void RunProfile(const PLSR_PROFILE_REQUEST *request,
- int64_t pulses,
- uint32_t refreshHz,
- uint32_t retargetHz,
- uint32_t retargetAfterSteps,
- int64_t *actualPulses,
- uint32_t *peakHz,
- int64_t *steps)
- {
- PLSR_PROFILE_STATE state;
- uint32_t frequency = 0U;
- uint8_t completed = 0U;
- int64_t stepCount = 0;
- uint32_t peak = 0U;
-
- CHECK(PlsrProfileStart(&state, request, pulses, refreshHz)
- == PLSR_RESULT_OK);
- while ((completed == 0U) && (stepCount < 5000000))
- {
- (void)PlsrProfileStep(&state, &frequency, &completed);
- if (frequency > peak)
- {
- peak = frequency;
- }
- stepCount++;
- if ((retargetHz != 0U) && (stepCount == retargetAfterSteps))
- {
- CHECK(PlsrProfileRetarget(&state, retargetHz) == PLSR_RESULT_OK);
- }
- }
- CHECK(completed != 0U);
- *actualPulses = (int64_t)(state.emittedPulsesQ32 >> 32U);
- *peakHz = peak;
- *steps = stepCount;
- }
-
- static PLSR_PROFILE_REQUEST MakeRequest(uint32_t targetHz,
- uint32_t startHz,
- uint32_t stopHz,
- uint32_t accelSlope,
- uint32_t decelSlope,
- uint8_t curveMode)
- {
- PLSR_PROFILE_REQUEST request;
-
- (void)memset(&request, 0, sizeof(request));
- request.targetFrequencyHz = targetHz;
- request.startFrequencyHz = startHz;
- request.stopFrequencyHz = stopHz;
- request.maxFrequencyHz = 100000UL;
- request.accelSlopeHzPerMs = accelSlope;
- request.decelSlopeHzPerMs = decelSlope;
- request.curveMode = curveMode;
- return request;
- }
-
- static void TestTrapezoid(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 20000, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 20000);
- CHECK(peak == 10000U);
- CHECK(steps > 2000);
- }
-
- static void TestTriangle(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- /* 脉冲太少:永远到不了目标频率,三角曲线。 */
- RunProfile(&request, 100, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 100);
- CHECK(peak < 10000U);
- CHECK(peak > 0U);
- }
-
- static void TestStartStopSpeed(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 1000U, 500U,
- 100U, 80U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 50000, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 50000);
- CHECK(peak == 10000U);
- }
-
- static void TestSCurve(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 1U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 20000, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 20000);
- CHECK(peak == 10000U);
- CHECK(steps > 2000);
- }
-
- static void TestSine(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 2U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 20000, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 20000);
- CHECK(peak == 10000U);
- }
-
- static void TestRetargetUp(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(5000U, 0U, 0U, 100U, 100U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- /* 运行中升频到 10000:平滑过渡且总脉冲精确。 */
- RunProfile(&request, 30000, 1000U, 10000U, 500, &pulses, &peak, &steps);
- CHECK(pulses == 30000);
- CHECK(peak == 10000U);
- }
-
- static void TestRetargetDown(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- /* 运行中降频到 3000:先减速到新目标再匀速,总脉冲精确。 */
- RunProfile(&request, 30000, 1000U, 3000U, 500, &pulses, &peak, &steps);
- CHECK(pulses == 30000);
- CHECK(peak == 10000U);
- CHECK(steps > 600);
- }
-
- static void TestNoAccel(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 0U, 0U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 5000, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 5000);
- CHECK(peak == 10000U);
- CHECK(steps == 500);
- }
-
- static void TestSubMillisecondRefresh(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- /* 0.1ms 刷新:精度更高,步数是 1ms 的约 10 倍。 */
- RunProfile(&request, 20000, 10000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 20000);
- CHECK(peak == 10000U);
- CHECK(steps > 20000);
- }
-
- static void TestSinglePulse(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(1000U, 0U, 0U, 100U, 100U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 1, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 1);
- CHECK(peak <= 1000U);
- }
-
- static void TestHighFrequency(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(100000U, 0U, 0U,
- 10000U, 10000U, 0U);
- int64_t pulses;
- uint32_t peak;
- int64_t steps;
-
- RunProfile(&request, 1000000, 1000U, 0U, 0, &pulses, &peak, &steps);
- CHECK(pulses == 1000000);
- CHECK(peak == 100000U);
- }
-
- static void TestArgumentValidation(void)
- {
- PLSR_PROFILE_STATE state;
- PLSR_PROFILE_REQUEST request = MakeRequest(1000U, 0U, 0U, 100U, 100U, 0U);
- uint32_t frequency;
- uint8_t completed;
-
- CHECK(PlsrProfileStart(NULL, &request, 100, 1000U)
- == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileStart(&state, NULL, 100, 1000U)
- == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileStart(&state, &request, 0, 1000U)
- == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileStart(&state, &request, 100, 0U)
- == PLSR_RESULT_INVALID_ARGUMENT);
- request.targetFrequencyHz = 0U;
- CHECK(PlsrProfileStart(&state, &request, 100, 1000U)
- == PLSR_RESULT_INVALID_ARGUMENT);
- request.targetFrequencyHz = 1000U;
-
- CHECK(PlsrProfileStep(NULL, &frequency, &completed)
- == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileStep(&state, NULL, &completed)
- == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileStep(&state, &frequency, NULL)
- == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileRetarget(NULL, 2000U) == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfileRetarget(&state, 0U) == PLSR_RESULT_INVALID_ARGUMENT);
- }
-
- static void TestPlan(void)
- {
- PLSR_PROFILE_REQUEST request = MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
- PLSR_PROFILE_PLAN plan;
- PLSR_PROFILE_REQUEST triangleRequest =
- MakeRequest(10000U, 0U, 0U, 100U, 100U, 0U);
-
- CHECK(PlsrProfilePlan(&request, 20000, &plan) == PLSR_RESULT_OK);
- CHECK(plan.accelTimeMs == 100U);
- CHECK(plan.decelTimeMs == 100U);
- CHECK(plan.triangular == 0U);
- CHECK(plan.peakFrequencyHz == 10000U);
- CHECK(plan.cruiseTimeMs > 0U);
-
- CHECK(PlsrProfilePlan(&triangleRequest, 100, &plan) == PLSR_RESULT_OK);
- CHECK(plan.triangular != 0U);
- CHECK(plan.peakFrequencyHz < 10000U);
- CHECK(plan.accelTimeMs > 0U);
-
- CHECK(PlsrProfilePlan(NULL, 100, &plan) == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfilePlan(&request, 0, &plan) == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrProfilePlan(&request, 100, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
- }
-
- int main(void)
- {
- TestTrapezoid();
- TestTriangle();
- TestStartStopSpeed();
- TestSCurve();
- TestSine();
- TestRetargetUp();
- TestRetargetDown();
- TestNoAccel();
- TestSubMillisecondRefresh();
- TestSinglePulse();
- TestHighFrequency();
- TestArgumentValidation();
- TestPlan();
-
- if (TestFailures != 0)
- {
- (void)printf("FAIL: %d of %d PLSR profile checks failed\n",
- TestFailures,
- TestChecks);
- return 1;
- }
- (void)printf("PASS: %d PLSR profile checks\n", TestChecks);
- return 0;
- }
|