public IRouteComponent Find(Pulse pulse, float threshold, ushort samples)
        {
            if (source.attributes.length() > 4)
            {
                throw new IllegalRouteOperationException("Cannot find pulses for data longer than 4 bytes");
            }

            if (source.attributes.length() <= 0)
            {
                throw new IllegalRouteOperationException("Cannot find pulses for null data");
            }

            if (source.eventConfig[0] == (byte)SENSOR_FUSION)
            {
                throw new IllegalRouteOperationException("Cannot find pulses for sensor fusion data");
            }

            DataTypeBase processor;

            switch (pulse)
            {
            case Pulse.Width:
                processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 2 }, 1, 0, false));
                break;

            case Pulse.Area:
                processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopySize((byte)4));
                break;

            case Pulse.Peak:
                processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopy());
                break;

            case Pulse.OnDetect:
                processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, false));
                break;

            default:
                processor = null;
                break;
            }

            byte[] config = new byte[10];
            config[0] = 0xb;
            config[1] = (byte)(source.attributes.length() - 1);
            config[2] = 0x0;
            config[3] = (byte)pulse;
            Array.Copy(Util.intToBytesLe((int)(threshold * source.scale(state.bridge))), 0, config, 4, 4);
            Array.Copy(Util.ushortToBytesLe(samples), 0, config, 8, 2);

            return(postCreate(null, new PulseEditorInner(config, processor, state.bridge)));
        }
Пример #2
0
            internal GpioPin(byte mask, byte pin, IModuleBoardBridge bridge) : base(bridge)
            {
                this.mask = mask;
                this.pin  = pin;

                if ((mask & 0x2) == 0x2)
                {
                    adc    = new IntegralDataType(GPIO, Util.setRead(READ_AI_ADC), pin, new DataAttributes(new byte[] { 2 }, 1, 0, false));
                    absRef = new MilliUnitsFloatDataType(GPIO, Util.setRead(READ_AI_ABS_REF), pin, new DataAttributes(new byte[] { 2 }, 1, 0, false));
                }
                if ((mask & 0x1) == 0x1)
                {
                    digital = new IntegralDataType(GPIO, Util.setRead(READ_DI), pin, new DataAttributes(new byte[] { 1 }, 1, 0, false));
                    monitor = new IntegralDataType(GPIO, PIN_CHANGE_NOTIFY, pin, new DataAttributes(new byte[] { 1 }, 1, 0, false));
                }
            }
        public IRouteBranchEnd Buffer()
        {
            if (source.attributes.length() <= 0)
            {
                throw new IllegalRouteOperationException("Cannot buffer null data");
            }

            DataTypeBase processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { }, 0, 0, false));
            var          config    = new BufferConfig(source.attributes.length());

            state.dataProcessors.AddLast(Tuple.Create(
                                             source.dataProcessorStateCopy(source, source.attributes),
                                             new NullEditor(config, processor, state.bridge) as EditorImplBase
                                             ));
            return(new RouteBranchEnd(this));
        }
        public IRouteComponent Find(Differential differential, float distance)
        {
            if (source.attributes.length() > 4)
            {
                throw new IllegalRouteOperationException("Cannot use differential filter for data longer than 4 bytes");
            }

            if (source.attributes.length() <= 0)
            {
                throw new IllegalRouteOperationException("Cannot use differential filter for null data");
            }

            if (source.eventConfig[0] == (byte)SENSOR_FUSION)
            {
                throw new IllegalRouteOperationException("Cannot use differential filter on sensor fusion data");
            }

            DataTypeBase processor;

            switch (differential)
            {
            case Differential.Absolute:
                processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopy());
                break;

            case Differential.Differential:
                processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopySigned(true));
                break;

            case Differential.Binary:
                processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, true));
                break;

            default:
                processor = null;
                break;
            }

            byte[] config = new byte[6];
            config[0] = 0xc;
            config[1] = (byte)(((source.attributes.length() - 1) & 0x3) | (source.attributes.signed ? 0x4 : 0) | ((byte)differential << 3));
            Array.Copy(Util.intToBytesLe((int)(distance * source.scale(state.bridge))), 0, config, 2, 4);

            return(postCreate(null, new DifferentialEditorInner(config, processor, state.bridge)));
        }
        public IRouteComponent Limit(Passthrough type, ushort value)
        {
            if (source.attributes.length() <= 0)
            {
                throw new IllegalRouteOperationException("Cannot limit null data");
            }

            DataTypeBase processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopy());

            byte[] config = new byte[4] {
                0x1, (byte)(((int)type) & 0x7), 0, 0
            };
            Array.Copy(Util.ushortToBytesLe(value), 0, config, 2, 2);

            DataTypeBase processorState = new IntegralDataType(DATA_PROCESSOR, Util.setRead(DataProcessor.STATE),
                                                               new DataAttributes(new byte[] { 2 }, (byte)1, (byte)0, false));

            return(postCreate(processorState, new PassthroughEditorInner(config, processor, state.bridge)));
        }
        public IRouteComponent Find(Threshold threshold, float boundary, float hysteresis)
        {
            if (source.attributes.length() > 4)
            {
                throw new IllegalRouteOperationException("Cannot use threshold filter on data longer than 4 bytes");
            }

            if (source.attributes.length() <= 0)
            {
                throw new IllegalRouteOperationException("Cannot use threshold filter on null data");
            }

            if (source.eventConfig[0] == (byte)SENSOR_FUSION)
            {
                throw new IllegalRouteOperationException("Cannot use threshold filter on sensor fusion data");
            }

            DataTypeBase processor;

            switch (threshold)
            {
            case Threshold.Absolute:
                processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopy());
                break;

            case Threshold.Binary:
                processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, new DataAttributes(new byte[] { 1 }, 1, 0, true));
                break;

            default:
                processor = null;
                break;
            }

            byte[] config = new byte[8];
            config[0] = 0xd;
            config[1] = (byte)((source.attributes.length() - 1) & 0x3 | (source.attributes.signed ? 0x4 : 0) | ((byte)threshold << 3));
            Array.Copy(Util.intToBytesLe((int)(source.scale(state.bridge) * boundary)), 0, config, 2, 4);
            Array.Copy(Util.shortToBytesLe((short)(source.scale(state.bridge) * hysteresis)), 0, config, 6, 2);

            return(postCreate(null, new ThresholdEditorInner(config, processor, state.bridge)));
        }
