cosmos 3.9.2 → 4.0.0

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 (438) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +23 -0
  3. data/.travis.yml +1 -0
  4. data/.yardopts +3 -0
  5. data/Gemfile +1 -1
  6. data/Manifest.txt +137 -52
  7. data/Rakefile +50 -44
  8. data/autohotkey/config/system/system.txt +0 -5
  9. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +6 -1
  10. data/autohotkey/config/targets/INST/screens/extra.txt +19 -0
  11. data/autohotkey/config/targets/INST/sequences/run_sequence.txt +1 -0
  12. data/autohotkey/config/targets/META/screens/data.txt +12 -0
  13. data/autohotkey/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
  14. data/autohotkey/config/targets/{COSMOS/cmd_tlm/cosmos_server_cmds.txt → SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
  15. data/autohotkey/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
  16. data/autohotkey/config/targets/SYSTEM/screens/limits_change.txt +14 -0
  17. data/autohotkey/config/targets/SYSTEM/screens/meta.txt +14 -0
  18. data/autohotkey/config/targets/SYSTEM/target.txt +12 -0
  19. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  20. data/autohotkey/config/tools/test_runner/test_runner2.txt +1 -1
  21. data/autohotkey/tools/CmdSequence +14 -0
  22. data/autohotkey/tools/CmdSequenceAHK +23 -0
  23. data/autohotkey/tools/CmdSequenceAHK2 +16 -0
  24. data/autohotkey/tools/cmd_extractor.ahk +2 -2
  25. data/autohotkey/tools/cmd_sender.ahk +4 -6
  26. data/autohotkey/tools/cmd_sequence.ahk +215 -0
  27. data/autohotkey/tools/cmd_sequence2.ahk +23 -0
  28. data/autohotkey/tools/data_viewer.ahk +2 -3
  29. data/autohotkey/tools/limits_monitor.ahk +9 -11
  30. data/autohotkey/tools/open_gl_builder.ahk +1 -2
  31. data/autohotkey/tools/packet_viewer.ahk +51 -35
  32. data/autohotkey/tools/replay.ahk +1 -2
  33. data/autohotkey/tools/script_runner.ahk +1 -2
  34. data/autohotkey/tools/script_runner2.ahk +1 -2
  35. data/autohotkey/tools/test_runner2.ahk +1 -5
  36. data/autohotkey/tools/test_runner3.ahk +1 -3
  37. data/autohotkey/tools/tlm_grapher.ahk +1 -3
  38. data/autohotkey/tools/tlm_grapher3.ahk +1 -2
  39. data/autohotkey/tools/tlm_viewer.ahk +8 -3
  40. data/autohotkey/tools/tlm_viewer2.ahk +2 -3
  41. data/autohotkey/tools/tlm_viewer5.ahk +1 -2
  42. data/cosmos.gemspec +26 -20
  43. data/data/cmd_sequence.png +0 -0
  44. data/data/config/_array_params.yaml +23 -0
  45. data/data/config/_id_items.yaml +24 -0
  46. data/data/config/_id_params.yaml +58 -0
  47. data/data/config/_interfaces.yaml +206 -0
  48. data/data/config/_items.yaml +20 -0
  49. data/data/config/_params.yaml +58 -0
  50. data/data/config/cmd_tlm_server.yaml +110 -0
  51. data/data/config/command.yaml +38 -0
  52. data/data/config/command_modifiers.yaml +127 -0
  53. data/data/config/command_telemetry.yaml +3 -0
  54. data/data/config/data_viewer.yaml +43 -0
  55. data/data/config/handbook_creator.yaml +23 -0
  56. data/data/config/housekeeping_params.yaml +71 -0
  57. data/data/config/interface_modifiers.yaml +44 -0
  58. data/data/config/item_modifiers.yaml +172 -0
  59. data/data/config/launcher.yaml +117 -0
  60. data/data/config/limits_monitor.yaml +53 -0
  61. data/data/config/linegraph_params.yaml +30 -0
  62. data/data/config/linegraph_plot.yaml +106 -0
  63. data/data/config/page_modifiers.yaml +128 -0
  64. data/data/config/param_item_modifiers.yaml +41 -0
  65. data/data/config/parameter_modifiers.yaml +144 -0
  66. data/data/config/protocols.yaml +257 -0
  67. data/data/config/screen.yaml +151 -0
  68. data/data/config/script_runner.yaml +15 -0
  69. data/data/config/system.yaml +153 -0
  70. data/data/config/table_manager.yaml +76 -0
  71. data/data/config/table_parameter_modifiers.yaml +9 -0
  72. data/data/config/target.yaml +71 -0
  73. data/data/config/telemetry.yaml +73 -0
  74. data/data/config/telemetry_modifiers.yaml +129 -0
  75. data/data/config/test_runner.yaml +118 -0
  76. data/data/config/tlm_extractor.yaml +109 -0
  77. data/data/config/tlm_grapher.yaml +78 -0
  78. data/data/config/tlm_viewer.yaml +107 -0
  79. data/data/config/unknown.yaml +3 -0
  80. data/data/config/widgets.yaml +1339 -0
  81. data/data/config/xy_params.yaml +50 -0
  82. data/data/config/xy_plot.yaml +12 -0
  83. data/data/config_editor.png +0 -0
  84. data/data/crc.txt +172 -161
  85. data/data/delete.png +0 -0
  86. data/demo/config/data/crc.txt +56 -36
  87. data/demo/config/data/meta_init.txt +1 -4
  88. data/demo/config/system/system.txt +15 -3
  89. data/demo/config/system/system2.txt +13 -3
  90. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +2 -6
  91. data/demo/config/targets/EXAMPLE/target.txt +3 -1
  92. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -0
  93. data/demo/config/targets/INST/lib/inst_dump_component.rb +34 -0
  94. data/demo/config/targets/INST/screens/adcs.txt +39 -15
  95. data/demo/config/targets/INST/screens/commanding.txt +26 -19
  96. data/demo/config/targets/INST/screens/spacing_box.txt +44 -0
  97. data/demo/config/targets/INST/screens/spacing_grid.txt +78 -0
  98. data/demo/config/targets/INST/screens/tabs.txt +0 -2
  99. data/demo/config/targets/INST/sequences/sequence.tsv +3 -0
  100. data/demo/config/targets/INST/tables/EventAction.csv +9 -0
  101. data/demo/config/targets/INST/tables/EventAction.dat +0 -0
  102. data/demo/config/targets/INST/tables/McConfigTable.csv +20 -0
  103. data/demo/config/targets/INST/tables/McConfigTable.dat +0 -0
  104. data/demo/config/targets/INST/target.txt +4 -0
  105. data/demo/config/targets/INST/tools/data_viewer/data_viewer.txt +2 -0
  106. data/demo/config/targets/INST/tools/data_viewer/data_viewer2.txt +2 -0
  107. data/demo/config/targets/INST/tools/table_manager/EventAction_def.txt +6 -0
  108. data/demo/config/targets/INST/tools/table_manager/McConfigTable_def.txt +38 -0
  109. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -3
  110. data/demo/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
  111. data/demo/config/targets/{COSMOS/cmd_tlm/cosmos_server_cmds.txt → SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
  112. data/demo/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
  113. data/demo/config/targets/{COSMOS → SYSTEM}/cmd_tlm_server.txt +2 -2
  114. data/demo/config/targets/SYSTEM/lib/limits_groups.rb +39 -0
  115. data/demo/config/targets/SYSTEM/screens/status.txt +1 -1
  116. data/demo/config/targets/SYSTEM/target.txt +12 -0
  117. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +1 -1
  118. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +8 -5
  119. data/demo/config/targets/TEMPLATED/target.txt +2 -0
  120. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +15 -6
  121. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +13 -5
  122. data/demo/config/tools/data_viewer/data_viewer.txt +9 -0
  123. data/demo/config/tools/launcher/launcher.txt +9 -6
  124. data/demo/config/tools/launcher/launcher2.txt +16 -13
  125. data/demo/config/tools/launcher/launcher_mini.txt +45 -0
  126. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +12 -11
  127. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +12 -11
  128. data/demo/config/tools/test_runner/test_runner.txt +1 -1
  129. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  130. data/demo/lib/example_background_task.rb +9 -5
  131. data/demo/lib/example_target.rb +5 -15
  132. data/demo/lib/scpi_target.rb +4 -10
  133. data/demo/procedures/cosmos_api_test.rb +17 -0
  134. data/demo/tools/CmdSequence +16 -0
  135. data/demo/tools/CmdSequence.bat +9 -0
  136. data/demo/tools/ConfigEditor +16 -0
  137. data/demo/tools/ConfigEditor.bat +9 -0
  138. data/demo/tools/mac/CmdSequence.app/Contents/Info.plist +38 -0
  139. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/CmdSequence.rb +16 -0
  140. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +10 -0
  141. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/tool_launch.rb +38 -0
  142. data/demo/tools/mac/CmdSequence.app/Contents/Resources/appIcon.icns +0 -0
  143. data/ext/cosmos/ext/packet/packet.c +5 -5
  144. data/install/config/data/crc.txt +12 -8
  145. data/install/config/system/system.txt +13 -3
  146. data/install/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +14 -0
  147. data/install/config/targets/SYSTEM/target.txt +12 -0
  148. data/install/tools/CmdSequence +16 -0
  149. data/install/tools/CmdSequence.bat +9 -0
  150. data/install/tools/ConfigEditor +16 -0
  151. data/install/tools/ConfigEditor.bat +9 -0
  152. data/install/tools/mac/CmdSequence.app/Contents/Info.plist +38 -0
  153. data/install/tools/mac/CmdSequence.app/Contents/MacOS/CmdSequence.rb +16 -0
  154. data/install/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +10 -0
  155. data/install/tools/mac/CmdSequence.app/Contents/MacOS/tool_launch.rb +38 -0
  156. data/install/tools/mac/CmdSequence.app/Contents/Resources/appIcon.icns +0 -0
  157. data/lib/cosmos.rb +1 -1
  158. data/lib/cosmos/config/config_parser.rb +147 -59
  159. data/lib/cosmos/config/meta_config_parser.rb +57 -0
  160. data/lib/cosmos/conversions/polynomial_conversion.rb +20 -4
  161. data/lib/cosmos/conversions/unix_time_conversion.rb +4 -4
  162. data/lib/cosmos/core_ext/array.rb +45 -5
  163. data/lib/cosmos/core_ext/cosmos_io.rb +31 -15
  164. data/lib/cosmos/core_ext/file.rb +2 -2
  165. data/lib/cosmos/core_ext/kernel.rb +1 -6
  166. data/lib/cosmos/core_ext/objectspace.rb +0 -2
  167. data/lib/cosmos/core_ext/string.rb +27 -4
  168. data/lib/cosmos/core_ext/time.rb +39 -10
  169. data/lib/cosmos/gui/choosers/combobox_chooser.rb +37 -26
  170. data/lib/cosmos/gui/choosers/file_chooser.rb +23 -6
  171. data/lib/cosmos/gui/choosers/float_chooser.rb +13 -11
  172. data/lib/cosmos/gui/choosers/integer_chooser.rb +13 -11
  173. data/lib/cosmos/gui/choosers/string_chooser.rb +18 -36
  174. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +64 -64
  175. data/lib/cosmos/gui/choosers/value_chooser.rb +15 -15
  176. data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -13
  177. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +11 -3
  178. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +1 -1
  179. data/lib/cosmos/gui/dialogs/details_dialog.rb +1 -1
  180. data/lib/cosmos/gui/dialogs/exception_dialog.rb +7 -7
  181. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +20 -15
  182. data/lib/cosmos/gui/dialogs/interface_raw_dialog.rb +143 -0
  183. data/lib/cosmos/gui/dialogs/legal_dialog.rb +6 -5
  184. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +5 -2
  185. data/lib/cosmos/gui/dialogs/progress_dialog.rb +1 -1
  186. data/lib/cosmos/gui/dialogs/pry_dialog.rb +4 -4
  187. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +3 -0
  188. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +7 -6
  189. data/lib/cosmos/gui/dialogs/splash.rb +1 -1
  190. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +1 -1
  191. data/lib/cosmos/gui/dialogs/tlm_graph_dialog.rb +114 -0
  192. data/lib/cosmos/gui/line_graph/line_graph.rb +9 -10
  193. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +7 -5
  194. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +3 -7
  195. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +3 -8
  196. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +2 -7
  197. data/lib/cosmos/gui/line_graph/overview_graph.rb +6 -1
  198. data/lib/cosmos/gui/opengl/earth_model.rb +6 -3
  199. data/lib/cosmos/gui/opengl/gl_bounds.rb +11 -23
  200. data/lib/cosmos/gui/opengl/gl_light.rb +3 -4
  201. data/lib/cosmos/gui/opengl/gl_material.rb +3 -4
  202. data/lib/cosmos/gui/opengl/gl_scene.rb +10 -4
  203. data/lib/cosmos/gui/opengl/gl_shape.rb +6 -2
  204. data/lib/cosmos/gui/opengl/gl_viewer.rb +5 -5
  205. data/lib/cosmos/gui/opengl/gl_viewport.rb +11 -12
  206. data/lib/cosmos/gui/opengl/moon_model.rb +6 -3
  207. data/lib/cosmos/gui/opengl/stl_reader.rb +8 -9
  208. data/lib/cosmos/gui/opengl/stl_shape.rb +4 -5
  209. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +7 -7
  210. data/lib/cosmos/gui/qt.rb +1 -1
  211. data/lib/cosmos/gui/qt_tool.rb +21 -10
  212. data/lib/cosmos/gui/text/completion.rb +23 -2
  213. data/lib/cosmos/gui/text/completion_text_edit.rb +38 -23
  214. data/lib/cosmos/gui/utilities/analyze_log.rb +1 -1
  215. data/lib/cosmos/gui/utilities/screenshot.rb +2 -2
  216. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +11 -1
  217. data/lib/cosmos/gui/widgets/packet_log_frame.rb +19 -6
  218. data/lib/cosmos/interfaces.rb +10 -0
  219. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +28 -47
  220. data/lib/cosmos/interfaces/interface.rb +240 -22
  221. data/lib/cosmos/interfaces/linc_interface.rb +3 -5
  222. data/lib/cosmos/interfaces/protocols/burst_protocol.rb +173 -0
  223. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +141 -0
  224. data/lib/cosmos/{streams/fixed_stream_protocol.rb → interfaces/protocols/fixed_protocol.rb} +40 -37
  225. data/lib/cosmos/{streams/length_stream_protocol.rb → interfaces/protocols/length_protocol.rb} +55 -48
  226. data/lib/cosmos/interfaces/protocols/override_protocol.rb +52 -0
  227. data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +141 -0
  228. data/lib/cosmos/interfaces/protocols/protocol.rb +60 -0
  229. data/lib/cosmos/interfaces/protocols/template_protocol.rb +209 -0
  230. data/lib/cosmos/interfaces/protocols/terminated_protocol.rb +81 -0
  231. data/lib/cosmos/interfaces/serial_interface.rb +28 -23
  232. data/lib/cosmos/interfaces/simulated_target_interface.rb +27 -16
  233. data/lib/cosmos/interfaces/stream_interface.rb +36 -108
  234. data/lib/cosmos/interfaces/tcpip_client_interface.rb +21 -21
  235. data/lib/cosmos/interfaces/tcpip_server_interface.rb +555 -94
  236. data/lib/cosmos/interfaces/udp_interface.rb +51 -83
  237. data/lib/cosmos/io/buffered_file.rb +92 -2
  238. data/lib/cosmos/io/json_drb.rb +2 -2
  239. data/lib/cosmos/io/posix_serial_driver.rb +3 -1
  240. data/lib/cosmos/io/raw_logger.rb +3 -3
  241. data/lib/cosmos/io/serial_driver.rb +14 -5
  242. data/lib/cosmos/io/win32_serial_driver.rb +16 -4
  243. data/lib/cosmos/packet_logs.rb +0 -1
  244. data/lib/cosmos/packet_logs/packet_log_reader.rb +11 -1
  245. data/lib/cosmos/packet_logs/packet_log_writer.rb +31 -13
  246. data/lib/cosmos/packets/binary_accessor.rb +599 -32
  247. data/lib/cosmos/packets/commands.rb +48 -24
  248. data/lib/cosmos/packets/packet.rb +140 -54
  249. data/lib/cosmos/packets/packet_config.rb +0 -2
  250. data/lib/cosmos/packets/parsers/packet_item_parser.rb +10 -2
  251. data/lib/cosmos/packets/structure.rb +81 -33
  252. data/lib/cosmos/packets/structure_item.rb +45 -5
  253. data/lib/cosmos/packets/telemetry.rb +149 -55
  254. data/lib/cosmos/script/api_shared.rb +1000 -0
  255. data/lib/cosmos/script/commands.rb +2 -2
  256. data/lib/cosmos/script/extract.rb +19 -4
  257. data/lib/cosmos/script/limits.rb +2 -0
  258. data/lib/cosmos/script/script.rb +1 -1
  259. data/lib/cosmos/script/scripting.rb +4 -784
  260. data/lib/cosmos/script/telemetry.rb +44 -23
  261. data/lib/cosmos/script/tools.rb +15 -69
  262. data/lib/cosmos/streams/serial_stream.rb +12 -19
  263. data/lib/cosmos/streams/stream.rb +2 -11
  264. data/lib/cosmos/streams/tcpip_socket_stream.rb +3 -13
  265. data/lib/cosmos/system/system.rb +187 -31
  266. data/lib/cosmos/system/target.rb +11 -2
  267. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +12 -11
  268. data/lib/cosmos/tools/cmd_sender/{cmd_sender_item_delegate.rb → cmd_param_table_item_delegate.rb} +11 -10
  269. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +209 -164
  270. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +652 -0
  271. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +510 -0
  272. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +194 -0
  273. data/lib/cosmos/tools/cmd_tlm_server/api.rb +179 -5
  274. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +31 -14
  275. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +23 -16
  276. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +92 -20
  277. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +1 -1
  278. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -4
  279. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +0 -5
  280. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +1 -2
  281. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +4 -4
  282. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +121 -0
  283. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +8 -4
  284. data/lib/cosmos/tools/config_editor/config_editor.rb +720 -0
  285. data/lib/cosmos/tools/config_editor/config_editor_frame.rb +675 -0
  286. data/lib/cosmos/tools/data_viewer/data_viewer.rb +44 -27
  287. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +8 -22
  288. data/lib/cosmos/tools/launcher/launcher.rb +29 -12
  289. data/lib/cosmos/tools/launcher/launcher_config.rb +1 -1
  290. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +153 -42
  291. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +44 -6
  292. data/lib/cosmos/tools/replay/replay.rb +36 -20
  293. data/lib/cosmos/tools/replay/replay_server.rb +1 -1
  294. data/lib/cosmos/tools/script_runner/script_runner_config.rb +1 -1
  295. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +31 -21
  296. data/lib/cosmos/tools/table_manager/table_config.rb +9 -3
  297. data/lib/cosmos/tools/table_manager/table_manager.rb +27 -7
  298. data/lib/cosmos/tools/test_runner/results_writer.rb +6 -6
  299. data/lib/cosmos/tools/test_runner/test_runner.rb +4 -6
  300. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +4 -5
  301. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -1
  302. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +1 -1
  303. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +23 -6
  304. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +44 -3
  305. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +20 -7
  306. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1 -1
  307. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +11 -4
  308. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +2 -2
  309. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +1 -1
  310. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +16 -0
  311. data/lib/cosmos/tools/tlm_viewer/screen.rb +36 -32
  312. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +59 -50
  313. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +2 -2
  314. data/lib/cosmos/tools/tlm_viewer/widgets.rb +1 -0
  315. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +1 -0
  316. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +22 -4
  317. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +9 -0
  318. data/lib/cosmos/tools/tlm_viewer/widgets/spacer_widget.rb +55 -0
  319. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +3 -2
  320. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +3 -2
  321. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +12 -12
  322. data/lib/cosmos/top_level.rb +34 -24
  323. data/lib/cosmos/utilities/crc.rb +108 -6
  324. data/lib/cosmos/utilities/csv.rb +68 -14
  325. data/lib/cosmos/utilities/logger.rb +2 -2
  326. data/lib/cosmos/utilities/low_fragmentation_array.rb +9 -1
  327. data/lib/cosmos/version.rb +6 -6
  328. data/lib/cosmos/win32/win32_main.rb +50 -46
  329. data/run_gui_tests.bat +3 -1
  330. data/spec/conversions/unix_time_formatted_conversion_spec.rb +2 -2
  331. data/spec/conversions/unix_time_seconds_conversion_spec.rb +2 -2
  332. data/spec/core_ext/file_spec.rb +1 -1
  333. data/spec/core_ext/objectspace_spec.rb +12 -9
  334. data/spec/core_ext/string_spec.rb +6 -0
  335. data/spec/core_ext/time_spec.rb +10 -0
  336. data/spec/gui/line_graph/line_clip_spec.rb +226 -224
  337. data/spec/gui/qt_spec.rb +81 -79
  338. data/spec/install/config/system/system.txt +0 -6
  339. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +5 -5
  340. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +8 -8
  341. data/spec/install/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
  342. data/{install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt → spec/install/config/targets/SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
  343. data/spec/install/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
  344. data/spec/install/config/targets/{COSMOS → SYSTEM}/cmd_tlm_server.txt +2 -2
  345. data/spec/install/config/targets/SYSTEM/screens/status.txt +12 -0
  346. data/spec/install/config/targets/SYSTEM/target.txt +12 -0
  347. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +9 -13
  348. data/spec/interfaces/interface_spec.rb +402 -18
  349. data/spec/interfaces/linc_interface_spec.rb +37 -39
  350. data/spec/interfaces/protocols/burst_protocol_spec.rb +300 -0
  351. data/spec/interfaces/protocols/crc_protocol_spec.rb +709 -0
  352. data/spec/interfaces/protocols/fixed_protocol_spec.rb +119 -0
  353. data/spec/interfaces/protocols/length_protocol_spec.rb +499 -0
  354. data/spec/interfaces/protocols/override_protocol_spec.rb +158 -0
  355. data/spec/interfaces/protocols/preidentified_protocol_spec.rb +149 -0
  356. data/spec/interfaces/protocols/template_protocol_spec.rb +218 -0
  357. data/spec/interfaces/protocols/terminated_protocol_spec.rb +174 -0
  358. data/spec/interfaces/serial_interface_spec.rb +35 -34
  359. data/spec/interfaces/simulated_target_interface_spec.rb +13 -13
  360. data/spec/interfaces/tcpip_client_interface_spec.rb +21 -16
  361. data/spec/interfaces/tcpip_server_interface_spec.rb +66 -69
  362. data/spec/interfaces/udp_interface_spec.rb +120 -55
  363. data/spec/io/serial_driver_spec.rb +41 -39
  364. data/spec/io/udp_sockets_spec.rb +13 -8
  365. data/spec/io/win32_serial_driver_spec.rb +62 -59
  366. data/spec/packet_logs/packet_log_reader_spec.rb +68 -47
  367. data/spec/packet_logs/packet_log_writer_spec.rb +7 -5
  368. data/spec/packets/commands_spec.rb +5 -5
  369. data/spec/packets/packet_spec.rb +2 -14
  370. data/spec/script/extract_spec.rb +21 -7
  371. data/spec/script/scripting_spec.rb +261 -6
  372. data/spec/script/telemetry_spec.rb +17 -9
  373. data/spec/spec_helper.rb +26 -10
  374. data/spec/streams/serial_stream_spec.rb +87 -82
  375. data/spec/streams/tcpip_client_stream_spec.rb +12 -4
  376. data/spec/streams/tcpip_socket_stream_spec.rb +5 -0
  377. data/spec/system/system_spec.rb +66 -50
  378. data/spec/system/target_spec.rb +33 -11
  379. data/spec/tools/cmd_tlm_server/api_spec.rb +5 -5
  380. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +75 -15
  381. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +125 -5
  382. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +244 -232
  383. data/spec/tools/cmd_tlm_server/commanding_spec.rb +18 -18
  384. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +124 -29
  385. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +2 -2
  386. data/spec/tools/cmd_tlm_server/limits_groups_background_task_spec.rb +145 -0
  387. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +50 -10
  388. data/spec/tools/table_manager/tablemanager_core_spec.rb +0 -1
  389. data/spec/top_level/top_level_spec.rb +39 -11
  390. data/spec/utilities/csv_spec.rb +62 -20
  391. data/tasks/gemfile_stats.rake +6 -3
  392. data/test/performance/config/system/system_packets.txt +0 -1
  393. data/test/performance/config/system/system_threads.txt +0 -1
  394. metadata +177 -92
  395. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  396. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +0 -6
  397. data/autohotkey/config/targets/COSMOS/target.txt +0 -5
  398. data/autohotkey/userpath.txt +0 -1
  399. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  400. data/demo/config/targets/COSMOS/screens/limits_change.txt +0 -20
  401. data/demo/config/targets/COSMOS/screens/version.txt +0 -19
  402. data/demo/config/targets/COSMOS/target.txt +0 -11
  403. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +0 -10
  404. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +0 -13
  405. data/demo/userpath.txt +0 -1
  406. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  407. data/install/config/targets/COSMOS/cmd_tlm_server.txt +0 -6
  408. data/install/config/targets/COSMOS/screens/limits_change.txt +0 -20
  409. data/install/config/targets/COSMOS/screens/version.txt +0 -19
  410. data/install/config/targets/COSMOS/target.txt +0 -9
  411. data/install/config/targets/SYSTEM/README.txt +0 -1
  412. data/install/userpath.txt +0 -1
  413. data/lib/cosmos/io/tcpip_server.rb +0 -571
  414. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +0 -107
  415. data/lib/cosmos/streams/burst_stream_protocol.rb +0 -25
  416. data/lib/cosmos/streams/preidentified_stream_protocol.rb +0 -118
  417. data/lib/cosmos/streams/stream_protocol.rb +0 -373
  418. data/lib/cosmos/streams/template_stream_protocol.rb +0 -140
  419. data/lib/cosmos/streams/terminated_stream_protocol.rb +0 -85
  420. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +0 -41
  421. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  422. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +0 -20
  423. data/spec/install/config/targets/COSMOS/screens/version.txt +0 -19
  424. data/spec/install/config/targets/COSMOS/target.txt +0 -5
  425. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +0 -4
  426. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +0 -4
  427. data/spec/install/userpath.txt +0 -1
  428. data/spec/interfaces/stream_interface_spec.rb +0 -157
  429. data/spec/io/tcpip_server_spec.rb +0 -338
  430. data/spec/packet_logs/meta_packet_log_writer_spec.rb +0 -170
  431. data/spec/streams/burst_stream_protocol_spec.rb +0 -32
  432. data/spec/streams/fixed_stream_protocol_spec.rb +0 -113
  433. data/spec/streams/length_stream_protocol_spec.rb +0 -300
  434. data/spec/streams/preidentified_stream_protocol_spec.rb +0 -121
  435. data/spec/streams/stream_protocol_spec.rb +0 -346
  436. data/spec/streams/template_stream_protocol_spec.rb +0 -156
  437. data/spec/streams/terminated_stream_protocol_spec.rb +0 -127
  438. data/test/performance/userpath.txt +0 -1
@@ -1,7 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
3
  require 'cosmos/packet_logs/packet_log_writer'
4
- require 'cosmos/packet_logs/meta_packet_log_writer'
5
4
  require 'cosmos/packet_logs/packet_log_writer_pair'
6
5
  require 'cosmos/packet_logs/packet_log_reader'
7
6
  require 'cosmos/packet_logs/ccsds_log_reader'
@@ -148,6 +148,16 @@ module Cosmos
148
148
  packet.set_received_time_fast(received_time)
149
149
  end
150
150
 
151
+ # Auto change configuration on SYSTEM META
152
+ if packet.target_name == 'SYSTEM'.freeze and packet.packet_name == 'META'.freeze
153
+ # Manually read the configuration from the buffer because the packet might not be identified if
154
+ # identify_and_define is false
155
+ buffer = packet.buffer(false)
156
+ if buffer.length >= 33
157
+ System.load_configuration(BinaryAccessor.read(8, 256, :STRING, buffer, :BIG_ENDIAN))
158
+ end
159
+ end
160
+
151
161
  packet.received_count += 1
152
162
  packet
153
163
  rescue => err
@@ -299,7 +309,7 @@ module Cosmos
299
309
  time_microseconds = @file.read(4)
300
310
  return [nil, nil, nil, nil] if time_microseconds.nil? or time_microseconds.length != 4
301
311
  time_microseconds = time_microseconds.unpack('N')[0]
302
- received_time = Time.at(time_seconds, time_microseconds)
312
+ received_time = Time.at(time_seconds, time_microseconds).sys
303
313
 
304
314
  # Read Target Name
305
315
  target_name = @file.read_length_bytes(1)
@@ -11,6 +11,7 @@
11
11
  require 'thread'
12
12
  require 'socket' # For gethostname
13
13
  require 'cosmos/config/config_parser'
14
+ require 'cosmos/packet_logs/packet_log_reader'
14
15
 
15
16
  module Cosmos
16
17
 
@@ -89,7 +90,7 @@ module Cosmos
89
90
  @filename = nil
90
91
  @label = nil
91
92
  @entry_header = String.new
92
- @start_time = Time.now
93
+ @start_time = Time.now.sys
93
94
 
94
95
  @cancel_threads = false
95
96
  @logging_thread = nil
@@ -173,7 +174,7 @@ module Cosmos
173
174
  # Starting a new log file is a critical operation so the entire method is
174
175
  # wrapped with a rescue and handled with handle_critical_exception
175
176
  # Assumes mutex has already been taken
176
- def start_new_file
177
+ def start_new_file(packet = nil)
177
178
  close_file(false)
178
179
  Cosmos.set_working_dir do
179
180
  # Create a filename that doesn't exist
@@ -196,19 +197,31 @@ module Cosmos
196
197
  @file.write(file_header)
197
198
  @file_size += file_header.length
198
199
  end
199
- @start_time = Time.now
200
+ @start_time = Time.now.sys
200
201
  Logger.instance.info "Log File Opened : #{@filename}"
201
- start_new_file_hook()
202
+ start_new_file_hook(packet)
202
203
  rescue => err
203
204
  Logger.instance.error "Error opening #{@filename} : #{err.formatted}"
204
205
  @logging_enabled = false
205
206
  Cosmos.handle_critical_exception(err)
206
207
  end
207
208
 
208
- # Hook after writing the file header in start_new_file
209
+ # Adds the meta packet at the beginning of telemetry packet logs
209
210
  # Mutex is held during this hook
210
- def start_new_file_hook
211
- # Default do nothing
211
+ def start_new_file_hook(packet)
212
+ # If the first packet is a SYSTEM META packet, make sure the file header matches
213
+ if packet and packet.target_name == 'SYSTEM'.freeze and packet.packet_name == 'META'.freeze
214
+ file_header = build_file_header(packet.read('CONFIG'))
215
+ if file_header
216
+ @file.seek(0, IO::SEEK_SET)
217
+ @file.write(file_header)
218
+ @file_size = file_header.length
219
+ end
220
+ else
221
+ # Else log the first packet as the SYSTEM META packet
222
+ packet = System.telemetry.packet('SYSTEM', 'META')
223
+ write_packet(packet, false)
224
+ end
212
225
  end
213
226
 
214
227
  # Closing a log file isn't critical so we just log an error
@@ -244,15 +257,16 @@ module Cosmos
244
257
  begin
245
258
  # This check includes logging_enabled again because it might have changed since we acquired the mutex
246
259
  if @logging_enabled and (!@file or (@cycle_size and (@file_size + packet.length) > @cycle_size))
247
- start_new_file()
260
+ start_new_file(packet)
248
261
  end
262
+ pre_write_entry_hook(packet)
249
263
  if @file
250
264
  @entry_header = build_entry_header(packet) # populate @entry_header
251
265
  if @entry_header
252
266
  @file.write(@entry_header)
253
267
  @file_size += @entry_header.length
254
268
  end
255
- buffer = packet.buffer
269
+ buffer = packet.buffer(false)
256
270
  @file.write(buffer)
257
271
  @file_size += buffer.length
258
272
  end
@@ -264,6 +278,10 @@ module Cosmos
264
278
  Cosmos.handle_critical_exception(err)
265
279
  end
266
280
 
281
+ # Hook to allow access to the packet immediately before writing its entry
282
+ def pre_write_entry_hook(packet)
283
+ end
284
+
267
285
  def logging_thread_body
268
286
  while true
269
287
  begin
@@ -282,7 +300,7 @@ module Cosmos
282
300
  # The check against start_time needs to be mutex protected to prevent a packet coming in between the check
283
301
  # and closing the file
284
302
  @mutex.synchronize do
285
- if @logging_enabled and @cycle_time and (Time.now - @start_time) > @cycle_time
303
+ if @logging_enabled and @cycle_time and (Time.now.sys - @start_time) > @cycle_time
286
304
  close_file(false)
287
305
  end
288
306
  end
@@ -291,16 +309,16 @@ module Cosmos
291
309
  end
292
310
  end
293
311
 
294
- def build_file_header
312
+ def build_file_header(configuration_name = System.configuration_name)
295
313
  hostname = Socket.gethostname.to_s
296
- file_header = "COSMOS2_#{@log_type}_#{System.configuration_name}_"
314
+ file_header = "COSMOS2_#{@log_type}_#{configuration_name.ljust(32, ' ')[0..31]}_"
297
315
  file_header << hostname.ljust(83)
298
316
  return file_header
299
317
  end
300
318
 
301
319
  def build_entry_header(packet)
302
320
  received_time = packet.received_time
303
- received_time = Time.now unless received_time
321
+ received_time = Time.now.sys unless received_time
304
322
  # This is an optimization to avoid creating a new entry_header object
305
323
  # each time we create an entry_header which we do a LOT!
306
324
  @entry_header.clear
@@ -11,7 +11,7 @@
11
11
  # This file contains the implementation of the BinaryAccessor class.
12
12
  # This class allows for easy reading and writing of binary data in Ruby
13
13
 
14
- require 'cosmos/ext/packet'
14
+ require 'cosmos/ext/packet' if RUBY_ENGINE == 'ruby' and !ENV['COSMOS_NO_EXT']
15
15
 
16
16
  module Cosmos
17
17
 
@@ -50,6 +50,21 @@ module Cosmos
50
50
  PACK_BIG_ENDIAN_32_BIT_FLOAT_ARRAY = 'g*'
51
51
  PACK_BIG_ENDIAN_64_BIT_FLOAT_ARRAY = 'G*'
52
52
 
53
+ if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_ENV']
54
+ MIN_INT8 = -128
55
+ MAX_INT8 = 127
56
+ MAX_UINT8 = 255
57
+ MIN_INT16 = -32768
58
+ MAX_INT16 = 32767
59
+ MAX_UINT16 = 65535
60
+ MIN_INT32 = -(2 ** 31)
61
+ MAX_INT32 = (2 ** 31) - 1
62
+ MAX_UINT32 = (2 ** 32) - 1
63
+ MIN_INT64 = -(2 ** 63)
64
+ MAX_INT64 = (2 ** 63) - 1
65
+ MAX_UINT64 = (2 ** 64) - 1
66
+ end
67
+
53
68
  # Additional Constants
54
69
  ZERO_STRING = "\000"
55
70
 
@@ -89,29 +104,578 @@ module Cosmos
89
104
  # Valid endianess
90
105
  ENDIANNESS = [:BIG_ENDIAN, :LITTLE_ENDIAN]
91
106
 
92
- # Reads binary data of any data type from a buffer
93
- #
94
- # @param bit_offset [Integer] Bit offset to the start of the item. A
95
- # negative number means to offset from the end of the buffer.
96
- # @param bit_size [Integer] Size of the item in bits
97
- # @param data_type [Symbol] {DATA_TYPES}
98
- # @param buffer [String] Binary string buffer to read from
99
- # @param endianness [Symbol] {ENDIANNESS}
100
- # @return [Integer] value read from the buffer
101
- # def self.read(bit_offset, bit_size, data_type, buffer, endianness)
107
+ if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_EXT']
108
+ # Reads binary data of any data type from a buffer
109
+ #
110
+ # @param bit_offset [Integer] Bit offset to the start of the item. A
111
+ # negative number means to offset from the end of the buffer.
112
+ # @param bit_size [Integer] Size of the item in bits
113
+ # @param data_type [Symbol] {DATA_TYPES}
114
+ # @param buffer [String] Binary string buffer to read from
115
+ # @param endianness [Symbol] {ENDIANNESS}
116
+ # @return [Integer] value read from the buffer
117
+ def self.read(bit_offset, bit_size, data_type, buffer, endianness)
118
+ given_bit_offset = bit_offset
119
+ given_bit_size = bit_size
120
+
121
+ bit_offset = check_bit_offset_and_size(:read, given_bit_offset, given_bit_size, data_type, buffer)
122
+
123
+ # If passed a negative bit size with strings or blocks
124
+ # recalculate based on the buffer length
125
+ if (bit_size <= 0) && ((data_type == :STRING) || (data_type == :BLOCK))
126
+ bit_size = (buffer.length * 8) - bit_offset + bit_size
127
+ if bit_size == 0
128
+ return ""
129
+ elsif bit_size < 0
130
+ raise_buffer_error(:read, buffer, data_type, given_bit_offset, given_bit_size)
131
+ end
132
+ end
102
133
 
103
- # Writes binary data of any data type to a buffer
104
- #
105
- # @param value [Varies] Value to write into the buffer
106
- # @param bit_offset [Integer] Bit offset to the start of the item. A
107
- # negative number means to offset from the end of the buffer.
108
- # @param bit_size [Integer] Size of the item in bits
109
- # @param data_type [Symbol] {DATA_TYPES}
110
- # @param buffer [String] Binary string buffer to write to
111
- # @param endianness [Symbol] {ENDIANNESS}
112
- # @param overflow [Symbol] {OVERFLOW_TYPES}
113
- # @return [Integer] value passed in as a parameter
114
- # def self.write(value, bit_offset, bit_size, data_type, buffer, endianness, overflow)
134
+ result, lower_bound, upper_bound = check_bounds_and_buffer_size(bit_offset, bit_size, buffer.length, endianness, data_type)
135
+ raise_buffer_error(:read, buffer, data_type, given_bit_offset, given_bit_size) unless result
136
+
137
+ if (data_type == :STRING) || (data_type == :BLOCK)
138
+ #######################################
139
+ # Handle :STRING and :BLOCK data types
140
+ #######################################
141
+
142
+ if byte_aligned(bit_offset)
143
+ if data_type == :STRING
144
+ return buffer[lower_bound..upper_bound].unpack('Z*')[0]
145
+ else
146
+ return buffer[lower_bound..upper_bound].unpack('a*')[0]
147
+ end
148
+ else
149
+ raise(ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}")
150
+ end
151
+
152
+ elsif (data_type == :INT) || (data_type == :UINT)
153
+ ###################################
154
+ # Handle :INT and :UINT data types
155
+ ###################################
156
+
157
+ if byte_aligned(bit_offset) && even_bit_size(bit_size)
158
+
159
+ if data_type == :INT
160
+ ###########################################################
161
+ # Handle byte-aligned 8, 16, 32, and 64 bit :INT
162
+ ###########################################################
163
+
164
+ case bit_size
165
+ when 8
166
+ return buffer[lower_bound].unpack(PACK_8_BIT_INT)[0]
167
+ when 16
168
+ if endianness == HOST_ENDIANNESS
169
+ return buffer[lower_bound..upper_bound].unpack(PACK_NATIVE_16_BIT_INT)[0]
170
+ else # endianness != HOST_ENDIANNESS
171
+ temp = buffer[lower_bound..upper_bound].reverse
172
+ return temp.unpack(PACK_NATIVE_16_BIT_INT)[0]
173
+ end
174
+ when 32
175
+ if endianness == HOST_ENDIANNESS
176
+ return buffer[lower_bound..upper_bound].unpack(PACK_NATIVE_32_BIT_INT)[0]
177
+ else # endianness != HOST_ENDIANNESS
178
+ temp = buffer[lower_bound..upper_bound].reverse
179
+ return temp.unpack(PACK_NATIVE_32_BIT_INT)[0]
180
+ end
181
+ when 64
182
+ if endianness == HOST_ENDIANNESS
183
+ return buffer[lower_bound..upper_bound].unpack(PACK_NATIVE_64_BIT_INT)[0]
184
+ else # endianness != HOST_ENDIANNESS
185
+ temp = buffer[lower_bound..upper_bound].reverse
186
+ return temp.unpack(PACK_NATIVE_64_BIT_INT)[0]
187
+ end
188
+ end
189
+ else # data_type == :UINT
190
+ ###########################################################
191
+ # Handle byte-aligned 8, 16, 32, and 64 bit :UINT
192
+ ###########################################################
193
+
194
+ case bit_size
195
+ when 8
196
+ return buffer.getbyte(lower_bound)
197
+ when 16
198
+ if endianness == :BIG_ENDIAN
199
+ return buffer[lower_bound..upper_bound].unpack(PACK_BIG_ENDIAN_16_BIT_UINT)[0]
200
+ else # endianness == :LITTLE_ENDIAN
201
+ return buffer[lower_bound..upper_bound].unpack(PACK_LITTLE_ENDIAN_16_BIT_UINT)[0]
202
+ end
203
+ when 32
204
+ if endianness == :BIG_ENDIAN
205
+ return buffer[lower_bound..upper_bound].unpack(PACK_BIG_ENDIAN_32_BIT_UINT)[0]
206
+ else # endianness == :LITTLE_ENDIAN
207
+ return buffer[lower_bound..upper_bound].unpack(PACK_LITTLE_ENDIAN_32_BIT_UINT)[0]
208
+ end
209
+ when 64
210
+ if endianness == HOST_ENDIANNESS
211
+ return buffer[lower_bound..upper_bound].unpack(PACK_NATIVE_64_BIT_UINT)[0]
212
+ else # endianness != HOST_ENDIANNESS
213
+ temp = buffer[lower_bound..upper_bound].reverse
214
+ return temp.unpack(PACK_NATIVE_64_BIT_UINT)[0]
215
+ end
216
+ end
217
+ end
218
+
219
+ else
220
+ ##########################
221
+ # Handle :INT and :UINT Bitfields
222
+ ##########################
223
+
224
+ #Extract Data for Bitfield
225
+ if endianness == :LITTLE_ENDIAN
226
+ #Bitoffset always refers to the most significant bit of a bitfield
227
+ num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1
228
+ upper_bound = bit_offset / 8
229
+ lower_bound = upper_bound - num_bytes + 1
230
+
231
+ if lower_bound < 0
232
+ raise(ArgumentError, "LITTLE_ENDIAN bitfield with bit_offset #{given_bit_offset} and bit_size #{given_bit_size} is invalid")
233
+ end
234
+
235
+ temp_data = buffer[lower_bound..upper_bound].reverse
236
+ else
237
+ temp_data = buffer[lower_bound..upper_bound]
238
+ end
239
+
240
+ #Determine temp upper bound
241
+ temp_upper = upper_bound - lower_bound
242
+
243
+ # Handle Bitfield
244
+ start_bits = bit_offset % 8
245
+ start_mask = ~(0xFF << (8 - start_bits))
246
+ total_bits = (temp_upper + 1) * 8
247
+ right_shift = total_bits - start_bits - bit_size
248
+
249
+ #Mask off unwanted bits at beginning
250
+ temp = temp_data.getbyte(0) & start_mask
251
+
252
+ if upper_bound > lower_bound
253
+ #Combine bytes into a FixNum
254
+ temp_data[1..temp_upper].each_byte {|temp_value| temp = temp << 8; temp = temp + temp_value }
255
+ end
256
+
257
+ # Shift off unwanted bits at end
258
+ temp = temp >> right_shift
259
+
260
+ if data_type == :INT
261
+ #Convert to negative if necessary
262
+ if ((bit_size > 1) && (temp[bit_size - 1] == 1))
263
+ temp = -((1 << bit_size) - temp)
264
+ end
265
+ end
266
+
267
+ return temp
268
+ end
269
+
270
+ elsif data_type == :FLOAT
271
+ ##########################
272
+ # Handle :FLOAT data type
273
+ ##########################
274
+
275
+ if byte_aligned(bit_offset)
276
+ case bit_size
277
+ when 32
278
+ if endianness == :BIG_ENDIAN
279
+ return buffer[lower_bound..upper_bound].unpack(PACK_BIG_ENDIAN_32_BIT_FLOAT)[0]
280
+ else # endianness == :LITTLE_ENDIAN
281
+ return buffer[lower_bound..upper_bound].unpack(PACK_LITTLE_ENDIAN_32_BIT_FLOAT)[0]
282
+ end
283
+ when 64
284
+ if endianness == :BIG_ENDIAN
285
+ return buffer[lower_bound..upper_bound].unpack(PACK_BIG_ENDIAN_64_BIT_FLOAT)[0]
286
+ else # endianness == :LITTLE_ENDIAN
287
+ return buffer[lower_bound..upper_bound].unpack(PACK_LITTLE_ENDIAN_64_BIT_FLOAT)[0]
288
+ end
289
+ else
290
+ raise(ArgumentError, "bit_size is #{given_bit_size} but must be 32 or 64 for data_type #{data_type}")
291
+ end
292
+ else
293
+ raise(ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}")
294
+ end
295
+
296
+ else
297
+ ############################
298
+ # Handle Unknown data types
299
+ ############################
300
+
301
+ raise(ArgumentError, "data_type #{data_type} is not recognized")
302
+ end
303
+
304
+ return return_value
305
+ end
306
+
307
+ # Writes binary data of any data type to a buffer
308
+ #
309
+ # @param value [Varies] Value to write into the buffer
310
+ # @param bit_offset [Integer] Bit offset to the start of the item. A
311
+ # negative number means to offset from the end of the buffer.
312
+ # @param bit_size [Integer] Size of the item in bits
313
+ # @param data_type [Symbol] {DATA_TYPES}
314
+ # @param buffer [String] Binary string buffer to write to
315
+ # @param endianness [Symbol] {ENDIANNESS}
316
+ # @param overflow [Symbol] {OVERFLOW_TYPES}
317
+ # @return [Integer] value passed in as a parameter
318
+ def self.write(value, bit_offset, bit_size, data_type, buffer, endianness, overflow)
319
+ given_bit_offset = bit_offset
320
+ given_bit_size = bit_size
321
+
322
+ bit_offset = check_bit_offset_and_size(:write, given_bit_offset, given_bit_size, data_type, buffer)
323
+
324
+ # If passed a negative bit size with strings or blocks
325
+ # recalculate based on the value length in bytes
326
+ if (bit_size <= 0) && ((data_type == :STRING) || (data_type == :BLOCK))
327
+ value = value.to_s
328
+ bit_size = value.length * 8
329
+ end
330
+
331
+ result, lower_bound, upper_bound = check_bounds_and_buffer_size(bit_offset, bit_size, buffer.length, endianness, data_type)
332
+ raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size) if !result && (given_bit_size > 0)
333
+
334
+ # Check overflow type
335
+ if (overflow != :TRUNCATE) && (overflow != :SATURATE) && (overflow != :ERROR) && (overflow != :ERROR_ALLOW_HEX)
336
+ raise(ArgumentError, "unknown overflow type #{overflow}")
337
+ end
338
+
339
+ if (data_type == :STRING) || (data_type == :BLOCK)
340
+ #######################################
341
+ # Handle :STRING and :BLOCK data types
342
+ #######################################
343
+ value = value.to_s
344
+
345
+ if byte_aligned(bit_offset)
346
+ temp = value
347
+ if given_bit_size <= 0
348
+ end_bytes = -(given_bit_size / 8)
349
+ old_upper_bound = buffer.length - 1 - end_bytes
350
+ # Lower bound + end_bytes can never be more than 1 byte outside of the given buffer
351
+ if (lower_bound + end_bytes) > buffer.length
352
+ raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size)
353
+ end
354
+
355
+ if old_upper_bound < lower_bound
356
+ # String was completely empty
357
+ if end_bytes > 0
358
+ # Preserve bytes at end of buffer
359
+ buffer_length = buffer.length
360
+ buffer << "\000" * value.length
361
+ buffer[lower_bound + value.length, end_bytes] = buffer[lower_bound, end_bytes]
362
+ end
363
+ elsif bit_size == 0
364
+ # Remove entire string
365
+ buffer[lower_bound, old_upper_bound - lower_bound + 1] = ''
366
+ elsif upper_bound < old_upper_bound
367
+ # Remove extra bytes from old string
368
+ buffer[upper_bound + 1, old_upper_bound - upper_bound] = ''
369
+ elsif (upper_bound > old_upper_bound) && (end_bytes > 0)
370
+ # Preserve bytes at end of buffer
371
+ buffer_length = buffer.length
372
+ diff = upper_bound - old_upper_bound
373
+ buffer << "\000" * diff
374
+ buffer[upper_bound + 1, end_bytes] = buffer[old_upper_bound + 1, end_bytes]
375
+ end
376
+ else # given_bit_size > 0
377
+ byte_size = bit_size / 8
378
+ if value.length < byte_size
379
+ # Pad the requested size with zeros
380
+ temp = value.ljust(byte_size, "\000")
381
+ elsif value.length > byte_size
382
+ if overflow == :TRUNCATE
383
+ # Resize the value to fit the field
384
+ value[byte_size, value.length - byte_size] = ''
385
+ else
386
+ raise(ArgumentError, "value of #{value.length} bytes does not fit into #{byte_size} bytes for data_type #{data_type}")
387
+ end
388
+ end
389
+ end
390
+ if bit_size != 0
391
+ buffer[lower_bound, temp.length] = temp
392
+ end
393
+ else
394
+ raise(ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}")
395
+ end
396
+
397
+ elsif (data_type == :INT) || (data_type == :UINT)
398
+ ###################################
399
+ # Handle :INT data type
400
+ ###################################
401
+ value = Integer(value)
402
+ min_value, max_value, hex_max_value = get_check_overflow_ranges(bit_size, data_type)
403
+ value = check_overflow(value, min_value, max_value, hex_max_value, bit_size, data_type, overflow)
404
+
405
+ if byte_aligned(bit_offset) && even_bit_size(bit_size)
406
+ ###########################################################
407
+ # Handle byte-aligned 8, 16, 32, and 64 bit
408
+ ###########################################################
409
+
410
+ if data_type == :INT
411
+ ###########################################################
412
+ # Handle byte-aligned 8, 16, 32, and 64 bit :INT
413
+ ###########################################################
414
+
415
+ case bit_size
416
+ when 8
417
+ buffer.setbyte(lower_bound, value)
418
+ when 16
419
+ if endianness == HOST_ENDIANNESS
420
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_16_BIT_INT)
421
+ else # endianness != HOST_ENDIANNESS
422
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_16_BIT_INT).reverse
423
+ end
424
+ when 32
425
+ if endianness == HOST_ENDIANNESS
426
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_32_BIT_INT)
427
+ else # endianness != HOST_ENDIANNESS
428
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_32_BIT_INT).reverse
429
+ end
430
+ when 64
431
+ if endianness == HOST_ENDIANNESS
432
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_INT)
433
+ else # endianness != HOST_ENDIANNESS
434
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_INT).reverse
435
+ end
436
+ end
437
+ else # data_type == :UINT
438
+ ###########################################################
439
+ # Handle byte-aligned 8, 16, 32, and 64 bit :UINT
440
+ ###########################################################
441
+
442
+ case bit_size
443
+ when 8
444
+ buffer.setbyte(lower_bound, value)
445
+ when 16
446
+ if endianness == :BIG_ENDIAN
447
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_16_BIT_UINT)
448
+ else # endianness == :LITTLE_ENDIAN
449
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_16_BIT_UINT)
450
+ end
451
+ when 32
452
+ if endianness == :BIG_ENDIAN
453
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_32_BIT_UINT)
454
+ else # endianness == :LITTLE_ENDIAN
455
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_32_BIT_UINT)
456
+ end
457
+ when 64
458
+ if endianness == HOST_ENDIANNESS
459
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_UINT)
460
+ else # endianness != HOST_ENDIANNESS
461
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_UINT).reverse
462
+ end
463
+ end
464
+ end
465
+
466
+ else
467
+ ###########################################################
468
+ # Handle bit fields
469
+ ###########################################################
470
+
471
+ # Extract Existing Data
472
+ if endianness == :LITTLE_ENDIAN
473
+ # Bitoffset always refers to the most significant bit of a bitfield
474
+ num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1
475
+ upper_bound = bit_offset / 8
476
+ lower_bound = upper_bound - num_bytes + 1
477
+ if lower_bound < 0
478
+ raise(ArgumentError, "LITTLE_ENDIAN bitfield with bit_offset #{given_bit_offset} and bit_size #{given_bit_size} is invalid")
479
+ end
480
+ temp_data = buffer[lower_bound..upper_bound].reverse
481
+ else
482
+ temp_data = buffer[lower_bound..upper_bound]
483
+ end
484
+
485
+ # Determine temp upper bound
486
+ temp_upper = upper_bound - lower_bound
487
+
488
+ # Determine Values needed to Handle Bitfield
489
+ start_bits = bit_offset % 8
490
+ start_mask = (0xFF << (8 - start_bits))
491
+ total_bits = (temp_upper + 1) * 8
492
+ end_bits = total_bits - start_bits - bit_size
493
+ end_mask = ~(0xFF << end_bits)
494
+
495
+ # Add in Start Bits
496
+ temp = temp_data.getbyte(0) & start_mask
497
+
498
+ # Adjust value to correct number of bits
499
+ temp_mask = (2 ** bit_size) - 1
500
+ temp_value = value & temp_mask
501
+
502
+ # Add in New Data
503
+ temp = (temp << (bit_size - (8 - start_bits))) + temp_value
504
+
505
+ # Add in Remainder of Existing Data
506
+ temp = (temp << end_bits) + (temp_data.getbyte(temp_upper) & end_mask)
507
+
508
+ # Extract into an array of bytes
509
+ temp_array = []
510
+ (0..temp_upper).each { temp_array.insert(0, (temp & 0xFF)); temp = temp >> 8 }
511
+
512
+ # Store into data
513
+ if endianness == :LITTLE_ENDIAN
514
+ buffer[lower_bound..upper_bound] = temp_array.pack(PACK_8_BIT_UINT_ARRAY).reverse
515
+ else
516
+ buffer[lower_bound..upper_bound] = temp_array.pack(PACK_8_BIT_UINT_ARRAY)
517
+ end
518
+
519
+ end
520
+
521
+ elsif data_type == :FLOAT
522
+ ##########################
523
+ # Handle :FLOAT data type
524
+ ##########################
525
+ value = Float(value)
526
+
527
+ if byte_aligned(bit_offset)
528
+ case bit_size
529
+ when 32
530
+ if endianness == :BIG_ENDIAN
531
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_32_BIT_FLOAT)
532
+ else # endianness == :LITTLE_ENDIAN
533
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_32_BIT_FLOAT)
534
+ end
535
+ when 64
536
+ if endianness == :BIG_ENDIAN
537
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_64_BIT_FLOAT)
538
+ else # endianness == :LITTLE_ENDIAN
539
+ buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_64_BIT_FLOAT)
540
+ end
541
+ else
542
+ raise(ArgumentError, "bit_size is #{given_bit_size} but must be 32 or 64 for data_type #{data_type}")
543
+ end
544
+ else
545
+ raise(ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}")
546
+ end
547
+
548
+ else
549
+ ############################
550
+ # Handle Unknown data types
551
+ ############################
552
+
553
+ raise(ArgumentError, "data_type #{data_type} is not recognized")
554
+ end
555
+
556
+ return value
557
+ end
558
+
559
+ protected
560
+
561
+ # Check the bit size and bit offset for problems. Recalulate the bit offset
562
+ # and return back through the passed in pointer.
563
+ def self.check_bit_offset_and_size(read_or_write, given_bit_offset, given_bit_size, data_type, buffer)
564
+ bit_offset = given_bit_offset
565
+
566
+ if (given_bit_size <= 0) && (data_type != :STRING) && (data_type != :BLOCK)
567
+ raise(ArgumentError, "bit_size #{given_bit_size} must be positive for data types other than :STRING and :BLOCK")
568
+ end
569
+
570
+ if (given_bit_size <= 0) && (given_bit_offset < 0)
571
+ raise(ArgumentError, "negative or zero bit_sizes (#{given_bit_size}) cannot be given with negative bit_offsets (#{given_bit_offset})")
572
+ end
573
+
574
+ if given_bit_offset < 0
575
+ bit_offset = (buffer.length * 8) + bit_offset
576
+ if bit_offset < 0
577
+ raise_buffer_error(read_or_write, buffer, data_type, given_bit_offset, given_bit_size)
578
+ end
579
+ end
580
+
581
+ return bit_offset
582
+ end
583
+
584
+ # Calculate the bounds of the string to access the item based on the bit_offset and bit_size.
585
+ # Also determine if the buffer size is sufficient.
586
+ def self.check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, endianness, data_type)
587
+ result = true # Assume ok
588
+
589
+ # Define bounds of string to access this item
590
+ lower_bound = bit_offset / 8
591
+ upper_bound = (bit_offset + bit_size - 1) / 8
592
+
593
+ # Sanity check buffer size
594
+ if upper_bound >= buffer_length
595
+ # If it's not the special case of little endian bit field then we fail and return false
596
+ if !( (endianness == :LITTLE_ENDIAN) &&
597
+ ((data_type == :INT) || (data_type == :UINT)) &&
598
+ # Not byte aligned with an even bit size
599
+ (!( (byte_aligned(bit_offset)) && (even_bit_size(bit_size)) )) &&
600
+ (lower_bound < buffer_length)
601
+ )
602
+ result = false
603
+ end
604
+ end
605
+ return result, lower_bound, upper_bound
606
+ end
607
+
608
+ def self.get_check_overflow_ranges(bit_size, data_type)
609
+ min_value = 0 # Default for UINT cases
610
+
611
+ case bit_size
612
+ when 8
613
+ hex_max_value = MAX_UINT8
614
+ if data_type == :INT
615
+ min_value = MIN_INT8
616
+ max_value = MAX_INT8
617
+ else
618
+ max_value = MAX_UINT8
619
+ end
620
+ when 16
621
+ hex_max_value = MAX_UINT16
622
+ if data_type == :INT
623
+ min_value = MIN_INT16
624
+ max_value = MAX_INT16
625
+ else
626
+ max_value = MAX_UINT16
627
+ end
628
+ when 32
629
+ hex_max_value = MAX_UINT32
630
+ if data_type == :INT
631
+ min_value = MIN_INT32
632
+ max_value = MAX_INT32
633
+ else
634
+ max_value = MAX_UINT32
635
+ end
636
+ when 64
637
+ hex_max_value = MAX_UINT64
638
+ if data_type == :INT
639
+ min_value = MIN_INT64
640
+ max_value = MAX_INT64
641
+ else
642
+ max_value = MAX_UINT64
643
+ end
644
+ else # Bitfield
645
+ if data_type == :INT
646
+ # Note signed integers must allow up to the maximum unsigned value to support values given in hex
647
+ if bit_size > 1
648
+ max_value = 2 ** (bit_size - 1)
649
+ # min_value = -(2 ** bit_size - 1)
650
+ min_value = -max_value
651
+ # max_value = (2 ** bit_size - 1) - 1
652
+ max_value -= 1
653
+ # hex_max_value = (2 ** bit_size) - 1
654
+ hex_max_value = (2 ** bit_size) - 1
655
+ else # 1-bit signed
656
+ min_value = -1
657
+ max_value = 1
658
+ hex_max_value = 1
659
+ end
660
+ else
661
+ max_value = (2 ** bit_size) - 1
662
+ hex_max_value = max_value
663
+ end
664
+ end
665
+
666
+ return min_value, max_value, hex_max_value
667
+ end
668
+
669
+ def self.byte_aligned(value)
670
+ (value % 8) == 0
671
+ end
672
+
673
+ def self.even_bit_size(bit_size)
674
+ (bit_size == 8) || (bit_size == 16) || (bit_size == 32) || (bit_size == 64)
675
+ end
676
+
677
+ public
678
+ end
115
679
 
