Initialisation depot

This commit is contained in:
Serge NOEL
2026-02-10 12:12:11 +01:00
commit c3176e8d79
818 changed files with 52573 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
/**
* @file AccessoryOutputs.h
* @brief Accessory Output Controller (N-channel MOSFETs)
*
* Controls 2 N-channel MOSFET outputs for accessories like smoke generators,
* sound modules, or other low-side switched loads.
*/
#ifndef ACCESSORY_OUTPUTS_H
#define ACCESSORY_OUTPUTS_H
#include <Arduino.h>
enum AccessoryMode {
ACC_OFF = 0, // Always off
ACC_ON = 1, // Always on
ACC_FUNCTION = 2, // Controlled by DCC function
ACC_PWM = 3, // PWM control
ACC_BLINK = 4, // Blinking mode
ACC_SPEED_DEPENDENT = 5 // Output follows speed
};
class AccessoryOutputs {
public:
AccessoryOutputs();
/**
* @brief Initialize accessory outputs
* @param output1Pin GPIO for accessory output 1 (N-FET gate)
* @param output2Pin GPIO for accessory output 2 (N-FET gate)
* @return true if successful
*/
bool begin(uint8_t output1Pin, uint8_t output2Pin);
/**
* @brief Set output mode
* @param outputNum Output number (1 or 2)
* @param mode Accessory mode
*/
void setMode(uint8_t outputNum, AccessoryMode mode);
/**
* @brief Set PWM duty cycle for output
* @param outputNum Output number (1 or 2)
* @param dutyCycle Duty cycle (0-255)
*/
void setPWM(uint8_t outputNum, uint8_t dutyCycle);
/**
* @brief Map DCC function to output
* @param outputNum Output number (1 or 2)
* @param functionNum DCC function number (0-28)
*/
void mapFunction(uint8_t outputNum, uint8_t functionNum);
/**
* @brief Update function state
* @param functionNum Function number (0-28)
* @param state Function state (true = on)
*/
void setFunctionState(uint8_t functionNum, bool state);
/**
* @brief Set speed for speed-dependent mode
* @param speed Speed value (0-126)
*/
void setSpeed(uint8_t speed);
/**
* @brief Update outputs (call regularly from loop)
*/
void update();
/**
* @brief Direct output control
* @param outputNum Output number (1 or 2)
* @param state Output state (true = on)
*/
void setOutput(uint8_t outputNum, bool state);
private:
uint8_t pins[2];
AccessoryMode modes[2];
uint8_t pwmValues[2];
uint8_t mappedFunctions[2];
bool functionStates[29]; // F0-F28
uint8_t currentSpeed;
// PWM channels
const uint8_t pwmChannels[2] = {2, 3};
const uint32_t pwmFrequency = 1000; // 1 kHz
const uint8_t pwmResolution = 8;
// Blink timing
unsigned long lastBlinkUpdate;
bool blinkState;
void updateOutput(uint8_t outputNum);
};
#endif // ACCESSORY_OUTPUTS_H

View File

@@ -0,0 +1,100 @@
/**
* @file CVManager.h
* @brief Configuration Variable (CV) Manager
*
* Manages NMRA-compliant Configuration Variables stored in non-volatile memory.
* Supports programming track operations and service mode programming.
*/
#ifndef CV_MANAGER_H
#define CV_MANAGER_H
#include <Arduino.h>
#include <Preferences.h>
// Standard DCC CVs
#define CV_PRIMARY_ADDRESS 1 // Short address (1-127)
#define CV_VSTART 2 // Start voltage
#define CV_ACCEL_RATE 3 // Acceleration rate
#define CV_DECEL_RATE 4 // Deceleration rate
#define CV_VHIGH 5 // Max voltage
#define CV_VMID 6 // Mid voltage
#define CV_VERSION_ID 7 // Manufacturer version
#define CV_MANUFACTURER_ID 8 // Manufacturer ID
#define CV_TOTAL_PWM_PERIOD 9 // PWM period
#define CV_EMF_FEEDBACK_CUTOUT 10 // EMF feedback cutout
#define CV_PACKET_TIMEOUT 11 // Packet timeout
#define CV_EXTENDED_ADDRESS_HIGH 17 // Long address high byte
#define CV_EXTENDED_ADDRESS_LOW 18 // Long address low byte
#define CV_CONSIST_ADDRESS 19 // Consist address
#define CV_CONFIG_DATA_1 29 // Configuration data
// Custom CVs for this decoder
#define CV_MOTOR_KP 50 // Motor PID Kp
#define CV_MOTOR_KI 51 // Motor PID Ki
#define CV_MOTOR_KD 52 // Motor PID Kd
#define CV_RAILCOM_ENABLE 53 // RailCom enable
#define CV_LOAD_COMP_ENABLE 54 // Load compensation enable
#define CV_LED_BRIGHTNESS 55 // LED brightness
#define CV_ACCESSORY_1_MODE 56 // Accessory output 1 mode
#define CV_ACCESSORY_2_MODE 57 // Accessory output 2 mode
#define MAX_CV_NUMBER 1024
class CVManager {
public:
CVManager();
/**
* @brief Initialize CV manager and load from NVS
* @return true if successful
*/
bool begin();
/**
* @brief Read CV value
* @param cvNumber CV number (1-1024)
* @param defaultValue Default value if CV not set
* @return CV value
*/
uint8_t readCV(uint16_t cvNumber, uint8_t defaultValue = 0);
/**
* @brief Write CV value
* @param cvNumber CV number (1-1024)
* @param value Value to write
* @return true if successful
*/
bool writeCV(uint16_t cvNumber, uint8_t value);
/**
* @brief Reset all CVs to factory defaults
*/
void resetToDefaults();
/**
* @brief Get locomotive address from CVs
* @return Locomotive address (1-10239)
*/
uint16_t getLocoAddress();
/**
* @brief Set locomotive address in CVs
* @param address Address to set (1-10239)
*/
void setLocoAddress(uint16_t address);
/**
* @brief Check if using extended (long) address
* @return true if using long address
*/
bool isLongAddress();
private:
Preferences preferences;
void setDefaultCVs();
String getCVKey(uint16_t cvNumber);
};
#endif // CV_MANAGER_H

