1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-27 01:56:14 +01:00

Fix hanging turnouts

Caused by tt->activate call when Turnouts was a struct not a class!
This commit is contained in:
Asbelos 2020-07-23 12:48:38 +01:00
parent 928a9d834a
commit 964f39d376
4 changed files with 35 additions and 18 deletions

View File

@ -46,30 +46,42 @@ const uint8_t PRESCALE_50HZ = (uint8_t)(((FREQUENCY_OSCILLATOR / (50.0 * 4096.0)
*/ */
byte PWMServoDriver::setupFlags=0; // boards that have been initialised byte PWMServoDriver::setupFlags=0; // boards that have been initialised
byte PWMServoDriver::failFlags=0; // boards that have faild initialisation
bool PWMServoDriver::setup(int board) {
if (board>3 || (failFlags & (1<<board))) return false;
if (setupFlags & (1<<board)) return true;
void PWMServoDriver::setup(int board) {
if (board>3 || setupFlags & (1<<board)) return;
Wire.begin(); Wire.begin();
uint8_t i2caddr=PCA9685_I2C_ADDRESS + board; uint8_t i2caddr=PCA9685_I2C_ADDRESS + board;
// Terst if device is available
Wire.beginTransmission(i2caddr);
byte error = Wire.endTransmission();
if (error!=0) {
DIAG(F("\nI2C Servo device 0x%x Not Found %d\n"),i2caddr, error);
failFlags|=1<<board;
return false;
}
//DIAG(F("\nPWMServoDriver::setup %x prescale=%d"),i2caddr,PRESCALE_50HZ); //DIAG(F("\nPWMServoDriver::setup %x prescale=%d"),i2caddr,PRESCALE_50HZ);
writeRegister(i2caddr,PCA9685_MODE1, MODE1_SLEEP | MODE1_AI); writeRegister(i2caddr,PCA9685_MODE1, MODE1_SLEEP | MODE1_AI);
writeRegister(i2caddr,PCA9685_PRESCALE, PRESCALE_50HZ); writeRegister(i2caddr,PCA9685_PRESCALE, PRESCALE_50HZ);
writeRegister(i2caddr,PCA9685_MODE1,MODE1_AI); writeRegister(i2caddr,PCA9685_MODE1,MODE1_AI);
writeRegister(i2caddr,PCA9685_MODE1, MODE1_RESTART | MODE1_AI); writeRegister(i2caddr,PCA9685_MODE1, MODE1_RESTART | MODE1_AI);
setupFlags|=1<<board; setupFlags|=1<<board;
return true;
} }
/*! /*!
* @brief Sets the PWM output to a servo * @brief Sets the PWM output to a servo
*/ */
void PWMServoDriver::setServo(byte servoNum, uint16_t value) { void PWMServoDriver::setServo(byte servoNum, uint16_t value) {
//DIAG(F("\nsetServo %d %d\n"),servoNum,value); DIAG(F("\nsetServo %d %d\n"),servoNum,value);
int board=servoNum/16; int board=servoNum/16;
int pin=servoNum%16; int pin=servoNum%16;
if ( board>3) return; // safe dropout if (setup(board)) {
setup(board); // in case not already done
Wire.beginTransmission(PCA9685_I2C_ADDRESS + board); Wire.beginTransmission(PCA9685_I2C_ADDRESS + board);
Wire.write(PCA9685_FIRST_SERVO + 4 * pin); // 4 registers per pin Wire.write(PCA9685_FIRST_SERVO + 4 * pin); // 4 registers per pin
Wire.write(0); Wire.write(0);
@ -78,6 +90,7 @@ void PWMServoDriver::setServo(byte servoNum, uint16_t value) {
Wire.write(value >> 8); Wire.write(value >> 8);
Wire.endTransmission(); Wire.endTransmission();
} }
}
void PWMServoDriver::writeRegister(uint8_t i2caddr,uint8_t hardwareRegister, uint8_t d) { void PWMServoDriver::writeRegister(uint8_t i2caddr,uint8_t hardwareRegister, uint8_t d) {
Wire.beginTransmission(i2caddr); Wire.beginTransmission(i2caddr);

View File

@ -13,7 +13,8 @@ public:
private: private:
static byte setupFlags; static byte setupFlags;
static void setup(int board); static byte failFlags;
static bool setup(int board);
static void writeRegister(uint8_t i2caddr,uint8_t hardwareRegister, uint8_t d); static void writeRegister(uint8_t i2caddr,uint8_t hardwareRegister, uint8_t d);
}; };

View File

@ -23,6 +23,7 @@
#include "PWMServoDriver.h" #include "PWMServoDriver.h"
bool Turnout::activate(int n,bool state){ bool Turnout::activate(int n,bool state){
//DIAG(F("\nTurnout::activate(%d,%d)\n"),n,state);
Turnout * tt=get(n); Turnout * tt=get(n);
if (tt==NULL) return false; if (tt==NULL) return false;
tt->activate(state); tt->activate(state);
@ -32,9 +33,10 @@
// activate is virtual here so that it can be overridden by a non-DCC turnout mechanism // activate is virtual here so that it can be overridden by a non-DCC turnout mechanism
void Turnout::activate(bool state) { void Turnout::activate(bool state) {
//DIAG(F("\nTurnout::activate\n"));
if (state) data.tStatus|=STATUS_ACTIVE; if (state) data.tStatus|=STATUS_ACTIVE;
else data.tStatus &= ~STATUS_ACTIVE; else data.tStatus &= ~STATUS_ACTIVE;
if (data.tStatus & STATUS_PWM) PWMServoDriver::setServo(data.tStatus & STATUS_PWMPIN, (data.inactiveAngle+state?data.moveAngle:0)); if (data.tStatus & STATUS_PWM) PWMServoDriver::setServo(data.tStatus & STATUS_PWMPIN, (data.inactiveAngle+(state?data.moveAngle:0)));
else DCC::setAccessory(data.address,data.subAddress, state); else DCC::setAccessory(data.address,data.subAddress, state);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -33,7 +33,8 @@ struct TurnoutData {
union {int address; int inactiveAngle;}; // DCC address or PWM servo angle union {int address; int inactiveAngle;}; // DCC address or PWM servo angle
}; };
struct Turnout{ class Turnout {
public:
static Turnout *firstTurnout; static Turnout *firstTurnout;
TurnoutData data; TurnoutData data;
Turnout *nextTurnout; Turnout *nextTurnout;
@ -47,7 +48,7 @@ struct Turnout{
static Turnout *create(int id); static Turnout *create(int id);
static void show(Print & stream, int n); static void show(Print & stream, int n);
static bool showAll(Print & stream); static bool showAll(Print & stream);
virtual void activate(bool state); void activate(bool state);
}; // Turnout }; // Turnout
#endif #endif