DPA .NET Class

ide_screenIf you worked for a real application with IQRF modules with DPA, you’ve probably reached to the conclusion that for communication with PC is very convenient to use UART. Me too. I like UART for his simple handling and easy accessibility, unlike SPI (just PC has no native SPI port 🙂 ). This post describes simple classes for DPA ↔ HDLC conversion written in C#.

What you need:

IQRF_DPA_Handler.cs consist three main parts:

  • class DPA_RX (this class handles RX events and decodes HDLC protocol to DPA params).
  • class DPA_TX (this class builds HDLC protocol from DPA params).
  • class DPA_UTILS (crc, etc…)

Class DPA_RX

Members:

public UInt16 NADR;             // Node address
public byte PNUM;               // Peripheral number
public byte PCMD;               // Peripheral command
public UInt16 HWPID;            // Hardware profile ID
public byte[] Data;             // DPA Data
public byte DLEN;               // DPA Data length
public byte ErrN;               // Error number
public byte DpaValue;
 
private bool HDLC_CE;           // control escape flag
private byte CRC;               // HDLC CRC
public ArrayList Buffer;        // Input buffer
 
public const byte HDLC_FLAG_SEQUENCE = 0x7E;    // Flag sequence constant
public const byte HDLC_CONTROL_ESCAPE = 0x7D;   // Control escape constant
public const byte HDLC_ESCAPE_BIT = 0x20;       // Escape bit constant
public const byte HDLC_MIN_LEN = 0x0B;          // Minimum length of response
public const byte HDLC_MAX_LEN = 0x80;          // Maximum length of buffer

Methods:

public DPA_RX()     // Constructor
public DPA_RX_STATE DPA_RX_Parse(byte character) // Received data parser

How to use it:

Create instance of DPA_RX object as global object:

DPA_RX DPA_RX_inst1 = new DPA_RX();

Inside SerialPort DataReceived event call DPA_RX_inst1.DPA_RX_Parse(character), where character is data byte received by SerialPort. Test result for DPA_RX_STATE.DPA_RX_OK. Example:

private void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    try
    {                
        byte[] bytes;
        SerialPort serialPort = (SerialPort)sender;
 
        // try to read all available bytes from serial port
        lock (serialPort)
        {
            bytes = new byte[serialPort.BytesToRead];
            serialPort.Read(bytes, 0, bytes.Length);
        }
 
        // try to parse message
        for (int index = 0; index < bytes.Length; index++)
        {
            byte oneByte = bytes[index];
            if (DPA_RX_inst1.DPA_RX_Parse(oneByte) == DPA_RX.DPA_RX_STATE.DPA_RX_OK)
                this.BeginInvoke(new EventHandler(ShowState));
        }
    } // Some problem with serial port or parsing
    catch (Exception ex)
    {
        MessageBox.Show("Ups, some problems with message parsing: \n"+ex.Message);
    }
}

Then you can have inside ShowState something like:

private void ShowState(object s, EventArgs e)
{
    // Fill labels against received parameters
    lblNADR.Text = "NADR: " + DPA_RX_inst1.NADR.ToString("X4");
    lblPNUM.Text = "PNUM: " + DPA_RX_inst1.PNUM.ToString("X2");
    lblPCMD.Text = "PCMD: " + DPA_RX_inst1.PCMD.ToString("X2");
    lblHWPID.Text = "HWPID: " + DPA_RX_inst1.HWPID.ToString("X4");
    lblERRN.Text = "ErrN: " + DPA_RX_inst1.ErrN.ToString("X2");
    lblDPAVAL.Text = "DpaValue: " + DPA_RX_inst1.DpaValue.ToString("X2");
}

which show you DPA Response data on relevant labels.

Class DPA_TX

Members:

public UInt16 NADR;             // Node address
public byte PNUM;               // Peripheral number
public byte PCMD;               // Peripheral command
public UInt16 HWPID;            // Hardware profile ID
public byte[] Data;             // DPA Data
public byte DLEN;               // DPA Data length
 
private byte CRC;               // HDLC CRC
public byte[] Buffer;           // Output buffer

Methods:

public DPA_TX()  // Constructor
public void BuildHDLC() // Build HDLC byte array form DPA Params

 How to use it:

Create instance of DPA_TX object where you need to send HDLC data:

DPA_TX DPA_TX_inst1 = new DPA_TX();

Then, set DPA Params, call BuilHDLC method, and send byte array Buffer via UART. Full example for Button click event:

private void button1_Click(object sender, EventArgs e)
{
    // Create new instance of DPA_TX
    DPA_TX DPA_TX_inst1 = new DPA_TX();
 
    DPA_TX_inst1.NADR = 0x0000;     // Node address 2
    DPA_TX_inst1.PNUM = 0x06;       // LEDR
    DPA_TX_inst1.PCMD = 0x03;       // Pulse LED
    DPA_TX_inst1.HWPID = 0xFFFF;    // All HWPIDs
    DPA_TX_inst1.DLEN = 0;          // No data
 
    DPA_TX_inst1.BuildHDLC();       // Fill output buffer           
 
    // Try to send buffer content to IQRF
    try
    {
        // send buffer content to IQRF
        sp1.Write(DPA_TX_inst1.Buffer, 0, DPA_TX_inst1.Buffer.Length);                
    }
    catch
    {
    }
}

Of course, you must have opened serial port.

class DPA_UTILS now consist only CalcCRC(ArrayList buffer) method. This method is internally used for CRC calculation and checking.

See full source code of .NET DPA class for details.

Enjoy.

Download Attachments

Leave a Reply

Your email address will not be published. Required fields are marked *