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