merge fix

This commit is contained in:
maliakal_d 2020-03-03 17:57:55 +01:00
commit 5430288ce8
6 changed files with 81 additions and 108 deletions

113
README.md
View File

@ -2,90 +2,67 @@
Detailed documentation can be found on the [official site.](https://www.psi.ch/detectors/users-support) Detailed documentation can be found on the [official site.](https://www.psi.ch/detectors/users-support)
### Binaries ### Binaries
Documentation to obtain the binaries via the conda package is available for [lib](https://github.com/slsdetectorgroup/sls_detector_lib) and [gui](https://github.com/slsdetectorgroup/sls_detector_gui) Binaries for the slsDetectorPackage are available through conda.
```
#Add conda channels
conda config --add channels conda-forge
conda config --add channels slsdetectorgroup
conda install slsdetlib #only shared lib and command line
conda install slsdet #python bindings (includes slsdetlib)
conda install slsdetgui #gui (includes qt4)
#Install specific version
conda install slsdet=2020.03.02.dev0 #developer version from 3 March 2020
```
### Source code ### Source code
One can also obtain the source code from this repository and compile while realizing the setup dependencies as required. One can also obtain the source code from this repository and compile.
``` ```
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git
``` ```
#### Setup dependencies #### Dependencies
* Gui Client <br> * Lib: c++11 compiler (gcc=>4.8), ZeroMQ 4
Requirements: Qt 4.8 and Qwt 6.0 * Gui: Qt 4.8 and Qwt 6.0
``` * Calibration wizards and ctbGUI: ROOT
export QTDIR=/usr/local/Trolltech/ * Optional: HDF5
export QWTDIR=/usr/local/qwt-6.0.1/
```
If either of them does not exist, the GUI client will not be built.
* Advanced user Calibration wizards<br>
Requirements: ROOT
```
export ROOTSYS=/usr/local/root-5.34
```
#### Compilation #### Compilation
Compiling can be done in two ways. Compiling can be done in two ways. Either with the convenience script
cmk.sh or directly with cmake for more control.
**1. Compile using script cmk.sh**<br> **1. Compile using script cmk.sh**<br>
After compiling, the libraries and executables will be found in `slsDetectorPackage/build/bin` directory<br> After compiling, the libraries and executables will be found in `slsDetectorPackage/build/bin` directory<br>
Usage: [-c] [-b] [-h] [-d HDF5 directory] [-j]<br> Usage: [-c] [-b] [-p] [e] [t] [r] [g] [s] [u] [i] [-h] [-d <HDF5 directory>] [-j] <Number of threads>
* -[no option]: only make<br> -[no option]: only make
* -c: Clean<br> -c: Clean
* -b: Builds/Rebuilds CMake files normal mode<br> -b: Builds/Rebuilds CMake files normal mode
* -h: Builds/Rebuilds Cmake files with HDF5 package<br> -p: Builds/Rebuilds Python API
* -d: HDF5 Custom Directory<br> -h: Builds/Rebuilds Cmake files with HDF5 package
* -t: Build/Rebuilds only text client<br> -d: HDF5 Custom Directory
* -r: Build/Rebuilds only receiver<br> -t: Build/Rebuilds only text client
* -g: Build/Rebuilds only gui<br> -r: Build/Rebuilds only receiver
* -j: Number of threads to compile through<br> -g: Build/Rebuilds only gui
* -e: Debug mode -s: Simulator
-u: Chip Test Gui
Basic Option: -j: Number of threads to compile through
./cmk.sh -b -e: Debug mode
-i: Builds tests
For only make:
./cmk.sh eg. Rebuild when you switch to a new build and compile in parallel:
./cmk.sh -bj5
For make clean;make:
./cmk.sh -c
For using hdf5 without custom dir /blabla:
./cmk.sh -h -d /blabla
For rebuilding cmake without hdf5
./cmk.sh -b
For using multiple cores to compile faster:
./cmk.sh -j9<br>
For rebuilding only certain sections<br>
./cmk.sh -tg #only text client and gui<br>
./cmk.sh -r #only receiver<br>
**2. Compile without script**<br> **2. Compile without script**<br>
Use cmake to create out-of-source builds, by creating a build folder parallel to source directory. Use cmake to create out-of-source builds, by creating a build folder parallel to source directory. This would create a debug build with address sanitizers.
``` ```
$ cd .. $ mkdir build
$ mkdir slsDetectorPackage-build $ cd build
$ cd slsDetectorPackage-build $ cmake ../slsDetectorPackage -DCMAKE_BUILD_TYPE=Debug -DSLS_USE_SANITIZER=ON
$ cmake ../slsDetectorPackage -DCMAKE_BUILD_TYPE=Debug -DSLS_USE_HDF5=OFF $ make -j12 #or whatever number of threads wanted
$ make
```
Use the following as an example to compile statically and using specific hdf5 folder
```
$ HDF5_ROOT=/opt/hdf5v1.10.0 cmake ../slsDetectorPackage -DCMAKE_BUILD_TYPE=Debug -DSLS_USE_HDF5=ON
```
After compiling, the libraries and executables will be found at `bin` directory
```
$ ls bin/
gui_client libSlsDetector.a libSlsDetector.so libSlsReceiver.a libSlsReceiver.so
sls_detector_acquire sls_detector_get slsDetectorGui sls_detector_help sls_detector_put slsReceiver slsMultiReceiver
``` ```

View File

@ -228,7 +228,7 @@
#define SET_DELAY_LSB_REG (0x22 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_DELAY_LSB_REG (0x22 * REG_OFFSET + BASE_FLOW_CONTROL)
#define SET_DELAY_MSB_REG (0x23 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_DELAY_MSB_REG (0x23 * REG_OFFSET + BASE_FLOW_CONTROL)
/* Cylces 64bit Write-register */ /* Cylces (also #bursts) 64bit Write-register */
#define SET_CYCLES_LSB_REG (0x24 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_CYCLES_LSB_REG (0x24 * REG_OFFSET + BASE_FLOW_CONTROL)
#define SET_CYCLES_MSB_REG (0x25 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_CYCLES_MSB_REG (0x25 * REG_OFFSET + BASE_FLOW_CONTROL)
@ -236,7 +236,7 @@
#define SET_FRAMES_LSB_REG (0x26 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_FRAMES_LSB_REG (0x26 * REG_OFFSET + BASE_FLOW_CONTROL)
#define SET_FRAMES_MSB_REG (0x27 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_FRAMES_MSB_REG (0x27 * REG_OFFSET + BASE_FLOW_CONTROL)
/* Period 64bit Write-register */ /* Period (also burst period) 64bit Write-register */
#define SET_PERIOD_LSB_REG (0x28 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_PERIOD_LSB_REG (0x28 * REG_OFFSET + BASE_FLOW_CONTROL)
#define SET_PERIOD_MSB_REG (0x29 * REG_OFFSET + BASE_FLOW_CONTROL) #define SET_PERIOD_MSB_REG (0x29 * REG_OFFSET + BASE_FLOW_CONTROL)

View File

@ -39,6 +39,7 @@ int virtual_stop = 0;
enum detectorSettings thisSettings = UNINITIALIZED; enum detectorSettings thisSettings = UNINITIALIZED;
int32_t clkPhase[NUM_CLOCKS] = {}; int32_t clkPhase[NUM_CLOCKS] = {};
uint32_t clkFrequency[NUM_CLOCKS] = {}; uint32_t clkFrequency[NUM_CLOCKS] = {};
uint32_t systemFrequency = 0;
int highvoltage = 0; int highvoltage = 0;
int dacValues[NDAC] = {0}; int dacValues[NDAC] = {0};
int onChipdacValues[ONCHIP_NDAC][NCHIP] = {0}; int onChipdacValues[ONCHIP_NDAC][NCHIP] = {0};
@ -49,7 +50,6 @@ uint8_t adcConfiguration[NCHIP][NADC];
int burstMode = BURST_INTERNAL; int burstMode = BURST_INTERNAL;
int64_t numTriggers = 1; int64_t numTriggers = 1;
int64_t numBursts = 1; int64_t numBursts = 1;
int64_t delayAfterTriggerNs = 0;
int64_t burstPeriodNs = 0; int64_t burstPeriodNs = 0;
int detPos[2] = {}; int detPos[2] = {};
@ -346,6 +346,7 @@ void setupDetector() {
clkFrequency[SYSTEM_C1] = DEFAULT_SYSTEM_C1; clkFrequency[SYSTEM_C1] = DEFAULT_SYSTEM_C1;
clkFrequency[SYSTEM_C2] = DEFAULT_SYSTEM_C2; clkFrequency[SYSTEM_C2] = DEFAULT_SYSTEM_C2;
clkFrequency[SYSTEM_C3] = DEFAULT_SYSTEM_C3; clkFrequency[SYSTEM_C3] = DEFAULT_SYSTEM_C3;
systemFrequency = INT_SYSTEM_C0_FREQUENCY;
detPos[0] = 0; detPos[0] = 0;
detPos[1] = 0; detPos[1] = 0;
@ -356,7 +357,6 @@ void setupDetector() {
burstMode = BURST_INTERNAL; burstMode = BURST_INTERNAL;
numTriggers = 1; numTriggers = 1;
numBursts = 1; numBursts = 1;
delayAfterTriggerNs = 0;
burstPeriodNs = 0; burstPeriodNs = 0;
{ {
int i, j; int i, j;
@ -394,6 +394,7 @@ void setupDetector() {
// on chip dacs // on chip dacs
ASIC_Driver_SetDefines(ONCHIP_DAC_DRIVER_FILE_NAME); ASIC_Driver_SetDefines(ONCHIP_DAC_DRIVER_FILE_NAME);
#endif #endif
setTimingSource(DEFAULT_TIMING_SOURCE);
// Default values // Default values
setHighVoltage(DEFAULT_HIGH_VOLTAGE); setHighVoltage(DEFAULT_HIGH_VOLTAGE);
@ -448,7 +449,6 @@ void setupDetector() {
setBurstPeriod(DEFAULT_BURST_PERIOD); setBurstPeriod(DEFAULT_BURST_PERIOD);
setTiming(DEFAULT_TIMING_MODE); setTiming(DEFAULT_TIMING_MODE);
setCurrentSource(DEFAULT_CURRENT_SOURCE); setCurrentSource(DEFAULT_CURRENT_SOURCE);
setTimingSource(DEFAULT_TIMING_SOURCE);
} }
int readConfigFile() { int readConfigFile() {
@ -867,12 +867,12 @@ int setExptimeCont(int64_t val) {
} }
int setExptimeBoth(int64_t val) { int setExptimeBoth(int64_t val) {
val *= (1E-9 * clkFrequency[SYSTEM_C0]); val *= (1E-9 * systemFrequency);
set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG); set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG);
// validate for tolerance // validate for tolerance
int64_t retval = getExptimeBoth(); int64_t retval = getExptimeBoth();
val /= (1E-9 * clkFrequency[SYSTEM_C0]); val /= (1E-9 * systemFrequency);
if (val != retval) { if (val != retval) {
return FAIL; return FAIL;
} }
@ -880,18 +880,18 @@ int setExptimeBoth(int64_t val) {
} }
int64_t getExptimeBoth() { int64_t getExptimeBoth() {
return get64BitReg(ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG) / (1E-9 * clkFrequency[SYSTEM_C0]); return get64BitReg(ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG) / (1E-9 * systemFrequency);
} }
int setPeriodBurst(int64_t val) { int setPeriodBurst(int64_t val) {
FILE_LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val)); FILE_LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val));
val *= (1E-9 * clkFrequency[SYSTEM_C0]); val *= (1E-9 * systemFrequency);
set64BitReg(val, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG); set64BitReg(val, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
// validate for tolerance // validate for tolerance
int64_t retval = getPeriodBurst(); int64_t retval = getPeriodBurst();
val /= (1E-9 * clkFrequency[SYSTEM_C0]); val /= (1E-9 * systemFrequency);
if (val != retval) { if (val != retval) {
return FAIL; return FAIL;
} }
@ -900,17 +900,17 @@ int setPeriodBurst(int64_t val) {
int64_t getPeriodBurst() { int64_t getPeriodBurst() {
FILE_LOG(logDEBUG, ("Getting period [Burst mode]\n")); FILE_LOG(logDEBUG, ("Getting period [Burst mode]\n"));
return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * clkFrequency[SYSTEM_C0]); return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
} }
int setPeriodCont(int64_t val) { int setPeriodCont(int64_t val) {
FILE_LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val)); FILE_LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val));
val *= (1E-9 * FIXED_PLL_FREQUENCY); val *= (1E-9 * systemFrequency);
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG); set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
// validate for tolerance // validate for tolerance
int64_t retval = getPeriodCont(); int64_t retval = getPeriodCont();
val /= (1E-9 * FIXED_PLL_FREQUENCY); val /= (1E-9 * systemFrequency);
if (val != retval) { if (val != retval) {
return FAIL; return FAIL;
} }
@ -919,7 +919,7 @@ int setPeriodCont(int64_t val) {
int64_t getPeriodCont() { int64_t getPeriodCont() {
FILE_LOG(logDEBUG, ("Getting period [Continuous mode]\n")); FILE_LOG(logDEBUG, ("Getting period [Continuous mode]\n"));
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * FIXED_PLL_FREQUENCY); return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
} }
int setDelayAfterTrigger(int64_t val) { int setDelayAfterTrigger(int64_t val) {
@ -928,17 +928,12 @@ int setDelayAfterTrigger(int64_t val) {
return FAIL; return FAIL;
} }
FILE_LOG(logINFO, ("Setting delay after trigger %lld ns\n", val)); FILE_LOG(logINFO, ("Setting delay after trigger %lld ns\n", val));
delayAfterTriggerNs = val; val *= (1E-9 * systemFrequency);
val *= (1E-9 * FIXED_PLL_FREQUENCY); set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
FILE_LOG(logINFO, ("\tBurst and Auto mode: not writing delay to register\n"));
} else {
set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
}
// validate for tolerance // validate for tolerance
int64_t retval = getDelayAfterTrigger(); int64_t retval = getDelayAfterTrigger();
val /= (1E-9 * FIXED_PLL_FREQUENCY); val /= (1E-9 * systemFrequency);
if (val != retval) { if (val != retval) {
return FAIL; return FAIL;
} }
@ -946,10 +941,7 @@ int setDelayAfterTrigger(int64_t val) {
} }
int64_t getDelayAfterTrigger() { int64_t getDelayAfterTrigger() {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { return get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG) / (1E-9 * systemFrequency);
return delayAfterTriggerNs;
}
return get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG) / (1E-9 * FIXED_PLL_FREQUENCY);
} }
int setBurstPeriod(int64_t val) { int setBurstPeriod(int64_t val) {
@ -959,16 +951,16 @@ int setBurstPeriod(int64_t val) {
} }
FILE_LOG(logINFO, ("Setting burst period %lld ns\n", val)); FILE_LOG(logINFO, ("Setting burst period %lld ns\n", val));
burstPeriodNs = val; burstPeriodNs = val;
val *= (1E-9 * FIXED_PLL_FREQUENCY); val *= (1E-9 * systemFrequency);
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { if (burstMode != BURST_OFF) {
set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG); set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
} else { } else {
FILE_LOG(logINFO, ("\tNot (Burst and Auto mode): not writing burst period to register\n")); FILE_LOG(logINFO, ("\t(Continuous mode): not writing burst period to register\n"));
} }
// validate for tolerance // validate for tolerance
int64_t retval = getBurstPeriod(); int64_t retval = getBurstPeriod();
val /= (1E-9 * FIXED_PLL_FREQUENCY); val /= (1E-9 * systemFrequency);
if (val != retval) { if (val != retval) {
return FAIL; return FAIL;
} }
@ -976,8 +968,8 @@ int setBurstPeriod(int64_t val) {
} }
int64_t getBurstPeriod() { int64_t getBurstPeriod() {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { if (burstMode != BURST_OFF) {
return get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG) / (1E-9 * FIXED_PLL_FREQUENCY); return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG) / (1E-9 * systemFrequency);
} }
return burstPeriodNs; return burstPeriodNs;
} }
@ -991,11 +983,11 @@ int64_t getNumTriggersLeft() {
} }
int64_t getDelayAfterTriggerLeft() { int64_t getDelayAfterTriggerLeft() {
return get64BitReg(GET_DELAY_LSB_REG, GET_DELAY_MSB_REG) / (1E-9 * FIXED_PLL_FREQUENCY); return get64BitReg(GET_DELAY_LSB_REG, GET_DELAY_MSB_REG) / (1E-9 * systemFrequency);
} }
int64_t getPeriodLeft() { int64_t getPeriodLeft() {
return get64BitReg(GET_PERIOD_LSB_REG, GET_PERIOD_MSB_REG) / (1E-9 * FIXED_PLL_FREQUENCY); return get64BitReg(GET_PERIOD_LSB_REG, GET_PERIOD_MSB_REG) / (1E-9 * systemFrequency);
} }
int64_t getFramesFromStart() { int64_t getFramesFromStart() {
@ -1210,8 +1202,6 @@ void setTiming( enum timingMode arg){
FILE_LOG(logINFO, ("\tUpdating trigger/burst and delay/burst period registers\n")) FILE_LOG(logINFO, ("\tUpdating trigger/burst and delay/burst period registers\n"))
setNumTriggers(numTriggers); setNumTriggers(numTriggers);
setNumBursts(numBursts); setNumBursts(numBursts);
setDelayAfterTrigger(delayAfterTriggerNs);
setBurstPeriod(burstPeriodNs);
} }
enum timingMode getTiming() { enum timingMode getTiming() {
@ -1574,6 +1564,10 @@ int setClockDivider(enum CLKINDEX ind, int val) {
ALTERA_PLL_C10_SetOuputFrequency (pllIndex, clkIndex, newfreq); ALTERA_PLL_C10_SetOuputFrequency (pllIndex, clkIndex, newfreq);
clkFrequency[ind] = newfreq; clkFrequency[ind] = newfreq;
FILE_LOG(logINFO, ("\t%s clock (%d) divider set to %d (%d Hz)\n", clock_names[ind], ind, val, clkFrequency[ind])); FILE_LOG(logINFO, ("\t%s clock (%d) divider set to %d (%d Hz)\n", clock_names[ind], ind, val, clkFrequency[ind]));
// update system frequency
if (ind == SYSTEM_C0) {
setTimingSource(getTimingSource());
}
// phase is reset by pll (when setting output frequency) // phase is reset by pll (when setting output frequency)
if (ind >= READOUT_C0) { if (ind >= READOUT_C0) {
@ -1890,10 +1884,9 @@ int setBurstMode(enum burstMode burst) {
return FAIL; return FAIL;
} }
FILE_LOG(logINFO, ("\tUpdating trigger/burst and delay/burst period registers\n")) FILE_LOG(logINFO, ("\tUpdating trigger/burst and burst period registers\n"))
setNumTriggers(numTriggers); setNumTriggers(numTriggers);
setNumBursts(numBursts); setNumBursts(numBursts);
setDelayAfterTrigger(delayAfterTriggerNs);
setBurstPeriod(burstPeriodNs); setBurstPeriod(burstPeriodNs);
// set number of frames and period again (set registers according to timing mode) // set number of frames and period again (set registers according to timing mode)
@ -1982,10 +1975,12 @@ void setTimingSource(enum timingSourceType value) {
case TIMING_INTERNAL: case TIMING_INTERNAL:
FILE_LOG(logINFO, ("Setting timing source to internal\n")); FILE_LOG(logINFO, ("Setting timing source to internal\n"));
bus_w(addr, (bus_r(addr) &~ CONTROL_TIMING_SOURCE_EXT_MSK)); bus_w(addr, (bus_r(addr) &~ CONTROL_TIMING_SOURCE_EXT_MSK));
systemFrequency = INT_SYSTEM_C0_FREQUENCY;
break; break;
case TIMING_EXTERNAL: case TIMING_EXTERNAL:
FILE_LOG(logINFO, ("Setting timing source to exernal\n")); FILE_LOG(logINFO, ("Setting timing source to exernal\n"));
bus_w(addr, (bus_r(addr) | CONTROL_TIMING_SOURCE_EXT_MSK)); bus_w(addr, (bus_r(addr) | CONTROL_TIMING_SOURCE_EXT_MSK));
systemFrequency = clkFrequency[SYSTEM_C0];
break; break;
default: default:
FILE_LOG(logERROR, ("Unknown timing source %d\n", value)); FILE_LOG(logERROR, ("Unknown timing source %d\n", value));

View File

@ -54,6 +54,7 @@
/* Firmware Definitions */ /* Firmware Definitions */
#define IP_HEADER_SIZE (20) #define IP_HEADER_SIZE (20)
#define FIXED_PLL_FREQUENCY (20000000) // 20MHz #define FIXED_PLL_FREQUENCY (20000000) // 20MHz
#define INT_SYSTEM_C0_FREQUENCY (144000000) //144 MHz
#define READOUT_PLL_VCO_FREQ_HZ (866666688) // 866 MHz #define READOUT_PLL_VCO_FREQ_HZ (866666688) // 866 MHz
#define SYSTEM_PLL_VCO_FREQ_HZ (722222224) // 722 MHz #define SYSTEM_PLL_VCO_FREQ_HZ (722222224) // 722 MHz

View File

@ -8,5 +8,5 @@
#define APIRECEIVER 0x200227 #define APIRECEIVER 0x200227
#define APIGUI 0x200227 #define APIGUI 0x200227
#define APICTB 0x200227 #define APICTB 0x200227
#define APIGOTTHARD2 0x200228 #define APIGOTTHARD2 0x200303
#define APIMOENCH 0x200303 #define APIMOENCH 0x200303