Files
ESP32/DCC-Centrale/Firmware/Controller/DCCpp_Controller/progComponents.pde
2026-02-10 11:05:54 +01:00

439 lines
17 KiB
Plaintext

//////////////////////////////////////////////////////////////////////////
// DCC++ CONTROLLER: Programming Components
//
// All classes and methods related to programming mobile decoder
// configuration variables (CVs)
////
// ProgWriteReadButton - sends a DCC PROGRAMMING COMMAND to the DCC++ Base Station
// that either reads from, or writes to, a user-specified CV in a mobile
// decoder on the Programming Track
// - Note: cab numbers (mobile decoder addresses) are not used on the Programming
// Track. Whatever locomotive is on the track will be programmed!
// - users specify the CV to be written or read via an input box
// - in the case of writing to a CV, three linked input boxes allow the user to
// specify the byte in either HEX, DECIMAL, or BINARY formats
// - in the case of reading from a CV, these three linked input boxes are updated
// to display the results of the read in HEX, DECIMAL, and BINARY formats
// - in the case of writing to a CV, the DCC++ Base Station automatically performs an
// subsequent read to verify the byte was properly written
//
// ProgAddReadButton - sends a series of DCC PROGRAMMING COMMANDS to the DCC++ Base Station
// that reads the following CVs from a mobile decoder on the Programming Track:
//
// * CV #1 - contains the short (single byte) cab address
// * CV #17 - contains the high byte of a long (two byte) cab address
// * CV #18 - contains the low byte of a long (two byte) cab address
// * CV #29 - bit 5 indicates whether mobile decoder is using long or short cab address
//
// - CV #17 and CV #18 are combined into a single cab address
// - three input boxes display the results of the short address, the long address,
// - and whether of not the mobile decoder is using the long or short cab address
//
// ProgShortAddWriteButton - sends a DCC PROGRAMMING COMMAND to the DCC++ Base Station
// that writes the short cab address specified in the first input box described above
// to a mobile decoder on the Programming Track
//
// ProgLongAddWriteButton - sends a DCC PROGRAMMING COMMAND to the DCC++ Base Station
// that writes the long cab address specified in the second input box described above
// to a mobile decoder on the Programming Track
//
// ProgLongShortButton - sends a DCC PROGRAMMING COMMAND to the DCC++ Base Station
// that indicates whether the mobile decoder on the Programming Track should use its
// short cab address or long cab address
//
// The default configuration of DCC++ Controller defines a Programming Window that includes all of the above components
//
//
// OpWriteButton - sends a DCC PROGRAMMING COMMAND to the DCC++ Base Station that writes a user-specified byte
// or sets/clears a user-specified bit in a user-specified CV of a mobile decoder with a
// user-specified cab address on the Main Operations Track
// - uses one input box for specifiying the cab address and one for the CV
// - when writing a full byte, uses 3 linked boxes for specifying the value in
// either HEX, DECIMAL, or BINARY format
// - when setting/clearing a bit, uses on input box to specify the bit number
// - the default configuration of DCC++ Controller defines an Operation Programming Window that
// includes all of these components
//////////////////////////////////////////////////////////////////////////
// DCC Component: ProgWriteReadButton
//////////////////////////////////////////////////////////////////////////
class ProgWriteReadButton extends EllipseButton implements CallBack{
InputBox progCVInput, progValueInput;
ProgWriteReadButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox progCVInput, InputBox progValueInput){
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText, progCVInput, progValueInput);
}
ProgWriteReadButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox progCVInput, InputBox progValueInput){
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT);
this.progCVInput=progCVInput;
this.progValueInput=progValueInput;
callBacks.add(this);
} // ProgrWriteReadButton
//////////////////////////////////////////////////////////////////////////
void pressed(){
super.pressed();
int cv=progCVInput.getIntValue();
int val=progValueInput.getIntValue();
if(cv<1 || cv>1024){
msgBoxMain.setMessage("Error - CV must be in range 1-1024",color(255,30,30));
} else if(bText=="WRITE"){
aPort.write("<W"+cv+" "+val+" "+callBacks.indexOf(this)+" 1>");
} else if(bText=="READ"){
aPort.write("<R"+cv+" "+callBacks.indexOf(this)+" 0>");
}
} // pressed
//////////////////////////////////////////////////////////////////////////
void execute(int n, String c){
String[] cs = splitTokens(c);
int cv=int(cs[0]);
int val=int(cs[1]);
progCVInput.setIntValue(cv);
if(val<0){
msgBoxMain.setMessage(n==0?"Error - Read Failed":"Error - Write Failed",color(255,30,30));
progHEXInput.resetValue();
progBINInput.resetValue();
progDECInput.resetValue();
} else{
msgBoxMain.setMessage(n==0?"Read Succeeded":"Write Succeeded",color(30,150,30));
progHEXInput.setIntValue(val);
progBINInput.setIntValue(val);
progDECInput.setIntValue(val);
}
} // execute
} // progWriteReadButton Class
//////////////////////////////////////////////////////////////////////////
// DCC Component: ProgAddReadButton
//////////////////////////////////////////////////////////////////////////
class ProgAddReadButton extends EllipseButton implements CallBack{
InputBox shortAddInput, longAddInput;
MessageBox activeAddBox;
int longAdd;
ProgAddReadButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox shortAddInput, InputBox longAddInput, MessageBox activeAddBox){
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText, shortAddInput, longAddInput, activeAddBox);
}
ProgAddReadButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox shortAddInput, InputBox longAddInput, MessageBox activeAddBox){
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT);
this.shortAddInput=shortAddInput;
this.longAddInput=longAddInput;
this.activeAddBox=activeAddBox;
callBacks.add(this);
} // ProgAddReadButton
//////////////////////////////////////////////////////////////////////////
void pressed(){
super.pressed();
aPort.write("<R1 "+callBacks.indexOf(this)+" 0>");
} // pressed
//////////////////////////////////////////////////////////////////////////
void execute(int n, String c){
String[] cs = splitTokens(c);
int cv=int(cs[0]);
int val=int(cs[1]);
switch(cv){
case 1:
if(val<0){
msgBoxMain.setMessage("Error - Reading Short Address Failed",color(255,30,30));
shortAddInput.resetValue();
} else{
shortAddInput.setIntValue(val);
aPort.write("<R17 "+callBacks.indexOf(this)+" 0>");
}
break;
case 17:
if(val<0){
msgBoxMain.setMessage("Error - Reading First Byte of Long Address Failed",color(255,30,30));
longAddInput.resetValue();
} else{
longAdd=(val&0x3F)*256;
aPort.write("<R18 "+callBacks.indexOf(this)+" 0>");
}
break;
case 18:
if(val<0){
msgBoxMain.setMessage("Error - Reading Second Byte of Long Address Failed",color(255,30,30));
longAddInput.resetValue();
} else{
longAdd+=val;
longAddInput.setIntValue(longAdd);
aPort.write("<R29 "+callBacks.indexOf(this)+" 0>");
}
break;
case 29:
if(val<0){
msgBoxMain.setMessage("Error - Reading Second Byte of Long Address Failed",color(255,30,30));
activeAddBox.setMessage("?",color(200,50,50));
} else{
if((val&0x20)==0)
activeAddBox.setMessage("SHORT",color(200,50,50));
else
activeAddBox.setMessage("LONG",color(200,50,50));
msgBoxMain.setMessage("Reading Short and Long Addresses Succeeded",color(30,150,30));
}
break;
}
} // execute
} // ProgAddReadButton Class
//////////////////////////////////////////////////////////////////////////
// DCC Component: ProgShortAddWriteButton
//////////////////////////////////////////////////////////////////////////
class ProgShortAddWriteButton extends EllipseButton implements CallBack{
InputBox addInput;
ProgShortAddWriteButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox addInput){
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText, addInput);
}
ProgShortAddWriteButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox addInput){
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT);
this.addInput=addInput;
callBacks.add(this);
} // ProgAddReadButton
//////////////////////////////////////////////////////////////////////////
void pressed(){
super.pressed();
int val=addInput.getIntValue();
if(val<1 || val>127){
msgBoxMain.setMessage("Error - Short Address must be in range 1-127",color(255,30,30));
} else {
aPort.write("<W1"+" "+val+" "+callBacks.indexOf(this)+" 0>");
}
} // pressed
//////////////////////////////////////////////////////////////////////////
void execute(int n, String c){
String[] cs = splitTokens(c);
int cv=int(cs[0]);
int val=int(cs[1]);
if(val<0){
msgBoxMain.setMessage("Error - Write Short Address Failed",color(255,30,30));
addInput.resetValue();
} else{
msgBoxMain.setMessage("Write Short Address Succeeded",color(30,150,30));
addInput.setIntValue(val);
}
} // execute
} // ProgShortAddWriteButton Class
//////////////////////////////////////////////////////////////////////////
// DCC Component: ProgLongAddWriteButton
//////////////////////////////////////////////////////////////////////////
class ProgLongAddWriteButton extends EllipseButton implements CallBack{
InputBox addInput;
int longAddIn, longAddOut;
ProgLongAddWriteButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox addInput){
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText, addInput);
}
ProgLongAddWriteButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox addInput){
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT);
this.addInput=addInput;
callBacks.add(this);
} // ProgAddReadButton
//////////////////////////////////////////////////////////////////////////
void pressed(){
super.pressed();
longAddIn=addInput.getIntValue();
if(longAddIn<0 || longAddIn>10239){
msgBoxMain.setMessage("Error - Long Address must be in range 0-10239",color(255,30,30));
} else {
aPort.write("<W17"+" "+(longAddIn/256+192)+" "+callBacks.indexOf(this)+" 0>");
}
} // pressed
//////////////////////////////////////////////////////////////////////////
void execute(int n, String c){
String[] cs = splitTokens(c);
int cv=int(cs[0]);
int val=int(cs[1]);
switch(cv){
case 17:
if(val<0){
msgBoxMain.setMessage("Error - Writing First Byte of Long Address Failed",color(255,30,30));
addInput.resetValue();
} else{
longAddOut=(val&0x3F)*256;
aPort.write("<W18"+" "+(longAddIn%256)+" "+callBacks.indexOf(this)+" 0>");
}
break;
case 18:
if(val<0){
msgBoxMain.setMessage("Error - Writing Second Byte of Long Address Failed",color(255,30,30));
addInput.resetValue();
} else{
msgBoxMain.setMessage("Write Long Address Succeeded",color(30,150,30));
longAddOut+=val;
addInput.setIntValue(longAddOut);
}
break;
}
} // execute
} // ProgLongAddWriteButton Class
//////////////////////////////////////////////////////////////////////////
// DCC Component: ProgLongShortButton
//////////////////////////////////////////////////////////////////////////
class ProgLongShortButton extends EllipseButton implements CallBack{
MessageBox activeAddBox;
ProgLongShortButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, MessageBox activeAddBox){
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText, activeAddBox);
}
ProgLongShortButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, MessageBox activeAddBox){
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT);
this.activeAddBox=activeAddBox;
callBacks.add(this);
} // ProgrWriteReadButton
//////////////////////////////////////////////////////////////////////////
void pressed(){
super.pressed();
if(bText=="Long"){
aPort.write("<B 29 5 1 "+callBacks.indexOf(this)+" 1>");
} else if(bText=="Short"){
aPort.write("<B 29 5 0 "+callBacks.indexOf(this)+" 0>");
}
} // pressed
//////////////////////////////////////////////////////////////////////////
void execute(int n, String c){
String[] cs = splitTokens(c);
int val=int(cs[2]);
switch(val){
case -1:
msgBoxMain.setMessage(n==1?"Error - Activating Long Address Failed":"Error - Activating Short Address Failed",color(255,30,30));
activeAddBox.setMessage("?",color(200,50,50));
break;
case 0:
msgBoxMain.setMessage("Activating Short Address Succeeded",color(30,150,30));
activeAddBox.setMessage("SHORT",color(200,50,50));
break;
case 1:
msgBoxMain.setMessage("Activating Long Address Succeeded",color(30,150,30));
activeAddBox.setMessage("LONG",color(200,50,50));
break;
}
} // execute
} // ProgLongShortButton Class
//////////////////////////////////////////////////////////////////////////
// DCC Component: OpWriteButton
//////////////////////////////////////////////////////////////////////////
class OpWriteButton extends EllipseButton{
InputBox opCVInput, opValueInput;
OpWriteButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox opCVInput, InputBox opValueInput){
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText, opCVInput, opValueInput);
}
OpWriteButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText, InputBox opCVInput, InputBox opValueInput){
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT);
this.opCVInput=opCVInput;
this.opValueInput=opValueInput;
} // OpWriteButton
//////////////////////////////////////////////////////////////////////////
void pressed(){
super.pressed();
int cab=opCabInput.getIntValue();
int cv=opCVInput.getIntValue();
int val=opValueInput.getIntValue();
if(cab<1 || cab>10239){
msgBoxMain.setMessage("Error - Cab must be in range 1-10239",color(255,30,30));
return;
}
if(cv<1 || cv>1024){
msgBoxMain.setMessage("Error - CV must be in range 1-1024",color(255,30,30));
return;
}
if(bText=="WRITE"){
aPort.write("<w"+cab+" "+cv+" "+val+" >");
return;
}
if(val>7){
msgBoxMain.setMessage("Error - Bit must be in range 0-7",color(255,30,30));
return;
}
if(bText=="SET"){
aPort.write("<b"+cab+" "+cv+" "+val+" 1>");
} else if(bText=="CLEAR"){
aPort.write("<b"+cab+" "+cv+" "+val+" 0>");
}
} // pressed
} // OpWriteButton Class