116
680
  # Reads an array of binary data of any data type from a buffer
117
681
  #
@@ -418,16 +982,16 @@ module Cosmos
418
982
  case bit_size
419
983
  when 8
420
984
  if data_type == :INT
421
- values = self.check_overflow_array(values, -128, 127, 255, bit_size, data_type, overflow)
985
+ values = self.check_overflow_array(values, MIN_INT8, MAX_INT8, MAX_UINT8, bit_size, data_type, overflow)
422
986
  packed = values.pack(PACK_8_BIT_INT_ARRAY)
423
987
  else # data_type == :UINT
424
- values = self.check_overflow_array(values, 0, 255, 255, bit_size, data_type, overflow)
988
+ values = self.check_overflow_array(values, 0, MAX_UINT8, MAX_UINT8, bit_size, data_type, overflow)
425
989
  packed = values.pack(PACK_8_BIT_UINT_ARRAY)
426
990
  end
427
991
 
428
992
  when 16
429
993
  if data_type == :INT
430
- values = self.check_overflow_array(values, -32768, 32767, 65535, bit_size, data_type, overflow)
994
+ values = self.check_overflow_array(values, MIN_INT16, MAX_INT16, MAX_UINT16, bit_size, data_type, overflow)
431
995
  if endianness == HOST_ENDIANNESS
