/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ #ifndef IMSCOPE_INTERNAL_H #define IMSCOPE_INTERNAL_H #include <mutex> #include <fstream> #include <vector> #include <fstream> #include "openair1/PHY/defs_nr_UE.h" extern "C" { #include "../phy_scope_interface.h" } #define MAX_OFFSETS 14 const char *scope_id_to_string(scopeDataType type); typedef struct ImScopeData { scopeGraphData_t *scope_graph_data; metadata meta; uint64_t time_taken_in_ns; uint64_t time_taken_in_ns_per_offset[MAX_OFFSETS]; size_t data_copied_per_offset[MAX_OFFSETS]; int scope_id; void dump_to_file(std::ofstream& stream) { stream.write((char*)scope_graph_data, sizeof(*scope_graph_data)); stream.write((char*)&meta, sizeof(meta)); stream.write((char*)&scope_id, sizeof(scope_id)); char *source = (char *)(scope_graph_data + 1); stream.write(source, scope_graph_data->dataSize); } void read_from_file(std::ifstream& stream) { scopeGraphData_t temp; stream.read((char*)&temp, sizeof(temp)); stream.read((char*)&meta, sizeof(meta)); stream.read((char*)&scope_id, sizeof(scope_id)); scope_graph_data = static_cast<scopeGraphData_t *>(malloc(temp.dataSize + sizeof(*scope_graph_data))); *scope_graph_data = temp; char *dest = (char *)(scope_graph_data + 1); stream.read(dest, temp.dataSize); } friend std::ostream& operator<<(std::ostream& os, const ImScopeData& dt); } ImScopeData; typedef struct MovingAverageTimer { uint64_t sum = 0; float average = 0; float last_update_time = 0; void UpdateAverage(float time) { if (time > last_update_time + 1) { float new_average = sum / (float)((time - last_update_time) / 1000); average = 0.95 * average + 0.05 * new_average; sum = 0; } } void Add(uint64_t ns) { sum += ns; } } MovingAverageTimer; typedef struct ImScopeDataWrapper { std::mutex write_mutex; bool is_data_ready; ImScopeData data; } ImScopeDataWrapper; typedef struct IQData { std::vector<int16_t> real; std::vector<int16_t> imag; int16_t max_iq; std::vector<float> power; float max_power; float timestamp; int nonzero_count; int len = 0; metadata meta; int scope_id; bool TryCollect(ImScopeDataWrapper *imscope_data_wrapper, float time, float epsilon, MovingAverageTimer &iq_procedure_timer) { if (imscope_data_wrapper->is_data_ready) { Collect(&imscope_data_wrapper->data, time, epsilon); iq_procedure_timer.Add(imscope_data_wrapper->data.time_taken_in_ns); imscope_data_wrapper->is_data_ready = false; return true; } return false; } void Collect(ImScopeData *scope_data, float time, float epsilon) { timestamp = time; scopeGraphData_t *iq_header = scope_data->scope_graph_data; len = iq_header->lineSz; real.resize(len); imag.resize(len); power.resize(len); c16_t *source = (c16_t *)(iq_header + 1); max_iq = 0; nonzero_count = 0; for (auto i = 0; i < len; i++) { real[i] = source[i].r; imag[i] = source[i].i; max_iq = std::max(max_iq, (int16_t)std::abs(source[i].r)); max_iq = std::max(max_iq, (int16_t)std::abs(source[i].i)); nonzero_count = std::abs(source[i].r) > epsilon || std::abs(source[i].i) > epsilon ? nonzero_count + 1 : nonzero_count; power[i] = std::sqrt(std::pow(source[i].r, 2) + std::pow(source[i].i, 2)); } meta = scope_data->meta; scope_id = scope_data->scope_id; } } IQData; extern ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES]; void copyDataThreadSafe(void *scopeData, enum scopeDataType type, void *dataIn, int elementSz, int colSz, int lineSz, int offset, metadata *meta); bool tryLockScopeData(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta); void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index); void unlockScopeData(enum scopeDataType type); void dumpScopeData(int slot, int frame); void *imscope_record_thread(void *data_void_ptr); void *imscope_thread(void *data_void_ptr); #endif