OpenSourceSimWheelESP32
Open-source wireless steering wheel/button box for ESP32 boards
Loading...
Searching...
No Matches
InternalTypes.hpp
Go to the documentation of this file.
1
12#pragma once
13
14//-------------------------------------------------------------------
15// Imports
16//-------------------------------------------------------------------
17
18#include <cstdint>
19#include <vector>
20#include <optional>
21#include "SimWheelTypes.hpp" // For uint128_t
22
23#if !CD_CI
25#define PRIVATE private
27#define PROTECTED protected
28#else
30#define PRIVATE public
32#define PROTECTED public
33#endif
34
35//-------------------------------------------------------------------
36// Testing
37//-------------------------------------------------------------------
38
44{
50 uint8_t leftAxis = 0;
52 uint8_t rightAxis = 0;
55
61 void press(uint8_t n)
62 {
63 state.set_bit(n, true);
64 }
65
71 void release(uint8_t n)
72 {
73 state.set_bit(n, false);
74 }
75
80 void clear()
81 {
82 state = {};
83 leftAxis = 0;
84 rightAxis = 0;
85 }
86};
87
88//-------------------------------------------------------------------
89// Device capabilities
90//-------------------------------------------------------------------
91
96enum class DeviceCapability : uint8_t
97{
99 CLUTCH_BUTTON = 0,
101 CLUTCH_ANALOG = 1,
103 ALT = 2,
105 DPAD = 3,
107 BATTERY = 4,
113 TELEMETRY_ECU = 7,
119 ROTARY_ENCODERS = 10,
121 TELEMETRY_WHEELS = 11,
122 _MAX_VALUE = TELEMETRY_WHEELS
123};
124
130{
131public:
138 static void setFlag(DeviceCapability capability, bool setOrClear = true)
139 {
140 if (setOrClear)
141 _flags |= (1 << static_cast<uint8_t>(capability));
142 else
143 _flags &= ~(1 << static_cast<uint8_t>(capability));
144 }
145
153 static bool hasFlag(DeviceCapability capability)
154 {
155 return _flags & (1 << static_cast<uint8_t>(capability));
156 }
157
163 static uint16_t getFlags() { return _flags; }
164
165private:
166 inline static uint16_t _flags = 0;
167};
168
169//-------------------------------------------------------------------
170// Clutch
171//-------------------------------------------------------------------
172
177enum class ClutchWorkingMode : uint8_t
178{
180 CLUTCH = 0,
182 AXIS,
184 ALT,
186 BUTTON,
191 _MAX_VALUE = LAUNCH_CONTROL_MASTER_RIGHT,
192 _DEFAULT_VALUE = CLUTCH
193};
194
196#define CLUTCH_NONE_VALUE 0
198#define CLUTCH_FULL_VALUE 254
200#define CLUTCH_DEFAULT_VALUE 127
202#define CLUTCH_1_4_VALUE 64
204#define CLUTCH_3_4_VALUE 192
206#define CLUTCH_INVALID_VALUE 255
207
208//-------------------------------------------------------------------
209// ALT BUTTONS
210//-------------------------------------------------------------------
211
216enum class AltButtonsWorkingMode : uint8_t
217{
219 Regular = 0,
221 ALT,
222 _MAX_VALUE = ALT,
223 _DEFAULT_VALUE = ALT
224};
225
226//-------------------------------------------------------------------
227// Rotary encoder
228//-------------------------------------------------------------------
229
234enum class PulseWidthMultiplier : uint8_t
235{
236 X1 = 1,
237 X2,
238 X3,
239 X4,
240 X5,
241 X6,
242 _MAX_VALUE = X6,
243 _DEFAULT_VALUE = X2
244};
245
246//-------------------------------------------------------------------
247// DPAD
248//-------------------------------------------------------------------
249
254enum class DPadWorkingMode : uint8_t
255{
257 Regular = 0,
260 _MAX_VALUE = Navigation,
261 _DEFAULT_VALUE = Navigation
262};
263
264//-------------------------------------------------------------------
265// Global firmware parameters
266//-------------------------------------------------------------------
267
272#define INPUT_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
273
274//-------------------------------------------------------------------
275// Queues
276//-------------------------------------------------------------------
277
286{
287public:
294 void enqueue(bool value)
295 {
296 uint8_t bqTailNext = bqTail;
297 incDataPointer(bqTailNext);
298 if (bqTailNext != bqHead)
299 {
300 // Queue not full
301 uint64_t aux = (1ULL << bqTail);
302 bitsQueue &= (~aux);
303 if (value)
304 bitsQueue |= aux;
305 bqTail = bqTailNext;
306 } // else queue full, overflow
307 }
308
316 bool dequeue(bool &value)
317 {
318 bool isNotEmpty = (bqHead != bqTail);
319 if (isNotEmpty)
320 {
321 uint64_t bitState = (1ULL << bqHead) & bitsQueue;
322 value = (bitState != 0ULL);
323 incDataPointer(bqHead);
324 }
325 return isNotEmpty;
326 }
327
329
330 PRIVATE : uint64_t bitsQueue = 0ULL;
331 uint8_t bqHead = 0; // "pointer" (short of) to head
332 uint8_t bqTail = 0; // "pointer" to tail
333
334 inline static void incDataPointer(uint8_t &pointer)
335 {
336 pointer = (pointer + 1) % 64;
337 };
338
340};
341
342//-------------------------------------------------------------------
343// Inputs-InputHub decoupling
344//-------------------------------------------------------------------
345
359
361#define MAX_DECOUPLING_EVENT_COUNT 64
362
363//-------------------------------------------------------------------
364// Battery Management
365//-------------------------------------------------------------------
366
369{
370public:
372 std::optional<uint8_t> stateOfCharge{};
374 std::optional<bool> isCharging{};
376 std::optional<bool> isBatteryPresent{};
378 std::optional<bool> usingExternalPower{};
379
387 constexpr bool operator==(const BatteryStatus &other) const noexcept
388 {
389 return (stateOfCharge == other.stateOfCharge) &&
390 (isCharging == other.isCharging) &&
391 (isBatteryPresent == other.isBatteryPresent) &&
392 (usingExternalPower == other.usingExternalPower);
393 }
394
399 inline void reset() noexcept
400 {
401 stateOfCharge.reset();
402 isCharging.reset();
403 isBatteryPresent.reset();
404 usingExternalPower.reset();
405 }
406};
407
408#pragma pack(push, 1)
409
413{
415 unsigned int flag_id_present : 1 = 1;
417 unsigned int flag_battery_level_present : 1 = 1;
419 unsigned int flag_additional_status_present : 1 = 1;
421 unsigned int flag_reserved : 5 = 0;
422
423 // End of byte 0
424
426 unsigned int ps_battery_present : 1 = 0;
428 unsigned int ps_wired_ext_power : 2 = 1;
430 unsigned int ps_wireless_ext_power : 2 = 0;
432 unsigned int ps_battery_charge_state : 2 = 0;
434 unsigned int ps_battery_charge_level : 2 = 1;
436 unsigned int ps_charging_type : 3 = 0;
438 unsigned int ps_fault_reason : 3 = 0;
440 unsigned int ps_reserved : 1 = 0;
441
442 // End of bytes 1-2
443
445 uint16_t id = 0x106;
446
447 // End of bytes 3-4
448
450 uint8_t battery_level = 100;
451
452 // End of byte 5
453
455 unsigned int as_service_required : 1 = 0;
457 unsigned int as_battery_fault : 2 = 0;
459 unsigned int as_reserved : 5 = 0;
460
461 // End of byte 6
462};
463
464// For unknown reasons, the x86 compiler ignores the pragma pack directive
465#if !CD_CI
466static_assert(
467 sizeof(BatteryStatusChrData) == 7,
468 "Wrong size of BatteryStatusChrData (check struct packaging)");
469#endif
470
471#pragma pack(pop)
472
473//-------------------------------------------------------------------
474// Internal events
475//-------------------------------------------------------------------
476
483enum class UserSetting : uint8_t
484{
485 ALL = 0,
486 AXIS_CALIBRATION,
487 AXIS_POLARITY,
488 PULSE_WIDTH,
489 SECURITY_LOCK,
490 BITE_POINT,
491 CLUTCH_WORKING_MODE,
492 ALT_WORKING_MODE,
493 DPAD_WORKING_MODE,
494 INPUT_MAP,
495 CUSTOM_HARDWARE_ID,
496 BATTERY_AUTO_CALIBRATION,
497 BATTERY_CALIBRATION_DATA,
498 _MAX_VALUE = BATTERY_CALIBRATION_DATA
499};
500
501//------------------------------------------------------------------------------
502
517template <class... Args>
519{
520public:
522 using type = static_event<Args...>;
524 using callback_type = typename ::std::add_pointer<void(Args...)>::type;
525
531 void subscribe(callback_type callback) noexcept
532 {
533 if (!callback)
534 return;
535 _subscriptions.push_back(callback);
536 }
537
543 void clear() noexcept
544 {
545 _subscriptions.clear();
546 }
547
553 void operator()(const Args &...args)
554 {
555 for (const auto &entry : _subscriptions)
556 {
557 entry(args...);
558 }
559 }
560
566 void operator()(const Args &...args) const
567 {
568 for (const auto &entry : _subscriptions)
569 {
570 entry(args...);
571 }
572 }
573
579 ::std::size_t subscribed()
580 {
581 return _subscriptions.size();
582 }
583
590 type &operator=(type &&source) noexcept
591 {
592 _subscriptions.swap(source._subscriptions);
593 return *this;
594 }
595
602 type &operator=(const type &source) noexcept
603 {
604 _subscriptions = source._subscriptions;
605 return *this;
606 }
607
612 constexpr static_event() noexcept = default;
613
619 static_event(const type &source)
620 {
621 _subscriptions = source._subscriptions;
622 }
623
630 {
631 _subscriptions.swap(source._subscriptions);
632 }
633
643 constexpr bool operator==(const type &other) const noexcept
644 {
645 return (_subscriptions == other._subscriptions);
646 }
647
648private:
650 ::std::vector<callback_type> _subscriptions{};
651};
652
658
664
671
677
683
689
695
701
707
713
720
726
732
738
739//-------------------------------------------------------------------
740// Automatic shutdown
741//-------------------------------------------------------------------
742
747#define AUTO_POWER_OFF_DELAY_SECS 60
748
749//-------------------------------------------------------------------
750// Simple commands
751//-------------------------------------------------------------------
752
SimpleCommand
Simple commands accepted from a feature HID report.
@ CMD_SHOW_PIXELS
Display all pixels in all pixel groups.
@ CMD_SAVE_NOW
Save all user settings to flash memory immediately.
@ CMD_AXIS_RECALIBRATE
Recalibrate analog axes (if any)
@ CMD_RESERVED
Not a command, reserved to avoid mistakes.
@ CMD_REVERSE_LEFT_AXIS
Reverse left axis (if any)
@ CMD_RESET_PIXELS
Turn off all pixels in all groups.
@ CMD_BATT_RECALIBRATE
Restart battery auto-calibration.
@ CMD_REVERSE_RIGHT_AXIS
Reverse right axis (if any)
@ CMD_RESET_BUTTONS_MAP
Reset buttons map to factory defaults.
static_event OnStart
System startup.
static_event OnShutdown
The system is about to shutdown.
static_event OnConnected
Host connection.
static_event OnLowBattery
Notified when a low battery condition is detected.
static_event< PulseWidthMultiplier > OnPulseWidthMultiplier
New pulse width multiplier.
#define CLUTCH_NONE_VALUE
Value for a fully released clutch.
static_event< uint8_t > OnBitePoint
New bite point.
#define PRIVATE
For testing.
ClutchWorkingMode
User-selected working mode of the clutch paddles.
@ LAUNCH_CONTROL_MASTER_LEFT
Launch control (left paddle is master)
@ CLUTCH
F1-Style clutch. Must be the first in the enum: do not change.
@ BUTTON
Regular buttons.
@ AXIS
Independent axes.
@ LAUNCH_CONTROL_MASTER_RIGHT
Launch control (right paddle is master)
PulseWidthMultiplier
User-selected pulse width multiplier.
AltButtonsWorkingMode
User-selected working mode of "ALT" buttons.
@ Regular
Regular button.
static_event< UserSetting > SaveSetting
Request to save a user setting.
static_event OnSettingsSaved
Save event.
DeviceCapability
Enumeration of device capabilities.
@ TELEMETRY_POWERTRAIN
Able to display powertrain telemetry data.
@ DPAD
Has a directional pad.
@ TELEMETRY_WHEELS
Able to display wheel telemetry data.
@ CLUTCH_BUTTON
Has digital clutch paddles (switches)
@ BATTERY_CALIBRATION_AVAILABLE
Has battery calibration data.
@ TELEMETRY_RACE_CONTROL
Able to display race control telemetry data.
@ BATTERY
Battery-operated.
@ CLUTCH_ANALOG
Has analog clutch paddles (potentiometers)
@ TELEMETRY_ECU
Able to display ECU telemetry data.
@ ROTARY_ENCODERS
Has one or more rotary encoders.
@ ALT
Has "ALT" buttons.
@ TELEMETRY_GAUGES
Able to display telemetry data for gauges.
static_event< UserSetting > LoadSetting
Request to load a user setting.
static_event< ClutchWorkingMode > OnClutchWorkingMode
New clutch working mode.
static_event< AltButtonsWorkingMode > OnAltButtonsWorkingMode
New ALT buttons working mode.
static_event OnDPadWorkingMode
New DPAD working mode.
DPadWorkingMode
User-selected working mode of directional pads.
@ Navigation
Navigation control.
static_event OnDisconnected
No host connection.
static_event< const BatteryStatus & > OnBatteryStatus
New battery level (state of charge) or battery status.
UserSetting
User setting to be stored in flash memory.
Types and constants required for custom firmware setup.
Queue for 61 bits.
void enqueue(bool value)
Push a bit into the queue.
bool dequeue(bool &value)
Extract a bit from the queue.
Publish-subscribe event (forever subscribed)
void operator()(const Args &...args) const
Dispatch event to all subscribed callbacks (const)
constexpr bool operator==(const type &other) const noexcept
Equality operator.
void subscribe(callback_type callback) noexcept
Subscribe forever.
typename ::std::add_pointer< void(Args...)>::type callback_type
Callback type for subscribers.
static_event< Args... > type
This type.
type & operator=(const type &source) noexcept
Copy-assignment.
constexpr static_event() noexcept=default
Default constructor.
void clear() noexcept
Clear all subscriptions.
void operator()(const Args &...args)
Dispatch event to all subscribed callbacks.
type & operator=(type &&source) noexcept
Move-assignment.
static_event(type &&source)
Move constructor.
::std::size_t subscribed()
Get the number of subscribed callbacks.
Data format for the Battery Level Status characteristic (packed)
unsigned int as_service_required
Additional status: service required.
unsigned int ps_battery_charge_level
Power state: summarized state of charge.
unsigned int flag_reserved
Flags: reserved for future use.
uint8_t battery_level
Field: Battery level.
unsigned int as_battery_fault
Additional status: battery fault status.
unsigned int flag_id_present
Flags: id field present.
unsigned int ps_wired_ext_power
Power state: is wired external power present.
unsigned int ps_fault_reason
Power state: charging fault reason.
unsigned int ps_battery_charge_state
Power state: battery charging status.
unsigned int flag_battery_level_present
Flags: battery level field present.
unsigned int as_reserved
Additional status: reserved for future use.
unsigned int ps_charging_type
Power state: charging type.
unsigned int flag_additional_status_present
Flags: additional status field present.
unsigned int ps_reserved
Power state: reserved for future use.
unsigned int ps_wireless_ext_power
Power state: is wireless external power present.
unsigned int ps_battery_present
Power state: is battery present.
Battery status.
constexpr bool operator==(const BatteryStatus &other) const noexcept
Compare for equality.
std::optional< bool > usingExternalPower
True if there is wired power.
std::optional< uint8_t > stateOfCharge
Measured battery level in the range from 0% to 100%.
void reset() noexcept
Reset to unknown.
std::optional< bool > isCharging
True if the battery is being charged.
std::optional< bool > isBatteryPresent
False if the battery is not connected.
Decoupling event.
uint8_t leftAxisValue
Position of the left axis.
uint128_t rawInputBitmap
Input bitmap.
uint8_t rightAxisValue
Position of the right axis.
Set of device capabilities.
static uint16_t getFlags()
Get all flags as a bitmap.
static void setFlag(DeviceCapability capability, bool setOrClear=true)
Clear or set a device capability.
static bool hasFlag(DeviceCapability capability)
Check if a capability is available.
Fake input specification used for testing.
uint8_t leftAxis
Left axis position.
uint8_t rightAxis
Right axis position.
void press(uint8_t n)
Simulate a button press.
void clear()
Simulate no input.
size_t recalibrationRequestCount
Count of times axis recalibration was asked.
uint128_t mask
Input mask.
void release(uint8_t n)
Simulate a button release.
uint128_t state
Input bitmap.
128-bit integer
constexpr void set_bit(uint8_t n, bool value=true) noexcept
Set or clear a single bit.