432
996
  packed = values.pack(PACK_NATIVE_16_BIT_INT_ARRAY)
433
997
  else # endianness != HOST_ENDIANNESS
@@ -435,7 +999,7 @@ module Cosmos
435
999
  self.byte_swap_buffer!(packed, 2)
436
1000
  end
437
1001
  else # data_type == :UINT
438
- values = self.check_overflow_array(values, 0, 65535, 65535, bit_size, data_type, overflow)
1002
+ values = self.check_overflow_array(values, 0, MAX_UINT16, MAX_UINT16, bit_size, data_type, overflow)
439
1003
  if endianness == :BIG_ENDIAN
440
1004
  packed = values.pack(PACK_BIG_ENDIAN_16_BIT_UINT_ARRAY)
441
1005
  else # endianness == :LITTLE_ENDIAN
@@ -445,7 +1009,7 @@ module Cosmos
445
1009
 
446
1010
  when 32
447
1011
  if data_type == :INT
448
- values = self.check_overflow_array(values, -2147483648, 2147483647, 4294967295, bit_size, data_type, overflow)
1012
+ values = self.check_overflow_array(values, MIN_INT32, MAX_INT32, MAX_UINT32, bit_size, data_type, overflow)
449
1013
  if endianness == HOST_ENDIANNESS
