microeye 2.3.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 (190) hide show
  1. microEye/__init__.py +47 -0
  2. microEye/_version.py +2 -0
  3. microEye/analysis/__init__.py +1 -0
  4. microEye/analysis/checklist_dialog.py +143 -0
  5. microEye/analysis/cmosMaps.py +228 -0
  6. microEye/analysis/filters/__init__.py +9 -0
  7. microEye/analysis/filters/base.py +21 -0
  8. microEye/analysis/filters/spatial.py +338 -0
  9. microEye/analysis/filters/temporal.py +76 -0
  10. microEye/analysis/fitting/__init__.py +0 -0
  11. microEye/analysis/fitting/fit.py +680 -0
  12. microEye/analysis/fitting/nena.py +375 -0
  13. microEye/analysis/fitting/phasor_fit.py +90 -0
  14. microEye/analysis/fitting/processing.py +317 -0
  15. microEye/analysis/fitting/psf/__init__.py +6 -0
  16. microEye/analysis/fitting/psf/extract.py +1129 -0
  17. microEye/analysis/fitting/psf/rubost_mean.py +150 -0
  18. microEye/analysis/fitting/psf/spline.py +167 -0
  19. microEye/analysis/fitting/psf/stats/__init__.py +12 -0
  20. microEye/analysis/fitting/psf/stats/core.py +295 -0
  21. microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
  22. microEye/analysis/fitting/psf/stats/io.py +104 -0
  23. microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
  24. microEye/analysis/fitting/psf/temp.py +147 -0
  25. microEye/analysis/fitting/psf/test.py +47 -0
  26. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
  27. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
  28. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
  29. microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
  30. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
  31. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
  32. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
  33. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
  34. microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
  35. microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
  36. microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
  37. microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
  38. microEye/analysis/fitting/results.py +917 -0
  39. microEye/analysis/fitting/results_stats.py +251 -0
  40. microEye/analysis/fitting/tardis.py +209 -0
  41. microEye/analysis/multi_viewer.py +568 -0
  42. microEye/analysis/processing/__init__.py +1 -0
  43. microEye/analysis/processing/frc.py +120 -0
  44. microEye/analysis/rendering/__init__.py +3 -0
  45. microEye/analysis/rendering/base.py +452 -0
  46. microEye/analysis/rendering/cloud.py +215 -0
  47. microEye/analysis/rendering/core.py +47 -0
  48. microEye/analysis/rendering/volumetric.py +198 -0
  49. microEye/analysis/tools/__init__.py +0 -0
  50. microEye/analysis/tools/kymograms.py +1079 -0
  51. microEye/analysis/tools/roi_selectors.py +556 -0
  52. microEye/analysis/utils/__init__.py +3 -0
  53. microEye/analysis/utils/coordinates.py +18 -0
  54. microEye/analysis/utils/images.py +68 -0
  55. microEye/analysis/utils/windows.py +19 -0
  56. microEye/analysis/viewer/__init__.py +3 -0
  57. microEye/analysis/viewer/image_options_widget.py +615 -0
  58. microEye/analysis/viewer/images.py +1225 -0
  59. microEye/analysis/viewer/layers_widget.py +415 -0
  60. microEye/analysis/viewer/localizations.py +1304 -0
  61. microEye/analysis/viewer/psf.py +1003 -0
  62. microEye/analysis/viewer/volume.py +456 -0
  63. microEye/hardware/__init__.py +3 -0
  64. microEye/hardware/cams/__init__.py +29 -0
  65. microEye/hardware/cams/camera_calibration.py +99 -0
  66. microEye/hardware/cams/camera_list.py +528 -0
  67. microEye/hardware/cams/camera_options.py +694 -0
  68. microEye/hardware/cams/camera_panel.py +941 -0
  69. microEye/hardware/cams/dummy/__init__.py +1 -0
  70. microEye/hardware/cams/dummy/dummy_panel.py +759 -0
  71. microEye/hardware/cams/jobs.py +497 -0
  72. microEye/hardware/cams/line_profiler.py +99 -0
  73. microEye/hardware/cams/linescan/IR_Cam.py +474 -0
  74. microEye/hardware/cams/linescan/__init__.py +1 -0
  75. microEye/hardware/cams/micam.py +524 -0
  76. microEye/hardware/cams/pco/__init__.py +58 -0
  77. microEye/hardware/cams/pco/enums.py +382 -0
  78. microEye/hardware/cams/pco/pco_cam.py +761 -0
  79. microEye/hardware/cams/pco/pco_panel.py +477 -0
  80. microEye/hardware/cams/shortcuts.py +312 -0
  81. microEye/hardware/cams/thorlabs/__init__.py +1 -0
  82. microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
  83. microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
  84. microEye/hardware/cams/ueye/__init__.py +1 -0
  85. microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
  86. microEye/hardware/cams/ueye/ueye_panel.py +861 -0
  87. microEye/hardware/cams/vimba/__init__.py +1 -0
  88. microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
  89. microEye/hardware/cams/vimba/vimba_panel.py +813 -0
  90. microEye/hardware/device.py +60 -0
  91. microEye/hardware/lasers/__init__.py +13 -0
  92. microEye/hardware/lasers/io_matchbox.py +791 -0
  93. microEye/hardware/lasers/io_params.py +85 -0
  94. microEye/hardware/lasers/io_single_laser.py +742 -0
  95. microEye/hardware/lasers/laser_relay.py +594 -0
  96. microEye/hardware/mieye/__init__.py +1 -0
  97. microEye/hardware/mieye/acquisition_manager.py +467 -0
  98. microEye/hardware/mieye/devices_manager.py +533 -0
  99. microEye/hardware/mieye/miEye.py +659 -0
  100. microEye/hardware/misc/__init__.py +0 -0
  101. microEye/hardware/misc/acquisition_view.py +71 -0
  102. microEye/hardware/misc/reglo.py +761 -0
  103. microEye/hardware/misc/temp.py +188 -0
  104. microEye/hardware/port_config.py +59 -0
  105. microEye/hardware/protocols/__init__.py +2 -0
  106. microEye/hardware/protocols/actions.py +402 -0
  107. microEye/hardware/protocols/actions_items.py +703 -0
  108. microEye/hardware/protocols/designer.py +244 -0
  109. microEye/hardware/protocols/scene_manager.py +191 -0
  110. microEye/hardware/protocols/serialization.py +97 -0
  111. microEye/hardware/pycromanager/__init__.py +16 -0
  112. microEye/hardware/pycromanager/core.py +1433 -0
  113. microEye/hardware/pycromanager/devices.py +461 -0
  114. microEye/hardware/pycromanager/enums.py +107 -0
  115. microEye/hardware/pycromanager/headless.py +153 -0
  116. microEye/hardware/pycromanager/utils.py +34 -0
  117. microEye/hardware/pycromanager/widgets/__init__.py +5 -0
  118. microEye/hardware/pycromanager/widgets/bridges.py +407 -0
  119. microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
  120. microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
  121. microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
  122. microEye/hardware/stages/__init__.py +18 -0
  123. microEye/hardware/stages/elliptec/__init__.py +5 -0
  124. microEye/hardware/stages/elliptec/baseDevice.py +314 -0
  125. microEye/hardware/stages/elliptec/device.py +384 -0
  126. microEye/hardware/stages/elliptec/deviceID.py +212 -0
  127. microEye/hardware/stages/elliptec/devicePort.py +379 -0
  128. microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
  129. microEye/hardware/stages/elliptec/devicesView.py +706 -0
  130. microEye/hardware/stages/elliptec/ellDevices.py +134 -0
  131. microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
  132. microEye/hardware/stages/elliptec/motorInfo.py +153 -0
  133. microEye/hardware/stages/elliptec/stage.py +62 -0
  134. microEye/hardware/stages/elliptec/test.py +139 -0
  135. microEye/hardware/stages/kinesis/__init__.py +1 -0
  136. microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
  137. microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
  138. microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
  139. microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
  140. microEye/hardware/stages/kinesis/kinesis.py +776 -0
  141. microEye/hardware/stages/piezo_concept.py +607 -0
  142. microEye/hardware/stages/stabilizer.py +785 -0
  143. microEye/hardware/stages/stage.py +89 -0
  144. microEye/hardware/widgets/__init__.py +10 -0
  145. microEye/hardware/widgets/controller.py +246 -0
  146. microEye/hardware/widgets/devices.py +133 -0
  147. microEye/hardware/widgets/focusWidget.py +264 -0
  148. microEye/hardware/widgets/qlist_slider.py +113 -0
  149. microEye/hardware/widgets/scan_acquisition.py +424 -0
  150. microEye/icons/1024.png +0 -0
  151. microEye/icons/128.png +0 -0
  152. microEye/icons/16.png +0 -0
  153. microEye/icons/24.png +0 -0
  154. microEye/icons/256.png +0 -0
  155. microEye/icons/32.png +0 -0
  156. microEye/icons/48.png +0 -0
  157. microEye/icons/512.png +0 -0
  158. microEye/icons/64.png +0 -0
  159. microEye/icons/__init__.py +0 -0
  160. microEye/icons/close.svg +88 -0
  161. microEye/icons/mieye.png +0 -0
  162. microEye/icons/min.svg +83 -0
  163. microEye/icons/viewer.png +0 -0
  164. microEye/launcher.py +42 -0
  165. microEye/qt.py +181 -0
  166. microEye/utils/__init__.py +2 -0
  167. microEye/utils/enum_encoder.py +10 -0
  168. microEye/utils/expandable_groupbox.py +93 -0
  169. microEye/utils/gui_helper.py +457 -0
  170. microEye/utils/hid/__init__.py +8 -0
  171. microEye/utils/hid/controller.py +153 -0
  172. microEye/utils/hid/device.py +63 -0
  173. microEye/utils/hid/enums.py +140 -0
  174. microEye/utils/hid/utils.py +58 -0
  175. microEye/utils/labelled_slider.py +134 -0
  176. microEye/utils/metadata.py +599 -0
  177. microEye/utils/metadata_tree.py +718 -0
  178. microEye/utils/micro_launcher.py +245 -0
  179. microEye/utils/parameter_tree.py +325 -0
  180. microEye/utils/pyscripting.py +444 -0
  181. microEye/utils/retry_exec.py +35 -0
  182. microEye/utils/start_gui.py +112 -0
  183. microEye/utils/thread_worker.py +115 -0
  184. microEye/utils/uImage.py +1512 -0
  185. microeye-2.3.2.dist-info/METADATA +401 -0
  186. microeye-2.3.2.dist-info/RECORD +190 -0
  187. microeye-2.3.2.dist-info/WHEEL +5 -0
  188. microeye-2.3.2.dist-info/entry_points.txt +2 -0
  189. microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
  190. microeye-2.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1002 @@
