001package jmri.jmrix.tmcc;
002
003import java.util.ArrayList;
004import java.util.List;
005import javax.annotation.Nonnull;
006
007import jmri.ProgrammingMode;
008import jmri.jmrix.AbstractProgrammer;
009
010
011/**
012 * Implements the jmri.Programmer interface via commands for the TMCC
013 * control interface.
014 *
015 * Made from the EasyDCC programmer
016 *
017 * @author Bob Jacobsen Copyright (C) 2001, 2025
018 */
019public class TmccProgrammer extends AbstractProgrammer {
020
021    public TmccProgrammer(TmccSystemConnectionMemo memo) {
022        tc = memo.getTrafficController();
023    }
024
025    protected SerialTrafficController tc = null;
026
027    /** 
028     * {@inheritDoc}
029     */
030    @Override
031    @Nonnull
032    public List<ProgrammingMode> getSupportedModes() {
033        List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>();
034
035        ret.add(TmccProgrammerManager.TMCCMODE1_ENGID);
036        ret.add(TmccProgrammerManager.TMCCMODE2_ENGID);
037        
038        ret.add(TmccProgrammerManager.TMCCMODE1_SWID);
039        ret.add(TmccProgrammerManager.TMCCMODE1_ACCID);
040
041        return ret;
042
043    }
044
045
046    int _cv; // points to "CV" input from Simple Programmer
047    int _val; // points to "Value" input from Simple Programmer
048    int _func; // points to "SET" command for TMCC1 and TMCC2 loco ID numbers
049
050
051    /** 
052     * {@inheritDoc}
053     */
054    @Override
055    public synchronized void writeCV(String CVname, int val, jmri.ProgListener p) throws jmri.ProgrammerException {
056        final int CV = Integer.parseInt(CVname);
057
058        _cv = CV;  // Value from Simple Programmer "CV" input
059        _val = val; // Value from Simple Programmer "Value" input
060        _func = 0x00002B; // SET command for both TMCC1 and TMCC2
061
062        // validate CV == 1 for TMCC loco ID programming
063        // validate ID#/address for TMCC is between 1-98
064        // format and send the TMCC loco ID write message
065        // note: the argument is long containing 3 bytes
066
067        if (CV == 1) {
068            
069            if (val > 0 && val < 99) {
070
071                if (getMode() == TmccProgrammerManager.TMCCMODE1_ENGID) {
072                    SerialMessage m = new SerialMessage();
073                    m.setOpCode(0xFE); // set the first byte/TMCC1 opcode to 0xFE
074                    m.putAsWord((val * 128) + _func); // set the second/third byte (address/SET command for TMCC1)
075                    tc.sendSerialMessage(m, null);
076                }
077
078                if  (getMode() == TmccProgrammerManager.TMCCMODE2_ENGID) {
079                    SerialMessage m = new SerialMessage();
080                    m.setOpCode(0xF8); // set the first byte/TMCC2 opcode to 0xF8
081                    m.putAsWord(((val * 512) + 256) + _func); // set the second/third byte (address/SET command for TMCC2)
082                    tc.sendSerialMessage(m, null);
083                }
084                
085                if  (getMode() == TmccProgrammerManager.TMCCMODE1_SWID) {
086                    SerialMessage m = new SerialMessage();
087                    m.setOpCode(0xFE); // set the first byte/TMCC1 opcode to 0xFE
088                    m.putAsWord(((val * 128) + 16384) + _func); // set the second/third byte (address/SET command for TMCC2)
089                    tc.sendSerialMessage(m, null);
090                }
091                
092                if  (getMode() == TmccProgrammerManager.TMCCMODE1_ACCID) {
093                    SerialMessage m = new SerialMessage();
094                    m.setOpCode(0xFE); // set the first byte/TMCC1 opcode to 0xFE
095                    m.putAsWord(((val * 128) + 32768) + _func); // set the second/third byte (address/SET command for TMCC2)
096                    tc.sendSerialMessage(m, null);
097                }              
098
099
100            } else {
101                SerialMessage m = new SerialMessage();
102                m.setOpCode(0x00);
103                m.putAsWord(00000);
104                tc.sendSerialMessage(m, null);
105                log.warn("Address Must be Between 1-98 for TMCC");
106            }
107
108
109        } else {
110            SerialMessage m = new SerialMessage();
111            m.setOpCode(0x00);
112            m.putAsWord(00001);
113            tc.sendSerialMessage(m, null);
114            log.warn("CV Must Equal 1 for Programming TMCC Loco/Engine, Switch, Accessory ID#s");
115
116        }
117
118        // End the "writing..." process in SimpleProgrammer
119        notifyProgListenerEnd(p, _val, jmri.ProgListener.OK);
120 
121    }
122
123
124    /** 
125     * {@inheritDoc}
126     */
127    @Override
128    public synchronized void confirmCV(String CV, int val, jmri.ProgListener p) throws jmri.ProgrammerException {
129    }
130
131    /** 
132     * {@inheritDoc}
133     */
134    @Override
135    public synchronized void readCV(String CVname, jmri.ProgListener p) throws jmri.ProgrammerException {
136    }
137
138
139    /** 
140     * {@inheritDoc}
141     */
142    @Override
143    synchronized protected void timeout() {
144    }
145    
146    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TmccProgrammer.class);
147
148}