COM Port Configuration
Relevant source files
The following files were used as context for generating this wiki page:The COM Port Configuration is a fundamental aspect of the Pulsar_DomeDriver, enabling communication between the ASCOM driver and the Pulsar dome controller hardware. Proper configuration involves selecting the correct serial port through the driver's settings interface, which is then used to establish a persistent and thread-safe communication channel.
This system is designed around several key components: a user interface for port selection, a configuration manager for persisting the setting, the main driver class for orchestrating the connection, and a specialized guard class to ensure reliable, synchronized access to the serial port during operations.
Architecture Overview
The COM port handling architecture involves a clear separation of concerns: UI, configuration, connection logic, and thread-safe communication.
The diagram below illustrates the relationships between the main classes involved in COM port configuration and communication.
Key Components
| Component | File | Description |
|---|---|---|
SettingsForm | UI/SettingsForm.cs | Provides the graphical user interface for selecting the COM port from a list of available system ports. |
ConfigManager | Config/ConfigManager.cs | Manages the persistence of the selected COM port name to the ASCOM driver profile in the Windows Registry. |
DomeDriver | Driver/Pulsar_DomeDriver.cs | The main driver class that initializes, connects, and disconnects the serial port based on the stored configuration. |
SerialPortGuard | Helper/SerialPortGuard.cs | A wrapper class that ensures thread-safe, synchronized access to the SerialPort object, preventing race conditions. |
SerialPort | System.IO.Ports | The .NET base class representing the serial port. |
Sources: UI/SettingsForm.cs, Config/ConfigManager.cs, Driver/Pulsar_DomeDriver.cs, Helper/SerialPortGuard.cs
Configuration Flow
The COM port is configured through the SettingsForm and persisted in the ASCOM profile.
1. UI Port Selection
When the SettingsForm is loaded, it populates a dropdown list (comboBoxSerialPort) with all serial ports currently available on the system. If a port is already configured but is not currently available, it is added to the list with an "(Unavailable)" suffix.
When the user clicks the "OK" button, the selected port name is saved to the ConfigManager.
Sources: UI/SettingsForm.cs:20-37, 91-92
The following flowchart shows the user interaction for configuring the COM port.
2. Configuration Persistence
The ConfigManager class provides a SerialPort property that acts as a getter and setter for the port name stored in the ASCOM profile. It uses the _profile.GetValue and _profile.WriteValue methods to interact with the registry.
// File: Config/ConfigManager.cs
public string SerialPort
{
get => _profile.GetValue(_driverId, "SerialPort", "") ?? serialPort;
set => _profile.WriteValue(_driverId, "SerialPort", value, "");
}
Sources: Config/ConfigManager.cs:91-95
Connection and Communication
Serial Port Initialization
When the DomeDriver is instantiated, it calls the InitializeSerialPort method. This method reads the saved port name from the ConfigManager and creates an instance of System.IO.Ports.SerialPort with hardcoded communication parameters.
| Parameter | Value |
|---|---|
BaudRate | 115200 |
Parity | None |
DataBits | 8 |
StopBits | One |
Handshake | None |
ReadTimeout | 2000 ms |
WriteTimeout | 2000 ms |
Sources: Driver/Pulsar_DomeDriver.cs:175-193
Connection Process
The connection is established in the ConnectController method. The process involves opening the port, wrapping it in a SerialPortGuard for thread safety, and then pinging the controller to ensure it is responsive.
The sequence diagram below details the steps taken to connect to the dome controller.
If the ping fails after two attempts, the port is closed, the guard is disposed, and the connection fails.
Sources: Driver/Pulsar_DomeDriver.cs:309-335
Thread-Safe Communication with SerialPortGuard
All serial communication is channeled through the SerialPortGuard class to prevent race conditions from multiple threads (e.g., the ASCOM client thread and the internal polling thread).
The SerialPortGuard uses a SemaphoreSlim(1, 1) to act as a mutex, ensuring that only one thread can execute a Send operation at any given time.
Key features of SerialPortGuard:
- Synchronization: Acquires a lock (
_gate.Wait()) before accessing the port and releases it in afinallyblock. - State Management: Invokes
_setBusyand_clearBusyactions to inform theDomeDriverthat a command is in progress. - Buffer Flushing: Clears the input and output buffers before writing a new command to prevent reading stale data.
- Command/Response Logic: Writes the command suffixed with
\r, then reads the response until a terminator (\ror\n) is seen or a 750ms timeout occurs.
// File: Helper/SerialPortGuard.cs
public string? Send(string command, bool expectResponse = true)
{
// ...
_gate.Wait();
_setBusy?.Invoke();
try
{
if (!IsReady)
throw new ASCOM.NotConnectedException("Serial port is not open.");
Thread.Sleep(60); // settle previous activity
if (_port.BytesToRead > 0)
{
_port.DiscardInBuffer();
}
_port.DiscardOutBuffer();
_port.Write($"{command}\r");
if (!expectResponse) return null;
// ... read logic with timeout ...
return raw;
}
finally
{
_clearBusy?.Invoke();
_gate.Release();
}
}
Sources: Helper/SerialPortGuard.cs:28-92
Summary
The COM port configuration and communication system in Pulsar_DomeDriver is a robust mechanism that starts with a simple user selection. The chosen port is persisted via the ConfigManager and used by the DomeDriver to initialize a connection. The critical SerialPortGuard class ensures that all interactions with the hardware are thread-safe and orderly, providing a stable foundation for all dome control operations.