View File

@@ -0,0 +1,82 @@
/**
* @file ConfigServer.h
* @brief WiFi/Bluetooth Configuration Server
*
* Provides WebSocket-based configuration interface over WiFi or Bluetooth.
* Allows reading/writing CVs, testing outputs, and monitoring decoder status.
*/
#ifndef CONFIG_SERVER_H
#define CONFIG_SERVER_H
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include "CVManager.h"
class ConfigServer {
public:
ConfigServer(CVManager& cvManager);
/**
* @brief Initialize configuration server
* @param ssid WiFi SSID (nullptr for AP mode with default name)
* @param password WiFi password
* @param useAP true for AP mode, false for station mode
* @return true if successful
*/
bool begin(const char* ssid = nullptr, const char* password = nullptr, bool useAP = true);
/**
* @brief Stop configuration server
*/
void stop();
/**
* @brief Check if configuration mode is active
*/
bool isActive() const { return active; }
/**
* @brief Update server (call from loop)
*/
void update();
/**
* @brief Set decoder status callback
* Function signature: void callback(JsonObject& status)
*/
typedef void (*StatusCallback)(JsonObject& status);
void setStatusCallback(StatusCallback callback);
private:
CVManager& cvMgr;
AsyncWebServer* server;
AsyncWebSocket* ws;
bool active;
StatusCallback statusCallback;
unsigned long lastStatusUpdate;
void setupWebSocket();
void setupHTTPRoutes();
void handleWebSocketMessage(void* arg, uint8_t* data, size_t len);
void handleWebSocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client,
AwsEventType type, void* arg, uint8_t* data, size_t len);
void handleReadCV(AsyncWebSocketClient* client, JsonObject& json);
void handleWriteCV(AsyncWebSocketClient* client, JsonObject& json);
void handleGetStatus(AsyncWebSocketClient* client);
void handleTestOutput(AsyncWebSocketClient* client, JsonObject& json);
void handleReset(AsyncWebSocketClient* client);
void sendResponse(AsyncWebSocketClient* client, const char* type,
bool success, const char* message = nullptr);
void broadcastStatus();
String getDefaultAPName();
};
#endif // CONFIG_SERVER_H

View File

