codex init
This commit is contained in:
101
OpticalChannelTester/Core.cpp
Normal file
101
OpticalChannelTester/Core.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "Core.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
const char *roleName(Role r) {
|
||||
static const char *names[] = {"SOLO", "MASTER", "SLAVE"};
|
||||
const uint8_t i = static_cast<uint8_t>(r);
|
||||
return i < 3 ? names[i] : "?";
|
||||
}
|
||||
|
||||
const char *failName(FailReason r) {
|
||||
static const char *names[] = {"NONE", "NO SIGNAL", "PERIOD OUT", "DUTY OUT",
|
||||
"EXTRA EDGE", "GLITCH", "LOST EDGE", "TOO FEW PERIODS", "LINK LOST",
|
||||
"UNSUPPORTED", "RESOLUTION", "ABORTED"};
|
||||
const uint8_t i = static_cast<uint8_t>(r);
|
||||
return i < (sizeof(names) / sizeof(names[0])) ? names[i] : "UNKNOWN";
|
||||
}
|
||||
|
||||
void StageStats::reset() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
minPeriod = minActive = UINT32_MAX;
|
||||
reason = FailReason::NONE;
|
||||
}
|
||||
|
||||
uint32_t settingsChecksum(const Settings &s) {
|
||||
const uint8_t *p = reinterpret_cast<const uint8_t *>(&s);
|
||||
const size_t n = offsetof(Settings, checksum);
|
||||
uint32_t hash = 2166136261UL;
|
||||
for (size_t i = 0; i < n; ++i) { hash ^= p[i]; hash *= 16777619UL; }
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t frequencyPointCount(uint32_t startHz, uint32_t endHz, uint32_t stepHz) {
|
||||
if (!startHz || !stepHz || endHz <= startHz) return 0;
|
||||
const uint64_t span = static_cast<uint64_t>(endHz) - startHz;
|
||||
return static_cast<uint32_t>(span / stepHz + 1U + ((span % stepHz) ? 1U : 0U));
|
||||
}
|
||||
|
||||
uint32_t frequencyAt(uint32_t startHz, uint32_t endHz, uint32_t stepHz, uint32_t index) {
|
||||
const uint32_t count = frequencyPointCount(startHz, endHz, stepHz);
|
||||
if (!count || index >= count) return 0;
|
||||
if (index == count - 1) return endHz;
|
||||
const uint64_t v = static_cast<uint64_t>(startHz) + static_cast<uint64_t>(stepHz) * index;
|
||||
return v < endHz ? static_cast<uint32_t>(v) : endHz;
|
||||
}
|
||||
|
||||
uint64_t nominalTotalUs(const TestParams &p, uint32_t settleCycles) {
|
||||
uint64_t total = 0;
|
||||
const uint32_t count = frequencyPointCount(p.startHz, p.endHz, p.stepHz);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const uint32_t f = frequencyAt(p.startHz, p.endHz, p.stepHz, i);
|
||||
total += (1000000ULL * settleCycles + f - 1) / f;
|
||||
total += static_cast<uint64_t>(p.testTimeMs) * 1000ULL * p.repeats;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
bool periodWithin(float measured, float expected, float tolerance) {
|
||||
return expected > 0.0f && fabsf(measured - expected) * 100.0f / expected <= tolerance + 0.0001f;
|
||||
}
|
||||
|
||||
bool dutyWithin(float measured, float expected, float tolerance) {
|
||||
return fabsf(measured - expected) <= tolerance + 0.0001f;
|
||||
}
|
||||
|
||||
FailReason validateResolution(uint32_t frequencyHz, float dutyPct, float accuracyPct,
|
||||
uint32_t captureHz, uint8_t pwmBits) {
|
||||
if (!frequencyHz || !captureHz || !pwmBits) return FailReason::RESOLUTION;
|
||||
const float periodTicks = static_cast<float>(captureHz) / frequencyHz;
|
||||
const float activeTicks = periodTicks * dutyPct / 100.0f;
|
||||
const float inactiveTicks = periodTicks - activeTicks;
|
||||
if (periodTicks < 4.0f || activeTicks < 2.0f || inactiveTicks < 2.0f) return FailReason::RESOLUTION;
|
||||
const float timerPeriodError = 100.0f / periodTicks;
|
||||
const float timerDutyError = 100.0f / periodTicks;
|
||||
const float pwmDutyStep = 100.0f / static_cast<float>((1UL << pwmBits) - 1UL);
|
||||
return (timerPeriodError > accuracyPct || timerDutyError > accuracyPct || pwmDutyStep > accuracyPct)
|
||||
? FailReason::RESOLUTION : FailReason::NONE;
|
||||
}
|
||||
|
||||
FailReason evaluatePeriod(const PulsePeriod &p, uint32_t tickHz, float expectedHz,
|
||||
float expectedDuty, float tolerance, uint8_t repeat,
|
||||
StageStats &s) {
|
||||
if (!p.periodTicks || p.activeTicks >= p.periodTicks) return FailReason::EXTRA_EDGE;
|
||||
const float hz = static_cast<float>(tickHz) / p.periodTicks;
|
||||
const float duty = 100.0f * p.activeTicks / p.periodTicks;
|
||||
++s.periods;
|
||||
s.periodSum += p.periodTicks; s.activeSum += p.activeTicks;
|
||||
if (p.periodTicks < s.minPeriod) s.minPeriod = p.periodTicks;
|
||||
if (p.periodTicks > s.maxPeriod) s.maxPeriod = p.periodTicks;
|
||||
if (p.activeTicks < s.minActive) s.minActive = p.activeTicks;
|
||||
if (p.activeTicks > s.maxActive) s.maxActive = p.activeTicks;
|
||||
FailReason reason = FailReason::NONE;
|
||||
if (!periodWithin(hz, expectedHz, tolerance)) reason = FailReason::PERIOD_OUT;
|
||||
else if (!dutyWithin(duty, expectedDuty, tolerance)) reason = FailReason::DUTY_OUT;
|
||||
if (reason != FailReason::NONE && s.reason == FailReason::NONE) {
|
||||
s.reason = reason; s.firstBadPeriod = s.periods; s.firstBadRepeat = repeat;
|
||||
s.badFrequency = hz; s.badDuty = duty;
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user