450
1014
  packed = values.pack(PACK_NATIVE_32_BIT_INT_ARRAY)
451
1015
  else # endianness != HOST_ENDIANNESS
@@ -453,7 +1017,7 @@ module Cosmos
453
1017
  self.byte_swap_buffer!(packed, 4)
454
1018
  end
455
1019
  else # data_type == :UINT
456
- values = self.check_overflow_array(values, 0, 4294967295, 4294967295, bit_size, data_type, overflow)
1020
+ values = self.check_overflow_array(values, 0, MAX_UINT32, MAX_UINT32, bit_size, data_type, overflow)
457
1021
  if endianness == :BIG_ENDIAN
458
1022
  packed = values.pack(PACK_BIG_ENDIAN_32_BIT_UINT_ARRAY)
459
1023
  else # endianness == :LITTLE_ENDIAN
@@ -463,7 +1027,7 @@ module Cosmos
463
1027
 
464
1028
  when 64
465
1029
  if data_type == :INT
466
- values = self.check_overflow_array(values, -9223372036854775808, 9223372036854775807, 18446744073709551615, bit_size, data_type, overflow)
1030
+ values = self.check_overflow_array(values, MIN_INT64, MAX_INT64, MAX_UINT64, bit_size, data_type, overflow)
467
1031
  if endianness == HOST_ENDIANNESS
