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: 5293d7dfacde
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 94ad19cfefed
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Apr 18, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    141ad88 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0a0d03b View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    94ad19c View commit details
Showing with 419 additions and 137 deletions.
  1. +395 −133 scopeprotocols/ESPIDecoder.cpp
  2. +24 −4 scopeprotocols/ESPIDecoder.h
528 changes: 395 additions & 133 deletions scopeprotocols/ESPIDecoder.cpp
Original file line number Diff line number Diff line change
@@ -103,6 +103,8 @@ vector<string> ESPIDecoder::GetHeaders()
vector<string> ret;
ret.push_back("Command");
ret.push_back("Address");
ret.push_back("Len");
ret.push_back("Tag");
ret.push_back("Info");
ret.push_back("Response");
ret.push_back("Status");
@@ -178,7 +180,13 @@ void ESPIDecoder::Refresh()

TXN_STATE_VWIRE_COUNT,
TXN_STATE_VWIRE_INDEX,
TXN_STATE_VWIRE_DATA
TXN_STATE_VWIRE_DATA,

TXN_STATE_FLASH_TYPE,
TXN_STATE_FLASH_TAG_LENHI,
TXN_STATE_FLASH_LENLO,
TXN_STATE_FLASH_ADDR,
TXN_STATE_FLASH_DATA

} txn_state = TXN_STATE_IDLE;

@@ -198,6 +206,7 @@ void ESPIDecoder::Refresh()
uint8_t crc = 0;
uint64_t data = 0;
uint64_t addr = 0;
size_t flash_len = 0;

int skip_bits = 0;
bool skip_next_falling = false;
@@ -206,6 +215,7 @@ void ESPIDecoder::Refresh()
uint8_t current_byte = 0;
bool byte_valid_next = false;
ESPISymbol::ESpiCompletion completion_type = ESPISymbol::COMPLETION_NONE;
ESPISymbol::ESpiFlashType flash_type = ESPISymbol::FLASH_READ;

while(true)
{
@@ -351,6 +361,9 @@ void ESPIDecoder::Refresh()
{
switch(txn_state)
{
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generic command parsing

//Nothign to do
case TXN_STATE_IDLE:
break; //end STATE_IDLE
@@ -387,12 +400,19 @@ void ESPIDecoder::Refresh()
txn_state = TXN_STATE_CONFIG_ADDRESS;
break;

//Expect a full flash completion TODO
case ESPISymbol::COMMAND_PUT_FLASH_C:
txn_state = TXN_STATE_FLASH_TYPE;
break;

//No arguments
case ESPISymbol::COMMAND_GET_STATUS:
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_STATUS];
txn_state = TXN_STATE_COMMAND_CRC8;
break;
case ESPISymbol::COMMAND_GET_FLASH_NP:
txn_state = TXN_STATE_COMMAND_CRC8;
break;
case ESPISymbol::COMMAND_GET_VWIRE:
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_READ];
txn_state = TXN_STATE_COMMAND_CRC8;
@@ -447,10 +467,6 @@ void ESPIDecoder::Refresh()
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_COMMAND];
txn_state = TXN_STATE_IDLE;
break;
case ESPISymbol::COMMAND_PUT_FLASH_C:
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_WRITE];
txn_state = TXN_STATE_IDLE;
break;

case ESPISymbol::COMMAND_GET_OOB:
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_READ];
@@ -470,6 +486,33 @@ void ESPIDecoder::Refresh()

break; //end TXN_STATE_OPCODE

case TXN_STATE_COMMAND_CRC8:

cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
if(current_byte == crc)
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_COMMAND_CRC_GOOD, current_byte));
else
{
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_COMMAND_CRC_BAD, current_byte));
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_ERROR];
}

//Expect a response after a 2-cycle bus turnaround
txn_state = TXN_STATE_RESPONSE;
skip_bits = 2;

//Switch read polarity
if(read_mode == READ_SI)
read_mode = READ_SO;
else if(read_mode == READ_QUAD_RISING)
read_mode = READ_QUAD_FALLING;

break; //end TXN_STATE_COMMAND_CRC8

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration packets

case TXN_STATE_CONFIG_ADDRESS:

