Record
public record HdlcControl : System.ValueType, System.IEquatable<SharpMeter.Dlms.Framing.HdlcControl>

Namespace: SharpMeter.Dlms.Framing

HDLC control field supporting I, S, and U frame types.

Inheritance

Inherits from: System.ValueType

Implements: System.IEquatable<SharpMeter.Dlms.Framing.HdlcControl>

Constructors

NameDescription
HdlcControl(…) HDLC control field supporting I, S, and U frame types.

HdlcControl(HdlcFrameType FrameType, bool PollFinal, byte SendSequence, byte ReceiveSequence)

HdlcControl.HdlcControl(HdlcFrameType FrameType, bool PollFinal = false, byte SendSequence = 0, byte ReceiveSequence = 0)

HDLC control field supporting I, S, and U frame types.

Parameters

NameTypeDescription
FrameTypeSharpMeter.Dlms.Framing.HdlcFrameTypeThe frame type.
PollFinalboolThe poll/final bit.
SendSequencebyteSend sequence number (N(S)) for I-frames.
ReceiveSequencebyteReceive sequence number (N(R)) for I/S-frames.

Properties

NameDescription
FrameType The frame type.
PollFinal The poll/final bit.
ReceiveSequence Receive sequence number (N(R)) for I/S-frames.
SendSequence Send sequence number (N(S)) for I-frames.

FrameType

HdlcFrameType HdlcControl.FrameType { get; init; }

The frame type.

PollFinal

bool HdlcControl.PollFinal { get; init; }

The poll/final bit.

ReceiveSequence

byte HdlcControl.ReceiveSequence { get; init; }

Receive sequence number (N(R)) for I/S-frames.

SendSequence

byte HdlcControl.SendSequence { get; init; }

Send sequence number (N(S)) for I-frames.

Methods

NameDescription
Decode(byte value) static Decodes a control byte.
Encode() Encodes this control field as a single byte.

Decode(byte value)

HdlcControl HdlcControl.Decode(byte value)

Decodes a control byte.

Encode()

byte HdlcControl.Encode()

Encodes this control field as a single byte.

Fields

NameDescription
Disc static DISC (Disconnect).
Dm static DM (Disconnected Mode).
Snrm static SNRM (Set Normal Response Mode) — connection establishment.
Ua static UA (Unnumbered Acknowledge).

Disc

SharpMeter.Dlms.Framing.HdlcControl Disc

DISC (Disconnect).

Dm

SharpMeter.Dlms.Framing.HdlcControl Dm

DM (Disconnected Mode).

Snrm

SharpMeter.Dlms.Framing.HdlcControl Snrm

SNRM (Set Normal Response Mode) — connection establishment.

Ua

SharpMeter.Dlms.Framing.HdlcControl Ua

UA (Unnumbered Acknowledge).

Type Relationships
classDiagram
                    style HdlcControl fill:#f9f,stroke:#333,stroke-width:2px
                    HdlcControl --|> ValueType : inherits
                    HdlcControl ..|> HdlcControl~ : implements
                
View Source
/// <summary>
///     HDLC control field supporting I, S, and U frame types.
/// </summary>
/// <param name = "FrameType">The frame type.</param>
/// <param name = "PollFinal">The poll/final bit.</param>
/// <param name = "SendSequence">Send sequence number (N(S)) for I-frames.</param>
/// <param name = "ReceiveSequence">Receive sequence number (N(R)) for I/S-frames.</param>
public readonly record struct HdlcControl(HdlcFrameType FrameType, bool PollFinal = false, byte SendSequence = 0, byte ReceiveSequence = 0)
{
#region Well-Known Controls
    /// <summary>SNRM (Set Normal Response Mode) — connection establishment.</summary>
    public static readonly HdlcControl Snrm = new(HdlcFrameType.Snrm, true);
    /// <summary>UA (Unnumbered Acknowledge).</summary>
    public static readonly HdlcControl Ua = new(HdlcFrameType.Ua, true);
    /// <summary>DISC (Disconnect).</summary>
    public static readonly HdlcControl Disc = new(HdlcFrameType.Disc, true);
    /// <summary>DM (Disconnected Mode).</summary>
    public static readonly HdlcControl Dm = new(HdlcFrameType.Dm, true);
#endregion
#region Methods
    /// <summary>Encodes this control field as a single byte.</summary>
    public byte Encode()
    {
        var pf = PollFinal ? 0x10 : 0;
        return FrameType switch
        {
            // I-frame: N(R) | P/F | N(S) | 0
            HdlcFrameType.Information => (byte)((ReceiveSequence << 5) | pf | (SendSequence << 1)),
            // RR: N(R) | P/F | 0001
            HdlcFrameType.ReceiveReady => (byte)((ReceiveSequence << 5) | pf | 0x01),
            // RNR: N(R) | P/F | 0101
            HdlcFrameType.ReceiveNotReady => (byte)((ReceiveSequence << 5) | pf | 0x05),
            // SNRM: 100 P/F 0011
            HdlcFrameType.Snrm => (byte)(0x83 | pf),
            // DISC: 010 P/F 0011
            HdlcFrameType.Disc => (byte)(0x43 | pf),
            // UA: 011 P/F 0011
            HdlcFrameType.Ua => (byte)(0x63 | pf),
            // DM: 000 P/F 1111
            HdlcFrameType.Dm => (byte)(0x0F | pf),
            // FRMR: 100 P/F 0111
            HdlcFrameType.FrameReject => (byte)(0x87 | pf),
            // UI: 000 P/F 0011
            HdlcFrameType.UnnumberedInformation => (byte)(0x03 | pf),
            _ => 0
        };
    }

    /// <summary>Decodes a control byte.</summary>
    public static HdlcControl Decode(byte value)
    {
        var pf = (value & 0x10) != 0;
        // I-frame: bit 0 = 0
        if ((value & 0x01) == 0)
        {
            var ns = (byte)((value >> 1) & 0x07);
            var nr = (byte)((value >> 5) & 0x07);
            return new HdlcControl(HdlcFrameType.Information, pf, ns, nr);
        }

        // S-frame: bits 1:0 = 01
        if ((value & 0x02) == 0)
        {
            var nr = (byte)((value >> 5) & 0x07);
            HdlcFrameType sType = (value & 0x0C) switch
            {
                0x00 => HdlcFrameType.ReceiveReady,
                0x04 => HdlcFrameType.ReceiveNotReady,
                _ => HdlcFrameType.ReceiveReady
            };
            return new HdlcControl(sType, pf, ReceiveSequence: nr);
        }

        // U-frame
        var masked = value & 0xEF; // mask out P/F
        HdlcFrameType frameType = masked switch
        {
            0x83 => HdlcFrameType.Snrm,
            0x43 => HdlcFrameType.Disc,
            0x63 => HdlcFrameType.Ua,
            0x0F => HdlcFrameType.Dm,
            0x87 => HdlcFrameType.FrameReject,
            0x03 => HdlcFrameType.UnnumberedInformation,
            _ => HdlcFrameType.UnnumberedInformation
        };
        return new HdlcControl(frameType, pf);
    }
#endregion
}
Was this page helpful?