Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 31deb55e11ab
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: bfd990ce2a09
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 3, 2020

  1. Copy the full SHA
    e657d31 View commit details
  2. CANDecoder: Added detection of FD mode bit. Can't actually decode FD-…

    …mode frames, but we can at least identify them. See #334.
    azonenberg committed Nov 3, 2020
    Copy the full SHA
    da307e5 View commit details
  3. Copy the full SHA
    bfd990c View commit details
Showing with 119 additions and 15 deletions.
  1. +113 −13 scopeprotocols/CANDecoder.cpp
  2. +6 −2 scopeprotocols/CANDecoder.h
126 changes: 113 additions & 13 deletions scopeprotocols/CANDecoder.cpp
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ using namespace std;
// Construction / destruction

CANDecoder::CANDecoder(const string& color)
: Filter(OscilloscopeChannel::CHANNEL_TYPE_COMPLEX, color, CAT_BUS)
: PacketDecoder(OscilloscopeChannel::CHANNEL_TYPE_COMPLEX, color, CAT_BUS)
, m_baudrateName("Bit Rate")
{
//Set up channels
@@ -60,6 +60,8 @@ void CANDecoder::SetDefaultName()

void CANDecoder::Refresh()
{
ClearPackets();

//Make sure we've got valid inputs
if(!VerifyAllInputsOK())
{
@@ -87,12 +89,15 @@ void CANDecoder::Refresh()
STATE_IDLE,
STATE_SOF,
STATE_ID,
STATE_EXT_ID,
STATE_RTR,
STATE_IDE,
STATE_FD,
STATE_R0,
STATE_DLC,
STATE_DATA,
STATE_CRC,

STATE_CRC_DELIM,
STATE_ACK,
STATE_ACK_DELIM,
@@ -102,6 +107,8 @@ void CANDecoder::Refresh()
//LogDebug("Starting CAN decode\n");
//LogIndenter li;

Packet* pack = NULL;

size_t len = diff->m_samples.size();
int64_t tbitstart = 0;
int64_t tblockstart = 0;
@@ -114,7 +121,10 @@ void CANDecoder::Refresh()
uint32_t current_field = 0;
bool frame_is_rtr = false;
bool extended_id = false;
bool fd_mode = false;
int frame_bytes_left = 0;
int32_t frame_id = 0;
char tmp[128];
for(size_t i = 0; i < len; i++)
{
bool v = diff->m_samples[i];
@@ -166,6 +176,10 @@ void CANDecoder::Refresh()
if(sampled_value == last_sampled_value)
bits_since_toggle ++;

//Don't look for stuff bits at the end of the frame
else if(state >= STATE_ACK)
{}

//Discard stuff bits
else
{
@@ -198,10 +212,20 @@ void CANDecoder::Refresh()

//SOF bit is over
case STATE_SOF:

//Start a new packet
pack = new Packet;
pack->m_offset = off * diff->m_timescale;
pack->m_len = 0;
m_packets.push_back(pack);

cap->m_offsets.push_back(tblockstart);
cap->m_durations.push_back(off - tblockstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_SOF, 0));

extended_id = false;
fd_mode = false;

tblockstart = off;
nbit = 0;
current_field = 0;
@@ -219,6 +243,13 @@ void CANDecoder::Refresh()
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_ID, current_field));

state = STATE_RTR;

frame_id = current_field;

snprintf(tmp, sizeof(tmp), "%03x", frame_id);
pack->m_headers["ID"] = tmp;
pack->m_headers["Format"] = "Base";
pack->m_headers["Mode"] = "CAN";
}

break;
@@ -231,19 +262,55 @@ void CANDecoder::Refresh()
cap->m_durations.push_back(end - tbitstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_RTR, frame_is_rtr));

state = STATE_IDE;
if(extended_id)
state = STATE_FD;
else
state = STATE_IDE;

break;

//Identifier extension
case STATE_IDE:
extended_id = sampled_value;

cap->m_offsets.push_back(tbitstart);
cap->m_durations.push_back(end - tbitstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_IDE, extended_id));
if(extended_id)
{
//Delete the old ID and SRR
for(int n=0; n<2; n++)
{
cap->m_offsets.pop_back();
cap->m_durations.pop_back();
cap->m_samples.pop_back();
}

state = STATE_R0;
nbit = 0;
current_field = 0;
state = STATE_EXT_ID;
}

else
state = STATE_R0;

break;

//Full ID
case STATE_EXT_ID:

