////////////////////////////////////////////////////////////////////////// // DCC++ CONTROLLER: Core Components // // PowerButton - send power on/off command to the DCC++ Base Station // // CurrentMeter - monitors main track current draw from the DCC++ Base Station // - displays scrolling bar chart of current measured // // HelpButton - toggles Help Window // // QuitButton - quits DCC++ Controller // - connection to DCC++ Base Station terminated // - NOTE: track power remains on and trains will continue to operate // since DCC+ Base Station operates independently! // // AccessoryButton - sends a DCC ACCESSORY COMMAND to the DCC++ Base Station // to either activate or de-activate an accessory depending on // whether the button is labeled "ON" or "OFF" // - two pre-specified input boxes are used: one for the user // to input the desired accessory address, and one for // accessory number (sub-address) // - the default configuration of DCC++ Controller defines an // Accessory Window that includes these two input boxes as well // as ON and OFF buttons. // // CleaningCarButton - sends a DCC THROTTLE COMMAND to the DCC++ Base Station that operates // a mobile decoder with a pre-specified cab number // - this decoder drives a motor that spins a cleaning pad in a // track-cleaning car // - clicking the button toggles the throttle between either 0 or 126 (max speed) // - the default configuration of DCC++ Controller defines an // Extras Window that includes this button // // LEDColorButton - provide for interactive control of an LED-RGB Light Strip ////////////////////////////////////////////////////////////////////////// // DCC Component: PowerButton ////////////////////////////////////////////////////////////////////////// class PowerButton extends RectButton{ PowerButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText); } PowerButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ super(window, xPos, yPos, bWidth, bHeight, baseHue, color(0), fontSize, bText, ButtonType.NORMAL); } // PowerButton ////////////////////////////////////////////////////////////////////////// void turnOn(){ aPort.write("<1>"); } ////////////////////////////////////////////////////////////////////////// void shiftPressed(){ aPort.write(""); exit(); } ////////////////////////////////////////////////////////////////////////// void turnOff(){ aPort.write("<0>"); } } // PowerButton Class ////////////////////////////////////////////////////////////////////////// // DCC Component: CurrentMeter ////////////////////////////////////////////////////////////////////////// class CurrentMeter extends DccComponent{ int nSamples, kHeight; int maxCurrent; int[] samples; int sampleIndex; int nGridLines; boolean isOn; CurrentMeter(int xPos, int yPos, int nSamples, int kHeight, int maxCurrent, int nGridLines){ this.xPos=xPos; this.yPos=yPos; this.nSamples=nSamples; this.kHeight=kHeight; this.maxCurrent=maxCurrent; this.nGridLines=nGridLines; this.isOn=true; samples=new int[nSamples]; sampleIndex=nSamples-1; dccComponents.add(this); } // CurrentMeter ////////////////////////////////////////////////////////////////////////// void display(){ int i; rectMode(CORNER); noFill(); strokeWeight(1); textFont(buttonFont,8); textAlign(LEFT,CENTER); stroke(200); rect(xPos,yPos,nSamples+1,kHeight+2); if(isOn) stroke(50,200,100); else stroke(200,100,100); for(i=0;i511) msgBoxMain.setMessage("Error - Accessory Address must be in range 0-511",color(255,30,30)); else if(accSubAddress>3) msgBoxMain.setMessage("Error - Accessory Sub Address must be in range 0-3",color(255,30,30)); else aPort.write(""); } } // AccessoryButton Class ////////////////////////////////////////////////////////////////////////// // DCC Component: Quit Button ////////////////////////////////////////////////////////////////////////// class QuitButton extends RectButton{ QuitButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText); } QuitButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.NORMAL); } // PowerButton ////////////////////////////////////////////////////////////////////////// void turnOn(){ super.turnOn(); exit(); } } // QuitButton Class ////////////////////////////////////////////////////////////////////////// // DCC Component: Help Button ////////////////////////////////////////////////////////////////////////// class HelpButton extends EllipseButton{ HelpButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText); } HelpButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ super(window, xPos, yPos, bWidth, bHeight, baseHue, color(255), fontSize, bText, ButtonType.ONESHOT); } // PowerButton ////////////////////////////////////////////////////////////////////////// void pressed(){ super.pressed(); helpWindow.toggle(); } } // HelpButton Class ////////////////////////////////////////////////////////////////////////// // DCC Component: CleaningCar Button ////////////////////////////////////////////////////////////////////////// class CleaningCarButton extends RectButton{ int cab; int reg; CleaningCarButton(int cab, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ this(null, cab, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText); } CleaningCarButton(Window window, int cab, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){ super(window, xPos, yPos, bWidth, bHeight, baseHue, color(0), fontSize, bText, ButtonType.NORMAL); reg=cabButtons.size()+1; this.cab=cab; } // PowerButton ////////////////////////////////////////////////////////////////////////// void turnOn(){ super.turnOn(); aPort.write(""); } ////////////////////////////////////////////////////////////////////////// void turnOff(){ super.turnOff(); aPort.write(""); } ////////////////////////////////////////////////////////////////////////// void shiftPressed(){ autoPilot.clean(); } } // CleaningCarButton Class ////////////////////////////////////////////////////////////////////////// // DCC Component: LED Color Button ////////////////////////////////////////////////////////////////////////// class LEDColorButton extends DccComponent{ int bWidth, bHeight; float hue; float sat; float val; LEDColorButton(Window window, int xPos, int yPos, int bWidth, int bHeight, float hue, float sat, float val){ this.xPos=xPos; this.yPos=yPos; this.bWidth=bWidth; this.bHeight=bHeight; this.hue=hue; this.sat=sat; this.val=val; this.window=window; window.windowComponents.add(this); } ////////////////////////////////////////////////////////////////////////// void display(){ rectMode(CENTER); colorMode(HSB,1.0,1.0,1.0); fill(hue,sat,val); rect(xPos+xWindow(),yPos+yWindow(),bWidth,bHeight); colorMode(RGB,255); } ////////////////////////////////////////////////////////////////////////// void update(int s){ color c; colorMode(HSB,1.0,1.0,1.0); c=color(hue,sat,val); colorMode(RGB,255); aPort.write(""); ledHueMsg.setMessage("Hue: "+int(hue*360),color(200,200,200)); ledSatMsg.setMessage("Sat: "+int(sat*100),color(200,200,200)); ledValMsg.setMessage("Val: "+int(val*100),color(200,200,200)); ledRedMsg.setMessage("Red: "+int(red(c)),color(200,200,200)); ledGreenMsg.setMessage("Green: "+int(green(c)),color(200,200,200)); ledBlueMsg.setMessage("Blue: "+int(blue(c)),color(200,200,200)); } } // LEDColorButton Class ////////////////////////////////////////////////////////////////////////// // DCC Component: LED Value Selector ////////////////////////////////////////////////////////////////////////// class LEDValSelector extends DccComponent{ int bWidth, bHeight; LEDColorButton cButton; PImage valBox; LEDValSelector(Window window, int xPos, int yPos, int bWidth, int bHeight, LEDColorButton cButton){ this.xPos=xPos; this.yPos=yPos; this.bWidth=bWidth; this.bHeight=bHeight; this.cButton=cButton; valBox = createImage(bWidth+1,bHeight+1,RGB); this.window=window; window.windowComponents.add(this); colorMode(HSB,1.0,1.0,1.0); valBox.loadPixels(); for(int y=0;y=xPos+xWindow()+cButton.val*float(bWidth)-5 && mouseX<=xPos+xWindow()+cButton.val*float(bWidth)+5 && mouseY>=yPos+yWindow()+bHeight+2 && mouseY<=yPos+yWindow()+bHeight+22){ cursorType=HAND; selectedComponent=this; } } ////////////////////////////////////////////////////////////////////////// void drag(){ cButton.val=constrain(float(mouseX-xPos-xWindow())/bWidth,0.0,1.0); cButton.update(0); } ////////////////////////////////////////////////////////////////////////// void released(){ cButton.update(1); } } // LEDValSelector Class ////////////////////////////////////////////////////////////////////////// // DCC Component: LED Color Selector ////////////////////////////////////////////////////////////////////////// class LEDColorSelector extends DccComponent{ PImage colorWheel; int radius; LEDColorButton cButton; LEDColorSelector(Window window, int xPos, int yPos, int radius, LEDColorButton cButton){ float d, h; this.xPos=xPos; this.yPos=yPos; this.radius=radius; this.cButton=cButton; colorWheel=createImage(radius*2+1,radius*2+1,RGB); this.window=window; window.windowComponents.add(this); colorWheel.loadPixels(); colorMode(HSB,1.0,1.0,1.0); for(int i=0, y=radius;y>=-radius;y--){ for(int x=-radius;x<=radius;x++){ d=sqrt(x*x+y*y); if(d<0.5){ colorWheel.pixels[i]=color(0.0,0.0,1.0); // center of wheel always has zero saturation (hue does not matter) } else if(d>radius){ colorWheel.pixels[i]=color(0.0,0.0,0.0); // outside of wheel is always fully black (hue and saturation does not matter) } else { h=acos(float(x)/d); // find angle in radians if(y<0) // adjust angle to reflect lower half of wheel h=TWO_PI-h; colorWheel.pixels[i]=color(h/TWO_PI,d/float(radius),1.0); // hue is based on angle normalized to 1.0, saturation is based on distance to center normalized to 1.0, brightness is always 1.0 } i++; } // x-loop } // y-loop colorMode(RGB,255); colorWheel.updatePixels(); } ////////////////////////////////////////////////////////////////////////// void display(){ imageMode(CENTER); colorMode(HSB,1.0,1.0,1.0); image(colorWheel,xPos+xWindow(),yPos+yWindow()); colorMode(RGB,255); } ////////////////////////////////////////////////////////////////////////// void check(){ if(selectedComponent==null && ((pow(mouseX-xPos-xWindow(),2)+pow(mouseY-yPos-yWindow(),2))<=pow(radius,2))){ cursorType=CROSS; selectedComponent=this; } } // check ////////////////////////////////////////////////////////////////////////// void pressed(){ drag(); } ////////////////////////////////////////////////////////////////////////// void drag(){ float d,h; color selectedColor; d=sqrt(pow(mouseX-xPos-xWindow(),2)+pow(mouseY-yPos-yWindow(),2)); if(d<0.5){ h=0.0; } else { h=acos(float(mouseX-xPos-xWindow())/d); if(mouseY>(yPos+yWindow())) h=TWO_PI-h; cButton.hue=h/TWO_PI; cButton.sat=constrain(d/float(radius),0.0,1.0); } cButton.update(0); } ////////////////////////////////////////////////////////////////////////// void released(){ cButton.update(1); } } // LEDColorSelector Class //////////////////////////////////////////////////////////////////////////