Jens Kühner

Geek stuff about the .NET, Compact and Micro Framework.

September 2007 - Posts

Fun with Emulator-COM-Ports - Part II

In my last post I described how you can route data between a .NET Micro Framework Emulator and Sockets to debug a .NET Micro Framework App with Hyper-Terminal. It is possible with the extensible emulator to route data to all kind of streams!

No you will learn how to let an emulated Microsoft .NET Micro Framework application communicate with physical COM-Ports on your host PC (also virtual Ports).Therefore I wrote the emulator component ComPortToPhysicalPcPort.This allows you to debug your app with feeding and
verifying serial test data with the socket component on Hyper-Teminal first.And then by just exchanging the socket component with the physical
component (only a few XML lines) allows you to connect a real device to a PC COM Port and debug without having a MF development board but your real serial device. At last if you have your real hardware platform and real serial device connect to it your code should run like a charm.

The emulator component:
using System;

using System.IO.Ports;

using Microsoft.SPOT.Emulator.Com;

 

namespace Kuehner.SPOT.Emulator

{

    public class ComPortToPhysicalPcSerialPort : ComPortToStream

    {

        private SerialPort serialPort;

        private string physicalPortName = "COM1";

        private int baudrate = 9600;

        private int readTimeout = 1000;

        private Handshake handshake = Handshake.None;

 

        protected override void InitializeProtected()

        {

            base.InitializeProtected();

            if (this.Stream == null)

            {

                this.serialPort = new SerialPort(this.physicalPortName, this.baudrate);

                this.serialPort.ReadTimeout = this.readTimeout;

                this.serialPort.Handshake = this.handshake;

                this.serialPort.Open();

                this.Stream = this.serialPort.BaseStream;

            }

        }

 

        protected override void UninitializeProtected()

        {

            base.UninitializeProtected();

            if (this.Stream != null)

            {

                this.serialPort.Close(); //also closes the underlying stream

                this.serialPort = null;

                this.Stream = null;

            }

        }

 

        #region properties

        public string PhysicalPortName

        {

            get { return this.physicalPortName; }

            set { this.physicalPortName = value; }

        }

 

        public int Baudrate

        {

            get { return this.baudrate; }

            set { this.baudrate = value; }

        }

 

        public int ReadTimeout

        {

            get { return this.readTimeout; }

            set { this.readTimeout = value; }

        }

 

        public Handshake Handshake

        {

            get { return this.handshake; }

            set { this.handshake = value; }

        }

        #endregion

    }

}

 

The emulator configuration:

<?xml version="1.0" encoding="utf-8" ?>

<Emulator>

  <Types>

    <PcCom>Kuehner.SPOT.Emulator.ComPortToPhysicalPcSerialPort, ComPortEmulatorComponents</PcCom>

  </Types>

 

  <EmulatorComponents>

    <PcCom>

      <ComPortHandle>Usart1</ComPortHandle>

      <!--optional-->

      <PhysicalPortName>COM1</PhysicalPortName>

      <Baudrate>9600</Baudrate>

      <ReadTimeout>1000</ReadTimeout>

    </PcCom>

  </EmulatorComponents>

 

</Emulator>

Connecting Emulator COM Ports to Hyper-Terminal

You might have a .NET Micro Framework Application that uses serial COM Ports and is running on an MF emulator. How nice would it be to see the serial output on Hyper-Terminal or provide input data via Hyper-Terminal. Yes that's possible, you do not have to leave the managed world to do that!

It is really amazing how extensible the .NET Micro Framework Extensible Emulator is. Luckily Hyper-Terminal is able to make connections via TCP/IP sockets. With sockets we can loop back data on one PC without needing virtual COM port drivers. Therefore I wrote a custom Serial Port Emulator Component called ComPortToServerSocket to bring the serial data to sockets. The component is placed in library assembly (dll) and can be used on any emulator. You just have to place the shared assembly in the same directory as your emulator and add the following lines to your emulator configuration.

<?xml version="1.0" encoding="utf-8" ?>

<Emulator>

  <Types>

    <SocketCom>Kuehner.SPOT.Emulator.ComPortToServerSocket, ComPortToSocketComponent</SocketCom>

  </Types>

 

  <EmulatorComponents>

    <SocketCom>

      <ComPortHandle>Usart1</ComPortHandle>

      <!--optional-->

      <ClientIpAddress>127.0.0.1</ClientIpAddress>

      <IpPort>23</IpPort>

      <ShowWaitMessage>true</ShowWaitMessage>

    </SocketCom>

  </EmulatorComponents>

 

</Emulator>

When the emulated MF app opens the COM-Port, a message box occurs and you need to make a TCP/IP connection on 12.0.0.1 at the specified port with Hyper-Terminal, press OK and then you go.

The source code for the component is here:

using System;

using Microsoft.SPOT.Emulator.Com;

using System.Net.Sockets;

using System.Net;

using System.Windows.Forms;

 

namespace Kuehner.SPOT.Emulator

{

    public class ComPortToServerSocket : ComPortToStream

    {

        private Socket serverSocket;

        private IPAddress clientIpAddress = IPAddress.Loopback;

        private int ipPort = 23;

        private bool showWaitMessage = true;

       

        protected override void InitializeProtected()

        {

            base.InitializeProtected();

            if (this.Stream == null)

            {

                this.serverSocket = new Socket(AddressFamily.InterNetwork,

                                               SocketType.Stream,

                                               ProtocolType.Tcp);

                this.serverSocket.Bind(new IPEndPoint(this.clientIpAddress, this.ipPort));

                this.serverSocket.Listen(1);

                string message = string.Format(null,

                 "The component {0} is waiting for a client to connect at port {1} for COM{2}.",

                                               this.ComponentId,

                                               this.ipPort,

                                               this.ComPortHandle.PortNumber);

                System.Diagnostics.Trace.WriteLine(message);

                if (this.showWaitMessage)

                {

                    MessageBox.Show(message,

                                    "ComPortToSocketServer Component waiting at Port " + this.ipPort,

                                    MessageBoxButtons.OK);

                }

                //the emulator will block until a client eg. HyperTerm connects

                Socket clientSocket = this.serverSocket.Accept();

                this.Stream = new NetworkStream(clientSocket, true);

            }

        }

 

        protected override void UninitializeProtected()

        {

            base.UninitializeProtected();

            if (this.Stream != null)

            {

                this.serverSocket.Close();

                this.serverSocket = null;

                this.Stream = null;

            }

        }

 

        #region properties

        public IPAddress ClientIpAddress

        {

            get { return this.clientIpAddress; }

            set { this.clientIpAddress = value; }

        }

 

        public int IpPort

        {

            get { return this.ipPort; }

            set { this.ipPort = value; }

        }

 

        public bool ShowWaitMessage

        {

            get { return this.showWaitMessage; }

            set { this.showWaitMessage = value; }

        }

        #endregion

    }

}