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 INCREMENTAL("incremental", 1, 1.0f, "SpeedStepIncremental"); 034 035 SpeedStepMode(String name, int numSteps, String description) { 036 this(name, numSteps, 1.0f / numSteps, description); 037 } 038 039 SpeedStepMode(String name, int numSteps, float increment, String description) { 040 this.name = name; 041 this.numSteps = numSteps; 042 this.increment = increment; 043 this.description = Bundle.getMessage(description); 044 } 045 046 public final String name; 047 public final int numSteps; 048 public final float increment; 049 public final String description; 050 051 /** 052 * Get a locale friendly Step Mode Description. 053 * For just "128" use name() 054 * @return e.g. "128 SS" 055 */ 056 @Override 057 public String toString() { 058 return description; 059 } 060 061 /** 062 * Convert a human-readable string to a DCC speed step mode. 063 * 064 * @param name string version of speed step mode; example "128" 065 * @return matching SpeedStepMode 066 * @throws IllegalArgumentException if name does not correspond to a valid speed step mode. 067 */ 068 static public SpeedStepMode getByName(String name) { 069 for (SpeedStepMode s : SpeedStepMode.values()) { 070 if (s.name.equals(name)) { 071 return s; 072 } 073 } 074 throw new IllegalArgumentException("Invalid speed step mode: " + name); 075 } 076 077 /** 078 * Convert a localized name string to a DCC speed step mode. 079 * 080 * @param name localized string version of speed step mode; example "128" 081 * @return matching SpeedStepMode 082 * @throws IllegalArgumentException if name does not correspond to a valid speed step mode. 083 */ 084 static public SpeedStepMode getByDescription(String name) { 085 for (SpeedStepMode s : SpeedStepMode.values()) { 086 if (s.description.equals(name)) { 087 return s; 088 } 089 } 090 throw new IllegalArgumentException("Invalid speed step mode: " + name); 091 } 092 093 static public EnumSet<SpeedStepMode> getCompatibleModes( 094 EnumSet<SpeedStepMode> command_station_modes, 095 EnumSet<SpeedStepMode> decoder_modes) { 096 EnumSet<SpeedStepMode> result = command_station_modes.clone(); 097 result.retainAll(decoder_modes); 098 return result; 099 } 100 101 static public SpeedStepMode bestCompatibleMode( 102 EnumSet<SpeedStepMode> command_station_modes, 103 EnumSet<SpeedStepMode> decoder_modes) { 104 EnumSet<SpeedStepMode> result = getCompatibleModes(command_station_modes, decoder_modes); 105 return bestMode(result); 106 } 107 108 static public SpeedStepMode bestMode(EnumSet<SpeedStepMode> modes) { 109 if(modes.contains(NMRA_DCC_128)) { 110 return NMRA_DCC_128; 111 } else if(modes.contains(TMCC_32)) { 112 return TMCC_32; 113 } else if(modes.contains(NMRA_DCC_28)) { 114 return NMRA_DCC_28; 115 } else if(modes.contains(MOTOROLA_28)) { 116 return MOTOROLA_28; 117 } else if(modes.contains(NMRA_DCC_27)) { 118 return NMRA_DCC_27; 119 } else if(modes.contains(NMRA_DCC_14)) { 120 return NMRA_DCC_14; 121 } 122 return UNKNOWN; 123 } 124 125 static public EnumSet<SpeedStepMode> getCompatibleModesForProtocol(LocoAddress.Protocol protocol) { 126 switch (protocol) { 127 case DCC: 128 case DCC_LONG: 129 case DCC_SHORT: 130 return EnumSet.of( 131 // NMRA Speed step modes. 132 SpeedStepMode.NMRA_DCC_128, 133 SpeedStepMode.NMRA_DCC_28, 134 SpeedStepMode.NMRA_DCC_27, 135 SpeedStepMode.NMRA_DCC_14, 136 // Incremental speed step mode, used by LENZ XPA 137 // XpressNet Phone Adapter. 138 SpeedStepMode.INCREMENTAL, 139 // TMCC mode, since some NMRA decoder models are used 140 // for TMCC locomotives. 141 SpeedStepMode.TMCC_32); 142 case MFX: 143 return EnumSet.of( 144 // NMRA Speed step modes. 145 SpeedStepMode.NMRA_DCC_128, 146 SpeedStepMode.NMRA_DCC_28, 147 SpeedStepMode.NMRA_DCC_27, 148 SpeedStepMode.NMRA_DCC_14, 149 // Incremental speed step mode, used by LENZ XPA 150 // XpressNet Phone Adapter. 151 SpeedStepMode.INCREMENTAL, 152 // MFX decoders also support Motorola speed step mode. 153 SpeedStepMode.MOTOROLA_28); 154 case MOTOROLA: 155 return EnumSet.of(SpeedStepMode.MOTOROLA_28); 156 case SELECTRIX: 157 case M4: 158 case OPENLCB: 159 case LGB: 160 // No compatible speed step modes for these protocols. 161 // NOTE: these protocols only appear to be used in conjunction 162 // with ECOS. 163 break; 164 default: 165 // Unhandled case; no compatible speed step mode. 166 break; 167 } 168 return EnumSet.noneOf(SpeedStepMode.class); 169 } 170}