001package jmri.jmrix.can.cbus.swing.bootloader;
002
003import java.util.Arrays;
004
005import static jmri.jmrix.can.cbus.node.CbusNodeConstants.*;
006
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010/**
011 * CBUS Node parameters
012 * 
013 * @author Andrew Crosland Copyright (C) 2020
014 */
015public class CbusParameters {
016
017    protected int [] paramData = null;
018    protected boolean valid = false;
019
020    
021    /**
022     * Create blank parameters
023     */
024    public CbusParameters() {
025        paramData = new int[33];
026        Arrays.fill(paramData, -1);
027    }
028    
029    
030    /**
031     * Create parameters from byte []
032     * 
033     * @param d byte [] array 
034     */
035    public CbusParameters(byte [] d) {
036        this();
037        
038        if (d.length > 32) {
039            log.error("Too many parameters");
040            valid = false;
041        } else {
042            paramData[0] = d.length;
043            for (int i = 0; i < paramData[0]; i++) {
044                paramData[i+1] = d[i] & 0xFF;
045            }
046            valid = true;
047        }
048    }
049
050
051    /**
052     * Get a parameter
053     * @param i index of parameter to get
054     * @return parameter value
055     */
056    public int getParam(int i) {
057        return paramData[i];
058    }
059    
060    
061    /**
062     * Set a parameter
063     * @param i index of the parameter to set
064     * @param v value for the parameter
065     */
066    public void setParam(int i, int v) {
067        paramData[i] = v;
068    }
069    
070    
071    /**
072     * Valid parameter block in a hex file by comparing against one
073     * read from hardware (or some other source)
074     * 
075     * @param fp Parameters from hex file
076     * @param hp parameters to validate against
077     * @return true if parameter blocks match
078     */
079    public boolean validate(CbusParameters fp, CbusParameters hp) {
080
081        if (!fp.valid || !hp.valid) {
082            return false;
083        }
084
085        // As a minimum, check manufacturer ID, module ID and processor type
086        if (fp.paramData[MANU_ID_IDX] != hp.paramData[MANU_ID_IDX]) {
087            log.error("Manufacturer ID mismatch {} {}", fp.paramData[MANU_ID_IDX], hp.paramData[MANU_ID_IDX]);
088            return false;
089        }
090        
091        if (fp.paramData[MODULE_ID_IDX] != hp.paramData[MODULE_ID_IDX]) {
092            log.error("Module ID mismatch {} {}", fp.paramData[MODULE_ID_IDX], hp.paramData[MODULE_ID_IDX]);
093            return false;
094        }
095        
096//        if (!checkVersion(fp, hp)) {
097//            log.error("Version mismatch {}.{} {}.{}", , fp.paramData[MAJOR_VER_IDX], fp.paramData[MINOR_VER_IDX],
098//                                hp.paramData[MAJOR_VER_IDX], hp.paramData[MINOR_VER_IDX]);
099//            return false;
100//        }
101
102        if (hp.paramData[NUM_PARAM_IDX] > 7) {
103            if (fp.paramData[PROC_TYPE_IDX] != hp.paramData[PROC_TYPE_IDX]) {
104                log.error("Processor type mismatch {} {}", fp.paramData[PROC_TYPE_IDX], hp.paramData[PROC_TYPE_IDX]);
105                return false;
106            }
107        }
108        
109        return true;
110    }
111    
112    
113// Not yet used in any meaningful way.
114// Comment out to make spotbugs happy for now
115//    /**
116//     * Compare two parameter blocks to see if one is a new version
117//     * 
118//     * @param pNew possible new version
119//     * @param pOld original parameters
120//     */
121//    public void checkVersion(CbusParameters pNew, CbusParameters pOld) {
122//        if (pNew.paramData[MAJOR_VER_IDX] > pOld.paramData[MAJOR_VER_IDX]) {
123//            newVersion = true;
124//        } else if (pNew.paramData[MAJOR_VER_IDX] < pOld.paramData[MAJOR_VER_IDX]) {
125//            newVersion = false;
126//        } else newVersion = pNew.paramData[MINOR_VER_IDX] > pOld.paramData[MINOR_VER_IDX];
127//    }
128    
129    
130    /**
131     * Return the load address which is stored in little endian order in four
132     * parameters
133     * 
134     * @return the load address
135     */
136    public int getLoadAddress() {
137        if (paramData[NUM_PARAM_IDX] == 7) {
138            return 0x800;
139        } else {
140            int la = (paramData[LOAD_ADDR_IDX]
141                    + paramData[LOAD_ADDR_IDX+1]*256
142                    + paramData[LOAD_ADDR_IDX+2]*256*256
143                    + paramData[LOAD_ADDR_IDX+3]*256*256*256);
144            log.debug("Load address is {}", la);
145            return la;
146        }
147    }
148    
149    
150    /**
151     * Return String representation of CBUS parameters
152     * 
153     * @return String
154     */
155    @Override
156    public String toString() {
157        if (valid == false) {
158            return Bundle.getMessage("ParamsInvalid");
159        } else {
160            StringBuilder sb = new StringBuilder();
161            for (int i = 1; i < paramData[0]; i++) {
162                sb.append(paramData[i] + " ");
163            }
164            return sb.toString();
165        }
166    }
167    
168    
169    /**
170     * Are the parameters valid?
171     * 
172     * @return true if valid
173     */
174    public boolean areValid() {
175        return valid;
176    }
177    
178    
179    /**
180     * Set parameter valid status
181     * 
182     * @param s true or false valid status
183     */
184    public void setValid(boolean s) {
185        valid = s;
186    }
187    
188    private final static Logger log = LoggerFactory.getLogger(CbusParameters.class);
189    
190}