Skip to content

Commit

Permalink
Refactor arduino interface to avoid event callback
Browse files Browse the repository at this point in the history
  • Loading branch information
glopesdev committed Jul 1, 2023
1 parent 32511ac commit 66e8d3e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 15 deletions.
60 changes: 47 additions & 13 deletions Bonsai.Arduino/Arduino.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace Bonsai.Arduino
{
Expand Down Expand Up @@ -90,7 +91,6 @@ public Arduino(string portName, int baudRate)
commandBuffer = new byte[MaxDataBytes];
sysexBuffer = new byte[MaxDataBytes];
readBuffer = new byte[serialPort.ReadBufferSize];
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
}

/// <summary>
Expand Down Expand Up @@ -141,28 +141,62 @@ void OnSysexReceived(SysexReceivedEventArgs e)
SysexReceived?.Invoke(this, e);
}

void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
Task RunAsync(CancellationToken cancellationToken)
{
var bytesToRead = serialPort.BytesToRead;
while (serialPort.IsOpen && bytesToRead > 0)
serialPort.Open();
Thread.Sleep(ConnectionDelay);
serialPort.ReadExisting();
return Task.Factory.StartNew(() =>
{
var bytesRead = serialPort.Read(readBuffer, 0, Math.Min(bytesToRead, readBuffer.Length));
for (int i = 0; i < bytesRead; i++)
using var cancellation = cancellationToken.Register(serialPort.Dispose);
while (!cancellationToken.IsCancellationRequested)
{
ProcessInput(readBuffer[i]);
try
{
var bytesToRead = serialPort.BytesToRead;
if (bytesToRead == 0)
{
var nextByte = serialPort.ReadByte();
if (nextByte < 0) break;
ProcessInput((byte)nextByte);
}
else
{
while (bytesToRead > 0)
{
var bytesRead = serialPort.Read(readBuffer, 0, Math.Min(bytesToRead, readBuffer.Length));
for (int i = 0; i < bytesRead; i++)
{
ProcessInput(readBuffer[i]);
}
bytesToRead -= bytesRead;
}
}
}
catch (Exception)
{
if (!cancellationToken.IsCancellationRequested)
{
throw;
}
break;
}
}
bytesToRead -= bytesRead;
}
},
cancellationToken,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}

/// <summary>
/// Opens a new serial port connection to the Arduino board.
/// </summary>
public void Open()
/// <param name="cancellationToken">
/// A <see cref="CancellationToken"/> which can be used to cancel the operation.
/// </param>
public void Open(CancellationToken cancellationToken = default)
{
serialPort.Open();
Thread.Sleep(ConnectionDelay);
serialPort.ReadExisting();
RunAsync(cancellationToken);
}

void ReportInput(ref int[] reportInput, byte command, int index, bool state)
Expand Down
6 changes: 4 additions & 2 deletions Bonsai.Arduino/ArduinoManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using System.Threading;

namespace Bonsai.Arduino
{
Expand Down Expand Up @@ -50,12 +51,13 @@ internal static ArduinoDisposable ReserveConnection(string portName, ArduinoConf
}
#pragma warning restore CS0612 // Type or member is obsolete

var cancellation = new CancellationTokenSource();
var arduino = new Arduino(serialPortName, arduinoConfiguration.BaudRate);
arduino.Open();
arduino.Open(cancellation.Token);
arduino.SamplingInterval(arduinoConfiguration.SamplingInterval);
var dispose = Disposable.Create(() =>
{
arduino.Close();
cancellation.Cancel();
openConnections.Remove(portName);
});

Expand Down

0 comments on commit 66e8d3e

Please sign in to comment.