Subversion Repositories group.electronics

Rev

Rev 171 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
158 pfowler 1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
using System.IO;
7
using System.Net;
8
using System.Net.Sockets;
9
using System.Threading;
10
 
11
namespace nitdcscore {
12
    public class DcsBios {
13
        private UdpClient _udpReceiveClient = null;
14
        private UdpClient _udpSendClient = null;
15
        private Thread _listeningThread;
16
 
17
        private String _receiveFromIP = "239.255.50.10";
18
        private String _sendToIP = "127.0.0.1";
19
        private int _receivePort = 5010;
20
        private int _sendPort = 7778;
21
        private IPEndPoint _ipEndPointReceiver = null;
22
        private IPEndPoint _ipEndPointSender = null;
23
 
24
        private readonly DCSProtocolParser _parser;
25
 
26
        public DcsBios() {
27
            _parser = new DCSProtocolParser();
28
        }
29
 
30
 
31
        public void InitUDP() {
32
            try {
33
                _ipEndPointReceiver = new IPEndPoint(IPAddress.Any, _receivePort);
34
                _ipEndPointSender = new IPEndPoint(IPAddress.Parse(_sendToIP), _sendPort);
35
 
36
                _udpReceiveClient = new UdpClient();
37
                _udpReceiveClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
38
                _udpReceiveClient.Client.Bind(_ipEndPointReceiver);
39
                _udpReceiveClient.JoinMulticastGroup(IPAddress.Parse(_receiveFromIP));
40
 
41
                _udpSendClient = new UdpClient();
42
                _udpSendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
43
                _udpSendClient.EnableBroadcast = true;
44
 
45
                if (_listeningThread != null) {
46
                    _listeningThread.Abort();
47
                }
48
 
49
                _listeningThread = new Thread(ReceiveData);
50
                _listeningThread.Start();
51
            } catch (Exception e) {
52
                if (_udpReceiveClient != null && _udpReceiveClient.Client.Connected) {
53
                    _udpReceiveClient.Close();
54
                    _udpReceiveClient = null;
55
                }
56
                if (_udpSendClient != null && _udpSendClient.Client.Connected) {
57
                    _udpSendClient.Close();
58
                    _udpSendClient = null;
59
                }
60
                Console.WriteLine(e.Message);
61
            }
62
 
63
 
64
        }
65
 
66
        public void ReceiveData() {
67
            try {
68
                while (true) {
69
                    var byteData = _udpReceiveClient.Receive(ref _ipEndPointReceiver);
70
                    for (int i=0; i<byteData.Length; i++) {
71
                        _parser.ProcessByte(byteData[i]);
72
                    }
73
                }
74
            } catch (Exception e) {
75
                Console.WriteLine(e.Message);
76
            }
77
        }
78
 
79
        public int SendData(string data) {
80
            var rslt = 0;
81
            try {
82
                var unicodeBytes = Encoding.Unicode.GetBytes(data);
83
                var asciiBytes = new List<byte>(data.Length);
84
                asciiBytes.AddRange(Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes));
85
                rslt = _udpSendClient.Send(asciiBytes.ToArray(), asciiBytes.ToArray().Length, _ipEndPointSender);
86
            } catch (Exception e) {
87
                Console.WriteLine(e.Message);
88
            }
89
 
90
            return rslt;
91
        }
92
 
93
        public void Shutdown() {
94
            try {
95
                if (_listeningThread != null) {
96
                    _listeningThread.Abort();
97
                    _listeningThread = null;
98
                }
99
                _udpReceiveClient.Close();
100
                _udpSendClient.Close();
101
            } catch (Exception e) {
102
                Console.WriteLine(e.Message);
103
            }
104
        }
105
 
106
    }
107
 
108
    public enum DCSBiosStateEnum {
109
        WAIT_FOR_SYNC = 0,
110
        ADDRESS_LOW = 1,
111
        ADDRESS_HIGH = 2,
112
        COUNT_LOW = 3,
113
        COUNT_HIGH = 4,
114
        DATA_LOW = 5,
115
        DATA_HIGH = 6,
116
    }
117
 
118
 
119
 
120
    internal class DCSProtocolParser {
121
        private DCSBiosStateEnum _state;
122
        private uint _address;
123
        private uint _count;
124
        private uint _data;
125
        private byte _syncByteCount;
126
 
127
        internal DCSProtocolParser() {
128
            _state = DCSBiosStateEnum.WAIT_FOR_SYNC;
129
            _syncByteCount = 0;
130
        }
131
 
132
        internal void ProcessByte(byte b) {
133
            switch (_state) {
134
                case DCSBiosStateEnum.WAIT_FOR_SYNC:
135
                    break;
136
                case DCSBiosStateEnum.ADDRESS_LOW:
137
                    _address = b;
138
                    _state = DCSBiosStateEnum.ADDRESS_HIGH;
139
                    break;
140
                case DCSBiosStateEnum.ADDRESS_HIGH:
141
                    _address = (uint) (b << 8) | _address;
142
                    _state = _address != 0x5555 ? DCSBiosStateEnum.COUNT_LOW : DCSBiosStateEnum.WAIT_FOR_SYNC;
143
                    break;
144
                case DCSBiosStateEnum.COUNT_LOW:
145
                    _count = b;
146
                    _state = DCSBiosStateEnum.COUNT_HIGH;
147
                    break;
148
                case DCSBiosStateEnum.COUNT_HIGH:
149
                    _count = (uint)(b << 8) | _count;
150
                    _state = DCSBiosStateEnum.DATA_LOW;
151
                    break;
152
                case DCSBiosStateEnum.DATA_LOW:
153
                    _data = b;
154
                    _count--;
155
                    _state = DCSBiosStateEnum.DATA_HIGH;
156
                    break;
157
                case DCSBiosStateEnum.DATA_HIGH:
158
                    _data = (uint)(b << 8) | _data;
159
                    _count--;
171 pfowler 160
 
161
                    //if (_address == 0x10fa) {
162
                    //    uint aapCdupwrValue = (_data & 0x4000) >> 14;
163
                    //    Console.WriteLine(_address.ToString("X") + ":" + aapCdupwrValue);
164
                    //}
172 pfowler 165
                    UInt16 data;
166
                    if (Globals.BiosOutput.TryGetValue((UInt16)_address, out data)) {
167
                        Globals.BiosOutput[(UInt16)_address] = data;
158 pfowler 168
                    }
169
 
170
                    _address += 2;
171
                    if (_count == 0)
172
                        _state = DCSBiosStateEnum.ADDRESS_LOW;
173
                    else
174
                        _state = DCSBiosStateEnum.DATA_LOW;
175
                    break;
176
            }
177
            if (b == 0x55)
178
                _syncByteCount++;
179
            else
180
                _syncByteCount = 0;
181
            if (_syncByteCount == 4) {
182
                _state = DCSBiosStateEnum.ADDRESS_LOW;
183
                _syncByteCount = 0;
184
            }
185
        }
186
    }
187
 
188
 
189
}