From 2d17a361e5c35884e76aeb6e81275e37f5539846 Mon Sep 17 00:00:00 2001
From: Martin Hierholzer <martin.hierholzer@desy.de>
Date: Fri, 20 Mar 2020 16:04:15 +0100
Subject: [PATCH] added skeleton for TecDummy

---
 config/dummydevice.map                        | 10 ++--
 tests/CMakeLists.txt                          | 11 +++--
 .../testTecModule.cc}                         |  0
 tests/include/TecDummy.h                      | 36 ++++++++++++++
 tests/src/TecDummy.cc                         | 48 +++++++++++++++++++
 5 files changed, 97 insertions(+), 8 deletions(-)
 rename tests/{testTemplateModule.cc => executable_src/testTecModule.cc} (100%)
 create mode 100644 tests/include/TecDummy.h
 create mode 100644 tests/src/TecDummy.cc

diff --git a/config/dummydevice.map b/config/dummydevice.map
index 61c02a6..a675be4 100644
--- a/config/dummydevice.map
+++ b/config/dummydevice.map
@@ -1,6 +1,6 @@
 # name                                                          n_words      address      n_bytes    BAR  n_bits  n_fractionalBits  signed   access
-UNIO0.BIT_TEC1091_ENABLE                                              1         4576            4      1       1                 0       0       RW
-UNIO0.BIT_TEC1091_CMD_LOOP_START                                      1         4580            4      1       1                 0       0       RW
-UNIO0.BIT_TEC1091_CMD_LOOP_DONE                                       1         4584            4      1       1                 0       0       RO
-UNIO0.AREA_TEC1091_CMD                                              256         5120         1024      1      32                 0       0       RW
-
+# note: addresses are hardcoded in the TecDummy!
+UNIO0.BIT_TEC1091_ENABLE                                              1            0            4      0       1                 0       0       RW
+UNIO0.BIT_TEC1091_CMD_LOOP_START                                      1            4            4      0       1                 0       0       RW
+UNIO0.BIT_TEC1091_CMD_LOOP_DONE                                       1            8            4      0       1                 0       0       RO
+UNIO0.AREA_TEC1091_CMD                                              256           12         1024      0      32                 0       0       RW
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 65207ab..24b7356 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -5,11 +5,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)
 # Add BOOST dependencies
 FIND_PACKAGE(Boost COMPONENTS thread system unit_test_framework REQUIRED)
 
-# The tests also require the server headers (TODO Potentially, module includes are also needed)
+# The tests also require the server headers
 include_directories(${CMAKE_SOURCE_DIR}/server/include)
 
+# build library with dummy device etc.
+include_directories(include)
+aux_source_directory(src testlibrary_sources)
+add_library(${PROJECT_NAME}testlib ${testlibrary_sources})
+
 # Add all tests residing in the "tests" directory
-aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} testExecutables)
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/executable_src testExecutables)
 foreach( testExecutableSrcFile ${testExecutables})
   #NAME_WE means the base name without path and (longest) extension
   get_filename_component(excutableName ${testExecutableSrcFile} NAME_WE)
@@ -19,7 +24,7 @@ foreach( testExecutableSrcFile ${testExecutables})
     PROPERTIES 
     LINK_FLAGS "${CMAKE_LINK_FLAGS}"
   )
