diff --git a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.CanBus.cs b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.CanBus.cs index 362ffbf26..135c07b5e 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.CanBus.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.CanBus.cs @@ -20,8 +20,8 @@ public class Mcp2515CanBus : ICanBus /// public CanBitrate BitRate { - get => Controller._bitrate; - set => Controller.Initialize(value, Controller._oscillator); + get => Controller.bitrate; + set => Controller.Initialize(value, Controller.oscillator); } /// diff --git a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.cs b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.cs index ae0cd5113..5bd1967bf 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.cs @@ -6,9 +6,9 @@ namespace Meadow.Foundation.ICs.CAN; /// -/// Encapsulation for the Microchip MCP2515 CAN controller +/// Represents a Microchip MCP2515 CAN controller, providing SPI-based communication with CAN functionality. /// -public partial class Mcp2515 : ICanController +public partial class Mcp2515 : ICanController, IDisposable { /// /// Default SPI clock mode for the MCP2515 @@ -23,20 +23,65 @@ public partial class Mcp2515 : ICanController private byte PHASE_SEG2_Default = 0x03;//0x02; private byte PROP_SEG_Default = 0x02;// 0x01; - private ICanBus? _busInstance; - private CanOscillator _oscillator; - private CanBitrate _bitrate; + private bool portsCreated; + private ICanBus? busInstance; + private CanOscillator oscillator; + private CanBitrate bitrate; private ISpiBus SpiBus { get; } private IDigitalOutputPort ChipSelect { get; } private Logger? Logger { get; } private IDigitalInterruptPort? InterruptPort { get; } + private IDigitalOutputPort? ResetPort { get; } + /// + /// Returns true if the instance has been disposed, otherwise false + /// + public bool IsDisposed { get; private set; } + + /// + /// Initializes a new instance of the class with specified SPI bus, chip select pin, and optional parameters. + /// + /// The SPI bus for communication. + /// The pin for chip select functionality. + /// The oscillator setting, default is 8 MHz. + /// Optional interrupt pin for CAN interrupts. + /// Optional reset pin for hardware resets. + /// Optional logger for diagnostic messages. + public Mcp2515( + ISpiBus bus, + IPin chipSelectPin, + CanOscillator oscillator = CanOscillator.Osc_8MHz, + IPin? interruptPin = null, + IPin? resetPin = null, + Logger? logger = null) + { + SpiBus = bus; + Logger = logger; + this.oscillator = oscillator; + + ChipSelect = chipSelectPin.CreateDigitalOutputPort(true); + InterruptPort = interruptPin?.CreateDigitalInterruptPort(InterruptMode.EdgeFalling, ResistorMode.InternalPullUp); + ResetPort = resetPin?.CreateDigitalOutputPort(true); + + portsCreated = true; + } + + /// + /// Initializes a new instance of the class with a digital output chip select port and optional parameters. + /// + /// The SPI bus for communication. + /// The digital output port for chip select. + /// The oscillator setting, default is 8 MHz. + /// Optional interrupt port for CAN interrupts. + /// Optional reset port for hardware resets. + /// Optional logger for diagnostic messages. public Mcp2515( ISpiBus bus, IDigitalOutputPort chipSelect, CanOscillator oscillator = CanOscillator.Osc_8MHz, IDigitalInterruptPort? interruptPort = null, + IDigitalOutputPort? resetPort = null, Logger? logger = null) { if (interruptPort != null) @@ -51,20 +96,22 @@ public Mcp2515( ChipSelect = chipSelect; Logger = logger; InterruptPort = interruptPort; - _oscillator = oscillator; + ResetPort = resetPort; + + this.oscillator = oscillator; } /// public ICanBus CreateCanBus(CanBitrate bitrate, int busNumber = 0) { - if (_busInstance == null) + if (busInstance == null) { - Initialize(bitrate, _oscillator); + Initialize(bitrate, oscillator); - _busInstance = new Mcp2515CanBus(this); + busInstance = new Mcp2515CanBus(this); } - return _busInstance; + return busInstance; } private void Initialize(CanBitrate bitrate, CanOscillator oscillator) @@ -78,6 +125,12 @@ private void Initialize(CanBitrate bitrate, CanOscillator oscillator) if (mode != Mode.Configure) { SetMode(Mode.Configure); + + var check = ReadRegister(Register.CANSTAT)[0]; + if (check == 0x00) + { + throw new Exception("Unable to read configuration register. Check signal lines are properly connected, including the RST."); + } } ClearFiltersAndMasks(); @@ -115,7 +168,7 @@ private void Initialize(CanBitrate bitrate, CanOscillator oscillator) WriteRegister(Register.CNF1, cfg.CFG1); WriteRegister(Register.CNF2, cfg.CFG2); WriteRegister(Register.CNF3, cfg.CFG3); - _bitrate = bitrate; + this.bitrate = bitrate; LogRegisters(Register.CNF3, 3); SetMode(Mode.Normal); @@ -123,13 +176,13 @@ private void Initialize(CanBitrate bitrate, CanOscillator oscillator) private CanBitrate Bitrate { - get => _bitrate; + get => bitrate; set { var mode = GetMode(); SetMode(Mode.Configure); - var cfg = GetConfigForOscillatorAndBitrate(_oscillator, value); + var cfg = GetConfigForOscillatorAndBitrate(oscillator, value); WriteRegister(Register.CNF1, cfg.CFG1); WriteRegister(Register.CNF2, cfg.CFG2); WriteRegister(Register.CNF3, cfg.CFG3); @@ -137,7 +190,7 @@ private CanBitrate Bitrate SetMode(mode); - _bitrate = value; + bitrate = value; } } @@ -251,6 +304,13 @@ private void WriteFrame(ICanFrame frame, int bufferNumber) private void Reset() { + if (ResetPort != null) + { + ResetPort.State = false; + Thread.Sleep(10); + ResetPort.State = true; + } + Span tx = stackalloc byte[1]; Span rx = stackalloc byte[1]; @@ -263,7 +323,7 @@ private void LogRegisters(Register start, byte count) { var values = ReadRegister(start, count); - Resolver.Log.Info($"{(byte)start:X2} ({start}): {BitConverter.ToString(values)}"); + Resolver.Log.Debug($"{(byte)start:X2} ({start}): {BitConverter.ToString(values)}", "driver"); } private Mode GetMode() @@ -523,4 +583,31 @@ private DataFrame ReadDataFrame(RxBufferNumber bufferNumber) return frame; } + + /// + protected virtual void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (disposing) + { + if (portsCreated) + { + ChipSelect.Dispose(); + InterruptPort?.Dispose(); + ResetPort?.Dispose(); + } + } + + IsDisposed = true; + } + } + + + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Samples/Mcp2515_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Samples/Mcp2515_Sample/MeadowApp.cs index 7e7403915..8d6b3d593 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Samples/Mcp2515_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Samples/Mcp2515_Sample/MeadowApp.cs @@ -23,10 +23,9 @@ public override Task Initialize() expander = new Mcp2515( Device.CreateSpiBus(), - Device.Pins.D05.CreateDigitalOutputPort(true), + Device.Pins.D05, Mcp2515.CanOscillator.Osc_8MHz, - Device.Pins.D05.CreateDigitalInterruptPort(InterruptMode.EdgeFalling), - Resolver.Log); + Device.Pins.D06); return base.Initialize();