internal virtual Tuple <DataTypeBase, DataTypeBase> transform(DataProcessorConfig config) { switch (config.id) { case DataProcessorConfig.BufferConfig.ID: return(Tuple.Create( new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { }, 0, 0, false)) as DataTypeBase, dataProcessorStateCopy(this, this.attributes) )); case DataProcessorConfig.AccumulatorConfig.ID: { DataProcessorConfig.AccumulatorConfig casted = (DataProcessorConfig.AccumulatorConfig)config; DataAttributes attributes = new DataAttributes(new byte[] { casted.output }, 1, 0, !casted.counter && this.attributes.signed); return(Tuple.Create( casted.counter ? new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, attributes) : dataProcessorCopy(this, attributes), casted.counter ? new IntegralDataType(null, DATA_PROCESSOR, Util.setRead(DataProcessor.STATE), NO_ID, attributes) : dataProcessorStateCopy(this, attributes) )); } case DataProcessorConfig.AverageConfig.ID: case DataProcessorConfig.DelayConfig.ID: case DataProcessorConfig.TimeConfig.ID: return(Tuple.Create <DataTypeBase, DataTypeBase>(dataProcessorCopy(this, this.attributes.dataProcessorCopy()), null)); case DataProcessorConfig.PassthroughConfig.ID: return(Tuple.Create( dataProcessorCopy(this, this.attributes.dataProcessorCopy()), new IntegralDataType(DATA_PROCESSOR, Util.setRead(DataProcessor.STATE), NO_ID, new DataAttributes(new byte[] { 2 }, 1, 0, false)) as DataTypeBase )); case DataProcessorConfig.MathConfig.ID: { DataProcessorConfig.MathConfig casted = (DataProcessorConfig.MathConfig)config; DataTypeBase processor = null; switch (casted.op) { case Add: processor = dataProcessorCopy(this, this.attributes.dataProcessorCopySize(4)); break; case Multiply: processor = dataProcessorCopy(this, this.attributes.dataProcessorCopySize(Math.Abs(casted.rhs) < 1 ? this.attributes.sizes[0] : (byte)4)); break; case Divide: processor = dataProcessorCopy(this, this.attributes.dataProcessorCopySize(Math.Abs(casted.rhs) < 1 ? (byte)4 : this.attributes.sizes[0])); break; case Subtract: processor = dataProcessorCopy(this, this.attributes.dataProcessorCopySigned(true)); break; case AbsValue: processor = dataProcessorCopy(this, this.attributes.dataProcessorCopySigned(false)); break; case Modulus: processor = dataProcessorCopy(this, this.attributes.dataProcessorCopy()); break; case Exponent: processor = new ByteArrayDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, this.attributes.dataProcessorCopySize(4)); break; case LeftShift: processor = new ByteArrayDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, this.attributes.dataProcessorCopySize((byte)Math.Min(this.attributes.sizes[0] + (casted.rhs / 8), 4))); break; case RightShift: processor = new ByteArrayDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, this.attributes.dataProcessorCopySize((byte)Math.Max(this.attributes.sizes[0] - (casted.rhs / 8), 1))); break; case Sqrt: processor = new ByteArrayDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, this.attributes.dataProcessorCopySigned(false)); break; case Constant: DataAttributes attributes = new DataAttributes(new byte[] { 4 }, (byte)1, (byte)0, casted.rhs >= 0); processor = new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, attributes); break; } if (processor != null) { return(Tuple.Create <DataTypeBase, DataTypeBase>(processor, null)); } break; } case DataProcessorConfig.PulseConfig.ID: { DataProcessorConfig.PulseConfig casted = (DataProcessorConfig.PulseConfig)config; DataTypeBase processor = null; switch (casted.mode) { case Width: processor = new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 2 }, 1, 0, false)); break; case Area: processor = dataProcessorCopy(this, attributes.dataProcessorCopySize(4)); break; case Peak: processor = dataProcessorCopy(this, attributes.dataProcessorCopy()); break; case OnDetect: processor = new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, false)); break; } if (processor != null) { return(Tuple.Create <DataTypeBase, DataTypeBase>(processor, null)); } break; } case DataProcessorConfig.ComparisonConfig.ID: { DataTypeBase processor = null; if (config is DataProcessorConfig.SingleValueComparisonConfig) { processor = dataProcessorCopy(this, attributes.dataProcessorCopy()); } else if (config is DataProcessorConfig.MultiValueComparisonConfig) { DataProcessorConfig.MultiValueComparisonConfig casted = (DataProcessorConfig.MultiValueComparisonConfig)config; if (casted.mode == ComparisonOutput.PassFail || casted.mode == ComparisonOutput.Zone) { processor = new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, false)); } else { processor = dataProcessorCopy(this, attributes.dataProcessorCopy()); } } if (processor != null) { return(Tuple.Create <DataTypeBase, DataTypeBase>(processor, null)); } break; } case DataProcessorConfig.ThresholdConfig.ID: { DataProcessorConfig.ThresholdConfig casted = (DataProcessorConfig.ThresholdConfig)config; switch (casted.mode) { case Threshold.Absolute: return(Tuple.Create <DataTypeBase, DataTypeBase>(dataProcessorCopy(this, attributes.dataProcessorCopy()), null)); case Threshold.Binary: return(Tuple.Create <DataTypeBase, DataTypeBase>(new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, true)), null)); } break; } case DataProcessorConfig.DifferentialConfig.ID: { DataProcessorConfig.DifferentialConfig casted = (DataProcessorConfig.DifferentialConfig)config; switch (casted.mode) { case Differential.Absolute: return(Tuple.Create <DataTypeBase, DataTypeBase>(dataProcessorCopy(this, attributes.dataProcessorCopy()), null)); case Differential.Differential: throw new InvalidOperationException("Differential processor in 'difference' mode must be handled by subclasses"); case Differential.Binary: return(Tuple.Create <DataTypeBase, DataTypeBase>(new IntegralDataType(this, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, true)), null)); } break; } case DataProcessorConfig.PackerConfig.ID: { DataProcessorConfig.PackerConfig casted = (DataProcessorConfig.PackerConfig)config; return(Tuple.Create <DataTypeBase, DataTypeBase>(dataProcessorCopy(this, attributes.dataProcessorCopyCopies(casted.count)), null)); } case DataProcessorConfig.AccounterConfig.ID: { DataProcessorConfig.AccounterConfig casted = (DataProcessorConfig.AccounterConfig)config; return(Tuple.Create <DataTypeBase, DataTypeBase>(dataProcessorCopy(this, new DataAttributes(new byte[] { casted.length, attributes.length() }, 1, 0, attributes.signed)), null)); } } throw new InvalidOperationException("Unable to determine the DataTypeBase object for config: " + Util.arrayToHexString(config.Build())); }
private RouteComponent applyMath(MathOp op, float rhs) { bool multiChnlMath = state.bridge.getFirmware().CompareTo(MULTI_CHANNEL_MATH) >= 0; if (!multiChnlMath && source.attributes.length() > 4) { throw new IllegalRouteOperationException("Cannot apply math operations on multi-channel data for firmware prior to " + MULTI_CHANNEL_MATH.ToString()); } if (source.attributes.length() <= 0) { throw new IllegalRouteOperationException("Cannot apply math operations to null data"); } if (source.eventConfig[0] == (byte)SENSOR_FUSION) { throw new IllegalRouteOperationException("Cannot apply math operations to sensor fusion data"); } DataTypeBase processor; switch (op) { case MathOp.Add: { DataAttributes newAttrs = source.attributes.dataProcessorCopySize(4); newAttrs.signed = source.attributes.signed || (!source.attributes.signed && rhs < 0); processor = source.dataProcessorCopy(source, newAttrs); break; } case MathOp.Multiply: { DataAttributes newAttrs = source.attributes.dataProcessorCopySize((byte)(Math.Abs(rhs) < 1 ? source.attributes.sizes[0] : 4)); newAttrs.signed = source.attributes.signed || (!source.attributes.signed && rhs < 0); processor = source.dataProcessorCopy(source, newAttrs); break; } case MathOp.Divide: { DataAttributes newAttrs = source.attributes.dataProcessorCopySize((byte)(Math.Abs(rhs) < 1 ? 4 : source.attributes.sizes[0])); newAttrs.signed = source.attributes.signed || (!source.attributes.signed && rhs < 0); processor = source.dataProcessorCopy(source, newAttrs); break; } case MathOp.Modulus: { processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopy()); break; } case MathOp.Exponent: { processor = new ByteArrayDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, source.attributes.dataProcessorCopySize((byte)4)); break; } case MathOp.LeftShift: { processor = new ByteArrayDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, source.attributes.dataProcessorCopySize((byte)Math.Min(source.attributes.sizes[0] + ((int)rhs / 8), 4))); break; } case MathOp.RightShift: { processor = new ByteArrayDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, source.attributes.dataProcessorCopySize((byte)Math.Max(source.attributes.sizes[0] - ((int)rhs / 8), 1))); break; } case MathOp.Subtract: { processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopySigned(true)); break; } case MathOp.Sqrt: { processor = new ByteArrayDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, source.attributes.dataProcessorCopySigned(false)); break; } case MathOp.AbsValue: { DataAttributes copy = source.attributes.dataProcessorCopySigned(false); processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopySigned(false)); break; } case MathOp.Constant: DataAttributes attributes = new DataAttributes(new byte[] { 4 }, 1, 0, source.attributes.signed); processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, attributes); break; default: processor = null; break; } float scaledRhs; switch (op) { case MathOp.Add: case MathOp.Modulus: case MathOp.Subtract: scaledRhs = rhs * source.scale(state.bridge); break; case MathOp.Sqrt: case MathOp.AbsValue: scaledRhs = 0; break; default: scaledRhs = rhs; break; } byte[] config = new byte[multiChnlMath ? 8 : 7]; config[0] = 0x9; config[1] = (byte)((processor.attributes.sizes[0] - 1) & 0x3 | ((source.attributes.sizes[0] - 1) << 2) | (source.attributes.signed ? 0x10 : 0)); config[2] = (byte)((byte)op + 1); Array.Copy(Util.intToBytesLe((int)scaledRhs), 0, config, 3, 4); if (multiChnlMath) { config[7] = (byte)(source.attributes.sizes.Length - 1); } return(postCreate(null, new MapEditorInner(config, processor, state.bridge))); }