diff --git a/plugins/regmap/CMakeLists.txt b/plugins/regmap/CMakeLists.txt index c20ea306c6..6357b4dfef 100644 --- a/plugins/regmap/CMakeLists.txt +++ b/plugins/regmap/CMakeLists.txt @@ -77,7 +77,9 @@ configure_file( ) set(SRC_LIST ${SRC_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/include/${SCOPY_MODULE}/scopy-${SCOPY_MODULE}_config.h) -add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES} ${PROJECT_RESOURCES}) +add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES} ${PROJECT_RESOURCES} + src/regmap_api.h + src/regmap_api.cpp) generate_export_header( ${PROJECT_NAME} EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/${SCOPY_MODULE}/${PROJECT_NAME}_export.h diff --git a/plugins/regmap/include/regmap/regmapplugin.h b/plugins/regmap/include/regmap/regmapplugin.h index cd3329c56c..8d8b4800ce 100644 --- a/plugins/regmap/include/regmap/regmapplugin.h +++ b/plugins/regmap/include/regmap/regmapplugin.h @@ -24,9 +24,11 @@ namespace regmap { class RegisterMapTool; class JsonFormatedElement; +class RegMap_API; class SCOPY_REGMAP_EXPORT RegmapPlugin : public QObject, public PluginBase { + friend class RegMap_API; Q_OBJECT SCOPY_PLUGIN; @@ -59,6 +61,8 @@ public Q_SLOTS: struct iio_device *getIioDevice(iio_context *ctx, const char *dev_name); bool isBufferCapable(iio_device *dev); RegisterMapTool *registerMapTool; + void InitApi(); + RegMap_API *api; }; } // namespace regmap } // namespace scopy diff --git a/plugins/regmap/src/deviceregistermap.cpp b/plugins/regmap/src/deviceregistermap.cpp index 97d80b8d03..96a33149eb 100644 --- a/plugins/regmap/src/deviceregistermap.cpp +++ b/plugins/regmap/src/deviceregistermap.cpp @@ -220,6 +220,8 @@ bool DeviceRegisterMap::hasTemplate() return false; } +bool DeviceRegisterMap::getAutoread() { return autoread; } + void DeviceRegisterMap::initSettings() { QObject::connect(this, &DeviceRegisterMap::requestRead, registerMapValues, &RegisterMapValues::requestRead); diff --git a/plugins/regmap/src/deviceregistermap.hpp b/plugins/regmap/src/deviceregistermap.hpp index 9b004fab3b..c44ddf6c5c 100644 --- a/plugins/regmap/src/deviceregistermap.hpp +++ b/plugins/regmap/src/deviceregistermap.hpp @@ -24,6 +24,7 @@ class RegisterMapTable; class SCOPY_REGMAP_EXPORT DeviceRegisterMap : public QWidget { + friend class RegMap_API; Q_OBJECT public: explicit DeviceRegisterMap(RegisterMapTemplate *registerMapTemplate = nullptr, @@ -34,6 +35,7 @@ class SCOPY_REGMAP_EXPORT DeviceRegisterMap : public QWidget void toggleAutoread(bool toggled); void applyFilters(QString filter); bool hasTemplate(); + bool getAutoread(); private: ToolTemplate *tool; diff --git a/plugins/regmap/src/registermapsettingsmenu.hpp b/plugins/regmap/src/registermapsettingsmenu.hpp index 0454062dc1..30b09651f6 100644 --- a/plugins/regmap/src/registermapsettingsmenu.hpp +++ b/plugins/regmap/src/registermapsettingsmenu.hpp @@ -15,6 +15,7 @@ namespace regmap { class RegisterMapSettingsMenu : public QWidget { friend class RegmapStyleHelper; + friend class RegMap_API; Q_OBJECT diff --git a/plugins/regmap/src/registermaptool.hpp b/plugins/regmap/src/registermaptool.hpp index 0d119ea9a8..da53182c44 100644 --- a/plugins/regmap/src/registermaptool.hpp +++ b/plugins/regmap/src/registermaptool.hpp @@ -23,6 +23,7 @@ class SearchBarWidget; class SCOPY_REGMAP_EXPORT RegisterMapTool : public QWidget { + friend class RegMap_API; Q_OBJECT public: explicit RegisterMapTool(QWidget *parent = nullptr); diff --git a/plugins/regmap/src/regmap_api.cpp b/plugins/regmap/src/regmap_api.cpp new file mode 100644 index 0000000000..dd551d2c62 --- /dev/null +++ b/plugins/regmap/src/regmap_api.cpp @@ -0,0 +1,101 @@ +#include "regmap_api.h" + +using namespace scopy::regmap; + +Q_LOGGING_CATEGORY(CAT_REGMAP_API, "RegMap_API") + +RegMap_API::RegMap_API(RegmapPlugin *regMapPlugin) + : ApiObject() + , m_regMapPlugin(regMapPlugin) +{} + +RegMap_API::~RegMap_API() {} + +void RegMap_API::write(QString addr, QString val) +{ + DeviceRegisterMap *devRegMap = getActiveDevRegMap(); + Q_EMIT devRegMap->registerMapValues->requestWrite(addr.toUInt(nullptr, 16), val.toUInt(nullptr, 16)); +} + +QStringList RegMap_API::getAvailableDevicesName() +{ + QStringList devicesName; + if(m_regMapPlugin->m_deviceList->size() != 0) { + for(const auto &dev : *(m_regMapPlugin->m_deviceList)) { + devicesName.append(iio_device_get_name(dev)); + } + } else { + qWarning(CAT_REGMAP_API) << "No devices available"; + } + return devicesName; +} + +bool RegMap_API::setDevice(QString device) +{ + m_regMapPlugin->registerMapTool->updateActiveRegisterMap(device); + QString currentRegMap = m_regMapPlugin->registerMapTool->activeRegisterMap; + if(currentRegMap == device) { + return true; + } + qWarning(CAT_REGMAP_API) << "Device " << device << " was not set"; + return false; +} + +QStringList RegMap_API::search(QString searchParam) +{ + QList resultIndexes; + DeviceRegisterMap *devRegMap = getActiveDevRegMap(); + resultIndexes = Search::searchForRegisters(devRegMap->registerMapTemplate->getRegisterList(), searchParam); + + QStringList resultList; + for(int i = 0; i < resultIndexes.size(); i++) { + RegisterModel *model = devRegMap->registerMapTemplate->getRegisterTemplate(resultIndexes[i]); + resultList.append(model->getName()); + } + return resultList; +} + +QStringList RegMap_API::readInterval(QString startAddr, QString stopAddr) +{ + DeviceRegisterMap *devRegMap = getActiveDevRegMap(); + uint32_t start = startAddr.toUInt(nullptr, 16); + uint32_t stop = stopAddr.toUInt(nullptr, 16); + QStringList readValues; + for(int i = start; i < stop; i++) { + Q_EMIT devRegMap->registerMapValues->requestRead(i); + } + return readValues; +} + +bool RegMap_API::enableAutoread(bool enable) +{ + DeviceRegisterMap *devRegMap = getActiveDevRegMap(); + devRegMap->toggleAutoread(enable); + if(devRegMap->getAutoread() == enable) { + return true; + } + qWarning(CAT_REGMAP_API) << "Autoread was not changed to " << enable; + return false; +} + +bool RegMap_API::isAutoreadEnabled() +{ + DeviceRegisterMap *devRegMap = getActiveDevRegMap(); + return devRegMap->getAutoread(); +} + +void RegMap_API::registerDump(QString filePath) +{ + DeviceRegisterMap *devRegMap = getActiveDevRegMap(); + Q_EMIT devRegMap->registerMapValues->registerDump(filePath); +} + +void RegMap_API::writeFromFile(QString filePath) +{ + +} + +DeviceRegisterMap *RegMap_API::getActiveDevRegMap() +{ + return m_regMapPlugin->registerMapTool->deviceList->value(m_regMapPlugin->registerMapTool->activeRegisterMap); +} diff --git a/plugins/regmap/src/regmap_api.h b/plugins/regmap/src/regmap_api.h new file mode 100644 index 0000000000..4a05188fa3 --- /dev/null +++ b/plugins/regmap/src/regmap_api.h @@ -0,0 +1,39 @@ +#ifndef REGMAP_API_H +#define REGMAP_API_H + +#include "scopy-regmap_export.h" + +#include +#include +#include +#include +#include +#include "search.hpp" + +namespace scopy::regmap { + +class SCOPY_REGMAP_EXPORT RegMap_API : public ApiObject +{ + + Q_OBJECT + +public: + explicit RegMap_API(RegmapPlugin *regMapPlugin); + ~RegMap_API(); + + Q_INVOKABLE void write(QString addr, QString val); + Q_INVOKABLE QStringList getAvailableDevicesName(); + Q_INVOKABLE bool setDevice(QString device); + Q_INVOKABLE QStringList search(QString searchParam); + Q_INVOKABLE QStringList readInterval(QString startAddr, QString stopAddr); + Q_INVOKABLE bool enableAutoread(bool enable); + Q_INVOKABLE bool isAutoreadEnabled(); + Q_INVOKABLE void registerDump(QString filePath); + Q_INVOKABLE void writeFromFile(QString filePath); + +private: + RegmapPlugin *m_regMapPlugin; + DeviceRegisterMap *getActiveDevRegMap(); +}; +} // namespace scopy::regmap +#endif // REGMAP_API_H diff --git a/plugins/regmap/src/regmapplugin.cpp b/plugins/regmap/src/regmapplugin.cpp index 6f8e8c529c..8a3ef99202 100644 --- a/plugins/regmap/src/regmapplugin.cpp +++ b/plugins/regmap/src/regmapplugin.cpp @@ -27,12 +27,14 @@ #include #include #include "logging_categories.h" +#include #include "iioutil/connectionprovider.h" #include "jsonformatedelement.hpp" #include "scopy-regmap_config.h" #include "utils.hpp" #include "utils.hpp" +#include #if defined __APPLE__ #include #endif @@ -185,6 +187,7 @@ bool RegmapPlugin::onConnect() m_toolList[0]->setEnabled(true); m_toolList[0]->setTool(m_registerMapWidget); + InitApi(); return true; } @@ -275,4 +278,11 @@ bool RegmapPlugin::isBufferCapable(iio_device *dev) return false; } +void RegmapPlugin::InitApi() +{ + api = new RegMap_API(this); + ScopyJS *js = ScopyJS::GetInstance(); + api->setObjectName("regmap"); + js->registerApi(api); +} #include "moc_regmapplugin.cpp" diff --git a/tools/plugingenerator/README.md b/tools/plugingenerator/README.md index a47afd0ce4..84dca76fe4 100644 --- a/tools/plugingenerator/README.md +++ b/tools/plugingenerator/README.md @@ -1,14 +1,14 @@ -# Plugin generator +# Plugin generator ## Pre-request `pip install -r requirements.txt` -## Run plugin generator script: +## Run plugin generator script 1. If it is run from "scopy/tools/plugingenerator" - - `python plugin_generator.py` + + `./plugin_generator.py` 2. Otherwise @@ -16,72 +16,94 @@ For help: `python plugin_generator.py -h` -### After running the script, you must insert the new plugin in plugins/CMakeLists.txt: +### After running the script, you must insert the new plugin in plugins/CMakeLists.txt + ``` option(ENABLE_PLUGIN_NEWPLUGIN "Enable NEWPLUGIN plugin" ON) if(ENABLE_PLUGIN_NEWPLUGIN) - add_subdirectory(new) - list(APPEND PLUGINS ${PLUGIN_NAME}) + add_subdirectory(new) + list(APPEND PLUGINS ${PLUGIN_NAME}) endif() ``` -## Config.json attributes explanation: - - 1. plugin: Contains details specific to the plugin. - 1.1 dir_name (string): The name of the plugin directory. - 1.2 plugin_name (string): The plugin name. The header and source files will have this name. - 1.3 class_name (string): The name of the class that will be created for the plugin. - 1.4 cmakelists (bool): If true a CMakeLists file will be created for the plugin. - 1.5 namespace (string): The namespace the plugin belongs to. - - The name of namespace should be short, meaningful, concise, and all lower-case. - - Try to avoid use of underscores inside namespace names. - - The keyword "namespace" is filled in automatically. All you have to do is to write the identifier (name of the namespace). - - For nested namespaces use the scope resolution operator (::). - 1.6 device_category (string): The category the plugin belogs to. (iio for example) - 1.7 tools: List wich contains the tools to be implemented and used by the plugin. - 1.7.1 id (string): Tool id. - 1.7.2 tool_name (string): The name that appears in Scopy. - 1.7.3 file_name (string): The tool header and source file will have this name. - - No special character is allowed in the file name except for underscore (‘_’) and dash (‘-‘). - - Do not use filenames that already exist in /user/include. or any predefined header file name. - 1.7.4 class_name (string): The name of the class that will be created for the tool. - - The class name should be a noun. - - Use upper case letters as word separators, and lower case for the rest of the word. - - The first character in the class name must be in upper case. - - No underscores (‘_’) are permitted in the class name. - 1.7.5 namespace (string): The namespace the tool belongs to. - - 2. cmakelists: Contains the details of the CMakeLists. - 2.1 cmake_min_required (float): Require a minimum version of cmake. - 2.2 cxx_standard (int): The C++ standard whose features are requested to build this target. - 2.3 enable_testing (string): Enables the tests for the plugin. The only accepted variants - are "ON" and "OFF". - - 3. test: Contains the details of the plugin tests. - 3.1 mkdir (bool): If true the test directory is created. - 3.2 cmakelists (bool): If true a CMakeLists file will be created for the tests. - 3.3 cmake_min_required (float): Require a minimum version of cmake. - 3.4 tst_pluginloader (bool): If true the pluginloader test is created. - 4. doc: Contains the details of the plugin documentation. - 4.1 mkdir (bool): If true the doc directory is created. - - 5. resources: Contains the details of the plugin resources. - 5.1 mkdir (bool): If true the res directory is created. - 5.2 resources_qrc (bool): If true the resources_qrc file is created. - - *All fields must be filled in. + +## Config.json attributes explanation + +1. **pdk**: Contains the configuration options of the plugin development tool. + 1. `enable` (bool): If true a ScopyPluginRunner project will be created at `project_path`. + - If pdk is enabled, the plugin will be generated in the ScopyPluginRunner project. + 2. `deps_path` (string): The path to the scopy pdk package (the package must be unzipped). + 3. `project_path` (string): The path to the directory where the PluginRunner project is created. +2. **plugin**: Contains details specific to the plugin. + 1. `dir_name` (string): The name of the plugin directory. + 2. `plugin_name` (string): The plugin name. The header and source files will have this name. + 3. `class_name` (string): The name of the class that will be created for the plugin. + 4. `cmakelists` (bool): If true a CMakeLists file will be created for the plugin. + 5. `namespace` (string): The namespace the plugin belongs to. + - The name of namespace should be short, meaningful, concise, and all lower-case. + - Try to avoid use of underscores inside namespace names. + - The keyword "namespace" is filled in automatically. All you have to do is to write the identifier (name of the namespace). + - For nested namespaces use the scope resolution operator (::). + 6. `device_category` (string): The category the plugin belongs to. (iio for example) + 7. `tools`: List which contains the tools to be implemented and used by the plugin. + 1. `id` (string): Tool id. + 2. `tool_name` (string): The name that appears in Scopy. + 3. `file_name` (string): The tool header and source file will have this name. + - No special character is allowed in the file name except for underscore (‘_’) and dash (‘-‘). + - Do not use filenames that already exist in /user/include. or any predefined header file name. + 4. `class_name` (string): The name of the class that will be created for the tool. + - The class name should be a noun. + - Use upper case letters as word separators, and lower case for the rest of the word. + - The first character in the class name must be in upper case. + - No underscores (‘_’) are permitted in the class name. + 5. `namespace` (string): The namespace the tool belongs to. +3. **cmakelists**: Contains the details of the CMakeLists. + 1. `cmake_min_required` (float): Require a minimum version of cmake. + 2. `cxx_standard` (int): The C++ standard whose features are requested to build this target. + 3. `enable_testing` (string): Enables the tests for the plugin. The only accepted variants are "ON" and "OFF". +4. **test**: Contains the details of the plugin tests. + 1. `mkdir` (bool): If true the test directory is created. + 2. `cmakelists` (bool): If true a CMakeLists file will be created for the tests. + 3. `cmake_min_required` (float): Require a minimum version of cmake. + 4. `tst_pluginloader` (bool): If true the pluginloader test is created. +5. **doc**: Contains the details of the plugin documentation. + 1. `mkdir` (bool): If true the doc directory is created. +6. **resources**: Contains the details of the plugin resources. + 1. `mkdir` (bool): If true the res directory is created. + 2. `resources_qrc` (bool): If true the resources_qrc file is created. + +*All fields must be filled in. + +## Scopy PDK + +### Add new modules to the PDK package + +If we want a new module from Scopy to be part of the package, then when installing libraries or directories in CMakeLists, the option `COMPONENT ${SCOPY_PDK}` must be added. + +- libraries: `install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${SCOPY_DLL_INSTALL_PATH} COMPONENT ${SCOPY_PDK} RUNTIME DESTINATION ${SCOPY_DLL_INSTALL_PATH})`. +- headers: `install(DIRECTORY include/ DESTINATION include/ COMPONENT ${SCOPY_PDK})`. +- resources: `install(DIRECTORY res/ DESTINATION resources/ COMPONENT ${SCOPY_PDK})`. + +### Develop a new plugin using ScopyPluginRunner + +1. Download the PDK package from the Scopy repository. + - If the package is not available or if changes have been made to the Scopy libraries, then Scopy must be built locally with the `--target package` option. + - In this case a `package` folder will be generated inside the Scopy build folder. +2. Generate the ScopyPluginRunner project using the `plugin_generator.py`. + - Fill in the `config.json` file. + - This project contains a `plugin` submodule where the desired plugin can be developed. +3. Choose an IDE and start working. + - Our recommendation is to use QtCreator. ## Adding new config specifications -For fields like "plugin", "tool" and "cmakelists" new specifications can be added. +For fields like `plugin`, `tool` and `cmakelists` new specifications can be added. A few steps must be completed: -1. Add the new specification in the desired field (add new fields in 'config.json'). -2. Use the specification in the templates. Each template contains a 'config' variable through which -the information from each field can be accessed. A specific syntax must be used because the script uses the -the mako library to render the templates. [Watch mako documentation page for more details.](https://docs.makotemplates.org/en/latest/) - - the changes made in the 'plugin' field will be reflected in the 'plugin_src_template' and 'plugin_header_template' template files - - the changes made in the 'tool' field will be reflected in the 'tool_src_template' and 'tool_header_template' template files - - the changes made in the 'cmakelists' field will be reflected in the 'cmakelists_template' template file -3. Run the plugin_generator.py script. - - +1. Add the new specification in the desired field (add new fields in `config.json`). +2. Use the specification in the templates. Each template contains a `config` variable through which +the information from each field can be accessed. A specific syntax must be used because the script uses the +the mako library to render the templates. [Watch mako documentation page for more details.](https://docs.makotemplates.org/en/latest/) + - the changes made in the `plugin` field will be reflected in the **plugin_src_template** and **plugin_header_template** template files + - the changes made in the `tool` field will be reflected in the **tool_src_template** and **tool_header_template** template files + - the changes made in the `cmakelists` field will be reflected in the **cmakelists_template** template file +3. Run the `plugin_generator.py` script.