123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- // // ******************************************************************
- // // /\ /| @File iic_decoder.cc
- // // \ V/ @Brief
- // // | "") @Author lijinwen, ghz005@uni-trend.com.cn
- // // / | @Creation 2024-07-19
- // // / \\ @Modified 2024-07-25
- // // *(__\_\
- // // ******************************************************************
- #include "iic_decoder.h"
- #include "constants.h"
- namespace Protocol
- {
- bool IicDecoder::DecodeIic(const IicDecodeOptions& option, const EdgePulseDataTwoLevels& edge_pulses_clk,
- const EdgePulseDataTwoLevels& edge_pulses_data, IicDecodeResult& result)
- {
- result = {};
- result.decoder_ptr = reinterpret_cast<intptr_t>(this);
- is_cancel_ptr_ = option.is_cancel;
- wave_data_len_ = static_cast<int32_t>(
- std::min(edge_pulses_clk.waveform_data_count, edge_pulses_data.waveform_data_count));
- bit_width_ = option.data_bit_width;
- const int32_t addr_len = bit_width_ == IicEnums::DataBitWidth::DATA_BIT_WIDTH_7_BIT ? 7 : 10;
- int32_t start_index = 0;
- packet_infos_.clear();
- packet_info_datas_.clear();
- TwoLevelEdgePulse* edge_pulses_data_ptr = edge_pulses_data.GetDataAddrPtr();
- TwoLevelEdgePulse* edge_pulses_clk_ptr = edge_pulses_clk.GetDataAddrPtr();
- /*auto t1 = offsetof(IicDataInfo, data);
- auto t2 = offsetof(IicDataInfo, ack);
- auto t3 = offsetof(IicDataInfo, ack_index);
- auto t4 = offsetof(IicDataInfo, ack_length);
- auto t5 = offsetof(IicDataInfo, success_ack);
- auto t6 = offsetof(IicDataInfo, has_ack);*/
- while (true)
- {
- // 检查是否取消
- if (is_cancel_ptr_ != nullptr && *is_cancel_ptr_)
- {
- WriteLog(LogLevel::Level2, "AsyncFunction canceled");
- return false;
- }
- while (start_index > 0 && edge_pulses_clk_ptr->start_index > start_index)
- {
- edge_pulses_clk_ptr--;
- }
- // find start index
- if (!FindStartNode(start_index, edge_pulses_data_ptr, edge_pulses_clk_ptr))
- {
- break;
- }
- //start_index = edge_pulses_data_ptr->start_index;
- int32_t data_len = wave_data_len_;
- IicEvent info = {};
- info.has_start = true;
- info.start_index = start_index;
- info.start_len = 1;
- //start_index = edge_pulses_clk_ptr++->start_index;
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- //if (start_index <= 0) break;
- //start_index = edge_pulses_clk_ptr++->start_index;
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- //if (start_index <= 0) break;
- info.addr_index = start_index;
- for (int index = 0; index < addr_len; ++index)
- {
- if (start_index >= data_len)
- {
- start_index = data_len;
- break;
- }
- if (!CommonHelper::GetNodeByIndex(start_index, edge_pulses_data_ptr))
- {
- start_index = data_len;
- break;
- }
- const bool bit = edge_pulses_data_ptr->current_level == TwoLevelEdgePulseStatusType::High;
- info.addr_data = static_cast<uint16_t>(info.addr_data << 1 | (bit ? 1 : 0));
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- }
- info.addr_len = start_index - info.addr_index;
- // 解析RW标识位
- info.rw_index = start_index;
- if (!CommonHelper::GetNodeByIndex(start_index, edge_pulses_data_ptr))
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- info.rw = edge_pulses_data_ptr->current_level == TwoLevelEdgePulseStatusType::High ? 1 : 0;//get level
- start_index = edge_pulses_clk_ptr->start_index;
- if (start_index <= 0 || (is_cancel_ptr_ != nullptr && *is_cancel_ptr_))
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- info.rw_len = start_index - info.rw_index;
- //解析Addr后的ACK信号
- info.addr_ack_index = start_index;
- info.success_addr_ack = false;
- if (start_index >= data_len)
- {
- packet_infos_.push_back(info);
- break;
- }
- if (!CommonHelper::GetNodeByIndex(start_index, edge_pulses_data_ptr))
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- info.addr_ack = edge_pulses_data_ptr->current_level == TwoLevelEdgePulseStatusType::High; //get level
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- info.addr_ack_len = start_index - info.addr_ack_index;
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (start_index <= 0 || (is_cancel_ptr_ != nullptr && *is_cancel_ptr_))
- {
- start_index = data_len;
- packet_infos_.push_back(info);
- break;
- }
- std::vector<IicDataInfo> temp_infos;
- //开始解析数据
- while (true)
- {
- int32_t stop_index = 0;
- if (info.end_index > 0)
- {
- stop_index = info.end_index;
- }
- else if (FindStopNode(start_index, edge_pulses_data_ptr, edge_pulses_clk_ptr, stop_index))
- {
- //stop_index = edge_pulses_data_ptr->start_index;
- if (stop_index > 0)
- {
- info.has_end = true;
- info.end_index = stop_index;
- info.end_len = 1;
- if (start_index >= stop_index)
- {
- start_index = stop_index + 1;
- break;
- }
- }
- //break;
- }
- //下一帧 查找下一段启动信号
- if (start_index > edge_pulses_clk_ptr->start_index)
- {
- start_index = edge_pulses_clk_ptr->start_index;
- }
- int32_t next_start_index = start_index;
- if (FindStartNode(next_start_index, edge_pulses_data_ptr, edge_pulses_clk_ptr) || (is_cancel_ptr_ != nullptr && *
- is_cancel_ptr_))
- {
- }
- else
- {
- next_start_index = -1;
- }
- if (start_index >= next_start_index && next_start_index != -1)
- {
- start_index = next_start_index - 1;
- break;
- }
- IicDataInfo data_info = {};
- data_info.index = start_index;
- //解析数据
- for (int32_t index = 0; index < 8; index++)
- {
- if (start_index >= data_len)
- {
- start_index = data_len;
- break;
- }
- if (start_index >= stop_index && stop_index > 0)
- {
- start_index = stop_index + 1;
- break;
- }
- if (start_index >= next_start_index && next_start_index > 0)
- {
- start_index = next_start_index - 1;
- break;
- }
- data_info.data <<= 1;
- if (!CommonHelper::GetNodeByIndex(start_index, edge_pulses_data_ptr))
- {
- start_index = data_len;
- break;
- }
- bool bit = edge_pulses_data_ptr->current_level == TwoLevelEdgePulseStatusType::High;
- data_info.data |= static_cast<uint8_t>(bit ? 1 : 0);
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (start_index <= 0 || (is_cancel_ptr_ != nullptr && *is_cancel_ptr_))
- {
- start_index = data_len;
- break;
- }
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (start_index <= 0 || (is_cancel_ptr_ != nullptr && *is_cancel_ptr_))
- {
- start_index = data_len;
- break;
- }
- }
- if (start_index >= data_len) break;
- if (start_index >= stop_index && stop_index > 0)
- {
- start_index = stop_index + 1;
- break;
- }
- if (start_index >= next_start_index && next_start_index != -1)
- {
- start_index = next_start_index - 1;
- break;
- }
- //计算长度
- //data_info.length = stop_index - start_index;
- data_info.length = start_index - data_info.index;
- //解析数据包后的ACK信号
- data_info.ack_index = start_index;
- if (!CommonHelper::GetNodeByIndex(start_index, edge_pulses_data_ptr))
- {
- start_index = data_len;
- break;
- }
- data_info.ack = edge_pulses_data_ptr->current_level == TwoLevelEdgePulseStatusType::High ? 1 : 0;
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (start_index <= 0 /*|| token.IsCancellationRequested || needclear*/)
- {
- start_index = data_len;
- break;
- }
- data_info.ack_length = start_index - data_info.ack_index;
- data_info.success_ack = 0;
- if (start_index >= stop_index && stop_index > 0)
- {
- start_index = stop_index + 1;
- break;
- }
- if (start_index >= next_start_index && next_start_index != -1)
- {
- start_index = next_start_index - 1;
- break;
- }
- temp_infos.push_back(data_info);
- if (!CommonHelper::FindNextNode(start_index, edge_pulses_clk_ptr) || edge_pulses_clk_ptr->start_index <= 0)
- {
- start_index = data_len;
- break;
- }
- start_index = edge_pulses_clk_ptr->start_index;
- if (start_index <= 0 || (is_cancel_ptr_ != nullptr && *is_cancel_ptr_))
- {
- start_index = data_len;
- break;
- }
- }
- //info.data_infos = temp_infos;
- //最后一个数据包的ACK信号为NACK
- if (!temp_infos.empty())
- {
- info.data_infos_index = static_cast<int32_t>(packet_info_datas_.size() + 1);
- //int32_t old_data_len = static_cast<int32_t>(packet_info_datas_.size());
- info.data_infos_count = static_cast<int32_t>(temp_infos.size());
- // 使用std::move将temp_infos的内容移动到packet_info_datas_的末尾
- packet_info_datas_.insert(packet_info_datas_.end(),
- std::make_move_iterator(temp_infos.begin()),
- std::make_move_iterator(temp_infos.end()));
- //info.data_infos_ptr = reinterpret_cast<intptr_t> (packet_info_datas_.data() + old_data_len - 1);
- info.has_end = true;
- //info.end_index = start_index;
- info.end_len = 1;
- //info.success_addr_ack = true;
- }
- packet_infos_.push_back(info);
- }
- if (!packet_infos_.empty())
- {
- result.decode_event_need_update = true;
- }
- result.decode_event_count = packet_infos_.size();
- result.decode_events_ptr = packet_infos_.data();
- result.decode_data_cell_ptr = packet_info_datas_.data();
- return true;
- }
- bool IicDecoder::FindStopNode(int32_t start_index, TwoLevelEdgePulse* node_sda,
- TwoLevelEdgePulse* node_scl, int32_t& stop_index)
- {
- if (start_index < 0)
- {
- return false;
- }
- TwoLevelEdgePulse* node_sda_tmp = node_sda;
- TwoLevelEdgePulse* node_scl_tmp = node_scl;
- const auto start_time = std::chrono::steady_clock::now();
- while (CommonHelper::CheckTwoLevelEdgePulseValid(node_sda_tmp))
- {
- // 找到SDA上升沿
- // 寻找SCL高
- /*if (node_sda_tmp->start_index > start_index || node_sda_tmp->current_level != TwoLevelEdgePulseStatusType::High)
- {
- node_sda_tmp++;
- continue;
- }*/
- while (node_sda_tmp->start_index < start_index || node_sda_tmp->current_level != TwoLevelEdgePulseStatusType::High)
- {
- node_sda_tmp++;
- if (!CommonHelper::CheckTwoLevelEdgePulseValid(node_sda_tmp))
- {
- return false;
- }
- }
- if (!CommonHelper::FindNextNode(node_sda_tmp->start_index, node_scl_tmp))
- {
- return false;
- }
- while (node_sda_tmp->start_index > node_scl_tmp->start_index)
- {
- node_scl_tmp++;
- if (!CommonHelper::CheckTwoLevelEdgePulseValid(node_scl))
- {
- return false;
- }
- }
- //sda高
- // 确认下一个SCL为低电平
- if (node_scl_tmp->current_level == TwoLevelEdgePulseStatusType::Low)
- {
- if (node_sda_tmp->start_index < node_scl_tmp->start_index)
- {
- // 找到目标停止条件
- stop_index = node_sda_tmp->start_index;
- return true;
- }
- }
- node_scl_tmp++;
- start_index = node_scl_tmp->end_index;
- //start_index = node_scl_tmp->end_index + 1;
- /* auto end_time = std::chrono::steady_clock::now();
- auto tmp = std::chrono::duration_cast<std::chrono::seconds>(
- end_time - start_time).count();*/
- if (auto end_time = std::chrono::steady_clock::now(); std::chrono::duration_cast<std::chrono::seconds>(
- end_time - start_time).count() >
- DECODE_OUT_TIME_BY_SEC)
- {
- WriteLog(LogLevel::Level2, "IIC FindStopNode TimeOut");
- return false;
- }
- }
- return CommonHelper::CheckTwoLevelEdgePulseValid(node_sda_tmp);
- }
- bool IicDecoder::FindStartNode(int32_t& start_index, TwoLevelEdgePulse* node_sda,
- TwoLevelEdgePulse* node_scl)
- {
- if (start_index < 0)
- {
- return false;
- }
- const auto start_time = std::chrono::steady_clock::now();
- while (CommonHelper::CheckTwoLevelEdgePulseValid(node_sda))
- {
- // 找到SDA下降沿
- // 寻找SCL高
- /* if (node_sda->start_index < start_index)
- {
- node_sda += 1;
- }
- if (!CommonHelper::CheckTwoLevelEdgePulseValid(node_sda))
- {
- return false;
- }
- if (node_sda->current_level != TwoLevelEdgePulseStatusType::Low)
- {
- node_sda += 1;
- }*/
- while (node_sda->start_index < start_index || node_sda->current_level != TwoLevelEdgePulseStatusType::Low)
- {
- node_sda++;
- if (!CommonHelper::CheckTwoLevelEdgePulseValid(node_sda))
- {
- return false;
- }
- }
- while (node_scl->start_index < start_index)
- {
- node_scl++;
- if (!CommonHelper::CheckTwoLevelEdgePulseValid(node_scl))
- {
- return false;
- }
- }
- //sda 低
- if (node_sda->start_index > node_scl->start_index)
- {
- node_scl += 1;
- }
- if (!CommonHelper::CheckTwoLevelEdgePulseValid(node_scl))
- {
- return false;
- }
- //找到SCL下降沿
- if (node_scl->current_level == TwoLevelEdgePulseStatusType::Low)
- {
- if (node_sda->start_index < node_scl->start_index)
- {
- //找到目标头
- start_index = node_sda->start_index;
- return true;
- }
- }
- if (node_sda->end_index < start_index)
- {
- node_sda++;
- }
- start_index = node_sda->end_index + 1;
- /*auto end_time = std::chrono::steady_clock::now();
- auto tmp = std::chrono::duration_cast<std::chrono::seconds>(
- end_time - start_time).count();*/
- if (auto end_time = std::chrono::steady_clock::now(); std::chrono::duration_cast<std::chrono::seconds>(
- end_time - start_time).count() >
- DECODE_OUT_TIME_BY_SEC)
- {
- WriteLog(LogLevel::Level2, "IIC FindStartNode TimeOut");
- return false;
- }
- }
- return CommonHelper::CheckTwoLevelEdgePulseValid(node_sda);
- }
- }
|