Skip to content

Commit

Permalink
Merge pull request #1068 from WildernessLabs/feature/mcp2515
Browse files Browse the repository at this point in the history
added error support to MCP2515
  • Loading branch information
adrianstevens authored Aug 21, 2024
2 parents cf76c9a + 3a0927a commit 29141e2
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Meadow.Hardware;
using System;

namespace Meadow.Foundation.ICs.CAN;

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public class Mcp2515CanBus : ICanBus

/// <inheritdoc/>
public event EventHandler<ICanFrame>? FrameReceived;
public event EventHandler<byte>? BusError;
/// <inheritdoc/>
public event EventHandler<CanErrorInfo>? BusError;

private Mcp2515 Controller { get; }

Expand Down Expand Up @@ -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;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -192,15 +190,15 @@ 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);
}
else if (frame is StandardRtrFrame srf)
{
// 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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class PCanBus : ICanBus
{
/// <inheritdoc/>
public event EventHandler<ICanFrame>? FrameReceived;
/// <inheritdoc/>
public event EventHandler<CanErrorInfo>? BusError;

/// <inheritdoc/>
public CanAcceptanceFilterCollection AcceptanceFilters { get; } = new(5);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ namespace ICs.IOExpanders.PCanBasic;

public class PCanFdBus : ICanBus
{
/// <inheritdoc/>
public event EventHandler<ICanFrame>? FrameReceived;
/// <inheritdoc/>
public event EventHandler<CanErrorInfo>? BusError;

internal PCanFdBus(PCanConfiguration configuration)
{
throw new NotImplementedException();
Expand All @@ -13,8 +18,6 @@ internal PCanFdBus(PCanConfiguration configuration)

public CanAcceptanceFilterCollection AcceptanceFilters => throw new NotImplementedException();

public event EventHandler<ICanFrame>? FrameReceived;

public void ClearReceiveBuffers()
{
throw new NotImplementedException();
Expand Down

0 comments on commit 29141e2

Please sign in to comment.