cgse 2024.7.0__py3-none-any.whl → 2025.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- README.md +27 -0
- bump.py +85 -0
- cgse-2025.0.2.dist-info/METADATA +38 -0
- cgse-2025.0.2.dist-info/RECORD +5 -0
- {cgse-2024.7.0.dist-info → cgse-2025.0.2.dist-info}/WHEEL +1 -2
- cgse-2024.7.0.dist-info/COPYING +0 -674
- cgse-2024.7.0.dist-info/COPYING.LESSER +0 -165
- cgse-2024.7.0.dist-info/METADATA +0 -144
- cgse-2024.7.0.dist-info/RECORD +0 -660
- cgse-2024.7.0.dist-info/entry_points.txt +0 -75
- cgse-2024.7.0.dist-info/top_level.txt +0 -2
- egse/__init__.py +0 -12
- egse/__main__.py +0 -32
- egse/aeu/aeu.py +0 -5238
- egse/aeu/aeu_awg.yaml +0 -265
- egse/aeu/aeu_crio.yaml +0 -273
- egse/aeu/aeu_cs.py +0 -627
- egse/aeu/aeu_devif.py +0 -321
- egse/aeu/aeu_main_ui.py +0 -903
- egse/aeu/aeu_metrics.py +0 -131
- egse/aeu/aeu_protocol.py +0 -463
- egse/aeu/aeu_psu.yaml +0 -204
- egse/aeu/aeu_ui.py +0 -873
- egse/aeu/arbdata/FccdRead.arb +0 -2
- egse/aeu/arbdata/FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/HeaterSync_FccdRead.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead50.arb +0 -2
- egse/aeu/arbdata/Heater_FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/ccdRead25.arb +0 -2
- egse/aeu/arbdata/ccdRead25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead50.arb +0 -2
- egse/aeu/arbdata/ccdRead50_150ms.arb +0 -2
- egse/alert/__init__.py +0 -1049
- egse/alert/alertman.yaml +0 -37
- egse/alert/alertman_cs.py +0 -233
- egse/alert/alertman_ui.py +0 -600
- egse/alert/gsm/beaglebone.py +0 -138
- egse/alert/gsm/beaglebone.yaml +0 -51
- egse/alert/gsm/beaglebone_cs.py +0 -108
- egse/alert/gsm/beaglebone_devif.py +0 -122
- egse/alert/gsm/beaglebone_protocol.py +0 -46
- egse/bits.py +0 -318
- egse/camera.py +0 -44
- egse/collimator/__init__.py +0 -0
- egse/collimator/fcul/__init__.py +0 -0
- egse/collimator/fcul/ogse.py +0 -1077
- egse/collimator/fcul/ogse.yaml +0 -14
- egse/collimator/fcul/ogse_cs.py +0 -154
- egse/collimator/fcul/ogse_devif.py +0 -358
- egse/collimator/fcul/ogse_protocol.py +0 -132
- egse/collimator/fcul/ogse_sim.py +0 -431
- egse/collimator/fcul/ogse_ui.py +0 -1108
- egse/command.py +0 -699
- egse/config.py +0 -410
- egse/confman/__init__.py +0 -1058
- egse/confman/confman.yaml +0 -70
- egse/confman/confman_cs.py +0 -240
- egse/confman/confman_ui.py +0 -381
- egse/confman/setup_ui.py +0 -565
- egse/control.py +0 -632
- egse/coordinates/__init__.py +0 -534
- egse/coordinates/avoidance.py +0 -100
- egse/coordinates/cslmodel.py +0 -127
- egse/coordinates/laser_tracker_to_dict.py +0 -122
- egse/coordinates/point.py +0 -707
- egse/coordinates/pyplot.py +0 -194
- egse/coordinates/referenceFrame.py +0 -1279
- egse/coordinates/refmodel.py +0 -737
- egse/coordinates/rotationMatrix.py +0 -85
- egse/coordinates/transform3d_addon.py +0 -419
- egse/csl/__init__.py +0 -50
- egse/csl/commanding.py +0 -78
- egse/csl/icons/hexapod-connected-selected.svg +0 -30
- egse/csl/icons/hexapod-connected.svg +0 -30
- egse/csl/icons/hexapod-homing-selected.svg +0 -68
- egse/csl/icons/hexapod-homing.svg +0 -68
- egse/csl/icons/hexapod-retract-selected.svg +0 -56
- egse/csl/icons/hexapod-retract.svg +0 -51
- egse/csl/icons/hexapod-zero-selected.svg +0 -56
- egse/csl/icons/hexapod-zero.svg +0 -56
- egse/csl/icons/logo-puna.svg +0 -92
- egse/csl/icons/stop.svg +0 -1
- egse/csl/initialisation.py +0 -102
- egse/csl/mech_pos_settings.yaml +0 -18
- egse/das.py +0 -1240
- egse/das.yaml +0 -7
- egse/data/conf/SETUP_CSL_00000_170620_150000.yaml +0 -5
- egse/data/conf/SETUP_CSL_00001_170620_151010.yaml +0 -69
- egse/data/conf/SETUP_CSL_00002_170620_151020.yaml +0 -69
- egse/data/conf/SETUP_CSL_00003_170620_151030.yaml +0 -69
- egse/data/conf/SETUP_CSL_00004_170620_151040.yaml +0 -69
- egse/data/conf/SETUP_CSL_00005_170620_151050.yaml +0 -69
- egse/data/conf/SETUP_CSL_00006_170620_151060.yaml +0 -69
- egse/data/conf/SETUP_CSL_00007_170620_151070.yaml +0 -69
- egse/data/conf/SETUP_CSL_00008_170620_151080.yaml +0 -75
- egse/data/conf/SETUP_CSL_00010_210308_083016.yaml +0 -138
- egse/data/conf/SETUP_INTA_00000_170620_150000.yaml +0 -4
- egse/data/conf/SETUP_SRON_00000_170620_150000.yaml +0 -4
- egse/decorators.py +0 -514
- egse/device.py +0 -269
- egse/dpu/__init__.py +0 -2698
- egse/dpu/ccd_ui.py +0 -514
- egse/dpu/dpu.py +0 -783
- egse/dpu/dpu.yaml +0 -153
- egse/dpu/dpu_cs.py +0 -272
- egse/dpu/dpu_ui.py +0 -671
- egse/dpu/fitsgen.py +0 -2096
- egse/dpu/fitsgen_ui.py +0 -399
- egse/dpu/hdf5_model.py +0 -332
- egse/dpu/hdf5_ui.py +0 -277
- egse/dpu/hdf5_viewer.py +0 -506
- egse/dpu/hk_ui.py +0 -468
- egse/dpu_commands.py +0 -81
- egse/dsi/__init__.py +0 -33
- egse/dsi/_libesl.py +0 -232
- egse/dsi/constants.py +0 -296
- egse/dsi/esl.py +0 -630
- egse/dsi/rmap.py +0 -444
- egse/dsi/rmapci.py +0 -39
- egse/dsi/spw.py +0 -335
- egse/dsi/spw_state.py +0 -29
- egse/dummy.py +0 -318
- egse/dyndummy.py +0 -179
- egse/env.py +0 -278
- egse/exceptions.py +0 -88
- egse/fdir/__init__.py +0 -26
- egse/fdir/fdir_manager.py +0 -85
- egse/fdir/fdir_manager.yaml +0 -37
- egse/fdir/fdir_manager_controller.py +0 -136
- egse/fdir/fdir_manager_cs.py +0 -164
- egse/fdir/fdir_manager_interface.py +0 -15
- egse/fdir/fdir_remote.py +0 -73
- egse/fdir/fdir_remote.yaml +0 -30
- egse/fdir/fdir_remote_controller.py +0 -30
- egse/fdir/fdir_remote_cs.py +0 -94
- egse/fdir/fdir_remote_interface.py +0 -9
- egse/fdir/fdir_remote_popup.py +0 -26
- egse/fee/__init__.py +0 -106
- egse/fee/f_fee_register.yaml +0 -43
- egse/fee/feesim.py +0 -914
- egse/fee/n_fee_hk.py +0 -768
- egse/fee/nfee.py +0 -188
- egse/filterwheel/__init__.py +0 -4
- egse/filterwheel/eksma/__init__.py +0 -49
- egse/filterwheel/eksma/fw8smc4.py +0 -657
- egse/filterwheel/eksma/fw8smc4.yaml +0 -121
- egse/filterwheel/eksma/fw8smc4_cs.py +0 -144
- egse/filterwheel/eksma/fw8smc4_devif.py +0 -473
- egse/filterwheel/eksma/fw8smc4_protocol.py +0 -82
- egse/filterwheel/eksma/fw8smc4_ui.py +0 -940
- egse/filterwheel/eksma/fw8smc5.py +0 -115
- egse/filterwheel/eksma/fw8smc5.yaml +0 -105
- egse/filterwheel/eksma/fw8smc5_controller.py +0 -307
- egse/filterwheel/eksma/fw8smc5_cs.py +0 -141
- egse/filterwheel/eksma/fw8smc5_interface.py +0 -65
- egse/filterwheel/eksma/fw8smc5_simulator.py +0 -29
- egse/filterwheel/eksma/fw8smc5_ui.py +0 -1065
- egse/filterwheel/eksma/testpythonfw.py +0 -215
- egse/fov/__init__.py +0 -65
- egse/fov/fov_hk.py +0 -710
- egse/fov/fov_ui.py +0 -859
- egse/fov/fov_ui_controller.py +0 -140
- egse/fov/fov_ui_model.py +0 -200
- egse/fov/fov_ui_view.py +0 -345
- egse/gimbal/__init__.py +0 -32
- egse/gimbal/symetrie/__init__.py +0 -26
- egse/gimbal/symetrie/alpha.py +0 -586
- egse/gimbal/symetrie/generic_gimbal_ui.py +0 -1521
- egse/gimbal/symetrie/gimbal.py +0 -877
- egse/gimbal/symetrie/gimbal.yaml +0 -168
- egse/gimbal/symetrie/gimbal_cs.py +0 -183
- egse/gimbal/symetrie/gimbal_protocol.py +0 -138
- egse/gimbal/symetrie/gimbal_ui.py +0 -361
- egse/gimbal/symetrie/pmac.py +0 -1006
- egse/gimbal/symetrie/pmac_regex.py +0 -83
- egse/graph.py +0 -132
- egse/gui/__init__.py +0 -47
- egse/gui/buttons.py +0 -378
- egse/gui/focalplane.py +0 -1285
- egse/gui/formatter.py +0 -10
- egse/gui/led.py +0 -162
- egse/gui/limitswitch.py +0 -143
- egse/gui/mechanisms.py +0 -587
- egse/gui/states.py +0 -148
- egse/gui/stripchart.py +0 -729
- egse/gui/styles.qss +0 -48
- egse/gui/switch.py +0 -112
- egse/h5.py +0 -274
- egse/help/__init__.py +0 -0
- egse/help/help_ui.py +0 -126
- egse/hexapod/__init__.py +0 -32
- egse/hexapod/symetrie/__init__.py +0 -137
- egse/hexapod/symetrie/alpha.py +0 -874
- egse/hexapod/symetrie/dynalpha.py +0 -1387
- egse/hexapod/symetrie/hexapod_ui.py +0 -1516
- egse/hexapod/symetrie/pmac.py +0 -1010
- egse/hexapod/symetrie/pmac_regex.py +0 -83
- egse/hexapod/symetrie/puna.py +0 -1167
- egse/hexapod/symetrie/puna.yaml +0 -193
- egse/hexapod/symetrie/puna_cs.py +0 -195
- egse/hexapod/symetrie/puna_protocol.py +0 -134
- egse/hexapod/symetrie/puna_ui.py +0 -433
- egse/hexapod/symetrie/punaplus.py +0 -107
- egse/hexapod/symetrie/zonda.py +0 -872
- egse/hexapod/symetrie/zonda.yaml +0 -337
- egse/hexapod/symetrie/zonda_cs.py +0 -172
- egse/hexapod/symetrie/zonda_devif.py +0 -414
- egse/hexapod/symetrie/zonda_protocol.py +0 -123
- egse/hexapod/symetrie/zonda_ui.py +0 -449
- egse/hk.py +0 -791
- egse/icons/aeu-cs-start.svg +0 -117
- egse/icons/aeu-cs-stop.svg +0 -118
- egse/icons/aeu-cs.svg +0 -107
- egse/icons/aeu_cs-started.svg +0 -112
- egse/icons/aeu_cs-stopped.svg +0 -112
- egse/icons/aeu_cs.svg +0 -55
- egse/icons/alert.svg +0 -1
- egse/icons/arrow-double-left.png +0 -0
- egse/icons/arrow-double-right.png +0 -0
- egse/icons/arrow-up.svg +0 -11
- egse/icons/backward.svg +0 -1
- egse/icons/busy.svg +0 -1
- egse/icons/cleaning.svg +0 -115
- egse/icons/color-scheme.svg +0 -1
- egse/icons/cs-connected-alert.svg +0 -91
- egse/icons/cs-connected-disabled.svg +0 -43
- egse/icons/cs-connected.svg +0 -89
- egse/icons/cs-not-connected.svg +0 -44
- egse/icons/double-left-arrow.svg +0 -1
- egse/icons/double-right-arrow.svg +0 -1
- egse/icons/erase-disabled.svg +0 -19
- egse/icons/erase.svg +0 -59
- egse/icons/fitsgen-start.svg +0 -47
- egse/icons/fitsgen-stop.svg +0 -48
- egse/icons/fitsgen.svg +0 -1
- egse/icons/forward.svg +0 -1
- egse/icons/fov-hk-start.svg +0 -33
- egse/icons/fov-hk-stop.svg +0 -37
- egse/icons/fov-hk.svg +0 -1
- egse/icons/front-desk.svg +0 -1
- egse/icons/home-actioned.svg +0 -15
- egse/icons/home-disabled.svg +0 -15
- egse/icons/home.svg +0 -13
- egse/icons/info.svg +0 -1
- egse/icons/invalid.png +0 -0
- egse/icons/led-green.svg +0 -20
- egse/icons/led-grey.svg +0 -20
- egse/icons/led-orange.svg +0 -20
- egse/icons/led-red.svg +0 -20
- egse/icons/led-square-green.svg +0 -134
- egse/icons/led-square-grey.svg +0 -134
- egse/icons/led-square-orange.svg +0 -134
- egse/icons/led-square-red.svg +0 -134
- egse/icons/limit-switch-all-green.svg +0 -115
- egse/icons/limit-switch-all-red.svg +0 -117
- egse/icons/limit-switch-el+.svg +0 -116
- egse/icons/limit-switch-el-.svg +0 -117
- egse/icons/location-marker.svg +0 -1
- egse/icons/logo-dpu.svg +0 -48
- egse/icons/logo-gimbal.svg +0 -112
- egse/icons/logo-huber.svg +0 -23
- egse/icons/logo-ogse.svg +0 -31
- egse/icons/logo-puna.svg +0 -92
- egse/icons/logo-tcs.svg +0 -29
- egse/icons/logo-zonda.svg +0 -66
- egse/icons/maximize.svg +0 -1
- egse/icons/meter.svg +0 -1
- egse/icons/more.svg +0 -45
- egse/icons/n-fee-hk-start.svg +0 -24
- egse/icons/n-fee-hk-stop.svg +0 -25
- egse/icons/n-fee-hk.svg +0 -83
- egse/icons/observing-off.svg +0 -46
- egse/icons/observing-on.svg +0 -46
- egse/icons/open-document-hdf5.png +0 -0
- egse/icons/open-document-hdf5.svg +0 -21
- egse/icons/ops-mode.svg +0 -1
- egse/icons/play-green.svg +0 -17
- egse/icons/plugged-disabled.svg +0 -27
- egse/icons/plugged.svg +0 -21
- egse/icons/pm_ui.svg +0 -1
- egse/icons/power-button-green.svg +0 -27
- egse/icons/power-button-red.svg +0 -27
- egse/icons/power-button.svg +0 -27
- egse/icons/radar.svg +0 -1
- egse/icons/radioactive.svg +0 -2
- egse/icons/reload.svg +0 -1
- egse/icons/remote-control-off.svg +0 -28
- egse/icons/remote-control-on.svg +0 -28
- egse/icons/repeat-blue.svg +0 -15
- egse/icons/repeat.svg +0 -1
- egse/icons/settings.svg +0 -1
- egse/icons/shrink.svg +0 -1
- egse/icons/shutter.svg +0 -1
- egse/icons/sign-off.svg +0 -1
- egse/icons/sign-on.svg +0 -1
- egse/icons/sim-mode.svg +0 -1
- egse/icons/small-buttons-go.svg +0 -20
- egse/icons/small-buttons-minus.svg +0 -51
- egse/icons/small-buttons-plus.svg +0 -51
- egse/icons/sponge.svg +0 -220
- egse/icons/start-button-disabled.svg +0 -84
- egse/icons/start-button.svg +0 -50
- egse/icons/stop-button-disabled.svg +0 -84
- egse/icons/stop-button.svg +0 -50
- egse/icons/stop-red.svg +0 -17
- egse/icons/stop.svg +0 -1
- egse/icons/switch-disabled-square.svg +0 -87
- egse/icons/switch-disabled.svg +0 -15
- egse/icons/switch-off-square.svg +0 -87
- egse/icons/switch-off.svg +0 -72
- egse/icons/switch-on-square.svg +0 -87
- egse/icons/switch-on.svg +0 -61
- egse/icons/temperature-control.svg +0 -44
- egse/icons/th_ui_logo.svg +0 -1
- egse/icons/unplugged.svg +0 -23
- egse/icons/unvalid.png +0 -0
- egse/icons/user-interface.svg +0 -1
- egse/icons/vacuum.svg +0 -1
- egse/icons/valid.png +0 -0
- egse/icons/zoom-to-pixel-dark.svg +0 -64
- egse/icons/zoom-to-pixel-white.svg +0 -36
- egse/images/big-rotation-stage.png +0 -0
- egse/images/connected-100.png +0 -0
- egse/images/cross.svg +0 -6
- egse/images/disconnected-100.png +0 -0
- egse/images/gui-icon.png +0 -0
- egse/images/home.svg +0 -6
- egse/images/info-icon.png +0 -0
- egse/images/led-black.svg +0 -89
- egse/images/led-green.svg +0 -85
- egse/images/led-orange.svg +0 -85
- egse/images/led-red.svg +0 -85
- egse/images/load-icon.png +0 -0
- egse/images/load-setup.png +0 -0
- egse/images/load.png +0 -0
- egse/images/pause.png +0 -0
- egse/images/play-button.svg +0 -8
- egse/images/play.png +0 -0
- egse/images/process-status.png +0 -0
- egse/images/restart.png +0 -0
- egse/images/search.png +0 -0
- egse/images/sma.png +0 -0
- egse/images/start.png +0 -0
- egse/images/stop-button.svg +0 -8
- egse/images/stop.png +0 -0
- egse/images/switch-off.svg +0 -48
- egse/images/switch-on.svg +0 -48
- egse/images/undo.png +0 -0
- egse/images/update-button.svg +0 -11
- egse/imageviewer/exposureselection.py +0 -475
- egse/imageviewer/imageviewer.py +0 -198
- egse/imageviewer/matchfocalplane.py +0 -179
- egse/imageviewer/subfieldposition.py +0 -133
- egse/lampcontrol/__init__.py +0 -4
- egse/lampcontrol/beaglebone/beaglebone.py +0 -178
- egse/lampcontrol/beaglebone/beaglebone.yaml +0 -62
- egse/lampcontrol/beaglebone/beaglebone_cs.py +0 -106
- egse/lampcontrol/beaglebone/beaglebone_devif.py +0 -150
- egse/lampcontrol/beaglebone/beaglebone_protocol.py +0 -73
- egse/lampcontrol/energetiq/__init__.py +0 -22
- egse/lampcontrol/energetiq/eq99.yaml +0 -98
- egse/lampcontrol/energetiq/lampEQ99.py +0 -283
- egse/lampcontrol/energetiq/lampEQ99_cs.py +0 -128
- egse/lampcontrol/energetiq/lampEQ99_devif.py +0 -158
- egse/lampcontrol/energetiq/lampEQ99_encode_decode_errors.py +0 -73
- egse/lampcontrol/energetiq/lampEQ99_protocol.py +0 -71
- egse/lampcontrol/energetiq/lampEQ99_ui.py +0 -465
- egse/lib/CentOS-7/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/CentOS-8/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/CentOS-8/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Debian/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/libetherspacelink_v35_21.dylib +0 -0
- egse/lib/Linux/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Linux/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/gssw/python3-gssw_2.2.3+31f63c9f-1_all.deb +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38 2.pyc +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38.pyc +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libbindy.dylib +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libxiwrapper.dylib +0 -0
- egse/lib/ximc/libximc.framework/Headers/ximc.h +0 -5510
- egse/lib/ximc/libximc.framework/Resources/Info.plist +0 -42
- egse/lib/ximc/libximc.framework/Resources/keyfile.sqlite +0 -0
- egse/lib/ximc/libximc.framework/libbindy.so +0 -0
- egse/lib/ximc/libximc.framework/libximc +0 -0
- egse/lib/ximc/libximc.framework/libximc.so +0 -0
- egse/lib/ximc/libximc.framework/libximc.so.7.0.0 +0 -0
- egse/lib/ximc/libximc.framework/libxiwrapper.so +0 -0
- egse/lib/ximc/pyximc.py +0 -922
- egse/listener.py +0 -179
- egse/logger/__init__.py +0 -243
- egse/logger/log_cs.py +0 -321
- egse/metrics.py +0 -102
- egse/mixin.py +0 -464
- egse/monitoring.py +0 -95
- egse/ni/alarms/__init__.py +0 -26
- egse/ni/alarms/cdaq9375.py +0 -300
- egse/ni/alarms/cdaq9375.yaml +0 -89
- egse/ni/alarms/cdaq9375_cs.py +0 -130
- egse/ni/alarms/cdaq9375_devif.py +0 -183
- egse/ni/alarms/cdaq9375_protocol.py +0 -48
- egse/obs_inspection.py +0 -165
- egse/observer.py +0 -41
- egse/obsid.py +0 -163
- egse/powermeter/__init__.py +0 -0
- egse/powermeter/ni/__init__.py +0 -38
- egse/powermeter/ni/cdaq9184.py +0 -224
- egse/powermeter/ni/cdaq9184.yaml +0 -73
- egse/powermeter/ni/cdaq9184_cs.py +0 -130
- egse/powermeter/ni/cdaq9184_devif.py +0 -201
- egse/powermeter/ni/cdaq9184_protocol.py +0 -48
- egse/powermeter/ni/cdaq9184_ui.py +0 -544
- egse/powermeter/thorlabs/__init__.py +0 -25
- egse/powermeter/thorlabs/pm100a.py +0 -380
- egse/powermeter/thorlabs/pm100a.yaml +0 -132
- egse/powermeter/thorlabs/pm100a_cs.py +0 -136
- egse/powermeter/thorlabs/pm100a_devif.py +0 -127
- egse/powermeter/thorlabs/pm100a_protocol.py +0 -80
- egse/powermeter/thorlabs/pm100a_ui.py +0 -725
- egse/process.py +0 -451
- egse/procman/__init__.py +0 -834
- egse/procman/cannot_start_process_popup.py +0 -43
- egse/procman/procman.yaml +0 -49
- egse/procman/procman_cs.py +0 -201
- egse/procman/procman_ui.py +0 -2081
- egse/protocol.py +0 -605
- egse/proxy.py +0 -531
- egse/randomwalk.py +0 -140
- egse/reg.py +0 -585
- egse/reload.py +0 -122
- egse/reprocess.py +0 -693
- egse/resource.py +0 -333
- egse/rmap.py +0 -406
- egse/rst.py +0 -135
- egse/search.py +0 -182
- egse/serialdevice.py +0 -190
- egse/services.py +0 -247
- egse/services.yaml +0 -68
- egse/settings.py +0 -379
- egse/settings.yaml +0 -980
- egse/setup.py +0 -1181
- egse/shutter/__init__.py +0 -0
- egse/shutter/thorlabs/__init__.py +0 -19
- egse/shutter/thorlabs/ksc101.py +0 -205
- egse/shutter/thorlabs/ksc101.yaml +0 -105
- egse/shutter/thorlabs/ksc101_cs.py +0 -136
- egse/shutter/thorlabs/ksc101_devif.py +0 -201
- egse/shutter/thorlabs/ksc101_protocol.py +0 -71
- egse/shutter/thorlabs/ksc101_ui.py +0 -548
- egse/shutter/thorlabs/sc10.py +0 -82
- egse/shutter/thorlabs/sc10.yaml +0 -52
- egse/shutter/thorlabs/sc10_controller.py +0 -81
- egse/shutter/thorlabs/sc10_cs.py +0 -108
- egse/shutter/thorlabs/sc10_interface.py +0 -25
- egse/shutter/thorlabs/sc10_simulator.py +0 -30
- egse/simulator.py +0 -41
- egse/slack.py +0 -61
- egse/socketdevice.py +0 -218
- egse/sockets.py +0 -218
- egse/spw.py +0 -1401
- egse/stages/__init__.py +0 -12
- egse/stages/aerotech/ensemble.py +0 -245
- egse/stages/aerotech/ensemble.yaml +0 -205
- egse/stages/aerotech/ensemble_controller.py +0 -275
- egse/stages/aerotech/ensemble_cs.py +0 -110
- egse/stages/aerotech/ensemble_interface.py +0 -132
- egse/stages/aerotech/ensemble_parameters.py +0 -433
- egse/stages/aerotech/ensemble_simulator.py +0 -27
- egse/stages/aerotech/mgse_sim.py +0 -188
- egse/stages/arun/smd3.py +0 -110
- egse/stages/arun/smd3.yaml +0 -68
- egse/stages/arun/smd3_controller.py +0 -470
- egse/stages/arun/smd3_cs.py +0 -112
- egse/stages/arun/smd3_interface.py +0 -53
- egse/stages/arun/smd3_simulator.py +0 -27
- egse/stages/arun/smd3_stop.py +0 -16
- egse/stages/huber/__init__.py +0 -49
- egse/stages/huber/smc9300.py +0 -920
- egse/stages/huber/smc9300.yaml +0 -63
- egse/stages/huber/smc9300_cs.py +0 -178
- egse/stages/huber/smc9300_devif.py +0 -345
- egse/stages/huber/smc9300_protocol.py +0 -113
- egse/stages/huber/smc9300_sim.py +0 -547
- egse/stages/huber/smc9300_ui.py +0 -973
- egse/state.py +0 -173
- egse/statemachine.py +0 -274
- egse/storage/__init__.py +0 -1067
- egse/storage/persistence.py +0 -2295
- egse/storage/storage.yaml +0 -79
- egse/storage/storage_cs.py +0 -231
- egse/styles/dark.qss +0 -343
- egse/styles/default.qss +0 -48
- egse/synoptics/__init__.py +0 -417
- egse/synoptics/syn.yaml +0 -9
- egse/synoptics/syn_cs.py +0 -195
- egse/system.py +0 -1611
- egse/tcs/__init__.py +0 -14
- egse/tcs/tcs.py +0 -879
- egse/tcs/tcs.yaml +0 -14
- egse/tcs/tcs_cs.py +0 -202
- egse/tcs/tcs_devif.py +0 -292
- egse/tcs/tcs_protocol.py +0 -180
- egse/tcs/tcs_sim.py +0 -177
- egse/tcs/tcs_ui.py +0 -543
- egse/tdms.py +0 -171
- egse/tempcontrol/__init__.py +0 -23
- egse/tempcontrol/agilent/agilent34970.py +0 -109
- egse/tempcontrol/agilent/agilent34970.yaml +0 -44
- egse/tempcontrol/agilent/agilent34970_cs.py +0 -114
- egse/tempcontrol/agilent/agilent34970_devif.py +0 -182
- egse/tempcontrol/agilent/agilent34970_protocol.py +0 -96
- egse/tempcontrol/agilent/agilent34972.py +0 -111
- egse/tempcontrol/agilent/agilent34972.yaml +0 -44
- egse/tempcontrol/agilent/agilent34972_cs.py +0 -115
- egse/tempcontrol/agilent/agilent34972_devif.py +0 -189
- egse/tempcontrol/agilent/agilent34972_protocol.py +0 -98
- egse/tempcontrol/beaglebone/beaglebone.py +0 -341
- egse/tempcontrol/beaglebone/beaglebone.yaml +0 -110
- egse/tempcontrol/beaglebone/beaglebone_cs.py +0 -117
- egse/tempcontrol/beaglebone/beaglebone_protocol.py +0 -134
- egse/tempcontrol/beaglebone/beaglebone_ui.py +0 -674
- egse/tempcontrol/digalox/digalox.py +0 -115
- egse/tempcontrol/digalox/digalox.yaml +0 -36
- egse/tempcontrol/digalox/digalox_cs.py +0 -108
- egse/tempcontrol/digalox/digalox_protocol.py +0 -56
- egse/tempcontrol/keithley/__init__.py +0 -33
- egse/tempcontrol/keithley/daq6510.py +0 -662
- egse/tempcontrol/keithley/daq6510.yaml +0 -105
- egse/tempcontrol/keithley/daq6510_cs.py +0 -163
- egse/tempcontrol/keithley/daq6510_devif.py +0 -343
- egse/tempcontrol/keithley/daq6510_protocol.py +0 -79
- egse/tempcontrol/keithley/daq6510_sim.py +0 -186
- egse/tempcontrol/lakeshore/__init__.py +0 -33
- egse/tempcontrol/lakeshore/lsci.py +0 -361
- egse/tempcontrol/lakeshore/lsci.yaml +0 -162
- egse/tempcontrol/lakeshore/lsci_cs.py +0 -174
- egse/tempcontrol/lakeshore/lsci_devif.py +0 -292
- egse/tempcontrol/lakeshore/lsci_protocol.py +0 -76
- egse/tempcontrol/lakeshore/lsci_ui.py +0 -387
- egse/tempcontrol/ni/__init__.py +0 -0
- egse/tempcontrol/spid/spid.py +0 -109
- egse/tempcontrol/spid/spid.yaml +0 -81
- egse/tempcontrol/spid/spid_controller.py +0 -279
- egse/tempcontrol/spid/spid_cs.py +0 -136
- egse/tempcontrol/spid/spid_protocol.py +0 -107
- egse/tempcontrol/spid/spid_ui.py +0 -723
- egse/tempcontrol/srs/__init__.py +0 -22
- egse/tempcontrol/srs/ptc10.py +0 -867
- egse/tempcontrol/srs/ptc10.yaml +0 -227
- egse/tempcontrol/srs/ptc10_cs.py +0 -128
- egse/tempcontrol/srs/ptc10_devif.py +0 -116
- egse/tempcontrol/srs/ptc10_protocol.py +0 -39
- egse/tempcontrol/srs/ptc10_ui.py +0 -906
- egse/ups/apc/apc.py +0 -236
- egse/ups/apc/apc.yaml +0 -45
- egse/ups/apc/apc_cs.py +0 -101
- egse/ups/apc/apc_protocol.py +0 -125
- egse/user.yaml +0 -7
- egse/vacuum/beaglebone/beaglebone.py +0 -149
- egse/vacuum/beaglebone/beaglebone.yaml +0 -44
- egse/vacuum/beaglebone/beaglebone_cs.py +0 -108
- egse/vacuum/beaglebone/beaglebone_devif.py +0 -159
- egse/vacuum/beaglebone/beaglebone_protocol.py +0 -192
- egse/vacuum/beaglebone/beaglebone_ui.py +0 -638
- egse/vacuum/instrutech/igm402.py +0 -91
- egse/vacuum/instrutech/igm402.yaml +0 -90
- egse/vacuum/instrutech/igm402_controller.py +0 -124
- egse/vacuum/instrutech/igm402_cs.py +0 -108
- egse/vacuum/instrutech/igm402_interface.py +0 -49
- egse/vacuum/instrutech/igm402_simulator.py +0 -36
- egse/vacuum/keller/kellerBus.py +0 -256
- egse/vacuum/keller/leo3.py +0 -100
- egse/vacuum/keller/leo3.yaml +0 -38
- egse/vacuum/keller/leo3_controller.py +0 -81
- egse/vacuum/keller/leo3_cs.py +0 -101
- egse/vacuum/keller/leo3_interface.py +0 -33
- egse/vacuum/mks/evision.py +0 -86
- egse/vacuum/mks/evision.yaml +0 -75
- egse/vacuum/mks/evision_cs.py +0 -101
- egse/vacuum/mks/evision_devif.py +0 -313
- egse/vacuum/mks/evision_interface.py +0 -60
- egse/vacuum/mks/evision_simulator.py +0 -24
- egse/vacuum/mks/evision_ui.py +0 -701
- egse/vacuum/pfeiffer/acp40.py +0 -87
- egse/vacuum/pfeiffer/acp40.yaml +0 -60
- egse/vacuum/pfeiffer/acp40_controller.py +0 -117
- egse/vacuum/pfeiffer/acp40_cs.py +0 -109
- egse/vacuum/pfeiffer/acp40_interface.py +0 -40
- egse/vacuum/pfeiffer/acp40_simulator.py +0 -37
- egse/vacuum/pfeiffer/tc400.py +0 -87
- egse/vacuum/pfeiffer/tc400.yaml +0 -83
- egse/vacuum/pfeiffer/tc400_controller.py +0 -136
- egse/vacuum/pfeiffer/tc400_cs.py +0 -109
- egse/vacuum/pfeiffer/tc400_interface.py +0 -70
- egse/vacuum/pfeiffer/tc400_simulator.py +0 -35
- egse/vacuum/pfeiffer/tpg261.py +0 -80
- egse/vacuum/pfeiffer/tpg261.yaml +0 -66
- egse/vacuum/pfeiffer/tpg261_controller.py +0 -150
- egse/vacuum/pfeiffer/tpg261_cs.py +0 -109
- egse/vacuum/pfeiffer/tpg261_interface.py +0 -59
- egse/vacuum/pfeiffer/tpg261_simulator.py +0 -23
- egse/version.py +0 -174
- egse/visitedpositions.py +0 -398
- egse/windowing.py +0 -213
- egse/zmq/__init__.py +0 -28
- egse/zmq/spw.py +0 -160
- egse/zmq_ser.py +0 -41
- scripts/alerts/cold.yaml +0 -278
- scripts/alerts/example_alerts.yaml +0 -54
- scripts/alerts/transition.yaml +0 -14
- scripts/alerts/warm.yaml +0 -49
- scripts/analyse_n_fee_hk_data.py +0 -52
- scripts/check_hdf5_files.py +0 -192
- scripts/check_register_sync.py +0 -47
- scripts/check_tcs_calib_coef.py +0 -90
- scripts/correct_ccd_cold_temperature_cal.py +0 -157
- scripts/create_hdf5_report.py +0 -293
- scripts/csl_model.py +0 -420
- scripts/csl_restore_setup.py +0 -229
- scripts/export-grafana-dashboards.py +0 -49
- scripts/fdir/cs_recovery/fdir_cs_recovery.py +0 -54
- scripts/fdir/fdir_table.yaml +0 -70
- scripts/fdir/fdir_test_recovery.py +0 -10
- scripts/fdir/hw_recovery/fdir_agilent_hw_recovery.py +0 -73
- scripts/fdir/limit_recovery/fdir_agilent_limit.py +0 -61
- scripts/fdir/limit_recovery/fdir_bb_heater_limit.py +0 -59
- scripts/fdir/limit_recovery/fdir_ensemble_limit.py +0 -33
- scripts/fdir/limit_recovery/fdir_pressure_limit_recovery.py +0 -71
- scripts/fix_csv.py +0 -80
- scripts/ias/correct_ccd_temp_cal_elfique.py +0 -43
- scripts/ias/correct_ccd_temp_cal_floreffe.py +0 -43
- scripts/ias/correct_trp_swap_achel.py +0 -199
- scripts/inta/correct_ccd_temp_cal_duvel.py +0 -43
- scripts/inta/correct_ccd_temp_cal_gueuze.py +0 -43
- scripts/n_fee_supply_voltage_calculation.py +0 -92
- scripts/playground.py +0 -30
- scripts/print_hdf5_hk_data.py +0 -68
- scripts/print_register_map.py +0 -43
- scripts/remove_lines_between_matches.py +0 -188
- scripts/sron/commanding/control_heaters.py +0 -44
- scripts/sron/commanding/pumpdown.py +0 -46
- scripts/sron/commanding/set_pid_setpoint.py +0 -19
- scripts/sron/commanding/shutdown_bbb_heaters.py +0 -10
- scripts/sron/commanding/shutdown_pumps.py +0 -33
- scripts/sron/correct_mgse_coordinates_brigand_chimay.py +0 -272
- scripts/sron/correct_trp_swap_brigand.py +0 -204
- scripts/sron/gimbal_conversions.py +0 -75
- scripts/sron/tm_gen/tm_gen_agilent.py +0 -37
- scripts/sron/tm_gen/tm_gen_heaters.py +0 -4
- scripts/sron/tm_gen/tm_gen_spid.py +0 -13
- scripts/update_operational_cgse.py +0 -268
- scripts/update_operational_cgse_old.py +0 -273
egse/fee/feesim.py
DELETED
|
@@ -1,914 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
The FEE Simulator application. This app provides basic FEE functionality and is used mainly to
|
|
3
|
-
test the DPU Processor. The communication between the FEE Simulator and the DPU Processor is
|
|
4
|
-
abstracted by a SpaceWireInterface which currently has two implementations:
|
|
5
|
-
|
|
6
|
-
1. a SpaceWireOverDSI, i.e. the 4Links Diagnostic SpaceWire Interface (DSI) or the
|
|
7
|
-
EtherSpaceLink (ESL) device running over SpaceWire and TCP/IP, or
|
|
8
|
-
2. a SpaceWireOverZeroMQ, i.e. all communication runs over ZeroMQ.
|
|
9
|
-
|
|
10
|
-
The FEE Simulator can be started as follows:
|
|
11
|
-
|
|
12
|
-
$ feesim start --dsi-address <IP address of the DSI> --dsi-port <the SpW port on the DSI>
|
|
13
|
-
$ feesim start --zeromq
|
|
14
|
-
|
|
15
|
-
The FEE Simulator can also be started to run over an ssh tunnel:
|
|
16
|
-
|
|
17
|
-
$ feesim start --tunnel -ssh-user <name>
|
|
18
|
-
|
|
19
|
-
When connecting over a tunnel, the SSH passphrase is requested.
|
|
20
|
-
"""
|
|
21
|
-
import getpass
|
|
22
|
-
import logging
|
|
23
|
-
import multiprocessing
|
|
24
|
-
import random
|
|
25
|
-
import sys
|
|
26
|
-
import time
|
|
27
|
-
from typing import List
|
|
28
|
-
from typing import NamedTuple
|
|
29
|
-
|
|
30
|
-
import click
|
|
31
|
-
import numpy as np
|
|
32
|
-
import sshtunnel
|
|
33
|
-
|
|
34
|
-
from egse.dsi.spw import SpaceWireOverDSI
|
|
35
|
-
from egse.fee import convert_ccd_order_value
|
|
36
|
-
from egse.fee import n_fee_mode
|
|
37
|
-
from egse.fee.n_fee_hk import ORIGIN
|
|
38
|
-
from egse.fee.nfee import HousekeepingData
|
|
39
|
-
from egse.hk import TmDictionaryColumns
|
|
40
|
-
from egse.randomwalk import RandomWalk
|
|
41
|
-
from egse.reg import RegisterMap
|
|
42
|
-
from egse.rmap import create_rmap_read_request_reply_packet
|
|
43
|
-
from egse.rmap import create_rmap_write_request_reply_packet
|
|
44
|
-
from egse.settings import Settings
|
|
45
|
-
from egse.setup import Setup
|
|
46
|
-
from egse.setup import SetupError
|
|
47
|
-
from egse.setup import load_setup
|
|
48
|
-
from egse.spw import DataPacketHeader
|
|
49
|
-
from egse.spw import DataPacketType
|
|
50
|
-
from egse.spw import PacketType
|
|
51
|
-
from egse.spw import ReadRequest
|
|
52
|
-
from egse.spw import SpaceWireInterface
|
|
53
|
-
from egse.spw import SpaceWirePacket
|
|
54
|
-
from egse.spw import WriteRequest
|
|
55
|
-
from egse.system import SignalCatcher
|
|
56
|
-
from egse.zmq.spw import SpaceWireOverZeroMQ
|
|
57
|
-
|
|
58
|
-
logging.basicConfig(level=logging.DEBUG, format=Settings.LOG_FORMAT_FULL)
|
|
59
|
-
|
|
60
|
-
LOGGER = logging.getLogger("egse.fee.feesim")
|
|
61
|
-
|
|
62
|
-
fee_settings = Settings.load("FEE")
|
|
63
|
-
dsi_settings = Settings.load("DSI")
|
|
64
|
-
site_settings = Settings.load("SITE")
|
|
65
|
-
dpu_settings = Settings.load("DPU Processor")
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# Define the possible states
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class States(NamedTuple):
|
|
72
|
-
ST_OFF: int
|
|
73
|
-
ST_ON: int
|
|
74
|
-
ST_FULL_IMAGE_PATTERN: int
|
|
75
|
-
ST_WINDOWING_PATTERN: int
|
|
76
|
-
ST_STANDBY: int
|
|
77
|
-
ST_FULL_IMAGE: int
|
|
78
|
-
ST_WINDOWING: int
|
|
79
|
-
ST_PERFORMANCE_TEST: int
|
|
80
|
-
ST_PARALLEL_TRAP_PUMPING_1: int
|
|
81
|
-
ST_PARALLEL_TRAP_PUMPING_2: int
|
|
82
|
-
ST_SERIAL_TRAP_PUMPING_1: int
|
|
83
|
-
ST_SERIAL_TRAP_PUMPING_2: int
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
states = States(
|
|
87
|
-
ST_OFF=-1,
|
|
88
|
-
ST_ON=0,
|
|
89
|
-
ST_FULL_IMAGE_PATTERN=1,
|
|
90
|
-
ST_WINDOWING_PATTERN=2,
|
|
91
|
-
ST_STANDBY=4,
|
|
92
|
-
ST_FULL_IMAGE=5,
|
|
93
|
-
ST_WINDOWING=6,
|
|
94
|
-
ST_PERFORMANCE_TEST=7,
|
|
95
|
-
ST_PARALLEL_TRAP_PUMPING_1=9,
|
|
96
|
-
ST_PARALLEL_TRAP_PUMPING_2=10,
|
|
97
|
-
ST_SERIAL_TRAP_PUMPING_1=11,
|
|
98
|
-
ST_SERIAL_TRAP_PUMPING_2=12,
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# Set the initial state
|
|
102
|
-
|
|
103
|
-
current_state: int = states.ST_OFF
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
# Define the transitions
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def goto_on_mode(state):
|
|
110
|
-
# N-FEE in ON-mode
|
|
111
|
-
# * Power of the CCDs is disabled
|
|
112
|
-
# * Power of subsystems is disabled
|
|
113
|
-
# * N-FEE is ready for receiving RMAP command
|
|
114
|
-
return states.ST_ON
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def goto_standby_mode(state):
|
|
118
|
-
# N-FEE in STANDBY-mode
|
|
119
|
-
# * CCDs and subsystems are powered
|
|
120
|
-
# * CCD timing signals are disabled
|
|
121
|
-
# * no image data shall be transferred
|
|
122
|
-
return states.ST_STANDBY
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def goto_windowing_mode(state):
|
|
126
|
-
# N-FEE in WINDOWING-mode
|
|
127
|
-
# * The full CCDs are readout
|
|
128
|
-
# * Only regions of interest (windows) are transmitted
|
|
129
|
-
# * Configuration:
|
|
130
|
-
# * This configuration needs to be set via RMAP before changing from STANDBY to WINDOWING mode
|
|
131
|
-
# * Set first and last row to read-out
|
|
132
|
-
# * Set serial transfers size (column size)
|
|
133
|
-
# * Set number of overscan lines.
|
|
134
|
-
# * Enable or disable charge injection
|
|
135
|
-
# * Set first and last line for charge injection - Set width and gap for charge injection.
|
|
136
|
-
# * Enable or disable warm-up (= disable data transfer) - Set data-packet size
|
|
137
|
-
# * Set CCD read-out order (all CCDs)
|
|
138
|
-
# * Set CCD side E or F- Upload the window-lists
|
|
139
|
-
# * Set the window-lists pointers
|
|
140
|
-
# * Set the window-list lengths
|
|
141
|
-
# * Set the window size
|
|
142
|
-
# * Set the copy-order list (including list-length for side E and F) -
|
|
143
|
-
# Set dump-gate high or low
|
|
144
|
-
return states.ST_WINDOWING
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
# Define all legal transitions
|
|
148
|
-
|
|
149
|
-
state_transitions = {
|
|
150
|
-
(states.ST_OFF, "goto_on"): goto_on_mode,
|
|
151
|
-
(states.ST_ON, "goto_standby"): goto_standby_mode,
|
|
152
|
-
(states.ST_WINDOWING, "goto_standby"): goto_standby_mode,
|
|
153
|
-
(states.ST_STANDBY, "goto_windowing"): goto_windowing_mode,
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
class NFEEInternals:
|
|
158
|
-
"""
|
|
159
|
-
The N-FEE Internals class represents the actual state of the N-FEE. A bit like the FPGA status
|
|
160
|
-
in the N-FEE hardware. The difference with the RegisterMap is that the register map is updated
|
|
161
|
-
on RMAP write requests, while this class is updated on sync pulses (from the content of the
|
|
162
|
-
register map). Therefore, the N-FEE Internals represent the actual state, while the register
|
|
163
|
-
map represents the commanded state.
|
|
164
|
-
"""
|
|
165
|
-
def __init__(self, reg_map: RegisterMap):
|
|
166
|
-
self.reg_map = reg_map
|
|
167
|
-
self.ccd_mode_config = self.reg_map["ccd_mode_config"]
|
|
168
|
-
self.sensor_sel = self.reg_map["sensor_sel"]
|
|
169
|
-
self.ccd_read_en = self.reg_map["ccd_read_en"]
|
|
170
|
-
self.v_start = self.reg_map["v_start"]
|
|
171
|
-
self.v_end = self.reg_map["v_end"]
|
|
172
|
-
self.digitise_en = self.reg_map["digitise_en"]
|
|
173
|
-
self.sync_sel = self.reg_map["sync_sel"]
|
|
174
|
-
self.int_sync_period = self.reg_map["int_sync_period"]
|
|
175
|
-
self.ccd_readout_order = self.reg_map["ccd_readout_order"]
|
|
176
|
-
LOGGER.info(f"Initialised {self.v_start=}, {self.v_end=}")
|
|
177
|
-
|
|
178
|
-
def update(self, pulse_type: int):
|
|
179
|
-
"""
|
|
180
|
-
Update the internal state from the register. Depending on the pulse_type, specific state
|
|
181
|
-
variables are updated from the current register map values.
|
|
182
|
-
|
|
183
|
-
Args:
|
|
184
|
-
pulse_type (int): a 200 or 400 ms pulse
|
|
185
|
-
"""
|
|
186
|
-
if pulse_type == 200:
|
|
187
|
-
self.sensor_sel = self.reg_map["sensor_sel"]
|
|
188
|
-
self.ccd_read_en = self.reg_map['ccd_read_en']
|
|
189
|
-
if pulse_type == 400:
|
|
190
|
-
self.sensor_sel = self.reg_map["sensor_sel"]
|
|
191
|
-
self.ccd_read_en = self.reg_map['ccd_read_en']
|
|
192
|
-
self.ccd_mode_config = self.reg_map["ccd_mode_config"]
|
|
193
|
-
self.v_start = self.reg_map["v_start"]
|
|
194
|
-
self.v_end = self.reg_map["v_end"]
|
|
195
|
-
self.digitise_en = self.reg_map["digitise_en"]
|
|
196
|
-
self.sync_sel = self.reg_map["sync_sel"]
|
|
197
|
-
self.int_sync_period = self.reg_map["int_sync_period"]
|
|
198
|
-
self.ccd_readout_order = self.reg_map["ccd_readout_order"]
|
|
199
|
-
LOGGER.info(f"Updated {self.v_start=}, {self.v_end=}, {self.ccd_mode_config=}")
|
|
200
|
-
|
|
201
|
-
def get_sync_period(self) -> float:
|
|
202
|
-
"""
|
|
203
|
-
Calculate and return the period between two successive sync pulses.
|
|
204
|
-
|
|
205
|
-
Note:
|
|
206
|
-
Please note that this value is calculated from what is known in the register map. The
|
|
207
|
-
external sync period is however dependent from the sync signal received from the AEU,
|
|
208
|
-
and the AEU might have been configured for extended sync periods.
|
|
209
|
-
|
|
210
|
-
Returns:
|
|
211
|
-
The sync period (time between two sync pulses) in seconds.
|
|
212
|
-
"""
|
|
213
|
-
sync_sel = self.sync_sel
|
|
214
|
-
if sync_sel:
|
|
215
|
-
sync_period = self.int_sync_period + 400 # add the duration of the long pulse
|
|
216
|
-
else:
|
|
217
|
-
sync_period = 6250
|
|
218
|
-
return sync_period / 1000
|
|
219
|
-
|
|
220
|
-
def get_readout_order(self) -> List:
|
|
221
|
-
"""Returns the ccd readout order as a list of CCD numbers, e.g. [1, 2, 3, 4]."""
|
|
222
|
-
return convert_ccd_order_value(self.ccd_readout_order)
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
temperature_walks = {
|
|
226
|
-
"TOU_SENSE_1": RandomWalk(boundary=(0, 0x7FFF)),
|
|
227
|
-
"TOU_SENSE_2": RandomWalk(boundary=(0, 0x7FFF)),
|
|
228
|
-
"TOU_SENSE_3": RandomWalk(boundary=(0, 0x7FFF)),
|
|
229
|
-
"TOU_SENSE_4": RandomWalk(boundary=(0, 0x7FFF)),
|
|
230
|
-
"TOU_SENSE_5": RandomWalk(boundary=(0, 0x7FFF)),
|
|
231
|
-
"TOU_SENSE_6": RandomWalk(boundary=(0, 0x7FFF)),
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def create_pattern_data(timecode: int, ccd_id: int, ccd_side: int) -> np.ndarray:
|
|
236
|
-
"""
|
|
237
|
-
Create pattern data as a two-dimensional ND array. The pattern data is generated as described
|
|
238
|
-
in PLATO-LESIA-PL-TN-023 - SimuCam pattern requirement.
|
|
239
|
-
|
|
240
|
-
The pattern is build up like this: each pixel is a 16-bit number with the following structure:
|
|
241
|
-
|
|
242
|
-
* Bits [15:13] = time-code % 8
|
|
243
|
-
* Bits [12:11] = CCD number [1, 2, 3, 4] should be [0-3]!
|
|
244
|
-
* Bit [10] = CCD side: 0 = left side, 1 = right side
|
|
245
|
-
* Bits [9:5] = Y-coordinate % 32
|
|
246
|
-
* Bits [4:0] = X-coordinate % 32
|
|
247
|
-
|
|
248
|
-
The total image data size of a full frame CCD is:
|
|
249
|
-
|
|
250
|
-
x = 4590 = 2 x (25 [serial prescan] + 2255 + 15 [serial overscan])
|
|
251
|
-
y = 4540 = 4510 + 30 [parallel overscan]
|
|
252
|
-
|
|
253
|
-
This function creates each side of the CCD separately, so each half can be treated individually
|
|
254
|
-
as is done in the N-FEE. The two sides can easily be concatenated to form the full image:
|
|
255
|
-
|
|
256
|
-
data = np.concatenate((data_left, data_right), axis=1)
|
|
257
|
-
|
|
258
|
-
Args:
|
|
259
|
-
timecode (int): the timecode for this readout
|
|
260
|
-
ccd_id (int): the CCD number [0-3]
|
|
261
|
-
ccd_side (int): the CCD side, 0 = left = E-side, 1 = right = F-side
|
|
262
|
-
Returns:
|
|
263
|
-
A two-dimensional ND array representing half of a CCD.
|
|
264
|
-
"""
|
|
265
|
-
|
|
266
|
-
ccd_number = ccd_id # save for later use
|
|
267
|
-
|
|
268
|
-
timecode = (timecode % 8) << 13 # timecode is 3 bits at [15:13]
|
|
269
|
-
ccd_id = (ccd_id & 0b0011) << 11 # ccd_id is 2 bits at [12:11]
|
|
270
|
-
ccd_side = (ccd_side & 0b0001) << 10 # ccd_side is 1 bit at [10]
|
|
271
|
-
|
|
272
|
-
x_size = 25 + 2255 + 15
|
|
273
|
-
y_size = 4510 + 30
|
|
274
|
-
|
|
275
|
-
rows, cols = np.indices((y_size, x_size), dtype=np.uint16)
|
|
276
|
-
cols %= 32
|
|
277
|
-
rows %= 32
|
|
278
|
-
|
|
279
|
-
data = rows * 16 + cols + timecode + ccd_side + ccd_id
|
|
280
|
-
|
|
281
|
-
# We leave set the msb because of the bit flipt for N-FEE EM
|
|
282
|
-
|
|
283
|
-
data[50:300, 100:105] = ccd_number | 0b10000000_00000000
|
|
284
|
-
data[100:105, 50:500] = ccd_number | 0b10000000_00000000
|
|
285
|
-
data[300:305, 50:150] = ccd_number | 0b10000000_00000000
|
|
286
|
-
data[50:150, 500:505] = ccd_number | 0b10000000_00000000
|
|
287
|
-
|
|
288
|
-
# We unset the msb because of the bit flip for N-FEE EM
|
|
289
|
-
|
|
290
|
-
data[110, 110] = 0x7FFF
|
|
291
|
-
|
|
292
|
-
return data
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
def initialise_hk_data(hk_data: HousekeepingData) -> HousekeepingData:
|
|
296
|
-
"""Initialises the housekeeping data to fake or simulated values."""
|
|
297
|
-
|
|
298
|
-
try:
|
|
299
|
-
setup = load_setup()
|
|
300
|
-
hk_info_table = setup.telemetry.dictionary
|
|
301
|
-
except AttributeError as exc:
|
|
302
|
-
raise SetupError("Version of the telemetry dictionary not specified in the current setup.") from exc
|
|
303
|
-
|
|
304
|
-
storage_mnemonic_col = hk_info_table[TmDictionaryColumns.STORAGE_MNEMONIC].values
|
|
305
|
-
original_name_col = hk_info_table[TmDictionaryColumns.ORIGINAL_EGSE_HK_NAMES].values
|
|
306
|
-
selection = np.where(storage_mnemonic_col == ORIGIN)
|
|
307
|
-
original_names = original_name_col[selection]
|
|
308
|
-
|
|
309
|
-
for name in temperature_walks:
|
|
310
|
-
hk_data[name] = int(next(temperature_walks[name]))
|
|
311
|
-
|
|
312
|
-
hk_data["CCD1_TS"] = 0x7FFF
|
|
313
|
-
hk_data["CCD2_TS"] = 0x7FFF
|
|
314
|
-
hk_data["CCD3_TS"] = 0x7FFF
|
|
315
|
-
hk_data["CCD4_TS"] = 0x7FFF
|
|
316
|
-
|
|
317
|
-
hk_data["PRT1"] = 0x7FFF
|
|
318
|
-
hk_data["PRT2"] = 0x7FFF
|
|
319
|
-
hk_data["PRT3"] = 0x7FFF
|
|
320
|
-
hk_data["PRT4"] = 0x7FFF
|
|
321
|
-
hk_data["PRT5"] = 0x7FFF
|
|
322
|
-
|
|
323
|
-
hk_data["ZERO_DIFF_AMP"] = 0x8015
|
|
324
|
-
|
|
325
|
-
if "CCD1_VOD_MON" in original_names:
|
|
326
|
-
hk_data["CCD1_VOD_MON"] = 0x8055
|
|
327
|
-
else:
|
|
328
|
-
if "CCD1_VOD_MON_E" in original_names:
|
|
329
|
-
hk_data["CCD1_VOD_MON_E"] = 0x8055
|
|
330
|
-
if "CCD1_VOD_MON_F" in original_names:
|
|
331
|
-
hk_data["CCD1_VOD_MON_F"] = 0x8055
|
|
332
|
-
hk_data["CCD1_VOG_MON"] = 0x8056
|
|
333
|
-
hk_data["CCD1_VRD_MON_E"] = 0x8056
|
|
334
|
-
|
|
335
|
-
if "CCD2_VOD_MON" in original_names:
|
|
336
|
-
hk_data["CCD2_VOD_MON"] = 0x8057
|
|
337
|
-
else:
|
|
338
|
-
if "CCD2_VOD_MON_E" in original_names:
|
|
339
|
-
hk_data["CCD2_VOD_MON_E"] = 0x8057
|
|
340
|
-
if "CCD2_VOD_MON_F" in original_names:
|
|
341
|
-
hk_data["CCD2_VOD_MON_F"] = 0x8057
|
|
342
|
-
hk_data["CCD2_VOG_MON"] = 0x8058
|
|
343
|
-
hk_data["CCD2_VRD_MON_E"] = 0x8057
|
|
344
|
-
|
|
345
|
-
if "CCD3_VOD_MON" in original_names:
|
|
346
|
-
hk_data["CCD3_VOD_MON"] = 0x8058
|
|
347
|
-
else:
|
|
348
|
-
if "CCD3_VOD_MON_E" in original_names:
|
|
349
|
-
hk_data["CCD3_VOD_MON_E"] = 0x8058
|
|
350
|
-
if "CCD3_VOD_MON_F" in original_names:
|
|
351
|
-
hk_data["CCD3_VOD_MON_F"] = 0x8058
|
|
352
|
-
hk_data["CCD3_VOG_MON"] = 0x8058
|
|
353
|
-
hk_data["CCD3_VRD_MON_E"] = 0x8058
|
|
354
|
-
|
|
355
|
-
if "CCD4_VOD_MON" in original_names:
|
|
356
|
-
hk_data["CCD4_VOD_MON"] = 0x8057
|
|
357
|
-
else:
|
|
358
|
-
if "CCD4_VOD_MON_E" in original_names:
|
|
359
|
-
hk_data["CCD4_VOD_MON_E"] = 0x8057
|
|
360
|
-
if "CCD4_VOD_MON_F" in original_names:
|
|
361
|
-
hk_data["CCD4_VOD_MON_F"] = 0x8057
|
|
362
|
-
hk_data["CCD4_VOG_MON"] = 0x8058
|
|
363
|
-
hk_data["CCD4_VRD_MON_E"] = 0x8058
|
|
364
|
-
|
|
365
|
-
hk_data["VCCD"] = 0x39BF
|
|
366
|
-
hk_data["VRCLK_MON"] = 0xFC8A
|
|
367
|
-
hk_data["VICLK"] = 0xFAE9
|
|
368
|
-
if "VRCLK_LOW" in original_names:
|
|
369
|
-
hk_data["VRCLK_LOW"] = 0x821A
|
|
370
|
-
|
|
371
|
-
if "5VB_POS_MON" in original_names:
|
|
372
|
-
hk_data["5VB_POS_MON"] = 0x1E6A
|
|
373
|
-
hk_data["5VB_NEG_MON"] = 0x1A9F
|
|
374
|
-
hk_data["3V3B_MON"] = 0xE75D
|
|
375
|
-
hk_data["2V5A_MON"] = 0x1979
|
|
376
|
-
hk_data["3V3D_MON"] = 0xE76E
|
|
377
|
-
hk_data["2V5D_MON"] = 0x1A8C
|
|
378
|
-
hk_data["1V5D_MON"] = 0xDF35
|
|
379
|
-
hk_data["5VREF_MON"] = 0x1A80
|
|
380
|
-
|
|
381
|
-
hk_data["VCCD_POS_RAW"] = 0x53BF
|
|
382
|
-
hk_data["VCLK_POS_RAW"] = 0x40BA
|
|
383
|
-
hk_data["VAN1_POS_RAW"] = 0x0744
|
|
384
|
-
hk_data["VAN3_NEG_MON"] = 0xFB7C
|
|
385
|
-
hk_data["VAN2_POS_RAW"] = 0x3AEC
|
|
386
|
-
hk_data["VDIG_RAW"] = 0x0AB5
|
|
387
|
-
if "5VB_POS_MON" in original_names:
|
|
388
|
-
hk_data["VDIG_RAW_2"] = 0x0A32
|
|
389
|
-
if "VICLK_LOW" in original_names:
|
|
390
|
-
hk_data["VICLK_LOW"] = 0x8277
|
|
391
|
-
|
|
392
|
-
hk_data["CCD1_VRD_MON_F"] = 0x8059
|
|
393
|
-
hk_data["CCD1_VDD_MON"] = 0x94CA
|
|
394
|
-
hk_data["CCD1_VGD_MON"] = 0x8056
|
|
395
|
-
hk_data["CCD2_VRD_MON_F"] = 0x8058
|
|
396
|
-
hk_data["CCD2_VDD_MON"] = 0x94C1
|
|
397
|
-
hk_data["CCD2_VGD_MON"] = 0x8055
|
|
398
|
-
hk_data["CCD3_VRD_MON_F"] = 0x8059
|
|
399
|
-
hk_data["CCD3_VDD_MON"] = 0x94C1
|
|
400
|
-
hk_data["CCD3_VGD_MON"] = 0x8058
|
|
401
|
-
hk_data["CCD4_VRD_MON_F"] = 0x8058
|
|
402
|
-
hk_data["CCD4_VDD_MON"] = 0x94BA
|
|
403
|
-
hk_data["CCD4_VGD_MON"] = 0x8056
|
|
404
|
-
|
|
405
|
-
hk_data["IG_HI_MON"] = 0x8057
|
|
406
|
-
if "IG_LO_MON" in original_names:
|
|
407
|
-
hk_data["IG_LO_MON"] = 0x8059
|
|
408
|
-
hk_data["TSENSE_A"] = 0x8059
|
|
409
|
-
hk_data["TSENSE_B"] = 0x805A
|
|
410
|
-
|
|
411
|
-
hk_data["spw_timecode"] = 0x0000
|
|
412
|
-
hk_data["rmap_target_status"] = 0x0000
|
|
413
|
-
hk_data["rmap_target_indicate"] = 0x0000
|
|
414
|
-
hk_data["spw_link_escape_error"] = 0x0000
|
|
415
|
-
hk_data["spw_credit_error"] = 0x0000
|
|
416
|
-
hk_data["spw_parity_error"] = 0x0000
|
|
417
|
-
hk_data["spw_link_disconnect"] = 0x0000
|
|
418
|
-
hk_data["spw_link_running"] = 0x0001
|
|
419
|
-
|
|
420
|
-
hk_data["frame_counter"] = 0x0000
|
|
421
|
-
hk_data["op_mode"] = 0x0000
|
|
422
|
-
hk_data["frame_number"] = 0x0000
|
|
423
|
-
|
|
424
|
-
hk_data["error_flags"] = 0x0000
|
|
425
|
-
|
|
426
|
-
hk_data["FPGA minor version"] = 0x0018
|
|
427
|
-
hk_data["FPGA major version"] = 0x0000
|
|
428
|
-
hk_data["Board ID"] = 0x0000
|
|
429
|
-
|
|
430
|
-
return hk_data
|
|
431
|
-
|
|
432
|
-
class FEESimulator:
|
|
433
|
-
"""
|
|
434
|
-
A software simulator for the front-end electronics of the PLATO cameras.
|
|
435
|
-
"""
|
|
436
|
-
|
|
437
|
-
def __init__(self, transport: SpaceWireInterface):
|
|
438
|
-
"""
|
|
439
|
-
Args:
|
|
440
|
-
transport: the SpaceWire transport method, e.g. DSI or ZeroMQ.
|
|
441
|
-
"""
|
|
442
|
-
self._transport: SpaceWireInterface = transport
|
|
443
|
-
self.register_map = RegisterMap("N-FEE")
|
|
444
|
-
self._hk_data = HousekeepingData()
|
|
445
|
-
self._hk_header = DataPacketHeader()
|
|
446
|
-
|
|
447
|
-
self.setup = load_setup()
|
|
448
|
-
|
|
449
|
-
self._IN = NFEEInternals(self.register_map)
|
|
450
|
-
|
|
451
|
-
initialise_hk_data(self._hk_data)
|
|
452
|
-
self.initialise_hk_header()
|
|
453
|
-
|
|
454
|
-
self._killer = SignalCatcher()
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
def initialise_hk_header(self):
|
|
458
|
-
"""
|
|
459
|
-
Initialise the header for the HK data packet. Call this method only after the HK data itself
|
|
460
|
-
has been initialised.
|
|
461
|
-
"""
|
|
462
|
-
self._hk_header.length = self._hk_data.data_length()
|
|
463
|
-
data_packet_type = DataPacketType()
|
|
464
|
-
data_packet_type.packet_type = PacketType.HOUSEKEEPING_DATA
|
|
465
|
-
data_packet_type.last_packet = True
|
|
466
|
-
self._hk_header.type = data_packet_type.value
|
|
467
|
-
|
|
468
|
-
def update_hk_header(self, pulse_type: int):
|
|
469
|
-
"""
|
|
470
|
-
Update the header of the HK data packet.
|
|
471
|
-
"""
|
|
472
|
-
data_packet_type = DataPacketType(self._hk_header.type)
|
|
473
|
-
data_packet_type.frame_number = self._hk_data.frame_number
|
|
474
|
-
data_packet_type.mode = self._IN.ccd_mode_config
|
|
475
|
-
self._hk_header.type = data_packet_type.value
|
|
476
|
-
self._hk_header.frame_counter = self._hk_data.frame_counter
|
|
477
|
-
if pulse_type == 400:
|
|
478
|
-
self._hk_header.sequence_counter = 0
|
|
479
|
-
|
|
480
|
-
def update_hk_data(self):
|
|
481
|
-
pass
|
|
482
|
-
|
|
483
|
-
def get_mode(self):
|
|
484
|
-
mode = self._IN.ccd_mode_config
|
|
485
|
-
return n_fee_mode(mode)
|
|
486
|
-
|
|
487
|
-
def get_sync_period(self) -> float:
|
|
488
|
-
return self._IN.get_sync_period()
|
|
489
|
-
|
|
490
|
-
def get_current_ccd_number(self):
|
|
491
|
-
"""Return the current CCD number [range=1-4]."""
|
|
492
|
-
readout_order = self._IN.ccd_readout_order
|
|
493
|
-
# The convert_ccd_order_value function returns CCD number [1-4]
|
|
494
|
-
readout_order = convert_ccd_order_value(readout_order)
|
|
495
|
-
# CCD number in the N-FEE is [0-3]
|
|
496
|
-
return readout_order[self._hk_data.frame_number]
|
|
497
|
-
|
|
498
|
-
@property
|
|
499
|
-
def sensor_sel(self) -> int:
|
|
500
|
-
return self._IN.sensor_sel
|
|
501
|
-
|
|
502
|
-
@property
|
|
503
|
-
def v_start(self) -> int:
|
|
504
|
-
return self._IN.v_start
|
|
505
|
-
|
|
506
|
-
@property
|
|
507
|
-
def v_end(self) -> int:
|
|
508
|
-
return self._IN.v_end
|
|
509
|
-
|
|
510
|
-
@property
|
|
511
|
-
def internal_sync(self) -> bool:
|
|
512
|
-
return bool(self._IN.sync_sel)
|
|
513
|
-
|
|
514
|
-
def decode_current_state(self) -> str:
|
|
515
|
-
return self.get_mode().name
|
|
516
|
-
|
|
517
|
-
def run(self):
|
|
518
|
-
|
|
519
|
-
LOGGER.info(f"FEE Simulator Current State: {self.decode_current_state()}")
|
|
520
|
-
n_fee_side = self.setup.camera.fee.ccd_sides.enum
|
|
521
|
-
sensor_sel_enum = self.setup.camera.fee.sensor_sel.enum
|
|
522
|
-
|
|
523
|
-
with self._transport:
|
|
524
|
-
|
|
525
|
-
LOGGER.info("SpaceWire Transport has been connected.")
|
|
526
|
-
|
|
527
|
-
self._transport.configure()
|
|
528
|
-
|
|
529
|
-
LOGGER.info("SpaceWire Transport has been configured.")
|
|
530
|
-
|
|
531
|
-
LOGGER.info("Listening for SpaceWire communication...")
|
|
532
|
-
|
|
533
|
-
start_time = time.perf_counter() # time in fractional seconds
|
|
534
|
-
|
|
535
|
-
while True:
|
|
536
|
-
|
|
537
|
-
sync_period = self.get_sync_period()
|
|
538
|
-
|
|
539
|
-
if self._killer.term_signal_received:
|
|
540
|
-
LOGGER.warning(f"Terminating N-FEE Simulator after receiving {self._killer.signal_name}")
|
|
541
|
-
break
|
|
542
|
-
|
|
543
|
-
if time.perf_counter() <= start_time + sync_period:
|
|
544
|
-
continue
|
|
545
|
-
|
|
546
|
-
# LOGGER.debug(f"{'-'*80} {sync_period = }")
|
|
547
|
-
|
|
548
|
-
start_time = time.perf_counter()
|
|
549
|
-
|
|
550
|
-
# Send a timecode packet -----------------------------------------------------------
|
|
551
|
-
|
|
552
|
-
timecode = self._hk_data.timecode
|
|
553
|
-
LOGGER.info(f"Sending timecode: 0x{timecode:02X} ({timecode})")
|
|
554
|
-
self._transport.send_timecode(timecode)
|
|
555
|
-
|
|
556
|
-
# Send a housekeeping packet -------------------------------------------------------
|
|
557
|
-
|
|
558
|
-
LOGGER.info(f"Sending HK packet: frame_counter={self._hk_data.frame_counter}, "
|
|
559
|
-
f"sequence_counter={self._hk_header.sequence_counter}, "
|
|
560
|
-
f"type={self._hk_header.type_as_object}")
|
|
561
|
-
LOGGER.debug(f"HK Packet: error_flags=0b{self._hk_data['error_flags']:0b}")
|
|
562
|
-
|
|
563
|
-
data = self._hk_header.data_as_bytes() + self._hk_data.data_as_bytes()
|
|
564
|
-
packet = SpaceWirePacket.create_packet(data)
|
|
565
|
-
self._transport.write_packet(packet.packet_as_bytes)
|
|
566
|
-
|
|
567
|
-
self._transport.flush()
|
|
568
|
-
|
|
569
|
-
# Check if error flags must be cleared ---------------------------------------------
|
|
570
|
-
|
|
571
|
-
if self.register_map['clear_error_flag']:
|
|
572
|
-
LOGGER.info("Clearing error flags")
|
|
573
|
-
self.register_map[('reg_21_config', 'clear_error_flag')] = 0
|
|
574
|
-
self._hk_data['error_flags'] = 0
|
|
575
|
-
|
|
576
|
-
# Send the Data packets ------------------------------------------------------------
|
|
577
|
-
|
|
578
|
-
LOGGER.info(f"mode={self.decode_current_state()}, "
|
|
579
|
-
f"Sensor={self.sensor_sel}, "
|
|
580
|
-
f"Digitising={bool(self._IN.digitise_en)}, "
|
|
581
|
-
f"Internal Sync={self.internal_sync}")
|
|
582
|
-
|
|
583
|
-
# FIXME: N-FEE sends E- and F-side interlaced, in the code code below we always
|
|
584
|
-
# send E-side first, then F-side.
|
|
585
|
-
|
|
586
|
-
if (self._IN.digitise_en and
|
|
587
|
-
self._IN.ccd_mode_config in (n_fee_mode.FULL_IMAGE_PATTERN_MODE,
|
|
588
|
-
n_fee_mode.FULL_IMAGE_MODE,)):
|
|
589
|
-
|
|
590
|
-
try:
|
|
591
|
-
ccd_id_to_bin = self.setup.camera.fee.ccd_numbering.CCD_ID_TO_BIN
|
|
592
|
-
except AttributeError:
|
|
593
|
-
raise SetupError("No entry in the setup for camera.fee.ccd_numbering.CCD_ID_TO_BIN")
|
|
594
|
-
|
|
595
|
-
LOGGER.info("Sending Data packets...")
|
|
596
|
-
|
|
597
|
-
ccd_number = ccd_id_to_bin[self.get_current_ccd_number()] # N-FEE CCD number [0-3]
|
|
598
|
-
if self.sensor_sel & sensor_sel_enum.E_SIDE:
|
|
599
|
-
send_data_packets(
|
|
600
|
-
self._transport, timecode,
|
|
601
|
-
ccd_id=ccd_number, ccd_side=n_fee_side.E_SIDE, frame_number=self._hk_data.frame_number,
|
|
602
|
-
ccd_mode=self._IN.ccd_mode_config, v_start=self.v_start, v_end=self.v_end, setup=self.setup
|
|
603
|
-
)
|
|
604
|
-
if self.sensor_sel & sensor_sel_enum.F_SIDE:
|
|
605
|
-
send_data_packets(
|
|
606
|
-
self._transport, timecode,
|
|
607
|
-
ccd_id=ccd_number, ccd_side=n_fee_side.F_SIDE, frame_number=self._hk_data.frame_number,
|
|
608
|
-
ccd_mode=self._IN.ccd_mode_config, v_start=self.v_start, v_end=self.v_end, setup=self.setup
|
|
609
|
-
)
|
|
610
|
-
|
|
611
|
-
if self._killer.user_signal_received and self._killer.signal_name == "SIGUSR1":
|
|
612
|
-
# On USR1 signal, set the error flags to a random number. There are currently 12 error flags.
|
|
613
|
-
self.set_error_flags(random.randint(0x0, 0b1111_1111_1111))
|
|
614
|
-
self._killer.clear()
|
|
615
|
-
|
|
616
|
-
# Process any RMAP commands that were sent -----------------------------------------
|
|
617
|
-
|
|
618
|
-
LOGGER.info("Processing RMAP commands...")
|
|
619
|
-
|
|
620
|
-
while time.perf_counter() < start_time + sync_period - 0.2:
|
|
621
|
-
process_rmap_command(self._transport, self.register_map, self._hk_data)
|
|
622
|
-
|
|
623
|
-
LOGGER.info("Updating internals...")
|
|
624
|
-
|
|
625
|
-
self._hk_data.increment_timecode()
|
|
626
|
-
|
|
627
|
-
if not self.internal_sync:
|
|
628
|
-
self._hk_data.increment_frame_number()
|
|
629
|
-
|
|
630
|
-
if self._hk_data.frame_number == 0:
|
|
631
|
-
self._hk_data.increment_frame_counter()
|
|
632
|
-
self._IN.update(400)
|
|
633
|
-
self.update_hk_header(400)
|
|
634
|
-
else:
|
|
635
|
-
self._IN.update(200)
|
|
636
|
-
self.update_hk_header(200)
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
def set_error_flags(self, flags: int):
|
|
640
|
-
"""Set error_flags to the given number."""
|
|
641
|
-
LOGGER.warning(f"Setting error flags to 0b{flags:012b}")
|
|
642
|
-
self._hk_data["error_flags"] = flags
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
def generate_data_packets(data: np.ndarray, header: DataPacketHeader, v_start: int, v_end: int, setup: Setup):
|
|
646
|
-
"""
|
|
647
|
-
This generator function creates and returns the SpaceWire packets to send to the DPU Processor.
|
|
648
|
-
|
|
649
|
-
Args:
|
|
650
|
-
data (ndarray): the full frame image data
|
|
651
|
-
header (DataPacketHeader): the data packet header
|
|
652
|
-
v_start (int): the first row to be transmitted
|
|
653
|
-
v_end (int): the last row to be transmitted
|
|
654
|
-
setup: Setup
|
|
655
|
-
|
|
656
|
-
Returns:
|
|
657
|
-
|
|
658
|
-
"""
|
|
659
|
-
# steps:
|
|
660
|
-
# * reshape data to 1D array
|
|
661
|
-
# * update header with length, last_packet
|
|
662
|
-
# * increment sequence number?
|
|
663
|
-
# * convert data part into bytes object
|
|
664
|
-
# * concatenate header and data -> bytes
|
|
665
|
-
# * yield the packet
|
|
666
|
-
|
|
667
|
-
N_FEE_SIDE = setup.camera.fee.ccd_sides.enum
|
|
668
|
-
|
|
669
|
-
MAX_PACKET_SIZE = 32140 # this is a register value reg_4_config
|
|
670
|
-
HEADER_LENGTH = 10
|
|
671
|
-
H_END = 2294
|
|
672
|
-
MAX_CCD_LINE = 4509
|
|
673
|
-
MAX_OVERSCAN_LINE = MAX_CCD_LINE + 30
|
|
674
|
-
|
|
675
|
-
nr_rows_in_packet = row_offset = (MAX_PACKET_SIZE - HEADER_LENGTH) // (H_END + 1) // 2
|
|
676
|
-
|
|
677
|
-
y_size, x_size = data.shape
|
|
678
|
-
h_end = x_size - 1
|
|
679
|
-
v_end_ccd = min(MAX_CCD_LINE, v_end)
|
|
680
|
-
|
|
681
|
-
ccd_side = header.type_as_object.ccd_side
|
|
682
|
-
|
|
683
|
-
# F-side is read out starting from the right, so we flip the data left to right
|
|
684
|
-
# before sending, which simulates the reverse readout.
|
|
685
|
-
|
|
686
|
-
data = np.fliplr(data) if ccd_side == N_FEE_SIDE.RIGHT_SIDE else data
|
|
687
|
-
|
|
688
|
-
header.length = nr_rows_in_packet * ((h_end + 1) * 2)
|
|
689
|
-
LOGGER.debug(f"{header.length = }, {nr_rows_in_packet = }, {h_end = }")
|
|
690
|
-
|
|
691
|
-
for idx in range(v_start, v_end_ccd + 1, nr_rows_in_packet):
|
|
692
|
-
if idx + nr_rows_in_packet > v_end_ccd:
|
|
693
|
-
row_offset = v_end_ccd - idx + 1
|
|
694
|
-
header.length = row_offset * ((h_end + 1) * 2)
|
|
695
|
-
header.last_packet = True
|
|
696
|
-
# LOGGER.debug(f"{idx=}, {row_offset=}")
|
|
697
|
-
chunk = bytearray(data[idx:idx+row_offset, :])
|
|
698
|
-
chunk[0::2], chunk[1::2] = chunk[1::2], chunk[0::2]
|
|
699
|
-
packet_data = header.data_as_bytes() + chunk
|
|
700
|
-
# LOGGER.debug(f"{len(packet_data)=}, {len(chunk)=}")
|
|
701
|
-
yield SpaceWirePacket.create_packet(packet_data)
|
|
702
|
-
|
|
703
|
-
# reset the header for the overscan lines
|
|
704
|
-
|
|
705
|
-
header.packet_type = PacketType.OVERSCAN_DATA
|
|
706
|
-
header.last_packet = False
|
|
707
|
-
header.length = nr_rows_in_packet * ((h_end + 1) * 2)
|
|
708
|
-
|
|
709
|
-
v_end_overscan = min(MAX_OVERSCAN_LINE, v_end)
|
|
710
|
-
|
|
711
|
-
# reset the row_offset
|
|
712
|
-
|
|
713
|
-
row_offset = nr_rows_in_packet
|
|
714
|
-
|
|
715
|
-
for idx in range(MAX_CCD_LINE+1, v_end_overscan + 1, nr_rows_in_packet):
|
|
716
|
-
if idx + nr_rows_in_packet > v_end_overscan:
|
|
717
|
-
row_offset = v_end_overscan - idx + 1
|
|
718
|
-
header.length = row_offset * ((h_end + 1) * 2)
|
|
719
|
-
header.last_packet = True
|
|
720
|
-
LOGGER.debug(f"{idx=}, {row_offset=}")
|
|
721
|
-
chunk = bytearray(data[idx:idx+row_offset, :])
|
|
722
|
-
chunk[0::2], chunk[1::2] = chunk[1::2], chunk[0::2]
|
|
723
|
-
packet_data = header.data_as_bytes() + chunk
|
|
724
|
-
LOGGER.debug(f"{len(packet_data)=}, {len(chunk)=}")
|
|
725
|
-
yield SpaceWirePacket.create_packet(packet_data)
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
def send_data_packets(
|
|
729
|
-
transport, timecode: int, ccd_id: int, ccd_side: int, frame_number: int, ccd_mode: int,
|
|
730
|
-
v_start: int, v_end: int, setup: Setup
|
|
731
|
-
):
|
|
732
|
-
"""
|
|
733
|
-
Generates pattern data and sends it over
|
|
734
|
-
"""
|
|
735
|
-
data = create_pattern_data(timecode, ccd_id, ccd_side)
|
|
736
|
-
|
|
737
|
-
header = DataPacketHeader()
|
|
738
|
-
packet_type = header.type_as_object
|
|
739
|
-
packet_type.ccd_side = ccd_side
|
|
740
|
-
packet_type.ccd_number = ccd_id
|
|
741
|
-
packet_type.last_packet = False
|
|
742
|
-
packet_type.frame_number = frame_number
|
|
743
|
-
packet_type.mode = ccd_mode
|
|
744
|
-
header.type = packet_type
|
|
745
|
-
|
|
746
|
-
LOGGER.info(f"**** {packet_type=!s}")
|
|
747
|
-
LOGGER.info(f"Sending data packets...{v_start=} {v_end=}")
|
|
748
|
-
|
|
749
|
-
for packet in generate_data_packets(data, header, v_start, v_end, setup):
|
|
750
|
-
if x := transport.write_packet(packet.packet_as_bytes):
|
|
751
|
-
LOGGER.error(f"Sending Data packet failed ({x}).")
|
|
752
|
-
transport.flush()
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
def process_rmap_command(transport: SpaceWireInterface, register: RegisterMap, hk_data: HousekeepingData):
|
|
756
|
-
|
|
757
|
-
_, buffer = transport.read_packet(timeout=200)
|
|
758
|
-
if not buffer:
|
|
759
|
-
return
|
|
760
|
-
|
|
761
|
-
# The following check is to cope with loss of connection when either the
|
|
762
|
-
# DPU Processor crashed or the connection dropped for some other reason.
|
|
763
|
-
# We will receive one packet with 0 or 1 bytes.
|
|
764
|
-
|
|
765
|
-
if len(buffer) in {0, 1}:
|
|
766
|
-
return
|
|
767
|
-
|
|
768
|
-
packet = SpaceWirePacket.create_packet(buffer)
|
|
769
|
-
|
|
770
|
-
LOGGER.debug(f"Received {packet!r}")
|
|
771
|
-
|
|
772
|
-
status = 0 # indicating OK
|
|
773
|
-
|
|
774
|
-
if isinstance(packet, ReadRequest):
|
|
775
|
-
# If address is start of HK memory area, read the data from the housekeeping data
|
|
776
|
-
if packet.address == 0x700:
|
|
777
|
-
data = hk_data.data_as_bytes()
|
|
778
|
-
else:
|
|
779
|
-
data = register.get_data(packet.address, packet.data_length)
|
|
780
|
-
|
|
781
|
-
data = create_rmap_read_request_reply_packet(
|
|
782
|
-
packet.instruction, packet.transaction_id, status, data, packet.data_length)
|
|
783
|
-
|
|
784
|
-
LOGGER.debug(f"Sending {SpaceWirePacket.create_packet(data)!r}")
|
|
785
|
-
|
|
786
|
-
transport.write_packet(data)
|
|
787
|
-
transport.flush()
|
|
788
|
-
|
|
789
|
-
elif isinstance(packet, WriteRequest):
|
|
790
|
-
if packet.is_verified():
|
|
791
|
-
LOGGER.debug(
|
|
792
|
-
f"Write data to register map: 0x{packet.address:x} [0x{' '.join(f'{x:02x}'for x in packet.data)}]"
|
|
793
|
-
)
|
|
794
|
-
register.set_data(packet.address, packet.data)
|
|
795
|
-
data = create_rmap_write_request_reply_packet(
|
|
796
|
-
packet.instruction, packet.transaction_id, status
|
|
797
|
-
)
|
|
798
|
-
|
|
799
|
-
LOGGER.debug(f"Sending {SpaceWirePacket.create_packet(data)!r}")
|
|
800
|
-
|
|
801
|
-
transport.write_packet(data)
|
|
802
|
-
transport.flush()
|
|
803
|
-
|
|
804
|
-
else:
|
|
805
|
-
LOGGER.warning("Unverified Write Request not yet implemented!")
|
|
806
|
-
else:
|
|
807
|
-
LOGGER.warning(f"Unexpected packet type received: {packet.__class__}")
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
def start_fee_simulator(transport: SpaceWireInterface):
|
|
811
|
-
|
|
812
|
-
try:
|
|
813
|
-
fee_sim = FEESimulator(transport)
|
|
814
|
-
fee_sim.run()
|
|
815
|
-
except KeyboardInterrupt:
|
|
816
|
-
print("Shutdown requested...exiting")
|
|
817
|
-
except SystemExit as exit_code:
|
|
818
|
-
print(f"System Exit with code {exit_code}.")
|
|
819
|
-
return exit_code
|
|
820
|
-
except Exception:
|
|
821
|
-
import traceback
|
|
822
|
-
|
|
823
|
-
traceback.print_exc(file=sys.stdout)
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
@click.group()
|
|
827
|
-
def cli():
|
|
828
|
-
pass
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
@cli.command()
|
|
832
|
-
@click.option("--tunnel", is_flag=True,
|
|
833
|
-
help="use an SSH tunnel to connect to the DSI")
|
|
834
|
-
@click.option("--zeromq", is_flag=True,
|
|
835
|
-
help="use ZeroMQ to connect to the DPU Processor")
|
|
836
|
-
@click.option("--ssh-user", "-u",
|
|
837
|
-
help="the username at the SSH server")
|
|
838
|
-
@click.option("--dsi-address", "-a",
|
|
839
|
-
help="the hostname or IP address of the DSI to which this client "
|
|
840
|
-
"will connect (+ tcp socket port)")
|
|
841
|
-
@click.option("--dsi-port", "-p", type=int, default=1,
|
|
842
|
-
help="the DSI port number to which this client needs to connect "
|
|
843
|
-
"(not the port on the socket) [type=int]")
|
|
844
|
-
def start(tunnel, zeromq, ssh_user, dsi_address, dsi_port):
|
|
845
|
-
"""
|
|
846
|
-
Start the FEE Simulator.
|
|
847
|
-
|
|
848
|
-
When --tunnel is specified, DSI_ADDRESS will default to 127.0.0.1
|
|
849
|
-
unless explicitly provided.
|
|
850
|
-
"""
|
|
851
|
-
multiprocessing.current_process().name = "feesim"
|
|
852
|
-
|
|
853
|
-
print(f"{tunnel=}, {zeromq=}, {ssh_user=}, {dsi_address=}, {dsi_port=}")
|
|
854
|
-
|
|
855
|
-
if tunnel:
|
|
856
|
-
user = getpass.getuser()
|
|
857
|
-
password = getpass.getpass("Enter SSH passphrase: ")
|
|
858
|
-
|
|
859
|
-
# This is the IP address of the SSH server.
|
|
860
|
-
|
|
861
|
-
server_host = site_settings.SSH_SERVER
|
|
862
|
-
server_port = site_settings.SSH_PORT
|
|
863
|
-
|
|
864
|
-
# The IP address of the DSI, i.e. the EtherSpaceLink device from 4Links and
|
|
865
|
-
# the default port as defined in the Settings configuration file.
|
|
866
|
-
|
|
867
|
-
remote_host = dsi_settings.DSI_FEE_IP_ADDRESS
|
|
868
|
-
remote_port = dsi_settings.DSI_FEE_PORT
|
|
869
|
-
|
|
870
|
-
# The host from which the connection will be established. Usually, this
|
|
871
|
-
# is the 'localhost', but can be specified on the commandline if needed.
|
|
872
|
-
|
|
873
|
-
if not dsi_address:
|
|
874
|
-
local_host = "127.0.0.1"
|
|
875
|
-
local_port = 4948 # this number is just an arbitrary choice
|
|
876
|
-
dsi_address = f"{local_host}:{local_port}"
|
|
877
|
-
else:
|
|
878
|
-
local_host, local_port = dsi_address.split(":")
|
|
879
|
-
local_port = int(local_port)
|
|
880
|
-
|
|
881
|
-
LOGGER.debug(
|
|
882
|
-
f"SSH server: {server_host}:{server_port}, "
|
|
883
|
-
f"DSI: {remote_host}:{remote_port}, "
|
|
884
|
-
f"{local_host=}:{local_port=}, "
|
|
885
|
-
f"{dsi_address=}, {dsi_port=}"
|
|
886
|
-
)
|
|
887
|
-
|
|
888
|
-
with sshtunnel.open_tunnel(
|
|
889
|
-
(server_host, server_port),
|
|
890
|
-
ssh_username=user,
|
|
891
|
-
# FIXME: hardcoded info should go into specific user settings or the file should
|
|
892
|
-
# be searched for in the user's home directory.
|
|
893
|
-
ssh_private_key="/Users/rik/.ssh/id_rsa",
|
|
894
|
-
ssh_private_key_password=password,
|
|
895
|
-
remote_bind_address=(remote_host, remote_port),
|
|
896
|
-
local_bind_address=(local_host, local_port),
|
|
897
|
-
):
|
|
898
|
-
transport = SpaceWireOverDSI(dsi_address, dsi_port)
|
|
899
|
-
return start_fee_simulator(transport)
|
|
900
|
-
else:
|
|
901
|
-
if zeromq:
|
|
902
|
-
transport = SpaceWireOverZeroMQ(
|
|
903
|
-
f"tcp://{dpu_settings.HOSTNAME}:5555", "DPU--FEE")
|
|
904
|
-
else:
|
|
905
|
-
if not dsi_address:
|
|
906
|
-
dsi_address = f"{dsi_settings.DSI_FEE_IP_ADDRESS}:{dsi_settings.DSI_FEE_PORT}"
|
|
907
|
-
|
|
908
|
-
transport = SpaceWireOverDSI(dsi_address, dsi_port)
|
|
909
|
-
|
|
910
|
-
return start_fee_simulator(transport)
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
if __name__ == "__main__":
|
|
914
|
-
sys.exit(cli())
|