Rev 172 | Blame | Compare with Previous | Last modification | View Log | RSS feed
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace nitdcscore {
public class DcsBios {
private UdpClient _udpReceiveClient = null;
private UdpClient _udpSendClient = null;
private Thread _listeningThread;
private String _receiveFromIP = "239.255.50.10";
private String _sendToIP = "127.0.0.1";
private int _receivePort = 5010;
private int _sendPort = 7778;
private IPEndPoint _ipEndPointReceiver = null;
private IPEndPoint _ipEndPointSender = null;
private readonly DCSProtocolParser _parser;
public DcsBios() {
_parser = new DCSProtocolParser();
}
public void InitUDP() {
try {
_ipEndPointReceiver = new IPEndPoint(IPAddress.Any, _receivePort);
_ipEndPointSender = new IPEndPoint(IPAddress.Parse(_sendToIP), _sendPort);
_udpReceiveClient = new UdpClient();
_udpReceiveClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_udpReceiveClient.Client.Bind(_ipEndPointReceiver);
_udpReceiveClient.JoinMulticastGroup(IPAddress.Parse(_receiveFromIP));
_udpSendClient = new UdpClient();
_udpSendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_udpSendClient.EnableBroadcast = true;
if (_listeningThread != null) {
_listeningThread.Abort();
}
_listeningThread = new Thread(ReceiveData);
_listeningThread.Start();
} catch (Exception e) {
if (_udpReceiveClient != null && _udpReceiveClient.Client.Connected) {
_udpReceiveClient.Close();
_udpReceiveClient = null;
}
if (_udpSendClient != null && _udpSendClient.Client.Connected) {
_udpSendClient.Close();
_udpSendClient = null;
}
Console.WriteLine(e.Message);
}
}
public void ReceiveData() {
try {
while (true) {
var byteData = _udpReceiveClient.Receive(ref _ipEndPointReceiver);
for (int i=0; i<byteData.Length; i++) {
_parser.ProcessByte(byteData[i]);
}
}
} catch (Exception e) {
Console.WriteLine(e.Message);
}
}
public int SendData(string data) {
var rslt = 0;
try {
var unicodeBytes = Encoding.Unicode.GetBytes(data);
var asciiBytes = new List<byte>(data.Length);
asciiBytes.AddRange(Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes));
rslt = _udpSendClient.Send(asciiBytes.ToArray(), asciiBytes.ToArray().Length, _ipEndPointSender);
} catch (Exception e) {
Console.WriteLine(e.Message);
}
return rslt;
}
public void Shutdown() {
try {
if (_listeningThread != null) {
_listeningThread.Abort();
_listeningThread = null;
}
_udpReceiveClient.Close();
_udpSendClient.Close();
} catch (Exception e) {
Console.WriteLine(e.Message);
}
}
}
public enum DCSBiosStateEnum {
WAIT_FOR_SYNC = 0,
ADDRESS_LOW = 1,
ADDRESS_HIGH = 2,
COUNT_LOW = 3,
COUNT_HIGH = 4,
DATA_LOW = 5,
DATA_HIGH = 6,
}
internal class DCSProtocolParser {
private DCSBiosStateEnum _state;
private uint _address;
private uint _count;
private uint _data;
private byte _syncByteCount;
internal DCSProtocolParser() {
_state = DCSBiosStateEnum.WAIT_FOR_SYNC;
_syncByteCount = 0;
}
internal void ProcessByte(byte b) {
switch (_state) {
case DCSBiosStateEnum.WAIT_FOR_SYNC:
break;
case DCSBiosStateEnum.ADDRESS_LOW:
_address = b;
_state = DCSBiosStateEnum.ADDRESS_HIGH;
break;
case DCSBiosStateEnum.ADDRESS_HIGH:
_address = (uint) (b << 8) | _address;
_state = _address != 0x5555 ? DCSBiosStateEnum.COUNT_LOW : DCSBiosStateEnum.WAIT_FOR_SYNC;
break;
case DCSBiosStateEnum.COUNT_LOW:
_count = b;
_state = DCSBiosStateEnum.COUNT_HIGH;
break;
case DCSBiosStateEnum.COUNT_HIGH:
_count = (uint)(b << 8) | _count;
_state = DCSBiosStateEnum.DATA_LOW;
break;
case DCSBiosStateEnum.DATA_LOW:
_data = b;
_count--;
_state = DCSBiosStateEnum.DATA_HIGH;
break;
case DCSBiosStateEnum.DATA_HIGH:
_data = (uint)(b << 8) | _data;
_count--;
UInt16 data;
if (Globals.BiosOutput.TryGetValue((UInt16)_address, out data)) {
Globals.BiosOutput[(UInt16)_address] = (UInt16)_data;
}
_address += 2;
if (_count == 0)
_state = DCSBiosStateEnum.ADDRESS_LOW;
else
_state = DCSBiosStateEnum.DATA_LOW;
break;
}
if (b == 0x55)
_syncByteCount++;
else
_syncByteCount = 0;
if (_syncByteCount == 4) {
_state = DCSBiosStateEnum.ADDRESS_LOW;
_syncByteCount = 0;
}
}
}
}