//Save start time
@@ -551,43 +594,8 @@ void ESPIDecoder::Refresh()

break; //end TXN_STATE_CONFIG_DATA

case TXN_STATE_COMMAND_CRC8:

cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
if(current_byte == crc)
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_COMMAND_CRC_GOOD, current_byte));
else
{
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_COMMAND_CRC_BAD, current_byte));
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_ERROR];
}

switch(current_cmd)
{
//Expect a response after a 2-cycle bus turnaround
case ESPISymbol::COMMAND_GET_CONFIGURATION:
case ESPISymbol::COMMAND_SET_CONFIGURATION:
case ESPISymbol::COMMAND_GET_STATUS:
case ESPISymbol::COMMAND_GET_FLASH_NP:
case ESPISymbol::COMMAND_GET_VWIRE:
txn_state = TXN_STATE_RESPONSE;
skip_bits = 2;
break;

//don't know what to do
default:
txn_state = TXN_STATE_IDLE;
break;
}

//Switch read polarity
if(read_mode == READ_SI)
read_mode = READ_SO;
else if(read_mode == READ_QUAD_RISING)
read_mode = READ_QUAD_FALLING;

break; //end TXN_STATE_COMMAND_CRC8
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generic reply packets

case TXN_STATE_RESPONSE:

@@ -598,7 +606,10 @@ void ESPIDecoder::Refresh()
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_OP, current_byte));

//TODO: support appended completions
completion_type = static_cast<ESPISymbol::ESpiCompletion>(current_byte >> 6);
if(completion_type != ESPISymbol::COMPLETION_NONE)
LogWarning("Appended completions not implemented yet\n");

pack->m_headers["Response"] = GetText(cap->m_samples.size()-1);

@@ -611,20 +622,138 @@ void ESPIDecoder::Refresh()
txn_state = TXN_STATE_RESPONSE_DATA;
break;

case ESPISymbol::COMMAND_GET_STATUS:
txn_state = TXN_STATE_STATUS;
break;

case ESPISymbol::COMMAND_GET_VWIRE:
txn_state = TXN_STATE_VWIRE_COUNT;
break;

case ESPISymbol::COMMAND_GET_FLASH_NP:
txn_state = TXN_STATE_FLASH_TYPE;
break;

case ESPISymbol::COMMAND_GET_STATUS:
default:
txn_state = TXN_STATE_IDLE;
txn_state = TXN_STATE_STATUS;
break;
}

break; //end TXN_STATE_RESPONSE

case TXN_STATE_RESPONSE_DATA:

if(count == 0)
{
tstart = bytestart;
cap->m_offsets.push_back(tstart);
}

//per page 93, data is LSB to MSB
data |= current_byte << ( (count & 3) * 8);
count ++;

pack->m_data.push_back(current_byte);

//TODO: different commands have different lengths for reply data
if(count == 4)
{
cap->m_durations.push_back(timestamp - tstart);

switch(current_cmd)
{
case ESPISymbol::COMMAND_GET_CONFIGURATION:
switch(addr)
{
case 0x8:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_GENERAL_CAPS, data));
pack->m_headers["Info"] = Trim(GetText(cap->m_samples.size()-1));
break;

case 0x20:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_CH1_CAPS_RD, data));
pack->m_headers["Info"] = Trim(GetText(cap->m_samples.size()-1));
break;

case 0x30:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_CH2_CAPS_RD, data));
pack->m_headers["Info"] = Trim(GetText(cap->m_samples.size()-1));
break;

default:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_DATA_32, data));
break;
}
break;

default:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_DATA_32, data));
break;
}

count = 0;
data = 0;
txn_state = TXN_STATE_STATUS;
}

break; //end TXN_STATE_RESPONSE_DATA

case TXN_STATE_STATUS:

//Save start time
if(count == 0)
{
tstart = bytestart;
cap->m_offsets.push_back(tstart);
}

//Save data (LSB to MSB)
data |= current_byte << ( (count & 3) * 8);
count ++;

//Add data
if(count == 2)
{
cap->m_durations.push_back(timestamp - tstart);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_STATUS, data));

