mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-21 23:19:02 +00:00
* Refactor clock delays and improve JTAG runtest timing logic * Refactor time calculations to use CH_FREQUENCY for consistency across modules * Improve delay mechanism for reference oscillator startup in portapack_tcxo_enable * comment * increasing the time * copilot
This commit is contained in:
@@ -59,7 +59,7 @@ void DfuMenu::paint(Painter& painter) {
|
||||
text_info_line_7.set(to_string_dec_uint(shared_memory.m4_stack_usage, 6));
|
||||
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
|
||||
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
|
||||
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
|
||||
text_info_line_10.set(to_string_dec_uint(chTimeNow() / CH_FREQUENCY, 6));
|
||||
|
||||
constexpr auto margin = 5;
|
||||
|
||||
|
||||
@@ -1012,10 +1012,17 @@ void SetTouchscreenThresholdView::focus() {
|
||||
|
||||
void SetTouchscreenThresholdView::on_frame_sync() {
|
||||
if (!in_auto_detect) return;
|
||||
|
||||
uint32_t time_now = chTimeNow();
|
||||
int32_t time_diff = time_now - time_start_auto_detect;
|
||||
text_wait_timer.set("ETA " + to_string_dec_uint((10 - time_diff / 1000) <= 0 ? 0 : 10 - time_diff / 1000) + "s");
|
||||
if (time_diff >= 10001 && !auto_detect_succeed_consumed) { // 10s
|
||||
|
||||
// Calculate elapsed seconds using CH_FREQUENCY
|
||||
uint32_t elapsed_seconds = time_diff / CH_FREQUENCY;
|
||||
int32_t remaining_seconds = 10 - (int32_t)elapsed_seconds;
|
||||
if (remaining_seconds < 0) remaining_seconds = 0;
|
||||
|
||||
text_wait_timer.set("ETA " + to_string_dec_uint(remaining_seconds) + "s");
|
||||
if (elapsed_seconds >= 10 && !auto_detect_succeed_consumed) { // 10s
|
||||
in_auto_detect = false;
|
||||
text_wait_timer.hidden(true);
|
||||
text_hint.set("OK, press save and reboot");
|
||||
|
||||
@@ -428,7 +428,7 @@ void ClockManager::portapack_tcxo_enable() {
|
||||
|
||||
/* Delay >10ms at 96MHz clock speed for reference oscillator to start. */
|
||||
/* Delay an additional 1ms (arbitrary) for the clock generator to detect a signal. */
|
||||
volatile uint32_t delay = 240000 + 24000;
|
||||
volatile uint32_t delay = 2400000 + 24000;
|
||||
while (delay--);
|
||||
}
|
||||
|
||||
@@ -668,37 +668,37 @@ ClockManager::ReferenceSource ClockManager::detect_reference_source() {
|
||||
}
|
||||
|
||||
ClockManager::Reference ClockManager::choose_reference() {
|
||||
#ifdef PRALINE
|
||||
const auto detected_reference = detect_reference_source();
|
||||
|
||||
if ((detected_reference == ReferenceSource::External) ||
|
||||
(detected_reference == ReferenceSource::PortaPack)) {
|
||||
const auto frequency = measure_gp_clkin_frequency();
|
||||
if ((frequency >= 9850000) && (frequency <= 10150000)) {
|
||||
return {detected_reference, 10000000};
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef PRALINE
|
||||
if (hackrf_r9) {
|
||||
gpio_control::r9_clkin_en.setActive();
|
||||
volatile uint32_t delay = 240000 + 24000;
|
||||
// Allow extra time for slower TCXOs on clone boards to stabilize before measurement
|
||||
volatile uint32_t delay = 240000 + 240000;
|
||||
while (delay--);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine reference source (respects user config and Si5351 loss-of-signal)
|
||||
const auto detected_reference = detect_reference_source();
|
||||
|
||||
// If an external or PortaPack source is detected, verify its actual frequency
|
||||
if ((detected_reference == ReferenceSource::External) ||
|
||||
(detected_reference == ReferenceSource::PortaPack)) {
|
||||
const auto frequency = measure_gp_clkin_frequency();
|
||||
|
||||
// Check if the measured frequency is within the valid 10 MHz range
|
||||
if ((frequency >= 9850000) && (frequency <= 10150000)) {
|
||||
return {detected_reference, 10000000};
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PRALINE
|
||||
if (hackrf_r9) {
|
||||
// Disable r9 clock input if the 10 MHz validation failed
|
||||
gpio_control::r9_clkin_en.setInactive();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fallback: Disable PortaPack TCXO and default to the HackRF 25 MHz crystal
|
||||
portapack_tcxo_disable();
|
||||
return {ReferenceSource::Xtal, 25000000};
|
||||
}
|
||||
|
||||
@@ -1130,13 +1130,18 @@ void SystemView::toggle_overlay() {
|
||||
}
|
||||
|
||||
void SystemView::paint_overlay() {
|
||||
static bool last_paint_state = false;
|
||||
// Static variable to store the timestamp of the last update
|
||||
static systime_t last_update_time = 0;
|
||||
|
||||
if (overlay_active) {
|
||||
// paint background only every other second
|
||||
if ((((chTimeNow() >> 10) & 0x01) == 0x01) == last_paint_state)
|
||||
// Update exactly once per second (CH_FREQUENCY equals 1 second of ticks)
|
||||
// This replaces the old hardcoded bit-shift logic for better portability
|
||||
if ((chTimeNow() - last_update_time) < CH_FREQUENCY)
|
||||
return;
|
||||
|
||||
last_paint_state = !last_paint_state;
|
||||
// One second has passed, save the new timestamp
|
||||
last_update_time = chTimeNow();
|
||||
|
||||
if (overlay_active == 1 && overlay)
|
||||
overlay->set_dirty();
|
||||
else if (overlay_active == 2 && overlay2)
|
||||
|
||||
@@ -1180,7 +1180,7 @@ static void cmd_sysinfo(BaseSequentialStream* chp, int argc, char* argv[]) {
|
||||
"M4 stack: " + to_string_dec_uint(shared_memory.m4_stack_usage) + "\r\n" +
|
||||
"M0 cpu%: " + to_string_dec_uint(shared_memory.m4_performance_counter) + "\r\n" +
|
||||
"M4 miss: " + to_string_dec_uint(shared_memory.m4_buffer_missed) + "\r\n" +
|
||||
"uptime: " + to_string_dec_uint(chTimeNow() / 1000) + "\r\n";
|
||||
"uptime: " + to_string_dec_uint(chTimeNow() / CH_FREQUENCY) + "\r\n";
|
||||
|
||||
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)info.c_str(), info.length());
|
||||
return;
|
||||
|
||||
@@ -125,15 +125,18 @@ void update_performance_counters() {
|
||||
if (performance_counter_active == 0x00)
|
||||
return;
|
||||
|
||||
static bool last_paint_state = false;
|
||||
if ((((chTimeNow() >> 10) & 0x01) == 0x01) == last_paint_state)
|
||||
static systime_t last_update_time = 0;
|
||||
|
||||
// The MS2ST(1000) guarantees that this is exactly 1 second, regardless of the system clock setting.
|
||||
if ((chTimeNow() - last_update_time) < MS2ST(1000))
|
||||
return;
|
||||
|
||||
// Idle thread state is sometimes unuseable
|
||||
if (chThdGetTicks(chSysGetIdleThread()) > 0x10000000)
|
||||
return;
|
||||
|
||||
last_paint_state = !last_paint_state;
|
||||
// Update the last update time
|
||||
last_update_time = chTimeNow();
|
||||
|
||||
if (performance_counter_active == 0x01) {
|
||||
auto utilisation = get_cpu_utilisation_in_percent();
|
||||
|
||||
@@ -318,29 +318,33 @@ void I2CDevManager::create_thread() {
|
||||
msg_t I2CDevManager::timer_fn(void* arg) {
|
||||
(void)arg;
|
||||
uint16_t curr_timer = 0; // seconds since thread start
|
||||
|
||||
while (1) {
|
||||
systime_t start_time = chTimeNow();
|
||||
bool changed = false;
|
||||
// check if i2c scan needed
|
||||
|
||||
// Check if i2c scan is needed
|
||||
if (force_scan || (scan_interval != 0 && curr_timer % scan_interval == 0)) {
|
||||
changed = changed | scan();
|
||||
force_scan = false;
|
||||
}
|
||||
|
||||
// Update connected devices based on their own intervals
|
||||
for (size_t i = 0; i < devlist.size(); i++) {
|
||||
if (devlist[i].addr != 0 && devlist[i].dev && devlist[i].dev->query_interval != 0) {
|
||||
if ((curr_timer % devlist[i].dev->query_interval) == 0) { // only if it is device's interval
|
||||
devlist[i].dev->update(); // updates it's data, and broadcasts it. if there is any error it will handle in it, and later we can remove it
|
||||
if ((curr_timer % devlist[i].dev->query_interval) == 0) {
|
||||
devlist[i].dev->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove all unneeded items
|
||||
// Remove all unneeded items (dead devices or devices throwing too many errors)
|
||||
chMtxLock(&mutex_list);
|
||||
size_t cnt = devlist.size();
|
||||
devlist.erase(std::remove_if(devlist.begin(), devlist.end(), [](const I2DevListElement& x) {
|
||||
if (x.addr == 0) return true;
|
||||
if (x.dev && x.dev->need_del == true) return true; // self destruct on too many errors
|
||||
return false; // won't remove the unidentified ones, so we can list them, and not trying all the time with them
|
||||
if (x.dev && x.dev->need_del == true) return true;
|
||||
return false;
|
||||
}),
|
||||
devlist.end());
|
||||
chMtxUnlock();
|
||||
@@ -350,11 +354,24 @@ msg_t I2CDevManager::timer_fn(void* arg) {
|
||||
I2CDevListChangedMessage msg{};
|
||||
EventDispatcher::send_message(msg);
|
||||
}
|
||||
systime_t end_time = chTimeNow();
|
||||
systime_t delta = (end_time > start_time) ? end_time - start_time : 100; // wont calculate overflow, just guess.
|
||||
if (delta > 950) delta = 950; // ensure minimum 50 milli sleep
|
||||
|
||||
chThdSleepMilliseconds(1000 - delta); // 1sec timer
|
||||
systime_t end_time = chTimeNow();
|
||||
|
||||
// 1. Calculate elapsed ticks safely handling overflow
|
||||
uint32_t delta_ticks = end_time - start_time;
|
||||
|
||||
// 2. Keep EVERYTHING in ticks (No MS conversion!) to prevent truncation drift
|
||||
if (delta_ticks < CH_FREQUENCY) {
|
||||
// Calculate exactly how many ticks are missing to complete 1 full second
|
||||
uint32_t sleep_ticks = CH_FREQUENCY - delta_ticks;
|
||||
|
||||
// Sleep using native ticks instead of milliseconds
|
||||
chThdSleep(sleep_ticks);
|
||||
} else {
|
||||
// Safety fallback: if processing took longer than 1 second, sleep 50ms to yield CPU
|
||||
chThdSleepMilliseconds(50);
|
||||
}
|
||||
|
||||
++curr_timer;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -59,8 +59,10 @@ class JTAG {
|
||||
|
||||
void runtest_ms(const size_t count) {
|
||||
auto starttime = chTimeNow();
|
||||
// We convert the count in milliseconds to system ticks:
|
||||
auto duration_ticks = MS2ST(count) + 1;
|
||||
|
||||
while ((chTimeNow() - starttime) < (count + 1))
|
||||
while ((chTimeNow() - starttime) < duration_ticks)
|
||||
target.clock(0, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user