// // ****************************************************************** // // /\ /| @File spi_decoder.cc // // \ V/ @Brief // // | "") @Author lijinwen, ghz005@uni-trend.com.cn // // / | @Creation 2024-07-19 // // / \\ @Modified 2024-07-23 // // *(__\_\ // // ****************************************************************** #include "spi_decoder.h" #include "../BaseHelper/common_helper.h" #include "../BaseHelper/constants.h" namespace Protocol { bool SpiDecoder::DecodeSpi(const SpiDecodeOptions& options, const EdgePulseDataTwoLevels& edge_pulse_data_clk, const EdgePulseDataTwoLevels& edge_pulse_data_cs, const EdgePulseDataTwoLevels& edge_pulse_data_mosi, const EdgePulseDataTwoLevels& edge_pulse_data_miso, SpiDecodeResult& decode_result) { is_cancel_ptr_ = options.is_cancel; decode_result = {}; decode_result.decoder_ptr = reinterpret_cast(this); need_decode_data_ = true; bool checked_params = true; if (edge_pulse_data_clk.waveform_data_count <= 0 || edge_pulse_data_cs.waveform_data_count <= 0 || edge_pulse_data_clk.sample_rate <= 0 || edge_pulse_data_cs.sample_rate <= 0) { checked_params = false; } const bool decode_mosi = options.decode_channel == SpiEnums::DecodeChannel::MOMI || options.decode_channel == SpiEnums::DecodeChannel::MOSI; const bool decode_miso = options.decode_channel == SpiEnums::DecodeChannel::MOMI || options.decode_channel == SpiEnums::DecodeChannel::MISO; if (decode_mosi && (edge_pulse_data_mosi.waveform_data_count <= 0 || edge_pulse_data_mosi.sample_rate <= 0)) { checked_params = false; } if (decode_miso && (edge_pulse_data_miso.waveform_data_count <= 0 || edge_pulse_data_miso.sample_rate <= 0)) { checked_params = false; } if (!checked_params) { need_decode_data_ = false; need_update_view_info_ = true; /*miso_data.clear(); mosi_data.clear();*/ data_packet_info_.clear(); packet_infos_.clear(); return false; } try { if (need_decode_data_) { /* miso_data.clear(); mosi_data.clear();*/ data_packet_info_.clear(); packet_infos_.clear(); need_decode_data_ = false; need_update_view_info_ = true; try { int32_t packet_index = 0, last_packet_index = 0; uint64_t cs_len = edge_pulse_data_cs.waveform_data_count; uint64_t clk_len = edge_pulse_data_clk.waveform_data_count; uint64_t miso_len = 0; uint64_t mosi_len = 0; uint64_t min_data_len = std::min(cs_len, clk_len); TwoLevelEdgePulse* edge_pulse_data_cs_ptr = edge_pulse_data_cs.GetDataAddrPtr(); TwoLevelEdgePulse* edge_pulse_data_clk_ptr = edge_pulse_data_clk.GetDataAddrPtr(); TwoLevelEdgePulse* edge_pulse_data_miso_ptr = nullptr; TwoLevelEdgePulse* edge_pulse_data_mosi_ptr = nullptr; if (decode_miso) { miso_len = edge_pulse_data_miso.waveform_data_count; edge_pulse_data_miso_ptr = edge_pulse_data_miso.GetDataAddrPtr(); min_data_len = std::min(min_data_len, miso_len); } if (decode_mosi) { mosi_len = edge_pulse_data_mosi.waveform_data_count; edge_pulse_data_mosi_ptr = edge_pulse_data_mosi.GetDataAddrPtr(); min_data_len = std::min(min_data_len, mosi_len); } data_len_ = static_cast(min_data_len); if (data_len_ == 0) { WriteLog(LogLevel::Level2, "data_len == 0"); return false; } int32_t cs_start_index = -1; const bool clk_state = options.clk_polarity == Polarity::POS; while (true) { // 检查是否取消 if (is_cancel_ptr_ != nullptr && *is_cancel_ptr_) { WriteLog(LogLevel::Level2, "AsyncFunction canceled"); return false; } if (!FindStartNode(packet_index, cs_start_index, edge_pulse_data_cs_ptr, edge_pulse_data_clk_ptr, options.cs_polarity, options.clk_polarity)) { WriteLog(LogLevel::Level2, "Not find start node"); break; } if (packet_index < 0) break; SpiPacket packet_info = {}; packet_info.start_index = cs_start_index; packet_info.start_len = 1; packet_info.has_start = cs_start_index >= 0 ? 1 : 0; if (!GetCsBitNextIndex(options.cs_polarity == Polarity::POS, packet_index, edge_pulse_data_cs_ptr)) { break; } const auto cs_end_index = edge_pulse_data_cs_ptr->start_index; if (is_cancel_ptr_ != nullptr && *is_cancel_ptr_) { WriteLog(LogLevel::Level2, "AsyncFunction canceled"); return false; } if (bool need_clear = false; need_clear) break; if (cs_end_index > packet_index) { packet_info.has_end = 1; packet_info.end_len = 1; packet_info.end_index = cs_end_index; } std::vector temp_data_packets; //数据解码 while (true) { DataPacketInfo temp_data_packet = {}; //std::vector temp_miso_datas = {}, temp_mosi_datas = {}; temp_data_packet.bit_count = frame_count_; temp_data_packet.index = packet_index; int32_t temp_miso_data = 0, temp_mosi_data = 0; bool get_miso_data = false, get_mosi_data = false; for (int32_t bit_index = 0; bit_index < frame_count_; ++bit_index) { bool miso_bit = false; bool mosi_bit = false; if (decode_miso) { if (!CommonHelper::GetNodeByIndex(packet_index, edge_pulse_data_miso_ptr)) { get_miso_data = false; break; } miso_bit = edge_pulse_data_miso_ptr->current_level == TwoLevelEdgePulseStatusType::High; if (options.miso_polarity == Polarity::NEG) { miso_bit = !miso_bit; } get_miso_data = true; } if (decode_mosi) { if (!CommonHelper::GetNodeByIndex(packet_index, edge_pulse_data_mosi_ptr)) { get_miso_data = false; break; } mosi_bit = edge_pulse_data_mosi_ptr->current_level == TwoLevelEdgePulseStatusType::High; if (options.mosi_polarity == Polarity::NEG) { mosi_bit = !mosi_bit; } get_mosi_data = true; } if (options.msb_lsb == SpiEnums::Msblsb::MSB) { temp_miso_data <<= 1; temp_miso_data |= (miso_bit ? 1 : 0); temp_mosi_data <<= 1; temp_mosi_data |= (mosi_bit ? 1 : 0); } else { temp_miso_data |= (miso_bit ? 1 : 0) << bit_index; temp_mosi_data |= (mosi_bit ? 1 : 0) << bit_index; } temp_data_packet.real_bit_count = bit_index + 1; if (!GetClkEdge(!clk_state, packet_index, edge_pulse_data_clk_ptr)) { break; } if ((packet_index > cs_end_index && cs_end_index >= 0) || packet_index == -1) { temp_data_packet.is_last = 1; break; } } if (packet_index > cs_end_index && cs_end_index != -1) { packet_index = cs_end_index; temp_data_packet.len = packet_index - temp_data_packet.index; } if (packet_index == -1) { if (cs_end_index != -1) { temp_data_packet.len = cs_end_index - temp_data_packet.index; } else { temp_data_packet.len = static_cast(miso_len - temp_data_packet.index); } } else if (packet_index >= temp_data_packet.index && temp_data_packet.len == 0) { temp_data_packet.len = packet_index - temp_data_packet.index; } //if (temp_data_packet.real_bit_count > 0) temp_data_packets.push_back(temp_data_packet); //end if (temp_data_packet.real_bit_count > 0) { //miso if (decode_miso) { temp_data_packet.miso_data_count = get_miso_data ? 1 : 0; if (temp_data_packet.miso_data_count > 0) { /* int32_t last_data_count = miso_data.size(); miso_data.push_back(temp_miso_data); temp_data_packet.miso_data_ptr = miso_data.data() + last_data_count; */ temp_data_packet.miso_data = static_cast(temp_miso_data); } } //mosi if (decode_mosi) { temp_data_packet.mosi_data_count = get_mosi_data ? 1 : 0; if (temp_data_packet.mosi_data_count > 0) { /*int32_t last_data_count = mosi_data.size(); mosi_data.push_back(temp_mosi_data); temp_data_packet.mosi_data_ptr = mosi_data.data() + last_data_count;*/ temp_data_packet.mosi_data = static_cast(temp_mosi_data); } } temp_data_packets.push_back(temp_data_packet); } if (temp_data_packet.is_last == 1 || packet_index >= data_len_) break; if (last_packet_index == packet_index) { break; } last_packet_index = packet_index; } //packet packet_info.data_count = static_cast(temp_data_packets.size()); if (packet_info.data_count > 0) { int32_t last_data_count = static_cast(data_packet_info_.size()); // 复制到末尾 data_packet_info_.insert(data_packet_info_.end(), std::make_move_iterator(temp_data_packets.begin()), std::make_move_iterator(temp_data_packets.end())); packet_info.data_ptr = reinterpret_cast(data_packet_info_.data() + last_data_count - 1); packet_info.data_info = temp_data_packets[0]; } packet_infos_.push_back(packet_info); if (decode_miso && packet_index >= static_cast(miso_len)) { break; } if (decode_mosi && packet_index >= static_cast(mosi_len)) { break; } if (packet_index < 0) { break; } } } catch (const std::exception& ex) { std::string error_message = "DecodeSpi Error: " + std::string(ex.what()); WriteLog(LogLevel::Level2, error_message.c_str()); } } } catch (const std::exception& ex) { std::string error_message = "DecodeSpi Error: " + std::string(ex.what()); WriteLog(LogLevel::Level2, error_message.c_str()); } if (need_update_view_info_) { need_update_view_info_ = false; if (packet_infos_.size() > 0) { decode_result.decode_events_ptr = packet_infos_.data(); decode_result.decode_event_count = packet_infos_.size(); } } return true; } bool SpiDecoder::GetClkEdge(const bool state, int32_t& start_index, TwoLevelEdgePulse*& node_clk) { if (!CommonHelper::GetNodeByIndex(start_index, node_clk)) { return false; } if (node_clk->current_level == TwoLevelEdgePulseStatusType::High != state) { if (!CommonHelper::FindNextNode(start_index, node_clk)) { return false; } start_index = node_clk->start_index; if (start_index < 0) return false; } if (start_index < 0) return false; if (!CommonHelper::FindNextNode(start_index, node_clk)) { return false; } start_index = node_clk->start_index; if (start_index < 0) return false; return true; } bool SpiDecoder::FindStartNode(int32_t& start_index, int32_t& cs_start_index, TwoLevelEdgePulse*& node_cs, TwoLevelEdgePulse*& node_clk, const Polarity polarity_cs, const Polarity polarity_clk) const { cs_start_index = -1; if (start_index >= data_len_) return false; const bool state = polarity_cs == Polarity::POS; const bool clk_state = polarity_clk == Polarity::NEG; if (!CommonHelper::GetNodeByIndex(start_index, node_cs)) { return false; } if (node_cs->current_level == TwoLevelEdgePulseStatusType::High != state) { if (!CommonHelper::FindNextNode(start_index, node_cs)) { return false; } cs_start_index = node_cs->start_index; if (cs_start_index < 0) return false; } else { if (start_index > 0) { cs_start_index = start_index; } } if (cs_start_index >= 0) { start_index = cs_start_index; } const auto start_time = std::chrono::steady_clock::now(); while (true) { if (!CommonHelper::GetNodeByIndex(start_index, node_clk)) { return false; } if (node_clk->current_level == TwoLevelEdgePulseStatusType::High != clk_state) { if (!CommonHelper::FindNextNode(start_index, node_clk)) { return false; } start_index = node_clk->start_index; } if (start_index <= 0) return false; if (!CommonHelper::FindNextNode(start_index, node_clk)) { return false; } start_index = node_clk->start_index; if (start_index <= 0) return false; if (!CommonHelper::GetNodeByIndex(start_index, node_cs)) { return false; } if (node_cs->current_level == TwoLevelEdgePulseStatusType::High == state) return node_cs->start_index; if (auto end_time = std::chrono::steady_clock::now(); std::chrono::duration_cast( end_time - start_time).count() > DECODE_OUT_TIME_BY_SEC) { WriteLog(LogLevel::Level2, "IIC FindStopNode TimeOut"); return false; } } } bool SpiDecoder::GetCsBitNextIndex(const bool state, int32_t start_index, TwoLevelEdgePulse*& node_cs) { if (!CommonHelper::GetNodeByIndex(start_index, node_cs)) { return false; } if (node_cs->current_level == TwoLevelEdgePulseStatusType::High != state) { if (!CommonHelper::FindNextNode(start_index, node_cs)) { return false; } start_index = node_cs->start_index; } if (start_index == -1) return false; if (!CommonHelper::FindNextNode(start_index, node_cs)) { return false; } //start_index = node_cs->start_index; return true; } }