001package jmri; 002 003import java.util.EnumSet; 004 005/** 006 * DCC Speed Step Mode. 007 * 008 * <hr> 009 * This file is part of JMRI. 010 * <p> 011 * JMRI is free software; you can redistribute it and/or modify it under the 012 * terms of version 2 of the GNU General Public License as published by the Free 013 * Software Foundation. See the "COPYING" file for a copy of this license. 014 * <p> 015 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 016 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 017 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 018 * 019 * @author Austin Hendrix Copyright (C) 2019 020 */ 021@javax.annotation.concurrent.Immutable 022public enum SpeedStepMode { 023 // NOTE: keep these up to date with xml/schema/locomotive-config.xsd 024 UNKNOWN("unknown", 1, 0.0f, "SpeedStepUnknown"), 025 // NMRA DCC standard speed step modes. 026 NMRA_DCC_128("128", 126, "SpeedStep128"), // Remember there are only 126 non-stop values in 128 speed. 027 NMRA_DCC_28("28", 28, "SpeedStep28"), 028 NMRA_DCC_27("27", 27, "SpeedStep27"), 029 NMRA_DCC_14("14", 14, "SpeedStep14"), 030 // Non-DCC speed step modes. 031 MOTOROLA_28("motorola_28", 28, "SpeedStep28Motorola"), // Motorola 28 speed step mode. 032 TMCC_32("tmcc_32", 32, "SpeedStep32TMCC"), // Lionel TMCC 32 speed step mode. 033 TMCC_200("tmcc_200", 200, "SpeedStep200TMCC"), // Lionel TMCC Legacy 200 speed step mode. 034 INCREMENTAL("incremental", 1, 1.0f, "SpeedStepIncremental"); 035 036 SpeedStepMode(String name, int numSteps, String description) { 037 this(name, numSteps, 1.0f / numSteps, description); 038 } 039 040 SpeedStepMode(String name, int numSteps, float increment, String description) { 041 this.name = name; 042 this.numSteps = numSteps; 043 this.increment = increment; 044 this.description = Bundle.getMessage(description); 045 } 046 047 public final String name; 048 public final int numSteps; 049 public final float increment; 050 public final String description; 051 052 /** 053 * Get a locale friendly Step Mode Description. 054 * For just "128" use name() 055 * @return e.g. "128 SS" 056 */ 057 @Override 058 public String toString() { 059 return description; 060 } 061 062 /** 063 * Convert a human-readable string to a DCC speed step mode. 064 * 065 * @param name string version of speed step mode; example "128" 066 * @return matching SpeedStepMode 067 * @throws IllegalArgumentException if name does not correspond to a valid speed step mode. 068 */ 069 static public SpeedStepMode getByName(String name) { 070 for (SpeedStepMode s : SpeedStepMode.values()) { 071 if (s.name.equals(name)) { 072 return s; 073 } 074 } 075 throw new IllegalArgumentException("Invalid speed step mode: " + name); 076 } 077 078 /** 079 * Convert a localized name string to a DCC speed step mode. 080 * 081 * @param name localized string version of speed step mode; example "128" 082 * @return matching SpeedStepMode 083 * @throws IllegalArgumentException if name does not correspond to a valid speed step mode. 084 */ 085 static public SpeedStepMode getByDescription(String name) { 086 for (SpeedStepMode s : SpeedStepMode.values()) { 087 if (s.description.equals(name)) { 088 return s; 089 } 090 } 091 throw new IllegalArgumentException("Invalid speed step mode: " + name); 092 } 093 094 static public EnumSet<SpeedStepMode> getCompatibleModes( 095 EnumSet<SpeedStepMode> command_station_modes, 096 EnumSet<SpeedStepMode> decoder_modes) { 097 EnumSet<SpeedStepMode> result = command_station_modes.clone(); 098 result.retainAll(decoder_modes); 099 return result; 100 } 101 102 static public SpeedStepMode bestCompatibleMode( 103 EnumSet<SpeedStepMode> command_station_modes, 104 EnumSet<SpeedStepMode> decoder_modes) { 105 EnumSet<SpeedStepMode> result = getCompatibleModes(command_station_modes, decoder_modes); 106 return bestMode(result); 107 } 108 109 static public SpeedStepMode bestMode(EnumSet<SpeedStepMode> modes) { 110 if(modes.contains(NMRA_DCC_128)) { 111 return NMRA_DCC_128; 112 } else if(modes.contains(TMCC_32)) { 113 return TMCC_32; 114 } else if(modes.contains(NMRA_DCC_28)) { 115 return NMRA_DCC_28; 116 } else if(modes.contains(MOTOROLA_28)) { 117 return MOTOROLA_28; 118 } else if(modes.contains(NMRA_DCC_27)) { 119 return NMRA_DCC_27; 120 } else if(modes.contains(NMRA_DCC_14)) { 121 return NMRA_DCC_14; 122 } 123 return UNKNOWN; 124 } 125 126 static public EnumSet<SpeedStepMode> getCompatibleModesForProtocol(LocoAddress.Protocol protocol) { 127 switch (protocol) { 128 case DCC: 129 case DCC_LONG: 130 case DCC_SHORT: 131 return EnumSet.of( 132 // NMRA Speed step modes. 133 SpeedStepMode.NMRA_DCC_128, 134 SpeedStepMode.NMRA_DCC_28, 135 SpeedStepMode.NMRA_DCC_27, 136 SpeedStepMode.NMRA_DCC_14, 137 // Incremental speed step mode, used by LENZ XPA 138 // XpressNet Phone Adapter. 139 SpeedStepMode.INCREMENTAL, 140 // TMCC mode, since some NMRA decoder models are used 141 // for TMCC locomotives. 142 SpeedStepMode.TMCC_32); 143 case MFX: 144 return EnumSet.of( 145 // NMRA Speed step modes. 146 SpeedStepMode.NMRA_DCC_128, 147 SpeedStepMode.NMRA_DCC_28, 148 SpeedStepMode.NMRA_DCC_27, 149 SpeedStepMode.NMRA_DCC_14, 150 // Incremental speed step mode, used by LENZ XPA 151 // XpressNet Phone Adapter. 152 SpeedStepMode.INCREMENTAL, 153 // MFX decoders also support Motorola speed step mode. 154 SpeedStepMode.MOTOROLA_28); 155 case MOTOROLA: 156 return EnumSet.of(SpeedStepMode.MOTOROLA_28); 157 case SELECTRIX: 158 case M4: 159 case OPENLCB: 160 case LGB: 161 // No compatible speed step modes for these protocols. 162 // NOTE: these protocols only appear to be used in conjunction 163 // with ECOS. 164 break; 165 default: 166 // Unhandled case; no compatible speed step mode. 167 break; 168 } 169 return EnumSet.noneOf(SpeedStepMode.class); 170 } 171}