@@ -0,0 +1,100 @@
/**
* @file DCCDecoder.h
* @brief DCC Signal Decoder for locomotive control
*
* Decodes DCC packets from the track signal, extracts speed and function commands,
* and manages locomotive addressing (short/long address support).
*/
#ifndef DCC_DECODER_H
#define DCC_DECODER_H
#include <Arduino.h>
// DCC Timing constants (in microseconds)
#define DCC_ONE_BIT_MIN 52
#define DCC_ONE_BIT_MAX 64
#define DCC_ZERO_BIT_MIN 95
#define DCC_ZERO_BIT_MAX 9900
// Maximum packet size
#define MAX_DCC_PACKET_SIZE 6
class DCCDecoder {
public:
DCCDecoder();
/**
* @brief Initialize the DCC decoder
* @param dccPin GPIO pin for DCC signal input
* @return true if initialization successful
*/
bool begin(uint8_t dccPin);
/**
* @brief Process DCC signal (call frequently from loop or ISR)
*/
void process();
/**
* @brief Get current speed value (0-126, 0=stop, 1=emergency stop)
* @return Current speed
*/
uint8_t getSpeed() const { return currentSpeed; }
/**
* @brief Get current direction
* @return true = forward, false = reverse
*/
bool getDirection() const { return direction; }
/**
* @brief Get function state (F0-F28)
* @param functionNum Function number (0-28)
* @return Function state (true = on)
*/
bool getFunction(uint8_t functionNum) const;
/**
* @brief Check if decoder has received valid packets recently
* @return true if signal is valid
*/
bool hasValidSignal() const;
/**
* @brief Set locomotive address
* @param address Locomotive address (1-10239)
*/
void setAddress(uint16_t address);
/**
* @brief Get current locomotive address
*/
uint16_t getAddress() const { return locoAddress; }
private:
static void IRAM_ATTR dccISR();
static DCCDecoder* instance;
void decodeDCCPacket();
void processSpeedPacket(uint8_t* data, uint8_t len);
void processFunctionPacket(uint8_t* data, uint8_t len);
uint8_t dccInputPin;
uint16_t locoAddress;
uint8_t currentSpeed;
bool direction;
uint32_t functions; // Bit field for F0-F28
// Packet assembly
uint8_t packetBuffer[MAX_DCC_PACKET_SIZE];
uint8_t packetIndex;
uint8_t bitCount;
bool assemblingPacket;
// Timing
unsigned long lastBitTime;
unsigned long lastValidPacket;
};
#endif // DCC_DECODER_H

View File

@@ -0,0 +1,108 @@
/**
* @file LEDController.h
* @brief WS2812 LED Controller for lighting effects
*
* Controls WS2812 addressable LEDs for headlights, taillights, and other effects.
* Supports direction-based lighting and function-controlled effects.
*/
#ifndef LED_CONTROLLER_H
#define LED_CONTROLLER_H
#include <Arduino.h>
#include <FastLED.h>
#define MAX_LEDS 16
#define DEFAULT_BRIGHTNESS 128
enum LightMode {
LIGHT_OFF = 0,
LIGHT_ON = 1,
LIGHT_BLINK = 2,
LIGHT_PULSE = 3,
LIGHT_DIRECTION_FRONT = 4, // On when moving forward
LIGHT_DIRECTION_REAR = 5 // On when moving backward
};
class LEDController {
public:
LEDController();
/**
* @brief Initialize LED controller
* @param ledPin GPIO pin for WS2812 data
* @param numLeds Number of LEDs in the strip
* @return true if successful
*/
bool begin(uint8_t ledPin, uint8_t numLeds);
/**
* @brief Update LED states (call regularly from loop)
*/
void update();
/**
* @brief Set LED mode for a specific LED
* @param ledIndex LED index (0-based)
* @param mode Light mode
*/
void setLEDMode(uint8_t ledIndex, LightMode mode);
/**
* @brief Set LED color
* @param ledIndex LED index
* @param r Red (0-255)
* @param g Green (0-255)
* @param b Blue (0-255)
*/
void setLEDColor(uint8_t ledIndex, uint8_t r, uint8_t g, uint8_t b);
/**
* @brief Set global brightness
* @param brightness Brightness (0-255)
*/
void setBrightness(uint8_t brightness);
/**
* @brief Set direction for directional lights
* @param forward true = forward, false = reverse
*/
void setDirection(bool forward);
/**
* @brief Map function to LED
* @param functionNum Function number (0-28)
* @param ledIndex LED index
* @param mode Light mode when function is active
*/
void mapFunctionToLED(uint8_t functionNum, uint8_t ledIndex, LightMode mode);
/**
* @brief Update function state
* @param functionNum Function number
* @param state Function state (true = on)
*/
void setFunctionState(uint8_t functionNum, bool state);
private:
CRGB leds[MAX_LEDS];
uint8_t numLEDs;
uint8_t dataPin;
bool direction;
struct LEDConfig {
LightMode mode;
CRGB color;
uint8_t mappedFunction; // 255 = no function mapping
};
LEDConfig ledConfig[MAX_LEDS];
bool functionStates[29]; // F0-F28
unsigned long lastUpdate;
uint16_t effectCounter;
void updateLED(uint8_t ledIndex);
};
#endif // LED_CONTROLLER_H

View File