//Don't report free space in the protocol analyzer
//to save column space
string tmp;
if(data & 0x2000)
tmp += "FLASH_NP_AVAIL ";
if(data & 0x1000)
tmp += "FLASH_C_AVAIL ";
if(data & 0x0200)
tmp += "FLASH_NP_FREE ";
if(data & 0x0080)
tmp += "OOB_AVAIL ";
if(data & 0x0040)
tmp += "VWIRE_AVAIL ";
pack->m_headers["Status"] = tmp;

txn_state = TXN_STATE_RESPONSE_CRC8;
}

break; //end TXN_STATE_STATUS

case TXN_STATE_RESPONSE_CRC8:

cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
if(current_byte == crc)
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_CRC_GOOD, current_byte));
else
{
LogDebug("Invalid response CRC (got %02x, expected %02x)\n", current_byte, crc);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_CRC_BAD, current_byte));
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_ERROR];
}

//Done with the packet
txn_state = TXN_STATE_IDLE;
break; //end TXN_STATE_COMMAND_CRC8

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Virtual wire channel

case TXN_STATE_VWIRE_COUNT:
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
@@ -772,64 +901,92 @@ void ESPIDecoder::Refresh()

break; //end TXN_STATE_VWIRE_DATA

case TXN_STATE_RESPONSE_DATA:
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Flash channel

if(count == 0)
case TXN_STATE_FLASH_TYPE:
pack->m_data.push_back(current_byte);

cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_FLASH_REQUEST_TYPE, current_byte));
txn_state = TXN_STATE_FLASH_TAG_LENHI;

flash_type = (ESPISymbol::ESpiFlashType)current_byte;

switch(flash_type)
{
tstart = bytestart;
cap->m_offsets.push_back(tstart);
case ESPISymbol::FLASH_ERASE:
pack->m_headers["Info"] = "Erase";
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_WRITE];
break;

case ESPISymbol::FLASH_READ:
pack->m_headers["Info"] = "Read";
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_READ];
break;

case ESPISymbol::FLASH_WRITE:
pack->m_headers["Info"] = "Write";
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_WRITE];
break;

case ESPISymbol::FLASH_SUCCESS_DATA_FIRST:
case ESPISymbol::FLASH_SUCCESS_DATA_MIDDLE:
case ESPISymbol::FLASH_SUCCESS_DATA_LAST:
case ESPISymbol::FLASH_SUCCESS_DATA_ONLY:
pack->m_headers["Info"] = "Read Data";
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_READ];
break;

default:
pack->m_headers["Info"] = "Unknown flash op";
break;
}

//per page 93, data is LSB to MSB
data |= current_byte << ( (count & 3) * 8);
count ++;
break; //end TXN_STATE_FLASH_TYPE

case TXN_STATE_FLASH_TAG_LENHI:
pack->m_data.push_back(current_byte);

//TODO: different commands have different lengths for reply data
if(count == 4)
{
cap->m_durations.push_back(timestamp - tstart);
//Tag is high 4 bits
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_FLASH_REQUEST_TAG, current_byte >> 4));
pack->m_headers["Tag"] = to_string(current_byte >> 4);

switch(current_cmd)
{
case ESPISymbol::COMMAND_GET_CONFIGURATION:
switch(addr)
{
case 0x8:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_GENERAL_CAPS, data));
pack->m_headers["Info"] = Trim(GetText(cap->m_samples.size()-1));
break;
//Low 4 bits of this byte are the high length bits
data = current_byte & 0xf;

case 0x20:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_CH1_CAPS_RD, data));
pack->m_headers["Info"] = Trim(GetText(cap->m_samples.size()-1));
break;
txn_state = TXN_STATE_FLASH_LENLO;
break; //end TXN_STATE_FLASH_TAG_LENHI

case 0x30:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_CH2_CAPS_RD, data));
pack->m_headers["Info"] = Trim(GetText(cap->m_samples.size()-1));
break;
case TXN_STATE_FLASH_LENLO:
pack->m_data.push_back(current_byte);

default:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_DATA_32, data));
break;
}
break;
//Save the rest of the length
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
flash_len = current_byte | data;
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_FLASH_REQUEST_LEN, flash_len));

