From 2848acf274e2b0814c7853af4b41eb3d7d0e3dcd Mon Sep 17 00:00:00 2001
From: Romain BROUCQUART <romain.broucquart@synchrotron-soleil.fr>
Date: Wed, 1 Mar 2023 14:52:54 +0100
Subject: [PATCH] feat(init):Add fofb-configurator

* This python script browse a simple file to write register using python
  deviceaccess.
---
 recipes-app/fofb-init/files/config_register   |   7 +
 .../fofb-init/files/fofb-configurator.py      | 145 ++++++++++++++++++
 recipes-app/fofb-init/files/fofb-init.sh      |   5 +
 recipes-app/fofb-init/fofb-init_1.0.bb        |   8 +-
 4 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 recipes-app/fofb-init/files/config_register
 create mode 100755 recipes-app/fofb-init/files/fofb-configurator.py

diff --git a/recipes-app/fofb-init/files/config_register b/recipes-app/fofb-init/files/config_register
new file mode 100644
index 0000000..02710f5
--- /dev/null
+++ b/recipes-app/fofb-init/files/config_register
@@ -0,0 +1,7 @@
+# Register configuration.
+
+# Line begining with # or empty are ignored
+# format is
+# register.path.name value
+# Everything not parsable will be ignored and reported as warning
+
diff --git a/recipes-app/fofb-init/files/fofb-configurator.py b/recipes-app/fofb-init/files/fofb-configurator.py
new file mode 100755
index 0000000..60bbbe3
--- /dev/null
+++ b/recipes-app/fofb-init/files/fofb-configurator.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+import deviceaccess as da
+import numpy as np
+import logging
+import argparse
+
+#######################################################################
+#       MODULE CONFIGURATION
+#######################################################################
+# Logger
+logger = logging.getLogger("fofb-configurator")
+logger.setLevel(logging.INFO)
+sh = logging.StreamHandler()
+sh.setLevel(logging.INFO)
+sh.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))
+logger.addHandler(sh)
+
+# Argparse
+parser=argparse.ArgumentParser(
+        prog="fofb-configurator",
+        description="Apply a default configuration file to a ChimeraTK device."
+        )
+
+parser.add_argument(
+        "--config", help="Path to configuration file (%(default)s).",
+        default="/opt/fofb/cfg/regconfig",)
+
+parser.add_argument(
+        "--dmap", help="ChimeraTK DMAP file (%(default)s).",
+        default="/opt/fofb/opcua-server/devices.dmap",)
+
+parser.add_argument(
+        "--devname", help="ChimeraTK device name (%(default)s).",
+        default="APPUIO",)
+
+
+#######################################################################
+#       GET DEVICE ACCESS
+#######################################################################
+def GetDeviceAccess(dmappath, devicename):
+    """
+    Open the device access
+    """
+    logger.info("Openning device {} in {}.".format(devicename, dmappath))
+
+    da.setDMapFilePath(dmappath)
+    dev=da.Device(devicename)
+
+    dev.open()
+
+    return dev
+
+
+#######################################################################
+#       READ CONFIG FILE
+#######################################################################
+def ReadConfigFile(filepath):
+    """
+    Read the configuration file, building a dictionnary
+    """
+    logger.info("Reading configuration file {}.".format(filepath))
+
+    dcfg={}
+    with open(filepath, 'r') as fp:
+
+        for i, l in enumerate(fp.readlines()):
+            # Ignore empty or comment
+            if len(l.strip()) <1:
+                continue
+            if l.strip().startswith('#'):
+                continue
+
+            # Try to split in two, or pass
+            try:
+                k,v = l.split()
+            except ValueError:
+                logger.warning("{} ignore line {}:'{}'".format(filepath, i, l))
+                continue
+
+            # Understand hex format
+            if v.lower().startswith("0x"):
+                base=16
+            else:
+                base=10
+
+            # Try to cast value, or pass
+            try:
+                v = int(v, base)
+            except ValueError:
+                logger.warning("{} ignore line {}:'{}'".format(filepath, i, l))
+                continue
+
+            dcfg[k]=v
+
+    return dcfg
+
+#######################################################################
+#        APPLY CONFIG
+#######################################################################
+def ApplyConfig(dev, config):
+    """
+    Apply dictionnary config to device dev.
+    """
+
+    for k, v in config.items():
+
+        try:
+            acc = dev.getScalarRegisterAccessor(np.int32, k)
+            acc.set(np.asarray([v], dtype=np.int32))
+            acc.write()
+        except:
+            logger.error("Could not apply value {} to {}".format(v,k))
+            raise
+
+        logger.info("Applied  {} = {}".format(k,v))
+
+
+
+#######################################################################
+#        MAIN
+#######################################################################
+if __name__ == '__main__':
+
+    args = parser.parse_args()
+
+    # Testing logger
+    logger.info("Welcome to FOFB-CONFIGURATOR")
+
+    try:
+        d=ReadConfigFile(args.config)
+    except FileNotFoundError:
+        logger.error("File not found: {}".format(args.config))
+        exit(1)
+
+    try:
+        dev=GetDeviceAccess(args.dmap, args.devname)
+    except Exception:
+        logger.error("Cannot open Device {} in {}".format(args.devname, args.dmap))
+        raise
+
+    ApplyConfig(dev, d)
+
+    dev.close()
+
+
diff --git a/recipes-app/fofb-init/files/fofb-init.sh b/recipes-app/fofb-init/files/fofb-init.sh
index 2ee9085..c452d9f 100644
--- a/recipes-app/fofb-init/files/fofb-init.sh
+++ b/recipes-app/fofb-init/files/fofb-init.sh
@@ -30,12 +30,17 @@ start() {
     echo "Loading FPGA image ${PATH_FPGABIN}"
     fpgautil -b ${PATH_FPGABIN}
 
+    # Reset the FPGA
+    /etc/init.d/fw_plreset.sh
 
     # Linking the correct MAP file
     PATH_MAP="/opt/fofb/map/app_${FOFB_APP}.mapt"
     echo "Linking map file ${PATH_MAP}"
     ln -sf ${PATH_MAP} /opt/fofb/map/app.mapt
 
+    # Applying configuration
+    fofb-configurator --config /opt/fofb/cfg/config_register --dmap /opt/fofb/opcua-server/devices.dmap
+
 }
 
 stop() {
diff --git a/recipes-app/fofb-init/fofb-init_1.0.bb b/recipes-app/fofb-init/fofb-init_1.0.bb
index 30ca7ef..5edd85a 100644
--- a/recipes-app/fofb-init/fofb-init_1.0.bb
+++ b/recipes-app/fofb-init/fofb-init_1.0.bb
@@ -10,13 +10,17 @@ inherit update-rc.d
 
 SRC_URI = " file://fofb-init.sh"
 SRC_URI += " file://configuration"
+SRC_URI += " file://config_register"
 SRC_URI += " file://fpgaversion.sh"
+SRC_URI += " file://fofb-configurator.py"
 
 RDEPENDS_${PN}=" fpga-manager-script bash"
 
 FILES_${PN}+="/etc/init.d/fofb-init.sh"
 FILES_${PN}+="/usr/bin/fpgaversion"
+FILES_${PN}+="/usr/bin/fofb-configurator"
 FILES_${PN}+="/opt/fofb/cfg/configuration"
+FILES_${PN}+="/opt/fofb/cfg/config_register"
 
 
 do_install() {
@@ -26,8 +30,10 @@ do_install() {
     # Write default configuration
     install -d ${D}/opt/fofb/cfg/
     install -m 0666 ${WORKDIR}/configuration ${D}/opt/fofb/cfg/configuration
+    install -m 0666 ${WORKDIR}/config_register ${D}/opt/fofb/cfg/config_register
 
-    # Add FPGA version reader
+    # Add FPGA version reader and FoFb Configurator
     install -d ${D}/usr/bin/
     install -m 0755 ${WORKDIR}/fpgaversion.sh ${D}/usr/bin/fpgaversion
+    install -m 0755 ${WORKDIR}/fofb-configurator.py ${D}/usr/bin/fofb-configurator
 }
-- 
GitLab