117 lines
3.7 KiB
C++
117 lines
3.7 KiB
C++
/**
|
|
* @file CVManager.cpp
|
|
* @brief Configuration Variable Manager Implementation
|
|
*/
|
|
|
|
#include "CVManager.h"
|
|
|
|
CVManager::CVManager() {}
|
|
|
|
bool CVManager::begin() {
|
|
if (!preferences.begin("dcc-decoder", false)) {
|
|
return false;
|
|
}
|
|
|
|
// Check if this is first boot
|
|
if (preferences.getUChar("initialized", 0) == 0) {
|
|
setDefaultCVs();
|
|
preferences.putUChar("initialized", 1);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint8_t CVManager::readCV(uint16_t cvNumber, uint8_t defaultValue) {
|
|
if (cvNumber < 1 || cvNumber > MAX_CV_NUMBER) {
|
|
return defaultValue;
|
|
}
|
|
|
|
return preferences.getUChar(getCVKey(cvNumber).c_str(), defaultValue);
|
|
}
|
|
|
|
bool CVManager::writeCV(uint16_t cvNumber, uint8_t value) {
|
|
if (cvNumber < 1 || cvNumber > MAX_CV_NUMBER) {
|
|
return false;
|
|
}
|
|
|
|
return preferences.putUChar(getCVKey(cvNumber).c_str(), value);
|
|
}
|
|
|
|
void CVManager::resetToDefaults() {
|
|
preferences.clear();
|
|
setDefaultCVs();
|
|
preferences.putUChar("initialized", 1);
|
|
}
|
|
|
|
uint16_t CVManager::getLocoAddress() {
|
|
// Check CV29 bit 5 to determine address mode
|
|
uint8_t cv29 = readCV(CV_CONFIG_DATA_1, 0x06);
|
|
|
|
if (cv29 & 0x20) {
|
|
// Long address mode
|
|
uint8_t highByte = readCV(CV_EXTENDED_ADDRESS_HIGH, 0xC0);
|
|
uint8_t lowByte = readCV(CV_EXTENDED_ADDRESS_LOW, 0x03);
|
|
return ((highByte & 0x3F) << 8) | lowByte;
|
|
} else {
|
|
// Short address mode
|
|
return readCV(CV_PRIMARY_ADDRESS, 3);
|
|
}
|
|
}
|
|
|
|
void CVManager::setLocoAddress(uint16_t address) {
|
|
if (address >= 1 && address <= 127) {
|
|
// Short address
|
|
writeCV(CV_PRIMARY_ADDRESS, address);
|
|
|
|
// Clear long address bit in CV29
|
|
uint8_t cv29 = readCV(CV_CONFIG_DATA_1, 0x06);
|
|
cv29 &= ~0x20;
|
|
writeCV(CV_CONFIG_DATA_1, cv29);
|
|
} else if (address >= 128 && address <= 10239) {
|
|
// Long address
|
|
uint8_t highByte = 0xC0 | ((address >> 8) & 0x3F);
|
|
uint8_t lowByte = address & 0xFF;
|
|
|
|
writeCV(CV_EXTENDED_ADDRESS_HIGH, highByte);
|
|
writeCV(CV_EXTENDED_ADDRESS_LOW, lowByte);
|
|
|
|
// Set long address bit in CV29
|
|
uint8_t cv29 = readCV(CV_CONFIG_DATA_1, 0x06);
|
|
cv29 |= 0x20;
|
|
writeCV(CV_CONFIG_DATA_1, cv29);
|
|
}
|
|
}
|
|
|
|
bool CVManager::isLongAddress() {
|
|
uint8_t cv29 = readCV(CV_CONFIG_DATA_1, 0x06);
|
|
return (cv29 & 0x20) != 0;
|
|
}
|
|
|
|
void CVManager::setDefaultCVs() {
|
|
// Standard CVs
|
|
writeCV(CV_PRIMARY_ADDRESS, 3); // Default address 3
|
|
writeCV(CV_VSTART, 1); // Start voltage
|
|
writeCV(CV_ACCEL_RATE, 10); // Acceleration rate
|
|
writeCV(CV_DECEL_RATE, 10); // Deceleration rate
|
|
writeCV(CV_VHIGH, 255); // Max voltage
|
|
writeCV(CV_VMID, 128); // Mid voltage
|
|
writeCV(CV_VERSION_ID, 1); // Version 1
|
|
writeCV(CV_MANUFACTURER_ID, 13); // DIY decoder
|
|
writeCV(CV_TOTAL_PWM_PERIOD, 20); // 20ms PWM period
|
|
writeCV(CV_CONFIG_DATA_1, 0x06); // 128 speed steps, short address
|
|
|
|
// Custom CVs
|
|
writeCV(CV_MOTOR_KP, 50); // PID Kp = 5.0
|
|
writeCV(CV_MOTOR_KI, 5); // PID Ki = 0.5
|
|
writeCV(CV_MOTOR_KD, 10); // PID Kd = 1.0
|
|
writeCV(CV_RAILCOM_ENABLE, 1); // RailCom enabled
|
|
writeCV(CV_LOAD_COMP_ENABLE, 1); // Load compensation enabled
|
|
writeCV(CV_LED_BRIGHTNESS, 128); // 50% brightness
|
|
writeCV(CV_ACCESSORY_1_MODE, ACC_FUNCTION); // Function controlled
|
|
writeCV(CV_ACCESSORY_2_MODE, ACC_FUNCTION); // Function controlled
|
|
}
|
|
|
|
String CVManager::getCVKey(uint16_t cvNumber) {
|
|
return "cv" + String(cvNumber);
|
|
}
|