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.
Files changed (664) hide show
  1. README.md +27 -0
  2. bump.py +85 -0
  3. cgse-2025.0.2.dist-info/METADATA +38 -0
  4. cgse-2025.0.2.dist-info/RECORD +5 -0
  5. {cgse-2024.7.0.dist-info → cgse-2025.0.2.dist-info}/WHEEL +1 -2
  6. cgse-2024.7.0.dist-info/COPYING +0 -674
  7. cgse-2024.7.0.dist-info/COPYING.LESSER +0 -165
  8. cgse-2024.7.0.dist-info/METADATA +0 -144
  9. cgse-2024.7.0.dist-info/RECORD +0 -660
  10. cgse-2024.7.0.dist-info/entry_points.txt +0 -75
  11. cgse-2024.7.0.dist-info/top_level.txt +0 -2
  12. egse/__init__.py +0 -12
  13. egse/__main__.py +0 -32
  14. egse/aeu/aeu.py +0 -5238
  15. egse/aeu/aeu_awg.yaml +0 -265
  16. egse/aeu/aeu_crio.yaml +0 -273
  17. egse/aeu/aeu_cs.py +0 -627
  18. egse/aeu/aeu_devif.py +0 -321
  19. egse/aeu/aeu_main_ui.py +0 -903
  20. egse/aeu/aeu_metrics.py +0 -131
  21. egse/aeu/aeu_protocol.py +0 -463
  22. egse/aeu/aeu_psu.yaml +0 -204
  23. egse/aeu/aeu_ui.py +0 -873
  24. egse/aeu/arbdata/FccdRead.arb +0 -2
  25. egse/aeu/arbdata/FccdRead_min_points.arb +0 -2
  26. egse/aeu/arbdata/HeaterSync_FccdRead.arb +0 -2
  27. egse/aeu/arbdata/HeaterSync_ccdRead25.arb +0 -2
  28. egse/aeu/arbdata/HeaterSync_ccdRead31_25.arb +0 -2
  29. egse/aeu/arbdata/HeaterSync_ccdRead37_50.arb +0 -2
  30. egse/aeu/arbdata/HeaterSync_ccdRead43_75.arb +0 -2
  31. egse/aeu/arbdata/HeaterSync_ccdRead50.arb +0 -2
  32. egse/aeu/arbdata/Heater_FccdRead_min_points.arb +0 -2
  33. egse/aeu/arbdata/ccdRead25.arb +0 -2
  34. egse/aeu/arbdata/ccdRead25_150ms.arb +0 -2
  35. egse/aeu/arbdata/ccdRead31_25.arb +0 -2
  36. egse/aeu/arbdata/ccdRead31_25_150ms.arb +0 -2
  37. egse/aeu/arbdata/ccdRead37_50.arb +0 -2
  38. egse/aeu/arbdata/ccdRead37_50_150ms.arb +0 -2
  39. egse/aeu/arbdata/ccdRead43_75.arb +0 -2
  40. egse/aeu/arbdata/ccdRead43_75_150ms.arb +0 -2
  41. egse/aeu/arbdata/ccdRead50.arb +0 -2
  42. egse/aeu/arbdata/ccdRead50_150ms.arb +0 -2
  43. egse/alert/__init__.py +0 -1049
  44. egse/alert/alertman.yaml +0 -37
  45. egse/alert/alertman_cs.py +0 -233
  46. egse/alert/alertman_ui.py +0 -600
  47. egse/alert/gsm/beaglebone.py +0 -138
  48. egse/alert/gsm/beaglebone.yaml +0 -51
  49. egse/alert/gsm/beaglebone_cs.py +0 -108
  50. egse/alert/gsm/beaglebone_devif.py +0 -122
  51. egse/alert/gsm/beaglebone_protocol.py +0 -46
  52. egse/bits.py +0 -318
  53. egse/camera.py +0 -44
  54. egse/collimator/__init__.py +0 -0
  55. egse/collimator/fcul/__init__.py +0 -0
  56. egse/collimator/fcul/ogse.py +0 -1077
  57. egse/collimator/fcul/ogse.yaml +0 -14
  58. egse/collimator/fcul/ogse_cs.py +0 -154
  59. egse/collimator/fcul/ogse_devif.py +0 -358
  60. egse/collimator/fcul/ogse_protocol.py +0 -132
  61. egse/collimator/fcul/ogse_sim.py +0 -431
  62. egse/collimator/fcul/ogse_ui.py +0 -1108
  63. egse/command.py +0 -699
  64. egse/config.py +0 -410
  65. egse/confman/__init__.py +0 -1058
  66. egse/confman/confman.yaml +0 -70
  67. egse/confman/confman_cs.py +0 -240
  68. egse/confman/confman_ui.py +0 -381
  69. egse/confman/setup_ui.py +0 -565
  70. egse/control.py +0 -632
  71. egse/coordinates/__init__.py +0 -534
  72. egse/coordinates/avoidance.py +0 -100
  73. egse/coordinates/cslmodel.py +0 -127
  74. egse/coordinates/laser_tracker_to_dict.py +0 -122
  75. egse/coordinates/point.py +0 -707
  76. egse/coordinates/pyplot.py +0 -194
  77. egse/coordinates/referenceFrame.py +0 -1279
  78. egse/coordinates/refmodel.py +0 -737
  79. egse/coordinates/rotationMatrix.py +0 -85
  80. egse/coordinates/transform3d_addon.py +0 -419
  81. egse/csl/__init__.py +0 -50
  82. egse/csl/commanding.py +0 -78
  83. egse/csl/icons/hexapod-connected-selected.svg +0 -30
  84. egse/csl/icons/hexapod-connected.svg +0 -30
  85. egse/csl/icons/hexapod-homing-selected.svg +0 -68
  86. egse/csl/icons/hexapod-homing.svg +0 -68
  87. egse/csl/icons/hexapod-retract-selected.svg +0 -56
  88. egse/csl/icons/hexapod-retract.svg +0 -51
  89. egse/csl/icons/hexapod-zero-selected.svg +0 -56
  90. egse/csl/icons/hexapod-zero.svg +0 -56
  91. egse/csl/icons/logo-puna.svg +0 -92
  92. egse/csl/icons/stop.svg +0 -1
  93. egse/csl/initialisation.py +0 -102
  94. egse/csl/mech_pos_settings.yaml +0 -18
  95. egse/das.py +0 -1240
  96. egse/das.yaml +0 -7
  97. egse/data/conf/SETUP_CSL_00000_170620_150000.yaml +0 -5
  98. egse/data/conf/SETUP_CSL_00001_170620_151010.yaml +0 -69
  99. egse/data/conf/SETUP_CSL_00002_170620_151020.yaml +0 -69
  100. egse/data/conf/SETUP_CSL_00003_170620_151030.yaml +0 -69
  101. egse/data/conf/SETUP_CSL_00004_170620_151040.yaml +0 -69
  102. egse/data/conf/SETUP_CSL_00005_170620_151050.yaml +0 -69
  103. egse/data/conf/SETUP_CSL_00006_170620_151060.yaml +0 -69
  104. egse/data/conf/SETUP_CSL_00007_170620_151070.yaml +0 -69
  105. egse/data/conf/SETUP_CSL_00008_170620_151080.yaml +0 -75
  106. egse/data/conf/SETUP_CSL_00010_210308_083016.yaml +0 -138
  107. egse/data/conf/SETUP_INTA_00000_170620_150000.yaml +0 -4
  108. egse/data/conf/SETUP_SRON_00000_170620_150000.yaml +0 -4
  109. egse/decorators.py +0 -514
  110. egse/device.py +0 -269
  111. egse/dpu/__init__.py +0 -2698
  112. egse/dpu/ccd_ui.py +0 -514
  113. egse/dpu/dpu.py +0 -783
  114. egse/dpu/dpu.yaml +0 -153
  115. egse/dpu/dpu_cs.py +0 -272
  116. egse/dpu/dpu_ui.py +0 -671
  117. egse/dpu/fitsgen.py +0 -2096
  118. egse/dpu/fitsgen_ui.py +0 -399
  119. egse/dpu/hdf5_model.py +0 -332
  120. egse/dpu/hdf5_ui.py +0 -277
  121. egse/dpu/hdf5_viewer.py +0 -506
  122. egse/dpu/hk_ui.py +0 -468
  123. egse/dpu_commands.py +0 -81
  124. egse/dsi/__init__.py +0 -33
  125. egse/dsi/_libesl.py +0 -232
  126. egse/dsi/constants.py +0 -296
  127. egse/dsi/esl.py +0 -630
  128. egse/dsi/rmap.py +0 -444
  129. egse/dsi/rmapci.py +0 -39
  130. egse/dsi/spw.py +0 -335
  131. egse/dsi/spw_state.py +0 -29
  132. egse/dummy.py +0 -318
  133. egse/dyndummy.py +0 -179
  134. egse/env.py +0 -278
  135. egse/exceptions.py +0 -88
  136. egse/fdir/__init__.py +0 -26
  137. egse/fdir/fdir_manager.py +0 -85
  138. egse/fdir/fdir_manager.yaml +0 -37
  139. egse/fdir/fdir_manager_controller.py +0 -136
  140. egse/fdir/fdir_manager_cs.py +0 -164
  141. egse/fdir/fdir_manager_interface.py +0 -15
  142. egse/fdir/fdir_remote.py +0 -73
  143. egse/fdir/fdir_remote.yaml +0 -30
  144. egse/fdir/fdir_remote_controller.py +0 -30
  145. egse/fdir/fdir_remote_cs.py +0 -94
  146. egse/fdir/fdir_remote_interface.py +0 -9
  147. egse/fdir/fdir_remote_popup.py +0 -26
  148. egse/fee/__init__.py +0 -106
  149. egse/fee/f_fee_register.yaml +0 -43
  150. egse/fee/feesim.py +0 -914
  151. egse/fee/n_fee_hk.py +0 -768
  152. egse/fee/nfee.py +0 -188
  153. egse/filterwheel/__init__.py +0 -4
  154. egse/filterwheel/eksma/__init__.py +0 -49
  155. egse/filterwheel/eksma/fw8smc4.py +0 -657
  156. egse/filterwheel/eksma/fw8smc4.yaml +0 -121
  157. egse/filterwheel/eksma/fw8smc4_cs.py +0 -144
  158. egse/filterwheel/eksma/fw8smc4_devif.py +0 -473
  159. egse/filterwheel/eksma/fw8smc4_protocol.py +0 -82
  160. egse/filterwheel/eksma/fw8smc4_ui.py +0 -940
  161. egse/filterwheel/eksma/fw8smc5.py +0 -115
  162. egse/filterwheel/eksma/fw8smc5.yaml +0 -105
  163. egse/filterwheel/eksma/fw8smc5_controller.py +0 -307
  164. egse/filterwheel/eksma/fw8smc5_cs.py +0 -141
  165. egse/filterwheel/eksma/fw8smc5_interface.py +0 -65
  166. egse/filterwheel/eksma/fw8smc5_simulator.py +0 -29
  167. egse/filterwheel/eksma/fw8smc5_ui.py +0 -1065
  168. egse/filterwheel/eksma/testpythonfw.py +0 -215
  169. egse/fov/__init__.py +0 -65
  170. egse/fov/fov_hk.py +0 -710
  171. egse/fov/fov_ui.py +0 -859
  172. egse/fov/fov_ui_controller.py +0 -140
  173. egse/fov/fov_ui_model.py +0 -200
  174. egse/fov/fov_ui_view.py +0 -345
  175. egse/gimbal/__init__.py +0 -32
  176. egse/gimbal/symetrie/__init__.py +0 -26
  177. egse/gimbal/symetrie/alpha.py +0 -586
  178. egse/gimbal/symetrie/generic_gimbal_ui.py +0 -1521
  179. egse/gimbal/symetrie/gimbal.py +0 -877
  180. egse/gimbal/symetrie/gimbal.yaml +0 -168
  181. egse/gimbal/symetrie/gimbal_cs.py +0 -183
  182. egse/gimbal/symetrie/gimbal_protocol.py +0 -138
  183. egse/gimbal/symetrie/gimbal_ui.py +0 -361
  184. egse/gimbal/symetrie/pmac.py +0 -1006
  185. egse/gimbal/symetrie/pmac_regex.py +0 -83
  186. egse/graph.py +0 -132
  187. egse/gui/__init__.py +0 -47
  188. egse/gui/buttons.py +0 -378
  189. egse/gui/focalplane.py +0 -1285
  190. egse/gui/formatter.py +0 -10
  191. egse/gui/led.py +0 -162
  192. egse/gui/limitswitch.py +0 -143
  193. egse/gui/mechanisms.py +0 -587
  194. egse/gui/states.py +0 -148
  195. egse/gui/stripchart.py +0 -729
  196. egse/gui/styles.qss +0 -48
  197. egse/gui/switch.py +0 -112
  198. egse/h5.py +0 -274
  199. egse/help/__init__.py +0 -0
  200. egse/help/help_ui.py +0 -126
  201. egse/hexapod/__init__.py +0 -32
  202. egse/hexapod/symetrie/__init__.py +0 -137
  203. egse/hexapod/symetrie/alpha.py +0 -874
  204. egse/hexapod/symetrie/dynalpha.py +0 -1387
  205. egse/hexapod/symetrie/hexapod_ui.py +0 -1516
  206. egse/hexapod/symetrie/pmac.py +0 -1010
  207. egse/hexapod/symetrie/pmac_regex.py +0 -83
  208. egse/hexapod/symetrie/puna.py +0 -1167
  209. egse/hexapod/symetrie/puna.yaml +0 -193
  210. egse/hexapod/symetrie/puna_cs.py +0 -195
  211. egse/hexapod/symetrie/puna_protocol.py +0 -134
  212. egse/hexapod/symetrie/puna_ui.py +0 -433
  213. egse/hexapod/symetrie/punaplus.py +0 -107
  214. egse/hexapod/symetrie/zonda.py +0 -872
  215. egse/hexapod/symetrie/zonda.yaml +0 -337
  216. egse/hexapod/symetrie/zonda_cs.py +0 -172
  217. egse/hexapod/symetrie/zonda_devif.py +0 -414
  218. egse/hexapod/symetrie/zonda_protocol.py +0 -123
  219. egse/hexapod/symetrie/zonda_ui.py +0 -449
  220. egse/hk.py +0 -791
  221. egse/icons/aeu-cs-start.svg +0 -117
  222. egse/icons/aeu-cs-stop.svg +0 -118
  223. egse/icons/aeu-cs.svg +0 -107
  224. egse/icons/aeu_cs-started.svg +0 -112
  225. egse/icons/aeu_cs-stopped.svg +0 -112
  226. egse/icons/aeu_cs.svg +0 -55
  227. egse/icons/alert.svg +0 -1
  228. egse/icons/arrow-double-left.png +0 -0
  229. egse/icons/arrow-double-right.png +0 -0
  230. egse/icons/arrow-up.svg +0 -11
  231. egse/icons/backward.svg +0 -1
  232. egse/icons/busy.svg +0 -1
  233. egse/icons/cleaning.svg +0 -115
  234. egse/icons/color-scheme.svg +0 -1
  235. egse/icons/cs-connected-alert.svg +0 -91
  236. egse/icons/cs-connected-disabled.svg +0 -43
  237. egse/icons/cs-connected.svg +0 -89
  238. egse/icons/cs-not-connected.svg +0 -44
  239. egse/icons/double-left-arrow.svg +0 -1
  240. egse/icons/double-right-arrow.svg +0 -1
  241. egse/icons/erase-disabled.svg +0 -19
  242. egse/icons/erase.svg +0 -59
  243. egse/icons/fitsgen-start.svg +0 -47
  244. egse/icons/fitsgen-stop.svg +0 -48
  245. egse/icons/fitsgen.svg +0 -1
  246. egse/icons/forward.svg +0 -1
  247. egse/icons/fov-hk-start.svg +0 -33
  248. egse/icons/fov-hk-stop.svg +0 -37
  249. egse/icons/fov-hk.svg +0 -1
  250. egse/icons/front-desk.svg +0 -1
  251. egse/icons/home-actioned.svg +0 -15
  252. egse/icons/home-disabled.svg +0 -15
  253. egse/icons/home.svg +0 -13
  254. egse/icons/info.svg +0 -1
  255. egse/icons/invalid.png +0 -0
  256. egse/icons/led-green.svg +0 -20
  257. egse/icons/led-grey.svg +0 -20
  258. egse/icons/led-orange.svg +0 -20
  259. egse/icons/led-red.svg +0 -20
  260. egse/icons/led-square-green.svg +0 -134
  261. egse/icons/led-square-grey.svg +0 -134
  262. egse/icons/led-square-orange.svg +0 -134
  263. egse/icons/led-square-red.svg +0 -134
  264. egse/icons/limit-switch-all-green.svg +0 -115
  265. egse/icons/limit-switch-all-red.svg +0 -117
  266. egse/icons/limit-switch-el+.svg +0 -116
  267. egse/icons/limit-switch-el-.svg +0 -117
  268. egse/icons/location-marker.svg +0 -1
  269. egse/icons/logo-dpu.svg +0 -48
  270. egse/icons/logo-gimbal.svg +0 -112
  271. egse/icons/logo-huber.svg +0 -23
  272. egse/icons/logo-ogse.svg +0 -31
  273. egse/icons/logo-puna.svg +0 -92
  274. egse/icons/logo-tcs.svg +0 -29
  275. egse/icons/logo-zonda.svg +0 -66
  276. egse/icons/maximize.svg +0 -1
  277. egse/icons/meter.svg +0 -1
  278. egse/icons/more.svg +0 -45
  279. egse/icons/n-fee-hk-start.svg +0 -24
  280. egse/icons/n-fee-hk-stop.svg +0 -25
  281. egse/icons/n-fee-hk.svg +0 -83
  282. egse/icons/observing-off.svg +0 -46
  283. egse/icons/observing-on.svg +0 -46
  284. egse/icons/open-document-hdf5.png +0 -0
  285. egse/icons/open-document-hdf5.svg +0 -21
  286. egse/icons/ops-mode.svg +0 -1
  287. egse/icons/play-green.svg +0 -17
  288. egse/icons/plugged-disabled.svg +0 -27
  289. egse/icons/plugged.svg +0 -21
  290. egse/icons/pm_ui.svg +0 -1
  291. egse/icons/power-button-green.svg +0 -27
  292. egse/icons/power-button-red.svg +0 -27
  293. egse/icons/power-button.svg +0 -27
  294. egse/icons/radar.svg +0 -1
  295. egse/icons/radioactive.svg +0 -2
  296. egse/icons/reload.svg +0 -1
  297. egse/icons/remote-control-off.svg +0 -28
  298. egse/icons/remote-control-on.svg +0 -28
  299. egse/icons/repeat-blue.svg +0 -15
  300. egse/icons/repeat.svg +0 -1
  301. egse/icons/settings.svg +0 -1
  302. egse/icons/shrink.svg +0 -1
  303. egse/icons/shutter.svg +0 -1
  304. egse/icons/sign-off.svg +0 -1
  305. egse/icons/sign-on.svg +0 -1
  306. egse/icons/sim-mode.svg +0 -1
  307. egse/icons/small-buttons-go.svg +0 -20
  308. egse/icons/small-buttons-minus.svg +0 -51
  309. egse/icons/small-buttons-plus.svg +0 -51
  310. egse/icons/sponge.svg +0 -220
  311. egse/icons/start-button-disabled.svg +0 -84
  312. egse/icons/start-button.svg +0 -50
  313. egse/icons/stop-button-disabled.svg +0 -84
  314. egse/icons/stop-button.svg +0 -50
  315. egse/icons/stop-red.svg +0 -17
  316. egse/icons/stop.svg +0 -1
  317. egse/icons/switch-disabled-square.svg +0 -87
  318. egse/icons/switch-disabled.svg +0 -15
  319. egse/icons/switch-off-square.svg +0 -87
  320. egse/icons/switch-off.svg +0 -72
  321. egse/icons/switch-on-square.svg +0 -87
  322. egse/icons/switch-on.svg +0 -61
  323. egse/icons/temperature-control.svg +0 -44
  324. egse/icons/th_ui_logo.svg +0 -1
  325. egse/icons/unplugged.svg +0 -23
  326. egse/icons/unvalid.png +0 -0
  327. egse/icons/user-interface.svg +0 -1
  328. egse/icons/vacuum.svg +0 -1
  329. egse/icons/valid.png +0 -0
  330. egse/icons/zoom-to-pixel-dark.svg +0 -64
  331. egse/icons/zoom-to-pixel-white.svg +0 -36
  332. egse/images/big-rotation-stage.png +0 -0
  333. egse/images/connected-100.png +0 -0
  334. egse/images/cross.svg +0 -6
  335. egse/images/disconnected-100.png +0 -0
  336. egse/images/gui-icon.png +0 -0
  337. egse/images/home.svg +0 -6
  338. egse/images/info-icon.png +0 -0
  339. egse/images/led-black.svg +0 -89
  340. egse/images/led-green.svg +0 -85
  341. egse/images/led-orange.svg +0 -85
  342. egse/images/led-red.svg +0 -85
  343. egse/images/load-icon.png +0 -0
  344. egse/images/load-setup.png +0 -0
  345. egse/images/load.png +0 -0
  346. egse/images/pause.png +0 -0
  347. egse/images/play-button.svg +0 -8
  348. egse/images/play.png +0 -0
  349. egse/images/process-status.png +0 -0
  350. egse/images/restart.png +0 -0
  351. egse/images/search.png +0 -0
  352. egse/images/sma.png +0 -0
  353. egse/images/start.png +0 -0
  354. egse/images/stop-button.svg +0 -8
  355. egse/images/stop.png +0 -0
  356. egse/images/switch-off.svg +0 -48
  357. egse/images/switch-on.svg +0 -48
  358. egse/images/undo.png +0 -0
  359. egse/images/update-button.svg +0 -11
  360. egse/imageviewer/exposureselection.py +0 -475
  361. egse/imageviewer/imageviewer.py +0 -198
  362. egse/imageviewer/matchfocalplane.py +0 -179
  363. egse/imageviewer/subfieldposition.py +0 -133
  364. egse/lampcontrol/__init__.py +0 -4
  365. egse/lampcontrol/beaglebone/beaglebone.py +0 -178
  366. egse/lampcontrol/beaglebone/beaglebone.yaml +0 -62
  367. egse/lampcontrol/beaglebone/beaglebone_cs.py +0 -106
  368. egse/lampcontrol/beaglebone/beaglebone_devif.py +0 -150
  369. egse/lampcontrol/beaglebone/beaglebone_protocol.py +0 -73
  370. egse/lampcontrol/energetiq/__init__.py +0 -22
  371. egse/lampcontrol/energetiq/eq99.yaml +0 -98
  372. egse/lampcontrol/energetiq/lampEQ99.py +0 -283
  373. egse/lampcontrol/energetiq/lampEQ99_cs.py +0 -128
  374. egse/lampcontrol/energetiq/lampEQ99_devif.py +0 -158
  375. egse/lampcontrol/energetiq/lampEQ99_encode_decode_errors.py +0 -73
  376. egse/lampcontrol/energetiq/lampEQ99_protocol.py +0 -71
  377. egse/lampcontrol/energetiq/lampEQ99_ui.py +0 -465
  378. egse/lib/CentOS-7/EtherSpaceLink_v34_86.dylib +0 -0
  379. egse/lib/CentOS-8/ESL-RMAP_v34_86.dylib +0 -0
  380. egse/lib/CentOS-8/EtherSpaceLink_v34_86.dylib +0 -0
  381. egse/lib/Debian/ESL-RMAP_v34_86.dylib +0 -0
  382. egse/lib/Debian/EtherSpaceLink_v34_86.dylib +0 -0
  383. egse/lib/Debian/libetherspacelink_v35_21.dylib +0 -0
  384. egse/lib/Linux/ESL-RMAP_v34_86.dylib +0 -0
  385. egse/lib/Linux/EtherSpaceLink_v34_86.dylib +0 -0
  386. egse/lib/Ubuntu-20/ESL-RMAP_v34_86.dylib +0 -0
  387. egse/lib/Ubuntu-20/EtherSpaceLink_v34_86.dylib +0 -0
  388. egse/lib/gssw/python3-gssw_2.2.3+31f63c9f-1_all.deb +0 -0
  389. egse/lib/ximc/__pycache__/pyximc.cpython-38 2.pyc +0 -0
  390. egse/lib/ximc/__pycache__/pyximc.cpython-38.pyc +0 -0
  391. egse/lib/ximc/libximc.framework/Frameworks/libbindy.dylib +0 -0
  392. egse/lib/ximc/libximc.framework/Frameworks/libxiwrapper.dylib +0 -0
  393. egse/lib/ximc/libximc.framework/Headers/ximc.h +0 -5510
  394. egse/lib/ximc/libximc.framework/Resources/Info.plist +0 -42
  395. egse/lib/ximc/libximc.framework/Resources/keyfile.sqlite +0 -0
  396. egse/lib/ximc/libximc.framework/libbindy.so +0 -0
  397. egse/lib/ximc/libximc.framework/libximc +0 -0
  398. egse/lib/ximc/libximc.framework/libximc.so +0 -0
  399. egse/lib/ximc/libximc.framework/libximc.so.7.0.0 +0 -0
  400. egse/lib/ximc/libximc.framework/libxiwrapper.so +0 -0
  401. egse/lib/ximc/pyximc.py +0 -922
  402. egse/listener.py +0 -179
  403. egse/logger/__init__.py +0 -243
  404. egse/logger/log_cs.py +0 -321
  405. egse/metrics.py +0 -102
  406. egse/mixin.py +0 -464
  407. egse/monitoring.py +0 -95
  408. egse/ni/alarms/__init__.py +0 -26
  409. egse/ni/alarms/cdaq9375.py +0 -300
  410. egse/ni/alarms/cdaq9375.yaml +0 -89
  411. egse/ni/alarms/cdaq9375_cs.py +0 -130
  412. egse/ni/alarms/cdaq9375_devif.py +0 -183
  413. egse/ni/alarms/cdaq9375_protocol.py +0 -48
  414. egse/obs_inspection.py +0 -165
  415. egse/observer.py +0 -41
  416. egse/obsid.py +0 -163
  417. egse/powermeter/__init__.py +0 -0
  418. egse/powermeter/ni/__init__.py +0 -38
  419. egse/powermeter/ni/cdaq9184.py +0 -224
  420. egse/powermeter/ni/cdaq9184.yaml +0 -73
  421. egse/powermeter/ni/cdaq9184_cs.py +0 -130
  422. egse/powermeter/ni/cdaq9184_devif.py +0 -201
  423. egse/powermeter/ni/cdaq9184_protocol.py +0 -48
  424. egse/powermeter/ni/cdaq9184_ui.py +0 -544
  425. egse/powermeter/thorlabs/__init__.py +0 -25
  426. egse/powermeter/thorlabs/pm100a.py +0 -380
  427. egse/powermeter/thorlabs/pm100a.yaml +0 -132
  428. egse/powermeter/thorlabs/pm100a_cs.py +0 -136
  429. egse/powermeter/thorlabs/pm100a_devif.py +0 -127
  430. egse/powermeter/thorlabs/pm100a_protocol.py +0 -80
  431. egse/powermeter/thorlabs/pm100a_ui.py +0 -725
  432. egse/process.py +0 -451
  433. egse/procman/__init__.py +0 -834
  434. egse/procman/cannot_start_process_popup.py +0 -43
  435. egse/procman/procman.yaml +0 -49
  436. egse/procman/procman_cs.py +0 -201
  437. egse/procman/procman_ui.py +0 -2081
  438. egse/protocol.py +0 -605
  439. egse/proxy.py +0 -531
  440. egse/randomwalk.py +0 -140
  441. egse/reg.py +0 -585
  442. egse/reload.py +0 -122
  443. egse/reprocess.py +0 -693
  444. egse/resource.py +0 -333
  445. egse/rmap.py +0 -406
  446. egse/rst.py +0 -135
  447. egse/search.py +0 -182
  448. egse/serialdevice.py +0 -190
  449. egse/services.py +0 -247
  450. egse/services.yaml +0 -68
  451. egse/settings.py +0 -379
  452. egse/settings.yaml +0 -980
  453. egse/setup.py +0 -1181
  454. egse/shutter/__init__.py +0 -0
  455. egse/shutter/thorlabs/__init__.py +0 -19
  456. egse/shutter/thorlabs/ksc101.py +0 -205
  457. egse/shutter/thorlabs/ksc101.yaml +0 -105
  458. egse/shutter/thorlabs/ksc101_cs.py +0 -136
  459. egse/shutter/thorlabs/ksc101_devif.py +0 -201
  460. egse/shutter/thorlabs/ksc101_protocol.py +0 -71
  461. egse/shutter/thorlabs/ksc101_ui.py +0 -548
  462. egse/shutter/thorlabs/sc10.py +0 -82
  463. egse/shutter/thorlabs/sc10.yaml +0 -52
  464. egse/shutter/thorlabs/sc10_controller.py +0 -81
  465. egse/shutter/thorlabs/sc10_cs.py +0 -108
  466. egse/shutter/thorlabs/sc10_interface.py +0 -25
  467. egse/shutter/thorlabs/sc10_simulator.py +0 -30
  468. egse/simulator.py +0 -41
  469. egse/slack.py +0 -61
  470. egse/socketdevice.py +0 -218
  471. egse/sockets.py +0 -218
  472. egse/spw.py +0 -1401
  473. egse/stages/__init__.py +0 -12
  474. egse/stages/aerotech/ensemble.py +0 -245
  475. egse/stages/aerotech/ensemble.yaml +0 -205
  476. egse/stages/aerotech/ensemble_controller.py +0 -275
  477. egse/stages/aerotech/ensemble_cs.py +0 -110
  478. egse/stages/aerotech/ensemble_interface.py +0 -132
  479. egse/stages/aerotech/ensemble_parameters.py +0 -433
  480. egse/stages/aerotech/ensemble_simulator.py +0 -27
  481. egse/stages/aerotech/mgse_sim.py +0 -188
  482. egse/stages/arun/smd3.py +0 -110
  483. egse/stages/arun/smd3.yaml +0 -68
  484. egse/stages/arun/smd3_controller.py +0 -470
  485. egse/stages/arun/smd3_cs.py +0 -112
  486. egse/stages/arun/smd3_interface.py +0 -53
  487. egse/stages/arun/smd3_simulator.py +0 -27
  488. egse/stages/arun/smd3_stop.py +0 -16
  489. egse/stages/huber/__init__.py +0 -49
  490. egse/stages/huber/smc9300.py +0 -920
  491. egse/stages/huber/smc9300.yaml +0 -63
  492. egse/stages/huber/smc9300_cs.py +0 -178
  493. egse/stages/huber/smc9300_devif.py +0 -345
  494. egse/stages/huber/smc9300_protocol.py +0 -113
  495. egse/stages/huber/smc9300_sim.py +0 -547
  496. egse/stages/huber/smc9300_ui.py +0 -973
  497. egse/state.py +0 -173
  498. egse/statemachine.py +0 -274
  499. egse/storage/__init__.py +0 -1067
  500. egse/storage/persistence.py +0 -2295
  501. egse/storage/storage.yaml +0 -79
  502. egse/storage/storage_cs.py +0 -231
  503. egse/styles/dark.qss +0 -343
  504. egse/styles/default.qss +0 -48
  505. egse/synoptics/__init__.py +0 -417
  506. egse/synoptics/syn.yaml +0 -9
  507. egse/synoptics/syn_cs.py +0 -195
  508. egse/system.py +0 -1611
  509. egse/tcs/__init__.py +0 -14
  510. egse/tcs/tcs.py +0 -879
  511. egse/tcs/tcs.yaml +0 -14
  512. egse/tcs/tcs_cs.py +0 -202
  513. egse/tcs/tcs_devif.py +0 -292
  514. egse/tcs/tcs_protocol.py +0 -180
  515. egse/tcs/tcs_sim.py +0 -177
  516. egse/tcs/tcs_ui.py +0 -543
  517. egse/tdms.py +0 -171
  518. egse/tempcontrol/__init__.py +0 -23
  519. egse/tempcontrol/agilent/agilent34970.py +0 -109
  520. egse/tempcontrol/agilent/agilent34970.yaml +0 -44
  521. egse/tempcontrol/agilent/agilent34970_cs.py +0 -114
  522. egse/tempcontrol/agilent/agilent34970_devif.py +0 -182
  523. egse/tempcontrol/agilent/agilent34970_protocol.py +0 -96
  524. egse/tempcontrol/agilent/agilent34972.py +0 -111
  525. egse/tempcontrol/agilent/agilent34972.yaml +0 -44
  526. egse/tempcontrol/agilent/agilent34972_cs.py +0 -115
  527. egse/tempcontrol/agilent/agilent34972_devif.py +0 -189
  528. egse/tempcontrol/agilent/agilent34972_protocol.py +0 -98
  529. egse/tempcontrol/beaglebone/beaglebone.py +0 -341
  530. egse/tempcontrol/beaglebone/beaglebone.yaml +0 -110
  531. egse/tempcontrol/beaglebone/beaglebone_cs.py +0 -117
  532. egse/tempcontrol/beaglebone/beaglebone_protocol.py +0 -134
  533. egse/tempcontrol/beaglebone/beaglebone_ui.py +0 -674
  534. egse/tempcontrol/digalox/digalox.py +0 -115
  535. egse/tempcontrol/digalox/digalox.yaml +0 -36
  536. egse/tempcontrol/digalox/digalox_cs.py +0 -108
  537. egse/tempcontrol/digalox/digalox_protocol.py +0 -56
  538. egse/tempcontrol/keithley/__init__.py +0 -33
  539. egse/tempcontrol/keithley/daq6510.py +0 -662
  540. egse/tempcontrol/keithley/daq6510.yaml +0 -105
  541. egse/tempcontrol/keithley/daq6510_cs.py +0 -163
  542. egse/tempcontrol/keithley/daq6510_devif.py +0 -343
  543. egse/tempcontrol/keithley/daq6510_protocol.py +0 -79
  544. egse/tempcontrol/keithley/daq6510_sim.py +0 -186
  545. egse/tempcontrol/lakeshore/__init__.py +0 -33
  546. egse/tempcontrol/lakeshore/lsci.py +0 -361
  547. egse/tempcontrol/lakeshore/lsci.yaml +0 -162
  548. egse/tempcontrol/lakeshore/lsci_cs.py +0 -174
  549. egse/tempcontrol/lakeshore/lsci_devif.py +0 -292
  550. egse/tempcontrol/lakeshore/lsci_protocol.py +0 -76
  551. egse/tempcontrol/lakeshore/lsci_ui.py +0 -387
  552. egse/tempcontrol/ni/__init__.py +0 -0
  553. egse/tempcontrol/spid/spid.py +0 -109
  554. egse/tempcontrol/spid/spid.yaml +0 -81
  555. egse/tempcontrol/spid/spid_controller.py +0 -279
  556. egse/tempcontrol/spid/spid_cs.py +0 -136
  557. egse/tempcontrol/spid/spid_protocol.py +0 -107
  558. egse/tempcontrol/spid/spid_ui.py +0 -723
  559. egse/tempcontrol/srs/__init__.py +0 -22
  560. egse/tempcontrol/srs/ptc10.py +0 -867
  561. egse/tempcontrol/srs/ptc10.yaml +0 -227
  562. egse/tempcontrol/srs/ptc10_cs.py +0 -128
  563. egse/tempcontrol/srs/ptc10_devif.py +0 -116
  564. egse/tempcontrol/srs/ptc10_protocol.py +0 -39
  565. egse/tempcontrol/srs/ptc10_ui.py +0 -906
  566. egse/ups/apc/apc.py +0 -236
  567. egse/ups/apc/apc.yaml +0 -45
  568. egse/ups/apc/apc_cs.py +0 -101
  569. egse/ups/apc/apc_protocol.py +0 -125
  570. egse/user.yaml +0 -7
  571. egse/vacuum/beaglebone/beaglebone.py +0 -149
  572. egse/vacuum/beaglebone/beaglebone.yaml +0 -44
  573. egse/vacuum/beaglebone/beaglebone_cs.py +0 -108
  574. egse/vacuum/beaglebone/beaglebone_devif.py +0 -159
  575. egse/vacuum/beaglebone/beaglebone_protocol.py +0 -192
  576. egse/vacuum/beaglebone/beaglebone_ui.py +0 -638
  577. egse/vacuum/instrutech/igm402.py +0 -91
  578. egse/vacuum/instrutech/igm402.yaml +0 -90
  579. egse/vacuum/instrutech/igm402_controller.py +0 -124
  580. egse/vacuum/instrutech/igm402_cs.py +0 -108
  581. egse/vacuum/instrutech/igm402_interface.py +0 -49
  582. egse/vacuum/instrutech/igm402_simulator.py +0 -36
  583. egse/vacuum/keller/kellerBus.py +0 -256
  584. egse/vacuum/keller/leo3.py +0 -100
  585. egse/vacuum/keller/leo3.yaml +0 -38
  586. egse/vacuum/keller/leo3_controller.py +0 -81
  587. egse/vacuum/keller/leo3_cs.py +0 -101
  588. egse/vacuum/keller/leo3_interface.py +0 -33
  589. egse/vacuum/mks/evision.py +0 -86
  590. egse/vacuum/mks/evision.yaml +0 -75
  591. egse/vacuum/mks/evision_cs.py +0 -101
  592. egse/vacuum/mks/evision_devif.py +0 -313
  593. egse/vacuum/mks/evision_interface.py +0 -60
  594. egse/vacuum/mks/evision_simulator.py +0 -24
  595. egse/vacuum/mks/evision_ui.py +0 -701
  596. egse/vacuum/pfeiffer/acp40.py +0 -87
  597. egse/vacuum/pfeiffer/acp40.yaml +0 -60
  598. egse/vacuum/pfeiffer/acp40_controller.py +0 -117
  599. egse/vacuum/pfeiffer/acp40_cs.py +0 -109
  600. egse/vacuum/pfeiffer/acp40_interface.py +0 -40
  601. egse/vacuum/pfeiffer/acp40_simulator.py +0 -37
  602. egse/vacuum/pfeiffer/tc400.py +0 -87
  603. egse/vacuum/pfeiffer/tc400.yaml +0 -83
  604. egse/vacuum/pfeiffer/tc400_controller.py +0 -136
  605. egse/vacuum/pfeiffer/tc400_cs.py +0 -109
  606. egse/vacuum/pfeiffer/tc400_interface.py +0 -70
  607. egse/vacuum/pfeiffer/tc400_simulator.py +0 -35
  608. egse/vacuum/pfeiffer/tpg261.py +0 -80
  609. egse/vacuum/pfeiffer/tpg261.yaml +0 -66
  610. egse/vacuum/pfeiffer/tpg261_controller.py +0 -150
  611. egse/vacuum/pfeiffer/tpg261_cs.py +0 -109
  612. egse/vacuum/pfeiffer/tpg261_interface.py +0 -59
  613. egse/vacuum/pfeiffer/tpg261_simulator.py +0 -23
  614. egse/version.py +0 -174
  615. egse/visitedpositions.py +0 -398
  616. egse/windowing.py +0 -213
  617. egse/zmq/__init__.py +0 -28
  618. egse/zmq/spw.py +0 -160
  619. egse/zmq_ser.py +0 -41
  620. scripts/alerts/cold.yaml +0 -278
  621. scripts/alerts/example_alerts.yaml +0 -54
  622. scripts/alerts/transition.yaml +0 -14
  623. scripts/alerts/warm.yaml +0 -49
  624. scripts/analyse_n_fee_hk_data.py +0 -52
  625. scripts/check_hdf5_files.py +0 -192
  626. scripts/check_register_sync.py +0 -47
  627. scripts/check_tcs_calib_coef.py +0 -90
  628. scripts/correct_ccd_cold_temperature_cal.py +0 -157
  629. scripts/create_hdf5_report.py +0 -293
  630. scripts/csl_model.py +0 -420
  631. scripts/csl_restore_setup.py +0 -229
  632. scripts/export-grafana-dashboards.py +0 -49
  633. scripts/fdir/cs_recovery/fdir_cs_recovery.py +0 -54
  634. scripts/fdir/fdir_table.yaml +0 -70
  635. scripts/fdir/fdir_test_recovery.py +0 -10
  636. scripts/fdir/hw_recovery/fdir_agilent_hw_recovery.py +0 -73
  637. scripts/fdir/limit_recovery/fdir_agilent_limit.py +0 -61
  638. scripts/fdir/limit_recovery/fdir_bb_heater_limit.py +0 -59
  639. scripts/fdir/limit_recovery/fdir_ensemble_limit.py +0 -33
  640. scripts/fdir/limit_recovery/fdir_pressure_limit_recovery.py +0 -71
  641. scripts/fix_csv.py +0 -80
  642. scripts/ias/correct_ccd_temp_cal_elfique.py +0 -43
  643. scripts/ias/correct_ccd_temp_cal_floreffe.py +0 -43
  644. scripts/ias/correct_trp_swap_achel.py +0 -199
  645. scripts/inta/correct_ccd_temp_cal_duvel.py +0 -43
  646. scripts/inta/correct_ccd_temp_cal_gueuze.py +0 -43
  647. scripts/n_fee_supply_voltage_calculation.py +0 -92
  648. scripts/playground.py +0 -30
  649. scripts/print_hdf5_hk_data.py +0 -68
  650. scripts/print_register_map.py +0 -43
  651. scripts/remove_lines_between_matches.py +0 -188
  652. scripts/sron/commanding/control_heaters.py +0 -44
  653. scripts/sron/commanding/pumpdown.py +0 -46
  654. scripts/sron/commanding/set_pid_setpoint.py +0 -19
  655. scripts/sron/commanding/shutdown_bbb_heaters.py +0 -10
  656. scripts/sron/commanding/shutdown_pumps.py +0 -33
  657. scripts/sron/correct_mgse_coordinates_brigand_chimay.py +0 -272
  658. scripts/sron/correct_trp_swap_brigand.py +0 -204
  659. scripts/sron/gimbal_conversions.py +0 -75
  660. scripts/sron/tm_gen/tm_gen_agilent.py +0 -37
  661. scripts/sron/tm_gen/tm_gen_heaters.py +0 -4
  662. scripts/sron/tm_gen/tm_gen_spid.py +0 -13
  663. scripts/update_operational_cgse.py +0 -268
  664. 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())