Skip to content

Commit

Permalink
Merge pull request #1070 from engunneer/driver/Ads1263
Browse files Browse the repository at this point in the history
Driver/ads1263
  • Loading branch information
adrianstevens authored Sep 9, 2024
2 parents 065df9f + 5129641 commit 83f081a
Show file tree
Hide file tree
Showing 16 changed files with 1,323 additions and 0 deletions.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using Meadow.Hardware;
using Meadow.Units;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Meadow.Foundation.ICs.IOExpanders
{
public partial class Ads1263
{
/// <summary>
/// Represents an Ads1263 analog input port
/// </summary>
public class AnalogInputPort : AnalogInputPortBase, IAnalogInputPort
{
/// <summary>
/// Is the port sampling
/// </summary>
public bool IsSampling { get; protected set; } = false;

private readonly Ads1263 controller;

private Voltage previousVoltageReading;

private CancellationTokenSource? SamplingTokenSource;

private readonly object _lock = new();

/// <summary>
/// Create a new AnalogInputPort object with a non-default reference voltage
/// </summary>
/// <param name="controller">The parent Ads1263 controller.</param>
/// <param name="pin">The pin associated with the port.</param>
/// <param name="channel">The channel information for the port.</param>
/// <param name="sampleCount">The number of samples to be taken during each reading.</param>
/// <param name="sampleInterval">The time interval between samples during each reading.</param>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="pin"/> or <paramref name="channel"/> is <c>null</c>.</exception>
public AnalogInputPort(Ads1263 controller,
IPin pin,
IAnalogChannelInfo channel,
int sampleCount, TimeSpan sampleInterval)
: base(pin, channel, sampleCount, sampleInterval, controller.GetADCReferenceVoltage(pin))
{
// TODO: Validate pin is valid before using it?
this.controller = controller;

SampleCount = sampleCount;
}

/// <summary>
/// Start the ADC conversions
/// </summary>
public void StartConversions()
{
controller.ADCStart(Pin);
}

/// <summary>
/// Stop the ADC conversions
/// </summary>
public void StopConversions()
{
controller.ADCStop(Pin);
}

/// <inheritdoc />
/// <remarks>Assumes conversions have been started</remarks>
public override async Task<Voltage> Read()
{
var result = controller.ReadAnalog(Pin);
await Task.Delay(SampleInterval);
return result;
}

/// <summary>
/// Start updating
/// </summary>
public override void StartUpdating(TimeSpan? updateInterval = null)
{
// thread safety
lock (_lock)
{
if (IsSampling)
return;

StartConversions();
IsSampling = true;

// if an update interval was passed in, override the default value
if (updateInterval is { } ui)
{ UpdateInterval = ui; }

SamplingTokenSource = new CancellationTokenSource();
var ct = SamplingTokenSource.Token;

Task.Factory.StartNew(async () =>
{
while (true)
{
// cleanup
if (ct.IsCancellationRequested)
{
// do task clean up here
Observers.ForEach(x => x.OnCompleted());
break;
}
var newVoltage = await Read();
var result = new ChangeResult<Voltage>(newVoltage, previousVoltageReading);
previousVoltageReading = newVoltage;
// raise our events and notify our subs
RaiseChangedAndNotify(result);
await Task.Delay(UpdateInterval, ct);
}
IsSampling = false;
}, SamplingTokenSource.Token);
}
}

/// <summary>
/// Stop updating the port
/// </summary>
public override void StopUpdating()
{
lock (_lock)
{
if (!IsSampling)
return;

SamplingTokenSource?.Cancel();

IsSampling = false;

StopConversions();
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Meadow.Hardware;
using System;

namespace Meadow.Foundation.ICs.IOExpanders
{
public partial class Ads1263
{
/// <summary>
/// Represents an Ads1263 digital input port
/// </summary>
public class DigitalInputPort : DigitalInputPortBase
{
/// <inheritdoc/>
public override bool State
{
get
{
if (Pin.Controller is Ads1263 controller)
{
Update(controller.ReadPort(Pin));
}
return state;
}
}
private bool state = false;

/// <inheritdoc/>
public override ResistorMode Resistor
{
get => portResistorMode;
set => throw new NotSupportedException("Cannot change port resistor mode");
}
private readonly ResistorMode portResistorMode;

/// <summary>
/// Create a new DigitalInputPort object
/// </summary>
/// <param name="pin">The input pin</param>
public DigitalInputPort(IPin pin)
: base(pin, (IDigitalChannelInfo)pin.SupportedChannels![0])
{
portResistorMode = ResistorMode.Disabled;
}

/// <summary>
/// Update the port value
/// </summary>
/// <param name="newState">The new port state</param>
internal void Update(bool newState)
{
state = newState;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Meadow.Hardware;

namespace Meadow.Foundation.ICs.IOExpanders
{
public partial class Ads1263
{
/// <summary>
/// Represents an Ads1263 DigitalOutputPort
/// </summary>
public class DigitalOutputPort : DigitalOutputPortBase
{
/// <summary>
/// Enable the caller to receive pin state updates
/// </summary>
/// <param name="pin"></param>
/// <param name="state"></param>
public delegate void SetPinStateDelegate(IPin pin, bool state);

/// <summary>
/// The SetPinState delegate
/// </summary>
public SetPinStateDelegate SetPinState = default!;

/// <summary>
/// The port state
/// True for high, false for low
/// </summary>
public override bool State
{
get => state;
set => SetPinState?.Invoke(Pin, state = value);
}
bool state;

/// <summary>
/// Create a new DigitalOutputPort
/// </summary>
/// <param name="pin">The pin representing the port</param>
/// <param name="initialState">The initial port state</param>
public DigitalOutputPort(
IPin pin,
bool initialState = false)
: base(pin, (IDigitalChannelInfo)pin.SupportedChannels![0], initialState, OutputType.PushPull)
{
}
}
}
}
Loading

0 comments on commit 83f081a

Please sign in to comment.