diff --git a/FastComtecMCS8A/MCS8A_default_config.SET b/FastComtecMCS8A/MCS8A_default_config.SET
new file mode 100644
index 0000000000000000000000000000000000000000..2f611f43cd471e4d9f940bbc50c65e51fb3d7425
--- /dev/null
+++ b/FastComtecMCS8A/MCS8A_default_config.SET
@@ -0,0 +1,65 @@
+[MCS8A A] 208 FW 3.104 SV 1.243 
+range=89408
+periods=2
+sweepmode=22fc3088
+fstchan=0
+holdafter=0
+streamstatus=0
+calreg0=0
+calreg1=0
+calreg2=0
+calreg3=0
+swpreset=1           
+prena=6
+syncout=0
+cycles=2
+sequences=1
+tagbits=16
+vdac0=1079c
+vdac1=479c
+vdac2=43b4
+vdac3=3b4
+vdac4=3b4
+vdac5=3b4
+vdac6=3b4
+vdac7=3b4
+timepreset=0.000       
+digio=0
+digval=0
+autoinc=0 
+savedata=2 
+mpafmt=dat
+sephead=1 
+fmt=dat
+smoothpts=5 
+wndwidth=163
+wndheight=286
+sysdef=0
+[CHN1]
+range=89408
+active=1
+bitshift=18
+cftfak=2580100
+evpreset=10          
+roimin=0
+roimax=256
+caloff=0.000000
+calfact=6710886.400000
+calfact2=0
+calfact3=0
+calunit=nsec
+caluse=1 
+[CHN2]
+range=89408
+active=1
+bitshift=18
+cftfak=2580100
+evpreset=10          
+roimin=0
+roimax=200
+caloff=0.000000
+calfact=6710886.400000
+calfact2=0
+calfact3=0
+calunit=nsec
+caluse=1 
diff --git a/FastComtecMCS8A/__init__.py b/FastComtecMCS8A/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/FastComtecMCS8A/blacs_tabs.py b/FastComtecMCS8A/blacs_tabs.py
new file mode 100644
index 0000000000000000000000000000000000000000..dabedede841b5ffa4516458792506db36cc88a52
--- /dev/null
+++ b/FastComtecMCS8A/blacs_tabs.py
@@ -0,0 +1,23 @@
+from blacs.device_base_class import DeviceTab
+
+class MCS8ATab(DeviceTab):
+    
+    def initialise_workers(self):
+        self.event_queue.logging_enabled =True
+
+        connection_table = self.settings['connection_table']
+        props = connection_table.find_by_name(self.device_name).properties
+        
+        self.create_worker(
+            'main_worker',
+            'user_devices.FastComtecMCS8A.blacs_workers.MCS8AWorker',
+            {
+                "config_path": props["config_path"]
+            },
+        )
+        self.primary_worker = 'main_worker'
+
+    def initialise_GUI(self):
+        widgets,_,_ = self.auto_create_widgets()
+        self.supports_smart_programming(True)
+        
\ No newline at end of file
diff --git a/FastComtecMCS8A/blacs_workers.py b/FastComtecMCS8A/blacs_workers.py
new file mode 100644
index 0000000000000000000000000000000000000000..538e683c99d7c0ec6a2fd4f82e86687bea54afbd
--- /dev/null
+++ b/FastComtecMCS8A/blacs_workers.py
@@ -0,0 +1,108 @@
+#####################################################################
+#                                                                   #
+# /user_devices/FastComtecMCS8A/blacs_workers.py                    #
+#                                                                   #
+# Jan 2025, Leolab Cavity                                           #
+#                                                                   #
+#                                                                   #
+#####################################################################
+
+from . import fastcomtec_api
+from blacs.tab_base_classes import Worker
+from labscript_utils.labconfig import LabConfig
+import os
+import labscript_utils.h5_lock
+import h5py
+import numpy as np
+import time
+from datetime import datetime
+
+class MCS8AWorker(Worker):
+
+    def init(self):
+        self.base_dir = LabConfig().get("DEFAULT","experiment_shot_storage") + "\\MCS8A"
+        os.makedirs(self.base_dir, exist_ok=True) # create MCS8A folder if it doesn't exist yet
+
+        self.device = fastcomtec_api.FastComTec()
+        # print("Status: ", self.device.get_acq_status())
+        if getattr(self.device.get_acq_status(),"started") == 1:
+            time.sleep(1)
+        self.device.halt_measurement()
+        self.dataindex=0
+
+        # load (default) config
+        if not os.path.realpath(self.config_path) == self.config_path.replace("/","\\"):
+            self.config_path = os.path.dirname(os.path.realpath(__file__)) + "\\" + self.config_path
+            self.config_path = self.config_path.replace("\\", "/")
+        print("Load config...", self.config_path)
+        self.device.load_config(self.config_path)
+
+        
+        # Save data only in list file and in binary format
+        self.device._send_dll_command("mpafmt=dat")
+        self.device._send_dll_command("savedata=2")
+
+        # Set how long each measurement lasts, i.e. how ofen a new file is started.
+        # We don't want it too long, because then the single files get huge, but we also don't
+        # want it too often, because each stopping and starting takes some time.
+        self.maxduration = 600 # seconds
+        self.device._send_dll_command("bitshift=18") # 400ps * 2^0x18 = 0.0067 s
+        range_int = np.ceil(self.maxduration / (400e-12 * 2**0x18) / 64) * 64
+        self.device._send_dll_command(f"range={int(range_int)}")
+    
+    def get_new_mpapath(self):
+        mpaname = self.device_name + "_" + datetime.now().strftime("%Y-%d-%m_%H-%M-%S") + ".mpa"
+        return self.base_dir + "\\" + mpaname
+    
+    def transition_to_buffered(self, device_name, h5_file, initial_values, fresh):
+        # If device is already started, we leave it running and just save the datapath and index in the h5file.
+        # If the device is not running, or already longer than the defined duration, send the stop command, set new datafile and start new measurement.
+        # TODO: How to handle parameters (start new measurment when they changed, or treat parameters statically)
+        with h5py.File(h5_file,'r') as f: 
+            stop_time = f["devices/" + f["connection table"].attrs["master_pseudoclock"]].attrs["stop_time"]
+        if getattr(self.device.get_acq_status(),"started") != 1 or time.perf_counter()-getattr(self,"start_time",-self.maxduration)>self.maxduration-stop_time-3:
+            if self.dataindex==0:
+                self.device.halt_measurement()
+            while getattr(self.device.get_acq_status(),"started") == 1:
+                # If the current measurement doesn't have enought time left for this shot, wait until measurment ends. 
+                time.sleep(0.1)
+                print("Wait until last measurement stopped...", end="\r")
+            self.device.halt_measurement()
+            mpapath = self.get_new_mpapath()
+            self.device._send_dll_command(f"mpaname={mpapath}")
+            self.datapath = mpapath.replace(".mpa",".lst")
+            self.dataindex = 0
+            print("Set filename...", self.datapath.split("\\")[-1])
+
+            # self.device.erase_measruement() # Don't erase because this takes super long for some reason
+            self.device.start_measurement()
+            self.start_time = time.perf_counter()
+            time.sleep(2) # some buffer time to make sure the measurement already started for sure
+            # TODO: What's the minimum time to wait here?
+
+        # Save where to find the measurement data (which file and within file)
+        with h5py.File(h5_file,'r+') as f:
+            group = f[f"devices/{self.device_name}"]
+            group.attrs["datapath"] = self.datapath
+            group.attrs["dataindex"] = self.dataindex
+            self.dataindex += group.attrs["n_trigger"]
+
+        return {}
+
+    def transition_to_manual(self):
+        return True
+    
+    def program_manual(self, values):
+        return {}
+    
+    def check_remote_values(self):
+        return True
+
+    def abort_buffered(self):
+        return self.transition_to_manual()
+
+    def abort_transition_to_buffered(self):
+        return True
+    
+    def shutdown(self):
+        self.device._send_dll_command("exit")
\ No newline at end of file
diff --git a/FastComtecMCS8A/docs/FastComTec_Doc_From_Manual.txt b/FastComtecMCS8A/docs/FastComTec_Doc_From_Manual.txt
new file mode 100644
index 0000000000000000000000000000000000000000..afc8b50e8adea7d5c7d2b822cc4d9368d583457a
--- /dev/null
+++ b/FastComtecMCS8A/docs/FastComTec_Doc_From_Manual.txt
@@ -0,0 +1,204 @@
+[MCS8A] 1004            ; Device and serial number
+range=4096              ; Spectrum length
+periods=2               ; Number of periods for folding
+fstchan=0               ; acquisition delay = number of first bin / 64
+holdafter=0             ; hold after sweep in units of 64 basic dwelltimes
+sweepmode=227ea080      ; (hex) sweepmode & 0xF: 0 = normal,
+                        ; 1=differential (relative to first stop in sweep)
+                        ; 4=sequential
+                        ; 5=seq.+diff (Ch1), bit0 = differential mode
+                        ; 9=differential to stop in Ch2, bit3 = Ch2 ref (diff.mode)
+                        ; 0xF = Corr.+diff (Ch2)
+                        ; bit 4: Softw. Start
+                        ; bit 5: "Don't show" tagbits
+                        ; bit 6: Endless
+                        ; bit 7: Start event generation
+                        ; bit 8: Enable Tag bits
+                        ; bit 9: start with rising edge
+                        ; bit 10: time under threshold for pulse width
+                        ; bit 11: pulse width mode for any spectra with both edges enabled
+                        ; bit 12: abandon Sweepcounter in Data
+                        ; bit 13: "one-hot" mode with tagbits
+                        ; bit 14: start ref (diff.mode) (MCS8)
+                        ; bit 15: MCS8, MCS8A1: enable start input sampling
+                        ; bit 16..bit 22 ~(input channel enable)
+                        ; MCS8A: bit 16..bit 23 ~(input channel enable)
+                        ; bit 26: 100 ps time resolution instead of 80 ps
+                        ; bit 27: Folded
+                        ; bit 28: Interleaved
+                        ; bit 29: MCS8A: don't use trigger, use CH1 to start sweep
+                        ; bit 30: Use only 1 decoder
+calreg0=fe00            ; result of input delay calibration, l
+                        ; lower 8 bits: start channel (always 0),
+                        ; higher 8 bits, first channel after start
+calreg1=0               ; second, third channel
+calreg2=0               ; ..
+calreg3=0               ; ..
+swpreset=1000000        ; Sweep-Preset value
+prena=4                 ; bit 0: realtime preset enabled
+                        ; bit 1:
+                        ; bit 2: sweep preset enabled
+                        ; bit 3: ROI preset enabled
+                        ; bit 4: Starts preset enabled
+                        ; bit 5: ROI2 preset enabled
+                        ; bit 6: ROI3 preset enabled
+                        ; bit 7: ROI4 preset enabled
+                        ; bit 8: ROI5 preset enabled
+                        ; bit 9: ROI6 preset enabled
+                        ; bit 10: ROI7 preset enabled
+                        ; bit 11: ROI8 preset enabled
+syncout=0               ; LOWORD: sync out; bit 0..5 NIM syncout, bit 8..13 TTL syncout
+                        ; bit7: NIM syncout_invert, bit15: TTL syncout_invert
+                        ; 0="0", 1=5 MHz, 2=50 MHz, 3=100 MHz, 4=1/(80 ps or 100 ps * 64),
+                        ; 5=1/(80 ps or 100 ps * 32), 6=PLL ref clock, 7=Input 0(Start), 8=Input 1,
+                        ; 9=Input 2, 10..13=Input 3..7, 15=GO in, 16=Start_of_sweep, 17=Armed,
+                        ; 18=SWEEP_ON, 19=WINDOW, 20=HOLD_OFF, 21=EOS_DEADTIME
+                        ; 22=TIME[0],...,51=TIME[29], 52...63=SWEEP[0]..SWEEP[11]
+cycles=18               ; cycles for sequential mode
+sequences=1             ; for sequential mode (default 1)
+                        ; specifies how often to repeat
+                        ; after performing cycles acquisitions
+tagbits=16              ; number of tagbits
+vdac0=8fa               ; (hex) dac0 value (start) voltage=2.048 * (1-vdac/2048)
+                        ; bit 16: start with rising edge
+                        ; (bit 14, 15) : 0=falling, 1=rising, 2=both, 3=both+CFT
+vdac1=8fa               ; dac1 value
+vdac2=8fa               ; dac2 value
+vdac3=8fa               ; ...
+vdac4=8fa               ; ...
+vdac5=8fa               ; ...
+vdac6=8fa               ; ...
+vdac7=8fa               ; …dac7 value
+dac0v=-0.2              ; dac0 value = -0.2 V (start)
+dac1v=-0.2              ; dac1 value = -0.2 V (STOP1)
+..
+dac7v=-0.2              ; dac7 value in Volt
+dacv=-0.1               ; set dac1..dac7 to -0.1 V, all dacs without dac0 (start)
+dacv+=0.001             ; increase all dac values without dac0 by 1 mV
+dac0v+=0.001            ; increase dac0 value by 1 mV (start)
+rtpreset=20.000         ; Timepreset (seconds)
+digio=0                 ; LOWORD: Use of Dig I/O, GO Line:
+                        ; bit 0: status dig 0..3
+                        ; bit 1: Output digval and increment digval after stop
+                        ; bit 2: Invert polarity
+                        ; bit 3: Push-Pull output, not possible
+                        ; bit 4: Start with Input Dig 4
+                        ; bit 5: Start with Input GO
+                        ; bit 8: GOWATCH
+                        ; bit 9: GO High at Start
+                        ; bit 10: GO Low at Stop
+                        ; bit 11: Clear at triggered start
+                        ; bit 12: Only triggered start
+digval=0                ; digval=0..255 value for samplechanger
+autoinc=0               ; 1=Enable auto increment of filename
+savedata=0              ; 0=No Save at Halt
+                        ; 1=Save at Halt
+                        ; 2=Write list file, no save at Halt
+                        ; 3=Write lit file, Save at Halt
+mpafmt=asc              ; data fromat used in MPA files
+                        ; (dat=binary, asc=ASCII, csv=CSV)
+sephead=0               ; 1=Seperated Header file (extension .MP) and
+                        ; Data file (extension dat, asc or spe) for seperated spectra
+fmt=asc                 ; data format used in seperated spectra (extension .MP)
+                        ; (dat=binary, asc=ASCII, csv=CSV)
+smoothpts=5             ; number of points to average for a smooth operation
+wndwidth=155            ; width of server window
+wndheight=273           ; height of server window
+sysdef=0                ; System definition word:
+                        ; bit0=0, bit1=0: dev#0 in system 1
+                        ; bit0=1, bit1=0: dev#0 in system 2
+                        ; bit0=0, bit1=1: dev#0 in system 3
+                        ; bit0=1, bit1=1: dev#0 in system 4
+                        ; ...
+                        ; bit6=1, bit7=1: dev#3 in system 4
+                        ; bit 31: any preset stops all
+
+[CHN1]                  ; the following section concerns parameters of CHN1
+range=4096              ; Spectrum length
+active=1                ; Spectrum definition words for CHN1..8:
+                        ; active & 0xF ==0 not used
+                        ; ==1..4 enabled, system 1..4
+                        ; bit 8: Enable Tag bits
+                        ; bit 9: start with rising edge
+                        ; bit 10: time under threshold for pulse width
+                        ; bit 11: pulse width mode for any spectra with both edges enabled
+                        ; Spectrum definition words for calc. Spectra:
+                        ; active & 0xF ==3 MAP, ((x-xoffs)>>xsh) x ((y-yoffs)>>ysh)
+                        ; bit4=1: x zoomed MAP
+                        ; bit5=1: y zoomed MAP
+                        ; ==5 SUM, (x + y)>>xsh
+                        ; ==6 DIFF,(x - y + range)>>xsh
+                        ; ==7 ANY, (for compare)
+                        ; ==8 COPY, x
+                        ; ==10 SW-HIS, Sweep History
+                        ; bit 8..11 xsh, bit 12..15 ysh or bit 8..15 xsh
+                        ; HIWORD(active) = condition no. (0=no condition)
+bitshift=0              ; LOWORD: Binwidth = 2 ^ (bitshift)
+                        ; HIWORD: Threshold for Coinc
+cftfak=2580100          ; LOWORD: 256 * cft factor (t_after_peak / t_to_peak)
+                        ; HIWORD: max pulse width for CFT
+evpreset=10             ; ROI preset value
+roimin=0                ; lower ROI limit
+roimax=4096             ; upper limit: roimin <= channel < roimax
+caloff=0.000000         ; calibration parameter: offset
+calfact=0.080000        ; calibration parameter: factor
+calfact2=0
+calfact3=0
+calunit=nsec            ; calibration unit
+caluse=1                ; bit 0=1: use calibration, higher bits: calibration formula
+roi=0 9986 ;starts      ; rectangular ROI from 0 to 9986 with name “starts” (lower left, upper right corner)
+
+[CHN2]                  ; the following section concerns parameters of CHN2
+...
+
+The following commands perform actions and therefore usually are not included in the MCS8A.SET file:
+
+start                   ; Clears the data and starts a new acquisition of system 1.
+                        ; Further execution of the .CTL file is suspended until any
+                        ; acquisition stops due to a preset.
+halt                    ; Stops acquisition of system 1 if one is running.
+cont                    ; Continues acquisition of system 1. If a time preset
+                        ; is already reached, the time preset is prolongated
+                        ; by the value which was valid when the “start“ command
+                        ; was executed. Further execution of the .CTL file
+                        ; is suspended (see start).
+erase                   ; Clears all spectra of system 1.
+savecnf                 ; Writes the settings into MCS8A.SET
+mpaname=filename        ; Defines the mpa filename
+savempa                 ; Saves all configuration and spectra data.
+                        ; An existing file is overwritten.
+pushname                ; pushes the actual mpa filename on an internal stack that can hold 4 names
+popname                 ; pops the last mpa filename from the internal stack
+loadmpa                 ; Loads mpa data; the filename
+                        ; must be specified before with a command mpaname=...
+addmpa                  ; Adds mpa data to actual spectra; the filename
+                        ; must be specified before with a command mpaname=...
+submpa                  ; Subtracts mpa data from actual spectra; the filename
+                        ; must be specified before with a command mpaname=...
+MC_A                    ; Sets actual input channel to MC_A (STOP1) for the rest of
+                        ; the control file.
+MC_B                    ; Sets actual multichannel analyzer to MC_B (STOP2)
+                        ; … MC_H (ch8)
+savedat                 ; Saves data of actual channel as separated
+                        ; spectrum (extension .MP) An existing file
+                        ; is overwritten.
+loaddat                 ; Loads data of actual channel, the filename
+                        ; must be specified before with a command datname=...
+adddat                  ; Adds data into actual spectra; the filename
+                        ; must be specified before with a command datname=...
+subdat                  ; Subtracts data from actual spectra channel; the filename
+                        ; must be specified before with a command datname=...
+smooth                  ; Smoothes the data in actual spectra
+erasedat                ; Clears the data of actual spectra.
+exit                    ; Exits the server (and MPANT) programs
+alert Message           ; Displays a Messagebox containing Message and an OK
+                        ; button that must be pressed before execution can continue.
+waitinfo 5000 Message   ; Displays a Messagebox containing Message, an OK
+                        ; and an END button. After the specified time (5000 msec)
+                        ; the Messagebox vanishes and execution continues. OK
+                        ; continues immediately, END escapes execution.
+beep *                  ; Makes a beep. The character '*' may be replaced with '?', '!' or
+                        ; left empty. The corresponding sound is defined in the WIN.INI
+                        ; file in the [sounds] section.
+delay 4000              ; Waits specified time (4000 msec = 4 sec).
+pulse 100               ; Outputs a pulse of 100 ms duration at dig 3
\ No newline at end of file
diff --git a/FastComtecMCS8A/docs/Fastcomtec_parameter_notes.md b/FastComtecMCS8A/docs/Fastcomtec_parameter_notes.md
new file mode 100644
index 0000000000000000000000000000000000000000..691701ce8c711697ff125da5c7d1b6181ce35e36
--- /dev/null
+++ b/FastComtecMCS8A/docs/Fastcomtec_parameter_notes.md
@@ -0,0 +1,138 @@
+# Basic Modes of Operation
+
+## 1. Stop after sweep mode (p.35f)
+When the MCS8A is armed it waits for a START input signal. When one occurs the sweep is started /
+triggered, meaning the time starts to count. Now the arrival times of the STOP input signals relative to the
+start are acquired on all channels that are enabled. A STOP event can be either a falling or a rising edge or
+both. Even further signals into the START input can be acquired. Since the type of edge is detected and
+marked in the acquired data even Time-over-Threshold or pulse width measurements can be accomplished.
+
+The data acquisition can be ended after a given time via the Time preset. In the edit field Range the length
+of the spectrum can be entered. A Bin width of 1 means the highest time resolution. The Bin width can be
+chosen in powers of 2 up to 1677216 times the elementary dwell time. If an Acq. Delay is specified, data are
+acquired in a sweep not before the specified time. Hold after sweep allows to wait a specified time after a
+sweep before the next sweep can be started.
+
+### 1.1. Start of measurement
+#### 1.1.1. Endless mode (p.44)
+mode of the measurement can be endless if the corresponding checkbox is crossed (in settings)
+#### 1.1.2. Software start (p.44)
+Doesn't require a start signal (checkbox in settings dialogue)
+
+### 1.2. Termination of measurement
+terminated by any of the preset (2) conditions
+#### 1.2.1. Time preset (total acquisition time) - THIS
+in steps of 2.56 ns - total measurement time (in the document: "sweep and so the data acquisition ends after that time" but with sweep preset you can get multiple sweeps. So this is more like a total measurement time)
+#### 1.2.2. Sweep preset (number of sweeps)- THIS
++ 48-bit sweep counter counts the real start of a new sweep rather than the completion of the sweeps
++ preset enabled: after preselected number of sweeps any further start of a sweep is prohibited
+#### 1.2.3. ROI preset (number of counts) - THIS
+Stop measurement after certain number of counts. ROI Preset
+### 1.3. Single sweep settings
+#### 1.3.1. Acquisiton delay (counting delay after START) - THIS
+in steps of 2.56 ns - accept only STOP events (= signals) that arrive after the selected delay 
+#### 1.3.2. Length of a single sweep - THIS
+The Sweep length is defined by the Range times the Bin Width.
+#### 1.3.3. Hold off time (pause time after sweep)- THIS
+in steps of 2.56 ns - allows new start only after this additional time has elapsed after the end of the sweep
+#### 1.3.4. End of sweep dead-time - THIS
+< 50ns
+#### 1.3.5. Selection range lmits - THIS
+Acq.Delay + TimeRange + Hold-Off ≤ 248 x 2.56 ns = 8.3 days max.
+
+
+
+## 2. Tagged spectra acquisiton (p.36)
+multi detector experiment: measure which detector has fired (time resolution 5.12ns), still maintain 80 ps bin width
+
+
+
+# Measurement Examples
+## 3. Pulse width measurement (p.45)
+As the edge information is contained in bit 4 of the data (a 1 in that bit means falling edge) it is possible to
+distinguish stop events from rising and falling signals and it is possible to analyze the pulse width of the
+signals, if Both Edges are chosen. There is a choice between "Over threshold" or "Under threshold" for
+the Pulse width analyzing, depending on the corresponding setting in the "inputs" dialog. To see the events
+from rising and falling signals separated, just enable Pulse width in the settings dialog and set y-Range to 2
+inside the box labeled ”2D spectra”. You will get a two dimensional spectra with a y-dimension of 2, for y=0 it
+contains the stop events from rising edges and for y=1 from falling edges. You can see here the separation
+time between both edges. If you set then the y-Range to a value larger than the maximum pulse width in
+channels, you will get a 2-dimensional spectra with the time of the first edge as x coordinate and the pulse
+width as y coordinate (see chapter 2.5.4). (There is more text in the document ...)
+
+# Input Settings
+
+## 4. ROI Preset (p.44)
+ROI Preset checkboxes marked: measurement stopped after acquiring more events than specified (events are counted only if they are within the ROI limits, i.e. >= the lower limit and < the upper limit)
+
+## 5. Treshold voltage (p.44) - THIS
++ Fast NIM (-0.3 V) or customized
++ Falling or Rising Edge
++ See "Measurement examples" or document p.45 for pulse width measurement
+
+# Electrical ratings (p.99)
+
+## 6. START / STOP (discriminator) inputs
++ Voltage range       -2.0 … +3.0 V
++ Threshold voltage   -1.0 … +1.5 V
+### 6.1. Absolute maximum ratings
++ DC input current            ± 80 mA
++ any discriminator input     -3.0 … +4.0 V
+
+# Notes
+## 7. Dark count histogram
+### 7.1. Parameter Correspondance
+#### 7.1.1. Number of repetions - Sweep preset
+#### 7.1.2. Expectation value $\lambda$ - controlle by Time range
+Range * bin width
+
+# How to set the settings
+## Active channels
++ active = 1
++ and dont forget sweepmode !
+## 8. Start event generation (???)
+If start event generation is checked, a start event is inserted into the data stream and counted.
+
+## 9. After sweep
+### 9.1. Save
++ savedata=1
+### 9.2. Auto increment data files
++ autoinc=1 
+
+## 10. Time Settings
+### 10.1. Binning (binwidth)
++ bitshift=0              ; LOWORD: Binwidth = 2 ^ (bitshift)
++ calfact=0.400000 * Binwidth (a setting only required to propperly show the histogram in software)
+### 10.2. Range (per channel)
++ range=4096 (in steps of 64)
+### 10.3. Hold off time
++ holdafter=6.4 (in of 6.4 ns)
+### 10.4. Acquisition delay
++ fstchan = 1 ; acquisition delay = fstchan * 6.4ns
++ caloff=6.4 * fstchan ; MPNAT software calibration for shwoing histogram
+## 11. Presets
+### 11.1. Prena (is HEX!)
++ prena=4              
++                       ; bit 0: realtime preset enabled
+                        ; bit 1:
+                        ; bit 2: sweep preset enabled
+                        ; bit 3: ROI preset enabled
+                        ; bit 4: Starts preset enabled
+                        ; bit 5: ROI2 preset enabled
+                        ; bit 6: ROI3 preset enabled
+                        ; bit 7: ROI4 preset enabled
+                        ; bit 8: ROI5 preset enabled
+                        ; bit 9: ROI6 preset enabled
+                        ; bit 10: ROI7 preset enabled
+                        ; bit 11: ROI8 preset enabled
+
+Examples
++ prena = 3 : time preset
++ prena = 6 : sweep preset
++ prena = 7 : sweep & time preset 
++ prena = 2 : nothing
+### 11.2. Time preset
++ WRONG: rtpreset=20.000; Timepreset (seconds) [from doc]
++ RIHGT: timepreset = 20.000; (seconds) [observed]
+### 11.3. Sweep preset
++ swpreset=20000000    
\ No newline at end of file
diff --git a/FastComtecMCS8A/fastcomtec_api.py b/FastComtecMCS8A/fastcomtec_api.py
new file mode 100644
index 0000000000000000000000000000000000000000..75c580ad3a745c73d607cb51a9091bf795cbaa2f
--- /dev/null
+++ b/FastComtecMCS8A/fastcomtec_api.py
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+
+import ctypes
+try:
+    from . import fastcomtec_types
+except ImportError:
+    import fastcomtec_types
+import re
+from typing import NamedTuple, List
+
+class FastComTec():
+    """ Hardware Class for the FastComtec MCS8. """
+
+    def __init__(self, dll_path = r'C:\Windows\System32\DMCS8.dll', **kwargs) -> None:
+        self.dll = ctypes.windll.LoadLibrary(dll_path)       
+    ########################################
+    # Fastcomtec Types
+    ########################################
+    def get_acq_status(self) -> fastcomtec_types.AcqStatus:
+        status = fastcomtec_types.AcqStatus()
+        self.dll.GetStatusData(ctypes.byref(status), 0)
+        return status
+    
+    def get_acq_settings(self) -> fastcomtec_types.AcqSettings:
+        settings = fastcomtec_types.AcqSettings()
+        self.dll.GetSettingData(ctypes.byref(settings), 0)
+        return settings
+    
+    def get_board_settings(self) -> fastcomtec_types.BoardSetting:
+        boardsettings = fastcomtec_types.BoardSetting()
+        self.dll.GetMCSSetting(ctypes.byref(boardsettings), 0)
+        return boardsettings
+    
+    def get_acq_data(self) -> fastcomtec_types.AcqData:
+        return NotImplementedError # code below doesn't give data for some reason
+        data = fastcomtec_types.AcqData()
+        self.dll.GetData(ctypes.byref(data), 0)
+        return data
+    ########################################
+    # DLL Interaction
+    ########################################
+    def _send_dll_command(self, command: str) -> None:
+        self.dll.RunCmd(0, bytes(command, ' utf-8'))
+
+    def _send_dll_commands(self, commands: List[str]) -> None:
+        for cmd in commands: 
+            self._send_dll_command(cmd)
+    ########################################
+    # Measurement 
+    ########################################
+    def start_measurement(self) -> None:
+        self._send_dll_command("start")
+
+    def halt_measurement(self) -> None:
+        self._send_dll_command("halt")
+    
+    def erase_measruement(self) -> None:
+        self._send_dll_command("erase")
+    ########################################
+    # Saving and Loading Data and Config
+    ########################################
+    def load_config(self, file_path: str) -> None:
+        """Doesn't have to be a .SET file, can also be a .mpa file."""
+        self._send_dll_command(f"loadcnf {file_path}")
+
+    def save_config(self) -> None:
+        """Config stored in C:/mcs8x64/MCS8A.SET"""
+        self._send_dll_command("savecnf") 
+
+    def save_config_and_data_seperately(self, file_path: str, ) -> None:
+        """
+        NOTE: 
+        + The Config gets saved twice, but both time with CHN1 as a header .
+        + TOTALSUM, ROISUM, MAXVAL for Channel 2 might be totally wrong
+        """
+        self._send_dll_command(f"datname={file_path}_CHN1")
+        self._send_dll_command("MC_A")
+        self._send_dll_command("savedat")
+        self._send_dll_command(f"datname={file_path}_CHN2")
+        self._send_dll_command("MC_B")
+        self._send_dll_command("savedat")
+
+    def save_config_with_data(self, file_path: str) -> None:
+        self._send_dll_command(f"mpaname={file_path}")
+        self._send_dll_command("savempa")
+    ########################################
+    # Change Individual Settings
+    ########################################
+    def set_time_preset(self, time_preset_sec: float) -> None:
+        self._send_dll_command(f"timepreset={time_preset_sec}")
+    def set_sweep_preset(self, swpreset: int) -> None:
+        self._send_dll_command(f"timepreset={swpreset}")
+        
+
+########################################
+# Separate config and data
+########################################    
+def separate_config_and_data(file_path: str) -> None:
+    path_split_up = file_path.split(".")
+    path_split_up[-2] += "_config"
+    config_path = ".".join(path_split_up) 
+
+    path_split_up = file_path.split(".")
+    path_split_up[-2] += "_data"
+    data_path = ".".join(path_split_up) 
+    
+    regex = re.compile("(TDAT)")
+    match = False
+    with open(file_path, "r") as f:
+        lines = f.readlines()
+    write_data = False
+    with open(config_path, "w+") as config_file:
+        with open(data_path, "w+") as data_file:
+            for line in lines:
+                match = regex.search(line)
+                if match:
+                    write_data = True
+                if write_data:
+                    data_file.write(line)
+                else:
+                    config_file.write(line)
+
+class BoundaryInfo(NamedTuple):
+    boundary_id: str
+    line_number: int
+
+def separate_config_and_data_per_channel(file_path: str) -> None:
+    path_split_up = file_path.split(".")
+    path_split_up[-2] += "_config"
+    config_path = ".".join(path_split_up) 
+    
+    # read in file
+    with open(file_path, "r") as f:
+        lines = f.readlines()
+    
+    boundaries: List[BoundaryInfo] = []
+
+    # find boundaries of data sections
+    regex_channel_data = re.compile("(TDAT)")
+    match = False
+    for i, line in enumerate(lines):
+        match = regex_channel_data.search(line)
+        if match:
+            boundaries.append(BoundaryInfo(line.split(",")[0][1:], i)) # exclue "[" in data_id
+
+    # write config file
+    with open(config_path, "w+") as config_file:
+        config_file.write("".join(lines[:boundaries[0].line_number]))
+
+    # write data files
+    for i in range(len(boundaries)):
+        path_split_up = file_path.split(".")
+        path_split_up[-2] += f"_data_{boundaries[i].boundary_id}"
+        data_path = ".".join(path_split_up) 
+        with open(data_path, "w+") as data_file:
+            if (i+1) < len(boundaries):
+                data_file.write("".join(lines[boundaries[i].line_number:boundaries[i+1].line_number]))
+            else:
+                data_file.write("".join(lines[boundaries[i].line_number:]))
+
+
diff --git a/FastComtecMCS8A/fastcomtec_types.py b/FastComtecMCS8A/fastcomtec_types.py
new file mode 100644
index 0000000000000000000000000000000000000000..150bfef47295c5b09a92dda7ebd4ffc490dc2ee9
--- /dev/null
+++ b/FastComtecMCS8A/fastcomtec_types.py
@@ -0,0 +1,259 @@
+import ctypes # general doc about Structures: https://docs.python.org/3/library/ctypes.html#structures-and-unions
+
+"""
+Remark to the usage of ctypes:
+All Python types except integers (int), strings (str), and bytes (byte) objects
+have to be wrapped in their corresponding ctypes type, so that they can be
+converted to the required C data type.
+
+ctypes type     C type                  Python type
+----------------------------------------------------------------
+c_bool          _Bool                   bool (1)
+c_char          char                    1-character bytes object
+c_wchar         wchar_t                 1-character string
+c_byte          char                    int
+c_ubyte         unsigned char           int
+c_short         short                   int
+c_ushort        unsigned short          int
+c_int           int                     int
+c_uint          unsigned int            int
+c_long          long                    int
+c_ulong         unsigned long           int
+c_longlong      __int64 or
+                long long               int
+c_ulonglong     unsigned __int64 or
+                unsigned long long      int
+c_size_t        size_t                  int
+c_ssize_t       ssize_t or
+                Py_ssize_t              int
+c_float         float                   float
+c_double        double                  float
+c_longdouble    long double             float
+c_char_p        char *
+                (NUL terminated)        bytes object or None
+c_wchar_p       wchar_t *
+                (NUL terminated)        string or None
+c_void_p        void *                  int or None
+
+"""
+# Reconstruct the proper structure of the variables, which can be extracted
+# from the header file 'struct.h'.
+
+
+class AcqStatus(ctypes.Structure):
+    """ Create a structured Data type with ctypes where the dll can write into.
+
+    This object handles and retrieves the acquisition status data from the
+    Fastcomtec.
+
+    int started;                // acquisition status: 1 if running, 0 else
+    double runtime;             // running time in seconds
+    double totalsum;            // total events
+    double roisum;              // events within ROI
+    double roirate;             // acquired ROI-events per second
+    double nettosum;            // ROI sum with background subtracted
+    double sweeps;              // Number of sweeps
+    double stevents;            // Start Events
+    unsigned long maxval;       // Maximum value in spectrum
+    """
+    def __init__(self):
+        super().__init__()
+        self.started    : ctypes.c_int  
+        self.runtime    : ctypes.c_double
+        self.totalsum   : ctypes.c_double
+        self.roisum     : ctypes.c_double
+        self.roirate    : ctypes.c_double
+        self.ofls       : ctypes.c_double  
+        self.sweeps     : ctypes.c_double
+        self.stevents   : ctypes.c_double
+        self.maxval     : ctypes.c_ulong 
+
+    _fields_ = [('started', ctypes.c_int),
+                ('runtime', ctypes.c_double),
+                ('totalsum', ctypes.c_double),
+                ('roisum', ctypes.c_double),
+                ('roirate', ctypes.c_double),
+                ('ofls', ctypes.c_double),
+                ('sweeps', ctypes.c_double),
+                ('stevents', ctypes.c_double),
+                ('maxval', ctypes.c_ulong), ]
+    
+    def __repr__(self) -> str:
+        return  'started : ' + str(self.started ) + '\n' \
+                'runtime : ' + str(self.runtime ) + '\n' \
+                'totalsum: ' + str(self.totalsum) + '\n' \
+                'roisum  : ' + str(self.roisum  ) + '\n' \
+                'roirate : ' + str(self.roirate ) + '\n' \
+                'ofls    : ' + str(self.ofls    ) + '\n' \
+                'sweeps  : ' + str(self.sweeps  ) + '\n' \
+                'stevents: ' + str(self.stevents) + '\n' \
+                'maxval  : ' + str(self.maxval  )
+
+class AcqData(ctypes.Structure):
+    """ Create a structured Data type with ctypes where the dll can write into.
+
+    This object handles and retrieves the acquisition data of the Fastcomtec.
+    """
+    def __init__(self):
+        super().__init__()
+        self.s0     : ctypes._Pointer 
+        self.region : ctypes._Pointer 
+        self.comment: ctypes.c_char_p 
+        self.cnt    : ctypes._Pointer 
+        self.hs0    : ctypes.c_int    
+        self.hrg    : ctypes.c_int    
+        self.hcm    : ctypes.c_int    
+        self.hct    : ctypes.c_int    
+
+    _fields_ = [('s0', ctypes.POINTER(ctypes.c_ulong)),
+                ('region', ctypes.POINTER(ctypes.c_ulong)),
+                ('comment', ctypes.c_char_p),
+                ('cnt', ctypes.POINTER(ctypes.c_double)),
+                ('hs0', ctypes.c_int),
+                ('hrg', ctypes.c_int),
+                ('hcm', ctypes.c_int),
+                ('hct', ctypes.c_int), ]
+    
+    def __repr__(self) -> str:
+        return  's0     : ' + str(self.s0     ) + '\n' \
+                'region : ' + str(self.region ) + '\n' \
+                'comment: ' + str(self.comment) + '\n' \
+                'cnt    : ' + str(self.cnt    ) + '\n' \
+                'hs0    : ' + str(self.hs0    ) + '\n' \
+                'hrg    : ' + str(self.hrg    ) + '\n' \
+                'hcm    : ' + str(self.hcm    ) + '\n' \
+                'hct    : ' + str(self.hct    )
+
+class AcqSettings(ctypes.Structure):
+    def __init__(self):
+        super().__init__()
+        self.range          : ctypes.c_long     
+        self.cftfak         : ctypes.c_long     
+        self.roimin         : ctypes.c_long     
+        self.roimax         : ctypes.c_long     
+        self.nregions       : ctypes.c_long     
+        self.caluse         : ctypes.c_long     
+        self.calpoints      : ctypes.c_long     
+        self.param          : ctypes.c_long     
+        self.offset         : ctypes.c_long     
+        self.xdim           : ctypes.c_long     
+        self.bitshift       : ctypes.c_ulong    
+        self.active         : ctypes.c_long     
+        self.eventpreset    : ctypes.c_double   
+        self.dummy1         : ctypes.c_double   
+        self.dummy2         : ctypes.c_double   
+        self.dummy3         : ctypes.c_double   
+
+    _fields_ = [('range',       ctypes.c_long),
+                ('cftfak',      ctypes.c_long),
+                ('roimin',      ctypes.c_long),
+                ('roimax',      ctypes.c_long),
+                ('nregions',    ctypes.c_long),
+                ('caluse',      ctypes.c_long),
+                ('calpoints',   ctypes.c_long),
+                ('param',       ctypes.c_long),
+                ('offset',      ctypes.c_long),
+                ('xdim',        ctypes.c_long),
+                ('bitshift',    ctypes.c_ulong),
+                ('active',      ctypes.c_long),
+                ('eventpreset', ctypes.c_double),
+                ('dummy1',      ctypes.c_double),
+                ('dummy2',      ctypes.c_double),
+                ('dummy3',      ctypes.c_double), ]
+    
+    def __repr__(self) -> str:
+        return  'range      : ' + str(self.range      ) + '\n' \
+                'cftfak     : ' + str(self.cftfak     ) + '\n' \
+                'roimin     : ' + str(self.roimin     ) + '\n' \
+                'roimax     : ' + str(self.roimax     ) + '\n' \
+                'nregions   : ' + str(self.nregions   ) + '\n' \
+                'caluse     : ' + str(self.caluse     ) + '\n' \
+                'calpoints  : ' + str(self.calpoints  ) + '\n' \
+                'param      : ' + str(self.param      ) + '\n' \
+                'offset     : ' + str(self.offset     ) + '\n' \
+                'xdim       : ' + str(self.xdim       ) + '\n' \
+                'bitshift   : ' + str(self.bitshift   ) + '\n' \
+                'active     : ' + str(self.active     ) + '\n' \
+                'eventpreset: ' + str(self.eventpreset) + '\n' \
+                'dummy1     : ' + str(self.dummy1     ) + '\n' \
+                'dummy2     : ' + str(self.dummy2     ) + '\n' \
+                'dummy3     : ' + str(self.dummy3     )
+
+class BoardSetting(ctypes.Structure):
+    def __init__(self):
+        super().__init__()
+        self.sweepmode : ctypes.c_long
+        self.prena     : ctypes.c_long
+        self.cycles    : ctypes.c_long
+        self.sequences : ctypes.c_long
+        self.syncout   : ctypes.c_long
+        self.digio     : ctypes.c_long
+        self.digval    : ctypes.c_long
+        self.dac0      : ctypes.c_long
+        self.dac1      : ctypes.c_long
+        self.dac2      : ctypes.c_long
+        self.dac3      : ctypes.c_long
+        self.dac4      : ctypes.c_long
+        self.dac5      : ctypes.c_long
+        self.fdac      : ctypes.c_int
+        self.tagbits   : ctypes.c_int
+        self.extclk    : ctypes.c_int
+        self.maxchan   : ctypes.c_long
+        self.serno     : ctypes.c_long
+        self.ddruse    : ctypes.c_long
+        self.active    : ctypes.c_long
+        self.holdafter : ctypes.c_double
+        self.swpreset  : ctypes.c_double
+        self.fstchan   : ctypes.c_double
+        self.timepreset: ctypes.c_double
+
+    _fields_ = [('sweepmode',   ctypes.c_long),
+                ('prena',       ctypes.c_long),
+                ('cycles',      ctypes.c_long),
+                ('sequences',   ctypes.c_long),
+                ('syncout',     ctypes.c_long),
+                ('digio',       ctypes.c_long),
+                ('digval',      ctypes.c_long),
+                ('dac0',        ctypes.c_long),
+                ('dac1',        ctypes.c_long),
+                ('dac2',        ctypes.c_long),
+                ('dac3',        ctypes.c_long),
+                ('dac4',        ctypes.c_long),
+                ('dac5',        ctypes.c_long),
+                ('fdac',        ctypes.c_int),
+                ('tagbits',     ctypes.c_int),
+                ('extclk',      ctypes.c_int),
+                ('maxchan',     ctypes.c_long),
+                ('serno',       ctypes.c_long),
+                ('ddruse',      ctypes.c_long),
+                ('active',      ctypes.c_long),
+                ('holdafter',   ctypes.c_double),
+                ('swpreset',    ctypes.c_double),
+                ('fstchan',     ctypes.c_double),
+                ('timepreset',  ctypes.c_double),]
+    
+    def __repr__(self) -> str:
+        return  'sweepmode : ' + str(self.sweepmode ) + '\n' \
+                'prena     : ' + str(self.prena     ) + '\n' \
+                'cycles    : ' + str(self.cycles    ) + '\n' \
+                'sequences : ' + str(self.sequences ) + '\n' \
+                'syncout   : ' + str(self.syncout   ) + '\n' \
+                'digio     : ' + str(self.digio     ) + '\n' \
+                'digval    : ' + str(self.digval    ) + '\n' \
+                'dac0      : ' + str(self.dac0      ) + '\n' \
+                'dac1      : ' + str(self.dac1      ) + '\n' \
+                'dac2      : ' + str(self.dac2      ) + '\n' \
+                'dac3      : ' + str(self.dac3      ) + '\n' \
+                'dac4      : ' + str(self.dac4      ) + '\n' \
+                'dac5      : ' + str(self.dac5      ) + '\n' \
+                'fdac      : ' + str(self.fdac      ) + '\n' \
+                'tagbits   : ' + str(self.tagbits   ) + '\n' \
+                'extclk    : ' + str(self.extclk    ) + '\n' \
+                'maxchan   : ' + str(self.maxchan   ) + '\n' \
+                'serno     : ' + str(self.serno     ) + '\n' \
+                'ddruse    : ' + str(self.ddruse    ) + '\n' \
+                'active    : ' + str(self.active    ) + '\n' \
+                'holdafter : ' + str(self.holdafter ) + '\n' \
+                'swpreset  : ' + str(self.swpreset  ) + '\n' \
+                'fstchan   : ' + str(self.fstchan   ) + '\n' \
+                'timepreset: ' + str(self.timepreset) 
diff --git a/FastComtecMCS8A/labscript_devices.py b/FastComtecMCS8A/labscript_devices.py
new file mode 100644
index 0000000000000000000000000000000000000000..a435fb81ab6a21f91039f78d6b3cf72bd0c19353
--- /dev/null
+++ b/FastComtecMCS8A/labscript_devices.py
@@ -0,0 +1,49 @@
+#####################################################################
+#                                                                   #
+# /user_devices/FastComtecMCS8A/labscript_devices.py                #
+#                                                                   #
+# Feb. 2024, Leonard Group                                          #
+#                                                                   #
+#                                                                   #
+#####################################################################
+from labscript import TriggerableDevice, Trigger, set_passed_properties, config
+
+class MCS8A(TriggerableDevice):
+    description = 'MCS8A'
+
+    @set_passed_properties(
+        property_names={"connection_table_properties":["config_path"]}
+    )
+    def __init__(self, name, parent_device, connection, SPCM_gate_parent=None, SPCM_gate_connection=None, config_path="MCS8A_default_config.SET",  **kwargs):
+        super().__init__(name, parent_device, connection, **kwargs)
+        self.BLACS_connection = "SPCM MCS8A"
+        self.config_path = config_path
+        self.labels = {}
+
+        if SPCM_gate_parent is not None:
+            self.SPCM_gate = Trigger(
+                f"{name}_SPCM_gate", SPCM_gate_parent, SPCM_gate_connection, trigger_edge_type="falling"
+            )
+
+    def acquire(self, t, duration, trigger_duration=None, label=""):
+        if trigger_duration is None:
+            trigger_duration = duration
+        self.labels[t] = label
+        self.trigger(t,trigger_duration)
+        if hasattr(self,"SPCM_gate"):
+            self.SPCM_gate.trigger(t,duration)
+
+    def generate_code(self, hdf5_file):
+        group = hdf5_file.create_group(f"devices/{self.name}")
+        labels_group = group.create_group("labels")
+        for t,label in self.labels.items():
+            labels_group.attrs[str(t)] = label
+        
+        group.attrs["n_trigger"] = len(self.trigger_device.triggerings)
+        durations = [triggering[1] for triggering in self.trigger_device.triggerings]
+        group.create_dataset("durations", compression = config.compression, data = durations)
+
+        super().generate_code(hdf5_file)
+       
+
+
diff --git a/FastComtecMCS8A/mcs8a_structures.py b/FastComtecMCS8A/mcs8a_structures.py
new file mode 100644
index 0000000000000000000000000000000000000000..1744076ca17e3a039cf04539cb46cd793c7035e8
--- /dev/null
+++ b/FastComtecMCS8A/mcs8a_structures.py
@@ -0,0 +1,52 @@
+from ctypes import * 
+
+class ACQSTATUS(Structure):
+    _fields_ = [("started", c_ulong),   #aquisition status
+                ("maxval", c_ulong),    #maxval
+                ("cnt", c_double*8)]    #status: runtime in msec, ofls, 
+                                        #total sum, roi sum, roi rate,sweeps,
+                                        #starts
+
+class ACQSETTING(Structure):
+    _fields_ = [("range", c_long),
+                ("cftfak", c_long),   #LOWORD: 256*cft factor(t_after_peak / t_to_peak); HIWORD:max pulse width for CFT
+                ("roimin", c_long),   #lower ROI limit
+                ("roimax", c_long),   #upper limit: roimin<=channel<roimax
+                ("nregions", c_long), #number of regions
+                ("caluse", c_long),   #bit0: 1 if calibration used, higher bits: formula
+                ("calpoints", c_long),#number of calibration points
+                ("param", c_long),    #(reserved:) for MAP and POS:LOWORD=x, HIWORD=y
+                ("offset", c_long),   #(reserved:) zoomed MAPS: LOWORD: xoffset, HIWORD, yoffset
+                ("xdim", c_long),     #(reserved:) x resolution of maps
+                ("bitshift", c_ulong),#LOWORD:Binwidth=2^(bitshift); HIWORD: Threshold for Coinc
+                ("active", c_long),   
+                ("roipreset", c_double),#ROI preset value
+                ("dummy1", c_double),
+                ("dummy2", c_double),
+                ("dummy3", c_double)]
+                
+class BOARDSETTING(Structure):          # This is a structure type describing special MCS6 hardware settings
+    _fields_ = [("sweepmode", c_long),
+                ("prena", c_long),  
+                ("cycles", c_long),  
+                ("sequences", c_long),
+                ("syncout", c_long),
+                ("digio", c_long),
+                ("digval", c_long),
+                ("dac0", c_long),#DAC0 value (START) 
+                ("dac1", c_long),#DAC1 value (STOP 1)
+                ("dac2", c_long),#DAC2 value (STOP 2)
+                ("dac3", c_long),#DAC3 value (STOP 3)
+                ("dac4", c_long),#DAC4 value (STOP 4) 
+                ("dac5", c_long),#DAC5 value (STOP 5)
+                ("fdac", c_int),
+                ("tagbits", c_int),
+                ("extclk", c_int),#use external clock
+                ("maxchan", c_long),  
+                ("serno", c_long),  
+                ("ddruse", c_long),
+                ("active", c_long),#module in system
+                ("holdafter", c_double),
+                ("swpreset", c_double),#sweep preset value
+                ("fstchan", c_double),#acquisition delay
+                ("timepreset", c_double)]#time preset      
diff --git a/FastComtecMCS8A/register_classes.py b/FastComtecMCS8A/register_classes.py
new file mode 100644
index 0000000000000000000000000000000000000000..fb9fb737d5b55e2b6258f0cb752a13605065498f
--- /dev/null
+++ b/FastComtecMCS8A/register_classes.py
@@ -0,0 +1,16 @@
+#####################################################################
+#                                                                   #
+# /user_devices/DCAMCamera/register_classes.py                      #
+#                                                                   #
+# Jan 2023, Marvin Holten                                           #
+#                                                                   #
+#                                                                   #
+#####################################################################
+
+from labscript_devices import register_classes
+
+register_classes(
+    'MCS8A',
+    BLACS_tab='user_devices.FastComtecMCS8A.blacs_tabs.MCS8ATab',
+    runviewer_parser=None,
+)
diff --git a/FastComtecMCS8A/runviewer_parser.py b/FastComtecMCS8A/runviewer_parser.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/FastComtecMCS8A/testing/fastcomtec_plotting.py b/FastComtecMCS8A/testing/fastcomtec_plotting.py
new file mode 100644
index 0000000000000000000000000000000000000000..98d2dfe880c9a635892690110f4df168dd01164d
--- /dev/null
+++ b/FastComtecMCS8A/testing/fastcomtec_plotting.py
@@ -0,0 +1,32 @@
+import matplotlib.pyplot as plt
+import numpy as np
+
+def plot_raw_histogram(config_path: str, data_path: str) -> None:
+    data = np.genfromtxt(data_path, dtype=np.int64, skip_header=1, delimiter='\n')
+    print(data)
+    plt.plot(data)
+    plt.xlabel("bin")
+    plt.ylabel("count")
+    plt.show()
+
+def plot_raw_histograms(config_path: str, data_path_1: str, data_path_2: str) -> None:
+    fig, axs = plt.subplots(2, 1)
+    data_1 = np.genfromtxt(data_path_1, dtype=np.int64, skip_header=1, delimiter='\n')
+    data_2 = np.genfromtxt(data_path_2, dtype=np.int64, skip_header=1, delimiter='\n')
+    x_values = (76.8/0.4 + np.arange(0, len(data_1))) * 0.4 
+    axs[0].plot(x_values, data_1, color = "blue")
+    axs[0].set_xlabel("$\Delta t$ (ns)")
+    axs[0].set_ylabel("count")
+    axs[0].set_xlim(76.8, (4096 + 76.8/0.4)*0.4)
+    axs[0].set_xticks(np.arange(100, 1800, 100), [str(n) for n in np.arange(100, 1800, 100)])
+    axs[0].set_title("CHN1, 10 MHz fast NIM")
+    axs[1].plot(data_2, color = "skyblue")
+    axs[1].set_xlabel("bin")
+    axs[1].set_ylabel("count")
+    axs[1].set_xlim(0, 4096)
+    axs[1].set_title("CHN2, 10 MHz $V_{pp} = 1 V$")
+    print("Sum CHN1", data_1.sum())
+    print("Max CHN1", data_1.max())
+    print("Sum CHN2", data_2.sum())
+    print("Max CHN2", data_2.max())
+    plt.show()
\ No newline at end of file
diff --git a/FastComtecMCS8A/testing/spcm_tt_histogram.py b/FastComtecMCS8A/testing/spcm_tt_histogram.py
new file mode 100644
index 0000000000000000000000000000000000000000..e424daa7213137f0a92a9add72ab14f1fa8d58e4
--- /dev/null
+++ b/FastComtecMCS8A/testing/spcm_tt_histogram.py
@@ -0,0 +1,130 @@
+import matplotlib.pyplot as plt
+import numpy as np
+import fastcomtec_api
+
+def printkw(**keywordarguments) -> None:
+    for kw in keywordarguments:
+        print(kw, f"{keywordarguments[kw]:e}")
+
+def print_kw_enum(**keywordarguments) -> None:
+    for kw in keywordarguments:
+        print(kw)
+        for i, el in enumerate(keywordarguments[kw]): 
+            print(f"{i:>2}:", el)
+        print("----------------------------")
+
+def tt_calculations():
+    bin_widths = 2**np.arange(0, 25)
+    fundamental_time_resolution = 400*10**(-12)
+    time_resolutions = fundamental_time_resolution * bin_widths
+    bins_per_second = 1 / time_resolutions
+
+    print_kw_enum(bin_widths = bin_widths, time_res = time_resolutions, bins_per_s = bins_per_second)
+
+    bin_selection = 24
+    total_measurement_duration_sec = 300
+
+    printkw(bins = bins_per_second[bin_selection] * total_measurement_duration_sec)
+
+    # print_kw(total_time = 29824*time_resolutions[22])
+
+def calculate_dark_count_histogram(file: str, name: str, total_time_sec: int, num_measurements: int):
+    
+    data = np.loadtxt(file, dtype=np.int32, skiprows=1)
+    # print(data.shape)
+    data_50s_split = np.array_split(data, num_measurements)
+    counts_per_measurement = []
+    for ar in data_50s_split:
+        # print(ar.shape)
+        counts_per_measurement.append(ar.sum())
+    bins=np.arange(np.array(counts_per_measurement).max() + 1) 
+    plt.hist(counts_per_measurement, bins, density=True, edgecolor='black', linewidth=1.2)
+    plt.xticks(bins+0.5, [str(b) for b in bins])
+    plt.title(f"SPCM {name} Histogram\n{num_measurements} $\cdot$ {total_time_sec/num_measurements}s measurements")
+    plt.ylabel("P(n)")
+    plt.xlabel("n")
+    plt.show()
+
+def calculate_test_diode_histogram(file: str, name: str, total_time_sec: int, num_measurements: int):
+    print("Loading data ...")
+    data = np.loadtxt(file, dtype=np.int32, skiprows=1)
+    # print(data.shape)
+    data_50s_split = np.array_split(data, num_measurements)
+    counts_per_measurement = []
+    print("Evaluating counts ...")
+    for ar in data_50s_split:
+        # print(ar.shape)
+        counts_per_measurement.append(ar.sum())
+    min_count = np.array(counts_per_measurement).min()
+    max_count = np.array(counts_per_measurement).max() + 1
+    # bins=np.arange(max_count) 
+    bins = np.linspace(min_count, max_count + 1, num=25)
+    bin_width = (max_count - min_count)/25
+    print("Plotting histogram ...")
+    plt.hist(counts_per_measurement, bins, edgecolor='black', linewidth=1.2)
+    plt.xticks(bins+bin_width * 0.5, [f"{int(b):.5e}" for b in bins], rotation=90)
+    plt.title(f"SPCM {name} Histogram\n{num_measurements} $\cdot$ {total_time_sec/num_measurements}s measurements")
+    plt.ylabel("P(n)")
+    plt.xlabel("n")
+    print("Done")
+    plt.show()
+    print("Exiting")
+
+def calculate_darkcount_histogram_tripple():
+    data_100_0 = np.loadtxt(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\100s_darkcount_data_TDAT1.mpa", dtype=np.int32, skiprows=1)
+    print(data_100_0.shape)
+    data_100_1 = np.loadtxt(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\100s-1_darkcount_data_TDAT1.mpa", dtype=np.int32, skiprows=1)
+    print(data_100_1.shape)
+    data_100_2 = np.loadtxt(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\100s-2_darkcount_data_TDAT1.mpa", dtype=np.int32, skiprows=1)
+    print(data_100_2.shape)
+    data_combined = np.hstack((data_100_0, data_100_1, data_100_2))
+    seconds = 300
+    data_split = np.array_split(data_combined, seconds)
+
+    counts_per_sec = []
+    for ar in data_split:
+        # print(ar.shape)
+        counts_per_sec.append(ar.sum())
+    # print(len(data_split))
+    bins=np.arange(25) 
+    plt.hist(counts_per_sec, bins, density=True)
+    plt.xticks(bins, [str(b) for b in bins])
+    plt.title(f"SPCM Dark Count Histogram ({seconds}x1s measurements)")
+    plt.ylabel("P(n)")
+    plt.xlabel("n")
+    plt.tight_layout()
+    plt.show()
+
+def light_calculations():
+    P0 = 2.5 * 10** (-3)
+    wavelen = 780 * 10**(-9)
+    h = 6 * 10**(-34)
+    c = 3 * 10**8
+    photon_energy = c/wavelen * h
+    num_photons = P0 / photon_energy
+    attenuation_dB = -5
+    printkw(photon_energy = photon_energy)
+    printkw(num_photons = num_photons)
+    printkw(attenuated = num_photons * 10**attenuation_dB)
+
+
+plt.rcParams.update({'figure.autolayout': True})
+
+### Split file
+# fastcomtec_api.separate_config_and_data_per_channel(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\Thorlabs Laser Diode\50s-2_5OD.mpa")
+
+### Dark counts
+# calculate_dark_count_histogram(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\Dark counts\50s_darkcount_data_TDAT1.mpa" , "Dark Count", 50, 50)
+# calculate_dark_count_histogram(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\Dark counts\100s_darkcount_data_TDAT1.mpa", "Dark Count", 100, 100)
+# calculate_darkcount_histogram_tripple()
+
+### Thorlabs Diode
+light_calculations()
+# calculate_test_diode_histogram(r"C:\Users\admin\benjamin_code\FastComTec_self\measurements\Thorlabs Laser Diode\50s_5OD_data_TDAT1.mpa", "780nm Diode Counts", 50, 50)
+
+
+
+### Calculations
+# tt_calculations()
+# light_calculations()
+
diff --git a/FastComtecMCS8A/testing/test.py b/FastComtecMCS8A/testing/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..acb6fca036b8dfcbf6b1057204ca08e577d6903a
--- /dev/null
+++ b/FastComtecMCS8A/testing/test.py
@@ -0,0 +1,119 @@
+import fastcomtec_api
+import time 
+import fastcomtec_plotting
+
+
+########################################################
+### Basics
+########################################################
+def load_dll():
+    print("--- Load Dll ---")
+    device = fastcomtec_api.FastComTec()
+    print(device.get_acq_status())
+
+def start_halt_erase():
+    print("--- Start Halt Erase ---")
+    device = fastcomtec_api.FastComTec()
+    device.erase_measruement()
+    device.start_measurement()
+    print(device.get_acq_status())
+    print()
+    time.sleep(5)
+    device.halt_measurement()
+    print(device.get_acq_status())
+    print()
+
+def start_halt_wo_erase():
+    print("--- Start Halt wo Erase ---")
+    device = fastcomtec_api.FastComTec()
+    print(device.get_acq_status())
+    print()
+    device.start_measurement()
+    time.sleep(5)
+    device.halt_measurement()
+    print(device.get_acq_status())
+    print()
+
+def load_cfg():
+    device = fastcomtec_api.FastComTec()
+    device.load_config("C:/Users/admin/benjamin_code/FastComTec_self/configs/ExampleMeasurement1_config.mpa")
+########################################################
+### Fastcomtec Types
+########################################################
+def test_get_data():
+    device = fastcomtec_api.FastComTec()
+    device.start_measurement()
+    data = device.get_acq_data()
+    device.halt_measurement()
+    print(data)
+
+def get_fastcomtec_types():
+    print("--- FastComTec types ----")
+    device = fastcomtec_api.FastComTec()
+    print("--- AcqSettings ---")
+    print(device.get_acq_settings())
+    print("--- AcqStatus ---")
+    print(device.get_acq_status())
+    print("--- BoardSettings ---")
+    print(device.get_board_settings())
+########################################################
+### Example measurements
+########################################################
+def two_channel_measurement():   
+    device = fastcomtec_api.FastComTec()
+    device.load_config("C:/Users/admin/benjamin_code/FastComTec_self/configs/TwoChannelMeasurement_config.mpa")
+    device.erase_measruement()
+    device._send_dll_command("MC_A")
+    device.start_measurement()
+    time.sleep(1)
+    device.halt_measurement()
+    device.save_config_with_data("C:/Users/admin/benjamin_code/FastComTec_self/measurements/TwoChannelMeasurement.mpa")
+    fastcomtec_api.separate_config_and_data_per_channel("C:/Users/admin/benjamin_code/FastComTec_self/measurements/TwoChannelMeasurement.mpa")
+
+def example_measurement_1():
+    device = fastcomtec_api.FastComTec()
+    device.load_config("C:/Users/admin/benjamin_code/FastComTec_self/configs/ExampleMeasurement1_config.mpa")
+    device.erase_measruement()
+    # device._send_dll_command("MC_A")
+    device.start_measurement()
+    time.sleep(1)
+    device.halt_measurement()
+    output_file = "C:/Users/admin/benjamin_code/FastComTec_self/test_example.mpa"
+    device.save_config_with_data(output_file)
+    # device.save_config_and_data_seperately("C:/Users/admin/benjamin_code/FastComTec_self/test_example")
+    fastcomtec_api.separate_config_and_data_per_channel(output_file)
+
+def load_cfg_and_perform_measurement(config_path_full: str, output_path_full: str, measurement_time: float):
+    device = fastcomtec_api.FastComTec()
+    device.load_config(config_path_full)
+    device.erase_measruement()
+    # device._send_dll_command("MC_A")
+    device.start_measurement()
+    time.sleep(measurement_time)
+    device.halt_measurement()
+    device.save_config_with_data(output_path_full)
+    fastcomtec_api.separate_config_and_data_per_channel(output_path_full)
+
+########################################################
+### Histogram plotting
+########################################################
+def print_data():
+    fastcomtec_plotting.plot_raw_histogram("test_example_config.mpa", "test_example_data.mpa")
+    fastcomtec_plotting.plot_raw_histograms("test_example_config.mpa", "test_example_data_TDAT0.mpa", "test_example_data_TDAT1.mpa") 
+
+def safe_config():
+    device = fastcomtec_api.FastComTec()
+    device.save_config()
+
+def custom_measurement():
+    load_cfg_and_perform_measurement(
+        config_path_full="C:/Users/admin/benjamin_code/FastComTec_self/configs/test.mpa",
+        output_path_full="C:/Users/admin/benjamin_code/FastComTec_self/measurements/TwoChannelMeasurement.mpa",
+        measurement_time=1
+    )
+
+def run_tests():
+    device = fastcomtec_api.FastComTec()
+    device._send_dll_command("bitshift=32")
+    device.save_config()
+run_tests()
diff --git a/FastComtecMCS8A/testing/tryout.py b/FastComtecMCS8A/testing/tryout.py
new file mode 100644
index 0000000000000000000000000000000000000000..a41c0b6a75c9aa672ce3c6f3c719377a6b0e3f54
--- /dev/null
+++ b/FastComtecMCS8A/testing/tryout.py
@@ -0,0 +1,21 @@
+
+import ctypes as ct 
+  
+# storing a ctypes long value 
+value_1 = ct.c_long(10) 
+  
+# using pointer() method we are pointing to the  
+# value_1 variable and storing it in ptr 
+ptr = ct.pointer(value_1) 
+
+
+print("-----")
+print(ptr.contents)
+print(ptr[0])
+print(ptr[1])
+print("-----")
+print(id(ptr))
+print(id(ptr[0]))
+print(id(ptr[1]))
+ptr = ptr +  1
+print(id(ptr))
\ No newline at end of file