//Read the other 18 bits of the ID
if(nbit == 18)
{
frame_id = (frame_id << 18) | current_field;

cap->m_offsets.push_back(tblockstart);
cap->m_durations.push_back(end - tblockstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_ID, frame_id));

snprintf(tmp, sizeof(tmp), "%08x", frame_id);
pack->m_headers["ID"] = tmp;
pack->m_headers["Format"] = "Ext";

state = STATE_RTR;
}

break;

@@ -259,6 +326,19 @@ void CANDecoder::Refresh()
current_field = 0;
break;

//FD mode (currently ignored)
case STATE_FD:
cap->m_offsets.push_back(tbitstart);
cap->m_durations.push_back(end - tbitstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_FD, sampled_value));

fd_mode = sampled_value;
if(fd_mode)
pack->m_headers["Mode"] = "CAN-FD";

state = STATE_R0;
break;

//Data length code (4 bits)
case STATE_DLC:

@@ -294,6 +374,8 @@ void CANDecoder::Refresh()
cap->m_durations.push_back(end - tblockstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_DATA, current_field));

pack->m_data.push_back(current_field);

//Go to CRC after we've read all the data
frame_bytes_left --;
if(frame_bytes_left == 0)
@@ -338,6 +420,11 @@ void CANDecoder::Refresh()
cap->m_durations.push_back(end - tbitstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_ACK, sampled_value));

if(sampled_value)
pack->m_headers["Ack"] = "NAK";
else
pack->m_headers["Ack"] = "ACK";

state = STATE_ACK_DELIM;
break;

@@ -359,6 +446,9 @@ void CANDecoder::Refresh()
//EOF is 7 bits long
if(nbit == 7)
{
snprintf(tmp, sizeof(tmp), "%d", (int)pack->m_data.size());
pack->m_headers["Len"] = tmp;

cap->m_offsets.push_back(tblockstart);
cap->m_durations.push_back(end - tblockstart);
cap->m_samples.push_back(CANSymbol(CANSymbol::TYPE_EOF, current_field));
@@ -400,10 +490,10 @@ Gdk::Color CANDecoder::GetColor(int i)
return m_standardColors[COLOR_ERROR];

case CANSymbol::TYPE_ID:
case CANSymbol::TYPE_IDE:
return m_standardColors[COLOR_ADDRESS];

case CANSymbol::TYPE_RTR:
case CANSymbol::TYPE_FD:
return m_standardColors[COLOR_CONTROL];

case CANSymbol::TYPE_DLC:
@@ -458,17 +548,17 @@ string CANDecoder::GetText(int i)
snprintf(tmp, sizeof(tmp), "ID %03x", s.m_data);
break;

case CANSymbol::TYPE_RTR:
case CANSymbol::TYPE_FD:
if(s.m_data)
return "REQ";
return "FD";
else
return "DATA";
return "STD";

case CANSymbol::TYPE_IDE:
case CANSymbol::TYPE_RTR:
if(s.m_data)
return "EXT";
return "REQ";
else
return "BASE";
return "DATA";

case CANSymbol::TYPE_R0:
return "RSVD";
@@ -510,3 +600,13 @@ string CANDecoder::GetText(int i)
return "ERROR";
}

vector<string> CANDecoder::GetHeaders()
{
vector<string> ret;
ret.push_back("ID");
ret.push_back("Format");
ret.push_back("Mode");
ret.push_back("Ack");
ret.push_back("Len");
return ret;
}
8 changes: 6 additions & 2 deletions scopeprotocols/CANDecoder.h
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@
#ifndef CANDecoder_h
#define CANDecoder_h

#include "PacketDecoder.h"

class CANSymbol
{
public:
@@ -15,8 +17,8 @@ class CANSymbol
TYPE_SOF,
TYPE_ID,
TYPE_RTR,
TYPE_IDE,
TYPE_R0,
TYPE_FD,
TYPE_DLC,
TYPE_DATA,
TYPE_CRC_OK,
@@ -47,7 +49,7 @@ class CANSymbol

typedef Waveform<CANSymbol> CANWaveform;

class CANDecoder : public Filter
class CANDecoder : public PacketDecoder
{
public:
CANDecoder(const std::string& color);
@@ -61,6 +63,8 @@ class CANDecoder : public Filter
static std::string GetProtocolName();
virtual void SetDefaultName();

std::vector<std::string> GetHeaders();

virtual bool ValidateChannel(size_t i, StreamDescriptor stream);

PROTOCOL_DECODER_INITPROC(CANDecoder)