LapCounter finished and working
This commit is contained in:
@@ -35,6 +35,8 @@ enum Type : uint8_t {
|
|||||||
DisplayMsgBatteryLow,
|
DisplayMsgBatteryLow,
|
||||||
DisplayMsgEngineTempLow,
|
DisplayMsgEngineTempLow,
|
||||||
DisplayMsgEngineTempHigh,
|
DisplayMsgEngineTempHigh,
|
||||||
|
DisplayMsgLapCounterStart,
|
||||||
|
DisplayMsgLapCounterLapTime,
|
||||||
ConfigTrackDetect,
|
ConfigTrackDetect,
|
||||||
ConfigWriteTempTrack,
|
ConfigWriteTempTrack,
|
||||||
ConfigTrackDelete,
|
ConfigTrackDelete,
|
||||||
@@ -46,6 +48,7 @@ enum Type : uint8_t {
|
|||||||
BatteryCal,
|
BatteryCal,
|
||||||
AllConfigUpdated,
|
AllConfigUpdated,
|
||||||
AllTrackLoaded,
|
AllTrackLoaded,
|
||||||
|
AllStartLineTriggered,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace task
|
} // namespace task
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ struct GpsData {
|
|||||||
GpsSubData lng_;
|
GpsSubData lng_;
|
||||||
GpsSubData speed_;
|
GpsSubData speed_;
|
||||||
GpsSubData course_;
|
GpsSubData course_;
|
||||||
|
uint32_t time_;
|
||||||
|
uint32_t time_write_time_;
|
||||||
uint32_t num_fix_;
|
uint32_t num_fix_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,3 +77,15 @@ template<typename T>
|
|||||||
inline void copyToVolatile(volatile T& dst, const T& src) {
|
inline void copyToVolatile(volatile T& dst, const T& src) {
|
||||||
memcpy((void*)&dst, &src, sizeof(T));
|
memcpy((void*)&dst, &src, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t hhmmsscc_to_cs(uint32_t t) {
|
||||||
|
uint32_t hours = t / 1000000;
|
||||||
|
uint32_t minutes = (t / 10000) % 100;
|
||||||
|
uint32_t seconds = (t / 100) % 100;
|
||||||
|
uint32_t cs = t % 100;
|
||||||
|
|
||||||
|
return hours * 360000 +
|
||||||
|
minutes * 6000 +
|
||||||
|
seconds * 100 +
|
||||||
|
cs;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,27 +6,20 @@
|
|||||||
volatile float vbat_global = 0;
|
volatile float vbat_global = 0;
|
||||||
volatile float teng_global = 0;
|
volatile float teng_global = 0;
|
||||||
volatile int gps_trigger_global = 0;
|
volatile int gps_trigger_global = 0;
|
||||||
|
volatile uint32_t last_lap_time_global = 0;
|
||||||
|
|
||||||
void vbatGlobalRead(float& out) {
|
void vbatGlobalRead(float &out) { out = vbat_global; }
|
||||||
out = vbat_global;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vbatGlobalWrite(const float& in) {
|
void vbatGlobalWrite(const float &in) { vbat_global = in; }
|
||||||
vbat_global = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tengGlobalRead(float& out) {
|
void tengGlobalRead(float &out) { out = teng_global; }
|
||||||
out = teng_global;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tengGlobalWrite(const float& in) {
|
void tengGlobalWrite(const float &in) { teng_global = in; }
|
||||||
teng_global = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpsTriggerGlobalRead(int& out) {
|
void gpsTriggerGlobalRead(int &out) { out = gps_trigger_global; }
|
||||||
out = gps_trigger_global;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpsTriggerGlobalWrite(const int& in) {
|
void gpsTriggerGlobalWrite(const int &in) { gps_trigger_global = in; }
|
||||||
gps_trigger_global = in;
|
|
||||||
}
|
void lastLapTimeGlobalRead(uint32_t &out) { out = last_lap_time_global; }
|
||||||
|
|
||||||
|
void lastLapTimeGlobalWrite(const uint32_t &in) { last_lap_time_global = in; }
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
|
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
extern volatile float vbat_global;
|
extern volatile float vbat_global;
|
||||||
extern volatile float teng_global;
|
extern volatile float teng_global;
|
||||||
extern volatile int gps_trigger_global;
|
extern volatile int gps_trigger_global;
|
||||||
|
extern volatile uint32_t last_lap_time_global;
|
||||||
|
|
||||||
void vbatGlobalRead(float& out);
|
void vbatGlobalRead(float& out);
|
||||||
void vbatGlobalWrite(const float& in);
|
void vbatGlobalWrite(const float& in);
|
||||||
@@ -15,3 +17,6 @@ void tengGlobalWrite(const float& in);
|
|||||||
|
|
||||||
void gpsTriggerGlobalRead(int& out);
|
void gpsTriggerGlobalRead(int& out);
|
||||||
void gpsTriggerGlobalWrite(const int& in);
|
void gpsTriggerGlobalWrite(const int& in);
|
||||||
|
|
||||||
|
void lastLapTimeGlobalRead(uint32_t& in);
|
||||||
|
void lastLapTimeGlobalWrite(const uint32_t& out);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "modules/battery/battery.h"
|
#include "modules/battery/battery.h"
|
||||||
#include "modules/thermocouple/thermocouple.h"
|
#include "modules/thermocouple/thermocouple.h"
|
||||||
#include "modules/telemetry/telemetry.h"
|
#include "modules/telemetry/telemetry.h"
|
||||||
|
#include "modules/lap_counter/lap_counter.h"
|
||||||
|
|
||||||
|
|
||||||
SystemLogger *logger = new SystemLogger(&Serial);
|
SystemLogger *logger = new SystemLogger(&Serial);
|
||||||
@@ -27,6 +28,7 @@ Cmd *command_handler = new Cmd(&Serial, logger);
|
|||||||
Battery *battery_module = new Battery(logger);
|
Battery *battery_module = new Battery(logger);
|
||||||
Thermocouple *thermocouple_module = new Thermocouple(logger);
|
Thermocouple *thermocouple_module = new Thermocouple(logger);
|
||||||
Telemetry *telemetry_module = new Telemetry(&Serial1, logger);
|
Telemetry *telemetry_module = new Telemetry(&Serial1, logger);
|
||||||
|
LapCounter *lap_counter_modules = new LapCounter(logger);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@ void setup() {
|
|||||||
module_registry[module::Battery] = battery_module;
|
module_registry[module::Battery] = battery_module;
|
||||||
module_registry[module::Thermocouple] = thermocouple_module;
|
module_registry[module::Thermocouple] = thermocouple_module;
|
||||||
module_registry[module::Telemetry] = telemetry_module;
|
module_registry[module::Telemetry] = telemetry_module;
|
||||||
|
module_registry[module::LapCounter] = lap_counter_modules;
|
||||||
|
|
||||||
display->init();
|
display->init();
|
||||||
display->printMessage("Starting Initialization");
|
display->printMessage("Starting Initialization");
|
||||||
@@ -63,6 +66,7 @@ void setup() {
|
|||||||
|
|
||||||
display->printMessage("GPS Init...");
|
display->printMessage("GPS Init...");
|
||||||
gps_module->init();
|
gps_module->init();
|
||||||
|
lap_counter_modules->init();
|
||||||
delay(750);
|
delay(750);
|
||||||
display->printMessage("GPS Init Complete");
|
display->printMessage("GPS Init Complete");
|
||||||
delay(750);
|
delay(750);
|
||||||
@@ -84,6 +88,7 @@ void setup() {
|
|||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
gps_module->loop();
|
gps_module->loop();
|
||||||
|
lap_counter_modules->loop();
|
||||||
display->loop();
|
display->loop();
|
||||||
command_handler->parseTask();
|
command_handler->parseTask();
|
||||||
system_config->loop();
|
system_config->loop();
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ int Gps::loop(unsigned long timeout_ms) {
|
|||||||
gpsTriggerGlobalWrite(start_line_trigger_);
|
gpsTriggerGlobalWrite(start_line_trigger_);
|
||||||
arm_sign_ = 0;
|
arm_sign_ = 0;
|
||||||
state_changed_at_ = now;
|
state_changed_at_ = now;
|
||||||
|
router::send(module::All, task::AllStartLineTriggered);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@@ -173,7 +174,11 @@ GpsData Gps::getData() {
|
|||||||
output.course_.valid_ = gps_->course.isValid();
|
output.course_.valid_ = gps_->course.isValid();
|
||||||
output.course_.value_ = gps_->course.deg();
|
output.course_.value_ = gps_->course.deg();
|
||||||
|
|
||||||
|
output.time_ = gps_->time.value();
|
||||||
|
output.time_write_time_ = millis() - gps_->time.age();
|
||||||
|
|
||||||
output.num_fix_ = gps_->sentencesWithFix();
|
output.num_fix_ = gps_->sentencesWithFix();
|
||||||
|
gps_->time.minute();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
#include "lap_counter.h"
|
#include "lap_counter.h"
|
||||||
#include "base/router.h"
|
#include "base/router.h"
|
||||||
#include "data/general_store.h"
|
#include "data/general_store.h"
|
||||||
|
#include "data/gps_store.h"
|
||||||
|
#include "data/track_store.h"
|
||||||
|
#include "custom_types.h"
|
||||||
|
|
||||||
int LapCounter::push(const Task &task) { return queue_.push(task); }
|
int LapCounter::push(const Task &task) { return queue_.push(task); }
|
||||||
|
|
||||||
@@ -12,3 +15,61 @@ LapCounter::LapCounter() : logger_(nullptr) {};
|
|||||||
LapCounter::LapCounter(SystemLogger *logger) : logger_(logger) {};
|
LapCounter::LapCounter(SystemLogger *logger) : logger_(logger) {};
|
||||||
|
|
||||||
LapCounter::~LapCounter() {}
|
LapCounter::~LapCounter() {}
|
||||||
|
|
||||||
|
int LapCounter::init() {
|
||||||
|
counting_ = false;
|
||||||
|
count_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LapCounter::loop() {
|
||||||
|
Task active_task;
|
||||||
|
int res = queue_.pop(active_task);
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
if (active_task.target_ == module::LapCounter) {
|
||||||
|
|
||||||
|
} else if (active_task.target_ == module::All) {
|
||||||
|
switch (active_task.type_) {
|
||||||
|
|
||||||
|
case task::AllStartLineTriggered: {
|
||||||
|
GpsData gps;
|
||||||
|
gpsGlobalRead(gps);
|
||||||
|
|
||||||
|
uint32_t base_cs = hhmmsscc_to_cs(gps.time_);
|
||||||
|
|
||||||
|
uint32_t elapsed_cs = (millis() - gps.time_write_time_) / 10;
|
||||||
|
|
||||||
|
uint32_t time_cs = base_cs + elapsed_cs;
|
||||||
|
|
||||||
|
if (!counting_) {
|
||||||
|
counting_ = true;
|
||||||
|
last_trigger_time_ = time_cs;
|
||||||
|
|
||||||
|
router::send(module::Lcd, task::DisplayMsgLapCounterStart, 1000);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
uint32_t lap_time = time_cs - last_trigger_time_;
|
||||||
|
|
||||||
|
lap_times_idx_ = (lap_times_idx_ + 1) & 63;
|
||||||
|
|
||||||
|
lap_times_[lap_times_idx_] = lap_time;
|
||||||
|
count_++;
|
||||||
|
|
||||||
|
last_trigger_time_ = time_cs;
|
||||||
|
|
||||||
|
lastLapTimeGlobalWrite(lap_time);
|
||||||
|
|
||||||
|
router::send(module::Lcd, task::DisplayMsgLapCounterLapTime, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -6,12 +6,20 @@
|
|||||||
#include "base/ring_buffer.h"
|
#include "base/ring_buffer.h"
|
||||||
#include "custom_types.h"
|
#include "custom_types.h"
|
||||||
#include "modules/logger/system_logger.h"
|
#include "modules/logger/system_logger.h"
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
class LapCounter : public ModuleBase {
|
class LapCounter : public ModuleBase {
|
||||||
private:
|
private:
|
||||||
SystemLogger *logger_;
|
SystemLogger *logger_;
|
||||||
RingBuffer<Task, 16> queue_;
|
RingBuffer<Task, 16> queue_;
|
||||||
|
|
||||||
|
bool counting_ = false;
|
||||||
|
uint16_t count_ = 0;
|
||||||
|
uint32_t last_trigger_time_ = 0;
|
||||||
|
uint32_t lap_times_[64];
|
||||||
|
int16_t lap_times_idx_ = -1;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int push(const Task &task) override;
|
int push(const Task &task) override;
|
||||||
LapCounter();
|
LapCounter();
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
|
||||||
|
#include "data/general_store.h"
|
||||||
|
#include "modules/gps/gps.h"
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "modules/gps/gps.h"
|
|
||||||
#include "data/general_store.h"
|
|
||||||
|
|
||||||
#define MOD "modules/lcd/lcd.h"
|
#define MOD "modules/lcd/lcd.h"
|
||||||
|
|
||||||
@@ -66,6 +66,8 @@ bool Lcd::isMessageTask(task::Type type) {
|
|||||||
case task::DisplayMsgBatteryLow:
|
case task::DisplayMsgBatteryLow:
|
||||||
case task::DisplayMsgEngineTempLow:
|
case task::DisplayMsgEngineTempLow:
|
||||||
case task::DisplayMsgEngineTempHigh:
|
case task::DisplayMsgEngineTempHigh:
|
||||||
|
case task::DisplayMsgLapCounterLapTime:
|
||||||
|
case task::DisplayMsgLapCounterStart:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -73,7 +75,8 @@ bool Lcd::isMessageTask(task::Type type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lcd::activateMessage(screen::LcdScreen msg_screen, unsigned long duration_ms) {
|
void Lcd::activateMessage(screen::LcdScreen msg_screen,
|
||||||
|
unsigned long duration_ms) {
|
||||||
if (duration_ms == 0) {
|
if (duration_ms == 0) {
|
||||||
duration_ms = frame_duration_;
|
duration_ms = frame_duration_;
|
||||||
}
|
}
|
||||||
@@ -171,8 +174,7 @@ int Lcd::renderDriverPrimary() {
|
|||||||
|
|
||||||
display_->setCursor(7, 0);
|
display_->setCursor(7, 0);
|
||||||
this->print("TRIG:");
|
this->print("TRIG:");
|
||||||
switch (line_trigger)
|
switch (line_trigger) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
this->print("I");
|
this->print("I");
|
||||||
break;
|
break;
|
||||||
@@ -278,29 +280,60 @@ int Lcd::renderMsgEngineTempHigh() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Lcd::push(const Task &task) {
|
int Lcd::renderMsgLapCounterStart() {
|
||||||
return queue_.push(task);
|
this->clear();
|
||||||
|
display_->setCursor(5, 1);
|
||||||
|
this->print("LAP COUNTER");
|
||||||
|
display_->setCursor(6, 2);
|
||||||
|
this->print("STARTED");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Lcd::renderMsgLapCounterLapTime() {
|
||||||
|
|
||||||
|
uint32_t time_cs;
|
||||||
|
lastLapTimeGlobalRead(time_cs);
|
||||||
|
|
||||||
|
uint32_t minutes = (time_cs / 6000);
|
||||||
|
uint32_t seconds = (time_cs / 100) % 60;
|
||||||
|
uint32_t cs = time_cs % 100;
|
||||||
|
|
||||||
|
this->clear();
|
||||||
|
|
||||||
|
display_->setCursor(6, 1);
|
||||||
|
this->print("LAP TIME");
|
||||||
|
|
||||||
|
display_->setCursor(6, 2);
|
||||||
|
|
||||||
|
if (minutes < 10) this->print('0');
|
||||||
|
this->print(minutes, 10);
|
||||||
|
|
||||||
|
this->print(':');
|
||||||
|
|
||||||
|
if (seconds < 10) this->print('0');
|
||||||
|
this->print(seconds, 10);
|
||||||
|
|
||||||
|
this->print('.');
|
||||||
|
|
||||||
|
if (cs < 10) this->print('0');
|
||||||
|
this->print(cs, 10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Lcd::push(const Task &task) { return queue_.push(task); }
|
||||||
|
|
||||||
Lcd::Lcd()
|
Lcd::Lcd()
|
||||||
: display_cleared_(false),
|
: display_cleared_(false), logger_(nullptr), screen_(screen::Blank),
|
||||||
logger_(nullptr),
|
data_screen_(screen::Blank), message_screen_(screen::Blank),
|
||||||
screen_(screen::Blank),
|
last_render_(0), frame_duration_(2000) {
|
||||||
data_screen_(screen::Blank),
|
|
||||||
message_screen_(screen::Blank),
|
|
||||||
last_render_(0),
|
|
||||||
frame_duration_(2000) {
|
|
||||||
display_ = new LiquidCrystal_I2C(0x27, 20, 4);
|
display_ = new LiquidCrystal_I2C(0x27, 20, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lcd::Lcd(SystemLogger *logger)
|
Lcd::Lcd(SystemLogger *logger)
|
||||||
: display_cleared_(false),
|
: display_cleared_(false), logger_(logger), screen_(screen::Blank),
|
||||||
logger_(logger),
|
data_screen_(screen::Blank), message_screen_(screen::Blank),
|
||||||
screen_(screen::Blank),
|
last_render_(0), frame_duration_(2000) {
|
||||||
data_screen_(screen::Blank),
|
|
||||||
message_screen_(screen::Blank),
|
|
||||||
last_render_(0),
|
|
||||||
frame_duration_(2000) {
|
|
||||||
display_ = new LiquidCrystal_I2C(0x27, 20, 4);
|
display_ = new LiquidCrystal_I2C(0x27, 20, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,6 +520,13 @@ int Lcd::loop(unsigned long timeout_ms) {
|
|||||||
activateMessage(screen::MsgEngineTempHigh, next_task.data_);
|
activateMessage(screen::MsgEngineTempHigh, next_task.data_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case task::DisplayMsgLapCounterStart:
|
||||||
|
activateMessage(screen::MsgLapCounterStart, next_task.data_);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case task::DisplayMsgLapCounterLapTime:
|
||||||
|
activateMessage(screen::MsgLapCounterLapTime, next_task.data_);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -553,6 +593,14 @@ int Lcd::loop(unsigned long timeout_ms) {
|
|||||||
this->renderMsgEngineTempHigh();
|
this->renderMsgEngineTempHigh();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case screen::MsgLapCounterStart:
|
||||||
|
this->renderMsgLapCounterStart();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case screen::MsgLapCounterLapTime:
|
||||||
|
this->renderMsgLapCounterLapTime();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ enum LcdScreen : uint8_t {
|
|||||||
MsgBatteryLow,
|
MsgBatteryLow,
|
||||||
MsgEngineTempLow,
|
MsgEngineTempLow,
|
||||||
MsgEngineTempHigh,
|
MsgEngineTempHigh,
|
||||||
|
MsgLapCounterStart,
|
||||||
|
MsgLapCounterLapTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace screen
|
} // namespace screen
|
||||||
@@ -74,6 +76,8 @@ private:
|
|||||||
int renderMsgBatteryLow();
|
int renderMsgBatteryLow();
|
||||||
int renderMsgEngineTempLow();
|
int renderMsgEngineTempLow();
|
||||||
int renderMsgEngineTempHigh();
|
int renderMsgEngineTempHigh();
|
||||||
|
int renderMsgLapCounterStart();
|
||||||
|
int renderMsgLapCounterLapTime();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int push(const Task &task) override;
|
int push(const Task &task) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user