468
1032
  packed = values.pack(PACK_NATIVE_64_BIT_INT_ARRAY)
469
1033
  else # endianness != HOST_ENDIANNESS
@@ -471,7 +1035,7 @@ module Cosmos
471
1035
  self.byte_swap_buffer!(packed, 8)
472
1036
  end
473
1037
  else # data_type == :UINT
474
- values = self.check_overflow_array(values, 0, 18446744073709551615, 18446744073709551615, bit_size, data_type, overflow)
1038
+ values = self.check_overflow_array(values, 0, MAX_UINT64, MAX_UINT64, bit_size, data_type, overflow)
475
1039
  if endianness == HOST_ENDIANNESS
476
1040
  packed = values.pack(PACK_NATIVE_64_BIT_UINT_ARRAY)
477
1041
  else # endianness != HOST_ENDIANNESS
@@ -590,7 +1154,10 @@ module Cosmos
590
1154
  # @param overflow [Symbol] {OVERFLOW_TYPES}
591
1155
  # @return [Integer] Potentially modified value
592
1156
  def self.check_overflow(value, min_value, max_value, hex_max_value, bit_size, data_type, overflow)
593
- if overflow != :TRUNCATE
1157
+ if overflow == :TRUNCATE
1158
+ # Note this will always convert to unsigned equivalent for signed integers
1159
+ value = value % (hex_max_value + 1)
1160
+ else
594
1161
  if value > max_value
595
1162
  if overflow == :SATURATE
596
1163
  value = max_value