Пример #7
0
        public Settings(IModuleBoardBridge bridge) : base(bridge)
        {
            var info = bridge.lookupModuleInfo(SETTINGS);

            if (info.revision >= DISCONNECTED_EVENT_REVISION)
            {
                disconnectDummyProducer = new IntegralDataType(SETTINGS, DISCONNECT_EVENT, new DataAttributes(new byte[] { }, 0, 0, false));
            }
            if (info.revision >= BATTERY_REVISION)
            {
                batteryState = new BatteryStateDataType();
            }
            if (info.revision >= CHARGE_STATUS_REVISION && (info.extra.Length > 0 && (info.extra[0] & 0x1) == 0x1))
            {
                powerStatus = new IntegralDataType(SETTINGS, POWER_STATUS, new DataAttributes(new byte[] { 1 }, 1, 0, false));
            }
            if (info.revision >= CHARGE_STATUS_REVISION && (info.extra.Length > 0 && (info.extra[0] & 0x2) == 0x2))
            {
                chargeStatus = new IntegralDataType(SETTINGS, CHARGE_STATUS, new DataAttributes(new byte[] { 1 }, 1, 0, false));
            }
        }
Пример #8
0
        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()));
        }
Пример #9
0
 public AccelerometerBmi160(IModuleBoardBridge bridge) : base(bridge)
 {
     stepCounterDataType  = new IntegralDataType(ACCELEROMETER, Util.setRead(STEP_COUNTER_DATA), new DataAttributes(new byte[] { 2 }, 1, 0, false));
     stepDetectorDataType = new IntegralDataType(ACCELEROMETER, STEP_DETECTOR_INTERRUPT, new DataAttributes(new byte[] { 1 }, 1, 0, false));
 }
        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)));
        }
        public IRouteComponent Filter(Comparison op, ComparisonOutput output, params float[] references)
        {
            if (source.attributes.length() > 4)
            {
                throw new IllegalRouteOperationException("Cannot compare data longer than 4 bytes");
            }

            if (source.attributes.length() <= 0)
            {
                throw new IllegalRouteOperationException("Cannot compare null data");
            }

            if (source.eventConfig[0] == (byte)SENSOR_FUSION)
            {
                throw new IllegalRouteOperationException("Cannot compare sensor sensor fusion data");
            }

            if (state.bridge.getFirmware().CompareTo(MULTI_COMPARISON_MIN_FIRMWARE) < 0)
            {
                float scaledReference = references[0] * source.scale(state.bridge);

                byte[] config = new byte[8];
                config[0] = 0x6;
                config[1] = (byte)(source.attributes.signed || references[0] < 0 ? 1 : 0);
                config[2] = (byte)op;
                config[3] = 0;
                Array.Copy(Util.intToBytesLe((int)(scaledReference)), 0, config, 4, 4);

                return(postCreate(null, new SingleValueComparatorEditor(config, source.dataProcessorCopy(source, source.attributes.dataProcessorCopy()), state.bridge)));
            }

            bool anySigned = false;

            foreach (float it in references)
            {
                anySigned |= it < 0;
            }
            bool signed = source.attributes.signed || anySigned;

            DataTypeBase processor;

            if (output == ComparisonOutput.PassFail || output == ComparisonOutput.Zone)
            {
                DataAttributes newAttrs = new DataAttributes(new byte[] { 1 }, 1, 0, false);
                processor = new IntegralDataType(source, DATA_PROCESSOR, DataProcessor.NOTIFY, newAttrs);
            }
            else
            {
                processor = source.dataProcessorCopy(source, source.attributes.dataProcessorCopy());
            }

            {
                //scope conflict with 'config' variable name
                byte[] config = new byte[2 + references.Length * source.attributes.length()];
                config[0] = 0x6;
                config[1] = (byte)((signed ? 1 : 0) | ((source.attributes.length() - 1) << 1) | ((int)op << 3) | ((int)output << 6));

                byte[] referenceValues = MultiValueComparatorEditor.fillReferences(source.scale(state.bridge), source, references);
                Array.Copy(referenceValues, 0, config, 2, referenceValues.Length);

                return(postCreate(null, new MultiValueComparatorEditor(config, processor, state.bridge)));
            }
        }