mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-01-19 11:11:03 +01:00
Dev/xilinx mat update (#959)
* put back code to obtain adc and dac device indexafter loading device tree and then create folder iio_device_links and create symbolic links there according to device indices found. ln -sf operation not permitted, so folder has to be deleted and created everytime. Also refactored definitions to have all the xilinx name or detector specific stuff out of programbyArm.c * uncommented waittransceiverreset at startup (should work now) and return of powering off chip at startup (error for transceiver alignment reset) * updated registerdefs from firmware * minor prints and updating names from registerdefs * waittransceiverreset has been fixed in firmware and removing warnign for that, transceiver alignment check for powering off chip is not done in fw (giving a warning and returning ok for now) * fixing ipchecksum (not done), removed startperiphery, allowing readout command to be allowed for xilinx when acquiring
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -70,3 +70,8 @@ int deleteFile(char *mess, char *fname, char *errorPrefix);
|
|||||||
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix);
|
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix);
|
||||||
|
|
||||||
int readParameterFromFile(char *fname, char *parameterName, int *value);
|
int readParameterFromFile(char *fname, char *parameterName, int *value);
|
||||||
|
|
||||||
|
int createAbsoluteDirectory(char *mess, const char *absPath, char *errorPrefix);
|
||||||
|
int deleteAbsoluteDirectory(char *mess, const char *absPath, char *errorPrefix);
|
||||||
|
|
||||||
|
int deleteItem(char *mess, int isFile, const char *absPath, char *errorPrefix);
|
||||||
@@ -10,3 +10,7 @@ int loadDeviceTree(char *mess);
|
|||||||
int checksBeforeCreatingDeviceTree(char *mess);
|
int checksBeforeCreatingDeviceTree(char *mess);
|
||||||
int createDeviceTree(char *mess);
|
int createDeviceTree(char *mess);
|
||||||
int verifyDeviceTree(char *mess);
|
int verifyDeviceTree(char *mess);
|
||||||
|
#ifndef VIRTUAL
|
||||||
|
int createSymbolicLinksForDevices(int adcDeviceIndex, int dacDeviceIndex,
|
||||||
|
char *mess);
|
||||||
|
#endif
|
||||||
@@ -198,7 +198,6 @@ int isChipConfigured();
|
|||||||
int powerChip(int on, char *mess);
|
int powerChip(int on, char *mess);
|
||||||
int getPowerChip();
|
int getPowerChip();
|
||||||
int configureChip(char *mess);
|
int configureChip(char *mess);
|
||||||
void startPeriphery();
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(JUNGFRAUD) || defined(MOENCHD) || defined(CHIPTESTBOARDD) || \
|
#if defined(JUNGFRAUD) || defined(MOENCHD) || defined(CHIPTESTBOARDD) || \
|
||||||
defined(MYTHEN3D) || defined(GOTTHARD2D)
|
defined(MYTHEN3D) || defined(GOTTHARD2D)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ u_int32_t writeRegister(u_int32_t offset, u_int32_t data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mapCSP0(void) {
|
int mapCSP0(void) {
|
||||||
|
LOG(logINFO, ("Mapping memory\n"));
|
||||||
u_int32_t csps[2] = {CSP0, CSP1};
|
u_int32_t csps[2] = {CSP0, CSP1};
|
||||||
u_int32_t **cspbases[2] = {&csp0base, &csp1base};
|
u_int32_t **cspbases[2] = {&csp0base, &csp1base};
|
||||||
u_int32_t memsize[2] = {MEM_SIZE_CSP0, MEM_SIZE_CSP1};
|
u_int32_t memsize[2] = {MEM_SIZE_CSP0, MEM_SIZE_CSP1};
|
||||||
@@ -58,7 +59,7 @@ int mapCSP0(void) {
|
|||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
// if not mapped
|
// if not mapped
|
||||||
if (*cspbases[i] == 0) {
|
if (*cspbases[i] == 0) {
|
||||||
LOG(logINFO, ("Mapping memory for %s\n", names[i]));
|
LOG(logINFO, ("\tMapping memory for %s\n", names[i]));
|
||||||
#ifdef VIRTUAL
|
#ifdef VIRTUAL
|
||||||
*cspbases[i] = malloc(memsize[i]);
|
*cspbases[i] = malloc(memsize[i]);
|
||||||
if (*cspbases[i] == NULL) {
|
if (*cspbases[i] == NULL) {
|
||||||
@@ -67,7 +68,7 @@ int mapCSP0(void) {
|
|||||||
memsize[i], names[i]));
|
memsize[i], names[i]));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("memory allocated for %s\n", names[i]));
|
LOG(logINFO, ("\tmemory allocated for %s\n", names[i]));
|
||||||
#else
|
#else
|
||||||
int fd = open("/dev/mem", O_RDWR | O_SYNC, 0);
|
int fd = open("/dev/mem", O_RDWR | O_SYNC, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@@ -75,7 +76,7 @@ int mapCSP0(void) {
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logDEBUG1,
|
LOG(logDEBUG1,
|
||||||
("/dev/mem opened for %s, (CSP:0x%x)\n", names[i], csps[i]));
|
("\t/dev/mem opened for %s, (CSP:0x%x)\n", names[i], csps[i]));
|
||||||
*cspbases[i] =
|
*cspbases[i] =
|
||||||
(u_int32_t *)mmap(0, memsize[i], PROT_READ | PROT_WRITE,
|
(u_int32_t *)mmap(0, memsize[i], PROT_READ | PROT_WRITE,
|
||||||
MAP_FILE | MAP_SHARED, fd, csps[i]);
|
MAP_FILE | MAP_SHARED, fd, csps[i]);
|
||||||
@@ -85,11 +86,11 @@ int mapCSP0(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG(logINFO,
|
LOG(logINFO,
|
||||||
("%s mapped of size %d from %p to %p,(CSP:0x%x) \n", names[i],
|
("\t%s mapped of size %d from %p to %p,(CSP:0x%x) \n", names[i],
|
||||||
memsize[i], *cspbases[i], *cspbases[i] + memsize[i], csps[i]));
|
memsize[i], *cspbases[i], *cspbases[i] + memsize[i], csps[i]));
|
||||||
// LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
|
// LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
|
||||||
} else
|
} else
|
||||||
LOG(logINFO, ("Memory %s already mapped before\n", names[i]));
|
LOG(logINFO, ("\tMemory %s already mapped before\n", names[i]));
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <libgen.h> // dirname
|
#include <libgen.h> // dirname
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h> // stat
|
||||||
#include <sys/utsname.h> // uname
|
#include <sys/utsname.h> // uname
|
||||||
#include <unistd.h> // readlink
|
#include <unistd.h> // readlink
|
||||||
|
|
||||||
@@ -677,31 +678,7 @@ int deleteFile(char *mess, char *fname, char *errorPrefix) {
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access(fullname, F_OK) == 0) {
|
return deleteItem(mess, 1, fullname, errorPrefix);
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
|
||||||
|
|
||||||
if (snprintf(cmd, MAX_STR_LENGTH, "rm %s", fullname) >=
|
|
||||||
MAX_STR_LENGTH) {
|
|
||||||
sprintf(mess, "Could not %s. Command to delete is too long\n",
|
|
||||||
errorPrefix);
|
|
||||||
LOG(logERROR, (mess));
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
|
||||||
"Could not %s. (deleting file %s). %s\n", errorPrefix,
|
|
||||||
fullname, retvals);
|
|
||||||
LOG(logERROR, (mess));
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
LOG(logINFO, ("\tDeleted file: %s (%s)\n", fullname, errorPrefix));
|
|
||||||
} else {
|
|
||||||
LOG(logINFO,
|
|
||||||
("\tFile does not exist anyway: %s (%s)\n", fullname, errorPrefix));
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix) {
|
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix) {
|
||||||
@@ -759,3 +736,59 @@ int readParameterFromFile(char *fname, char *parameterName, int *value) {
|
|||||||
fclose(fd);
|
fclose(fd);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int createAbsoluteDirectory(char *mess, const char *absPath,
|
||||||
|
char *errorPrefix) {
|
||||||
|
// check if folder exists
|
||||||
|
if (access(absPath, F_OK) == 0) {
|
||||||
|
LOG(logINFO, ("Folder %s already exists\n", absPath));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// folder does not exist, create it
|
||||||
|
if (mkdir(absPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
|
||||||
|
sprintf(mess, "Could not %s. Could not create folder %s\n", errorPrefix,
|
||||||
|
absPath);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tCreated folder: %s (%s)\n", absPath, errorPrefix));
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int deleteAbsoluteDirectory(char *mess, const char *absPath,
|
||||||
|
char *errorPrefix) {
|
||||||
|
return deleteItem(mess, 0, absPath, errorPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
int deleteItem(char *mess, int isFile, const char *absPath, char *errorPrefix) {
|
||||||
|
// item does not exist
|
||||||
|
if (access(absPath, F_OK) != 0) {
|
||||||
|
LOG(logINFO, ("\t%s does not exist anyway: %s (%s)\n",
|
||||||
|
(isFile ? "File" : "Folder"), absPath, errorPrefix));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete item
|
||||||
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
|
if (snprintf(cmd, MAX_STR_LENGTH, "rm %s %s", (isFile ? "-f" : "-rf"),
|
||||||
|
absPath) >= MAX_STR_LENGTH) {
|
||||||
|
sprintf(mess, "Could not %s. Command to delete is too long\n",
|
||||||
|
errorPrefix);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
|
snprintf(mess, MAX_STR_LENGTH, "Could not %s. (deleting %s %s). %s\n",
|
||||||
|
errorPrefix, (isFile ? "file" : "folder"), absPath, retvals);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tDeleted %s: %s (%s)\n", (isFile ? "file" : "folder"),
|
||||||
|
absPath, errorPrefix));
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
@@ -2,20 +2,19 @@
|
|||||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
#include "programViaArm.h"
|
#include "programViaArm.h"
|
||||||
#include "clogger.h"
|
#include "clogger.h"
|
||||||
|
#include "common.h"
|
||||||
#include "sls/sls_detector_defs.h"
|
#include "sls/sls_detector_defs.h"
|
||||||
|
#include "slsDetectorServer_defs.h"
|
||||||
|
|
||||||
#include <string.h> //memset
|
#include <string.h> //memset
|
||||||
#include <unistd.h> // access
|
#include <unistd.h> // access
|
||||||
|
|
||||||
#define CMD_ARM_LOAD_BIT_FILE \
|
#define CMD_ARM_LOAD_BIT_FILE "~/fpgautil/fpgautil -b " FIRMWARE_FILE " -f Full"
|
||||||
"~/fpgautil/fpgautil -b /root/apps/xilinx-ctb/XilinxCTB.bit -f Full"
|
#define CMD_ARM_LOAD_DEVICE_TREE \
|
||||||
#define CMD_ARM_DEVICE_TREE_API_FOLDER \
|
"cat " DEVICE_TREE_OVERLAY_FILE " > " DEVICE_TREE_API_FOLDER "/dtbo"
|
||||||
"/sys/kernel/config/device-tree/overlays/spidr"
|
#define CMD_ARM_SYM_LINK_FORMAT \
|
||||||
#define CMD_ARM_DEVICE_TREE_OVERLAY_FILE "/root/apps/xilinx-ctb/pl.dtbo"
|
"ln -sf " DEVICE_TREE_DST "%d " IIO_DEVICE_FOLDER "/%s"
|
||||||
#define CMD_ARM_LOAD_DEVICE_TREE_FORMAT "cat %s > %s/dtbo"
|
#define TIME_LOAD_DEVICE_TREE_MS (500)
|
||||||
#define CMD_ARM_DEVICE_TREE_DST "/sys/bus/iio/devices/iio:device"
|
|
||||||
#define CMD_ARM_DEVICE_NAME "xilinx-ams", "ad7689", "dac@0", "dac@1", "dac@2"
|
|
||||||
#define TIME_LOAD_DEVICE_TREE_MS (500)
|
|
||||||
|
|
||||||
extern int executeCommand(char *command, char *result, enum TLogLevel level);
|
extern int executeCommand(char *command, char *result, enum TLogLevel level);
|
||||||
|
|
||||||
@@ -56,54 +55,54 @@ int loadDeviceTree(char *mess) {
|
|||||||
|
|
||||||
int checksBeforeCreatingDeviceTree(char *mess) {
|
int checksBeforeCreatingDeviceTree(char *mess) {
|
||||||
// check if device tree overlay file exists
|
// check if device tree overlay file exists
|
||||||
if (access(CMD_ARM_DEVICE_TREE_OVERLAY_FILE, F_OK) != 0) {
|
if (access(DEVICE_TREE_OVERLAY_FILE, F_OK) != 0) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Device tree overlay file (%s) does not exist\n",
|
"Device tree overlay file (%s) does not exist\n",
|
||||||
CMD_ARM_DEVICE_TREE_OVERLAY_FILE);
|
DEVICE_TREE_OVERLAY_FILE);
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tDevice tree overlay file exists (%s)\n",
|
LOG(logINFO,
|
||||||
CMD_ARM_DEVICE_TREE_OVERLAY_FILE));
|
("\tDevice tree overlay file exists (%s)\n", DEVICE_TREE_OVERLAY_FILE));
|
||||||
|
|
||||||
// check if device tree folder exists. If it does, remove it
|
// check if device tree folder exists. If it does, remove it
|
||||||
if (access(CMD_ARM_DEVICE_TREE_API_FOLDER, F_OK) == 0) {
|
if (access(DEVICE_TREE_API_FOLDER, F_OK) == 0) {
|
||||||
// remove it
|
// remove it
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
memset(cmd, 0, MAX_STR_LENGTH);
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
sprintf(cmd, "rmdir %s", CMD_ARM_DEVICE_TREE_API_FOLDER);
|
sprintf(cmd, "rmdir %s", DEVICE_TREE_API_FOLDER);
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
memset(retvals, 0, MAX_STR_LENGTH);
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not unload device tree overlay api with %s (%s)\n",
|
"Could not unload device tree overlay api with %s (%s)\n",
|
||||||
cmd, retvals);
|
cmd, retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tUnloaded existing device tree overlay api (%s)\n",
|
LOG(logINFO, ("\tUnloaded existing device tree overlay api (%s)\n",
|
||||||
CMD_ARM_DEVICE_TREE_API_FOLDER));
|
DEVICE_TREE_API_FOLDER));
|
||||||
} else {
|
} else {
|
||||||
LOG(logINFO, ("\tNo existing device tree overlay api found(%s)\n",
|
LOG(logINFO, ("\tNo existing device tree overlay api found(%s)\n",
|
||||||
CMD_ARM_DEVICE_TREE_API_FOLDER));
|
DEVICE_TREE_API_FOLDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create device tree overlay folder
|
// create device tree overlay folder
|
||||||
{
|
{
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
memset(cmd, 0, MAX_STR_LENGTH);
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
sprintf(cmd, "mkdir %s", CMD_ARM_DEVICE_TREE_API_FOLDER);
|
sprintf(cmd, "mkdir %s", DEVICE_TREE_API_FOLDER);
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
memset(retvals, 0, MAX_STR_LENGTH);
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not create device tree overlay api with %s (%s)\n",
|
"Could not create device tree overlay api with %s (%s)\n",
|
||||||
cmd, retvals);
|
cmd, retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tDevice tree overlay api created (%s)\n",
|
LOG(logINFO, ("\tDevice tree overlay api created (%s)\n",
|
||||||
CMD_ARM_DEVICE_TREE_API_FOLDER));
|
DEVICE_TREE_API_FOLDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -112,15 +111,14 @@ int checksBeforeCreatingDeviceTree(char *mess) {
|
|||||||
int createDeviceTree(char *mess) {
|
int createDeviceTree(char *mess) {
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
memset(cmd, 0, MAX_STR_LENGTH);
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
sprintf(cmd, CMD_ARM_LOAD_DEVICE_TREE_FORMAT,
|
strcpy(cmd, CMD_ARM_LOAD_DEVICE_TREE);
|
||||||
CMD_ARM_DEVICE_TREE_OVERLAY_FILE, CMD_ARM_DEVICE_TREE_API_FOLDER);
|
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
memset(retvals, 0, MAX_STR_LENGTH);
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not load device tree overlay with %s (%s)\n", cmd,
|
"Could not load device tree overlay with %s (%s)\n", cmd,
|
||||||
retvals);
|
retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tDevice tree overlay created (cmd: %s)\n", cmd));
|
LOG(logINFO, ("\tDevice tree overlay created (cmd: %s)\n", cmd));
|
||||||
@@ -131,20 +129,27 @@ int createDeviceTree(char *mess) {
|
|||||||
|
|
||||||
int verifyDeviceTree(char *mess) {
|
int verifyDeviceTree(char *mess) {
|
||||||
LOG(logINFOBLUE, ("Verifying Device Tree...\n"));
|
LOG(logINFOBLUE, ("Verifying Device Tree...\n"));
|
||||||
#ifndef VIRTUAL
|
|
||||||
|
#ifdef VIRTUAL
|
||||||
|
LOG(logINFOBLUE, ("Device tree verified successfully\n"));
|
||||||
|
return OK;
|
||||||
|
#else
|
||||||
|
|
||||||
// check if iio:device0-4 exists in device tree destination
|
// check if iio:device0-4 exists in device tree destination
|
||||||
int hardcodedDeviceIndex = 0;
|
int hardcodedDeviceIndex = 0;
|
||||||
|
int adcDeviceIndex = 1;
|
||||||
|
int dacDeviceIndex = 2;
|
||||||
|
|
||||||
for (int i = 0; i != 5; ++i) {
|
for (int i = 0; i != 5; ++i) {
|
||||||
char deviceName[MAX_STR_LENGTH] = {0};
|
char deviceName[MAX_STR_LENGTH] = {0};
|
||||||
memset(deviceName, 0, MAX_STR_LENGTH);
|
memset(deviceName, 0, MAX_STR_LENGTH);
|
||||||
sprintf(deviceName, "%s%d/name", CMD_ARM_DEVICE_TREE_DST, i);
|
sprintf(deviceName, "%s%d/name", DEVICE_TREE_DST, i);
|
||||||
// check if device exist
|
// check if device exist
|
||||||
if (access(deviceName, F_OK) != 0) {
|
if (access(deviceName, F_OK) != 0) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not verify device tree. Device %s does not exist\n",
|
"Could not verify device tree. Device %s does not exist\n",
|
||||||
deviceName);
|
deviceName);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
// find name
|
// find name
|
||||||
@@ -157,24 +162,26 @@ int verifyDeviceTree(char *mess) {
|
|||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not retrieve device name from device %s (%s)\n",
|
"Could not retrieve device name from device %s (%s)\n",
|
||||||
deviceName, retvals);
|
deviceName, retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
// verify name
|
// verify name
|
||||||
char *deviceNames[] = {CMD_ARM_DEVICE_NAME};
|
char *deviceNames[] = {DEVICE_NAME_LIST};
|
||||||
if (strstr(retvals, deviceNames[hardcodedDeviceIndex]) == NULL) {
|
if (strstr(retvals, deviceNames[hardcodedDeviceIndex]) == NULL) {
|
||||||
// dacs got loaded first
|
// dacs got loaded first
|
||||||
if (i == 1 &&
|
if (i == 1 &&
|
||||||
strstr(retvals, deviceNames[hardcodedDeviceIndex + 1]) !=
|
strstr(retvals, deviceNames[hardcodedDeviceIndex + 1]) !=
|
||||||
NULL) {
|
NULL) {
|
||||||
++hardcodedDeviceIndex;
|
++hardcodedDeviceIndex;
|
||||||
|
adcDeviceIndex = 4;
|
||||||
|
dacDeviceIndex = 1;
|
||||||
} else {
|
} else {
|
||||||
snprintf(
|
snprintf(
|
||||||
mess, MAX_STR_LENGTH,
|
mess, MAX_STR_LENGTH,
|
||||||
"Could not verify device tree. Device %s expected %s but "
|
"Could not verify device tree. Device %s expected %s but "
|
||||||
"got %s\n",
|
"got %s\n",
|
||||||
deviceName, deviceNames[i], retvals);
|
deviceName, deviceNames[i], retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +190,66 @@ int verifyDeviceTree(char *mess) {
|
|||||||
if (hardcodedDeviceIndex == 5)
|
if (hardcodedDeviceIndex == 5)
|
||||||
hardcodedDeviceIndex = 1;
|
hardcodedDeviceIndex = 1;
|
||||||
}
|
}
|
||||||
|
LOG(logINFOBLUE, ("Device tree verified successfully [temp: 0, adc:%d, "
|
||||||
|
"dac:%d, %d, %d]\n",
|
||||||
|
adcDeviceIndex, dacDeviceIndex, dacDeviceIndex + 1,
|
||||||
|
dacDeviceIndex + 2));
|
||||||
|
|
||||||
|
return createSymbolicLinksForDevices(adcDeviceIndex, dacDeviceIndex, mess);
|
||||||
#endif
|
#endif
|
||||||
LOG(logINFOBLUE, ("Device tree verified successfully\n"));
|
}
|
||||||
|
|
||||||
|
#ifndef VIRTUAL
|
||||||
|
int createSymbolicLinksForDevices(int adcDeviceIndex, int dacDeviceIndex,
|
||||||
|
char *mess) {
|
||||||
|
|
||||||
|
// delete andcreate iio device links folder (deleting because cannot
|
||||||
|
// overwrite symbolic links with -sf)
|
||||||
|
if (deleteAbsoluteDirectory(mess, IIO_DEVICE_FOLDER,
|
||||||
|
"create sym links for device trees") ==
|
||||||
|
FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (createAbsoluteDirectory(mess, IIO_DEVICE_FOLDER,
|
||||||
|
"create sym links for device trees") ==
|
||||||
|
FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *deviceNames[] = {DEVICE_NAME_LIST};
|
||||||
|
// create symbolic links for adc
|
||||||
|
{
|
||||||
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
|
sprintf(cmd, CMD_ARM_SYM_LINK_FORMAT, adcDeviceIndex, deviceNames[1]);
|
||||||
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
|
"Could not create sym link [adc] (%s)\n", retvals);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tSym link [adc] created (%s)\n", cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
// create symbolic links for dacs
|
||||||
|
for (int idac = 0; idac != 3; ++idac) {
|
||||||
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
|
sprintf(cmd, CMD_ARM_SYM_LINK_FORMAT, dacDeviceIndex + idac,
|
||||||
|
deviceNames[idac + 2]);
|
||||||
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
|
"Could not create sym link [dac%d] (%s)\n", idac,
|
||||||
|
retvals);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tSym link [dac%d] created (%s)\n", idac, cmd));
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -8470,7 +8470,7 @@ int start_readout(int file_des) {
|
|||||||
#else
|
#else
|
||||||
if (Server_VerifyLock() == OK) {
|
if (Server_VerifyLock() == OK) {
|
||||||
enum runStatus s = getRunStatus();
|
enum runStatus s = getRunStatus();
|
||||||
if (s == RUNNING || s == WAITING) {
|
if ((s == RUNNING || s == WAITING) && (myDetectorType != XILINX_CHIPTESTBOARD)) {
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
strcpy(mess, "Could not start readout because the detector is "
|
strcpy(mess, "Could not start readout because the detector is "
|
||||||
"already running!\n");
|
"already running!\n");
|
||||||
|
|||||||
@@ -817,18 +817,16 @@
|
|||||||
|
|
||||||
#define MATTERHORNSPICTRL (0x608)
|
#define MATTERHORNSPICTRL (0x608)
|
||||||
|
|
||||||
#define MATTERHORNSPICTRL_EN_OFST (0)
|
#define CONFIGSTART_P_OFST (0)
|
||||||
#define MATTERHORNSPICTRL_EN_MSK (0x00000001 << MATTERHORNSPICTRL_EN_OFST)
|
#define CONFIGSTART_P_MSK (0x00000001 << CONFIGSTART_P_OFST)
|
||||||
#define CONFIGSTART_OFST (1)
|
#define PERIPHERYRST_P_OFST (1)
|
||||||
#define CONFIGSTART_MSK (0x00000001 << CONFIGSTART_OFST)
|
#define PERIPHERYRST_P_MSK (0x00000001 << PERIPHERYRST_P_OFST)
|
||||||
#define START_P_OFST (2)
|
#define STARTREAD_P_OFST (2)
|
||||||
#define START_P_MSK (0x00000001 << START_P_OFST)
|
#define STARTREAD_P_MSK (0x00000001 << STARTREAD_P_OFST)
|
||||||
#define STARTREAD_P_OFST (3)
|
#define BUSY_OFST (3)
|
||||||
#define STARTREAD_P_MSK (0x00000001 << STARTREAD_P_OFST)
|
#define BUSY_MSK (0x00000001 << BUSY_OFST)
|
||||||
#define BUSY_OFST (4)
|
#define READOUTFROMASIC_OFST (4)
|
||||||
#define BUSY_MSK (0x00000001 << BUSY_OFST)
|
#define READOUTFROMASIC_MSK (0x00000001 << READOUTFROMASIC_OFST)
|
||||||
#define READOUTFROMASIC_OFST (5)
|
|
||||||
#define READOUTFROMASIC_MSK (0x00000001 << READOUTFROMASIC_OFST)
|
|
||||||
|
|
||||||
#define EMPTY60CREG (0x60C)
|
#define EMPTY60CREG (0x60C)
|
||||||
|
|
||||||
@@ -905,6 +903,8 @@
|
|||||||
#define RESETRXPLLANDDATAPATH_MSK (0x00000001 << RESETRXPLLANDDATAPATH_OFST)
|
#define RESETRXPLLANDDATAPATH_MSK (0x00000001 << RESETRXPLLANDDATAPATH_OFST)
|
||||||
#define RESETRXDATAPATHIN_OFST (4)
|
#define RESETRXDATAPATHIN_OFST (4)
|
||||||
#define RESETRXDATAPATHIN_MSK (0x00000001 << RESETRXDATAPATHIN_OFST)
|
#define RESETRXDATAPATHIN_MSK (0x00000001 << RESETRXDATAPATHIN_OFST)
|
||||||
|
#define RXPOLARITY_OFST (5)
|
||||||
|
#define RXPOLARITY_MSK (0x0000000f << RXPOLARITY_OFST)
|
||||||
|
|
||||||
#define EMPTY65CREG (0x65C)
|
#define EMPTY65CREG (0x65C)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -387,15 +387,15 @@ void setupDetector() {
|
|||||||
initializePatternWord();
|
initializePatternWord();
|
||||||
#endif
|
#endif
|
||||||
// initialization only at start up (restart fpga)
|
// initialization only at start up (restart fpga)
|
||||||
// initError = waitTransceiverReset(initErrorMessage);
|
initError = waitTransceiverReset(initErrorMessage);
|
||||||
// if (initError == FAIL) {
|
if (initError == FAIL) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// // power off chip
|
// power off chip
|
||||||
initError = powerChip(0, initErrorMessage);
|
initError = powerChip(0, initErrorMessage);
|
||||||
// if (initError == FAIL) {
|
if (initError == FAIL) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
LTC2620_D_SetDefines(DAC_MIN_MV, DAC_MAX_MV, DAC_DRIVER_FILE_NAME, NDAC,
|
LTC2620_D_SetDefines(DAC_MIN_MV, DAC_MAX_MV, DAC_DRIVER_FILE_NAME, NDAC,
|
||||||
NPWR, DAC_POWERDOWN_DRIVER_FILE_NAME);
|
NPWR, DAC_POWERDOWN_DRIVER_FILE_NAME);
|
||||||
@@ -469,11 +469,6 @@ int waitTransceiverReset(char *mess) {
|
|||||||
sprintf(mess, "Resetting transceiver timed out, time:%.2fs\n",
|
sprintf(mess, "Resetting transceiver timed out, time:%.2fs\n",
|
||||||
(timeNs / (1E9)));
|
(timeNs / (1E9)));
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
|
|
||||||
LOG(logINFORED, ("Waiting for Firmware to be fixed here. Skipping "
|
|
||||||
"this error for now.\n"));
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
usleep(0);
|
usleep(0);
|
||||||
@@ -557,9 +552,6 @@ int powerChip(int on, char *mess) {
|
|||||||
if (configureChip(mess) == FAIL)
|
if (configureChip(mess) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
startPeriphery();
|
|
||||||
|
|
||||||
chipConfigured = 1;
|
|
||||||
} else {
|
} else {
|
||||||
LOG(logINFOBLUE, ("Powering chip: off\n"));
|
LOG(logINFOBLUE, ("Powering chip: off\n"));
|
||||||
bus_w(addr, bus_r(addr) & ~mask);
|
bus_w(addr, bus_r(addr) & ~mask);
|
||||||
@@ -573,6 +565,11 @@ int powerChip(int on, char *mess) {
|
|||||||
if (isTransceiverAligned()) {
|
if (isTransceiverAligned()) {
|
||||||
sprintf(mess, "Transceiver alignment not reset\n");
|
sprintf(mess, "Transceiver alignment not reset\n");
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
|
|
||||||
|
// to be removed when fixed later
|
||||||
|
LOG(logWARNING, ("Bypassing this error for now. To be fixed later...\n"));
|
||||||
|
return OK;
|
||||||
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tTransceiver alignment has been reset\n"));
|
LOG(logINFO, ("\tTransceiver alignment has been reset\n"));
|
||||||
@@ -598,8 +595,8 @@ int configureChip(char *mess) {
|
|||||||
|
|
||||||
// start configuration
|
// start configuration
|
||||||
uint32_t addr = MATTERHORNSPICTRL;
|
uint32_t addr = MATTERHORNSPICTRL;
|
||||||
bus_w(addr, bus_r(addr) | CONFIGSTART_MSK);
|
bus_w(addr, bus_r(addr) | CONFIGSTART_P_MSK);
|
||||||
bus_w(addr, bus_r(addr) & ~CONFIGSTART_MSK);
|
bus_w(addr, bus_r(addr) & ~CONFIGSTART_P_MSK);
|
||||||
|
|
||||||
// wait until configuration is done
|
// wait until configuration is done
|
||||||
#ifndef VIRTUAL
|
#ifndef VIRTUAL
|
||||||
@@ -615,16 +612,11 @@ int configureChip(char *mess) {
|
|||||||
configDone = (bus_r(MATTERHORNSPICTRL) & BUSY_MSK);
|
configDone = (bus_r(MATTERHORNSPICTRL) & BUSY_MSK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
chipConfigured = 1;
|
||||||
LOG(logINFOBLUE, ("\tChip configured\n"));
|
LOG(logINFOBLUE, ("\tChip configured\n"));
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void startPeriphery() {
|
|
||||||
LOG(logINFOBLUE, ("\tStarting periphery\n"));
|
|
||||||
bus_w(MATTERHORNSPICTRL, bus_r(MATTERHORNSPICTRL) | START_P_MSK);
|
|
||||||
// TODO ?
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set parameters - dr */
|
/* set parameters - dr */
|
||||||
|
|
||||||
int setDynamicRange(int dr) {
|
int setDynamicRange(int dr) {
|
||||||
@@ -1223,14 +1215,21 @@ void calcChecksum(udp_header *udp) {
|
|||||||
|
|
||||||
// ignore ethertype (from udp header)
|
// ignore ethertype (from udp header)
|
||||||
addr++;
|
addr++;
|
||||||
|
// ignore udp_srcmac_lsb (from udp header)
|
||||||
|
addr++;
|
||||||
|
addr++;
|
||||||
|
|
||||||
// from identification to srcip_lsb
|
// from ip_protocol to ip_checksum
|
||||||
while (count > 2) {
|
while (count > 2) {
|
||||||
sum += *addr++;
|
sum += *addr++;
|
||||||
count -= 2;
|
count -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore src udp port (from udp header)
|
// ignore udp_checksum (from udp header)
|
||||||
|
addr++;
|
||||||
|
// ignore udp_destport (from udp header)
|
||||||
|
addr++;
|
||||||
|
// ignore udp_srcport (from udp header)
|
||||||
addr++;
|
addr++;
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@@ -1240,6 +1239,7 @@ void calcChecksum(udp_header *udp) {
|
|||||||
long int checksum = sum & 0xffff;
|
long int checksum = sum & 0xffff;
|
||||||
checksum += UDP_IP_HEADER_LENGTH_BYTES;
|
checksum += UDP_IP_HEADER_LENGTH_BYTES;
|
||||||
udp->ip_checksum = checksum;
|
udp->ip_checksum = checksum;
|
||||||
|
LOG(logINFO, ("\tIP checksum: 0x%x\n", checksum));
|
||||||
}
|
}
|
||||||
|
|
||||||
int configureMAC() {
|
int configureMAC() {
|
||||||
@@ -1334,7 +1334,7 @@ int startStateMachine() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOG(logINFOBLUE, ("Starting State Machine\n"));
|
LOG(logINFOBLUE, ("Starting State Machine\n"));
|
||||||
cleanFifos();
|
//cleanFifos(); removing this for now as its done before readout pattern
|
||||||
|
|
||||||
// start state machine
|
// start state machine
|
||||||
bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
|
bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
|
||||||
@@ -1356,6 +1356,7 @@ int startStateMachine() {
|
|||||||
usleep(0);
|
usleep(0);
|
||||||
commaDet = (bus_r(TRANSCEIVERSTATUS) & RXCOMMADET_MSK);
|
commaDet = (bus_r(TRANSCEIVERSTATUS) & RXCOMMADET_MSK);
|
||||||
}
|
}
|
||||||
|
LOG(logINFORED, ("Kwords or end of acquisition detected\n"));
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -1516,6 +1517,7 @@ int startReadOut() {
|
|||||||
usleep(0);
|
usleep(0);
|
||||||
streamingBusy = (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK);
|
streamingBusy = (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK);
|
||||||
}
|
}
|
||||||
|
LOG(logINFORED, ("Streaming done\n"));
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,16 +25,20 @@
|
|||||||
#define DYNAMIC_RANGE (16)
|
#define DYNAMIC_RANGE (16)
|
||||||
#define NUM_BYTES_PER_PIXEL (DYNAMIC_RANGE / 8)
|
#define NUM_BYTES_PER_PIXEL (DYNAMIC_RANGE / 8)
|
||||||
|
|
||||||
#define DAC_DRIVER_FILE_NAME ("/root/apps/xilinx-ctb/current_board_links/ao%d")
|
#define MAIN_APP_FOLDER "/root/apps/xilinx-ctb"
|
||||||
#define DAC_POWERDOWN_DRIVER_FILE_NAME \
|
#define FIRMWARE_FILE MAIN_APP_FOLDER "/XilinxCTB.bit"
|
||||||
("/root/apps/xilinx-ctb/current_board_links/ao%d_pd")
|
#define DEVICE_TREE_OVERLAY_FILE MAIN_APP_FOLDER "/pl.dtbo"
|
||||||
|
#define CURRENT_BOARD_LINKS_FOLDER MAIN_APP_FOLDER "/current_board_links"
|
||||||
|
#define IIO_DEVICE_FOLDER MAIN_APP_FOLDER "/iio_device_links"
|
||||||
|
|
||||||
#define SLOWADC_DRIVER_FILE_NAME \
|
#define DEVICE_TREE_DST "/sys/bus/iio/devices/iio:device"
|
||||||
("/root/apps/xilinx-ctb/mythenIII_0.2_1.1/links/ai%d")
|
#define DEVICE_NAME_LIST "xilinx-ams", "ad7689", "dac@0", "dac@1", "dac@2"
|
||||||
// #define SLOWDAC_CONVERTION_FACTOR_TO_UV (62.500953)
|
#define DEVICE_TREE_API_FOLDER "/sys/kernel/config/device-tree/overlays/spidr"
|
||||||
|
|
||||||
#define TEMP_DRIVER_FILE_NAME \
|
#define DAC_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ao%d"
|
||||||
("/sys/bus/iio/devices/iio:device0/in_temp7_input")
|
#define DAC_POWERDOWN_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ao%d_pd"
|
||||||
|
#define SLOWADC_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ai%d"
|
||||||
|
#define TEMP_DRIVER_FILE_NAME DEVICE_TREE_DST "0/in_temp7_input"
|
||||||
|
|
||||||
/** Default Parameters */
|
/** Default Parameters */
|
||||||
#define DEFAULT_NUM_FRAMES (1)
|
#define DEFAULT_NUM_FRAMES (1)
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
#define RELEASE "developer"
|
#define RELEASE "developer"
|
||||||
#define APILIB "developer 0x230224"
|
#define APILIB "developer 0x230224"
|
||||||
#define APIRECEIVER "developer 0x230224"
|
#define APIRECEIVER "developer 0x230224"
|
||||||
#define APICTB "developer 0x240822"
|
#define APICTB "developer 0x240910"
|
||||||
#define APIGOTTHARD "developer 0x240822"
|
#define APIGOTTHARD "developer 0x240910"
|
||||||
#define APIGOTTHARD2 "developer 0x240822"
|
#define APIGOTTHARD2 "developer 0x240910"
|
||||||
#define APIMYTHEN3 "developer 0x240822"
|
#define APIJUNGFRAU "developer 0x240910"
|
||||||
#define APIMOENCH "developer 0x240822"
|
#define APIMYTHEN3 "developer 0x240910"
|
||||||
#define APIXILINXCTB "developer 0x240822"
|
#define APIMOENCH "developer 0x240910"
|
||||||
#define APIEIGER "developer 0x240822"
|
#define APIXILINXCTB "developer 0x240910"
|
||||||
#define APIJUNGFRAU "developer 0x240822"
|
#define APIEIGER "developer 0x240910"
|
||||||
|
|||||||
Reference in New Issue
Block a user