00001 using System;
00002 using System.Collections.Generic;
00003 using System.ComponentModel;
00004 using System.Data;
00005 using System.Drawing;
00006 using System.Linq;
00007 using System.Text;
00008 using System.Windows.Forms;
00009 using System.IO;
00010 using System.IO.Ports;
00011 using System.Threading;
00012
00013 namespace RS232Port {
00014 public partial class RS232MainForm : Form {
00015
00016
00017
00018
00019 string[] _portNames;
00020 string _serialData;
00021 byte[] _serialBytes;
00022
00023 public byte[] SerialBytes {
00024 get { return _serialBytes; }
00025 set { _serialBytes = value; }
00026 }
00027 private bool[] _ctsDsrStates = new bool[2];
00028
00029 public delegate void receiveDataEventHandler();
00030 public delegate void pinChangedEventHandler();
00031 public delegate void updateStatusEventHandler();
00032 public delegate void updateErrorEventHandler(Exception error);
00033 public event updateErrorEventHandler updateErrorEvent;
00034
00035
00036
00037
00038 public event receiveDataEventHandler receiveDataEvent;
00039 public event pinChangedEventHandler ctsChangedEvent;
00040 public event pinChangedEventHandler dsrChangedEvent;
00041 public event updateStatusEventHandler setSilentModeEvent;
00042
00043 Thread receiveDataThread;
00044 Thread ctsStateChangedThread;
00045 Thread dsrStateChangedThread;
00046
00047 public enum debugTerminalMode {
00048 silent,
00049 quiet,
00050 verbose,
00051 };
00052
00053 bool _silent = true;
00054 public bool Silent {
00055 get { return _silent; }
00056 set {
00057 _silent = value;
00058 if (_silent) {
00059 receiveDataEvent -= onReceiveData;
00060 ctsChangedEvent -= onCtsChanged;
00061 dsrChangedEvent -= onDsrChanged;
00062 } else {
00063 receiveDataEvent += onReceiveData;
00064 ctsChangedEvent += onCtsChanged;
00065 dsrChangedEvent += onDsrChanged;
00066 }
00067 if (setSilentModeEvent != null)
00068 setSilentModeEvent.Invoke();
00069 }
00070 }
00071
00072 private debugTerminalMode _debugMode;
00073
00074 public debugTerminalMode DebugMode {
00075 set {
00076 _debugMode = value;
00077 }
00078 get {
00079 return _debugMode;
00080 }
00081 }
00082
00083 string _status;
00084 public string Status {
00085 get {return _status;}
00086 }
00087
00088 public SerialPort Port {
00089 get {
00090 return _port;
00091 }
00092 }
00093
00094 public string[] PortNames {
00095 get {
00096 return _portNames;
00097 }
00098 }
00099
00100 public string SerialData {
00101 get {
00102 return _serialData;
00103 }
00104 }
00105
00106 bool _ctsState = false;
00107 public bool CtsState {
00108 get {return _ctsState;}
00109 }
00110
00111 bool _dsrState = false;
00112 public bool DsrState {
00113 get {return _dsrState;}
00114 }
00115
00116 int _recieveDelayMs = 0;
00117 public int RecieveDelayMs {
00118 get { return _recieveDelayMs; }
00119 set { _recieveDelayMs = value; }
00120 }
00121
00122 public RS232MainForm() {
00123 InitializeComponent();
00124 comPortSelectionComboBox.Items.AddRange(SerialPort.GetPortNames());
00125 _portNames = new string[comPortSelectionComboBox.Items.Count];
00126 _portNames = SerialPort.GetPortNames();
00127 updateStatusMessage("Open a serial port from the drop down menu.");
00128 _debugMode = debugTerminalMode.silent;
00129
00130 }
00131
00132 private void comPortSelectionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
00133 _port.PortName = comPortSelectionComboBox.SelectedItem.ToString();
00134 openPortButton.Enabled = true;
00135 openPortButton.Text = "Open Port";
00136 updateButtons();
00137 }
00138
00139 public void setPortName(string name) {
00140
00141 _port.PortName = name;
00142 }
00143
00144 private void openPortButton_Click(object sender, EventArgs e) {
00145 if (!_port.IsOpen) {
00146 openPortButton.BackColor = Color.Lime;
00147 openPortButton.Text = "Close Port";
00148 updateStatusMessage(initializeComPort());
00149 } else {
00150 openPortButton.BackColor = SystemColors.Control;
00151 openPortButton.Text = "Open Port";
00152 updateStatusMessage(closePort());
00153 }
00154 updateButtons();
00155 }
00156
00157 public string initializeComPort() {
00158 string returnMessage = "";
00159 try {
00160 openPort();
00161 returnMessage = "opened " + _port.PortName;
00162 } catch (System.UnauthorizedAccessException e) {
00163 if (updateErrorEvent != null)
00164 updateErrorEvent.Invoke(e);
00165 returnMessage = "opening " + _port.PortName
00166 + " failed, unauthorized access!";
00167 } catch (System.InvalidOperationException e) {
00168 if (updateErrorEvent != null)
00169 updateErrorEvent.Invoke(e);
00170 returnMessage = _port.PortName
00171 + " is allready open, invalid operation!";
00172 } catch (System.IO.IOException e) {
00173 if (updateErrorEvent != null)
00174 updateErrorEvent.Invoke(e);
00175 returnMessage = _port.PortName
00176 + " does not exist!";
00177 }
00178 return returnMessage;
00179 }
00180
00181 private void openPort() {
00182 if (!_port.IsOpen) {
00183 _port.Open();
00184 updatePortSettings();
00185 toggleControlls();
00186 }
00187 }
00188
00189 public string closePort() {
00190 string returnMessage = "";
00191 if (_port.IsOpen) {
00192 _port.DiscardOutBuffer();
00193 _port.DiscardInBuffer();
00194 _port.Close();
00195 toggleControlls();
00196 returnMessage = "closed " + _port.PortName;
00197 } else returnMessage = _port.PortName + " is allready closed";
00198 return returnMessage;
00199 }
00200
00201 private void toggleControlls() {
00202 comPortSelectionComboBox.Enabled = !_port.IsOpen;
00203 bitsPerSecondComboBox.Enabled = !_port.IsOpen;
00204 dataBitsComboBox.Enabled = !_port.IsOpen;
00205 parityComboBox.Enabled = !_port.IsOpen;
00206 stopBitsComboBox.Enabled = !_port.IsOpen;
00207 flowControlComboBox.Enabled = !_port.IsOpen;
00208 }
00209
00210 private void updateButtons() {
00211 if (_port.IsOpen) {
00212 if (_port.CtsHolding)
00213 ctsHoldingButton.BackColor = Color.Lime;
00214 else
00215 ctsHoldingButton.BackColor = SystemColors.Control;
00216 if (_port.DsrHolding)
00217 dsrHoldingButton.BackColor = Color.Lime;
00218 else
00219 dsrHoldingButton.BackColor = SystemColors.Control;
00220 } else {
00221 ctsHoldingButton.BackColor = SystemColors.Control;
00222 dsrHoldingButton.BackColor = SystemColors.Control;
00223 }
00224 dtrEnableButton.Enabled = _port.IsOpen;
00225 if (_port.Handshake != Handshake.RequestToSendXOnXOff
00226 && _port.Handshake != Handshake.RequestToSend)
00227 rtsEnableButton.Enabled = _port.IsOpen;
00228 }
00229
00230 private void dtrEnableButton_Click(object sender, EventArgs e) {
00231
00232 _port.DtrEnable = !_port.DtrEnable;
00233 updateStatusMessage("DTR Enabled: " + _port.DtrEnable.ToString());
00234 if (_port.DtrEnable)
00235 dtrEnableButton.BackColor = Color.Lime;
00236 else
00237 dtrEnableButton.BackColor = SystemColors.Control;
00238 }
00239
00240 private void rtsEnableButton_Click(object sender, EventArgs e) {
00241
00242 _port.RtsEnable = !_port.RtsEnable;
00243 updateStatusMessage("RTS Enabled: " + _port.RtsEnable.ToString());
00244 if (_port.RtsEnable)
00245 rtsEnableButton.BackColor = Color.Lime;
00246 else
00247 rtsEnableButton.BackColor = SystemColors.Control;
00248 }
00249
00250 private void _port_PinChanged(object sender, SerialPinChangedEventArgs e) {
00251
00252 if (_ctsState != _port.CtsHolding) {
00253 _ctsState = _port.CtsHolding;
00254
00255 if (_silent && ctsChangedEvent != null)
00256 ctsChangedEvent.Invoke();
00257 else if (ctsChangedEvent != null) {
00258 ctsStateChangedThread = new Thread(new ThreadStart(onCtsChanged));
00259
00260 ctsStateChangedThread.Start();
00261 }
00262 }
00263 if (_dsrState != _port.DsrHolding) {
00264 _dsrState = _port.DsrHolding;
00265 if (_silent && dsrChangedEvent != null)
00266 dsrChangedEvent.Invoke();
00267 else if(dsrChangedEvent != null) {
00268 dsrStateChangedThread = new Thread(new ThreadStart(onDsrChanged));
00269
00270 dsrStateChangedThread.Start();
00271 }
00272 }
00273
00274
00275 }
00276
00277
00278 private void onCtsChanged() {
00279 if (debugTextBox.InvokeRequired)
00280 this.Invoke(ctsChangedEvent);
00281 else {
00282 if (DebugMode == debugTerminalMode.verbose)
00283 updateDebugTextBox("CTS changed to: " + _port.CtsHolding.ToString());
00284 }
00285 }
00286
00287
00288 private void onDsrChanged() {
00289 if (debugTextBox.InvokeRequired)
00290 this.Invoke(dsrChangedEvent);
00291 else {
00292 if (DebugMode == debugTerminalMode.verbose)
00293 updateDebugTextBox("DSR changed to: " + _port.DsrHolding.ToString());
00294 }
00295 }
00296
00297 private void _port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
00298
00299 if (_recieveDelayMs > 0)
00300 Thread.Sleep(_recieveDelayMs);
00301 if (_port.IsOpen) {
00302 try {
00303 _serialBytes = new byte[_port.BytesToRead];
00304 _port.Read(_serialBytes, 0, _port.BytesToRead);
00305 _serialData = System.Text.ASCIIEncoding.ASCII.GetString(_serialBytes);
00306 } catch(Exception ex) {
00307
00308 _port.DiscardInBuffer();
00309 }
00310
00311 if (_silent && receiveDataEvent != null)
00312 receiveDataEvent.Invoke();
00313 else if (receiveDataEvent != null) {
00314 receiveDataThread = new Thread(new ThreadStart(onReceiveData));
00315 receiveDataThread.Start();
00316 }
00317 }
00318 }
00319
00320
00321 private void onReceiveData() {
00322 if (debugTextBox.InvokeRequired) {
00323 this.Invoke(receiveDataEvent);
00324 } else {
00325 if (DebugMode != debugTerminalMode.silent) {
00326 rxToolStripStatusLabel.BackColor = Color.Lime;
00327 resetRXImageTimer.Enabled = true;
00328 updateDebugTextBox(_serialData);
00329 if (DebugMode == debugTerminalMode.verbose)
00330 updateDebugTextBox("Received: " + _serialData);
00331 }
00332 }
00333 }
00334
00335 private void silentRadioButton_CheckedChanged(object sender, EventArgs e) {
00336 foreach (Control c in debugTerminalModeGroupBox.Controls) {
00337 if (c is RadioButton) {
00338 if (((RadioButton)c).Checked) {
00339 switch (((RadioButton)c).Text) {
00340 case "Silent":
00341 _debugMode = debugTerminalMode.silent;
00342 silentCheckBox.Checked = true;
00343 break;
00344 case "Quiet":
00345 _debugMode = debugTerminalMode.quiet;
00346 silentCheckBox.Checked = false;
00347 break;
00348 case "Verbose":
00349 _debugMode = debugTerminalMode.verbose;
00350 silentCheckBox.Checked = false;
00351 break;
00352 default:
00353 break;
00354 }
00355 }
00356 }
00357 }
00358 updateStatusMessage("Terminal mode set to: " + _debugMode.ToString());
00359 }
00360
00361 private void updateDebugTextBox(string message) {
00362 if(debugTextBox.Text.Length > 500000)
00363 debugTextBox.Clear();
00364 debugTextBox.AppendText(message);
00365 }
00366
00367 public void clearDebugTextBox() {
00368 debugTextBox.Clear();
00369 updateStatusMessage("Cleared debug text box");
00370 }
00371
00372 public void updateStatusMessage(string update) {
00373 _status = update;
00374 toolStripStatusLabel.Text = update;
00375 if (_debugMode == debugTerminalMode.verbose)
00376 updateDebugTextBox(update);
00377 }
00378
00379 public void updatePortSettings() {
00380 for (int i = 0; i < comPortSelectionComboBox.Items.Count; i++) {
00381 if (comPortSelectionComboBox.Items[i].ToString() == _port.PortName)
00382 comPortSelectionComboBox.SelectedIndex = i;
00383 }
00384 for (int i = 0; i < bitsPerSecondComboBox.Items.Count; i++) {
00385 if (bitsPerSecondComboBox.Items[i].ToString() == _port.BaudRate.ToString())
00386 bitsPerSecondComboBox.SelectedIndex = i;
00387 }
00388 for (int i = 0; i < dataBitsComboBox.Items.Count; i++) {
00389 if (dataBitsComboBox.Items[i].ToString() == _port.DataBits.ToString())
00390 dataBitsComboBox.SelectedIndex = i;
00391 }
00392 for (int i = 0; i < parityComboBox.Items.Count; i++) {
00393 if (parityComboBox.Items[i].ToString() == _port.Parity.ToString())
00394 parityComboBox.SelectedIndex = i;
00395 }
00396 for (int i = 0; i < stopBitsComboBox.Items.Count; i++) {
00397 if (stopBitsComboBox.Items[i].ToString() == _port.StopBits.ToString())
00398 stopBitsComboBox.SelectedIndex = i;
00399 }
00400 for (int i = 0; i < flowControlComboBox.Items.Count; i++) {
00401 if (flowControlComboBox.Items[i].ToString() == _port.Handshake.ToString())
00402 flowControlComboBox.SelectedIndex = i;
00403 }
00404 }
00405
00406 private void bitsPerSecondComboBox_SelectedIndexChanged(object sender, EventArgs e) {
00407 _port.BaudRate = int.Parse(bitsPerSecondComboBox.SelectedItem.ToString());
00408 }
00409
00410 private void dataBitsComboBox_SelectedIndexChanged(object sender, EventArgs e) {
00411 _port.DataBits = int.Parse(dataBitsComboBox.SelectedItem.ToString());
00412 }
00413
00414 private void parityComboBox_SelectedIndexChanged(object sender, EventArgs e) {
00415 switch (parityComboBox.SelectedItem.ToString()) {
00416 case "Even":
00417 _port.Parity = Parity.Even;
00418 break;
00419 case "Mark":
00420 _port.Parity = Parity.Mark;
00421 break;
00422 case "None":
00423 _port.Parity = Parity.None;
00424 break;
00425 case "Odd":
00426 _port.Parity = Parity.Odd;
00427 break;
00428 case "Space":
00429 _port.Parity = Parity.Space;
00430 break;
00431 default:
00432 break;
00433 }
00434 }
00435
00436 private void stopBitsComboBox_SelectedIndexChanged(object sender, EventArgs e) {
00437 switch (stopBitsComboBox.SelectedItem.ToString()) {
00438 case "One":
00439 _port.StopBits = StopBits.One;
00440 break;
00441 case "OnePointFive":
00442 _port.StopBits = StopBits.OnePointFive;
00443 break;
00444 case "Two":
00445 _port.StopBits = StopBits.Two;
00446 break;
00447 default:
00448 break;
00449 }
00450 }
00451
00452 private void flowControlComboBox_SelectedIndexChanged(object sender, EventArgs e) {
00453 switch (flowControlComboBox.SelectedItem.ToString()) {
00454 case "None":
00455 _port.Handshake = Handshake.None;
00456 break;
00457 case "RequestToSend":
00458 _port.Handshake = Handshake.RequestToSend;
00459 break;
00460 case "RequestToSendXOnXOff":
00461 _port.Handshake = Handshake.RequestToSendXOnXOff;
00462 break;
00463 case "XOnXOff":
00464 _port.Handshake = Handshake.XOnXOff;
00465 break;
00466 default:
00467 break;
00468 }
00469 }
00470
00471 private void sendDataButton_Click(object sender, EventArgs e) {
00472 transmit(clipboardTextBox.Text);
00473 }
00474
00475 public void transmit(string data) {
00476 if (_port.IsOpen) {
00477 if (_debugMode != debugTerminalMode.silent) {
00478 txToolStripStatusLabel.BackColor = Color.Lime;
00479 if (_debugMode == debugTerminalMode.verbose)
00480 updateDebugTextBox("Sent: " + data);
00481 resetTXImageTimer.Enabled = true;
00482 }
00483 _port.Write(data);
00484 }
00485 }
00486
00487 private void resetTXImageTimer_Tick(object sender, EventArgs e) {
00488 txToolStripStatusLabel.BackColor = Color.Red;
00489 resetTXImageTimer.Enabled = false;
00490 }
00491
00492 private void resetRXImageTimer_Tick(object sender, EventArgs e) {
00493 rxToolStripStatusLabel.BackColor = Color.Red;
00494 resetRXImageTimer.Enabled = false;
00495 }
00496
00497 private void clearDebugTerminalButton_Click(object sender, EventArgs e) {
00498 debugTextBox.Clear();
00499 }
00500
00501 private void clipboardTextBox_KeyUp(object sender, KeyEventArgs e) {
00502 if(e.KeyCode == Keys.Enter)
00503 transmit(clipboardTextBox.Text);
00504 }
00505
00506 private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
00507 exitGracefully();
00508 }
00509
00510 public void exitGracefully() {
00511 if (_port.IsOpen) {
00512 _port.DiscardOutBuffer();
00513 _port.DiscardInBuffer();
00514 _port.Close();
00515 }
00516 Thread.Sleep(500);
00517 this.Dispose();
00518 }
00519
00520 private void RS232MainForm_FormClosing(object sender, FormClosingEventArgs e) {
00521 exitGracefully();
00522 }
00523
00524 private void hideToolStripMenuItem_Click(object sender, EventArgs e) {
00525 this.Hide();
00526 }
00527
00528 private void silentCheckBox_CheckedChanged(object sender, EventArgs e) {
00529 Silent = silentCheckBox.Checked;
00530 silentRadioButton.Checked = true;
00531 }
00532
00533 private void sendByteButton_Click(object sender, EventArgs e) {
00534 short sendInt = 0;
00535 short.TryParse(sendByteTextBox.Text, out sendInt);
00536 byte sendByte = (byte)sendInt;
00537 sendSerialCommand(commandComboBox.SelectedItem.ToString()[0], (byte)sendInt);
00538 }
00539
00540 byte[] _byteArray = {0, 58, 0, 59};
00541 Encoding _enc = Encoding.ASCII;
00542 public void sendSerialCommand(char headder, byte command) {
00543 _byteArray[0] = (byte)headder;
00544 _byteArray[2] = command;
00545 if (_port.IsOpen) {
00546 if (_debugMode != debugTerminalMode.silent) {
00547 txToolStripStatusLabel.BackColor = Color.Lime;
00548 if (_debugMode == debugTerminalMode.verbose)
00549 updateDebugTextBox("Sent: " + new string(_enc.GetChars(_byteArray)));
00550 resetTXImageTimer.Enabled = true;
00551 }
00552 _port.Write(_byteArray, 0, 4);
00553 }
00554 }
00555
00556 }
00557 }