예제 #1
0
        /// <summary>
        /// Constructor must be initialized with the HidDevice, the Teensy this
        /// report is for and the HexImage object to upload.
        /// </summary>
        public HidUploadReport(HidDevice device,
                               Teensy teensy,
                               HexImage image) : base(device)
        {
            Teensy = teensy;
            Image  = image;

            // The block size must be less than the HID report length.
            if (teensy.DataBlockSize > device.ReportLength - 1)
            {
                throw new TeensyException(
                          $"The data block size of a {Constants.TeensyWord} must be smaller than the HID report size, including the first byte, which is the report ID.");
            }
        }
예제 #2
0
        /// <summary>
        /// Find a Teensy with the specified serial number. Returns null if not
        /// found. If desired, the result can also be filtered by UsbType. If
        /// serialNumber is 0, this will return the first Teensy found. type, if
        /// present, will still be used to filter results.
        /// </summary>
        public Teensy Find(uint serialNumber = 0,
                           UsbTypes?type     = null)
        {
            Teensy result = null;

            EnumTeensies(teensy =>
            {
                if (serialNumber == 0 || teensy.SerialNumber == serialNumber)
                {
                    if (!type.HasValue || type.Value == teensy.UsbType)
                    {
                        result = teensy;
                    }
                }

                return(result == null);
            });

            return(result);
        }
예제 #3
0
        /// <summary>
        /// Upload an image to the Teensy.
        /// </summary>
        public void Upload()
        {
        #if DEBUG
            // ReSharper disable HeuristicUnreachableCode
            #pragma warning disable 162
            const string filePath = null;
            //const string filePath = "T:\\Source\\Teensy.Net\\TestFiles\\blinkLC.hex.TeensyNetOutput";
            //const string filePath = "T:\\Source\\Teensy.Net\\TestFiles\\blink32.hex.TeensyNetOutput";

            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            if (filePath != null)
            {
                TestOutputStream = File.Open(filePath,
                                             FileMode.Create,
                                             FileAccess.Write,
                                             FileShare.None);
            }
            #pragma warning restore 162
            // ReSharper restore HeuristicUnreachableCode
        #endif

            Image.Chunk((bytes, imageOffset) =>
            {
                // The data offset is how much free space to leave in the HID
                // report data before writing of actual image data. The address
                // is always first, but writing image data should occur at this
                // offset.
                var dataOffset = 2u;

                // Add address (image offset).
                if (Teensy.DataBlockSize <= 256 && Teensy.FlashSize < 0x10000)
                {
                    AddData((byte)(imageOffset & 0xFF));
                    AddData((byte)((imageOffset >> 8) & 0xFF));
                }
                else if (Teensy.DataBlockSize == 256)
                {
                    AddData((byte)((imageOffset >> 8) & 0xFF));
                    AddData((byte)((imageOffset >> 16) & 0xFF));
                }
                else
                {
                    AddData((byte)(imageOffset & 0xFF));
                    AddData((byte)((imageOffset >> 8) & 0xFF));
                    AddData((byte)((imageOffset >> 16) & 0xFF));

                    dataOffset = 64;
                }

                // Copy data to report, starting at data offset.
                SetDataStart(dataOffset);
                Fill(bytes);

                if (imageOffset == 0)
                {
                    Teensy.ProvideFeedback(
                        $"Erasing {Constants.TeensyWord} Flash Memory");
                }

                Write();

                // The first write erases the chip and needs a little
                // longer to complete.
                Thread.Sleep(imageOffset == 0 ? 3000 : 500);

                Teensy.ProvideFeedback(imageOffset + Teensy.DataBlockSize,
                                       Image.Size);
            });

        #if DEBUG
            if (TestOutputStream != null)
            {
                TestOutputStream.Close();
                TestOutputStream.Dispose();
                TestOutputStream = null;
            }
        #endif
        }
