001package jmri.jmrit.symbolicprog; 002 003import java.util.HashMap; 004import javax.swing.JLabel; 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007 008/** 009 * Representation of a short address (CV1). 010 * <p> 011 * This is a decimal value, extended to modify the other CVs when written. The 012 * CVs to be modified and their new values are stored in two arrays for 013 * simplicity. 014 * <p> 015 * 016 * The NMRA has decided that writing CV1 causes other CVs to update within the 017 * decoder (CV19 for consisting, CV29 for short/long address). We want DP to 018 * overwrite those _after_ writing CV1, so that the DP values are forced to be 019 * the correct ones. 020 * 021 * @author Bob Jacobsen Copyright (C) 2001, 2006, 2007 022 * 023 */ 024public class ShortAddrVariableValue extends DecVariableValue { 025 026 public ShortAddrVariableValue(String name, String comment, String cvName, 027 boolean readOnly, boolean infoOnly, boolean writeOnly, boolean opsOnly, 028 String cvNum, String mask, 029 HashMap<String, CvValue> v, JLabel status, String stdname) { 030 // specify min, max value explicitly. 031 // short address 0 = alternate power source as per S9.2.2. 032 super(name, comment, cvName, readOnly, infoOnly, writeOnly, opsOnly, cvNum, mask, 0, 127, v, status, stdname); 033 034 // add default overwrites as per NMRA spec 035 firstFreeSpace = 0; 036 setModifiedCV("19"); // consisting 037 setModifiedCV("29"); // control bits 038 } 039 040 /** 041 * Register a CV to be modified regardless of current value. 042 * @param cvNum cv number string. 043 */ 044 public void setModifiedCV(String cvNum) { 045 if (firstFreeSpace >= maxCVs) { 046 log.error("too many CVs registered for changes!"); 047 return; 048 } 049 cvNumbers[firstFreeSpace] = cvNum; 050 newValues[firstFreeSpace] = -10; 051 firstFreeSpace++; 052 } 053 054 /** 055 * Change CV values due to change in short address 056 */ 057 private void updateCvForAddrChange() { 058 for (int i = 0; i < firstFreeSpace; i++) { 059 CvValue cv = _cvMap.get(cvNumbers[i]); 060 if (cv == null) { 061 continue; // if CV not present this decoder... 062 } 063 if (!cvNumbers[i].equals(cv.number())) { 064 log.error("CV numbers don't match: {} {}", cvNumbers[i], cv.number()); 065 } 066 cv.setToWrite(true); 067 cv.setState(ValueState.EDITED); 068 if (log.isDebugEnabled()) { 069 log.debug("Mark to write {}", cv.number()); 070 } 071 } 072 } 073 074 int firstFreeSpace = 0; 075 static final int maxCVs = 20; 076 String[] cvNumbers = new String[maxCVs]; 077 int[] newValues = new int[maxCVs]; 078 079 @Override 080 public void writeChanges() { 081 if (getReadOnly()) { 082 log.error("unexpected writeChanges operation when readOnly is set"); 083 } 084 setBusy(true); // will be reset when value changes 085 // mark other CVs as possibly needing write 086 updateCvForAddrChange(); 087 // and change the value of this one 088 _cvMap.get(getCvNum()).write(_status); 089 } 090 091 @Override 092 public void writeAll() { 093 if (getReadOnly()) { 094 log.error("unexpected writeAll operation when readOnly is set"); 095 } 096 setBusy(true); // will be reset when value changes 097 // mark other CVs as possibly needing write 098 updateCvForAddrChange(); 099 // and change the value of this one 100 _cvMap.get(getCvNum()).write(_status); 101 } 102 103 // clean up connections when done 104 @Override 105 public void dispose() { 106 super.dispose(); 107 } 108 109 // initialize logging 110 private final static Logger log = LoggerFactory.getLogger(ShortAddrVariableValue.class); 111 112}