1
+ import struct
2
+ from dataclasses import dataclass
3
+ from enum import Enum, IntFlag, auto
4
+ from typing import Any, Optional, Union
5
+
6
+
7
+ class CommandType(Enum):
8
+ GENERIC = auto()
9
+ CHANNEL = auto()
10
+ COMPLEX = auto()
11
+
12
+
13
+ class DataType(Enum):
14
+ WORD = 'H' # Unsigned 16-bit integer
15
+ SHORT = 'h' # Signed 16-bit integer
16
+ DWORD = 'I' # Unsigned 32-bit integer
17
+ LONG = 'i' # Signed 32-bit integer
18
+ CHAR = 'B' # 1 byte
19
+ STRING = 's' # String of N characters
20
+
21
+
22
+ @dataclass
23
+ class DataField:
24
+ name: str
25
+ data_type: DataType
26
+ length: int = 1 # For strings, specify the number of characters
27
+
28
+
29
+ @dataclass
30
+ class PacketStructure:
31
+ data_fields: list[DataField]
32
+
33
+ @property
34
+ def has_data(self) -> bool:
35
+ return len(self.data_fields) > 0
36
+
37
+ @property
38
+ def has_length(self) -> bool:
39
+ return any(field.name == 'length' for field in self.data_fields)
40
+
41
+
42
+ class KDC101_RESPONSES(Enum):
43
+ def __init__(self, value, packet: Optional[PacketStructure] = None):
44
+ self._value_ = value
45
+ self.packet = packet
46
+
47
+
48
+ MGMSG_MOD_GET_CHANENABLESTATE = (
49
+ 0x0212,
50
+ PacketStructure(
51
+ [
52
+ DataField('id', DataType.WORD),
53
+ DataField('channel', DataType.CHAR),
54
+ DataField('enable_state', DataType.CHAR),
55
+ DataField('destination', DataType.CHAR),
56
+ DataField('source', DataType.CHAR),
57
+ ]
58
+ ),
59
+ )
60
+ '''Response of MGMSG_MOD_REQ_CHANENABLESTATE'''
61
+
62
+ MGMSG_HW_RESPONSE = (
63
+ 0x0080,
64
+ PacketStructure(
65
+ [
66
+ DataField('id', DataType.WORD),
67
+ DataField('code', DataType.WORD),
68
+ DataField('destination', DataType.CHAR),
69
+ DataField('source', DataType.CHAR),
70
+ ]
71
+ ),
72
+ )
73
+ '''Sent by the controllers to notify Thorlabs Server of some event that
74
+ requires user intervention, usually some fault or error condition that
75
+ needs to be handled before normal operation can resume.
76
+
77
+ The message transmits the fault code as a numerical value – see the
78
+ Return Codes listed in the Thorlabs Server helpfile for details on the
79
+ specific return codes.
80
+ '''
81
+ MGMSG_HW_RICHRESPONSE = (
82
+ 0x0081,
83
+ PacketStructure(
84
+ [
85
+ DataField('id', DataType.WORD),
86
+ DataField('length', DataType.WORD),
87
+ DataField('destination', DataType.CHAR),
88
+ DataField('source', DataType.CHAR),
89
+ DataField('msg_id', DataType.WORD),
90
+ DataField('code', DataType.WORD),
91
+ DataField('notes', DataType.STRING, length=64),
92
+ ]
93
+ ),
94
+ )
95
+ '''
96
+ Similarly, to HW_RESPONSE, this message is sent by the controllers
97
+ to notify Thorlabs Server of some event that requires user
98
+ intervention,
99
+
100
+ usually some fault or error condition that needs to be
101
+ handled before normal operation can resume.
102
+
103
+ However, unlike HW_RESPONSE, this message also transmits a printable text string.
104
+
105
+ Upon receiving the message, Thorlabs Server displays both the
106
+ numerical value and the text information, which is useful in finding
107
+ the cause of the problem.
108
+ '''
109
+
110
+ MGMSG_HW_GET_INFO = (
111
+ 0x0006,
112
+ PacketStructure(
113
+ [
114
+ DataField('id', DataType.WORD),
115
+ DataField('length', DataType.WORD),
116
+ DataField('destination', DataType.CHAR),
117
+ DataField('source', DataType.CHAR),
118
+ DataField('serial number', DataType.LONG),
119
+ DataField('model', DataType.STRING, length=8),
120
+ DataField('type', DataType.WORD),
121
+ DataField('minor revision number', DataType.CHAR),
122
+ DataField('interim revision number', DataType.CHAR),
123
+ DataField('major revision number', DataType.CHAR),
124
+ DataField('unused', DataType.CHAR),
125
+ DataField('hw version', DataType.WORD),
126
+ DataField('mod state', DataType.WORD),
127
+ DataField('nchs', DataType.WORD),
128
+ ]
129
+ ),
130
+ )
131
+ '''Response of MGMSG_HW_REQ_INFO'''
132
+
133
+ MGMSG_HUB_GET_BAYUSED = (
134
+ 0x0066,
135
+ PacketStructure(
136
+ [
137
+ DataField('id', DataType.WORD),
138
+ DataField('bay id', DataType.CHAR),
139
+ DataField('unused', DataType.CHAR),
140
+ DataField('destination', DataType.CHAR),
141
+ DataField('source', DataType.CHAR),
142
+ ]
143
+ ),
144
+ )
145
+ '''Response of MGMSG_HUB_REQ_BAYUSED'''
146
+
147
+ MGMSG_MOT_GET_POSCOUNTER = (
148
+ 0x0412,
149
+ PacketStructure(
150
+ [
151
+ DataField('id', DataType.WORD),
152
+ DataField('length', DataType.WORD),
153
+ DataField('destination', DataType.CHAR),
154
+ DataField('source', DataType.CHAR),
155
+ DataField('channel', DataType.WORD),
156
+ DataField('position', DataType.LONG),
157
+ ]
158
+ ),
159
+ )
160
+ '''Response of MGMSG_MOT_REQ_POSCOUNTER'''
161
+
162
+ MGMSG_MOT_GET_ENCCOUNTER = (
163
+ 0x040B,
164
+ PacketStructure(
165
+ [
166
+ DataField('id', DataType.WORD),
167
+ DataField('length', DataType.WORD),
168
+ DataField('destination', DataType.CHAR),
169
+ DataField('source', DataType.CHAR),
170
+ DataField('channel', DataType.WORD),
171
+ DataField('encoder count', DataType.LONG),
172
+ ]
173
+ ),
174
+ )
175
+ '''Response of MGMSG_MOT_REQ_ENCCOUNTER'''
176
+
177
+ MGMSG_MOT_GET_VELPARAMS = (
178
+ 0x0415,
179
+ PacketStructure(
180
+ [
181
+ DataField('id', DataType.WORD),
182
+ DataField('length', DataType.WORD),
183
+ DataField('destination', DataType.CHAR),
184
+ DataField('source', DataType.CHAR),
185
+ DataField('channel', DataType.WORD),
186
+ DataField('min velocity', DataType.LONG),
187
+ DataField('acceleration', DataType.LONG),
188
+ DataField('max velocity', DataType.LONG),
189
+ ]
190
+ ),
191
+ )
192
+ '''Response of MGMSG_MOT_REQ_VELPARAMS'''
193
+
194
+ MGMSG_MOT_GET_JOGPARAMS = (
195
+ 0x0418,
196
+ PacketStructure(
197
+ [
198
+ DataField('id', DataType.WORD),
199
+ DataField('length', DataType.WORD),
200
+ DataField('destination', DataType.CHAR),
201
+ DataField('source', DataType.CHAR),
202
+ DataField('channel', DataType.WORD),
203
+ DataField('jog mode', DataType.WORD),
204
+ DataField('jog step size', DataType.LONG),
205
+ DataField('jog min velocity', DataType.LONG),
206
+ DataField('jog acceleration', DataType.LONG),
207
+ DataField('jog max velocity', DataType.LONG),
208
+ DataField('jog stop mode', DataType.WORD),
209
+ ]
210
+ ),
211
+ )
212
+ '''Response of MGMSG_MOT_REQ_JOGPARAMS'''
213
+
214
+ MGMSG_MOT_GET_LIMSWITCHPARAMS = (
215
+ 0x0425,
216
+ PacketStructure(
217
+ [
218
+ DataField('id', DataType.WORD),
219
+ DataField('length', DataType.WORD),
220
+ DataField('destination', DataType.CHAR),
221
+ DataField('source', DataType.CHAR),
222
+ DataField('channel', DataType.WORD),
223
+ DataField('cw hard limit', DataType.WORD),
224
+ DataField('ccw hard limit', DataType.WORD),
225
+ DataField('cw soft limit', DataType.LONG),
226
+ DataField('ccw soft limit', DataType.LONG),
227
+ DataField('soft limit mode', DataType.WORD),
228
+ ]
229
+ ),
230
+ )
231
+ '''Response of MGMSG_MOT_REQ_LIMSWITCHPARAMS'''
232
+
233
+ MGMSG_MOT_GET_GENMOVEPARAMS = (
234
+ 0x043C,
235
+ PacketStructure(
236
+ [
237
+ DataField('id', DataType.WORD),
238
+ DataField('length', DataType.WORD),
239
+ DataField('destination', DataType.CHAR),
240
+ DataField('source', DataType.CHAR),
241
+ DataField('channel', DataType.WORD),
242
+ DataField('distance', DataType.LONG),
243
+ ]
244
+ ),
245
+ )
246
+ '''Response of MGMSG_MOT_REQ_GENMOVEPARAMS'''
247
+
248
+ MGMSG_MOT_GET_HOMEPARAMS = (
249
+ 0x0442,
250
+ PacketStructure(
251
+ [
252
+ DataField('id', DataType.WORD),
253
+ DataField('length', DataType.WORD),
254
+ DataField('destination', DataType.CHAR),
255
+ DataField('source', DataType.CHAR),
256
+ DataField('channel', DataType.WORD),
257
+ DataField('direction', DataType.WORD),
258
+ DataField('limit switch', DataType.WORD),
259
+ DataField('velocity', DataType.LONG),
260
+ DataField('zero offset', DataType.LONG),
261
+ ]
262
+ ),
263
+ )
264
+ '''Response of MGMSG_MOT_REQ_HOMEPARAMS'''
265
+
266
+ MGMSG_MOT_MOVE_HOMED = (
267
+ 0x0444,
268
+ PacketStructure(
269
+ [
270
+ DataField('id', DataType.WORD),
271
+ DataField('channel', DataType.CHAR),
272
+ DataField('unused', DataType.CHAR),
273
+ DataField('destination', DataType.CHAR),
274
+ DataField('source', DataType.CHAR),
275
+ ]
276
+ ),
277
+ )
278
+ '''
279
+ No response on initial message, but upon completion of home
280
+ sequence controller sends a “homing completed” message'''
281
+
282
+ MGMSG_MOT_GET_MOVERELPARAMS = (
283
+ 0x0447,
284
+ PacketStructure(
285
+ [
286
+ DataField('id', DataType.WORD),
287
+ DataField('length', DataType.WORD),
288
+ DataField('destination', DataType.CHAR),
289
+ DataField('source', DataType.CHAR),
290
+ DataField('channel', DataType.WORD),
291
+ DataField('distance', DataType.LONG),
292
+ ]
293
+ ),
294
+ )
295
+ '''Response of MGMSG_MOT_REQ_MOVERELPARAMS'''
296
+
297
+ MGMSG_MOT_GET_MOVEABSPARAMS = (
298
+ 0x0452,
299
+ PacketStructure(
300
+ [
301
+ DataField('id', DataType.WORD),
302
+ DataField('length', DataType.WORD),
303
+ DataField('destination', DataType.CHAR),
304
+ DataField('source', DataType.CHAR),
305
+ DataField('channel', DataType.WORD),
306
+ DataField('position', DataType.LONG),
307
+ ]
308
+ ),
309
+ )
310
+ '''Response of MGMSG_MOT_REQ_MOVEABSPARAMS'''
311
+
312
+ MGMSG_MOT_MOVE_COMPLETED = (
313
+ 0x0464,
314
+ PacketStructure(
315
+ [
316
+ DataField('id', DataType.WORD),
317
+ DataField('channel', DataType.CHAR),
318
+ DataField('unused', DataType.CHAR),
319
+ DataField('destination', DataType.CHAR),
320
+ DataField('source', DataType.CHAR),
321
+ # MOT DC STATUS
322
+ DataField('channel', DataType.WORD),
323
+ DataField('position', DataType.LONG),
324
+ DataField('velocity', DataType.WORD),
325
+ DataField('motor current', DataType.WORD),
326
+ DataField('status bits', DataType.DWORD),
327
+ ]
328
+ ),
329
+ )
330
+ '''
331
+ No response on initial message, but upon completion of the relative
332
+ or absolute move sequence, the controller sends a “move
333
+ completed” message.
334
+ '''
335
+
336
+ MGMSG_MOT_MOVE_STOPPED = (
337
+ 0x0466,
338
+ PacketStructure(
339
+ [
340
+ DataField('id', DataType.WORD),
341
+ DataField('length', DataType.WORD),
342
+ DataField('destination', DataType.CHAR),
343
+ DataField('source', DataType.CHAR),
344
+ # MOT DC STATUS
345
+ DataField('channel', DataType.WORD),
346
+ DataField('position', DataType.LONG),
347
+ DataField('velocity', DataType.WORD),
348
+ DataField('motor current', DataType.WORD),
349
+ DataField('status bits', DataType.DWORD),
350
+ ]
351
+ ),
352
+ )
353
+ '''
354
+ No response on initial message, but upon completion of the stop
355
+ move, the controller sends a “move stopped” message.
356
+ '''
357
+
358
+ MGMSG_MOT_GET_DCSTATUSUPDATE = (
359
+ 0x0491,
360
+ PacketStructure(
361
+ [
362
+ DataField('id', DataType.WORD),
363
+ DataField('length', DataType.WORD),
364
+ DataField('destination', DataType.CHAR),
365
+ DataField('source', DataType.CHAR),
366
+ # MOT DC STATUS
367
+ DataField('channel', DataType.WORD),
368
+ DataField('position', DataType.LONG),
369
+ DataField('velocity', DataType.WORD),
370
+ DataField('motor current', DataType.WORD),
371
+ DataField('status bits', DataType.DWORD),
372
+ ]
373
+ ),
374
+ )
375
+ '''Response of MGMSG_MOT_REQ_DCSTATUSUPDATE'''
376
+
377
+ # MGMSG_MOT_ACK_DCSTATUSUPDATE = 0x0492
378
+ '''Acknowledgement of MGMSG_MOT_REQ_DCSTATUSUPDATE
379
+
380
+ Only Applicable If Using USB COMMS. Does not apply to RS-232 COMMS'''
381
+
382
+ MGMSG_MOT_GET_STATUSBITS = (
383
+ 0x042A,
384
+ PacketStructure(
385
+ [
386
+ DataField('id', DataType.WORD),
387
+ DataField('length', DataType.WORD),
388
+ DataField('destination', DataType.CHAR),
389
+ DataField('source', DataType.CHAR),
390
+ DataField('channel', DataType.WORD),
391
+ DataField('status bits', DataType.DWORD),
392
+ ]
393
+ ),
394
+ )
395
+ '''Response of MGMSG_MOT_REQ_STATUSBITS'''
396
+
397
+ @classmethod
398
+ def get(cls, response: Union[int, list]):
399
+ '''Get the response enum for a given response code.'''
400
+ try:
401
+ if isinstance(response, list):
402
+ if len(response) < 2:
403
+ raise ValueError('Not enough bytes to get command.')
404
+
405
+ response = (response[1] << 8) | response[0]
406
+
407
+ if not isinstance(response, int):
408
+ raise ValueError(
409
+ 'Command must be an integer or list of integers/bytes.'
410
+ )
411
+
412
+ # Iterate through enum members to find the one with the matching value
413
+ for member in cls:
414
+ if member.value == response:
415
+ return member
416
+ except ValueError:
417
+ return None
418
+
419
+
420
+ class KDC101_CMDS(Enum):
421
+ def __init__(
422
+ self,
423
+ value,
424
+ cmd_type: CommandType,
425
+ packet: Optional[PacketStructure] = None,
426
+ response: Optional[KDC101_RESPONSES] = None,
427
+ ):
428
+ self._value_ = value
429
+ self.cmd_type = cmd_type
430
+ self.packet = packet
431
+ self.response = response
432
+
433
+ MGMSG_MOD_IDENTIFY = (0x0223, CommandType.CHANNEL)
434
+ '''Instruct hardware unit to identify itself (by flashing its front panel
435
+ LEDs).'''
436
+
437
+ MGMSG_MOD_SET_CHANENABLESTATE = (0x0210, CommandType.CHANNEL)
438
+ '''Sent to enable or disable the specified drive channel.'''
439
+ MGMSG_MOD_REQ_CHANENABLESTATE = (
440
+ 0x0211,
441
+ CommandType.CHANNEL,
442
+ None,
443
+ KDC101_RESPONSES.MGMSG_MOD_GET_CHANENABLESTATE,
444
+ )
445
+ '''Sent to request the enable state of the specified drive channel.'''
446
+
447
+ MGMSG_HW_DISCONNECT = (0x0002, CommandType.GENERIC)
448
+ '''Sent by the hardware unit or host to disconnect from the
449
+ Ethernet/USB bus.'''
450
+
451
+ MGMSG_HW_START_UPDATEMSGS = (0x0011, CommandType.GENERIC)
452
+ '''Sent to start automatic status updates from the embedded controller.'''
453
+ MGMSG_HW_STOP_UPDATEMSGS = (0x0012, CommandType.GENERIC)
454
+ '''
455
+ Sent to stop automatic status updates from the controller – usually
456
+ called by a client application when it is shutting down, to instruct
457
+ the controller to turn off status updates to prevent USB buffer
458
+ overflows on the PC.
459
+ '''
460
+
461
+ MGMSG_HW_REQ_INFO = (
462
+ 0x0005,
463
+ CommandType.GENERIC,
464
+ None,
465
+ KDC101_RESPONSES.MGMSG_HW_GET_INFO,
466
+ )
467
+ '''Sent to request hardware information from the controller.'''
468
+
469
+ MGMSG_HUB_REQ_BAYUSED = (
470
+ 0x0065,
471
+ CommandType.GENERIC,
472
+ None,
473
+ KDC101_RESPONSES.MGMSG_HUB_GET_BAYUSED,
474
+ )
475
+ '''Sent to determine to which bay a specific unit is fitted.'''
476
+
477
+ MGMSG_MOT_REQ_POSCOUNTER = (
478
+ 0x0411,
479
+ CommandType.CHANNEL,
480
+ None,
481
+ KDC101_RESPONSES.MGMSG_MOT_GET_POSCOUNTER,
482
+ )
483
+ '''Used to request the ‘live’ position count in the controller.'''
484
+
485
+ MGMSG_MOT_REQ_ENCCOUNTER = (
486
+ 0x040A,
487
+ CommandType.CHANNEL,
488
+ None,
489
+ KDC101_RESPONSES.MGMSG_MOT_GET_ENCCOUNTER,
490
+ )
491
+ '''
492
+ Used to set the encoder count in the controller and is
493
+ only applicable to stages and actuators fitted with an encoder.
494
+ '''
495
+
496
+ MGMSG_MOT_SET_VELPARAMS = (
497
+ 0x0413,
498
+ CommandType.COMPLEX,
499
+ PacketStructure(
500
+ [
501
+ DataField('min_velocity', DataType.LONG),
502
+ DataField('acceleration', DataType.LONG),
503
+ DataField('max_velocity', DataType.LONG),
504
+ ]
505
+ ),
506
+ )
507
+ '''
508
+ Used to set the trapezoidal velocity parameters for the specified
509
+ motor channel.
510
+
511
+ For DC servo controllers, the velocity is set in
512
+ encoder counts/sec and acceleration is set in encoder
513
+ counts/sec/sec.
514
+
515
+ For stepper motor controllers the velocity is set in microsteps/sec
516
+ and acceleration is set in microsteps/sec/sec.'''
517
+ MGMSG_MOT_REQ_VELPARAMS = (
518
+ 0x0414,
519
+ CommandType.CHANNEL,
520
+ None,
521
+ KDC101_RESPONSES.MGMSG_MOT_GET_VELPARAMS,
522
+ )
523
+ '''
524
+ Used to request the trapezoidal velocity parameters for the specified motor channel.
525
+ '''
526
+
527
+ MGMSG_MOT_SET_JOGPARAMS = (
528
+ 0x0416,
529
+ CommandType.COMPLEX,
530
+ PacketStructure(
531
+ [
532
+ DataField('jog_mode', DataType.WORD),
533
+ DataField('jog_step_size', DataType.LONG),
534
+ DataField('jog_min_velocity', DataType.LONG),
535
+ DataField('jog_acceleration', DataType.LONG),
536
+ DataField('jog_max_velocity', DataType.LONG),
537
+ DataField('jog_stop_mode', DataType.WORD),
538
+ ]
539
+ ),
540
+ )
541
+ '''
542
+ Used to set the velocity jog parameters for the specified motor
543
+ channel.
544
+
545
+ For DC servo controllers, values set in encoder counts.
546
+
547
+ For stepper motor controllers the values is set in microsteps.'''
548
+ MGMSG_MOT_REQ_JOGPARAMS = (
549
+ 0x0417,
550
+ CommandType.CHANNEL,
551
+ None,
552
+ KDC101_RESPONSES.MGMSG_MOT_GET_JOGPARAMS,
553
+ )
554
+ '''Used to request the velocity jog parameters for the specified motor channel.'''
555
+
556
+ MGMSG_MOT_SET_LIMSWITCHPARAMS = (
557
+ 0x0423,
558
+ CommandType.COMPLEX,
559
+ PacketStructure(
560
+ [
561
+ DataField('cw_hard_limit', DataType.WORD),
562
+ DataField('ccw_hard_limit', DataType.WORD),
563
+ DataField('cw_soft_limit', DataType.LONG),
564
+ DataField('ccw_soft_limit', DataType.LONG),
565
+ DataField('soft_limit_mode', DataType.WORD),
566
+ ]
567
+ ),
568
+ )
569
+ '''
570
+ Used to set the limit switch parameters for the specified motor channel.
571
+ '''
572
+ MGMSG_MOT_REQ_LIMSWITCHPARAMS = (
573
+ 0x0424,
574
+ CommandType.CHANNEL,
575
+ None,
576
+ KDC101_RESPONSES.MGMSG_MOT_GET_LIMSWITCHPARAMS,
577
+ )
578
+ '''Used to request the limit switch parameters for the specified motor channel.'''
579
+
580
+ MGMSG_MOT_SET_GENMOVEPARAMS = (
581
+ 0x043A,
582
+ CommandType.COMPLEX,
583
+ PacketStructure([DataField('distance', DataType.LONG)]),
584
+ )
585
+ '''
586
+ Used to set the general move parameters for the specified motor channel.
587
+
588
+ Currently this refers specifically to the backlash settings. '''
589
+ MGMSG_MOT_REQ_GENMOVEPARAMS = (
590
+ 0x043B,
591
+ CommandType.CHANNEL,
592
+ None,
593
+ KDC101_RESPONSES.MGMSG_MOT_GET_GENMOVEPARAMS,
594
+ )
595
+ '''Used to request the general move parameters for the specified motor channel.'''
596
+
597
+ MGMSG_MOT_SET_HOMEPARAMS = (
598
+ 0x0440,
599
+ CommandType.COMPLEX,
600
+ PacketStructure(
601
+ [
602
+ DataField('direction', DataType.WORD),
603
+ DataField('lim_switch', DataType.WORD),
604
+ DataField('velocity', DataType.LONG),
605
+ DataField('zero_offset', DataType.LONG),
606
+ ]
607
+ ),
608
+ )
609
+ '''
610
+ Used to set the home parameters for the specified motor channel.
611
+
612
+ These parameters are stage specific and for the MLS203 stage
613
+ implementation the only parameter that can be changed is the
614
+ homing velocity.'''
615
+
616
+ MGMSG_MOT_REQ_HOMEPARAMS = (
617
+ 0x0441,
618
+ CommandType.CHANNEL,
619
+ None,
620
+ KDC101_RESPONSES.MGMSG_MOT_GET_HOMEPARAMS,
621
+ )
622
+ '''
623
+ Used to request the home parameters for the specified motor channel.'''
624
+
625
+ MGMSG_MOT_SET_MOVERELPARAMS = (
626
+ 0x0445,
627
+ CommandType.COMPLEX,
628
+ PacketStructure([DataField('distance', DataType.LONG)]),
629
+ )
630
+ '''
631
+ Used to set the relative move parameters for the specified motor channel.
632
+
633
+ The only significant parameter currently is the relative move distance itself.
634
+
635
+ This gets stored by the controller and is used the next time a relative move
636
+ is initiated.'''
637
+ MGMSG_MOT_REQ_MOVERELPARAMS = (
638
+ 0x0446,
639
+ CommandType.CHANNEL,
640
+ None,
641
+ KDC101_RESPONSES.MGMSG_MOT_GET_MOVERELPARAMS,
642
+ )
643
+ '''Used to request the relative move parameters for the specified motor channel.'''
644
+
645
+ MGMSG_MOT_SET_MOVEABSPARAMS = (
646
+ 0x0450,
647
+ CommandType.COMPLEX,
648
+ PacketStructure([DataField('position', DataType.LONG)]),
649
+ )
650
+ '''
651
+ Used to set the absolute move parameters for the specified motor channel.
652
+
653
+ The only significant parameter currently is the absolute
654
+ move position itself.
655
+
656
+ This gets stored by the controller and is used
657
+ the next time an absolute move is initiated.
658
+ '''
659
+ MGMSG_MOT_REQ_MOVEABSPARAMS = (
660
+ 0x0451,
661
+ CommandType.CHANNEL,
662
+ None,
663
+ KDC101_RESPONSES.MGMSG_MOT_GET_MOVEABSPARAMS,
664
+ )
665
+ '''Used to request the absolute move parameters for the specified motor channel.'''
666
+
667
+ MGMSG_MOT_MOVE_HOME = (
668
+ 0x0443,
669
+ CommandType.CHANNEL,
670
+ None,
671
+ KDC101_RESPONSES.MGMSG_MOT_MOVE_HOMED,
672
+ )
673
+ '''Sent to start a home move sequence on the specified motor channel.'''
674
+
675
+ MGMSG_MOT_MOVE_RELATIVE = (
676
+ 0x0448,
677
+ CommandType.COMPLEX,
678
+ PacketStructure([DataField('distance', DataType.LONG)]),
679
+ KDC101_RESPONSES.MGMSG_MOT_MOVE_COMPLETED,
680
+ )
681
+ '''
682
+ This command can be used to start a relative move on the specified
683
+ motor channel (using the relative move distance parameter above).
684
+
685
+ There are two versions of this command: a shorter (6-byte header
686
+ only) version and a longer (6 byte header plus 6 data bytes) version.
687
+
688
+ When the first one is used, the relative distance parameter used for
689
+ the move will be the parameter sent previously by a
690
+ MGMSG_MOT_SET_MOVERELPARAMS command.
691
+
692
+ If the longer version of the command is used, the relative distance
693
+ is encoded in the data packet that follows the header.
694
+ '''
695
+
696
+ MGMSG_MOT_MOVE_ABSOLUTE = (
697
+ 0x0453,
698
+ CommandType.COMPLEX,
699
+ PacketStructure([DataField('position', DataType.LONG)]),
700
+ KDC101_RESPONSES.MGMSG_MOT_MOVE_COMPLETED,
701
+ )
702
+ '''
703
+ Used to start an absolute move on the specified motor channel
704
+ (using the absolute move position parameter above).
705
+
706
+ As previously described in the “MOVE RELATIVE” command, there are two
707
+ versions of this command: a shorter (6-byte header only) version
708
+ and a longer (6 byte header plus 6 data bytes) version.
709
+
710
+ When the first one is used, the absolute move position parameter used for the
711
+ move will be the parameter sent previously by a MGMSG_MOT_SET_MOVEABSPARAMS command.
712
+
713
+ If the longer version of the command is used, the absolute position is encoded in
714
+ the data packet that follows the header.
715
+
716
+ Upon completion of the absolute move the controller sends a Move Completed message
717
+ as previously described.
718
+ '''
719
+
720
+ MGMSG_MOT_MOVE_JOG = (
721
+ 0x046A,
722
+ CommandType.CHANNEL,
723
+ None,
724
+ KDC101_RESPONSES.MGMSG_MOT_MOVE_COMPLETED,
725
+ )
726
+ '''Sent to start a jog move on the specified motor channel.
727
+
728
+ Upon completion of the jog move the controller sends a Move Completed message as
729
+ previously described.
730
+
731
+ **Note:**
732
+ The direction of the jog move is device dependent, i.e., on some devices jog forward
733
+ may be towards the home position while on other devices it could be the opposite.'''
734
+
735
+ MGMSG_MOT_MOVE_VELOCITY = (
736
+ 0x0457,
737
+ CommandType.CHANNEL,
738
+ None,
739
+ KDC101_RESPONSES.MGMSG_MOT_MOVE_COMPLETED,
740
+ )
741
+ '''
742
+ This command can be used to start a move on the specified motor
743
+ channel.
744
+
745
+ When this method is called, the motor will move continuously in the
746
+ specified direction, using the velocity parameters set in the
747
+ MGMSG_MOT_SET_VELPARAMS command until either a stop
748
+ command (either StopImmediate or StopProfiled) is called, or a limit
749
+ switch is reached.
750
+ '''
751
+
752
+ MGMSG_MOT_MOVE_STOP = (
753
+ 0x0465,
754
+ CommandType.CHANNEL,
755
+ None,
756
+ KDC101_RESPONSES.MGMSG_MOT_MOVE_STOPPED,
757
+ )
758
+ '''
759
+ Sent to stop any type of motor move (relative, absolute, homing or move at velocity)
760
+ on the specified motor channel.
761
+ '''
762
+
763
+ MGMSG_MOT_REQ_DCSTATUSUPDATE = (
764
+ 0x0490,
765
+ CommandType.CHANNEL,
766
+ None,
767
+ KDC101_RESPONSES.MGMSG_MOT_GET_DCSTATUSUPDATE,
768
+ )
769
+ '''
770
+ Used to request a status update for the specified motor channel.
771
+
772
+ This request can be used instead of enabling regular updates as
773
+ described above.'''
774
+
775
+ MGMSG_MOT_REQ_STATUSBITS = (
776
+ 0x0429,
777
+ CommandType.CHANNEL,
778
+ None,
779
+ KDC101_RESPONSES.MGMSG_MOT_GET_STATUSBITS,
780
+ )
781
+ '''
782
+ Used to request a “cut down” version of the status update message,
783
+ only containing the status bits, without data about position and
784
+ velocity.
785
+ '''
786
+
787
+ MGMSG_MOT_SUSPEND_ENDOFMOVEMSGS = (0x046B, CommandType.GENERIC)
788
+ '''
789
+ Sent to disable all unsolicited end of move messages and error
790
+ messages returned by the controller, i.e.
791
+
792
+ - MGMSG_MOT_MOVE_STOPPED
793
+ - MGMSG_MOT_MOVE_COMPLETED
794
+ - MGMSG_MOT_MOVE_HOMED
795
+ '''
796
+
797
+ MGMSG_MOT_RESUME_ENDOFMOVEMSGS = (0x046C, CommandType.GENERIC)
798
+ '''
799
+ Sent to resume all unsolicited end of move messages and error
800
+ messages returned by the controller, i.e.
801
+
802
+ - MGMSG_MOT_MOVE_STOPPED
803
+ - MGMSG_MOT_MOVE_COMPLETED
804
+ - MGMSG_MOT_MOVE_HOMED
805
+
806
+ The command also disables the error messages that the controller
807
+ sends when an error conditions is detected:
808
+
809
+ - MGMSG_HW_RESPONSE
810
+ - MGMSG_HW_RICHRESPONSE
811
+
812
+ This is the default state when the controller is powered up.'''
813
+
814
+ @classmethod
815
+ def get(cls, cmd: Union[int, list]):
816
+ '''Get the command enum for a given command code.'''
817
+ try:
818
+ if isinstance(cmd, list):
819
+ if len(cmd) < 2:
820
+ raise ValueError('Not enough bytes to get command.')
821
+
822
+ cmd = (cmd[1] << 8) | cmd[0]
823
+
824
+ if not isinstance(cmd, int):
825
+ raise ValueError(
826
+ 'Command must be an integer or list of integers/bytes.'
827
+ )
828
+
829
+ # Iterate through enum members to find the one with the matching value
830
+ for member in cls:
831
+ if member.value == cmd:
832
+ return member
833
+ except ValueError:
834
+ return None
835
+
836
+
837
+ class Channels(Enum):
838
+ NA = 0x00
839
+ CHAN1 = 0x01
840
+ CHAN2 = 0x02
841
+ CHAN3 = 0x04
842
+ CHAN4 = 0x08
843
+
844
+
845
+ class ChannelEnableState(Enum):
846
+ ENABLE = 0x01
847
+ DISABLE = 0x02
848
+
849
+
850
+ class BayStates(Enum):
851
+ BAY_OCCUPIED = 0x01
852
+ BAY_EMPTY = 0x02
853
+
854
+
855
+ class HubBayIdents(Enum):
856
+ STANDALONE = 0x01 # T-Cube being standalone, i.e., off the hub
857
+ UNKNOWN = 0x00 # T-Cube on hub, but bay unknown
858
+ BAY_1 = 0x01 # Bay 1
859
+ BAY_2 = 0x02 # Bay 2
860
+ BAY_3 = 0x03 # Bay 3
861
+ BAY_4 = 0x04 # Bay 4
862
+ BAY_5 = 0x05 # Bay 5
863
+ BAY_6 = 0x06 # Bay 6
864
+
865
+
866
+ class JogDirection(Enum):
867
+ FORWARD = 0x01 # Jog forward
868
+ REVERSE = 0x02 # Jog in the reverse direction
869
+
870
+
871
+ class JogMode(Enum):
872
+ CONTINUOUS = 0x01 # Continuous jogging
873
+ SINGLE_STEP = 0x02 # Single step jogging
874
+
875
+
876
+ class StopMode(Enum):
877
+ IMMEDIATE = 0x01 # Stop immediately (abrupt)
878
+ PROFILED = 0x02 # Stop in a controller (profiled) manner
879
+
880
+
881
+ class MotorStatusBits(Enum):
882
+ P_MOT_SB_CWHARDLIMIT = 0x00000001
883
+ '''
884
+ Clockwise hardware limit switch.
885
+
886
+ On linear stages, this corresponds to the forward limit switch.'''
887
+
888
+ P_MOT_SB_CCWHARDLIMIT = 0x00000002
889
+ '''
890
+ Counter-clockwise hardware limit switch.
891
+
892
+ On linear stages, this corresponds to the reverse limit switch.'''
893
+
894
+ P_MOT_SB_CWSOFTLIMIT = 0x00000004
895
+ '''
896
+ Clockwise software limit switch.
897
+
898
+ Restricts motion to a narrower range than the hardware limit switch.'''
899
+
900
+ P_MOT_SB_CCWSOFTLIMIT = 0x00000008
901
+ '''
902
+ Counter-clockwise software limit switch.
903
+
904
+ Restricts motion to a narrower range than the hardware limit switch.'''
905
+
906
+ P_MOT_SB_INMOTIONCW = 0x00000010
907
+ '''Indicates that the motor is in motion, moving clockwise.'''
908
+
909
+ P_MOT_SB_INMOTIONCCW = 0x00000020
910
+ '''Indicates that the motor is in motion, moving counter-clockwise.'''
911
+
912
+ P_MOT_SB_JOGGINGCW = 0x00000040
913
+ '''Indicates that the motor is jogging, moving clockwise.'''
914
+
915
+ P_MOT_SB_JOGGINGCCW = 0x00000080
916
+ '''Indicates that the motor is jogging, moving counter-clockwise.'''
917
+
918
+ P_MOT_SB_CONNECTED = 0x00000100
919
+ '''Indicates that the motor has been recognized by the controller.'''
920
+
921
+ P_MOT_SB_HOMING = 0x00000200
922
+ '''Indicates that the motor is performing a homing move.'''
923
+
924
+ P_MOT_SB_HOMED = 0x00000400
925
+ '''Indicates that the motor has completed the homing move,
926
+ and the absolute position is known.'''
927
+
928
+ P_MOT_SB_POSITIONERROR = 0x00004000
929
+ '''
930
+ Indicates that the actual position is outside the margin specified around the
931
+ trajectory position.
932
+
933
+ (In simple terms the motor is not where it should be.)
934
+
935
+ This can occur momentarily during fast acceleration
936
+ (the motor lags behind the trajectory) or when the motor
937
+ is jammed, or the move is obstructed.
938
+
939
+ Typically the condition can trigger the controller to disable
940
+ the motor in order to prevent damage, which in turn will clear the error.
941
+ '''
942
+ P_MOT_SB_DIGIP1 = 0x00100000
943
+ P_MOT_SB_DIGIP2 = 0x00200000
944
+
945
+ P_MOT_SB_ERROR = 0x40000000
946
+ '''
947
+ Indicates an error condition, either listed above or arising as a result of another
948
+ abnormal condition.'''
949
+ P_MOT_SB_ENABLED = 0x80000000
950
+ '''
951
+ Indicates that the motor output is enabled and the controller is in charge of
952
+ maintaining the required position.
953
+
954
+ When the output is disabled, the motor is not controlled by the electronics
955
+ and can be moved manually, as much as the mechanical construction (such as
956
+ any leadscrew and gearbox fitted) allows.
957
+
958
+ This is not full list of all the bits but the remaining bits reflect information
959
+ about the state of the hardware that in most cases does not affect motion.
960
+ '''
961
+
962
+
963
+ class LimitSwitchOperation(IntFlag):
964
+ '''Clockwise Limit switch operation flags.
965
+
966
+ Flag SWAP_CW_CCW is required for CCW.'''
967
+
968
+ IGNORE_SWITCH = 0x01
969
+ '''Ignore switch or switch not present'''
970
+ MAKES_ON_CONTACT = 0x02
971
+ '''Switch makes on contact'''
972
+ BREAKS_ON_CONTACT = 0x03
973
+ '''Switch breaks on contact'''
974
+ MAKES_ON_CONTACT_HOMING = 0x04
975
+ '''Switch makes on contact (for homing)'''
976
+ BREAKS_ON_CONTACT_HOMING = 0x05
977
+ '''Switch breaks on contact (for homing)'''
978
+ INDEX_MARK_HOMING = 0x06
979
+ '''PMD based brushless servo controllers only, uses index mark for homing'''
980
+ SWAP_CW_CCW = 0x80
981
+ '''
982
+ Bitwise OR this with one of the settings above to swap CW and CCW limit switches
983
+ '''
984
+
985
+
986
+ class LimitSwitchMode(IntFlag):
987
+ '''Software limit switch mode.
988
+
989
+ Flag ROTATION_STAGE_LIMIT is required for rotation stage.'''
990
+
991
+ IGNORE_LIMIT = 0x01
992
+ '''Ignore limit'''
993
+ STOP_IMMEDIATE = 0x02
994
+ '''Stop immediately at limit'''
995
+ PROFILED_STOP = 0x03
996
+ '''Profiled stop at limit'''
997
+ ROTATION_STAGE_LIMIT = 0x80
998
+ '''
999
+ Bitwise OR this with one of the settings
1000
+ above to set rotation stage limit.
1001
+
1002
+ (Not applicable to TDC001 units)'''