Example #1
0
        public BitsRange Intersect(BitsRange bitsRange)
        {
            // bitsRange   .....------...........
            // this        .............-----....

            // this        .....------...........
            // bitsRange   .............-----....

            // bitsRange   ...---------------....
            // this        ....--------..........

            // this        ...---------------....
            // bitsRange   ....--------..........

            // bitsRange   ........----------....
            // this        ....--------..........

            // bitsRange   ....--------..........
            // this        ........----------....

            int from = Math.Max(FromBits, bitsRange.FromBits);
            int to   = Math.Min(ToBits, bitsRange.ToBits);

            return(from > to
                ? Empty
                : new BitsRange(from, to));
        }
Example #2
0
        private static string GetComposedValue(
            BitsRange bitsRange,
            int registerLength,
            int byteIndex,
            string[] byteParameterNames)
        {
            byte[] byteMasks = bitsRange.GetByteMasks(registerLength, byteIndex);

            bool anyMask      = false;
            var  byteMaskList = new List <string>();

            for (int i = 0; i < byteMasks.Length; i++)
            {
                if (byteMasks[i] > 0)
                {
                    bool needsMask = byteMasks[i] != 0xFF;

                    string byteMask = !needsMask
                        ? byteParameterNames[i]
                        : $"({byteParameterNames[i]} & {ToHex(byteMasks[i], 2)})";

                    int shift = bitsRange.FromBits - (byteIndex - i) * 8;

                    byteMask = ShiftValue(byteMask, shift);

                    byteMaskList.Add(byteMask);

                    if (needsMask)
                    {
                        anyMask = true;
                    }
                }
            }

            string composedValue;
            bool   needsCasting;

            if ((byteMaskList.Count == 1) && !anyMask)
            {
                needsCasting  = false;
                composedValue = byteMaskList[0];
            }
            else
            {
                needsCasting  = true;
                composedValue = ((byteMaskList.Count == 1) && anyMask)
                    ? $"{string.Join(" | ", byteMaskList)}"
                    : $"({string.Join(" | ", byteMaskList)})";
            }

            if (needsCasting)
            {
                composedValue = $"({GetIntegerType(bitsRange)})" + composedValue;
            }

            return(composedValue);
        }
Example #3
0
        private static BitsRange GetBitsRange(XElement element, int registerLength, BitsRange defaultBitsRange, out int byteIndex)
        {
            BitsRange bitsRange = GetBitsRange(element) ?? defaultBitsRange;

            byteIndex = registerLength - 1;
            while (bitsRange.FromBits > 7)
            {
                byteIndex--;
                bitsRange = new BitsRange(bitsRange.FromBits - 8, bitsRange.ToBits - 8);
            }

            return(bitsRange);
        }
Example #4
0
        private static uint GetIntegerTypeMaxValue(BitsRange bitsRange)
        {
            switch (bitsRange.ByteCount)
            {
            case 1:
                return(0xFF);

            case 2:
                return(0xFFFF);

            case 3:
            case 4:
                return(0xFFFFFFFF);

            default:
                throw new Exception($"Unsupported integer size: {bitsRange.ByteCount} bytes.");
            }
        }
Example #5
0
        private static string[] GetDecomposedValues(
            string name,
            BitsRange bitsRange,
            int registerLength,
            int byteIndex,
            bool isNumeric)
        {
            byte[] byteMasks = bitsRange.GetByteMasks(registerLength, byteIndex);

            var getAsBytesValues = new string[registerLength];

            if (!isNumeric)
            {
                name = $"({GetIntegerType(bitsRange)}){name}";
            }

            for (int i = 0; i < byteMasks.Length; i++)
            {
                if (byteMasks[i] > 0)
                {
                    bool needsMask = byteMasks[i] != 0xFF;

                    int shift = (byteIndex - i) * 8 - bitsRange.FromBits;

                    string propertyMask = ShiftValue(name, shift);

                    if (needsMask)
                    {
                        propertyMask = $"(byte)({propertyMask} & {ToHex(byteMasks[i], 2)})";
                    }
                    else if (bitsRange.ByteCount > 1)
                    {
                        propertyMask = "(byte)" + propertyMask;
                    }

                    getAsBytesValues[i] = propertyMask;
                }
            }

            return(getAsBytesValues);
        }