default:
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_DATA_32, data));
break;
}
pack->m_headers["Len"] = to_string(flash_len);

count = 0;
data = 0;
txn_state = TXN_STATE_STATUS;
//Get ready to read the address or data
count = 0;
data = 0;

if(flash_type >= ESPISymbol::FLASH_SUCCESS_NODATA)
{
pack->m_data.clear();
txn_state = TXN_STATE_FLASH_DATA;
}
else
txn_state = TXN_STATE_FLASH_ADDR;

break; //end TXN_STATE_RESPONSE_DATA
break; //end TXN_STATE_FLASH_LENLO

case TXN_STATE_STATUS:
case TXN_STATE_FLASH_ADDR:

//Save start time
if(count == 0)
@@ -838,52 +995,66 @@ void ESPIDecoder::Refresh()
cap->m_offsets.push_back(tstart);
}

//Save data (LSB to MSB)
data |= current_byte << ( (count & 3) * 8);
//Save address (MSB to LSB)
data = (data << 8) | current_byte;
count ++;

//Add data
if(count == 2)
if(count == 4)
{
cap->m_durations.push_back(timestamp - tstart);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_STATUS, data));
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_FLASH_REQUEST_ADDR, data));

//Don't report free space in the protocol analyzer
//to save column space
string tmp;
if(data & 0x2000)
tmp += "FLASH_NP_AVAIL ";
if(data & 0x1000)
tmp += "FLASH_C_AVAIL ";
if(data & 0x0200)
tmp += "FLASH_NP_FREE ";
if(data & 0x0080)
tmp += "OOB_AVAIL ";
if(data & 0x0040)
tmp += "VWIRE_AVAIL ";
pack->m_headers["Status"] = tmp;
char tmp[32];
snprintf(tmp, sizeof(tmp), "%08lx", data);
pack->m_headers["Address"] = tmp;

txn_state = TXN_STATE_RESPONSE_CRC8;
count = 0;
data = 0;

//Write requests are followed by data
if(flash_type == ESPISymbol::FLASH_WRITE)
{
pack->m_data.clear();
txn_state = TXN_STATE_FLASH_DATA;
}

//Reads and erases are done after the address
else
txn_state = TXN_STATE_STATUS;
}

break; //end TXN_STATE_STATUS
break; //end TXN_STATE_FLASH_ADDR

case TXN_STATE_RESPONSE_CRC8:
case TXN_STATE_FLASH_DATA:

pack->m_data.push_back(current_byte);

//Save the data byte
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(timestamp - bytestart);
if(current_byte == crc)
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_CRC_GOOD, current_byte));
else
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_FLASH_REQUEST_DATA, current_byte));

//See if we're done
count ++;
if(count >= flash_len)
{
LogDebug("Invalid response CRC (got %02x, expected %02x)\n", current_byte, crc);
cap->m_samples.push_back(ESPISymbol(ESPISymbol::TYPE_RESPONSE_CRC_BAD, current_byte));
pack->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_ERROR];
count = 0;
data = 0;

//Completion? Done with command
if(current_cmd == ESPISymbol::COMMAND_PUT_FLASH_C)
txn_state = TXN_STATE_COMMAND_CRC8;

//Request? Done with response
else
txn_state = TXN_STATE_STATUS;
}

//Done with the packet
txn_state = TXN_STATE_IDLE;
break; //end TXN_STATE_COMMAND_CRC8
break; //end TXN_STATE_FLASH_DATA

}

//Checksum this byte
@@ -942,14 +1113,15 @@ Gdk::Color ESPIDecoder::GetColor(int i)
case ESPISymbol::TYPE_COMMAND_TYPE:
case ESPISymbol::TYPE_RESPONSE_OP:
case ESPISymbol::TYPE_RESPONSE_STATUS:
case ESPISymbol::TYPE_FLASH_REQUEST_TYPE:
case ESPISymbol::TYPE_FLASH_REQUEST_LEN:
return m_standardColors[COLOR_CONTROL];

