Пример #1
0
        public void Evaluate(int SpreadMax)
        {
            if (In.IsChanged)
            {
                Values.SliceCount = PortNumber.SliceCount * 8;                 // 8 bits per port
                Port.SliceCount   = PortNumber.SliceCount;

                foreach (string msg in In)
                {
                    byte[] data = Encoding.GetEncoding(1252).GetBytes(msg);
                    if (!FirmataUtils.ContainsCommand(data, Command.DIGITALMESSAGE))
                    {
                        continue;                         //
                    }
                    int   port;
                    int[] values;
                    if (FirmataUtils.DecodePortMessage(data, out port, out values))
                    {
                        Port[0] = port;
                        Values.AssignFrom(values);
                        CachedValues = Values.Clone();
                    }
                    else
                    {
                        Values = CachedValues.Clone();
                    }
                }
            }
        }
Пример #2
0
        public void Evaluate(int maxSpread)
        {
            if (Data.IsChanged)
            {
                if (Data.SliceCount < 2)
                {
                    return;
                }

                int _address = FirmataUtils.GetValueFromBytes(Data[1], Data[0]);
                if (_address != Address[0] && Data.SliceCount < 4)
                {
                    return;
                }

                int[] empty = {};
                ParsedRegister.AssignFrom(empty);
                ParsedData.AssignFrom(empty);

                for (int i = 2; i < Data.SliceCount - 4; i += 4)
                {
                    ParsedRegister.Add(FirmataUtils.GetValueFromBytes(Data[i + 1], Data[i]));
                    ParsedData.Add(FirmataUtils.GetValueFromBytes(Data[i + 3], Data[i + 2]));
                }
            }
        }
Пример #3
0
        void GetSamplerateCommand(int rate)
        {
            byte lsb, msb;

            FirmataUtils.GetBytesFromValue(rate, out msb, out lsb);
            CommandBuffer.Enqueue(Command.SYSEX_START);
            CommandBuffer.Enqueue(Command.SAMPLING_INTERVAL);
            CommandBuffer.Enqueue(lsb);
            CommandBuffer.Enqueue(msb);
            CommandBuffer.Enqueue(Command.SYSEX_END);
        }
Пример #4
0
        ///
        /// TODO: Make it spreadable with Address spread as size
        ///
        public void Evaluate(int maxSpread)
        {
            if (Data.IsChanged)
            {
                FDebug.SliceCount = 0;

                if (Data.SliceCount <= 0 || Address.SliceCount < 1)
                {
                    clearOutputs();
                    return;
                }

                int NumBytes = (int)Data[0].Length - 4; // substract Address & Register
                if (NumBytes <= 0)
                {
                    FDebug.Add(NumBytes > 0 ? "No data bytes to process" : "Not enough bytes at all");
                    clearOutputs();
                    return;
                }

                byte LSB      = (byte)Data[0].ReadByte();
                byte MSB      = (byte)Data[0].ReadByte();
                int  _Address = FirmataUtils.GetValueFromBytes(MSB, LSB);

                if (_Address != Address[0])
                {
                    clearOutputs();
                    FDebug.Add("Address does not match");
                    return;
                }

                LSB = (byte)Data[0].ReadByte();
                MSB = (byte)Data[0].ReadByte();
                ParsedRegister.SliceCount = 1;
                int register = FirmataUtils.GetValueFromBytes(MSB, LSB);
                ParsedRegister[0] = register == 255 ? -1 : register; // Handle REGISTER_NOT_SPECIFIED

                try {
                    ParsedData.SliceCount = 1;
                    Stream data = new MemoryStream(NumBytes / 2); // we deal with 7-bit encoding!
                    for (int i = 0; i < NumBytes; i += 2)
                    {
                        LSB = (byte)Data[0].ReadByte();
                        MSB = (byte)Data[0].ReadByte();
                        data.WriteByte((byte)FirmataUtils.GetValueFromBytes(MSB, LSB));
                    }
                    ParsedData[0] = data;
                }
                catch (Exception e) {
                    FDebug.Add("Could not read data: " + e.ToString());
                }
            }
        }