-  target_link_libraries(${excutableName} ${PROJECT_NAME}lib ${ChimeraTK-ApplicationCore_LIBRARIES} ${Adapter_LIBRARIES} )
+  target_link_libraries(${excutableName} ${PROJECT_NAME}lib ${ChimeraTK-ApplicationCore_LIBRARIES} ${Adapter_LIBRARIES} ${PROJECT_NAME}testlib)
   add_test(
     NAME ${excutableName}
     COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${excutableName}
diff --git a/tests/testTemplateModule.cc b/tests/executable_src/testTecModule.cc
similarity index 100%
rename from tests/testTemplateModule.cc
rename to tests/executable_src/testTecModule.cc
diff --git a/tests/include/TecDummy.h b/tests/include/TecDummy.h
new file mode 100644
index 0000000..b46de59
--- /dev/null
+++ b/tests/include/TecDummy.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <ChimeraTK/DummyBackend.h>
+#include <ChimeraTK/BackendFactory.h>
+#include <ChimeraTK/DummyRegisterAccessor.h>
+
+struct TecDummy : ChimeraTK::DummyBackend {
+  TecDummy(std::string mapFileName) : DummyBackend(mapFileName) {}
+  ~TecDummy() override;
+
+  // hardcoded addresses used by the dummy, need to match addresses of map file
+  constexpr static uint8_t TecDummy_bar{0};
+  constexpr static uint32_t TecDummy_address_loopDone{8};
+
+  // Accessors for the registers
+  ChimeraTK::DummyRegisterAccessor<uint32_t> reg_loopStart{this, "UNIO0", "BIT_TEC1091_CMD_LOOP_START"};
+  ChimeraTK::DummyRegisterAccessor<uint32_t> reg_loopDone{this, "UNIO0", "BIT_TEC1091_CMD_LOOP_DONE"};
+  ChimeraTK::DummyRegisterAccessor<uint32_t> reg_command{this, "UNIO0", "AREA_TEC1091_CMD"};
+
+  static boost::shared_ptr<DeviceBackend> createInstance(std::string, std::map<std::string, std::string> parameters) {
+    return boost::shared_ptr<DeviceBackend>(new TecDummy(parameters["map"]));
+  }
+
+  void read(uint8_t bar, uint32_t address, int32_t* data, size_t sizeInBytes) override;
+
+  // In this function the TEC device is actually simulated.
+  std::string dataProcessing(const std::string& command);
+
+  class BackendRegisterer {
+   public:
+    BackendRegisterer();
+  };
+  static BackendRegisterer backendRegisterer;
+};
+
+TecDummy::BackendRegisterer TecDummy::backendRegisterer;
diff --git a/tests/src/TecDummy.cc b/tests/src/TecDummy.cc
new file mode 100644
index 0000000..d4dfe04
--- /dev/null
+++ b/tests/src/TecDummy.cc
@@ -0,0 +1,48 @@
+#include "TecDummy.h"
+
+/*********************************************************************************************************************/
+
+TecDummy::BackendRegisterer::BackendRegisterer() {
+  std::cout << "TecDummy::BackendRegisterer: registering backend type TecDummy" << std::endl;
+  ChimeraTK::BackendFactory::getInstance().registerBackendType("TecDummy", &TecDummy::createInstance);
+}
+
+/*********************************************************************************************************************/
+
+void TecDummy::read(uint8_t bar, uint32_t address, int32_t* data, size_t sizeInBytes) {
+  DummyBackend::read(bar, address, data, sizeInBytes);
+  if(bar != TecDummy_bar || address != TecDummy_address_loopDone) return;
+  if(reg_loopStart != 1) return;
+
+  // convert command into string
+  // FIXME: this can be done better if the DummyRegisterRawAccessor would allow us to use the raw pointer to this...
+  std::string commandString(reg_command.getNumberOfElements() * 4, 0);
+  for(size_t i = 0; i < reg_command.getNumberOfElements(); ++i) {
+    uint32_t word = reg_command[i];
+    std::memcpy(&(commandString[4 * i]), &word, 4);
+  }
+
+  // perform data processing
+  auto reply = dataProcessing(commandString);
+
+  // convert reply back into byte stream
+  for(size_t i = 0; i < reply.length(); ++i) {
+    uint32_t word;
+    std::memcpy(&word, &(reply[4 * i]), 4);
+    reg_command[i] = word;
+  }
+
+  reg_loopDone = 1;
+}
+
+/*********************************************************************************************************************/
+
+std::string TecDummy::dataProcessing(const std::string& command) {
+  // Place data processing code here. Parse data from the "command" dummy accessor and place the reply on the same
+  // accessor. Just return this function, the done flag is automatically set by the caller. Remove this comment after
+  // implementation.
+  std::cout << "TecDummy::dataProcessing() command = " << command << std::endl;
+  return "MY REPLY";
+}
+
+/*********************************************************************************************************************/
-- 
GitLab