case ESPISymbol::TYPE_CAPS_ADDR:
case ESPISymbol::TYPE_VWIRE_COUNT:
case ESPISymbol::TYPE_VWIRE_INDEX:
/*case ESPISymbol::TYPE_COMMAND_ADDR_16:
case ESPISymbol::TYPE_COMMAND_ADDR_32:
case ESPISymbol::TYPE_COMMAND_ADDR_64:*/
case ESPISymbol::TYPE_FLASH_REQUEST_TAG:
case ESPISymbol::TYPE_FLASH_REQUEST_ADDR:
return m_standardColors[COLOR_ADDRESS];

case ESPISymbol::TYPE_COMMAND_CRC_GOOD:
@@ -967,6 +1139,7 @@ Gdk::Color ESPIDecoder::GetColor(int i)
case ESPISymbol::TYPE_VWIRE_DATA:
case ESPISymbol::TYPE_COMMAND_DATA_32:
case ESPISymbol::TYPE_RESPONSE_DATA_32:
case ESPISymbol::TYPE_FLASH_REQUEST_DATA:
return m_standardColors[COLOR_DATA];

default:
@@ -1106,6 +1279,7 @@ string ESPIDecoder::GetText(int i)
stmp += "x1 mode\n";
break;
case 1:

stmp += "x2 mode\n";
break;
case 2:
@@ -1312,11 +1486,12 @@ string ESPIDecoder::GetText(int i)

return stmp; //end TYPE_CH2_CAPS_WR

case ESPISymbol::TYPE_COMMAND_DATA_32:
snprintf(tmp, sizeof(tmp), "%08lx", s.m_data);
case ESPISymbol::TYPE_FLASH_REQUEST_DATA:
snprintf(tmp, sizeof(tmp), "%02lx", s.m_data);
return tmp;

case ESPISymbol::TYPE_RESPONSE_DATA_32:
case ESPISymbol::TYPE_COMMAND_DATA_32:
snprintf(tmp, sizeof(tmp), "%08lx", s.m_data);
return tmp;

@@ -1343,18 +1518,35 @@ string ESPIDecoder::GetText(int i)
stmp += "PC_FREE";
return stmp;

/*case ESPISymbol::TYPE_COMMAND_ADDR_16:
snprintf(tmp, sizeof(tmp), "Addr: %04lx", s.m_data);
return tmp;
case ESPISymbol::TYPE_FLASH_REQUEST_TYPE:
switch(s.m_data)
{
case ESPISymbol::FLASH_READ:
return "Read";
case ESPISymbol::FLASH_WRITE:
return "Write";
case ESPISymbol::FLASH_ERASE:
return "Erase";

case ESPISymbol::FLASH_SUCCESS_NODATA:
case ESPISymbol::FLASH_SUCCESS_DATA_FIRST:
case ESPISymbol::FLASH_SUCCESS_DATA_MIDDLE:
case ESPISymbol::FLASH_SUCCESS_DATA_LAST:
case ESPISymbol::FLASH_SUCCESS_DATA_ONLY:
return "Success";
}
break;

case ESPISymbol::TYPE_FLASH_REQUEST_TAG:
return string("Tag: ") + to_string(s.m_data);

case ESPISymbol::TYPE_FLASH_REQUEST_LEN:
return string("Len: ") + to_string(s.m_data);

case ESPISymbol::TYPE_COMMAND_ADDR_32:
case ESPISymbol::TYPE_FLASH_REQUEST_ADDR:
snprintf(tmp, sizeof(tmp), "Addr: %08lx", s.m_data);
return tmp;

case ESPISymbol::TYPE_COMMAND_ADDR_64:
snprintf(tmp, sizeof(tmp), "Addr: %016lx", s.m_data);
return tmp;*/

case ESPISymbol::TYPE_ERROR:
default:
return "ERROR";
@@ -1363,12 +1555,82 @@ string ESPIDecoder::GetText(int i)
return "";
}

