diff --git a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.BitCalc.cs b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.BitCalc.cs
index dd0a03531..b7bf71090 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.BitCalc.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.BitCalc.cs
@@ -1,4 +1,5 @@
using Meadow.Hardware;
+using System;
namespace Meadow.Foundation.ICs.CAN;
@@ -41,7 +42,18 @@ public partial class Mcp2515
break;
case CanOscillator.Osc_10MHz:
- // TODO: add supported things here
+ switch (bitrate)
+ {
+ // case CanBitrate.Can_125kbps:
+ // return (0x03, 0xb8, 0x05);
+ case CanBitrate.Can_250kbps:
+ return (0x01, 0x90, 0x02);
+ case CanBitrate.Can_500kbps:
+ return (0x00, 0x90, 0x02);
+ case CanBitrate.Can_1Mbps:
+ return (0x00, 0x80, 0x00);
+ // TODO: add supported things here
+ }
break;
case CanOscillator.Osc_16MHz:
@@ -110,6 +122,39 @@ public partial class Mcp2515
}
- throw new System.NotSupportedException("Provided Bitrate and Oscillator frequency is not supported");
+ // if we don't have a fixed, pre-calculated value, try to calculate one
+ var freq = oscillator switch
+ {
+ CanOscillator.Osc_8MHz => 8_000_000,
+ CanOscillator.Osc_10MHz => 10_000_000,
+ CanOscillator.Osc_16MHz => 16_000_000,
+ CanOscillator.Osc_20MHz => 20_000_000,
+ _ => throw new NotSupportedException(),
+ };
+
+ return CalculateConfigForOscillatorAndBitrate((int)oscillator, (int)bitrate);
+ }
+
+ private (byte CFG1, byte CFG2, byte CFG3) CalculateConfigForOscillatorAndBitrate(int oscillatorFreq, int bitRate)
+ {
+ int TQ = 16; // Assume 16 time quanta per bit time
+ int PropSeg = 3; // Propagation segment
+ int PhaseSeg1 = 5; // Phase Segment 1
+ int PhaseSeg2 = 5; // Phase Segment 2
+ int SJW = 1; // Synchronization Jump Width (1 TQ)
+
+ // Calculate Baud Rate Prescaler (BRP)
+ int brp = (oscillatorFreq / (2 * bitRate * TQ)) - 1;
+ if (brp < 0 || brp > 63) // BRP must fit in 6 bits
+ {
+ throw new ArgumentOutOfRangeException("Cannot calculate BRP for the given oscillator frequency and bitrate.");
+ }
+
+ // Calculate CNF1, CNF2, CNF3
+ var cfg1 = (byte)(((SJW - 1) << 6) | (brp & 0x3F)); // SJW is 2 bits, BRP is 6 bits
+ var cfg2 = (byte)(0x80 | ((PhaseSeg1 - 1) << 3) | (PropSeg - 1)); // Set SAM = 1 for single sampling
+ var cfg3 = (byte)(PhaseSeg2 - 1); // PhaseSeg2
+
+ return (cfg1, cfg2, cfg3);
}
}
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 de622f105..362ffbf26 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
@@ -12,7 +12,8 @@ public class Mcp2515CanBus : ICanBus
///
public event EventHandler? FrameReceived;
- public event EventHandler? BusError;
+ ///
+ public event EventHandler? BusError;
private Mcp2515 Controller { get; }
@@ -105,8 +106,20 @@ private void OnInterruptPortChanged(object sender, DigitalPortResult e)
}
break;
case InterruptCode.Error:
- var errors = Controller.ReadRegister(Register.EFLG)[0];
- BusError?.Invoke(this, errors);
+ if (BusError != null)
+ {
+ var errors = Controller.ReadRegister(Register.EFLG)[0];
+ // read the error counts
+ var tec = Controller.ReadRegister(Register.TEC)[0];
+ var rec = Controller.ReadRegister(Register.REC)[0];
+ BusError.Invoke(this, new CanErrorInfo
+ {
+ ReceiveErrorCount = rec,
+ TransmitErrorCount = tec
+ });
+ // clear the error interrupt
+ Controller.ClearInterrupt(InterruptFlag.ERRIF | InterruptFlag.MERRF);
+ }
break;
}
}
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.Enums.cs
index 8e72ee632..9bd82b53f 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.Enums.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.Enums.cs
@@ -6,10 +6,10 @@ public partial class Mcp2515
{
public enum CanOscillator
{
- Osc_8MHz,
- Osc_10MHz,
- Osc_16MHz,
- Osc_20MHz,
+ Osc_8MHz = 8_000_000,
+ Osc_10MHz = 10_000_000,
+ Osc_16MHz = 16_000_000,
+ Osc_20MHz = 20_000_000,
}
private enum Register : byte
@@ -143,8 +143,8 @@ private enum Control : byte
private enum Status : byte
{
NONE = 0,
- RX0IF = (1 << 0),
- RX1IF = (1 << 1)
+ RX0IF = 1 << 0,
+ RX1IF = 1 << 1
}
private enum Result : byte
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 b451aafe0..53c456387 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.CAN.Mcp2515/Driver/Mcp2515.cs
@@ -83,9 +83,7 @@ private void Initialize(CanBitrate bitrate, CanOscillator oscillator)
if (InterruptPort != null)
{
- // TODO: add error condition handling
- ConfigureInterrupts(InterruptEnable.RXB0 | InterruptEnable.RXB1 | InterruptEnable.ERR | InterruptEnable.MSG_ERR);
- //ConfigureInterrupts(InterruptEnable.RXB0 | InterruptEnable.RXB1);
+ ConfigureInterrupts(InterruptEnable.RXB0 | InterruptEnable.RXB1 | InterruptEnable.ERR);
ClearInterrupt((InterruptFlag)0xff);
}
else
@@ -192,7 +190,7 @@ private void WriteFrame(ICanFrame frame, int bufferNumber)
{
// put the frame id into a buffer (0-2)
var sidh = (byte)(sdf.ID >> 3);
- var sidl = (byte)(sdf.ID << 5 & 0xe0);
+ var sidl = (byte)((sdf.ID << 5) & 0xe0);
WriteRegister(ctrl_reg + 1, sidh);
WriteRegister(ctrl_reg + 2, sidl);
}
@@ -200,7 +198,7 @@ private void WriteFrame(ICanFrame frame, int bufferNumber)
{
// put the frame id into a buffer (0-2)
var sidh = (byte)(srf.ID >> 3);
- var sidl = (byte)(srf.ID << 5 & 0xe0);
+ var sidl = (byte)((srf.ID << 5) & 0xe0);
WriteRegister(ctrl_reg + 1, sidh);
WriteRegister(ctrl_reg + 2, sidl);
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanBus.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanBus.cs
index de5f6c489..32c909301 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanBus.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanBus.cs
@@ -10,6 +10,8 @@ public class PCanBus : ICanBus
{
///
public event EventHandler? FrameReceived;
+ ///
+ public event EventHandler? BusError;
///
public CanAcceptanceFilterCollection AcceptanceFilters { get; } = new(5);
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanFdBus.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanFdBus.cs
index 281a0c3f4..307f1d15a 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanFdBus.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.PCanBasic/Driver/PCanFdBus.cs
@@ -4,6 +4,11 @@ namespace ICs.IOExpanders.PCanBasic;
public class PCanFdBus : ICanBus
{
+ ///
+ public event EventHandler? FrameReceived;
+ ///
+ public event EventHandler? BusError;
+
internal PCanFdBus(PCanConfiguration configuration)
{
throw new NotImplementedException();
@@ -13,8 +18,6 @@ internal PCanFdBus(PCanConfiguration configuration)
public CanAcceptanceFilterCollection AcceptanceFilters => throw new NotImplementedException();
- public event EventHandler? FrameReceived;
-
public void ClearReceiveBuffers()
{
throw new NotImplementedException();