Пример #5
0
        void SetPinStates(ISpread <double> values)
        {
            // get the number of output ports
            // FIXME: Make MAX_PORTS avaiable through Firmata
            int[] digital_out = new int[OUTPUT_PORT_MASKS.Length];

            for (int i = 0; i < values.SliceCount; i++)
            {
                double  value = values[i];
                PinMode mode  = PinModeForPin(i);
                switch (mode)
                {
                case PinMode.ANALOG:
                case PinMode.PWM:
                case PinMode.SERVO:
                    byte LSB, MSB;
                    value *= mode == PinMode.SERVO ? 180 : 255;                   // servo is in degrees
                    FirmataUtils.GetBytesFromValue((int)value, out MSB, out LSB);
                    CommandBuffer.Enqueue((byte)(Command.ANALOGMESSAGE | i));
                    CommandBuffer.Enqueue(LSB);
                    CommandBuffer.Enqueue(MSB);
                    break;

                case PinMode.OUTPUT:
                case PinMode.INPUT:                           // fixes PullUp enabling issue, thx to motzi!
                    int port_index = PortIndexForPin(i);
                    // Break, if we have no ouputports we can get
                    if (port_index >= digital_out.Length)
                    {
                        break;
                    }

                    int shift       = i % 8;
                    int state       = value >= 0.5 ? 0x01 : 0x00;
                    int port_before = digital_out[port_index];
                    digital_out[port_index] = ((state << shift) | digital_out[port_index]) & OUTPUT_PORT_MASKS[port_index];
                    break;
                }
            }

            /// Write all the output ports to the command buffer
            for (int port_index = 0; port_index < digital_out.Length; port_index++)
            {
                byte LSB, MSB;
                byte atmega_port = (byte)port_index;                  //Array.GetValues(Port)[port_index];
                FirmataUtils.GetBytesFromValue(digital_out[port_index], out MSB, out LSB);

                CommandBuffer.Enqueue((byte)(Command.DIGITALMESSAGE | atmega_port));
                CommandBuffer.Enqueue(LSB);
                CommandBuffer.Enqueue(MSB);
            }
        }
