diff --git a/.gitignore b/.gitignore index 8496be4e..42d69966 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ *.pyc *_ui.py +*.o +*.so +*.a build/* nottcontrol.egg-info/* nottcontrol/script/data/* diff --git a/nottcontrol/camera/__init__.py b/nottcontrol/camera/infratec/__init__.py similarity index 100% rename from nottcontrol/camera/__init__.py rename to nottcontrol/camera/infratec/__init__.py diff --git a/nottcontrol/camera/brightness_calculator.py b/nottcontrol/camera/infratec/brightness_calculator.py similarity index 88% rename from nottcontrol/camera/brightness_calculator.py rename to nottcontrol/camera/infratec/brightness_calculator.py index b693de3b..ff5356b9 100644 --- a/nottcontrol/camera/brightness_calculator.py +++ b/nottcontrol/camera/infratec/brightness_calculator.py @@ -6,7 +6,7 @@ """ import numpy -from nottcontrol.camera.utils.utils import BrightnessResults +from nottcontrol.camera.infratec.utils.utils import BrightnessResults class BrightnessCalculator(): diff --git a/nottcontrol/camera/hirbgrab.py b/nottcontrol/camera/infratec/hirbgrab.py similarity index 100% rename from nottcontrol/camera/hirbgrab.py rename to nottcontrol/camera/infratec/hirbgrab.py diff --git a/nottcontrol/camera/infratec_interface.py b/nottcontrol/camera/infratec/infratec_interface.py similarity index 98% rename from nottcontrol/camera/infratec_interface.py rename to nottcontrol/camera/infratec/infratec_interface.py index 46433684..2925fce6 100644 --- a/nottcontrol/camera/infratec_interface.py +++ b/nottcontrol/camera/infratec/infratec_interface.py @@ -20,8 +20,8 @@ # old syspath.append version sys.path.append(r'D:\Python_Entwicklertools\IRBGrab') sys.path.append(r'D:\Python_Entwicklertools\analyseFunctions') - import nottcontrol.camera.irbgrab as irbg - import nottcontrol.camera.hirbgrab as hirb + import nottcontrol.camera.infratec.irbgrab as irbg + import nottcontrol.camera.infratec.hirbgrab as hirb class InfratecInterface: def __init__(self): diff --git a/nottcontrol/camera/irbgrab.py b/nottcontrol/camera/infratec/irbgrab.py similarity index 99% rename from nottcontrol/camera/irbgrab.py rename to nottcontrol/camera/infratec/irbgrab.py index fefec5f8..6198c796 100644 --- a/nottcontrol/camera/irbgrab.py +++ b/nottcontrol/camera/infratec/irbgrab.py @@ -11,7 +11,7 @@ import IRBGrab.hirbgrab as hirb except ImportError: # print('HERE') - import nottcontrol.camera.hirbgrab as hirb + import nottcontrol.camera.infratec.hirbgrab as hirb import pkg_resources as pkgrsrc diff --git a/nottcontrol/camera/mainwindow.ui b/nottcontrol/camera/infratec/mainwindow.ui similarity index 100% rename from nottcontrol/camera/mainwindow.ui rename to nottcontrol/camera/infratec/mainwindow.ui diff --git a/nottcontrol/camera/parametersdialog.py b/nottcontrol/camera/infratec/parametersdialog.py similarity index 100% rename from nottcontrol/camera/parametersdialog.py rename to nottcontrol/camera/infratec/parametersdialog.py diff --git a/nottcontrol/camera/parametersdialog.ui b/nottcontrol/camera/infratec/parametersdialog.ui similarity index 100% rename from nottcontrol/camera/parametersdialog.ui rename to nottcontrol/camera/infratec/parametersdialog.ui diff --git a/nottcontrol/camera/roi.py b/nottcontrol/camera/infratec/roi.py similarity index 100% rename from nottcontrol/camera/roi.py rename to nottcontrol/camera/infratec/roi.py diff --git a/nottcontrol/camera/roiwidget.py b/nottcontrol/camera/infratec/roiwidget.py similarity index 93% rename from nottcontrol/camera/roiwidget.py rename to nottcontrol/camera/infratec/roiwidget.py index a7ec3579..e8039fef 100644 --- a/nottcontrol/camera/roiwidget.py +++ b/nottcontrol/camera/infratec/roiwidget.py @@ -2,8 +2,8 @@ from PyQt5.uic import loadUi from PyQt5.QtGui import QColor, QPalette from PyQt5.QtWidgets import QFrame -from nottcontrol.camera.utils.utils import BrightnessResults -from nottcontrol.camera.roi import Roi +from nottcontrol.camera.infratec.utils.utils import BrightnessResults +from nottcontrol.camera.infratec.roi import Roi import pyqtgraph as pg from collections import deque diff --git a/nottcontrol/camera/roiwidget.ui b/nottcontrol/camera/infratec/roiwidget.ui similarity index 100% rename from nottcontrol/camera/roiwidget.ui rename to nottcontrol/camera/infratec/roiwidget.ui diff --git a/nottcontrol/camera/scify.py b/nottcontrol/camera/infratec/scify.py similarity index 98% rename from nottcontrol/camera/scify.py rename to nottcontrol/camera/infratec/scify.py index f2f8bb23..92cf28d0 100644 --- a/nottcontrol/camera/scify.py +++ b/nottcontrol/camera/infratec/scify.py @@ -15,18 +15,18 @@ from PyQt5.QtWidgets import QVBoxLayout from PyQt5.QtWidgets import QFileDialog from PyQt5.QtGui import QColorConstants -from nottcontrol.camera.infratec_interface import InfratecInterface, Image +from nottcontrol.camera.infratec.infratec_interface import InfratecInterface, Image import numpy import cv2 -from nottcontrol.camera.brightness_calculator import BrightnessCalculator -from nottcontrol.camera.parametersdialog import ParametersDialog +from nottcontrol.camera.infratec.brightness_calculator import BrightnessCalculator +from nottcontrol.camera.infratec.parametersdialog import ParametersDialog from nottcontrol.redisclient import RedisClient from nottcontrol import config from collections import deque from enum import Enum -from nottcontrol.camera.roi import Roi -from nottcontrol.camera.roiwidget import RoiWidget +from nottcontrol.camera.infratec.roi import Roi +from nottcontrol.camera.infratec.roiwidget import RoiWidget import queue from pathlib import Path import zmq diff --git a/nottcontrol/camera/utils/utils.py b/nottcontrol/camera/infratec/utils/utils.py similarity index 100% rename from nottcontrol/camera/utils/utils.py rename to nottcontrol/camera/infratec/utils/utils.py diff --git a/nottcontrol/camera/macie/MACIE_Installation_notes.txt b/nottcontrol/camera/macie/MACIE_Installation_notes.txt new file mode 100644 index 00000000..44358418 --- /dev/null +++ b/nottcontrol/camera/macie/MACIE_Installation_notes.txt @@ -0,0 +1,108 @@ +MACIE Installation Notes +======================== + +Install readline required for macie_exe command line program: + - sudo apt-get install libreadline6 libreadline6-dev + + +Linux - Software v4.0/5.0 +------------------------- + +Program directory: + /home/observer/macie_linux will be symlink to latest version + ln -s macie_v5.1_ubuntu macie_linux + In macie_v5.1_ubuntu: ln -s MacieApp msac + +Macie library files + sudo cp -r /home/observer/macie_linux/MacieApp /usr/local/lib/macie_lib_v5.1 + ln -s /usr/local/lib/macie_lib_v5.1 /home/observer/macie_v5.1_ubuntu/macie_lib + sudo ln -s /usr/local/lib/macie_lib_v5.1 /usr/local/lib/macie_lib + Run "sudo ldconfig -nN ." in /usr/local/lib/macie_lib folder + Make symlinks libcfitsio.so, libMACIE.so, libmil.so, and libQt5SerialPort.so in /usr/local/lib/macie_lib/ + sudo ln -s libcfitsio.so.2.3.37 libcfitsio.so + sudo ln -s libmil.so.10.20.517 libmil.so + sudo ln -s libQt5SerialPort.so.5.10.1 libQt5SerialPort.so + + +In .bashrc: + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/macie_lib + export CPATH=$CPATH:/usr/local/lib/macie_lib + +Sym links of programs somewhere in $PATH: + Make sure to chmod +x ds9 in msac/ + sudo ln -s /home/observer/macie_linux/MacieApp/msac /usr/local/bin/ + sudo ln -s /home/observer/macie_linux/MacieApp/ds9 /usr/local/bin/ [optional] + +Disable ibus language: + Switch System Setting > Language to none rather than ibus. + Otherwise, large CPU usage for no apparent reason? + +Rules file: + sudo cp 51-ftd3xx.rules /etc/udev/rules.d + sudo udevadm control --reload-rules + +======================================================================= + +To create rules file: + +$ lsusb +Bus 003 Device 008: ID 0403:601f Future Technology Devices International, Ltd + +Indicates MACIE mounted at: /dev/bus/usb/003/008 + +Look at device info: + + $ udevadm info -a -p $(udevadm info -q path -n /dev/bus/usb/003/008) + +Create a rules document (NOTE: it is ATTRS in the rules file, not ATTR) +Make sure observer is part of users group: + + $ sudo adduser observer users + +In file 51-ftd3xx.rules: +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601e", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601f", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602a", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602b", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602c", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602d", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602f", MODE="0666" + +or + +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601[e-f]", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602[a-f]", MODE="0666" + +or + +SUBSYSTEMS!="usb", ACTION!="add", GOTO="macie_rules_end" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601e", MODE="0666" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601f", MODE="0666" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602a", MODE="0666" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602b", MODE="0666" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602c", MODE="0666" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602d", MODE="0666" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602f", MODE="0666" +LABEL="macie_rules_end" + +or + +SUBSYSTEMS!="usb", ACTION!="add", GOTO="macie_rules_end" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601e", GROUP="users", MODE="0660" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601f", GROUP="users", MODE="0660" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602a", GROUP="users", MODE="0660" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602b", GROUP="users", MODE="0660" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602c", GROUP="users", MODE="0660" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602d", GROUP="users", MODE="0660" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="602f", GROUP="users", MODE="0660" +LABEL="macie_rules_end" + + + +Then run: + sudo cp 51-ftd3xx.rules /etc/udev/rules.d + sudo udevadm control --reload-rules + #sudo udevadm trigger + + + diff --git a/nottcontrol/camera/macie/libmacie/Makefile b/nottcontrol/camera/macie/libmacie/Makefile new file mode 100644 index 00000000..d39d9280 --- /dev/null +++ b/nottcontrol/camera/macie/libmacie/Makefile @@ -0,0 +1,22 @@ +# Makefile for libmacie.a + +# gcc +CC = LD_LIBRARY_PATH=/usr/local/lib/macie_lib CPATH=/usr/local/lib/macie_lib g++ +CFLAGS = -O2 -Wall -g -fPIC + +all: libmacie.a + +SRCS = \ + macie_lib.c \ + +OBJS = $(SRCS:.c=.o) + +libmacie.a: $(OBJS) + ar r $@ $(OBJS) + ranlib $@ + +clean: clobber + +clobber: + rm -rf $(OBJS) libmacie.a + diff --git a/nottcontrol/camera/macie/libmacie/macie_lib.c b/nottcontrol/camera/macie/libmacie/macie_lib.c new file mode 100644 index 00000000..f9cbe8c6 --- /dev/null +++ b/nottcontrol/camera/macie/libmacie/macie_lib.c @@ -0,0 +1,5369 @@ +/// macie_lib.c +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2018, Jarron Leisenring, All rights reserved. +// + +#include "macie_lib.h" + +using std::map; +using std::string; +using std::vector; + +// Timestamp in terms of microsec +typedef unsigned long long timestamp_t; +static timestamp_t get_timestamp() +{ + struct timeval now; + gettimeofday(&now, NULL); + return now.tv_usec + (timestamp_t)now.tv_sec * 1000000; +} + +// Sleep for some number of millisec +void delay(int ms) +{ + // clock_t t0 = clock(); + // while ((clock() - t0) * 1000 / CLOCKS_PER_SEC < ms); + usleep(1000 * ms); +} + +bool SettingsCheckNULL(MACIE_Settings *ptUserData) +{ + // Is our structure ok? + if (ptUserData == NULL) + { + fprintf(stderr, "User data structure is not valid\n"); + return false; + } + + return true; +} + +/// \brief create_param_struct Use this function to populate defaults for +/// variables within newly created ptUserData structure. For instance, +/// specify: struct MACIE_Settings *ptUserData = new MACIE_Settings; +/// then: create_param_struct(ptUserData, LOG_INFO); +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param verbosity Verbosity level to set things moving forward. +bool create_param_struct(MACIE_Settings *ptUserData, LOG_LEVEL verbosity) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + ptUserData->verbosity = verbosity; + + ptUserData->saveDir = ""; + ptUserData->filePrefix = ""; + + // Initialize some values to defaults and others to 0 + ptUserData->pCard = new MACIE_CardInfo[8]; + ptUserData->numCards = 0; + ptUserData->handle = 0; + ptUserData->avaiMACIEs = 0; + ptUserData->slctMACIEs = 1; + ptUserData->bMACIEslot1 = true; + ptUserData->avaiASICs = 0; + ptUserData->slctASICs = 1; + + ptUserData->clkRateM = 0; + ptUserData->clkRateMDefault = 0; + ptUserData->clkPhase = 0; + ptUserData->clkPhaseDefault = 0; + ptUserData->pixelRate = 0; + + ptUserData->uiNumCoadds = 1; + ptUserData->uiNumSaves = 0; + ptUserData->uiNumGroups_max = 2; // Must be 2 or greater + + ptUserData->nBuffer = 20; // Default number of buffers + ptUserData->nPixBuffer = 2048 * 2048; // Default buffer size (in pixels) + ptUserData->nPixBuffMin = 4 * 1024 * 1024; // Min size (in pixels) for successful buffer allocation + ptUserData->nPixBuffMax = 120 * 2048 * 2048; // Max size (in pixels) for a single buffer + // ptUserData->nBytesMin = 1024 * 1024; + ptUserData->nBytesMax = UINT_MAX; // Maximum number of total bytes allowed for mem allocation + ptUserData->bUseSciDataFunc = false; // Use MACIE_ReadUSBScienceData() or MACIE_ReadUSBFrameData()? + + ptUserData->bSaveData = false; + ptUserData->uiFileNum = 0; + + ptUserData->uiDetectorWidth = 0; + ptUserData->uiDetectorHeight = 0; + + ptUserData->bStripeModeAllowed = false; + ptUserData->bStripeMode = false; + + // Pixel clocking scheme for full frame and subarray window + // Normal (0) or Enhanced (1) + // Only here until Enhanced+Window works correctly in future ASIC microcode + ptUserData->ffPixelClkScheme = 0; + ptUserData->winPixelClkScheme = 0; + + ptUserData->offline_develop = false; + + // Set all error counters to 0 + std::fill_n(ptUserData->errArr, MACIE_ERROR_COUNTERS, 0); + + verbose_printf(LOG_DEBUG, ptUserData, "%s() returns true\n", __func__); + // verbose_printf(LOG_INFO, ptUserData, "macieSerialNumber=%i\n", ptUserData->pCard[0].macieSerialNumber); + + return true; +} + +void CardInfo_testing(MACIE_CardInfo **pCard) +{ + (*pCard)[0].macieSerialNumber = 1337; + (*pCard)[0].bUART = false; + (*pCard)[0].bGigE = false; + (*pCard)[0].bUSB = true; + strcpy((*pCard)[0].usbSerialNumber, "MACIE01337"); + (*pCard)[0].usbSpeed = 48; +} + +string addr_name_hex(unsigned int addr) +{ + string addr_name = "0x"; + + // Convert decimal addr to hex string + std::stringstream ss; + ss << std::hex << addr; + addr_name.append(ss.str()); + + return addr_name; +} + +// 1. Check Interfaces: Detects and reports available MACIE cards and communication interfaces +//////////////////////////////////////////////////////////////////////////////// +/// \brief CheckInterfaces Find all available MACIE cards that are connected to +/// the computer (directly or via network) and provide information about the +/// available interfaces (Camera Link, GigE and USB) to each card. Information +/// about each interface connection will be printed to console if +/// ptUserData.verbosity is high enough level. +/// \param ptUserData The user-set structure containing all the hardware parameters +bool CheckInterfaces(MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Check interfaces + verbose_printf(LOG_INFO, ptUserData, "Checking MACIE Communication Interfaces....\n"); + if (ptUserData->offline_develop == false) + { + if (MACIE_CheckInterfaces(0, NULL, 0, &ptUserData->numCards, &ptUserData->pCard) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_CheckInterfaces failed: %s\n", MACIE_Error()); + return false; + } + } + else + { + ptUserData->numCards = 1; + CardInfo_testing(&ptUserData->pCard); + } + verbose_printf(LOG_INFO, ptUserData, "numCards = %i\n", ptUserData->numCards); + + // Initialize pCard pointer shortcut + MACIE_CardInfo *pCard = ptUserData->pCard; + + // Print information + for (int i = 0; i < ptUserData->numCards; i++) + { + verbose_printf(LOG_INFO, ptUserData, "macieSerialNumber=%i\n", pCard[i].macieSerialNumber); + // verbose_printf(LOG_INFO, ptUserData, "TEMP PRINT bUART=%i\n", pCard[i].bUART); + // CamLink + if (pCard[i].bUART == true) + { + verbose_printf(LOG_INFO, ptUserData, " MACIE card connected to CamLink port\n"); + verbose_printf(LOG_INFO, ptUserData, " serialPortName=%s\n", pCard[i].serialPortName); + } + // GigE + if (pCard[i].bGigE == true) + { + verbose_printf(LOG_INFO, ptUserData, " MACIE card connected to GigE port\n"); + verbose_printf(LOG_INFO, ptUserData, " ipAddr=%i.%i.%i.%i\n", + static_cast((pCard[i].ipAddr)[0]), static_cast((pCard[i].ipAddr)[1]), + static_cast((pCard[i].ipAddr)[2]), static_cast((pCard[i].ipAddr)[3])); + } + // USB + if (pCard[i].bUSB == true) + { + verbose_printf(LOG_INFO, ptUserData, " MACIE card connected to USB port\n"); + verbose_printf(LOG_INFO, ptUserData, " usbSerialNumber=%s\n", pCard[i].usbSerialNumber); + verbose_printf(LOG_INFO, ptUserData, " USBSpeed=%i\n", pCard[i].usbSpeed); + } + } + + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; +} + +// 2. Get Handle (USB): Obtain a handle for the first available MACIE card connected by USB port +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetHandleUSB Set current communication interface with the input MACIE +/// serial number and USB connection. Grabs the first MACIE card it finds +/// connected to a USB connections. Sets a unique handle based on the MACIE +/// serial number and the MACIE_Connection type. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool GetHandleUSB(MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // CardInfo was already set in CheckInterfaces + // if (ptUserData->offline_develop == false) + // { + // if (MACIE_CheckInterfaces(0, NULL, 0, &ptUserData->numCards, &ptUserData->pCard) != MACIE_OK) + // { + // verbose_printf(LOG_ERROR, ptUserData, "MACIE_CheckInterfaces failed: %s\n", MACIE_Error()); + // return false; + // } + // } + // else + // { + // ptUserData->pCard = ptUserData->CardInfo); + // } + + MACIE_CardInfo *pCard = ptUserData->pCard; + + if (ptUserData->numCards == 0) + { + verbose_printf(LOG_ERROR, ptUserData, "No cards found: numCards = %i\n", ptUserData->numCards); + return false; + } + + ptUserData->handle = 0; + + // Cycle through each card to find USB and save info and handle + for (int i = 0; i < ptUserData->numCards; i++) + { + if (pCard[i].bUSB == true) + { + verbose_printf(LOG_INFO, ptUserData, "Get handle for the interface of MACIE %i on USB port\n", + pCard[i].macieSerialNumber); + + if (ptUserData->offline_develop == false) + ptUserData->handle = MACIE_GetHandle(pCard[i].macieSerialNumber, ptUserData->connection); + else + ptUserData->handle = 1; + + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; + } + } + + // If failed to find a USB, then handle=0 + if ((ptUserData->handle == 0) || (ptUserData->numCards == 0)) + { + verbose_printf(LOG_ERROR, ptUserData, " No USB cards found. Check interfaces.\n"); + verbose_printf(LOG_ERROR, ptUserData, " numCards=%i, handle=%i\n", + ptUserData->numCards, ptUserData->handle); + return false; + } + + // Should never get here, but compiler was complaining about no return statement + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; +} + +// 2. Get Handle (gigE): Obtain a handle for the first available MACIE card connected by gigE port +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetHandleGigE Set current communication interface with the input MACIE +/// serial number and gigE connection. Grabs the first MACIE card it finds +/// connected to a gigE connections. Sets a unique handle based on the MACIE +/// serial number and the MACIE_Connection type. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool GetHandleGigE(MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // CardInfo was already set in CheckInterfaces + // if (ptUserData->offline_develop == false) + // { + // if (MACIE_CheckInterfaces(0, NULL, 0, &ptUserData->numCards, &ptUserData->pCard) != MACIE_OK) + // { + // verbose_printf(LOG_ERROR, ptUserData, "MACIE_CheckInterfaces failed: %s\n", MACIE_Error()); + // return false; + // } + // } + // else + // { + // ptUserData->pCard = ptUserData->CardInfo); + // } + + MACIE_CardInfo *pCard = ptUserData->pCard; + + if (ptUserData->numCards == 0) + { + verbose_printf(LOG_ERROR, ptUserData, "No cards found: numCards = %i\n", ptUserData->numCards); + return false; + } + + ptUserData->handle = 0; + + // Cycle through each card to find the ethernet connection and save info and handle + for (int i = 0; i < ptUserData->numCards; i++) + { + if (pCard[i].bGigE == true) // TODO: maybe extend this to support more than one protocol at the same time? + { + verbose_printf(LOG_INFO, ptUserData, "Get handle for the interface of MACIE %i on USB port\n", + pCard[i].macieSerialNumber); + + if (ptUserData->offline_develop == false) + ptUserData->handle = MACIE_GetHandle(pCard[i].macieSerialNumber, ptUserData->connection); + else + ptUserData->handle = 1; + + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; + } + } + + // If failed to find a USB, then handle=0 + if ((ptUserData->handle == 0) || (ptUserData->numCards == 0)) + { + verbose_printf(LOG_ERROR, ptUserData, " No USB cards found. Check interfaces.\n"); + verbose_printf(LOG_ERROR, ptUserData, " numCards=%i, handle=%i\n", + ptUserData->numCards, ptUserData->handle); + return false; + } + + // Should never get here, but compiler was complaining about no return statement + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; +} + + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetAvailableMACIEs Detect Available MACIE cards: Reports how many +/// MACIE cards are connected at the port that is associated with the handle +/// stored in ptUserData. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool GetAvailableMACIEs(MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + unsigned int val = 3; + + // avaiMACIEs consists of 8 bits indicating up to eight possible MACIE cards + // slctMACIEs selects which MACIE to use + verbose_printf(LOG_INFO, ptUserData, "Get available MACIE cards...\n"); + if (ptUserData->offline_develop == false) + ptUserData->avaiMACIEs = MACIE_GetAvailableMACIEs(ptUserData->handle); + else + ptUserData->avaiMACIEs = 1; + ptUserData->slctMACIEs = ptUserData->avaiMACIEs & 1; // Select MACIE0 + + if (ptUserData->slctMACIEs == 0) + { + verbose_printf(LOG_ERROR, ptUserData, " slctMACIEs = %i is invalid (avaiMACIEs = 0x%01x)\n", + ptUserData->slctMACIEs, ptUserData->avaiMACIEs); + return false; + } + else if (ptUserData->offline_develop == false) + { + if (MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, 0x0300, &val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, " MACIE read h0300 failed: %s\n", MACIE_Error()); + return false; + } + } + else + { + verbose_printf(LOG_INFO, ptUserData, " MACIEs Available: MACIE%i\n", + (unsigned short)ptUserData->slctMACIEs - 1); + verbose_printf(LOG_DEBUG, ptUserData, " MACIE h0300 = 0x%04x\n", val); + } + + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetAvailableASICs Detect Available ASIC cards: Reports how many +/// ASIC cards are connected through the same interface that is associated with +/// the handle stored in ptUserData. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool GetAvailableASICs(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // avaiASICs consists of 8 bits indicating up to eight possible ASIC cards (paried to 8 MACIEs) + // slctASICs selects which ASIC to use + verbose_printf(LOG_INFO, ptUserData, "Get available ASIC cards...\n"); + if (ptUserData->offline_develop == false) + ptUserData->avaiASICs = MACIE_GetAvailableASICs(ptUserData->handle, 0); + else + ptUserData->avaiASICs = 1; + ptUserData->slctASICs = ptUserData->avaiASICs & 1; // Select ASIC0 + + if (ptUserData->slctASICs == 0) + { + verbose_printf(LOG_ERROR, ptUserData, " slctASICs = %i is invalid (avaiASICs = 0x%1x)\n", + ptUserData->slctASICs, ptUserData->avaiASICs); + return false; + } + else + { + verbose_printf(LOG_INFO, ptUserData, " ASIC Selected: ASIC%i\n", + (unsigned short)ptUserData->slctASICs - 1); + } + + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ASIC_Defaults Set default values for various ASIC parameters +/// depending on the detector type. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool ASIC_Defaults(MACIE_Settings *ptUserData) +{ + + // Update intrinsic detector size + if (ptUserData->DetectorType == CAMERA_TYPE_H1RG) + { + ptUserData->uiDetectorWidth = 1024; + ptUserData->uiDetectorHeight = 1024; + // ptUserData->nBuffer = ptUserData->DetectorMode==CAMERA_MODE_FAST ? 480 : 80; + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + SetASICParameter(ptUserData, "DetectorType", 1); + } + } + else if (ptUserData->DetectorType == CAMERA_TYPE_H2RG) + { + ptUserData->uiDetectorWidth = 2048; + ptUserData->uiDetectorHeight = 2048; + // ptUserData->nBuffer = ptUserData->DetectorMode==CAMERA_MODE_FAST ? 100 : 20; + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + SetASICParameter(ptUserData, "DetectorType", 2); + } + } + else if (ptUserData->DetectorType == CAMERA_TYPE_H4RG) + { + ptUserData->uiDetectorWidth = 4096; + ptUserData->uiDetectorHeight = 4096; + // ptUserData->nBuffer = ptUserData->DetectorMode==CAMERA_MODE_FAST ? 25 : 10; + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + SetASICParameter(ptUserData, "DetectorType", 4); + } + } + else + { + verbose_printf(LOG_ERROR, ptUserData, "DetectorType not recognized.\n"); + return false; + } + + // Reference Inputs + if (ptUserData->DetectorMode == CAMERA_MODE_FAST) // Ground Fast + ASIC_Inputs(ptUserData, true, 0x5a0a); + + // Extra pixels per line + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + SetASICParameter(ptUserData, "ExtraPixels", 0); + } + else + { + SetASICParameter(ptUserData, "ExtraPixels", 3); + } + + // Extra lines per frame + SetASICParameter(ptUserData, "ExtraLines", 0); + + // X and Y positions for full frame (???) + ASIC_setX1(ptUserData, 0); + ASIC_setX2(ptUserData, ptUserData->uiDetectorWidth - 1); + ASIC_setY1(ptUserData, 0); + ASIC_setY2(ptUserData, ptUserData->uiDetectorHeight - 1); + + // Update PixPerRow & RowsPerFrame for offline testing mode + if (ptUserData->offline_develop == true) + { + unsigned int nout = ASIC_NumOutputs(ptUserData); + unsigned int xtra_pix = ASIC_Generic(ptUserData, "ExtraPixels", false, 0); + unsigned int xtra_lines = ASIC_Generic(ptUserData, "ExtraLines", false, 0); + unsigned int ppr = ptUserData->uiDetectorWidth / nout + xtra_pix; + unsigned int rpf = ptUserData->uiDetectorHeight + xtra_lines; + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + SetASICParameter(ptUserData, "PixPerRow", ppr + 8); + else + SetASICParameter(ptUserData, "PixPerRow", ppr); + SetASICParameter(ptUserData, "RowsPerFrame", rpf + 1); + } + + // Fast Mode Gains and offsets + if (ptUserData->DetectorMode == CAMERA_MODE_FAST) + { + ASIC_Gain(ptUserData, true, 5); + ASIC_CapComp(ptUserData, true, 38); + SetASICParameter(ptUserData, "VPreAmpRef1", 0x72c0); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief InitializeASIC Initialize ASIC associated with handle in ptUserData. +/// GetAvailableMACIEs must already have been run to populate slctMACIEs. +/// This function loads the MACIE firmware in the specified slot, downloads +/// the MACIE registers to the device, downloads +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool InitializeASIC(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // MACIEFile = MACIE_Registers_Fast.mrf or MACIE_Registers_Slow.mrf + // ASICFile = *.mcd + + unsigned int val = 0; + + // verbose_printf(LOG_INFO, ptUserData, "MACIE Library Version: %.1f\n", MACIE_LibVersion()); + verbose_printf(LOG_INFO, ptUserData, "Initializing with handle %i\n", ptUserData->handle); + + if ((unsigned short)ptUserData->slctMACIEs == 0) + { + verbose_printf(LOG_ERROR, ptUserData, " No MACIEs available\n"); + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // step 1: load MACIE firmware from slot 1 (true) or slot 2 (false) + verbose_printf(LOG_INFO, ptUserData, "Load MACIE firmware in slot %i...\n", ((ptUserData->bMACIEslot1 == true) ? 1 : 2)); + if (ptUserData->offline_develop == false) + { + if (MACIE_loadMACIEFirmware(ptUserData->handle, ptUserData->slctMACIEs, ptUserData->bMACIEslot1, &val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, " Failed: %s\n", MACIE_Error()); + return false; + } + if (val != 0xac1e) // Confirm firmware is for SIDECAR ASIC (0xac1e) + { + verbose_printf(LOG_ERROR, ptUserData, " Verification of MACIE firmware load failed: \n"); + verbose_printf(LOG_ERROR, ptUserData, " Readback of hFFFB = 0x%04x\n", val); + return false; + } + verbose_printf(LOG_INFO, ptUserData, " Succeeded.\n"); + // Store firmware information + MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, 0xfffd, &ptUserData->firmwareVersion); + MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, 0xfffe, &ptUserData->firmwareMonthDay); + MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, 0xffff, &ptUserData->firmwareYear); + } + else + { + ptUserData->firmwareVersion = 0x0310; + ptUserData->firmwareMonthDay = 0x0101; + ptUserData->firmwareYear = 0x2018; + } + verbose_printf(LOG_INFO, ptUserData, "Version = %04X MonthDay = %04X Year = %04X\n", + ptUserData->firmwareVersion, ptUserData->firmwareMonthDay, ptUserData->firmwareYear); + + //////////////////////////////////////////////////////////////////////////////// + // step 2: download MACIE registers + verbose_printf(LOG_INFO, ptUserData, "Downloading MACIE register %s\n", ptUserData->MACIEFile); + if (ptUserData->offline_develop == false) + { + if (MACIE_DownloadMACIEFile(ptUserData->handle, ptUserData->slctMACIEs, ptUserData->MACIEFile) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, " Failed: %s\n", MACIE_Error()); + return false; + } + } + else + { + verbose_printf(LOG_INFO, ptUserData, " Offline testing mode, skipping MACIE_DownloadMACIEFile().\n"); + } + verbose_printf(LOG_INFO, ptUserData, " Succeeded.\n"); + + //////////////////////////////////////////////////////////////////////////////// + // step 3: set default clkRate and clkPhase value stored in ptUserData + verbose_printf(LOG_INFO, ptUserData, "Setting MACIE clock rate and phase parameters to default\n"); + if (GetMACIEClockRate(ptUserData) == false) + return false; + // if (SetMACIEClockRate(ptUserData, ptUserData->clkRateMDefault) == false) + // return false; + // verbose_printf(LOG_INFO, ptUserData, "Setting MACIE phase parameters to default\n"); + if (SetMACIEPhaseShift(ptUserData, ptUserData->clkPhaseDefault) == false) + return false; + + //////////////////////////////////////////////////////////////////////////////// + // step 4: Load ASIC firmware, download register values, and load some defaults + if (LoadASIC(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, " LoadASIC: failed in %s\n", __func__); + return false; + } + + verbose_printf(LOG_INFO, ptUserData, "Initialization succeeded.\n"); + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + verbose_printf(LOG_NONE, ptUserData, "\n"); // Print blank line + return true; +} + +bool LoadASIC(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + //////////////////////////////////////////////////////////////////////////////// + // step 1: reset science data error counters + if (ResetErrorCounters(ptUserData) == false) + return false; + verbose_printf(LOG_INFO, ptUserData, "Reset error counters succeeded.\n"); + + //////////////////////////////////////////////////////////////////////////////// + // step 2: download ASIC file, for example ASIC mcd file + // This must happen before GetAvailableASICs in order to enable the ASIC + // command interface output buffer so the MACIE can communicate. + verbose_printf(LOG_INFO, ptUserData, "Downloading ASIC microcode %s\n", ptUserData->ASICFile); + verbose_printf(LOG_INFO, ptUserData, " into ASIC%i\n", ptUserData->slctMACIEs - 1); + delay(500); + if (ptUserData->offline_develop == false) + { + if (MACIE_DownloadASICFile(ptUserData->handle, ptUserData->slctMACIEs, ptUserData->ASICFile, true) != MACIE_OK) // m_asicIds + { + verbose_printf(LOG_ERROR, ptUserData, " Failed: %s\n", MACIE_Error()); + return false; + } + } + else + { + // Only perform this when testing. + if (initASICRegs_testing(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, " initASICRegs_testing failed to complete.\n"); + return false; + } + verbose_printf(LOG_INFO, ptUserData, " Offline testing mode, skipping MACIE_DownloadASICFile().\n"); + } + + //////////////////////////////////////////////////////////////////////////////// + // step 3: get available ASICs + if (GetAvailableASICs(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "GetAvailableASICs failed in %s\n", __func__); + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // step 4: Save settings to ptUserData->RegMap + if (GetASICSettings(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, " GetASICSettings failed to complete.\n"); + return false; + } + verbose_printf(LOG_INFO, ptUserData, " GetASICSettings Succeeded.\n"); + + //////////////////////////////////////////////////////////////////////////////// + // step 5: set default values for various ASIC Settings + if (ASIC_Defaults(ptUserData) == false) + return false; + verbose_printf(LOG_INFO, ptUserData, "ASIC_Defaults succeeded.\n"); + + // TODO: + // Pixel Clock scheme checks (i.e., Normal vs Enhanced) are necessary if there are + // differences between full frame and subarray window clocking schemes. Normally + // these would be the same, but there is a bug in the Slow Mode v5.0+ microcode + // where Enhanced mode causes the columns to shift every other acquisition. + // The shifted column then persists after switching back to full frame. + // Something is wrong with the pixel timing code, so we always want window + // mode to be operated in Normal + map &RegMap = ptUserData->RegMap; + if (RegMap.count("PixelClkScheme") > 0) + { + unsigned int pixClk = 0; + GetASICParameter(ptUserData, "PixelClkScheme", &pixClk); + ptUserData->ffPixelClkScheme = pixClk; + ptUserData->winPixelClkScheme = 0; + } + verbose_printf(LOG_INFO, ptUserData, "PixelClkScheme succeeded.\n"); + + //////////////////////////////////////////////////////////////////////////////// + // step 6: set_exposure_settings() also calls ReconfigureASIC() + if (set_exposure_settings(ptUserData, true, 1, 1, 1, 1, 0, 1) == false) + return false; + + verbose_printf(LOG_INFO, ptUserData, "LoadASIC succeeded.\n"); + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + verbose_printf(LOG_NONE, ptUserData, "\n"); // Print blank line + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ReconfigureASIC Reconfigure ASIC using h6900 register. +/// Update the user configuration registers (h4000-h402f) then initiate +/// a reconfiguration sequence by writing 0x8002 to h6900. +/// \param ptUserData The user-set structure containing all the hardware parameters +bool ReconfigureASIC(MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->DetectorMode == CAMERA_MODE_FAST) + { + // pseudo-reconfigure for Fast Mode to update output settings + if (WriteASICReg(ptUserData, 0x6900, 0x8001) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "WriteASICReg failed in %s\n", __func__); + return false; + } + delay(100); + if (WriteASICReg(ptUserData, 0x6900, 0x8000) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "WriteASICReg failed in %s\n", __func__); + return false; + } + delay(100); + // Check that h6900=0x8000 + if (ptUserData->offline_develop == false) + { + unsigned int regval = 0; + if (ReadASICReg(ptUserData, 0x6900, ®val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICReg failed in %s\n", __func__); + return false; + } + if (regval != 0x8000) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICReg failed with h6900 = 0x%04x\n", regval); + return false; + } + } + // Resetting error counters just because?? + if (ResetErrorCounters(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Reset error counters failed.\n"); + verbose_printf(LOG_ERROR, ptUserData, " MACIE Error: %s\n", MACIE_Error()); + } + } + else // Slow Mode + { + unsigned int idle_value = 0; + unsigned int regtemp = 0; + unsigned int time_tot = 0; + unsigned int time_wait = 100; + // Assume full frame idle time + unsigned int nout = ASIC_NumOutputs(ptUserData, true); + unsigned int ff_time_pix = ptUserData->uiDetectorHeight * ptUserData->uiDetectorWidth / nout; + unsigned int ff_time_ms = ff_time_pix / ptUserData->pixelRate; + unsigned int timeout = 0; + unsigned int ypix = 0; + if ((ypix_burst_stripe(ptUserData, &ypix, false) == true) || (nout > 1)) + timeout = 2 * ff_time_ms; + else + timeout = 2 * exposure_frametime_ms(ptUserData); + // unsigned int timeout = 2 * exposure_frametime_ms(ptUserData); + if (timeout < time_wait) + timeout = 2 * time_wait; + + // Write h6900 = 0x8002 to reconfigure ASIC + struct regInfo *regWrite = new regInfo; + *regWrite = gen_regInfo(0x6900, 0, 15, 0x8002); + idle_value = 0x8000; + + // Perfom ASIC write to reconfigure + if (WriteASICBits(ptUserData, regWrite) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "WriteASICReg failed in %s\n", __func__); + return false; + } + + // Poll the ASIC register every 100 msec. + // Waiting for it to change. + regtemp = regWrite->value; + while (regtemp == regWrite->value) + { + if (ptUserData->offline_develop == true) + { + regWrite->value = idle_value; + WriteASICBits(ptUserData, regWrite); + regWrite->value = regtemp; + } + + if (time_tot > timeout) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfiguration timed out after %i msec\n", timeout); + break; + } + + if (ReadASICBits(ptUserData, regWrite, ®temp) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + return false; + } + + delay(time_wait); + time_tot += time_wait; + } + // Make sure h6900==0x8000 + if (regtemp != idle_value) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfiguration failed with h%04x<%i:%i> = 0x%04x. Expecting 0x%04x\n", + regWrite->addr, regWrite->bit0, regWrite->bit1, regtemp, idle_value); + return false; + } + + // Make sure detector information is consistent + unsigned int uiDetType = 0; + GetASICParameter(ptUserData, "DetectorType", &uiDetType); + if (uiDetType == 1) + { + ptUserData->uiDetectorWidth = 1024; + ptUserData->uiDetectorHeight = 1024; + ptUserData->DetectorType = CAMERA_TYPE_H1RG; + } + else if (uiDetType == 2) + { + ptUserData->uiDetectorWidth = 2048; + ptUserData->uiDetectorHeight = 2048; + ptUserData->DetectorType = CAMERA_TYPE_H2RG; + } + else if (uiDetType == 4) + { + ptUserData->uiDetectorWidth = 4096; + ptUserData->uiDetectorHeight = 4096; + ptUserData->DetectorType = CAMERA_TYPE_H4RG; + } + else + { + verbose_printf(LOG_ERROR, ptUserData, "DetectorType not recognized.\n"); + return false; + } + } + + // Check if STRIPE Mode is enabled + // We need to update RowsPerFrame since this is not done properly + if (ASIC_STRIPEMode(ptUserData, false, false)) + { + unsigned int ypix_sub = exposure_ypix(ptUserData); + + unsigned int ExtraLines = 0; + GetASICParameter(ptUserData, "ExtraLines", &ExtraLines); + SetASICParameter(ptUserData, "RowsPerFrame", ypix_sub + ExtraLines + 1); + } + + // Save settings to ptUserData->RegMap + if (GetASICSettings(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, " GetASICSettings failed to complete in %s.\n", __func__); + return false; + } + + // Save exposure frame and ramp times to ptUserData for use during acquisition + ptUserData->frametime_ms = exposure_frametime_ms(ptUserData); + ptUserData->ramptime_ms = exposure_ramptime_ms(ptUserData); + + verbose_printf(LOG_INFO, ptUserData, "Reconfiguration succeeded.\n"); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetMemAvailable Linux-specific command to get available RAM (kBytes). +/// \param ptUserData The user-set structure containing all the hardware parameters. +unsigned long GetMemAvailable(MACIE_Settings *ptUserData) +{ + string token; + string linebuffer; + unsigned long mem = 0; + + std::ifstream infile; + + infile.open("/proc/meminfo"); + if (infile.is_open() == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Could not open file /proc/meminfo \n"); + return 0; + } + else + { + while (infile >> token) + { + if (token == "MemAvailable:") + { + if (infile >> mem) + { + verbose_printf(LOG_DEBUG, ptUserData, "MemAvailable = %li kB\n", mem); + } + else + { + verbose_printf(LOG_WARNING, ptUserData, "MemAvailable token not found in /proc/meminfo\n"); + verbose_printf(LOG_WARNING, ptUserData, "MemAvailable set to 0 kB!\n"); + } + } + } + infile.close(); + } + + return mem; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief CalcBuffSize Calculate the size in pixels of a single buffer. +/// \param ptUserData The user-set structure containing all the hardware parameters. +unsigned long CalcBuffSize(MACIE_Settings *ptUserData) +{ + // Updated on 2/16/2021 to always use MACIE_ReadUSBFrameData() + return CalcBuffSize(ptUserData, 1); +} +//////////////////////////////////////////////////////////////////////////////// +/// \brief CalcBuffSize Calculate the size in pixels of a single buffer. +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param mode Mode=1: force MACIE_ReadUSBFrameData(); +/// Mode=2: MACIE_ReadUSBScienceData(). +/// Mode=0: (or otherwise), autoselect based on full frame or subarray setting. +unsigned long CalcBuffSize(MACIE_Settings *ptUserData, unsigned int mode) +{ + // Number of pixels requested in frame + unsigned long xpix = (unsigned long)exposure_xpix(ptUserData); + unsigned long ypix = (unsigned long)exposure_ypix(ptUserData); + unsigned long framesize = xpix * ypix; + + // Size of a full frame + unsigned long fullframe = (unsigned long)(ptUserData->uiDetectorHeight * ptUserData->uiDetectorWidth); + + // Number of frames in the exposure and in a ramp + unsigned long nframes_tot = (unsigned long)exposure_nframes(ptUserData, false); + unsigned long nframes_ramp = nframes_tot / ((unsigned long)ASIC_NRamps(ptUserData, false, 0)); + + // Number of pixels in an exposure and ramp + // unsigned long npix_tot = nframes_tot * framesize; + unsigned long npix_ramp = nframes_ramp * framesize; + + unsigned long res = 0; + + // Auto-select Sci or Frame data func + // Check if acquiring full frame images or subarray + if ((mode != 1) && (mode != 2)) + mode = (framesize == fullframe) ? 1 : 2; + + if (mode == 1) // Want to use frame function, MACIE_ReadUSBFrameData() + { + ptUserData->bUseSciDataFunc = false; + // Each buffer is the size of a frame + res = framesize; + } + + else if (mode == 2) // Otherwise use MACIE_ReadUSBScienceData() + { + ptUserData->bUseSciDataFunc = true; + // Set individual buffer to number of pixels in a ramp + res = npix_ramp; + + // Enforce res to be an integer multiple of 1024*1024 + unsigned long mult = 1024 * 1024; + unsigned long res_mod = res % mult; + if (res_mod != 0) + res += (mult - res_mod); + } + + verbose_printf(LOG_INFO, ptUserData, "%s(): Buffer size equals %li pixels (%li bytes)\n", __func__, res, 2 * res); + return res; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief CalcBuffSize Calculate the number of frame buffers based on user settings. +/// \param ptUserData The user-set structure containing all the hardware parameters. +short CalcNBuffers(MACIE_Settings *ptUserData) +{ + + unsigned long res = 1; + + // Number of pixels requested in frame + unsigned long xpix = (unsigned long)exposure_xpix(ptUserData); + unsigned long ypix = (unsigned long)exposure_ypix(ptUserData); + unsigned long framesize = xpix * ypix; + + // Number of frames in the exposure and in a ramp + unsigned long nframes_tot = (unsigned long)exposure_nframes(ptUserData, false); + // unsigned long nframes_ramp = nframes_tot / ( (unsigned long) ASIC_NRamps(ptUserData, false, 0) ); + + // Number of pixels in an exposure and ramp + unsigned long npix_tot = nframes_tot * framesize; + // unsigned long npix_ramp = nframes_ramp * framesize; + + // Minimum and Maximum number of frame buffers allowed to meet requirements + unsigned long nbuff_min = ptUserData->nPixBuffMin / ptUserData->nPixBuffer + 1; + unsigned long nbuff_max = ptUserData->nPixBuffMax / ptUserData->nPixBuffer; + if (nbuff_min < 10) + nbuff_min = 10; + + // First check that ptUserData->nPixBuffer is valid + if ((ptUserData->nPixBuffer == 0) || (ptUserData->nPixBuffer > ptUserData->nPixBuffMax)) + { + verbose_printf(LOG_WARNING, ptUserData, "%s(): Buffer size (%li pixels) is invalid.\n", + __func__, ptUserData->nPixBuffer); + ptUserData->nPixBuffer = CalcBuffSize(ptUserData); + verbose_printf(LOG_WARNING, ptUserData, "%s(): Updated buffer size: %li pixels (%li MBytes).\n", + __func__, ptUserData->nPixBuffer, 2 * ptUserData->nPixBuffer / (1024 * 1024)); + } + + // If we're using MACIE_ReadUSBScienceData(), then make one large buffer, + // otherwise determine necessary number of buffers to house all requested data + if (ptUserData->bUseSciDataFunc == true) + { + + // If npix_tot is less than nPixBuffMin, then set nbuff_min + if (npix_tot < ptUserData->nPixBuffMin) + res = nbuff_min; + else + res = npix_tot / ptUserData->nPixBuffer + 1; + + // Make sure we're not allocating too few buffers + if (res < nbuff_min) + res = nbuff_min; + + // Make sure we're not allocating more buffers than allowed + if (res > nbuff_max) + res = nbuff_max; + } + else + { + + // Set to nframes_min if too few frames allocated, + // otherwise set to total number of requested frames for d/l + if (nframes_tot < nbuff_min) + res = nbuff_min; + else + res = nframes_tot; + + // Make sure we're not allocating more frames than allowed + if (res > nbuff_max) + res = nbuff_max; + } + + verbose_printf(LOG_INFO, ptUserData, "%s(): nBuffers = %li \n", __func__, res); + return (short)res; +} + +// Calculate buffer size and number of required buffers +void ConfigBuffers(MACIE_Settings *ptUserData) +{ + ptUserData->nPixBuffer = CalcBuffSize(ptUserData); + ptUserData->nBuffer = CalcNBuffers(ptUserData); +} + +// Set size of buffer in pixels. If nPixBuffer is 0, then call CalcBuffSize() +void SetBuffSize(MACIE_Settings *ptUserData, unsigned int nPixBuffer) +{ + + if ((nPixBuffer == 0) || (nPixBuffer > ptUserData->nPixBuffMax)) + { + verbose_printf(LOG_WARNING, ptUserData, "%s(): Buffer size (%li pixels) is invalid.\n", + __func__, ptUserData->nPixBuffer); + ptUserData->nPixBuffer = CalcBuffSize(ptUserData); + } + else + { + ptUserData->nPixBuffer = nPixBuffer; + } +} + +// Set number of image buffers allocated to receive science data +// If nBuffer set to 0 or <1, then calls CalcNBuffers() +void SetNBuffer(MACIE_Settings *ptUserData, short nBuffer) +{ + if (nBuffer < 1) + { + short val = CalcNBuffers(ptUserData); + verbose_printf(LOG_WARNING, ptUserData, "%s(): nBuffer must be greater than 0. Setting to %i.\n", + __func__, val); + ptUserData->nBuffer = val; + verbose_printf(LOG_WARNING, ptUserData, "%s(): Updated buffer size: %li pixels (%li MBytes).\n", + __func__, ptUserData->nPixBuffer, 2 * ptUserData->nPixBuffer / (1024 * 1024)); + } + else + { + ptUserData->nBuffer = nBuffer; + } +} + +// Determine if subarray size is a valid setting. +// MACIE data management has some bugs that restrict +// certain subarray sizes. This may have been fixed in +// MACIE v5.0 while using frame-by-frame data download. +bool verify_subarray_size(MACIE_Settings *ptUserData, uint nx, uint ny, unsigned long nybtes_ramp) +{ + + // If nx is a factor of 512 then requested bytes need to be a multiple of 1048576 + unsigned int nx_remain = nx % 512; + unsigned long nb_remain = nybtes_ramp % 1048576; + if ((nx_remain == 0) && (nb_remain != 0)) + { + if (nb_remain != 0) + { + verbose_printf(LOG_WARNING, ptUserData, + "Number of requested bytes in a ramp (%li bytes) is not a multiple of 1Mbyte.\n", + nybtes_ramp); + } + // Check if ny is a power of two + if ((ny & (ny - 1)) != 0) + { + verbose_printf(LOG_WARNING, ptUserData, + "For nx=%i, ny may need to be a power of 2 (currently, ny=%i).\n", + nx, ny); + + // Warn about the top/bottom reference rows for burst stripe + uint ypix_temp = 0; + if (ypix_burst_stripe(ptUserData, &ypix_temp, false)) + { + verbose_printf(LOG_WARNING, ptUserData, + " BurstStripe is enabled: Make sure to account for top/bottom reference rows (8 total).\n"); + } + } + return false; + } + return true; +} + +// Check to make sure buffer information makes sense +bool VerifyBuffers(MACIE_Settings *ptUserData) +{ + // Conditions to verify: + // 0. Check that enough memory is available for allocation + // 1. Total buffer size needs to be less than nPixBuffMax. + // 2. Total buffer size needs to be more than nPixBuffMin. + // 3. nPixBuff should accommodate a full ramp. + // 4. Single Buffer sizes needs to be less than nPixBuffMax + // 5. Buffer sizes need to be multiples of 1024x1024 (???) + // 6. If bUseSciDataFunc=false, buffer size must equal frame size + // 7. We must command more than nBytesMin worth of data from the camera (???) + + // MUST COMMAND DATA THAT IS MULTIPLE OF 1MB??? DATA PACKETS? + + // Number of pixels in frame + unsigned long xpix = (unsigned long)exposure_xpix(ptUserData); + unsigned long ypix = (unsigned long)exposure_ypix(ptUserData); + unsigned long framesize = xpix * ypix; + + // Number of frames in the exposure and in a ramp + unsigned long nframes_tot = (unsigned long)exposure_nframes(ptUserData, false); + unsigned long nframes_ramp = nframes_tot / ((unsigned long)ASIC_NRamps(ptUserData, false, 0)); + + // Number of pixels in an exposure and ramp + unsigned long npix_tot = nframes_tot * framesize; + unsigned long npix_ramp = nframes_ramp * framesize; + + // Buffer information + unsigned long nBuffer = (unsigned long)ptUserData->nBuffer; + unsigned long nPixBuffer = ptUserData->nPixBuffer; + unsigned long nPixBuffTot = nBuffer * nPixBuffer; + + // Number of total bytes requested from ASIC + unsigned long nbytes_tot = 2 * npix_tot; + // Number of bytes requested per ramp + unsigned long nbytes_ramp = 2 * npix_ramp; + + verbose_printf(LOG_DEBUG, ptUserData, "%s(): framesize = %li pixels\n", __func__, framesize); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): npix_ramp = %li pixels\n", __func__, npix_ramp); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): npix_exp = %li pixels\n", __func__, npix_tot); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): nbytes_ramp = %li bytes\n", __func__, nbytes_ramp); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): nbytes_exp = %li bytes\n", __func__, nbytes_tot); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): Total buffer space = %li bytes \n", + __func__, 2 * nPixBuffTot); + + // 0. Check that enough memory is available for allocation + unsigned long memAvailMBytes = GetMemAvailable(ptUserData) / 1024; + unsigned long memReqMBytes = 2 * nPixBuffTot / (1024 * 1024); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): Memory Available = %li MBytes\n", __func__, memAvailMBytes); + verbose_printf(LOG_DEBUG, ptUserData, "%s(): Memory Requested = %li MBytes\n", __func__, memReqMBytes); + if ((9 * memAvailMBytes) / 10 < memReqMBytes) + { + verbose_printf(LOG_WARNING, ptUserData, "%s(): MemAvailable (x0.9) = %li MBytes; Requested = %li MBytes\n", + __func__, (9 * memAvailMBytes) / 10, memReqMBytes); + } + if (memAvailMBytes < memReqMBytes) + { + verbose_printf(LOG_ERROR, ptUserData, "%s(): MemAvailable = %li MBytes; Requested = %li MBytes\n", + __func__, memAvailMBytes, memReqMBytes); + return false; + } + // 1. Total buffer size relative to maximum allowed allocation + if (memReqMBytes > ptUserData->nBytesMax) + { + verbose_printf(LOG_ERROR, ptUserData, "%s(): nPixBuffTot = %li. Must be <= %li pixels (ptUserData->nBytesMax / 2)\n", + __func__, nPixBuffTot, ptUserData->nBytesMax / 2); + return false; + } + // 2. Total buffer size relative to nPixBuffMin + if (nPixBuffTot < ptUserData->nPixBuffMin) + { + verbose_printf(LOG_ERROR, ptUserData, "%s(): nPixBuffTot = %li. Must be >= %li pixels (nPixBuffMin)\n", + __func__, nPixBuffTot, ptUserData->nPixBuffMin); + return false; + } + // 3. nPixBuffTot should accommodate a full ramp for SciData function. + if ((nPixBuffTot < npix_ramp) && (ptUserData->bUseSciDataFunc == true)) + { + verbose_printf(LOG_ERROR, ptUserData, "%s(): nPixBuffTot = %li. Must be >= %li pixels (npix_ramp)\n", + __func__, nPixBuffTot, npix_ramp); + return false; + } + + // 4. Single Buffer sizes needs to be less than nPixBuffMax + if (nPixBuffer > ptUserData->nPixBuffMax) + { + verbose_printf(LOG_ERROR, ptUserData, "%s(): nPixBuffer = %li. Must be <= %li pixels (ptUserData->nPixBuffMax)\n", + __func__, nPixBuffer, ptUserData->nPixBuffMax); + return false; + } + // 5. Single Buffer sizes needs to be multiple of 1024x1024 + // if (nPixBuffer % (1024*1024) != 0) + // { + // verbose_printf(LOG_ERROR, ptUserData, "%s(): nPixBuffer = %li; must be multiple of %i\n", + // __func__, nPixBuffer, 1024*1024); + // return false; + // } + + // 6. If bUseSciDataFunc=false, buffer size must equal frame size + if ((ptUserData->bUseSciDataFunc == false) && (nPixBuffer != framesize)) + { + verbose_printf(LOG_ERROR, ptUserData, "%s(): nPixBuffer (%li) must equal framesize (%li)\n", + __func__, nPixBuffer, framesize); + return false; + } + // 7. We must command more than nBytesMin worth of data from the camera + // if (nbytes_tot < ptUserData->nBytesMin) + // { + // verbose_printf(LOG_WARNING, ptUserData, "%s(): Total requested bytes (%li) must be >%li (?)\n", + // __func__, nbytes_tot, ptUserData->nBytesMin); + // } + + // 7. Check subarray size setting + // TODO: This is temporary until MACIE data handling issue is resolved + if (verify_subarray_size(ptUserData, xpix, ypix, nbytes_ramp) == false) + { + verbose_printf(LOG_WARNING, ptUserData, + "%s(): Possible problematic subarray size (nx=%i, ny=%i) with %li bytes in ramp\n", + __func__, xpix, ypix, nbytes_ramp); + // return false; + } + + verbose_printf(LOG_INFO, ptUserData, "%s(): Buffer info looks good!\n", __func__); + return true; +} + +// Fraction of buffer space currently used +// This can only be called after calling +// MACIE_ConfigureUSBScienceInterface() and before CloseUSBScienceInterface() +double MemBufferFrac(MACIE_Settings *ptUserData) +{ + // int xpix = (int) exposure_xpix(ptUserData); + // int ypix = (int) exposure_ypix(ptUserData); + double nbytes_buf = (double)2 * ptUserData->nPixBuffer * ptUserData->nBuffer; + return ((double)MACIE_AvailableScienceData(ptUserData->handle)) / nbytes_buf; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief AcquireDataUSB Trigger the ASIC to start acquiring data. +/// First configure science USB data interface then trigger exposure acquisition. +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param externalTrigger Boolean to indicaton communication and synchronization +/// with an external trigger, such as an external shutter or modulator. +bool AcquireDataUSB(MACIE_Settings *ptUserData, bool externalTrigger) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->connection != MACIE_USB) + { + verbose_printf(LOG_ERROR, ptUserData, "Connection type is not USB.\n"); + return false; + } + + unsigned long handle = ptUserData->handle; + unsigned char slctMACIEs = ptUserData->slctMACIEs; + + unsigned short data_mode = (ptUserData->DetectorMode == CAMERA_MODE_SLOW) ? 0 : 3; + + // Number of frame buffers to allocate for storing data. + // short nframes_tot = (short) exposure_nframes(ptUserData, false); + // short nbuf = (nframes_tot < ptUserData->nBuffer) ? nframes_tot : ptUserData->nBuffer; + // ptUserData->nBuffer = CalcNBuffers(ptUserData); + + ConfigBuffers(ptUserData); + // SetBuffSize(ptUserData, exposure_xpix(ptUserData)*exposure_ypix(ptUserData)); + // SetNBuffer(ptUserData, 100); + // ptUserData->bUseSciDataFunc = false; + + if (VerifyBuffers(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "VerifyBuffers failed in %s\n", __func__); + return false; + } + short nbuf = ptUserData->nBuffer; + int buffsize = (int)ptUserData->nPixBuffer; + + // short nframes_tot = (short) exposure_nframes(ptUserData, false); + // short nbuf = 20; //(nframes_tot < ptUserData->nBuffer) ? nframes_tot : ptUserData->nBuffer; + // int buffsize = exposure_xpix(ptUserData) * exposure_ypix(ptUserData); + // ptUserData->bUseSciDataFunc = false; + + // Function to update any burst-stripe features (h4300-h4304 and h4034) + unsigned int ypix = ptUserData->uiDetectorHeight; + if (ypix_burst_stripe(ptUserData, &ypix, true) == true) + { + verbose_printf(LOG_DEBUG, ptUserData, "Burst stripe is enabled with %i rows.\n", ypix); + // Delay partial frame time to ensure proper transition from full frame to stripe + delay(int(0.5 * ptUserData->frametime_ms)); + } + else + { + verbose_printf(LOG_DEBUG, ptUserData, "Burst stripe disabled; %i rows.\n", ypix); + } + + // Make sure h6900<0> is 0 before triggering acquisition. + // For USB, this must be done before configuring interface, + // because USB interface's data read and command read share + // the same USB pipe. + if (ptUserData->offline_develop == false) + { + unsigned int regval = 0; + + regInfo regComp = gen_regInfo(0x6900, 0, 5, 0); + if (ReadASICBits(ptUserData, ®Comp, ®val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + return false; + } + if (regval != 0) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed with h6900<5:0> = 0x%04x\n", regval); + return false; + } + } + verbose_printf(LOG_INFO, ptUserData, "ReadASICBits 0x6900 succeeded.\n"); + + // Set up USB3 science data interface for image acquisition. + // MACIE_CloseUSBScienceInterface needs to be called before we + // can use any read functions again (e.g., MACIE_ReadASICReg). + verbose_printf(LOG_INFO, ptUserData, "Configuring science interface...\n"); + verbose_printf(LOG_INFO, ptUserData, " nbuf = %i\n", nbuf); + verbose_printf(LOG_INFO, ptUserData, " buffsize = %i pixels\n", buffsize); + if (ptUserData->offline_develop == false) + { + // Give a slight delay before opening USB interface + delay(100); + try + { + if (MACIE_ConfigureUSBScienceInterface(handle, slctMACIEs, data_mode, buffsize, nbuf) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "Science interface configuration failed.\n"); + return false; + } + } + catch (const std::exception &e) + { + verbose_printf(LOG_ERROR, ptUserData, + "Caught exception at %s during MACIE_ConfigureUSBScienceInterface().\n", + __func__); + std::cerr << e.what() << '\n'; + + return false; + } + } + verbose_printf(LOG_INFO, ptUserData, "Science interface configuration succeeded.\n"); + verbose_printf(LOG_INFO, ptUserData, "Trigger image acquisition...\n"); + + // Trigger image acquisition + if (ptUserData->offline_develop == false) + { + + // External trigger + if (externalTrigger) + { + // TODO: Experimental + unsigned int val = 0x8001; + bool bLineBoundar = true, bFrameBoundary = false; + if (bLineBoundar) + val |= 0x0002; + if (bFrameBoundary) + val |= 0x0004; + + if (MACIE_WriteMACIEReg(handle, slctMACIEs, 0x01f0, 1) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, + "Writing MACIE 0x01f0 with value 1 failed\n"); + CloseUSBScienceInterface(ptUserData); + return false; + } + if (MACIE_WriteMACIEReg(handle, slctMACIEs, 0x01f1, 0x6900) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, + "Writing ASIC register address 0x6900 to MACIE 0x01f1 failed\n"); + CloseUSBScienceInterface(ptUserData); + return false; + } + if (MACIE_WriteMACIEReg(handle, slctMACIEs, 0x01f2, val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, + "Writing MACIE 0x01f2 with value 0x%04x failed\n", val); + CloseUSBScienceInterface(ptUserData); + return false; + } + } + else + { + + // Write h6900 = 0x8001 to start acquisition + struct regInfo *regWrite = new regInfo; + *regWrite = gen_regInfo(0x6900, 0, 15, 0x8001); + + if (WriteASICBits(ptUserData, regWrite) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Acquisition triggering failed\n"); + CloseUSBScienceInterface(ptUserData); + return false; + } + verbose_printf(LOG_INFO, ptUserData, "Acquisition triggering succeeded\n"); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief AcquireDataGigE Trigger the ASIC to start acquiring data. +/// First configure science GigE data interface then trigger exposure acquisition. +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param externalTrigger Boolean to indicaton communication and synchronization +/// with an external trigger, such as an external shutter or modulator. +bool AcquireDataGigE(MACIE_Settings *ptUserData, bool externalTrigger) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->connection != MACIE_GigE) + { + verbose_printf(LOG_ERROR, ptUserData, "Connection type is not GigE.\n"); + return false; + } + + unsigned long handle = ptUserData->handle; + unsigned char slctMACIEs = ptUserData->slctMACIEs; + + unsigned short data_mode = (ptUserData->DetectorMode == CAMERA_MODE_SLOW) ? 0 : 3; + + // Number of frame buffers to allocate for storing data. + // short nframes_tot = (short) exposure_nframes(ptUserData, false); + // short nbuf = (nframes_tot < ptUserData->nBuffer) ? nframes_tot : ptUserData->nBuffer; + // ptUserData->nBuffer = CalcNBuffers(ptUserData); + + ConfigBuffers(ptUserData); + // SetBuffSize(ptUserData, exposure_xpix(ptUserData)*exposure_ypix(ptUserData)); + // SetNBuffer(ptUserData, 100); + // ptUserData->bUseSciDataFunc = false; + + if (VerifyBuffers(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "VerifyBuffers failed in %s\n", __func__); + return false; + } + short nbuf = ptUserData->nBuffer; + int buffsize = (int)ptUserData->nPixBuffer; + + // short nframes_tot = (short) exposure_nframes(ptUserData, false); + // short nbuf = 20; //(nframes_tot < ptUserData->nBuffer) ? nframes_tot : ptUserData->nBuffer; + // int buffsize = exposure_xpix(ptUserData) * exposure_ypix(ptUserData); + // ptUserData->bUseSciDataFunc = false; + + // Function to update any burst-stripe features (h4300-h4304 and h4034) + unsigned int ypix = ptUserData->uiDetectorHeight; + if (ypix_burst_stripe(ptUserData, &ypix, true) == true) + { + verbose_printf(LOG_DEBUG, ptUserData, "Burst stripe is enabled with %i rows.\n", ypix); + // Delay partial frame time to ensure proper transition from full frame to stripe + delay(int(0.5 * ptUserData->frametime_ms)); + } + else + { + verbose_printf(LOG_DEBUG, ptUserData, "Burst stripe disabled; %i rows.\n", ypix); + } + + // Make sure h6900<0> is 0 before triggering acquisition. + // For USB, this must be done before configuring interface, + // because USB interface's data read and command read share + // the same USB pipe. + if (ptUserData->offline_develop == false) + { + unsigned int regval = 0; + + regInfo regComp = gen_regInfo(0x6900, 0, 5, 0); + if (ReadASICBits(ptUserData, ®Comp, ®val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + return false; + } + if (regval != 0) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed with h6900<5:0> = 0x%04x\n", regval); + return false; + } + } + verbose_printf(LOG_INFO, ptUserData, "ReadASICBits 0x6900 succeeded.\n"); + + // Set up USB3 science data interface for image acquisition. + // MACIE_CloseUSBScienceInterface needs to be called before we + // can use any read functions again (e.g., MACIE_ReadASICReg). + verbose_printf(LOG_INFO, ptUserData, "Configuring science interface...\n"); + verbose_printf(LOG_INFO, ptUserData, " nbuf = %i\n", nbuf); + verbose_printf(LOG_INFO, ptUserData, " buffsize = %i pixels\n", buffsize); + if (ptUserData->offline_develop == false) + { + // Give a slight delay before opening USB interface + delay(100); + try + { + int bufferSize; + int remotePort = 42037; //TODO:verify + if(MACIE_ConfigureGigeScienceInterface(handle, slctMACIEs, data_mode, buffsize, remotePort, &bufferSize) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "Science interface configuration failed.\n"); + return false; + } + } + catch (const std::exception &e) + { + verbose_printf(LOG_ERROR, ptUserData, + "Caught exception at %s during AcquireDataGigE().\n", + __func__); + std::cerr << e.what() << '\n'; + + return false; + } + } + verbose_printf(LOG_INFO, ptUserData, "Science interface configuration succeeded.\n"); + verbose_printf(LOG_INFO, ptUserData, "Trigger image acquisition...\n"); + + // Trigger image acquisition + if (ptUserData->offline_develop == false) + { + + // External trigger + if (externalTrigger) + { + // TODO: Experimental + unsigned int val = 0x8001; + bool bLineBoundar = true, bFrameBoundary = false; + if (bLineBoundar) + val |= 0x0002; + if (bFrameBoundary) + val |= 0x0004; + + if (MACIE_WriteMACIEReg(handle, slctMACIEs, 0x01f0, 1) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, + "Writing MACIE 0x01f0 with value 1 failed\n"); + CloseGigEScienceInterface(ptUserData); + return false; + } + if (MACIE_WriteMACIEReg(handle, slctMACIEs, 0x01f1, 0x6900) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, + "Writing ASIC register address 0x6900 to MACIE 0x01f1 failed\n"); + CloseGigEScienceInterface(ptUserData); + return false; + } + if (MACIE_WriteMACIEReg(handle, slctMACIEs, 0x01f2, val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, + "Writing MACIE 0x01f2 with value 0x%04x failed\n", val); + CloseGigEScienceInterface(ptUserData); + return false; + } + } + else + { + + // Write h6900 = 0x8001 to start acquisition + struct regInfo *regWrite = new regInfo; + *regWrite = gen_regInfo(0x6900, 0, 15, 0x8001); + + if (WriteASICBits(ptUserData, regWrite) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Acquisition triggering failed\n"); + CloseGigEScienceInterface(ptUserData); + return false; + } + verbose_printf(LOG_INFO, ptUserData, "Acquisition triggering succeeded\n"); + } + } + + return true; +} + + +unsigned int getFileNumStart(MACIE_Settings *ptUserData) +{ + + string strDir = ptUserData->saveDir; + + // Create save directory if it doesn't exist + struct stat st = {0}; + if (stat(strDir.c_str(), &st) == -1) + mkdir(strDir.c_str(), 0700); + + // Go through files in save directory to find last written file number + DIR *dir = opendir(strDir.c_str()); + struct dirent *ent; + uint val; + uint max_val = 0; + int pos; + string s, sub; + while ((ent = readdir(dir)) != NULL) + { + s = string(ent->d_name); + if ((s.rfind(".fits") != string::npos) && (s.size() > 6)) + { + pos = s.rfind("_"); + sub = s.substr(pos + 1, 6); + val = atoi(sub.c_str()); + if (val >= max_val) + max_val = val + 1; + } + } + closedir(dir); + return max_val; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief getFileNames Return a string vector of filenames. +/// \param ptUserData The user-set structure containing the hardware parameters +std::vector getFileNames(MACIE_Settings *ptUserData) +{ + uint nfiles = ptUserData->uiNumSaves; + string strDir = ptUserData->saveDir; + string strPre = ptUserData->filePrefix; + uint fnum = getFileNumStart(ptUserData); + + std::stringstream ss; + + string name = ""; + std::vector names; // Empty on creation + // printf("nfiles: %i\n", nfiles); + for (uint i = 0; i < nfiles; ++i) + { + ss.str(""); + ss << std::setw(6) << std::setfill('0') << fnum; + name = strDir + strPre + ss.str() + ".fits"; + names.push_back(name); + // verbose_printf(LOG_INFO, ptUserData, " filename: %s\n", names[i].c_str()); + fnum++; + } + return names; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief CloseUSBScienceInterface Close MACIE USB Science interface. +/// Normally this function should be called after the image acquisition is done. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool CloseUSBScienceInterface(MACIE_Settings *ptUserData) +{ + verbose_printf(LOG_INFO, ptUserData, "Closing MACIE USB science interface...\n"); + if (ptUserData->offline_develop == false) + { + if (MACIE_CloseUSBScienceInterface(ptUserData->handle, ptUserData->slctMACIEs) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_CloseUSBScienceInterface failed: %s\n", MACIE_Error()); + return false; + } + } + // Set burst stripe to idle in full frame + burst_stripe_set_ffidle(ptUserData); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief CloseGigEScienceInterface Close MACIE GigE Science interface. +/// Normally this function should be called after the image acquisition is done. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool CloseGigEScienceInterface(MACIE_Settings *ptUserData) +{ + verbose_printf(LOG_INFO, ptUserData, "Closing MACIE GigE science interface...\n"); + if (ptUserData->offline_develop == false) + { + if (MACIE_CloseGigeScienceInterface(ptUserData->handle, ptUserData->slctMACIEs) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_CloseGigeScienceInterface failed: %s\n", MACIE_Error()); + return false; + } + } + // Set burst stripe to idle in full frame + burst_stripe_set_ffidle(ptUserData); + + return true; +} + +void HaltCameraAcq(MACIE_Settings *ptUserData) +{ + verbose_printf(LOG_INFO, ptUserData, "Halting data acquisition...\n"); + // verbose_printf(LOG_INFO, ptUserData, "Waiting for last ramp to complete...\n"); + + if (ptUserData->DetectorMode == CAMERA_MODE_FAST) + { + WriteASICReg(ptUserData, 0x6900, 0x8000); + delay(100); + } + else + { + WriteASICReg(ptUserData, 0x6900, 0x8000); + // TODO: Is this delay necessary? Frame boundary? + // int tframe_ms = (int)exposure_frametime_ms(ptUserData); + // delay(tframe_ms); + delay(100); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief DownloadAndSaveAllUSB Function to download all requested frames +/// from MACIE, coadd average if requested, and save to FITS. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool DownloadAndSaveAllUSB(MACIE_Settings *ptUserData) +{ + // Number of ramps to coadd together + const int ncoadds = (int)ptUserData->uiNumCoadds; + + const int xpix = (int)exposure_xpix(ptUserData); + const int ypix = (int)exposure_ypix(ptUserData); + // Number of pixels in frame for download + const int framesize = xpix * ypix; + + // Number of requested ramps + const int nramps = (int)ASIC_NRamps(ptUserData, false, 0); + // Number of groups in a ramp + const int ngroups = (int)ASIC_NGroups(ptUserData, false, 0); + // Number of frame reads in a group + const int nreads = (int)ASIC_NReads(ptUserData, false, 0); + + // Saving reset frames? + int nresets_ramp = (int)ASIC_NResets(ptUserData, false, 0); + int nresets_save = 0; + unsigned int val = 0; + if (GetASICParameter(ptUserData, "SaveRstFrames", &val) == true) + if (val == 1) + nresets_save = nresets_ramp; + + // Number of frames in a ramp (to download) + const int nframes_ramp = ngroups * nreads + nresets_save; + // Number of pixels in ramp (to download) + const int rampsize = framesize * nframes_ramp; + + // clock_t t, t0; + timestamp_t t, t0; + double time_taken; + + // Set up data axes information + std::vector filenames = getFileNames(ptUserData); + vector naxis; + naxis.push_back(xpix); + naxis.push_back(ypix); + if (nframes_ramp > 1) + naxis.push_back(nframes_ramp); + + // Frame and Ramp times + double frametime_ms = ptUserData->frametime_ms; + double ramptime_ms = ptUserData->ramptime_ms; + // Calculate a timeout to wait for data. + // Assume full frame idle time + // Timeout setting while waiting for data download to trigger + int triggerTimeout = int(ramptime_ms + 2 * frametime_ms + 100); + // unsigned int nout = ASIC_NumOutputs(ptUserData, true); + // unsigned int ff_time_pix = ptUserData->uiDetectorHeight * ptUserData->uiDetectorWidth / nout; + // double ff_time_ms = (double) ff_time_pix / ptUserData->pixelRate; + // int triggerTimeout = int(exposure_nframes(ptUserData, true) + 2) * int(ff_time_ms); + // Wait delta (in msec) to sample available science data bytes + int wait_delta = int(frametime_ms / 10); + if (wait_delta < 1) + wait_delta = 1; + + // Allocate memory to store each ramp + unsigned short *pData; + try + { + // long SIZE = (long) rampsize; + pData = new unsigned short[rampsize](); + } + catch (const std::exception &e) + { + verbose_printf(LOG_ERROR, ptUserData, "Failed to allocate memory for pData at %s.\n", __func__); + std::cerr << e.what() << '\n'; + + // Explicitly send Halt command (h6900=0x8000) + HaltCameraAcq(ptUserData); + CloseGigEScienceInterface(ptUserData); + + return false; + } + // 32-bit coadd buffer (actually takes average of ramps) + float *pRampBuffer; + try + { + pRampBuffer = new float[rampsize](); + } + catch (const std::exception &e) + { + verbose_printf(LOG_ERROR, ptUserData, "Failed to allocate memory for pRampBuffer at %s.\n", __func__); + std::cerr << e.what() << '\n'; + + // Delete all data + delete[] pData; + + // Explicitly send Halt command (h6900=0x8000) + HaltCameraAcq(ptUserData); + CloseGigEScienceInterface(ptUserData); + + return false; + } + + int coadd_cnt = 0; + int ifile = 0; + + // Flag indicating buffer is getting too full + bool buff_flag = false; + double buff_frac = 0; + uint nbytes_req = uint(rampsize) * uint(nramps); + + t0 = get_timestamp(); + for (int ii = 0; ii < nramps; ++ii) + { + + // Testing of Halt Acquisition + // if (ii==30) + // { + // verbose_printf(LOG_ERROR, ptUserData, "Halt encountered on ramp %i of %i.\n", ii+1, nramps); + // break; + // } + + // If the memory buffer is 90% full, then set buffer overflow flag. + // But only if the number of requested bytes is greater than max buffer size. + // Resume when we've gone below 65% + buff_frac = MemBufferFrac(ptUserData); + verbose_printf(LOG_INFO, ptUserData, " Buffer fraction: %f\n", buff_frac); + if ((buff_frac > 0.9) && (nbytes_req > 2 * ptUserData->nPixBuffer)) + buff_flag = true; + if (buff_flag && (buff_frac < 0.65)) + buff_flag = false; + + // Download data as it becomes available + t = get_timestamp(); + if (DownloadRampUSB(ptUserData, pData, framesize, nframes_ramp, triggerTimeout, wait_delta) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Failed download on ramp %i of %i.\n", ii + 1, nramps); + verbose_printf(LOG_ERROR, ptUserData, "Breaking out of acquisition on sequence %i of %i.\n", ii + 1, nramps); + break; + } + t = get_timestamp() - t; + time_taken = t / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, " DownloadRampUSB total time: %f seconds\n", time_taken); + + // Go to next iteration if memory buffer is too full + if (buff_flag) + { + verbose_printf(LOG_WARNING, ptUserData, " Buffer reaching max capacity. Skipping ramp %i of %i.\n", ii + 1, nramps); + continue; + } + + // If no coadding, keep in 16-bit format and save + if (ncoadds == 1) + { + if (ptUserData->bSaveData) + { + verbose_printf(LOG_INFO, ptUserData, "Writing: %s\n", filenames[ifile].c_str()); + t = get_timestamp(); + if (WriteFITSRamp(pData, naxis, USHORT_IMG, filenames[ifile]) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Failed to write FITS (16-bit) at %s\n", __func__); + verbose_printf(LOG_ERROR, ptUserData, "Breaking out of acquisition on sequence %i of %i.\n", ii + 1, nramps); + break; + } + t = get_timestamp() - t; + time_taken = t / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, " Time to write FITS file: %f seconds\n\n", time_taken); + // Increment file name index + ifile++; + } + } + // Otherwise add pData to 32-bit coadder + else + { + // Pixel-by-pixel add to buffer + t = get_timestamp(); + for (int jj = 0; jj < rampsize; ++jj) + pRampBuffer[jj] += pData[jj]; + t = get_timestamp() - t; + time_taken = t / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, " Time to take copy ramp: %f seconds\n", time_taken); + + // Increment coadd counter + coadd_cnt++; + + if (coadd_cnt == ncoadds) + { + // Take average + if (ncoadds > 1) + { + t = get_timestamp(); + for (int jj = 0; jj < rampsize; ++jj) + pRampBuffer[jj] /= ncoadds; + t = get_timestamp() - t; + time_taken = t / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, " Time to take average: %f seconds\n", time_taken); + } + + if (ptUserData->bSaveData) + { + // Save FITS files + verbose_printf(LOG_INFO, ptUserData, "Writing: %s\n", filenames[ifile].c_str()); + t = get_timestamp(); + if (WriteFITSRamp(pRampBuffer, naxis, FLOAT_IMG, filenames[ifile]) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Failed to write FITS (32-bit) at %s\n", __func__); + verbose_printf(LOG_ERROR, ptUserData, "Breaking out of acquisition on sequence %i of %i.\n", ii + 1, nramps); + break; + } + t = get_timestamp() - t; + time_taken = t / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, " Time to write FITS file: %f seconds\n\n", time_taken); + // Increment file name index + ifile++; + } + + // Reset pRampBuffer to 0s + memset(pRampBuffer, 0, rampsize * sizeof(pRampBuffer[0])); + // Clear counter + coadd_cnt = 0; + } + } + } + + t = get_timestamp() - t0; + time_taken = t / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, " DownloadAll for loop time: %f seconds\n\n", time_taken); + + // // Test to see if we are getting more bytes than expected + // if (get_verbose(ptUserData) == LOG_DEBUG) + // { + // long nbytes = 0; + // int delay_time = int(ramptime_ms); + // int wait_total = 0; + // wait_delta = int(frametime_ms / 5); + // if (wait_delta < 1) + // wait_delta = 1; + + // verbose_printf(LOG_DEBUG, ptUserData, "Delaying %i ms to see if more bytes come down...\n", delay_time); + // // Poll MACIE_AvailableScienceData + // while (wait_total < delay_time) + // { + // nbytes = (long) MACIE_AvailableScienceData(ptUserData->handle); + // verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + // delay(wait_delta); + // wait_total += wait_delta; + // } + // nbytes = (long) MACIE_AvailableScienceData(ptUserData->handle); + // verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + // if (nbytes>0) + // verbose_printf(LOG_WARNING, ptUserData, " Additional %li bytes after exposure!\n", nbytes); + // } + + // Delete all data + delete[] pData; + delete[] pRampBuffer; + + // Explicitly send Halt command (h6900=0x8000) + HaltCameraAcq(ptUserData); + delay(100); + if (CloseGigEScienceInterface(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "CloseGigEScienceInterface failed after acquisition\n"); + return false; + } + else + verbose_printf(LOG_INFO, ptUserData, "CloseGigEScienceInterface succeeded after acquisition\n"); + // Do this again?? + + return true; +} + +// +//////////////////////////////////////////////////////////////////////////////// +/// \brief DownloadRampUSB Download a ramp. Choose whether or not to use +/// DownloadRampUSB_Frame or DownloadRampUSB_Data . +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param pData Pointer to a pre-allocated unsigned short data buffer. +/// \param framesize Number of pixels in a frame. +/// \param nframes_save Number of frames read in ramp. +/// \param triggerTimeout How long to wait for frames to complete before failing +/// (e.g. a ramp time) +/// \param wait_delta Time interval to poll for available bytes +/// (e.g. some fraction of a frame time) +bool DownloadRampUSB(MACIE_Settings *ptUserData, unsigned short pData[], long framesize, + long nframes_save, int triggerTimeout, int wait_delta) +{ + + // Before downloading, make sure to clear all data in ramp mem storage + // This helps identify missing data in saved frames due to d/l errors. + uint rampsize = (uint)framesize * nframes_save; + memset(pData, 0, rampsize * sizeof(pData[0])); + + // Select which download function to use (Data vs Frame) based on user setting. + // Generally, these correspond to subbarray (USB_Data) and full frame (USB_Frame). + if (ptUserData->bUseSciDataFunc == true) + { + return DownloadRampUSB_Data(ptUserData, pData, framesize, nframes_save, triggerTimeout, wait_delta); + } + else + { + return DownloadRampUSB_Frame(ptUserData, pData, framesize, nframes_save, triggerTimeout, wait_delta); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief DownloadRampUSB_Frame Download a ramp frame-by-frame. First, we check +/// how many bytes are available on the MACIE buffer. Once a frame's worth +/// of data exists, it downloads and saves those bytes into the approrpriate +/// location in pData. Continue for the next frame until ramp is completed. +bool DownloadRampUSB_Frame(MACIE_Settings *ptUserData, unsigned short pData[], long framesize, + long nframes_save, int triggerTimeout, int wait_delta) +{ + + long nbytes = 0; + long nbytes_frm = framesize * 2; // 16 bits = 2 bytes + + verbose_printf(LOG_DEBUG, ptUserData, "triggerTimeout = %i, wait_delta:%i\n", triggerTimeout, wait_delta); + // unsigned short dltimeout = (ptUserData->DetectorMode==CAMERA_MODE_SLOW) ? 6500 : 1500; + int wait_total = 0; + + // Delay the larger of 1 second or 1 frame time to see if rest comes down + int delay_time = 1000; + int frame_time_ms = (int)ptUserData->frametime_ms; + if (delay_time < frame_time_ms) + delay_time = frame_time_ms; + + // Download timeout + unsigned short dltimeout = (ushort)ptUserData->ramptime_ms; + + timestamp_t t; + double time_taken = 0; + for (long i = 0; i < nframes_save; ++i) + { + verbose_printf(LOG_DEBUG, ptUserData, " Frame %li of %li\n", i + 1, nframes_save); + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + wait_total = 0; + + // Poll available science data + // When any amount of data shows up, break out and call the d/l function + // Timeout if no data after triggertimout is reached + while (nbytes <= 0) + { + // Delay for some time + delay(wait_delta); + wait_total += wait_delta; + + // Check to see if data has shown up on port yet + if (ptUserData->offline_develop == true) + nbytes = nbytes_frm; + else + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + + verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + // Return false if we've reached time limit but haven't gotten all the bytes + if (wait_total > triggerTimeout) + { + verbose_printf(LOG_ERROR, ptUserData, "Trigger timeout limit of %i ms reached at: %s\n", + triggerTimeout, __func__); + verbose_printf(LOG_ERROR, ptUserData, " Frame %li of %li.\n", i + 1, nframes_save); + verbose_printf(LOG_ERROR, ptUserData, " Expecting %li bytes. Only %li bytes available in %i ms.\n", + nbytes_frm, nbytes, wait_total); + + // Delay the larger of 1 second or 1 frame time to see if rest comes down + verbose_printf(LOG_ERROR, ptUserData, " Delaying %i msec more...\n", delay_time); + delay(delay_time); + + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + verbose_printf(LOG_WARNING, ptUserData, " After delay, nbytes available: %li\n", nbytes); + if (nbytes < nbytes_frm) + { + verbose_printf(LOG_ERROR, ptUserData, " Returning...\n"); + return false; + } + else + { + verbose_printf(LOG_ERROR, ptUserData, " Continuing...\n"); + break; + } + } + } + + if (get_verbose(ptUserData) == LOG_DEBUG) + { + wait_total = 0; + while (wait_total < delay_time) + { + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + delay(wait_delta); + wait_total += wait_delta; + + if (nbytes >= nbytes_frm) + break; + } + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + } + verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + // Download a frame into pData buffer + t = get_timestamp(); + // if (DownloadDataUSB(ptUserData, &pData[i*framesize], framesize, dltimeout)==false) + if (DownloadFrameUSB(ptUserData, &pData[i * framesize], framesize, dltimeout) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "DownloadFrameUSB failed at %s\n", __func__); + verbose_printf(LOG_ERROR, ptUserData, " Frame %li of %li.\n", i + 1, nframes_save); + + verbose_printf(LOG_ERROR, ptUserData, " Saw nbytes before d/l attempt: %li)\n", nbytes); + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + verbose_printf(LOG_ERROR, ptUserData, " Saw nbytes after d/l attempt: %li)\n", nbytes); + + return false; + } + t = get_timestamp() - t; + time_taken = t / 1000.0L; + + verbose_printf(LOG_DEBUG, ptUserData, " Frame dl time: %.0f ms (wait_total: %i ms, nbytes: %li)\n", + time_taken, wait_total, nbytes); + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief DownloadFrameUSB Read a single frame's woth of science data. +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param pData Pointer to a pre-allocated unsigned short data buffer. +/// \param SIZE Number of science data words to read (equal to framesize=xpix*ypix). +/// \param timeout Unsigned short (in ms) after which the function will +/// stop reading from the port and return NULL. +bool DownloadFrameUSB(MACIE_Settings *ptUserData, unsigned short pData[], long SIZE, unsigned short timeout) +{ + + // unsigned int timeout = (ptUserData->DetectorMode==CAMERA_MODE_SLOW) ? 6500 : 1500; + if (ptUserData->offline_develop == true) + { + // long xpix = (long) exposure_xpix(ptUserData); + // long ypix = (long) exposure_ypix(ptUserData); + exposure_test_data(ptUserData, pData, SIZE); // xpix*ypix); + } + else + { + ushort *ptemp = MACIE_ReadGigeScienceFrame(ptUserData->handle, timeout); + // Check if returns NULL + if (!ptemp) + { + // Wait 1000 msec and try again + verbose_printf(LOG_ERROR, ptUserData, "Null frame encountered in function: %s. Waiting 1 sec and re-attempting...\n", __func__); + verbose_printf(LOG_ERROR, ptUserData, " MACIE Error string: %s\n", MACIE_Error()); + delay(1000); + ptemp = MACIE_ReadUSBScienceFrame(ptUserData->handle, timeout); + } + // If still NULL, then return false + if (!ptemp) + { + verbose_printf(LOG_ERROR, ptUserData, "Null frame encountered in function: %s\n", __func__); + verbose_printf(LOG_ERROR, ptUserData, " MACIE Error string: %s\n", MACIE_Error()); + return false; + } + + // Fast Mode observations are backwards + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + memcpy(pData, ptemp, sizeof(ushort) * SIZE); + } + else + { + // for (long i=0; iramptime_ms; + int wait_total = 0; + + verbose_printf(LOG_DEBUG, ptUserData, "triggerTimeout = %i, wait_delta:%i\n", + triggerTimeout, wait_delta); + + timestamp_t t; + long nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + + // Poll available science data + while (nbytes <= 0) + { + // Delay for some time + delay(wait_delta); + + // Check to see if data has shown up on port yet + if (ptUserData->offline_develop == true) + nbytes = nbytes_ramp; + else + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + + wait_total += wait_delta; + verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + // Return false if we've reached time limit but haven't gotten all the bytes. + // There's a special case if nbytes isn't a multiple of 1024x1024, then + // the remainder bytes don't show up with MACIE_AvailableScienceData(), + // but we can still download them from the buffer. In this case, assume + // the bytes are there and just break out. Usually this only occurs on the + // very first or very last ramp. + if (wait_total > triggerTimeout) + { + verbose_printf(LOG_WARNING, ptUserData, "Trigger timeout limit of %i ms reached at: %s\n", + triggerTimeout, __func__); + if (nbytes_ramp % (1024 * 1024) != 0) + { + // delay(100); + break; + } + + verbose_printf(LOG_WARNING, ptUserData, " Expecting %li bytes. %li bytes available in %i ms.\n", + nbytes_ramp, nbytes, wait_total); + + // Delay the larger of 1 second to see if rest comes down + verbose_printf(LOG_ERROR, ptUserData, " Delaying %i msec more...\n", 1000); + delay(1000); + + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + verbose_printf(LOG_WARNING, ptUserData, " After delay, nbytes available: %li\n", nbytes); + if (nbytes < nbytes_ramp) + { + verbose_printf(LOG_ERROR, ptUserData, " Insufficient number of bytes available...\n"); + return false; + } + else + { + verbose_printf(LOG_WARNING, ptUserData, " Continuing...\n"); + break; + } + } + } + + if (get_verbose(ptUserData) == LOG_DEBUG) + { + wait_total = 0; + while (wait_total < int(ptUserData->ramptime_ms)) + { + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + delay(wait_delta); + wait_total += wait_delta; + if (nbytes >= nbytes_ramp) + break; + } + nbytes = (long)MACIE_AvailableScienceData(ptUserData->handle); + } + verbose_printf(LOG_DEBUG, ptUserData, " wait_total (ms): %i, nbytes: %li\n", wait_total, nbytes); + + // Download a ramp into pData buffer + t = get_timestamp(); + if (DownloadDataUSB(ptUserData, &pData[0], framesize * nframes_save, dltimeout) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "DownloadDataUSB failed at %s\n", __func__); + return false; + } + t = get_timestamp() - t; + double time_taken = t / 1000.0L; + + verbose_printf(LOG_DEBUG, ptUserData, " Ramp dl time: %.0f ms (wait_total: %i ms, nbytes: %li)\n", + time_taken, wait_total, nbytes); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief DownloadDataUSB Read science data. Capture some arbitrary amount of +/// science data. +/// \param ptUserData The user-set structure containing all the hardware parameters. +/// \param pData Pointer to a pre-allocated unsigned short data buffer. +/// \param SIZE Number of science data words to read. +/// \param timeout Unsigned short (in ms) after which the function will +/// stop reading from the port and return NULL. +bool DownloadDataUSB(MACIE_Settings *ptUserData, unsigned short pData[], long SIZE, unsigned short timeout) +{ + int nwords = 0; + + // unsigned int timeout = (ptUserData->DetectorMode==CAMERA_MODE_SLOW) ? 6500 : 1500; + if (ptUserData->offline_develop == true) + { + exposure_test_data(ptUserData, pData, SIZE); + return true; + } + else + { + nwords = MACIE_ReadGigeScienceData(ptUserData->handle, timeout, SIZE, pData); + verbose_printf(LOG_INFO, ptUserData, " Number of acquired science data words: %i pixels (%i bytes)\n", nwords, 2 * nwords); + } + + if (!pData) + { + verbose_printf(LOG_ERROR, ptUserData, "Null frame: %s\n", MACIE_Error()); + return false; + } + else if (ptUserData->DetectorMode == CAMERA_MODE_FAST) + { + // for (long i=0; i naxis, int bitpix, string filename) +{ + + long naxes = naxis.size(); + long npix = (naxes == 2) ? naxis[0] * naxis[1] : naxis[0] * naxis[1] * naxis[2]; + + // pointer to the FITS file + fitsfile *poutfits; + + // BITPIX options + // 1. [U]SHORT_IMG (16-bit [un]signed) -> T[U]SHORT // BITPIX=16 + // 2. [U]LONG_IMG (32-bit [un]signed) -> T[U]LONG // BITPIX=32 + // 3. [U]LONGLONG_IMG (64-bit [un]signed) -> T[U]LONGLONG // BITPIX=64 + // 4. FLOAT_IMG (32-bit) -> TFLOAT // BITPIX=-32 + // 5. DOUBLE_IMG (64-bit) -> TDOUBLE // BITPIX=-64 + + int datatype; + switch (bitpix) + { + case SHORT_IMG: + datatype = TSHORT; + break; + case USHORT_IMG: + datatype = TUSHORT; + break; + + case LONG_IMG: + datatype = TLONG; + break; + case ULONG_IMG: + datatype = TULONG; + break; + + case LONGLONG_IMG: + datatype = TLONGLONG; + break; + // case ULONGLONG_IMG: datatype = TULONGLONG; + // break; + + case FLOAT_IMG: + datatype = TFLOAT; + break; + case DOUBLE_IMG: + datatype = TDOUBLE; + break; + + default: + datatype = TUINT; + break; + } + + int status = 0; + + // create new FITS file + if (fits_create_file(&poutfits, filename.c_str(), &status)) + { + if (status) + { + printf("Failed at fits_create_file()\n"); + fits_report_error(stderr, status); + return false; + } + } + + // Write the required keywords for the primary array image + if (fits_create_img(poutfits, bitpix, naxes, &naxis[0], &status)) + { + if (status) + { + printf("Failed at fits_create_img()\n"); + fits_report_error(stderr, status); + return false; + } + } + + // Write data array to the FITS file + if (fits_write_img(poutfits, datatype, 1, npix, pData, &status)) + { + if (status) + { + printf("Failed at fits_write_img()\n"); + fits_report_error(stderr, status); + return false; + } + } + + // Add header keywords + + // Close FITS file + if (fits_close_file(poutfits, &status)) + ; + { + if (status) + { + printf("Failed at fits_close_file()\n"); + fits_report_error(stderr, status); + return false; + } + } + + return true; +} + +// Creates a data of some size to simulate output of MACIE_ReadUSBScienceData. +void exposure_test_data(MACIE_Settings *ptUserData, unsigned short pData[], long SIZE) +{ + + long xpix = (long)exposure_xpix(ptUserData); + unsigned int nout = ASIC_NumOutputs(ptUserData); + + long chsize = xpix / long(nout); + + // Print out expected channel values + verbose_printf(LOG_INFO, ptUserData, "Fake Data channels values = chnum*100 + %i\n", ptUserData->uiFileNum); + + // srand(time(NULL)); + for (long i = 0; i < SIZE; ++i) + { + pData[i] = 100 * int((i % xpix) / chsize + 1) + int(ptUserData->uiFileNum); // + int(rand() % 10); + // printf("pData[%lu] = %i\n", i, *(pData + i)); + } + // Every time we call this function, increment uiFileNum to get unique offset + ptUserData->uiFileNum++; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetMACIEClockRate Get the current MACIE master clock rate +/// from the MACIE card. Saves in ptUserData structure. +/// \param ptUserData The user-set structure containing all the hardware parameters. +bool GetMACIEClockRate(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + unsigned int val = 0; + + // Get MACIE Clock Speed + // verbose_printf(LOG_INFO, ptUserData, "Get MACIE clock rate....\n"); + if (ptUserData->offline_develop == false) + { + if (MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, 0x0010, &val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_ReadMACIEReg failed: %s\n", MACIE_Error()); + return false; + } + // Below 0x6f (DEC 111), 1 MHZ is a change of 4 values + // Above 0x6f (DEC 111), 1 MHZ is a change of 2 values + ptUserData->clkRateM = (val < 111) ? (val + 1) / 4 : (val - 55) / 2; + } + + // Update pixel rate information + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + // clkRateM in MHz to kHz pixel rate + // For instance, 10MHz master clock corresponds to 100 khz pixel rate + ptUserData->pixelRate = ptUserData->clkRateM * 10; + } + else + { + // For Fast Mode + // 80 Mhz -> 10000 kHz pixel rate (H1RG) + // 80 Mhz -> 5000 kHz pixel rate (H2RG, H4RG) + ptUserData->pixelRate = (1000 * ptUserData->clkRateM) / 8; + if (ptUserData->DetectorType != CAMERA_TYPE_H1RG) + ptUserData->pixelRate /= 2; + } + + // verbose_printf(LOG_INFO, ptUserData, " Succeeded.\n"); + verbose_printf(LOG_INFO, ptUserData, " MACIE Clock Rate = %i MHz\n", ptUserData->clkRateM); + verbose_printf(LOG_INFO, ptUserData, " Detector Pixel Rate = %i kHz\n", ptUserData->pixelRate); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetVoltages Print voltages or current for each MACIE Power DAC. +/// \param ptUserData The user-set structure containing all the hardware parameters +/// \param vArr[] Output pointer array holding voltages/currents +bool GetVoltages(MACIE_Settings *ptUserData, float vArr[]) +{ + + string names[MACIE_PWR_DAC_SIZE] = {"VREF1", + "VDDAHIGH1", "VDDAHIGH1_VL", "VDDAHIGH1_CL", + "VDDALOW1", "VDDALOW1_VL", "VDDALOW1_CL", + "VDDHIGH1", "VDDHIGH1_VL", "VDDHIGH1_CL", + "VDDLOW1", "VDDLOW1_VL", "VDDLOW1_CL", + "VDDIO1", "VDDIO1_VL", "VDDIO1_CL", + "VSSIO1", "VSSIO1_VL", + "VDDAUX1", + "VREF2", + "VDDAHIGH2", "VDDAHIGH2_VL", "VDDAHIGH2_CL", + "VDDALOW2", "VDDALOW2_VL", "VDDALOW2_CL", + "VDDHIGH2", "VDDHIGH2_VL", "VDDHIGH2_CL", + "VDDLOW2", "VDDLOW2_VL", "VDDLOW2_CL", + "VDDIO2", "VDDIO2_VL", "VDDIO2_CL", + "VSSIO2", "VSSIO2_VL", + "VDDAUX2"}; + + float fval = 0.0; + verbose_printf(LOG_NONE, ptUserData, "MACIE Power DAC Values:\n"); + for (int i = 0; i < MACIE_PWR_DAC_SIZE; i++) + { + if (ptUserData->offline_develop == false) + { + if (MACIE_GetVoltage(ptUserData->handle, ptUserData->slctMACIEs, MACIE_PWR_DAC(i), &fval) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_GetVoltage failed in %s\n", __func__); + return false; + } + } + + vArr[i] = fval; + verbose_printf(LOG_NONE, ptUserData, "%15s = %.2f %s\n", names[i].c_str(), vArr[i], + (names[i].substr(names[i].length() - 2) == "CL") ? "mA" : "V"); + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetPower Print on/off status for each MACIE Power Control item. +/// \param ptUserData The user-set structure containing all the hardware parameters +/// \param pArr[] Output pointer array indicating which elements are on/off +bool GetPower(MACIE_Settings *ptUserData, bool pArr[]) +{ + + string names[MACIE_PWR_CTRL_SIZE] = {"5V_ASIC", + "GIGE", "GIGE_OVERRIDE", + "DGND_FILTER_BYPASS", + "USB_FILTER_BYPASS", + "AGND_CLEAN_FILTER_BYPASS", + "AGND_DIRTY_FILTER_BYPASS", + "VDDAUX1", "VDDAUX2", + "VDDAHIGH1", "VDDALOW1", "VREF1", + "SENSE_VREF1_GNDA", + "SENSE_VDDAHIGH1_GNDA", "SENSE_VDDAHIGH1", + "SENSE_VDDALOW1_GNDA", "SENSE_VDDALOW1", + "VDDHIGH1", "VDDLOW1", + "VDDIO1", "VSSIO1", + "SENSE_VDDHIGH1_GND", "SENSE_VDDHIGH1", + "SENSE_VDDLOW1_GND", "SENSE_VDDLOW1", + "VDDAHIGH2", "VDDALOW2", "VREF2", + "SENSE_VREF2_GNDA", + "SENSE_VDDAHIGH2_GNDA", "SENSE_VDDAHIGH2", + "SENSE_VDDALOW2_GNDA", "SENSE_VDDALOW2", + "VDDHIGH2", "VDDLOW2", + "VDDIO2", "VSSIO2", + "SENSE_VDDHIGH2_GND", "SENSE_VDDHIGH2", + "SENSE_VDDLOW2_GND", "SENSE_VDDLOW2"}; + + bool bEn = true; + verbose_printf(LOG_NONE, ptUserData, "MACIE Power Control Settings:\n"); + for (int i = 0; i < MACIE_PWR_CTRL_SIZE; i++) + { + if (ptUserData->offline_develop == false) + { + if (MACIE_GetPower(ptUserData->handle, ptUserData->slctMACIEs, MACIE_PWR_CTRL(i), &bEn) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_GetPower failed in %s\n", __func__); + return false; + } + } + + pArr[i] = bEn; + verbose_printf(LOG_NONE, ptUserData, "%25s = %s\n", names[i].c_str(), + (pArr[i] == true) ? "ON" : "OFF"); + } + + return true; +} + +bool GetPowerASIC(MACIE_Settings *ptUserData, bool *bEn) +{ + if (ptUserData->offline_develop == false) + { + if (MACIE_GetPower(ptUserData->handle, ptUserData->slctMACIEs, MACIE_CTRL_5V_ASIC, bEn) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_GetPower failed in %s\n", __func__); + return false; + } + } + else + { + *bEn = true; + } + verbose_printf(LOG_INFO, ptUserData, "ASIC is powered %s.\n", *bEn ? "ON" : "OFF"); + + return true; +} + +bool SetPowerASIC(MACIE_Settings *ptUserData, bool bEn) +{ + unsigned int reg = 0x0300; + unsigned int val = 0; + unsigned int bitmask = 1; + + if (ptUserData->offline_develop == false) + { + + // Read MACIE 0x0300 and store in val + if (MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, reg, &val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "Initial MACIE_ReadMACIEReg (h%04x) failed in %s\n", + reg, __func__); + return false; + } + } + else + { + val = 0x3; + } + + if (bEn == true) + val |= bitmask; // Enable bit0 + else + val &= ~bitmask; // Clear bit0 + verbose_printf(LOG_DEBUG, ptUserData, "Writing to MACIE: h%04x = 0x%04x\n", reg, val); + + if (ptUserData->offline_develop == false) + { + // Write new value with bit0 cleared + if (MACIE_WriteMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, reg, val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_WriteMACIEReg (h%04x) failed in %s\n", reg, __func__); + return false; + } + + // Confirm bit0 has been written correctly + if (MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, reg, &val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_ReadMACIEReg (h%04x) failed in %s\n", reg, __func__); + return false; + } + + val &= bitmask; // AND mask of bit0 + if ((bEn == false && val == 1) || (bEn == true && val == 0)) + { + verbose_printf(LOG_ERROR, ptUserData, "ASIC failed to power %s.\n", bEn ? "on" : "off"); + return false; + } + } + + // Print out MACIE power settings + if (GetPowerASIC(ptUserData, &bEn) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "GetPowerASIC failed in %s\n", __func__); + return false; + } + + // verbose_printf(LOG_INFO, ptUserData, "ASIC succesfully powered %s.\n", bEn ? "on" : "off"); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief SetLED Set brightness of MACIE's status LEDs. This writes to MACIE +/// register 0x000a on bits 0, 1, and 2. Setting bit2=1 turns off LEDS. +/// Setting bits 0 and 1 to values 0,1,2, or 3 changes the LED brightness. +/// \param ptUserData The user-set structure containing all the hardware parameters +/// \param set_val A alue 0-4, where 0 is off and 1-4 is faintest to brightest +bool SetLED(MACIE_Settings *ptUserData, unsigned int set_val) +{ + + unsigned int reg = 0x000a; + unsigned int reg_val = 0; + unsigned int bitmask = 0; + + if (ptUserData->offline_develop == false) + { + + // Read MACIE 0x000a and store in reg_val + if (MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, reg, ®_val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "Initial MACIE_ReadMACIEReg (h%04x) failed in %s\n", reg, __func__); + return false; + } + } + else + { + reg_val = 0x3; + } + + // Clear first three bits + // bit2 controls + bitmask = 0x7; + reg_val &= ~bitmask; + + // Determine val to write to MACIE + if (set_val == 0) + { // Power off + bitmask = 0x4; + } + else if (set_val <= 4) + { // Power on (bit2=0) with bits 0 and 1 values being 0-3 + bitmask = set_val - 1; + } + else + { // Any other setting, max brightness + bitmask = 0x3; + } + + // Enable bits set in bitmask + reg_val |= bitmask; + verbose_printf(LOG_DEBUG, ptUserData, "Writing to MACIE: h%04x = 0x%04x\n", reg, reg_val); + + if (ptUserData->offline_develop == false) + { + // Write new value + if (MACIE_WriteMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, reg, reg_val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_WriteMACIEReg (h%04x) failed in %s\n", reg, __func__); + return false; + } + + // Confirm bit0 has been written correctly + if (MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, reg, ®_val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_ReadMACIEReg (h%04x) failed in %s\n", reg, __func__); + return false; + } + // Clear all but first three bits and check if equal to bitmask + reg_val &= 0x7; + if (reg_val != bitmask) + { + verbose_printf(LOG_ERROR, ptUserData, "reg_val (%i) != bitmask (%i) \n", reg_val, bitmask); + return false; + } + } + + verbose_printf(LOG_INFO, ptUserData, "ASIC LED power set succesfully to %i.\n", set_val); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief SetMACIEClockRate Set the MACIE master clock rate. +/// \param ptUserData The user-set structure containing all hardware parameters. +/// \param clkRateM Value to set clock rate in MHz. +bool SetMACIEClockRate(MACIE_Settings *ptUserData, unsigned int clkRateM) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Check that clkRateM is valid + // Slow: [5-50] (5-500 kHz pixel rate) + // Fast: [8-80] (0.5-5 MHz pixel rate) + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + if ((clkRateM < 5) || (clkRateM > 50)) + { + verbose_printf(LOG_ERROR, ptUserData, + "SetMACIEClockRate value (%i MHz) out of range (5-50)\n", clkRateM); + return false; + } + } + else + { + if ((clkRateM < 8) || (clkRateM > 80)) + { + verbose_printf(LOG_ERROR, ptUserData, + "SetMACIEClockRate value (%i MHz) out of range (8-80)\n", clkRateM); + return false; + } + } + + // Set MACIE Clock Speed + unsigned int val = 0; + verbose_printf(LOG_INFO, ptUserData, "Set MACIE clock rate to %i MHz\n", clkRateM); + + // Convert clock rate in MHz to register value + val = (clkRateM < 28) ? (4 * clkRateM) - 1 : (2 * clkRateM) + 55; + if (ptUserData->offline_develop == false) + { + if (MACIE_WriteMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, 0x0010, val) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_WriteMACIEReg failed: %s\n", MACIE_Error()); + return false; + } + } + + // If we've succeeded, then save value to ptUserData + ptUserData->clkRateM = clkRateM; + GetMACIEClockRate(ptUserData); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetMACIEPhaseShift Get the current ASIC clock phase shift setting +/// from the MACIE card. +/// \param ptUserData The user-set structure containing all hardware parameters. +bool GetMACIEPhaseShift(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Get MACIE Clock Phase Shift + verbose_printf(LOG_INFO, ptUserData, "Get MACIE clock phase parameters....\n"); + if (ptUserData->offline_develop == false) + { + if (MACIE_GetMACIEPhaseShift(ptUserData->handle, ptUserData->slctMACIEs, &ptUserData->clkPhase) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_GetMACIEPhaseShift failed: %s\n", MACIE_Error()); + return false; + } + } + verbose_printf(LOG_INFO, ptUserData, " clkPhase = 0x%04x\n", ptUserData->clkPhase); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief SetMACIEPhaseShift Optimize the ASIC clock phase for science data +/// transmission from ASIC to MACIE. Normally is function is only used for ASIC +/// fast mode application. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \param clkPhase ASIC clock phase setting register value. +bool SetMACIEPhaseShift(MACIE_Settings *ptUserData, unsigned short clkPhase) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Set MACIE Clock Phase Shift + verbose_printf(LOG_INFO, ptUserData, "Set MACIE clkPhase = 0x%04x\n", clkPhase); + if (ptUserData->offline_develop == false) + { + if (MACIE_SetMACIEPhaseShift(ptUserData->handle, ptUserData->slctMACIEs, clkPhase) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_SetMACIEPhaseShift failed: %s\n", MACIE_Error()); + return false; + } + } + + // If we've succeeded, then save value to ptUserData + ptUserData->clkPhase = clkPhase; + // verbose_printf(LOG_INFO, ptUserData, " Succeeded.\n"); + verbose_printf(LOG_DEBUG, ptUserData, " clkPhase = 0x%04x\n", ptUserData->clkPhase); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ToggleMACIEPhaseShift Toggle clock phase shifting on or off. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \param enable Enable clock phase shifting; true or false. +bool ToggleMACIEPhaseShift(MACIE_Settings *ptUserData, bool enable) +{ + unsigned short pos = 8; // Bit 8 controls whether or not Phase Shift is enabled + unsigned short newPhase = 0; + bool bit; // Used to check if already enabled + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Assume ptUserData->clkPhase accurately represents hardware state + bit = (ptUserData->clkPhase >> pos) & 1U; + if (bit == enable) + { + verbose_printf(LOG_WARNING, ptUserData, "Phase Shift already %s. Returning.\n", + (enable == true) ? "enabled" : "disabled"); + return true; + } + + // Update clkPhase parameter + newPhase = (enable == true) ? ptUserData->clkPhase | (1UL << pos) : // Toggle bit 8 to on + ptUserData->clkPhase & ~(1UL << pos); // Toggle bit 8 to off + + verbose_printf(LOG_INFO, ptUserData, "%s Clock Phase Shift\n", + (enable == true) ? "Enabling" : "Disabling"); + // clkPhase is updated inside SetMACIEPhaseShift + return SetMACIEPhaseShift(ptUserData, newPhase); +} + +bool FindOptimalPhaseShift(MACIE_Settings *ptUserData, ushort val_start, ushort val_end) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Make sure Clock Phase Shift bit is enabled (bit 8) + val_start |= (1UL << 8); + val_end |= (1UL << 8); + if (val_start > val_end) + { + verbose_printf(LOG_ERROR, ptUserData, "val_start must be less than val_end\n"); + return false; + } + + // Current values to revert to at the end + bool bSaveTemp = ptUserData->bSaveData; + ushort usCPTemp = ptUserData->clkPhase; + LOG_LEVEL llTemp = get_verbose(ptUserData); + + // Don't saving and only print error messages + ptUserData->bSaveData = false; + set_verbose(ptUserData, LOG_ERROR); + + // Variable to hold error counts + uint errCnts = 0; + + // First and last values where err counts = 0 + ushort val0_1 = 0; + ushort val0_2 = 0; + + // Increment through each value + for (ushort i = val_start; i < val_end + 1; i++) + { + // Reset Error Counters + if (ResetErrorCounters(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ResetErrorCounters failed at %s\n", __func__); + ptUserData->bSaveData = bSaveTemp; + set_verbose(ptUserData, llTemp); + return false; + } + // Set the Phase Shift value + if (SetMACIEPhaseShift(ptUserData, i) == false) + { + verbose_printf(LOG_ERROR, ptUserData, + "SetMACIEPhaseShift failed at %s with clkPhase = 0x%04x\n", __func__, i); + ptUserData->bSaveData = bSaveTemp; + set_verbose(ptUserData, llTemp); + GetErrorCounters(ptUserData, true); + return false; + } + + // Acquire exposures + if (AcquireDataUSB(ptUserData, false) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "AcquireDataUSB failed at %s()\n", __func__); + ptUserData->bSaveData = bSaveTemp; + set_verbose(ptUserData, llTemp); + GetErrorCounters(ptUserData, true); + return false; + } + // Download data (will not be saved) + if (DownloadAndSaveAllUSB(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "DownloadAndSaveAllUSB failed at %s()\n", __func__); + ptUserData->bSaveData = bSaveTemp; + set_verbose(ptUserData, llTemp); + GetErrorCounters(ptUserData, true); + return false; + } + + // Download Error Counters and check ASIC errors + if (GetErrorCounters(ptUserData, false) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "GetErrorCounters failed at %s()\n", __func__); + ptUserData->bSaveData = bSaveTemp; + set_verbose(ptUserData, llTemp); + return false; + } + // Sum all error counts for ASIC Science + errCnts = TotalErrorCounts(ptUserData); + fprintf(stderr, " 0x%04x %i\n", i, errCnts); + + if (errCnts == 0) + { + if (val0_1 == 0) + val0_1 = i; + + val0_2 = i; + } + } + + ResetErrorCounters(ptUserData); + + // Recommended value + fprintf(stderr, "Recommended Value: 0x%04x\n", val0_1 + (val0_2 - val0_1 + 1) / 2); + + // Revert back to original value + ptUserData->bSaveData = bSaveTemp; + SetMACIEPhaseShift(ptUserData, usCPTemp); + set_verbose(ptUserData, llTemp); + return true; +} + +// Return total number of errors in errArr +unsigned int TotalErrorCounts(MACIE_Settings *ptUserData) +{ + uint errCnts = 0; + for (int j = 0; j < MACIE_ERROR_COUNTERS; j++) + errCnts += (uint)ptUserData->errArr[j]; + return errCnts; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetErrorCounters Read MACIE error counter registers. +/// \param ptUserData The user-set structure containing the hardware parameters. +/// \param bVerb A more verbose output describing error counter sections. +bool GetErrorCounters(MACIE_Settings *ptUserData, bool bVerb) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->offline_develop == false) + { + if (MACIE_GetErrorCounters(ptUserData->handle, ptUserData->slctMACIEs, ptUserData->errArr) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_GetErrorCounters failed: %s\n", MACIE_Error()); + return false; + } + } + + // 1. UART Parity Errors + // 2. UART Stopbit Errors + // 3. UART Timeout Errors + // 4. USB Timeout Errors + // 5. GigE Timeout Errors + // 6-13 ASIC 1 configuration interface errors + // 14-21 ASIC 2 configuration interface errors + // 22-25 FIFO errors (e.g. overflow of main FIFO at 22) + // 26-29 ASIC 1 science interface errors + // 30-33 ASIC 2 science interface errors + + if (bVerb) + { + fprintf(stderr, " UART (Parity, Stopbit, Timout) = ("); + for (int i = 0; i < 3; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + + fprintf(stderr, " (USB, GigE) Timout = ("); + for (int i = 3; i < 5; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + + fprintf(stderr, " ASIC1 Config = ("); + for (int i = 5; i < 13; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + + fprintf(stderr, " ASIC2 Config = ("); + for (int i = 13; i < 21; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + + fprintf(stderr, " FIFO errors = ("); + for (int i = 21; i < 25; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + + fprintf(stderr, " ASIC1 Science = ("); + for (int i = 25; i < 29; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + + fprintf(stderr, " ASIC2 Science = ("); + for (int i = 29; i < 33; i++) + fprintf(stderr, " %04x", ptUserData->errArr[i]); + fprintf(stderr, " )\n"); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ResetErrorCounters Reset MACIE error counter registers. +/// \param ptUserData The user-set structure containing the hardware parameters. +bool ResetErrorCounters(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->offline_develop == false) + { + if (MACIE_ResetErrorCounters(ptUserData->handle, ptUserData->slctMACIEs) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_ResetErrorCounters failed: %s\n", MACIE_Error()); + return false; + } + } + // Set all error counters to 0 if success + std::fill_n(ptUserData->errArr, MACIE_ERROR_COUNTERS, 0); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ReadASICReg Read ASIC register. +/// \param ptUserData The user-set structure containing the hardware parameters. +/// \param addr Register address +/// \param val Pointer or value read from the address (output). +bool ReadASICReg(MACIE_Settings *ptUserData, unsigned short addr, unsigned int *val) +{ + unsigned short ntry = 3; + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Try a few times and return if successful + if (ptUserData->offline_develop == false) + { + for (int i = 0; i < ntry; i++) + { + // TODO: Maybe put in a slight delay between reads? + // If read is succesful, then return true + delay(10); + if (MACIE_ReadASICReg(ptUserData->handle, ptUserData->slctASICs, addr, val, false, true) == MACIE_OK) + { + verbose_printf(LOG_DEBUG, ptUserData, " ReadASICReg h%04x = 0x%04x\n", addr, *val); + return true; + } + // if not successful and we haven't hit the last iteration, + // then ResetErrorCounters (which could also fail) + else if (i < ntry - 1) + { + if (ResetErrorCounters(ptUserData) == false) + break; + } + } + } + else + { + string addr_name = addr_name_hex(addr); + *val = ptUserData->RegAllASIC[addr_name].value; + verbose_printf(LOG_DEBUG, ptUserData, " %s: h%04x = 0x%04x\n", __func__, addr, *val); + + return true; + } + + // If we've gotten here, then we were not successful + verbose_printf(LOG_ERROR, ptUserData, "MACIE_ReadASICReg failed: %s\n", MACIE_Error()); + return false; +} + +bool ReadASICBits(MACIE_Settings *ptUserData, regInfo *reg, unsigned int *val) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Read the ASIC registers + if (ReadASICReg(ptUserData, reg->addr, val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICReg failed in %s\n", __func__); + return false; + } + + // Number of bits + unsigned int nbits = reg->bit1 - reg->bit0 + 1; + *val >>= reg->bit0; // Shift val bits to the right + *val &= (1 << nbits) - 1; // Bitwise AND with a bitmask + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ReadASICBlock Read a number of contiguous registers starting at the +/// specified register address. +/// \param ptUserData The user-set structure containing the hardware parameters. +/// \param addr ASIC register address to start reading (ie., 0x6000) +/// \param nreg Number of ASIC registers to read +/// \param val Pointer or address of array storing the readback register values. +bool ReadASICBlock(MACIE_Settings *ptUserData, unsigned short addr, int nreg, + unsigned int *val_arr) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->offline_develop == false) + { + if (MACIE_ReadASICBlock(ptUserData->handle, ptUserData->slctASICs, addr, val_arr, nreg, false, true) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_ReadASICBlock failed: %s\n", MACIE_Error()); + return false; + } + } + else + { + string addr_name; + // unsigned int val_arr[nreg]; + for (int i = 0; i < nreg; i++) + { + // Convert decimal addr to hex string + addr_name = addr_name_hex(addr + i); + val_arr[i] = ptUserData->RegAllASIC[addr_name].value; + } + } + + for (int i = 0; i < nreg; i++) + verbose_printf(LOG_DEBUG, ptUserData, " %s: h%04x = 0x%04x\n", __func__, addr + i, val_arr[i]); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief WriteASICReg Write value to ASIC register. +/// \param addr Register address +/// \param val Value to write to the register address. +bool WriteASICReg(MACIE_Settings *ptUserData, unsigned short addr, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->offline_develop == false) + { + if (MACIE_WriteASICReg(ptUserData->handle, ptUserData->slctASICs, addr, val, true) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_WriteASICReg failed: %s\n", MACIE_Error()); + return false; + } + // verbose_printf(LOG_DEBUG, ptUserData, "WriteASICReg: h%04x, 0x%04x\n", addr, val); + verbose_printf(LOG_DEBUG, ptUserData, " %s: h%04x = 0x%04x\n", __func__, addr, val); + } + else + { + // Convert decimal addr to hex string + string addr_name = addr_name_hex(addr); + ptUserData->RegAllASIC[addr_name] = gen_regInfo(addr, 0, 15, val); + verbose_printf(LOG_DEBUG, ptUserData, " %s: h%04x = 0x%04x\n", __func__, addr, val); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief WriteASICBits Write only specified bits of a register +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \param reg Register info structure {address, bit0, bit1, value} +bool WriteASICBits(MACIE_Settings *ptUserData, regInfo *reg) +{ + unsigned int regval = 0; + unsigned int bitmask = 0; + unsigned int nbits = 0; + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Read the ASIC registers + if (ReadASICReg(ptUserData, reg->addr, ®val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICReg failed in %s\n", __func__); + return false; + } + + // Create bitmask + nbits = reg->bit1 - reg->bit0 + 1; + bitmask = (1 << nbits) - 1; + // Ensure input reg.value indeed only covers that many bits + reg->value &= bitmask; + + // Shift bitmask and clear bits + regval &= ~(bitmask << reg->bit0); + + // Replace cleared bits with reg.value + regval |= reg->value << reg->bit0; + + // Write final ASIC registers + if (WriteASICReg(ptUserData, reg->addr, regval) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "WriteASICReg failed in %s\n", __func__); + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief WriteASICBlock Write a number of contiguous registers starting at the +/// specified register address. +/// \param addr ASIC register address to start writing (ie., 0x6000) +/// \param nreg Number of ASIC registers to write to +/// \param val Pointer or address of array storing the register write values. +bool WriteASICBlock(MACIE_Settings *ptUserData, unsigned short addr, int nreg, + unsigned int *val) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ptUserData->offline_develop == false) + { + if (MACIE_WriteASICBlock(ptUserData->handle, ptUserData->slctASICs, addr, val, nreg, true) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_WRiteASICBlock failed: %s\n", MACIE_Error()); + return false; + } + } + else + { + // Update stored registers + string addr_name; + for (int i = 0; i < nreg; i++) + { + addr_name = addr_name_hex(addr + i); + ptUserData->RegAllASIC[addr_name] = gen_regInfo(addr, 0, 15, val[i]); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetASICSettings Grab all ASIC register settings defined in RegMap +/// mapped dictionary, which exists inside UserData settings. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +bool GetASICSettings(MACIE_Settings *ptUserData) +{ + map &RegMap = ptUserData->RegMap; + map::iterator it; + unsigned int val = 0; + regInfo *reg; + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // verbose_printf(LOG_INFO, ptUserData, "Reading ASIC registers...\n"); + for (it = RegMap.begin(); it != RegMap.end(); it++) + { + reg = &it->second; + + // Read the ASIC registers + // TODO: Maybe put in a slight delay between reads? + if (ReadASICBits(ptUserData, reg, &val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + return false; + } + reg->value = val; + + verbose_printf(LOG_DEBUG, ptUserData, "%s : h%04x <%i:%i> = %i\n", + it->first.c_str(), reg->addr, reg->bit1, reg->bit0, reg->value); + } + + verbose_printf(LOG_INFO, ptUserData, "Succeeded reading ASIC registers.\n"); + return true; +} + +// NumResets 0x4000 0 15 # NReset +// NumReads 0x4001 0 15 # NRead in each Group +// NumDrops 0x4005 0 15 # NDrop between consecutive Groups +// NumGroups 0x4004 0 15 # NGroups +// NumRamps 0x4003 0 15 # NRamps +// ExtraPixels 0x4006 0 15 # Number of extra pixel times added per row +// ExtraLines 0x4007 0 15 # Number of extra rows added per frame + +//////////////////////////////////////////////////////////////////////////////// +/// \brief SetASICParameter Modify ASIC parameters as defined in .cfg files. +/// This function only modifies those relevant bits (bits0 to bit1) +/// \param ptUserData The user-set structure containing the hardware parameters. +/// \param addr_name Name of parameter to modify, such as NumReads or VReset1 +/// \param val Value to set parameter +bool SetASICParameter(MACIE_Settings *ptUserData, string addr_name, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + map &RegMap = ptUserData->RegMap; + + // Check if addr_name key exists + // If it's not valid, throw warning, but return true. + if (RegMap.count(addr_name) == 0) + { + verbose_printf(LOG_WARNING, ptUserData, + "Parameter name %s does not exist in Register Map.\n", addr_name.c_str()); + return false; + } + + regInfo *reg = &RegMap[addr_name]; + regInfo regNew = gen_regInfo(reg->addr, reg->bit0, reg->bit1, val); + unsigned int valOut; + + // Check if desired value is different than current value + // If so, then just return + if (ReadASICBits(ptUserData, reg, &valOut) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + return false; + } + if (val == valOut) + { + reg->value = valOut; + return true; + } + + // Write ASIC register + if (WriteASICBits(ptUserData, ®New) == false) + { + verbose_printf(LOG_ERROR, ptUserData, + "WriteASICBits failed to write %s in %s\n", addr_name.c_str(), __func__); + return false; + } + + // Read the updated ASIC register value + if (ReadASICBits(ptUserData, reg, &valOut) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + return false; + } + + // Verify ASIC reg value matches input + if (val != valOut) + { + verbose_printf(LOG_ERROR, ptUserData, + "Write value of %i (0x%04x) does not match ASIC read value of %i (0x%04x) for %s in %s.\n", + val, val, valOut, valOut, addr_name.c_str(), __func__); + return false; + } + + verbose_printf(LOG_INFO, ptUserData, "Updated %s from %i (0x%04x) to %i (0x%04x).\n", + addr_name.c_str(), reg->value, reg->value, valOut, valOut); + + reg->value = valOut; + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief GetASICParameter Obtain ASIC parameters as defined in .cfg files. +/// This function only reads current ASIC setting stored in RegMap. +/// \param ptUserData The user-set structure containing the hardware parameters. +/// \param addr_name Name of parameter to read, such as NumReads or VReset1. +/// \param val Value output. +bool GetASICParameter(MACIE_Settings *ptUserData, string addr_name, unsigned int *val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + map &RegMap = ptUserData->RegMap; + + // Check if addr_name key exists + if (RegMap.count(addr_name) == 0) + { + verbose_printf(LOG_ERROR, ptUserData, + "Parameter name %s does not exist in Register Map.\n", addr_name.c_str()); + return false; + } + + // Assume RegMap accurately reflects current state of ASIC registries + // Allows us to grab measurements if USB pipe is being used by data download. + regInfo *reg = &RegMap[addr_name]; + *val = reg->value; + // unsigned int valOut; + + // // Read the ASIC register value + // if (ReadASICBits(ptUserData, reg, &valOut)==false) + // { + // verbose_printf(LOG_ERROR, ptUserData, "ReadASICBits failed in %s\n", __func__); + // return false; + // } + + // // Store in ptUserData->RegMap + // reg->value = valOut; + // *val = reg->value; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// ASIC convenience functions +//////////////////////////////////////////////////////////////////////////////// +unsigned int ASIC_Generic(MACIE_Settings *ptUserData, string addr_name, bool bSet, unsigned int val) +{ + if (bSet == true) + { + if (SetASICParameter(ptUserData, addr_name, val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "SetASICParameter (addr_name=%s) failed at %s()\n", + addr_name.c_str(), __func__); + val = 0; + } + } + else + { + if (GetASICParameter(ptUserData, addr_name, &val) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "GetASICParameter (addr_name=%s) failed at %s()\n", + addr_name.c_str(), __func__); + val = 0; + } + } + verbose_printf(LOG_DEBUG, ptUserData, " %s(): %s returns %i\n", __func__, addr_name.c_str(), val); + return val; +} +unsigned int ASIC_NResets(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if ((bSet == true) && (val < 1)) + { + verbose_printf(LOG_ERROR, ptUserData, "NumResets should be >0. Setting to 1.\n"); + val = 1; + } + return ASIC_Generic(ptUserData, "NumResets", bSet, val); +} +unsigned int ASIC_NReads(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if ((bSet == true) && (val < 1)) + { + verbose_printf(LOG_ERROR, ptUserData, "NumReads should be >0. Setting to 1.\n"); + val = 1; + } + return ASIC_Generic(ptUserData, "NumReads", bSet, val); +} +unsigned int ASIC_NDrops(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + return ASIC_Generic(ptUserData, "NumDrops", bSet, val); +} +unsigned int ASIC_NGroups(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if ((bSet == true) && (val < 1)) + { + verbose_printf(LOG_ERROR, ptUserData, "NumGroups should be >0. Setting to 1.\n"); + val = 1; + } + return ASIC_Generic(ptUserData, "NumGroups", bSet, val); +} +unsigned int ASIC_NRamps(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if ((bSet == true) && (val < 1)) + { + verbose_printf(LOG_ERROR, ptUserData, "NumRamps should be >0. Setting to 1.\n"); + val = 1; + } + return ASIC_Generic(ptUserData, "NumRamps", bSet, val); +} +unsigned int ASIC_NCoadds(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if ((bSet == true) && (val < 1)) + { + verbose_printf(LOG_ERROR, ptUserData, "NumCoadds should be >0. Setting to 1.\n"); + val = 1; + } + + if (bSet == true) + { + ptUserData->uiNumCoadds = val; + } + else + { + val = ptUserData->uiNumCoadds; + } + return val; +} +unsigned int ASIC_NSaves(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if ((bSet == true) && (val < 1)) + { + verbose_printf(LOG_ERROR, ptUserData, "uiNumSaves should be >0. Setting to 1.\n"); + val = 1; + } + + if (bSet == true) + { + ptUserData->uiNumSaves = val; + } + else + { + val = ptUserData->uiNumSaves; + } + return val; +} + +// Return the number of frames in exposure (either just frames for d/l or all w/ resets+drops) +// If include_all=false, then only include number of saved frames (reads + maybe resets) +unsigned int exposure_nframes(MACIE_Settings *ptUserData, bool include_all) +{ + unsigned int nramps = ASIC_NRamps(ptUserData, false, 0); + unsigned int ngroups = ASIC_NGroups(ptUserData, false, 0); + unsigned int nreads = ASIC_NReads(ptUserData, false, 0); + unsigned int ndrops = 0; + unsigned int nresets = 0; + + // Saving reset frames? + unsigned int val = 0; + if (GetASICParameter(ptUserData, "SaveRstFrames", &val) == true) + if (val == 1) + nresets = ASIC_NResets(ptUserData, false, 0); + + if (include_all) + { + ndrops = ASIC_NDrops(ptUserData, false, 0); + nresets = ASIC_NResets(ptUserData, false, 0); + } + + return nramps * (ngroups * nreads + (ngroups - 1) * ndrops + nresets); +} + +// Input desired ramp integration time in millisec (tint_ms) and maximum number of groups. +// Returns the total number of groups and drops to obtain tint_ms. +// NReads is always assumed to be 1. Ramp time increased by adding drop frames. +bool calc_ramp_settings(MACIE_Settings *ptUserData, double tint_ms, int ngmax, + uint *ngroups, uint *ndrops, uint *nreads) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (ngmax <= 0) + ngmax = ptUserData->uiNumGroups_max; + + // Special case, single frame + double ftime_ms = ptUserData->frametime_ms; + if (tint_ms < ftime_ms) + { + *ngroups = 1; + *nreads = 1; + *ndrops = 0; + return true; + } + + // Total number of requested frames based on ramp integration time + int nftot = (int)ceil(tint_ms / ftime_ms); + int nr = 1; + int nd = 0; + int ng = 2; + + // Special case, 2 groups + if ((ngmax == 2) || (ngmax == 1)) + { + if (ngmax == 1) + verbose_printf(LOG_WARNING, ptUserData, + "Maximum number of groups must be greater than or equal to 2\n"); + ng = 2; + nd = nftot - (ng * nr); + *ngroups = ng; + *nreads = nr; + *ndrops = nd; + return true; + } + + // More requested frames that groups + // Need to insert drop frames into each group + // Optimize ndrops and ngroups to obtain request int time + if (nftot > ngmax) + { + int nftot_res = 0, ngmin = 0; + double frac = 1.0, nf_diff = 0.0; + ngmin = (ngmax <= 3) ? ngmax - 1 : 2; + + int ng_best = 0, nd_best = 0; + double nf_diff_prev = 10.0; + double frac_prev = 1.0; + + for (int i = ngmax; i > ngmin; --i) + { + ng = i; + nd = ceil((tint_ms / ftime_ms - (ng * nr)) / (ng - 1)); + nftot_res = ng * nr + (ng - 1) * nd; + + // Break conditions + nf_diff = (double)nftot_res - (tint_ms / ftime_ms); + frac = nf_diff * ftime_ms / tint_ms; + + // This keeps the highest ngroups if same values for multiple combinations + if ((nf_diff < nf_diff_prev) || (frac < frac_prev)) + { + ng_best = ng; + nd_best = nd; + nf_diff_prev = nf_diff; + frac_prev = frac; + } + + double tint = (double)ftime_ms * (ng * nr + (ng - 1) * nd); + printf("ng: %i, nd: %i, nftot: %i, nftot_res: %i, nf_diff: %f, frac: %f, tint: %f\n", + ng, nd, nftot, nftot_res, nf_diff, frac, tint); + + if ((nf_diff <= 1) || (frac <= 0.05)) + break; + } + printf("ng_best: %i, nd_best: %i\n", ng_best, nd_best); + ng = ng_best; + nd = nd_best; + } + else + { + ng = nftot; + nd = 0; + nr = 1; + } + + *ngroups = ng; + *nreads = nr; + *ndrops = nd; + + return true; +} + +// Set exposure settings: nramps, ncoadds, ngroups, nreads, ndrops +// The number of ramps requested from the ASIC will be ncoadds*nsaved_ramps +bool set_exposure_settings(MACIE_Settings *ptUserData, bool bSave, + uint ncoadds, uint nsaved_ramps, uint ngroups, uint nreads, uint ndrops, uint nresets) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + ptUserData->bSaveData = bSave; + + if (ngroups < 1) + ngroups = 1; + if (nreads < 1) + nreads = 1; + if (nresets < 1) + nresets = 1; + + if (ncoadds < 1) + ncoadds = 1; + if (nsaved_ramps < 1) + nsaved_ramps = 1; + + ASIC_NCoadds(ptUserData, true, ncoadds); + ASIC_NSaves(ptUserData, true, nsaved_ramps); + + verbose_printf(LOG_INFO, ptUserData, "Save data is currently %s\n", bSave ? "ENABLED" : "DISABLED"); + verbose_printf(LOG_INFO, ptUserData, "Number of coadds: %i\n", ncoadds); + verbose_printf(LOG_INFO, ptUserData, "Number of saved ramps: %i\n", nsaved_ramps); + + ASIC_NRamps(ptUserData, true, ncoadds * nsaved_ramps); + ASIC_NGroups(ptUserData, true, ngroups); + ASIC_NReads(ptUserData, true, nreads); + ASIC_NDrops(ptUserData, true, ndrops); + ASIC_NResets(ptUserData, true, nresets); + + if (ReconfigureASIC(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfigure failed at %s()\n", __func__); + return false; + } + + double rtime_ms = ptUserData->ramptime_ms; // Ramp time including reset frames + double itime_ms = exposure_inttime_ms(ptUserData); // Photon collection time + double etime_sec = rtime_ms * ncoadds * nsaved_ramps / 1000; + verbose_printf(LOG_INFO, ptUserData, "MACIE Clock Rate = %i MHz\n", ptUserData->clkRateM); + verbose_printf(LOG_INFO, ptUserData, "Frame time: %.3f ms\n", ptUserData->frametime_ms); + verbose_printf(LOG_INFO, ptUserData, "Ramp time: %.3f ms\n", rtime_ms); + verbose_printf(LOG_INFO, ptUserData, "Ramp photon-collection time: %.3f ms\n", itime_ms); + verbose_printf(LOG_INFO, ptUserData, "Estimated time to execute Exposure: %.3f sec\n", etime_sec); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief set_frame_settings Set the window and stripe frame sizes. +/// \param ptUserData The user-set structure containing the hardware parameters. +/// \param bHorzWin Set horizontal window mode (if set, then window mode). +/// \param bVertWin Set vertical window mode (either window or stripe mode). +/// \param val Value output. +bool set_frame_settings(MACIE_Settings *ptUserData, bool bHorzWin, bool bVertWin, + uint x1, uint x2, uint y1, uint y2) +{ + + unsigned int xdet = ptUserData->uiDetectorWidth; + unsigned int ydet = ptUserData->uiDetectorHeight; + + // Fix values that are outside of detector bounds + if (x1 > xdet - 1) + x1 = 0; + if (x2 > xdet - 1) + x2 = xdet - 1; + if (y1 > ydet - 1) + y1 = 0; + if (y2 > ydet - 1) + y2 = ydet - 1; + + // Make sure x1 and y1 are not larger than x2 and y2, respectively + if (y1 >= y2) + { + verbose_printf(LOG_WARNING, ptUserData, "%s(): y1=%i must be less than y2=%i. Setting y1=0.\n", + __func__, y1, y2); + y1 = 0; + } + if (x1 >= x2) + { + verbose_printf(LOG_WARNING, ptUserData, "%s(): x1=%i must be less than x2=%i. Setting x1=0.\n", + __func__, x1, x2); + x1 = 0; + } + + // uint ny = y2 - y1 + 1; + // uint nx = x2 - x1 + 1; + + // First check if we're trying to set Stripe Mode + if ((bVertWin == true) && (bHorzWin == false)) + { + // Enable stripe mode + ASIC_STRIPEMode(ptUserData, true, true); + + // // TODO: For the meantime, we are restricted to powers of 2 + // if ((ny & (ny - 1)) != 0) + // { + // verbose_printf(LOG_WARNING, ptUserData, ""); + // } + } + else + { + // Turn vertical window on/off first, then horizontal + // Order matters, because ASIC_WinHorz will disable stripe + ASIC_WinVert(ptUserData, true, (uint)bVertWin); + ASIC_WinHorz(ptUserData, true, (uint)bHorzWin); + } + + // Set y1=0 and y2=ydet-1 if bVertWin=False + if (bVertWin == false) + { + y1 = 0; + y2 = ydet - 1; + } + // Set x1=0 and x2=ydet-1 if bHorzWin=False + if (bHorzWin == false) + { + x1 = 0; + x2 = xdet - 1; + } + + ASIC_setX1(ptUserData, x1); + ASIC_setX2(ptUserData, x2); + ASIC_setY1(ptUserData, y1); + ASIC_setY2(ptUserData, y2); + + if (ReconfigureASIC(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfigure failed at %s()\n", __func__); + return false; + } + + // TODO: + // Pixel Clock scheme checks (i.e., Normal vs Enhanced) are necessary if there are + // differences between full frame and subarray window clocking schemes. Normally + // these would be the same, but there is a bug in the Slow Mode v5.0+ microcode + // where Enhanced mode causes the columns to shift every other acquisition. + // The shifted column then persists after switching back to full frame. + // Something is wrong with the pixel timing code. + map &RegMap = ptUserData->RegMap; + if (RegMap.count("PixelClkScheme") > 0) + { + uint pixClk = (bHorzWin == false) ? ptUserData->ffPixelClkScheme : ptUserData->winPixelClkScheme; + SetASICParameter(ptUserData, "PixelClkScheme", pixClk); + if (ReconfigureASIC(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfigure failed at %s()\n", __func__); + } + } + + x1 = ASIC_getX1(ptUserData); + x2 = ASIC_getX2(ptUserData); + y1 = ASIC_getY1(ptUserData); + y2 = ASIC_getY2(ptUserData); + // Get final xpix and ypix + unsigned int xpix = exposure_xpix(ptUserData); + unsigned int ypix = exposure_ypix(ptUserData); + + verbose_printf(LOG_INFO, ptUserData, "Horizontal Window: %i\n", ASIC_WinHorz(ptUserData, false, 0)); + verbose_printf(LOG_INFO, ptUserData, " X1: %i X2: %i, xpix: %i\n", x1, x2, xpix); + verbose_printf(LOG_INFO, ptUserData, "Vertical Window: %i\n", ASIC_WinVert(ptUserData, false, 0)); + verbose_printf(LOG_INFO, ptUserData, " Y1: %i Y2: %i, ypix: %i\n", y1, y2, ypix); + verbose_printf(LOG_INFO, ptUserData, "STRIPE Mode: %i\n", (uint)ASIC_STRIPEMode(ptUserData, false, false)); + verbose_printf(LOG_INFO, ptUserData, "Frame time: %.3f ms\n", ptUserData->frametime_ms); + + // If not full frame, check if subarray values and bytes requested are valid + // TODO: This is temporary until MACIE data handling issue is resolved + if ((bVertWin == true) || (bHorzWin == true)) + { + // Number of bytes requested per ramp + unsigned long framesize = (unsigned long)xpix * ypix; + unsigned long nframes_ramp = (unsigned long)(ASIC_NReads(ptUserData, false, 0) * ASIC_NGroups(ptUserData, false, 0)); + unsigned long nbytes_ramp = 2 * nframes_ramp * framesize; + if (verify_subarray_size(ptUserData, xpix, ypix, nbytes_ramp) == false) + { + verbose_printf(LOG_WARNING, ptUserData, + "%s(): Possible problematic subarray size (nx=%i, ny=%i) for %li bytes in ramp\n", + __func__, xpix, ypix, nbytes_ramp); + // return false; + } + } + + return true; +} + +// Subarray mode might not exist in certain microcodes. +// If these parameters don't exist, then return detector limits. +// If not in window mode, then return detector limits. + +// Set/get STRIPE mode +bool ASIC_STRIPEMode(MACIE_Settings *ptUserData, bool bSet, bool bVal) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + map &RegMap = ptUserData->RegMap; + + // Check if we're turning Stripe Mode on/off + if (bSet == true) + { + // If not allowed, then print warning and explicitly set bVal=false + if ((ptUserData->bStripeModeAllowed == false) && (bVal == true)) + { + verbose_printf(LOG_WARNING, ptUserData, "Stripe Mode is not allowed for current microcode.\n"); + verbose_printf(LOG_WARNING, ptUserData, " Check ASIC Regs file: %s.\n", ptUserData->ASICRegs); + bVal = false; + } + ptUserData->bStripeMode = bVal; + + // Enable/disable horizontal/vertical windows if enabling STRIPE + if (bVal == true) + { + // Turn off Horizontal Window + if (RegMap.count("WinMode") > 0) + ASIC_Generic(ptUserData, "WinMode", true, 0); + if (RegMap.count("HorzWinMode") > 0) + ASIC_Generic(ptUserData, "HorzWinMode", true, 0); + + // Turn on Vertical Window + if (RegMap.count("VertWinMode") > 0) + ASIC_Generic(ptUserData, "VertWinMode", true, 1); + } + else if (ptUserData->bStripeModeAllowed) + { + // Turn off Vertical Window + if (RegMap.count("VertWinMode") > 0) + ASIC_Generic(ptUserData, "VertWinMode", true, 0); + // Turn off any burst Striping + if (RegMap.count("StripeReads1") > 0) + ASIC_Generic(ptUserData, "StripeReads1", true, 0); + if (RegMap.count("StripeReads2") > 0) + ASIC_Generic(ptUserData, "StripeReads2", true, 0); + if (RegMap.count("StripeSkips1") > 0) + ASIC_Generic(ptUserData, "StripeSkips1", true, 0); + if (RegMap.count("StripeSkips2") > 0) + ASIC_Generic(ptUserData, "StripeSkips2", true, 0); + } + } + else // Or simply get current state + { + // If not allowed, explicitly set bVal=false (no need for warning) + if (ptUserData->bStripeModeAllowed == false) + ptUserData->bStripeMode = false; + + bVal = ptUserData->bStripeMode; + } + + return bVal; +} +// Horizontal Window +unsigned int ASIC_WinHorz(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + map &RegMap = ptUserData->RegMap; + + // Return 0 if Window Mode not possible + string addr_name = "WinMode"; + if (RegMap.count(addr_name) == 0) + { + addr_name = "HorzWinMode"; + if (RegMap.count(addr_name) == 0) + return 0; + } + + // Disable STRIPE mode if we're enabling Horizontal Window + if ((bSet == true) && (val > 0)) + ASIC_STRIPEMode(ptUserData, true, false); + + val = ASIC_Generic(ptUserData, addr_name, bSet, val); + verbose_printf(LOG_DEBUG, ptUserData, "ASIC_WinHorz returns %i.\n", val); + return val; +} +// Vertical Window +unsigned int ASIC_WinVert(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + map &RegMap = ptUserData->RegMap; + + bool bVal = (val == 0) ? false : true; + // First check if we're en/disabling vertical window + if (bSet == true) + { + // Set STRIPE mode if Horizontal Window Mode is false + if ((ASIC_WinHorz(ptUserData, false, 0) == 0) && (ptUserData->bStripeModeAllowed)) + { + ASIC_STRIPEMode(ptUserData, bSet, bVal); + if (RegMap.count("VertWinMode") > 0) + val = ASIC_Generic(ptUserData, "VertWinMode", bSet, val); + else if ((RegMap.count("WinMode") == 0) && (bVal == false)) + { + ASIC_setY1(ptUserData, 0); + ASIC_setY2(ptUserData, ptUserData->uiDetectorHeight - 1); + } + } + else if (RegMap.count("VertWinMode") > 0) + { + val = ASIC_Generic(ptUserData, "VertWinMode", bSet, val); + } + else if (RegMap.count("WinMode") > 0) + { + val = ASIC_Generic(ptUserData, "WinMode", bSet, val); + verbose_printf(LOG_WARNING, ptUserData, "Setting WinMode=%i also controls Horizontal Window.\n", val); + } + else + { + val = 0; + } + } + else + { + if (ASIC_STRIPEMode(ptUserData, bSet, bVal) == true) + val = 1; + else if (RegMap.count("VertWinMode") > 0) + val = ASIC_Generic(ptUserData, "VertWinMode", bSet, val); + else if (RegMap.count("WinMode") > 0) + val = ASIC_Generic(ptUserData, "WinMode", bSet, val); + else + val = 0; + } + verbose_printf(LOG_DEBUG, ptUserData, "ASIC_WinVert returns %i.\n", val); + + return val; +} + +// Get subarray starting position along x-axis +// If Horizontal Window is disabled, return 0 +unsigned int ASIC_getX1(MACIE_Settings *ptUserData) +{ + map &RegMap = ptUserData->RegMap; + unsigned int val = 0; + + if (ASIC_WinHorz(ptUserData, 0, 0) == false) + val = 0; + else if (RegMap.count("X1") > 0) + val = ASIC_Generic(ptUserData, "X1", false, 0); + else if (RegMap.count("XStart") > 0) + val = ASIC_Generic(ptUserData, "XStart", false, 0); + + return val; +} +// Get subarray ending position along x-axis +// If Horizontal Window is disabled, return detector size +unsigned int ASIC_getX2(MACIE_Settings *ptUserData) +{ + map &RegMap = ptUserData->RegMap; + unsigned int xdet = ptUserData->uiDetectorWidth; + unsigned int val = xdet - 1; + + if (ASIC_WinHorz(ptUserData, 0, 0) == false) + val = xdet - 1; + else if (RegMap.count("X2") > 0) + val = ASIC_Generic(ptUserData, "X2", false, 0); + else if (RegMap.count("XSize") > 0) + val = ASIC_getX1(ptUserData) + ASIC_Generic(ptUserData, "XSize", false, 0); + + return val; +} +unsigned int ASIC_getY1(MACIE_Settings *ptUserData) +{ + map &RegMap = ptUserData->RegMap; + unsigned int val = 0; + + if (ASIC_WinVert(ptUserData, false, 0) == false) + val = 0; + else if (RegMap.count("Y1") > 0) + val = ASIC_Generic(ptUserData, "Y1", false, 0); + else if (RegMap.count("YStart") > 0) + val = ASIC_Generic(ptUserData, "YStart", false, 0); + + return val; +} +unsigned int ASIC_getY2(MACIE_Settings *ptUserData) +{ + map &RegMap = ptUserData->RegMap; + unsigned int ydet = ptUserData->uiDetectorHeight; + unsigned int val = ydet - 1; + + if (ASIC_WinVert(ptUserData, false, 0) == false) + val = ydet - 1; + else if (RegMap.count("Y2") > 0) + val = ASIC_Generic(ptUserData, "Y2", false, 0); + else if (RegMap.count("YSize") > 0) + val = ASIC_getY1(ptUserData) + ASIC_Generic(ptUserData, "YSize", false, 0) - 1; + + return val; +} + +// Set subarray positions +// These functions only set the reg values and performs bounds checking. +// Will NOT enable Horizontal Window if it is disabled; use ASIC_WinHorz +// for that functionality. +unsigned int ASIC_setX1(MACIE_Settings *ptUserData, unsigned int val) +{ + map &RegMap = ptUserData->RegMap; + unsigned int xdet = ptUserData->uiDetectorWidth; + + // Check if keys exist + string addr_name = "X1"; + if (RegMap.count(addr_name) == 0) + { + addr_name = "XStart"; + if (RegMap.count(addr_name) == 0) + { + verbose_printf(LOG_WARNING, ptUserData, "Neither X1 nor XStart are valid register names.\n"); + return 0; + } + } + + // Valid range? + if (val > xdet - 1) + { + verbose_printf(LOG_WARNING, ptUserData, "Value of %i is out of range. Valid values span 0 to %i.\n", + val, xdet - 1); + val = 0; + } + + verbose_printf(LOG_INFO, ptUserData, "Setting %s to %i.\n", addr_name.c_str(), val); + return ASIC_Generic(ptUserData, addr_name, true, val); +} +unsigned int ASIC_setX2(MACIE_Settings *ptUserData, unsigned int val) +{ + map &RegMap = ptUserData->RegMap; + unsigned int xdet = ptUserData->uiDetectorWidth; + + // Check if keys exist + string addr_name = "X2"; + if (RegMap.count(addr_name) == 0) + { + addr_name = "XSize"; + if (RegMap.count(addr_name) == 0) + { + verbose_printf(LOG_WARNING, ptUserData, "Neither X2 nor XSize are valid register names.\n"); + return xdet - 1; + } + } + + if (val > xdet - 1) + { + verbose_printf(LOG_WARNING, ptUserData, "Value of %i is out of range. Valid values span 0 to %i.\n", + val, xdet - 1); + val = xdet - 1; + } + + if (addr_name == "XSize") + val = val - ASIC_getX1(ptUserData) + 1; + + verbose_printf(LOG_INFO, ptUserData, "Setting %s to %i.\n", addr_name.c_str(), val); + return ASIC_Generic(ptUserData, addr_name, true, val); +} +unsigned int ASIC_setY1(MACIE_Settings *ptUserData, unsigned int val) +{ + map &RegMap = ptUserData->RegMap; + unsigned int ydet = ptUserData->uiDetectorHeight; + + // Check if keys exist + string addr_name = "Y1"; + if (RegMap.count(addr_name) == 0) + { + addr_name = "YStart"; + if (RegMap.count(addr_name) == 0) + { + verbose_printf(LOG_WARNING, ptUserData, "Neither Y1 nor YStart are valid register names.\n"); + return 0; + } + } + + if (val > ydet - 1) + { + verbose_printf(LOG_WARNING, ptUserData, "Value of %i is out of range. Valid values span 0 to %i.\n", + val, ydet - 1); + val = 0; + } + + // If vertical window is off, then set to 0 if "VertWinMode" and "WinMode" don't exist + if ((ASIC_WinVert(ptUserData, false, 0) == 0) && + (RegMap.count("VertWinMode") + RegMap.count("WinMode")) == 0) + { + val = 0; + } + verbose_printf(LOG_INFO, ptUserData, "Setting %s to %i.\n", addr_name.c_str(), val); + return ASIC_Generic(ptUserData, addr_name, true, val); +} +unsigned int ASIC_setY2(MACIE_Settings *ptUserData, unsigned int val) +{ + map &RegMap = ptUserData->RegMap; + unsigned int ydet = ptUserData->uiDetectorHeight; + + // Check if keys exist + string addr_name = "Y2"; + if (RegMap.count(addr_name) == 0) + { + addr_name = "YSize"; + if (RegMap.count(addr_name) == 0) + { + verbose_printf(LOG_WARNING, ptUserData, "Neither Y2 nor YSize are valid register names.\n"); + return 0; + } + } + + if (val > ydet - 1) + { + verbose_printf(LOG_WARNING, ptUserData, "Value of %i is out of range. Valid values span 0 to %i.\n", + val, ydet - 1); + val = ydet - 1; + } + + // If vertical window is off, then set Y2=2047 if "VertWinMode" and "WinMode" don't exist + if ((ASIC_WinVert(ptUserData, false, 0) == 0) && + (RegMap.count("VertWinMode") + RegMap.count("WinMode")) == 0) + { + val = ydet - 1; + } + + if (addr_name == "YSize") + val = val - ASIC_getY1(ptUserData) + 1; + + verbose_printf(LOG_INFO, ptUserData, "Setting %s to %i.\n", addr_name.c_str(), val); + return ASIC_Generic(ptUserData, addr_name, true, val); +} + +// Call this function to set burst mode to full frame for idling purposes (after acquisition) +void burst_stripe_set_ffidle(MACIE_Settings *ptUserData) +{ + + map &RegMap = ptUserData->RegMap; + unsigned int ydet = ptUserData->uiDetectorHeight; + unsigned int ypix = 0; + // If burst stripe mode is enabled, + if (ypix_burst_stripe(ptUserData, &ypix, true) == true) + { + if (RegMap.count("StripeReads1") > 0) + ASIC_Generic(ptUserData, "StripeReads1", true, 0); + if (RegMap.count("StripeReads2") > 0) + ASIC_Generic(ptUserData, "StripeReads2", true, 0); + if (RegMap.count("StripeSkips1") > 0) + ASIC_Generic(ptUserData, "StripeSkips1", true, 0); + if (RegMap.count("StripeSkips2") > 0) + ASIC_Generic(ptUserData, "StripeSkips2", true, 0); + if (RegMap.count("RowReads") > 0) + ASIC_Generic(ptUserData, "RowReads", true, ydet); + } +} + +// Returns true if running Burst Stripe Mode, otherwise false +bool ypix_burst_stripe(MACIE_Settings *ptUserData, unsigned int *ypix, bool bSet) +{ + map &RegMap = ptUserData->RegMap; + + unsigned int ydet = ptUserData->uiDetectorHeight; + unsigned int y1 = ASIC_getY1(ptUserData); + unsigned int y2 = ASIC_getY2(ptUserData); + unsigned int ny = y2 - y1 + 1; // Number of requested rows + + // Set all to 0 if Stripe Mode is disabled or burst striping is not existent + // or y1 and y2 cover the entire active region + if ((ASIC_STRIPEMode(ptUserData, false, 0) == 0) || (RegMap.count("StripeReads1") == 0) || ((y1 < 4) && (y2 > ydet - 5))) + { + // Turn off any burst Striping + if (bSet) + { + if (RegMap.count("StripeReads1") > 0) + ASIC_Generic(ptUserData, "StripeReads1", true, 0); + if (RegMap.count("StripeReads2") > 0) + ASIC_Generic(ptUserData, "StripeReads2", true, 0); + if (RegMap.count("StripeSkips1") > 0) + ASIC_Generic(ptUserData, "StripeSkips1", true, 0); + if (RegMap.count("StripeSkips2") > 0) + ASIC_Generic(ptUserData, "StripeSkips2", true, 0); + if (RegMap.count("RowReads") > 0) + ASIC_Generic(ptUserData, "RowReads", true, ydet); + } + + *ypix = ny; + return false; + } + + unsigned int yrows = 0; + // If Stripe Mode is enabled and Burst Striping exists, update registers based on Y1 and Y2 + // We also want to always include the top/bottom reference rows + if (y1 < 4) // Lower reference pixels included in active block + { + // yrows = ny + y1 + 4; // Number of requested rows plus bottom plus top + yrows = ny; + if (bSet) + { + ASIC_Generic(ptUserData, "StripeReads1", true, yrows - 4); + ASIC_Generic(ptUserData, "StripeSkips1", true, ydet - yrows); + ASIC_Generic(ptUserData, "StripeReads2", true, 4); + ASIC_Generic(ptUserData, "StripeSkips2", true, 0); + ASIC_Generic(ptUserData, "RowReads", true, yrows); + } + } + else if (y2 > ydet - 5) // Upper reference pixels included in active block + { + // yrows = 4 + (ydet - y1); // Number of requested rows plus bottom plus top + yrows = ny; + if (bSet) + { + ASIC_Generic(ptUserData, "StripeReads1", true, 4); + ASIC_Generic(ptUserData, "StripeSkips1", true, y1); + ASIC_Generic(ptUserData, "StripeReads2", true, ydet - y1 - 4); + ASIC_Generic(ptUserData, "StripeSkips2", true, 0); + ASIC_Generic(ptUserData, "RowReads", true, yrows); + } + } + else // No reference pixels included in requested block + { + // yrows = ny + 8; + yrows = ny; + if (bSet) + { + ASIC_Generic(ptUserData, "StripeReads1", true, 4); + ASIC_Generic(ptUserData, "StripeSkips1", true, y1); + ASIC_Generic(ptUserData, "StripeReads2", true, ny - 8); + ASIC_Generic(ptUserData, "StripeSkips2", true, ydet - y2 - 1); + ASIC_Generic(ptUserData, "RowReads", true, yrows); + } + } + + *ypix = yrows; + return true; +} + +unsigned int exposure_xpix(MACIE_Settings *ptUserData) +{ + return ASIC_getX2(ptUserData) - ASIC_getX1(ptUserData) + 1; +} +unsigned int exposure_ypix(MACIE_Settings *ptUserData) +{ + unsigned int ypix = 0; + // Returns proper number BurstStripe is off or non-existent (Fast Mode) + ypix_burst_stripe(ptUserData, &ypix, false); + return ypix; +} + +// Returns the frame time in terms of number of pixel times. +unsigned int exposure_frametime_pix(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Update PixPerRow & RowsPerFrame for offline testing mode + if (ptUserData->offline_develop == true) + { + LOG_LEVEL log_prev = get_verbose(ptUserData); + set_verbose(ptUserData, LOG_WARNING); + unsigned int nout = ASIC_NumOutputs(ptUserData); + unsigned int xtra_pix = ASIC_Generic(ptUserData, "ExtraPixels", false, 0); + unsigned int xtra_lines = ASIC_Generic(ptUserData, "ExtraLines", false, 0); + unsigned int ppr = exposure_xpix(ptUserData) / nout + xtra_pix; + unsigned int rpf = exposure_ypix(ptUserData) + xtra_lines; + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + SetASICParameter(ptUserData, "PixPerRow", ppr + 8); + else + SetASICParameter(ptUserData, "PixPerRow", ppr); + SetASICParameter(ptUserData, "RowsPerFrame", rpf + 1); + set_verbose(ptUserData, log_prev); + } + + unsigned int PixPerRow = 0; + unsigned int RowsPerFrame = 0; + unsigned int PixPerFrame = 0; + + // Get number of Pixels per Row + if (GetASICParameter(ptUserData, "PixPerRow", &PixPerRow) == false) + return 0; + // Get number of Rows per Frame + if (GetASICParameter(ptUserData, "RowsPerFrame", &RowsPerFrame) == false) + return 0; + + PixPerFrame = PixPerRow * RowsPerFrame; + + return PixPerFrame; +} + +// Time in msec to complete a frame +double exposure_frametime_ms(MACIE_Settings *ptUserData) +{ + double npix = (double)exposure_frametime_pix(ptUserData); + + // If in burst stripe mode, add in extra overhead for skipping rows + double xtra_time = 0.0; + unsigned int ypix = 0; + unsigned int ydet = ptUserData->uiDetectorHeight; + if (ypix_burst_stripe(ptUserData, &ypix, false) == true) + { + // 1.2 usec per skipped row at 100kHz + // Should scale with pixel rate + xtra_time = 0.0012 * (100. / double(ptUserData->pixelRate)) * (ydet - ypix); + } + + // When in kHz, 1/f is msec + return npix / ptUserData->pixelRate + xtra_time; +} + +// Time in msec to complete a group +double exposure_grouptime_ms(MACIE_Settings *ptUserData) +{ + int nf_group = ASIC_NReads(ptUserData, false, 0) + ASIC_NDrops(ptUserData, false, 0); + + return nf_group * ptUserData->frametime_ms; +} + +// Time in msec to complete a ramp (including resets) +double exposure_ramptime_ms(MACIE_Settings *ptUserData) +{ + int exp_nframe = (int)exposure_nframes(ptUserData, true); + int nramps = (int)ASIC_NRamps(ptUserData, false, 0); + + return ptUserData->frametime_ms * (exp_nframe / nramps); +} + +// On-sky integration (photon collection) time for a ramp +double exposure_inttime_ms(MACIE_Settings *ptUserData) +{ + int nresets = (int)ASIC_NResets(ptUserData, false, 0); + return ptUserData->ramptime_ms - nresets * ptUserData->frametime_ms; +} + +double exposure_efficiency(MACIE_Settings *ptUserData) +{ + + unsigned int ui_ngroups = ASIC_NGroups(ptUserData, false, 0); + unsigned int ui_nreads = ASIC_NReads(ptUserData, false, 0); + unsigned int ui_nresets = ASIC_NResets(ptUserData, false, 0); + + if ((ui_ngroups == 1) && (ui_nreads == 1)) + { + return 1.0 / double(1 + ui_nresets); + } + else + { + double itime = exposure_inttime_ms(ptUserData) - ptUserData->frametime_ms; + return itime / ptUserData->ramptime_ms; + } +} + +// Return number of outputs for given detector configuration (science frames) +unsigned int ASIC_NumOutputs(MACIE_Settings *ptUserData) +{ + // Default to return nout=1 if subarray, else NumOutputs reg value + return ASIC_NumOutputs(ptUserData, false); +} +// Return number of configured outputs for given detector configuration +// bFullFrame is used for determing full frame NOuts in case window mode is enabled +unsigned int ASIC_NumOutputs(MACIE_Settings *ptUserData, bool bFullFrame) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + unsigned int nout = 0; + // Slow Mode values are stored in "NumOutputs" + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + // If Horizontal Window is enabled, only 1 output + if ((ASIC_WinHorz(ptUserData, false, 0) == 1) && (bFullFrame == false)) + nout = 1; + else + GetASICParameter(ptUserData, "NumOutputs", &nout); + } + // Fast Mode outputs are either 16 (H1RG) or 32 (H2/4RG) + else + { + nout = ptUserData->DetectorType == CAMERA_TYPE_H1RG ? 16 : 32; + } + + return nout; +} +// Overloaded version of above for setting (and getting) NumOutputs +unsigned int ASIC_NumOutputs(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + + if (bSet == false) + { + val = ASIC_NumOutputs(ptUserData); + verbose_printf(LOG_INFO, ptUserData, "NumOutputs = %i\n", val); + return val; + } + else + { + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Slow Mode values are stored in "NumOutputs" keyword + if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + unsigned int uiDetType = 0; + GetASICParameter(ptUserData, "DetectorType", &uiDetType); + + // If Horizontal Window is enabled, only 1 output + if (ASIC_WinHorz(ptUserData, false, 0) == 1) + { + verbose_printf(LOG_INFO, ptUserData, "Horizontal Window mode enabled. NumOutputs=1\n"); + val = 1; + } + else if (uiDetType == 1) + { + // Values can either be 1, 2, or 16 + if ((val != 1) && (val != 2) && (val != 16)) + { + val = 2; + verbose_printf(LOG_ERROR, ptUserData, + "DetType=%i. NumOutputs can either be 1, 2, or 16. Setting to default of %i\n", + uiDetType, val); + } + } + else if (uiDetType == 2) + { + // Values can either be 1, 4, or 32 + if ((val != 1) && (val != 4) && (val != 32)) + { + // GetASICParameter(ptUserData, "NumOutputs", &val); + val = 4; + verbose_printf(LOG_ERROR, ptUserData, + "DetType=%i. NumOutputs can either be 1, 4, or 32. Setting to default of%i\n", + uiDetType, val); + } + } + else if (uiDetType == 4) + { + // Values can either be 1, 4, 16, or 32 + if ((val != 1) && (val != 4) && (val != 16) && (val != 32)) + { + val = 2; + verbose_printf(LOG_ERROR, ptUserData, + "DetType=%i. NumOutputs can either be 1, 4, 16, or 32. Setting to default of%i\n", + uiDetType, val); + } + } + SetASICParameter(ptUserData, "NumOutputs", val); + } + // Fast Mode outputs are either 16 (H1RG) or 32 (H2/4RG) + else + { + val = ASIC_NumOutputs(ptUserData); + // GetASICParameter(ptUserData, "NumOutputs", &val); + verbose_printf(LOG_INFO, ptUserData, "NumOutputs is always fixed for Fast Mode. Staying at %i\n", val); + } + } + return val; +} + +//////////////////////////////////////////////////////////////////////////////// +// Preamp Gain (dB) +// Cap Comp (fF) +// Filter Pole (kHz) +unsigned int ASIC_Gain(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Check if addr_name key exists + map &RegMap = ptUserData->RegMap; + string addr_name = "Gain"; + + if (RegMap.count(addr_name) == 0) + { + unsigned int addr = 0x6101; + struct regInfo *reg = new regInfo; + reg->addr = addr; + reg->bit0 = 0; + reg->bit1 = 3; + reg->value = val; + + // If Gain keyword doesn't exist, then there is no shadow register + // so we need to get/set Gain regs (6101, 6105, etc.) directly + unsigned int nout = ASIC_NumOutputs(ptUserData, true); + if (bSet == true) + { + for (unsigned int i = 0; i < nout; ++i) + { + reg->addr = addr + 4 * i; + // printf("h%04x, %i-%i, %i\n", reg->addr, reg->bit0, reg->bit1, reg->value); + WriteASICBits(ptUserData, reg); + } + } + ReadASICBits(ptUserData, reg, &val); + } + else + { + val = ASIC_Generic(ptUserData, addr_name, bSet, val); + } + + int gain_db[16] = {-3, 0, 3, 6, 6, 9, 9, 12, 12, 15, 15, 18, 18, 21, 24, 27}; + int val_db = gain_db[val]; + + verbose_printf(LOG_INFO, ptUserData, "Gain = %i (%i db)\n", val, val_db); + return val; +} + +// Recommended values in Table 3-10 of SIDECAR Manual +// Val should be 0 to 63. +unsigned int ASIC_CapComp(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Check if addr_name key exists + map &RegMap = ptUserData->RegMap; + string addr_name = "CapComp"; + + // unsigned int nbits = 0; + // If CapComp doesn't exist as a shadow register, + // then we need to set register directly + if (RegMap.count(addr_name) == 0) + { + unsigned int addr = 0x6101; + struct regInfo *reg = new regInfo; + reg->addr = addr; + reg->bit0 = 4; + reg->bit1 = 9; + reg->value = val; + + // If keyword doesn't exist, then there is no shadow register + // so we need to get/set regs (6101, 6105, etc.) directly + unsigned int nout = ASIC_NumOutputs(ptUserData, true); + if (bSet == true) + { + for (unsigned int i = 0; i < nout; ++i) + { + reg->addr = addr + 4 * i; + WriteASICBits(ptUserData, reg); + } + } + ReadASICBits(ptUserData, reg, &val); + // nbits = reg->bit1 - reg->bit0 + 1; + } + else + { + val = ASIC_Generic(ptUserData, addr_name, bSet, val); + // nbits = RegMap[addr_name].bit1 - RegMap[addr_name].bit0 + 1; + } + + unsigned int val_fF = 53 * val; + // for (unsigned int i = 0; i < nbits; ++i) + // val_fF += ((val >> i) & 1) * 53 * uint(pow(2, i)); + verbose_printf(LOG_INFO, ptUserData, "CapComp = %i (%i fF)\n", val, val_fF); + + return val; +} + +// Set filter pole to 5-10 times the pixel clock rate +unsigned int ASIC_FiltPole(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Check if addr_name key exists + map &RegMap = ptUserData->RegMap; + string addr_name = "FiltPole"; + + // If keyword doesn't exist, then there is no shadow register + // so we need to get/set regs (6102, 6106, etc.) directly + if (RegMap.count(addr_name) == 0) + { + unsigned int addr = 0x6102; + struct regInfo *reg = new regInfo; + reg->addr = addr; + reg->bit0 = 12; + reg->bit1 = 15; + reg->value = val; + + unsigned int nout = ASIC_NumOutputs(ptUserData, true); + if (bSet == true) + { + for (unsigned int i = 0; i < nout; ++i) + { + reg->addr = addr + 4 * i; + WriteASICBits(ptUserData, reg); + } + } + ReadASICBits(ptUserData, reg, &val); + } + else + { + val = ASIC_Generic(ptUserData, addr_name, bSet, val); + } + + int khz_fast[16] = {265392, 15165, 7582, 5055, 3791, 2527, 1895, + 1263, 947, 669, 465, 334, 232, 164, 116, 82}; + int khz_slow[16] = {132696, 7582, 3791, 2527, 1895, 1263, 947, 631, + 473, 392, 272, 196, 136, 109, 86, 65}; + int val_kHz = ptUserData->DetectorMode == CAMERA_MODE_SLOW ? khz_slow[val] : khz_fast[val]; + + verbose_printf(LOG_INFO, ptUserData, "FiltPole = %i (%i kHz)\n", val, val_kHz); + return val; +} + +// Set ASIC inputs (ie., single-ended, differential, grounded) directly using the override reg. +// val should be a 16-bit HEX value like 0xaaaa that eventually propogates to h6100, etc. +// There are three possible implementations depending on detector and mode. +// 1. If RefInput does not exist, then we're in Fast Mode and need to directly set h6100, etc. +// 2. Otherwise, we're using he HxRG ucode, so set RefOverride=1 and set h5100=val. +unsigned int ASIC_Inputs(MACIE_Settings *ptUserData, bool bSet, unsigned int val) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Check if addr_name key exists + map &RegMap = ptUserData->RegMap; + if (RegMap.count("RefInput") == 0) + { + // Fast Mode with 16/32 channels + unsigned int addr = 0x6100; + struct regInfo *reg = new regInfo; + reg->addr = addr; + reg->bit0 = 0; + reg->bit1 = 15; + reg->value = val; + + unsigned int nout = ASIC_NumOutputs(ptUserData, true); + if (bSet == true) + { + for (unsigned int i = 0; i < nout; ++i) + { + reg->addr = addr + 4 * i; + WriteASICBits(ptUserData, reg); + } + } + ReadASICBits(ptUserData, reg, &val); + } + else if (RegMap.count("RefOverride") == 0) + { + // JWST Mode (ie., no RefOverride) + // If bSet is false, then this will output the value of h433a or h433b + // depending on the current RefInput setting. + // If bSet is true, then we set RefInput=1 to tell ucode to grab + // setting from h433b, then we modify h433b + if (ASIC_Generic(ptUserData, "RefInput", bSet, 1) == 0) + val = ASIC_Generic(ptUserData, "SingValue", bSet, val); + else + val = ASIC_Generic(ptUserData, "DiffValue", bSet, val); + } + else + { + unsigned int sing_val = ASIC_Generic(ptUserData, "NumChAvg", false, 0) == 1 ? 0x4a0a : 0x4aca; + unsigned int diff_val = ASIC_Generic(ptUserData, "NumChAvg", false, 0) == 1 ? 0x4502 : 0x45c2; + + // HxRG microcode + // If bSet is true, then set RefOverride, set OverrideVals, and return OverrideVals in h5100 + // If bSet is false, but RefOverride==1, then return OverrideVals in h5100 + // Otherwise, return single or differential values (bSet should then be false). + if (ASIC_Generic(ptUserData, "RefOverride", bSet, 1) == 1) + val = ASIC_Generic(ptUserData, "OverrideVals", bSet, val); + else + val = ASIC_Generic(ptUserData, "RefInput", false, 0) == 0 ? sing_val : diff_val; + } + + verbose_printf(LOG_INFO, ptUserData, "Ref Inputs = 0x%04x\n", val); + return val; +} + +// DAC Setting consists of bits 0-10 +// Bit 0-9 give the Voltage +// Bit 10 sets the low/high range (0-2V or 1.3-3.3V) +float ConvertDACToV(unsigned int dac_setting) +{ + // unsigned int nbits = reg->bit1 - reg->bit0 + 1; + // *val >>= reg->bit0; // Shift val bits to the right + // *val &= (1 << nbits) - 1; // Bitwise AND with a bitmask + + // AND with bitmask to get voltage + unsigned int bitmask = (1 << 10) - 1; + unsigned int reg_voltage = dac_setting & bitmask; + // Shift and AND to get range + unsigned int reg_range = (dac_setting >> 10) & 1; + + return (float)2 * reg_voltage / 1023 + 1.3 * reg_range; +} + +unsigned int ConvertVToDAC(float volts) +{ + unsigned int value = 0; + if (volts < 2) + value = (uint)ceil(1023 * (volts / 2.0)); + else + { + value = (uint)ceil(1023 * ((volts - 1.3) / 2.0)); + value |= (1 << 10); + } + + return value; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief readASICconfig Given a start address and number of registers, +/// decdode the register configurations to voltages, CapComp, DACBuff, current, etc. +/// All data is printed to the terminal output. +/// \param ptUserData The user-set structure containing hardware parameters +/// \param addr Start register address +/// \param nreg Number of registers to decode +bool readASICconfig(MACIE_Settings *ptUserData, unsigned short addr, int nreg) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + uint val_arr[nreg] = {}; + if (ReadASICBlock(ptUserData, addr, nreg, &val_arr[0]) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ReadASICBlock failed in %s\n", __func__); + return false; + } + + uint uiDACrange, uiDACvolt, uiDACPwrDwn, uiCapComp, uiDACbuff; + float flDACvolt = 0; + float flDACbuff = 0; + + uint uiCurrFine, uiCurrCoarse, uiISinkEn, uiCurrPwrDwn; + float flCurr_uA = 0; + + uint uiAddr, uiVal; + for (int i = 0; i < nreg; i++) + { + uiAddr = (uint)addr + i; + uiVal = val_arr[i]; + // Voltage Config addresses + if ((uiAddr % 2 == 0) && (uiAddr >= 0x6000) && (uiAddr <= 0x6037)) + { + // Check if powered + uiDACPwrDwn = (uiVal >> 11) & 1; + + // Get Capacitor Compensation + uiCapComp = (uiVal >> 12) & 3; + + // Calculate DAC Voltage + uiDACrange = (uiVal >> 10) & 1; + uiDACvolt = uiVal & ((1 << 10) - 1); + flDACvolt = (float)2 * uiDACvolt / 1023 + 1.3 * uiDACrange; + + // Calculate DAC buffer stored in next register + regInfo regDACbuff = gen_regInfo((ushort)uiAddr + 1, 10, 15, 0); + ReadASICBits(ptUserData, ®DACbuff, &uiDACbuff); + flDACbuff = 60 * pow(pow(10, -1.421 / 20), 63 - uiDACbuff); + + printf(" 0x%04x = 0x%04x (%5.3f V; DACPwr %s); CapComp = %i; DACBuff = %6.3f mA\n", + uiAddr, uiVal, flDACvolt, uiDACPwrDwn == 1 ? "OFF" : "ON", uiCapComp, flDACbuff); + } + // Current Config addresses + else if ((uiAddr % 2 == 1) && (uiAddr >= 0x6000) && (uiAddr <= 0x6037)) + { + // Get fine and coarse current settings + uiCurrFine = uiVal & ((1 << 8) - 1); + uiCurrCoarse = (uiVal >> 8) & 3; + + flCurr_uA = (float)0.1 * (uiCurrFine + 1) * pow(10, uiCurrCoarse); + + // Get current source PwrDwn bit and ISinkEn bit from previous address + regInfo regPrev = gen_regInfo((ushort)uiAddr - 1, 15, 15, 0); + ReadASICBits(ptUserData, ®Prev, &uiCurrPwrDwn); + regPrev.bit0 = 14; + regPrev.bit1 = 14; + ReadASICBits(ptUserData, ®Prev, &uiISinkEn); + + printf(" 0x%04x = 0x%04x (%7.1f uA; CurrPwr %s); ISinkEn: %s\n", + uiAddr, uiVal, flCurr_uA, uiCurrPwrDwn == 1 ? "OFF" : "ON", uiISinkEn == 1 ? "Sink" : "Source"); + } + // Internal Bias Currents 8-16 + else if ((uiAddr >= 0x6038) && (uiAddr <= 0x603b)) + { + regInfo regVals = gen_regInfo((ushort)uiAddr, 0, 0, 0); + + uint uiVal1 = uiVal & ((1 << 8) - 1); + uint uiVal2 = uiVal >> 8; + + //////////////////////////////// + // First current (bits 0-7) + uiCurrFine = uiVal1; + + // Coarse selection + regVals.addr = 0x603c; + regVals.bit0 = 4 * (uiAddr - 0x6038); + regVals.bit1 = regVals.bit0 + 1; + ReadASICBits(ptUserData, ®Vals, &uiCurrCoarse); + + flCurr_uA = (float)0.1 * (uiCurrFine + 1) * pow(10, uiCurrCoarse); + + // Get current source PwrDwn bit and ISinkEn bit from previous address + regVals.addr = 0x603d; + regVals.bit0 = 2 * (uiAddr - 0x6038); + regVals.bit1 = regVals.bit0; + ReadASICBits(ptUserData, ®Vals, &uiISinkEn); + regVals.bit0 += 8; // Shift to top 8 bits + regVals.bit1 = regVals.bit0; + ReadASICBits(ptUserData, ®Vals, &uiCurrPwrDwn); + + printf(" 0x%04x<7-0> = 0x%04x (%7.1f uA; CurrPwr %s); ISinkEn: %s\n", + uiAddr, uiVal1, flCurr_uA, uiCurrPwrDwn == 1 ? "OFF" : "ON", uiISinkEn == 1 ? "Sink" : "Source"); + + //////////////////////////////// + // Second current (bits 8-15) + uiCurrFine = uiVal2; + + // Coarse selection + regVals.addr = 0x603c; + regVals.bit0 = 4 * (uiAddr - 0x6038) + 2; + regVals.bit1 = regVals.bit0 + 1; + ReadASICBits(ptUserData, ®Vals, &uiCurrCoarse); + + flCurr_uA = (float)0.1 * (uiCurrFine + 1) * pow(10, uiCurrCoarse); + + // Get current source PwrDwn bit and ISinkEn bit from previous address + regVals.addr = 0x603d; + regVals.bit0 = 2 * (uiAddr - 0x6038) + 1; + regVals.bit1 = regVals.bit0; + ReadASICBits(ptUserData, ®Vals, &uiISinkEn); + regVals.bit0 += 8; + regVals.bit1 = regVals.bit0; + ReadASICBits(ptUserData, ®Vals, &uiCurrPwrDwn); + + printf(" 0x%04x<15-8> = 0x%04x (%7.1f uA; CurrPwr %s); ISinkEn: %s\n", + uiAddr, uiVal2, flCurr_uA, uiCurrPwrDwn == 1 ? "OFF" : "ON", uiISinkEn == 1 ? "Sink" : "Source"); + } + else + { + printf(" Cannot calculate values for register h%04x\n", uiAddr); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief ASIC_VReadBack Perform voltage/current telemetry readack on the ASIC. +/// Refer to Table 3.3 in the ASIC Manual for details. For instance, to readback +/// register h6000, set mux_index to 0. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \param mux_index Which register to readback. Values [0-63] +/// \param val_h7000 Output for h7000 register (current) +/// \param val_h7400 Output for h7400 register (voltage) +bool ASIC_VReadBack(MACIE_Settings *ptUserData, unsigned int mux_index, + unsigned int *val_h7000, unsigned int *val_h7400) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Update h6192 to reroute voltage, current, and digital signals to + // preamps for digitization. + struct regInfo *reg = new regInfo; + *reg = gen_regInfo(0x6192, 10, 15, mux_index); + unsigned int val_orig = 0; + + // Store current values in val_origi + if (ReadASICReg(ptUserData, reg->addr, &val_orig) == false) + return false; + + // Write new values + if (WriteASICBits(ptUserData, reg) == false) + return false; + + // Delay 100 msec + delay(100); + + // Return to original value after reading + reg->value = val_orig; + + if (ReadASICReg(ptUserData, 0x7000, val_h7000) == false) + { + WriteASICBits(ptUserData, reg); + return false; + } + if (ReadASICReg(ptUserData, 0x7400, val_h7400) == false) + { + WriteASICBits(ptUserData, reg); + return false; + } + + WriteASICBits(ptUserData, reg); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief verbose_printf Prints out messages based on a 'level' to +/// stderr. The level requested is specified by calling 'isdec_set_verbose'. +/// If the level requested here is greater than or equal to the level set by +/// the user, the message will be printed. +/// \param level The verbosity level this message has. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \param format A string using a printf-like format to print out the string. +void verbose_printf(LOG_LEVEL level, MACIE_Settings *ptUserData, const char *format, ...) +{ + if (get_verbose(ptUserData) <= level) + { + if (level != LOG_NONE) + fprintf(stderr, "[%5s] ", convert_log_type_str(level)); + + va_list arg; + va_start(arg, format); + vfprintf(stderr, format, arg); + va_end(arg); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief set_verbose Sets the verbosity requested by the user. This +/// value is stored in the MACIE_Settings struct. If the struct is NULL, +/// nothing is changed. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \param level The level of verbosity requested by the user. +// LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_NONE + +void set_verbose(MACIE_Settings *ptUserData, LOG_LEVEL level) +{ + // Is our structure ok? + if (SettingsCheckNULL(ptUserData) == true) + ptUserData->verbosity = level; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief get_verbose Gets the verbosity set by the user and stored in +/// the MACIE_Settings struct. If the struct is NULL, 0 is returned by default. +/// \param ptUserData The user-set structure containing all the parameters +/// for the hardware. +/// \return The verbosity level set, or LOG_NONE if ptUserData is invalid. +LOG_LEVEL get_verbose(MACIE_Settings *ptUserData) +{ + // Is our structure ok? + if (SettingsCheckNULL(ptUserData) == true) + return ptUserData->verbosity; + else + return LOG_NONE; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +string strip_white(const string &input) +{ + size_t b = input.find_first_not_of(' '); + if (b == string::npos) + b = 0; + return input.substr(b, input.find_last_not_of(' ') + 1 - b); +} + +string strip_comments(const string &input, const string &delimiters) +{ + return strip_white(input.substr(0, input.find_first_of(delimiters))); +} + +// Quick function to create register info in a RegMap +regInfo gen_regInfo(unsigned short addr, unsigned short bit0, unsigned short bit1, + unsigned int value) +{ + regInfo reg = {addr, bit0, bit1, value}; + return reg; +} + +// Given a Detector type and Readout mode, return a mapped dictionary +// of the register addresses, bits, and values. +// This reads the *.cfg files that correspond to the .mcd microcode files. +// For this initializaton phase, all reg values are set to 0. +bool initRegMap(MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Create variable that points to ptUserData->RegMap + map &RegMap = ptUserData->RegMap; + RegMap.clear(); + + std::ifstream regs_file(ptUserData->ASICRegs); + if (regs_file.is_open()) + { + unsigned int linecount = 0; + const string whitespace(" \t\n\r"); + const string delimiters("#/;"); + string linebuffer; + + string addr_name, addr_str; + unsigned short addr; + unsigned short bit0; + unsigned short bit1; + + // vector results; + + while (getline(regs_file, linebuffer)) + { + size_t first_nonws = linebuffer.find_first_not_of(whitespace); + + // skip empty lines + if (first_nonws == string::npos) + { + continue; + } + // skip comment lines + if ((linebuffer.find("/") == first_nonws) || + (linebuffer.find("#") == first_nonws) || + (linebuffer.find(";") == first_nonws)) + { + continue; + } + + // Remove comments from end of line + linebuffer = strip_comments(linebuffer, delimiters); + + // Make string stream + std::istringstream iss(linebuffer); + + // Stream to reg name, address, bit0, and bit1 + iss >> addr_name >> addr_str >> bit0 >> bit1; + // Convert HEX string to unsigned short + addr = strtoul(addr_str.c_str(), 0, 16); + + // if (addr_name == "StripeAllowed") // Special case + if (addr_name.compare("StripeAllowed") == 0) + ptUserData->bStripeModeAllowed = bit1 == 0 ? false : true; + else + RegMap[addr_name] = gen_regInfo(addr, bit0, bit1, 0); + + ++linecount; + } + } + else + { + verbose_printf(LOG_ERROR, ptUserData, "Could not open file %s\n", ptUserData->ASICRegs); + return false; + } + + // map RegMap = ptUserData->RegMap; + map::iterator it; + regInfo *reg; + + for (it = RegMap.begin(); it != RegMap.end(); it++) + { + reg = &it->second; + verbose_printf(LOG_DEBUG, ptUserData, "%s : h%04x <%i:%i> = %i\n", + it->first.c_str(), reg->addr, reg->bit1, reg->bit0, reg->value); + } + return true; +} + +const char *convert_camera_type_str(CAMERA_TYPE type) +{ + if (type == CAMERA_TYPE_H1RG) + return "H1RG"; + else if (type == CAMERA_TYPE_H2RG) + return "H2RG"; + else if (type == CAMERA_TYPE_H4RG) + return "H4RG"; + + return "UNKNOWN"; +} + +CAMERA_TYPE convert_camera_type(const char *pcDetectorType) +{ + if (strcmp(pcDetectorType, "H1RG") == 0) + return CAMERA_TYPE_H1RG; + else if (strcmp(pcDetectorType, "H2RG") == 0) + return CAMERA_TYPE_H2RG; + else if (strcmp(pcDetectorType, "H4RG") == 0) + return CAMERA_TYPE_H4RG; + + return CAMERA_TYPE_H2RG; +} + +const char *convert_camera_mode_str(CAMERA_MODE mode) +{ + if (mode == CAMERA_MODE_SLOW) + return "SLOW"; + else if (mode == CAMERA_MODE_FAST) + return "FAST"; + + return "UNKNOWN"; +} + +CAMERA_MODE convert_camera_mode(const char *pcDetectorMode) +{ + if (strcmp(pcDetectorMode, "SLOW") == 0) + return CAMERA_MODE_SLOW; + else if (strcmp(pcDetectorMode, "FAST") == 0) + return CAMERA_MODE_FAST; + + return CAMERA_MODE_SLOW; +} + +const char *convert_log_type_str(LOG_LEVEL level) +{ + if (level == LOG_DEBUG) + return "DEBUG"; + else if (level == LOG_INFO) + return "INFO"; + else if (level == LOG_WARNING) + return "WARN"; + else if (level == LOG_ERROR) + return "ERROR"; + else if (level == LOG_NONE) + return "NONE"; + + return "UNKNOWN"; +} + +LOG_LEVEL convert_log_type(const char *pcLevel) +{ + if (strcmp(pcLevel, "DEBUG") == 0) + return LOG_DEBUG; + else if (strcmp(pcLevel, "INFO") == 0) + return LOG_INFO; + else if (strcmp(pcLevel, "WARN") == 0) + return LOG_WARNING; + else if (strcmp(pcLevel, "ERROR") == 0) + return LOG_ERROR; + else if (strcmp(pcLevel, "NONE") == 0) + return LOG_NONE; + + return LOG_NONE; +} + +//////////////////////////////////////////////////////////////////////////////// + +// Given a Detector type and Readout mode, return a mapped dictionary +// of the register addresses, bits, and values. +// This reads the *.cfg files that correspond to the .mcd microcode files. +// For this initializaton phase, all reg values are set to 0. +// Only used for testing when no hardware is connected. +bool initASICRegs_testing(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + // Create variable that points to ptUserData->RegMap + map &RegMap = ptUserData->RegAllASIC; + RegMap.clear(); + + std::ifstream regs_file(ptUserData->ASICFile); + if (regs_file.is_open()) + { + unsigned int linecount = 0; + const string whitespace(" \t\n\r"); + const string delimiters("#/;"); + string linebuffer; + + string addr_str, value_str; + unsigned short addr, value; + + // vector results; + + while (getline(regs_file, linebuffer)) + { + size_t first_nonws = linebuffer.find_first_not_of(whitespace); + + // skip empty lines + if (first_nonws == string::npos) + { + continue; + } + // skip comment lines + if ((linebuffer.find("/") == first_nonws) || + (linebuffer.find("#") == first_nonws) || + (linebuffer.find(";") == first_nonws)) + { + continue; + } + + // Remove comments from end of line + linebuffer = strip_comments(linebuffer, delimiters); + + // Make string stream + std::istringstream iss(linebuffer); + + // Stream to reg name, address, bit0, and bit1 + // iss >> addr_name >> addr_str >> bit0 >> bit1; + iss >> addr_str >> value_str; + addr_str.insert(0, "0x"); + value_str.insert(0, "0x"); + + if ((addr_str.length() == 6) && (value_str.length() == 6)) + { + // Convert HEX strings to unsigned short + addr = strtoul(addr_str.c_str(), 0, 16); + value = strtoul(value_str.c_str(), 0, 16); + RegMap[addr_str] = gen_regInfo(addr, 0, 15, value); + } + + ++linecount; + } + } + else + { + verbose_printf(LOG_ERROR, ptUserData, "Could not open file %s\n", ptUserData->ASICFile); + return false; + } + + // map RegMap = ptUserData->RegMap; + map::iterator it; + regInfo *reg; + + for (it = RegMap.begin(); it != RegMap.end(); it++) + { + reg = &it->second; + verbose_printf(LOG_DEBUG, ptUserData, "%s : h%04x = 0x%04x\n", + it->first.c_str(), reg->addr, reg->value); + } + return true; +} diff --git a/nottcontrol/camera/macie/libmacie/macie_lib.h b/nottcontrol/camera/macie/libmacie/macie_lib.h new file mode 100644 index 00000000..42c14a19 --- /dev/null +++ b/nottcontrol/camera/macie/libmacie/macie_lib.h @@ -0,0 +1,408 @@ +/// macie_lib.h +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2018, Jarron Leisenring, All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "macie.h" +#include "fitsio.h" +#include "dirent.h" + +#ifndef MACIELIB_H +#define MACIELIB_H + +// TRUE/FALSE definitions +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!(FALSE)) +#endif + + +//------------------------------------------------------------------------ +// Allowed values for various mode settings +//------------------------------------------------------------------------ + +// H1/2/4RG +typedef enum CAMERA_TYPE +{ + CAMERA_TYPE_H1RG, + CAMERA_TYPE_H2RG, + CAMERA_TYPE_H4RG +} CAMERA_TYPE; + +// Fast or Slow pixel rate +typedef enum CAMERA_MODE +{ + CAMERA_MODE_SLOW, + CAMERA_MODE_FAST +} CAMERA_MODE; + +typedef enum LOG_LEVEL +{ + LOG_DEBUG, + LOG_INFO, + LOG_WARNING, + LOG_ERROR, + LOG_NONE +} LOG_LEVEL; + +//------------------------------------------------------------------------ +// All MACIE settings and parameters +//------------------------------------------------------------------------ + +// Register address info and value +// 3-element array describing reg address, bit start, bit end +typedef struct regInfo +{ + unsigned short addr; // Register address + unsigned short bit0; // First (lowest) relevant bit + unsigned short bit1; // Last (highest) relevant bit + unsigned int value; // Value assigned to bits +} regInfo; + +// This is the structure used to hold information about the MACIE and ASIC. +typedef struct MACIE_Settings +{ + LOG_LEVEL verbosity; // Message log level + + // Detector type and mode inputs + CAMERA_TYPE DetectorType; // Detector type (H1RG,H2RG,H4RG) + CAMERA_MODE DetectorMode; // Fast or Slow readout Mode + MACIE_Connection connection; // MACIE connection input + + // Detector size populated after init + unsigned int uiDetectorWidth; // Full SCA width + unsigned int uiDetectorHeight; // Full SCA height + + // Config file inputs + char MACIEFile[2048]; // MACIE register file + char ASICFile[2048]; // ASIC microcode file + char ASICRegs[2048]; // ASIC Register config file + // File save info + bool bSaveData; // Write FITS file to disk? + std::string saveDir; // Directory to save FITS files + std::string filePrefix; // Filename prefix: LMIR_YYYMMDD_*.fits + unsigned int uiFileNum; // Ramp file number for incrementing; only use for test data offset... + + // MACIE and ASIC card selection + // Nominally updated during MACIE and ASIC init + MACIE_CardInfo *pCard; // pointer to CardInfo + unsigned short numCards; // Number of connected MACIESs + unsigned long handle; // Handle of selected card (USB+MACIE0) + unsigned char avaiMACIEs; // Available connected MACIEs + unsigned char slctMACIEs; // Selected MACIE (currently always MACIE0) + bool bMACIEslot1; // Load firmware from MACIE Slot1? + unsigned char avaiASICs; // Available connected ASICs + unsigned char slctASICs; // Selected ASIC (currently always ASIC0) + + unsigned int clkRateM; // Value of MACIE clock driver (MHz) + unsigned int clkRateMDefault; // Default MACIE clock driver (MHz) + unsigned short clkPhase; // Value of phase shift on MACIE register + unsigned short clkPhaseDefault; // Default phase shift value to set on init + unsigned int pixelRate; // Detector pixel rate (kHz) + + unsigned int uiNumCoadds; // # of Ramp/Int to average + unsigned int uiNumSaves; // # of final saved ramps + unsigned int uiNumGroups_max; // Max number of Groups in a ramp + + double frametime_ms; // Storage for frametime information + double ramptime_ms; // Storage for ramptime information + + short nBuffer; // # of local frame buffers to store data + // unsigned long nBytesMin; // Minimum number of bytes allowed to command detector + unsigned long nBytesMax; // Maximum number of total bytes allowed for mem allocation + unsigned long nPixBuffMin; // Minimum number of 16-bit pixels for a given buffer + unsigned long nPixBuffMax; // Maximum number of 16-bit pixels for a given buffer (single ramp restriction) + unsigned long nPixBuffer; // Number of pixels currently set for a given buffer size + bool bUseSciDataFunc; // Use MACIE_ReadUSBScienceData() instead of MACIE_ReadUSBScienceFrame() + + // MACIE error counters + unsigned short errArr[MACIE_ERROR_COUNTERS]; + + // MACIE firmware version info + // Values should be displayed as HEX for human readable + unsigned int firmwareVersion; + unsigned int firmwareMonthDay; + unsigned int firmwareYear; + + // Assembly Code values mapped as a dictionary + std::map RegMap; + + // Is STRIPE mode allowed? + bool bStripeModeAllowed; + bool bStripeMode; + + // Pixel clocking scheme for full frame and subarray window + // Normal (0) or Enhanced (1) + // Only here until Enhanced+Window works correctly in future ASIC microcode + unsigned int ffPixelClkScheme; + unsigned int winPixelClkScheme; + + // Set for offline code development and testing + bool offline_develop; + std::map RegAllASIC; // Only used for testing + +} MACIE_Settings; + +extern void delay(int ms); +extern ushort subtract_ushort(ushort x, ushort y); + +// Parameter structure handling +extern bool SettingsCheckNULL(MACIE_Settings *ptUserData); +extern bool create_param_struct(MACIE_Settings *ptUserData, LOG_LEVEL verbosity); + +// MACIE interface and init +extern bool CheckInterfaces(MACIE_Settings *ptUserData); +extern bool GetHandleUSB(MACIE_Settings *ptUserData); +extern bool GetHandleGigE(MACIE_Settings *ptUserData); +extern bool GetAvailableMACIEs(MACIE_Settings *ptUserData); +extern bool GetAvailableASICs(MACIE_Settings *ptUserData); +extern bool ASIC_Defaults(MACIE_Settings *ptUserData); +extern bool InitializeASIC(MACIE_Settings *ptUserData); +extern bool LoadASIC(MACIE_Settings *ptUserData); +extern bool ReconfigureASIC(MACIE_Settings *ptUserData); + +extern unsigned long GetMemAvailable(MACIE_Settings *ptUserData); +extern void SetNBuffer(MACIE_Settings *ptUserData, short nBuffer); +extern void SetBuffSize(MACIE_Settings *ptUserData, unsigned int PixBuffer); +extern unsigned long CalcBuffSize(MACIE_Settings *ptUserData); +extern unsigned long CalcBuffSize(MACIE_Settings *ptUserData, unsigned int mode); +extern short CalcNBuffers(MACIE_Settings *ptUserData); +extern void ConfigBuffers(MACIE_Settings *ptUserData); +extern bool VerifyBuffers(MACIE_Settings *ptUserData); +extern double MemBufferFrac(MACIE_Settings *ptUserData); + +// MACIE power and voltage settings +#define MACIE_PWR_DAC_SIZE 38 +#define MACIE_PWR_CTRL_SIZE 41 +extern bool GetVoltages(MACIE_Settings *ptUserData, float vArr[]); +extern bool GetPower(MACIE_Settings *ptUserData, bool pArr[]); +extern bool GetPowerASIC(MACIE_Settings *ptUserData, bool *bEn); +extern bool SetPowerASIC(MACIE_Settings *ptUserData, bool bEn); +extern bool SetLED(MACIE_Settings *ptUserData, unsigned int set_val); + +extern bool AcquireDataUSB(MACIE_Settings *ptUserData, bool externalTrigger); +extern bool AcquireDataGigE(MACIE_Settings *ptUserData, bool externalTrigger); +extern void HaltCameraAcq(MACIE_Settings *ptUserData); +extern bool DownloadAndSaveAllUSB(MACIE_Settings *ptUserData); +extern bool DownloadRampUSB(MACIE_Settings *ptUserData, unsigned short pData[], long framesize, + long nframes_save, int triggerTimeout, int wait_delta); +extern bool DownloadRampUSB_Frame(MACIE_Settings *ptUserData, unsigned short pData[], long framesize, + long nframes_save, int triggerTimeout, int wait_delta); +extern bool DownloadRampUSB_Data(MACIE_Settings *ptUserData, unsigned short pData[], long framesize, + long nframes_save, int triggerTimeout, int wait_delta); +extern bool DownloadDataUSB(MACIE_Settings *ptUserData, unsigned short pData[], long SIZE, unsigned short timeout); +extern bool DownloadFrameUSB(MACIE_Settings *ptUserData, unsigned short pData[], long SIZE, unsigned short timeout); +extern bool CloseUSBScienceInterface(MACIE_Settings *ptUserData); +extern bool CloseGigEScienceInterface(MACIE_Settings *ptUserData); +extern bool WriteFITSFile(MACIE_Settings *ptUserData, unsigned short *pData, char *fileName); +extern bool WriteFITSRamp(void *pData, std::vector naxis, int bitpix, std::string filename); +extern void exposure_test_data(MACIE_Settings *ptUserData, unsigned short pData[], long SIZE); + +// MACIE phase shifting +extern bool GetMACIEPhaseShift(MACIE_Settings *ptUserData); +extern bool SetMACIEPhaseShift(MACIE_Settings *ptUserData, unsigned short clkPhase); +extern bool ToggleMACIEPhaseShift(MACIE_Settings *ptUserData, bool enable); +extern bool FindOptimalPhaseShift(MACIE_Settings *ptUserData, ushort val_start, ushort val_end); +extern bool GetMACIEClockRate(MACIE_Settings *ptUserData); +extern bool SetMACIEClockRate(MACIE_Settings *ptUserData, unsigned int clkRateM); + +// ASIC register reading +extern bool ReadASICReg(MACIE_Settings *ptUserData, unsigned short addr, unsigned int *val); +extern bool ReadASICBits(MACIE_Settings *ptUserData, regInfo *reg, unsigned int *val); +extern bool ReadASICBlock(MACIE_Settings *ptUserData, unsigned short addr, int nreg, unsigned int *val); +extern bool readASICconfig(MACIE_Settings *ptUserData, unsigned short addr, int nreg); + + +// ASIC reg writing +extern bool WriteASICReg(MACIE_Settings *ptUserData, unsigned short addr, unsigned int val); +extern bool WriteASICBits(MACIE_Settings *ptUserData, regInfo *reg); +extern bool WriteASICBlock(MACIE_Settings *ptUserData, unsigned short addr, int nreg, + unsigned int *val); + +// Storing ASIC settings locally +extern regInfo gen_regInfo(unsigned short addr, unsigned short bit0, unsigned short bit1, + unsigned int value); +extern bool initRegMap(MACIE_Settings *ptUserData); +extern bool GetASICSettings(MACIE_Settings *ptUserData); +extern bool SetASICParameter(MACIE_Settings *ptUserData, std::string addr_name, unsigned int val); +extern bool GetASICParameter(MACIE_Settings *ptUserData, std::string addr_name, unsigned int *val); + +// Convenience functions for various ASIC parameters +extern unsigned int ASIC_Generic(MACIE_Settings *ptUserData, std::string addr_name, bool bSet, unsigned int val); +extern unsigned int ASIC_NResets(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_NReads(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_NDrops(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_NGroups(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_NRamps(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_NCoadds(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_NSaves(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +// Window/Subarray settings +extern bool verify_subarray_size(MACIE_Settings *ptUserData, uint nx, uint ny, unsigned long nybtes_ramp); +extern void burst_stripe_set_ffidle(MACIE_Settings *ptUserData); +extern bool ypix_burst_stripe(MACIE_Settings *ptUserData, unsigned int *ypix, bool bSet); +extern bool ASIC_STRIPEMode(MACIE_Settings *ptUserData, bool bSet, bool bVal); +extern unsigned int ASIC_WinHorz(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_WinVert(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_getX1(MACIE_Settings *ptUserData); +extern unsigned int ASIC_getX2(MACIE_Settings *ptUserData); +extern unsigned int ASIC_getY1(MACIE_Settings *ptUserData); +extern unsigned int ASIC_getY2(MACIE_Settings *ptUserData); +extern unsigned int ASIC_setX1(MACIE_Settings *ptUserData, unsigned int val); +extern unsigned int ASIC_setX2(MACIE_Settings *ptUserData, unsigned int val); +extern unsigned int ASIC_setY1(MACIE_Settings *ptUserData, unsigned int val); +extern unsigned int ASIC_setY2(MACIE_Settings *ptUserData, unsigned int val); +extern unsigned int ASIC_NumOutputs(MACIE_Settings *ptUserData); +extern unsigned int ASIC_NumOutputs(MACIE_Settings *ptUserData, bool bFullFrame); +extern unsigned int ASIC_NumOutputs(MACIE_Settings *ptUserData, bool bSet, unsigned int val); + +// More frame info +extern unsigned int exposure_nframes(MACIE_Settings *ptUserData, bool include_all); +extern unsigned int exposure_xpix(MACIE_Settings *ptUserData); +extern unsigned int exposure_ypix(MACIE_Settings *ptUserData); +extern unsigned int exposure_frametime_pix(MACIE_Settings *ptUserData); +extern double exposure_frametime_ms(MACIE_Settings *ptUserData); +extern double exposure_grouptime_ms(MACIE_Settings *ptUserData); +extern double exposure_ramptime_ms(MACIE_Settings *ptUserData); +extern double exposure_inttime_ms(MACIE_Settings *ptUserData); +extern double exposure_efficiency(MACIE_Settings *ptUserData); + +extern bool set_exposure_settings(MACIE_Settings *ptUserData, bool bSave, + uint ncoadds, uint nsaved_ramps, uint ngroups, uint nreads, uint ndrops, uint nresets); +extern bool set_frame_settings(MACIE_Settings *ptUserData, bool bHorzWin, bool bVertWin, + uint x1, uint x2, uint y1, uint y2); +extern bool calc_ramp_settings(MACIE_Settings *ptUserData, double tint_ms, int ngmax, + uint *ngroups, uint *ndrops, uint *nreads); + +// ASIC Inputs, Gain, Cap Comp, and low-frequency filter +extern unsigned int ASIC_Inputs(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_Gain(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_CapComp(MACIE_Settings *ptUserData, bool bSet, unsigned int val); +extern unsigned int ASIC_FiltPole(MACIE_Settings *ptUserData, bool bSet, unsigned int val); + +extern float ConvertDACToV(unsigned int dac_setting); +extern unsigned int ConvertVToDAC(float volts); + +// Error counters +extern unsigned int TotalErrorCounts(MACIE_Settings *ptUserData); +extern bool ResetErrorCounters(MACIE_Settings *ptUserData); +extern bool GetErrorCounters(MACIE_Settings *ptUserData, bool bVerb); + +// Some utility function +extern std::string strip_white(const std::string &input); +extern std::string strip_comments(const std::string &input, const std::string &delimiters); + +extern void verbose_printf(LOG_LEVEL level, MACIE_Settings *ptUserData, const char *format, ... ); +extern void set_verbose(MACIE_Settings *ptUserData, LOG_LEVEL level); +extern LOG_LEVEL get_verbose(MACIE_Settings *ptUserData); + +extern const char *convert_camera_type_str(CAMERA_TYPE type); +extern CAMERA_TYPE convert_camera_type(const char *pcDetectorType); +extern const char *convert_camera_mode_str(CAMERA_MODE mode); +extern CAMERA_MODE convert_camera_mode(const char *pcDetectorMode); +extern const char *convert_log_type_str(LOG_LEVEL level); +extern LOG_LEVEL convert_log_type(const char *pcLevel); + +extern bool initASICRegs_testing(MACIE_Settings *ptUserData); + +#endif // MACIELIB_H + +//------------------------------------------------------------------------ +// MACIE API functions +//------------------------------------------------------------------------ +// MACIE_LibVersion(); +// MACIE_Init(); +// MACIE_Free(); +// MACIE_Error(); +// +// MACIE_CheckInterfaces(); +// MACIE_GetHandle(); +// +// MACIE_GetAvailableMACIEs(); +// MACIE_GetAvailableASICs(); +// +// MACIE_ReadMACIEReg(); +// MACIE_WriteMACIEReg(); +// MACIE_ReadMACIEBlock(); +// MACIE_WriteMACIEBlock(); +// +// MACIE_loadMACIEFirmware(); +// MACIE_DownloadMACIEFile(); +// MACIE_DownloadLoadfile(); +// +// MACIE_WriteASICReg(); +// MACIE_ReadASICReg(); +// MACIE_WriteASICBlock(); +// MACIE_ReadASICBlock(); +// MACIE_DownloadASICFile(); +// +// MACIE_ClosePort(); +// MACIE_GetErrorCounters(); +// MACIE_ResetErrorCounters(); +// +// MACIE_SetMACIEPhaseShift(); +// MACIE_GetMACIEPhaseShift(); +// +// MACIE_ConfigureCamLinkInterface(); +// MACIE_ConfigureGigeScienceInterface(); +// MACIE_ConfigureUSBScienceInterface(); +// +// MACIE_AvailableScienceData(); +// MACIE_AvailableScienceFrames(); +// +// MACIE_ReadGigeScienceFrame(); +// MACIE_ReadGigeScienceData(); +// MACIE_ReadCamlinkScienceFrame(); +// MACIE_ReadUSBScienceFrame(); +// MACIE_ReadUSBScienceData(); +// +// MACIE_WriteFitsFile(); +// +// MACIE_CloseCamlinkScienceInterface(); +// MACIE_CloseGigeScienceInterface(); +// MACIE_CloseUSBScienceInterface(); +// +// MACIE_SetVoltage(); +// MACIE_GetVoltage(); +// MACIE_EnablePower(); +// MACIE_DisablePower(); +// MACIE_SetPower(); +// MACIE_GetPower(); +// +// MACIE_SetTelemetryConfiguration(); +// MACIE_GetTelemetryConfiguration(); +// MACIE_GetTelemetry(); +// MACIE_GetTelemetrySet(); +// MACIE_GetTelemetryAll(); diff --git a/nottcontrol/camera/macie/load_files/FastMode_2048.dcf b/nottcontrol/camera/macie/load_files/FastMode_2048.dcf new file mode 100644 index 00000000..0c7901d4 --- /dev/null +++ b/nottcontrol/camera/macie/load_files/FastMode_2048.dcf @@ -0,0 +1,2128 @@ +/Matrox Electronic Systems Ltd. +/Copyright 2005. +/ +/no name DCF template. +/ +/ +/ +/ +/ +/ +/ +/ +/ +[CAMERA_NAME] +no name +[CONFIG_FILE] +50CF +ODYSSEY +Wed Jun 05 16:58:18 2013 +[INFO_FILE_REV] +0009.0016.0000 +HELIOS/CL/FULL +[GENERAL_PARAMETERS] +GEN_MATCH_HW 0x1 +GEN_SAVED_W_ERR 0x0 +CT_LS 0x0 +CT_FS 0x1 +CT_CONV_INVERTED 0x0 +CT_TAPS 0x1 +CT_CAMERA 0x0 +CT_BAYER_DISABLE 0x1 +CT_BAYER_BG 0x0 +CT_BAYER_GB 0x0 +CT_BAYER_GR 0x0 +CT_BAYER_RG 0x0 +VDC_DIG 0x1 +VDC_ANA 0x0 +VDC_MONO 0x1 +VDC_C_COLOR 0x0 +VDC_RGB_COL 0x0 +VDC_RGB_PACK 0x0 +VDC_RGB_ALPHA 0x0 +VDC_SVID 0x0 +VDC_YUVVID 0x0 +VDC_TTL 0x0 +VDC_422 0x0 +VDC_OPTO 0x0 +VDC_LVDS 0x1 +VDC_WD8 0x0 +VDC_WD16 0x0 +VDC_WD24 0x0 +VDC_WD32 0x0 +VDC_WD64 0x0 +VDC_ALT_GRAB 0x0 +VDC_FROM_VCR 0x0 +VDC_IN_CH0 0x1 +VDC_IN_CH1 0x0 +VDC_IN_CH2 0x0 +VDC_IN_CH3 0x0 +VDC_IN_CH_C 0x0 +VDC_DIGITIZER 0x0 +VDC_PSG_MODE_1_CHECK 0x1 +VDC_PSG_MODE_2_CHECKS 0x0 +VDC_PSG_MODE_3_CHECKS 0x0 +VDC_PSG_MODE_4_CHECKS 0x0 +VDC_PSG_MODE_1_3_CHECKS 0x0 +VDC_PSG_MODE_ANY_CHECKS 0x0 +VDC_MIL_CHANNEL 0x0 +VDC_USE_PSG_0 0x1 +VDC_USE_PSG_1 0x0 +VDC_USE_PSG_2 0x0 +VDC_USE_PSG_3 0x0 +VDC_0_AC_WITH_DC 0x0 +VDC_0_DC_WITH_DC 0x0 +VDC_0_DC_WITHOUT_DC 0x0 +VDC_0_NO_FILTER 0x0 +VDC_0_FILTER_0 0x0 +VDC_0_FILTER_1 0x0 +VDC_1_AC_WITH_DC 0x0 +VDC_1_DC_WITH_DC 0x0 +VDC_1_DC_WITHOUT_DC 0x0 +VDC_1_NO_FILTER 0x0 +VDC_1_FILTER_0 0x0 +VDC_1_FILTER_1 0x0 +VDC_2_AC_WITH_DC 0x0 +VDC_2_DC_WITH_DC 0x0 +VDC_2_DC_WITHOUT_DC 0x0 +VDC_2_NO_FILTER 0x0 +VDC_2_FILTER_0 0x0 +VDC_2_FILTER_1 0x0 +VDC_3_AC_WITH_DC 0x0 +VDC_3_DC_WITH_DC 0x0 +VDC_3_DC_WITHOUT_DC 0x0 +VDC_3_NO_FILTER 0x0 +VDC_3_FILTER_0 0x0 +VDC_3_FILTER_1 0x0 +VDT_USE_HLOCK 0x0 +VDT_USE_VLOCK 0x0 +VDT_STD_170 0x0 +VDT_STD_330 0x0 +VDT_STD_CCIR 0x0 +VDT_STD_NTSC 0x0 +VDT_STD_PAL 0x0 +VDT_STD_CL 0x0 +VDT_STD_DIGITAL 0x0 +VDT_NOVERT 0x0 +VDT_HSYNC 0x0 +VDT_HBPORCH 0x0 +VDT_HFPORCH 0x0 +VDT_HACTIVE 0x400 +VDT_HTOTAL 0x400 +VDT_HSYNC_FREQ 0x1312d +VDT_VSYNC 0x0 +VDT_VBPORCH 0x0 +VDT_VFPORCH 0x0 +VDT_VACTIVE 0x800 +VDT_VTOTAL 0x800 +VDT_VSYNC_FREQ 0x26 +VDT_CL_IMAGE_SIZE_X 0x0 +VDT_CL_IMAGE_SIZE_Y 0x0 +VDT_CL_CROPPING_X 0x0 +VDT_CL_CROPPING_Y 0x0 +VDT_INTERL 0x0 +VDT_NINTRL 0x1 +VDT_SER 0x0 +VDT_EQU 0x0 +VDT_CLP_SYN 0x0 +VDT_CLP_BPO 0x0 +VDT_CLP_FPO 0x0 +PCK_CAM_GEN 0x0 +PCK_CAM_REC 0x0 +PCK_CAM_R&G 0x0 +PCK_OTH_REC 0x0 +PCK_USE_OUT 0x0 +PCK_CAM_XCHG 0x0 +PCK_ITTL 0x0 +PCK_I422 0x0 +PCK_IOPTO 0x0 +PCK_ILVDS 0x0 +PCK_IPOS 0x0 +PCK_INEG 0x0 +PCK_FREQ 0x4c4b400 +PCK_INTDVED 0x0 +PCK_INTDIVF 0x0 +PCK_ODVED 0x0 +PCK_ODIVF 0x0 +PCK_OFREQDV 0x4c4b400 +PCK_OTTL 0x0 +PCK_O422 0x0 +PCK_OOPTO 0x0 +PCK_OLVDS 0x0 +PCK_OPOS 0x0 +PCK_ONEG 0x0 +PCK_IDELAY 0x0 +SYC_DIG 0x1 +SYC_ANA 0x0 +SYC_CAM_GEN 0x1 +SYC_CAM_R&G 0x0 +SYC_CAM_LATENCY 0x0 +SYC_MD_CSYN 0x0 +SYC_MD_HVSY 0x1 +SYC_MD_VSYN 0x0 +SYC_MD_HSYN 0x0 +SYC_EXT_VSY 0x0 +SYC_H_IN 0x1 +SYC_H_OUT 0x0 +SYC_H_ITTL 0x0 +SYC_H_I422 0x0 +SYC_H_IOPTO 0x0 +SYC_H_ILVDS 0x1 +SYC_H_IPOS 0x1 +SYC_H_INEG 0x0 +SYC_H_OTTL 0x0 +SYC_H_O422 0x0 +SYC_H_OOPTO 0x0 +SYC_H_OLVDS 0x0 +SYC_H_OPOS 0x0 +SYC_H_ONEG 0x0 +SYC_V_IN 0x1 +SYC_V_OUT 0x0 +SYC_V_ITTL 0x0 +SYC_V_I422 0x0 +SYC_V_IOPTO 0x0 +SYC_V_ILVDS 0x1 +SYC_V_IPOS 0x1 +SYC_V_INEG 0x0 +SYC_V_OTTL 0x0 +SYC_V_O422 0x0 +SYC_V_OOPTO 0x0 +SYC_V_OLVDS 0x0 +SYC_V_OPOS 0x0 +SYC_V_ONEG 0x0 +SYC_C_IN 0x0 +SYC_C_OUT 0x0 +SYC_C_ITTL 0x0 +SYC_C_I422 0x0 +SYC_C_IOPTO 0x0 +SYC_C_ILVDS 0x0 +SYC_C_IPOS 0x0 +SYC_C_INEG 0x0 +SYC_C_OTTL 0x0 +SYC_C_O422 0x0 +SYC_C_OOPTO 0x0 +SYC_C_OLVDS 0x0 +SYC_C_OPOS 0x0 +SYC_C_ONEG 0x0 +SYC_BLK 0x0 +SYC_COMP 0x0 +SYC_SEP 0x0 +SYC_IN_CH 0x0 +EXP_SYN_CLK 0x0 +EXP_ASY_CLK 0x0 +EXP_CLK_FREQ 0x4c4b400 +EXP_CLK_DVED 0x0 +EXP_CLK_DIVF 0x0 +EXP_MD_PERD 0x0 +EXP_MD_W_TRG 0x0 +EXP_MD_EXT 0x0 +EXP_MD_HSY 0x0 +EXP_MD_VSY 0x0 +EXP_MD_SW 0x0 +EXP_TRG_TTL 0x1 +EXP_TRG_422 0x0 +EXP_TRG_OPTO 0x0 +EXP_TRG_LVDS 0x0 +EXP_TRG_DEFAULT 0x0 +EXP_TRG_POS 0x0 +EXP_TRG_NEG 0x0 +EXP_OUT_DLYD 0x0 +EXP_OUT_T0 0x0 +EXP_OUT_T1 0x0 +EXP_OUT_T2 0x0 +EXP_OUT_T3 0x0 +EXP_OUT_TTL 0x0 +EXP_OUT_422 0x0 +EXP_OUT_OPTO 0x0 +EXP_OUT_LVDS 0x0 +EXP_OUT_DEFAULT 0x0 +EXP_OUT_POS 0x0 +EXP_OUT_NEG 0x0 +EXP_ARM_ENABLE 0x0 +EXP_ARM_DISABLE 0x0 +EXP_ARM_TTL 0x1 +EXP_ARM_422 0x0 +EXP_ARM_OPTO 0x0 +EXP_ARM_LVDS 0x0 +EXP_ARM_DEFAULT 0x0 +EXP_ARM_POS 0x1 +EXP_ARM_NEG 0x0 +GRB_MD_CONT 0x1 +GRB_MD_SW_TRG 0x0 +GRB_MD_HW_TRG 0x0 +GRB_START_ODD 0x0 +GRB_START_EVEN 0x0 +GRB_START_ANY 0x1 +GRB_ACT_NXT_FRM 0x0 +GRB_ACT_IMMEDIATE 0x0 +GRB_ACT_IMM_SKP_NFR 0x0 +GRB_TRG_TTL 0x0 +GRB_TRG_422 0x0 +GRB_TRG_OPTO 0x0 +GRB_TRG_LVDS 0x0 +GRB_TRG_DEFAULT 0x0 +GRB_TRG_POS 0x0 +GRB_TRG_NEG 0x0 +GRB_LS_FREE_RUN 0x0 +GRB_LS_FIXED_LINE 0x0 +GRB_LS_VARIABLE_LINE 0x0 +GRB_LS_FRMFIX_LINEFIX 0x0 +GRB_LS_FRMFIX_LINEVAR 0x0 +GRB_LS_FRMVAR_LINEFIX 0x0 +GRB_LS_FRMVAR_LINEVAR 0x0 +GRB_TRG_ARM_TTL 0x0 +GRB_TRG_ARM_422 0x0 +GRB_TRG_ARM_OPTO 0x0 +GRB_TRG_ARM_LVDS 0x0 +GRB_TRG_ARM_DEFAULT 0x0 +GRB_TRG_ARM_POS 0x0 +GRB_TRG_ARM_NEG 0x0 +VDL_USE_DEFVAL 0x1 +VDL_POS_SWG 0x1 +VDL_NEG_SWG 0x0 +VDL_BTH_SWG 0x0 +VDL_AMPL 0x2bc +VDL_PEDEST 0x0 +VDL_PED_AMP 0x32 +VDL_GAIN_IND 0x2 +VDL_GAIN 0xaf0 +VDL_BRGHT 0x32 +VDL_CONTR 0x32 +VDL_SATUR 0x32 +VDL_HUE 0x32 +DCF_IS_VIRTUAL 0x0 +DAT_INFOFILE_REV_MAJOR 0x9 +DAT_INFOFILE_REV_MINOR 0x10 +DAT_INFOFILE_REV_BUILD 0x0 +EXP_SYN_CLK_2 0x0 +EXP_ASY_CLK_2 0x0 +EXP_CLK_FREQ_2 0x4c4b400 +EXP_CLK_DVED_2 0x0 +EXP_CLK_DIVF_2 0x0 +EXP_MD_PERD_2 0x0 +EXP_MD_W_TRG_2 0x0 +EXP_MD_EXT_2 0x0 +EXP_MD_HSY_2 0x0 +EXP_MD_VSY_2 0x0 +EXP_MD_SW_2 0x0 +EXP_TRG_TTL_2 0x1 +EXP_TRG_422_2 0x0 +EXP_TRG_OPTO_2 0x0 +EXP_TRG_LVDS_2 0x0 +EXP_TRG_DEFAULT_2 0x0 +EXP_TRG_POS_2 0x0 +EXP_TRG_NEG_2 0x0 +EXP_OUT_DLYD_2 0x0 +EXP_OUT_T0_2 0x0 +EXP_OUT_T1_2 0x0 +EXP_OUT_T2_2 0x0 +EXP_OUT_T3_2 0x0 +EXP_OUT_TTL_2 0x0 +EXP_OUT_422_2 0x0 +EXP_OUT_OPTO_2 0x0 +EXP_OUT_LVDS_2 0x0 +EXP_OUT_DEFAULT_2 0x0 +EXP_OUT_POS_2 0x0 +EXP_OUT_NEG_2 0x0 +EXP_ARM_ENABLE_2 0x0 +EXP_ARM_DISABLE_2 0x0 +EXP_ARM_TTL_2 0x1 +EXP_ARM_422_2 0x0 +EXP_ARM_OPTO_2 0x0 +EXP_ARM_LVDS_2 0x0 +EXP_ARM_DEFAULT_2 0x0 +EXP_ARM_POS_2 0x1 +EXP_ARM_NEG_2 0x0 +TAP_MULTIPLEX_X 0x1 +TAP_MULTIPLEX_Y 0x1 +TAP_ORDERS 0x343efcea +REGION_DIRECTIONS 0x0 +TAP_REGIONSX 0x1 +TAP_REGIONSY 0x1 +TAP_PIXADJX 0x2 +TAP_PIXADJY 0x1 +CLC_MODE 0x0 +CLC_MODE_INIT_WIDTH_10_16 0x1 +CLC_ACTIVE_CH0 0x1 +VDT_CL_USE_CAMERA_VALID 0x1 +CL_MODE_BITMAP 0x4 +CLC_MODE_CH0 0x3 +CLC_SYNC_SOURCE 0x0 +CLC_VSYNC_SEL 0x0 +CLC_VSYNC_POL 0x0 +CLC_HSYNC_SEL 0x0 +CLC_HSYNC_POL 0x0 +CLB_CC1 0x5 +CLB_CC2 0x4 +CLB_CC3 0x4 +CLB_CC4 0x4 +CLB_CCOUTEN1 0x1 +CLB_CCOUTEN2 0x0 +USR_IENABLE 0x0 +USR_ITTL 0x0 +USR_ILVDS 0x0 +USR_IOPTO 0x0 +USR_OENABLE 0x0 +USR_OTTL 0x0 +USR_OLVDS 0x0 +USR_BIT_0_OTH0 0x0 +USR_BIT_1_OTH0 0x0 +USR_BIT_2_OTH0 0x0 +USR_BIT_3_OTH0 0x0 +USR_BIT_4_OTH0 0x0 +USR_BIT_5_OTH0 0x0 +USR_BIT_6_OTH0 0x0 +TM_ENABLE 0x0 +TM_LINENUMBER 0x0 +TM_PIXELMODE 0x0 +VDC_VID_WIDTH_10 0x0 +VDC_VID_WIDTH_12 0x1 +VDC_VID_WIDTH_14 0x0 +VDC_VID_WIDTH_16 0x0 +VDC_ODYSSEY_ANA_FILTER 0x0 +VDT_HCNT_LD_ARM_TRG_OPTO 0x0 +VDT_HCNT_LD_ARM_TRG_TTL 0x0 +VDT_HCNT_LD_ARM_TRG_LVDS 0x0 +VDT_HCNT_LD_ARM_DIS 0x0 +VDT_HCNT_LD_ARM_QUADTIMERSTART 0x0 +VDT_HCNT_LD_ARM_TIMER0 0x0 +VDT_HCNT_LD_ARM_TIMER1 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC01_OPTO_CL 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC01_OPTO_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_OPTO_CL_SOL_BASE 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_OPTO_CL_SOL_BASE 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC1_OPTO_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC1_OPTO_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_TTL_CL_SOL_BASE 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_TTL_CL_SOL_BASE 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC01_TTL_CL 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC01_TTL_CL 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC01_LVDS_CL 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC01_LVDS_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_LVDS_CL_SOL_BASE 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_LVDS_CL_SOL_BASE 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC1_LVDS_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC1_LVDS_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_OPTO_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_OPTO_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_TTL_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_TTL_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC1_TTL_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC1_TTL_CL 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_LVDS_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_LVDS_CL 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_OPTO_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC1_OPTO_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC2_OPTO_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC3_OPTO_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC1_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC2_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC3_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX0_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX1_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX2_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX3_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX4_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX5_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX6_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX7_TTL_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX0_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX1_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX2_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX3_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX4_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX5_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_2_4AC_AUX6_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_3_4AC_AUX7_LVDS_ANA 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC1_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC1_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC2_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC2_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC3_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC3_OPTO_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC0_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC1_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC2_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_1_AC3_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC0_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC1_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC2_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_0_AC3_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC0_AUX1_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC0_AUX2_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC1_AUX1_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC1_AUX2_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC2_AUX1_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC2_AUX2_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC3_AUX1_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC3_AUX2_TTL_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC0_AUX1_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC0_AUX2_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC1_AUX1_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC1_AUX2_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC2_AUX1_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC2_AUX2_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_2_AC3_AUX1_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_3_AC3_AUX2_LVDS_DIG 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_CL_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC1_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC1_LVDS_CL_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +VDT_HCNT_LD_ARM_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +VDT_HCNT_LD_ARM_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +SLOW_SCAN_PLL_HREFSEL_DEFAULT 0x0 +SLOW_SCAN_PLL_HREFSEL_NONE 0x0 +SLOW_SCAN_PLL_HREFSEL_DVI 0x0 +SLOW_SCAN_PLL_HREFSEL_AUX 0x0 +SLOW_SCAN_PLL_HREFSEL_VIDEO 0x0 +SLOW_SCAN_PLL_HREFSEL_DVI_OTHERAC 0x0 +SLOW_SCAN_PLL_HREFSEL_DVI_AC1 0x0 +SLOW_SCAN_PLL_PCKSEL_DEFAULT 0x0 +SLOW_SCAN_PLL_PCKSEL_NONE 0x0 +SLOW_SCAN_PLL_PCKSEL_DVI 0x0 +SLOW_SCAN_PLL_PCKSEL_AUX 0x0 +SLOW_SCAN_PLL_PCKSEL_VIDEO 0x0 +SLOW_SCAN_PLL_PCKSEL_DVI_OTHERAC 0x0 +SLOW_SCAN_PLL_PCKSEL_DVI_AC1 0x0 +GRB_TRG_HS_PSG 0x0 +GRB_TRG_VS_PSG 0x0 +GRB_TRG_TIMER0 0x0 +GRB_TRG_TIMER1 0x0 +GRB_TRG_TIMER2 0x0 +GRB_TRG_TIMER3 0x0 +GRB_TRG_2_AC01_OPTO_CL_SOL_EVCL 0x0 +GRB_TRG_3_AC01_OPTO_CL_SOL_EVCL 0x0 +GRB_TRG_2_AC01_OPTO_CL 0x0 +GRB_TRG_3_AC01_OPTO_CL 0x0 +GRB_TRG_0_AC0_OPTO_CL_SOL_BASE 0x0 +GRB_TRG_1_AC0_OPTO_CL_SOL_BASE 0x0 +GRB_TRG_0_AC0_OPTO_CL_SOL_EVCL 0x0 +GRB_TRG_1_AC0_OPTO_CL_SOL_EVCL 0x0 +GRB_TRG_0_AC0_OPTO_CL 0x0 +GRB_TRG_1_AC0_OPTO_CL 0x0 +GRB_TRG_0_AC1_OPTO_CL_SOL_EVCL 0x0 +GRB_TRG_1_AC1_OPTO_CL_SOL_EVCL 0x0 +GRB_TRG_0_AC1_OPTO_CL 0x0 +GRB_TRG_1_AC1_OPTO_CL 0x0 +GRB_TRG_0_AC0_TTL_CL_SOL_BASE 0x0 +GRB_TRG_1_AC0_TTL_CL_SOL_BASE 0x0 +GRB_TRG_0_AC0_TTL_CL_SOL_EVCL 0x0 +GRB_TRG_1_AC0_TTL_CL_SOL_EVCL 0x0 +GRB_TRG_0_AC0_TTL_CL 0x0 +GRB_TRG_1_AC0_TTL_CL 0x0 +GRB_TRG_0_AC1_TTL_CL_SOL_EVCL 0x0 +GRB_TRG_1_AC1_TTL_CL_SOL_EVCL 0x0 +GRB_TRG_0_AC1_TTL_CL 0x0 +GRB_TRG_1_AC1_TTL_CL 0x0 +GRB_TRG_2_AC01_TTL_CL_SOL_EVCL 0x0 +GRB_TRG_3_AC01_TTL_CL_SOL_EVCL 0x0 +GRB_TRG_2_AC01_TTL_CL 0x0 +GRB_TRG_3_AC01_TTL_CL 0x0 +GRB_TRG_0_AC0_LVDS_CL_SOL_BASE 0x0 +GRB_TRG_1_AC0_LVDS_CL_SOL_BASE 0x0 +GRB_TRG_0_AC0_LVDS_CL_SOL_EVCL 0x0 +GRB_TRG_1_AC0_LVDS_CL_SOL_EVCL 0x0 +GRB_TRG_0_AC0_LVDS_CL 0x0 +GRB_TRG_1_AC0_LVDS_CL 0x0 +GRB_TRG_0_AC1_LVDS_CL_SOL_EVCL 0x0 +GRB_TRG_1_AC1_LVDS_CL_SOL_EVCL 0x0 +GRB_TRG_0_AC1_LVDS_CL 0x0 +GRB_TRG_1_AC1_LVDS_CL 0x0 +GRB_TRG_2_AC01_LVDS_CL_SOL_EVCL 0x0 +GRB_TRG_3_AC01_LVDS_CL_SOL_EVCL 0x0 +GRB_TRG_2_AC01_LVDS_CL 0x0 +GRB_TRG_3_AC01_LVDS_CL 0x0 +GRB_TRG_1_AC0_OPTO_ANA 0x0 +GRB_TRG_1_AC1_OPTO_ANA 0x0 +GRB_TRG_1_AC2_OPTO_ANA 0x0 +GRB_TRG_1_AC3_OPTO_ANA 0x0 +GRB_TRG_0_AC0_TTL_ANA 0x0 +GRB_TRG_0_AC1_TTL_ANA 0x0 +GRB_TRG_0_AC2_TTL_ANA 0x0 +GRB_TRG_0_AC3_TTL_ANA 0x0 +GRB_TRG_2_4AC_AUX0_TTL_ANA 0x0 +GRB_TRG_3_4AC_AUX1_TTL_ANA 0x0 +GRB_TRG_2_4AC_AUX2_TTL_ANA 0x0 +GRB_TRG_3_4AC_AUX3_TTL_ANA 0x0 +GRB_TRG_2_4AC_AUX4_TTL_ANA 0x0 +GRB_TRG_3_4AC_AUX5_TTL_ANA 0x0 +GRB_TRG_2_4AC_AUX6_TTL_ANA 0x0 +GRB_TRG_3_4AC_AUX7_TTL_ANA 0x0 +GRB_TRG_2_4AC_AUX0_LVDS_ANA 0x0 +GRB_TRG_3_4AC_AUX1_LVDS_ANA 0x0 +GRB_TRG_2_4AC_AUX2_LVDS_ANA 0x0 +GRB_TRG_3_4AC_AUX3_LVDS_ANA 0x0 +GRB_TRG_2_4AC_AUX4_LVDS_ANA 0x0 +GRB_TRG_3_4AC_AUX5_LVDS_ANA 0x0 +GRB_TRG_2_4AC_AUX6_LVDS_ANA 0x0 +GRB_TRG_3_4AC_AUX7_LVDS_ANA 0x0 +GRB_TRG_0_AC0_OPTO_DIG 0x0 +GRB_TRG_1_AC0_OPTO_DIG 0x0 +GRB_TRG_0_AC1_OPTO_DIG 0x0 +GRB_TRG_1_AC1_OPTO_DIG 0x0 +GRB_TRG_0_AC2_OPTO_DIG 0x0 +GRB_TRG_1_AC2_OPTO_DIG 0x0 +GRB_TRG_0_AC3_OPTO_DIG 0x0 +GRB_TRG_1_AC3_OPTO_DIG 0x0 +GRB_TRG_1_AC0_TTL_DIG 0x0 +GRB_TRG_1_AC1_TTL_DIG 0x0 +GRB_TRG_1_AC2_TTL_DIG 0x0 +GRB_TRG_1_AC3_TTL_DIG 0x0 +GRB_TRG_0_AC0_LVDS_DIG 0x0 +GRB_TRG_0_AC1_LVDS_DIG 0x0 +GRB_TRG_0_AC2_LVDS_DIG 0x0 +GRB_TRG_0_AC3_LVDS_DIG 0x0 +GRB_TRG_2_AC0_AUX1_TTL_DIG 0x0 +GRB_TRG_3_AC0_AUX2_TTL_DIG 0x0 +GRB_TRG_2_AC1_AUX1_TTL_DIG 0x0 +GRB_TRG_3_AC1_AUX2_TTL_DIG 0x0 +GRB_TRG_2_AC2_AUX1_TTL_DIG 0x0 +GRB_TRG_3_AC2_AUX2_TTL_DIG 0x0 +GRB_TRG_2_AC3_AUX1_TTL_DIG 0x0 +GRB_TRG_3_AC3_AUX2_TTL_DIG 0x0 +GRB_TRG_2_AC0_AUX1_LVDS_DIG 0x0 +GRB_TRG_3_AC0_AUX2_LVDS_DIG 0x0 +GRB_TRG_2_AC1_AUX1_LVDS_DIG 0x0 +GRB_TRG_3_AC1_AUX2_LVDS_DIG 0x0 +GRB_TRG_2_AC2_AUX1_LVDS_DIG 0x0 +GRB_TRG_3_AC2_AUX2_LVDS_DIG 0x0 +GRB_TRG_2_AC3_AUX1_LVDS_DIG 0x0 +GRB_TRG_3_AC3_AUX2_LVDS_DIG 0x0 +GRB_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC0_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC0_LVDS_CL_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC1_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC1_LVDS_CL_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +GRB_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +GRB_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +GRB_TRG_LVDS_ROTARY_ENCODER 0x0 +GRB_DISABLED_ARM 0x0 +GRB_HARDWARE_ARM 0x0 +GRB_SOFTWARE_ARM 0x0 +GRB_HARDWARE_LATCH_ARM 0x0 +EXP_TRG_TTL_TIMER0 0x0 +EXP_TRG_CNTEQ0_TIMER0 0x0 +EXP_TRG_TIMER1 0x0 +EXP_TRG_TIMER2 0x0 +EXP_TRG_TIMER3 0x0 +EXP_0_TRG_TIMER0_AC0 0x0 +EXP_0_TRG_TIMER0_AC1 0x0 +EXP_0_TRG_TIMER0_AC2 0x0 +EXP_0_TRG_TIMER0_AC3 0x0 +EXP_0_TRG_2_AC01_OPTO_CL_SOL_EVCL 0x0 +EXP_0_TRG_3_AC01_OPTO_CL_SOL_EVCL 0x0 +EXP_0_TRG_2_AC01_OPTO_CL 0x0 +EXP_0_TRG_3_AC01_OPTO_CL 0x0 +EXP_0_TRG_0_AC0_OPTO_CL_SOL_BASE 0x0 +EXP_0_TRG_1_AC0_OPTO_CL_SOL_BASE 0x0 +EXP_0_TRG_0_AC0_OPTO_CL_SOL_EVCL 0x0 +EXP_0_TRG_1_AC0_OPTO_CL_SOL_EVCL 0x0 +EXP_0_TRG_0_AC0_OPTO_CL 0x0 +EXP_0_TRG_1_AC0_OPTO_CL 0x0 +EXP_0_TRG_0_AC1_OPTO_CL_SOL_EVCL 0x0 +EXP_0_TRG_1_AC1_OPTO_CL_SOL_EVCL 0x0 +EXP_0_TRG_0_AC1_OPTO_CL 0x0 +EXP_0_TRG_1_AC1_OPTO_CL 0x0 +EXP_0_TRG_0_AC0_TTL_CL_SOL_BASE 0x0 +EXP_0_TRG_1_AC0_TTL_CL_SOL_BASE 0x0 +EXP_0_TRG_0_AC0_TTL_CL_SOL_EVCL 0x0 +EXP_0_TRG_1_AC0_TTL_CL_SOL_EVCL 0x0 +EXP_0_TRG_0_AC0_TTL_CL 0x0 +EXP_0_TRG_1_AC0_TTL_CL 0x0 +EXP_0_TRG_0_AC1_TTL_CL_SOL_EVCL 0x0 +EXP_0_TRG_1_AC1_TTL_CL_SOL_EVCL 0x0 +EXP_0_TRG_0_AC1_TTL_CL 0x0 +EXP_0_TRG_1_AC1_TTL_CL 0x0 +EXP_0_TRG_2_AC01_TTL_CL_SOL_EVCL 0x0 +EXP_0_TRG_3_AC01_TTL_CL_SOL_EVCL 0x0 +EXP_0_TRG_2_AC01_TTL_CL 0x0 +EXP_0_TRG_3_AC01_TTL_CL 0x0 +EXP_0_TRG_0_AC0_LVDS_CL_SOL_BASE 0x0 +EXP_0_TRG_1_AC0_LVDS_CL_SOL_BASE 0x0 +EXP_0_TRG_0_AC0_LVDS_CL_SOL_EVCL 0x0 +EXP_0_TRG_1_AC0_LVDS_CL_SOL_EVCL 0x0 +EXP_0_TRG_0_AC0_LVDS_CL 0x0 +EXP_0_TRG_1_AC0_LVDS_CL 0x0 +EXP_0_TRG_0_AC1_LVDS_CL_SOL_EVCL 0x0 +EXP_0_TRG_1_AC1_LVDS_CL_SOL_EVCL 0x0 +EXP_0_TRG_0_AC1_LVDS_CL 0x0 +EXP_0_TRG_1_AC1_LVDS_CL 0x0 +EXP_0_TRG_2_AC01_LVDS_CL_SOL_EVCL 0x0 +EXP_0_TRG_3_AC01_LVDS_CL_SOL_EVCL 0x0 +EXP_0_TRG_2_AC01_LVDS_CL 0x0 +EXP_0_TRG_3_AC01_LVDS_CL 0x0 +EXP_0_TRG_1_AC0_OPTO_ANA 0x0 +EXP_0_TRG_1_AC1_OPTO_ANA 0x0 +EXP_0_TRG_1_AC2_OPTO_ANA 0x0 +EXP_0_TRG_1_AC3_OPTO_ANA 0x0 +EXP_0_TRG_0_AC0_TTL_ANA 0x0 +EXP_0_TRG_0_AC1_TTL_ANA 0x0 +EXP_0_TRG_0_AC2_TTL_ANA 0x0 +EXP_0_TRG_0_AC3_TTL_ANA 0x0 +EXP_0_TRG_2_4AC_AUX0_TTL_ANA 0x0 +EXP_0_TRG_3_4AC_AUX1_TTL_ANA 0x0 +EXP_0_TRG_2_4AC_AUX2_TTL_ANA 0x0 +EXP_0_TRG_3_4AC_AUX3_TTL_ANA 0x0 +EXP_0_TRG_2_4AC_AUX4_TTL_ANA 0x0 +EXP_0_TRG_3_4AC_AUX5_TTL_ANA 0x0 +EXP_0_TRG_2_4AC_AUX6_TTL_ANA 0x0 +EXP_0_TRG_3_4AC_AUX7_TTL_ANA 0x0 +EXP_0_TRG_2_4AC_AUX0_LVDS_ANA 0x0 +EXP_0_TRG_3_4AC_AUX1_LVDS_ANA 0x0 +EXP_0_TRG_2_4AC_AUX2_LVDS_ANA 0x0 +EXP_0_TRG_3_4AC_AUX3_LVDS_ANA 0x0 +EXP_0_TRG_2_4AC_AUX4_LVDS_ANA 0x0 +EXP_0_TRG_3_4AC_AUX5_LVDS_ANA 0x0 +EXP_0_TRG_2_4AC_AUX6_LVDS_ANA 0x0 +EXP_0_TRG_3_4AC_AUX7_LVDS_ANA 0x0 +EXP_0_TRG_0_AC0_OPTO_DIG 0x0 +EXP_0_TRG_1_AC0_OPTO_DIG 0x0 +EXP_0_TRG_0_AC1_OPTO_DIG 0x0 +EXP_0_TRG_1_AC1_OPTO_DIG 0x0 +EXP_0_TRG_0_AC2_OPTO_DIG 0x0 +EXP_0_TRG_1_AC2_OPTO_DIG 0x0 +EXP_0_TRG_0_AC3_OPTO_DIG 0x0 +EXP_0_TRG_1_AC3_OPTO_DIG 0x0 +EXP_0_TRG_1_AC0_TTL_DIG 0x0 +EXP_0_TRG_1_AC1_TTL_DIG 0x0 +EXP_0_TRG_1_AC2_TTL_DIG 0x0 +EXP_0_TRG_1_AC3_TTL_DIG 0x0 +EXP_0_TRG_0_AC0_LVDS_DIG 0x0 +EXP_0_TRG_0_AC1_LVDS_DIG 0x0 +EXP_0_TRG_0_AC2_LVDS_DIG 0x0 +EXP_0_TRG_0_AC3_LVDS_DIG 0x0 +EXP_0_TRG_2_AC0_AUX1_TTL_DIG 0x0 +EXP_0_TRG_3_AC0_AUX2_TTL_DIG 0x0 +EXP_0_TRG_2_AC1_AUX1_TTL_DIG 0x0 +EXP_0_TRG_3_AC1_AUX2_TTL_DIG 0x0 +EXP_0_TRG_2_AC2_AUX1_TTL_DIG 0x0 +EXP_0_TRG_3_AC2_AUX2_TTL_DIG 0x0 +EXP_0_TRG_2_AC3_AUX1_TTL_DIG 0x0 +EXP_0_TRG_3_AC3_AUX2_TTL_DIG 0x0 +EXP_0_TRG_2_AC0_AUX1_LVDS_DIG 0x0 +EXP_0_TRG_3_AC0_AUX2_LVDS_DIG 0x0 +EXP_0_TRG_2_AC1_AUX1_LVDS_DIG 0x0 +EXP_0_TRG_3_AC1_AUX2_LVDS_DIG 0x0 +EXP_0_TRG_2_AC2_AUX1_LVDS_DIG 0x0 +EXP_0_TRG_3_AC2_AUX2_LVDS_DIG 0x0 +EXP_0_TRG_2_AC3_AUX1_LVDS_DIG 0x0 +EXP_0_TRG_3_AC3_AUX2_LVDS_DIG 0x0 +EXP_0_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC0_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC0_LVDS_CL_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC1_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC1_LVDS_CL_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_0_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_0_TRG_LVDS_ROTARY_ENCODER 0x0 +EXP_CLK_CLKGEN 0x0 +EXP_CLK_HS 0x0 +EXP_CLK_VS 0x0 +EXP_CLK_TIMER1 0x0 +EXP_CLK_TIMER2 0x0 +EXP_CLK_TIMER3 0x0 +EXP_CLK_AUXIN1_LVDS 0x0 +EXP_CLK_AUXIN3_LVDS 0x0 +EXP_CLK_AUXIN1_AC0_CL 0x0 +EXP_CLK_AUXIN3_AC1_CL 0x0 +EXP_CLK_AUXIN1_AC0_CL_SOL_EVCL 0x0 +EXP_CLK_AUXIN3_AC1_CL_SOL_EVCL 0x0 +EXP_CLK_AUXIN1_AC0_ANA 0x0 +EXP_CLK_AUXIN3_AC1_ANA 0x0 +EXP_CLK_AUXIN5_AC2_ANA 0x0 +EXP_CLK_AUXIN7_AC3_ANA 0x0 +EXP_CLK_AUXIN2_AC0_DIG 0x0 +EXP_CLK_AUXIN2_AC1_DIG 0x0 +EXP_CLK_AUXIN2_AC2_DIG 0x0 +EXP_CLK_AUXIN2_AC3_DIG 0x0 +ARM_EXP_0_CNTEQ0 0x1 +ARM_EXP_0_SOFTWARE 0x0 +ARM_EXP_0_TIMER1 0x0 +ARM_EXP_0_TIMER2 0x0 +ARM_EXP_0_TIMER3 0x0 +ARM_EXP_0_TRG_TIMER0_AC0 0x0 +ARM_EXP_0_TRG_TIMER0_AC1 0x0 +ARM_EXP_0_TRG_TIMER0_AC2 0x0 +ARM_EXP_0_TRG_TIMER0_AC3 0x0 +ARM_EXP_0_HS_PSG 0x0 +ARM_EXP_0_VS_PSG 0x0 +ARM_EXP_0_TRG_2_AC01_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_3_AC01_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_2_AC01_OPTO_CL 0x0 +ARM_EXP_0_TRG_3_AC01_OPTO_CL 0x0 +ARM_EXP_0_TRG_0_AC0_OPTO_CL_SOL_BASE 0x0 +ARM_EXP_0_TRG_1_AC0_OPTO_CL_SOL_BASE 0x0 +ARM_EXP_0_TRG_0_AC0_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_1_AC0_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_0_AC0_OPTO_CL 0x0 +ARM_EXP_0_TRG_1_AC0_OPTO_CL 0x0 +ARM_EXP_0_TRG_0_AC1_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_1_AC1_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_0_AC1_OPTO_CL 0x0 +ARM_EXP_0_TRG_1_AC1_OPTO_CL 0x0 +ARM_EXP_0_TRG_0_AC0_TTL_CL_SOL_BASE 0x0 +ARM_EXP_0_TRG_1_AC0_TTL_CL_SOL_BASE 0x0 +ARM_EXP_0_TRG_0_AC0_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_1_AC0_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_0_AC0_TTL_CL 0x0 +ARM_EXP_0_TRG_1_AC0_TTL_CL 0x0 +ARM_EXP_0_TRG_0_AC1_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_1_AC1_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_0_AC1_TTL_CL 0x0 +ARM_EXP_0_TRG_1_AC1_TTL_CL 0x0 +ARM_EXP_0_TRG_2_AC01_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_3_AC01_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_2_AC01_TTL_CL 0x0 +ARM_EXP_0_TRG_3_AC01_TTL_CL 0x0 +ARM_EXP_0_TRG_0_AC0_LVDS_CL_SOL_BASE 0x0 +ARM_EXP_0_TRG_1_AC0_LVDS_CL_SOL_BASE 0x0 +ARM_EXP_0_TRG_0_AC0_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_1_AC0_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_0_AC0_LVDS_CL 0x0 +ARM_EXP_0_TRG_1_AC0_LVDS_CL 0x0 +ARM_EXP_0_TRG_0_AC1_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_1_AC1_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_0_AC1_LVDS_CL 0x0 +ARM_EXP_0_TRG_1_AC1_LVDS_CL 0x0 +ARM_EXP_0_TRG_2_AC01_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_3_AC01_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_0_TRG_2_AC01_LVDS_CL 0x0 +ARM_EXP_0_TRG_3_AC01_LVDS_CL 0x0 +ARM_EXP_0_TRG_1_AC0_OPTO_ANA 0x0 +ARM_EXP_0_TRG_1_AC1_OPTO_ANA 0x0 +ARM_EXP_0_TRG_1_AC2_OPTO_ANA 0x0 +ARM_EXP_0_TRG_1_AC3_OPTO_ANA 0x0 +ARM_EXP_0_TRG_0_AC0_TTL_ANA 0x0 +ARM_EXP_0_TRG_0_AC1_TTL_ANA 0x0 +ARM_EXP_0_TRG_0_AC2_TTL_ANA 0x0 +ARM_EXP_0_TRG_0_AC3_TTL_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX0_TTL_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX1_TTL_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX2_TTL_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX3_TTL_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX4_TTL_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX5_TTL_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX6_TTL_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX7_TTL_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX0_LVDS_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX1_LVDS_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX2_LVDS_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX3_LVDS_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX4_LVDS_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX5_LVDS_ANA 0x0 +ARM_EXP_0_TRG_2_4AC_AUX6_LVDS_ANA 0x0 +ARM_EXP_0_TRG_3_4AC_AUX7_LVDS_ANA 0x0 +ARM_EXP_0_TRG_0_AC0_OPTO_DIG 0x0 +ARM_EXP_0_TRG_1_AC0_OPTO_DIG 0x0 +ARM_EXP_0_TRG_0_AC1_OPTO_DIG 0x0 +ARM_EXP_0_TRG_1_AC1_OPTO_DIG 0x0 +ARM_EXP_0_TRG_0_AC2_OPTO_DIG 0x0 +ARM_EXP_0_TRG_1_AC2_OPTO_DIG 0x0 +ARM_EXP_0_TRG_0_AC3_OPTO_DIG 0x0 +ARM_EXP_0_TRG_1_AC3_OPTO_DIG 0x0 +ARM_EXP_0_TRG_1_AC0_TTL_DIG 0x0 +ARM_EXP_0_TRG_1_AC1_TTL_DIG 0x0 +ARM_EXP_0_TRG_1_AC2_TTL_DIG 0x0 +ARM_EXP_0_TRG_1_AC3_TTL_DIG 0x0 +ARM_EXP_0_TRG_0_AC0_LVDS_DIG 0x0 +ARM_EXP_0_TRG_0_AC1_LVDS_DIG 0x0 +ARM_EXP_0_TRG_0_AC2_LVDS_DIG 0x0 +ARM_EXP_0_TRG_0_AC3_LVDS_DIG 0x0 +ARM_EXP_0_TRG_2_AC0_AUX1_TTL_DIG 0x0 +ARM_EXP_0_TRG_3_AC0_AUX2_TTL_DIG 0x0 +ARM_EXP_0_TRG_2_AC1_AUX1_TTL_DIG 0x0 +ARM_EXP_0_TRG_3_AC1_AUX2_TTL_DIG 0x0 +ARM_EXP_0_TRG_2_AC2_AUX1_TTL_DIG 0x0 +ARM_EXP_0_TRG_3_AC2_AUX2_TTL_DIG 0x0 +ARM_EXP_0_TRG_2_AC3_AUX1_TTL_DIG 0x0 +ARM_EXP_0_TRG_3_AC3_AUX2_TTL_DIG 0x0 +ARM_EXP_0_TRG_2_AC0_AUX1_LVDS_DIG 0x0 +ARM_EXP_0_TRG_3_AC0_AUX2_LVDS_DIG 0x0 +ARM_EXP_0_TRG_2_AC1_AUX1_LVDS_DIG 0x0 +ARM_EXP_0_TRG_3_AC1_AUX2_LVDS_DIG 0x0 +ARM_EXP_0_TRG_2_AC2_AUX1_LVDS_DIG 0x0 +ARM_EXP_0_TRG_3_AC2_AUX2_LVDS_DIG 0x0 +ARM_EXP_0_TRG_2_AC3_AUX1_LVDS_DIG 0x0 +ARM_EXP_0_TRG_3_AC3_AUX2_LVDS_DIG 0x0 +ARM_EXP_0_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC0_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC0_LVDS_CL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC1_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC1_LVDS_CL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_0_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_0_TRG_LVDS_ROTARY_ENCODER 0x0 +EXP_NOCOMBINE 0x0 +EXP_COMBINE_XOR_T1 0x0 +EXP_COMBINE_XOR_T0AC1 0x0 +EXP_COMBINE_T1 0x0 +EXP_0_NOCOMBINE_AC0_CL_SOL_BASE_HD_CC 0x0 +EXP_0_COMBINE_XOR_T1_AC0_CL_SOL_BASE_HD_CC 0x0 +EXP_0_COMBINE_T1_AC0_CL_SOL_BASE_HD_CC 0x0 +EXP_0_NOCOMBINE_AC0_CL_HD_CC 0x1 +EXP_0_COMBINE_XOR_T1_AC0_CL_HD_CC 0x0 +EXP_0_COMBINE_T1_AC0_CL_HD_CC 0x0 +EXP_0_NOCOMBINE_AC1_CL_HD_CC 0x0 +EXP_0_COMBINE_XOR_T1_AC1_CL_HD_CC 0x0 +EXP_0_COMBINE_T1_AC1_CL_HD_CC 0x0 +EXP_0_NOCOMBINE_CL_CC 0x0 +EXP_0_COMBINE_XOR_T1_CL_CC 0x0 +EXP_0_COMBINE_T1_CL_CC 0x0 +EXP_0_NOCOMBINE_AC0_ANA_HD_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC0_ANA_HD_DVI 0x0 +EXP_0_COMBINE_T1_AC0_ANA_HD_DVI 0x0 +EXP_0_NOCOMBINE_AC1_ANA_HD_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC1_ANA_HD_DVI 0x0 +EXP_0_COMBINE_T1_AC1_ANA_HD_DVI 0x0 +EXP_0_NOCOMBINE_AC2_ANA_HD_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC2_ANA_HD_DVI 0x0 +EXP_0_COMBINE_T1_AC2_ANA_HD_DVI 0x0 +EXP_0_NOCOMBINE_AC3_ANA_HD_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC3_ANA_HD_DVI 0x0 +EXP_0_COMBINE_T1_AC3_ANA_HD_DVI 0x0 +EXP_0_NOCOMBINE_AC0_ANA_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC0_ANA_DVI 0x0 +EXP_0_COMBINE_T1_AC0_ANA_DVI 0x0 +EXP_0_NOCOMBINE_AC1_ANA_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC1_ANA_DVI 0x0 +EXP_0_COMBINE_T1_AC1_ANA_DVI 0x0 +EXP_0_NOCOMBINE_AC2_ANA_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC2_ANA_DVI 0x0 +EXP_0_COMBINE_T1_AC2_ANA_DVI 0x0 +EXP_0_NOCOMBINE_AC3_ANA_DVI 0x0 +EXP_0_COMBINE_XOR_T1_AC3_ANA_DVI 0x0 +EXP_0_COMBINE_T1_AC3_ANA_DVI 0x0 +EXP_0_NOCOMBINE_AC0_DIG_HD_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC0_DIG_HD_DCON 0x0 +EXP_0_COMBINE_T1_AC0_DIG_HD_DCON 0x0 +EXP_0_NOCOMBINE_AC1_DIG_HD_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC1_DIG_HD_DCON 0x0 +EXP_0_COMBINE_T1_AC1_DIG_HD_DCON 0x0 +EXP_0_NOCOMBINE_AC2_DIG_HD_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC2_DIG_HD_DCON 0x0 +EXP_0_COMBINE_T1_AC2_DIG_HD_DCON 0x0 +EXP_0_NOCOMBINE_AC3_DIG_HD_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC3_DIG_HD_DCON 0x0 +EXP_0_COMBINE_T1_AC3_DIG_HD_DCON 0x0 +EXP_0_NOCOMBINE_AC0_DIG_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC0_DIG_DCON 0x0 +EXP_0_COMBINE_T1_AC0_DIG_DCON 0x0 +EXP_0_NOCOMBINE_AC1_DIG_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC1_DIG_DCON 0x0 +EXP_0_COMBINE_T1_AC1_DIG_DCON 0x0 +EXP_0_NOCOMBINE_AC2_DIG_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC2_DIG_DCON 0x0 +EXP_0_COMBINE_T1_AC2_DIG_DCON 0x0 +EXP_0_NOCOMBINE_AC3_DIG_DCON 0x0 +EXP_0_COMBINE_XOR_T1_AC3_DIG_DCON 0x0 +EXP_0_COMBINE_T1_AC3_DIG_DCON 0x0 +EXP_PRESCALE1_1 0x0 +EXP_PRESCALE1_2 0x0 +EXP_PRESCALE1_4 0x0 +EXP_PRESCALE1_8 0x0 +EXP_PRESCALE1_16 0x0 +EXP_TRG_TTL_TIMER1 0x0 +EXP_TRG_TTL_TIMER2 0x0 +EXP_TRG_CNTEQ0_TIMER1 0x0 +EXP_TRG_TIMER0_2 0x0 +EXP_TRG_TIMER2_2 0x0 +EXP_TRG_TIMER3_2 0x0 +EXP_1_TRG_TIMER1_AC0 0x0 +EXP_1_TRG_TIMER1_AC1 0x0 +EXP_1_TRG_TIMER1_AC2 0x0 +EXP_1_TRG_TIMER1_AC3 0x0 +EXP_1_TRG_2_AC01_OPTO_CL_SOL_EVCL 0x0 +EXP_1_TRG_3_AC01_OPTO_CL_SOL_EVCL 0x0 +EXP_1_TRG_2_AC01_OPTO_CL 0x0 +EXP_1_TRG_3_AC01_OPTO_CL 0x0 +EXP_1_TRG_0_AC0_OPTO_CL_SOL_BASE 0x0 +EXP_1_TRG_1_AC0_OPTO_CL_SOL_BASE 0x0 +EXP_1_TRG_0_AC0_OPTO_CL_SOL_EVCL 0x0 +EXP_1_TRG_1_AC0_OPTO_CL_SOL_EVCL 0x0 +EXP_1_TRG_0_AC0_OPTO_CL 0x0 +EXP_1_TRG_1_AC0_OPTO_CL 0x0 +EXP_1_TRG_0_AC1_OPTO_CL_SOL_EVCL 0x0 +EXP_1_TRG_1_AC1_OPTO_CL_SOL_EVCL 0x0 +EXP_1_TRG_0_AC1_OPTO_CL 0x0 +EXP_1_TRG_1_AC1_OPTO_CL 0x0 +EXP_1_TRG_0_AC0_TTL_CL_SOL_BASE 0x0 +EXP_1_TRG_1_AC0_TTL_CL_SOL_BASE 0x0 +EXP_1_TRG_0_AC0_TTL_CL_SOL_EVCL 0x0 +EXP_1_TRG_1_AC0_TTL_CL_SOL_EVCL 0x0 +EXP_1_TRG_0_AC0_TTL_CL 0x0 +EXP_1_TRG_1_AC0_TTL_CL 0x0 +EXP_1_TRG_0_AC1_TTL_CL_SOL_EVCL 0x0 +EXP_1_TRG_1_AC1_TTL_CL_SOL_EVCL 0x0 +EXP_1_TRG_0_AC1_TTL_CL 0x0 +EXP_1_TRG_1_AC1_TTL_CL 0x0 +EXP_1_TRG_2_AC01_TTL_CL_SOL_EVCL 0x0 +EXP_1_TRG_3_AC01_TTL_CL_SOL_EVCL 0x0 +EXP_1_TRG_2_AC01_TTL_CL 0x0 +EXP_1_TRG_3_AC01_TTL_CL 0x0 +EXP_1_TRG_0_AC0_LVDS_CL_SOL_BASE 0x0 +EXP_1_TRG_1_AC0_LVDS_CL_SOL_BASE 0x0 +EXP_1_TRG_0_AC0_LVDS_CL_SOL_EVCL 0x0 +EXP_1_TRG_1_AC0_LVDS_CL_SOL_EVCL 0x0 +EXP_1_TRG_0_AC0_LVDS_CL 0x0 +EXP_1_TRG_1_AC0_LVDS_CL 0x0 +EXP_1_TRG_0_AC1_LVDS_CL_SOL_EVCL 0x0 +EXP_1_TRG_1_AC1_LVDS_CL_SOL_EVCL 0x0 +EXP_1_TRG_0_AC1_LVDS_CL 0x0 +EXP_1_TRG_1_AC1_LVDS_CL 0x0 +EXP_1_TRG_2_AC01_LVDS_CL_SOL_EVCL 0x0 +EXP_1_TRG_3_AC01_LVDS_CL_SOL_EVCL 0x0 +EXP_1_TRG_2_AC01_LVDS_CL 0x0 +EXP_1_TRG_3_AC01_LVDS_CL 0x0 +EXP_1_TRG_1_AC0_OPTO_ANA 0x0 +EXP_1_TRG_1_AC1_OPTO_ANA 0x0 +EXP_1_TRG_1_AC2_OPTO_ANA 0x0 +EXP_1_TRG_1_AC3_OPTO_ANA 0x0 +EXP_1_TRG_0_AC0_TTL_ANA 0x0 +EXP_1_TRG_0_AC1_TTL_ANA 0x0 +EXP_1_TRG_0_AC2_TTL_ANA 0x0 +EXP_1_TRG_0_AC3_TTL_ANA 0x0 +EXP_1_TRG_2_4AC_AUX0_TTL_ANA 0x0 +EXP_1_TRG_3_4AC_AUX1_TTL_ANA 0x0 +EXP_1_TRG_2_4AC_AUX2_TTL_ANA 0x0 +EXP_1_TRG_3_4AC_AUX3_TTL_ANA 0x0 +EXP_1_TRG_2_4AC_AUX4_TTL_ANA 0x0 +EXP_1_TRG_3_4AC_AUX5_TTL_ANA 0x0 +EXP_1_TRG_2_4AC_AUX6_TTL_ANA 0x0 +EXP_1_TRG_3_4AC_AUX7_TTL_ANA 0x0 +EXP_1_TRG_2_4AC_AUX0_LVDS_ANA 0x0 +EXP_1_TRG_3_4AC_AUX1_LVDS_ANA 0x0 +EXP_1_TRG_2_4AC_AUX2_LVDS_ANA 0x0 +EXP_1_TRG_3_4AC_AUX3_LVDS_ANA 0x0 +EXP_1_TRG_2_4AC_AUX4_LVDS_ANA 0x0 +EXP_1_TRG_3_4AC_AUX5_LVDS_ANA 0x0 +EXP_1_TRG_2_4AC_AUX6_LVDS_ANA 0x0 +EXP_1_TRG_3_4AC_AUX7_LVDS_ANA 0x0 +EXP_1_TRG_0_AC0_OPTO_DIG 0x0 +EXP_1_TRG_1_AC0_OPTO_DIG 0x0 +EXP_1_TRG_0_AC1_OPTO_DIG 0x0 +EXP_1_TRG_1_AC1_OPTO_DIG 0x0 +EXP_1_TRG_0_AC2_OPTO_DIG 0x0 +EXP_1_TRG_1_AC2_OPTO_DIG 0x0 +EXP_1_TRG_0_AC3_OPTO_DIG 0x0 +EXP_1_TRG_1_AC3_OPTO_DIG 0x0 +EXP_1_TRG_1_AC0_TTL_DIG 0x0 +EXP_1_TRG_1_AC1_TTL_DIG 0x0 +EXP_1_TRG_1_AC2_TTL_DIG 0x0 +EXP_1_TRG_1_AC3_TTL_DIG 0x0 +EXP_1_TRG_0_AC0_LVDS_DIG 0x0 +EXP_1_TRG_0_AC1_LVDS_DIG 0x0 +EXP_1_TRG_0_AC2_LVDS_DIG 0x0 +EXP_1_TRG_0_AC3_LVDS_DIG 0x0 +EXP_1_TRG_2_AC0_AUX1_TTL_DIG 0x0 +EXP_1_TRG_3_AC0_AUX2_TTL_DIG 0x0 +EXP_1_TRG_2_AC1_AUX1_TTL_DIG 0x0 +EXP_1_TRG_3_AC1_AUX2_TTL_DIG 0x0 +EXP_1_TRG_2_AC2_AUX1_TTL_DIG 0x0 +EXP_1_TRG_3_AC2_AUX2_TTL_DIG 0x0 +EXP_1_TRG_2_AC3_AUX1_TTL_DIG 0x0 +EXP_1_TRG_3_AC3_AUX2_TTL_DIG 0x0 +EXP_1_TRG_2_AC0_AUX1_LVDS_DIG 0x0 +EXP_1_TRG_3_AC0_AUX2_LVDS_DIG 0x0 +EXP_1_TRG_2_AC1_AUX1_LVDS_DIG 0x0 +EXP_1_TRG_3_AC1_AUX2_LVDS_DIG 0x0 +EXP_1_TRG_2_AC2_AUX1_LVDS_DIG 0x0 +EXP_1_TRG_3_AC2_AUX2_LVDS_DIG 0x0 +EXP_1_TRG_2_AC3_AUX1_LVDS_DIG 0x0 +EXP_1_TRG_3_AC3_AUX2_LVDS_DIG 0x0 +EXP_1_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC0_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC0_LVDS_CL_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC1_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC1_LVDS_CL_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +EXP_1_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +EXP_1_TRG_LVDS_ROTARY_ENCODER 0x0 +EXP_CLK_2_CLKGEN 0x0 +EXP_CLK_2_HS 0x0 +EXP_CLK_2_VS 0x0 +EXP_CLK_2_TIMER0 0x0 +EXP_CLK_2_TIMER2 0x0 +EXP_CLK_2_TIMER3 0x0 +EXP_CLK_2_AUXIN1_LVDS 0x0 +EXP_CLK_2_AUXIN3_LVDS 0x0 +EXP_CLK_2_AUXIN1_AC0_CL 0x0 +EXP_CLK_2_AUXIN3_AC1_CL 0x0 +EXP_CLK_2_AUXIN1_AC0_CL_SOL_EVCL 0x0 +EXP_CLK_2_AUXIN3_AC1_CL_SOL_EVCL 0x0 +EXP_CLK_2_AUXIN1_AC0_ANA 0x0 +EXP_CLK_2_AUXIN3_AC1_ANA 0x0 +EXP_CLK_2_AUXIN5_AC2_ANA 0x0 +EXP_CLK_2_AUXIN7_AC3_ANA 0x0 +EXP_CLK_2_AUXIN2_AC0_DIG 0x0 +EXP_CLK_2_AUXIN2_AC1_DIG 0x0 +EXP_CLK_2_AUXIN2_AC2_DIG 0x0 +EXP_CLK_2_AUXIN2_AC3_DIG 0x0 +ARM_EXP_1_CNTEQ0 0x1 +ARM_EXP_1_SOFTWARE 0x0 +ARM_EXP_1_TIMER0 0x0 +ARM_EXP_1_TIMER2 0x0 +ARM_EXP_1_TIMER3 0x0 +ARM_EXP_1_TRG_TIMER1_AC0 0x0 +ARM_EXP_1_TRG_TIMER1_AC1 0x0 +ARM_EXP_1_TRG_TIMER1_AC2 0x0 +ARM_EXP_1_TRG_TIMER1_AC3 0x0 +ARM_EXP_1_HS_PSG 0x0 +ARM_EXP_1_VS_PSG 0x0 +ARM_EXP_1_TRG_2_AC01_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_3_AC01_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_2_AC01_OPTO_CL 0x0 +ARM_EXP_1_TRG_3_AC01_OPTO_CL 0x0 +ARM_EXP_1_TRG_0_AC0_OPTO_CL_SOL_BASE 0x0 +ARM_EXP_1_TRG_1_AC0_OPTO_CL_SOL_BASE 0x0 +ARM_EXP_1_TRG_0_AC0_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_1_AC0_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_0_AC0_OPTO_CL 0x0 +ARM_EXP_1_TRG_1_AC0_OPTO_CL 0x0 +ARM_EXP_1_TRG_0_AC1_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_1_AC1_OPTO_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_0_AC1_OPTO_CL 0x0 +ARM_EXP_1_TRG_1_AC1_OPTO_CL 0x0 +ARM_EXP_1_TRG_0_AC0_TTL_CL_SOL_BASE 0x0 +ARM_EXP_1_TRG_1_AC0_TTL_CL_SOL_BASE 0x0 +ARM_EXP_1_TRG_0_AC0_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_1_AC0_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_0_AC0_TTL_CL 0x0 +ARM_EXP_1_TRG_1_AC0_TTL_CL 0x0 +ARM_EXP_1_TRG_0_AC1_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_1_AC1_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_0_AC1_TTL_CL 0x0 +ARM_EXP_1_TRG_1_AC1_TTL_CL 0x0 +ARM_EXP_1_TRG_2_AC01_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_3_AC01_TTL_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_2_AC01_TTL_CL 0x0 +ARM_EXP_1_TRG_3_AC01_TTL_CL 0x0 +ARM_EXP_1_TRG_0_AC0_LVDS_CL_SOL_BASE 0x0 +ARM_EXP_1_TRG_1_AC0_LVDS_CL_SOL_BASE 0x0 +ARM_EXP_1_TRG_0_AC0_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_1_AC0_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_0_AC0_LVDS_CL 0x0 +ARM_EXP_1_TRG_1_AC0_LVDS_CL 0x0 +ARM_EXP_1_TRG_0_AC1_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_1_AC1_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_0_AC1_LVDS_CL 0x0 +ARM_EXP_1_TRG_1_AC1_LVDS_CL 0x0 +ARM_EXP_1_TRG_2_AC01_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_3_AC01_LVDS_CL_SOL_EVCL 0x0 +ARM_EXP_1_TRG_2_AC01_LVDS_CL 0x0 +ARM_EXP_1_TRG_3_AC01_LVDS_CL 0x0 +ARM_EXP_1_TRG_1_AC0_OPTO_ANA 0x0 +ARM_EXP_1_TRG_1_AC1_OPTO_ANA 0x0 +ARM_EXP_1_TRG_1_AC2_OPTO_ANA 0x0 +ARM_EXP_1_TRG_1_AC3_OPTO_ANA 0x0 +ARM_EXP_1_TRG_0_AC0_TTL_ANA 0x0 +ARM_EXP_1_TRG_0_AC1_TTL_ANA 0x0 +ARM_EXP_1_TRG_0_AC2_TTL_ANA 0x0 +ARM_EXP_1_TRG_0_AC3_TTL_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX0_TTL_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX1_TTL_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX2_TTL_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX3_TTL_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX4_TTL_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX5_TTL_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX6_TTL_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX7_TTL_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX0_LVDS_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX1_LVDS_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX2_LVDS_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX3_LVDS_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX4_LVDS_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX5_LVDS_ANA 0x0 +ARM_EXP_1_TRG_2_4AC_AUX6_LVDS_ANA 0x0 +ARM_EXP_1_TRG_3_4AC_AUX7_LVDS_ANA 0x0 +ARM_EXP_1_TRG_0_AC0_OPTO_DIG 0x0 +ARM_EXP_1_TRG_1_AC0_OPTO_DIG 0x0 +ARM_EXP_1_TRG_0_AC1_OPTO_DIG 0x0 +ARM_EXP_1_TRG_1_AC1_OPTO_DIG 0x0 +ARM_EXP_1_TRG_0_AC2_OPTO_DIG 0x0 +ARM_EXP_1_TRG_1_AC2_OPTO_DIG 0x0 +ARM_EXP_1_TRG_0_AC3_OPTO_DIG 0x0 +ARM_EXP_1_TRG_1_AC3_OPTO_DIG 0x0 +ARM_EXP_1_TRG_1_AC0_TTL_DIG 0x0 +ARM_EXP_1_TRG_1_AC1_TTL_DIG 0x0 +ARM_EXP_1_TRG_1_AC2_TTL_DIG 0x0 +ARM_EXP_1_TRG_1_AC3_TTL_DIG 0x0 +ARM_EXP_1_TRG_0_AC0_LVDS_DIG 0x0 +ARM_EXP_1_TRG_0_AC1_LVDS_DIG 0x0 +ARM_EXP_1_TRG_0_AC2_LVDS_DIG 0x0 +ARM_EXP_1_TRG_0_AC3_LVDS_DIG 0x0 +ARM_EXP_1_TRG_2_AC0_AUX1_TTL_DIG 0x0 +ARM_EXP_1_TRG_3_AC0_AUX2_TTL_DIG 0x0 +ARM_EXP_1_TRG_2_AC1_AUX1_TTL_DIG 0x0 +ARM_EXP_1_TRG_3_AC1_AUX2_TTL_DIG 0x0 +ARM_EXP_1_TRG_2_AC2_AUX1_TTL_DIG 0x0 +ARM_EXP_1_TRG_3_AC2_AUX2_TTL_DIG 0x0 +ARM_EXP_1_TRG_2_AC3_AUX1_TTL_DIG 0x0 +ARM_EXP_1_TRG_3_AC3_AUX2_TTL_DIG 0x0 +ARM_EXP_1_TRG_2_AC0_AUX1_LVDS_DIG 0x0 +ARM_EXP_1_TRG_3_AC0_AUX2_LVDS_DIG 0x0 +ARM_EXP_1_TRG_2_AC1_AUX1_LVDS_DIG 0x0 +ARM_EXP_1_TRG_3_AC1_AUX2_LVDS_DIG 0x0 +ARM_EXP_1_TRG_2_AC2_AUX1_LVDS_DIG 0x0 +ARM_EXP_1_TRG_3_AC2_AUX2_LVDS_DIG 0x0 +ARM_EXP_1_TRG_2_AC3_AUX1_LVDS_DIG 0x0 +ARM_EXP_1_TRG_3_AC3_AUX2_LVDS_DIG 0x0 +ARM_EXP_1_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC0_LVDS_CL_SOL_BASE_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC0_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC0_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC0_LVDS_CL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC1_LVDS_CL_SOL_EVCL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC1_LVDS_CL_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC1_LVDS_CL_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC0_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC1_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC2_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC3_LVDS_ANA_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC0_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC1_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC2_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_FOW 0x0 +ARM_EXP_1_TRG_AC3_LVDS_DIG_ROTARY_ENCODER_REV 0x0 +ARM_EXP_1_TRG_LVDS_ROTARY_ENCODER 0x0 +EXP_NOCOMBINE_2 0x0 +EXP_COMBINE_2_XOR_T0 0x0 +EXP_COMBINE_2_XOR_T1AC1 0x0 +EXP_COMBINE_2_T0 0x0 +EXP_1_NOCOMBINE_AC0_CL_SOL_BASE_HD_CC 0x0 +EXP_1_COMBINE_XOR_T0_AC0_CL_SOL_BASE_HD_CC 0x0 +EXP_1_COMBINE_T0_AC0_CL_SOL_BASE_HD_CC 0x0 +EXP_1_NOCOMBINE_AC0_CL_HD_CC 0x1 +EXP_1_COMBINE_XOR_T0_AC0_CL_HD_CC 0x0 +EXP_1_COMBINE_T0_AC0_CL_HD_CC 0x0 +EXP_1_NOCOMBINE_AC1_CL_HD_CC 0x0 +EXP_1_COMBINE_XOR_T0_AC1_CL_HD_CC 0x0 +EXP_1_COMBINE_T0_AC1_CL_HD_CC 0x0 +EXP_1_NOCOMBINE_CL_CC 0x0 +EXP_1_COMBINE_XOR_T0_CL_CC 0x0 +EXP_1_COMBINE_T0_CL_CC 0x0 +EXP_1_NOCOMBINE_AC0_ANA_HD 0x0 +EXP_1_COMBINE_XOR_T0_AC0_ANA_HD 0x0 +EXP_1_COMBINE_T0_AC0_ANA_HD 0x0 +EXP_1_NOCOMBINE_AC1_ANA_HD 0x0 +EXP_1_COMBINE_XOR_T0_AC1_ANA_HD 0x0 +EXP_1_COMBINE_T0_AC1_ANA_HD 0x0 +EXP_1_NOCOMBINE_AC2_ANA_HD 0x0 +EXP_1_COMBINE_XOR_T0_AC2_ANA_HD 0x0 +EXP_1_COMBINE_T0_AC2_ANA_HD 0x0 +EXP_1_NOCOMBINE_AC3_ANA_HD 0x0 +EXP_1_COMBINE_XOR_T0_AC3_ANA_HD 0x0 +EXP_1_COMBINE_T0_AC3_ANA_HD 0x0 +EXP_1_NOCOMBINE_AC0_DIG_DCON 0x0 +EXP_1_COMBINE_XOR_T0_AC0_DIG_DCON 0x0 +EXP_1_COMBINE_T0_AC0_DIG_DCON 0x0 +EXP_1_NOCOMBINE_AC1_DIG_DCON 0x0 +EXP_1_COMBINE_XOR_T0_AC1_DIG_DCON 0x0 +EXP_1_COMBINE_T0_AC1_DIG_DCON 0x0 +EXP_1_NOCOMBINE_AC2_DIG_DCON 0x0 +EXP_1_COMBINE_XOR_T0_AC2_DIG_DCON 0x0 +EXP_1_COMBINE_T0_AC2_DIG_DCON 0x0 +EXP_1_NOCOMBINE_AC3_DIG_DCON 0x0 +EXP_1_COMBINE_XOR_T0_AC3_DIG_DCON 0x0 +EXP_1_COMBINE_T0_AC3_DIG_DCON 0x0 +EXP_PRESCALE2_1 0x0 +EXP_PRESCALE2_2 0x0 +EXP_PRESCALE2_4 0x0 +EXP_PRESCALE2_8 0x0 +EXP_PRESCALE2_16 0x0 +DEF_ODYSSEY_CL 0x0 +DEF_ODYSSEY_CL_DUAL 0x0 +DEF_ODYSSEY_ANA 0x0 +DEF_ODYSSEY_DIG 0x0 +DEF_HELIOS_CL 0x1 +DEF_HELIOS_CL_DUAL 0x0 +DEF_HELIOS_ANA 0x0 +DEF_HELIOS_DIG 0x0 +DEF_SOLIOS_CL_FULL 0x0 +DEF_SOLIOS_CL_MEDIUM 0x0 +DEF_SOLIOS_CL_DUAL 0x0 +DEF_SOLIOS_CL_BASE 0x0 +DEF_SOLIOS_CL_DUAL_EVCL 0x0 +DEF_SOLIOS_CL_MEDIUM_EVCL 0x0 +DEF_SOLIOS_CL_FULL_EVCL 0x0 +DEF_SOLIOS_CL_DUAL_EMCL 0x0 +DEF_SOLIOS_CL_MEDIUM_EMCL 0x0 +DEF_SOLIOS_CL_FULL_EMCL 0x0 +DEF_SOLIOS_CL_EVCL 0x0 +DEF_SOLIOS_ANA 0x0 +DEF_SOLIOS_DIG 0x0 +DEF_AC0_PROGRAMMED 0x1 +DEF_AC1_PROGRAMMED 0x0 +DEF_AC2_PROGRAMMED 0x0 +DEF_AC3_PROGRAMMED 0x0 +DEF_AC0_CL_TRG2_TTL_ACTIF 0x0 +DEF_AC1_CL_TRG3_TTL_ACTIF 0x0 +DEF_HTOTAL_ENTRY 0x400 +DEF_HACTIVE_ENTRY 0x400 +DEF_VTOTAL_ENTRY 0x800 +DEF_VACTIVE_ENTRY 0x800 +DEF_CL_NEW_HCROPPING 0x0 +DEF_CL_NEW_VCROPPING 0x0 +DEF_DLY_ANA_FACTOR 0x0 +DEF_CLOCK_DELAY_ANA 0x2710 +DEF_PCK_DELAY_STEP 0x0 +DEF_HDELAY 0x0 +DEF_ERR_MIN_HSYNC_PLL_LOCK 0x0 +DEF_ADJUST_PLUS_HOTAL 0x0 +DEF_ADJUST_PLUS_HDLY_HSVAL 0x0 +DEF_ADJUST_MINUS_HDLY_HSVAL 0x0 +DEF_ADJUST_PLUS_HDLY_HEVAL 0x0 +DEF_ADJUST_MINUS_HDLY_HEVAL 0x0 +DEF_NTSC 0x0 +DEF_PAL 0x0 +DEF_CCIR601 0x0 +DEF_SLOW_SCAN_PCK_OTHER_CHSYNC_DVI 0x0 +DEF_SLOW_SCAN_HSYNC_OTHER_CON_DVI_AUX 0x0 +DEF_HSUBSEL_REGVALUE 0x0 +DEF_MONO_CAM 0x1 +DEF_COLOR_CAM 0x0 +DEF_VACTIVE_ODD 0x0 +DEF_VSTART_ODD 0x0 +DEF_VTOTAL_ENTRY_NOTSTD 0x1 +DEF_VDELAY_MIN 0x0 +DEF_VINTRL_ODD_EVEN 0x0 +DEF_VSVAL_EQUA_ZERO 0x1 +DEF_VEVAL_EQUA_VTOTAL 0x1 +DEF_ANA_SYC_DIG_FOLLOW_VIDEO 0x0 +DEF_MIN_CNT_CLAMP 0x11 +DEF_MIN_CLP_MARGIN 0x8 +DEF_HCLAMP_MARGIN 0x0 +DEF_MIN_CNT_CLAMP_REACHED 0x0 +DEF_MINUS_CNT_CLAMP_REACHED 0x0 +DEF_ADD_HCLAMP_COMPENSATION 0x0 +DEF_ADD_HSCLAMP_COMPENSATION 0x0 +DEF_ADD_HECLAMP_COMPENSATION 0x0 +DEF_MINUS_HSCLAMP_COMPENSATION 0x0 +DEF_MINUS_HECLAMP_COMPENSATION 0x0 +DEF_SOLIOS_MINUS_HCLAMP_COMP 0x0 +DEF_DIGITIZER_MASTER 0x0 +DEF_ERR_HCLAMP_MIN 0x0 +DEF_CASE_HVBLANK_ZERO 0x1 +DEF_ADD_3MAX_TOTAL_HVBLANK_ZERO 0x3 +DEF_ADD_HTOTAL_EQUA_HEVAL 0x0 +DEF_ERR_NGHECNT_HTOTAL_MIN 0x0 +DEF_HFPORCH_MIN_ANA 0x0 +DEF_TEST_MODE_HBP_MIN 0x0 +DEF_TEST_MODE_HFP_MIN 0x0 +DEF_TEST_MODE_HSY_HBP_MIN_CL 0x0 +DEF_TEST_MODE_VFP_MIN 0x0 +DEF_TEST_MODE_VBP_MIN 0x0 +DEF_TEST_MODE_VS_VBP_MIN_ANA_DIG_CL 0x0 +DEF_HSVAL_EQUA_ZERO 0x1 +DEF_HEVAL_EQUA_HTOTAL 0x0 +DEF_VAL_SOFSEL 0x0 +DEF_ANA_TANDEM_MODE 0x0 +DEF_TIMER0_ENABLED 0x0 +DEF_TIMER1_ENABLED 0x0 +DEF_TIMER0_TRIGGERS_PIPE_DELAY 0x0 +DEF_TIMER1_TRIGGERS_PIPE_DELAY 0x0 +DEF_TIMER0_CLK_NOTAV 0x0 +DEF_TIMER1_CLK_NOTAV 0x0 +DEF_TIMER0_FREQ_NO_T1CLK 0x0 +DEF_TIMER1_FREQ_NO_T0CLK 0x0 +DEF_TIMER0_FREQ 0x0 +DEF_TIMER1_FREQ 0x0 +DEF_TIMER0_AUX_CLK_IN 0x0 +DEF_TIMER1_AUX_CLK_2_IN 0x0 +DEF_TIMER0_PIPE_DELAY1 0x0 +DEF_TIMER1_PIPE_DELAY1 0x0 +DEF_TMR0_CLKTMR1_CNT 0x0 +DEF_TMR1_CLKTMR0_CNT 0x0 +DEF_VALUE_EXP_0_DELAY1 0x0 +DEF_VALUE_EXP_0_DELAY2 0x0 +DEF_VALUE_EXP_0_TIME1 0x0 +DEF_VALUE_EXP_0_TIME2 0x0 +DEF_VALUE_EXP_1_DELAY1 0x0 +DEF_VALUE_EXP_1_DELAY2 0x0 +DEF_VALUE_EXP_1_TIME1 0x0 +DEF_VALUE_EXP_1_TIME2 0x0 +DEF_TIMER0_MAX_CNT_TIM_DLY 0x0 +DEF_TIMER1_MAX_CNT_TIM_DLY 0x0 +DEF_OVRF_EXP0_DELAY1 0x0 +DEF_OVRF_EXP0_DELAY2 0x0 +DEF_OVRF_EXP0_TIME1 0x0 +DEF_OVRF_EXP0_TIME2 0x0 +DEF_OVRF_EXP1_DELAY1 0x0 +DEF_OVRF_EXP1_DELAY2 0x0 +DEF_OVRF_EXP1_TIME1 0x0 +DEF_OVRF_EXP1_TIME2 0x0 +DEF_TIMER0_CNT_OVERFLOW 0x0 +DEF_TIMER1_CNT_OVERFLOW 0x0 +DEF_TIMER0_T1CLK_PERD_FREQ 0x1 +DEF_TIMER1_T0CLK_PERD_FREQ 0x1 +DEF_TMR0_CLKFREQ_LESS_EQU_TRGFREQ 0x0 +DEF_TMR1_CLKFREQ_LESS_EQU_TRGFREQ 0x0 +DEF_HW_CHANNEL_USED 0x1 +DEF_ATTENUATOR 0x1 +DEF_CODE_GAIN 0x5b7 +DEF_CODE_OFFSET 0x800 +DEF_CL_BUS_WIDTH 0xc +DEF_CL_NUM_TAPS 0x2 +DEF_ERR_BUS_WIDTH 0x0 +DEF_GRAB_PSG_CHANGE_ERROR 0x0 +DEF_EXP0_PSG_CHANGE_ERROR 0x0 +DEF_ARM_EXP0_PSG_CHANGE_ERROR 0x0 +DEF_EXP1_PSG_CHANGE_ERROR 0x0 +DEF_ARM_EXP1_PSG_CHANGE_ERROR 0x0 +DEF_ERR_INTERNAL_TRG0_2_FORMATS_SEL 0x0 +DEF_ERR_INTERNAL_TRG1_2_FORMATS_SEL 0x0 +DEF_ERR_INTERNAL_TRG2_2_FORMATS_SEL 0x0 +DEF_ERR_INTERNAL_TRG3_2_FORMATS_SEL 0x0 +DEF_ERR_TRIGGER2_PATH_CONFLICT 0x0 +DEF_ERR_TRIGGER3_PATH_CONFLICT 0x0 +DEF_ROTARY_CL_HCNT_LD_ARM_AC01_NOT_REV 0x1 +DEF_ROTARY_CL_GRB_AC01_NOT_REV 0x1 +DEF_ROTARY_CL_EXP0_AC01_NOT_REV 0x1 +DEF_ROTARY_CL_EXP1_AC01_NOT_REV 0x1 +DEF_ROTARY_CL_AEXP0_AC01_NOT_REV 0x1 +DEF_ROTARY_CL_AEXP1_AC01_NOT_REV 0x1 +DEF_ROTARY_CL_HCNT_LD_ARM_AC01_NOT_FOW 0x1 +DEF_ROTARY_CL_GRB_AC01_NOT_FOW 0x1 +DEF_ROTARY_CL_EXP0_AC01_NOT_FOW 0x1 +DEF_ROTARY_CL_EXP1_AC01_NOT_FOW 0x1 +DEF_ROTARY_CL_AEXP0_AC01_NOT_FOW 0x1 +DEF_ROTARY_CL_AEXP1_AC01_NOT_FOW 0x1 +DEF_ROTARY_ANA_HCNT_LD_ARM_AC03_NOT_REV 0x1 +DEF_ROTARY_ANA_GRB_AC03_NOT_REV 0x1 +DEF_ROTARY_ANA_EXP0_AC03_NOT_REV 0x1 +DEF_ROTARY_ANA_EXP1_AC03_NOT_REV 0x1 +DEF_ROTARY_ANA_AEXP0_AC03_NOT_REV 0x1 +DEF_ROTARY_ANA_AEXP1_AC03_NOT_REV 0x1 +DEF_ROTARY_ANA_HCNT_LD_ARM_AC03_NOT_FOW 0x1 +DEF_ROTARY_ANA_GRB_AC03_NOT_FOW 0x1 +DEF_ROTARY_ANA_EXP0_AC03_NOT_FOW 0x1 +DEF_ROTARY_ANA_EXP1_AC03_NOT_FOW 0x1 +DEF_ROTARY_ANA_AEXP0_AC03_NOT_FOW 0x1 +DEF_ROTARY_ANA_AEXP1_AC03_NOT_FOW 0x1 +DEF_ROTARY_DIG_HCNT_LD_ARM_AC03_NOT_REV 0x1 +DEF_ROTARY_DIG_GRB_AC03_NOT_REV 0x1 +DEF_ROTARY_DIG_EXP0_AC03_NOT_REV 0x1 +DEF_ROTARY_DIG_EXP1_AC03_NOT_REV 0x1 +DEF_ROTARY_DIG_AEXP0_AC03_NOT_REV 0x1 +DEF_ROTARY_DIG_AEXP1_AC03_NOT_REV 0x1 +DEF_ROTARY_DIG_HCNT_LD_ARM_AC03_NOT_FOW 0x1 +DEF_ROTARY_DIG_GRB_AC03_NOT_FOW 0x1 +DEF_ROTARY_DIG_EXP0_AC03_NOT_FOW 0x1 +DEF_ROTARY_DIG_EXP1_AC03_NOT_FOW 0x1 +DEF_ROTARY_DIG_AEXP0_AC03_NOT_FOW 0x1 +DEF_ROTARY_DIG_AEXP1_AC03_NOT_FOW 0x1 +DEF_USE_ROTARY_ALL_BOARDS_GRB 0x0 +DEF_USE_ROTARY_ALL_BOARDS_EXP0 0x0 +DEF_USE_ROTARY_ALL_BOARDS_EXP1 0x0 +DEF_USE_ROTARY_ALL_BOARDS_AEXP0 0x0 +DEF_USE_ROTARY_ALL_BOARDS_AEXP1 0x0 +DEF_USE_ROTARY_CL_BOARD 0x0 +DEF_USE_ROTARY_ANA_BOARD 0x0 +DEF_USE_ROTARY_DIG_BOARD 0x0 +DEF_DIG1_TAPDIR 0x0 +DEF_DIG2_TAPDIR 0x0 +DEF_DIG3_TAPDIR 0x0 +DEF_DIG4_TAPDIR 0x0 +DEF_DIG5_TAPDIR 0x0 +DEF_DIG6_TAPDIR 0x0 +DEF_DIG7_TAPDIR 0x0 +DEF_DIG8_TAPDIR 0x0 +DEF_DIG8_TAPORDER 0x7 +DEF_DIG7_TAPORDER 0x6 +DEF_DIG6_TAPORDER 0x5 +DEF_DIG5_TAPORDER 0x4 +DEF_DIG4_TAPORDER 0x3 +DEF_DIG3_TAPORDER 0x2 +DEF_DIG2_TAPORDER 0x1 +DEF_DIG1_TAPORDER 0x0 +DEF_TAPS_ORDER 0x76543210 +DEF_TAPS_MULTIPLEX_X 0x0 +DEF_TAPS_MULTIPLEX_Y 0x0 +[REG_DIGIT] +INFO_CUSTOM 0x0 +INFO_REGISTER_REV 0x1 +INFO_XSIZE 0x800 +INFO_YSIZE 0x800 +INFO_TYPE 0x2 +INFO_BAYER 0x0 +INFO_BURSTSIZE 0x0 +INFO_CAM 0x0 +INFO_GRABPATH 0x1 +INFO_SSPCLKSEL 0x0 +INFO_SSHREFSEL 0x0 +INFO_PIXCLK 0x4c4b400 +INFO_CLOCKDELAY 0x0 +INFO_USRCLK 0x4c4b400 +INFO_SAMPLEMODE 0x0 +INFO_SIGNALTYPE 0x2 +INFO_INPUTSOURCE 0x0 +INFO_CHANNEL 0x1 +INFO_SYNCGRABCHAN 0x1 +INFO_SYNCCHANNEL 0x0 +INFO_ATTENUATION 0x11111111 +INFO_GAIN0 0x5b7 +INFO_GAIN1 0x5b7 +INFO_GAIN2 0x5b7 +INFO_GAIN3 0x5b7 +INFO_OFFSET0 0x800 +INFO_OFFSET1 0x800 +INFO_OFFSET2 0x800 +INFO_OFFSET3 0x800 +INFO_CLAMP 0x1 +INFO_LUTBUFID 0x0 +INFO_LUTPROG 0x0 +INFO_LUTMODE 0x1 +INFO_LUTPALETTE 0x0 +INFO_CLMODE 0x0 +INFO_TESTMODE 0x0 +INFO_BITSPERCOMPONENT 0xc +INFO_NUMCOMPONENTS 0x2 +INFO_COMPONENTSPERPIXEL 0x1 +INFO_PACKEDCOMPONENTS 0x0 +INFO_HDELAY 0x0 +INFO_LINEDELAY 0x0 +INFO_TIMEMULTICH 0x1 +INFO_TIMEMULTIPIX 0x1 +INFO_XTAPSPERCH 0x1 +INFO_YTAPSPERCH 0x1 +INFO_XTAPSPERCHADJ 0x2 +INFO_YTAPSPERCHADJ 0x1 +INFO_TAPSDIR 0x0 +INFO_TAPSORDER 0x76543210 +INFO_BYTESORDER 0x76543210 +INFO_HARDGRABTRIG 0x0 +INFO_TRIGSRC 0x1 +INFO_T0DELAY 0x0 +INFO_T0DELAY1 0x0 +INFO_T0TRIGSRC 0x0 +INFO_T0CLKSRC 0x0 +INFO_T0USRCLK 0x0 +INFO_T0OTHERUSRCLK 0x0 +INFO_T1DELAY 0x0 +INFO_T1DELAY1 0x0 +INFO_T1TRIGSRC 0x0 +INFO_T1CLKSRC 0x0 +INFO_T1USRCLK 0x4c4b400 +INFO_T1OTHERUSRCLK 0x0 +INFO_T2DELAY 0x0 +INFO_T2DELAY1 0x0 +INFO_T2TRIGSRC 0x0 +INFO_T2CLKSRC 0x0 +INFO_T2USRCLK 0x0 +INFO_T2OTHERUSRCLK 0x0 +INFO_T3DELAY 0x0 +INFO_T3DELAY1 0x0 +INFO_T3TRIGSRC 0x0 +INFO_T3CLKSRC 0x0 +INFO_T3USRCLK 0x0 +INFO_T3OTHERUSRCLK 0x0 +INFO_MISC 0x0 +INFO_DEPTH 0xc +INFO_BAND 0x1 +INFO_INPUT 0x0 +INFO_MODULE_422 0x0 +INFO_FORMAT 0x0 +INFO_INPUT_MUX_SEL 0x0 +INFO_M_CHANNEL 0x1 +INFO_M_CHANNEL_SYNC 0x0 +INFO_M_GRAB_INPUT_GAIN 0x1 +INFO_M_INPUT_FILTER 0x0 +INFO_M_GRAB_TRIGGER_ENABLE 0x0 +INFO_M_GRAB_TRIGGER_MODE 0x1 +INFO_M_GRAB_TRIGGER_FORMAT 0x0 +INFO_M_GRAB_TRIGGER_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_0_MODE 0x0 +INFO_M_GRAB_EXPOSURE_0_TRIGGER_MODE 0x0 +INFO_M_GRAB_EXPOSURE_0_TRIGGER_FORMAT 0x1 +INFO_M_GRAB_EXPOSURE_0_TRIGGER_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_0_TIME_DELAY1 0x0 +INFO_M_GRAB_EXPOSURE_0_TIME_DELAY2 0x0 +INFO_M_GRAB_EXPOSURE_0_TIME1 0x0 +INFO_M_GRAB_EXPOSURE_0_TIME2 0x0 +INFO_M_GRAB_EXPOSURE_1_MODE 0x0 +INFO_M_GRAB_EXPOSURE_1_TRIGGER_MODE 0x0 +INFO_M_GRAB_EXPOSURE_1_TRIGGER_FORMAT 0x1 +INFO_M_GRAB_EXPOSURE_1_TRIGGER_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_1_TIME_DELAY1 0x0 +INFO_M_GRAB_EXPOSURE_1_TIME_DELAY2 0x0 +INFO_M_GRAB_EXPOSURE_1_TIME1 0x0 +INFO_M_GRAB_EXPOSURE_1_TIME2 0x0 +INFO_M_GRAB_EXPOSURE_2_MODE 0x0 +INFO_M_GRAB_EXPOSURE_2_TRIGGER_MODE 0x1 +INFO_M_GRAB_EXPOSURE_2_TRIGGER_FORMAT 0x1 +INFO_M_GRAB_EXPOSURE_2_TIME_DELAY1 0x0 +INFO_M_GRAB_EXPOSURE_2_TIME_DELAY2 0x0 +INFO_M_GRAB_EXPOSURE_2_TIME1 0x0 +INFO_M_GRAB_EXPOSURE_2_TIME2 0x0 +INFO_M_GRAB_EXPOSURE_3_MODE 0x0 +INFO_M_GRAB_EXPOSURE_3_TRIGGER_MODE 0x1 +INFO_M_GRAB_EXPOSURE_3_TRIGGER_FORMAT 0x1 +INFO_M_GRAB_EXPOSURE_3_TIME_DELAY1 0x0 +INFO_M_GRAB_EXPOSURE_3_TIME_DELAY2 0x0 +INFO_M_GRAB_EXPOSURE_3_TIME1 0x0 +INFO_M_GRAB_EXPOSURE_3_TIME2 0x0 +INFO_MODE 0x0 +INFO_SIGNALBLACKLVL 0x0 +INFO_SIGNALWHITELVL 0x0 +INFO_LUTINSIZE 0x0 +INFO_LUTOUTSIZE 0x0 +INFO_CLCONFIGMODE 0x0 +INFO_PACKEDPIXELS 0x0 +INFO_T0TRGSRC 0x0 +INFO_T1TRGSRC 0x0 +INFO_T2TRGSRC 0x0 +INFO_T3TRGSRC 0x0 +INFO_T1EXPMOD 0x0 +INFO_T1DELAY2 0x0 +INFO_T2EXPMOD 0x0 +INFO_T2DELAY2 0x0 +INFO_M_GRAB_EXPOSURE_0_CLOCK_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_1_CLOCK_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_2_CLOCK_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_3_CLOCK_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_1_TIME 0x0 +INFO_M_GRAB_EXPOSURE_2_TIME 0x0 +INFO_M_GRAB_EXPOSURE_1_TIME_DELAY 0x0 +INFO_M_GRAB_EXPOSURE_2_TIME_DELAY 0x0 +INFO_M_GRAB_EXPOSURE_2_TRIGGER_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_3_TRIGGER_SOURCE 0x0 +INFO_M_GRAB_EXPOSURE_2_TRIGGER_MODE 0x0 +INFO_M_GRAB_EXPOSURE_2_TRIGGER_FORMAT 0x0 +INFO_MASK_TRGIN 0xf +INFO_MASK_USROUTDYN 0x3 +INFO_MASK_USROUT0 0x3 +INFO_MASK_USROUT1 0x0 +INFO_MASK_USROUT2 0x0 +INFO_MASK_USROUT3 0x0 +INFO_MASK_IOCTLCLDYNL 0x0 +INFO_MASK_IOCTLCLDYNH 0x0 +INFO_MASK_IOCTLCL0L 0xffff +INFO_MASK_IOCTLCL0H 0x0 +INFO_MASK_IOCTLCL1L 0x0 +INFO_MASK_IOCTLCL1H 0x0 +INFO_MASK_IOCTLANDYN 0x0 +INFO_MASK_IOCTLAN0 0x0 +INFO_MASK_IOCTLAN1 0x0 +INFO_MASK_IOCTLAN2 0x0 +INFO_MASK_IOCTLAN3 0x0 +INFO_MASK_IOCTLDIDYN 0x0 +INFO_MASK_IOCTLDI0 0x0 +INFO_MASK_IOCTLDI1 0x0 +INFO_MASK_IOCTLDI2 0x0 +INFO_MASK_IOCTLDI3 0x0 +INFO_MASK_ENCTLCLDYN 0x0 +INFO_MASK_ENCTLCL0 0x80 +INFO_MASK_ENCTLCL1 0x0 +INFO_MASK_ENCTLANDYN 0x0 +INFO_MASK_ENCTLAN0 0x0 +INFO_MASK_ENCTLAN1 0x0 +INFO_MASK_ENCTLAN2 0x0 +INFO_MASK_ENCTLAN3 0x0 +INFO_MASK_ENCTLDIDYN 0x0 +INFO_MASK_ENCTLDI0 0x0 +INFO_MASK_ENCTLDI1 0x0 +INFO_MASK_ENCTLDI2 0x0 +INFO_MASK_ENCTLDI3 0x0 +DIG_HCNT 0x1 +DIG_HTOTAL 0x402 +DIG_HSCNT 0x0 +DIG_HECNT 0x1 +DIG_HSSYNC 0x0 +DIG_HESYNC 0x0 +DIG_HSVAL 0x0 +DIG_HEVAL 0x3ff +DIG_HSCLM 0x0 +DIG_HECLM 0x0 +DIG_HCTL 0x1e0 +DIG_VCNT 0x1 +DIG_VTOTAL 0x7ff +DIG_VSCNT 0x0 +DIG_VECNT 0x0 +DIG_VSSYNC 0x0 +DIG_VESYNC 0x1 +DIG_VSVAL 0x0 +DIG_VEVAL 0x7ff +DIG_VSCLM 0x0 +DIG_VECLM 0x0 +DIG_VCTL 0x6160 +DIG_T0CNT 0x0 +DIG_T0SCNT 0x0 +DIG_T0S0PUL 0x0 +DIG_T0E0PUL 0x0 +DIG_T0S1PUL 0x0 +DIG_T0CTLL 0x0 +DIG_T0CTLH 0x1 +DIG_T1CNT 0x0 +DIG_T1SCNT 0x0 +DIG_T1S0PUL 0x0 +DIG_T1E0PUL 0x0 +DIG_T1S1PUL 0x0 +DIG_T1CTLL 0x0 +DIG_T1CTLH 0x1 +DIG_QUADCTL 0x90001 +DIG_QUADCTL_HIGH 0x0 +DIG_QUADCNT 0x0 +DIG_CLKCTL 0x0 +DIG_GRBCTL 0x5 +DIG_VALCTL 0x27138900 +DIG_FLDCTL 0x2 +DIG_SYNCOUT 0x88 +DIG_TRGIN 0x0 +DIG_EXPOUT 0x0 +DIG_USROUT 0x2 +DIG_USROUT0 0x2 +DIG_USROUT1 0x0 +DIG_USROUT2 0x0 +DIG_USROUT3 0x0 +DIG_CLCTL 0xc +DIG_IOCTL0L 0x0 +DIG_IOCTL0H 0x0 +DIG_IOCTLCL0L 0x2223 +DIG_IOCTLCL0H 0x0 +DIG_IOCTLCL1L 0x0 +DIG_IOCTLCL1H 0x0 +DIG_IOCTL1 0x1 +DIG_IOCTLAN0 0x1 +DIG_IOCTLAN1 0x0 +DIG_IOCTLAN2 0x0 +DIG_IOCTLAN3 0x0 +DIG_IOCTL2 0x0 +DIG_IOCTLDI0 0x0 +DIG_IOCTLDI1 0x0 +DIG_IOCTLDI2 0x0 +DIG_IOCTLDI3 0x0 +DIG_ENCTL0 0x0 +DIG_ENCTLCL0 0x80 +DIG_ENCTLCL1 0x0 +DIG_ENCTL1 0x0 +DIG_ENCTLAN0 0x0 +DIG_ENCTLAN1 0x0 +DIG_ENCTLAN2 0x0 +DIG_ENCTLAN3 0x0 +DIG_ENCTL2 0x0 +DIG_ENCTLDI0 0x0 +DIG_ENCTLDI1 0x0 +DIG_ENCTLDI2 0x0 +DIG_ENCTLDI3 0x0 +DIG_ANACTL 0x0 +DIG_ANCTL 0x0 +DIG_ANCTL0 0x0 +DIG_ANCTL1 0x0 +DIG_ANCTL2 0x0 +DIG_ANCTL3 0x0 +DIG_PLLCTL 0x0 +DIG_NGHECNT 0x0 +DIG_NGVECNT 0x0 +DIG_NGFECNT 0x0 +DIG_GRABCTRL 0x4540 +DIG_GTM 0x51 +DIG_GCTRLCHNL 0x42 +DIG_T0CTL_L 0x0 +DIG_T0CTL_H 0x0 +DIG_T1CTL_L 0x0 +DIG_T1CTL_H 0x0 +DIG_IOCTL0_L 0x0 +DIG_IOCTL0_H 0x0 +DIG_IOCTL1_L 0x0 +DIG_IOCTL1_H 0x0 +DIG_IOCTL1L 0x0 +DIG_IOCTL1H 0x0 +DIG_IOCTL0_L 0x0 +DIG_ENCTL 0x0 +[REG_MODIF_STATE] +INFO_CUSTOM not_modified +INFO_REGISTER_REV not_modified +INFO_XSIZE not_modified +INFO_YSIZE not_modified +INFO_TYPE not_modified +INFO_BAYER not_modified +INFO_BURSTSIZE not_modified +INFO_CAM not_modified +INFO_GRABPATH not_modified +INFO_SSPCLKSEL not_modified +INFO_SSHREFSEL not_modified +INFO_PIXCLK not_modified +INFO_CLOCKDELAY not_modified +INFO_USRCLK not_modified +INFO_SAMPLEMODE not_modified +INFO_SIGNALTYPE not_modified +INFO_INPUTSOURCE not_modified +INFO_CHANNEL not_modified +INFO_SYNCGRABCHAN not_modified +INFO_SYNCCHANNEL not_modified +INFO_ATTENUATION not_modified +INFO_GAIN0 not_modified +INFO_GAIN1 not_modified +INFO_GAIN2 not_modified +INFO_GAIN3 not_modified +INFO_OFFSET0 not_modified +INFO_OFFSET1 not_modified +INFO_OFFSET2 not_modified +INFO_OFFSET3 not_modified +INFO_CLAMP not_modified +INFO_LUTBUFID not_modified +INFO_LUTPROG not_modified +INFO_LUTMODE not_modified +INFO_LUTPALETTE not_modified +INFO_CLMODE not_modified +INFO_TESTMODE not_modified +INFO_BITSPERCOMPONENT not_modified +INFO_NUMCOMPONENTS not_modified +INFO_COMPONENTSPERPIXEL not_modified +INFO_PACKEDCOMPONENTS not_modified +INFO_HDELAY not_modified +INFO_LINEDELAY not_modified +INFO_TIMEMULTICH not_modified +INFO_TIMEMULTIPIX not_modified +INFO_XTAPSPERCH not_modified +INFO_YTAPSPERCH not_modified +INFO_XTAPSPERCHADJ not_modified +INFO_YTAPSPERCHADJ not_modified +INFO_TAPSDIR not_modified +INFO_TAPSORDER not_modified +INFO_BYTESORDER not_modified +INFO_HARDGRABTRIG not_modified +INFO_TRIGSRC not_modified +INFO_T0DELAY not_modified +INFO_T0DELAY1 not_modified +INFO_T0TRIGSRC not_modified +INFO_T0CLKSRC not_modified +INFO_T0USRCLK not_modified +INFO_T0OTHERUSRCLK not_modified +INFO_T1DELAY not_modified +INFO_T1DELAY1 not_modified +INFO_T1TRIGSRC not_modified +INFO_T1CLKSRC not_modified +INFO_T1USRCLK not_modified +INFO_T1OTHERUSRCLK not_modified +INFO_T2DELAY not_modified +INFO_T2DELAY1 not_modified +INFO_T2TRIGSRC not_modified +INFO_T2CLKSRC not_modified +INFO_T2USRCLK not_modified +INFO_T2OTHERUSRCLK not_modified +INFO_T3DELAY not_modified +INFO_T3DELAY1 not_modified +INFO_T3TRIGSRC not_modified +INFO_T3CLKSRC not_modified +INFO_T3USRCLK not_modified +INFO_T3OTHERUSRCLK not_modified +INFO_MISC not_modified +INFO_DEPTH not_modified +INFO_BAND not_modified +INFO_INPUT not_modified +INFO_MODULE_422 not_modified +INFO_FORMAT not_modified +INFO_INPUT_MUX_SEL not_modified +INFO_M_CHANNEL not_modified +INFO_M_CHANNEL_SYNC not_modified +INFO_M_GRAB_INPUT_GAIN not_modified +INFO_M_INPUT_FILTER not_modified +INFO_M_GRAB_TRIGGER_ENABLE not_modified +INFO_M_GRAB_TRIGGER_MODE not_modified +INFO_M_GRAB_TRIGGER_FORMAT not_modified +INFO_M_GRAB_TRIGGER_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_0_MODE not_modified +INFO_M_GRAB_EXPOSURE_0_TRIGGER_MODE not_modified +INFO_M_GRAB_EXPOSURE_0_TRIGGER_FORMAT not_modified +INFO_M_GRAB_EXPOSURE_0_TRIGGER_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_0_TIME_DELAY1 not_modified +INFO_M_GRAB_EXPOSURE_0_TIME_DELAY2 not_modified +INFO_M_GRAB_EXPOSURE_0_TIME1 not_modified +INFO_M_GRAB_EXPOSURE_0_TIME2 not_modified +INFO_M_GRAB_EXPOSURE_1_MODE not_modified +INFO_M_GRAB_EXPOSURE_1_TRIGGER_MODE not_modified +INFO_M_GRAB_EXPOSURE_1_TRIGGER_FORMAT not_modified +INFO_M_GRAB_EXPOSURE_1_TRIGGER_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_1_TIME_DELAY1 not_modified +INFO_M_GRAB_EXPOSURE_1_TIME_DELAY2 not_modified +INFO_M_GRAB_EXPOSURE_1_TIME1 not_modified +INFO_M_GRAB_EXPOSURE_1_TIME2 not_modified +INFO_M_GRAB_EXPOSURE_2_MODE not_modified +INFO_M_GRAB_EXPOSURE_2_TRIGGER_MODE not_modified +INFO_M_GRAB_EXPOSURE_2_TRIGGER_FORMAT not_modified +INFO_M_GRAB_EXPOSURE_2_TIME_DELAY1 not_modified +INFO_M_GRAB_EXPOSURE_2_TIME_DELAY2 not_modified +INFO_M_GRAB_EXPOSURE_2_TIME1 not_modified +INFO_M_GRAB_EXPOSURE_2_TIME2 not_modified +INFO_M_GRAB_EXPOSURE_3_MODE not_modified +INFO_M_GRAB_EXPOSURE_3_TRIGGER_MODE not_modified +INFO_M_GRAB_EXPOSURE_3_TRIGGER_FORMAT not_modified +INFO_M_GRAB_EXPOSURE_3_TIME_DELAY1 not_modified +INFO_M_GRAB_EXPOSURE_3_TIME_DELAY2 not_modified +INFO_M_GRAB_EXPOSURE_3_TIME1 not_modified +INFO_M_GRAB_EXPOSURE_3_TIME2 not_modified +INFO_MODE not_modified +INFO_SIGNALBLACKLVL not_modified +INFO_SIGNALWHITELVL not_modified +INFO_LUTINSIZE not_modified +INFO_LUTOUTSIZE not_modified +INFO_CLCONFIGMODE not_modified +INFO_PACKEDPIXELS not_modified +INFO_T0TRGSRC not_modified +INFO_T1TRGSRC not_modified +INFO_T2TRGSRC not_modified +INFO_T3TRGSRC not_modified +INFO_T1EXPMOD not_modified +INFO_T1DELAY2 not_modified +INFO_T2EXPMOD not_modified +INFO_T2DELAY2 not_modified +INFO_M_GRAB_EXPOSURE_0_CLOCK_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_1_CLOCK_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_2_CLOCK_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_3_CLOCK_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_1_TIME not_modified +INFO_M_GRAB_EXPOSURE_2_TIME not_modified +INFO_M_GRAB_EXPOSURE_1_TIME_DELAY not_modified +INFO_M_GRAB_EXPOSURE_2_TIME_DELAY not_modified +INFO_M_GRAB_EXPOSURE_2_TRIGGER_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_3_TRIGGER_SOURCE not_modified +INFO_M_GRAB_EXPOSURE_2_TRIGGER_MODE not_modified +INFO_M_GRAB_EXPOSURE_2_TRIGGER_FORMAT not_modified +INFO_MASK_TRGIN not_modified +INFO_MASK_USROUTDYN not_modified +INFO_MASK_USROUT0 not_modified +INFO_MASK_USROUT1 not_modified +INFO_MASK_USROUT2 not_modified +INFO_MASK_USROUT3 not_modified +INFO_MASK_IOCTLCLDYNL not_modified +INFO_MASK_IOCTLCLDYNH not_modified +INFO_MASK_IOCTLCL0L not_modified +INFO_MASK_IOCTLCL0H not_modified +INFO_MASK_IOCTLCL1L not_modified +INFO_MASK_IOCTLCL1H not_modified +INFO_MASK_IOCTLANDYN not_modified +INFO_MASK_IOCTLAN0 not_modified +INFO_MASK_IOCTLAN1 not_modified +INFO_MASK_IOCTLAN2 not_modified +INFO_MASK_IOCTLAN3 not_modified +INFO_MASK_IOCTLDIDYN not_modified +INFO_MASK_IOCTLDI0 not_modified +INFO_MASK_IOCTLDI1 not_modified +INFO_MASK_IOCTLDI2 not_modified +INFO_MASK_IOCTLDI3 not_modified +INFO_MASK_ENCTLCLDYN not_modified +INFO_MASK_ENCTLCL0 not_modified +INFO_MASK_ENCTLCL1 not_modified +INFO_MASK_ENCTLANDYN not_modified +INFO_MASK_ENCTLAN0 not_modified +INFO_MASK_ENCTLAN1 not_modified +INFO_MASK_ENCTLAN2 not_modified +INFO_MASK_ENCTLAN3 not_modified +INFO_MASK_ENCTLDIDYN not_modified +INFO_MASK_ENCTLDI0 not_modified +INFO_MASK_ENCTLDI1 not_modified +INFO_MASK_ENCTLDI2 not_modified +INFO_MASK_ENCTLDI3 not_modified +DIG_HCNT not_modified +DIG_HTOTAL not_modified +DIG_HSCNT not_modified +DIG_HECNT not_modified +DIG_HSSYNC not_modified +DIG_HESYNC not_modified +DIG_HSVAL not_modified +DIG_HEVAL not_modified +DIG_HSCLM not_modified +DIG_HECLM not_modified +DIG_HCTL not_modified +DIG_VCNT not_modified +DIG_VTOTAL not_modified +DIG_VSCNT not_modified +DIG_VECNT not_modified +DIG_VSSYNC not_modified +DIG_VESYNC not_modified +DIG_VSVAL not_modified +DIG_VEVAL not_modified +DIG_VSCLM not_modified +DIG_VECLM not_modified +DIG_VCTL not_modified +DIG_T0CNT not_modified +DIG_T0SCNT not_modified +DIG_T0S0PUL not_modified +DIG_T0E0PUL not_modified +DIG_T0S1PUL not_modified +DIG_T0CTLL not_modified +DIG_T0CTLH not_modified +DIG_T1CNT not_modified +DIG_T1SCNT not_modified +DIG_T1S0PUL not_modified +DIG_T1E0PUL not_modified +DIG_T1S1PUL not_modified +DIG_T1CTLL not_modified +DIG_T1CTLH not_modified +DIG_QUADCTL not_modified +DIG_QUADCTL_HIGH not_modified +DIG_QUADCNT not_modified +DIG_CLKCTL not_modified +DIG_GRBCTL not_modified +DIG_VALCTL not_modified +DIG_FLDCTL not_modified +DIG_SYNCOUT not_modified +DIG_TRGIN not_modified +DIG_EXPOUT not_modified +DIG_USROUT not_modified +DIG_USROUT0 not_modified +DIG_USROUT1 not_modified +DIG_USROUT2 not_modified +DIG_USROUT3 not_modified +DIG_CLCTL not_modified +DIG_IOCTL0L not_modified +DIG_IOCTL0H not_modified +DIG_IOCTLCL0L not_modified +DIG_IOCTLCL0H not_modified +DIG_IOCTLCL1L not_modified +DIG_IOCTLCL1H not_modified +DIG_IOCTL1 not_modified +DIG_IOCTLAN0 not_modified +DIG_IOCTLAN1 not_modified +DIG_IOCTLAN2 not_modified +DIG_IOCTLAN3 not_modified +DIG_IOCTL2 not_modified +DIG_IOCTLDI0 not_modified +DIG_IOCTLDI1 not_modified +DIG_IOCTLDI2 not_modified +DIG_IOCTLDI3 not_modified +DIG_ENCTL0 not_modified +DIG_ENCTLCL0 not_modified +DIG_ENCTLCL1 not_modified +DIG_ENCTL1 not_modified +DIG_ENCTLAN0 not_modified +DIG_ENCTLAN1 not_modified +DIG_ENCTLAN2 not_modified +DIG_ENCTLAN3 not_modified +DIG_ENCTL2 not_modified +DIG_ENCTLDI0 not_modified +DIG_ENCTLDI1 not_modified +DIG_ENCTLDI2 not_modified +DIG_ENCTLDI3 not_modified +DIG_ANACTL not_modified +DIG_ANCTL not_modified +DIG_ANCTL0 not_modified +DIG_ANCTL1 not_modified +DIG_ANCTL2 not_modified +DIG_ANCTL3 not_modified +DIG_PLLCTL not_modified +DIG_NGHECNT not_modified +DIG_NGVECNT not_modified +DIG_NGFECNT not_modified +DIG_GRABCTRL not_modified +DIG_GTM not_modified +DIG_GCTRLCHNL not_modified +DIG_T0CTL_L not_modified +DIG_T0CTL_H not_modified +DIG_T1CTL_L not_modified +DIG_T1CTL_H not_modified +DIG_IOCTL0_L not_modified +DIG_IOCTL0_H not_modified +DIG_IOCTL1_L not_modified +DIG_IOCTL1_H not_modified +DIG_IOCTL1L not_modified +DIG_IOCTL1H not_modified +DIG_IOCTL0_L not_modified +DIG_ENCTL not_modified +[EOF] +FILE_SIZE 0x20661 +FILE_CRC 0x95513600 \ No newline at end of file diff --git a/nottcontrol/camera/macie/load_files/MACIE_Registers_Fast.mrf b/nottcontrol/camera/macie/load_files/MACIE_Registers_Fast.mrf new file mode 100644 index 00000000..06a5bd72 --- /dev/null +++ b/nottcontrol/camera/macie/load_files/MACIE_Registers_Fast.mrf @@ -0,0 +1,29 @@ +0010 00d7 +0300 0003 +0321 0ce4 +0341 0ce4 +0322 02c0 +0323 0fff +0324 0fff +0328 02c0 +0329 0fff +032a 0fff +032b 0564 +032c 0fff +032d 0fff +032e 092e +032f 0fff +0330 0fff +0331 03e8 +0332 0fff +0340 0004 +0210 005c +0202 03ff +0200 01df +0100 3e81 +0180 0007 +01b0 0081 +01c2 03ff +01c3 07ff +01c0 0001 +0320 0f05 diff --git a/nottcontrol/camera/macie/load_files/MACIE_Registers_Fast_Cryo.mrf b/nottcontrol/camera/macie/load_files/MACIE_Registers_Fast_Cryo.mrf new file mode 100644 index 00000000..1489a929 --- /dev/null +++ b/nottcontrol/camera/macie/load_files/MACIE_Registers_Fast_Cryo.mrf @@ -0,0 +1,29 @@ +0010 00d7 +0300 0003 +0321 0ce4 +0341 0ce4 +0322 02c0 +0323 0fff +0324 0fff +0328 02c0 +0329 0fff +032a 0fff +032b 061e +032c 0fff +032d 0fff +032e 092e +032f 0fff +0330 0fff +0331 03e8 +0332 0fff +0340 0004 +0210 005c +0202 03ff +0200 005f +0100 3e81 +0180 0007 +01b0 0081 +01c2 03ff +01c3 07ff +01c0 0001 +0320 0f05 diff --git a/nottcontrol/camera/macie/load_files/MACIE_Registers_Slow.mrf b/nottcontrol/camera/macie/load_files/MACIE_Registers_Slow.mrf new file mode 100644 index 00000000..e3dfdbb7 --- /dev/null +++ b/nottcontrol/camera/macie/load_files/MACIE_Registers_Slow.mrf @@ -0,0 +1,29 @@ +0010 0027 +0300 0003 +0321 0ce4 +0341 0ce4 +0322 02c0 +0323 0fff +0324 0fff +0328 02c0 +0329 0fff +032a 0fff +032b 0564 +032c 0fff +032d 0fff +032e 092e +032f 0fff +0330 0fff +0331 03e8 +0332 0fff +0340 0004 +0210 005c +0202 03ff +0200 01df +0100 3e81 +0180 0006 +01b0 0081 +01c2 03ff +01c3 07ff +01c0 0001 +0320 0f05 diff --git a/nottcontrol/camera/macie/load_files/MACIE_Registers_Slow_250kHz.mrf b/nottcontrol/camera/macie/load_files/MACIE_Registers_Slow_250kHz.mrf new file mode 100644 index 00000000..021d25e6 --- /dev/null +++ b/nottcontrol/camera/macie/load_files/MACIE_Registers_Slow_250kHz.mrf @@ -0,0 +1,29 @@ +0010 0063 +0300 0003 +0321 0ce4 +0341 0ce4 +0322 02c0 +0323 0fff +0324 0fff +0328 02c0 +0329 0fff +032a 0fff +032b 0564 +032c 0fff +032d 0fff +032e 092e +032f 0fff +0330 0fff +0331 03e8 +0332 0fff +0340 0004 +0210 005c +0202 03ff +0200 01df +0100 3e81 +0180 0006 +01b0 0081 +01c2 03ff +01c3 07ff +01c0 0001 +0320 0f05 \ No newline at end of file diff --git a/nottcontrol/camera/macie/load_files/cfg/H2RG_12bit_32output_5MHz_coldASIC.cfg b/nottcontrol/camera/macie/load_files/cfg/H2RG_12bit_32output_5MHz_coldASIC.cfg new file mode 100644 index 00000000..cd1858ed --- /dev/null +++ b/nottcontrol/camera/macie/load_files/cfg/H2RG_12bit_32output_5MHz_coldASIC.cfg @@ -0,0 +1,86 @@ +# Config file for DevBrd_H2RG_12bit_32output_5MHz_coldASIC.mcd +# +# Defines all of the various parameters encoded in each +# register and their bit locations (first to last). + +# Special Case: is Stripe Mode allowed (0xFFFF 0 0 for false, 0xFFFF 1 1 for true) +StripeAllowed 0xFFFF 0 0 + +# Name Address BitRange +SaveRstFrames 0x4002 0 0 # Save reset frame +LEDPulse 0x4002 1 1 # Pulse LED at Group boundary +ClkSCADrop 0x4002 2 2 # Enable clocking of drop frames +IdleMode 0x4002 3 4 # 0 - Do Nothing, 1 - Reset, 2 - Reset/Read +Shutter 0x4002 5 6 # Shutter control pulse at the end of a group + +NumResets 0x4000 0 15 # NReset +NumReads 0x4001 0 15 # NRead in each Group +NumDrops 0x4005 0 15 # NDrop between consecutive Groups +NumGroups 0x4004 0 15 # NGroups +NumRamps 0x4003 0 15 # NRamps +ExtraPixels 0x4006 0 15 # Number of extra pixel times added per row +ExtraLines 0x4007 0 15 # Number of extra rows added per frame +PixPerRow 0x4008 0 15 # Line/row time in pixel counts (Out) +RowsPerFrame 0x4009 0 15 # Frame time in number of row (Out) + +# Detector Biases +VReset1 0x6000 0 15 # Voltage +VReset2 0x6001 0 15 # Current / Strength +DSub1 0x6002 0 15 # Voltage +DSub2 0x6003 0 15 # Current / Strength +VBiasGate1 0x6004 0 15 +VBiasGate2 0x6005 0 15 +VBiasPower1 0x6006 0 15 +VBiasPower2 0x6007 0 15 +CellDrain1 0x6008 0 15 +CellDrain2 0x6009 0 15 +Drain1 0x600a 0 15 +Drain2 0x600b 0 15 +Vdda1 0x600c 0 15 +Vdda2 0x600d 0 15 +Vdd1 0x600e 0 15 +Vdd2 0x600f 0 15 + +# Fast Mode Only biases +RefSample1 0x6010 0 15 +RefSample2 0x6011 0 15 +RefColBuf1 0x6012 0 15 +RefColBuf2 0x6013 0 15 +VnBias1 0x6014 0 15 +VnBias2 0x6015 0 15 +VpBias1 0x6016 0 15 +VpBias2 0x6017 0 15 +VnCasc1 0x6018 0 15 +VnCasc2 0x6019 0 15 +VpCasc1 0x601a 0 15 +VpCasc2 0x601b 0 15 +VBiaOutBuf1 0x601c 0 15 +VBiaOutBuf2 0x601d 0 15 +VSub1 0x601e 0 15 # GND digital SCA ground +VSub2 0x601f 0 15 + +# Internal ASIC biases +VPreAmpRef1 0x6028 0 15 +IPreAmpBias 0x6029 0 15 +VPreAmpRef2 0x602a 0 15 +IPreAmpCasc 0x602b 0 15 +VRefMain 0x602c 0 15 +IPreAmpDAC 0x602d 0 15 +VpcfBias 0x602e 0 15 +IPullup 0x602f 0 15 +VRP 0x6030 0 15 +I_NBIAS1 0x6031 0 15 +VRN 0x6032 0 15 +I_NBIAS2 0x6033 0 15 +VPreMidRef 0x6034 0 15 +I_NFB1 0x6035 0 15 +Vcm 0x6036 0 15 +I_NFB2 0x6037 0 15 + +# 12bit ADC +#IPipeAmp 0x6038 0 7 +#IPipeComp 0x6038 8 15 +#IClkS 0x603a 0 7 +#IClkL 0x603a 8 15 +#IClkDC 0x603b 0 7 +#IbiasLVDS 0x603b 8 15 diff --git a/nottcontrol/camera/macie/load_files/cfg/HxRG_Main.cfg b/nottcontrol/camera/macie/load_files/cfg/HxRG_Main.cfg new file mode 100644 index 00000000..d82a03aa --- /dev/null +++ b/nottcontrol/camera/macie/load_files/cfg/HxRG_Main.cfg @@ -0,0 +1,112 @@ +# Config file for HxRG_Main.mcd +# +# Defines all of the various parameters encoded in each +# register and their bit locations (first to last). + +# Special Case: is Stripe Mode allowed? (0xFFFF 0 0 for false, 0xFFFF 1 1 for true) +StripeAllowed 0xFFFF 1 1 + +SaveRstFrames 0x4002 0 0 # Save reset frame +LEDPulse 0x4002 1 1 # Pulse LED at Group boundary +ClkSCADrop 0x4002 2 2 # Enable clocking of drop frames +IdleMode 0x4002 3 4 # 0 - Do Nothing 1 - Reset 2 - Reset/Read +Shutter 0x4002 5 6 # Shutter control pulse at the end of a group + +DetectorType 0x4010 0 2 # Detector type (1,2,4) +NumOutputs 0x4011 0 5 # Number of outputs (1,2,4,16,32) +NumChAvg 0x4012 0 3 # Number of ADC channels to average (1,2,4,8) + +DisableSCA 0x4013 0 0 # 0 - Powered 1 - Turned off +DisableClks 0x4014 0 0 # 0 - Powered 1 - Turned off + +WarmOrCold 0x4015 0 0 # 0 - Cold 1 - Warm +KtcRemove 0x4016 0 0 # 0 - No kTC removal 1 - Use kTC removal +PreampRstScheme 0x4016 1 1 # 0 - per frame (cold) 1 - per row (warm) + +PixelClkScheme 0x4017 0 0 # 0 - Normal 1 - Enhanced (adds 2 HCLKs/row) +PixelRstScheme 0x4017 1 1 # 0 - Line/Pixel 1 - Global +ExpMode 0x4018 0 0 # 0 - Up the Ramp 1 - Fowler +WinMode 0x4018 1 1 # 0 - Full frame 1 - Window + +X1 0x4020 0 11 # Xstart (0-4095) +X2 0x4021 0 11 # XStop (0-4095 NX = XStop-XStart+1 +Y1 0x4022 0 11 # Ystart (0-4095) +Y2 0x4023 0 11 # YStop (0-4095 Ny = YStop-YStart+1 + +# These values modify h6100 h6104 h6108 ... h618c +RefInput 0x4019 0 0 # 0 - 0x4a0a (single) 1 - 0x4502 (V4,3,2,1) (differential) +RefOverride 0x4019 1 1 # Use values stored in h5100 (0xaaaa) +OverrideVals 0x5100 0 15 + +Buff 0x401b 0 2 # bit0 - preamp current source + # bit1 - unbuffered/buffered on detector outputs + # bit2 - H4RG NMOS = b100 + # Unbuffered = b000; Buff with/without curr src = b011/b010 +Gain 0x401a 0 3 # PreAmp Gain (0-15) +CapComp 0x4054 0 5 # PreAmp Compensation capacitor (0-63) +FiltPole 0x4055 0 3 # PreAmp Low Pass filter (0-15) +IFData 0x401c 0 3 # Data type and bit depth (0-15) +SerChannel 0x401d 0 1 # Number of Serial Channels (0-3) + +RefOutputVal 0x4051 0 0 # 0 - Disable seperate refOutput 1 - Enable seperate refOutput. + # Only for single-ended, non H4RG-1output. Conflit with telemetry readback. +HorizScanDir 0x4053 0 2 # 0 ->->; 1:<-->; 2-><-; 3:<-<- + # 4: default defined in the code. (-><- for sci, ->-> for ref output) + +NumResets 0x4000 0 15 # NReset +NumReads 0x4001 0 15 # NRead in each Group +NumDrops 0x4005 0 15 # NDrop between consecutive Groups +NumGroups 0x4004 0 15 # NGroups +NumRamps 0x4003 0 15 # NRamps + +# NOTE: h4006/7 might be h4005/6 for Fowler Sampling??? +ExtraPixels 0x4006 0 15 # Number of extra pixel times added per row +ExtraLines 0x4007 0 15 # Number of extra rows added per frame +PixPerRow 0x4008 0 15 # Line/row time in pixel counts (Out) +RowsPerFrame 0x4009 0 15 # Frame time in number of row (Out) + +# Fowler sampling time between Fowler pairs +FExpReg1 0x400a 0 15 # Lower counter value for tFowler +FExpReg2 0x400b 0 15 # Upper counter value for tFowler +FFCounter3 0x400c 0 15 # Lower Counter for Exposure Counter (Out) +FFCounter4 0x400d 0 15 # Upper Counter for Exposure Counter (Out) +# t_exp = (h400c + 65535*h400d) x 2 x t_pixel + + +# Detector Biases +VReset1 0x6000 0 15 # Voltage +VReset2 0x6001 0 15 # Current / Strength +DSub1 0x6002 0 15 # Voltage +DSub2 0x6003 0 15 # Current / Strength +VBiasGate1 0x6004 0 15 +VBiasGate2 0x6005 0 15 +VBiasPower1 0x6006 0 15 +VBiasPower2 0x6007 0 15 +CellDrain1 0x6008 0 15 +CellDrain2 0x6009 0 15 +Drain1 0x600a 0 15 +Drain2 0x600b 0 15 +Vdda1 0x600c 0 15 +Vdda2 0x600d 0 15 +Vdd1 0x600e 0 15 +Vdd2 0x600f 0 15 +Gnd1 0x601e 0 15 +Gnd2 0x601f 0 15 + +# Internal ASIC biases +VPreAmpRef1 0x6028 0 15 +IPreAmpBias 0x6029 0 15 +VPreAmpRef2 0x602a 0 15 +IPreAmpCasc 0x602b 0 15 +VRefMain 0x602c 0 15 +IPreAmpDAC 0x602d 0 15 +VpcfBias 0x602e 0 15 # 0.1V - 0.4V (SAR ADCs) +IPullup 0x602f 0 15 +VRP 0x6030 0 15 # 1.6V - 2.0V (SAR ADCs) +I_NBIAS1 0x6031 0 15 # 5 uA (SAR ADCS) +VRN 0x6032 0 15 # 0.2V - 0.8V (SAR ADCs) +I_NBIAS2 0x6033 0 15 # 5 uA (SAR ADCs) +VPreMidRef 0x6034 0 15 # 1.2V (SAR ADCs) +I_NFB1 0x6035 0 15 # 1.6 uA (SAR ADCs) +Vcm 0x6036 0 15 # Slow=1.2V; Fast = 1.65V +I_NFB2 0x6037 0 15 # 1.6 uA (SAR ADCs) diff --git a/nottcontrol/camera/macie/load_files/cfg/HxRG_v5.0.cfg b/nottcontrol/camera/macie/load_files/cfg/HxRG_v5.0.cfg new file mode 100644 index 00000000..0106dbd7 --- /dev/null +++ b/nottcontrol/camera/macie/load_files/cfg/HxRG_v5.0.cfg @@ -0,0 +1,112 @@ +# Config file for HxRG_Main.mcd +# +# Defines all of the various parameters encoded in each +# register and their bit locations (first to last). + +# Special Case: is Stripe Mode allowed? (0xFFFF 0 0 for false, 0xFFFF 1 1 for true) +StripeAllowed 0xFFFF 0 0 + +SaveRstFrames 0x4002 0 0 # Save reset frame +LEDPulse 0x4002 1 1 # Pulse LED at Group boundary +ClkSCADrop 0x4002 2 2 # Enable clocking of drop frames +IdleMode 0x4002 3 4 # 0 - Do Nothing 1 - Reset 2 - Reset/Read +Shutter 0x4002 5 6 # Shutter control pulse at the end of a group + +DetectorType 0x4010 0 2 # Detector type (1,2,4) +NumOutputs 0x4011 0 5 # Number of outputs (1,2,4,16,32) +NumChAvg 0x4012 0 3 # Number of ADC channels to average (1,2,4,8) + +DisableSCA 0x4013 0 0 # 0 - Powered 1 - Turned off +DisableClks 0x4014 0 0 # 0 - Powered 1 - Turned off + +WarmOrCold 0x4015 0 0 # 0 - Cold 1 - Warm +KtcRemove 0x4016 0 0 # 0 - No kTC removal 1 - Use kTC removal +PreampRstScheme 0x4016 1 1 # 0 - per frame (cold) 1 - per row (warm) + +PixelClkScheme 0x4017 0 0 # 0 - Normal 1 - Enhanced (adds 2 HCLKs/row) +PixelRstScheme 0x4017 1 1 # 0 - Line/Pixel 1 - Global +ExpMode 0x4018 0 0 # 0 - Up the Ramp 1 - Fowler +WinMode 0x4018 1 1 # 0 - Full frame 1 - Window + +X1 0x4020 0 11 # Xstart (0-4095) +X2 0x4021 0 11 # XStop (0-4095 NX = XStop-XStart+1 +Y1 0x4022 0 11 # Ystart (0-4095) +Y2 0x4023 0 11 # YStop (0-4095 Ny = YStop-YStart+1 + +# These values modify h6100 h6104 h6108 ... h618c +RefInput 0x4019 0 0 # 0 - 0x4a0a (single) 1 - 0x4502 (V4,3,2,1) (differential) +RefOverride 0x4019 1 1 # Use values stored in h5100 (0xaaaa) +OverrideVals 0x5100 0 15 + +Buff 0x401b 0 2 # bit0 - preamp current source + # bit1 - unbuffered/buffered on detector outputs + # bit2 - H4RG NMOS = b100 + # Unbuffered = b000; Buff with/without curr src = b011/b010 +Gain 0x401a 0 3 # PreAmp Gain (0-15) +CapComp 0x4054 0 5 # PreAmp Compensation capacitor (0-63) +FiltPole 0x4055 0 3 # PreAmp Low Pass filter (0-15) +IFData 0x401c 0 3 # Data type and bit depth (0-15) +SerChannel 0x401d 0 1 # Number of Serial Channels (0-3) + +RefOutputVal 0x4051 0 0 # 0 - Disable seperate refOutput 1 - Enable seperate refOutput. + # Only for single-ended, non H4RG-1output. Conflit with telemetry readback. +HorizScanDir 0x4053 0 2 # 0 ->->; 1:<-->; 2-><-; 3:<-<- + # 4: default defined in the code. (-><- for sci, ->-> for ref output) + +NumResets 0x4000 0 15 # NReset +NumReads 0x4001 0 15 # NRead in each Group +NumDrops 0x4005 0 15 # NDrop between consecutive Groups +NumGroups 0x4004 0 15 # NGroups +NumRamps 0x4003 0 15 # NRamps + +# NOTE: h4006/7 might be h4005/6 for Fowler Sampling??? +ExtraPixels 0x4006 0 15 # Number of extra pixel times added per row +ExtraLines 0x4007 0 15 # Number of extra rows added per frame +PixPerRow 0x4008 0 15 # Line/row time in pixel counts (Out) +RowsPerFrame 0x4009 0 15 # Frame time in number of row (Out) + +# Fowler sampling time between Fowler pairs +FExpReg1 0x400a 0 15 # Lower counter value for tFowler +FExpReg2 0x400b 0 15 # Upper counter value for tFowler +FFCounter3 0x400c 0 15 # Lower Counter for Exposure Counter (Out) +FFCounter4 0x400d 0 15 # Upper Counter for Exposure Counter (Out) +# t_exp = (h400c + 65535*h400d) x 2 x t_pixel + + +# Detector Biases +VReset1 0x6000 0 15 # Voltage +VReset2 0x6001 0 15 # Current / Strength +DSub1 0x6002 0 15 # Voltage +DSub2 0x6003 0 15 # Current / Strength +VBiasGate1 0x6004 0 15 +VBiasGate2 0x6005 0 15 +VBiasPower1 0x6006 0 15 +VBiasPower2 0x6007 0 15 +CellDrain1 0x6008 0 15 +CellDrain2 0x6009 0 15 +Drain1 0x600a 0 15 +Drain2 0x600b 0 15 +Vdda1 0x600c 0 15 +Vdda2 0x600d 0 15 +Vdd1 0x600e 0 15 +Vdd2 0x600f 0 15 +Gnd1 0x601e 0 15 +Gnd2 0x601f 0 15 + +# Internal ASIC biases +VPreAmpRef1 0x6028 0 15 +IPreAmpBias 0x6029 0 15 +VPreAmpRef2 0x602a 0 15 +IPreAmpCasc 0x602b 0 15 +VRefMain 0x602c 0 15 +IPreAmpDAC 0x602d 0 15 +VpcfBias 0x602e 0 15 # 0.1V - 0.4V (SAR ADCs) +IPullup 0x602f 0 15 +VRP 0x6030 0 15 # 1.6V - 2.0V (SAR ADCs) +I_NBIAS1 0x6031 0 15 # 5 uA (SAR ADCS) +VRN 0x6032 0 15 # 0.2V - 0.8V (SAR ADCs) +I_NBIAS2 0x6033 0 15 # 5 uA (SAR ADCs) +VPreMidRef 0x6034 0 15 # 1.2V (SAR ADCs) +I_NFB1 0x6035 0 15 # 1.6 uA (SAR ADCs) +Vcm 0x6036 0 15 # Slow=1.2V; Fast = 1.65V +I_NFB2 0x6037 0 15 # 1.6 uA (SAR ADCs) diff --git a/nottcontrol/camera/macie/load_files/mcd/HxRG_Main.mcd b/nottcontrol/camera/macie/load_files/mcd/HxRG_Main.mcd new file mode 100755 index 00000000..9ae9c61b --- /dev/null +++ b/nottcontrol/camera/macie/load_files/mcd/HxRG_Main.mcd @@ -0,0 +1,3972 @@ +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +6700 6a18 +6701 6a10 +6702 64fe +6703 64ff +6704 681a +6705 6905 +6706 6913 +6707 6910 +6708 4016 +6709 6804 +670a 668c +670b 6801 +670c 5100 +670d 6418 +670e 4100 +670f 6800 +6710 6810 +6711 6900 +6712 5401 +6713 6a00 +6714 6600 +6715 4040 +6716 4000 +6717 4030 +6718 4020 +6719 4050 +671a 4060 +671b 5400 +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +6000 804a +6001 5000 +6002 80cd +6003 8000 +6004 b580 +6005 7800 +6006 87ff +6007 c400 +6008 8000 +6009 fc00 +600a 8000 +600b fc00 +600c 87e3 +600d 9400 +600e 87e3 +600f 9400 +601e 8000 +601f fc00 +6012 8800 +6013 0000 +6028 4280 +6029 9135 +602a 4234 +602b 9134 +602c 8334 +602d 8800 +602e 8080 +602f 3607 +6030 0507 +6031 ce04 +6032 003f +6033 9e03 +6034 0212 +6035 790e +6036 01ff +6037 810d +603b 0f00 +603c 410a +603d ff70 +603e 2041 +603f 9933 +6040 0050 +6041 0000 +6042 0000 +6043 aadd +6044 0000 +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +4010 0002 +4011 0020 +4012 0001 +4013 0000 +4014 0000 +4015 0000 +4016 0000 +4017 0001 +4018 0000 +401c 0005 +4019 0001 +401a 0008 +401b 0000 +401d 0000 +401e 0003 +401f 0001 +4050 0000 +4051 0000 +4052 0000 +4053 0004 +4054 0016 +4055 0008 +4000 0000 +4001 0001 +4002 000c +4003 0001 +4004 0001 +4005 0001 +4006 0000 +4007 0000 +4008 0040 +4009 0800 +4003 0001 +400a 2080 +400b 0000 +400c 0000 +400d 0000 +4020 a000 +4021 b063 +4022 8000 +4023 9063 +410f 1005 +4110 2010 +4111 3072 +4112 4011 +4113 5000 +4114 6000 +4115 700c +4116 8000 +4117 9400 +4118 a000 +4119 b400 +411a c099 +411b d000 +411c e000 +411d f000 +411e 1055 +411f 2010 +4120 3072 +4121 4018 +4122 5000 +4123 6000 +4124 700c +4125 8000 +4126 9400 +4127 a000 +4128 b400 +4129 c055 +412a d000 +412b e000 +412c f000 +412d 1041 +412e 2f0f +412f 3008 +4130 4006 +4131 5000 +4132 6000 +4133 700c +4134 8000 +4135 9400 +4136 a000 +4137 b400 +4138 c000 +4139 d210 +413a e055 +413b f0c0 +5100 aaaa +5101 aaaa +5102 88f1 +5103 6642 +5104 2000 +5105 aaaa +5106 88f1 +5107 6642 +5108 6000 +5200 0030 +5201 0001 +5300 1c13 +5301 03ff +5302 0000 +5303 03ff +5304 03ff +5305 0001 +5306 0000 +5307 0000 +5308 0000 +5309 0000 +530a 03ff +530b 8000 +530c 1c12 +530d 01ff +530e 0000 +530f 01ff +5310 01ff +5311 0001 +5312 2000 +5313 ffff +5314 2000 +5315 0002 +5316 03ff +5317 8000 +5318 1c10 +5319 003f +531a 0000 +531b 003f +531c 003f +531d 0001 +531e 0400 +531f ffff +5320 0400 +5321 0002 +5322 03ff +5323 8000 +5324 1c13 +5325 07ff +5326 0000 +5327 07ff +5328 0000 +5329 0001 +532a 0000 +532b 0000 +532c 0000 +532d 0000 +532e 07ff +532f 8000 +5330 1c12 +5331 01ff +5332 0000 +5333 01ff +5334 01ff +5335 0001 +5336 2000 +5337 ffff +5338 2000 +5339 0002 +533a 07ff +533b 8000 +533c 1c10 +533d 003f +533e 0000 +533f 003f +5340 003f +5341 0001 +5342 0400 +5343 ffff +5344 0400 +5345 0002 +5346 07ff +5347 8000 +5348 1c13 +5349 0fff +534a 0000 +534b 0000 +534c 0000 +534d 0001 +534e 0000 +534f 0000 +5350 0000 +5351 0000 +5352 0fff +5353 8000 +5354 1c12 +5355 03ff +5356 0000 +5357 03ff +5358 03ff +5359 0001 +535a 2000 +535b ffff +535c 2000 +535d 0002 +535e 0fff +535f 8000 +5360 1c10 +5361 00ff +5362 0000 +5363 00ff +5364 00ff +5365 0001 +5366 0800 +5367 ffff +5368 0800 +5369 0002 +536a 0fff +536b 8400 +536c 1c10 +536d 007f +536e 0000 +536f 007f +5370 007f +5371 0001 +5372 0400 +5373 ffff +5374 0400 +5375 0002 +5376 0fff +5377 8000 +5400 1200 +5401 4024 +5402 4023 +5403 4034 +5404 4033 +5405 4025 +5406 5405 +5407 4024 +5408 4023 +5409 4034 +540b 0000 +540c 0000 +540d 2a40 +540e 2a40 +5500 0110 +5501 1800 +5502 0000 +5503 0001 +5504 0000 +5505 003f +5506 0001 +5507 0002 +5508 0210 +5509 f800 +550a 0000 +550b 0001 +550c 0000 +550d 003f +550e 0001 +550f 0002 +5510 c1f0 +5511 f800 +5512 0000 +5513 0001 +5514 0000 +5515 003f +5516 0001 +5517 0103 +5518 0210 +5519 f800 +551a 0000 +551b 0001 +551c 0000 +551d 003f +551e 0001 +551f 0100 +5520 c1d0 +5521 f800 +5522 0000 +5523 0001 +5524 0000 +5525 003f +5526 0001 +5527 010b +5528 c210 +5529 f800 +552a 0000 +552b 0001 +552c 0000 +552d 003f +552e 0001 +552f 0108 +5530 c210 +5531 f800 +5532 0000 +5533 0001 +5534 0000 +5535 003f +5536 0001 +5537 0105 +5538 0210 +5539 f800 +553a 0000 +553b 0001 +553c 0000 +553d 003f +553e 0001 +553f 0102 +5540 c1b0 +5541 f800 +5542 0000 +5543 0001 +5544 0000 +5545 003f +5546 0001 +5547 0117 +5548 c210 +5549 f800 +554a 0000 +554b 0001 +554c 0000 +554d 003f +554e 0001 +554f 0114 +5550 c210 +5551 f800 +5552 0000 +5553 0001 +5554 0000 +5555 003f +5556 0001 +5557 0111 +5558 c210 +5559 f800 +555a 0000 +555b 0001 +555c 0000 +555d 003f +555e 0001 +555f 010e +5560 c210 +5561 f800 +5562 0000 +5563 0001 +5564 0000 +5565 003f +5566 0001 +5567 010b +5568 c210 +5569 f800 +556a 0000 +556b 0001 +556c 0000 +556d 003f +556e 0001 +556f 0108 +5570 c210 +5571 f800 +5572 0000 +5573 0001 +5574 0000 +5575 003f +5576 0001 +5577 0105 +5578 0210 +5579 f800 +557a 0000 +557b 0001 +557c 0000 +557d 003f +557e 0001 +557f 0102 +4201 0021 +4200 0020 +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +6916 0800 +6903 0001 +6928 5fff +6928 affd +6928 5fff +6928 afff +6814 c001 +6906 55d7 +6907 87d5 +6904 0505 +6905 0505 +6190 0580 +6191 9580 +6192 f400 +6193 2800 +6817 3487 +6818 2000 +6819 0f40 +6419 8600 +641a 2a40 +641b 0fbf +64c1 0600 +64c2 2a41 +64c3 003e +6a00 0000 +6a02 0040 +6a03 0063 +6a04 0000 +6a06 0042 +6a07 0086 +6a08 0000 +6a0a ffff +6a0b 0106 +6a0c 0000 +6a0e ffff +6a0f 001f +6a10 0000 +6a12 0015 +6a13 0014 +6a18 020f +6a20 8207 +6a21 2009 +6a22 0d0c +6a24 0006 +6a28 1a12 +6a29 0605 +6910 ac78 +6916 4800 +6911 2b04 +6912 f000 +6913 0500 +6919 2004 +6812 0100 +6816 0003 +blockstart +address 0000 +length 3 +0000 +0b01 +af00 +blockend +blockstart +address 0100 +length 512 +5e70 +5600 +49c2 +49cb +07b4 +7c01 +7d02 +7d03 +c604 +a6fa +5e1e +5610 +0b69 +2e0b +5e78 +5600 +0b69 +2e16 +af4d +6bbb +570f +5f02 +1f00 +1750 +06f0 +06f1 +1f50 +13a2 +11a6 +10a7 +07db +1150 +6d91 +a53e +6d90 +a557 +0d08 +6db3 +950a +0d01 +6db4 +8507 +001a +1150 +6d91 +a532 +6d90 +a54b +afe2 +0eff +17f3 +16f4 +15f9 +14f8 +06ce +13f7 +6b83 +0eff +0017 +001f +e000 +97f3 +6b81 +10f0 +03f0 +0eff +0eff +6db4 +a6da +0d01 +0ed1 +17f3 +16f4 +06ce +6b83 +0ed1 +0017 +001f +e000 +97fc +6b81 +10f0 +03f0 +0eff +0eff +0e51 +16f4 +064e +6b83 +0e51 +1150 +6d91 +a503 +6d90 +a51c +afbf +0a01 +8e90 +0a09 +8ee8 +0a01 +8ea5 +0a03 +8e44 +0a07 +8ed2 +0a0a +8e4c +0a0a +8e6f +0a0a +8ea8 +0a08 +8e48 +0a0a +8e2a +0a0a +8e14 +0a09 +8eed +0a0a +8e02 +af98 +0b40 +2018 +6d80 +a502 +0a00 +a6ab +12a3 +07d4 +0b40 +210b +e100 +a707 +5107 +5920 +0b40 +220a +5306 +5b01 +af06 +5107 +5982 +52ff +5aff +531f +5b00 +0b6a +2920 +0b6a +2a0a +0b6a +2b0f +17a0 +16a4 +15a1 +14a5 +13a2 +0d04 +6b91 +11a6 +10a7 +0fff +17f3 +16f4 +15f9 +14f8 +13f7 +6b83 +0eff +0d08 +6db0 +a503 +0c10 +06ce +07e1 +0d80 +e700 +a207 +0d80 +6bb9 +07f8 +0cff +10f0 +0270 +8ff6 +17f1 +16f2 +0c10 +064e +07ed +1150 +6d90 +0aff +864f +0cff +10f0 +0270 +0d20 +6ba9 +e500 +b7f0 +07f6 +15a1 +07f6 +0d08 +6db2 +a502 +0a09 +8e48 +0d08 +eb60 +a202 +0a01 +8e05 +17aa +1f7a +177b +06f7 +1f7b +17ab +e700 +a201 +6bb9 +1f7e +177f +06f7 +1f7f +6bbb +1f78 +1f7c +57ff +5f02 +1f00 +1150 +6d90 +0aff +8624 +0cff +06ce +10f0 +0270 +aa01 +aff6 +0d08 +6db2 +a502 +0a09 +8e3d +17f1 +16f2 +0c10 +064e +07ed +571f +5f00 +0b6a +2f0f +6bba +1f7a +1f7e +6bbb +1f78 +1f7c +57ff +5f02 +1f00 +0058 +0d08 +eb60 +8202 +0a00 +aed4 +1150 +1950 +6d90 +0afe +86fc +0cff +10f0 +0270 +0d20 +6ba9 +e500 +b7ef +07f6 +570f +5f02 +1f00 +1778 +1fac +177c +1fad +0d04 +e200 +0aff +a759 +0afe +afe7 +12a3 +07d4 +6bba +1f7a +1f7e +6bbb +1f78 +1f7c +57ff +5f02 +1f00 +17a0 +16a4 +15a1 +14a5 +13a2 +0d04 +6b91 +11a6 +10a7 +0fff +17f1 +16f2 +15f9 +14f8 +13f7 +6b83 +0eff +0d89 +6db0 +9502 +0ed0 +06ce +17f3 +16f4 +0ed0 +0d01 +6b8b +1978 +197c +e700 +8212 +1150 +6d90 +0afe +86b9 +0017 +001f +e000 +92fc +6b81 +0eff +0b54 +2000 +0370 +17f3 +16f4 +0eff +bfe9 +6bb9 +0ed0 +064e +17f1 +16f2 +0ed0 +0d79 +6db1 +9602 +6b93 +0628 +e600 +606e +0afe +a29d +0d01 +e500 +8216 +1150 +6d90 +0afe +8696 +0017 +001f +e000 +97fc +6b81 +0eff +10f0 +0370 +17f1 +16f2 +0eff +1150 +6a8a +1950 +0698 +1950 +bfe8 +6ba9 +60f9 +e601 +a709 +0d04 +e200 +a799 +1778 +1fac +177c +1fad +0afe +8f78 +6db2 +a50b +0ef8 +0a08 +8e7b +17f1 +16f2 +15f9 +14f8 +06ce +13f7 +0ef8 +af05 +0ed0 +17f1 +16f2 +06ce +0ed0 +0d01 +e400 +8216 +1150 +6d90 +0afe +865f +0017 +001f +e000 +97fc +6b81 +0eff +10f0 +0370 +17f1 +16f2 +0eff +1150 +6a8a +1950 +0698 +1950 +bfca +6ba1 +6db2 +a509 +0ef8 +0a08 +8e6c +17f1 +16f2 +15f9 +14f8 +13f7 +0ef8 +0e10 +064e +0e10 +6bb1 +0f08 +eb60 +a202 +ae04 +ae0c +0f08 +bf96 +0d30 +1050 +0609 +1850 +6db6 +8602 +0689 +0000 +0009 +1850 +1050 +0689 +6db5 +8502 +0609 +0000 +1850 +0689 +0000 +0000 +0009 +1850 +0b40 +231c +653c +0b68 +250b +52ff +5a0f +6a6a +682b +1d3b +0b40 +231e +653e +0b40 +blockend +blockstart +address 0300 +length 11 +251d +655c +681d +0b68 +250c +52ff +5a0f +6a6a +682b +1d3c +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +blockstart +address 030b +length 417 +0b40 +2016 +6d81 +a52e +6d80 +a516 +51f8 +59ac +0b69 +2910 +51c4 +5986 +0b51 +2903 +51a8 +59ac +0b54 +2907 +0b54 +2909 +061e +0b54 +2908 +5132 +5900 +0b52 +2900 +af46 +5178 +59ac +0b69 +2910 +5142 +5966 +0b51 +2903 +5168 +59ac +0b54 +2907 +0b54 +2909 +061e +0b54 +2908 +5130 +5900 +0b52 +2900 +af30 +6d80 +a517 +51f8 +59ac +0b69 +2910 +51c4 +5986 +0b51 +2903 +51a8 +59ac +0b54 +2907 +0614 +0b54 +2909 +061e +0b54 +2908 +5132 +5900 +0b52 +2900 +af17 +5178 +59ac +0b69 +2910 +5142 +5966 +0b51 +2903 +5168 +59ac +0b54 +2907 +0614 +0b54 +2909 +061e +0b54 +2908 +5130 +5900 +0b52 +2900 +af00 +0b40 +2019 +0b40 +2112 +6d81 +a508 +6d80 +a536 +520a +5a4a +1a18 +52ca +5a4a +1a19 +e101 +a70f +5780 +5f05 +0b40 +2251 +6da0 +a602 +57c0 +5f01 +0b61 +2f90 +0a90 +c700 +0b61 +2f91 +af4f +e102 +a709 +5702 +5f04 +0b61 +2f90 +5702 +5f94 +0b61 +2f91 +af44 +e104 +a709 +5702 +5f04 +0b61 +2f90 +5702 +5f94 +0b61 +2f91 +af39 +570a +5f04 +0b61 +2f90 +570a +5f94 +0b61 +2f91 +af30 +5202 +5a45 +1a18 +52c2 +5a45 +1a19 +e101 +a709 +5780 +5f05 +0b61 +2f90 +5780 +5f8d +0b61 +2f91 +af1f +e102 +a709 +5782 +5f05 +0b61 +2f90 +5782 +5f8d +0b61 +2f91 +af14 +e104 +a709 +5782 +5f05 +0b61 +2f90 +5782 +5f8d +0b61 +2f91 +af09 +578a +5f05 +0b61 +2f90 +578a +5f8d +0b61 +2f91 +af00 +0b40 +201a +0b40 +211b +0b40 +2210 +6b9b +6ba3 +0b60 +252e +6bb3 +6d92 +a607 +065f +0b60 +2d2e +1523 +5524 +1d23 +af3c +6d90 +a51e +5300 +5b90 +065f +0b60 +2d2e +0b41 +2503 +6d91 +a51d +e201 +a705 +56f0 +5eff +6a6e +0653 +af0b +e202 +a705 +56f0 +5eff +6a6e +0653 +af04 +56fc +5eff +6a6e +0651 +0b41 +2d03 +af1c +5300 +5b88 +06df +065e +0b60 +2d2e +0b41 +2503 +e201 +a705 +56f0 +5eff +6a6e +0651 +af0b +e202 +a705 +56f0 +5eff +6a6e +0651 +af04 +56fc +5eff +6a6e +0650 +0b41 +2d03 +0b40 +2515 +6dd0 +a536 +6ba3 +d003 +c003 +6388 +6801 +0378 +54e0 +5c01 +af63 +54c1 +5c01 +af60 +54b2 +5c01 +af5d +5493 +5c01 +af5a +5494 +5c01 +af57 +5485 +5c01 +af54 +5486 +5c01 +af51 +5467 +5c01 +af4e +5468 +5c01 +af4b +5449 +5c01 +af48 +544a +5c01 +af45 +543b +5c01 +af42 +543c +5c01 +af3f +541d +5c01 +af3c +540e +5c01 +af39 +54ef +5c00 +af36 +6ba3 +d003 +c003 +6388 +6801 +0378 +54f0 +5c00 +af2d +54f1 +5c00 +af2a +54d2 +5c00 +af27 +54a3 +5c00 +af24 +54a4 +5c00 +af21 +5495 +5c00 +af1e +5496 +5c00 +af1b +5487 +5c00 +af18 +5488 +5c00 +af15 +5479 +5c00 +af12 +547a +5c00 +af0f +546b +5c00 +af0c +546c +5c00 +af09 +544d +5c00 +af06 +543e +5c00 +af03 +542f +5c00 +af00 +654c +65cc +0b40 +2554 +6554 +6825 +6823 +1c1a +141b +6544 +65c4 +0b40 +2555 +655c +6825 +1c1b +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +blockstart +address 04ac +length 512 +0b40 +2010 +0b40 +2111 +0b40 +2212 +49d3 +0b40 +2718 +6df1 +0a02 +a576 +0b41 +2306 +54fc +5cff +6a5c +0b41 +2b06 +e001 +0a00 +a785 +e101 +a734 +0b41 +2302 +54f8 +5cff +6a5c +0630 +0b41 +2b02 +0b41 +2300 +5300 +0b41 +2b00 +5600 +5e53 +530a +5b00 +1bb8 +e201 +a707 +5380 +5b00 +6ba3 +5508 +5d55 +0a01 +af95 +e202 +a707 +53c0 +5b00 +6ba3 +5510 +5d55 +0a01 +af8c +e204 +a707 +53f0 +5b00 +6ba3 +5520 +5d55 +0a01 +af83 +53ff +5b00 +6ba3 +5540 +5d55 +0a01 +af7c +e102 +a734 +0b41 +2302 +54f8 +5cff +6a5c +0631 +0b41 +2b02 +0b41 +2300 +5308 +0b41 +2b00 +560c +5e53 +5309 +5b00 +1bb8 +e201 +a707 +5380 +5b80 +6ba3 +5508 +5d55 +0a01 +af5f +e202 +a707 +53c0 +5bc0 +6ba3 +5510 +5d55 +0a01 +af56 +e204 +a707 +53f0 +5bf0 +6ba3 +5520 +5d55 +0a01 +af4d +53ff +5bff +6ba3 +5540 +5d55 +0a01 +af46 +0b41 +2302 +54f8 +5cff +6a5c +0632 +0b41 +2b02 +0b41 +2300 +530a +0b41 +2b00 +5618 +5e53 +5306 +5b00 +1bb8 +53ff +5bff +6ba3 +5508 +5d55 +0a01 +af2d +e002 +0a00 +a78a +e101 +a734 +0b41 +2302 +54f8 +5cff +6a5c +0630 +0b41 +2b02 +0b41 +2300 +5300 +0b41 +2b00 +5624 +5e53 +530b +5b00 +1bb8 +e201 +a707 +5380 +5b00 +6ba3 +5508 +5d55 +0a01 +af0d +e202 +a707 +53c0 +5b00 +6ba3 +5510 +5d55 +0a01 +af04 +e204 +a707 +53f0 +5b00 +6ba3 +5520 +5d55 +0a00 +affb +53ff +5b00 +6ba3 +5540 +5d55 +0a00 +aff4 +e104 +a738 +0b41 +2302 +54f8 +5cff +6a5c +0631 +0b41 +2b02 +0b41 +2300 +5388 +0b41 +2b00 +5630 +5e53 +5309 +5b00 +1bb8 +e201 +a708 +5380 +5b80 +5480 +5c80 +5508 +5d55 +0a00 +afd6 +e202 +a708 +53c0 +5bc0 +54c0 +5cc0 +5510 +5d55 +0a00 +afcc +e204 +a708 +53f0 +5bf0 +54f0 +5cf0 +5520 +5d55 +0a00 +afc2 +53ff +5bff +54ff +5cff +5540 +5d55 +0a00 +afba +0b41 +2302 +54f8 +5cff +6a5c +0632 +0b41 +2b02 +0b41 +2300 +53aa +0b41 +2b00 +5306 +5b00 +1bb8 +53ff +5bff +54ff +5cff +5508 +5d55 +563c +5e53 +0a00 +afa0 +e101 +a731 +0b41 +2302 +54e0 +5cff +6a5c +0630 +0b41 +2b02 +0b41 +230c +06b8 +0b41 +2b0c +5648 +5e53 +530c +5b00 +1bb8 +e201 +a707 +5380 +5b00 +6ba3 +5508 +5d55 +0a00 +af83 +e202 +a706 +53c0 +5b00 +6ba3 +5510 +5d55 +af7b +e204 +a706 +53f0 +5b00 +6ba3 +5520 +5d55 +af73 +53ff +5b00 +6ba3 +5540 +5d55 +af6d +e104 +a735 +0b41 +2302 +54e0 +5cff +6a5c +0631 +0b41 +2b02 +0b41 +230c +06b8 +0639 +0b41 +2b0c +5654 +5e53 +530a +5b00 +1bb8 +e201 +a707 +5380 +5b80 +5480 +5c80 +5508 +5d55 +af4f +e202 +a707 +53c0 +5bc0 +54c0 +5cc0 +5510 +5d55 +af46 +e204 +a707 +53f0 +5bf0 +54f0 +5cf0 +5520 +5d55 +af3d +53ff +5bff +54ff +5cff +5540 +5d55 +af36 +e110 +a71a +0b41 +2302 +54e0 +5cff +6a5c +0632 +0b41 +2b02 +0b41 +230c +06b8 +0639 +0b41 +2b0c +5660 +5e53 +5308 +5b00 +1bb8 +53aa +5baa +54aa +5caa +5508 +5d55 +af1a +0b41 +2302 +54e0 +5cff +6a5c +0633 +0b41 +2b02 +0b41 +230c +06b8 +0639 +0b41 +2b0c +566c +5e53 +5307 +5b00 +1bb8 +53ff +5bff +54ff +5cff +5508 +5d55 +af00 +07e6 +0437 +1f5b +2701 +1f11 +1fb2 +1fb7 +c701 +250b +682f +1db3 +1d34 +1fb6 +e204 +a004 +c702 +1f72 +c702 +af02 +1f72 +c707 +0b40 +2506 +683d +1fb5 +1f76 +6bb8 +1fa8 +2705 +1f35 +2706 +1f36 +2707 +1f37 +2708 +1f38 +0b40 +271c +657c +2503 +682f +1d3b +0b40 +271e +657e +0b40 +251d +655c +683d +2504 +683d +1f3c +0b40 +271f +657e +2509 +blockend +blockstart +address 06ac +length 512 +655c +683d +1f3e +270a +1f40 +1fb1 +6bb8 +1fb4 +6bb8 +1fa9 +e004 +a034 +0b40 +2752 +6df0 +a630 +4c21 +17b2 +15b2 +6ba8 +683d +1f11 +1fb2 +1fb7 +1772 +6bb8 +1f72 +17b6 +683d +1fb6 +5700 +5f40 +e104 +a402 +5700 +5f10 +1fbb +682f +17b3 +683d +1fb3 +1f34 +17bb +686f +17b5 +683d +c728 +1fb5 +1f76 +6bb8 +1fa8 +173b +683d +0a0f +efff +0ab0 +c700 +1f3b +173c +683d +1f3c +17b8 +6bb8 +1fb8 +0b40 +2751 +6df0 +a63c +5500 +5d7c +0437 +e104 +a105 +5500 +5d70 +0aff +eff0 +c705 +1f5b +17b2 +6bb8 +682f +1db3 +1d34 +e004 +9404 +1540 +682f +1d40 +af11 +4c20 +5504 +5d00 +e120 +8406 +5507 +5d00 +e110 +8402 +5518 +5d00 +17b5 +683d +1fb5 +1f76 +6bb8 +1fa8 +5500 +5d04 +e110 +a704 +e004 +a702 +5500 +5d08 +e104 +a102 +5500 +5d20 +1711 +686f +1d36 +173e +0acf +efff +0a10 +c700 +1f3e +0a00 +afc9 +0b41 +2306 +5403 +5c00 +6a9c +0b41 +2b06 +0b40 +271f +657e +1f3e +6bbb +6bb8 +1f35 +16c0 +6bab +5da0 +6ab5 +0b41 +2e09 +6875 +17c1 +5db0 +6abd +0b41 +2f0a +687d +687e +1f11 +1f91 +1fb7 +1f90 +1f40 +6bb8 +5500 +5d80 +682f +1d92 +1d34 +1f96 +e204 +a004 +c702 +1f72 +c702 +af02 +1f72 +c704 +0b40 +2606 +c602 +683e +1f76 +1f95 +6bb8 +1fa8 +6bab +16c2 +5d80 +6ab5 +0b41 +2e07 +6875 +17c3 +5d90 +6abd +0b41 +2f08 +687d +687e +6bb8 +15a7 +683d +1f94 +6bb8 +1fa9 +0b41 +2302 +e004 +a702 +06b5 +af01 +06b3 +0b41 +2b02 +5600 +5e53 +0437 +1f5b +e201 +a706 +5380 +5b00 +6ba3 +5508 +5d55 +af16 +e202 +a706 +53c0 +5b00 +6ba3 +5510 +5d55 +af0e +e204 +a706 +53f0 +5b00 +6ba3 +5520 +5d55 +af06 +53ff +5b00 +6ba3 +5540 +5d55 +af00 +07e6 +e004 +a02a +1540 +0a08 +e500 +a426 +0b40 +2752 +6df0 +a622 +1791 +1591 +6ba8 +683d +1f11 +1f91 +1fb7 +1790 +683d +1f90 +1f40 +1772 +6bb8 +1f72 +1796 +683d +1f96 +1792 +683d +1f92 +1f34 +1795 +683d +1f95 +1f76 +17a8 +683d +1fa8 +173b +683d +1f3b +173c +683d +1f3c +1540 +0a08 +e500 +a421 +0b40 +2751 +6df0 +a61d +5700 +5f10 +687d +1f36 +173b +0af0 +ef00 +683d +1f3b +1740 +6ba8 +683d +1f90 +1f40 +5700 +5f70 +683d +1f92 +1f34 +175b +0aff +eff0 +c706 +1f5b +173e +0acf +efff +067c +1f3e +6b83 +6b80 +6b8b +0c20 +e011 +a005 +6358 +cb11 +6ce3 +a506 +8f54 +6378 +cf01 +6cdf +a501 +8f4f +6a0a +a002 +6b8b +0c20 +6370 +ce01 +d604 +5700 +5f61 +6837 +6b88 +6a0a +a704 +0b51 +2700 +2f00 +af03 +0b51 +2701 +2f00 +6b89 +0b51 +2702 +2f01 +0b51 +2703 +2f02 +0b51 +2704 +2f03 +6370 +ce01 +d604 +5700 +5f62 +6837 +0b52 +2700 +2f00 +6370 +ce01 +d608 +5700 +5f65 +6837 +042f +2f00 +6ba8 +042f +2f01 +6ba8 +042f +2f02 +6ba8 +042f +2f03 +6ba8 +042f +2f04 +6ba8 +17b7 +2f05 +6ba8 +042f +2f06 +6ba8 +042f +0b40 +2252 +6da0 +a602 +0a01 +c700 +0b40 +2212 +2f07 +6ba8 +bf3a +6b88 +6370 +ce01 +d604 +5700 +5f61 +6837 +0b51 +2705 +2f00 +0b51 +2706 +2f01 +0b51 +2707 +2f02 +0b51 +2708 +2f03 +6370 +ce01 +d604 +5700 +5f62 +6837 +0b52 +2701 +2f00 +6370 +ce01 +d608 +5700 +5f65 +6837 +0b55 +2700 +2f00 +0b55 +2701 +2f01 +0b55 +2702 +2f02 +0b55 +2703 +2f03 +0b55 +2704 +2f04 +0b55 +2705 +2f05 +0b55 +2706 +2f06 +0b55 +2707 +2f07 +e020 +0aff +b069 +6b80 +5680 +5e61 +5732 +5f22 +2f00 +570f +5f90 +2f01 +578c +5f86 +0b40 +2016 +6d80 +a602 +5742 +5f66 +2f02 +2f06 +5700 +5f20 +2f03 +2f07 +5725 +5f55 +2f04 +blockend +blockstart +address 08ac +length 144 +57f0 +5f91 +2f05 +5680 +5e62 +5702 +5f00 +2f00 +2f04 +5600 +5e66 +5710 +5fe1 +2f00 +2f08 +5700 +5ff8 +0b40 +2351 +6db0 +a602 +5700 +5f18 +2f01 +2f09 +1fb9 +06fd +1fba +57ff +5f00 +2f03 +2f0b +5700 +5f00 +2f04 +2f0c +5701 +5f00 +2f05 +2f0d +2f06 +2f0e +5701 +5f01 +2f07 +2f0f +0b40 +2351 +6db0 +8630 +0c20 +568c +5e61 +0b51 +2700 +0aff +ef0f +c720 +2f00 +0b51 +2702 +2f01 +0b51 +2703 +2f02 +0b51 +2704 +2f03 +0b52 +2700 +0b62 +2f8c +5618 +5e66 +042f +2f00 +6ba8 +042f +2f01 +6ba8 +042f +2f02 +6ba8 +042f +2f03 +6ba8 +042f +2f04 +6ba8 +17b7 +2f05 +6ba8 +042f +2f06 +6ba8 +042f +2f07 +af2c +568c +5e61 +0b51 +2705 +2f00 +0b51 +2706 +2f01 +0b51 +2707 +2f02 +0b51 +2708 +2f03 +0b52 +2701 +0b62 +2f8c +5618 +5e66 +0b55 +2700 +2f00 +0b55 +2701 +2f01 +0b55 +2702 +2f02 +0b55 +2703 +2f03 +0b55 +2704 +2f04 +0b55 +2705 +2f05 +0b55 +2706 +2f06 +0b55 +2707 +2f07 +0000 +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +blockstart +address 093c +length 126 +0b40 +2010 +6b8b +6bb3 +e004 +a711 +0b40 +2052 +6d80 +a601 +0618 +0b40 +2050 +6d80 +a608 +56ff +5eff +0617 +0619 +061a +061c +061d +061b +1e03 +6b83 +6370 +d608 +0a64 +c680 +6cc8 +a604 +5700 +5ffc +0477 +9f02 +6bbb +0477 +e00f +b0f2 +6b80 +0b40 +2010 +e004 +a748 +0b40 +2050 +6d80 +a644 +6d81 +a634 +5004 +5869 +0407 +5105 +5905 +0441 +5000 +5856 +6b8b +1503 +06d7 +06d9 +1d03 +0657 +1d03 +1503 +06dd +06da +1d03 +0402 +e1ff +9116 +6bb3 +e610 +840e +530f +5b00 +1503 +06da +1d03 +6521 +9502 +065c +06dc +1d03 +065a +1d03 +bff1 +6bb0 +1503 +1d03 +6b80 +bfe4 +6b88 +1503 +06dc +065d +1d03 +5004 +5869 +0447 +af0e +1503 +06d7 +0000 +0000 +0000 +0000 +0000 +1d03 +0657 +0659 +06da +06dc +065d +1d03 +1603 +06e8 +1efb +0b40 +2052 +0600 +a601 +0668 +1efc +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +blockstart +address 09ba +length 402 +6b83 +6b8b +0b40 +2212 +0b40 +2313 +0b40 +2414 +5600 +5e64 +0610 +0611 +0612 +0613 +0614 +0615 +061e +0b40 +2517 +6dd0 +a602 +0617 +0616 +19fa +6db0 +6dc0 +a601 +6b8b +6370 +d608 +0a64 +c600 +6cc8 +0a00 +a6b1 +5700 +5ffc +0477 +e003 +0a00 +97ad +0b67 +2e0d +5700 +5f86 +2f01 +57bf +5f0f +2f03 +5714 +5f00 +0b6a +2f13 +6bbb +c720 +6838 +0676 +0b6a +2f03 +e202 +a13f +5740 +5f2a +2f02 +5704 +5f2b +0b69 +2f11 +5704 +5f20 +0b69 +2f19 +0b40 +2717 +6df0 +a509 +570b +5f00 +0b6a +2f12 +57bf +5f0f +0b64 +2f1b +af08 +570b +5f00 +0b6a +2f12 +57ef +5f0f +0b64 +2f1b +5705 +5f05 +0b69 +2f04 +0b69 +2f05 +e201 +a701 +af70 +0b40 +2717 +6df0 +a509 +570b +5f00 +0b6a +2f12 +57bf +5f0f +0b64 +2f1b +af08 +570b +5f00 +0b6a +2f12 +57ef +5f0f +0b64 +2f1b +af5a +e204 +a729 +5744 +5f2a +2f02 +0b40 +2717 +6df0 +a509 +5712 +5f00 +0b6a +2f12 +577f +5f0f +0b64 +2f1b +af08 +5712 +5f00 +0b6a +2f12 +577f +5f0f +0b64 +2f1b +5701 +5f01 +0b69 +2f04 +5705 +5f05 +0b69 +2f05 +5704 +5f2b +0b69 +2f11 +5704 +5f20 +0b69 +2f19 +af2f +5744 +5f2a +2f02 +577f +5f0f +0b64 +2f1b +0b40 +2717 +6df0 +a509 +5712 +5f00 +0b6a +2f12 +577f +5f0f +0b64 +2f1b +af08 +5712 +5f00 +0b6a +2f12 +577f +5f0f +0b64 +2f1b +5701 +5f01 +0b69 +2f04 +5705 +5f05 +0b69 +2f05 +5704 +5f2b +0b69 +2f11 +5704 +5f20 +0b69 +2f19 +af02 +6bbb +0477 +e010 +0aff +b043 +6b80 +171e +1ffd +0b40 +2052 +6d80 +a601 +0670 +1ffe +0b40 +2017 +6d80 +a539 +6bbb +067e +0675 +0672 +0b54 +2f01 +6bbb +067e +0675 +0671 +0670 +0b54 +2f02 +6bbb +067e +0675 +0672 +0674 +0b54 +2f03 +6bbb +067e +0675 +0671 +0670 +0674 +0b54 +2f04 +6bbb +067e +0675 +0672 +0670 +0b54 +2f05 +0b54 +2f06 +0b41 +2104 +0691 +0b41 +2904 +0b41 +2105 +0691 +0b41 +2905 +0b40 +2118 +6d91 +a503 +5100 +5910 +af42 +5100 +5911 +af3f +6bbb +067e +0675 +0677 +0672 +0b54 +2f01 +6bbb +067e +0675 +0672 +0671 +0670 +0b54 +2f02 +6bbb +067e +0675 +0672 +0674 +0677 +0b54 +2f03 +6bbb +067e +0675 +0672 +0671 +0670 +0674 +0b54 +2f04 +6bbb +067e +0675 +0672 +0670 +0677 +0676 +0b54 +2f05 +0b54 +2f06 +0b41 +2104 +0611 +0b41 +2904 +0b41 +2105 +0611 +0b41 +2905 +0b40 +2118 +6d91 +a503 +5100 +5912 +af03 +5100 +5913 +af00 +0b54 +2900 +0008 +6b9b +1402 +15fa +6373 +d608 +0a64 +c600 +0437 +e303 +a207 +e30f +a208 +6ce3 +a503 +06fe +6c2b +af02 +06ff +6c2b +0477 +e310 +b0ed +6b98 +5314 +5b00 +0b6a +2b13 +0008 +6b9b +1402 +15fa +6373 +d608 +0a64 +c600 +0437 +6ceb +a603 +067e +067f +0477 +e310 +b0f4 +6b98 +5314 +5b00 +0b6a +2b13 +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +blockstart +address 0b4c +length 221 +0b40 +2010 +6b8b +5600 +5e41 +e001 +a703 +570f +5f41 +af07 +e002 +a703 +571e +5f41 +af02 +572d +5f41 +043d +0475 +6bb8 +6bb0 +e10e +b7fa +6b88 +0008 +1002 +060e +1802 +6b8b +510f +6b89 +e100 +a7fd +068e +1802 +6b8b +51f0 +6b89 +e100 +a7fd +060e +1802 +6b8b +510f +6b89 +e100 +a7fd +0008 +6b83 +5100 +5941 +040a +1a04 +6bbb +5728 +6bb9 +a7fe +6b80 +e00e +b7f7 +6b88 +0008 +5010 +5860 +5100 +5960 +0b40 +2213 +6da0 +a504 +040b +06bb +044b +af03 +040b +063b +044b +6b88 +6b88 +6a08 +a7f3 +0008 +0b40 +2017 +6d81 +a50b +0b41 +2104 +0697 +0b41 +2904 +0b41 +2105 +0697 +0b41 +2905 +af0a +0b41 +2104 +0617 +0b41 +2904 +0b41 +2105 +0617 +0b41 +2905 +0008 +0b40 +2010 +0b40 +2111 +0b40 +2751 +6df0 +a61c +e004 +a015 +e101 +a218 +0b41 +230c +06b8 +06b9 +0b41 +2b0c +0b41 +2300 +063a +0b41 +2b00 +6df1 +a60b +0b41 +2302 +0636 +0b41 +2b02 +8f05 +0b41 +2300 +5300 +0b41 +2b00 +0008 +0b40 +2753 +e704 +a236 +ef03 +0b40 +2010 +0b40 +2111 +e004 +a009 +0b41 +230c +0afc +ebff +6578 +681f +0b41 +2b0c +af26 +0b41 +2300 +5300 +e102 +a404 +6df0 +a61a +5301 +af18 +e110 +a40b +e701 +a014 +a102 +5311 +af11 +e703 +a402 +5388 +af0d +5399 +af0b +e701 +a009 +a102 +5355 +af06 +e703 +a402 +53aa +af02 +53ff +af00 +e004 +a401 +eb0f +0b41 +2b00 +0008 +0b40 +2010 +e004 +a709 +0b40 +2052 +6d80 +a605 +0b41 +2700 +06f6 +0b41 +2f00 +0008 +6bb9 +a7fe +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +blockstart +address 1000 +length 134 +0634 +1b07 +6b83 +6b80 +e004 +a7fd +06b4 +1b07 +6b83 +6b80 +e004 +a7fd +6b83 +1100 +0698 +1900 +1801 +0017 +8a68 +001f +1f02 +0670 +1f02 +1e02 +1f02 +0673 +1f02 +1b07 +1100 +0618 +1900 +6353 +063c +1186 +6d10 +1986 +198e +11fe +191e +0000 +11fc +1903 +1100 +0019 +1b07 +1a07 +06f3 +0698 +1900 +001e +06bc +1831 +1186 +6d10 +1986 +198e +1134 +12b8 +6c8a +4ce0 +9615 +1f02 +12b7 +e000 +9205 +1a40 +684a +1236 +684a +1934 +1c07 +0000 +1d07 +0000 +0014 +0000 +12b7 +680a +1236 +680a +12b1 +1a40 +4ce1 +a609 +12bb +684a +1934 +1c07 +0000 +1d07 +0014 +0000 +680a +6b93 +1a01 +6d80 +9502 +1a70 +12b6 +1934 +11ba +1981 +1989 +1a10 +11b7 +6811 +1a11 +11b9 +1981 +1989 +11fd +191e +11fb +1903 +11b4 +6b80 +6a01 +1c07 +b09a +1d07 +11b3 +1934 +0008 +001f +06d4 +1c07 +1d07 +11b3 +1934 +6b8b +1910 +11b7 +1911 +0008 +blockend +blockstart +address 1100 +length 108 +0634 +1b07 +6b83 +6b80 +e004 +a7fd +06b4 +6b83 +6b80 +e004 +a7fd +6b83 +1100 +0698 +1900 +1801 +0017 +8a50 +001f +1f02 +0670 +1f02 +1e02 +1f02 +0673 +1f02 +1b07 +1100 +0618 +1900 +6353 +063c +06f3 +1186 +6d10 +1986 +198e +11fe +0000 +191e +0000 +11fc +1903 +1100 +0019 +1f02 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0673 +1f02 +1b07 +1a07 +06f3 +0698 +1900 +001e +06bc +1831 +1186 +6d10 +1986 +198e +1192 +6d80 +6b93 +1a01 +1f02 +9503 +1a70 +1296 +684a +1934 +11ba +1981 +1989 +1a10 +11b7 +6811 +1a11 +11b9 +1981 +1989 +11fd +191e +11fb +1903 +1194 +6b80 +6a01 +1c07 +b0b0 +1d07 +0008 +001f +1c07 +1d07 +1192 +1934 +6b8b +1910 +11b7 +1911 +0008 +blockend +blockstart +address 1200 +length 151 +0634 +1b07 +6b83 +6b80 +e004 +a7fd +06b4 +6b83 +6b80 +e004 +a7fd +6b83 +1100 +0698 +1900 +1801 +0677 +0676 +0667 +0666 +6007 +4c00 +06f4 +06e4 +0017 +8a76 +001f +1f02 +0670 +1f02 +1e02 +1f02 +609c +1f02 +0673 +06f2 +0000 +0000 +0000 +0000 +0000 +1f02 +0672 +1100 +0618 +1900 +6353 +1b07 +063c +1186 +6d10 +1986 +198e +11fe +0000 +191e +11fc +0000 +1903 +1100 +0019 +1f02 +1f02 +0673 +1f02 +1b07 +1a07 +06f3 +0698 +1900 +001e +06bc +1831 +1186 +6d10 +1986 +198e +1134 +12b8 +6c8a +4ce0 +9615 +1f02 +12b7 +e000 +9205 +1a40 +684a +1236 +684a +1934 +1c07 +0000 +1d07 +0000 +0014 +0000 +12b7 +680a +1236 +680a +12b1 +1a40 +4ce1 +a609 +12bb +684a +1934 +1c07 +0000 +1d07 +0014 +0000 +680a +6b93 +1a01 +6d80 +9502 +1a70 +12b6 +1934 +11ba +1981 +1989 +1a10 +11b7 +6811 +1a11 +11b9 +1981 +1989 +11fd +191e +11fb +1903 +11b4 +6b80 +6a01 +1c07 +b08c +1d07 +11b3 +1934 +0008 +11b3 +1934 +6b8b +1910 +11b7 +1911 +0008 +blockend +blockstart +address 1300 +length 117 +0634 +1b07 +6b83 +6b80 +e004 +a7fd +06b4 +6b83 +6b80 +e004 +a7fd +6b83 +1100 +0698 +1900 +1801 +1f02 +0670 +1f02 +06f7 +06f6 +1f02 +0677 +0676 +1f02 +06f0 +0017 +8a4f +001f +1f02 +0670 +1f02 +1e02 +1f02 +0673 +06f2 +1f02 +0672 +1b07 +1100 +0618 +1900 +6353 +063c +06f3 +1186 +6d10 +1986 +198e +11fe +0000 +191e +0000 +11fc +1903 +1100 +0019 +1f02 +0000 +0000 +0000 +0000 +0673 +1f02 +1b07 +1a07 +06f3 +0698 +1900 +001e +06bc +1831 +1186 +6d10 +1986 +198e +1192 +6d80 +6b93 +1a01 +1f02 +b503 +1a70 +1296 +684a +1934 +11ba +1981 +1989 +1a10 +11b7 +6811 +1a11 +11b9 +1981 +1989 +11fd +191e +11fb +1903 +1194 +6b80 +6a01 +1c07 +b0b1 +1d07 +0008 +001f +1c07 +1d07 +1192 +1934 +6b8b +1910 +11b7 +1911 +0008 +blockend +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +5fff 0240 +5ffd 0323 +5ffe 2011 +5fff 1636 +6903 0000 diff --git a/nottcontrol/camera/macie/macie_exe/MacieMain.c b/nottcontrol/camera/macie/macie_exe/MacieMain.c new file mode 100644 index 00000000..9fa57a27 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/MacieMain.c @@ -0,0 +1,1680 @@ +// Macie_exe.c +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2019, Jarron Leisenring, All rights reserved. +// + +#include "macie_lib.h" + +#include +#include +#include + +#include +#include + +#include +#include + +// #ifndef FALSE +// #define FALSE 0 +// #endif +// #ifndef TRUE +// #define TRUE (!(FALSE)) +// #endif + +#include +// using namespace std; +using std::map; +using std::string; +using std::vector; + +// Timestamp in terms of microsec +typedef unsigned long long timestamp_t; +static timestamp_t get_timestamp() +{ + struct timeval now; + gettimeofday(&now, NULL); + return now.tv_usec + (timestamp_t)now.tv_sec * 1000000; +} + +// Run an ASIC Tuning file +bool run_asic_tune_file(string tuneFile, MACIE_Settings *ptUserData); + +// Testing buffere allocation function +bool test_buff_config(MACIE_Settings *ptUserData, int buffsize, short nbuf); + +// Function to parse camera/mode-specific config file and load settings +bool ParseConfig(string configFile, MACIE_Settings *ptUserData, bool update_regs); + +// Function to initialize MACIE/ASIC/Detector +bool InitCamera(string configFile, MACIE_Connection connection, MACIE_Settings *ptUserData); + +// Free up resources +bool free_resources(MACIE_Settings *ptUserData); + +// returns number of words in char string +unsigned int countWords(char *str); + +// Test if string is HEX or decimal by presence of "0x" +unsigned int str2uint(string option); + +// Class to parse command line input +class InputParser +{ +public: + InputParser(int &argc, char **argv) + { + for (int i = 1; i < argc; ++i) + this->tokens.push_back(std::string(argv[i])); + } + const std::string &getCmdOption(const std::string &option) const + { + std::vector::const_iterator itr; + itr = std::find(this->tokens.begin(), this->tokens.end(), option); + if (itr != this->tokens.end() && ++itr != this->tokens.end()) + { + return *itr; + } + static const std::string empty_string(""); + return empty_string; + } + bool cmdOptionExists(const std::string &option) const + { + return std::find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end(); + } + +private: + std::vector tokens; +}; + +/////////////////////////////////////////////////// +// Tab completion from: +// https://eli.thegreenplace.net/2016/basics-of-using-the-readline-library/ +// Update README.md after adding new commands +string arr[] = {"testing", "initCamera", "expSettings", "intTime", "frameSettings", "reconfigASIC", "acquire", + "readASIC_block", "readASIC", "writeASIC", "printRegs", "updateRegMap", "setParam", "getParam", + "readASICconfig", "getInputs", "setInputs", "setGain", "getGain", "setNBuffer", "getNBuffer", + "setCapComp", "getCapComp", "setFiltPole", "getFiltPole", "setNOut", "getNOut", + "setClock", "getClock", "setPhase", "getPhase", "findPhase", "getErrors", "resetErrors", + "setVerbose", "getVerbose", "exit", "quit", "getPower", "getVoltages", "setLED", + "powerOff", "powerOn", "readMACIE", "writeMACIE", "haltAcq", "configBuffers", "runTuneAcq"}; +vector vocabulary(arr, arr + sizeof(arr) / sizeof(arr[0])); + +char *completion_generator(const char *text, int state) +{ + // This function is called with state=0 the first time; subsequent calls are + // with a nonzero state. state=0 can be used to perform one-time + // initialization for this completion session. + static std::vector matches; + static size_t match_index = 0; + + if (state == 0) + { + // During initialization, compute the actual matches for 'text' and keep + // them in a static vector. + matches.clear(); + match_index = 0; + + // Collect a vector of matches: vocabulary words that begin with text. + std::string textstr = std::string(text); + std::vector::iterator it; + for (it = vocabulary.begin(); it != vocabulary.end(); it++) + { + string word = *it; + if ((word.size() >= textstr.size()) && (word.compare(0, textstr.size(), textstr) == 0)) + { + matches.push_back(word); + } + } + } + + if (match_index >= matches.size()) + { + // We return nullptr to notify the caller no more matches are available. + return NULL; + } + else + { + // Return a malloc'd char* for the match. The caller frees it. + return strdup(matches[match_index++].c_str()); + } +} + +char **completer(const char *text, int start, int end) +{ + // Don't do filename completion even if our generator finds no matches. + rl_attempted_completion_over = 1; + + // Note: returning nullptr here will make readline use the default filename + // completer. + return rl_completion_matches(text, completion_generator); +} + +int initialize(string configFile, MACIE_Settings *ptUserData) +{ + std::cout << std::fixed << std::setprecision(1); + std::cout << "MACIE Library Version: " << MACIE_LibVersion() << std::endl; + + if (create_param_struct(ptUserData, LOG_INFO) == false) + { + std::cout << "create_param_struct failed. Exiting." << std::endl; + return -1; + } + + // ptUserData->offline_develop = true; + + // Initialize MACIE interface + if (MACIE_Init() != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_Init failed: %s\n", MACIE_Error()); + free_resources(ptUserData); + return -1; + } + + return 0; +} + +void halt_acquisition(MACIE_Settings *ptUserData) +{ + verbose_printf(LOG_INFO, ptUserData, "Halting Data Acquisition...\n"); + + // What is the proper order? + HaltCameraAcq(ptUserData); + delay(300); + CloseGigEScienceInterface(ptUserData); +} + +void acquire(bool no_recon, MACIE_Settings *ptUserData ) +{ + verbose_printf(LOG_INFO, ptUserData, "Starting Data Acquisition...\n"); + + // First reconfigure ASIC in case we forgot + // Then trigger image acquisition + // Then download and save data + bool bOutput = true; + if (!no_recon) + { + timestamp_t t0 = get_timestamp(); + bOutput = ReconfigureASIC(ptUserData); + timestamp_t t1 = get_timestamp(); + double time_taken = (t1 - t0) / 1000000.0L; + verbose_printf(LOG_INFO, ptUserData, "ReconfigureASIC() took %f seconds to execute.\n", time_taken); + } + + if (bOutput == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfigure ASIC failed at %s()\n", __func__); + } + else if (AcquireDataGigE(ptUserData, false) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "AcquireDataGigE failed at %s()\n", __func__); + } + else + { + timestamp_t t0 = get_timestamp(); + DownloadAndSaveAllUSB(ptUserData); + timestamp_t t1 = get_timestamp(); + double time_taken = (t1 - t0) / 1000000.0L; + printf("\nDownloadAndSaveAllUSB() took %f seconds to execute.\n", time_taken); + } + + // Check for errors + GetErrorCounters(ptUserData, false); + uint errCnts = 0; + for (int j = 0; j < MACIE_ERROR_COUNTERS; j++) + errCnts += (uint)ptUserData->errArr[j]; + if (errCnts > 0) + { + verbose_printf(LOG_WARNING, ptUserData, "MACIE Errors encountered!\n"); + if (get_verbose(ptUserData) <= LOG_WARNING) + GetErrorCounters(ptUserData, true); + + // If just science errors, then reset error counters + errCnts = 0; + for (int j = 0; j < 25; j++) + errCnts += (uint)ptUserData->errArr[j]; + if (errCnts == 0) + { + verbose_printf(LOG_INFO, ptUserData, "Resetting error counters...\n"); + ResetErrorCounters(ptUserData); + } + } +} + +void toggle_offline_testing(bool offline_testing, MACIE_Settings *ptUserData) +{ + ptUserData->offline_develop = offline_testing; +} + +// Run command line executable: +// $ ./macieacq config_files/basic_slow_HxRG_warm.cfg +int main(int argc, char *argv[]) +{ + string option, configFile; + unsigned int val = 0; + unsigned short addr = 0; + struct MACIE_Settings *ptUserData = new MACIE_Settings;; + + // Get config file and copy to string + if (argc == 1) + { + std::cout << "\nNo config file name passed..." << std::endl; + return -1; + } + else if (argc > 2) + { + std::cout << "\nToo many argument passed. Requires only 1." << std::endl; + return -1; + } + else + { + string configFile = argv[1]; + + if(initialize(configFile, ptUserData) == -1) + { + return -1; + } + } + + // Command line info + string line; + int argc2 = 0; + + map::iterator it; + regInfo *reg; + + rl_attempted_completion_function = completer; + + char *buf; + std::cout << "\nEnter a command. Type 'exit' or 'quit' to end. \n"; + std::cout << "Use Tab key to print list of commands (tab completion enabled). \n"; + do + { + + buf = readline(">> "); + line = string(buf); + + if (strlen(buf) > 0) + { + add_history(buf); + } + + argc2 = countWords(buf) + 1; // Number of words in input + char *argv2[argc2]; // Create char pointer array + + // Separate words to array positions + argv2[0] = argv[0]; + argv2[1] = strtok(buf, " ="); + verbose_printf(LOG_DEBUG, ptUserData, "0 %i %s\n", argc2, argv2[0]); + verbose_printf(LOG_DEBUG, ptUserData, "1 %i %s\n", argc2, argv2[1]); + for (int i = 2; i < argc2; ++i) + { + argv2[i] = strtok(NULL, " ="); + verbose_printf(LOG_DEBUG, ptUserData, "%i %i %s\n", i, argc2, argv2[i]); + } + + // Parse input options + InputParser input2(argc2, argv2); + + //////////////////////////////////////////////////////////////////////////////// + // Enable/disable offline software testing/debugging + if (input2.cmdOptionExists("testing")) + { + option = input2.getCmdOption("testing"); + transform(option.begin(), option.end(), option.begin(), ::tolower); + if ((option == "true") || (option == "1")) + { + verbose_printf(LOG_INFO, ptUserData, "Offline testing enabled.\n"); + ptUserData->offline_develop = true; + } + else if ((option == "false") || (option == "0")) + { + verbose_printf(LOG_INFO, ptUserData, "Offline testing disabled.\n"); + ptUserData->offline_develop = false; + } + else + { + printf("Usage: testing true/false\n"); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Initialize Camera (MACIE+ASIC+Detector) + if (input2.cmdOptionExists("initCamera")) + { + verbose_printf(LOG_INFO, ptUserData, "Initializing Camera...\n"); + if (InitCamera(configFile, MACIE_GigE, ptUserData) == false) + verbose_printf(LOG_ERROR, ptUserData, "InitCamera failed at %s()\nReturning.\n", __func__); + else + verbose_printf(LOG_INFO, ptUserData, "InitCamera Completed\n"); + + // unsigned int valOut; + // unsigned int bitmask = (1 << 11) - 1; + // float volts = 0; + // unsigned int dac_val = 0; + + // reg = &(ptUserData->RegMap["VReset1"]); + // ReadASICBits(ptUserData, reg, &valOut); + // valOut &= bitmask; + + // volts = ConvertDACToV(valOut); + // printf("h%04x[0:10] = 0x%04x (%f V)\n", reg->addr, valOut, volts); + // dac_val = ConvertVToDAC(volts); + // printf("%f V -> 0x%04x\n", volts, dac_val); + + // reg = &(ptUserData->RegMap["DSub1"]); + // ReadASICBits(ptUserData, reg, &valOut); + // valOut &= bitmask; + + // volts = ConvertDACToV(valOut); + // printf("h%04x[0:10] = 0x%04x (%f V)\n", reg->addr, valOut, volts); + // dac_val = ConvertVToDAC(volts); + // printf("%f V -> 0x%04x\n", volts, dac_val); + } + + //////////////////////////////////////////////////////////////////////////////// + // MACIE Power and Voltage values + if (input2.cmdOptionExists("getPower")) + { + bool pArr[MACIE_PWR_CTRL_SIZE]; + GetPower(ptUserData, pArr); + } + if (input2.cmdOptionExists("getVoltages")) + { + float vArr[MACIE_PWR_DAC_SIZE]; + GetVoltages(ptUserData, vArr); + } + if (input2.cmdOptionExists("powerOff")) + { + SetPowerASIC(ptUserData, false); + } + if (input2.cmdOptionExists("powerOn")) + { + bool bEn = false; + GetPowerASIC(ptUserData, &bEn); + if (bEn == true) + { + verbose_printf(LOG_INFO, ptUserData, "ASIC already powered ON\n"); + } + else + { + if (SetPowerASIC(ptUserData, true) == true) + { + LoadASIC(ptUserData); + ParseConfig(configFile, ptUserData, true); + } + } + } + if (input2.cmdOptionExists("setLED")) + { + option = input2.getCmdOption("setLED"); + if (!option.empty()) + { + val = str2uint(option); + SetLED(ptUserData, val); + } + else + { + printf("Usage: setLED [0-4]\n"); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Update Exposure Settings + if (input2.cmdOptionExists("expSettings")) + { + + // Grab current values + bool bSave = ptUserData->bSaveData; + unsigned int ncoadds = ptUserData->uiNumCoadds; + unsigned int nsaved_ramps = ASIC_NRamps(ptUserData, false, 0) / ncoadds; + unsigned int ngroups = ASIC_NGroups(ptUserData, false, 0); + unsigned int nreads = ASIC_NReads(ptUserData, false, 0); + unsigned int ndrops = ASIC_NDrops(ptUserData, false, 0); + unsigned int nresets = ASIC_NResets(ptUserData, false, 0); + + // Print help + option = input2.getCmdOption("expSettings"); + // if ( (input2.cmdOptionExists("--help")) || option.empty() ) + if (input2.cmdOptionExists("--help")) + { + printf("Usage: expSettings --save bool -c ncoadds -i nseq -g ngroups -r nreads -s ndrops -k nresets\n"); + } + else + { + verbose_printf(LOG_INFO, ptUserData, "Updating Exposure Settings...\n"); + + // Save Data? + option = input2.getCmdOption("--save"); + if (!option.empty()) + { + transform(option.begin(), option.end(), option.begin(), ::tolower); + bSave = ((option == "false") || (option == "0")) ? false : true; + } + + // Coadds + option = input2.getCmdOption("-c"); + if (!option.empty()) + ncoadds = atoi(option.c_str()); + // Ramps (Integrations) + option = input2.getCmdOption("-i"); + if (!option.empty()) + nsaved_ramps = atoi(option.c_str()); + // Groups + option = input2.getCmdOption("-g"); + if (!option.empty()) + ngroups = atoi(option.c_str()); + // Reads + option = input2.getCmdOption("-r"); + if (!option.empty()) + nreads = atoi(option.c_str()); + // Drops (Spin) + option = input2.getCmdOption("-s"); + if (!option.empty()) + ndrops = atoi(option.c_str()); + // Resets + option = input2.getCmdOption("-k"); + if (!option.empty()) + nresets = atoi(option.c_str()); + + set_exposure_settings(ptUserData, bSave, ncoadds, nsaved_ramps, + ngroups, nreads, ndrops, nresets); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Update Frame Settings + if (input2.cmdOptionExists("intTime")) + { + + // Grab current values + bool bSave = ptUserData->bSaveData; + unsigned int ncoadds = ptUserData->uiNumCoadds; + unsigned int nsaved_ramps = ASIC_NRamps(ptUserData, false, 0) / ncoadds; + unsigned int ngroups = ASIC_NGroups(ptUserData, false, 0); + unsigned int nreads = ASIC_NReads(ptUserData, false, 0); + unsigned int ndrops = ASIC_NDrops(ptUserData, false, 0); + unsigned int nresets = ASIC_NResets(ptUserData, false, 0); + + double tint_ms = 0; + unsigned int ngmax = 0; + + // Print help + option = input2.getCmdOption("intTime"); + if ((input2.cmdOptionExists("--help")) || option.empty()) + { + printf("Usage: intTime -t tint_ms -g ngmax\n"); + } + else + { + + option = input2.getCmdOption("-t"); + if (!option.empty()) + tint_ms = strtod(option.c_str(), NULL); + // Ramps (Integrations) + option = input2.getCmdOption("-g"); + if (!option.empty()) + ngmax = atoi(option.c_str()); + + calc_ramp_settings(ptUserData, tint_ms, ngmax, &ngroups, &ndrops, &nreads); + set_exposure_settings(ptUserData, bSave, ncoadds, nsaved_ramps, + ngroups, nreads, ndrops, nresets); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Update Frame Settings + if (input2.cmdOptionExists("frameSettings")) + { + + // Grab current values + unsigned int x1 = ASIC_getX1(ptUserData); + unsigned int x2 = ASIC_getX2(ptUserData); + unsigned int y1 = ASIC_getY1(ptUserData); + unsigned int y2 = ASIC_getY2(ptUserData); + bool bHorzWin = (bool)ASIC_WinHorz(ptUserData, false, 0); + bool bVertWin = (bool)ASIC_WinVert(ptUserData, false, 0); + + // Print help + option = input2.getCmdOption("frameSettings"); + if ((input2.cmdOptionExists("--help")) || option.empty()) + { + printf("Usage: frameSettings --xWin bool --yWin bool -x1 uint -x2 uint -y1 uint -y2 uint\n"); + } + else + { + verbose_printf(LOG_INFO, ptUserData, "Updating Frame Settings...\n"); + + // Horizontal Window + option = input2.getCmdOption("--xWin"); + if (!option.empty()) + { + transform(option.begin(), option.end(), option.begin(), ::tolower); + bHorzWin = ((option == "false") || (option == "0")) ? false : true; + } + // Vertical Window + option = input2.getCmdOption("--yWin"); + if (!option.empty()) + { + transform(option.begin(), option.end(), option.begin(), ::tolower); + bVertWin = ((option == "false") || (option == "0")) ? false : true; + } + + // update x1 + option = input2.getCmdOption("-x1"); + if (!option.empty()) + x1 = atoi(option.c_str()); + // update x2 + option = input2.getCmdOption("-x2"); + if (!option.empty()) + x2 = atoi(option.c_str()); + // update y1 + option = input2.getCmdOption("-y1"); + if (!option.empty()) + y1 = atoi(option.c_str()); + // update y2 + option = input2.getCmdOption("-y2"); + if (!option.empty()) + y2 = atoi(option.c_str()); + + set_frame_settings(ptUserData, bHorzWin, bVertWin, x1, x2, y1, y2); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Update PreAmp Inputs, Gain, Cap Comp, and Filter Pole + if (input2.cmdOptionExists("setInputs")) + { + option = input2.getCmdOption("setInputs"); + if (!option.empty()) + { + // Always assume input value is 16bit HEX string + val = strtoul(option.c_str(), NULL, 16); + val = ASIC_Inputs(ptUserData, true, val); + } + else + { + printf("Usage: setInputs 0xaaaa\n"); + } + } + if (input2.cmdOptionExists("setGain")) + { + option = input2.getCmdOption("setGain"); + if (!option.empty()) + { + val = str2uint(option); + val = ASIC_Gain(ptUserData, true, val); + } + else + { + printf("Usage: setGain [0-15]\n"); + } + } + if (input2.cmdOptionExists("setCapComp")) + { + option = input2.getCmdOption("setCapComp"); + if (!option.empty()) + { + val = str2uint(option); + val = ASIC_CapComp(ptUserData, true, val); + } + else + { + printf("Usage: setCapComp [0-63]\n"); + } + } + if (input2.cmdOptionExists("setFiltPole")) + { + option = input2.getCmdOption("setFiltPole"); + if (!option.empty()) + { + val = str2uint(option); + val = ASIC_FiltPole(ptUserData, true, val); + } + else + { + printf("Usage: setFiltPole [0-15]\n"); + } + } + if (input2.cmdOptionExists("setNOut")) + { + option = input2.getCmdOption("setNOut"); + if (!option.empty()) + { + val = str2uint(option); + val = ASIC_NumOutputs(ptUserData, true, val); + } + else + { + printf("Usage: setNOut [1,2,4,16,32]\n"); + } + } + if (input2.cmdOptionExists("getInputs")) + ASIC_Inputs(ptUserData, false, 0); + if (input2.cmdOptionExists("getGain")) + ASIC_Gain(ptUserData, false, 0); + if (input2.cmdOptionExists("getCapComp")) + ASIC_CapComp(ptUserData, false, 0); + if (input2.cmdOptionExists("getFiltPole")) + ASIC_FiltPole(ptUserData, false, 0); + if (input2.cmdOptionExists("getNOut")) + ASIC_NumOutputs(ptUserData, false, 0); + + //////////////////////////////////////////////////////////////////////////////// + // Acquire data + if (input2.cmdOptionExists("acquire")) + { + acquire(input2.cmdOptionExists("--no_recon"), ptUserData); + } + // Halt a failed acquisition + if (input2.cmdOptionExists("haltAcq")) + { + // What is the proper order? + HaltCameraAcq(ptUserData); + delay(300); + CloseUSBScienceInterface(ptUserData); + } + + //////////////////////////////////////////////////////////////////////////////// + // Read specific MACIE register + if (input2.cmdOptionExists("readMACIE")) + { + option = input2.getCmdOption("--addr"); + if (!option.empty()) + { + addr = strtoul(option.c_str(), NULL, 16); + MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, addr, &val); + printf("h%04x = 0x%04x\n", addr, val); + } + else + { + // In case we forget the --addr argument + // (which happens all the time) + option = input2.getCmdOption("readMACIE"); + if (!option.empty()) + { + addr = strtoul(option.c_str(), NULL, 16); + MACIE_ReadMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, addr, &val); + printf("h%04x = 0x%04x\n", addr, val); + } + else + { + printf("Usage: readMACIE --addr 0x4000\n"); + } + } + } + //////////////////////////////////////////////////////////////////////////////// + // Write MACIE register + // Address and values assumed to be in HEX + if (input2.cmdOptionExists("writeMACIE")) + { + // Get address + option = input2.getCmdOption("--addr"); + if (option.empty()) + { + addr = 0; + } + else + { + addr = strtoul(option.c_str(), NULL, 16); + } + + // Get value + option = input2.getCmdOption("--val"); + if (option.empty()) + { + val = 0; + } + else + { + val = str2uint(option); // Checks if hex (0x) or dec + // val = strtoul(option.c_str(), NULL, 16); + } + + if (addr != 0) + { + MACIE_WriteMACIEReg(ptUserData->handle, ptUserData->slctMACIEs, addr, val); + } + else + { + printf("Usage: writeMACIE --addr 0x4000 --val 0x1\n"); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Read specific ASIC register + if (input2.cmdOptionExists("readASIC")) + { + option = input2.getCmdOption("--addr"); + if (!option.empty()) + { + addr = strtoul(option.c_str(), NULL, 16); + ReadASICReg(ptUserData, addr, &val); + printf("h%04x = 0x%04x\n", addr, val); + } + else + { + // In case we forget the --addr argument + // (which happens all the time) + option = input2.getCmdOption("readASIC"); + if (!option.empty()) + { + addr = strtoul(option.c_str(), NULL, 16); + ReadASICReg(ptUserData, addr, &val); + printf("h%04x = 0x%04x\n", addr, val); + } + else + { + printf("Usage: readASIC --addr 0x4000\n"); + } + } + } + //////////////////////////////////////////////////////////////////////////////// + // Write ASIC register + // Address and values assumed to be in HEX + if (input2.cmdOptionExists("writeASIC")) + { + // Get address + option = input2.getCmdOption("--addr"); + if (option.empty()) + { + addr = 0; + } + else + { + addr = strtoul(option.c_str(), NULL, 16); + } + + // Get value + option = input2.getCmdOption("--val"); + if (option.empty()) + { + val = 0; + } + else + { + val = str2uint(option); // Checks if hex (0x) or dec + // val = strtoul(option.c_str(), NULL, 16); + } + + if (addr != 0) + { + WriteASICReg(ptUserData, addr, val); + } + else + { + printf("Usage: writeASIC --addr 0x4000 --val 0x1\n"); + } + } + //////////////////////////////////////////////////////////////////////////////// + // Read specific ASIC register block + if (input2.cmdOptionExists("readASIC_block")) + { + // Get address + option = input2.getCmdOption("--addr"); + if (option.empty()) + { + addr = 0; + } + else + { + addr = strtoul(option.c_str(), NULL, 16); + } + + // Get number of registers + int nreg = 0; + option = input2.getCmdOption("--nreg"); + if (!option.empty()) + { + nreg = str2uint(option); // Checks if hex (0x) or dec + } + + if ((addr != 0) && (nreg != 0)) + { + unsigned int val_arr[nreg] = {}; + ReadASICBlock(ptUserData, addr, nreg, &val_arr[0]); + for (int i = 0; i < nreg; i++) + printf(" h%04x = 0x%04x\n", addr + i, val_arr[i]); + } + else + { + printf("Usage: readASIC_block --addr 0x6000 --nreg 16\n"); + } + } + //////////////////////////////////////////////////////////////////////////////// + // Read specific ASIC register block + if (input2.cmdOptionExists("readASICconfig")) + { + // Get address + option = input2.getCmdOption("--addr"); + if (option.empty()) + { + addr = 0; + } + else + { + addr = strtoul(option.c_str(), NULL, 16); + } + + // Get number of registers + int nreg = 0; + option = input2.getCmdOption("--nreg"); + if (!option.empty()) + { + nreg = str2uint(option); // Checks if hex (0x) or dec + } + + if ((addr != 0) && (nreg != 0)) + { + readASICconfig(ptUserData, addr, nreg); + } + else + { + printf("Usage: readASICconfig --addr 0x6000 --nreg 16\n"); + } + } + //////////////////////////////////////////////////////////////////////////////// + // Update the ASIC reg settings stored in ptUserData + if (input2.cmdOptionExists("updateRegMap")) + { + if (GetASICSettings(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, " GetASICSettings failed to complete.\n"); + return false; + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Print all stored ASIC registry information in RegMap + if (input2.cmdOptionExists("printRegs")) + { + verbose_printf(LOG_INFO, ptUserData, "Current Registry Configuration\n"); + for (it = ptUserData->RegMap.begin(); it != ptUserData->RegMap.end(); it++) + { + reg = &it->second; + printf("%s : h%04x <%i:%i> = 0x%04x\n", + it->first.c_str(), reg->addr, reg->bit1, reg->bit0, reg->value); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Set/Get number of buffers + if (input2.cmdOptionExists("setNBuffer")) + { + option = input2.getCmdOption("setNBuffer"); + if (!option.empty()) + { + val = str2uint(option); + SetNBuffer(ptUserData, (short)val); + verbose_printf(LOG_INFO, ptUserData, " nBuffer = %i\n", ptUserData->nBuffer); + } + else + { + printf("Usage: setNBuffer [1-100]\n"); + } + } + if (input2.cmdOptionExists("getNBuffer")) + { + verbose_printf(LOG_INFO, ptUserData, " nBuffer = %i\n", ptUserData->nBuffer); + } + if (input2.cmdOptionExists("configBuffers")) + { + // Print help + option = input2.getCmdOption("configBuffers"); + if (input2.cmdOptionExists("--help")) + { + printf("Usage: configBuffers --sciFunc bool --buffsize int --nbuf int\n"); + } + else if ((input2.cmdOptionExists("--buffsize")) || (input2.cmdOptionExists("--nbuf"))) + { + // Defaults + int buffsize = 1024 * 1024; + short nbuf = 1; + + option = input2.getCmdOption("--buffsize"); + if (!option.empty()) + buffsize = (int)str2uint(option); + + option = input2.getCmdOption("--nbuf"); + if (!option.empty()) + nbuf = (short)str2uint(option); + + test_buff_config(ptUserData, buffsize, nbuf); + } + else // if ( input2.cmdOptionExists("--sciFunc") ) + { + // Use MACIE_ReadUSBScienceData() instead of MACIE_ReadUSBScienceFrame()? + option = input2.getCmdOption("--sciFunc"); + if (!option.empty()) + { + transform(option.begin(), option.end(), option.begin(), ::tolower); + ptUserData->bUseSciDataFunc = ((option == "false") || (option == "0")) ? false : true; + } + + ConfigBuffers(ptUserData); + if (VerifyBuffers(ptUserData) == false) + verbose_printf(LOG_ERROR, ptUserData, "VerifyBuffers failed!\n"); + else + verbose_printf(LOG_INFO, ptUserData, "VerifyBuffers succeeded.\n"); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Reconfigure ASIC after updating user parameters + if (input2.cmdOptionExists("reconfigASIC")) + { + verbose_printf(LOG_INFO, ptUserData, "Reconfiguring ASIC Registers...\n"); + if (ReconfigureASIC(ptUserData) == false) + verbose_printf(LOG_ERROR, ptUserData, "Reconfigure failed at %s()\n", __func__); + else + verbose_printf(LOG_INFO, ptUserData, "Done.\n"); + } + + //////////////////////////////////////////////////////////////////////////////// + // Run tuning acquisitions + if (input2.cmdOptionExists("runTuneAcq")) + { + option = input2.getCmdOption("runTuneAcq"); + if ((input2.cmdOptionExists("--help")) || (option.empty())) + { + printf("Usage: runTuneAcq filename.txt\n"); + } + else + { + timestamp_t t0 = get_timestamp(); + run_asic_tune_file(option, ptUserData); + timestamp_t t1 = get_timestamp(); + + double time_taken = (t1 - t0) / 1000000.0L; + printf("\nrun_asic_tune_file() took %f seconds to execute.\n", time_taken); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Set/Get MACIE Phase Shift parameters + // Bit 8: enable ASIC phase shift, otherwise phase shift bits 7-0 are ignored + // Bit 7-0: valid values range from 0x00 to 0xFF + if (input2.cmdOptionExists("setPhase")) + { + option = input2.getCmdOption("setPhase"); + if (!option.empty()) + { + // val = str2uint(option); + val = strtoul(option.c_str(), NULL, 16); + SetMACIEPhaseShift(ptUserData, (unsigned short)val); + } + else + { + printf("Usage: setPhase 0x01e0\n"); + } + } + if (input2.cmdOptionExists("getPhase")) + GetMACIEPhaseShift(ptUserData); + if (input2.cmdOptionExists("findPhase")) + { + ushort val1 = 0; + ushort val2 = 0; + + // Get val1 + option = input2.getCmdOption("--val1"); + if (!option.empty()) + val1 = strtoul(option.c_str(), NULL, 16); + // Get val2 + option = input2.getCmdOption("--val2"); + if (!option.empty()) + val2 = strtoul(option.c_str(), NULL, 16); + + if ((val1 == 0) || (val2 == 0)) + { + printf("Usage: findPhase --val1 0x01b0 --val2 0x01e0\n"); + } + else + { + FindOptimalPhaseShift(ptUserData, val1, val2); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Set/Get MACIE Clock Rate + if (input2.cmdOptionExists("setClock")) + { + option = input2.getCmdOption("setClock"); + if (!option.empty()) + { + val = str2uint(option); + // val = strtoul(option.c_str(), NULL, 16); + SetMACIEClockRate(ptUserData, val); + verbose_printf(LOG_INFO, ptUserData, " MACIE Clock Rate = %i MHz\n", ptUserData->clkRateM); + } + else + { + printf("Usage: setClock [5-80]\n"); + } + } + if (input2.cmdOptionExists("getClock")) + { + GetMACIEClockRate(ptUserData); + verbose_printf(LOG_INFO, ptUserData, " MACIE Clock Rate = %i MHz\n", ptUserData->clkRateM); + } + + //////////////////////////////////////////////////////////////////////////////// + // Reset/Read MACIE error counters + if (input2.cmdOptionExists("resetErrors")) + ResetErrorCounters(ptUserData); + if (input2.cmdOptionExists("getErrors")) + GetErrorCounters(ptUserData, true); + + //////////////////////////////////////////////////////////////////////////////// + // Set/Get Log Level Settings + option = input2.getCmdOption("setVerbose"); + transform(option.begin(), option.end(), option.begin(), ::toupper); + if (!option.empty()) + { + set_verbose(ptUserData, convert_log_type(option.c_str())); + printf("New log levels: %s\n", convert_log_type_str(get_verbose(ptUserData))); + } + if (input2.cmdOptionExists("getVerbose")) + { + printf("Log level settings: %s\n", convert_log_type_str(get_verbose(ptUserData))); + } + + //////////////////////////////////////////////////////////////////////////////// + // Update ASIC setting + if (input2.cmdOptionExists("setParam")) + { + // Get parameter name + string pname = input2.getCmdOption("--param"); + if (pname.empty()) + pname = input2.getCmdOption("-p"); + + // Get value + option = input2.getCmdOption("--val"); + if (option.empty()) + option = input2.getCmdOption("-v"); + + if (pname.empty() || option.empty()) + { + printf("Usage: setParam --param Name --val 15 (or 0xf)\n"); + } + else + { + val = str2uint(option); + SetASICParameter(ptUserData, pname, val); + } + } + if (input2.cmdOptionExists("getParam")) + { + option = input2.getCmdOption("--param"); + if (option.empty()) + option = input2.getCmdOption("-p"); + // If we forgot the --param or -p tag, assume the next string is the param + if (option.empty()) + option = input2.getCmdOption("getParam"); + + if (!option.empty()) + { + if (GetASICParameter(ptUserData, option, &val) == true) + printf("%s = %i (0x%04x)\n", option.c_str(), val, val); + } + else + { + // In case we forget the --param argument + // (which happens regularly) + // option = input2.getCmdOption("getP"); // Is this a typo?? (JML 7/16/2019) + option = input2.getCmdOption("getParam"); + if ((option.empty() == true) || (option.compare("--param") == 0)) + { + printf("Usage: getParam --param Name\n"); + } + else + { + if (GetASICParameter(ptUserData, option, &val) == true) + printf("%s = %i (0x%04x)\n", option.c_str(), val, val); + } + } + } + + // readline malloc's a new buffer every time. + free(buf); + + } while ((line != "exit") && (line != "quit")); + + SetPowerASIC(ptUserData, false); + + // Call MACIE_Free + if (free_resources(ptUserData) == false) + return -1; + else + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// \brief InitCamera Initialize camera performing the following steps: +/// 1. Select appropriate MACIE and ASIC registry Files. +/// 2. Setup ASIC registry address map for local storage in ptUserData. +/// 3. Check connection interfaces +/// 4. Get handle for (currently USB connection only) +/// 5. Get available MACIEs associated with handle +/// 6. Initialize MACIE and ASIC +/// for the hardware. +bool InitCamera(string configFile, MACIE_Connection connection, MACIE_Settings *ptUserData) +{ + // Store info in user settings + ptUserData->connection = connection; + + //////////////////////////////////////////////////////////////////////////////// + // 1. Save directory setup + // Set load files and detector info from config files + if (ParseConfig(configFile, ptUserData, false) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ParseConfig failed at %s()\n", __func__); + return false; + } + printf("detType = %s\n", convert_camera_type_str(ptUserData->DetectorType)); + printf("detMode = %s\n", convert_camera_mode_str(ptUserData->DetectorMode)); + + //////////////////////////////////////////////////////////////////////////////// + // 1. Save directory setup + + // Time/date info + time_t t1 = time(0); // get time now + struct tm *now = gmtime(&t1); // in GMT + + // Save directory + // If save directory is not set (equals "") then set to default ~/data/$DATE/ + char buffer[80]; + std::stringstream ss; + string homedir = getenv("HOME"); + if (ptUserData->saveDir.compare("") == 0) + { + strftime(buffer, 80, "/data/%Y%m%d/", now); + ss << buffer; + ptUserData->saveDir = homedir + ss.str(); + } + else + { + strftime(buffer, 80, "%Y%m%d/", now); + ss << buffer; + ptUserData->saveDir = ptUserData->saveDir + ss.str(); + } + + // Add date to filename prefix + char buffer2[80]; + std::stringstream ss2; + strftime(buffer2, 80, "%Y%m%d_", now); + ss2 << buffer2; + ptUserData->filePrefix = ptUserData->filePrefix + ss2.str(); + + printf("saveDir: %s\n", ptUserData->saveDir.c_str()); + printf("prefix: %s\n", ptUserData->filePrefix.c_str()); + + // Create save directory + struct stat st = {0}; + if (stat(ptUserData->saveDir.c_str(), &st) == -1) + { + verbose_printf(LOG_INFO, ptUserData, "Creating directory: %s\n", ptUserData->saveDir.c_str()); + mkdir(ptUserData->saveDir.c_str(), 0700); + } + + //////////////////////////////////////////////////////////////////////////////// + // 2. Set up registry address map + // Only defines addresses. No values yet. + if (initRegMap(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "initRegMap failed at %s()\n", __func__); + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // 3. Check interfaces + verbose_printf(LOG_NONE, ptUserData, "\n"); // Print blank line + if (CheckInterfaces(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "CheckInterfaces failed at %s()\n", __func__); + return false; + } + verbose_printf(LOG_NONE, ptUserData, "\n"); // Print blank line + + //////////////////////////////////////////////////////////////////////////////// + // 4. Get Handle for (GigE only) + if (GetHandleGigE(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "GetHandleGigE failed at %s()\n", __func__); + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // 5. Get available MACIEs associated with handle + if (GetAvailableMACIEs(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "GetAvailableMACIEs failed at %s()\n", __func__); + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // 6. Initialize MACIE and ASIC + verbose_printf(LOG_NONE, ptUserData, "\n"); // Print blank line + if (InitializeASIC(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "InitializeASIC failed at %s()\n", __func__); + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // 7. Update ASIC register settings from config file + if (ParseConfig(configFile, ptUserData, true) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "ParseConfig failed at %s()\n", __func__); + return false; + } + + verbose_printf(LOG_DEBUG, ptUserData, " %s returns true\n", __func__); + return true; +} + +// Run this command before closing main program. +bool free_resources(MACIE_Settings *ptUserData) +{ + if (SettingsCheckNULL(ptUserData) == false) + return false; + + if (MACIE_Free() != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "MACIE_Free failed:\n %s\n", MACIE_Error()); + return false; + } + + delete ptUserData; + return true; +} + +// returns number of words in char string +unsigned int countWords(char *str) +{ + int state = 0; + unsigned wc = 0; // word count + + // Scan all characters one by one + while (*str) + { + // If next character is a separator, set the state as 0 + // otherwise if already 0, set to 1 and increment wc + if (*str == ' ' || *str == '\n' || *str == '\t') + state = 0; + else if (state == 0) + { + state = 1; + ++wc; + } + // Move to next character + ++str; + } + return wc; +} + +// Test if string is HEX or decimal by presence of "0x" +unsigned int str2uint(string option) +{ + unsigned int val; + if (option.find("0x") != string::npos) + val = strtoul(option.c_str(), NULL, 16); + else // Value is decimal + val = atoi(option.c_str()); + + return val; +} + +bool ParseConfig(string configFile, MACIE_Settings *ptUserData, bool update_regs) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + string linebuffer; + unsigned int linecount = 0; + const string ws(" \t\n\r"); + const string delimiters("#;"); + + string MACIEFile, ASICFile, ASICRegs; + string str1, str2; + + // Open file to ifstream + std::ifstream infile; + infile.open(configFile.c_str()); + + if (infile.is_open() == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Could not open file %s\n", configFile.c_str()); + return false; + } + else + { + while (std::getline(infile, linebuffer)) + { + size_t first_nonws = linebuffer.find_first_not_of(ws); + + // skip empty lines + if (first_nonws == string::npos) + { + continue; + } + // skip comment lines + if ((linebuffer.find("/") == first_nonws) || + (linebuffer.find("#") == first_nonws) || + (linebuffer.find(";") == first_nonws)) + { + continue; + } + + // Remove comments from end of line + linebuffer = strip_comments(linebuffer, delimiters); + + // Stream to str1 and str2 + std::istringstream iss(linebuffer); + iss >> str1 >> str2; + + // Parse out firmware files, detector type/mode, and clkphase/rate + if (update_regs == false) + { + // verbose_printf(LOG_INFO, ptUserData, " str1: %s, str2: %s\n", str1.c_str(), str2.c_str()); + + if (str1.compare("MACIEFile") == 0) + strncpy(ptUserData->MACIEFile, str2.c_str(), str2.size()); + if (str1.compare("MACIEslot") == 0) + ptUserData->bMACIEslot1 = (str2uint(str2) == 1) ? true : false; + else if (str1.compare("ASICFile") == 0) + strncpy(ptUserData->ASICFile, str2.c_str(), str2.size()); + else if (str1.compare("ASICRegs") == 0) + strncpy(ptUserData->ASICRegs, str2.c_str(), str2.size()); + + else if (str1.compare("saveDir") == 0) + { + // Expand home directory? + if (str2.compare(0, 1, "~") == 0) + ptUserData->saveDir = getenv("HOME") + str2.substr(1); + else + ptUserData->saveDir = str2; + + // Check that last element in string is a "/" + char LastChar = *(ptUserData->saveDir).rbegin(); + std::stringstream ss; + ss << LastChar; + string LastStr = ss.str(); + if (LastStr.compare("/") != 0) + ptUserData->saveDir = ptUserData->saveDir + string("/"); + + // Create save directory + struct stat st = {0}; + if (stat(ptUserData->saveDir.c_str(), &st) == -1) + { + verbose_printf(LOG_INFO, ptUserData, "Creating directory: %s\n", ptUserData->saveDir.c_str()); + mkdir(ptUserData->saveDir.c_str(), 0700); + } + } + else if (str1.compare("filePrefix") == 0) + { + // std::string::iterator it = str2.rbegin(); + char LastChar = *str2.rbegin(); + + std::stringstream ss; + ss << LastChar; + string LastStr = ss.str(); + if (LastStr.compare("_") == 0) + ptUserData->filePrefix = str2; + else + ptUserData->filePrefix = str2 + string("_"); + } + + else if (str1.compare("DetType") == 0) + { + ptUserData->DetectorType = convert_camera_type(str2.c_str()); + } + else if (str1.compare("DetMode") == 0) + { + ptUserData->DetectorMode = convert_camera_mode(str2.c_str()); + if (ptUserData->DetectorMode == CAMERA_MODE_FAST) + { + ptUserData->clkRateMDefault = 80; + ptUserData->clkPhaseDefault = 0x1e0; + } + else if (ptUserData->DetectorMode == CAMERA_MODE_SLOW) + { + ptUserData->clkRateMDefault = 10; + ptUserData->clkPhaseDefault = 0; + } + } + } + else + { + // verbose_printf(LOG_INFO, ptUserData, " str1: %s, str2: %s\n", str1.c_str(), str2.c_str()); + + // Check for reg_ prefix + if (str1.compare(0, 4, "reg_") == 0) + { + string reg_name = str1.substr(4); + unsigned int reg_val = str2uint(str2); + SetASICParameter(ptUserData, reg_name, reg_val); + } + // Check for 0x addresses + else if (str1.compare(0, 2, "0x") == 0) + { + unsigned int reg_addr = strtoul(str1.c_str(), 0, 16); + unsigned int reg_val = str2uint(str2); // Can be HEX (0x) or DEC + WriteASICReg(ptUserData, reg_addr, reg_val); + } + else if (str1.compare("NumOutputs") == 0) + ASIC_NumOutputs(ptUserData, true, str2uint(str2)); + else if (str1.compare("Inputs") == 0) + ASIC_Inputs(ptUserData, true, str2uint(str2)); + else if (str1.compare("Gain") == 0) + ASIC_Gain(ptUserData, true, str2uint(str2)); + else if (str1.compare("CapComp") == 0) + ASIC_CapComp(ptUserData, true, str2uint(str2)); + else if (str1.compare("FiltPole") == 0) + ASIC_FiltPole(ptUserData, true, str2uint(str2)); + else if (str1.compare("clkPhase") == 0) + SetMACIEPhaseShift(ptUserData, str2uint(str2)); + else if (str1.compare("clkRateM") == 0) + SetMACIEClockRate(ptUserData, str2uint(str2)); + } + + ++linecount; + } + infile.close(); + } + + if (update_regs == true) + { + if (ReconfigureASIC(ptUserData) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Reconfigure failed at %s()\n", __func__); + return false; + } + } + + return true; +} + +bool test_buff_config(MACIE_Settings *ptUserData, int buffsize, short nbuf) +{ + + unsigned int handle = ptUserData->handle; + unsigned char slctMACIEs = ptUserData->slctMACIEs; + unsigned short data_mode = (ptUserData->DetectorMode == CAMERA_MODE_SLOW) ? 0 : 3; + + verbose_printf(LOG_INFO, ptUserData, "test_buff_config(): Configuring science interface...\n"); + verbose_printf(LOG_INFO, ptUserData, " nbuf = %i\n", nbuf); + verbose_printf(LOG_INFO, ptUserData, " buffsize = %i pixels\n", buffsize); + + unsigned long pixBuffer = (unsigned long)nbuf * (unsigned long)buffsize; + unsigned long memAvail1 = GetMemAvailable(ptUserData); + verbose_printf(LOG_INFO, ptUserData, " MemAvail Start = %li MBytes\n", memAvail1 / 1024); + + if (ptUserData->offline_develop == false) + { + try + { + if (MACIE_ConfigureUSBScienceInterface(handle, slctMACIEs, data_mode, buffsize, nbuf) != MACIE_OK) + { + verbose_printf(LOG_ERROR, ptUserData, "Science interface configuration failed.\n"); + return false; + } + } + catch (const std::exception &e) + { + verbose_printf(LOG_ERROR, ptUserData, "Caught exception at %s.\n", __func__); + std::cerr << e.what() << '\n'; + CloseUSBScienceInterface(ptUserData); + + return false; + } + delay(500); + } + + unsigned long memAvail2 = GetMemAvailable(ptUserData); + verbose_printf(LOG_INFO, ptUserData, " MemAvail Diff = %li MBytes; Expected Buff = %li MBytes\n", + (memAvail1 - memAvail2) / 1024, 2 * pixBuffer / (1024 * 1024)); + + // Testing frame download with no data + /////////////////// + // const int framesize = 1024*1024; + // unsigned short *pData; + // pData = new unsigned short [framesize](); + + // // DownloadRampUSB_Data(ptUserData, pData, framesize, 1, triggerTimeout, wait_delta) + // if (DownloadDataUSB(ptUserData, &pData[0], (long)framesize, 1500)==false) + // { + // verbose_printf(LOG_ERROR, ptUserData, "DownloadDataUSB failed at %s\n", __func__); + // } + // string filename = "/home/observer/test_data/blank.fits"; + // vector naxis; naxis.push_back(1024); naxis.push_back(1024); + // verbose_printf(LOG_INFO, ptUserData, "Writing: %s\n", filename.c_str()); + // if (WriteFITSRamp(pData, naxis, USHORT_IMG, filename) == false) + // { + // verbose_printf(LOG_ERROR, ptUserData, "Failed to write FITS (16-bit) at %s\n", __func__); + // } + + // delete[] pData; + // End Testing + /////////////////////// + + if (ptUserData->offline_develop == false) + { + CloseUSBScienceInterface(ptUserData); + delay(500); + } + memAvail1 = GetMemAvailable(ptUserData); + verbose_printf(LOG_INFO, ptUserData, " MemAvail End = %li MBytes\n", memAvail1 / 1024); + + // verbose_printf(LOG_INFO, ptUserData, "No Seg Fault!\n"); + return true; +} + +bool run_asic_tune_file(string tuneFile, MACIE_Settings *ptUserData) +{ + + if (SettingsCheckNULL(ptUserData) == false) + return false; + + string linebuffer; + unsigned int linecount = 0; + const string ws(" \t\n\r"); + const string delimiters("#;"); + + string str1, str2; + + // Open file to ifstream + std::ifstream infile; + infile.open(tuneFile.c_str()); + + if (infile.is_open() == false) + { + verbose_printf(LOG_ERROR, ptUserData, "Could not open file: %s\n", tuneFile.c_str()); + return false; + } + else + { + + while (std::getline(infile, linebuffer)) + { + size_t first_nonws = linebuffer.find_first_not_of(ws); + + // skip empty lines + if (first_nonws == string::npos) + { + continue; + } + // skip comment lines + if ((linebuffer.find("/") == first_nonws) || + (linebuffer.find("#") == first_nonws) || + (linebuffer.find(";") == first_nonws)) + { + continue; + } + + // Remove comments from end of line + linebuffer = strip_comments(linebuffer, delimiters); + + // Stream to str1 and str2 + std::istringstream iss(linebuffer); + iss >> str1 >> str2; + + // Check for reg_ prefix + if (str1.compare(0, 4, "reg_") == 0) + { + string reg_name = str1.substr(4); + unsigned int reg_val = str2uint(str2); // Can be HEX (0x) or DEC + SetASICParameter(ptUserData, reg_name, reg_val); + } + // Check for 0x addresses + else if (str1.compare(0, 2, "0x") == 0) + { + unsigned int reg_addr = strtoul(str1.c_str(), 0, 16); + unsigned int reg_val = str2uint(str2); // Can be HEX (0x) or DEC + WriteASICReg(ptUserData, reg_addr, reg_val); + printf(" h%04x = 0x%04x\n", reg_addr, reg_val); + } + + // Wait 1 sec for settling then take data + delay(1000); + + // Acquire data + if (AcquireDataUSB(ptUserData, false) == false) + { + verbose_printf(LOG_ERROR, ptUserData, "AcquireDataUSB failed at %s()\n", __func__); + } + else + { + DownloadAndSaveAllUSB(ptUserData); + } + + // Check for errors + GetErrorCounters(ptUserData, false); + uint errCnts = 0; + for (int j = 0; j < MACIE_ERROR_COUNTERS; j++) + errCnts += (uint)ptUserData->errArr[j]; + if (errCnts > 0) + { + // verbose_printf(LOG_WARNING, ptUserData, "MACIE Errors encountered!\n"); + if (get_verbose(ptUserData) <= LOG_WARNING) + GetErrorCounters(ptUserData, false); + + // If just science errors, then reset error counters + errCnts = 0; + for (int j = 0; j < 25; j++) + errCnts += (uint)ptUserData->errArr[j]; + if (errCnts == 0) + { + // verbose_printf(LOG_INFO, ptUserData, "Resetting error counters...\n"); + ResetErrorCounters(ptUserData); + } + } + + ++linecount; + } + infile.close(); + } + + return true; +} diff --git a/nottcontrol/camera/macie/macie_exe/MacieMain.h b/nottcontrol/camera/macie/macie_exe/MacieMain.h new file mode 100644 index 00000000..21691970 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/MacieMain.h @@ -0,0 +1,10 @@ +#include +#include "macie.h" +#include "macie_lib.h" + +int initialize(string configFile, MACIE_Settings *ptUserData); +void acquire(bool no_recon, MACIE_Settings *ptUserData); +void halt_acquisition(MACIE_Settings *ptUserData); +bool InitCamera(string configFile, MACIE_Connection connection, MACIE_Settings *ptUserData); +bool free_resources(MACIE_Settings *ptUserData); +void toggle_offline_testing(bool offline_testing, MACIE_Settings *ptUserData); \ No newline at end of file diff --git a/nottcontrol/camera/macie/macie_exe/Makefile b/nottcontrol/camera/macie/macie_exe/Makefile new file mode 100644 index 00000000..ac424434 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/Makefile @@ -0,0 +1,38 @@ +CC = g++ + +SHELL = /bin/bash + +CFLAGS = -O2 -Wall -g -I../libmacie -fPIC +LDFLAGS = -L../libmacie -L/usr/local/lib/macie_lib +LIBS = -lmacie -lMACIE -lcfitsio -lreadline +SRCS = macie_interface.c MacieMain.c +OBJS = macie_interface.o MacieMain.o + +DEST = bin +EXE = macie_acq + +LINK.c := $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -static-libstdc++ + +all: libmacie_interface.so +libmacie_interface.so: macie_interface.o MacieMain.o + $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -static-libstdc++ -shared -o $@ + +# Rule showing which targets to build when you simply do "make". +pass5: $(EXE) + +install: $(DEST) $(EXE) + @ if [ -n "$(EXE)" ]; then cp -f $(EXE) $(DEST); fi + +$(EXE): MacieMain.o + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) MacieMain.o $(LIBS) + +$(DEST): + mkdir -p $(DEST) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +clean: clobber + +clobber: + rm -rf $(EXE) $(OBJS) libmacie_interface.so diff --git a/nottcontrol/camera/macie/macie_exe/README.md b/nottcontrol/camera/macie/macie_exe/README.md new file mode 100644 index 00000000..46f73d65 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/README.md @@ -0,0 +1,129 @@ +MACIE Acquisition Software +========================== + +*Authors:* Jarron Leisenring (University of Arizona) + +*Description:* Acquisition software for MACIE controller + +Software Operations +------------------- + +Run command line executable: + + ./macieacq config_files/basic_slow_HxRG_warm.cfg + +Commands: +1. testing true/false + - Enables offline software tests +0. powerOff + - Shut down ASIC power +0. powerOn + - Turn on ASIC power and reload firmware and default settings + - Mainly for use after power off +0. initCamera + - Select appropriate MACIE and ASIC registry Files. + - Setup ASIC registry address map for local storage in ptUserData. + - Check connection interfaces + - Get handle for (currently USB connection only) + - Get available MACIEs associated with handle + - Initialize MACIE and ASIC +0. expSettings + - Usage: expSettings --save bool -c ncoadds -i nseq -g ngroups -r nreads -s ndrops -k nresets + - A reconfiguration sequence is included +0. frameSettings + - Usage: frameSettings --xWin bool --yWin bool -x1 uint -x2 uint -y1 uint -y2 uint +0. set/getInputs + - The four reference inputs, each spanning 4 bits. + - Usage: setInputs 0xaaaa (for instance, aaaa = shorted inputs) +0. set/getGain + - Preamp gain settings (16 possible settings). + - Usage: setGain [0-15] +0. set/getCapComp + - Preamp capacitive compensation settings (64 possible settings). + - Recommended values in Table 3-10 of SIDECAR Manual. + - Usage: setCapComp [0-63] +0. set/getFiltPole + - Preamp low-pass filter settings (16 possible settings). + - Set filter pole to 5-10 times the pixel clock rate. + - Usage: setFiltPole [0-15] +0. set/getNOut + - Number of outputs; only applicable to Slow Mode. + - Usage: setNOut [1,2,4,16,32] +0. reconfigASIC + - Necessary to reconfigure ASIC after updating values for registers h4??? +0. acquire + - Acquire frames from detector and download to PC. +0. haltAcq + - Halt a failed acquisition + - Runs CloseUSBScienceInterface() and HaltCameraAcq() +0. readASIC/writeASIC + - Read/Write specific ASIC register + - Address assumed to be in HEX, but val can be INT or HEX + - Usage: writeASIC --addr 0x4000 --val 0x1 + - Usage: readASIC --addr 0x4000 +0. readASIC_block + - Read a number of contiguous registers + - Usage: readASIC_block --addr 0x6000 --nreg 16 +0. readASICconfig + - Parses detector and ASIC bias voltage and current settings + - Usage: readASICconfig --addr 0x6000 --nreg 16 +0. runTuneAcq + - Run a tuning acquisition file + - Files should be a sequence list of registers and values + - Of form `reg_VBiasGate1 0x8550` or `0x6004 0x8550` + - Data will be acquired and saved in current exposure and frame config + - Usage: runTuneAcq filename.txt +0. readMACIE/writeMACIE + - Read/Write specific MACIE register + - Usage: readMACIE --addr 0x0010 + - Usage: writeMACIE --addr 0x0010 --val 0x27 +0. printRegs + - Print all stored ASIC registry information in RegMap +0. updateRegMap + - Send registry update request to ASIC and store all values in ptUserData->RegMap +0. setParam/getParam + - Update (or read) any ASIC setting defined in .cfg file + - Usage: setParam --param (-p) Name --val (-v) 15 (or 0xf) + - Usage: getParam --param (-p) Name +0. setClock/getClock + - Set/print MACIE master clock rate. + - Input value is in MHz (80 for Fast, 10 for Slow) + - Usage: setClock [5-80] +0. setPhase/getPhase + - Set/print MACIE clock phase shift setting. + - Value always assumed to be in HEX. + - Bit 8 is on/off. Bits 7-0 are phase value. + - Usage: setPhase 0x01e0 +0. findPhase + - Cycle through a range of Phase Shift settings + - Prints out number of error counts for each setting + - Usage: findPhase --val1 0x01a0 --val2 0x01e0 +0. setNBuffer/getNBuffer + - Manually set/print the number of frame buffers in ptUserData->nBuffer. + - In normal operations, this will be set optimally, depending on exposure settings. + - sage: setNBuffer [1-100] +0. configBuffers + - Configure nbuf, npixels, and Sci or Frame function + - sciFunc should not be used along with buffsize and nbuf (??) + - Usage: configBuffers --sciFunc bool --buffsize int --nbuf int +0. getErrors + - Grab error counters from MACIE +0. resetErrors + - Clear MACIE error counters +0. getPower + - Print MACIE power structure on/off values +0. getVoltages + - Print MACIE voltage settings +0. setLED + - Set LED brightness (values 0-4) + - Usage: setLED [0-4] +0. setVerbose/getVerbose + - Set/print log levels to debug, info, warn, error + +* TODO + - Telemetry readback + - readASICBits 0x0000<0:1> + - ASIC Temperature sensors + - Reset ASIC (run powerOff then powerOn?) + - get/setOffset + - Normal/enhanced mode in Slow Mode (?) diff --git a/nottcontrol/camera/macie/macie_exe/config_files/basic_fast_H2RG_cold.cfg b/nottcontrol/camera/macie/macie_exe/config_files/basic_fast_H2RG_cold.cfg new file mode 100644 index 00000000..c5565726 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/config_files/basic_fast_H2RG_cold.cfg @@ -0,0 +1,18 @@ +# Configuration file for H2RG Fast Mode with Vertical Window + +MACIEFile load_files/MACIE_Registers_Fast_Cryo.mrf +MACIEslot 2 +ASICFile load_files/mcd/H2RG_5MHz_Ramp_VertWindow_coldASIC.mcd +ASICRegs load_files/cfg/H2RG_5MHz_Ramp_VertWindow_coldASIC.cfg + +# Clock Rate and phase info for Fast Mode +clkRateM 80 # Master Clock (MHz) +clkPhase 0x01ea # 0x01ea - Cold; 0x01ca - Warm + +saveDir ~/test_data/ +filePrefix H2RG_Fast_VertWin + +DetType H2RG # H1RG, H2RG, H4RG +DetMode FAST # SLOW or FAST + +Inputs 0xaaaa # 0x5a0a - Single-ended; 0xaaaa - Inputs Shorted/Grounded diff --git a/nottcontrol/camera/macie/macie_exe/config_files/basic_fast_H2RG_warm.cfg b/nottcontrol/camera/macie/macie_exe/config_files/basic_fast_H2RG_warm.cfg new file mode 100755 index 00000000..abb4942d --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/config_files/basic_fast_H2RG_warm.cfg @@ -0,0 +1,18 @@ +# Configuration file for H2RG Fast Mode with Vertical Window + +MACIEFile load_files/MACIE_Registers_Fast.mrf +MACIEslot 2 +ASICFile load_files/mcd/HxRG_Main.mcd +ASICRegs load_files/cfg/HxRG_Main.cfg + +saveDir ~/test_data/ +filePrefix H2RG_Fast_VertWin + +# Clock Rate and phase info for Fast Mode +clkRateM 80 # Master Clock (MHz) +clkPhase 0x01b7 # 0x01ea - Cold; 0x01ca - Warm + +DetType H2RG # H1RG, H2RG, H4RG +DetMode SLOW # SLOW or FAST + +Inputs 0xaaaa # 0x5a0a - Single-ended; 0xaaaa - Inputs Shorted/Grounded \ No newline at end of file diff --git a/nottcontrol/camera/macie/macie_exe/config_files/basic_slow_HxRG_cold.cfg b/nottcontrol/camera/macie/macie_exe/config_files/basic_slow_HxRG_cold.cfg new file mode 100644 index 00000000..f499e54a --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/config_files/basic_slow_HxRG_cold.cfg @@ -0,0 +1,30 @@ +# Configuration file for vanilla HxRG Slow Mdoe + +MACIEFile load_files/MACIE_Registers_Slow.mrf +MACIEslot 2 +ASICFile load_files/mcd/HxRG_Main.mcd +ASICRegs load_files/cfg/HxRG_Main.cfg + +saveDir ~/test_data/ +filePrefix HxRG_Main + +DetType H2RG # H1RG, H2RG, H4RG +DetMode SLOW # SLOW or FAST + +clkPhase 0x0 +clkRateM 10 + +# Register Values to set upon load +reg_NumOutputs 32 +reg_RefInput 1 # 0 - 0x4a0a (single) 1 - 0x4502 (V4,3,2,1) (differential) +reg_RefOverride 1 # Use Inputs stored in OverrideVals? +reg_OverrideVals 0xaaaa # 0xaaa = Shorted ground inputs + +reg_Buff 0x0 # Unbuffered 0x0, buffered 0x3 +reg_Gain 12 # PreAmp Gain (0-15) +reg_CapComp 19 # 19 => 19*53 = 1007fF +reg_FiltPole 5 # 5 => 1263 KHz (4.2 x 300 KHz) + +reg_WarmOrCold 0 +reg_PreampRstScheme 0 # 0 - per frame (cold) 1 - per row (warm) + diff --git a/nottcontrol/camera/macie/macie_exe/config_files/basic_warm_slow.cfg b/nottcontrol/camera/macie/macie_exe/config_files/basic_warm_slow.cfg new file mode 100755 index 00000000..b0162c68 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/config_files/basic_warm_slow.cfg @@ -0,0 +1,18 @@ +# Configuration file for H2RG Fast Mode with Vertical Window + +MACIEFile load_files/MACIE_Registers_Slow.mrf +MACIEslot 2 +ASICFile load_files/mcd/HxRG_Main.mcd +ASICRegs load_files/cfg/HxRG_Main.cfg + +saveDir ~/test_data/slow_mode/ramp_test +filePrefix H2RG_Slow_FullWin + +# Clock Rate and phase info for Fast Mode +clkRateM 10 # Master Clock (MHz) +clkPhase 0x01ca # 0x01ea - Cold; 0x01ca - Warm + +DetType H2RG # H1RG, H2RG, H4RG +DetMode SLOW # SLOW or FAST + +Inputs 0x5a0a # 0x5a0a - Single-ended; 0xaaaa - Inputs Shorted/Grounded \ No newline at end of file diff --git a/nottcontrol/camera/macie/macie_exe/macie_interface.c b/nottcontrol/camera/macie/macie_exe/macie_interface.c new file mode 100644 index 00000000..07683171 --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/macie_interface.c @@ -0,0 +1,74 @@ +#include "macie_interface.h" +#include +#include +#include "macie_lib.h" +#include "MacieMain.h" +#include +#include "macie.h" + + +string _configFile = ""; +MACIE_Settings *_ptUserData; + +extern "C" int M_initialize(const char* configFile, bool offline_mode) +{ + string cfgFile = string(configFile); + printf("Calling initialize, configfile %s, offline_mode %d \n", configFile, offline_mode); + _configFile = cfgFile; + _ptUserData = new MACIE_Settings; + int ret = initialize(cfgFile, _ptUserData); + if(offline_mode) + { + toggle_offline_testing(true, _ptUserData); + } + return ret; +} +extern "C" void M_acquire(const bool no_recon) +{ + std::cout << "Calling acquire" << std::endl;; + std::cout << no_recon; + acquire(no_recon, _ptUserData); + return; +} + +extern "C" void M_halt_acquisition() +{ + std::cout << "Calling halt" << std::endl;; + halt_acquisition(_ptUserData); + return; +} + +extern "C" bool M_initCamera() +{ + std::cout << "Calling initCamera" << std::endl;; + if(_configFile.empty()){ + std::cout << "Init failed, config file not set" << std::endl;; + return false; + } + return InitCamera(_configFile, MACIE_GigE, _ptUserData); +} + +extern "C" void M_powerOff() +{ + std::cout << "Calling powerOff" << std::endl;; + SetPowerASIC(_ptUserData, false); +} +extern "C" void M_powerOn() +{ + std::cout << "Calling powerOn" << std::endl;; + SetPowerASIC(_ptUserData, true); +} + +extern "C" void M_getPower() +{ + std::cout << "Calling getPower" << std::endl; + bool pArr[MACIE_PWR_CTRL_SIZE]; + GetPower(_ptUserData, pArr); +} + +extern "C" void M_close() +{ + std::cout << "Calling close" << std::endl; + SetPowerASIC(_ptUserData, false); + free_resources(_ptUserData); +} \ No newline at end of file diff --git a/nottcontrol/camera/macie/macie_exe/macie_interface.h b/nottcontrol/camera/macie/macie_exe/macie_interface.h new file mode 100644 index 00000000..8131d8fa --- /dev/null +++ b/nottcontrol/camera/macie/macie_exe/macie_interface.h @@ -0,0 +1,11 @@ +#include +using std::string; + +extern "C" int M_initialize(const char* configFile, bool offline_mode); +extern "C" void M_acquire(const bool no_recon); +extern "C" void M_halt_acquisition(); +extern "C" bool M_initCamera(); +extern "C" void M_powerOff(); +extern "C" void M_powerOn(); +extern "C" void M_getPower(); +extern "C" void M_close(); \ No newline at end of file diff --git a/nottcontrol/camera/macie/macie_interface.py b/nottcontrol/camera/macie/macie_interface.py new file mode 100644 index 00000000..d8a043bb --- /dev/null +++ b/nottcontrol/camera/macie/macie_interface.py @@ -0,0 +1,75 @@ +import os +import ctypes +from threading import Thread, Event + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + +#Usage: calling init_camera puts the camera in a state where it is ready to acquire images. +#By using the python 'with' statement, you can ensure that both the initialization and the de-initialization are done +class MacieInterface(): + + def __init__(self, offline_mode = False, config_file="basic_warm_slow.cfg"): + self._macielib = ctypes.CDLL(BASE_DIR + "/macie_exe/libmacie_interface.so", mode = os.RTLD_LAZY) + + self._macielib.M_initialize.argtypes = [ctypes.c_char_p, ctypes.c_bool] + self._macielib.M_powerOn.argtypes = [] + self._macielib.M_powerOff.argtypes = [] + self._macielib.M_getPower.argtypes = [] + self._macielib.M_initCamera.argtypes = [] + self._macielib.M_acquire.argtypes = [ctypes.c_bool] + self._macielib.M_halt_acquisition.argtypes = [] + self._macielib.M_close.argtypes = [] + + #Load ctypes dll, and call initialize + file = os.path.join(BASE_DIR + "/macie_exe/config_files", config_file) + self._macielib.M_initialize(bytes(file, "utf-8"), offline_mode) + + self.continuous_acquisition_running = False + self._acquiring = Event() + self._acquiring.clear() + self._closing = Event() + + def __enter__(self): + self.init_camera() + return self + + def __exit__(self): + self.close() + + def power_off(self): + self._macielib.M_powerOff() + + def power_on(self): + self._macielib.M_powerOn() + + def init_camera(self): + self._macielib.M_initCamera() + + #Start the thread for continuous acquisition - it won't execute anything until start_continuous_acquisition is called + thread = Thread(target = self.continuous_acquisition) + thread.start() + + def acquire(self, no_recon = False): + self._macielib.M_acquire(no_recon) + + def get_power(self): + self._macielib.M_getPower() + + def close(self): + self._closing.set() + self._macielib.M_close() + + def halt_acquisition(self): + self._macielib.M_halt_acquisition() + + def start_continuous_acquisition(self): + self._acquiring.set() + + def stop_continuous_acquisition(self): + self._acquiring.clear() + + def continuous_acquisition(self): + #Run for as long as the interface is not closed + while not self._closing.is_set(): + self._acquiring.wait() + self.acquire() \ No newline at end of file diff --git a/nottcontrol/camera/macie/python_test.py b/nottcontrol/camera/macie/python_test.py new file mode 100644 index 00000000..765abb1f --- /dev/null +++ b/nottcontrol/camera/macie/python_test.py @@ -0,0 +1,6 @@ +from macie_interface import MacieInterface + +interface = MacieInterface(offline_mode = True) +interface.init_camera() +interface.acquire() +interface.close() \ No newline at end of file diff --git a/nottcontrol/camera/macie/ui/MacieControl.py b/nottcontrol/camera/macie/ui/MacieControl.py new file mode 100644 index 00000000..c7881632 --- /dev/null +++ b/nottcontrol/camera/macie/ui/MacieControl.py @@ -0,0 +1,54 @@ +from PyQt5.QtWidgets import QMainWindow +from PyQt5.uic import loadUi +from PyQt5.QtWidgets import QApplication +import sys +from nottcontrol.camera.macie import macie_interface + +class MacieControl(QMainWindow): + def __init__(self): + super(MacieControl, self).__init__() + self.ui = loadUi('MacieControl.ui', self) + self.connectSignalSlots() + self._macie_interface = macie_interface.MacieInterface() + + def connectSignalSlots(self): + self.ui.button_init.clicked.connect(self.init_camera) + self.ui.button_powerOn.clicked.connect(self.power_on) + self.ui.button_powerOff.clicked.connect(self.power_off) + self.ui.button_take_background.clicked.connect(self.take_background) + self.ui.button_live.clicked.connect(self.live_clicked) + self.ui.button_acquire.clicked.connect(self.acquire) + self.ui.button_halt.clicked.connect(self.halt) + + def init_camera(self): + print("executing init camera") + self._macie_interface.init_camera() + + def power_on(self): + print("executing power on") + self._macie_interface.power_on() + + def power_off(self): + print("executing power off") + self._macie_interface.power_off() + + def take_background(self): + print("executing take background") + + def live_clicked(self): + print("executing live_clicked") + + def acquire(self): + print("executing acquire") + self._macie_interface.acquire() + + def halt(self): + print("executing halt") + + + +if __name__ == "__main__": + app = QApplication(sys.argv) + window = MacieControl() + window.show() + sys.exit(app.exec()) \ No newline at end of file diff --git a/nottcontrol/camera/macie/ui/MacieControl.ui b/nottcontrol/camera/macie/ui/MacieControl.ui new file mode 100644 index 00000000..f8ce406e --- /dev/null +++ b/nottcontrol/camera/macie/ui/MacieControl.ui @@ -0,0 +1,540 @@ + + + Form + + + + 0 + 0 + 1053 + 633 + + + + Form + + + + + 700 + 20 + 331 + 131 + + + + Detector Configuration + + + + + 10 + 30 + 113 + 32 + + + + Init + + + + + + 10 + 60 + 113 + 32 + + + + Power On + + + + + + 10 + 90 + 113 + 32 + + + + Power Off + + + + + + 130 + 30 + 101 + 16 + + + + Detector mode: + + + + + + 230 + 30 + 91 + 32 + + + + + + + 130 + 60 + 101 + 16 + + + + Window mode: + + + + + + 230 + 60 + 91 + 32 + + + + + + + 130 + 100 + 60 + 16 + + + + Status: + + + + + + 200 + 100 + 113 + 21 + + + + true + + + + + + + 700 + 160 + 341 + 241 + + + + Data Acquisition + + + + + 10 + 30 + 111 + 16 + + + + Integration time (s): + + + + + + 190 + 30 + 113 + 21 + + + + + + + 10 + 60 + 131 + 16 + + + + Number of co-adds: + + + + + + 190 + 60 + 113 + 21 + + + + + + + 10 + 90 + 121 + 16 + + + + Number of frames: + + + + + + 190 + 90 + 113 + 21 + + + + + + + 10 + 120 + 161 + 16 + + + + Total integration time (s): + + + + + + 190 + 120 + 113 + 21 + + + + true + + + + + + 10 + 150 + 101 + 16 + + + + Frame number: + + + + + + 190 + 150 + 113 + 21 + + + + true + + + + + + 10 + 180 + 131 + 31 + + + + Take Background + + + + + + 10 + 210 + 113 + 32 + + + + Live + + + + + + 120 + 210 + 113 + 32 + + + + Acquire + + + + + + 230 + 210 + 113 + 32 + + + + Halt + + + + + + + 700 + 410 + 341 + 211 + + + + Data Visualisation + + + + + 10 + 30 + 161 + 21 + + + + Substract Background + + + + + + 10 + 60 + 86 + 20 + + + + Average + + + + + + 10 + 90 + 86 + 20 + + + + Max + + + + + + 10 + 120 + 86 + 20 + + + + Min + + + + + + 190 + 30 + 71 + 20 + + + + ROI1 + + + + + + 190 + 90 + 61 + 20 + + + + ROI3 + + + + + + 190 + 120 + 61 + 20 + + + + ROI4 + + + + + + 190 + 150 + 61 + 20 + + + + ROI5 + + + + + + 190 + 60 + 71 + 20 + + + + ROI2 + + + + + + 250 + 120 + 61 + 20 + + + + ROI9 + + + + + + 250 + 150 + 61 + 20 + + + + ROI10 + + + + + + 250 + 60 + 71 + 20 + + + + ROI7 + + + + + + 250 + 30 + 71 + 20 + + + + ROI6 + + + + + + 250 + 90 + 61 + 20 + + + + ROI8 + + + + + + + 0 + 0 + 691 + 621 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + diff --git a/nottcontrol/camera/parametersdialog_ui.py b/nottcontrol/camera/parametersdialog_ui.py deleted file mode 100644 index 0cda373a..00000000 --- a/nottcontrol/camera/parametersdialog_ui.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'c:\Users\fys-lab-ivs\Documents\Git\NottControl\NOTTControl\camera\parametersdialog.ui' -# -# Created by: PyQt5 UI code generator 5.15.9 -# -# WARNING: Any manual changes made to this file will be lost when pyuic5 is -# run again. Do not edit this file unless you know what you are doing. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(253, 212) - self.widget = QtWidgets.QWidget(Dialog) - self.widget.setGeometry(QtCore.QRect(10, 10, 233, 201)) - self.widget.setObjectName("widget") - self.formLayout = QtWidgets.QFormLayout(self.widget) - self.formLayout.setContentsMargins(0, 0, 0, 0) - self.formLayout.setObjectName("formLayout") - self.label_4 = QtWidgets.QLabel(self.widget) - self.label_4.setObjectName("label_4") - self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_4) - self.cb_presets = QtWidgets.QComboBox(self.widget) - self.cb_presets.setObjectName("cb_presets") - self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.cb_presets) - self.label = QtWidgets.QLabel(self.widget) - self.label.setObjectName("label") - self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label) - self.edit_param_nr = QtWidgets.QLineEdit(self.widget) - self.edit_param_nr.setObjectName("edit_param_nr") - self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.edit_param_nr) - self.label_2 = QtWidgets.QLabel(self.widget) - self.label_2.setObjectName("label_2") - self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2) - self.cb_parametertype = QtWidgets.QComboBox(self.widget) - self.cb_parametertype.setObjectName("cb_parametertype") - self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.cb_parametertype) - self.label_3 = QtWidgets.QLabel(self.widget) - self.label_3.setObjectName("label_3") - self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_3) - self.edit_param_value = QtWidgets.QLineEdit(self.widget) - self.edit_param_value.setObjectName("edit_param_value") - self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.edit_param_value) - self.button_get = QtWidgets.QPushButton(self.widget) - self.button_get.setObjectName("button_get") - self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.button_get) - self.button_set = QtWidgets.QPushButton(self.widget) - self.button_set.setObjectName("button_set") - self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.button_set) - self.label_feedback = QtWidgets.QLabel(self.widget) - self.label_feedback.setText("") - self.label_feedback.setObjectName("label_feedback") - self.formLayout.setWidget(5, QtWidgets.QFormLayout.SpanningRole, self.label_feedback) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Configure Parameters")) - self.label_4.setText(_translate("Dialog", "Presets:")) - self.label.setText(_translate("Dialog", "Parameter nr.")) - self.label_2.setText(_translate("Dialog", "Parameter type:")) - self.label_3.setText(_translate("Dialog", "Value:")) - self.button_get.setText(_translate("Dialog", "Get")) - self.button_set.setText(_translate("Dialog", "Set")) diff --git a/nottcontrol/redisclient.py b/nottcontrol/redisclient.py index 736f7508..1efae725 100644 --- a/nottcontrol/redisclient.py +++ b/nottcontrol/redisclient.py @@ -1,6 +1,6 @@ import redis from datetime import datetime -from nottcontrol.camera.utils.utils import BrightnessResults +from nottcontrol.camera.infratec.utils.utils import BrightnessResults import json class RedisClient: diff --git a/nottcontrol/scifygui.py b/nottcontrol/scifygui.py index 17d0da62..6a6034ff 100644 --- a/nottcontrol/scifygui.py +++ b/nottcontrol/scifygui.py @@ -5,7 +5,7 @@ from asyncua import ua from datetime import datetime from nottcontrol.redisclient import RedisClient -from nottcontrol.camera.scify import MainWindow as camera_ui +from nottcontrol.camera.infratec.scify import MainWindow as camera_ui from nottcontrol import config from nottcontrol.components.motor import Motor from nottcontrol.shutters_window import ShutterWindow diff --git a/nottcontrol/tiptilt_window.py b/nottcontrol/tiptilt_window.py index c1a845f8..424f598d 100644 --- a/nottcontrol/tiptilt_window.py +++ b/nottcontrol/tiptilt_window.py @@ -5,7 +5,7 @@ from asyncua import ua from datetime import datetime from nottcontrol.redisclient import RedisClient -from nottcontrol.camera.scify import MainWindow as camera_ui +from nottcontrol.camera.infratec.scify import MainWindow as camera_ui from nottcontrol import config from nottcontrol.components.motor import Motor from nottcontrol.shutters_window import ShutterWindow