mirror of
https://github.com/lupettohf/kv4p-sharp.git
synced 2025-01-19 01:36:30 +08:00
V1, Library and example GUI Application.
This commit is contained in:
parent
357047bc40
commit
0315d8d7dc
|
@ -3,22 +3,36 @@ using System.IO;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using NAudio.Wave;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace RadioControllerApp
|
||||
{
|
||||
public class FormRadio : Form
|
||||
{
|
||||
|
||||
// Pre-buffering fields
|
||||
private const int PreBufferSize = 5000; // Adjust as needed
|
||||
private ConcurrentQueue<byte[]> preBufferQueue = new ConcurrentQueue<byte[]>();
|
||||
private int preBufferedBytes = 0;
|
||||
private bool preBufferingComplete = false;
|
||||
|
||||
private RadioController radioController;
|
||||
private WaveInEvent waveIn;
|
||||
private BufferedWaveProvider receivedAudioBuffer;
|
||||
private WaveOutEvent waveOut;
|
||||
|
||||
private bool isRecording = false;
|
||||
private bool isTransmitting = false;
|
||||
|
||||
// PTT Key Handling
|
||||
private Keys pttKey = Keys.Space;
|
||||
private bool waitingForPTTKey = false;
|
||||
|
||||
// UI Controls
|
||||
private TextBox txtPortName;
|
||||
private Button btnOpenConnection;
|
||||
private Button btnCloseConnection;
|
||||
private Button btnInitialize;
|
||||
|
||||
private TextBox txtTXFrequency;
|
||||
private TextBox txtRXFrequency;
|
||||
|
@ -31,35 +45,38 @@ namespace RadioControllerApp
|
|||
private CheckBox chkLowpass;
|
||||
private Button btnSetFilters;
|
||||
|
||||
private Button btnStartRX;
|
||||
private Button btnStartTX;
|
||||
private Button btnEndTX;
|
||||
private Button btnStop;
|
||||
|
||||
private Button btnStartRecording;
|
||||
private Button btnStopRecording;
|
||||
private Button btnPlayReceivedAudio;
|
||||
private Button btnSetPTTKey;
|
||||
|
||||
private TextBox txtStatus;
|
||||
|
||||
private Panel pnlStatusIndicator;
|
||||
|
||||
public FormRadio()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeRadioController();
|
||||
LoadConfigurations();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.AutoScaleMode = AutoScaleMode.Dpi; // Enable DPI scaling
|
||||
|
||||
// Form properties
|
||||
this.Text = "Radio Controller";
|
||||
this.Size = new System.Drawing.Size(800, 700);
|
||||
this.MinimumSize = new System.Drawing.Size(600, 600);
|
||||
this.FormClosing += FormRadio_FormClosing;
|
||||
|
||||
// Initialize controls
|
||||
InitializeControls();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormRadio));
|
||||
SuspendLayout();
|
||||
//
|
||||
// FormRadio
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(144F, 144F);
|
||||
AutoScaleMode = AutoScaleMode.Dpi;
|
||||
ClientSize = new Size(778, 644);
|
||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||
KeyPreview = true;
|
||||
MinimumSize = new Size(600, 600);
|
||||
Name = "FormRadio";
|
||||
Text = "Radio Controller";
|
||||
FormClosing += FormRadio_FormClosing;
|
||||
KeyDown += FormRadio_KeyDown;
|
||||
KeyUp += FormRadio_KeyUp;
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
private void InitializeControls()
|
||||
|
@ -74,33 +91,37 @@ namespace RadioControllerApp
|
|||
};
|
||||
this.Controls.Add(mainLayout);
|
||||
|
||||
// Adjust row styles
|
||||
// Insert row styles
|
||||
mainLayout.RowStyles.Insert(0, new RowStyle(SizeType.Absolute, 20F)); // Status Indicator
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Connection Controls
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Frequency Controls
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Filter Controls
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Mode Controls
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Audio Controls
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); // Status TextBox
|
||||
|
||||
// Status Indicator Panel
|
||||
pnlStatusIndicator = new Panel
|
||||
{
|
||||
Height = 20,
|
||||
Dock = DockStyle.Fill,
|
||||
BackColor = System.Drawing.Color.Green // Assume green for RX
|
||||
};
|
||||
mainLayout.Controls.Add(pnlStatusIndicator, 0, 0);
|
||||
|
||||
// Connection Controls GroupBox
|
||||
GroupBox grpConnection = CreateConnectionControls();
|
||||
grpConnection.Dock = DockStyle.Fill;
|
||||
mainLayout.Controls.Add(grpConnection, 0, 0);
|
||||
mainLayout.Controls.Add(grpConnection, 0, 1);
|
||||
|
||||
// Frequency Controls GroupBox
|
||||
GroupBox grpFrequency = CreateFrequencyControls();
|
||||
grpFrequency.Dock = DockStyle.Fill;
|
||||
mainLayout.Controls.Add(grpFrequency, 0, 1);
|
||||
mainLayout.Controls.Add(grpFrequency, 0, 2);
|
||||
|
||||
// Filter Controls GroupBox
|
||||
GroupBox grpFilters = CreateFilterControls();
|
||||
grpFilters.Dock = DockStyle.Fill;
|
||||
mainLayout.Controls.Add(grpFilters, 0, 2);
|
||||
|
||||
// Mode Controls GroupBox
|
||||
GroupBox grpModes = CreateModeControls();
|
||||
grpModes.Dock = DockStyle.Fill;
|
||||
mainLayout.Controls.Add(grpModes, 0, 3);
|
||||
mainLayout.Controls.Add(grpFilters, 0, 3);
|
||||
|
||||
// Audio Controls GroupBox
|
||||
GroupBox grpAudio = CreateAudioControls();
|
||||
|
@ -130,7 +151,7 @@ namespace RadioControllerApp
|
|||
TableLayoutPanel layout = new TableLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
ColumnCount = 5,
|
||||
ColumnCount = 4,
|
||||
AutoSize = true
|
||||
};
|
||||
grpConnection.Controls.Add(layout);
|
||||
|
@ -139,23 +160,19 @@ namespace RadioControllerApp
|
|||
txtPortName = new TextBox { Text = "COM3", Anchor = AnchorStyles.Left };
|
||||
btnOpenConnection = new Button { Text = "Open Connection", AutoSize = true };
|
||||
btnCloseConnection = new Button { Text = "Close Connection", AutoSize = true };
|
||||
btnInitialize = new Button { Text = "Initialize", AutoSize = true };
|
||||
|
||||
btnOpenConnection.Click += btnOpenConnection_Click;
|
||||
btnCloseConnection.Click += btnCloseConnection_Click;
|
||||
btnInitialize.Click += btnInitialize_Click;
|
||||
|
||||
layout.Controls.Add(lblPortName, 0, 0);
|
||||
layout.Controls.Add(txtPortName, 1, 0);
|
||||
layout.Controls.Add(btnOpenConnection, 2, 0);
|
||||
layout.Controls.Add(btnCloseConnection, 3, 0);
|
||||
layout.Controls.Add(btnInitialize, 4, 0);
|
||||
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); // Label
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); // TextBox
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33F)); // Button
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33F)); // Button
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 34F)); // Button
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); // Button
|
||||
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); // Button
|
||||
|
||||
return grpConnection;
|
||||
}
|
||||
|
@ -243,41 +260,6 @@ namespace RadioControllerApp
|
|||
return grpFilters;
|
||||
}
|
||||
|
||||
private GroupBox CreateModeControls()
|
||||
{
|
||||
GroupBox grpModes = new GroupBox
|
||||
{
|
||||
Text = "Mode Controls",
|
||||
AutoSize = true,
|
||||
Dock = DockStyle.Fill
|
||||
};
|
||||
|
||||
FlowLayoutPanel layout = new FlowLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
AutoSize = true,
|
||||
WrapContents = false,
|
||||
};
|
||||
grpModes.Controls.Add(layout);
|
||||
|
||||
btnStartRX = new Button { Text = "Start RX Mode", AutoSize = true };
|
||||
btnStartTX = new Button { Text = "Start TX Mode", AutoSize = true };
|
||||
btnEndTX = new Button { Text = "End TX Mode", AutoSize = true };
|
||||
btnStop = new Button { Text = "Stop", AutoSize = true };
|
||||
|
||||
btnStartRX.Click += btnStartRX_Click;
|
||||
btnStartTX.Click += btnStartTX_Click;
|
||||
btnEndTX.Click += btnEndTX_Click;
|
||||
btnStop.Click += btnStop_Click;
|
||||
|
||||
layout.Controls.Add(btnStartRX);
|
||||
layout.Controls.Add(btnStartTX);
|
||||
layout.Controls.Add(btnEndTX);
|
||||
layout.Controls.Add(btnStop);
|
||||
|
||||
return grpModes;
|
||||
}
|
||||
|
||||
private GroupBox CreateAudioControls()
|
||||
{
|
||||
GroupBox grpAudio = new GroupBox
|
||||
|
@ -295,17 +277,10 @@ namespace RadioControllerApp
|
|||
};
|
||||
grpAudio.Controls.Add(layout);
|
||||
|
||||
btnStartRecording = new Button { Text = "Start Recording", AutoSize = true };
|
||||
btnStopRecording = new Button { Text = "Stop Recording", AutoSize = true };
|
||||
btnPlayReceivedAudio = new Button { Text = "Play Received Audio", AutoSize = true };
|
||||
btnSetPTTKey = new Button { Text = "Set PTT Key", AutoSize = true };
|
||||
btnSetPTTKey.Click += btnSetPTTKey_Click;
|
||||
|
||||
btnStartRecording.Click += btnStartRecording_Click;
|
||||
btnStopRecording.Click += btnStopRecording_Click;
|
||||
btnPlayReceivedAudio.Click += btnPlayReceivedAudio_Click;
|
||||
|
||||
layout.Controls.Add(btnStartRecording);
|
||||
layout.Controls.Add(btnStopRecording);
|
||||
layout.Controls.Add(btnPlayReceivedAudio);
|
||||
layout.Controls.Add(btnSetPTTKey);
|
||||
|
||||
return grpAudio;
|
||||
}
|
||||
|
@ -315,9 +290,16 @@ namespace RadioControllerApp
|
|||
// Disable controls that require an open connection
|
||||
ToggleControls(false);
|
||||
|
||||
receivedAudioBuffer = new BufferedWaveProvider(new WaveFormat(44100, 16, 1));
|
||||
receivedAudioBuffer = new BufferedWaveProvider(new WaveFormat(44100, 8, 1))
|
||||
{
|
||||
BufferDuration = TimeSpan.FromSeconds(5),
|
||||
DiscardOnBufferOverflow = true
|
||||
};
|
||||
waveOut = new WaveOutEvent();
|
||||
waveOut.Init(receivedAudioBuffer);
|
||||
}
|
||||
|
||||
|
||||
private void btnOpenConnection_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
|
@ -334,7 +316,14 @@ namespace RadioControllerApp
|
|||
radioController.AudioDataReceived += RadioController_AudioDataReceived;
|
||||
radioController.OpenConnection();
|
||||
|
||||
radioController.Initialize();
|
||||
btnTune_Click(null, null);
|
||||
// Start RX mode
|
||||
isTransmitting = false;
|
||||
UpdateStatusIndicator(false);
|
||||
|
||||
AppendStatus($"Connection opened on {portName}.");
|
||||
radioController.StartRXMode();
|
||||
ToggleControls(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -362,19 +351,6 @@ namespace RadioControllerApp
|
|||
}
|
||||
}
|
||||
|
||||
private void btnInitialize_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
radioController.Initialize();
|
||||
AppendStatus("Radio initialized.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error initializing radio: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void btnTune_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
|
@ -410,59 +386,44 @@ namespace RadioControllerApp
|
|||
}
|
||||
}
|
||||
|
||||
private void btnStartRX_Click(object sender, EventArgs e)
|
||||
private void btnSetPTTKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
radioController.StartRXMode();
|
||||
AppendStatus("Started RX mode.");
|
||||
AppendStatus("Press any key to set as PTT.");
|
||||
waitingForPTTKey = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
private void FormRadio_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
AppendStatus($"Error starting RX mode: {ex.Message}");
|
||||
if (waitingForPTTKey)
|
||||
{
|
||||
pttKey = e.KeyCode;
|
||||
waitingForPTTKey = false;
|
||||
AppendStatus($"PTT key set to: {pttKey}");
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.KeyCode == pttKey)
|
||||
{
|
||||
if (!isTransmitting)
|
||||
{
|
||||
StartTransmission();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void btnStartTX_Click(object sender, EventArgs e)
|
||||
private void FormRadio_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
try
|
||||
if (!waitingForPTTKey && e.KeyCode == pttKey)
|
||||
{
|
||||
radioController.StartTXMode();
|
||||
AppendStatus("Started TX mode.");
|
||||
if (isTransmitting)
|
||||
{
|
||||
StopTransmission();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error starting TX mode: {ex.Message}");
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void btnEndTX_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
radioController.EndTXMode();
|
||||
AppendStatus("Ended TX mode.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error ending TX mode: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void btnStop_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
radioController.Stop();
|
||||
AppendStatus("Radio stopped.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error stopping radio: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void btnStartRecording_Click(object sender, EventArgs e)
|
||||
private void StartTransmission()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -473,39 +434,45 @@ namespace RadioControllerApp
|
|||
}
|
||||
|
||||
radioController.StartTXMode();
|
||||
isRecording = true;
|
||||
isTransmitting = true;
|
||||
|
||||
waveIn = new WaveInEvent();
|
||||
waveIn.WaveFormat = new WaveFormat(44100, 16, 1);
|
||||
waveIn.WaveFormat = new WaveFormat(44100, 8, 1);
|
||||
waveIn.DataAvailable += WaveIn_DataAvailable;
|
||||
waveIn.StartRecording();
|
||||
|
||||
AppendStatus("Recording started.");
|
||||
AppendStatus("Transmission started.");
|
||||
|
||||
// Update status indicator
|
||||
UpdateStatusIndicator(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error starting recording: {ex.Message}");
|
||||
AppendStatus($"Error starting transmission: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void btnStopRecording_Click(object sender, EventArgs e)
|
||||
private void StopTransmission()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isRecording && waveIn != null)
|
||||
if (isTransmitting && waveIn != null)
|
||||
{
|
||||
waveIn.StopRecording();
|
||||
waveIn.Dispose();
|
||||
waveIn = null;
|
||||
isRecording = false;
|
||||
isTransmitting = false;
|
||||
|
||||
radioController.EndTXMode();
|
||||
AppendStatus("Recording stopped.");
|
||||
AppendStatus("Transmission stopped.");
|
||||
radioController.StartRXMode();
|
||||
// Update status indicator
|
||||
UpdateStatusIndicator(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error stopping recording: {ex.Message}");
|
||||
AppendStatus($"Error stopping transmission: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,13 +480,13 @@ namespace RadioControllerApp
|
|||
{
|
||||
try
|
||||
{
|
||||
if (isRecording && radioController != null)
|
||||
if (isTransmitting && radioController != null)
|
||||
{
|
||||
byte[] buffer = new byte[e.BytesRecorded];
|
||||
Array.Copy(e.Buffer, buffer, e.BytesRecorded);
|
||||
|
||||
// Convert audio data to the required format if necessary
|
||||
await radioController.SendAudioDataAsync(buffer);
|
||||
// Send audio data asynchronously
|
||||
await radioController.SendAudioDataAsync(buffer, 0, buffer.Length);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -528,25 +495,6 @@ namespace RadioControllerApp
|
|||
}
|
||||
}
|
||||
|
||||
private void btnPlayReceivedAudio_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (waveOut == null)
|
||||
{
|
||||
waveOut = new WaveOutEvent();
|
||||
waveOut.Init(receivedAudioBuffer);
|
||||
}
|
||||
waveOut.Play();
|
||||
|
||||
AppendStatus("Playing received audio.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppendStatus($"Error playing received audio: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void RadioController_ErrorOccurred(object sender, ErrorEventArgs e)
|
||||
{
|
||||
AppendStatus($"Error: {e.GetException().Message}");
|
||||
|
@ -554,9 +502,39 @@ namespace RadioControllerApp
|
|||
|
||||
private void RadioController_AudioDataReceived(object sender, byte[] data)
|
||||
{
|
||||
// Buffer the received audio data
|
||||
Console.WriteLine($"AudioDataReceived called with {data.Length} bytes");
|
||||
|
||||
if (!preBufferingComplete)
|
||||
{
|
||||
preBufferQueue.Enqueue(data);
|
||||
preBufferedBytes += data.Length;
|
||||
|
||||
if (preBufferedBytes >= PreBufferSize)
|
||||
{
|
||||
// Pre-buffering complete, start playback
|
||||
preBufferingComplete = true;
|
||||
|
||||
// Add all pre-buffered data to the buffer
|
||||
while (preBufferQueue.TryDequeue(out byte[] preBufferData))
|
||||
{
|
||||
receivedAudioBuffer.AddSamples(preBufferData, 0, preBufferData.Length);
|
||||
}
|
||||
|
||||
// Start playback
|
||||
waveOut.Play();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add received audio data to the buffer
|
||||
receivedAudioBuffer.AddSamples(data, 0, data.Length);
|
||||
AppendStatus($"Audio data received. Length: {data.Length} bytes.");
|
||||
|
||||
// Ensure playback is ongoing
|
||||
if (waveOut.PlaybackState != PlaybackState.Playing)
|
||||
{
|
||||
waveOut.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendStatus(string message)
|
||||
|
@ -571,19 +549,30 @@ namespace RadioControllerApp
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateStatusIndicator(bool isTransmitting)
|
||||
{
|
||||
if (pnlStatusIndicator.InvokeRequired)
|
||||
{
|
||||
pnlStatusIndicator.Invoke(new Action(() => UpdateStatusIndicator(isTransmitting)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isTransmitting)
|
||||
{
|
||||
pnlStatusIndicator.BackColor = System.Drawing.Color.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
pnlStatusIndicator.BackColor = System.Drawing.Color.Green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleControls(bool isEnabled)
|
||||
{
|
||||
btnInitialize.Enabled = isEnabled;
|
||||
btnTune.Enabled = isEnabled;
|
||||
btnSetFilters.Enabled = isEnabled;
|
||||
btnStartRX.Enabled = isEnabled;
|
||||
btnStartTX.Enabled = isEnabled;
|
||||
btnEndTX.Enabled = isEnabled;
|
||||
btnStop.Enabled = isEnabled;
|
||||
|
||||
btnStartRecording.Enabled = isEnabled;
|
||||
btnStopRecording.Enabled = isEnabled;
|
||||
btnPlayReceivedAudio.Enabled = isEnabled;
|
||||
btnSetPTTKey.Enabled = isEnabled;
|
||||
|
||||
// Disable connection buttons appropriately
|
||||
btnOpenConnection.Enabled = !isEnabled;
|
||||
|
@ -610,6 +599,77 @@ namespace RadioControllerApp
|
|||
waveOut.Dispose();
|
||||
waveOut = null;
|
||||
}
|
||||
|
||||
// Save configurations
|
||||
SaveConfigurations();
|
||||
}
|
||||
|
||||
private void LoadConfigurations()
|
||||
{
|
||||
string configFile = "config.ini";
|
||||
if (File.Exists(configFile))
|
||||
{
|
||||
string[] lines = File.ReadAllLines(configFile);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.StartsWith("PortName="))
|
||||
{
|
||||
txtPortName.Text = line.Substring("PortName=".Length);
|
||||
}
|
||||
else if (line.StartsWith("PTTKey="))
|
||||
{
|
||||
if (Enum.TryParse(line.Substring("PTTKey=".Length), out Keys key))
|
||||
{
|
||||
pttKey = key;
|
||||
}
|
||||
}
|
||||
else if (line.StartsWith("TXFrequency="))
|
||||
{
|
||||
txtTXFrequency.Text = line.Substring("TXFrequency=".Length);
|
||||
}
|
||||
else if (line.StartsWith("RXFrequency="))
|
||||
{
|
||||
txtRXFrequency.Text = line.Substring("RXFrequency=".Length);
|
||||
}
|
||||
else if (line.StartsWith("Tone="))
|
||||
{
|
||||
txtTone.Text = line.Substring("Tone=".Length);
|
||||
}
|
||||
else if (line.StartsWith("SquelchLevel="))
|
||||
{
|
||||
txtSquelchLevel.Text = line.Substring("SquelchLevel=".Length);
|
||||
}
|
||||
else if (line.StartsWith("Emphasis="))
|
||||
{
|
||||
chkEmphasis.Checked = line.Substring("Emphasis=".Length) == "True";
|
||||
}
|
||||
else if (line.StartsWith("Highpass="))
|
||||
{
|
||||
chkHighpass.Checked = line.Substring("Highpass=".Length) == "True";
|
||||
}
|
||||
else if (line.StartsWith("Lowpass="))
|
||||
{
|
||||
chkLowpass.Checked = line.Substring("Lowpass=".Length) == "True";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveConfigurations()
|
||||
{
|
||||
string configFile = "config.ini";
|
||||
using (StreamWriter writer = new StreamWriter(configFile))
|
||||
{
|
||||
writer.WriteLine($"PortName={txtPortName.Text}");
|
||||
writer.WriteLine($"PTTKey={pttKey}");
|
||||
writer.WriteLine($"TXFrequency={txtTXFrequency.Text}");
|
||||
writer.WriteLine($"RXFrequency={txtRXFrequency.Text}");
|
||||
writer.WriteLine($"Tone={txtTone.Text}");
|
||||
writer.WriteLine($"SquelchLevel={txtSquelchLevel.Text}");
|
||||
writer.WriteLine($"Emphasis={chkEmphasis.Checked}");
|
||||
writer.WriteLine($"Highpass={chkHighpass.Checked}");
|
||||
writer.WriteLine($"Lowpass={chkLowpass.Checked}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,4 +117,66 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
|
@ -2,13 +2,29 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<Company>Monocul.us</Company>
|
||||
<Authors>Andrea Santaniello</Authors>
|
||||
<Description>Radio GUI for KV4P radio</Description>
|
||||
<PackageIcon>icon-lg-dark.png</PackageIcon>
|
||||
<ApplicationIcon>icon-lg-dark.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="icon-lg-dark.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="E:\malattie\malattie_json\icon-lg-dark.png">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NAudio" Version="2.2.1" />
|
||||
</ItemGroup>
|
||||
|
|
BIN
RadioGUI/icon-lg-dark.ico
Normal file
BIN
RadioGUI/icon-lg-dark.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -73,6 +74,7 @@ public class RadioController : IDisposable
|
|||
WriteTimeout = writeTimeout
|
||||
};
|
||||
serialPort.DataReceived += SerialPort_DataReceived;
|
||||
|
||||
}
|
||||
|
||||
public void OpenConnection()
|
||||
|
@ -181,7 +183,7 @@ public class RadioController : IDisposable
|
|||
SendCommand(ESP32Command.FILTERS, paramsStr);
|
||||
}
|
||||
|
||||
public async Task SendAudioDataAsync(byte[] audioData, CancellationToken cancellationToken = default)
|
||||
public async Task SendAudioDataAsync(byte[] audioData, int offset, int count, CancellationToken cancellationToken = default)
|
||||
{
|
||||
lock (_syncLock)
|
||||
{
|
||||
|
@ -193,10 +195,10 @@ public class RadioController : IDisposable
|
|||
int chunkSize = 512;
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
|
||||
for (int i = 0; i < audioData.Length; i += chunkSize)
|
||||
for (int i = offset; i < count; i += chunkSize)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
int remaining = audioData.Length - i;
|
||||
int remaining = count - i;
|
||||
int size = remaining > chunkSize ? chunkSize : remaining;
|
||||
byte[] chunk = new byte[size];
|
||||
Array.Copy(audioData, i, chunk, 0, size);
|
||||
|
@ -217,6 +219,7 @@ public class RadioController : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
byte[] receivedData = null;
|
||||
|
@ -246,7 +249,7 @@ public class RadioController : IDisposable
|
|||
{
|
||||
mode = currentMode;
|
||||
}
|
||||
if (mode == RadioMode.RX)
|
||||
if (mode != RadioMode.TX)
|
||||
{
|
||||
// Raise an event with the received audio data
|
||||
OnAudioDataReceived(data);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<RootNamespace>kv4p_sharp</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
Loading…
Reference in New Issue
Block a user