Пример #6
0
        //called when data for any output pin is requested
        public void Evaluate(int SpreadMax)
        {
            analogIns.SliceCount  = analogInputCount[0];
            digitalIns.SliceCount = digitalInputCount[0];

            /// Using a Queue and iterate over it (nice to handle and inexpensive)
            foreach (byte b in Encoding.GetEncoding(1252).GetBytes(ansiMessage[0]))
            {
                // we should check for max buffer size and not constantly enque things...
                buffer.Enqueue(b);
            }

            // A cache for sysex data
            Queue <byte> cache = new Queue <byte>();
            // A flag if parsing sysex data
            bool bIsSysex = false;

            // PARSE:
            while (buffer.Count > 0)
            {
                byte current = buffer.Dequeue();
                switch (current)
                {
                case Command.SYSEX_START:
                case Command.SYSEX_END:
                    //            byte cmd = buffer.Dequeue();
                    if (current == Command.SYSEX_START)
                    {
                        bIsSysex = true;
                    }
                    else if (current == Command.SYSEX_END)
                    {
                        // Process the Sysexdata:
                        ProcessSysex(cache);
                        bIsSysex = false;
                    }
                    cache.Clear();
                    break;

                default:
                    if (bIsSysex)
                    {
                        cache.Enqueue(current);
                    }
                    else
                    {
                        // Treat Ananlog & Digital Messages:
                        bool hasDigitalMessage = FirmataUtils.VerifiyCommand(current, Command.DIGITALMESSAGE);
                        bool hasAnalogMessage  = FirmataUtils.VerifiyCommand(current, Command.ANALOGMESSAGE);
                        // We have a data for commands
                        if (buffer.Count >= 2 && (hasDigitalMessage || hasAnalogMessage))
                        {
                            // Reihenfolge matters!
                            byte[] data = { current, buffer.Dequeue(), buffer.Dequeue() };
                            // Check for Analog Command
                            if (hasAnalogMessage)
                            {
                                int pinNum, value;
                                FirmataUtils.DecodeAnalogMessage(data, out pinNum, out value);
                                if (pinNum < analogInputCount[0])
                                {
                                    analogIns[pinNum] = value;                             // assign the found value to the spread
                                }
                            }
                            else if (hasDigitalMessage)
                            {
                                int port; int[] vals;
                                // Decode the values from the bytes:
                                FirmataUtils.DecodePortMessage(data, out port, out vals);
                                // Fill the spread with parsed pinstates
                                for (int i = 0; i < Constants.BitsPerPort; i++)
                                {
                                    int pinNum = i + Constants.BitsPerPort * port;
                                    if (pinNum < digitalIns.SliceCount)
                                    {
                                        digitalIns[pinNum] = vals[i];
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }
Пример #7
0
        public void Evaluate(int SpreadMax)
        {
            SpreadMax = SpreadUtils.SpreadMax(Address, ReadWriteMode);

            if (DoSend.IndexOf(true) < 0 || SpreadMax == 0)
            {
                DataOut[0] = Stream.Null;
                return; // return when nothing to send
            }

            Out.Position = 0;
            Out.SetLength(0);

            byte lsb, msb;

            // I2C config up front
            Out.WriteByte(Command.SYSEX_START);
            Out.WriteByte(Command.I2C_CONFIG);
            FirmataUtils.GetBytesFromValue(I2CDelay[0], out msb, out lsb);
            Out.WriteByte(lsb); Out.WriteByte(msb);
            Out.WriteByte(Command.SYSEX_END);

            for (int i = 0; i < SpreadMax; i++)
            {
                if ((ReadWriteMode[i] != I2CMode.WRITE && DoSend[i] == false) ||
                    (ReadWriteMode[i] == I2CMode.WRITE && DataIn[i].Length == 0)
                    )
                {
                    continue;
                }

                // handle read continuously readings, keep track of requests
                if (ReadWriteMode[i] == I2CMode.READ_CONTINUOUSLY)
                {
                    if (ContinuouslyReadings.Contains(Address[i]))
                    {
                        continue;
                    }
                    else
                    {
                        ContinuouslyReadings.Add(Address[i]);
                    }
                }
                else if (ReadWriteMode[i] == I2CMode.STOP_READING && ContinuouslyReadings.Contains(Address[i]))
                {
                    ContinuouslyReadings.Remove(Address[i]);
                }

                // Write the request header
                Out.WriteByte(Firmata.Command.SYSEX_START);
                Out.WriteByte(Firmata.Command.I2C_REQUEST);

                // Write therequest address and mode
                Out.WriteByte((byte)(Address[i] & 0x7F)); // LSB

                byte mode = (byte)ReadWriteMode[i];
                // Handle 10-bit mode
                if (AddressMode[i].Index > 0)
                {
                    mode |= 0x20;                             // enable
                    mode |= (byte)((Address[i] >> 8) & 0x03); // add MSB of address
                }
                Out.WriteByte(mode);

                switch (ReadWriteMode[i])
                {
                case I2CMode.WRITE:
                    if (Register[i] > 0)
                    {
                        FirmataUtils.GetBytesFromValue(Math.Max(Register[i], 0), out msb, out lsb);
                        Out.WriteByte(lsb); Out.WriteByte(msb);
                    }
                    while (DataIn[i].Position < DataIn[i].Length)
                    {
                        FirmataUtils.GetBytesFromValue((int)DataIn[i].ReadByte(), out msb, out lsb);
                        Out.WriteByte(lsb); Out.WriteByte(msb);
                    }
                    break;

                case I2CMode.READ_ONCE:
                case I2CMode.READ_CONTINUOUSLY:
                    if (Register[i] > 0 || ReadWriteMode[i] == I2CMode.READ_CONTINUOUSLY)
                    {
                        FirmataUtils.GetBytesFromValue(Math.Max(Register[i], 0), out msb, out lsb);
                        Out.WriteByte(lsb); Out.WriteByte(msb);
                    }
                    FirmataUtils.GetBytesFromValue(BytesToRead[i], out msb, out lsb);
                    Out.WriteByte(lsb); Out.WriteByte(msb);
                    break;
                }

                // Close SysEx message
                Out.WriteByte(Firmata.Command.SYSEX_END);
            }

            DataOut[0] = Out;
        }
Пример #8
0
        void SetPinStates(ISpread <double> values)
        {
            // get the number of output ports
            // FIXME: Get only those ports, whos values have changed
            int[]        digital_out         = new int[NUM_PORTS];
            Queue <byte> AnalogCommandBuffer = new Queue <byte>();
            int          analogOutCount      = 0;
            int          pinCount            = Math.Min(Default.MaxDigitalPins, Math.Min(NUM_PINS, values.SliceCount));

            for (int pin = 0; pin < pinCount; pin++)
            {
                double  value = values[pin];
                PinMode mode  = PinModeForPin(pin);
                switch (mode)
                {
                case PinMode.PWM:
                case PinMode.SERVO:
                    byte LSB, MSB;
                    value *= mode == PinMode.SERVO ? 180 : 255; // servo is in degrees
                    FirmataUtils.GetBytesFromValue((int)value, out MSB, out LSB);
                    if (pin <= 0x0F)
                    {
                        AnalogCommandBuffer.Enqueue((byte)(Command.ANALOGMESSAGE | pin));
                        AnalogCommandBuffer.Enqueue(LSB);
                        AnalogCommandBuffer.Enqueue(MSB);
                    }
                    else
                    {
                        AnalogCommandBuffer.Enqueue(Command.SYSEX_START);
                        AnalogCommandBuffer.Enqueue(Command.EXTENDED_ANALOG);
                        AnalogCommandBuffer.Enqueue((byte)(pin & 0x7F)); // mask 7 Bit
                        AnalogCommandBuffer.Enqueue(LSB);
                        AnalogCommandBuffer.Enqueue(MSB);
                        AnalogCommandBuffer.Enqueue(Command.SYSEX_END);
                    }
                    break;

                case PinMode.OUTPUT:
                case PinMode.INPUT: // fixes PullUp enabling issue, thx to motzi!
                    int port = PortIndexForPin(pin);
                    // Break, if we have no outputports we can get
                    if (port < NUM_PORTS)
                    {
                        int state = (value >= 0.5 ? 0x01 : 0x00) << pin % 8;
                        state            |= digital_out[port];
                        state            &= OUTPUT_PORT_MASKS[port];
                        digital_out[port] = (byte)state;
                    }
                    break;
                }
            }

            /// Write all the output ports to the command buffer
            for (int port = 0; port < digital_out.Length; port++)
            {
                byte LSB, MSB;
                FirmataUtils.GetBytesFromValue(digital_out[port], out MSB, out LSB);
                CommandBuffer.Enqueue((byte)(Command.DIGITALMESSAGE | port));
                CommandBuffer.Enqueue(LSB);
                CommandBuffer.Enqueue(MSB);
            }

            /// Append the Commands for the analog messages
            if (AnalogCommandBuffer.Count > 0)
            {
                foreach (byte b in AnalogCommandBuffer)
                {
                    CommandBuffer.Enqueue(b);
                }
            }
        }
Пример #9
0
        void ProcessSysex(Queue <byte> data)
        {
            if (data.Count == 0)
            {
                return;
            }

            switch (data.Dequeue())
            {
            /// Handle Firmwareversion replies:
            case Command.REPORT_FIRMWARE:
                if (data.Count < 2)
                {
                    break;
                }
                int major = data.Dequeue();
                int minor = data.Dequeue();
                // Read the name, of the Version
                string name     = FirmataUtils.GetStringFromBytes(data);
                string the_name = major + "." + minor;
                if (name.Length > 0)
                {
                    the_name += " " + name.ToString();
                }

                FFirmwareMajorVersion[0] = major;
                FFirmwareMinorVersion[0] = minor;
                FFirmwareName[0]         = name.ToString();
                FFirmwareVersion[0]      = the_name;
                break;

            /// Handle String Data
            case Command.STRING_DATA:
                string message = FirmataUtils.GetStringFromBytes(data);
                StringOut.Add(message);
                StringOut.Flush(true); // Signal change, regardless of the message
                break;

            /// Handle I2C replies
            case Command.I2C_REPLY:
                try {
                    MemoryStream i2cStream = new MemoryStream(data.ToArray());

                    FI2CData.Length = 1;
                    using (var i2cWriter = FI2CData.GetWriter()) {
                        i2cWriter.Write(i2cStream);
                    }
                } catch (Exception e) {
                    FI2CData.Length = 0;
                }
                data.Clear();

                break;

            case Command.CAPABILITY_RESPONSE:
                string report   = "";
                int    pinCount = 0;

                int    digitalPins = 0;
                int    analogPins  = 0;
                int    servoPins   = 0;
                int    pwmPins     = 0;
                int    shiftPins   = 0;
                int    i2cPins     = 0;
                byte[] buffer      = data.ToArray();

                for (int a = 0; a < buffer.Length; a++)
                {
                    pinCount++;
                    report += "Pin " + pinCount.ToString() + ":";

                    if (buffer[a] == 0x7f)
                    {
                        report += "\tNot available!";
                    }

                    while (buffer[a] != 0x7f)
                    {
                        PinMode mode = (PinMode)buffer[a++];
                        switch (mode)
                        {
                        case PinMode.ANALOG:
                            analogPins++;
                            break;

                        case PinMode.INPUT:
                        case PinMode.OUTPUT:
                            digitalPins++;
                            break;

                        case PinMode.SERVO:
                            servoPins++;
                            break;

                        case PinMode.PWM:
                            pwmPins++;
                            break;

                        case PinMode.I2C:
                            i2cPins++;
                            break;

                        case PinMode.SHIFT:
                            shiftPins++;
                            break;
                        }

                        int resolution = buffer[a++];

                        report += "\t" + FirmataUtils.PinModeToString(mode);
                        report += " (" + resolution.ToString() + " bit) ";
                    }

                    report += "\r\n";
                }
                digitalPins /= 2;
                report      += "Total number of pins: " + pinCount.ToString() + "\r\n";
                report      += string.Format("{0} digital, {1} analog, {2} servo, {3} pwm and {4} i2c pins\r\n", digitalPins, analogPins, servoPins, pwmPins, i2cPins);
                FCapabilities.SliceCount = 1;
                FCapabilities[0]         = report;
                break;
            }
        }
Пример #10
0
        private void Decode(byte data)
        {
            if ((data & 0x80) > 0)
            {
                byte cmd = FirmataUtils.GetCommandFromByte(data);

                lastCommand = cmd;
                switch (cmd)
                {
                case Command.RESET:
                    buffer.Clear();
                    break;

                case Command.DIGITALMESSAGE:
                case Command.ANALOGMESSAGE:
                case Command.REPORT_VERSION:
                case Command.SETPINMODE:
                    remaining = 2;
                    buffer.Clear();
                    buffer.Enqueue(data);
                    break;

                case Command.TOGGLEDIGITALREPORT:
                case Command.TOGGLEANALOGREPORT:
                    remaining = 1;
                    buffer.Clear();
                    buffer.Enqueue(data);
                    break;

                case Command.SYSEX_START:
                    buffer.Clear();
                    break;

                case Command.SYSEX_END:
                    // Fire Sysex event
                    ProcessSysex(buffer);
                    break;

                default:
                    // unknown command
                    break;
                }
            }
            else
            {
                buffer.Enqueue(data);
                if (--remaining == 0)
                {
                    // process the message
                    switch (lastCommand)
                    {
                    case Command.ANALOGMESSAGE:
                        int pin, value;
                        FirmataUtils.DecodeAnalogMessage(buffer.ToArray(), out pin, out value);
                        if (pin < FAnalogInputCount[0])
                        {
                            FAnalogIns[pin] = value;                   // assign the found value to the spread
                        }
                        break;

                    case Command.DIGITALMESSAGE:
                        int port; int[] vals;
                        // Decode the values from the bytes:
                        FirmataUtils.DecodePortMessage(buffer.ToArray(), out port, out vals);
                        // Fill the spread with parsed pinstates
                        int pinNum;
                        for (int i = 0; i < Constants.BitsPerPort; i++)
                        {
                            pinNum = i + Constants.BitsPerPort * port;
                            if (pinNum < FDigitalIns.SliceCount)
                            {
                                FDigitalIns[pinNum] = vals[i];
                            }
                        }
                        break;

                    case Command.REPORT_VERSION:
                        int major = (int)buffer.Dequeue();
                        int minor = (int)buffer.Dequeue();
                        FFirmwareMajorVersion[0] = major;
                        FFirmwareMinorVersion[0] = minor;
                        break;

                    default:
                        // unkown byte...
                        break;
                    }
                }
            }
        }
Пример #11
0
        private void HandleStream(Stream InStream)
        {
            // Check, if the incoming Stream is usable
            if (InStream == null || InStream.Length == 0 || !InStream.CanRead)
            {
                return;
            }

            // Read the incoming bytes to the internal stream buffer
            while (InStream.Position < InStream.Length)
            {
                Buffer.Enqueue((byte)InStream.ReadByte());
            }

            // A cache for sysex data
            Queue <byte> cache = new Queue <byte>();
            // A flag if parsing sysex data
            bool bIsSysex = false;

            // PARSE:
            while (Buffer.Count > 0)
            {
                byte current = Buffer.Dequeue();
                switch (current)
                {
                case Command.SYSEX_START:
                case Command.SYSEX_END:
                    if (current == Command.SYSEX_START)
                    {
                        bIsSysex = true;
                    }
                    else if (current == Command.SYSEX_END)
                    {
                        // Process the Sysexdata:
                        ProcessSysex(cache);
                        bIsSysex = false;
                    }
                    cache.Clear();
                    break;

                default:
                    if (bIsSysex) // Collect bytes for the SysSex message cache
                    {
                        cache.Enqueue(current);
                    }
                    else
                    {
                        // Treat Ananlog & Digital Messages:
                        bool hasDigitalMessage = FirmataUtils.VerifiyCommand(current, Command.DIGITALMESSAGE);
                        bool hasAnalogMessage  = FirmataUtils.VerifiyCommand(current, Command.ANALOGMESSAGE);
                        // We have a data for commands
                        if (Buffer.Count >= 2 && (hasDigitalMessage || hasAnalogMessage))
                        {
                            // Reihenfolge matters!
                            byte[] data = { current, Buffer.Dequeue(), Buffer.Dequeue() };
                            // Check for Analog Command
                            if (hasAnalogMessage)
                            {
                                int pinNum, value;
                                FirmataUtils.DecodeAnalogMessage(data, out pinNum, out value);
                                if (pinNum < FAnalogInputCount[0])
                                {
                                    FAnalogIns[pinNum] = value;                  // assign the found value to the spread
                                }
                            }
                            else if (hasDigitalMessage)
                            {
                                int port; int[] vals;
                                // Decode the values from the bytes:
                                FirmataUtils.DecodePortMessage(data, out port, out vals);
                                // Fill the spread with parsed pinstates
                                for (int i = 0; i < Constants.BitsPerPort; i++)
                                {
                                    int pinNum = i + Constants.BitsPerPort * port;
                                    if (pinNum < FDigitalIns.SliceCount)
                                    {
                                        FDigitalIns[pinNum] = vals[i];
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }