001package jmri.jmrix.loconet.sdf; 002 003import jmri.util.StringUtil; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Implement the LOAD_MODIFIER macro from the Digitrax sound definition language 009 * 010 * Arg1: Upper 4 bits - math modifiers FMATH_LODE et al Arg2: Arg3: 011 * 012 * 013 * @author Bob Jacobsen Copyright (C) 2007 014 */ 015public class LoadModifier extends SdfMacro { 016 017 public LoadModifier(int byte0, int arg1, int arg2, int arg3) { 018 this.modType = byte0 & 0x0F; 019 this.byte0 = byte0; 020 this.arg1 = arg1; 021 this.arg2 = arg2; 022 this.arg3 = arg3; 023 } 024 025 @Override 026 public String name() { 027 return "LOAD_MODIFIER"; // NOI18N 028 } 029 030 int byte0; 031 int modType; 032 int arg1, arg2, arg3; 033 034 @Override 035 public int length() { 036 return 4; 037 } 038 039 static public SdfMacro match(SdfBuffer buff) { 040 // course match 041 if ((buff.getAtIndex() & 0xF0) != 0xE0) { 042 return null; 043 } 044 int byte1 = buff.getAtIndexAndInc() & 0xFF; 045 int byte2 = buff.getAtIndexAndInc() & 0xFF; 046 int byte3 = buff.getAtIndexAndInc() & 0xFF; 047 int byte4 = buff.getAtIndexAndInc() & 0xFF; 048 return new LoadModifier(byte1, byte2, byte3, byte4); 049 } 050 051 String modTypeVal() { 052 return jmri.util.StringUtil.getNameFromState(modType, modControlCodes, modControlNames); 053 } 054 055 /** 056 * Format the three bytes as simple numbers, for lack of anything better 057 * right now 058 * @return 3 digit string 059 */ 060 String argVal() { 061 String arg1Val = "" + arg1; 062 String arg2Val = "" + arg2; 063 String arg3Val = "" + arg3; 064 return arg1Val + "," + arg2Val + "," + arg3Val; 065 } 066 067 /** 068 * Store into a buffer. 069 */ 070 @Override 071 public void loadByteArray(SdfBuffer buffer) { 072 // data 073 buffer.setAtIndexAndInc(byte0); 074 buffer.setAtIndexAndInc(arg1); 075 buffer.setAtIndexAndInc(arg2); 076 buffer.setAtIndexAndInc(arg3); 077 078 // store children 079 super.loadByteArray(buffer); 080 } 081 082 @Override 083 public String toString() { 084 return "Set Modifier " + modTypeVal() + '\n'; // NOI18N 085 } 086 087 @Override 088 public String oneInstructionString() { 089 String args; 090 String arg1Val; 091 String arg2Val; 092 String arg3Val; 093 String temp1, temp2; 094 095 switch (modType) { 096 case MTYPE_TIME: 097 args = argVal(); 098 return name() + ' ' + modTypeVal() + "," + args + '\n'; 099 100 case MTYPE_GAIN: 101 // arg1 is IMMED_GAIN_MODIFY or ANALOG_GAIN_MODIFY 102 // plus possible 5 bit modifier 103 if ((arg1 & 0xE0) == IMMED_GAIN_MODIFY) { 104 if (arg1 == IMMED_GAIN_MODIFY) { 105 arg1Val = "IMMED_GAIN_MODIFY"; // NOI18N 106 } else { 107 arg1Val = "IMMED_GAIN_MODIFY+0x" + StringUtil.twoHexFromInt(arg1 & 0x1f); // NOI18N 108 } 109 } else if ((arg1 & 0xE0) == ANALOG_GAIN_MODIFY) { 110 if (arg1 == ANALOG_GAIN_MODIFY) { 111 arg1Val = "ANALOG_GAIN_MODIFY"; // NOI18N 112 } else { 113 arg1Val = "ANALOG_GAIN_MODIFY+" // NOI18N 114 + StringUtil.getNameFromState(arg1 & 0x1f, workRegCodes, workRegNames); 115 } 116 } else { 117 arg1Val = StringUtil.twoHexFromInt(arg1); 118 } 119 arg2Val = StringUtil.getNameFromState(arg2, fixedCVCodes, fixedCVNames); 120 if (arg2Val == null) { 121 arg2Val = "0x" + StringUtil.twoHexFromInt(arg2); // NOI18N 122 } 123 arg3Val = decodeFlags(arg3, arg3ModCodes, arg3ModMasks, arg3ModNames); 124 if (arg3Val == null) { 125 arg3Val = "0x" + StringUtil.twoHexFromInt(arg3); // NOI18N 126 } 127 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; // NOI18N 128 129 case MTYPE_PITCH: 130 // arg1 is CV_PITCH_MODIFY or ANALOG_PITCH_MODIFY 131 // plus possible 5 bit modifier 132 if ((arg1 & 0xE0) == CV_PITCH_MODIFY) { 133 if (arg1 == CV_PITCH_MODIFY) { 134 arg1Val = "CV_PITCH_MODIFY"; // NOI18N 135 } else { 136 arg1Val = "CV_PITCH_MODIFY+0x" + StringUtil.twoHexFromInt(arg1 & 0x1f); // NOI18N 137 } 138 } else if ((arg1 & 0xE0) == ANALOG_PITCH_MODIFY) { 139 if (arg1 == ANALOG_PITCH_MODIFY) { 140 arg1Val = "ANALOG_PITCH_MODIFY"; // NOI18N 141 } else { 142 arg1Val = "ANALOG_PITCH_MODIFY+" // NOI18N 143 + StringUtil.getNameFromState(arg1 & 0x1f, workRegCodes, workRegNames); 144 } 145 } else { 146 arg1Val = StringUtil.twoHexFromInt(arg1); 147 } 148 arg2Val = StringUtil.getNameFromState(arg2, maxPCodes, maxPNames); 149 if (arg2Val == null) { 150 arg2Val = "0x" + StringUtil.twoHexFromInt(arg2); // NOI18N 151 } 152 arg3Val = StringUtil.getNameFromState(arg3, ditherPCodes, ditherPNames); 153 if (arg3Val == null) { 154 arg3Val = "0x" + StringUtil.twoHexFromInt(arg3); // NOI18N 155 } 156 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; 157 158 case MTYPE_BLEND: 159 arg1Val = decodeFlags(arg1, blendArg1Codes, blendArg1Masks, blendArg1Names); 160 161 arg2Val = StringUtil.getNameFromState(arg2, blendArg2Codes, blendArg2Names); 162 if (arg2Val == null) { 163 arg2Val = "0x" + StringUtil.twoHexFromInt(arg2); // NOI18N 164 } 165 166 arg3Val = StringUtil.getNameFromState(arg3, blendArg3Codes, blendArg3Names); 167 if (arg3Val == null) { 168 arg3Val = "0x" + StringUtil.twoHexFromInt(arg3); // NOI18N 169 } 170 171 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; 172 173 case MTYPE_SCATTER: 174 arg1Val = StringUtil.getNameFromState(arg1 & 0x38, scatCommandCodes, scatCommandNames) 175 + "+" + StringUtil.getNameFromState(arg1 & 0x03, scatChannelCodes, scatChannelNames); 176 177 arg2Val = StringUtil.getNameFromState(arg2, fixedCVCodes, fixedCVNames); 178 if (arg2Val == null) { 179 arg2Val = "0x" + StringUtil.twoHexFromInt(arg2); // NOI18N 180 } 181 182 arg3Val = StringUtil.getNameFromState(arg3, sintenCodes, sintenNames); 183 if (arg3Val == null) { 184 arg3Val = "0x" + StringUtil.twoHexFromInt(arg3); // NOI18N 185 } 186 187 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; 188 189 case MTYPE_SNDCV: 190 arg1Val = StringUtil.getNameFromState(arg1, fixedCVCodes, fixedCVNames); 191 if (arg1Val == null) { 192 arg1Val = "0x" + StringUtil.twoHexFromInt(arg1); // NOI18N 193 } 194 arg2Val = "" + arg2; 195 arg3Val = "" + arg3; 196 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; 197 198 case MTYPE_WORK_IMMED: 199 // math operations w immediate operands 200 temp1 = StringUtil.getNameFromState(arg1 & 0xE0, arg1ModCodes, arg1ModNames); 201 temp2 = StringUtil.getNameFromState(arg1 & 0x1F, workRegCodes, workRegNames); 202 if (temp1 != null && temp2 != null) { 203 arg1Val = temp1 + "+" + temp2; 204 } else if (temp1 != null && temp2 == null) { 205 arg1Val = temp1; 206 } else if (temp1 == null && temp2 != null) { 207 arg1Val = temp2; 208 } else { 209 arg1Val = "0"; // an odd error, actually 210 } 211 arg2Val = StringUtil.getNameFromState(arg2, maxPCodes, maxPNames); 212 if (arg2Val == null) { 213 arg2Val = "0x" + StringUtil.twoHexFromInt(arg2); // NOI18N 214 } 215 216 // occasionally see MERGE_ALL_MASK in arg3, but that's zero 217 arg3Val = "" + arg3; 218 219 // special cases 220 // status bit register 221 if ((arg1 & 0x1F) == WORK_STATUS_BITS) { 222 arg2Val = decodeFlags(arg2, workStatusBitCodes, workStatusBitCodes, workStatusBitNames); 223 } 224 if ((arg1 & 0x1F) == WORK_GLBL_GAIN && arg2 == DEFAULT_GLBL_GAIN) { 225 arg2Val = "DEFAULT_GLBL_GAIN"; // NOI18N 226 } 227 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; 228 229 case MTYPE_WORK_INDIRECT: 230 // math operations from one reg to another 231 temp1 = StringUtil.getNameFromState(arg1 & 0xE0, arg1ModCodes, arg1ModNames); 232 temp2 = StringUtil.getNameFromState(arg1 & 0x1F, workRegCodes, workRegNames); 233 if (temp1 != null && temp2 != null) { 234 arg1Val = temp1 + "+" + temp2; 235 } else if (temp1 != null && temp2 == null) { 236 arg1Val = temp1; 237 } else if (temp1 == null && temp2 != null) { 238 arg1Val = temp2; 239 } else { 240 arg1Val = "0"; // an odd error, actually // NOI18N 241 } 242 arg2Val = StringUtil.getNameFromState(arg2 & 0x1F, workRegCodes, workRegNames); 243 if (arg2Val == null) { 244 arg2Val = "0x" + StringUtil.twoHexFromInt(arg2); // NOI18N 245 } 246 247 // occasionally see MERGE_ALL_MASK in arg3, but that's zero 248 arg3Val = "" + arg3; 249 250 return name() + ' ' + modTypeVal() + "," + arg1Val + "," + arg2Val + "," + arg3Val + '\n'; // NOI18N 251 default: 252 log.warn("Unhandled modifyer type code: {}", modType); 253 break; 254 } 255 return "<could not parse, should not happen>"; // NOI18N 256 } 257 258 @Override 259 public String allInstructionString(String indent) { 260 return indent + oneInstructionString(); 261 } 262 263 private final static Logger log = LoggerFactory.getLogger(LoadModifier.class); 264}