001package jmri.jmrix.easydcc; 002 003import java.util.EnumSet; 004import jmri.DccLocoAddress; 005import jmri.LocoAddress; 006import jmri.SpeedStepMode; 007import jmri.jmrix.AbstractThrottleManager; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * EasyDCC implementation of a ThrottleManager. 013 * <p> 014 * Based on early NCE code. 015 * 016 * @author Bob Jacobsen Copyright (C) 2001, 2005 017 * @author Modified by Kelly Loyd 018 */ 019public class EasyDccThrottleManager extends AbstractThrottleManager { 020 021 private EasyDccSystemConnectionMemo _memo = null; 022 023 /** 024 * Constructor 025 * @param memo system connection. 026 */ 027 public EasyDccThrottleManager(EasyDccSystemConnectionMemo memo) { 028 super(memo); 029 _memo = memo; 030 } 031 032 @Override 033 public void requestThrottleSetup(LocoAddress address, boolean control) { 034 // Not sure if EasyDcc requires feedback. May need to extend this. 035 /* It appears that the first command sent to the Queue in EasyDcc 036 is 'lost' - so it may be beneficial to send a 'Send' command 037 just to wake up the command station. 038 This was tested on v418 - also appears as an issue with the 039 radio throttles. 040 */ 041 if (address instanceof DccLocoAddress ) { 042 log.debug("new EasyDccThrottle for {}", address); 043 notifyThrottleKnown(new EasyDccThrottle(_memo, (DccLocoAddress) address), address); 044 } 045 else { 046 log.error("LocoAddress {} is not a DccLocoAddress",address); 047 failedThrottleRequest(address, "LocoAddress " +address+ " is not a DccLocoAddress"); 048 } 049 } 050 051 // EasyDcc does not have a 'dispatch' function. 052 @Override 053 public boolean hasDispatchFunction() { 054 return false; 055 } 056 057 /** 058 * Address 100 and above is a long address. 059 */ 060 @Override 061 public boolean canBeLongAddress(int address) { 062 return isLongAddress(address); 063 } 064 065 /** 066 * Address 99 and below is a short address. 067 */ 068 @Override 069 public boolean canBeShortAddress(int address) { 070 return !isLongAddress(address); 071 } 072 073 /** 074 * Are there any ambiguous addresses (short vs long) on this system? 075 */ 076 @Override 077 public boolean addressTypeUnique() { 078 return true; 079 } 080 081 /* 082 * Local method for deciding short/long address. 083 */ 084 static boolean isLongAddress(int num) { 085 return (num >= 100); 086 } 087 088 @Override 089 public EnumSet<SpeedStepMode> supportedSpeedModes() { 090 return EnumSet.of(SpeedStepMode.NMRA_DCC_128, SpeedStepMode.NMRA_DCC_28); 091 } 092 093 @Override 094 public boolean disposeThrottle(jmri.DccThrottle t, jmri.ThrottleListener l) { 095 if (super.disposeThrottle(t, l)) { 096 int value = 0; 097 DccLocoAddress address = (DccLocoAddress) t.getLocoAddress(); 098 byte[] result = jmri.NmraPacket.speedStep128Packet(address.getNumber(), 099 address.isLongAddress(), value, t.getIsForward()); 100 // KSL 20040409 - this is messy, as I only wanted 101 // the address to be sent. 102 EasyDccMessage m = new EasyDccMessage(7); 103 // for EasyDCC, release the loco. 104 // D = Dequeue 105 // Cx xx (address) 106 int i = 0; // message index counter 107 m.setElement(i++, 'D'); 108 109 if (address.isLongAddress()) { 110 m.setElement(i++, ' '); 111 m.addIntAsTwoHex(result[0] & 0xFF, i); 112 i = i + 2; 113 m.setElement(i++, ' '); 114 m.addIntAsTwoHex(result[1] & 0xFF, i); 115 } else { // short address 116 m.setElement(i++, ' '); 117 m.addIntAsTwoHex(0, i); 118 i = i + 2; 119 m.setElement(i++, ' '); 120 m.addIntAsTwoHex(result[0] & 0xFF, i); 121 } 122 123 _memo.getTrafficController().sendEasyDccMessage(m, null); 124 if (t instanceof EasyDccThrottle) { 125 EasyDccThrottle lnt = (EasyDccThrottle) t; 126 lnt.throttleDispose(); 127 return true; 128 } 129 else { 130 log.error("DccThrottle {} is not an EasyDccThrottle",t); 131 } 132 } 133 return false; 134 } 135 136 private final static Logger log = LoggerFactory.getLogger(EasyDccThrottleManager.class); 137 138}