Example #6
0
        private static string GetIntegerType(BitsRange bitsRange)
        {
            string type;

            switch (bitsRange.ByteCount)
            {
            case 1:
                type = "byte";
                break;

            case 2:
                type = "ushort";
                break;

            case 3:
            case 4:
                type = "uint";
                break;

            default:
                throw new Exception($"Unsupported integer size: {bitsRange.ByteCount} bytes.");
            }
            return(type);
        }
Example #7
0
        public byte[] GetByteMasks(int registerLength, int byteIndex)
        {
            byte[] byteMasks = new byte[registerLength];

            int addOn = (registerLength - 1 - byteIndex) * 8;

            BitsRange denormalizedBitsRange = addOn > 0
                ? new BitsRange(FromBits + addOn, ToBits + addOn)
                : this;

            for (int i = 0; i < registerLength; i++)
            {
                BitsRange intersect = denormalizedBitsRange.Intersect(GetByteRange(i));

                intersect = intersect.Shift(-i * 8);

                if (!intersect.IsEmpty)
                {
                    byteMasks[registerLength - i - 1] = (byte)(intersect.MaxValue << intersect.FromBits);
                }
            }

            return(byteMasks);
        }
Example #8
0
        private void GenerateNumber(
            CodeWriter code,
            RegisterMode registerMode,
            int registerLength,
            List <RegisterProperty> properties,
            XElement element)
        {
            string name      = GetName(element) ?? "Value";
            string paramName = GetLocalName(name);

            int       byteIndex;
            BitsRange bitsRange = GetBitsRange(element, registerLength, null, out byteIndex);

            uint defaultValue;

            if (registerMode == RegisterMode.ReadWrite)
            {
                defaultValue = ConvertToInteger(element.Attribute("default")?.Value) << bitsRange.FromBits;
            }
            else
            {
                defaultValue = 0;
            }

            string integerType = GetIntegerType(bitsRange);

            Action <CodeWriter, string> appendPropertyAssigmentValidation = (codeWriter, actualParamName) =>
            {
                uint integerTypeMaxValue = GetIntegerTypeMaxValue(bitsRange);
                if (integerTypeMaxValue != bitsRange.MaxValue)
                {
                    AppendVerboseComment(codeWriter, "Validating the numerical range.");
                    codeWriter.AppendLine($"if ({actualParamName} > {ToHex(bitsRange.MaxValue, bitsRange.NibbleCount)})");
                    codeWriter.AppendLine("{");
                    codeWriter.Indent++;
                    codeWriter.AppendLine($"throw new ArgumentException($\"{{nameof({actualParamName})}} must be in the range of [{ToHex(0, bitsRange.NibbleCount)} - {ToHex(bitsRange.MaxValue, bitsRange.NibbleCount)}].\");");
                    codeWriter.Indent--;
                    codeWriter.AppendLine("}");
                    codeWriter.AppendLine();
                }
            };

            Action <CodeWriter, string[]> appendPropertyAssigmentFromBytes = (codeWriter, byteParameterNames) =>
            {
                AppendVerboseComment(codeWriter, "Assigning the composed numerical value.");
                string composedValue = GetComposedValue(bitsRange, registerLength, byteIndex, byteParameterNames);
                codeWriter.AppendLine($"{name} = {composedValue};");
            };

            Func <string[]> getByteIndexAsByteStrings = () =>
                                                        GetDecomposedValues(name, bitsRange, registerLength, byteIndex, true);

            properties.Add(new RegisterProperty(
                               PropertyType.Numeric,
                               registerMode,
                               name,
                               paramName,
                               integerType,
                               ToHex(defaultValue, bitsRange.NibbleCount),
                               GetDescription(element),
                               appendPropertyAssigmentValidation,
                               appendPropertyAssigmentFromBytes,
                               getByteIndexAsByteStrings,
                               byteIndex));
        }