1 // 2 // Copyright 2020 Ettus Research, a National Instruments Brand 3 // 4 // SPDX-License-Identifier: GPL-3.0-or-later 5 // 6 7 #pragma once 8 9 #include <uhd/config.hpp> 10 #include <stddef.h> 11 #include <string> 12 #include <vector> 13 #include <functional> 14 15 namespace uhd { namespace usrp { namespace cal { 16 17 //! Identify the source of calibration data, i.e., where was it stored 18 // 19 // This enum lists the sources in reverse order of priority, i.e., user-provided 20 // data has the highest priority, and hard-coded data from the resource compiler 21 // has the lowest priority. 22 enum class source { 23 NONE, //!< No calibration data available 24 ANY, //!< Undefined source 25 RC, //!< Internal Resource Compiler (i.e., hard-coded within UHD) 26 FLASH, //!< Stored on device flash memory, e.g. EEPROM 27 FILESYSTEM, //!< Stored on the local filesystem 28 USER //!< Provided by the user 29 }; 30 31 /*! Calibration Data Storage/Retrieval Class 32 * 33 * UHD can store calibration data on disk or compiled within UHD. This class 34 * provides access to both locations. 35 * 36 * \section cal_db_blob Format of binary data 37 * 38 * This class can read and write binary data, but it does not verify the data 39 * or expect any kind of format. It simply manages BLOBs (binary large objects). 40 * It is up to the consumers and producers of this data to agree on a format. 41 * Typically, since this class stores calibration data, it will be consuming 42 * data that was produced by uhd::usrp::cal::container::serialize(). 43 * 44 * \section cal_db_serial Serial number and key 45 * 46 * Calibration data is indexed by two keys: An arbitrary key that describes the 47 * type of calibration data (e.g., "rx_iq") and a serial number. The serial 48 * number has to uniquely identify the device for which the calibration data was 49 * obtained. This can either be the serial number of the daughterboard (if the 50 * calibration data only relates to the daughterboard), the motherboard (for 51 * example, if there is no such thing as a daughterboard, or the data only 52 * relates to the motherboard), it can be combination of both daughterboard and 53 * motherboard serial (if the calibration data is only valid for a combination), 54 * or it can be a combination of a device serial number and a channel index 55 * (if a device with single serial has different channels that have separate 56 * characteristics). 57 * 58 * It is up to the individual device drivers which value they use for the serial 59 * numbers and keys. 60 * 61 * Note that the serial number is irrelevant when the data is pulled out of the 62 * resource compiler. By definition, it is not permitted to store data in the 63 * resource compiler that is specific to a certain serial number, only data that 64 * applies to an entire family of devices is permitted. 65 */ 66 class UHD_API database 67 { 68 public: 69 //! Return a calibration data set as a serialized string 70 // 71 // Note: the \p source_type parameter can be used to specify where to read 72 // cal data from. However, this class only has 73 // access to RC and FILESYSTEM type cal data. ANY 74 // will pick FILESYSTEM data if both are available, 75 // and RC data if only RC data is available. 76 // \param key The calibration type key (e.g., "rx_iq") 77 // \param serial The serial number of the device this data is for. See also 78 // \ref cal_db_serial 79 // \param source_type Where to read the calibration data from. See comments 80 // above. For anything other than RC, FILESYSTEM, or ANY, 81 // this will always throw a uhd::key_error because this 82 // class does not have access to user data or EEPROM data. 83 // 84 // \throws uhd::key_error if no calibration data is found matching the source 85 // type. 86 static std::vector<uint8_t> read_cal_data(const std::string& key, 87 const std::string& serial, 88 const source source_type = source::ANY); 89 90 //! Check if calibration data exists for a given source type 91 // 92 // This can be called before calling read_cal_data() to avoid having to 93 // catch an exception. If \p source_type is FILESYSTEM, then it will only 94 // return true if a file is found with the appropriate cal data. The same 95 // is true for RC. If \p is ANY, then having either RC or FILESYSTEM data 96 // will yield true. 97 // 98 // \param key The calibration type key (e.g., "rx_iq") 99 // \param serial The serial number of the device this data is for. See also 100 // \ref cal_db_serial 101 // \param source_type Where to read the calibration data from. For anything 102 // other than RC, FILESYSTEM, or ANY, this will always 103 // return false because this class does not have access 104 // to user data or EEPROM data. 105 // \return true if calibration data is available that matches this key/serial 106 // pair. 107 static bool has_cal_data(const std::string& key, 108 const std::string& serial, 109 const source source_type = source::ANY); 110 111 //! Store calibration data to the local filesystem database 112 // 113 // This implies a source type of FILESYSTEM. Note that writing the data does 114 // not apply it to a currently running UHD session. Devices will typically 115 // load calibration data at initialization time, and thus this call will 116 // take effect only for future UHD sessions. 117 // 118 // If calibration data for this key/serial pair already exists in the 119 // database, the original data will be backed up by renaming the original 120 // file from `filename.cal` to `filename.cal.$TIMESTAMP`. Alternatively, a 121 // custom extension can be chosen instead of `$TIMESTAMP`. 122 // 123 // \param key The calibration type key (e.g., "rx_iq") 124 // \param serial The serial number of the device this data is for. See also 125 // \ref cal_db_serial 126 // \param cal_data The calibration data to be written 127 // \param backup_ext A custom extension for backing up calibration data. If 128 // left empty, a POSIX timestamp is used. 129 static void write_cal_data(const std::string& key, 130 const std::string& serial, 131 const std::vector<uint8_t>& cal_data, 132 const std::string& backup_ext = ""); 133 134 //! Function type to look up if there is cal data given a key and serial 135 using has_data_fn_type = std::function<bool(const std::string&, const std::string&)>; 136 137 //! Function type to return serialized cal data key and serial 138 // 139 // These functions should throw a uhd::runtime_error if called with invalid 140 // key/serial pairs, although database will internally always call the 141 // corresponding 'has' function before calling this. 142 using get_data_fn_type = 143 std::function<std::vector<uint8_t>(const std::string&, const std::string&)>; 144 145 //! Register a lookup function for cal data 146 // 147 // \param has_cal_data A function object to a function that returns true if 148 // cal data is available 149 // \param get_cal_data A function object to a function that returns serialized 150 // cal data 151 // \param source_type Reserved. Must be source::FLASH. 152 static void register_lookup(has_data_fn_type has_cal_data, 153 get_data_fn_type get_cal_data, 154 const source source_type = source::FLASH); 155 }; 156 157 158 }}} // namespace uhd::usrp::cal 159