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.
- checksums.yaml +4 -4
- data/.rubocop.yml +23 -0
- data/.travis.yml +1 -0
- data/.yardopts +3 -0
- data/Gemfile +1 -1
- data/Manifest.txt +137 -52
- data/Rakefile +50 -44
- data/autohotkey/config/system/system.txt +0 -5
- data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +6 -1
- data/autohotkey/config/targets/INST/screens/extra.txt +19 -0
- data/autohotkey/config/targets/INST/sequences/run_sequence.txt +1 -0
- data/autohotkey/config/targets/META/screens/data.txt +12 -0
- data/autohotkey/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
- data/autohotkey/config/targets/{COSMOS/cmd_tlm/cosmos_server_cmds.txt → SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
- data/autohotkey/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
- data/autohotkey/config/targets/SYSTEM/screens/limits_change.txt +14 -0
- data/autohotkey/config/targets/SYSTEM/screens/meta.txt +14 -0
- data/autohotkey/config/targets/SYSTEM/target.txt +12 -0
- data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
- data/autohotkey/config/tools/test_runner/test_runner2.txt +1 -1
- data/autohotkey/tools/CmdSequence +14 -0
- data/autohotkey/tools/CmdSequenceAHK +23 -0
- data/autohotkey/tools/CmdSequenceAHK2 +16 -0
- data/autohotkey/tools/cmd_extractor.ahk +2 -2
- data/autohotkey/tools/cmd_sender.ahk +4 -6
- data/autohotkey/tools/cmd_sequence.ahk +215 -0
- data/autohotkey/tools/cmd_sequence2.ahk +23 -0
- data/autohotkey/tools/data_viewer.ahk +2 -3
- data/autohotkey/tools/limits_monitor.ahk +9 -11
- data/autohotkey/tools/open_gl_builder.ahk +1 -2
- data/autohotkey/tools/packet_viewer.ahk +51 -35
- data/autohotkey/tools/replay.ahk +1 -2
- data/autohotkey/tools/script_runner.ahk +1 -2
- data/autohotkey/tools/script_runner2.ahk +1 -2
- data/autohotkey/tools/test_runner2.ahk +1 -5
- data/autohotkey/tools/test_runner3.ahk +1 -3
- data/autohotkey/tools/tlm_grapher.ahk +1 -3
- data/autohotkey/tools/tlm_grapher3.ahk +1 -2
- data/autohotkey/tools/tlm_viewer.ahk +8 -3
- data/autohotkey/tools/tlm_viewer2.ahk +2 -3
- data/autohotkey/tools/tlm_viewer5.ahk +1 -2
- data/cosmos.gemspec +26 -20
- data/data/cmd_sequence.png +0 -0
- data/data/config/_array_params.yaml +23 -0
- data/data/config/_id_items.yaml +24 -0
- data/data/config/_id_params.yaml +58 -0
- data/data/config/_interfaces.yaml +206 -0
- data/data/config/_items.yaml +20 -0
- data/data/config/_params.yaml +58 -0
- data/data/config/cmd_tlm_server.yaml +110 -0
- data/data/config/command.yaml +38 -0
- data/data/config/command_modifiers.yaml +127 -0
- data/data/config/command_telemetry.yaml +3 -0
- data/data/config/data_viewer.yaml +43 -0
- data/data/config/handbook_creator.yaml +23 -0
- data/data/config/housekeeping_params.yaml +71 -0
- data/data/config/interface_modifiers.yaml +44 -0
- data/data/config/item_modifiers.yaml +172 -0
- data/data/config/launcher.yaml +117 -0
- data/data/config/limits_monitor.yaml +53 -0
- data/data/config/linegraph_params.yaml +30 -0
- data/data/config/linegraph_plot.yaml +106 -0
- data/data/config/page_modifiers.yaml +128 -0
- data/data/config/param_item_modifiers.yaml +41 -0
- data/data/config/parameter_modifiers.yaml +144 -0
- data/data/config/protocols.yaml +257 -0
- data/data/config/screen.yaml +151 -0
- data/data/config/script_runner.yaml +15 -0
- data/data/config/system.yaml +153 -0
- data/data/config/table_manager.yaml +76 -0
- data/data/config/table_parameter_modifiers.yaml +9 -0
- data/data/config/target.yaml +71 -0
- data/data/config/telemetry.yaml +73 -0
- data/data/config/telemetry_modifiers.yaml +129 -0
- data/data/config/test_runner.yaml +118 -0
- data/data/config/tlm_extractor.yaml +109 -0
- data/data/config/tlm_grapher.yaml +78 -0
- data/data/config/tlm_viewer.yaml +107 -0
- data/data/config/unknown.yaml +3 -0
- data/data/config/widgets.yaml +1339 -0
- data/data/config/xy_params.yaml +50 -0
- data/data/config/xy_plot.yaml +12 -0
- data/data/config_editor.png +0 -0
- data/data/crc.txt +172 -161
- data/data/delete.png +0 -0
- data/demo/config/data/crc.txt +56 -36
- data/demo/config/data/meta_init.txt +1 -4
- data/demo/config/system/system.txt +15 -3
- data/demo/config/system/system2.txt +13 -3
- data/demo/config/targets/EXAMPLE/lib/example_interface.rb +2 -6
- data/demo/config/targets/EXAMPLE/target.txt +3 -1
- data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -0
- data/demo/config/targets/INST/lib/inst_dump_component.rb +34 -0
- data/demo/config/targets/INST/screens/adcs.txt +39 -15
- data/demo/config/targets/INST/screens/commanding.txt +26 -19
- data/demo/config/targets/INST/screens/spacing_box.txt +44 -0
- data/demo/config/targets/INST/screens/spacing_grid.txt +78 -0
- data/demo/config/targets/INST/screens/tabs.txt +0 -2
- data/demo/config/targets/INST/sequences/sequence.tsv +3 -0
- data/demo/config/targets/INST/tables/EventAction.csv +9 -0
- data/demo/config/targets/INST/tables/EventAction.dat +0 -0
- data/demo/config/targets/INST/tables/McConfigTable.csv +20 -0
- data/demo/config/targets/INST/tables/McConfigTable.dat +0 -0
- data/demo/config/targets/INST/target.txt +4 -0
- data/demo/config/targets/INST/tools/data_viewer/data_viewer.txt +2 -0
- data/demo/config/targets/INST/tools/data_viewer/data_viewer2.txt +2 -0
- data/demo/config/targets/INST/tools/table_manager/EventAction_def.txt +6 -0
- data/demo/config/targets/INST/tools/table_manager/McConfigTable_def.txt +38 -0
- data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -3
- data/demo/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
- data/demo/config/targets/{COSMOS/cmd_tlm/cosmos_server_cmds.txt → SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
- data/demo/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
- data/demo/config/targets/{COSMOS → SYSTEM}/cmd_tlm_server.txt +2 -2
- data/demo/config/targets/SYSTEM/lib/limits_groups.rb +39 -0
- data/demo/config/targets/SYSTEM/screens/status.txt +1 -1
- data/demo/config/targets/SYSTEM/target.txt +12 -0
- data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +1 -1
- data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +8 -5
- data/demo/config/targets/TEMPLATED/target.txt +2 -0
- data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +15 -6
- data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +13 -5
- data/demo/config/tools/data_viewer/data_viewer.txt +9 -0
- data/demo/config/tools/launcher/launcher.txt +9 -6
- data/demo/config/tools/launcher/launcher2.txt +16 -13
- data/demo/config/tools/launcher/launcher_mini.txt +45 -0
- data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +12 -11
- data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +12 -11
- data/demo/config/tools/test_runner/test_runner.txt +1 -1
- data/demo/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
- data/demo/lib/example_background_task.rb +9 -5
- data/demo/lib/example_target.rb +5 -15
- data/demo/lib/scpi_target.rb +4 -10
- data/demo/procedures/cosmos_api_test.rb +17 -0
- data/demo/tools/CmdSequence +16 -0
- data/demo/tools/CmdSequence.bat +9 -0
- data/demo/tools/ConfigEditor +16 -0
- data/demo/tools/ConfigEditor.bat +9 -0
- data/demo/tools/mac/CmdSequence.app/Contents/Info.plist +38 -0
- data/demo/tools/mac/CmdSequence.app/Contents/MacOS/CmdSequence.rb +16 -0
- data/demo/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +10 -0
- data/demo/tools/mac/CmdSequence.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/CmdSequence.app/Contents/Resources/appIcon.icns +0 -0
- data/ext/cosmos/ext/packet/packet.c +5 -5
- data/install/config/data/crc.txt +12 -8
- data/install/config/system/system.txt +13 -3
- data/install/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +14 -0
- data/install/config/targets/SYSTEM/target.txt +12 -0
- data/install/tools/CmdSequence +16 -0
- data/install/tools/CmdSequence.bat +9 -0
- data/install/tools/ConfigEditor +16 -0
- data/install/tools/ConfigEditor.bat +9 -0
- data/install/tools/mac/CmdSequence.app/Contents/Info.plist +38 -0
- data/install/tools/mac/CmdSequence.app/Contents/MacOS/CmdSequence.rb +16 -0
- data/install/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +10 -0
- data/install/tools/mac/CmdSequence.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/CmdSequence.app/Contents/Resources/appIcon.icns +0 -0
- data/lib/cosmos.rb +1 -1
- data/lib/cosmos/config/config_parser.rb +147 -59
- data/lib/cosmos/config/meta_config_parser.rb +57 -0
- data/lib/cosmos/conversions/polynomial_conversion.rb +20 -4
- data/lib/cosmos/conversions/unix_time_conversion.rb +4 -4
- data/lib/cosmos/core_ext/array.rb +45 -5
- data/lib/cosmos/core_ext/cosmos_io.rb +31 -15
- data/lib/cosmos/core_ext/file.rb +2 -2
- data/lib/cosmos/core_ext/kernel.rb +1 -6
- data/lib/cosmos/core_ext/objectspace.rb +0 -2
- data/lib/cosmos/core_ext/string.rb +27 -4
- data/lib/cosmos/core_ext/time.rb +39 -10
- data/lib/cosmos/gui/choosers/combobox_chooser.rb +37 -26
- data/lib/cosmos/gui/choosers/file_chooser.rb +23 -6
- data/lib/cosmos/gui/choosers/float_chooser.rb +13 -11
- data/lib/cosmos/gui/choosers/integer_chooser.rb +13 -11
- data/lib/cosmos/gui/choosers/string_chooser.rb +18 -36
- data/lib/cosmos/gui/choosers/telemetry_chooser.rb +64 -64
- data/lib/cosmos/gui/choosers/value_chooser.rb +15 -15
- data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -13
- data/lib/cosmos/gui/dialogs/calendar_dialog.rb +11 -3
- data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +1 -1
- data/lib/cosmos/gui/dialogs/details_dialog.rb +1 -1
- data/lib/cosmos/gui/dialogs/exception_dialog.rb +7 -7
- data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +20 -15
- data/lib/cosmos/gui/dialogs/interface_raw_dialog.rb +143 -0
- data/lib/cosmos/gui/dialogs/legal_dialog.rb +6 -5
- data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +5 -2
- data/lib/cosmos/gui/dialogs/progress_dialog.rb +1 -1
- data/lib/cosmos/gui/dialogs/pry_dialog.rb +4 -4
- data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +3 -0
- data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +7 -6
- data/lib/cosmos/gui/dialogs/splash.rb +1 -1
- data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +1 -1
- data/lib/cosmos/gui/dialogs/tlm_graph_dialog.rb +114 -0
- data/lib/cosmos/gui/line_graph/line_graph.rb +9 -10
- data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +7 -5
- data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +3 -7
- data/lib/cosmos/gui/line_graph/line_graph_popups.rb +3 -8
- data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +2 -7
- data/lib/cosmos/gui/line_graph/overview_graph.rb +6 -1
- data/lib/cosmos/gui/opengl/earth_model.rb +6 -3
- data/lib/cosmos/gui/opengl/gl_bounds.rb +11 -23
- data/lib/cosmos/gui/opengl/gl_light.rb +3 -4
- data/lib/cosmos/gui/opengl/gl_material.rb +3 -4
- data/lib/cosmos/gui/opengl/gl_scene.rb +10 -4
- data/lib/cosmos/gui/opengl/gl_shape.rb +6 -2
- data/lib/cosmos/gui/opengl/gl_viewer.rb +5 -5
- data/lib/cosmos/gui/opengl/gl_viewport.rb +11 -12
- data/lib/cosmos/gui/opengl/moon_model.rb +6 -3
- data/lib/cosmos/gui/opengl/stl_reader.rb +8 -9
- data/lib/cosmos/gui/opengl/stl_shape.rb +4 -5
- data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +7 -7
- data/lib/cosmos/gui/qt.rb +1 -1
- data/lib/cosmos/gui/qt_tool.rb +21 -10
- data/lib/cosmos/gui/text/completion.rb +23 -2
- data/lib/cosmos/gui/text/completion_text_edit.rb +38 -23
- data/lib/cosmos/gui/utilities/analyze_log.rb +1 -1
- data/lib/cosmos/gui/utilities/screenshot.rb +2 -2
- data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +11 -1
- data/lib/cosmos/gui/widgets/packet_log_frame.rb +19 -6
- data/lib/cosmos/interfaces.rb +10 -0
- data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +28 -47
- data/lib/cosmos/interfaces/interface.rb +240 -22
- data/lib/cosmos/interfaces/linc_interface.rb +3 -5
- data/lib/cosmos/interfaces/protocols/burst_protocol.rb +173 -0
- data/lib/cosmos/interfaces/protocols/crc_protocol.rb +141 -0
- data/lib/cosmos/{streams/fixed_stream_protocol.rb → interfaces/protocols/fixed_protocol.rb} +40 -37
- data/lib/cosmos/{streams/length_stream_protocol.rb → interfaces/protocols/length_protocol.rb} +55 -48
- data/lib/cosmos/interfaces/protocols/override_protocol.rb +52 -0
- data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +141 -0
- data/lib/cosmos/interfaces/protocols/protocol.rb +60 -0
- data/lib/cosmos/interfaces/protocols/template_protocol.rb +209 -0
- data/lib/cosmos/interfaces/protocols/terminated_protocol.rb +81 -0
- data/lib/cosmos/interfaces/serial_interface.rb +28 -23
- data/lib/cosmos/interfaces/simulated_target_interface.rb +27 -16
- data/lib/cosmos/interfaces/stream_interface.rb +36 -108
- data/lib/cosmos/interfaces/tcpip_client_interface.rb +21 -21
- data/lib/cosmos/interfaces/tcpip_server_interface.rb +555 -94
- data/lib/cosmos/interfaces/udp_interface.rb +51 -83
- data/lib/cosmos/io/buffered_file.rb +92 -2
- data/lib/cosmos/io/json_drb.rb +2 -2
- data/lib/cosmos/io/posix_serial_driver.rb +3 -1
- data/lib/cosmos/io/raw_logger.rb +3 -3
- data/lib/cosmos/io/serial_driver.rb +14 -5
- data/lib/cosmos/io/win32_serial_driver.rb +16 -4
- data/lib/cosmos/packet_logs.rb +0 -1
- data/lib/cosmos/packet_logs/packet_log_reader.rb +11 -1
- data/lib/cosmos/packet_logs/packet_log_writer.rb +31 -13
- data/lib/cosmos/packets/binary_accessor.rb +599 -32
- data/lib/cosmos/packets/commands.rb +48 -24
- data/lib/cosmos/packets/packet.rb +140 -54
- data/lib/cosmos/packets/packet_config.rb +0 -2
- data/lib/cosmos/packets/parsers/packet_item_parser.rb +10 -2
- data/lib/cosmos/packets/structure.rb +81 -33
- data/lib/cosmos/packets/structure_item.rb +45 -5
- data/lib/cosmos/packets/telemetry.rb +149 -55
- data/lib/cosmos/script/api_shared.rb +1000 -0
- data/lib/cosmos/script/commands.rb +2 -2
- data/lib/cosmos/script/extract.rb +19 -4
- data/lib/cosmos/script/limits.rb +2 -0
- data/lib/cosmos/script/script.rb +1 -1
- data/lib/cosmos/script/scripting.rb +4 -784
- data/lib/cosmos/script/telemetry.rb +44 -23
- data/lib/cosmos/script/tools.rb +15 -69
- data/lib/cosmos/streams/serial_stream.rb +12 -19
- data/lib/cosmos/streams/stream.rb +2 -11
- data/lib/cosmos/streams/tcpip_socket_stream.rb +3 -13
- data/lib/cosmos/system/system.rb +187 -31
- data/lib/cosmos/system/target.rb +11 -2
- data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +12 -11
- data/lib/cosmos/tools/cmd_sender/{cmd_sender_item_delegate.rb → cmd_param_table_item_delegate.rb} +11 -10
- data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +209 -164
- data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +652 -0
- data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +510 -0
- data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +194 -0
- data/lib/cosmos/tools/cmd_tlm_server/api.rb +179 -5
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +31 -14
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +23 -16
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +92 -20
- data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +1 -1
- data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -4
- data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +0 -5
- data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +1 -2
- data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +4 -4
- data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +121 -0
- data/lib/cosmos/tools/cmd_tlm_server/routers.rb +8 -4
- data/lib/cosmos/tools/config_editor/config_editor.rb +720 -0
- data/lib/cosmos/tools/config_editor/config_editor_frame.rb +675 -0
- data/lib/cosmos/tools/data_viewer/data_viewer.rb +44 -27
- data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +8 -22
- data/lib/cosmos/tools/launcher/launcher.rb +29 -12
- data/lib/cosmos/tools/launcher/launcher_config.rb +1 -1
- data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +153 -42
- data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +44 -6
- data/lib/cosmos/tools/replay/replay.rb +36 -20
- data/lib/cosmos/tools/replay/replay_server.rb +1 -1
- data/lib/cosmos/tools/script_runner/script_runner_config.rb +1 -1
- data/lib/cosmos/tools/script_runner/script_runner_frame.rb +31 -21
- data/lib/cosmos/tools/table_manager/table_config.rb +9 -3
- data/lib/cosmos/tools/table_manager/table_manager.rb +27 -7
- data/lib/cosmos/tools/test_runner/results_writer.rb +6 -6
- data/lib/cosmos/tools/test_runner/test_runner.rb +4 -6
- data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +4 -5
- data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -1
- data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +1 -1
- data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +23 -6
- data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +44 -3
- data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +20 -7
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1 -1
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +11 -4
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +2 -2
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +1 -1
- data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +16 -0
- data/lib/cosmos/tools/tlm_viewer/screen.rb +36 -32
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +59 -50
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +2 -2
- data/lib/cosmos/tools/tlm_viewer/widgets.rb +1 -0
- data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +1 -0
- data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +22 -4
- data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +9 -0
- data/lib/cosmos/tools/tlm_viewer/widgets/spacer_widget.rb +55 -0
- data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +3 -2
- data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +3 -2
- data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +12 -12
- data/lib/cosmos/top_level.rb +34 -24
- data/lib/cosmos/utilities/crc.rb +108 -6
- data/lib/cosmos/utilities/csv.rb +68 -14
- data/lib/cosmos/utilities/logger.rb +2 -2
- data/lib/cosmos/utilities/low_fragmentation_array.rb +9 -1
- data/lib/cosmos/version.rb +6 -6
- data/lib/cosmos/win32/win32_main.rb +50 -46
- data/run_gui_tests.bat +3 -1
- data/spec/conversions/unix_time_formatted_conversion_spec.rb +2 -2
- data/spec/conversions/unix_time_seconds_conversion_spec.rb +2 -2
- data/spec/core_ext/file_spec.rb +1 -1
- data/spec/core_ext/objectspace_spec.rb +12 -9
- data/spec/core_ext/string_spec.rb +6 -0
- data/spec/core_ext/time_spec.rb +10 -0
- data/spec/gui/line_graph/line_clip_spec.rb +226 -224
- data/spec/gui/qt_spec.rb +81 -79
- data/spec/install/config/system/system.txt +0 -6
- data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +5 -5
- data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +8 -8
- data/spec/install/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
- data/{install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt → spec/install/config/targets/SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
- data/spec/install/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
- data/spec/install/config/targets/{COSMOS → SYSTEM}/cmd_tlm_server.txt +2 -2
- data/spec/install/config/targets/SYSTEM/screens/status.txt +12 -0
- data/spec/install/config/targets/SYSTEM/target.txt +12 -0
- data/spec/interfaces/cmd_tlm_server_interface_spec.rb +9 -13
- data/spec/interfaces/interface_spec.rb +402 -18
- data/spec/interfaces/linc_interface_spec.rb +37 -39
- data/spec/interfaces/protocols/burst_protocol_spec.rb +300 -0
- data/spec/interfaces/protocols/crc_protocol_spec.rb +709 -0
- data/spec/interfaces/protocols/fixed_protocol_spec.rb +119 -0
- data/spec/interfaces/protocols/length_protocol_spec.rb +499 -0
- data/spec/interfaces/protocols/override_protocol_spec.rb +158 -0
- data/spec/interfaces/protocols/preidentified_protocol_spec.rb +149 -0
- data/spec/interfaces/protocols/template_protocol_spec.rb +218 -0
- data/spec/interfaces/protocols/terminated_protocol_spec.rb +174 -0
- data/spec/interfaces/serial_interface_spec.rb +35 -34
- data/spec/interfaces/simulated_target_interface_spec.rb +13 -13
- data/spec/interfaces/tcpip_client_interface_spec.rb +21 -16
- data/spec/interfaces/tcpip_server_interface_spec.rb +66 -69
- data/spec/interfaces/udp_interface_spec.rb +120 -55
- data/spec/io/serial_driver_spec.rb +41 -39
- data/spec/io/udp_sockets_spec.rb +13 -8
- data/spec/io/win32_serial_driver_spec.rb +62 -59
- data/spec/packet_logs/packet_log_reader_spec.rb +68 -47
- data/spec/packet_logs/packet_log_writer_spec.rb +7 -5
- data/spec/packets/commands_spec.rb +5 -5
- data/spec/packets/packet_spec.rb +2 -14
- data/spec/script/extract_spec.rb +21 -7
- data/spec/script/scripting_spec.rb +261 -6
- data/spec/script/telemetry_spec.rb +17 -9
- data/spec/spec_helper.rb +26 -10
- data/spec/streams/serial_stream_spec.rb +87 -82
- data/spec/streams/tcpip_client_stream_spec.rb +12 -4
- data/spec/streams/tcpip_socket_stream_spec.rb +5 -0
- data/spec/system/system_spec.rb +66 -50
- data/spec/system/target_spec.rb +33 -11
- data/spec/tools/cmd_tlm_server/api_spec.rb +5 -5
- data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +75 -15
- data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +125 -5
- data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +244 -232
- data/spec/tools/cmd_tlm_server/commanding_spec.rb +18 -18
- data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +124 -29
- data/spec/tools/cmd_tlm_server/interfaces_spec.rb +2 -2
- data/spec/tools/cmd_tlm_server/limits_groups_background_task_spec.rb +145 -0
- data/spec/tools/cmd_tlm_server/router_thread_spec.rb +50 -10
- data/spec/tools/table_manager/tablemanager_core_spec.rb +0 -1
- data/spec/top_level/top_level_spec.rb +39 -11
- data/spec/utilities/csv_spec.rb +62 -20
- data/tasks/gemfile_stats.rake +6 -3
- data/test/performance/config/system/system_packets.txt +0 -1
- data/test/performance/config/system/system_threads.txt +0 -1
- metadata +177 -92
- data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
- data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +0 -6
- data/autohotkey/config/targets/COSMOS/target.txt +0 -5
- data/autohotkey/userpath.txt +0 -1
- data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
- data/demo/config/targets/COSMOS/screens/limits_change.txt +0 -20
- data/demo/config/targets/COSMOS/screens/version.txt +0 -19
- data/demo/config/targets/COSMOS/target.txt +0 -11
- data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +0 -10
- data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +0 -13
- data/demo/userpath.txt +0 -1
- data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
- data/install/config/targets/COSMOS/cmd_tlm_server.txt +0 -6
- data/install/config/targets/COSMOS/screens/limits_change.txt +0 -20
- data/install/config/targets/COSMOS/screens/version.txt +0 -19
- data/install/config/targets/COSMOS/target.txt +0 -9
- data/install/config/targets/SYSTEM/README.txt +0 -1
- data/install/userpath.txt +0 -1
- data/lib/cosmos/io/tcpip_server.rb +0 -571
- data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +0 -107
- data/lib/cosmos/streams/burst_stream_protocol.rb +0 -25
- data/lib/cosmos/streams/preidentified_stream_protocol.rb +0 -118
- data/lib/cosmos/streams/stream_protocol.rb +0 -373
- data/lib/cosmos/streams/template_stream_protocol.rb +0 -140
- data/lib/cosmos/streams/terminated_stream_protocol.rb +0 -85
- data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +0 -41
- data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
- data/spec/install/config/targets/COSMOS/screens/limits_change.txt +0 -20
- data/spec/install/config/targets/COSMOS/screens/version.txt +0 -19
- data/spec/install/config/targets/COSMOS/target.txt +0 -5
- data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +0 -4
- data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +0 -4
- data/spec/install/userpath.txt +0 -1
- data/spec/interfaces/stream_interface_spec.rb +0 -157
- data/spec/io/tcpip_server_spec.rb +0 -338
- data/spec/packet_logs/meta_packet_log_writer_spec.rb +0 -170
- data/spec/streams/burst_stream_protocol_spec.rb +0 -32
- data/spec/streams/fixed_stream_protocol_spec.rb +0 -113
- data/spec/streams/length_stream_protocol_spec.rb +0 -300
- data/spec/streams/preidentified_stream_protocol_spec.rb +0 -121
- data/spec/streams/stream_protocol_spec.rb +0 -346
- data/spec/streams/template_stream_protocol_spec.rb +0 -156
- data/spec/streams/terminated_stream_protocol_spec.rb +0 -127
- data/test/performance/userpath.txt +0 -1
data/lib/cosmos/packet_logs.rb
CHANGED
|
@@ -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
|
-
#
|
|
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
|
-
#
|
|
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}_#{
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|