@@ -0,0 +1,114 @@
/**
* @file MotorDriver.h
* @brief TB67H450FNG Motor Driver Controller
*
* Controls the TB67H450FNG H-bridge motor driver with PWM speed control,
* direction control, and optional load compensation/BEMF feedback.
*/
#ifndef MOTOR_DRIVER_H
#define MOTOR_DRIVER_H
#include <Arduino.h>
// TB67H450FNG control pins
// IN1 and IN2 control direction and brake
// PWM controls speed
class MotorDriver {
public:
MotorDriver();
/**
* @brief Initialize motor driver
* @param in1Pin GPIO for IN1 (Motor phase A)
* @param in2Pin GPIO for IN2 (Motor phase B)
* @param pwmPin GPIO for PWM speed control
* @param currentSensePin ADC pin for current sensing (optional, 255 = disabled)
* @return true if successful
*/
bool begin(uint8_t in1Pin, uint8_t in2Pin, uint8_t pwmPin, uint8_t currentSensePin = 255);
/**
* @brief Set motor speed and direction
* @param speed Speed value (0-126, DCC format: 0=stop, 1=emergency stop, 2-127=speed)
* @param forward Direction (true=forward, false=reverse)
*/
void setSpeed(uint8_t speed, bool forward);
/**
* @brief Emergency stop
*/
void emergencyStop();
/**
* @brief Update motor control (call regularly for load compensation)
*/
void update();
/**
* @brief Enable/disable load compensation
* @param enable true to enable
*/
void setLoadCompensation(bool enable);
/**
* @brief Get motor current (if current sensing enabled)
* @return Current in mA
*/
uint16_t getMotorCurrent();
/**
* @brief Set PID parameters for load compensation
* @param kp Proportional gain
* @param ki Integral gain
* @param kd Derivative gain
*/
void setPIDParameters(float kp, float ki, float kd);
/**
* @brief Set acceleration rate
* @param rate Rate value (0-255, higher = faster)
*/
void setAccelRate(uint8_t rate);
/**
* @brief Set deceleration rate
* @param rate Rate value (0-255, higher = faster)
*/
void setDecelRate(uint8_t rate);
private:
uint8_t pinIN1;
uint8_t pinIN2;
uint8_t pinPWM;
uint8_t pinCurrentSense;
uint8_t targetSpeed;
uint8_t currentSpeed;
bool targetDirection;
bool loadCompensationEnabled;
// Acceleration/deceleration
uint8_t accelRate;
uint8_t decelRate;
unsigned long lastSpeedUpdate;
// Load compensation (PID)
float Kp, Ki, Kd;
float integral;
float lastError;
uint16_t targetCurrent;
// PWM settings
const uint8_t pwmChannel = 0;
const uint32_t pwmFrequency = 20000; // 20 kHz
const uint8_t pwmResolution = 8; // 8-bit (0-255)
void applyMotorControl();
void updateAcceleration();
void updateLoadCompensation();
uint16_t readCurrent();
};
#endif // MOTOR_DRIVER_H

View File

@@ -0,0 +1,93 @@
/**
* @file RailCom.h
* @brief RailCom Feedback Controller
*
* Implements RailCom channel 1 and 2 for bidirectional communication
* with the command station. Sends locomotive address and status information.
*/
#ifndef RAILCOM_H
#define RAILCOM_H
#include <Arduino.h>
// RailCom timing (in microseconds)
#define RAILCOM_CHANNEL1_START 26
#define RAILCOM_CHANNEL1_END 177
#define RAILCOM_CHANNEL2_START 193
#define RAILCOM_CHANNEL2_END 454
// RailCom 4bit to 8bit encoding table
#define RAILCOM_4BIT_TO_8BIT_SIZE 16
class RailCom {
public:
RailCom();
/**
* @brief Initialize RailCom
* @param txPin GPIO for RailCom transmit (UART TX)
* @param cutoutDetectPin GPIO to detect DCC cutout (optional, 255 = disabled)
* @return true if successful
*/
bool begin(uint8_t txPin, uint8_t cutoutDetectPin = 255);
/**
* @brief Enable/disable RailCom
* @param enable true to enable
*/
void setEnabled(bool enable);
/**
* @brief Check if RailCom is enabled
*/
bool isEnabled() const { return enabled; }
/**
* @brief Send RailCom data during cutout window
* This should be called when DCC cutout is detected
*/
void sendRailComData();
/**
* @brief Set locomotive address for RailCom reporting
* @param address Locomotive address
*/
void setAddress(uint16_t address);
/**
* @brief Set decoder state information
* @param speed Current speed
* @param direction Current direction
*/
void setDecoderState(uint8_t speed, bool direction);
/**
* @brief Update RailCom (call regularly from loop)
*/
void update();
private:
uint8_t txPin;
uint8_t cutoutPin;
bool enabled;
uint16_t locoAddress;
uint8_t currentSpeed;
bool currentDirection;
HardwareSerial* railcomSerial;
// RailCom encoding
uint8_t encode4to8(uint8_t data);
void sendChannel1();
void sendChannel2();
// Timing
unsigned long lastCutoutTime;
bool inCutout;
static const uint8_t railcom4to8[16];
};
#endif // RAILCOM_H