bool ESPIDecoder::CanMerge(Packet* /*first*/, Packet* /*cur*/, Packet* /*next*/)
bool ESPIDecoder::CanMerge(Packet* first, Packet* /*cur*/, Packet* next)
{
//Merge a "Get Status" with subsequent "Get Flash Non-Posted"
if( (first->m_headers["Command"] == "Get Status") &&
(first->m_headers["Status"].find("FLASH_NP_AVAIL") != string::npos) &&
(next->m_headers["Command"] == "Get Flash Non-Posted") )
{
return true;
}

//Merge a "Get Status" with subsequent "Put Flash Completion"
//TODO: Only if the tags match!
if( (first->m_headers["Command"] == "Get Status") &&
(first->m_headers["Status"].find("FLASH_NP_AVAIL") != string::npos) &&
(next->m_headers["Command"] == "Put Flash Completion") )
{
return true;
}

return false;
}

Packet* ESPIDecoder::CreateMergedHeader(Packet* /*pack*/, size_t /*i*/)
Packet* ESPIDecoder::CreateMergedHeader(Packet* pack, size_t i)
{
return NULL;
Packet* ret = new Packet;
ret->m_offset = pack->m_offset;
ret->m_len = pack->m_len; //TODO: extend?

Packet* first = m_packets[i];

if(first->m_headers["Command"] == "Get Status")
{
//Look up the second packet in the string (the flash request)
if(i+1 < m_packets.size())
{
Packet* second = m_packets[i+1];

//It's a flash transaction
if(second->m_headers["Command"] == "Get Flash Non-Posted")
{
ret->m_headers["Address"] = second->m_headers["Address"];
ret->m_headers["Len"] = second->m_headers["Len"];
ret->m_headers["Tag"] = second->m_headers["Tag"];

if(second->m_headers["Info"] == "Read")
{
ret->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_READ];
ret->m_headers["Command"] = "Flash Read";
}
else if(second->m_headers["Info"] == "Write")
{
ret->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_WRITE];
ret->m_headers["Command"] = "Flash Write";
}
else if(second->m_headers["Info"] == "Erase")
{
ret->m_displayBackgroundColor = m_backgroundColors[PROTO_COLOR_DATA_WRITE];
ret->m_headers["Command"] = "Flash Erase";
}

//Append any flash completions we find
//TODO: handle out-of-order here
for(size_t j=i+2; j<m_packets.size(); j++)
{
Packet* p = m_packets[j];
if(p->m_headers["Command"] != "Put Flash Completion")
break;
if(p->m_headers["Tag"] != second->m_headers["Tag"])
break;

for(auto b : p->m_data)
ret->m_data.push_back(b);
}
}
}
}

return ret;
}
28 changes: 24 additions & 4 deletions scopeprotocols/ESPIDecoder.h
Original file line number Diff line number Diff line change
@@ -47,10 +47,6 @@ class ESPISymbol

TYPE_CAPS_ADDR,

/*TYPE_COMMAND_ADDR_16,
TYPE_COMMAND_ADDR_32,
TYPE_COMMAND_ADDR_64,*/

TYPE_COMMAND_DATA_8,
TYPE_COMMAND_DATA_32,
TYPE_COMMAND_CRC_GOOD,
@@ -72,6 +68,12 @@ class ESPISymbol
TYPE_CH2_CAPS_RD,
TYPE_CH2_CAPS_WR,

TYPE_FLASH_REQUEST_TYPE,
TYPE_FLASH_REQUEST_TAG,
TYPE_FLASH_REQUEST_LEN,
TYPE_FLASH_REQUEST_ADDR,
TYPE_FLASH_REQUEST_DATA,

TYPE_ERROR
} m_type;

@@ -136,6 +138,24 @@ class ESPISymbol
COMPLETION_FLASH = 3
};

//Table 6
enum ESpiFlashType
{
FLASH_READ = 0,
FLASH_WRITE = 1,
FLASH_ERASE = 2,

//completion types
FLASH_SUCCESS_NODATA = 0x06,
FLASH_SUCCESS_DATA_MIDDLE = 0x09,
FLASH_SUCCESS_DATA_FIRST = 0x0b,
FLASH_SUCCESS_DATA_LAST = 0x0d,
FLASH_SUCCESS_DATA_ONLY = 0x0f,

FLASH_FAIL_LAST = 0x08,
FLASH_FAIL_ONLY = 0x0e
};

uint64_t m_data;
ESPISymbol()
{}