001package jmri.jmrix.easydcc; 002 003import java.util.ArrayList; 004import java.util.List; 005import javax.annotation.Nonnull; 006 007import jmri.AddressedProgrammer; 008import jmri.NmraPacket; 009import jmri.ProgListener; 010import jmri.ProgrammerException; 011import jmri.ProgrammingMode; 012 013/** 014 * Provide an Ops Mode Programmer via a wrapper that works with the 015 * EasyDccCommandStation object. 016 * <p> 017 * Functionally, this just creates packets to send via the Command Station. 018 * 019 * @see jmri.Programmer 020 * @author Bob Jacobsen Copyright (C) 2002 021 */ 022public class EasyDccOpsModeProgrammer extends EasyDccProgrammer implements AddressedProgrammer { 023 024 int mAddress; 025 boolean mLongAddr; 026 027 public EasyDccOpsModeProgrammer(int pAddress, boolean pLongAddr, EasyDccSystemConnectionMemo memo) { 028 super(memo); 029 mAddress = pAddress; 030 mLongAddr = pLongAddr; 031 } 032 033 /** 034 * {@inheritDoc} 035 * 036 * Forward a write request to an ops-mode write operation. 037 */ 038 @Override 039 public synchronized void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException { 040 final int CV = Integer.parseInt(CVname); 041 log.debug("write CV={} val={}", CV, val); 042 // create the message and fill it, 043 byte[] contents = NmraPacket.opsCvWriteByte(mAddress, mLongAddr, CV, val); 044 EasyDccMessage msg = new EasyDccMessage(4 + 3 * contents.length); 045 msg.setOpCode('S'); 046 msg.setElement(1, ' '); 047 msg.setElement(2, '0'); 048 msg.setElement(3, '5'); 049 int j = 4; 050 for (int i = 0; i < contents.length; i++) { 051 msg.setElement(j++, ' '); 052 msg.addIntAsTwoHex(contents[i] & 0xFF, j); 053 j = j + 2; 054 } 055 056 // record state. COMMANDSENT is just waiting for a reply... 057 useProgrammer(p); 058 _progRead = false; 059 progState = COMMANDSENT; 060 _val = val; 061 _cv = CV; 062 063 // start the error timer 064 startShortTimer(); 065 066 // send it 067 tc.sendEasyDccMessage(msg, this); 068 } 069 070 /** 071 * {@inheritDoc} 072 */ 073 @Override 074 public synchronized void readCV(String CVname, ProgListener p) throws ProgrammerException { 075 final int CV = Integer.parseInt(CVname); 076 log.debug("read CV={}", CV); 077 log.error("readCV not available in this protocol"); 078 throw new ProgrammerException(); 079 } 080 081 /** 082 * {@inheritDoc} 083 */ 084 @Override 085 public synchronized void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException { 086 log.debug("confirm CV={}", CV); 087 log.error("confirmCV not available in this protocol"); 088 throw new ProgrammerException(); 089 } 090 091 /** 092 * {@inheritDoc} 093 */ 094 @Override 095 @Nonnull 096 public List<ProgrammingMode> getSupportedModes() { 097 List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>(); 098 ret.add(ProgrammingMode.OPSBYTEMODE); 099 return ret; 100 } 101 102 /** 103 * {@inheritDoc} 104 * 105 * Can this ops-mode programmer read back values? For now, no, but maybe 106 * later. 107 * 108 * @return always false for now 109 */ 110 @Override 111 public boolean getCanRead() { 112 return false; 113 } 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public boolean getLongAddress() { 120 return mLongAddr; 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public int getAddressNumber() { 128 return mAddress; 129 } 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public String getAddress() { 136 return "" + getAddressNumber() + " " + getLongAddress(); 137 } 138 139 /** 140 * {@inheritDoc} 141 * 142 * Ops-mode programming doesn't put the command station in programming mode, 143 * so we don't have to send an exit-programming command at end. Therefore, 144 * this routine does nothing except to replace the parent routine that does 145 * something. 146 */ 147 @Override 148 void cleanup() { 149 } 150 151 // initialize logging 152 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EasyDccOpsModeProgrammer.class); 153 154}