001package jmri; 002 003import java.beans.PropertyChangeListener; 004import java.util.List; 005import javax.annotation.Nonnull; 006 007/** 008 * Provide access to the hardware DCC decoder programming capability. 009 * <p> 010 * Programmers come in multiple types: 011 * <ul> 012 * <li>Global, previously "Service Mode" or on a programming track 013 * <li>Addressed, previously "Ops Mode" also known as "programming on the main" 014 * </ul> 015 * Different equipment may also require different programmers: 016 * <ul> 017 * <li>DCC CV programming, on service mode track or on the main 018 * <li>CBUS Node Variable programmers 019 * <li>LocoNet System Variable programmers 020 * <li>LocoNet Op Switch programmers 021 * <li>etc 022 * </ul> 023 * Depending on which type you have, only certain modes can be set. Valid modes 024 * are specified by the class static constants. 025 * <p> 026 * You get a Programmer object from a {@link GlobalProgrammerManager} or an 027 * {@link AddressedProgrammerManager}, which in turn can be located from the 028 * {@link InstanceManager}. 029 * <p> 030 * Starting in JMRI 3.5.5, the CV addresses are Strings for generality. The 031 * methods that use ints for CV addresses will later be deprecated. 032 * <p> 033 * Added possibility to supply CV value hint to the system 034 * <hr> 035 * This file is part of JMRI. 036 * <p> 037 * JMRI is free software; you can redistribute it and/or modify it under the 038 * terms of version 2 of the GNU General Public License as published by the Free 039 * Software Foundation. See the "COPYING" file for a copy of this license. 040 * <p> 041 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 042 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 043 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 044 * 045 * @see jmri.GlobalProgrammerManager 046 * @see jmri.AddressedProgrammerManager 047 * @author Bob Jacobsen Copyright (C) 2001, 2008, 2013 048 * @author Andrew Crosland (C) 2021 049 */ 050public interface Programmer extends jmri.Disposable { 051 052 /** 053 * Perform a CV write in the system-specific manner, and using the specified 054 * programming mode. 055 * <p> 056 * Handles a general address space through a String address. Each programmer 057 * defines the acceptable formats. 058 * <p> 059 * Note that this returns before the write is complete; you have to provide 060 * a ProgListener to hear about completion. For simplicity, expect the return to be on the 061 * <a href="http://jmri.org/help/en/html/doc/Technical/Threads.shtml">GUI thread</a>. 062 * <p> 063 * Exceptions will only be 064 * thrown at the start, not during the actual programming sequence. A 065 * typical exception would be due to an invalid mode (though that should be 066 * prevented earlier) 067 * 068 * @param CV the CV to write 069 * @param val the value to write 070 * @param p the listener that will be notified of the write 071 * @throws jmri.ProgrammerException if unable to communicate 072 */ 073 void writeCV(String CV, int val, ProgListener p) throws ProgrammerException; 074 075 /** 076 * Perform a CV read in the system-specific manner, and using the specified 077 * programming mode. 078 * <p> 079 * Handles a general address space through a String address. Each programmer 080 * defines the acceptable formats. 081 * <p> 082 * Note that this returns before the write is complete; you have to provide 083 * a ProgListener to hear about completion. For simplicity, expect the return to be on the 084 * <a href="http://jmri.org/help/en/html/doc/Technical/Threads.shtml">GUI thread</a>. 085 * <p> 086 * Exceptions will only be 087 * thrown at the start, not during the actual programming sequence. A 088 * typical exception would be due to an invalid mode (though that should be 089 * prevented earlier) 090 * 091 * @param CV the CV to read 092 * @param p the listener that will be notified of the read 093 * @throws jmri.ProgrammerException if unable to communicate 094 */ 095 void readCV(String CV, ProgListener p) throws ProgrammerException; 096 097 /** 098 * Perform a CV read in the system-specific manner, and using the specified 099 * programming mode, possibly using a hint of the current value to speed up 100 * programming. 101 * <p> 102 * Handles a general address space through a String address. Each programmer 103 * defines the acceptable formats. 104 * <p> 105 * On systems that support it, the startVal is a hint as to what the current 106 * value of the CV might be (e.g. the value from the roster). This could be 107 * verified immediately in direct byte mode to speed up the read process. 108 * <p> 109 * Note that this returns before the write is complete; you have to provide 110 * a ProgListener to hear about completion. For simplicity, expect the return to be on the 111 * <a href="http://jmri.org/help/en/html/doc/Technical/Threads.shtml">GUI thread</a>. 112 * <p> 113 * Defaults to the normal read method if not overridden in a specific implementation. 114 * <p> 115 * Exceptions will only be 116 * thrown at the start, not during the actual programming sequence. A 117 * typical exception would be due to an invalid mode (though that should be 118 * prevented earlier) 119 * 120 * @param CV the CV to read 121 * @param p the listener that will be notified of the read 122 * @param startVal a hint of what the current value might be, or 0 123 * @throws jmri.ProgrammerException if unable to communicate 124 */ 125 default void readCV(String CV, ProgListener p, int startVal) throws ProgrammerException { 126 readCV(CV, p); 127 } 128 129 /** 130 * Confirm the value of a CV using the specified programming mode. On some 131 * systems, this is faster than a read. 132 * <p> 133 * Handles a general address space through a String address. Each programmer 134 * defines the acceptable formats. 135 * <p> 136 * Note that this returns before the write is complete; you have to provide 137 * a ProgListener to hear about completion. For simplicity, expect the return to be on the 138 * <a href="http://jmri.org/help/en/html/doc/Technical/Threads.shtml">GUI thread</a>. 139 * <p> 140 * Exceptions will only be 141 * thrown at the start, not during the actual programming sequence. A 142 * typical exception would be due to an invalid mode (though that should be 143 * prevented earlier) 144 * 145 * @param CV the CV to confirm 146 * @param val the value to confirm 147 * @param p the listener that will be notified of the confirmation 148 * @throws jmri.ProgrammerException if unable to communicate 149 */ 150 void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException; 151 152 /** 153 * Get the list of {@link ProgrammingMode} supported by this Programmer. If 154 * the order is significant, earlier modes are better. 155 * 156 * @return the list of supported modes or an empty list 157 */ 158 @Nonnull 159 List<ProgrammingMode> getSupportedModes(); 160 161 /** 162 * Set the programmer to a particular mode. 163 * <p> 164 * Mode is a bound parameter; mode changes fire listeners. 165 * <p> 166 * Only modes returned by {@link #getSupportedModes} are supported. If an 167 * invalid mode is requested, the active mode is unchanged. 168 * 169 * @param p a valid node returned by {@link #getSupportedModes()} or null; 170 * null is ignored if {@link #getSupportedModes()} is not empty 171 */ 172 void setMode(ProgrammingMode p); 173 174 /** 175 * Get the current programming mode 176 * 177 * @return the current mode or null if none is defined and no default mode 178 * is defined 179 */ 180 ProgrammingMode getMode(); 181 182 /** 183 * Checks the general read capability, regardless of mode 184 * 185 * @return true if the programmer is capable of reading; false otherwise 186 */ 187 boolean getCanRead(); 188 189 /** 190 * Checks the general read capability, regardless of mode, for a specific 191 * address 192 * 193 * @param addr the address to read 194 * @return true if the address can be read; false otherwise 195 */ 196 boolean getCanRead(String addr); 197 198 /** 199 * Checks the general write capability, regardless of mode 200 * 201 * @return true if the programmer is capable of writing; false otherwise 202 */ 203 boolean getCanWrite(); 204 205 /** 206 * Checks the general write capability, regardless of mode, for a specific 207 * address 208 * 209 * @param addr the address to write to 210 * @return true if the address can be written to; false otherwise 211 */ 212 boolean getCanWrite(String addr); 213 214 /** 215 * Learn about whether the programmer does any kind of verification of write 216 * operations 217 * 218 * @param addr A CV address to check (in case this varies with CV range) or 219 * null for any 220 * @return The confirmation behavior that can be counted on (might be better 221 * in some cases) 222 */ 223 @Nonnull 224 WriteConfirmMode getWriteConfirmMode(String addr); 225 226 enum WriteConfirmMode { 227 /** 228 * No verification available, writes are blind 229 */ 230 NotVerified, 231 /** 232 * Programmer signals error if there's no reply from the device 233 */ 234 DecoderReply, 235 /** 236 * Programmer does a read after write to verify 237 */ 238 ReadAfterWrite 239 } 240 241 /** 242 * wrapper to call {@link jmri.ProgListener#programmingOpReply} that verifies 243 * the specified progListener is not null. 244 * 245 * @param p listener to notify 246 * @param value result value 247 * @param status code from jmri.ProgListener 248 */ 249 default void notifyProgListenerEnd(ProgListener p, int value, int status) { 250 if ( p != null ) { 251 p.programmingOpReply(value, status); 252 } 253 } 254 255 void addPropertyChangeListener(PropertyChangeListener p); 256 257 void removePropertyChangeListener(PropertyChangeListener p); 258 259 // error handling on request is via exceptions 260 // results are returned via the ProgListener callback 261 @Nonnull 262 String decodeErrorCode(int i); 263 264 /** 265 * Free up system resources. 266 * Overriding classes should be capable of this being called 267 * multiple times as per the {@link jmri.Disposable} interface. 268 * {@inheritDoc} 269 */ 270 @Override 271 default void dispose() {} 272 273}