예제 #4
0
        /// <summary>
        /// Create a Teensy from management object, if the management object
        /// specifies Teensy information.
        /// </summary>
        private Teensy CreateTeensy(ManagementBaseObject o)
        {
            Teensy result       = null;
            var    teensyType   = TeensyTypes.Unknown;
            string portName     = null;
            var    serialNumber = (uint)0;
            var    usbType      = UsbTypes.Disconnected;

            // Safely get a field value from management object.
            T GetFieldValue <T>(string fieldName)
            {
                var value = default(T);

                Utility.Try(() =>
                {
                    var obj = o[fieldName];

                    if (obj is T test)
                    {
                        value = test;
                    }
                });

                return(value);
            }

            // Given a field that is a string array, return the index value or
            // null.
            string GetFieldPart(string fieldName,
                                int index)
            {
                string value = null;

                var stringParts = GetFieldValue <string[]>(fieldName);

                if (stringParts != null && index < stringParts.Length)
                {
                    value = stringParts[index];
                }

                return(value);
            }

            // Given a field that is a string to be split, return the index value
            // or null.
            string GetSplitField(string fieldName,
                                 char[] splitOn,
                                 int index)
            {
                string value = null;

                var stringParts = GetFieldValue <string>(fieldName)?.Split(splitOn);

                if (stringParts != null && index < stringParts.Length)
                {
                    value = stringParts[index];
                }

                return(value);
            }

            var parts = GetFieldValue <string>("PNPDeviceID")?.Split('\\');

            if (parts?.Length > 2 && parts[0] == "USB")
            {
                var id = Convert.ToUInt32(parts[1].Substring(
                                              parts[1].IndexOf("PID_", StringComparison.Ordinal) + 4, 4),
                                          16);

                if (id == SerialNumberId)
                {
                    var hwId = GetFieldPart("HardwareID", 0);

                    if (hwId != null)
                    {
                        portName = GetSplitField("Caption", new[] { '(', ')' }, 1);

                        if (portName != null)
                        {
                            serialNumber = Convert.ToUInt32(parts[2]);
                            usbType      = UsbTypes.Serial;

                            switch (hwId.Substring(hwId.IndexOf(
                                                       "REV_",
                                                       StringComparison.Ordinal) + 4, 4))
                            {
                            case "0273":
                            {
                                teensyType = TeensyTypes.TeensyLc;
                                break;
                            }

                            case "0274":
                            {
                                teensyType = TeensyTypes.Teensy30;
                                break;
                            }

                            case "0275":
                            {
                                // There is not a unique value for Teensy 3.1
                                // so we assume 3.2.
                                teensyType = TeensyTypes.Teensy32;
                                break;
                            }

                            case "0276":
                            {
                                teensyType = TeensyTypes.Teensy35;
                                break;
                            }

                            case "0277":
                            {
                                teensyType = TeensyTypes.Teensy36;
                                break;
                            }

                            case "0279":
                            {
                                teensyType = TeensyTypes.Teensy40;
                                break;
                            }
                            }
                        }
                    }
                }
                // Device is running bootloader? Have to use HID.
                else if (id == Constants.BootloaderId)
                {
                    serialNumber = Utility.FixSerialNumber(
                        Convert.ToUInt32(parts[2], 16));

                    // Find Teensy running bootloader.
                    using (var teensy = HidDevice.FindDevice(serialNumber))
                    {
                        if (teensy != null)
                        {
                            teensyType = teensy.TeensyType;
                            usbType    = UsbTypes.Bootloader;
                        }
                    }
                }

                // We must know these things!
                if (teensyType != TeensyTypes.Unknown &&
                    usbType != UsbTypes.Disconnected &&
                    serialNumber != 0)
                {
                    result = new Teensy(this,
                                        teensyType,
                                        portName,
                                        serialNumber,
                                        usbType);
                }
            }

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Constructor must be initialized with the Teensy type and the reader to
        /// read image data from.
        /// </summary>
        public HexImage(TeensyTypes type,
                        TextReader reader,
                        bool disposeStream = false)
        {
            if (reader == null)
            {
                throw new TeensyException(
                          "The HEX stream to read must be specified.");
            }

            TeensyType = Teensy.CheckType(type);

            switch (TeensyType)
            {
            case TeensyTypes.Teensy2:
            {
                DataBlockSize = 128;
                break;
            }

            case TeensyTypes.Teensy2PlusPlus:
            {
                DataBlockSize = 256;
                break;
            }

            case TeensyTypes.TeensyLc:
            {
                DataBlockSize = 512;
                break;
            }

            default:
            {
                DataBlockSize = 1024;
                break;
            }
            }

            // Initialize image.
            var valid = false;
            var size  = Teensy.GetFlashSize(TeensyType);

            _data = new byte[size];

            for (var i = 0; i < size; i++)
            {
                _data[i] = 0xFF;
            }

            var lineNumber = (uint)1;

            // Upper Linear Base Address.
            var ulba = (uint)0;

            // Segment Base Address.
            var segba = (uint)0;

            // Do not allow parsing to throw exception. We may need to dispose of
            // the stream after.
            var exception = Utility.Try(() =>
            {
                var tempData = new byte[0];

                while (ParseLine(reader.ReadLine(),
                                 ref ulba,
                                 ref segba,
                                 ref tempData,
                                 ref valid))
                {
                    ++lineNumber;
                }
            });

            if (disposeStream)
            {
                Utility.Try(reader.Dispose);
            }

            if (exception != null)
            {
                Utility.Throw(
                    exception,
                    $"Invalid HEX file image data was found on or near line {lineNumber}.");
            }

            // Determine the total length of data that will be written.
            var totalLength = 0u;

            Chunk((bytes, imageOffset) =>
            {
                totalLength = imageOffset + DataBlockSize;
            });

            // Reset Data to match actual size.
            Array.Resize(ref _data, (int)totalLength);
        }