001package jmri.jmrix.loconet.pm4;
002
003import java.awt.FlowLayout;
004import javax.swing.JCheckBox;
005import javax.swing.JComboBox;
006import javax.swing.JLabel;
007import javax.swing.JPanel;
008import jmri.jmrix.loconet.AbstractBoardProgPanel;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012/**
013 * Frame displaying and programming a PM4 configuration.
014 * <p>
015 * The read and write require a sequence of operations, which we handle with a
016 * state variable.
017 * <p>
018 * Programming of the PM4 is done via configuration messages, so the PM4 should
019 * not be put into programming mode via the built-in pushbutton while this tool
020 * is in use.
021 * <p>
022 * Some of the message formats used in this class are Copyright Digitrax, Inc.
023 * and used with permission as part of the JMRI project. That permission does
024 * not extend to uses in other software products. If you wish to use this code,
025 * algorithm or these message formats outside of JMRI, please contact Digitrax
026 * Inc for separate permission.
027 *
028 * @author Bob Jacobsen Copyright (C) 2002, 2004, 2007, 2010
029 */
030public class PM4Panel extends AbstractBoardProgPanel {
031
032    public PM4Panel() {
033        this(1);
034    }
035
036    public PM4Panel(int boardNum) {
037        super(boardNum, false, "PM4x");
038
039        appendLine(provideAddressing());  // add read/write buttons, address // NOI18N
040
041        JPanel panec = new JPanel();
042        panec.setLayout(new FlowLayout());
043        panec.add(new JLabel(Bundle.getMessage("CurrentLabel")));
044        panec.add(current);
045        current.setSelectedIndex(1);
046        appendLine(panec);
047
048        JPanel pane1 = new JPanel();
049        pane1.setLayout(new FlowLayout());
050        pane1.add(new JLabel(Bundle.getMessage("SectionXSpeedLabel", 1)));
051        pane1.add(slow1);
052        //pane1.add(new JLabel(Bundle.getMessage("AutoReverseLabel")));
053        pane1.add(rev1);
054        appendLine(pane1);
055
056        JPanel pane2 = new JPanel();
057        pane2.setLayout(new FlowLayout());
058        pane2.add(new JLabel(Bundle.getMessage("SectionXSpeedLabel", 2)));
059        pane2.add(slow2);
060        //pane2.add(new JLabel(Bundle.getMessage("AutoReverseLabel")));
061        pane2.add(rev2);
062        appendLine(pane2);
063
064        JPanel pane3 = new JPanel();
065        pane3.setLayout(new FlowLayout());
066        pane3.add(new JLabel(Bundle.getMessage("SectionXSpeedLabel", 3)));
067        pane3.add(slow3);
068        //pane3.add(new JLabel(Bundle.getMessage("AutoReverseLabel")));
069        pane3.add(rev3);
070        appendLine(pane3);
071
072        JPanel pane4 = new JPanel();
073        pane4.setLayout(new FlowLayout());
074        pane4.add(new JLabel(Bundle.getMessage("SectionXSpeedLabel", 4)));
075        pane4.add(slow4);
076        //pane4.add(new JLabel(Bundle.getMessage("AutoReverseLabel")));
077        pane4.add(rev4);
078        appendLine(pane4);
079
080        appendLine(provideStatusLine());
081
082        slow1.setSelectedIndex(1);
083        slow2.setSelectedIndex(1);
084        slow3.setSelectedIndex(1);
085        slow4.setSelectedIndex(1);
086
087        // add status
088        appendLine(provideStatusLine());
089        setStatus(Bundle.getMessage("Status1"));
090
091        setTypeWord(0x70); // configure PM4 message type
092
093        panelToScroll();
094
095    }
096
097    @Override
098    public String getHelpTarget() {
099        return "package.jmri.jmrix.loconet.pm4.PM4Frame"; // NOI18N
100    }
101
102    @Override
103    public String getTitle() {
104        return getTitle(Bundle.getMessage("MenuItemPM4Programmer"));
105    }
106
107    void setSpeedFromDisplay(int offset, JComboBox<String> box) {
108        switch (box.getSelectedIndex()) {
109            case 0:
110                opsw[offset] = false;
111                opsw[offset + 2] = true;      // true is closed
112                return;
113            default:
114            case 1:
115                opsw[offset] = false;
116                opsw[offset + 2] = false;
117                return;
118            case 2:
119                opsw[offset] = true;
120                opsw[offset + 2] = true;
121                return;
122            case 3:
123                opsw[offset] = true;
124                opsw[offset + 2] = false;
125                return;
126        }
127    }
128
129    /**
130     * Copy from the GUI to the opsw array.
131     * <p>
132     * Used before write operations start
133     */
134    @Override
135    protected void copyToOpsw() {
136        // copy over the display
137        setSpeedFromDisplay(3, slow1);
138        opsw[6] = rev1.isSelected();
139        setSpeedFromDisplay(11, slow2);
140        opsw[14] = rev2.isSelected();
141        setSpeedFromDisplay(19, slow3);
142        opsw[22] = rev3.isSelected();
143        setSpeedFromDisplay(27, slow4);
144        opsw[30] = rev4.isSelected();
145        // get current limit
146        // bit 9 is the low bit, but "closed" is a 0 in the calculation
147        // bit 1 is the middle bit, closed is a 1
148        // bit 2 is the MSB, closed is a 1
149        int index = current.getSelectedIndex();
150        opsw[2] = ((index & 0x04) != 0) ? true : false;
151        opsw[1] = ((index & 0x02) != 0) ? true : false;
152        opsw[9] = ((index & 0x01) != 0) ? false : true;
153
154    }
155
156    void setDisplaySpeed(int offset, JComboBox<String> box) {
157        int index = 0;
158        if (!opsw[offset + 2]) {
159            index++;
160        }
161        if (opsw[offset]) {
162            index += 2;
163        }
164        box.setSelectedIndex(index);
165    }
166
167    @Override
168    protected void updateDisplay() {
169        setDisplaySpeed(3, slow1);
170        rev1.setSelected(opsw[6]);
171        setDisplaySpeed(11, slow2);
172        rev2.setSelected(opsw[14]);
173        setDisplaySpeed(19, slow3);
174        rev3.setSelected(opsw[22]);
175        setDisplaySpeed(27, slow4);
176        rev4.setSelected(opsw[30]);
177        // display current limit
178        // bit 9 is the low bit, but "closed" is a 0 in the calculation
179        // bit 1 is the middle bit, closed is a 1
180        // bit 2 is the MSB, closed is a 1
181        int index = 0;
182        if (opsw[2]) {
183            index += 4;
184        }
185        if (opsw[1]) {
186            index += 2;
187        }
188        if (!opsw[9]) {
189            index += 1;
190        }
191        current.setSelectedIndex(index);
192    }
193
194    @Override
195    protected int nextState(int state) {
196        switch (state) {
197            case 1:
198                return 2;
199            case 2:
200                return 3;
201            case 3:
202                return 5;
203            case 5:
204                return 6;
205            case 6:
206                return 9;
207            case 9:
208                return 11;
209            case 11:
210                return 13;
211            case 13:
212                return 14;
213            case 14:
214                return 19;
215            case 19:
216                return 21;
217            case 21:
218                return 22;
219            case 22:
220                return 27;
221            case 27:
222                return 29;
223            case 29:
224                return 30;
225            case 30:
226                return 0;   // done!
227            default:
228                log.error("unexpected state {}", state); // NOI18N
229                return 0;
230        }
231    }
232
233    JComboBox<String> current = new JComboBox<String>(new String[]{
234            Bundle.getMessage("CurrentXBox", "1.5"), Bundle.getMessage("CurrentXBox", "3"),
235            Bundle.getMessage("CurrentXBox", "4.5"), Bundle.getMessage("CurrentXBox", "6"),
236            Bundle.getMessage("CurrentXBox", "7.5"), Bundle.getMessage("CurrentXBox", "9"),
237            Bundle.getMessage("CurrentXBox", "10.5"), Bundle.getMessage("CurrentXBox", "12")
238    });
239
240    JComboBox<String> slow1 = new JComboBox<String>(new String[]{
241            Bundle.getMessage("Box1a"), Bundle.getMessage("Box1b"),
242            Bundle.getMessage("Box1c"), Bundle.getMessage("Box1d")});
243    JCheckBox rev1 = new JCheckBox(Bundle.getMessage("AutoReverseBox"));
244    JComboBox<String> slow2 = new JComboBox<String>(new String[]{
245            Bundle.getMessage("Box1a"), Bundle.getMessage("Box1b"),
246            Bundle.getMessage("Box1c"), Bundle.getMessage("Box1d")});
247    JCheckBox rev2 = new JCheckBox(Bundle.getMessage("AutoReverseBox"));
248    JComboBox<String> slow3 = new JComboBox<String>(new String[]{
249            Bundle.getMessage("Box1a"), Bundle.getMessage("Box1b"),
250            Bundle.getMessage("Box1c"), Bundle.getMessage("Box1d")});
251    JCheckBox rev3 = new JCheckBox(Bundle.getMessage("AutoReverseBox"));
252    JComboBox<String> slow4 = new JComboBox<String>(new String[]{
253            Bundle.getMessage("Box1a"), Bundle.getMessage("Box1b"),
254            Bundle.getMessage("Box1c"), Bundle.getMessage("Box1d")});
255    JCheckBox rev4 = new JCheckBox(Bundle.getMessage("AutoReverseBox"));
256
257    private final static Logger log = LoggerFactory.getLogger(PM4Panel.class);
258
259}