cosmos 3.9.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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