├── LICENSE ├── README.md ├── en_notes_start_hi3536ev100.md ├── gk7205v200 ├── 659A7_OpenIPC_FPV.bin ├── 88XXau.ko_8812_8821 ├── etc │ ├── init.d │ │ ├── S95majestic │ │ └── S98datalink │ ├── majestic.yaml │ ├── sensors │ │ └── imx307_i2c_2l_720p_50fps.ini │ └── wfb.conf ├── root │ ├── 1080.sh │ ├── 1080b.sh │ ├── 1080c.sh │ ├── 3K.sh │ ├── 4K.sh │ ├── 720.sh │ ├── 720b.sh │ ├── 720c.sh │ ├── 720d.sh │ ├── channels.sh │ ├── channels2.sh │ ├── ircut.sh │ └── kill.sh ├── u-boot-gk7205v200-universal.bin └── usr │ ├── bin │ ├── telemetry │ ├── venc │ └── wifibroadcast │ ├── lib │ └── sensors │ │ └── libsns_imx307_2l_720p_50fps.so │ └── sbin │ └── gkrcparams ├── gk7205v200_u-boot-7502v200-for-telemetry.md ├── gk7502v300 ├── etc │ ├── majestic.yaml │ ├── telemetry.conf │ └── wfb.conf ├── root │ └── ircut.sh └── usr │ └── lib │ └── sensors │ └── libsns_imx307.so ├── gkrcparams.md ├── gstlaunch_on_windows.md ├── hi3536dv100 ├── 88XXau-ko │ ├── 88XXau.ko_8812au │ └── 88XXau.ko_8812au_8814au ├── etc │ ├── init.d │ │ ├── S96gpio_monitor │ │ └── S99rcjoystick │ ├── mavlink.conf │ └── telemetry.conf ├── hi3536dv100.generic.config ├── hi3536dv100_fpv_defconfig ├── lib │ └── modules │ │ └── 4.9.37 │ │ └── extra │ │ ├── 8188eu.ko │ │ └── 88XXau.ko ├── original_firmware │ ├── env.txt │ └── fullflash_202303012255_W25Q128BV_16MB_HI3536DV100_orig_dev2.bin ├── root │ ├── gpio_monitor.sh │ ├── resolution.sh │ └── vdec ├── rootfs.squashfs.hi3536dv100 ├── uImage.hi3536dv100 └── usr │ └── bin │ ├── mavlink-routerd │ └── rcjoystick ├── lte-fpv.md ├── mavfwd ├── mavfwd ├── mavfwd.c └── readme.md ├── note-nvr-tab-ap.md ├── note-two-cameras-switched.md ├── note_nvr_wdt.md ├── note_telemetry_baud.md ├── notes_cam_control.md ├── notes_files ├── IMG_20230323_081622_212.jpg ├── OpenIPC_telemetry.csv ├── OpenIPC_video.csv ├── Screenshot_1.png ├── Screenshot_2.png ├── ZTNCUI.png ├── baud38400.jpg ├── gk7205v200.png ├── hi3536ev100.png ├── hi3536ev100_pinout.png ├── link_hw.png ├── mp_h265.png ├── photo_2023-03-23_02-12-40.jpg ├── qgc-udp-settings.png ├── telemetry.png ├── usb-ethernet.png └── video.png ├── notes_imx335_gk7205v300.md ├── notes_link_gk7205v200_hi3536ev100.md ├── notes_start_hi3536ev100.md ├── notes_start_ivg-g2s.md ├── nvr_gpio.md ├── rcjoystick.md ├── rcjoystick ├── Config.in ├── rcjoystick.mk └── src │ ├── Makefile │ ├── checksum.h │ ├── common │ ├── common.h │ ├── mavlink.h │ ├── mavlink_msg_actuator_control_target.h │ ├── mavlink_msg_actuator_output_status.h │ ├── mavlink_msg_adsb_vehicle.h │ ├── mavlink_msg_ais_vessel.h │ ├── mavlink_msg_altitude.h │ ├── mavlink_msg_att_pos_mocap.h │ ├── mavlink_msg_attitude.h │ ├── mavlink_msg_attitude_quaternion.h │ ├── mavlink_msg_attitude_quaternion_cov.h │ ├── mavlink_msg_attitude_target.h │ ├── mavlink_msg_auth_key.h │ ├── mavlink_msg_autopilot_state_for_gimbal_device.h │ ├── mavlink_msg_autopilot_version.h │ ├── mavlink_msg_battery_status.h │ ├── mavlink_msg_button_change.h │ ├── mavlink_msg_camera_capture_status.h │ ├── mavlink_msg_camera_fov_status.h │ ├── mavlink_msg_camera_image_captured.h │ ├── mavlink_msg_camera_information.h │ ├── mavlink_msg_camera_settings.h │ ├── mavlink_msg_camera_tracking_geo_status.h │ ├── mavlink_msg_camera_tracking_image_status.h │ ├── mavlink_msg_camera_trigger.h │ ├── mavlink_msg_can_filter_modify.h │ ├── mavlink_msg_can_frame.h │ ├── mavlink_msg_canfd_frame.h │ ├── mavlink_msg_cellular_config.h │ ├── mavlink_msg_cellular_status.h │ ├── mavlink_msg_change_operator_control.h │ ├── mavlink_msg_change_operator_control_ack.h │ ├── mavlink_msg_collision.h │ ├── mavlink_msg_command_ack.h │ ├── mavlink_msg_command_cancel.h │ ├── mavlink_msg_command_int.h │ ├── mavlink_msg_command_long.h │ ├── mavlink_msg_component_information.h │ ├── mavlink_msg_component_metadata.h │ ├── mavlink_msg_control_system_state.h │ ├── mavlink_msg_current_event_sequence.h │ ├── mavlink_msg_data_stream.h │ ├── mavlink_msg_data_transmission_handshake.h │ ├── mavlink_msg_debug.h │ ├── mavlink_msg_debug_float_array.h │ ├── mavlink_msg_debug_vect.h │ ├── mavlink_msg_distance_sensor.h │ ├── mavlink_msg_efi_status.h │ ├── mavlink_msg_encapsulated_data.h │ ├── mavlink_msg_esc_info.h │ ├── mavlink_msg_esc_status.h │ ├── mavlink_msg_estimator_status.h │ ├── mavlink_msg_event.h │ ├── mavlink_msg_extended_sys_state.h │ ├── mavlink_msg_fence_status.h │ ├── mavlink_msg_file_transfer_protocol.h │ ├── mavlink_msg_flight_information.h │ ├── mavlink_msg_follow_target.h │ ├── mavlink_msg_generator_status.h │ ├── mavlink_msg_gimbal_device_attitude_status.h │ ├── mavlink_msg_gimbal_device_information.h │ ├── mavlink_msg_gimbal_device_set_attitude.h │ ├── mavlink_msg_gimbal_manager_information.h │ ├── mavlink_msg_gimbal_manager_set_attitude.h │ ├── mavlink_msg_gimbal_manager_set_manual_control.h │ ├── mavlink_msg_gimbal_manager_set_pitchyaw.h │ ├── mavlink_msg_gimbal_manager_status.h │ ├── mavlink_msg_global_position_int.h │ ├── mavlink_msg_global_position_int_cov.h │ ├── mavlink_msg_global_vision_position_estimate.h │ ├── mavlink_msg_gps2_raw.h │ ├── mavlink_msg_gps2_rtk.h │ ├── mavlink_msg_gps_global_origin.h │ ├── mavlink_msg_gps_inject_data.h │ ├── mavlink_msg_gps_input.h │ ├── mavlink_msg_gps_raw_int.h │ ├── mavlink_msg_gps_rtcm_data.h │ ├── mavlink_msg_gps_rtk.h │ ├── mavlink_msg_gps_status.h │ ├── mavlink_msg_high_latency.h │ ├── mavlink_msg_high_latency2.h │ ├── mavlink_msg_highres_imu.h │ ├── mavlink_msg_hil_actuator_controls.h │ ├── mavlink_msg_hil_controls.h │ ├── mavlink_msg_hil_gps.h │ ├── mavlink_msg_hil_optical_flow.h │ ├── mavlink_msg_hil_rc_inputs_raw.h │ ├── mavlink_msg_hil_sensor.h │ ├── mavlink_msg_hil_state.h │ ├── mavlink_msg_hil_state_quaternion.h │ ├── mavlink_msg_home_position.h │ ├── mavlink_msg_hygrometer_sensor.h │ ├── mavlink_msg_isbd_link_status.h │ ├── mavlink_msg_landing_target.h │ ├── mavlink_msg_link_node_status.h │ ├── mavlink_msg_local_position_ned.h │ ├── mavlink_msg_local_position_ned_cov.h │ ├── mavlink_msg_local_position_ned_system_global_offset.h │ ├── mavlink_msg_log_data.h │ ├── mavlink_msg_log_entry.h │ ├── mavlink_msg_log_erase.h │ ├── mavlink_msg_log_request_data.h │ ├── mavlink_msg_log_request_end.h │ ├── mavlink_msg_log_request_list.h │ ├── mavlink_msg_logging_ack.h │ ├── mavlink_msg_logging_data.h │ ├── mavlink_msg_logging_data_acked.h │ ├── mavlink_msg_mag_cal_report.h │ ├── mavlink_msg_manual_control.h │ ├── mavlink_msg_manual_setpoint.h │ ├── mavlink_msg_memory_vect.h │ ├── mavlink_msg_message_interval.h │ ├── mavlink_msg_mission_ack.h │ ├── mavlink_msg_mission_clear_all.h │ ├── mavlink_msg_mission_count.h │ ├── mavlink_msg_mission_current.h │ ├── mavlink_msg_mission_item.h │ ├── mavlink_msg_mission_item_int.h │ ├── mavlink_msg_mission_item_reached.h │ ├── mavlink_msg_mission_request.h │ ├── mavlink_msg_mission_request_int.h │ ├── mavlink_msg_mission_request_list.h │ ├── mavlink_msg_mission_request_partial_list.h │ ├── mavlink_msg_mission_set_current.h │ ├── mavlink_msg_mission_write_partial_list.h │ ├── mavlink_msg_mount_orientation.h │ ├── mavlink_msg_named_value_float.h │ ├── mavlink_msg_named_value_int.h │ ├── mavlink_msg_nav_controller_output.h │ ├── mavlink_msg_obstacle_distance.h │ ├── mavlink_msg_odometry.h │ ├── mavlink_msg_onboard_computer_status.h │ ├── mavlink_msg_open_drone_id_arm_status.h │ ├── mavlink_msg_open_drone_id_authentication.h │ ├── mavlink_msg_open_drone_id_basic_id.h │ ├── mavlink_msg_open_drone_id_location.h │ ├── mavlink_msg_open_drone_id_message_pack.h │ ├── mavlink_msg_open_drone_id_operator_id.h │ ├── mavlink_msg_open_drone_id_self_id.h │ ├── mavlink_msg_open_drone_id_system.h │ ├── mavlink_msg_open_drone_id_system_update.h │ ├── mavlink_msg_optical_flow.h │ ├── mavlink_msg_optical_flow_rad.h │ ├── mavlink_msg_orbit_execution_status.h │ ├── mavlink_msg_param_ext_ack.h │ ├── mavlink_msg_param_ext_request_list.h │ ├── mavlink_msg_param_ext_request_read.h │ ├── mavlink_msg_param_ext_set.h │ ├── mavlink_msg_param_ext_value.h │ ├── mavlink_msg_param_map_rc.h │ ├── mavlink_msg_param_request_list.h │ ├── mavlink_msg_param_request_read.h │ ├── mavlink_msg_param_set.h │ ├── mavlink_msg_param_value.h │ ├── mavlink_msg_ping.h │ ├── mavlink_msg_play_tune.h │ ├── mavlink_msg_play_tune_v2.h │ ├── mavlink_msg_position_target_global_int.h │ ├── mavlink_msg_position_target_local_ned.h │ ├── mavlink_msg_power_status.h │ ├── mavlink_msg_radio_status.h │ ├── mavlink_msg_raw_imu.h │ ├── mavlink_msg_raw_pressure.h │ ├── mavlink_msg_raw_rpm.h │ ├── mavlink_msg_rc_channels.h │ ├── mavlink_msg_rc_channels_override.h │ ├── mavlink_msg_rc_channels_raw.h │ ├── mavlink_msg_rc_channels_scaled.h │ ├── mavlink_msg_request_data_stream.h │ ├── mavlink_msg_request_event.h │ ├── mavlink_msg_resource_request.h │ ├── mavlink_msg_response_event_error.h │ ├── mavlink_msg_safety_allowed_area.h │ ├── mavlink_msg_safety_set_allowed_area.h │ ├── mavlink_msg_scaled_imu.h │ ├── mavlink_msg_scaled_imu2.h │ ├── mavlink_msg_scaled_imu3.h │ ├── mavlink_msg_scaled_pressure.h │ ├── mavlink_msg_scaled_pressure2.h │ ├── mavlink_msg_scaled_pressure3.h │ ├── mavlink_msg_serial_control.h │ ├── mavlink_msg_servo_output_raw.h │ ├── mavlink_msg_set_actuator_control_target.h │ ├── mavlink_msg_set_attitude_target.h │ ├── mavlink_msg_set_gps_global_origin.h │ ├── mavlink_msg_set_home_position.h │ ├── mavlink_msg_set_mode.h │ ├── mavlink_msg_set_position_target_global_int.h │ ├── mavlink_msg_set_position_target_local_ned.h │ ├── mavlink_msg_setup_signing.h │ ├── mavlink_msg_sim_state.h │ ├── mavlink_msg_smart_battery_info.h │ ├── mavlink_msg_statustext.h │ ├── mavlink_msg_storage_information.h │ ├── mavlink_msg_supported_tunes.h │ ├── mavlink_msg_sys_status.h │ ├── mavlink_msg_system_time.h │ ├── mavlink_msg_terrain_check.h │ ├── mavlink_msg_terrain_data.h │ ├── mavlink_msg_terrain_report.h │ ├── mavlink_msg_terrain_request.h │ ├── mavlink_msg_time_estimate_to_target.h │ ├── mavlink_msg_timesync.h │ ├── mavlink_msg_trajectory_representation_bezier.h │ ├── mavlink_msg_trajectory_representation_waypoints.h │ ├── mavlink_msg_tunnel.h │ ├── mavlink_msg_uavcan_node_info.h │ ├── mavlink_msg_uavcan_node_status.h │ ├── mavlink_msg_utm_global_position.h │ ├── mavlink_msg_v2_extension.h │ ├── mavlink_msg_vfr_hud.h │ ├── mavlink_msg_vibration.h │ ├── mavlink_msg_vicon_position_estimate.h │ ├── mavlink_msg_video_stream_information.h │ ├── mavlink_msg_video_stream_status.h │ ├── mavlink_msg_vision_position_estimate.h │ ├── mavlink_msg_vision_speed_estimate.h │ ├── mavlink_msg_wheel_distance.h │ ├── mavlink_msg_wifi_config_ap.h │ ├── mavlink_msg_winch_status.h │ ├── mavlink_msg_wind_cov.h │ ├── testsuite.h │ └── version.h │ ├── mavlink_conversions.h │ ├── mavlink_get_info.h │ ├── mavlink_helpers.h │ ├── mavlink_sha256.h │ ├── mavlink_types.h │ ├── minimal │ ├── mavlink.h │ ├── mavlink_msg_heartbeat.h │ ├── mavlink_msg_protocol_version.h │ ├── minimal.h │ ├── testsuite.h │ └── version.h │ ├── protocol.h │ ├── rcjoystick.c │ └── standard │ ├── mavlink.h │ ├── standard.h │ ├── testsuite.h │ └── version.h ├── sbus-to-usb-joystick ├── ArduinoJoystickLibrary │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── examples │ │ ├── ArcadeStickExample │ │ │ └── ArcadeStickExample.ino │ │ ├── DrivingControllerTest │ │ │ └── DrivingControllerTest.ino │ │ ├── FlightControllerTest │ │ │ └── FlightControllerTest.ino │ │ ├── FunduinoJoystickShield │ │ │ └── FunduinoJoystickShield.ino │ │ ├── GamepadExample │ │ │ └── GamepadExample.ino │ │ ├── HatSwitchTest │ │ │ └── HatSwitchTest.ino │ │ ├── JoystickButton │ │ │ └── JoystickButton.ino │ │ ├── JoystickKeyboard │ │ │ └── JoystickKeyboard.ino │ │ ├── JoystickTest │ │ │ └── JoystickTest.ino │ │ └── MultipleJoystickTest │ │ │ └── MultipleJoystickTest.ino │ ├── library.properties │ └── src │ │ ├── DynamicHID │ │ ├── DynamicHID.cpp │ │ └── DynamicHID.h │ │ ├── JoystickMHX.cpp │ │ └── JoystickMHX.h ├── photo_2023-03-30_04-58-32.jpg ├── readme.md ├── sbus-inverter-diagram-schematics.jpg ├── sbus-to-usb-joystick.ino ├── sbus.cpp └── sbus.h ├── sigmastar ├── .dot ├── ssc338q-nand.bin └── ssc338q_initramfs.zip ├── usb-eth-modem.md ├── usb-modeswitch.md ├── usb-modeswitch ├── glibc │ ├── libusb-1.0.so.0.3.0 │ └── usb_modeswitch └── musl │ ├── libusb-1.0.so.0.3.0 │ └── usb_modeswitch ├── usb-tethering.md ├── user_TipoMan ├── .dot ├── gkrcparams └── mavfwd_mavlink2.tar ├── wfb.zip └── wfbopenhd.zip /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 OpenIPC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sandbox-fpv 2 | Sandbox for FPV experiments. Telegram-group: `https://t.me/+BMyMoolVOpkzNWUy` | [link](https://t.me/+BMyMoolVOpkzNWUy) 3 | 4 | ## News 5 | * `26.07.2023` - FPV link setup via 4G modem . 6 | 7 | * `01.07.2023` - A short note about the imx335 gk7205v300 camera . About baud for telemetry . 8 | 9 | * `22.06.2023` - Finally, the problem with the picture being jerky at 30fps was resolved . 10 | 11 | * `06.04.2023` - Added coupler firmware for ivg-g2s with u-boot on board. 12 | 13 | * `05.04.2023` - Added functionality to rcjoystick for displaying packet losses (link quality) in rssi. 14 | 15 | * `04.04.2023` - OpenIPC has added the majestic streamer, now the ivg-g2s camera runs h265 cbr (constant bitrate). This gave a cleaner picture and a significant reduction in noise. At the same time, changes were made to the link launch process. The main service is now S98datalinkwith the config /etc/datalink.conf, and wfb is now launched via /usr/bin/wifibroadcast. The articles have been corrected to accommodate this innovation. 16 | 17 | * `01.04.2023` - Due to certain circumstances, wfb-ng was replaced in my camera and recorder with an alternative from OpenHD . Here is the package for assembly in buildroot OpenIPC. The shell wrappers take into account both options, due to the presence of a parameter link_idthat is not required in the OpenHD implementation. Archive with binaries of both options. 18 | 19 | ## Notes 20 | 21 | * [Notes on setting up the link on the gk7205v200 camera and hi3536ev100 (dv100) recorder](notes_link_gk7205v200_hi3536ev100.md) 22 | * [Notes on camera firmware gk7205v200 on OpenIPC](notes_start_ivg-g2s.md) 23 | * [Notes on firmware for hi3536ev100 recorder on OpenIPC](notes_start_hi3536ev100.md) 24 | * [A note about the imx335 gk7205v300 camera](notes_imx335_gk7205v300.md) 25 | * [Adding smoothness to video on goke/hisilicon cameras](gkrcparams.md) 26 | * [A note about controlling the camera via RC channels from the ground](notes_cam_control.md) 27 | * [Switch between two cameras in the air](note-two-cameras-switched.md) 28 | * [Loader for telemetry for gk7502v200, which does not hang the camera upon reboot](gk7205v200_u-boot-7502v200-for-telemetry.md) 29 | * [Controlling buttons from the front panel on the recorder](nvr_gpio.md) 30 | * [Connecting and setting up a tablet or smartphone for video and OSD via USB](usb-tethering.md) 31 | * [Connecting the tablet to the recorder via wifi via the tablet's AP](note-nvr-tab-ap.md) 32 | * [Connecting the tablet to the recorder via ethernet-usb-device](usb-eth-modem.md) 33 | * [Using the hardware as a joystick to transmit RC channels via mavlink](rcjoystick.md) 34 | * [About the analogue of RSSI](rcjoystick.md#rssi) 35 | * [SBUS-to-USB joystick for using any equipment with an sbus receiver](sbus-to-usb-joystick) 36 | * [FPV link setup via 4G modem](lte-fpv.md) 37 | * [Installing usb_modeswitch on a camera with fpv, lite firmware](usb-modeswitch.md) 38 | 39 | #### Miscellaneous 40 | * [mavfwd for inav (one way msp) for camera](user_TipoMan/mavfwd_mavlink2.tar?raw=true) 41 | * [Displaying video on windows and MP](gstlaunch_on_windows.md) 42 | * [Disabling watchdog on the hi3536dv100 recorder](note_nvr_wdt.md) 43 | * [Different from 115200 baud on camera uart for telemetry](note_telemetry_baud.md) 44 | 45 | ## Road map 46 | * ~~Starting video with transfer from the recorder to the PC.~~ 47 | * ~~Launch one- and two-way telemetry.~~ 48 | * ~~Starting video transfer via usb tethering to an Android tablet.~~ 49 | * ~~Building and testing LTE firmware on e3372h + zerotier~~ 50 | * ~~Starting telemetry routing via mavlink-router.~~ 51 | * ~~Finding ways to control the camera through mavlink.~~. 52 | * Finding ways to output video and osd via hdmi. 53 | * ~~~Switching between several cameras, where one is the master with wfb-ng, and the rest are slaves.~~~ 54 | * Development of expansion board for camera: bec 5v/3.3v; usb hub, uart, wifi/modem power transistor, microSD. 55 | * Development of a zoom lens control board and a method for controlling commercially available boards. 56 | * Development of a stabilizing gimbal controlled from the ground via wfb-ng. 57 | 58 | 59 | 60 | ## Russians: 61 | 62 | ## Новое 63 | * `26.07.2023` - Настройка FPV-линка [через 4G модем](lte-fpv.md). 64 | 65 | * `01.07.2023` - Короткая заметка о камере [imx335 gk7205v300](notes_imx335_gk7205v300.md). О [baud для телеметрии](note_telemetry_baud.md). 66 | 67 | * `22.06.2023` - Наконец [решилась](gkrcparams.md) проблема с дерганностью картинки на 30fps. 68 | 69 | * `06.04.2023` - Добавлена [прошивка coupler](notes_start_ivg-g2s.md#L33) для ivg-g2s с u-boot на борту. 70 | 71 | * `05.04.2023` - В rcjoystick [добавлен](rcjoystick.md#rssi) функционал для целей отображения потерь пакетов (качества линка) в rssi. 72 | 73 | * `04.04.2023` - В OpenIPC "допилили" стример majestic, теперь на камере ivg-g2s работает h265 cbr (постоянный битрейт). Это дало более чистую картинку и значительное уменьшение шума. Вместе с этим были внесены изменения в процесс запуска линка. Основным сервисом теперь является `S98datalink` с конфигом `/etc/datalink.conf`, а запуск wfb теперь производится через `/usr/bin/wifibroadcast`. Статьи были исправлены под это нововведение. 74 | 75 | * `01.04.2023` - В связи с некоторыми обстоятельствами, wfb-ng был заменен в моих камере и регистраторе на альтернативу от [OpenHD](https://github.com/OpenHD/wifibroadcast/). [Тут](wfbopenhd.zip) пакет для сборки в buildroot OpenIPC. В шелл-обертках учтены оба варианта, по наличию параметра `link_id` который не требуется в реализации от OpenHD. [Архив](https://github.com/OpenIPC/sandbox-fpv/blob/master/wfb.zip) с бинарниками обоих вариантов. 76 | 77 | ## Заметки 78 | 79 | * [Заметки о настройке линка на камере gk7205v200 и регистраторе hi3536ev100 (dv100)](notes_link_gk7205v200_hi3536ev100.md) 80 | * [Заметки о прошивке камеры gk7205v200 на OpenIPC](notes_start_ivg-g2s.md) 81 | * [Заметки о прошивке регистратора hi3536ev100 на OpenIPC](notes_start_hi3536ev100.md) 82 | * [Заметка о камере imx335 gk7205v300](notes_imx335_gk7205v300.md) 83 | * [Добавляем плавности видео на goke/hisilicon камерах](gkrcparams.md) 84 | * [Заметка о управлении камерой через RC каналы с наземки](notes_cam_control.md) 85 | * [Переключение между двумя камерами в воздухе](note-two-cameras-switched.md) 86 | * [Загрузчик под телеметрию для gk7502v200, который не вешает камеру при ребуте](gk7205v200_u-boot-7502v200-for-telemetry.md) 87 | * [Управление кнопками с front panel на регистраторе](nvr_gpio.md) 88 | * [Подключение и настройка планшета или смартфона для видео и OSD по USB](usb-tethering.md) 89 | * [Подключение планшета к регистратору по wifi через AP планшета](note-nvr-tab-ap.md) 90 | * [Подключение планшета к регистратору через ethernet-usb-device](usb-eth-modem.md) 91 | * [Использование аппаратуры как джойстика для передачи каналов RC через mavlink](rcjoystick.md) 92 | * [Про аналог RSSI](rcjoystick.md#rssi) 93 | * [SBUS-to-USB joystick для использования любой аппаратуры с sbus приемником](sbus-to-usb-joystick) 94 | * [Настройка FPV-линка через 4G модем](lte-fpv.md) 95 | * [Установка usb_modeswitch на камеру с прошивкой fpv, lite](usb-modeswitch.md) 96 | 97 | #### Разное 98 | * [mavfwd для inav (односторонний msp) для камеры](user_TipoMan/mavfwd_mavlink2.tar?raw=true) 99 | * [Отображение видео на windows и в MP](gstlaunch_on_windows.md) 100 | * [Отключение watchdog на регистраторе hi3536dv100](note_nvr_wdt.md) 101 | * [Отличный от 115200 baud на uartе камеры для телеметрии](note_telemetry_baud.md) 102 | 103 | ## Дорожная карта 104 | * ~~Запуск видео с передачей с регистратора на пк.~~ 105 | * ~~Запуск одно-и двусторонней телеметрии.~~ 106 | * ~~Запуск передачи видео через usb tethering на android-планшет.~~ 107 | * ~~Сборка и тестирование прошивки LTE на e3372h + zerotier~~ 108 | * ~~Запуск маршрутизации телеметрии через mavlink-router.~~ 109 | * ~~Поиск путей управления камерой сквозь mavlink~~. 110 | * Поиск способов вывода видео и osd через hdmi. 111 | * ~~~Переключение между несколькими камерами, где одна ведущая с wfb-ng, а остальные ведомые.~~~ 112 | * Разработка платы расширения для камеры: bec 5v/3.3v; usb hub, uart, транзистор питания wifi/modem, microSD. 113 | * Разработка платы управления зум-объективом и способа управления имеющимися в продаже платами. 114 | * Разработка стабилизирующего подвеса, управляемого с земли сквозь wfb-ng. 115 | -------------------------------------------------------------------------------- /en_notes_start_hi3536ev100.md: -------------------------------------------------------------------------------- 1 | ### Notes on NVR hi3536ev100 firmware on OpenIPC for FPV purposes 2 | [RU](notes_start_hi3536ev100.md) 3 | 4 |
5 | How memory works 6 | To begin with, you need to figure out how the memory of the recorder (and the camera too) works and what needs to be flashed. Data is stored on spi-flash 16mb in the form of mtd blocks: 7 | 8 | ``` 9 | cat /proc/cmdline 10 | mem=150M console=ttyAMA0,115200 panic=20 root=/dev/mtdblock3 rootfstype=squashfs init=/init mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),8192k(rootfs),-(rootfs_data) 11 | ls /dev/mtdb* 12 | /dev/mtdblock0 /dev/mtdblock1 /dev/mtdblock2 /dev/mtdblock3 /dev/mtdblock4 13 | ``` 14 | As follows from the output, block zero is the u-boot bootloader; Next comes a block for storing environment variables (`printenv`, `setenv` commands are written to RAM, and `saveenv` saves it in this block); next is the uImage core; then rootfs.squashfs (immutable file system image); and finally rootfs_data or also overlay - a changeable part where differences from rootfs are written if you change any files. Thus, by clearing the overlay, we will reset the file system to default: 15 | ``` 16 | sf probe 0 #select a device 17 | sf erase 0xA50000 0x500000 #we clean 18 | reset #reboot nvr 19 | ``` 20 | It's even easier to reset the firmware to factory defaults using the `firstboot` command. 21 | 22 | An address calculator for commands is available [here](https://openipc.org/tools/firmware-partitions-calculation). In our case, the rootfs partition: 8192kB, which means the start address of the overlay will be 0xA50000. For a camera with a flash of 8mB and a rootfs size of 5120kB, the addresses will be different, including environment variables! 23 |
24 | 25 | The bootloader of this recorder does not have a password, and you can access it via uart/115200 baud by pressing Ctrl+C several times at startup while connected to the debug-uart port of the recorder via a usb-uart 3v3 adapter (ftdi, ch340). Debug uart is located opposite the VGA connector on the opposite edge of the board and is labeled gnd/tx/rx. We don't need to flash the bootloader, we don't need burn. Our ENVs (environment variables) are different from the factory ones, but they are easier to install directly from the bootloader line by line: 26 | ``` 27 | setenv ipaddr '192.168.0.222' #here is the ip in your subnet from the free ones 28 | setenv serverip '192.168.0.107' #PC address with tftp server 29 | setenv netmask '255.255.255.0' 30 | setenv bootcmd 'sf probe 0; sf read 0x82000000 0x50000 0x200000; bootm 0x82000000' 31 | setenv uk 'mw.b 0x82000000 ff 1000000;tftp 0x82000000 uImage.${soc}; sf probe 0; sf erase 0x50000 0x200000; sf write 0x82000000 0x50000 ${filesize}' 32 | setenv ur 'mw.b 0x82000000 ff 1000000;tftp 0x82000000 rootfs.squashfs.${soc}; sf probe 0; sf erase 0x250000 0x800000; sf write 0x82000000 0x250000 ${filesize}' 33 | setenv bootargs 'mem=192M console=ttyAMA0,115200 panic=20 root=/dev/mtdblock3 rootfstype=squashfs init=/init mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),8192k(rootfs) ,-(rootfs_data)' 34 | setenv osmem '192M' 35 | setenv totalmem '256M' 36 | setenv soc 'hi3536dv100' 37 | #here we clear variables that are no longer needed 38 | setenvda; setenv du; setenv dr; setenv dw; setenv dl; setenv dc; setenv up; setenv tk; setenvdd; setenv de; setenv jpeg_addr; setenv jpeg_size; setenv vobuf; setenv loadlogo; setenv appVideoStandard; setenv appSystemLanguage; setenv appCloudExAbility 39 | saveenv #save the new variable environment 40 | printenv #see if everything is ok 41 | ``` 42 | The original env and full dump of the chip (16mb backup of factory firmware in case of recovery) are available [here](https://github.com/OpenIPC/sandbox-fpv/tree/master/hi3536dv100/original_firmware). 43 | 44 | As you may have noticed, the uk and ur variables store macros for the uImage and rootfs downloading them from [tftp server](https://pjo2.github.io/tftpd64/) specified in serverip variable. All addresses correspond to the bootargs variable, the contents of which specify the file system layout for the kernel at boot. The layout is different from the usual for goke/hisilicone cameras, our core is the same as lite/fpv, 2MB in size, but the file system is 8MB in size, like ultimate. The remaining ~5MB are used by the overlay (your changes to the files relative to the original rootfs). For firmware, use official builds from the releases page [openipc/firmware](https://github.com/OpenIPC/firmware/releases/download/latest/openipc.hi3536dv100-nor-fpv.tgz). The archive contains the kernel and file system. 45 | 46 | So, after setting the variables, you can start flashing the remaining part. Start the tftpd server, put uImage.hi3536dv100 and rootfs.squashfs.hi3536dv100 in its root, select the appropriate network interface and run the macro in the bootloader: `run uk`. A series of commands must be executed, the output of which should indicate that the uImage file has been downloaded and flashed into flash. Similarly, run `run ur` to flash rootfs. If the addresses are set correctly, but the download is stuck at "Downloading", change the registrar address to a nearby free one: `setenv ipaddr '192.168.0.223'`. 47 | If everything went without errors, do a `reset` and boot into the operating system, login root, password 12345. 48 | 49 | The configs from the hi3536dv100 catalog are not relevant, but they may be of interest regarding connecting the tablet via usb/wifi/ethernet hotspot; you can transfer them, by analogy, to the configs of the official firmware or use separate bash scripts. Usually the essence of these changes is to determine the address of the connected tablet (which is the gateway for the registrar in cases where the tablet has a dhcp server) and specifying this address in an additional instance of wfb_rx for the video stream and for telemetry streams. 50 | 51 | The firmware is updated via the Internet using the command `sysupgrade -r -k -n`. 52 | 53 |
54 | Update without internet from /tmp 55 | In the future, you can update the recorder's firmware by uploading the kernel and rootfs into the `/tmp` directory via WinSCP and running `sysupgrade --kernel=/tmp/uImage.hi3536dv100 --rootfs=/tmp/rootfs.squashfs.hi3536dv100 -z` . The `-z` parameter is needed if you do not have an Internet connection (does not update the sysupgrade script), `-n` will clear the user fs (overlay). 56 |
57 | -------------------------------------------------------------------------------- /gk7205v200/659A7_OpenIPC_FPV.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7205v200/659A7_OpenIPC_FPV.bin -------------------------------------------------------------------------------- /gk7205v200/88XXau.ko_8812_8821: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7205v200/88XXau.ko_8812_8821 -------------------------------------------------------------------------------- /gk7205v200/etc/init.d/S95majestic: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DAEMON="majestic" 4 | PIDFILE="/var/run/$DAEMON.pid" 5 | 6 | DAEMON_ARGS="-s" 7 | 8 | # shellcheck source=/dev/null 9 | [ -r "/etc/default/$DAEMON" ] && . "/etc/default/$DAEMON" 10 | 11 | load_majestic() { 12 | printf 'Starting %s: ' "$DAEMON" 13 | [ -f /usr/bin/$DAEMON ] || echo -en "DISABLED, " 14 | # shellcheck disable=SC2086 # we need the word splitting 15 | [ -f /etc/coredump.conf ] && . /etc/coredump.conf 16 | if [ "$coredump_enabled" ]; then 17 | [ "$(cli -g .watchdog.timeout)" -lt "30" ] && cli -s .watchdog.timeout 30 18 | ulimit -c unlimited && echo "|/usr/sbin/sendcoredump.sh" >/proc/sys/kernel/core_pattern 19 | fi 20 | 21 | cli -s .isp.sensorConfig /etc/sensors/imx307_i2c_2l_1080p.ini 22 | cli -s .video0.size 1920x1080 23 | cli -s .video0.fps 30 24 | 25 | start-stop-daemon -b -m -S -q -p "$PIDFILE" -x "/usr/bin/$DAEMON" -- $DAEMON_ARGS 26 | 27 | sleep .5 28 | 29 | cli -s .isp.sensorConfig /etc/sensors/imx307_i2c_2l_720p_50fps.ini 30 | cli -s .video0.size 1280x720 31 | cli -s .video0.fps 50 32 | 33 | killall -1 majestic 34 | 35 | sleep 1 36 | gkrcparams --MaxQp 30 --MaxI 2 37 | 38 | status=$? 39 | if [ "$status" -eq 0 ]; then 40 | echo "OK" 41 | else 42 | echo "FAIL" 43 | fi 44 | return "$status" 45 | } 46 | 47 | # The daemon does not create a pidfile, and use "-m" to instruct start-stop-daemon to create one. 48 | start() { 49 | logger -s -p daemon.info -t $(ipcinfo -v) "Loading video system has started..." 50 | export SENSOR=$(fw_printenv -n sensor) 51 | load_majestic 52 | } 53 | 54 | stop() { 55 | printf 'Stopping %s: ' "$DAEMON" 56 | [ -f /usr/bin/$DAEMON ] || echo -en "DISABLED, " 57 | start-stop-daemon -K -q -p "$PIDFILE" 58 | status=$? 59 | if [ "$status" -eq 0 ]; then 60 | rm -f "$PIDFILE" 61 | echo "OK" 62 | else 63 | echo "FAIL" 64 | fi 65 | return "$status" 66 | } 67 | 68 | restart() { 69 | stop 70 | sleep 1 71 | reload 72 | } 73 | 74 | reload() { 75 | load_majestic 76 | } 77 | 78 | case "$1" in 79 | start|stop|restart|reload) 80 | "$1";; 81 | *) 82 | echo "Usage: $0 {start|stop|restart|reload}" 83 | exit 1 84 | esac 85 | -------------------------------------------------------------------------------- /gk7205v200/etc/init.d/S98datalink: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Start fpv datalink 4 | # 5 | 6 | . /etc/datalink.conf 7 | 8 | chip=$(ipcinfo -c) 9 | fw=$(grep "BUILD_OPTION" "/etc/os-release" | cut -d= -f2) 10 | 11 | start() { 12 | if ! [ -f /etc/system.ok ]; then 13 | killall majestic 14 | tweaksys ${chip} 15 | fi 16 | 17 | echo "Starting FPV datalink..." 18 | if ! [ -f /etc/servicemode ]; then 19 | echo "Start wlan0 in Service Mode (connect to your AP)" 20 | rm -f /etc/servicemode 21 | wpa_passphrase "ssid" "password" >/tmp/wpa_supplicant.conf 22 | sed -i '2i \\tscan_ssid=1' /tmp/wpa_supplicant.conf 23 | sleep 3 24 | wpa_supplicant -B -D nl80211 -i wlan0 -c /tmp/wpa_supplicant.conf 25 | ifconfig wlan0 up 26 | udhcpc -x hostname:openipc-servicemode -T 1 -t 5 -R -b -O search -i wlan0 27 | else 28 | if [ ${fw} = "lte" ]; then 29 | if [ ${usb_modem} = "true" ]; then 30 | echo "Starting lte modem configuration..." 31 | echo "ToDo: Running usb_modeswitch or other shit here..." 32 | fi 33 | # for the future 34 | #cli -s .outgoing.url1 udp://${gs_ipaddr}:${gs_port} 35 | if [ ${use_zt} = "true" ]; then 36 | echo "Starting ZeroTier-One daemon..." 37 | /usr/sbin/zerotier-one -d & 38 | if [ ! -f /var/lib/zerotier-one/networks.d/${zt_netid}.conf ]; then 39 | sleep 8 40 | zerotier-cli join ${zt_netid} &> /dev/null 41 | echo "Don't forget authorize in the my.zerotier.com!" 42 | fi 43 | fi 44 | if [ ${telemetry} = "true" ]; then 45 | /usr/bin/telemetry start 46 | fi 47 | else 48 | echo "Starting wifibroadcast service..." 49 | /usr/bin/wifibroadcast start 50 | fi 51 | fi 52 | } 53 | 54 | stop() { 55 | echo "Stopping all services..." 56 | kill -9 $(pidof wfb_tx) 57 | kill -9 $(pidof telemetry_rx) 58 | kill -9 $(pidof telemetry_tx) 59 | kill -9 $(pidof mavlink-routerd) 60 | kill -9 $(pidof mavfwd) 61 | } 62 | 63 | case "$1" in 64 | start) 65 | start 66 | ;; 67 | stop) 68 | stop 69 | ;; 70 | restart) 71 | stop 72 | start 73 | ;; 74 | *) 75 | echo "Usage: $0 {start|stop|restart}" 76 | exit 1 77 | esac 78 | -------------------------------------------------------------------------------- /gk7205v200/etc/majestic.yaml: -------------------------------------------------------------------------------- 1 | system: 2 | webAdmin: disabled 3 | buffer: 1024 4 | image: 5 | mirror: false 6 | flip: false 7 | rotate: none 8 | contrast: 50 9 | hue: 50 10 | saturation: 50 11 | luminance: 50 12 | osd: 13 | enabled: false 14 | template: "%a %e %B %Y %H:%M:%S %Z" 15 | nightMode: 16 | enabled: false 17 | records: 18 | enabled: false 19 | path: /mnt/mmc/%Y/%m/%d/%H.mp4 20 | maxUsage: 95 21 | video0: 22 | enabled: true 23 | bitrate: 6144 24 | codec: h265 25 | rcMode: cbr 26 | gopSize: 1.0 27 | size: 1280x720 28 | fps: 50 29 | video1: 30 | enabled: false 31 | jpeg: 32 | enabled: false 33 | mjpeg: 34 | size: 640x360 35 | fps: 5 36 | bitrate: 1024 37 | audio: 38 | enabled: false 39 | volume: auto 40 | srate: 8000 41 | rtsp: 42 | enabled: false 43 | port: 554 44 | hls: 45 | enabled: false 46 | youtube: 47 | enabled: false 48 | motionDetect: 49 | enabled: false 50 | visualize: true 51 | debug: true 52 | ipeye: 53 | enabled: false 54 | watchdog: 55 | enabled: true 56 | timeout: 10 57 | isp: 58 | slowShutter: disabled 59 | drc: 350 60 | lowDelay: true 61 | sensorConfig: /etc/sensors/imx307_i2c_2l_720p_50fps.ini 62 | netip: 63 | enabled: false 64 | outgoing: 65 | - udp://127.0.0.1:5600 66 | -------------------------------------------------------------------------------- /gk7205v200/etc/sensors/imx307_i2c_2l_720p_50fps.ini: -------------------------------------------------------------------------------- 1 | [sensor] 2 | Sensor_type =stSnsImx307_2l_Obj ;sensor name 3 | Mode =0 ;WDR_MODE_NONE = 0 4 | ;WDR_MODE_BUILT_IN = 1 5 | ;WDR_MODE_QUDRA = 2 6 | ;WDR_MODE_2To1_LINE = 3 7 | ;WDR_MODE_2To1_FRAME = 4 8 | ;WDR_MODE_2To1_FRAME_FULL_RATE = 5 9 | ;WDR_MODE_3To1_LINE = 6 10 | ;WDR_MODE_3To1_FRAME = 7 11 | ;WDR_MODE_3To1_FRAME_FULL_RATE = 8 12 | ;WDR_MODE_4To1_LINE = 9 13 | ;WDR_MODE_4To1_FRAME = 10 14 | ;WDR_MODE_4To1_FRAME_FULL_RATE = 11 15 | DllFile = /usr/lib/sensors/libsns_imx307_2l_720p_50fps.so ;sensor lib path 16 | 17 | 18 | [mode] 19 | input_mode =0 ;INPUT_MODE_MIPI = 0 20 | ;INPUT_MODE_SUBLVDS = 1 21 | ;INPUT_MODE_LVDS = 2 ...etc 22 | 23 | raw_bitness = 10 24 | 25 | [mipi] 26 | ;----------only for mipi_dev--------- 27 | data_type = DATA_TYPE_RAW_10BIT 28 | lane_id = 0|2|-1|-1|-1|-1|-1|-1| ;lane_id: -1 - disable 29 | 30 | [isp_image] 31 | Isp_x =0 32 | Isp_y =0 33 | Isp_W =1280 34 | Isp_H =720 35 | Isp_FrameRate=60 36 | Isp_Bayer =0 ;BAYER_RGGB=0, BAYER_GRBG=1, BAYER_GBRG=2, BAYER_BGGR=3 37 | 38 | [vi_dev] 39 | Input_mod = 6 40 | ; VI_MODE_BT656 = 0, /* ITU-R BT.656 YUV4:2:2 */ 41 | ; VI_MODE_BT656_PACKED_YUV, /* ITU-R BT.656 packed YUV4:2:2 */ 42 | ; VI_MODE_BT601, /* ITU-R BT.601 YUV4:2:2 */ 43 | ; VI_MODE_DIGITAL_CAMERA, /* digatal camera mode */ 44 | ; VI_MODE_BT1120_STANDARD, /* BT.1120 progressive mode */ 45 | ; VI_MODE_BT1120_INTERLEAVED, /* BT.1120 interstage mode */ 46 | ; VI_MODE_MIPI, /* MIPI RAW mode */ 47 | ; VI_MODE_MIPI_YUV420_NORMAL, /* MIPI YUV420 normal mode */ 48 | ; VI_MODE_MIPI_YUV420_LEGACY, /* MIPI YUV420 legacy mode */ 49 | ; VI_MODE_MIPI_YUV422, /* MIPI YUV422 mode */ 50 | ; VI_MODE_LVDS, /* LVDS mode */ 51 | ; VI_MODE_HISPI, /* HiSPi mode */ 52 | ; VI_MODE_SLVS, /* SLVS mode */ 53 | Work_mod =0 ;VI_WORK_MODE_1Multiplex = 0 54 | ;VI_WORK_MODE_2Multiplex, 55 | ;VI_WORK_MODE_4Multiplex 56 | Combine_mode =0 ;Y/C composite or separation mode 57 | ;VI_COMBINE_COMPOSITE = 0 /*Composite mode */ 58 | ;VI_COMBINE_SEPARATE, /*Separate mode */ 59 | Comp_mode =0 ;Component mode (single-component or dual-component) 60 | ;VI_COMP_MODE_SINGLE = 0, /*single component mode */ 61 | ;VI_COMP_MODE_DOUBLE = 1, /*double component mode */ 62 | Clock_edge =1 ;Clock edge mode (sampling on the rising or falling edge) 63 | ;VI_CLK_EDGE_SINGLE_UP=0, /*rising edge */ 64 | ;VI_CLK_EDGE_SINGLE_DOWN, /*falling edge */ 65 | Mask_num =2 ;Component mask 66 | Mask_0 =0xFFF00000 67 | Mask_1 =0x0 68 | Scan_mode = 1;VI_SCAN_INTERLACED = 0 69 | ;VI_SCAN_PROGRESSIVE, 70 | Data_seq =2 ;data sequence (ONLY for YUV format) 71 | ;----2th component U/V sequence in bt1120 72 | ; VI_INPUT_DATA_VUVU = 0, 73 | ; VI_INPUT_DATA_UVUV, 74 | ;----input sequence for yuv 75 | ; VI_INPUT_DATA_UYVY = 0, 76 | ; VI_INPUT_DATA_VYUY, 77 | ; VI_INPUT_DATA_YUYV, 78 | ; VI_INPUT_DATA_YVYU 79 | 80 | Vsync =1 ; vertical synchronization signal 81 | ;VI_VSYNC_FIELD = 0, 82 | ;VI_VSYNC_PULSE, 83 | VsyncNeg=1 ;Polarity of the vertical synchronization signal 84 | ;VI_VSYNC_NEG_HIGH = 0, 85 | ;VI_VSYNC_NEG_LOW /*if VIU_VSYNC_E 86 | Hsync =0 ;Attribute of the horizontal synchronization signal 87 | ;VI_HSYNC_VALID_SINGNAL = 0, 88 | ;VI_HSYNC_PULSE, 89 | HsyncNeg =0 ;Polarity of the horizontal synchronization signal 90 | ;VI_HSYNC_NEG_HIGH = 0, 91 | ;VI_HSYNC_NEG_LOW 92 | VsyncValid =1 ;Attribute of the valid vertical synchronization signal 93 | ;VI_VSYNC_NORM_PULSE = 0, 94 | ;VI_VSYNC_VALID_SINGAL, 95 | VsyncValidNeg =0;Polarity of the valid vertical synchronization signal 96 | ;VI_VSYNC_VALID_NEG_HIGH = 0, 97 | ;VI_VSYNC_VALID_NEG_LOW 98 | Timingblank_HsyncHfb =0 ;Horizontal front blanking width 99 | Timingblank_HsyncAct =1280 ;Horizontal effetive width 100 | Timingblank_HsyncHbb =0 ;Horizontal back blanking width 101 | Timingblank_VsyncVfb =0 ;Vertical front blanking height 102 | Timingblank_VsyncVact =720 ;Vertical effetive width 103 | Timingblank_VsyncVbb=0 ;Vertical back blanking height 104 | Timingblank_VsyncVbfb =0 ;Even-field vertical front blanking height(interlace, invalid progressive) 105 | Timingblank_VsyncVbact=0 ;Even-field vertical effetive width(interlace, invalid progressive) 106 | Timingblank_VsyncVbbb =0 ;Even-field vertical back blanking height(interlace, invalid progressive) 107 | 108 | ;----- only for bt656 ---------- 109 | FixCode =0 ;BT656_FIXCODE_1 = 0, 110 | ;BT656_FIXCODE_0 111 | FieldPolar=0 ;BT656_FIELD_POLAR_STD = 0 112 | ;BT656_FIELD_POLAR_NSTD 113 | DataPath =1 ;ISP enable or bypass 114 | ;VI_PATH_BYPASS = 0,/* ISP bypass */ 115 | ;VI_PATH_ISP = 1,/* ISP enable */ 116 | ;VI_PATH_RAW = 2,/* Capture raw data, for debug */ 117 | InputDataType=1 ;VI_DATA_TYPE_YUV = 0,VI_DATA_TYPE_RGB = 1, 118 | DataRev =FALSE ;Data reverse. FALSE = 0; TRUE = 1 119 | DevRect_x=200 ; 120 | DevRect_y=20 ; 121 | DevRect_w=1280 ; 122 | DevRect_h=720 ; 123 | FullLinesStd=750 124 | 125 | [vi_chn] 126 | CapRect_X =320 127 | CapRect_Y =180 128 | CapRect_Width=1280 129 | CapRect_Height=720 130 | DestSize_Width=1280 131 | DestSize_Height=720 132 | -------------------------------------------------------------------------------- /gk7205v200/etc/wfb.conf: -------------------------------------------------------------------------------- 1 | wlan=wlan0 2 | region=BO 3 | # By default used channel number, but, you may set freq instead. For ex: 2387M 4 | channel=44 5 | #frequency=5220M 6 | txpower=20 7 | driver_txpower_override=16 8 | bandwidth=20 9 | stbc=1 10 | ldpc=1 11 | mcs_index=1 12 | stream=0 13 | link_id=7669206 14 | udp_port=5600 15 | fec_k=8 16 | fec_n=12 17 | fec_timeout=0 18 | guard_interval=long 19 | -------------------------------------------------------------------------------- /gk7205v200/root/1080.sh: -------------------------------------------------------------------------------- 1 | #yaml-cli -s .isp.sensorConfig /etc/sensors/imx307_i2c_2l_1080p.ini #use this for imx307 2 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415.bin 3 | yaml-cli -s .isp.exposure 10 4 | yaml-cli -s .video0.size 1920x1080 5 | yaml-cli -s .video0.fps 30 6 | yaml-cli -s .video0.crop 0x0x1920x1080 7 | sleep .2 8 | /root/kill.sh 9 | -------------------------------------------------------------------------------- /gk7205v200/root/1080b.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 1920x1080 2 | yaml-cli -s .video0.crop 0x0x1920x1080 3 | yaml-cli -s .video0.fps 60 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415f.bin 5 | yaml-cli -s .isp.exposure 20 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/1080c.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 1920x1080 2 | yaml-cli -s .video0.crop 0x0x1920x1080 3 | yaml-cli -s .video0.fps 90 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415f.bin 5 | yaml-cli -s .isp.exposure 30 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/3K.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 3200x1800 2 | yaml-cli -s .video0.crop 250x150x2560x1440 3 | yaml-cli -s .video0.fps 30 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415.bin 5 | yaml-cli -s .isp.exposure 10 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/4K.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 3840x2160 2 | yaml-cli -s .video0.crop 575x330x2560x1440 3 | yaml-cli -s .video0.fps 20 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415.bin 5 | yaml-cli -s .isp.exposure 10 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/720.sh: -------------------------------------------------------------------------------- 1 | #yaml-cli -s .isp.sensorConfig /etc/sensors/720p30_imx307_50.ini #use this for imx307 2 | #yaml-cli -s .video0.fps 50 #use thise for imx307 3 | yaml-cli -s .video0.size 1280x720 4 | yaml-cli -s .video0.fps 30 5 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415.bin 6 | yaml-cli -s .isp.exposure 10 7 | yaml-cli -s .video0.crop 0x0x1280x720 8 | sleep .2 9 | /root/kill.sh 10 | -------------------------------------------------------------------------------- /gk7205v200/root/720b.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 1280x720 2 | yaml-cli -s .video0.crop 0x0x1280x720 3 | yaml-cli -s .video0.fps 60 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415f.bin 5 | yaml-cli -s .isp.exposure 20 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/720c.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 1280x720 2 | yaml-cli -s .video0.crop 0x0x1280x720 3 | yaml-cli -s .video0.fps 90 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415f.bin 5 | yaml-cli -s .isp.exposure 30 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/720d.sh: -------------------------------------------------------------------------------- 1 | yaml-cli -s .video0.size 1280x720 2 | yaml-cli -s .video0.crop 0x0x1280x720 3 | yaml-cli -s .video0.fps 120 4 | yaml-cli -s .isp.sensorConfig /etc/sensors/imx415f.bin 5 | yaml-cli -s .isp.exposure 30 6 | sleep .2 7 | /root/kill.sh 8 | -------------------------------------------------------------------------------- /gk7205v200/root/channels.sh: -------------------------------------------------------------------------------- 1 | echo $1 $2 >>/tmp/channels.log 2 | 3 | #channel 5 4 | if [ $1 -eq 5 ]; then 5 | if [ $2 -gt 1600 ]; then 6 | CURRENT_SIZE=`yaml-cli -g .video0.size` 7 | if [ $CURRENT_SIZE == '1280x720' ]; then 8 | /root/1080.sh 9 | sleep 3 10 | else 11 | /root/720.sh 12 | sleep 3 13 | fi 14 | fi 15 | fi 16 | 17 | #channel 6 18 | #if [ $1 -eq 6 ]; then 19 | # if [ $2 -lt 1600 ]; then 20 | # /root/ircut.sh off 21 | # else 22 | # /root/ircut.sh on 23 | # fi 24 | #fi 25 | 26 | if [ $1 -eq 6 ]; then 27 | if [ $2 -gt 1600 ]; then 28 | CURRENT_SIZE=`yaml-cli -g .video0.size` 29 | CURRENT_FPS=`yaml-cli -g .video0.fps` 30 | if [ $CURRENT_SIZE == '1280x720' ] && [ $CURRENT_FPS == '30' ] ; then 31 | /root/720b.sh 32 | sleep 3 33 | elif [ $CURRENT_SIZE == '1280x720' ] && [ $CURRENT_FPS == '60' ] ; then 34 | /root/720c.sh 35 | sleep 3 36 | elif [ $CURRENT_SIZE == '1280x720' ] && [ $CURRENT_FPS == '90' ] ; then 37 | /root/720d.sh 38 | sleep 3 39 | elif [ $CURRENT_SIZE == '1280x720' ] && [ $CURRENT_FPS == '120' ] ; then 40 | /root/1080.sh 41 | sleep 3 42 | elif [ $CURRENT_SIZE == '1920x1080' ] && [ $CURRENT_FPS == '30' ] ; then 43 | /root/1080b.sh 44 | sleep 3 45 | elif [ $CURRENT_SIZE == '1920x1080' ] && [ $CURRENT_FPS == '60' ] ; then 46 | /root/1080c.sh 47 | sleep 3 48 | elif [ $CURRENT_SIZE == '1920x1080' ] && [ $CURRENT_FPS == '90' ] ; then 49 | /root/3K.sh 50 | sleep 3 51 | elif [ $CURRENT_SIZE == '3200x1800' ]; then 52 | /root/4K.sh 53 | sleep 3 54 | else 55 | /root/720.sh 56 | sleep 3 57 | fi 58 | fi 59 | fi 60 | 61 | #channel 7 62 | if [ $1 -eq 7 ]; then 63 | if [ $2 -lt 1400 ]; then 64 | yaml-cli -s .image.luminance 50 65 | killall -1 majestic 66 | elif [ $2 -gt 1400 ] && [ $2 -lt 1600 ]; then 67 | yaml-cli -s .image.luminance 90 68 | killall -1 majestic 69 | else 70 | yaml-cli -s .image.luminance 30 71 | killall -1 majestic 72 | fi 73 | fi 74 | 75 | #channel 8 76 | if [ $1 -eq 8 ]; then 77 | if [ $2 -gt 1600 ]; then 78 | CURRENT_BITRATE=`yaml-cli -g .video0.bitrate` 79 | if [ $CURRENT_BITRATE -lt 7168 ]; then 80 | NEW_BITRATE="$(($CURRENT_BITRATE+1024))" 81 | else 82 | NEW_BITRATE="1024" 83 | sleep 2 84 | fi 85 | yaml-cli -s .video0.bitrate $NEW_BITRATE 86 | sleep .2 87 | /root/kill.sh 88 | fi 89 | sleep 3 90 | fi 91 | 92 | exit 1 93 | -------------------------------------------------------------------------------- /gk7205v200/root/channels2.sh: -------------------------------------------------------------------------------- 1 | if [ $1 -eq 7 ]; then 2 | if [ $2 -gt 1600 ]; then 3 | /root/ircut.sh on 4 | elif [ $2 -gt 1400 ] && [ $2 -lt 1600 ]; then 5 | /root/ircut.sh off 6 | fi 7 | fi 8 | 9 | if [ $1 -eq 8 ]; then 10 | if [ $2 -gt 1600 ]; then 11 | killall venc 12 | venc -p 5600 -f 30 -r 12288 -c 265cbr -v 200_imx307F -d frame --low-delay & 13 | elif [ $2 -gt 1400 ] && [ $2 -lt 1600 ]; then 14 | killall venc 15 | venc -p 5600 -f 50 -r 12288 -c 265cbr -v 200_imx307B -d frame & 16 | fi 17 | fi 18 | 19 | exit 1 20 | -------------------------------------------------------------------------------- /gk7205v200/root/ircut.sh: -------------------------------------------------------------------------------- 1 | #use: ./ircut.sh on | off 2 | 3 | function gpio_setup { 4 | if [ ! -e /sys/class/gpio/gpio$1 ]; then 5 | echo $1 > /sys/class/gpio/export 6 | fi 7 | echo $2 > /sys/class/gpio/gpio$1/direction 8 | } 9 | 10 | function set_gpio { 11 | echo $2 > /sys/class/gpio/gpio$1/value 12 | } 13 | 14 | function ircut_on { 15 | set_gpio 8 0 16 | set_gpio 9 1 17 | sleep 0.1 18 | set_gpio 8 0 19 | } 20 | 21 | function ircut_off { 22 | set_gpio 8 1 23 | set_gpio 9 0 24 | sleep 0.1 25 | set_gpio 8 0 26 | } 27 | 28 | gpio_setup 8 out 29 | gpio_setup 9 out 30 | ircut_$1 31 | 32 | 33 | -------------------------------------------------------------------------------- /gk7205v200/root/kill.sh: -------------------------------------------------------------------------------- 1 | killall majestic 2 | sleep 1 3 | majestic 4 | sleep 5 5 | gkrcparams --MaxQp 30 --MaxI 2 6 | -------------------------------------------------------------------------------- /gk7205v200/u-boot-gk7205v200-universal.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7205v200/u-boot-gk7205v200-universal.bin -------------------------------------------------------------------------------- /gk7205v200/usr/bin/telemetry: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Start telemetry 4 | # 5 | 6 | . /etc/datalink.conf 7 | . /etc/telemetry.conf 8 | 9 | keydir="/etc" 10 | 11 | fw=$(grep "BUILD_OPTION" "/etc/os-release" | cut -d= -f2) 12 | 13 | start_telemetry() { 14 | if [ ! -f /usr/bin/telemetry_rx -a ! -f /usr/bin/telemetry_tx ]; then 15 | ln -s /usr/bin/wfb_rx /usr/bin/telemetry_rx ; chmod +x /usr/bin/telemetry_rx 16 | ln -s /usr/bin/wfb_tx /usr/bin/telemetry_tx ; chmod +x /usr/bin/telemetry_tx 17 | else 18 | if [ ${one_way} = "false" ]; then 19 | if [ -z "${link_id}" ]; then 20 | telemetry2_rx -r ${stream_rx} -u ${port_rx} -K ${keydir}/drone.key ${wlan} >/dev/null & 21 | else 22 | telemetry_rx -p ${stream_rx} -u ${port_rx} -K ${keydir}/drone.key -i ${link_id} ${wlan} >/dev/null & 23 | fi 24 | fi 25 | if [ -z "${link_id}" ]; then 26 | telemetry2_tx -r ${stream_tx} -u ${port_tx} -K ${keydir}/drone.key -B ${bandwidth} -M ${mcs_index} -S ${stbc} -L ${ldpc} -G ${guard_interval} -k ${fec_k} -p ${fec_p} ${wlan} >/dev/null & 27 | else 28 | telemetry_tx -p ${stream_tx} -u ${port_tx} -K ${keydir}/drone.key -B ${bandwidth} -M ${mcs_index} -S ${stbc} -L ${ldpc} -G ${guard_interval} -k ${fec_k} -n ${fec_n} -T ${fec_timeout} -i ${link_id} ${wlan} >/dev/null & 29 | fi 30 | fi 31 | } 32 | 33 | case "$1" in 34 | start) 35 | echo "Loading MAVLink telemetry service..." 36 | 37 | if [ ${router} -eq 1 ] || [ ${fw} = "lte" ]; then 38 | /usr/bin/mavlink-routerd & 39 | else 40 | mavfwd --master ${serial} --baudrate ${baud} --out 127.0.0.1:${port_tx} --in 127.0.0.1:${port_rx} & 41 | fi 42 | if [ ${fw} = "fpv" ]; then 43 | start_telemetry 44 | fi 45 | echo "Done." 46 | ;; 47 | stop) 48 | echo "Stopping telemetry services..." 49 | kill -9 $(pidof telemetry_rx) 50 | kill -9 $(pidof telemetry_tx) 51 | kill -9 $(pidof mavlink-routerd) 52 | kill -9 $(pidof mavfwd) 53 | ;; 54 | *) 55 | echo "Usage: $0 {start|stop}" 56 | exit 1 57 | esac 58 | -------------------------------------------------------------------------------- /gk7205v200/usr/bin/venc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7205v200/usr/bin/venc -------------------------------------------------------------------------------- /gk7205v200/usr/bin/wifibroadcast: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Start wifibroadcast 4 | # 5 | 6 | . /etc/datalink.conf 7 | . /etc/wfb.conf 8 | 9 | keydir="/etc" 10 | chip=$(ipcinfo -c) 11 | vendor=$(ipcinfo -v) 12 | 13 | driver="" 14 | 15 | set_mcs() { 16 | if [ ${vendor} = "ingenic" ]; then 17 | mcs=$(ls -l /lib/firmware | grep "htc_9271" | awk {'print $11'} | cut -d "." -f3) 18 | else 19 | mcs=$(ls -l /lib/firmware/ath9k_htc | grep "htc_9271-1.4.0.fw" | cut -d "." -f6) 20 | fi 21 | if [ -z "${mcs}" ]; then 22 | setmcs ${mcs_index} 23 | fi 24 | if [ ${mcs_index} -eq 1 ] || [ ${mcs_index} -eq 3 ]; then 25 | if [ ! ${mcs_index} -eq ${mcs} ]; then 26 | setmcs ${mcs_index} 27 | sleep 3 28 | fi 29 | fi 30 | } 31 | 32 | # "0bda:8813" -> (8814) -> 8814au 33 | # "0846:9052" -> (8811) -> 8821au 34 | 35 | detect_wifi_card() { 36 | echo "Detecting wifi card vendor..." 37 | devices=$(lsusb | cut -d ' ' -f6 | sort | uniq) 38 | for card in ${devices} 39 | do 40 | case "${card}" in 41 | "0bda:8812" | "0bda:881a" | "0b05:17d2" | "2357:0101") 42 | driver="realtek" 43 | modprobe 88XXau rtw_tx_pwr_idx_override=${driver_txpower_override} 44 | ;; 45 | "0cf3:9271" | "040d:3801") 46 | driver="atheros" 47 | set_mcs 48 | modprobe mac80211 49 | modprobe ath9k_htc 50 | ;; 51 | esac 52 | done 53 | 54 | if [ -z "${driver}" ]; then 55 | echo "No usb wifi card detected. Check wifi stick connection, usb power or possible bad soldering." 56 | exit 57 | else 58 | echo "Detected:" ${driver} 59 | fi 60 | 61 | echo "Awaiting interface ${wlan} in system..." 62 | 63 | local n=0 64 | while ! $(ifconfig -a | grep -q ${wlan}) 65 | do 66 | if [ ${n} -ge 5 ]; then 67 | echo "No interface ${wlan}. Check wifi stick connection, usb power or possible bad soldering." 68 | exit 69 | fi 70 | sleep 0.5 71 | n=$(expr ${n} + 1) 72 | done 73 | } 74 | 75 | load_modules() { 76 | modprobe cfg80211 77 | detect_wifi_card 78 | } 79 | 80 | load_interface() { 81 | if [ ${driver} = "realtek" ]; then 82 | ifconfig ${wlan} up 83 | iwconfig ${wlan} mode monitor 84 | elif [ ${driver} = "atheros" ]; then 85 | iwconfig ${wlan} mode monitor 86 | ifconfig ${wlan} up 87 | fi 88 | 89 | iw reg set ${region} 90 | 91 | if [ ! -z "${frequency}" ]; then 92 | iwconfig ${wlan} freq ${frequency} 93 | else 94 | iwconfig ${wlan} channel ${channel} 95 | fi 96 | # dirty fix crash if txpower set. setting txpower disabled because patched driver always set txpower level 58 97 | # iw dev ${wlan} set txpower fixed $((${txpower} * 100)) 98 | } 99 | 100 | start_wfb() { 101 | if [ -z "${link_id}" ]; then 102 | wfb2_tx -r ${stream} -u ${udp_port} -K ${keydir}/drone.key -B ${bandwidth} -M ${mcs_index} -S ${stbc} -L ${ldpc} -G ${guard_interval} -k ${fec_k} -p ${fec_p} ${wlan} >/dev/null & 103 | else 104 | wfb_tx -p ${stream} -u ${udp_port} -K ${keydir}/drone.key -B ${bandwidth} -M ${mcs_index} -S ${stbc} -L ${ldpc} -G ${guard_interval} -k ${fec_k} -n ${fec_n} -T ${fec_timeout} -i ${link_id} ${wlan} & 105 | fi 106 | } 107 | 108 | case "$1" in 109 | start) 110 | if [ ${daemon} -eq 1 ]; then 111 | 112 | echo "Loading modules and wifi card driver..." 113 | 114 | load_modules 115 | 116 | echo "Preparing interface wlan..." 117 | 118 | load_interface 119 | 120 | if ! cat ${keydir}/drone.key > /dev/null 2>&1; then 121 | echo "Generating drone & ground station keys..." 122 | cd ${keydir} ; wfb_keygen 123 | else 124 | echo "Drone key exist..." 125 | fi 126 | 127 | echo "Starting Wifibroadcast service..." 128 | 129 | start_wfb 130 | 131 | echo "Done." 132 | 133 | if [ ${telemetry} = "true" ]; then 134 | if [ ${chip} = "gk7205v200" ]; then 135 | # UART2_RX mux 136 | devmem 0x120c0010 32 0x1e04 137 | fi 138 | /usr/bin/telemetry start 139 | fi 140 | 141 | else 142 | echo "Wifibroadcast service disabled in wfb.conf..." 143 | fi 144 | ;; 145 | stop) 146 | echo "Stopping all services..." 147 | kill -9 $(pidof wfb_tx) 148 | kill -9 $(pidof telemetry_rx) 149 | kill -9 $(pidof telemetry_tx) 150 | kill -9 $(pidof mavlink-routerd) 151 | kill -9 $(pidof mavfwd) 152 | ;; 153 | *) 154 | echo "Usage: $0 {start|stop}" 155 | exit 1 156 | esac 157 | -------------------------------------------------------------------------------- /gk7205v200/usr/lib/sensors/libsns_imx307_2l_720p_50fps.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7205v200/usr/lib/sensors/libsns_imx307_2l_720p_50fps.so -------------------------------------------------------------------------------- /gk7205v200/usr/sbin/gkrcparams: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7205v200/usr/sbin/gkrcparams -------------------------------------------------------------------------------- /gk7205v200_u-boot-7502v200-for-telemetry.md: -------------------------------------------------------------------------------- 1 | ## U-Boot для телеметрии 2 | #### только для gk7502v200! 3 | 4 | загрузчик внесён разработчиками в релизы, и если вы прошиваетесь с инструкций на openipc.net, то этого уже делать не надо, только установить bootdelay 0. 5 | 6 | Чтобы поток телеметрии не прерывал загрузку камеры, когда u-boot считает телеметрию "нажатием любой кнопки для входа в консоль загрузчика", нужно залить этот загрузчик 7 | [(ССЫЛКА)](https://github.com/OpenIPC/sandbox-fpv/raw/master/gk7205v200/u-boot-gk7205v200-universal.bin): 8 | ``` 9 | # закачайте файл u-boot-gk7205v200-universal.bin в /tmp камеры через winscp ИЛИ выполните команду и УБЕДИТЕСЬ ЧТО ФАЙЛ СКАЧАЛСЯ!!!#curl -o /tmp/u-boot-gk7205v200-universal.bin http://fpv.openipc.net/u-boot-gk7205v200-universal.bin 10 | 11 | flashcp -v /tmp/u-boot-gk7205v200-universal.bin /dev/mtd0 12 | ``` 13 | и установите нулевую задержку загрузки командой `fw_setenv bootdelay 0`. 14 | 15 | При первой прошивке просто используйте этот файл вместо указанного на странице инструкций. Только для gk7502v200! 16 | 17 | Данный загрузчик прерывается по комбинации клавиш Ctrl+C, а не любой. Будьте осторожны! Завалите загрузчик - придется паять и шить программатором. 18 | -------------------------------------------------------------------------------- /gk7502v300/etc/majestic.yaml: -------------------------------------------------------------------------------- 1 | system: 2 | webAdmin: disabled 3 | buffer: 1024 4 | image: 5 | mirror: false 6 | flip: false 7 | rotate: none 8 | contrast: 50 9 | hue: 50 10 | saturation: 50 11 | luminance: 50 12 | osd: 13 | enabled: false 14 | template: "%a %e %B %Y %H:%M:%S %Z" 15 | nightMode: 16 | enabled: false 17 | records: 18 | enabled: false 19 | path: /mnt/mmcblk0p1/%Y-%m-%d-%H.mp4 20 | maxUsage: 95 21 | video0: 22 | enabled: true 23 | bitrate: 5192 24 | codec: h265 25 | rcMode: cbr 26 | gopSize: 0.2 27 | size: 1920x1080 28 | fps: 30 29 | #crop: 320x180x1280x720 30 | video1: 31 | enabled: false 32 | jpeg: 33 | enabled: false 34 | mjpeg: 35 | size: 640x360 36 | fps: 5 37 | bitrate: 1024 38 | audio: 39 | enabled: false 40 | volume: auto 41 | srate: 8000 42 | rtsp: 43 | enabled: false 44 | port: 554 45 | hls: 46 | enabled: false 47 | youtube: 48 | enabled: false 49 | motionDetect: 50 | enabled: false 51 | visualize: true 52 | debug: true 53 | ipeye: 54 | enabled: false 55 | watchdog: 56 | enabled: false 57 | timeout: 10 58 | isp: 59 | sensorConfig: /etc/sensors/smtsec_imx307_i2c_4l_1080p.ini 60 | slowShutter: disabled 61 | drc: 420 62 | lowDelay: true 63 | #rawMode: none 64 | blkCnt: 12 65 | #dis: true 66 | netip: 67 | enabled: false 68 | outgoing: 69 | - udp://127.0.0.1:5600 70 | -------------------------------------------------------------------------------- /gk7502v300/etc/telemetry.conf: -------------------------------------------------------------------------------- 1 | serial=/dev/ttyAMA0 2 | baud=115200 3 | ### router: use simple mavfwd (0) or classic mavlink-routerd (1) 4 | router=0 5 | 6 | wlan=wlan0 7 | bandwidth=20 8 | stbc=1 9 | ldpc=1 10 | mcs_index=1 11 | stream_rx=144 12 | stream_tx=16 13 | link_id=7669206 14 | port_rx=14551 15 | port_tx=14550 16 | fec_k=1 17 | fec_n=2 18 | fec_timeout=0 19 | guard_interval=long 20 | one_way=false 21 | -------------------------------------------------------------------------------- /gk7502v300/etc/wfb.conf: -------------------------------------------------------------------------------- 1 | wlan=wlan0 2 | region=BO 3 | # By default used channel number, but, you may set freq instead. For ex: 2387M 4 | channel=44 5 | frequency= 6 | txpower=20 7 | driver_txpower_override=20 8 | bandwidth=20 9 | stbc=1 10 | ldpc=1 11 | mcs_index=1 12 | stream=0 13 | link_id=7669206 14 | udp_port=5600 15 | fec_k=8 16 | fec_n=12 17 | fec_timeout=0 18 | guard_interval=long 19 | -------------------------------------------------------------------------------- /gk7502v300/root/ircut.sh: -------------------------------------------------------------------------------- 1 | #use: ./ircut.sh on | off 2 | 3 | function gpio_setup { 4 | if [ ! -e /sys/class/gpio/gpio$1 ]; then 5 | echo $1 > /sys/class/gpio/export 6 | fi 7 | echo $2 > /sys/class/gpio/gpio$1/direction 8 | } 9 | 10 | function set_gpio { 11 | echo $2 > /sys/class/gpio/gpio$1/value 12 | } 13 | 14 | function ircut_on { 15 | set_gpio 11 0 16 | set_gpio 10 1 17 | sleep 0.1 18 | set_gpio 11 0 19 | } 20 | 21 | function ircut_off { 22 | set_gpio 11 1 23 | set_gpio 10 0 24 | sleep 0.1 25 | set_gpio 11 0 26 | } 27 | 28 | gpio_setup 11 out 29 | gpio_setup 10 out 30 | ircut_$1 31 | 32 | 33 | -------------------------------------------------------------------------------- /gk7502v300/usr/lib/sensors/libsns_imx307.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/gk7502v300/usr/lib/sensors/libsns_imx307.so -------------------------------------------------------------------------------- /gkrcparams.md: -------------------------------------------------------------------------------- 1 | ## Добавляем плавности видео 2 | На режимах 1080p@30fps заметно легкое подергивание видео, а при замедленной съемке таймера видно что картинка замирает на какое то время и далее обновляется. Это происходит из за неравномерности потока, который резко возрастает на ключевых кадрах. 3 | Исправить это можно, перенастроив на камере два параметра энкодера. 4 | Спасибо за проделанную работу TipoMan и widgetii! 5 | 6 | Нам нужно положить файл [gkrcparams](https://github.com/OpenIPC/sandbox-fpv/raw/master/user_TipoMan/gkrcparams) в /usr/sbin, дать права на выполнение `chmod +x /usr/sbin/gkrcparams` и вставить запуск его после старта majestic в /etc/init.d/S95majestic: 7 | 8 | ``` 9 | start-stop-daemon -b -m -S -q -p "$PIDFILE" -x "/usr/bin/$DAEMON" -- $DAEMON_ARGS 10 | sleep 1 <=== ЭТО ВСТАВИТЬ 11 | gkrcparams --MaxQp 30 --MaxI 2 <=== ЭТО ВСТАВИТЬ 12 | status=$? 13 | ``` 14 | После перезапуска картинка должна стать плавной. Прочие настройки в majestic.yaml для режима mcs1: 15 | 16 | ``` 17 | video0: 18 | enabled: true 19 | bitrate: 7168 20 | codec: h265 21 | rcMode: cbr 22 | gopSize: 1.0 23 | size: 1920x1080 24 | ``` 25 | 26 | Если же картинка все равно иногда подергивается, придется изменить mcs на 3 в `/etc/wfb.conf` потеряв в дальности либо уменьшать битрейт. 27 | -------------------------------------------------------------------------------- /gstlaunch_on_windows.md: -------------------------------------------------------------------------------- 1 | ## Прием и отображение видео на windows 2 | 3 | В "классическом режиме" (на камере стримит majestic, а NVR пересылает видеопоток на ПК, не забываем указать IP адрес ПК в wfb.conf регистратора) видео можно принимать в QGroundControl, Mission Planner и можно просто вывести в отдельном окне 4 | без привязки к программам. Для этого нужно установить [GStreamer](https://gstreamer.freedesktop.org/download/) и запускать его на прием с некими параметрами, например: 5 | ``` 6 | C:\gstreamer\1.0\msvc_x86_64\bin\gst-launch-1.0.exe -v udpsrc port=5600 buffer-size=32768 ! application/x-rtp ! rtph265depay ! queue max-size-buffers=5 ! avdec_h265 ! videoconvert ! videoscale ! video/x-raw,width=1280,height=720,format=BGRA ! autovideosink sync=false 7 | ``` 8 | 9 | В данном примере размер видео изменяется до 1280x720. Для запуска видео с разрешением оригинального потока убираем из строки `videoscale ! ` и `width=1280,height=720,`. 10 | 11 | 12 | ![preview](https://github.com/OpenIPC/sandbox-fpv/raw/master/notes_files/Screenshot_2.png) 13 | 14 | Для воспроизведения видео в окне Mission Planner нужно кликнуть правой кнопкой мыши по его окну с горизонтом и выбрать `Video > Set GStreamer source`, внести строку параметров: `udpsrc port=5600 buffer-size=32768 ! application/x-rtp ! rtph265depay ! queue max-size-buffers=5 ! avdec_h265 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink`, нажать Ok. Строка сохранится для будущий применений. 15 | -------------------------------------------------------------------------------- /hi3536dv100/88XXau-ko/88XXau.ko_8812au: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/88XXau-ko/88XXau.ko_8812au -------------------------------------------------------------------------------- /hi3536dv100/88XXau-ko/88XXau.ko_8812au_8814au: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/88XXau-ko/88XXau.ko_8812au_8814au -------------------------------------------------------------------------------- /hi3536dv100/etc/init.d/S96gpio_monitor: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Start gpio monitor 4 | # 5 | 6 | case "$1" in 7 | start) 8 | echo "Starting gpio_monitor daemon..." 9 | /root/gpio_monitor.sh & 10 | ;; 11 | stop) 12 | echo "Stopping gpio_monitor daemon..." 13 | kill -9 $(pidof {exe} ash /root/gpio_monitor.sh) 14 | ;; 15 | *) 16 | echo "Usage: $0 {start|stop}" 17 | exit 1 18 | esac 19 | -------------------------------------------------------------------------------- /hi3536dv100/etc/init.d/S99rcjoystick: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | start() { 4 | /usr/bin/rcjoystick -t 25 -c 16 -i wlan0 & 5 | } 6 | 7 | stop() { 8 | killall rcjoystick 9 | } 10 | 11 | restart() { 12 | stop 13 | sleep 1 14 | start 15 | } 16 | 17 | case "$1" in 18 | start|stop|restart) 19 | "$1";; 20 | *) 21 | echo "Usage: $0 {start|stop|restart}" 22 | exit 1 23 | esac 24 | -------------------------------------------------------------------------------- /hi3536dv100/etc/mavlink.conf: -------------------------------------------------------------------------------- 1 | [General] 2 | TcpServerPort = 0 3 | DebugLogLevel = error 4 | 5 | [UdpEndpoint qgroundcontrol] 6 | Mode = Server 7 | Address = 0.0.0.0 8 | Port = 14550 9 | 10 | [UdpEndpoint telemetry_tx] 11 | Group=wfb 12 | Mode = Normal 13 | Address = 127.0.0.1 14 | Port = 14650 15 | 16 | [UdpEndpoint telemetry_rx] 17 | Group=wfb 18 | Mode = Server 19 | Address = 127.0.0.1 20 | Port = 14651 21 | 22 | -------------------------------------------------------------------------------- /hi3536dv100/etc/telemetry.conf: -------------------------------------------------------------------------------- 1 | serial=/dev/ttyAMA0 2 | baud=115200 3 | ### router: use simple mavfwd (0) or classic mavlink-routerd (1) 4 | router=1 5 | 6 | wlan=wlan0 7 | bandwidth=20 8 | stbc=1 9 | ldpc=1 10 | mcs_index=1 11 | stream_rx=16 12 | stream_tx=144 13 | link_id=7669206 14 | port_rx=14651 15 | port_tx=14650 16 | fec_k=1 17 | fec_n=2 18 | fec_timeout=0 19 | guard_interval=long 20 | one_way=false 21 | -------------------------------------------------------------------------------- /hi3536dv100/hi3536dv100_fpv_defconfig: -------------------------------------------------------------------------------- 1 | # Architecture 2 | BR2_arm=y 3 | BR2_cortex_a7=y 4 | BR2_ARM_EABI=y 5 | BR2_ARM_FPU_NEON_VFPV4=y 6 | BR2_ARM_INSTRUCTIONS_THUMB2=y 7 | BR2_KERNEL_HEADERS_VERSION=y 8 | BR2_DEFAULT_KERNEL_VERSION="4.9.37" 9 | BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_9=y 10 | 11 | # Toolchain 12 | BR2_PER_PACKAGE_DIRECTORIES=y 13 | BR2_GCC_VERSION_8_X=y 14 | # BR2_TOOLCHAIN_USES_UCLIBC is not set 15 | # BR2_TOOLCHAIN_BUILDROOT_UCLIBC is not set 16 | # BR2_TOOLCHAIN_BUILDROOT_LIBC="uclibc" 17 | # BR2_TOOLCHAIN_USES_MUSL is not set 18 | # BR2_TOOLCHAIN_BUILDROOT_MUSL is not set 19 | # BR2_TOOLCHAIN_BUILDROOT_LIBC="musl" 20 | BR2_TOOLCHAIN_USES_GLIBC=y 21 | BR2_TOOLCHAIN_BUILDROOT_GLIBC=y 22 | BR2_TOOLCHAIN_BUILDROOT_LIBC="glibc" 23 | BR2_PACKAGE_GLIBC_UTILS=y 24 | BR2_TOOLCHAIN_BUILDROOT_CXX=y 25 | # BR2_TOOLCHAIN_BUILDROOT_LOCALE is not set 26 | BR2_TOOLCHAIN_BUILDROOT_USE_SSP=y 27 | BR2_PIC_PIE=y 28 | BR2_GCC_ENABLE_LTO=y 29 | BR2_INSTALL_LIBSTDCPP=y 30 | 31 | # Kernel 32 | BR2_LINUX_KERNEL=y 33 | BR2_LINUX_KERNEL_CUSTOM_VERSION=y 34 | BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.9.37" 35 | BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y 36 | BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_HISILICON_PATH)/board/hi3536dv100/kernel/hi3536dv100.generic.config" 37 | BR2_LINUX_KERNEL_UIMAGE=y 38 | BR2_LINUX_KERNEL_UIMAGE_LOADADDR="0x80008000" 39 | BR2_LINUX_KERNEL_XZ=y 40 | BR2_LINUX_KERNEL_EXT_HISI_PATCHER=y 41 | BR2_LINUX_KERNEL_EXT_HISI_PATCHER_LIST="$(BR2_EXTERNAL_HISILICON_PATH)/board/hi3536dv100/kernel/patches/ $(BR2_EXTERNAL_HISILICON_PATH)/board/hi3536dv100/kernel/overlay" 42 | 43 | # Filesystem 44 | # BR2_TARGET_TZ_INFO is not set 45 | # BR2_TARGET_ROOTFS_CPIO is not set 46 | BR2_TARGET_ROOTFS_SQUASHFS=y 47 | BR2_TARGET_ROOTFS_SQUASHFS4_XZ=y 48 | BR2_ROOTFS_OVERLAY="$(TOPDIR)/../general/overlay" 49 | BR2_ROOTFS_POST_BUILD_SCRIPT="$(TOPDIR)/../scripts/executing_commands_for_$(BR2_TOOLCHAIN_BUILDROOT_LIBC).sh" 50 | 51 | # OpenIPC configuration 52 | BR2_TOOLCHAIN_BUILDROOT_VENDOR="openipc" 53 | BR2_TARGET_GENERIC_ISSUE="Welcome to OpenIPC" 54 | BR2_TARGET_GENERIC_HOSTNAME="openipc-hi3536dv100" 55 | BR2_GLOBAL_PATCH_DIR="$(TOPDIR)/../general/package/all-patches" 56 | 57 | # OpenIPC packages 58 | BR2_PACKAGE_HISILICON_OSDRV_HI3536DV100=y 59 | BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config" 60 | BR2_PACKAGE_DROPBEAR_OPENIPC=y 61 | # BR2_PACKAGE_FDK_AAC_OPENIPC is not set 62 | BR2_PACKAGE_FWPRINTENV_OPENIPC=y 63 | # BR2_PACKAGE_HASERL is not set 64 | # BR2_PACKAGE_HISI_GPIO is not set 65 | BR2_PACKAGE_IPCTOOL=y 66 | # BR2_PACKAGE_JSON_C is not set 67 | # BR2_PACKAGE_JSONFILTER is not set 68 | # BR2_PACKAGE_LAME_OPENIPC is not set 69 | BR2_PACKAGE_LIBCURL_OPENIPC=y 70 | BR2_PACKAGE_LIBCURL_OPENIPC_CURL=y 71 | # BR2_PACKAGE_LIBCURL_OPENIPC_VERBOSE is not set 72 | # BR2_PACKAGE_LIBCURL_OPENIPC_PROXY_SUPPORT is not set 73 | # BR2_PACKAGE_LIBCURL_OPENIPC_COOKIES_SUPPORT is not set 74 | # BR2_PACKAGE_LIBCURL_OPENIPC_EXTRA_PROTOCOLS_FEATURES is not set 75 | BR2_PACKAGE_LIBCURL_OPENIPC_MBEDTLS=y 76 | # BR2_PACKAGE_LIBEVENT_OPENIPC is not set 77 | # BR2_PACKAGE_LIBEVENT_OPENIPC_REMOVE_PYSCRIPT is not set 78 | # BR2_PACKAGE_LIBOGG_OPENIPC is not set 79 | # BR2_PACKAGE_LIBWEBSOCKETS_OPENIPC is not set 80 | # BR2_PACKAGE_LIBYAML is not set 81 | # BR2_PACKAGE_MAJESTIC_FONTS is not set 82 | BR2_PACKAGE_MBEDTLS_OPENIPC=y 83 | # BR2_PACKAGE_MBEDTLS_OPENIPC_PROGRAMS is not set 84 | # BR2_PACKAGE_MBEDTLS_OPENIPC_COMPRESSION is not set 85 | # BR2_PACKAGE_MICROBE_WEB is not set 86 | # BR2_PACKAGE_MINI_SNMPD is not set 87 | # BR2_PACKAGE_OPUS_OPENIPC is not set 88 | # BR2_PACKAGE_OPUS_OPENIPC_FIXED_POINT is not set 89 | # BR2_PACKAGE_SSHPASS is not set 90 | # BR2_PACKAGE_UACME_OPENIPC is not set 91 | BR2_PACKAGE_VTUND_OPENIPC=y 92 | # BR2_PACKAGE_YAML_CLI is not set 93 | # BR2_PACKAGE_XMDP is not set 94 | 95 | # WiFi 96 | BR2_PACKAGE_WIRELESS_TOOLS=y 97 | BR2_PACKAGE_WPA_SUPPLICANT=y 98 | # BR2_PACKAGE_WPA_SUPPLICANT_CLI is not set 99 | BR2_PACKAGE_WPA_SUPPLICANT_NL80211=y 100 | BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y 101 | BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC=y 102 | # BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC_MT7601U is not set 103 | # BR2_PACKAGE_RTL8188EU is not set 104 | BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC_ATHEROS_9271=y 105 | BR2_PACKAGE_RTL8812AU_OPENIPC=y 106 | 107 | # FPV 108 | BR2_PACKAGE_DATALINK=y 109 | BR2_PACKAGE_WIFIBROADCAST=y 110 | # BR2_PACKAGE_WFBOPENHD is not set 111 | BR2_PACKAGE_MAVLINK_ROUTER=y 112 | # BR2_PACKAGE_MAVFWD is not set 113 | 114 | #FFMPEG 115 | BR2_PACKAGE_FFMPEG_OPENIPC=y 116 | 117 | 118 | # ZEROTIER 119 | BR2_PACKAGE_ZEROTIER_ONE=y 120 | 121 | # IPTABLES 122 | # BR2_PACKAGE_IPTABLES is not set 123 | 124 | # WIREGUARD 125 | # BR2_PACKAGE_WIREGUARD_LINUX_COMPAT is not set 126 | # BR2_PACKAGE_WIREGUARD_TOOLS is not set 127 | 128 | # DEBUG 129 | BR2_PACKAGE_HOST_GDB=y 130 | BR2_PACKAGE_GDB=y 131 | 132 | BR2_PACKAGE_ZLIB=y 133 | 134 | # SDL2 135 | # BR2_PACKAGE_SDL2 is not set 136 | # BR2_PACKAGE_SDL2_IMAGE is not set 137 | # BR2_PACKAGE_SDL2_TTF is not set 138 | 139 | -------------------------------------------------------------------------------- /hi3536dv100/lib/modules/4.9.37/extra/8188eu.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/lib/modules/4.9.37/extra/8188eu.ko -------------------------------------------------------------------------------- /hi3536dv100/lib/modules/4.9.37/extra/88XXau.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/lib/modules/4.9.37/extra/88XXau.ko -------------------------------------------------------------------------------- /hi3536dv100/original_firmware/env.txt: -------------------------------------------------------------------------------- 1 | === original ENV 2 | hisilicon # printenv 3 | bootcmd=sf probe 0;sf read 0x84000000 0xf60000 0x20000;logoload 0x84000000;decjpg;sf read 0x82000000 0x50000 0x500000;squashfsload 82000000;bootm 0x81000000 4 | bootdelay=0 5 | baudrate=115200 6 | ethaddr=00:0b:3f:00:00:01 7 | ipaddr=192.168.1.10 8 | serverip=192.168.1.1 9 | netmask=255.255.0.0 10 | bootfile="uImage" 11 | da=mw.b 0x82000000 ff 1000000;tftp 0x82000000 u-boot.bin.img;sf probe 0;flwrite 12 | du=mw.b 0x82000000 ff 1000000;tftp 0x82000000 user-x.cramfs.img;sf probe 0;flwrite 13 | dr=mw.b 0x82000000 ff 1000000;tftp 0x82000000 romfs-x.cramfs.img;sf probe 0;flwrite 14 | dw=mw.b 0x82000000 ff 1000000;tftp 0x82000000 web-x.cramfs.img;sf probe 0;flwrite 15 | dl=mw.b 0x82000000 ff 1000000;tftp 0x82000000 logo-x.cramfs.img;sf probe 0;flwrite 16 | dc=mw.b 0x82000000 ff 1000000;tftp 0x82000000 custom-x.cramfs.img;sf probe 0;flwrite 17 | up=mw.b 0x82000000 ff 1000000;tftp 0x82000000 update.img;sf probe 0;flwrite 18 | tk=mw.b 0x82000000 ff 1000000;tftp 0x82000000 zImage.img; bootm 0x82000000 19 | dd=mw.b 0x82000000 ff 1000000;tftp 0x82000000 mtd-x.jffs2.img;sf probe 0;flwrite 20 | de=mw.b 0x82000000 ff 1000000;tftp 0x82000000 u-boot.env.bin.img;sf probe 0;flwrite 21 | jpeg_addr=0x8dc00000 22 | jpeg_size=0xb85f9 23 | vobuf=0x8dd00000 24 | loadlogo=sf probe 0;sf read 0x84000000 0xF60000 0x20000;logoload 0x84000000;decjpg 25 | bootargs=mem=139M console=ttyAMA0,115200 root=/dev/mtdblock1 rootfstype=squashfs mtdparts=hi_sfc:320K(boot),3968K(romfs),7040K(usr),1600K(web),2816K(custom),128K(logo),512K(mtd) coherent_pool=2M 26 | appVideoStandard=PAL 27 | appSystemLanguage=English 28 | appCloudExAbility=E7nsOhUNSfs= 29 | stdin=serial 30 | stdout=serial 31 | stderr=serial 32 | verify=n 33 | ver=U-Boot 2010.06-svn1560 (May 06 2021 - 19:15:51) 34 | 35 | Environment size: 1617/65532 bytes 36 | -------------------------------------------------------------------------------- /hi3536dv100/original_firmware/fullflash_202303012255_W25Q128BV_16MB_HI3536DV100_orig_dev2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/original_firmware/fullflash_202303012255_W25Q128BV_16MB_HI3536DV100_orig_dev2.bin -------------------------------------------------------------------------------- /hi3536dv100/root/gpio_monitor.sh: -------------------------------------------------------------------------------- 1 | ##IR 2 | ##Y2 !17 3 | ##Y1 !6 4 | ##X2 !13 5 | ##Y3 !8 6 | ##X1 !7 7 | ##ALARM 10 8 | ##REC 11 9 | 10 | function gpio_setup { 11 | if [ ! -e /sys/class/gpio/gpio$1 ]; then 12 | echo $1 > /sys/class/gpio/export 13 | fi 14 | echo $2 > /sys/class/gpio/gpio$1/direction 15 | } 16 | 17 | function set_gpio { 18 | echo $2 > /sys/class/gpio/gpio$1/value 19 | } 20 | 21 | 22 | function get_gpio { 23 | return `cat /sys/class/gpio/gpio${1}/value` 24 | } 25 | 26 | #buttons 27 | for i in 6 7 8 13 17 28 | do 29 | gpio_setup $i in 30 | done 31 | 32 | #ALARM led 33 | gpio_setup 10 out 34 | 35 | while [ true ] 36 | do 37 | get_gpio 6 38 | if [ "$?" -eq 0 ]; then 39 | set_gpio 10 1 40 | echo 6 >>/tmp/gpio.log 41 | #ifdown usb0 42 | #ifup usb0 43 | /usr/bin/wifibroadcast restart 44 | sleep .1 45 | set_gpio 10 0 46 | fi 47 | 48 | get_gpio 7 49 | if [ "$?" -eq 0 ]; then 50 | set_gpio 10 1 51 | echo 7 >>/tmp/gpio.log 52 | ifconfig eth0:1 192.168.11.1 53 | sleep .5 54 | set_gpio 10 0 55 | fi 56 | 57 | get_gpio 8 58 | if [ "$?" -eq 0 ]; then 59 | set_gpio 10 1 60 | echo 8 >>/tmp/gpio.log 61 | sleep .5 62 | set_gpio 10 0 63 | fi 64 | 65 | get_gpio 13 66 | if [ "$?" -eq 0 ]; then 67 | set_gpio 10 1 68 | echo 13 >>/tmp/gpio.log 69 | sleep .5 70 | set_gpio 10 0 71 | fi 72 | 73 | get_gpio 17 74 | if [ "$?" -eq 0 ]; then 75 | set_gpio 10 1 76 | echo 17 >>/tmp/gpio.log 77 | sleep .5 78 | set_gpio 10 0 79 | fi 80 | 81 | sleep .2 82 | done -------------------------------------------------------------------------------- /hi3536dv100/root/resolution.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ARG="`cat /etc/vdec.conf`" 4 | value=${ARG#*mode=} 5 | value2=${value%%p60*} 6 | if [ $value2 == '720' ]; then 7 | sed -i -e 's/mode=720p60/mode=1080p60/g' /etc/vdec.conf 8 | elif [ $value2 == '1080' ]; then 9 | sed -i -e 's/mode=1080p60/mode=720p60/g' /etc/vdec.conf 10 | fi 11 | reboot # Please probe this for re-read config: killall -1 vdec 12 | 13 | -------------------------------------------------------------------------------- /hi3536dv100/root/vdec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/root/vdec -------------------------------------------------------------------------------- /hi3536dv100/rootfs.squashfs.hi3536dv100: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/rootfs.squashfs.hi3536dv100 -------------------------------------------------------------------------------- /hi3536dv100/uImage.hi3536dv100: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/uImage.hi3536dv100 -------------------------------------------------------------------------------- /hi3536dv100/usr/bin/mavlink-routerd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/usr/bin/mavlink-routerd -------------------------------------------------------------------------------- /hi3536dv100/usr/bin/rcjoystick: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/hi3536dv100/usr/bin/rcjoystick -------------------------------------------------------------------------------- /lte-fpv.md: -------------------------------------------------------------------------------- 1 | ## Подключение камеры к планшету или ПК через LTE (4G) модем 2 | 3 | Летать через 4G - крайне интересная тема для самолетов под стабилизацией или автоматическим маршрутом. Разобъем процесс настройки на задачи: 4 | 5 | * настроить интернет через модем на камере 6 | * настроить свой сервер zerotier (можно воспользоваться публичным) 7 | * подключить камеру и ПК к одной сети zerotier и настроить стрим 8 | 9 | Следуя [этим инструкциям](usb-modeswitch.md), настроим usb_modeswitch и сетевой интерфейс eth1 на камере под прошивкой OpenIPC LTE. Если у вас FPV или LITE прошивка, предварительно нужно ее сменить онлайн: 10 | ``` 11 | #тут меняем fpv на lte в файле /etc/os-release, можно это сделать вручную 12 | sed -i 's/BUILD_OPTION=fpv/BUILD_OPTION=lte/' /etc/os-release 13 | #а это если у вас lite версия 14 | sed -i 's/BUILD_OPTION=lite/BUILD_OPTION=lte/' /etc/os-release 15 | 16 | sysupgrade --force_ver -k -r -n 17 | ``` 18 | Мы получаем камеру с заводскими настройками и lte прошивкой, в которой в отличие от fpv удален wfb а взамен установлен zerotier-one клиент. 19 | На самом деле, правильным решением будет не использовать usb_modeswitch а настроить вторичную композицию модема сразу на cdc_ethernet. Тогда модем перестанет быть универсальным и сразу будет отображаться как сетевая карта, но зато исчезнет вероятность возникновения ряда проблем. 20 | 21 | #### zerotier 22 | Это программное обеспечение для объединения нескольких устройств в одну локальную сеть. Существует публичный сервер для создания своей сети, но лучше поднять свой. 23 | Для этого потребуется vps-сервер под ubuntu. 24 | ``` 25 | apt-get install -y apt-transport-https gnupg mc iftop #устанавливаем зависимости 26 | curl -s https://install.zerotier.com | sudo bash #устанавливаем клиентскую часть 27 | 28 | curl -O https://s3-us-west-1.amazonaws.com/key-networks/deb/ztncui/1/x86_64/ztncui_0.7.1_amd64.deb #устанавливаем панель управления 29 | apt-get install ./ztncui_0.7.1_amd64.deb 30 | 31 | echo 'HTTPS_PORT=6443' > /opt/key-networks/ztncui/.env #порт для вебморды управления 32 | echo 'NODE_ENV=production' >> /opt/key-networks/ztncui/.env #режим работы 33 | echo 'HTTPS_HOST=nn.mm.ff.dd' >> /opt/key-networks/ztncui/.env #внешний ip-адрес нашего сервера 34 | 35 | systemctl restart ztncui 36 | ``` 37 | 38 | Входим по ссылке https://ip_addr:6443, логин admin, пароль password. 39 | Далее создаем сеть и настраиваем параметры выдачи адресов, какие вам больше нравятся, остальные настройки по умолчанию. 40 | В режиме private после подключения клиента требуется установить галочку Authorized чтобы разрешить ему подключение. 41 | 42 | ![ZTNCUI](https://github.com/OpenIPC/sandbox-fpv/raw/master/notes_files/ZTNCUI.png) 43 | 44 | Существует альтернатива в виде [публичного сервера](https://my.zerotier.com/), но вопрос надежности и быстродействия остается подвешенным. Программы - клиенты для windows, android скачивать [тут](https://www.zerotier.com/download/). 45 | 46 | Подключение к сети производится через указание Network ID, 16-значной символьной строки, которую берем из панели управления. Для камеры ее указываем в /etc/datalink.conf 47 | ``` 48 | use_zt=true 49 | zt_netid=a8867b0bxxxxxxxxx 50 | ``` 51 | после чего перезагружаем камеру. При наличии интернет-подключения, хоть LTE хоть ethernet, камера должна подключиться к сети zerotier. Это можно проверить через веб-панель управления и на камере командой ifconfig. 52 | ``` 53 | ztuplek3wb Link encap:Ethernet HWaddr 92:31:B1:54:8B 54 | inet addr:10.7.0.1 Bcast:10.7.0.255 Mask:255.255.255.0 55 | inet6 addr: fe80::9031:b1ff:fe54/64 Scope:Link 56 | UP BROADCAST RUNNING MULTICAST MTU:2800 Metric:1 57 | RX packets:93 errors:0 dropped:0 overruns:0 frame:0 58 | TX packets:1236835 errors:0 dropped:0 overruns:0 carrier:0 59 | collisions:0 txqueuelen:1000 60 | RX bytes:5677 (5.5 KiB) TX bytes:1493618333 (1.3 GiB) 61 | ``` 62 | 63 | Для ПК или андроид-устройства [устанавливаем](https://www.zerotier.com/download/) программу и аналогично добавляем сеть по ее id, авторизуем устройство в веб-панели. Пробуем перекрестный ping, он должен проходить. Если имеется файервол/брендмауер, как например под windows, нужно добавить в нем разрешающее правило с нашей подсетью. 64 | 65 | #### Настройка стрима 66 | Остается в /etc/majestic.yaml указать ip-адрес наземки из сети zerotier и видео можно принимать. Не забудьте согласовать кодеки. 67 | ``` 68 | outgoing: 69 | - udp://ip_from_zerotier:5600 70 | ``` 71 | 72 | #### Телеметрия 73 | Проверку телеметрии я еще не делал, но работать все должно как то так. 74 | Используется mavlink-routerd с конфигом /etc/mavlink.conf. Нужно указать эндпоинты для локального serial и наземки по ip-адресу zerotier: 75 | ``` 76 | [General] 77 | TcpServerPort = 0 78 | 79 | [UartEndpoint drone] 80 | Device = /dev/ttyAMA0 81 | Baud = 115200 82 | 83 | [UdpEndpoint qgroundcontrol] 84 | Mode = Normal 85 | Address = gs_ip_from_zerotier 86 | Port = 14550 87 | ``` 88 | 89 | Так как соединение является двунаправленным, автоматически получаем телеметрию в обе стороны. 90 | -------------------------------------------------------------------------------- /mavfwd/mavfwd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/mavfwd/mavfwd -------------------------------------------------------------------------------- /mavfwd/readme.md: -------------------------------------------------------------------------------- 1 | ### Зачем нужен mavfwd 2 | `mavfwd` в первую очередь необходим для связи телеметрийного потока wifibroadcast, 3 | разделенного на входящий и исходящий на разных udp-портах, с uart камеры, который 4 | подключен к uart полетного контроллера UAV, настроенного на обмен телеметрией. 5 | Поддерживается mavlink 1 и 2 версий. Подробности о параметрах доступны по `mavfwd --help`. 6 | 7 | Во вторую очередь, mavfwd способен мониторить передаваемые в mavlink-пакете [RC_CHANNELS #65](https://mavlink.io/en/messages/common.html#RC_CHANNELS) 8 | значения каналов с 4-го и выше, указанное в параметре --channels числом. По изменению значений каналов вызывается bash-скрипт /root/channels.sh, 9 | передавая ему параметрами номер канала и его значение. Это нужно, чтобы организовать какое-то управление хост-системой (камерой), например ее перезагрузку 10 | или настройку каких-то параметров стримера. В приложенном примере производятся: 11 | * переключение разрешений 1080p / 720p; 12 | * включение и отключение ircut камеры; 13 | * пороговое изменение яркости, три режима, для подбора нужного под текущие условия освещённости (яркий день, обычный день, ночь). 14 | -------------------------------------------------------------------------------- /note-nvr-tab-ap.md: -------------------------------------------------------------------------------- 1 | ## Подключение планшета к регистратору по wifi через AP планшета 2 | 3 | Схема проста: в регистратор вставляется [TL-725n](https://www.tp-link.com/ru/home-networking/adapter/tl-wn725n/) или аналогичный адаптер на rtp8188eu, либо адаптер под 4 | который есть драйвер в прошивке OpenIPC; планшет включает точку доступа; регистратор коннектится к этой точке доступа; при перезапуске сервис wfb обнаруживает указанный wlan и 5 | настраивает трансляцию и телеметрию на планшет. 6 | 7 | ### Поднимем сеть 8 | * Закачаем драйвер [8188eu](hi3536dv100/lib/modules/4.9.37/extra/8188eu.ko) в `/lib/modules/4.9.37/extra/` 9 | * Настроим поднятие сети на адаптере в [`/etc/network/interfaces`](hi3536dv100/etc/network/interfaces), указывая свои ssid и password: 10 | ``` 11 | auto wlan1 12 | iface wlan1 inet dhcp 13 | pre-up if ! lsmod | grep 8188eu; then insmod /lib/modules/4.9.37/extra/8188eu.ko; fi 14 | pre-up sleep 1 15 | pre-up wpa_passphrase "ssid" "password" >/tmp/wpa_supplicant.conf 16 | pre-up sed -i '2i \\tscan_ssid=1' /tmp/wpa_supplicant.conf 17 | pre-up sleep 3 18 | pre-up wpa_supplicant -B -D nl80211 -i wlan1 -c/tmp/wpa_supplicant.conf 19 | post-down killall wpa_supplicant 20 | ``` 21 | ### Поправим конфиги сервисы 22 | * Закачаем обновленные [`/usr/bin/wifibroadcast`](hi3536dv100/usr/bin/wifibroadcast) и [`/usr/bin/telemetry`](hi3536dv100/usr/bin/telemetry) с детектированием подключения в /usr/bin. 23 | * Добавим в [wfb.conf](hi3536dv100/etc/wfb.conf) новую строчку с параметром - наименованием интерфейса для ap 24 | ``` 25 | tab_wlan=wlan1 26 | ``` 27 | * Если мы не пользуемся отправкой потока на PC, можно закомментировать параметр `udp_addr`, это немного разгрузит регистратор. 28 | * Включаем на планшете точку доступа и перезагружаем регистратор, либо нажимаем кнопку на [front panel](nvr_gpio.md). 29 | -------------------------------------------------------------------------------- /note-two-cameras-switched.md: -------------------------------------------------------------------------------- 1 | ## Несколько камер на одном линке 2 | 3 | У камер есть сетевой интерфейс, который в случае двух камер можно использовать даже без свича, просто соединив четыре провода интерфейса друг с другом. Этот интерфейс и будем использовать для связи между камерами. 4 | Если /etc/network/interfaces доработать примерно таким образом: 5 | ``` 6 | auto eth0 7 | iface eth0 inet dhcp 8 | hwaddress ether $(fw_printenv -n ethaddr || echo 00:24:B8:FF:FF:FF) 9 | 10 | auto eth0:1 11 | iface eth0:1 inet static 12 | address $(fw_printenv -n ipaddr || echo 192.168.1.9) 13 | netmask 255.255.255.0 14 | ``` 15 | то у камер появится саб-интерфейс с адресом, прописанным в переменной env `ipaddr` либо, если она пуста, указанным в address. Нам нужно, чтобы у камер были адреса из одной подсети, например пусть это будут 192.168.1.9 и 192.168.1.10 у "первой" и "второй" камер. 16 | Первая - та, на которой расположен линк wfb и wifi-свисток. От второй нужен только поток на дополнительный порт, пусть 5601 на адрес первой камеры. 17 | В случае, если на второй камере стоит openipc, нужно на ней отключить wfb через `daemon=0` в `datalink.conf` и настроить udp поток в majestic.yaml на 192.168.1.9:5601. 18 | Теперь создадим на первой камере демонстрационный скрипт переключения камер `camswitch.sh`: 19 | ``` 20 | function wfb_restart { 21 | kill -9 $(pidof wfb_tx) 22 | . /etc/wfb.conf 23 | wfb_tx -p ${stream} -u ${udp_port} -K /etc/drone.key -B ${bandwidth} -M ${mcs_index} -S ${stbc} -L ${ldpc} -G ${guard_interval} -k ${fec_k} -n ${fec_n} -T ${fec_timeout} -i ${link_id} ${wlan} & 24 | } 25 | 26 | function cam_1 { 27 | # this is main cam, with wfb_tx 28 | sed -i 's/udp_port=5601/udp_port=5600/' /etc/wfb.conf 29 | wfb_restart 30 | } 31 | 32 | function cam_2 { 33 | # set '- udp: cam1ip:5601' in /etc/majestic.yaml on cam2 34 | sed -i 's/udp_port=5600/udp_port=5601/' /etc/wfb.conf 35 | wfb_restart 36 | } 37 | 38 | cam_$1 39 | ``` 40 | Дадим ему права на выполнение через `chmod +x camswitch.sh` и теперь мы можем переключаться между камерами, вызывая `camswitch.sh 1` или `camswitch.sh 2`. 41 | Скрипт останавливает wfb_tx, заменяет в его конфиге udp_port (основная камера шлет на 5600 а вторая на 5601) и запускает заново, таким образом переключаясь между потоками. 42 | Можно подключить вызов скрипта например к [channels.sh](notes_cam_control.md) и управлять переключением с какого то канала RC. 43 | -------------------------------------------------------------------------------- /note_nvr_wdt.md: -------------------------------------------------------------------------------- 1 | ## Отключение watchdog на регистраторе 2 | 3 | Загрузчик на регистраторе запускает собаку, которая раз в полчаса перезагружает его. Для отключения копируем [`wdt.ko`](hi3536dv100/lib/wdt.ko) в `/lib` и добавляем в [`/etc/init.d/S95hisilicon`](hi3536dv100/etc/init.d/S95hisilicon) к загрузкам модулей, тут же выгружая: 4 | ``` 5 | insmod /lib/wdt.ko 6 | rmmod /lib/wdt.ko 7 | ``` 8 | 9 | Перезагружаемся, watchdog больше не должен срабатывать. 10 | -------------------------------------------------------------------------------- /note_telemetry_baud.md: -------------------------------------------------------------------------------- 1 | ## Заметка об отличной от 115200 скорости uart для телеметрии 2 | 3 | TipoMan столкнулся с проблемой: камера зависала при подаче на uart телеметрии на скорости, отличной от 115200. Решение: установка нужной скорости в `/etc/inittab`. 4 | 5 | ![inittab](notes_files/baud38400.jpg) 6 | -------------------------------------------------------------------------------- /notes_cam_control.md: -------------------------------------------------------------------------------- 1 | ### Управление камерой с земли 2 | 3 | В качестве эксперимента [`mavfwd`](mavfwd) был дополнен парсером mavlink-пакета RC_CHANNELS (значения RC каналов, отправленные с любого RC-линка, например с наземной станции [(джойстика)](https://github.com/whoim2/arduremote) через [Mission Planner joystick](https://ardupilot.org/copter/docs/common-joystick.html)) или с [подключенного](rcjoystick.md) к регистратору джойстика. 4 | 5 | Он мониторит изменения в указанном в аргументе `--channels X` или `-c X`каналах, считая после первых 4х, и при их наличии вызывает скрипт [`/root/channels.sh`](gk7205v200/root), передавая в него два параметра (номер канала и значение), и который производит необходимые операции. Например, `-c 1` будет мониторить только 5й канал, а `-c 4` будет мониторить 5,6,7,8 каналы. В текущем [примере](gk7205v200/root/channels.sh) это изменение режима работы камеры (1080p@30fsp / 720p@5-fps) на 5-м канале, смена luminance на 7м (трехпозиционный переключатель) и переключатель ircut (поляризационного фильтра). По умолчанию `-c 0`, т.е. отключен. 6 | 7 | Для установки его на камеру замените в `/usr/sbin/` штатный mavfwd на [измененный](mavfwd/mavfwd), и добавьте параметр `-c` в [`/usr/bin/telemetry`](gk7205v200/usr/bin/telemetry#L39). Заодно получите возможность установить скорость телеметрии для связи с полетником выше чем 115200, конечно на свой страх и риск! 8 | Приветствуются идеи и пожелания по этому поводу, которые можно высказать [здесь](https://t.me/+BMyMoolVOpkzNWUy). 9 | 10 | upd 31.03.2023 Добавил распознавание mavlink 2 протокола. 11 | 12 | -------------------------------------------------------------------------------- /notes_files/IMG_20230323_081622_212.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/IMG_20230323_081622_212.jpg -------------------------------------------------------------------------------- /notes_files/OpenIPC_telemetry.csv: -------------------------------------------------------------------------------- 1 | text,type,typeId,Description 2 | ​,Rectangle,creately.basic.rectangle, 3 | GROUND (NVR),Text,creately.basic.text, 4 | WIFI,WiFi,creately.material-icons.wifi_twotone_2, 5 | rtl8812au,Rectangle,creately.basic.rectangle, 6 | wifi adapter driver in monitor mode,Rectangle,creately.basic.rectangle, 7 | wfb-rx,Rectangle,creately.basic.rectangle, 8 | LAN / WLAN or usb network,Ellipse,creately.basic.ellipse, 9 | ​,Rectangle,creately.basic.rectangle, 10 | PC or Pocket,Text,creately.basic.text, 11 | GS telemetry program,Computer,creately.material-icons.computer_twotone_2, 12 | udp:14551,Text,creately.basic.text, 13 | udp:14550,Text,creately.basic.text, 14 | ​,Rectangle,creately.basic.rectangle, 15 | CAM,Text,creately.basic.text, 16 | mavfwd,Rectangle,creately.basic.rectangle, 17 | wfb-tx,Rectangle,creately.basic.rectangle, 18 | wfb-rx,Rectangle,creately.basic.rectangle, 19 | udp:14550,Text,creately.basic.text, 20 | udp:14551,Text,creately.basic.text, 21 | FC > cam uart,Rectangle,creately.basic.rectangle, 22 | wifi adapter driver in monitor mode,Rectangle,creately.basic.rectangle, 23 | rtl8812au,Rectangle,creately.basic.rectangle, 24 | WIFI,WiFi,creately.material-icons.wifi_twotone_2, 25 | wfb-rx,Rectangle,creately.basic.rectangle, 26 | mavlink-routerd,Rectangle,creately.basic.rectangle, 27 | udp:14550,Text,creately.basic.text, -------------------------------------------------------------------------------- /notes_files/OpenIPC_video.csv: -------------------------------------------------------------------------------- 1 | text,type,typeId,Description 2 | ​,Rectangle,creately.basic.rectangle, 3 | sensor,Rectangle,creately.basic.rectangle, 4 | CAM,Text,creately.basic.text, 5 | majestic or vencoder,Rectangle,creately.basic.rectangle, 6 | wfb-tx,Rectangle,creately.basic.rectangle, 7 | wifi adapter driver in monitor mode,Rectangle,creately.basic.rectangle, 8 | isp,Text,creately.basic.text, 9 | rtp:5600,Text,creately.basic.text, 10 | rtl8812au,Rectangle,creately.basic.rectangle, 11 | WIFI,WiFi,creately.material-icons.wifi_twotone_2, 12 | ​,Rectangle,creately.basic.rectangle, 13 | GROUND (NVR),Text,creately.basic.text, 14 | WIFI,WiFi,creately.material-icons.wifi_twotone_2, 15 | rtl8812au,Rectangle,creately.basic.rectangle, 16 | wifi adapter driver in monitor mode,Rectangle,creately.basic.rectangle, 17 | wfb-rx,Rectangle,creately.basic.rectangle, 18 | LAN / WLAN or usb network,Ellipse,creately.basic.ellipse, 19 | ​,Rectangle,creately.basic.rectangle, 20 | PC or Pocket,Text,creately.basic.text, 21 | videoplayer or GS program,Computer,creately.material-icons.computer_twotone_2, 22 | ,To Right Arrow,creately.arrows.torightarrow, 23 | ,To Right Arrow,creately.arrows.torightarrow, 24 | rtp:5600,Text,creately.basic.text, 25 | rtp:5600,Text,creately.basic.text, 26 | wfb-rx,Rectangle,creately.basic.rectangle, 27 | vdecoder,Rectangle,creately.basic.rectangle, 28 | HDMI,Rectangle,creately.basic.rectangle, 29 | udp:5000,Text,creately.basic.text, -------------------------------------------------------------------------------- /notes_files/Screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/Screenshot_1.png -------------------------------------------------------------------------------- /notes_files/Screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/Screenshot_2.png -------------------------------------------------------------------------------- /notes_files/ZTNCUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/ZTNCUI.png -------------------------------------------------------------------------------- /notes_files/baud38400.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/baud38400.jpg -------------------------------------------------------------------------------- /notes_files/gk7205v200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/gk7205v200.png -------------------------------------------------------------------------------- /notes_files/hi3536ev100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/hi3536ev100.png -------------------------------------------------------------------------------- /notes_files/hi3536ev100_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/hi3536ev100_pinout.png -------------------------------------------------------------------------------- /notes_files/link_hw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/link_hw.png -------------------------------------------------------------------------------- /notes_files/mp_h265.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/mp_h265.png -------------------------------------------------------------------------------- /notes_files/photo_2023-03-23_02-12-40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/photo_2023-03-23_02-12-40.jpg -------------------------------------------------------------------------------- /notes_files/qgc-udp-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/qgc-udp-settings.png -------------------------------------------------------------------------------- /notes_files/telemetry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/telemetry.png -------------------------------------------------------------------------------- /notes_files/usb-ethernet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/usb-ethernet.png -------------------------------------------------------------------------------- /notes_files/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/notes_files/video.png -------------------------------------------------------------------------------- /notes_imx335_gk7205v300.md: -------------------------------------------------------------------------------- 1 | ## Заметки о использовании камеры gk7205v300 с сенсором imx335 2 | 3 | В главном работа с камерой ничем не отличается от прочих камер gk. Точно так же прошивается lite или fpv, либо lite обновляется до fpv. 4 | Наличие и расположение пинов для USB и UART нужно смотреть на странице продавца. Для примера, камера купленная по [ссылке ](https://aliexpress.ru/item/1005005492432144.html) имеет USB 5 | на разъеме для шлейфа FPC и названы в описании WIFI_DP и WIFI_DN (USB DP/DN). 6 | 7 | Нюансы касаются настройки разрешения. Режим 1080p (установка size: 1920x1080 в majestic.yaml) выдает 15 кадров / секунду, что конечно неприемлимо. Необходимо в файле `/etc/sensors/imx335_i2c_4M.ini` 8 | закомментировать (через `;`) строчку `clock=27MHz` и установить `Isp_FrameRate=30`, после чего перезагрузить камеру. Исправленные файлы лежат в каталоге [imx335_gk7205v300](/imx335_gk7205v300). 9 | Также работает режим `size: 2592x1520` и выдает 20fps, но угол обзора картинки не меняется, что наводит на мысли об интерполяции. Но неизвестно, из какого разрешения - в какое. По факту задержка в 1520p@20 ниже и составляет около 165мс, в 1080p@30 - 185мс. 10 | 11 | Также необходим [gkrcparams](gkrcparams.md) для более плавной картинки. 12 | -------------------------------------------------------------------------------- /notes_start_hi3536ev100.md: -------------------------------------------------------------------------------- 1 | ### Заметки о прошивке NVR hi3536ev100 на OpenIPC для целей FPV 2 | [EN](en_notes_start_hi3536ev100.md) 3 | 4 | Данная статья неактуальна в части прошивки, используйте https://github.com/OpenIPC/wiki/blob/master/en/fpv-nvr.md, эта же статья может быть полезна отдельными моментами. 5 | 6 | 7 |
8 | Как устроена память 9 | Для начала, следует разобраться, как устроена память регистратора (да и камеры тоже) и что нужно прошивать. Данные хранятся на spi-flash 16mb в виде блоков mtd: 10 | 11 | ``` 12 | cat /proc/cmdline 13 | mem=150M console=ttyAMA0,115200 panic=20 root=/dev/mtdblock3 rootfstype=squashfs init=/init mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),8192k(rootfs),-(rootfs_data) 14 | ls /dev/mtdb* 15 | /dev/mtdblock0 /dev/mtdblock1 /dev/mtdblock2 /dev/mtdblock3 /dev/mtdblock4 16 | ``` 17 | Как следует из вывода, нулевой блок это загрузчик u-boot; далее идет блок для хранения переменных окружения (`printenv`, `setenv` команды пишут в ОЗУ, а `saveenv` сохраняет именно в этот блок); следом ядро uImage; потом rootfs.squashfs (неизменяемый образ файловой системы); и наконец rootfs_data или он же overlay - изменяемая часть, куда пишутся отличия от rootfs если вы изменяете какие-либо файлы. Таким образом, очистив overlay, мы "скинем" файловую систему до "дефолта": 18 | ``` 19 | sf probe 0 #выбираем устройство 20 | sf erase 0xA50000 0x500000 #производим очистку 21 | reset #перезагрузка 22 | ``` 23 | Еще проще сбросить до "заводских" прошивки командой `firstboot`. 24 | 25 | Калькулятор адресов для команд доступен [здесь](https://openipc.org/tools/firmware-partitions-calculation). В нашем случае раздел rootfs: 8192kB, значит адрес начала overlay будет 0xA50000. Для камеры, у которой flash 8mB, размер rootfs 5120kB, адреса будут другие, включая переменные окружения! 26 |
27 | 28 | Загрузчик у этого регистратора не имеет пароля, и в него можно попасть через uart/115200 бод, нажав при старте несколько раз Ctrl+C будучи подключенным к порту debug-uart регистратора через адаптер usb-uart 3v3 (ftdi, ch340). Debug uart расположен напротив разъема VGA на противоположном краю платы и подписан как gnd/tx/rx. Загрузчик нам прошивать не требуется, burn не нужен. ENV (переменные окружения) у нас отличаются от заводских, но их проще установить прямо из загрузчика построчно: 29 | ``` 30 | setenv ipaddr '192.168.0.222' #тут ip в вашей подсети из свободных 31 | setenv serverip '192.168.0.107' #адрес ПК с tftp сервером 32 | setenv netmask '255.255.255.0' 33 | setenv bootcmd 'sf probe 0; sf read 0x82000000 0x50000 0x200000; bootm 0x82000000' 34 | setenv uk 'mw.b 0x82000000 ff 1000000;tftp 0x82000000 uImage.${soc}; sf probe 0; sf erase 0x50000 0x200000; sf write 0x82000000 0x50000 ${filesize}' 35 | setenv ur 'mw.b 0x82000000 ff 1000000;tftp 0x82000000 rootfs.squashfs.${soc}; sf probe 0; sf erase 0x250000 0x800000; sf write 0x82000000 0x250000 ${filesize}' 36 | setenv bootargs 'mem=192M console=ttyAMA0,115200 panic=20 root=/dev/mtdblock3 rootfstype=squashfs init=/init mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),8192k(rootfs),-(rootfs_data)' 37 | setenv osmem '192M' 38 | setenv totalmem '256M' 39 | setenv soc 'hi3536dv100' 40 | #тут очищаем ненужные далее переменные 41 | setenv da; setenv du; setenv dr; setenv dw; setenv dl; setenv dc; setenv up; setenv tk; setenv dd; setenv de; setenv jpeg_addr; setenv jpeg_size; setenv vobuf; setenv loadlogo; setenv appVideoStandard; setenv appSystemLanguage; setenv appCloudExAbility 42 | saveenv #сохраняем новое окружение переменных 43 | printenv #смотрим, все ли в порядке 44 | ``` 45 | Оригинальные env и полный дамп микросхемы (бекап заводской прошивки 16mb на случай восстановления) доступны [здесь](https://github.com/OpenIPC/sandbox-fpv/tree/master/hi3536dv100/original_firmware). 46 | 47 | Как вы могли заметить, в переменных uk и ur хранятся макросы для прошивки uImage и rootfs с загрузкой их с [tftp сервера](https://pjo2.github.io/tftpd64/), указанного в переменной serverip. Все адреса соответствуют переменной bootargs, содержимое которой и задает разметку файловой системы для ядра при загрузке. Разметка отличается от привычных для камер goke/hisilicone, ядро у нас как и у lite/fpv размером 2мб, однако файловая система размером 8мб, как у ultimate. Оставшиеся ~5мб используются оверлеем (вашими изменениями файлов относительно оригинальной rootfs). Для прошивки используйте официальные сборки со страницы релизов [openipc/firmware](https://github.com/OpenIPC/firmware/releases/download/latest/openipc.hi3536dv100-nor-fpv.tgz). Архив содержит ядро и файловую систему. 48 | 49 | Итак, после установки переменных можно приступать к прошивке оставшейся части. Запустите tftpd сервер, положите в его корень uImage.hi3536dv100 и rootfs.squashfs.hi3536dv100, выберите соответствующий сетевой интерфейс и в загрузчике запустите макрос: `run uk`. Должен выполниться ряд команд, из вывода которых должно следовать, что файл uImage скачался и прошился во flash. Аналогично выполните `run ur` для прошивки rootfs. Если адреса установлены верно, но скачивание застревает на "Downloading", смените адрес регистратора на соседний свободный: `setenv ipaddr '192.168.0.223'`. 50 | Если все прошло без ошибок, делайте `reset` и грузитесь в операционную систему, логин root, пароль 12345. 51 | 52 | Конфиги из каталога hi3536dv100 неактуальны, однако могут представлять интерес касаемо подключения планшета по usb/wifi/ethernet hotspot, вы можете перенести их по аналогии в конфиги официальной прошивки или оформить отдельными bash-скриптами. Обычно суть этих изменений в определении адреса подключаемого планшета (который является для регистратора шлюзом в случаях, если планшет у нас dhcp-сервер) и указании этого адреса в дополнительном экземпляре wfb_rx для видеопотока и для телеметрийных потоков. 53 | 54 | Обновление прошивки происходит через интернет командой `sysupgrade -r -k -n`. 55 | 56 |
57 | Обновление без интернета из /tmp 58 | В дальнейшем прошивку регистратора можно делать, залив в него через WinSCP ядро и rootfs в каталог `/tmp` и выполнив `sysupgrade --kernel=/tmp/uImage.hi3536dv100 --rootfs=/tmp/rootfs.squashfs.hi3536dv100 -z`. Параметр `-z` нужен если у вас нет подключения к интернету (не обновляет скрипт sysupgrade), `-n` очистит пользовательскую fs (overlay). 59 |
60 | -------------------------------------------------------------------------------- /notes_start_ivg-g2s.md: -------------------------------------------------------------------------------- 1 | ## Заметки по прошивке камеры IVG-G2S прошивкой OpenIPC. 2 | 3 | ВНИМАНИЕ! Большая часть информации из этой статьи безнадежно устарела, все дополнительные помимо прошивки шаги уже неактуальны - они внесены в прошивку, и все работает из коробки, необходимо лишь произвести копирование ключа gs.key с камеры на наземную станцию и указать правильно каналы на обоих. 4 | 5 | 6 | Цель этой заметки - помочь привлечь внимание к крайне перспективной теме запуска digital fpv на дешевых камерах без одноплатника на борту. 7 | Разработчикам **ОЧЕНЬ** важны отзывы, при наличии популярности проект будет развиваться с их помощью значительно быстрее. 8 | Переходите в специально созданный для этой темы [телеграмм-чат](https://t.me/+BMyMoolVOpkzNWUy), задавайте вопросы которые не описаны тут и по ссылкам ниже, публикуйте информацию о своих успехах и запрашивайте помощь в решении проблем. 9 | Еще раз - фидбеки крайне важны, даже если у вас все получилось и работает - пожалуйста, не поленитесь описать свой сетап и опубликуйте в чате отзыв. Это позволит развиваться проекту с участием разработчиков. 10 | 11 | * [Основная страница по OpenIPC + FPV теме, обязательна к прочтению](https://github.com/OpenIPC/wiki/blob/master/ru/fpv.md) 12 | * [Основная wiki проекта](https://github.com/OpenIPC/wiki) (на текущий момент EN версия содержит больше информации) 13 | * [Генератор инструкций на сайте](https://openipc.org/supported-hardware/featured) 14 | 15 | 16 | ### Термины 17 | 18 | * Flash - в данном контексте SPI-flash, микросхема памяти. 19 | * U-Boot - загрузчик. Есть "родной", есть от OpenIPC. Родной запаролен. Нам нужен скачанный из генератора инструкций. 20 | * uImage - ядро Embedded Linux, в виде bin файла. 21 | * Root-FS - файловая система выбранной версии (lite, ultimate, fpv), в виде squash-fs файла [https://ru.wikipedia.org/wiki/Squashfs]. uImage и rootfs нужно добывать через конструктор инструкций, раздельная прошивка u-boot и root-fs. 22 | * Shell - командная строка linux камеры, доступна через uart и ssh (программа putty). Также есть shell загрузчика, только uart. Логин root, пароля нет. 23 | * Majestic - утилита - стример потоков видео, из комплекта прошивки OpenIPC. 24 | 25 | Платы оснащаются обычно spi-flash размером 8 или 16 мб. Версия ultimate требует 16, можно перепаять. Для fpv целей достаточно 8мб. 26 | 27 | Если у вас нет кабеля ethernet для подключения камеры к вашему свичу/роутеру, его можно сделать из половинки обычного патч-корда и разъема jst xh1.25 8pin. Такие использовались в полетниках Omnibus F4 и много где еще. 28 | Распиновки камеры и коннектора легко гуглятся, соединять необходимо 4 линии: rx+, rx-, tx+, tx- на кабеле и камере. На тот же разъем подается питание от 5 до 12в на пины 7(gnd) и 8(vcc). 29 | 30 | Рекомендую сначала прошить lite, поскольку в ней разблокирован shell через uart (в файле /etc/inittab) и это позволит подключаться в нештатных ситуациях, например при отсутствии сети. 31 | 32 | Существует три способа прошить камеру ivg-g2s на OpenIPC. В порядке усложнения: coupler, burn, программатор. 33 | 34 | - Coupler [https://github.com/OpenIPC/coupler] - это загрузка ядра и rootfs одним файлом через родной веб-интерфейс камеры. Минусы - не меняется родной запароленный 35 | загрузчик, можно выполнить только один раз, откат или смена прошивок только через прочие способы. 36 | Алгоритм: выяснить в родном веб-интерфейсе версию, на ее основании скачать прошивку, загрузить как обновление в родном вебинтерфейсе. Для ivg-g2s/659A7 есть [прошивка с загрузчиком](gk7205v200/659A7_OpenIPC_FPV.bin). 37 | 38 | - Burn [https://github.com/OpenIPC/burn] - загрузка незапароленного загрузчика u-boot от OpenIPC через uart камеры и uart-usb адаптер (например, ch340) и дальнейшая работа в загрузчике, согласно конструктору инструкций OpenIPC. 39 | Минусов нет, меняется загрузчик которым в любой момент можно загрузить с tftpf сервера [https://pjo2.github.io/tftpd64/] нужный образ и прошить во flash. 40 | Алгоритм описан видеоинструкциями на канале OpenIPC [https://www.youtube.com/@openipc/videos]. Далее, загрузив в RAM загрузчик (только [выбираем свой](gk7205v200_u-boot-7502v200-for-telemetry.md) ввиду нюансов), работаем через конструктор инструкций. uImage и root-fs распаковываем и кладем в каталог tftpd. 41 | Я пробовал пробросить usb-uart в archlinux под virtualbox и ипользовать burn оттуда, но загрузка не проходила, связь с uart была в одну сторону, только на чтение. Из под windows 7 все прошло штатно. 42 | Используйте короткие провода как от usb порта до адаптера, так и от адаптера до камеры. Распиновка uart на камере есть в первой статье из списка выше, соединять необходимо "накрест" - tx адаптера на rx камеры и rx адаптера на tx камеры. 43 | Если все в порядке, но tftp не загружает файл - попробуйте сменить адрес камере на соседний свободный, `setenv ipaddr '192.168.0.223'`. 44 | 45 | - Программатор - выпаивание флеш или одной ноги и подключение к программатору, прошивка всего через программатор. 46 | Самый сложный способ, это единственный минус. 47 | 48 | При первой загрузке необходимо выполнить команду firstboot. 49 | Если камера циклично перезагружается - это срабатывает watchdog от majestic (стримера). Скорее всего нужно снять колпачок объектива и включить свет. Отключается в /etc/majestic.yaml, убить процесс быстро: `killall majestic`. 50 | 51 | Управлять параметрами конфига с сохранением можно через утилиту cli шелла: 52 | ``` 53 | cli -s .image.contrast 50 54 | cli -s .image.luminance 50 55 | cli -s .video0.codec h264 56 | cli -s .hls.enabled false 57 | cli -s .isp.sensorConfig /etc/sensors/imx307_i2c_2l_1080p.ini 58 | cli -s .video0.size 1920x1080 59 | cli -s .video0.fps 30 60 | ``` 61 | Рекомендую выполнить эти команды, это настроит majestic для первоначальных попыток. 62 | 63 | Перейти на версию FPV с обновлением. Внимание! В версии FPV отключен shell через uart (освобожден для работы телеметрии), после загрузки, остается только сетевой доступ. Сам загрузчик, конечно, работает через uart. 64 | ``` 65 | sed -i 's/BUILD_OPTION=lite/BUILD_OPTION=fpv/' /etc/os-release 66 | sysupgrade --force_ver -k -r -n 67 | ``` 68 | Если вы не собираетесь использовать телеметрию сквозь этот видеолинк, можете включить его назад: 69 | ``` 70 | sed -i 's/#console::respawn:\/sbin\/getty/console::respawn:\/sbin\/getty/' /etc/inittab 71 | reboot 72 | ``` 73 | Если flash заблокирована (вы как то прошили ядро предыдущих версий, которые не умеют разблокировать флеш), то эта и любые прочие команды выполнены не будут. 74 | 75 | Пример вывода `dmesg | grep bsp-sfc` для определения блокировки флешки: 76 | 77 | Разблокирована 78 | ``` 79 | bsp-sfc bsp_spi_nor.0: SR1:[02]->[00] 80 | bsp-sfc bsp_spi_nor.0: SR2:[02]->[00] 81 | bsp-sfc bsp_spi_nor.0: all blocks are unlocked. 82 | bsp-sfc bsp_spi_nor.0: Winbond: SR1 [], SR2 [QE], SR3 [DRV0,DRV1] 83 | ``` 84 | 85 | Заблокирована 86 | ``` 87 | bsp-sfc bsp_spi_nor.0: SR1:[02]->[00] 88 | bsp-sfc bsp_spi_nor.0: SR2:[02]->[00] 89 | bsp-sfc bsp_spi_nor.0: all blocks are unlocked. 90 | bsp-sfc bsp_spi_nor.0: Winbond: SR1 [TB], SR2 [QE], SR3 [WPS,DRV0,DRV1] 91 | ``` 92 | 93 | Попытка разблокировать флеш из shell (мне не помогла) 94 | ``` 95 | devmem 0x10010024 32 0x06;devmem 0x10010030 32 0;devmem 0x1001003C 32 0x81;devmem 0x14000000 16 0x0000;devmem 0x10010024 32 0x01;devmem 0x10010030 32 0;devmem 0x10010038 32 2;devmem 0x1001003C 32 0xA1 96 | # 97 | sysupgrade --force_ver -k -r -n 98 | ``` 99 | 100 | Путь к разблокировке flash лежит через загрузку свежего ядра, распакованного архиватором из tgz файла с ядром и rootfs, взятого из конструктора инструкций. Загрузившись, оно автоматически разблокирует flash. Делается из загрузчика, залитого в ram через burn. 101 | 102 | ``` 103 | # Устанавливаем адрес камеры и адрес сервера tftpd 104 | setenv ipaddr 192.168.0.222; setenv serverip 192.168.0.107 105 | 106 | # Устанавливаем аргументы окружения (env) 107 | setenv bootargs 'mem=32M console=ttyAMA0,115200 panic=20 rootfstype=squashfs root=/dev/mtdblock3 init=/init mtdparts=sfc:256k(boot),64k(env),2048k(kernel),5120k(rootfs),-(rootfs_data)' 108 | 109 | # Очищаем область оперативной памяти для скачивания ядра 110 | mw.b 0x42000000 ff 1000000 111 | 112 | # Загружаем ядро uImage.gk7205v200 с tftpd сервера 113 | tftpboot 0x42000000 uImage.${soc} 114 | 115 | # Запускаем ядро 116 | bootm 0x42000000 117 | ``` 118 | -------------------------------------------------------------------------------- /nvr_gpio.md: -------------------------------------------------------------------------------- 1 | ## Настройка кнопок со своим функционалом на регистраторе 2 | 3 | ![front_panel](https://github.com/OpenIPC/sandbox-fpv/raw/master/notes_files/IMG_20230323_081622_212.jpg) 4 | 5 | Регистратор имеет на борту разъем для подключения фронт-панели с кнопками, ir-ресивером: 6 | 7 | ![nvr-ports](notes_files/photo_2023-03-23_02-12-40.jpg) 8 | 9 | Разъем cn5 подписан с обратной стороны. С назначением +3.3в и GND понятно, IR задействовать не удалось, остальные пины ведут на GPIO процессора: 10 | ``` 11 | Y2 ^17 12 | Y1 ^6 13 | X2 ^13 14 | Y3 ^8 15 | X1 ^7 16 | ALARM 10 17 | REC 11 18 | ``` 19 | 20 | Символ `^` означает подтяжку резистором к +3.3, значит кнопкой эти пины надо замыкать на GND и ловить значение 0. Это реализовано в файле [`root/gpio_monitor.sh`](hi3536dv100/root/gpio_monitor.sh). 21 | По замыканию пина Y1 на землю он производит рестарт сервиса [wfb](hi3536dv100/etc/init.d/S98wfb), который следом рестартует [телеметрию](hi3536dv100/usr/bin/telemetry), для более удобного подключения смартфона или планшета [по USB](usb-tethering.md), или после смены wifi-адаптера. Скрипт мониторинга ведет лог нажатий, который можно наблюдать по `tail -f /tmp/gpio.log`. 22 | Примеры использования GPIO на выход можно посмотреть в [`testgpio.sh`](hi3536dv100/root/testgpio.sh), и можно подключить пин ALARM или REC к малмощному светодиоду с резистором для индикации процессов, например перезапуска wfb-ng как сделано в `gpio_monitor.sh`. 23 | 24 | Для запуска монитора как системного демона создадим файл [`/etc/init.d/S99gpio_monitor`](hi3536dv100/etc/init.d/S99gpio_monitor) откуда и будем запускать наш [`root/gpio_monitor.sh`](hi3536dv100/root/gpio_monitor.sh): 25 | ``` 26 | #!/bin/sh 27 | # 28 | # Start gpio monitor 29 | # 30 | 31 | case "$1" in 32 | start) 33 | echo "Starting gpio_monitor daemon..." 34 | /root/gpio_monitor.sh & 35 | ;; 36 | stop) 37 | echo "Stopping gpio_monitor daemon..." 38 | kill -9 $(pidof {exe} ash /root/gpio_monitor.sh) 39 | ;; 40 | *) 41 | echo "Usage: $0 {start|stop}" 42 | exit 1 43 | esac 44 | ``` 45 | 46 | Перезагружаемся без wifi адаптера и/или usb modem, активируем их уже после загрузки и убеждаемся, что по нажатию кнопки (хотя бы полсекунды подержите) сервисы запускаются. 47 | Список запущенных процессов всегда можно посмотреть командой `ps axww`. 48 | -------------------------------------------------------------------------------- /rcjoystick.md: -------------------------------------------------------------------------------- 1 | ## Использование аппаратуры как джойстика для передачи каналов RC через mavlink 2 | 3 | ### Теория 4 | Программы наземных станций, такие как Mission Planner или QGroundControl, способны распознавать подключенные джойстики либо аппаратуры в режиме usb-джойстика и 5 | передавать на полетный контроллер значения осей в пакете RC_CHANNELS_OVERRIDE (#70). Однако, QGC передает только первые 4 канала (две оси), остальное можно назначить только на кнопки, 6 | а MP может это делать только под Windows, что не всегда удобно. Я написал простейшее приложение для регистратора, которое распознает подключенный джойстик и отправляет пакеты [RC_CHANNELS_OVERRIDE](https://mavlink.io/en/messages/common.html#RC_CHANNELS_OVERRIDE) в версии протокола mavlink 2 для поддержки 18 каналов напрямую в порт telemetry_tx, который обычно опубликован на 127.0.0.1:14650 регистратора. Порт, адрес, время между отправками пакетов, число осей и устройство в системе можно переназначить, смотрите `rcjoystick -h`. 7 | 8 | ``` 9 | Usage: 10 | [-v] verbose; 11 | [-d device] default '/dev/input/js0'; 12 | [-a addr] ip address send to, default 127.0.0.1; 13 | [-p port] udp port send to, default 14650; 14 | [-t time] update RC_CHANNEL_OVERRIDE time in ms, default 50; 15 | [-x axes_count] 2..9 axes, default 5, other channels mapping to js buttons from button 0; 16 | [-r rssi_channel] store rx packets per second value to this channel, default 0 (disabled); 17 | [-i interface] wlan interface for rx packets statistics, default wlan0; 18 | 19 | ``` 20 | 21 | Например, отправлять можно не в telemetry_tx, а в mavlink_routerd, если вам так нужно. Пакет для сборки в buildroot от OpenIPC [тут](rcjoystick). 22 | 23 | ### Запускаем 24 | Нам необходимо ядро и rootfs с поддержкой usb-hid на регистраторе. Для этого [прошейте](notes_start_hi3536ev100) их из [`/hi3536dv100`](hi3536dv100) каталога. 25 | ~~Необходимо обеспечить запуск модуля `hid-generic.ko`, для этого добавьте `modprobe hid-generic.ko` в [`S95hisilicon`](hi3536dv100/etc/init.d/S95hisilicon).~~ В свежесобранном ядре модуль `hid-generic.ko` загружается автоматически. 26 | 27 | Далее нужно скопировать бинарник [`rcjoystick`](hi3536dv100/usr/bin/rcjoystick) в /usr/bin регистратора, через WinSCP и назначить права на исполнение: `chmod +x /usr/bin/rcjoystick`. 28 | Перезагружаемся, подключаем аппаратуру к регистратору по usb и пробуем в консоли запустить `rcjoystick -v`. Если все прошло хорошо, то на экране мы должны увидеть значения осей при изменении положения стиков и переключателей, а в программе телеметрии, например в QGC (analyse tools > Mavlink inspector > RC_CHANNELS_RAW) должны изменяться каналы. Для запуска на постоянную можно прописать его в отдельный сервис [`S99rcjoystick`](hi3536dv100/etc/init.d/S99rcjoystick), главное чтобы он запускался после wifibroadcast. 29 | 30 | ### RSSI 31 | 32 | Также в rcjoystick была добавлена функция инжекции аналога rssi (числа полученных от воздушной части пакетов в секунду) для хоть какого то индикатора качества приема, так как отдельный сервис для этого заводить нет желания и смысла, учитывая невысокий уровень регистратора. В rcjoystick уже есть большая часть необходимого для инжекции. 33 | 34 | Указываем `-r 16` и, если интерфейс wfb не wlan0, то и его `-i wlanX` и в указанный канал будет попадать число принятых наземкой пакетов в секунду. У меня оно в районе 800, вы можете увидеть свое применив ключ verbose (`-v`). Далее указываем на полетнике: 35 | ``` 36 | RSSI_TYPE 2 37 | RSSI_CHANNEL 16 38 | RSSI_CHAN_LOW 0 39 | RSSI_CHAN_HIGH 800 //ваше обычное значение, примерно среднее, не максимальное и не минимальное. 40 | ``` 41 | Значение будет отправлено на полетник, где он его обработает и установит 0..99 в rssi. 42 | 43 | Проект пока в стадии тестирования, поэтому [присылайте](https://t.me/+BMyMoolVOpkzNWUy) свои отзывы о попытках и пожелания. 44 | 45 | ### Текущие проблемы 46 | Иногда наблюдаются кратковременные фризы, если активно долбить оба стика во всех направлениях. Дебаг говорит, что от драйвера не приходят в это время события о перемещении. Этот эффект не наблюдается, если использовать ["радиоудлинитель" джойстика](sbus-to-usb-joystick) в виде arduino pro micro, которая парсит SBUS от вашего приемника и переводит в usb-hid-joystick. 47 | -------------------------------------------------------------------------------- /rcjoystick/Config.in: -------------------------------------------------------------------------------- 1 | config BR2_PACKAGE_RCJOYSTICK 2 | bool "rcjoystick" 3 | help 4 | joystick /dev/input/js0 to mavlink rc_channels_override udp 127.0.0.1:14550 5 | 6 | https://github.com/whoim2/rcjoystick 7 | -------------------------------------------------------------------------------- /rcjoystick/rcjoystick.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # rcjoystick 4 | # 5 | ################################################################################ 6 | 7 | RCJOYSTICK_LICENSE = GPL-2.0 8 | 9 | define RCJOYSTICK_EXTRACT_CMDS 10 | cp -avr ../general/package/rcjoystick/src/* $(@D)/ 11 | endef 12 | 13 | RCJOYSTICK_MAKE_OPTS = \ 14 | CC="$(TARGET_CC)" 15 | 16 | define RCJOYSTICK_BUILD_CMDS 17 | $(MAKE) $(RCJOYSTICK_MAKE_OPTS) -C $(@D) 18 | endef 19 | 20 | define RCJOYSTICK_INSTALL_TARGET_CMDS 21 | install -m 0755 -D $(@D)/rcjoystick $(TARGET_DIR)/usr/bin/rcjoystick 22 | endef 23 | 24 | $(eval $(generic-package)) 25 | -------------------------------------------------------------------------------- /rcjoystick/src/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-O1 -g -fno-omit-frame-pointer -Wall -Wextra 2 | LDFLAGS=-g 3 | #LDLIBS=-levent_core 4 | 5 | rcjoystick: -------------------------------------------------------------------------------- /rcjoystick/src/checksum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(MAVLINK_USE_CXX_NAMESPACE) 4 | namespace mavlink { 5 | #elif defined(__cplusplus) 6 | extern "C" { 7 | #endif 8 | 9 | // Visual Studio versions before 2010 don't have stdint.h, so we just error out. 10 | #if (defined _MSC_VER) && (_MSC_VER < 1600) 11 | #error "The C-MAVLink implementation requires Visual Studio 2010 or greater" 12 | #endif 13 | 14 | #include 15 | 16 | /** 17 | * 18 | * CALCULATE THE CHECKSUM 19 | * 20 | */ 21 | 22 | #define X25_INIT_CRC 0xffff 23 | #define X25_VALIDATE_CRC 0xf0b8 24 | 25 | #ifndef HAVE_CRC_ACCUMULATE 26 | /** 27 | * @brief Accumulate the CRC16_MCRF4XX checksum by adding one char at a time. 28 | * 29 | * The checksum function adds the hash of one char at a time to the 30 | * 16 bit checksum (uint16_t). 31 | * 32 | * @param data new char to hash 33 | * @param crcAccum the already accumulated checksum 34 | **/ 35 | static inline void crc_accumulate(uint8_t data, uint16_t *crcAccum) 36 | { 37 | /*Accumulate one byte of data into the CRC*/ 38 | uint8_t tmp; 39 | 40 | tmp = data ^ (uint8_t)(*crcAccum &0xff); 41 | tmp ^= (tmp<<4); 42 | *crcAccum = (*crcAccum>>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4); 43 | } 44 | #endif 45 | 46 | 47 | /** 48 | * @brief Initialize the buffer for the MCRF4XX CRC16 49 | * 50 | * @param crcAccum the 16 bit MCRF4XX CRC16 51 | */ 52 | static inline void crc_init(uint16_t* crcAccum) 53 | { 54 | *crcAccum = X25_INIT_CRC; 55 | } 56 | 57 | 58 | /** 59 | * @brief Calculates the CRC16_MCRF4XX checksum on a byte buffer 60 | * 61 | * @param pBuffer buffer containing the byte array to hash 62 | * @param length length of the byte array 63 | * @return the checksum over the buffer bytes 64 | **/ 65 | static inline uint16_t crc_calculate(const uint8_t* pBuffer, uint16_t length) 66 | { 67 | uint16_t crcTmp; 68 | crc_init(&crcTmp); 69 | while (length--) { 70 | crc_accumulate(*pBuffer++, &crcTmp); 71 | } 72 | return crcTmp; 73 | } 74 | 75 | 76 | /** 77 | * @brief Accumulate the MCRF4XX CRC16 by adding an array of bytes 78 | * 79 | * The checksum function adds the hash of one char at a time to the 80 | * 16 bit checksum (uint16_t). 81 | * 82 | * @param data new bytes to hash 83 | * @param crcAccum the already accumulated checksum 84 | **/ 85 | static inline void crc_accumulate_buffer(uint16_t *crcAccum, const char *pBuffer, uint16_t length) 86 | { 87 | const uint8_t *p = (const uint8_t *)pBuffer; 88 | while (length--) { 89 | crc_accumulate(*p++, crcAccum); 90 | } 91 | } 92 | 93 | #if defined(MAVLINK_USE_CXX_NAMESPACE) || defined(__cplusplus) 94 | } 95 | #endif 96 | -------------------------------------------------------------------------------- /rcjoystick/src/common/mavlink.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * @brief MAVLink comm protocol built from common.xml 3 | * @see http://mavlink.org 4 | */ 5 | #pragma once 6 | #ifndef MAVLINK_H 7 | #define MAVLINK_H 8 | 9 | #define MAVLINK_PRIMARY_XML_HASH 7898611588819456034 10 | 11 | #ifndef MAVLINK_STX 12 | #define MAVLINK_STX 253 13 | #endif 14 | 15 | #ifndef MAVLINK_ENDIAN 16 | #define MAVLINK_ENDIAN MAVLINK_LITTLE_ENDIAN 17 | #endif 18 | 19 | #ifndef MAVLINK_ALIGNED_FIELDS 20 | #define MAVLINK_ALIGNED_FIELDS 1 21 | #endif 22 | 23 | #ifndef MAVLINK_CRC_EXTRA 24 | #define MAVLINK_CRC_EXTRA 1 25 | #endif 26 | 27 | #ifndef MAVLINK_COMMAND_24BIT 28 | #define MAVLINK_COMMAND_24BIT 1 29 | #endif 30 | 31 | #include "version.h" 32 | #include "common.h" 33 | 34 | #endif // MAVLINK_H 35 | -------------------------------------------------------------------------------- /rcjoystick/src/common/version.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * @brief MAVLink comm protocol built from common.xml 3 | * @see http://mavlink.org 4 | */ 5 | #pragma once 6 | 7 | #ifndef MAVLINK_VERSION_H 8 | #define MAVLINK_VERSION_H 9 | 10 | #define MAVLINK_BUILD_DATE "Mon Mar 27 2023" 11 | #define MAVLINK_WIRE_PROTOCOL_VERSION "2.0" 12 | #define MAVLINK_MAX_DIALECT_PAYLOAD_SIZE 255 13 | 14 | #endif // MAVLINK_VERSION_H 15 | -------------------------------------------------------------------------------- /rcjoystick/src/mavlink_conversions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef MAVLINK_NO_CONVERSION_HELPERS 4 | 5 | /* enable math defines on Windows */ 6 | #ifdef _MSC_VER 7 | #ifndef _USE_MATH_DEFINES 8 | #define _USE_MATH_DEFINES 9 | #endif 10 | #endif 11 | #include 12 | 13 | #ifndef M_PI_2 14 | #define M_PI_2 ((float)asin(1)) 15 | #endif 16 | 17 | /** 18 | * @file mavlink_conversions.h 19 | * 20 | * These conversion functions follow the NASA rotation standards definition file 21 | * available online. 22 | * 23 | * Their intent is to lower the barrier for MAVLink adopters to use gimbal-lock free 24 | * (both rotation matrices, sometimes called DCM, and quaternions are gimbal-lock free) 25 | * rotation representations. Euler angles (roll, pitch, yaw) will be phased out of the 26 | * protocol as widely as possible. 27 | * 28 | * @author James Goppert 29 | * @author Thomas Gubler 30 | */ 31 | 32 | 33 | /** 34 | * Converts a quaternion to a rotation matrix 35 | * 36 | * @param quaternion a [w, x, y, z] ordered quaternion (null-rotation being 1 0 0 0) 37 | * @param dcm a 3x3 rotation matrix 38 | */ 39 | MAVLINK_HELPER void mavlink_quaternion_to_dcm(const float quaternion[4], float dcm[3][3]) 40 | { 41 | double a = (double)quaternion[0]; 42 | double b = (double)quaternion[1]; 43 | double c = (double)quaternion[2]; 44 | double d = (double)quaternion[3]; 45 | double aSq = a * a; 46 | double bSq = b * b; 47 | double cSq = c * c; 48 | double dSq = d * d; 49 | dcm[0][0] = aSq + bSq - cSq - dSq; 50 | dcm[0][1] = 2 * (b * c - a * d); 51 | dcm[0][2] = 2 * (a * c + b * d); 52 | dcm[1][0] = 2 * (b * c + a * d); 53 | dcm[1][1] = aSq - bSq + cSq - dSq; 54 | dcm[1][2] = 2 * (c * d - a * b); 55 | dcm[2][0] = 2 * (b * d - a * c); 56 | dcm[2][1] = 2 * (a * b + c * d); 57 | dcm[2][2] = aSq - bSq - cSq + dSq; 58 | } 59 | 60 | 61 | /** 62 | * Converts a rotation matrix to euler angles 63 | * 64 | * @param dcm a 3x3 rotation matrix 65 | * @param roll the roll angle in radians 66 | * @param pitch the pitch angle in radians 67 | * @param yaw the yaw angle in radians 68 | */ 69 | MAVLINK_HELPER void mavlink_dcm_to_euler(const float dcm[3][3], float* roll, float* pitch, float* yaw) 70 | { 71 | float phi, theta, psi; 72 | theta = asinf(-dcm[2][0]); 73 | 74 | if (fabsf(theta - (float)M_PI_2) < 1.0e-3f) { 75 | phi = 0.0f; 76 | psi = (atan2f(dcm[1][2] - dcm[0][1], 77 | dcm[0][2] + dcm[1][1]) + phi); 78 | 79 | } else if (fabsf(theta + (float)M_PI_2) < 1.0e-3f) { 80 | phi = 0.0f; 81 | psi = atan2f(dcm[1][2] - dcm[0][1], 82 | dcm[0][2] + dcm[1][1] - phi); 83 | 84 | } else { 85 | phi = atan2f(dcm[2][1], dcm[2][2]); 86 | psi = atan2f(dcm[1][0], dcm[0][0]); 87 | } 88 | 89 | *roll = phi; 90 | *pitch = theta; 91 | *yaw = psi; 92 | } 93 | 94 | 95 | /** 96 | * Converts a quaternion to euler angles 97 | * 98 | * @param quaternion a [w, x, y, z] ordered quaternion (null-rotation being 1 0 0 0) 99 | * @param roll the roll angle in radians 100 | * @param pitch the pitch angle in radians 101 | * @param yaw the yaw angle in radians 102 | */ 103 | MAVLINK_HELPER void mavlink_quaternion_to_euler(const float quaternion[4], float* roll, float* pitch, float* yaw) 104 | { 105 | float dcm[3][3]; 106 | mavlink_quaternion_to_dcm(quaternion, dcm); 107 | mavlink_dcm_to_euler((const float(*)[3])dcm, roll, pitch, yaw); 108 | } 109 | 110 | 111 | /** 112 | * Converts euler angles to a quaternion 113 | * 114 | * @param roll the roll angle in radians 115 | * @param pitch the pitch angle in radians 116 | * @param yaw the yaw angle in radians 117 | * @param quaternion a [w, x, y, z] ordered quaternion (null-rotation being 1 0 0 0) 118 | */ 119 | MAVLINK_HELPER void mavlink_euler_to_quaternion(float roll, float pitch, float yaw, float quaternion[4]) 120 | { 121 | float cosPhi_2 = cosf(roll / 2); 122 | float sinPhi_2 = sinf(roll / 2); 123 | float cosTheta_2 = cosf(pitch / 2); 124 | float sinTheta_2 = sinf(pitch / 2); 125 | float cosPsi_2 = cosf(yaw / 2); 126 | float sinPsi_2 = sinf(yaw / 2); 127 | quaternion[0] = (cosPhi_2 * cosTheta_2 * cosPsi_2 + 128 | sinPhi_2 * sinTheta_2 * sinPsi_2); 129 | quaternion[1] = (sinPhi_2 * cosTheta_2 * cosPsi_2 - 130 | cosPhi_2 * sinTheta_2 * sinPsi_2); 131 | quaternion[2] = (cosPhi_2 * sinTheta_2 * cosPsi_2 + 132 | sinPhi_2 * cosTheta_2 * sinPsi_2); 133 | quaternion[3] = (cosPhi_2 * cosTheta_2 * sinPsi_2 - 134 | sinPhi_2 * sinTheta_2 * cosPsi_2); 135 | } 136 | 137 | 138 | /** 139 | * Converts a rotation matrix to a quaternion 140 | * Reference: 141 | * - Shoemake, Quaternions, 142 | * http://www.cs.ucr.edu/~vbz/resources/quatut.pdf 143 | * 144 | * @param dcm a 3x3 rotation matrix 145 | * @param quaternion a [w, x, y, z] ordered quaternion (null-rotation being 1 0 0 0) 146 | */ 147 | MAVLINK_HELPER void mavlink_dcm_to_quaternion(const float dcm[3][3], float quaternion[4]) 148 | { 149 | float tr = dcm[0][0] + dcm[1][1] + dcm[2][2]; 150 | if (tr > 0.0f) { 151 | float s = sqrtf(tr + 1.0f); 152 | quaternion[0] = s * 0.5f; 153 | s = 0.5f / s; 154 | quaternion[1] = (dcm[2][1] - dcm[1][2]) * s; 155 | quaternion[2] = (dcm[0][2] - dcm[2][0]) * s; 156 | quaternion[3] = (dcm[1][0] - dcm[0][1]) * s; 157 | } else { 158 | /* Find maximum diagonal element in dcm 159 | * store index in dcm_i */ 160 | int dcm_i = 0; 161 | int i; 162 | for (i = 1; i < 3; i++) { 163 | if (dcm[i][i] > dcm[dcm_i][dcm_i]) { 164 | dcm_i = i; 165 | } 166 | } 167 | 168 | int dcm_j = (dcm_i + 1) % 3; 169 | int dcm_k = (dcm_i + 2) % 3; 170 | 171 | float s = sqrtf((dcm[dcm_i][dcm_i] - dcm[dcm_j][dcm_j] - 172 | dcm[dcm_k][dcm_k]) + 1.0f); 173 | quaternion[dcm_i + 1] = s * 0.5f; 174 | s = 0.5f / s; 175 | quaternion[dcm_j + 1] = (dcm[dcm_i][dcm_j] + dcm[dcm_j][dcm_i]) * s; 176 | quaternion[dcm_k + 1] = (dcm[dcm_k][dcm_i] + dcm[dcm_i][dcm_k]) * s; 177 | quaternion[0] = (dcm[dcm_k][dcm_j] - dcm[dcm_j][dcm_k]) * s; 178 | } 179 | } 180 | 181 | 182 | /** 183 | * Converts euler angles to a rotation matrix 184 | * 185 | * @param roll the roll angle in radians 186 | * @param pitch the pitch angle in radians 187 | * @param yaw the yaw angle in radians 188 | * @param dcm a 3x3 rotation matrix 189 | */ 190 | MAVLINK_HELPER void mavlink_euler_to_dcm(float roll, float pitch, float yaw, float dcm[3][3]) 191 | { 192 | float cosPhi = cosf(roll); 193 | float sinPhi = sinf(roll); 194 | float cosThe = cosf(pitch); 195 | float sinThe = sinf(pitch); 196 | float cosPsi = cosf(yaw); 197 | float sinPsi = sinf(yaw); 198 | 199 | dcm[0][0] = cosThe * cosPsi; 200 | dcm[0][1] = -cosPhi * sinPsi + sinPhi * sinThe * cosPsi; 201 | dcm[0][2] = sinPhi * sinPsi + cosPhi * sinThe * cosPsi; 202 | 203 | dcm[1][0] = cosThe * sinPsi; 204 | dcm[1][1] = cosPhi * cosPsi + sinPhi * sinThe * sinPsi; 205 | dcm[1][2] = -sinPhi * cosPsi + cosPhi * sinThe * sinPsi; 206 | 207 | dcm[2][0] = -sinThe; 208 | dcm[2][1] = sinPhi * cosThe; 209 | dcm[2][2] = cosPhi * cosThe; 210 | } 211 | 212 | #endif // MAVLINK_NO_CONVERSION_HELPERS 213 | -------------------------------------------------------------------------------- /rcjoystick/src/mavlink_get_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef MAVLINK_USE_MESSAGE_INFO 4 | #define MAVLINK_HAVE_GET_MESSAGE_INFO 5 | 6 | /* 7 | return the message_info struct for a message 8 | */ 9 | MAVLINK_HELPER const mavlink_message_info_t *mavlink_get_message_info_by_id(uint32_t msgid) 10 | { 11 | static const mavlink_message_info_t mavlink_message_info[] = MAVLINK_MESSAGE_INFO; 12 | /* 13 | use a bisection search to find the right entry. A perfect hash may be better 14 | Note that this assumes the table is sorted with primary key msgid 15 | */ 16 | const uint32_t count = sizeof(mavlink_message_info)/sizeof(mavlink_message_info[0]); 17 | if (count == 0) { 18 | return NULL; 19 | } 20 | uint32_t low=0, high=count-1; 21 | while (low < high) { 22 | uint32_t mid = (low+high)/2; 23 | if (msgid < mavlink_message_info[mid].msgid) { 24 | high = mid; 25 | continue; 26 | } 27 | if (msgid > mavlink_message_info[mid].msgid) { 28 | low = mid+1; 29 | continue; 30 | } 31 | return &mavlink_message_info[mid]; 32 | } 33 | if (mavlink_message_info[low].msgid == msgid) { 34 | return &mavlink_message_info[low]; 35 | } 36 | return NULL; 37 | } 38 | 39 | /* 40 | return the message_info struct for a message 41 | */ 42 | MAVLINK_HELPER const mavlink_message_info_t *mavlink_get_message_info(const mavlink_message_t *msg) 43 | { 44 | return mavlink_get_message_info_by_id(msg->msgid); 45 | } 46 | 47 | /* 48 | return the message_info struct for a message 49 | */ 50 | MAVLINK_HELPER const mavlink_message_info_t *mavlink_get_message_info_by_name(const char *name) 51 | { 52 | static const struct { const char *name; uint32_t msgid; } mavlink_message_names[] = MAVLINK_MESSAGE_NAMES; 53 | /* 54 | use a bisection search to find the right entry. A perfect hash may be better 55 | Note that this assumes the table is sorted with primary key name 56 | */ 57 | const uint32_t count = sizeof(mavlink_message_names)/sizeof(mavlink_message_names[0]); 58 | if (count == 0) { 59 | return NULL; 60 | } 61 | uint32_t low=0, high=count-1; 62 | while (low < high) { 63 | uint32_t mid = (low+high)/2; 64 | int cmp = strcmp(mavlink_message_names[mid].name, name); 65 | if (cmp > 0) { 66 | high = mid; 67 | continue; 68 | } 69 | if (cmp < 0) { 70 | low = mid+1; 71 | continue; 72 | } 73 | low = mid; 74 | break; 75 | } 76 | if (strcmp(mavlink_message_names[low].name, name) == 0) { 77 | return mavlink_get_message_info_by_id(mavlink_message_names[low].msgid); 78 | } 79 | return NULL; 80 | } 81 | #endif // MAVLINK_USE_MESSAGE_INFO 82 | 83 | 84 | -------------------------------------------------------------------------------- /rcjoystick/src/mavlink_sha256.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | sha-256 implementation for MAVLink based on Heimdal sources, with 5 | modifications to suit mavlink headers 6 | */ 7 | /* 8 | * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan 9 | * (Royal Institute of Technology, Stockholm, Sweden). 10 | * All rights reserved. 11 | * 12 | * Redistribution and use in source and binary forms, with or without 13 | * modification, are permitted provided that the following conditions 14 | * are met: 15 | * 16 | * 1. Redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer. 18 | * 19 | * 2. Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in the 21 | * documentation and/or other materials provided with the distribution. 22 | * 23 | * 3. Neither the name of the Institute nor the names of its contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 | * SUCH DAMAGE. 38 | */ 39 | 40 | /* 41 | allow implementation to provide their own sha256 with the same API 42 | */ 43 | #ifndef HAVE_MAVLINK_SHA256 44 | 45 | #ifdef MAVLINK_USE_CXX_NAMESPACE 46 | namespace mavlink { 47 | #endif 48 | 49 | #ifndef MAVLINK_HELPER 50 | #define MAVLINK_HELPER 51 | #endif 52 | 53 | typedef struct { 54 | uint32_t sz[2]; 55 | uint32_t counter[8]; 56 | union { 57 | unsigned char save_bytes[64]; 58 | uint32_t save_u32[16]; 59 | } u; 60 | } mavlink_sha256_ctx; 61 | 62 | #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 63 | #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 64 | 65 | #define ROTR(x,n) (((x)>>(n)) | ((x) << (32 - (n)))) 66 | 67 | #define Sigma0(x) (ROTR(x,2) ^ ROTR(x,13) ^ ROTR(x,22)) 68 | #define Sigma1(x) (ROTR(x,6) ^ ROTR(x,11) ^ ROTR(x,25)) 69 | #define sigma0(x) (ROTR(x,7) ^ ROTR(x,18) ^ ((x)>>3)) 70 | #define sigma1(x) (ROTR(x,17) ^ ROTR(x,19) ^ ((x)>>10)) 71 | 72 | static const uint32_t mavlink_sha256_constant_256[64] = { 73 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 74 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 75 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 76 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 77 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 78 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 79 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 80 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 81 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 82 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 83 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 84 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 85 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 86 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 87 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 88 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 89 | }; 90 | 91 | MAVLINK_HELPER void mavlink_sha256_init(mavlink_sha256_ctx *m) 92 | { 93 | m->sz[0] = 0; 94 | m->sz[1] = 0; 95 | m->counter[0] = 0x6a09e667; 96 | m->counter[1] = 0xbb67ae85; 97 | m->counter[2] = 0x3c6ef372; 98 | m->counter[3] = 0xa54ff53a; 99 | m->counter[4] = 0x510e527f; 100 | m->counter[5] = 0x9b05688c; 101 | m->counter[6] = 0x1f83d9ab; 102 | m->counter[7] = 0x5be0cd19; 103 | } 104 | 105 | static inline void mavlink_sha256_calc(mavlink_sha256_ctx *m, uint32_t *in) 106 | { 107 | uint32_t AA, BB, CC, DD, EE, FF, GG, HH; 108 | uint32_t data[64]; 109 | int i; 110 | 111 | AA = m->counter[0]; 112 | BB = m->counter[1]; 113 | CC = m->counter[2]; 114 | DD = m->counter[3]; 115 | EE = m->counter[4]; 116 | FF = m->counter[5]; 117 | GG = m->counter[6]; 118 | HH = m->counter[7]; 119 | 120 | for (i = 0; i < 16; ++i) 121 | data[i] = in[i]; 122 | for (i = 16; i < 64; ++i) 123 | data[i] = sigma1(data[i-2]) + data[i-7] + 124 | sigma0(data[i-15]) + data[i - 16]; 125 | 126 | for (i = 0; i < 64; i++) { 127 | uint32_t T1, T2; 128 | 129 | T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + mavlink_sha256_constant_256[i] + data[i]; 130 | T2 = Sigma0(AA) + Maj(AA,BB,CC); 131 | 132 | HH = GG; 133 | GG = FF; 134 | FF = EE; 135 | EE = DD + T1; 136 | DD = CC; 137 | CC = BB; 138 | BB = AA; 139 | AA = T1 + T2; 140 | } 141 | 142 | m->counter[0] += AA; 143 | m->counter[1] += BB; 144 | m->counter[2] += CC; 145 | m->counter[3] += DD; 146 | m->counter[4] += EE; 147 | m->counter[5] += FF; 148 | m->counter[6] += GG; 149 | m->counter[7] += HH; 150 | } 151 | 152 | MAVLINK_HELPER void mavlink_sha256_update(mavlink_sha256_ctx *m, const void *v, uint32_t len) 153 | { 154 | const unsigned char *p = (const unsigned char *)v; 155 | uint32_t old_sz = m->sz[0]; 156 | uint32_t offset; 157 | 158 | m->sz[0] += len * 8; 159 | if (m->sz[0] < old_sz) 160 | ++m->sz[1]; 161 | offset = (old_sz / 8) % 64; 162 | while(len > 0){ 163 | uint32_t l = 64 - offset; 164 | if (len < l) { 165 | l = len; 166 | } 167 | memcpy(m->u.save_bytes + offset, p, l); 168 | offset += l; 169 | p += l; 170 | len -= l; 171 | if(offset == 64){ 172 | int i; 173 | uint32_t current[16]; 174 | const uint32_t *u = m->u.save_u32; 175 | for (i = 0; i < 16; i++){ 176 | const uint8_t *p1 = (const uint8_t *)&u[i]; 177 | uint8_t *p2 = (uint8_t *)¤t[i]; 178 | p2[0] = p1[3]; 179 | p2[1] = p1[2]; 180 | p2[2] = p1[1]; 181 | p2[3] = p1[0]; 182 | } 183 | mavlink_sha256_calc(m, current); 184 | offset = 0; 185 | } 186 | } 187 | } 188 | 189 | /* 190 | get first 48 bits of final sha256 hash 191 | */ 192 | MAVLINK_HELPER void mavlink_sha256_final_48(mavlink_sha256_ctx *m, uint8_t result[6]) 193 | { 194 | unsigned char zeros[72]; 195 | unsigned offset = (m->sz[0] / 8) % 64; 196 | unsigned int dstart = (120 - offset - 1) % 64 + 1; 197 | uint8_t *p = (uint8_t *)&m->counter[0]; 198 | 199 | *zeros = 0x80; 200 | memset (zeros + 1, 0, sizeof(zeros) - 1); 201 | zeros[dstart+7] = (m->sz[0] >> 0) & 0xff; 202 | zeros[dstart+6] = (m->sz[0] >> 8) & 0xff; 203 | zeros[dstart+5] = (m->sz[0] >> 16) & 0xff; 204 | zeros[dstart+4] = (m->sz[0] >> 24) & 0xff; 205 | zeros[dstart+3] = (m->sz[1] >> 0) & 0xff; 206 | zeros[dstart+2] = (m->sz[1] >> 8) & 0xff; 207 | zeros[dstart+1] = (m->sz[1] >> 16) & 0xff; 208 | zeros[dstart+0] = (m->sz[1] >> 24) & 0xff; 209 | 210 | mavlink_sha256_update(m, zeros, dstart + 8); 211 | 212 | // this ordering makes the result consistent with taking the first 213 | // 6 bytes of more conventional sha256 functions. It assumes 214 | // little-endian ordering of m->counter 215 | result[0] = p[3]; 216 | result[1] = p[2]; 217 | result[2] = p[1]; 218 | result[3] = p[0]; 219 | result[4] = p[7]; 220 | result[5] = p[6]; 221 | } 222 | 223 | // prevent conflicts with users of the header 224 | #undef Ch 225 | #undef ROTR 226 | #undef Sigma0 227 | #undef Sigma1 228 | #undef sigma0 229 | #undef sigma1 230 | 231 | #ifdef MAVLINK_USE_CXX_NAMESPACE 232 | } // namespace mavlink 233 | #endif 234 | 235 | #endif // HAVE_MAVLINK_SHA256 236 | -------------------------------------------------------------------------------- /rcjoystick/src/minimal/mavlink.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * @brief MAVLink comm protocol built from minimal.xml 3 | * @see http://mavlink.org 4 | */ 5 | #pragma once 6 | #ifndef MAVLINK_H 7 | #define MAVLINK_H 8 | 9 | #define MAVLINK_PRIMARY_XML_HASH 3620580151627289427 10 | 11 | #ifndef MAVLINK_STX 12 | #define MAVLINK_STX 253 13 | #endif 14 | 15 | #ifndef MAVLINK_ENDIAN 16 | #define MAVLINK_ENDIAN MAVLINK_LITTLE_ENDIAN 17 | #endif 18 | 19 | #ifndef MAVLINK_ALIGNED_FIELDS 20 | #define MAVLINK_ALIGNED_FIELDS 1 21 | #endif 22 | 23 | #ifndef MAVLINK_CRC_EXTRA 24 | #define MAVLINK_CRC_EXTRA 1 25 | #endif 26 | 27 | #ifndef MAVLINK_COMMAND_24BIT 28 | #define MAVLINK_COMMAND_24BIT 1 29 | #endif 30 | 31 | #include "version.h" 32 | #include "minimal.h" 33 | 34 | #endif // MAVLINK_H 35 | -------------------------------------------------------------------------------- /rcjoystick/src/minimal/testsuite.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * @brief MAVLink comm protocol testsuite generated from minimal.xml 3 | * @see https://mavlink.io/en/ 4 | */ 5 | #pragma once 6 | #ifndef MINIMAL_TESTSUITE_H 7 | #define MINIMAL_TESTSUITE_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #ifndef MAVLINK_TEST_ALL 14 | #define MAVLINK_TEST_ALL 15 | 16 | static void mavlink_test_minimal(uint8_t, uint8_t, mavlink_message_t *last_msg); 17 | 18 | static void mavlink_test_all(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) 19 | { 20 | 21 | mavlink_test_minimal(system_id, component_id, last_msg); 22 | } 23 | #endif 24 | 25 | 26 | 27 | 28 | static void mavlink_test_heartbeat(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) 29 | { 30 | #ifdef MAVLINK_STATUS_FLAG_OUT_MAVLINK1 31 | mavlink_status_t *status = mavlink_get_channel_status(MAVLINK_COMM_0); 32 | if ((status->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1) && MAVLINK_MSG_ID_HEARTBEAT >= 256) { 33 | return; 34 | } 35 | #endif 36 | mavlink_message_t msg; 37 | uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; 38 | uint16_t i; 39 | mavlink_heartbeat_t packet_in = { 40 | 963497464,17,84,151,218,3 41 | }; 42 | mavlink_heartbeat_t packet1, packet2; 43 | memset(&packet1, 0, sizeof(packet1)); 44 | packet1.custom_mode = packet_in.custom_mode; 45 | packet1.type = packet_in.type; 46 | packet1.autopilot = packet_in.autopilot; 47 | packet1.base_mode = packet_in.base_mode; 48 | packet1.system_status = packet_in.system_status; 49 | packet1.mavlink_version = packet_in.mavlink_version; 50 | 51 | 52 | #ifdef MAVLINK_STATUS_FLAG_OUT_MAVLINK1 53 | if (status->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1) { 54 | // cope with extensions 55 | memset(MAVLINK_MSG_ID_HEARTBEAT_MIN_LEN + (char *)&packet1, 0, sizeof(packet1)-MAVLINK_MSG_ID_HEARTBEAT_MIN_LEN); 56 | } 57 | #endif 58 | memset(&packet2, 0, sizeof(packet2)); 59 | mavlink_msg_heartbeat_encode(system_id, component_id, &msg, &packet1); 60 | mavlink_msg_heartbeat_decode(&msg, &packet2); 61 | MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); 62 | 63 | memset(&packet2, 0, sizeof(packet2)); 64 | mavlink_msg_heartbeat_pack(system_id, component_id, &msg , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status ); 65 | mavlink_msg_heartbeat_decode(&msg, &packet2); 66 | MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); 67 | 68 | memset(&packet2, 0, sizeof(packet2)); 69 | mavlink_msg_heartbeat_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status ); 70 | mavlink_msg_heartbeat_decode(&msg, &packet2); 71 | MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); 72 | 73 | memset(&packet2, 0, sizeof(packet2)); 74 | mavlink_msg_to_send_buffer(buffer, &msg); 75 | for (i=0; iflags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1) && MAVLINK_MSG_ID_PROTOCOL_VERSION >= 256) { 97 | return; 98 | } 99 | #endif 100 | mavlink_message_t msg; 101 | uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; 102 | uint16_t i; 103 | mavlink_protocol_version_t packet_in = { 104 | 17235,17339,17443,{ 151, 152, 153, 154, 155, 156, 157, 158 },{ 175, 176, 177, 178, 179, 180, 181, 182 } 105 | }; 106 | mavlink_protocol_version_t packet1, packet2; 107 | memset(&packet1, 0, sizeof(packet1)); 108 | packet1.version = packet_in.version; 109 | packet1.min_version = packet_in.min_version; 110 | packet1.max_version = packet_in.max_version; 111 | 112 | mav_array_memcpy(packet1.spec_version_hash, packet_in.spec_version_hash, sizeof(uint8_t)*8); 113 | mav_array_memcpy(packet1.library_version_hash, packet_in.library_version_hash, sizeof(uint8_t)*8); 114 | 115 | #ifdef MAVLINK_STATUS_FLAG_OUT_MAVLINK1 116 | if (status->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1) { 117 | // cope with extensions 118 | memset(MAVLINK_MSG_ID_PROTOCOL_VERSION_MIN_LEN + (char *)&packet1, 0, sizeof(packet1)-MAVLINK_MSG_ID_PROTOCOL_VERSION_MIN_LEN); 119 | } 120 | #endif 121 | memset(&packet2, 0, sizeof(packet2)); 122 | mavlink_msg_protocol_version_encode(system_id, component_id, &msg, &packet1); 123 | mavlink_msg_protocol_version_decode(&msg, &packet2); 124 | MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); 125 | 126 | memset(&packet2, 0, sizeof(packet2)); 127 | mavlink_msg_protocol_version_pack(system_id, component_id, &msg , packet1.version , packet1.min_version , packet1.max_version , packet1.spec_version_hash , packet1.library_version_hash ); 128 | mavlink_msg_protocol_version_decode(&msg, &packet2); 129 | MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); 130 | 131 | memset(&packet2, 0, sizeof(packet2)); 132 | mavlink_msg_protocol_version_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.version , packet1.min_version , packet1.max_version , packet1.spec_version_hash , packet1.library_version_hash ); 133 | mavlink_msg_protocol_version_decode(&msg, &packet2); 134 | MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); 135 | 136 | memset(&packet2, 0, sizeof(packet2)); 137 | mavlink_msg_to_send_buffer(buffer, &msg); 138 | for (i=0; i 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/ArcadeStickExample/ArcadeStickExample.ino: -------------------------------------------------------------------------------- 1 | // Simple arcade stick example that demonstrates how to read twelve 2 | // Arduino Pro Micro digital pins and map them to the 3 | // Arduino Joystick library. 4 | // 5 | 6 | // The digital pins 2 - 20 are grounded when they are pressed. 7 | // Pin 10, A10, Red = UP 8 | // Pin 15, D15, Yellow = RIGHT 9 | // Pin 16, D16, Orange = DOWN 10 | // Pin 14, D14, Green = LEFT 11 | 12 | // Pin 9, A9 = Button 1 13 | // Pin 8, A8 = Button 2 14 | // Pin 7, D7 = Button 3 15 | // Pin 3, D3 = Button 4 16 | // Pin 2, D2 = Button 5 17 | // Pin 4, A6 = Button 6 18 | 19 | // Pin 20, A2 = Select Button 1 20 | // Pin 19, A1 = Start Button 2 21 | 22 | // Pin 5, D5 = Other Button 23 | // Pin 6, A7 = Other Button 24 | // Pin 18, A0 = Other Button 25 | // Pin 21, A3 = Other Button 26 | 27 | // NOTE: This sketch file is for use with Arduino Pro Micro only. 28 | // 29 | // Original gamepad example by Matthew Heironimus 30 | // 2016-11-24 31 | // Adapted for arcade machine setup by Ben Parmeter 32 | // 2019-05-20 33 | //-------------------------------------------------------------------- 34 | 35 | #include 36 | 37 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 38 | 8, 0, // Button Count, Hat Switch Count 39 | true, true, false, // X and Y, but no Z Axis 40 | false, false, false, // No Rx, Ry, or Rz 41 | false, false, // No rudder or throttle 42 | false, false, false); // No accelerator, brake, or steering 43 | 44 | void setup() { 45 | // Initialize Button Pins 46 | pinMode(2, INPUT_PULLUP); 47 | pinMode(3, INPUT_PULLUP); 48 | pinMode(4, INPUT_PULLUP); 49 | pinMode(5, INPUT_PULLUP); 50 | pinMode(6, INPUT_PULLUP); 51 | pinMode(7, INPUT_PULLUP); 52 | pinMode(8, INPUT_PULLUP); 53 | pinMode(9, INPUT_PULLUP); 54 | pinMode(10, INPUT_PULLUP); 55 | pinMode(14, INPUT_PULLUP); 56 | pinMode(15, INPUT_PULLUP); 57 | pinMode(16, INPUT_PULLUP); 58 | pinMode(18, INPUT_PULLUP); 59 | pinMode(19, INPUT_PULLUP); 60 | pinMode(20, INPUT_PULLUP); 61 | pinMode(21, INPUT_PULLUP); 62 | 63 | // Initialize Joystick Library 64 | Joystick.begin(); 65 | Joystick.setXAxisRange(-1, 1); 66 | Joystick.setYAxisRange(-1, 1); 67 | } 68 | 69 | // Last state of the buttons 70 | int lastButtonState[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 71 | int buttonMap[16] = {10,15,16,14,9,8,7,3,2,4,20,19,5,6,18,21}; 72 | 73 | // ButtonMap = 0, Pin 10 = UP 74 | // ButtonMap = 1, Pin 15 = RIGHT 75 | // ButtonMap = 2, Pin 16 = DOWN 76 | // ButtonMap = 3, Pin 14 = LEFT 77 | 78 | // ButtonMap = 4, Pin 9 = Button 1 79 | // ButtonMap = 5, Pin 8 = Button 2 80 | // ButtonMap = 6, Pin 7 = Button 3 81 | // ButtonMap = 7, Pin 3 = Button 4 82 | // ButtonMap = 8, Pin 2 = Button 5 83 | // ButtonMap = 9, Pin 4 = Button 6 84 | 85 | // ButtonMap = 10, Pin 20 = Select Button 1 86 | // ButtonMap = 11, Pin 19 = Start Button 2 87 | 88 | // ButtonMap = 12, Pin 5 = Other Button 89 | // ButtonMap = 13, Pin 6 = Other Button 90 | // ButtonMap = 14, Pin 18 = Other Button 91 | // ButtonMap = 15, Pin 21 = Other Button 92 | 93 | 94 | void loop() { 95 | 96 | // Read pin values 97 | for (int index = 0; index < 16; index++) 98 | { 99 | int currentButtonState = !digitalRead(buttonMap[index]); 100 | if (currentButtonState != lastButtonState[index]) 101 | { 102 | switch (index) { 103 | case 0: // UP 104 | if (currentButtonState == 1) { 105 | Joystick.setYAxis(-1); 106 | } else { 107 | Joystick.setYAxis(0); 108 | } 109 | break; 110 | case 1: // RIGHT 111 | if (currentButtonState == 1) { 112 | Joystick.setXAxis(1); 113 | } else { 114 | Joystick.setXAxis(0); 115 | } 116 | break; 117 | case 2: // DOWN 118 | if (currentButtonState == 1) { 119 | Joystick.setYAxis(1); 120 | } else { 121 | Joystick.setYAxis(0); 122 | } 123 | break; 124 | case 3: // LEFT 125 | if (currentButtonState == 1) { 126 | Joystick.setXAxis(-1); 127 | } else { 128 | Joystick.setXAxis(0); 129 | } 130 | break; 131 | case 4: // Black Button 1 132 | Joystick.setButton(0, currentButtonState); 133 | break; 134 | case 5: // Black Button 2 135 | Joystick.setButton(1, currentButtonState); 136 | break; 137 | case 6: // Black Button 3 138 | Joystick.setButton(2, currentButtonState); 139 | break; 140 | case 7: // Black Button 4 141 | Joystick.setButton(3, currentButtonState); 142 | break; 143 | case 8: // Black Button 5 144 | Joystick.setButton(4, currentButtonState); 145 | break; 146 | case 9: // Black Button 6 147 | Joystick.setButton(5, currentButtonState); 148 | break; 149 | case 10: // Select Button 150 | Joystick.setButton(6, currentButtonState); 151 | break; 152 | case 11: // Start Button 153 | Joystick.setButton(7, currentButtonState); 154 | break; 155 | case 12: // Other Button 1 156 | Joystick.setButton(8, currentButtonState); 157 | break; 158 | case 13: // Other Button 2 159 | Joystick.setButton(9, currentButtonState); 160 | break; 161 | case 14: // Other Button 3 162 | Joystick.setButton(10, currentButtonState); 163 | break; 164 | case 15: // Other Button 4 165 | Joystick.setButton(11, currentButtonState); 166 | break; 167 | } 168 | lastButtonState[index] = currentButtonState; 169 | } 170 | } 171 | 172 | delay(10); 173 | } 174 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/DrivingControllerTest/DrivingControllerTest.ino: -------------------------------------------------------------------------------- 1 | // Program used to test the driving simulator functions on 2 | // the USB Joystick object on the Arduino Leonardo or 3 | // Arduino Micro. 4 | // 5 | // Matthew Heironimus 6 | // 2016-05-29 Original version. 7 | //------------------------------------------------------------ 8 | 9 | #include "Joystick.h" 10 | 11 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 12 | JOYSTICK_TYPE_MULTI_AXIS, 4, 0, 13 | false, false, false, false, false, false, 14 | false, false, true, true, true); 15 | 16 | // Set to true to test "Auto Send" mode or false to test "Manual Send" mode. 17 | //const bool testAutoSendMode = true; 18 | const bool testAutoSendMode = false; 19 | 20 | const unsigned long gcCycleDelta = 1000; 21 | const unsigned long gcButtonDelta = 500; 22 | const unsigned long gcAnalogDelta = 25; 23 | unsigned long gNextTime = 0; 24 | unsigned int gCurrentStep = 0; 25 | 26 | void testSingleButtonPush(unsigned int button) 27 | { 28 | if (button > 0) 29 | { 30 | Joystick.releaseButton(button - 1); 31 | } 32 | if (button < 4) 33 | { 34 | Joystick.pressButton(button); 35 | } 36 | } 37 | 38 | void testMultiButtonPush(unsigned int currentStep) 39 | { 40 | for (int button = 0; button < 4; button++) 41 | { 42 | if ((currentStep == 0) || (currentStep == 2)) 43 | { 44 | if ((button % 2) == 0) 45 | { 46 | Joystick.pressButton(button); 47 | } else if (currentStep != 2) 48 | { 49 | Joystick.releaseButton(button); 50 | } 51 | } // if ((currentStep == 0) || (currentStep == 2)) 52 | if ((currentStep == 1) || (currentStep == 2)) 53 | { 54 | if ((button % 2) != 0) 55 | { 56 | Joystick.pressButton(button); 57 | } else if (currentStep != 2) 58 | { 59 | Joystick.releaseButton(button); 60 | } 61 | } // if ((currentStep == 1) || (currentStep == 2)) 62 | if (currentStep == 3) 63 | { 64 | Joystick.releaseButton(button); 65 | } // if (currentStep == 3) 66 | } // for (int button = 0; button < 32; button++) 67 | } 68 | 69 | void testAcceleratorBrake(int value) 70 | { 71 | Joystick.setAccelerator(value); 72 | Joystick.setBrake(260 - value); 73 | } 74 | 75 | void testSteering(int value) 76 | { 77 | if (value < 300) { 78 | Joystick.setSteering(value); 79 | } else { 80 | Joystick.setSteering(600 - value); 81 | } 82 | } 83 | 84 | void setup() { 85 | 86 | Joystick.setAcceleratorRange(0, 260); 87 | Joystick.setBrakeRange(0, 260); 88 | Joystick.setSteeringRange(0, 300); 89 | 90 | if (testAutoSendMode) 91 | { 92 | Joystick.begin(); 93 | } 94 | else 95 | { 96 | Joystick.begin(false); 97 | } 98 | 99 | pinMode(A0, INPUT_PULLUP); 100 | pinMode(LED_BUILTIN, OUTPUT); 101 | } 102 | 103 | void loop() { 104 | 105 | // System Disabled 106 | if (digitalRead(A0) != 0) 107 | { 108 | // Turn indicator light off. 109 | digitalWrite(LED_BUILTIN, 0); 110 | return; 111 | } 112 | 113 | // Turn indicator light on. 114 | digitalWrite(LED_BUILTIN, 1); 115 | 116 | if (millis() >= gNextTime) 117 | { 118 | 119 | if (gCurrentStep < 4) 120 | { 121 | gNextTime = millis() + gcButtonDelta; 122 | testSingleButtonPush(gCurrentStep); 123 | } 124 | else if (gCurrentStep < 9) 125 | { 126 | gNextTime = millis() + gcButtonDelta; 127 | testMultiButtonPush(gCurrentStep - 5); 128 | } 129 | else if (gCurrentStep < (9 + 260)) 130 | { 131 | gNextTime = millis() + gcAnalogDelta; 132 | testAcceleratorBrake(gCurrentStep - 9); 133 | } 134 | else if (gCurrentStep < (9 + 260 + 600)) 135 | { 136 | gNextTime = millis() + gcAnalogDelta; 137 | testSteering(gCurrentStep - (9 + 260)); 138 | } 139 | 140 | if (testAutoSendMode == false) 141 | { 142 | Joystick.sendState(); 143 | } 144 | 145 | gCurrentStep++; 146 | if (gCurrentStep >= (9 + 260 + 600)) 147 | { 148 | gNextTime = millis() + gcCycleDelta; 149 | gCurrentStep = 0; 150 | } 151 | } 152 | } 153 | 154 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/FlightControllerTest/FlightControllerTest.ino: -------------------------------------------------------------------------------- 1 | // Program used to test the USB Joystick library when used as 2 | // a Flight Controller on the Arduino Leonardo or Arduino 3 | // Micro. 4 | // 5 | // Matthew Heironimus 6 | // 2016-05-29 - Original Version 7 | //------------------------------------------------------------ 8 | 9 | #include "Joystick.h" 10 | 11 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 12 | JOYSTICK_TYPE_MULTI_AXIS, 32, 0, 13 | true, true, false, false, false, false, 14 | true, true, false, false, false); 15 | 16 | // Set to true to test "Auto Send" mode or false to test "Manual Send" mode. 17 | //const bool testAutoSendMode = true; 18 | const bool testAutoSendMode = false; 19 | 20 | const unsigned long gcCycleDelta = 1000; 21 | const unsigned long gcAnalogDelta = 25; 22 | const unsigned long gcButtonDelta = 500; 23 | unsigned long gNextTime = 0; 24 | unsigned int gCurrentStep = 0; 25 | 26 | void testSingleButtonPush(unsigned int button) 27 | { 28 | if (button > 0) 29 | { 30 | Joystick.releaseButton(button - 1); 31 | } 32 | if (button < 32) 33 | { 34 | Joystick.pressButton(button); 35 | } 36 | } 37 | 38 | void testMultiButtonPush(unsigned int currentStep) 39 | { 40 | for (int button = 0; button < 32; button++) 41 | { 42 | if ((currentStep == 0) || (currentStep == 2)) 43 | { 44 | if ((button % 2) == 0) 45 | { 46 | Joystick.pressButton(button); 47 | } else if (currentStep != 2) 48 | { 49 | Joystick.releaseButton(button); 50 | } 51 | } // if ((currentStep == 0) || (currentStep == 2)) 52 | if ((currentStep == 1) || (currentStep == 2)) 53 | { 54 | if ((button % 2) != 0) 55 | { 56 | Joystick.pressButton(button); 57 | } else if (currentStep != 2) 58 | { 59 | Joystick.releaseButton(button); 60 | } 61 | } // if ((currentStep == 1) || (currentStep == 2)) 62 | if (currentStep == 3) 63 | { 64 | Joystick.releaseButton(button); 65 | } // if (currentStep == 3) 66 | } // for (int button = 0; button < 32; button++) 67 | } 68 | 69 | void testXYAxis(unsigned int currentStep) 70 | { 71 | int xAxis; 72 | int yAxis; 73 | 74 | if (currentStep < 256) 75 | { 76 | xAxis = currentStep - 127; 77 | yAxis = -127; 78 | Joystick.setXAxis(xAxis); 79 | Joystick.setYAxis(yAxis); 80 | } 81 | else if (currentStep < 512) 82 | { 83 | yAxis = currentStep - 256 - 127; 84 | Joystick.setYAxis(yAxis); 85 | } 86 | else if (currentStep < 768) 87 | { 88 | xAxis = 128 - (currentStep - 512); 89 | Joystick.setXAxis(xAxis); 90 | } 91 | else if (currentStep < 1024) 92 | { 93 | yAxis = 128 - (currentStep - 768); 94 | Joystick.setYAxis(yAxis); 95 | } 96 | else if (currentStep < 1024 + 128) 97 | { 98 | xAxis = currentStep - 1024 - 127; 99 | Joystick.setXAxis(xAxis); 100 | Joystick.setYAxis(xAxis); 101 | } 102 | } 103 | 104 | void testThrottleRudder(unsigned int value) 105 | { 106 | Joystick.setThrottle(value); 107 | Joystick.setRudder(255 - value); 108 | } 109 | 110 | void setup() { 111 | 112 | Joystick.setXAxisRange(-127, 127); 113 | Joystick.setYAxisRange(-127, 127); 114 | Joystick.setZAxisRange(-127, 127); 115 | Joystick.setThrottleRange(0, 255); 116 | Joystick.setRudderRange(0, 255); 117 | 118 | if (testAutoSendMode) 119 | { 120 | Joystick.begin(); 121 | } 122 | else 123 | { 124 | Joystick.begin(false); 125 | } 126 | 127 | pinMode(A0, INPUT_PULLUP); 128 | pinMode(LED_BUILTIN, OUTPUT); 129 | } 130 | 131 | void loop() { 132 | 133 | // System Disabled 134 | if (digitalRead(A0) != 0) 135 | { 136 | // Turn indicator light off. 137 | digitalWrite(LED_BUILTIN, 0); 138 | return; 139 | } 140 | 141 | // Turn indicator light on. 142 | digitalWrite(LED_BUILTIN, 1); 143 | 144 | if (millis() >= gNextTime) 145 | { 146 | 147 | if (gCurrentStep < 33) 148 | { 149 | gNextTime = millis() + gcButtonDelta; 150 | testSingleButtonPush(gCurrentStep); 151 | } 152 | else if (gCurrentStep < 37) 153 | { 154 | gNextTime = millis() + gcButtonDelta; 155 | testMultiButtonPush(gCurrentStep - 33); 156 | } 157 | else if (gCurrentStep < (37 + 256)) 158 | { 159 | gNextTime = millis() + gcAnalogDelta; 160 | testThrottleRudder(gCurrentStep - 37); 161 | } 162 | else if (gCurrentStep < (37 + 256 + 1024 + 128)) 163 | { 164 | gNextTime = millis() + gcAnalogDelta; 165 | testXYAxis(gCurrentStep - (37 + 256)); 166 | } 167 | 168 | if (testAutoSendMode == false) 169 | { 170 | Joystick.sendState(); 171 | } 172 | 173 | gCurrentStep++; 174 | if (gCurrentStep >= (37 + 256 + 1024 + 128)) 175 | { 176 | gNextTime = millis() + gcCycleDelta; 177 | gCurrentStep = 0; 178 | } 179 | } 180 | } 181 | 182 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/FunduinoJoystickShield/FunduinoJoystickShield.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const uint8_t buttonCount = 7; 4 | Joystick_ controller(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, buttonCount, 5 | 0, true, true, false, 6 | false, false, false, 7 | false, false, false, 8 | false, false); 9 | 10 | int const BTN_A_PIN = 2; 11 | int const BTN_B_PIN = 3; 12 | int const BTN_C_PIN = 4; 13 | int const BTN_D_PIN = 5; 14 | int const BTN_E_PIN = 6; 15 | int const BTN_F_PIN = 7; 16 | int const BTN_K_PIN = 8; 17 | int const AXIS_X_PIN = A0; 18 | int const AXIS_Y_PIN = A1; 19 | 20 | int const buttonPins[buttonCount] = { 21 | BTN_A_PIN, 22 | BTN_B_PIN, 23 | BTN_C_PIN, 24 | BTN_D_PIN, 25 | BTN_E_PIN, 26 | BTN_F_PIN, 27 | BTN_K_PIN 28 | }; 29 | int lastButtonValue[buttonCount]; 30 | int lastXAxisValue = -1; 31 | int lastYAxisValue = -1; 32 | 33 | void setup() 34 | { 35 | controller.setYAxisRange(0, 1023); 36 | controller.setYAxisRange(1023, 0); 37 | controller.begin(false); 38 | 39 | for (int i = 0; i < buttonCount; i++) 40 | { 41 | pinMode(buttonPins[i], INPUT_PULLUP); 42 | lastButtonValue[i] = -1; 43 | } 44 | 45 | pinMode(LED_BUILTIN, OUTPUT); 46 | digitalWrite(LED_BUILTIN, LOW); 47 | } 48 | 49 | void loop() 50 | { 51 | bool sendUpdate = false; 52 | for (int i = 0; i < buttonCount; i++) 53 | { 54 | const int buttonValue = digitalRead(buttonPins[i]); 55 | 56 | if (buttonValue != lastButtonValue[i]) 57 | { 58 | controller.setButton(i, !buttonValue); 59 | lastButtonValue[i] = buttonValue; 60 | sendUpdate = true; 61 | } 62 | } 63 | 64 | const int currentXAxisValue = analogRead(AXIS_X_PIN); 65 | if (currentXAxisValue != lastXAxisValue) 66 | { 67 | controller.setXAxis(currentXAxisValue); 68 | lastXAxisValue = currentXAxisValue; 69 | sendUpdate = true; 70 | } 71 | 72 | const int currentYAxisValue = analogRead(AXIS_Y_PIN); 73 | if (currentYAxisValue != lastYAxisValue) 74 | { 75 | controller.setYAxis(currentYAxisValue); 76 | lastYAxisValue = currentYAxisValue; 77 | sendUpdate = true; 78 | } 79 | 80 | if (sendUpdate) 81 | { 82 | controller.sendState(); 83 | } 84 | delay(50); 85 | } 86 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/GamepadExample/GamepadExample.ino: -------------------------------------------------------------------------------- 1 | // Simple gamepad example that demonstraits how to read five Arduino 2 | // digital pins and map them to the Arduino Joystick library. 3 | // 4 | // The digital pins 2 - 6 are grounded when they are pressed. 5 | // Pin 2 = UP 6 | // Pin 3 = RIGHT 7 | // Pin 4 = DOWN 8 | // Pin 5 = LEFT 9 | // Pin 6 = FIRE 10 | // 11 | // NOTE: This sketch file is for use with Arduino Leonardo and 12 | // Arduino Micro only. 13 | // 14 | // by Matthew Heironimus 15 | // 2016-11-24 16 | //-------------------------------------------------------------------- 17 | 18 | #include 19 | 20 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 21 | 1, 0, // Button Count, Hat Switch Count 22 | true, true, false, // X and Y, but no Z Axis 23 | false, false, false, // No Rx, Ry, or Rz 24 | false, false, // No rudder or throttle 25 | false, false, false); // No accelerator, brake, or steering 26 | 27 | void setup() { 28 | // Initialize Button Pins 29 | pinMode(2, INPUT_PULLUP); 30 | pinMode(3, INPUT_PULLUP); 31 | pinMode(4, INPUT_PULLUP); 32 | pinMode(5, INPUT_PULLUP); 33 | pinMode(6, INPUT_PULLUP); 34 | 35 | // Initialize Joystick Library 36 | Joystick.begin(); 37 | Joystick.setXAxisRange(-1, 1); 38 | Joystick.setYAxisRange(-1, 1); 39 | } 40 | 41 | // Last state of the buttons 42 | int lastButtonState[5] = {0,0,0,0,0}; 43 | 44 | void loop() { 45 | 46 | // Read pin values 47 | for (int index = 0; index < 5; index++) 48 | { 49 | int currentButtonState = !digitalRead(index + 2); 50 | if (currentButtonState != lastButtonState[index]) 51 | { 52 | switch (index) { 53 | case 0: // UP 54 | if (currentButtonState == 1) { 55 | Joystick.setYAxis(-1); 56 | } else { 57 | Joystick.setYAxis(0); 58 | } 59 | break; 60 | case 1: // RIGHT 61 | if (currentButtonState == 1) { 62 | Joystick.setXAxis(1); 63 | } else { 64 | Joystick.setXAxis(0); 65 | } 66 | break; 67 | case 2: // DOWN 68 | if (currentButtonState == 1) { 69 | Joystick.setYAxis(1); 70 | } else { 71 | Joystick.setYAxis(0); 72 | } 73 | break; 74 | case 3: // LEFT 75 | if (currentButtonState == 1) { 76 | Joystick.setXAxis(-1); 77 | } else { 78 | Joystick.setXAxis(0); 79 | } 80 | break; 81 | case 4: // FIRE 82 | Joystick.setButton(0, currentButtonState); 83 | break; 84 | } 85 | lastButtonState[index] = currentButtonState; 86 | } 87 | } 88 | 89 | delay(10); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/HatSwitchTest/HatSwitchTest.ino: -------------------------------------------------------------------------------- 1 | // Simple example application that shows how to read four Arduino 2 | // digital pins and map them to the USB Joystick library's hat switch. 3 | // 4 | // The digital pins 4, 5, 6, 7, 8, 9, 10, and 11 are grounded when 5 | // they are pressed. 6 | // 7 | // Pin Mappings: 8 | // 4 - Hat Switch #0 UP 9 | // 5 - Hat Switch #0 RIGHT 10 | // 6 - Hat Switch #0 DOWN 11 | // 7 - Hat Switch #0 LEFT 12 | // 8 - Hat Switch #1 UP 13 | // 9 - Hat Switch #1 RIGHT 14 | // 10 - Hat Switch #1 DOWN 15 | // 11 - Hat Switch #1 LEFT 16 | // 17 | // NOTE: This sketch file is for use with Arduino Leonardo and 18 | // Arduino Micro only. 19 | // 20 | // by Matthew Heironimus 21 | // 2016-05-30 22 | //-------------------------------------------------------------------- 23 | 24 | #include 25 | 26 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 27 | JOYSTICK_TYPE_GAMEPAD, 0, 28 | JOYSTICK_DEFAULT_HATSWITCH_COUNT, 29 | false, false, false, false, false, false, 30 | false, false, false, false, false); 31 | 32 | void setup() { 33 | 34 | // Initialize Button Pins 35 | for (int index = 4; index < 12; index++) 36 | { 37 | pinMode(index, INPUT_PULLUP); 38 | } 39 | 40 | // Initialize Joystick Library 41 | Joystick.begin(); 42 | } 43 | 44 | // Last state of the pins 45 | int lastButtonState[2][4] = {{0,0,0,0}, {0,0,0,0}}; 46 | 47 | void loop() { 48 | 49 | bool valueChanged[2] = {false, false}; 50 | int currentPin = 4; 51 | 52 | // Read pin values 53 | for (int hatSwitch = 0; hatSwitch < 2; hatSwitch++) 54 | { 55 | for (int index = 0; index < 4; index++) 56 | { 57 | int currentButtonState = !digitalRead(currentPin++); 58 | if (currentButtonState != lastButtonState[hatSwitch][index]) 59 | { 60 | valueChanged[hatSwitch] = true; 61 | lastButtonState[hatSwitch][index] = currentButtonState; 62 | } 63 | } 64 | } 65 | 66 | for (int hatSwitch = 0; hatSwitch < 2; hatSwitch++) 67 | { 68 | if (valueChanged[hatSwitch]) { 69 | 70 | if ((lastButtonState[hatSwitch][0] == 0) 71 | && (lastButtonState[hatSwitch][1] == 0) 72 | && (lastButtonState[hatSwitch][2] == 0) 73 | && (lastButtonState[hatSwitch][3] == 0)) { 74 | Joystick.setHatSwitch(hatSwitch, -1); 75 | } 76 | if (lastButtonState[hatSwitch][0] == 1) { 77 | Joystick.setHatSwitch(hatSwitch, 0); 78 | } 79 | if (lastButtonState[hatSwitch][1] == 1) { 80 | Joystick.setHatSwitch(hatSwitch, 90); 81 | } 82 | if (lastButtonState[hatSwitch][2] == 1) { 83 | Joystick.setHatSwitch(hatSwitch, 180); 84 | } 85 | if (lastButtonState[hatSwitch][3] == 1) { 86 | Joystick.setHatSwitch(hatSwitch, 270); 87 | } 88 | 89 | } // if the value changed 90 | 91 | } // for each hat switch 92 | 93 | delay(50); 94 | } 95 | 96 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/JoystickButton/JoystickButton.ino: -------------------------------------------------------------------------------- 1 | // Simple example application that shows how to read four Arduino 2 | // digital pins and map them to the USB Joystick library. 3 | // 4 | // Ground digital pins 9, 10, 11, and 12 to press the joystick 5 | // buttons 0, 1, 2, and 3. 6 | // 7 | // NOTE: This sketch file is for use with Arduino Leonardo and 8 | // Arduino Micro only. 9 | // 10 | // by Matthew Heironimus 11 | // 2015-11-20 12 | //-------------------------------------------------------------------- 13 | 14 | #include 15 | 16 | Joystick_ Joystick; 17 | 18 | void setup() { 19 | // Initialize Button Pins 20 | pinMode(9, INPUT_PULLUP); 21 | pinMode(10, INPUT_PULLUP); 22 | pinMode(11, INPUT_PULLUP); 23 | pinMode(12, INPUT_PULLUP); 24 | 25 | // Initialize Joystick Library 26 | Joystick.begin(); 27 | } 28 | 29 | // Constant that maps the phyical pin to the joystick button. 30 | const int pinToButtonMap = 9; 31 | 32 | // Last state of the button 33 | int lastButtonState[4] = {0,0,0,0}; 34 | 35 | void loop() { 36 | 37 | // Read pin values 38 | for (int index = 0; index < 4; index++) 39 | { 40 | int currentButtonState = !digitalRead(index + pinToButtonMap); 41 | if (currentButtonState != lastButtonState[index]) 42 | { 43 | Joystick.setButton(index, currentButtonState); 44 | lastButtonState[index] = currentButtonState; 45 | } 46 | } 47 | 48 | delay(50); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/JoystickKeyboard/JoystickKeyboard.ino: -------------------------------------------------------------------------------- 1 | // Simple example application that shows how to read four Arduino 2 | // digital pins and map them to buttons on a joystick or keys on a 3 | // keyboard uisng the Arduino Joystick and Keyboard libraries. 4 | // 5 | // The digital pins 9, 10, 11, and 12 are grounded when they are pressed. 6 | // 7 | // NOTE: This sketch file is for use with Arduino Leonardo and 8 | // Arduino Micro only. 9 | // 10 | // Pin 9 = Joystick Button 0 11 | // Pin 10 = Joystick Button 1 12 | // Pin 11 = 1 key on the Keyboard 13 | // Pin 12 = 2 key on the Keyboard 14 | // 15 | // by Matthew Heironimus 16 | // 2016-05-13 17 | //-------------------------------------------------------------------- 18 | 19 | #include 20 | #include 21 | 22 | Joystick_ Joystick; 23 | 24 | void setup() { 25 | // Initialize Button Pins 26 | pinMode(9, INPUT_PULLUP); 27 | pinMode(10, INPUT_PULLUP); 28 | pinMode(11, INPUT_PULLUP); 29 | pinMode(12, INPUT_PULLUP); 30 | 31 | // Initialize Joystick Library 32 | Joystick.begin(); 33 | } 34 | 35 | // Constant that maps the phyical pin to the joystick button. 36 | const int pinToButtonMap = 9; 37 | 38 | // Last state of the button 39 | int lastButtonState[4] = {0,0,0,0}; 40 | 41 | void loop() { 42 | 43 | // Read pin values 44 | for (int index = 0; index < 4; index++) 45 | { 46 | int currentButtonState = !digitalRead(index + pinToButtonMap); 47 | if (currentButtonState != lastButtonState[index]) 48 | { 49 | if (index < 2) { 50 | Joystick.setButton(index, currentButtonState); 51 | lastButtonState[index] = currentButtonState; 52 | } else { 53 | if (currentButtonState) { 54 | Keyboard.write(47 + index); 55 | delay(500); 56 | } 57 | } 58 | } 59 | } 60 | 61 | delay(100); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/JoystickTest/JoystickTest.ino: -------------------------------------------------------------------------------- 1 | // Program used to test the USB Joystick object on the 2 | // Arduino Leonardo or Arduino Micro. 3 | // 4 | // Matthew Heironimus 5 | // 2015-03-28 - Original Version 6 | // 2015-11-18 - Updated to use the new Joystick library 7 | // written for Arduino IDE Version 1.6.6 and 8 | // above. 9 | // 2016-05-13 Updated to use new dynamic Joystick library 10 | // that can be customized. 11 | // 2022-03-29 Updated to work with version 2.1.0 of the 12 | // Joystick library. 13 | //------------------------------------------------------------ 14 | 15 | #include "Joystick.h" 16 | 17 | // Create Joystick 18 | Joystick_ Joystick; 19 | 20 | // Set to true to test "Auto Send" mode or false to test "Manual Send" mode. 21 | //const bool testAutoSendMode = true; 22 | const bool testAutoSendMode = false; 23 | 24 | const unsigned long gcCycleDelta = 1000; 25 | const unsigned long gcAnalogDelta = 25; 26 | const unsigned long gcButtonDelta = 500; 27 | unsigned long gNextTime = 0; 28 | unsigned int gCurrentStep = 0; 29 | 30 | void testSingleButtonPush(unsigned int button) 31 | { 32 | if (button > 0) 33 | { 34 | Joystick.releaseButton(button - 1); 35 | } 36 | if (button < 32) 37 | { 38 | Joystick.pressButton(button); 39 | } 40 | } 41 | 42 | void testMultiButtonPush(unsigned int currentStep) 43 | { 44 | for (int button = 0; button < 32; button++) 45 | { 46 | if ((currentStep == 0) || (currentStep == 2)) 47 | { 48 | if ((button % 2) == 0) 49 | { 50 | Joystick.pressButton(button); 51 | } else if (currentStep != 2) 52 | { 53 | Joystick.releaseButton(button); 54 | } 55 | } // if ((currentStep == 0) || (currentStep == 2)) 56 | if ((currentStep == 1) || (currentStep == 2)) 57 | { 58 | if ((button % 2) != 0) 59 | { 60 | Joystick.pressButton(button); 61 | } else if (currentStep != 2) 62 | { 63 | Joystick.releaseButton(button); 64 | } 65 | } // if ((currentStep == 1) || (currentStep == 2)) 66 | if (currentStep == 3) 67 | { 68 | Joystick.releaseButton(button); 69 | } // if (currentStep == 3) 70 | } // for (int button = 0; button < 32; button++) 71 | } 72 | 73 | void testXYAxis(unsigned int currentStep) 74 | { 75 | int xAxis; 76 | int yAxis; 77 | 78 | if (currentStep < 256) 79 | { 80 | xAxis = currentStep - 127; 81 | yAxis = -127; 82 | Joystick.setXAxis(xAxis); 83 | Joystick.setYAxis(yAxis); 84 | } 85 | else if (currentStep < 512) 86 | { 87 | yAxis = currentStep - 256 - 127; 88 | Joystick.setYAxis(yAxis); 89 | } 90 | else if (currentStep < 768) 91 | { 92 | xAxis = 128 - (currentStep - 512); 93 | Joystick.setXAxis(xAxis); 94 | } 95 | else if (currentStep < 1024) 96 | { 97 | yAxis = 128 - (currentStep - 768); 98 | Joystick.setYAxis(yAxis); 99 | } 100 | else if (currentStep < 1024 + 128) 101 | { 102 | xAxis = currentStep - 1024 - 127; 103 | Joystick.setXAxis(xAxis); 104 | Joystick.setYAxis(xAxis); 105 | } 106 | } 107 | 108 | void testZAxis(unsigned int currentStep) 109 | { 110 | int z; 111 | 112 | if (currentStep < 128) 113 | { 114 | z = -currentStep; 115 | } 116 | else if (currentStep < 256 + 128) 117 | { 118 | z = currentStep - 128 - 127; 119 | } 120 | else if (currentStep < 256 + 128 + 127) 121 | { 122 | z = 127 - (currentStep - 383); 123 | } 124 | 125 | Joystick.setZAxis(z); 126 | } 127 | 128 | void testHatSwitch(unsigned int currentStep) 129 | { 130 | if (currentStep < 8) 131 | { 132 | Joystick.setHatSwitch(0, currentStep * 45); 133 | } 134 | else if (currentStep == 8) 135 | { 136 | Joystick.setHatSwitch(0, -1); 137 | } 138 | else if (currentStep < 17) 139 | { 140 | Joystick.setHatSwitch(1, (currentStep - 9) * 45); 141 | } 142 | else if (currentStep == 17) 143 | { 144 | Joystick.setHatSwitch(1, -1); 145 | } 146 | else if (currentStep == 18) 147 | { 148 | Joystick.setHatSwitch(0, 0); 149 | Joystick.setHatSwitch(1, 0); 150 | } 151 | else if (currentStep < 27) 152 | { 153 | Joystick.setHatSwitch(0, (currentStep - 18) * 45); 154 | Joystick.setHatSwitch(1, (8 - (currentStep - 18)) * 45); 155 | } 156 | else if (currentStep == 27) 157 | { 158 | Joystick.setHatSwitch(0, -1); 159 | Joystick.setHatSwitch(1, -1); 160 | } 161 | } 162 | 163 | void testThrottleRudder(unsigned int value) 164 | { 165 | Joystick.setThrottle(value); 166 | Joystick.setRudder(value); 167 | } 168 | 169 | void testXYZAxisRotation(unsigned int degree) 170 | { 171 | Joystick.setRxAxis(degree); 172 | Joystick.setRyAxis(degree); 173 | Joystick.setRzAxis(degree * 2); 174 | } 175 | 176 | void setup() { 177 | 178 | // Set Range Values 179 | Joystick.setXAxisRange(-127, 127); 180 | Joystick.setYAxisRange(-127, 127); 181 | Joystick.setZAxisRange(-127, 127); 182 | Joystick.setRxAxisRange(0, 360); 183 | Joystick.setRyAxisRange(360, 0); 184 | Joystick.setRzAxisRange(0, 720); 185 | Joystick.setThrottleRange(0, 255); 186 | Joystick.setRudderRange(255, 0); 187 | 188 | if (testAutoSendMode) 189 | { 190 | Joystick.begin(); 191 | } 192 | else 193 | { 194 | Joystick.begin(false); 195 | } 196 | 197 | pinMode(A0, INPUT_PULLUP); 198 | pinMode(LED_BUILTIN, OUTPUT); 199 | } 200 | 201 | void loop() { 202 | 203 | // System Disabled 204 | if (digitalRead(A0) != 0) 205 | { 206 | // Turn indicator light off. 207 | digitalWrite(LED_BUILTIN, 0); 208 | return; 209 | } 210 | 211 | // Turn indicator light on. 212 | digitalWrite(LED_BUILTIN, 1); 213 | 214 | if (millis() >= gNextTime) 215 | { 216 | 217 | if (gCurrentStep < 33) 218 | { 219 | gNextTime = millis() + gcButtonDelta; 220 | testSingleButtonPush(gCurrentStep); 221 | } 222 | else if (gCurrentStep < 37) 223 | { 224 | gNextTime = millis() + gcButtonDelta; 225 | testMultiButtonPush(gCurrentStep - 33); 226 | } 227 | else if (gCurrentStep < (37 + 256)) 228 | { 229 | gNextTime = millis() + gcAnalogDelta; 230 | testThrottleRudder(gCurrentStep - 37); 231 | } 232 | else if (gCurrentStep < (37 + 256 + 1024 + 128)) 233 | { 234 | gNextTime = millis() + gcAnalogDelta; 235 | testXYAxis(gCurrentStep - (37 + 256)); 236 | } 237 | else if (gCurrentStep < (37 + 256 + 1024 + 128 + 510)) 238 | { 239 | gNextTime = millis() + gcAnalogDelta; 240 | testZAxis(gCurrentStep - (37 + 256 + 1024 + 128)); 241 | } 242 | else if (gCurrentStep < (37 + 256 + 1024 + 128 + 510 + 28)) 243 | { 244 | gNextTime = millis() + gcButtonDelta; 245 | testHatSwitch(gCurrentStep - (37 + 256 + 1024 + 128 + 510)); 246 | } 247 | else if (gCurrentStep < (37 + 256 + 1024 + 128 + 510 + 28 + 360)) 248 | { 249 | gNextTime = millis() + gcAnalogDelta; 250 | testXYZAxisRotation(gCurrentStep - (37 + 256 + 1024 + 128 + 510 + 28)); 251 | } 252 | 253 | if (testAutoSendMode == false) 254 | { 255 | Joystick.sendState(); 256 | } 257 | 258 | gCurrentStep++; 259 | if (gCurrentStep == (37 + 256 + 1024 + 128 + 510 + 28 + 360)) 260 | { 261 | gNextTime = millis() + gcCycleDelta; 262 | gCurrentStep = 0; 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/examples/MultipleJoystickTest/MultipleJoystickTest.ino: -------------------------------------------------------------------------------- 1 | // Program used to test using the Arduino Joystick Library 2 | // to create multiple Joystick objects on a single Arduino 3 | // Leonardo or Arduino Micro. 4 | // 5 | // Each joystick has a unique configuration. 6 | // 7 | // Matthew Heironimus 8 | // 2016-05-13 - Original Version 9 | // 2022-03-29 - Updated to work with Joystick Library v2.1.0 10 | //------------------------------------------------------------ 11 | #include 12 | 13 | #define JOYSTICK_COUNT 4 14 | 15 | Joystick_ Joystick[JOYSTICK_COUNT] = { 16 | Joystick_(0x03, JOYSTICK_TYPE_JOYSTICK, 4, 2, true, true, false, false, false, false, false, false, false, false, false), 17 | Joystick_(0x04, JOYSTICK_TYPE_JOYSTICK, 8, 1, true, true, true, true, false, false, false, false, false, false, false), 18 | Joystick_(0x05, JOYSTICK_TYPE_JOYSTICK, 16, 0, false, true, false, true, false, false, true, true, false, false, false), 19 | Joystick_(0x06, JOYSTICK_TYPE_JOYSTICK, 32, 1, true, true, false, true, true, false, false, false, false, false, false) 20 | }; 21 | 22 | // Set to true to test "Auto Send" mode or false to test "Manual Send" mode. 23 | //const bool testAutoSendMode = true; 24 | const bool testAutoSendMode = false; 25 | 26 | const unsigned long gcCycleDelta = 1000; 27 | const unsigned long gcAnalogDelta = 25; 28 | const unsigned long gcButtonDelta = 500; 29 | unsigned long gNextTime = 0; 30 | unsigned int gCurrentStep = 0; 31 | int gJoystickId = 0; 32 | 33 | void testSingleButtonPush(int joystickId, unsigned int button) 34 | { 35 | if (button > 0) 36 | { 37 | Joystick[joystickId].releaseButton(button - 1); 38 | } 39 | if (button < 16) 40 | { 41 | Joystick[joystickId].pressButton(button); 42 | } 43 | } 44 | 45 | void testMultiButtonPush(int joystickId, unsigned int currentStep) 46 | { 47 | for (int button = 0; button < 16; button++) 48 | { 49 | if ((currentStep == 0) || (currentStep == 2)) 50 | { 51 | if ((button % 2) == 0) 52 | { 53 | Joystick[joystickId].pressButton(button); 54 | } else if (currentStep != 2) 55 | { 56 | Joystick[joystickId].releaseButton(button); 57 | } 58 | } // if ((currentStep == 0) || (currentStep == 2)) 59 | if ((currentStep == 1) || (currentStep == 2)) 60 | { 61 | if ((button % 2) != 0) 62 | { 63 | Joystick[joystickId].pressButton(button); 64 | } else if (currentStep != 2) 65 | { 66 | Joystick[joystickId].releaseButton(button); 67 | } 68 | } // if ((currentStep == 1) || (currentStep == 2)) 69 | if (currentStep == 3) 70 | { 71 | Joystick[joystickId].releaseButton(button); 72 | } // if (currentStep == 3) 73 | } // for (int button = 0; button < 32; button++) 74 | } 75 | 76 | void testXYAxis(int joystickId, unsigned int currentStep) 77 | { 78 | int x; 79 | int y; 80 | 81 | if (currentStep < 255) 82 | { 83 | x = currentStep - 127; 84 | y = -127; 85 | } 86 | else if (currentStep < 510) 87 | { 88 | x = 127; 89 | y = currentStep - 255 - 127; 90 | } 91 | else if (currentStep < 765) 92 | { 93 | x = 127 - (currentStep - 510); 94 | y = 127; 95 | } 96 | else if (currentStep < 1020) 97 | { 98 | x = -127; 99 | y = 127 - (currentStep - 765); 100 | } 101 | else if (currentStep <= 1020 + 127) 102 | { 103 | x = currentStep - 1020 - 127; 104 | y = currentStep - 1020 - 127; 105 | } 106 | 107 | Joystick[joystickId].setXAxis(x); 108 | Joystick[joystickId].setYAxis(y); 109 | } 110 | 111 | void setup() { 112 | 113 | for (int index = 0; index < JOYSTICK_COUNT; index++) 114 | { 115 | Joystick[index].setXAxisRange(-127, 127); 116 | Joystick[index].setYAxisRange(-127, 127); 117 | 118 | if (testAutoSendMode) 119 | { 120 | Joystick[index].begin(); 121 | } 122 | else 123 | { 124 | Joystick[index].begin(false); 125 | } 126 | } 127 | 128 | pinMode(A0, INPUT_PULLUP); 129 | pinMode(LED_BUILTIN, OUTPUT); 130 | } 131 | 132 | void loop() { 133 | 134 | // System Disabled 135 | if (digitalRead(A0) != 0) 136 | { 137 | digitalWrite(LED_BUILTIN, 0); 138 | return; 139 | } 140 | 141 | // Turn indicator light on. 142 | digitalWrite(LED_BUILTIN, 1); 143 | 144 | if (millis() >= gNextTime) 145 | { 146 | 147 | if (gCurrentStep < 17) 148 | { 149 | gNextTime = millis() + gcButtonDelta; 150 | testSingleButtonPush(gJoystickId, gCurrentStep); 151 | } 152 | else if (gCurrentStep < (17 + 4)) 153 | { 154 | gNextTime = millis() + gcButtonDelta; 155 | testMultiButtonPush(gJoystickId, gCurrentStep - 17); 156 | } 157 | else if (gCurrentStep < (17 + 4 + 1024 + 128)) 158 | { 159 | gNextTime = millis() + gcAnalogDelta; 160 | testXYAxis(gJoystickId, gCurrentStep - (17 + 4)); 161 | } 162 | 163 | if (testAutoSendMode == false) 164 | { 165 | Joystick[gJoystickId].sendState(); 166 | } 167 | 168 | gCurrentStep++; 169 | if (gCurrentStep == (17 + 4 + 1024 + 128)) 170 | { 171 | gNextTime = millis() + gcCycleDelta; 172 | gCurrentStep = 0; 173 | 174 | if (++gJoystickId >= JOYSTICK_COUNT) 175 | { 176 | gJoystickId = 0; 177 | } 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/library.properties: -------------------------------------------------------------------------------- 1 | name=Joystick 2 | version=2.1.1 3 | author=Matthew Heironimus 4 | maintainer=Matthew Heironimus 5 | sentence=Allows an Arduino board with USB capabilities (e.g. Leonardo, Arduino Micro, Arudino Due, etc.) to appear as a Joystick or Gamepad. 6 | paragraph=This library is built on the PluggableUSB library. It can be used with or without other HID-based libraries (Mouse, Keyboard, etc.). 7 | category=Device Control 8 | url=https://github.com/MHeironimus/ArduinoJoystickLibrary 9 | architectures=avr,sam 10 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/src/DynamicHID/DynamicHID.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Modified by Matthew Heironimus to support HID Report Descriptors to be in 3 | standard RAM in addition to program memory (PROGMEM). 4 | 5 | Copyright (c) 2015, Arduino LLC 6 | Original code (pre-library): Copyright (c) 2011, Peter Barrett 7 | 8 | Permission to use, copy, modify, and/or distribute this software for 9 | any purpose with or without fee is hereby granted, provided that the 10 | above copyright notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 15 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 16 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 17 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 18 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 19 | SOFTWARE. 20 | */ 21 | 22 | #include "DynamicHID.h" 23 | 24 | #if defined(USBCON) 25 | 26 | #ifdef _VARIANT_ARDUINO_DUE_X_ 27 | #define USB_SendControl USBD_SendControl 28 | #define USB_Send USBD_Send 29 | #endif 30 | 31 | DynamicHID_& DynamicHID() 32 | { 33 | static DynamicHID_ obj; 34 | return obj; 35 | } 36 | 37 | int DynamicHID_::getInterface(uint8_t* interfaceCount) 38 | { 39 | *interfaceCount += 1; // uses 1 40 | DYNAMIC_HIDDescriptor hidInterface = { 41 | D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, DYNAMIC_HID_SUBCLASS_NONE, DYNAMIC_HID_PROTOCOL_NONE), 42 | D_HIDREPORT(descriptorSize), 43 | D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) 44 | }; 45 | return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); 46 | } 47 | 48 | int DynamicHID_::getDescriptor(USBSetup& setup) 49 | { 50 | // Check if this is a HID Class Descriptor request 51 | if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } 52 | if (setup.wValueH != DYNAMIC_HID_REPORT_DESCRIPTOR_TYPE) { return 0; } 53 | 54 | // In a HID Class Descriptor wIndex cointains the interface number 55 | if (setup.wIndex != pluggedInterface) { return 0; } 56 | 57 | int total = 0; 58 | DynamicHIDSubDescriptor* node; 59 | for (node = rootNode; node; node = node->next) { 60 | int res = USB_SendControl((node->inProgMem ? TRANSFER_PGM : 0), node->data, node->length); 61 | if (res == -1) 62 | return -1; 63 | total += res; 64 | } 65 | 66 | // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol 67 | // due to the USB specs, but Windows and Linux just assumes its in report mode. 68 | protocol = DYNAMIC_HID_REPORT_PROTOCOL; 69 | 70 | return total; 71 | } 72 | 73 | uint8_t DynamicHID_::getShortName(char *name) 74 | { 75 | name[0] = 'H'; 76 | name[1] = 'I'; 77 | name[2] = 'D'; 78 | name[3] = 'A' + (descriptorSize & 0x0F); 79 | name[4] = 'A' + ((descriptorSize >> 4) & 0x0F); 80 | return 5; 81 | } 82 | 83 | void DynamicHID_::AppendDescriptor(DynamicHIDSubDescriptor *node) 84 | { 85 | if (!rootNode) { 86 | rootNode = node; 87 | } else { 88 | DynamicHIDSubDescriptor *current = rootNode; 89 | while (current->next) { 90 | current = current->next; 91 | } 92 | current->next = node; 93 | } 94 | descriptorSize += node->length; 95 | } 96 | 97 | int DynamicHID_::SendReport(uint8_t id, const void* data, int len) 98 | { 99 | uint8_t p[len + 1]; 100 | p[0] = id; 101 | memcpy(&p[1], data, len); 102 | return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, p, len + 1); 103 | } 104 | 105 | bool DynamicHID_::setup(USBSetup& setup) 106 | { 107 | if (pluggedInterface != setup.wIndex) { 108 | return false; 109 | } 110 | 111 | uint8_t request = setup.bRequest; 112 | uint8_t requestType = setup.bmRequestType; 113 | 114 | if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) 115 | { 116 | if (request == DYNAMIC_HID_GET_REPORT) { 117 | // TODO: DYNAMIC_HID_GetReport(); 118 | return true; 119 | } 120 | if (request == DYNAMIC_HID_GET_PROTOCOL) { 121 | // TODO: Send8(protocol); 122 | return true; 123 | } 124 | if (request == DYNAMIC_HID_GET_IDLE) { 125 | // TODO: Send8(idle); 126 | } 127 | } 128 | 129 | if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) 130 | { 131 | if (request == DYNAMIC_HID_SET_PROTOCOL) { 132 | // The USB Host tells us if we are in boot or report mode. 133 | // This only works with a real boot compatible device. 134 | protocol = setup.wValueL; 135 | return true; 136 | } 137 | if (request == DYNAMIC_HID_SET_IDLE) { 138 | idle = setup.wValueL; 139 | return true; 140 | } 141 | if (request == DYNAMIC_HID_SET_REPORT) 142 | { 143 | //uint8_t reportID = setup.wValueL; 144 | //uint16_t length = setup.wLength; 145 | //uint8_t data[length]; 146 | // Make sure to not read more data than USB_EP_SIZE. 147 | // You can read multiple times through a loop. 148 | // The first byte (may!) contain the reportID on a multreport. 149 | //USB_RecvControl(data, length); 150 | } 151 | } 152 | 153 | return false; 154 | } 155 | 156 | DynamicHID_::DynamicHID_(void) : PluggableUSBModule(1, 1, epType), 157 | rootNode(NULL), descriptorSize(0), 158 | protocol(DYNAMIC_HID_REPORT_PROTOCOL), idle(1) 159 | { 160 | epType[0] = EP_TYPE_INTERRUPT_IN; 161 | PluggableUSB().plug(this); 162 | } 163 | 164 | int DynamicHID_::begin(void) 165 | { 166 | return 0; 167 | } 168 | 169 | #endif /* if defined(USBCON) */ 170 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/ArduinoJoystickLibrary/src/DynamicHID/DynamicHID.h: -------------------------------------------------------------------------------- 1 | /* 2 | Modified by Matthew Heironimus to support HID Report Descriptors to be in 3 | standard RAM in addition to program memory (PROGMEM). 4 | 5 | Copyright (c) 2015, Arduino LLC 6 | Original code (pre-library): Copyright (c) 2011, Peter Barrett 7 | 8 | Permission to use, copy, modify, and/or distribute this software for 9 | any purpose with or without fee is hereby granted, provided that the 10 | above copyright notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 15 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 16 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 17 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 18 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 19 | SOFTWARE. 20 | */ 21 | 22 | #ifndef DYNAMIC_HID_h 23 | #define DYNAMIC_HID_h 24 | 25 | #include 26 | #include 27 | 28 | #ifdef _VARIANT_ARDUINO_DUE_X_ 29 | // The following values are the same as AVR's USBAPI.h 30 | // Reproduced here because SAM doesn't have these in 31 | // its own USBAPI.H 32 | #define USB_EP_SIZE 64 33 | #define TRANSFER_PGM 0x80 34 | 35 | #include "USB/PluggableUSB.h" 36 | #else 37 | #include "PluggableUSB.h" 38 | #endif 39 | 40 | #if defined(USBCON) 41 | 42 | #define _USING_DYNAMIC_HID 43 | 44 | // DYNAMIC_HID 'Driver' 45 | // ------------ 46 | #define DYNAMIC_HID_GET_REPORT 0x01 47 | #define DYNAMIC_HID_GET_IDLE 0x02 48 | #define DYNAMIC_HID_GET_PROTOCOL 0x03 49 | #define DYNAMIC_HID_SET_REPORT 0x09 50 | #define DYNAMIC_HID_SET_IDLE 0x0A 51 | #define DYNAMIC_HID_SET_PROTOCOL 0x0B 52 | 53 | #define DYNAMIC_HID_DESCRIPTOR_TYPE 0x21 54 | #define DYNAMIC_HID_REPORT_DESCRIPTOR_TYPE 0x22 55 | #define DYNAMIC_HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 56 | 57 | // HID subclass HID1.11 Page 8 4.2 Subclass 58 | #define DYNAMIC_HID_SUBCLASS_NONE 0 59 | #define DYNAMIC_HID_SUBCLASS_BOOT_INTERFACE 1 60 | 61 | // HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols 62 | #define DYNAMIC_HID_PROTOCOL_NONE 0 63 | #define DYNAMIC_HID_PROTOCOL_KEYBOARD 1 64 | #define DYNAMIC_HID_PROTOCOL_MOUSE 2 65 | 66 | // Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request 67 | // "protocol" variable is used for this purpose. 68 | #define DYNAMIC_HID_BOOT_PROTOCOL 0 69 | #define DYNAMIC_HID_REPORT_PROTOCOL 1 70 | 71 | // HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request 72 | #define DYNAMIC_HID_REPORT_TYPE_INPUT 1 73 | #define DYNAMIC_HID_REPORT_TYPE_OUTPUT 2 74 | #define DYNAMIC_HID_REPORT_TYPE_FEATURE 3 75 | 76 | typedef struct 77 | { 78 | uint8_t len; // 9 79 | uint8_t dtype; // 0x21 80 | uint8_t addr; 81 | uint8_t versionL; // 0x101 82 | uint8_t versionH; // 0x101 83 | uint8_t country; 84 | uint8_t desctype; // 0x22 report 85 | uint8_t descLenL; 86 | uint8_t descLenH; 87 | } DYNAMIC_HIDDescDescriptor; 88 | 89 | typedef struct 90 | { 91 | InterfaceDescriptor hid; 92 | DYNAMIC_HIDDescDescriptor desc; 93 | EndpointDescriptor in; 94 | } DYNAMIC_HIDDescriptor; 95 | 96 | class DynamicHIDSubDescriptor { 97 | public: 98 | DynamicHIDSubDescriptor *next = NULL; 99 | DynamicHIDSubDescriptor(const void *d, const uint16_t l, const bool ipm = true) : data(d), length(l), inProgMem(ipm) { } 100 | 101 | const void* data; 102 | const uint16_t length; 103 | const bool inProgMem; 104 | }; 105 | 106 | class DynamicHID_ : public PluggableUSBModule 107 | { 108 | public: 109 | DynamicHID_(void); 110 | int begin(void); 111 | int SendReport(uint8_t id, const void* data, int len); 112 | void AppendDescriptor(DynamicHIDSubDescriptor* node); 113 | 114 | protected: 115 | // Implementation of the PluggableUSBModule 116 | int getInterface(uint8_t* interfaceCount); 117 | int getDescriptor(USBSetup& setup); 118 | bool setup(USBSetup& setup); 119 | uint8_t getShortName(char* name); 120 | 121 | private: 122 | #ifdef _VARIANT_ARDUINO_DUE_X_ 123 | uint32_t epType[1]; 124 | #else 125 | uint8_t epType[1]; 126 | #endif 127 | 128 | DynamicHIDSubDescriptor* rootNode; 129 | uint16_t descriptorSize; 130 | 131 | uint8_t protocol; 132 | uint8_t idle; 133 | }; 134 | 135 | // Replacement for global singleton. 136 | // This function prevents static-initialization-order-fiasco 137 | // https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use 138 | DynamicHID_& DynamicHID(); 139 | 140 | #define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } 141 | 142 | #endif // USBCON 143 | 144 | #endif // DYNAMIC_HID_h 145 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/photo_2023-03-30_04-58-32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/sbus-to-usb-joystick/photo_2023-03-30_04-58-32.jpg -------------------------------------------------------------------------------- /sbus-to-usb-joystick/readme.md: -------------------------------------------------------------------------------- 1 | ## USB-джойстик из обычной радиоапппаратуры с приемником SBUS на arduino pro micro 2 | 3 | ![photo_2023-03-30_04-58-32.jpg](photo_2023-03-30_04-58-32.jpg) 4 | 5 | Сигнал SBUS от приемника подключать на rx, нужен неинвертированный. Если у вас "обычный" инвертированный, вам придется использовать транзистор для инверсии. 6 | 7 | ![sbus-inverter-diagram-schematics.jpg](sbus-inverter-diagram-schematics.jpg) 8 | 9 | Я использую "цифровые" транзисторы dtc144eka или bcr533 и не ставлю резистор в базу. В качестве передатчика и приемника sbus я использую qczek, вы можете использовать любой приемник. 10 | Его задача - передать значения каналов от аппаратуры до USB регистратора через [arduino](https://docs.arduino.cc/hardware/micro) на 32u4 ([ali](https://aliexpress.ru/item/1005003622414316.html)), которая определяется как hid-usb-joystick. При этом немного вырастает задержка за счет дополнительного 11 | процесса по приему и передаче значений, но вы не привязаны к регистратору проводом, что удобно. 12 | 13 | Скетч, доработанная под 10 каналов осей библиотека джойстика (остальные каналы заполняются кнопками), [тут](https://github.com/OpenIPC/sandbox-fpv/tree/master/sbus-to-usb-joystick). 14 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/sbus-inverter-diagram-schematics.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/sbus-to-usb-joystick/sbus-inverter-diagram-schematics.jpg -------------------------------------------------------------------------------- /sbus-to-usb-joystick/sbus-to-usb-joystick.ino: -------------------------------------------------------------------------------- 1 | #include "sbus.h" 2 | #include 3 | 4 | //#define SERIAL_DEBUG 5 | 6 | //Joystic settings 7 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_JOYSTICK, 8 | 32, 2, // Button Count, Hat Switch Count 9 | true, true, true, // X and Y, Z Axis 10 | true, true, true, // Rx, Ry, Rz 11 | true, true, true, true, // slider, dial, rudder and throttle 12 | false, false, false); // accelerator, brake, and steering 13 | 14 | bfs::SbusRx sbus_rx(&Serial1); 15 | bfs::SbusData data; 16 | 17 | void setup() { 18 | #ifdef SERIAL_DEBUG 19 | Serial.begin(115200); 20 | while (!Serial) {} 21 | Serial.println("Started"); 22 | #else 23 | Joystick.begin(); 24 | //range 25 | Joystick.setXAxisRange(0, 2000); 26 | Joystick.setYAxisRange(0, 2000); 27 | Joystick.setZAxisRange(0, 2000); 28 | Joystick.setRxAxisRange(0, 2000); 29 | Joystick.setRyAxisRange(0, 2000); 30 | Joystick.setRzAxisRange(0, 2000); 31 | Joystick.setSliderRange(0, 2000); 32 | Joystick.setDialRange(0, 2000); 33 | Joystick.setRudderRange(0, 2000); 34 | Joystick.setThrottleRange(0, 2000); 35 | //default 36 | //Joystick.setRudder(1500); 37 | //Joystick.setAccelerator(0); 38 | //Joystick.setBrake(1500); 39 | //Joystick.setSteering(1500); 40 | #endif 41 | sbus_rx.Begin(); 42 | } 43 | 44 | void loop() { 45 | if (sbus_rx.Read()) { 46 | data = sbus_rx.data(); 47 | 48 | #ifdef SERIAL_DEBUG 49 | for (int8_t i = 0; i < data.NUM_CH; i++) { 50 | Serial.print(data.ch[i]); 51 | Serial.print("\t"); 52 | } 53 | Serial.println(); 54 | #else 55 | Joystick.setXAxis (data.ch[0]); 56 | Joystick.setYAxis (data.ch[1]); 57 | Joystick.setZAxis (data.ch[2]); 58 | Joystick.setRxAxis (data.ch[3]); 59 | Joystick.setRyAxis (data.ch[4]); 60 | Joystick.setRzAxis (data.ch[5]); 61 | Joystick.setSlider (data.ch[6]); 62 | Joystick.setRudder (data.ch[7]); 63 | Joystick.setThrottle (data.ch[8]); 64 | Joystick.setDial (data.ch[9]); 65 | if(data.ch[10] > 1490) Joystick.setButton(0, 255); else Joystick.setButton(0, 0); 66 | if(data.ch[11] > 1490) Joystick.setButton(1, 255); else Joystick.setButton(1, 0); 67 | if(data.ch[12] > 1490) Joystick.setButton(2, 255); else Joystick.setButton(2, 0); 68 | if(data.ch[13] > 1490) Joystick.setButton(3, 255); else Joystick.setButton(3, 0); 69 | if(data.ch[14] > 1490) Joystick.setButton(4, 255); else Joystick.setButton(4, 0); 70 | Joystick.sendState(); 71 | #endif 72 | } //sbus_rx.Read 73 | } 74 | -------------------------------------------------------------------------------- /sbus-to-usb-joystick/sbus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Brian R Taylor 3 | * brian.taylor@bolderflight.com 4 | * 5 | * Copyright (c) 2022 Bolder Flight Systems Inc 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the “Software”), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef SRC_SBUS_H_ 27 | #define SRC_SBUS_H_ 28 | 29 | #if defined(ARDUINO) 30 | #include 31 | #else 32 | #include 33 | #include 34 | #include "core/core.h" 35 | #endif 36 | 37 | namespace bfs { 38 | 39 | struct SbusData { 40 | bool lost_frame; 41 | bool failsafe; 42 | bool ch17, ch18; 43 | static constexpr int8_t NUM_CH = 16; 44 | int16_t ch[NUM_CH]; 45 | }; 46 | 47 | class SbusRx { 48 | public: 49 | #if defined(ESP32) 50 | SbusRx(HardwareSerial *bus, const int8_t rxpin, const int8_t txpin, 51 | const bool inv) : uart_(bus), inv_(inv), rxpin_(rxpin), txpin_(txpin) 52 | {} 53 | SbusRx(HardwareSerial *bus, const int8_t rxpin, const int8_t txpin, 54 | const bool inv, const bool fast) : uart_(bus), inv_(inv), fast_(fast), 55 | rxpin_(rxpin), txpin_(txpin) {} 56 | #else 57 | explicit SbusRx(HardwareSerial *bus) : uart_(bus) {} 58 | SbusRx(HardwareSerial *bus, const bool inv) : uart_(bus), inv_(inv) {} 59 | SbusRx(HardwareSerial *bus, const bool inv, const bool fast) : uart_(bus), 60 | inv_(inv), 61 | fast_(fast) {} 62 | #endif 63 | void Begin(); 64 | bool Read(); 65 | inline SbusData data() const {return data_;} 66 | 67 | private: 68 | /* Communication */ 69 | HardwareSerial *uart_; 70 | bool inv_ = true; 71 | bool fast_ = false; 72 | #if defined(ESP32) 73 | int8_t rxpin_, txpin_; 74 | #endif 75 | int32_t baud_ = 100000; 76 | /* Message len */ 77 | static constexpr int8_t PAYLOAD_LEN_ = 23; 78 | static constexpr int8_t HEADER_LEN_ = 1; 79 | static constexpr int8_t FOOTER_LEN_ = 1; 80 | /* SBUS message defs */ 81 | static constexpr int8_t NUM_SBUS_CH_ = 16; 82 | static constexpr uint8_t HEADER_ = 0x0F; 83 | static constexpr uint8_t FOOTER_ = 0x00; 84 | static constexpr uint8_t FOOTER2_ = 0x04; 85 | static constexpr uint8_t CH17_MASK_ = 0x01; 86 | static constexpr uint8_t CH18_MASK_ = 0x02; 87 | static constexpr uint8_t LOST_FRAME_MASK_ = 0x04; 88 | static constexpr uint8_t FAILSAFE_MASK_ = 0x08; 89 | /* Parsing state tracking */ 90 | int8_t state_ = 0; 91 | uint8_t prev_byte_ = FOOTER_; 92 | uint8_t cur_byte_; 93 | /* Buffer for storing messages */ 94 | uint8_t buf_[25]; 95 | /* Data */ 96 | bool new_data_; 97 | SbusData data_; 98 | bool Parse(); 99 | }; 100 | 101 | class SbusTx { 102 | public: 103 | #if defined(ESP32) 104 | SbusTx(HardwareSerial *bus, const int8_t rxpin, const int8_t txpin, 105 | const bool inv) : uart_(bus), inv_(inv), rxpin_(rxpin), txpin_(txpin) 106 | {} 107 | SbusTx(HardwareSerial *bus, const int8_t rxpin, const int8_t txpin, 108 | const bool inv, const bool fast) : uart_(bus), inv_(inv), fast_(fast), 109 | rxpin_(rxpin), txpin_(txpin) {} 110 | #else 111 | explicit SbusTx(HardwareSerial *bus) : uart_(bus) {} 112 | SbusTx(HardwareSerial *bus, const bool inv) : uart_(bus), inv_(inv) {} 113 | SbusTx(HardwareSerial *bus, const bool inv, const bool fast) : uart_(bus), 114 | inv_(inv), 115 | fast_(fast) {} 116 | #endif 117 | void Begin(); 118 | void Write(); 119 | inline void data(const SbusData &data) {data_ = data;} 120 | inline SbusData data() const {return data_;} 121 | 122 | private: 123 | /* Communication */ 124 | HardwareSerial *uart_; 125 | bool inv_ = true; 126 | bool fast_ = false; 127 | #if defined(ESP32) 128 | int8_t rxpin_, txpin_; 129 | #endif 130 | int32_t baud_ = 100000; 131 | /* Message len */ 132 | static constexpr int8_t BUF_LEN_ = 25; 133 | /* SBUS message defs */ 134 | static constexpr int8_t NUM_SBUS_CH_ = 16; 135 | static constexpr uint8_t HEADER_ = 0x0F; 136 | static constexpr uint8_t FOOTER_ = 0x00; 137 | static constexpr uint8_t FOOTER2_ = 0x04; 138 | static constexpr uint8_t CH17_MASK_ = 0x01; 139 | static constexpr uint8_t CH18_MASK_ = 0x02; 140 | static constexpr uint8_t LOST_FRAME_MASK_ = 0x04; 141 | static constexpr uint8_t FAILSAFE_MASK_ = 0x08; 142 | /* Data */ 143 | uint8_t buf_[BUF_LEN_]; 144 | SbusData data_; 145 | }; 146 | 147 | } // namespace bfs 148 | 149 | #endif // SRC_SBUS_H_ 150 | -------------------------------------------------------------------------------- /sigmastar/.dot: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sigmastar/ssc338q-nand.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/sigmastar/ssc338q-nand.bin -------------------------------------------------------------------------------- /sigmastar/ssc338q_initramfs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/sigmastar/ssc338q_initramfs.zip -------------------------------------------------------------------------------- /usb-eth-modem.md: -------------------------------------------------------------------------------- 1 | ## Подключение планшета или телефона по usb-ethernet устройству. 2 | 3 | Устройство являет собой сетевую карту, подключаемую по usb к планшету, и выглядит примерно так: 4 | 5 | ![usb-ethernet.png](https://github.com/OpenIPC/sandbox-fpv/raw/master/notes_files/usb-ethernet.png) 6 | 7 | Оно подключается к регистратору посредством ethernet-кабеля, после чего в [`/etc/wfb.conf`](hi3536dv100/etc/wfb.conf) указывается `udp_addr=auto` взамен фиксированного адреса. На самом планшете нужно включить функцию "Ethernet-modem" 8 | в настройках "Сеть и интернет > Точка доступа и модем". 9 | 10 | Далее все сделают сервисы [`/usr/bin/wifibroadcast`](hi3536dv100/usr/bin/wifibroadcast) и [`/usr/bin/telemetry`](hi3536dv100/usr/bin/telemetry) при загрузке регистратора или перезапуске с [front-panel](nvr_gpio.md). 11 | -------------------------------------------------------------------------------- /usb-modeswitch.md: -------------------------------------------------------------------------------- 1 | ### Установка usb_modeswitch на камеру с прошивкой fpv, lite и NVR hi3536[ed]v100 2 | 3 | Проверяем с модемом e3372h. 4 | 5 | Камера: 6 | ``` 7 | curl -o /usr/sbin/usb_modeswitch http://fpv.openipc.net/files/usb-modeswitch/musl/usb_modeswitch && chmod +x /usr/sbin/usb_modeswitch 8 | curl -o /usr/lib/libusb-1.0.so.0.3.0 http://fpv.openipc.net/files/usb-modeswitch/musl/libusb-1.0.so.0.3.0 && chmod +x /usr/lib/libusb-1.0.so.0.3.0 9 | ln -s -f /usr/lib/libusb-1.0.so.0.3.0 /usr/lib/libusb-1.0.so 10 | ln -s -f /usr/lib/libusb-1.0.so.0.3.0 /usr/lib/libusb-1.0.so.0 11 | ``` 12 | NVR: 13 | ``` 14 | ntpd -Nnq 15 | curl -k -L -o /usr/sbin/usb_modeswitch https://github.com/OpenIPC/sandbox-fpv/raw/master/usb-modeswitch/musl/usb_modeswitch && chmod +x /usr/sbin/usb_modeswitch 16 | curl -k -L -o /usr/lib/libusb-1.0.so.0.3.0 https://github.com/OpenIPC/sandbox-fpv/raw/master/usb-modeswitch/musl/libusb-1.0.so.0.3.0 && chmod +x /usr/lib/libusb-1.0.so.0.3.0 17 | ln -s -f /usr/lib/libusb-1.0.so.0.3.0 /usr/lib/libusb-1.0.so 18 | ln -s -f /usr/lib/libusb-1.0.so.0.3.0 /usr/lib/libusb-1.0.so.0 19 | ln -s -f /lib/libc-2.32.so /lib/libc.so 20 | ``` 21 | 22 | 23 |
24 | альтернативное хранилище 25 | 26 | ``` 27 | 28 | curl -o /usr/sbin/usb_modeswitch http://fpv.openipc.net/files/usb-modeswitch/glibc/usb_modeswitch && chmod +x /usr/sbin/usb_modeswitch 29 | curl -o /usr/lib/libusb-1.0.so.0.3.0 http://fpv.openipc.net/files/usb-modeswitch/glibc/libusb-1.0.so.0.3.0 && chmod +x /usr/lib/libusb-1.0.so.0.3.0 30 | ln -s -f /usr/lib/libusb-1.0.so.0.3.0 /usr/lib/libusb-1.0.so 31 | ln -s -f /usr/lib/libusb-1.0.so.0.3.0 /usr/lib/libusb-1.0.so.0 32 | ln -s -f /lib/libc-2.32.so /lib/libc.so 33 | ``` 34 |
35 | 36 | 37 | 38 | Вносим этот текст для e3372h в файл `/etc/network/interfaces.d/eth1` (создадим файл если отсутствует): 39 | ``` 40 | auto eth1 41 | iface eth1 inet dhcp 42 | pre-up sleep 4 43 | pre-up if [ ! -z "`lsusb | grep 12d1:1f01`" ]; then usb_modeswitch -v 0x12d1 -p 0x1f01 -J; fi 44 | pre-up if [ ! -z "`lsusb | grep 12d1:14dc`" ]; then modprobe usbserial vendor=0x12d1 product=0x14dc; fi 45 | pre-up modprobe rndis_host 46 | pre-up sleep 2 47 | ``` 48 | 49 | Передергиваем модем, пробуем `ifup eth1` или перезагружаем. Если сетевая поднялась (есть eth1 в `ip a`), в interfaces можем manual заменить на auto. 50 | 51 | #### Проблемы 52 | Если usb_modeswitch произвел переключение модема в cdc_ethernet, то при перезагрузке системы например через reboot интерфейс не поднимается - ошибка ip: SIOCGIFFLAGS: No such device. Поэтому если нужно полностью перегрузить систему чтобы модем заработал, нужно рвать питание модема перед перезагрузкой. 53 | 54 | ### Результат 55 | Модем e3372h с прошивкой hilink должен отобразиться сетевым интерфейсом eth1 и при вставленной работоспособной sim-карте раздавать интернет на камеру: 56 | ``` 57 | Trying to send message 1 to endpoint 0x01 ... 58 | OK, message successfully sent 59 | Read the response to message 1 (CSW) ... 60 | Device seems to have vanished after reading. Good. 61 | Device is gone, skip any further commands 62 | -> Run lsusb to note any changes. Bye! 63 | 64 | udhcpc: started, v1.36.0 65 | udhcpc: broadcasting discover 66 | udhcpc: broadcasting discover 67 | udhcpc: broadcasting discover 68 | udhcpc: broadcasting discover 69 | udhcpc: broadcasting select for 192.168.8.100, server 192.168.8.1 70 | udhcpc: lease of 192.168.8.100 obtained from 192.168.8.1, lease time 86400 71 | deleting routers 72 | adding dns 192.168.8.1 73 | adding dns 192.168.8.1 74 | OK 75 | ``` 76 | ifconfig: 77 | ``` 78 | eth1 Link encap:Ethernet HWaddr 0C:5B:8F:27:9A:64 79 | inet addr:192.168.8.100 Bcast:192.168.8.255 Mask:255.255.255.0 80 | inet6 addr: fe80::e5b:8fff:fe27:9a64/64 Scope:Link 81 | UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 82 | RX packets:34 errors:0 dropped:0 overruns:0 frame:0 83 | TX packets:806 errors:0 dropped:0 overruns:0 carrier:0 84 | collisions:0 txqueuelen:1000 85 | RX bytes:4557 (4.4 KiB) TX bytes:822513 (803.2 KiB) 86 | 87 | ``` 88 | -------------------------------------------------------------------------------- /usb-modeswitch/glibc/libusb-1.0.so.0.3.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/usb-modeswitch/glibc/libusb-1.0.so.0.3.0 -------------------------------------------------------------------------------- /usb-modeswitch/glibc/usb_modeswitch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/usb-modeswitch/glibc/usb_modeswitch -------------------------------------------------------------------------------- /usb-modeswitch/musl/libusb-1.0.so.0.3.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/usb-modeswitch/musl/libusb-1.0.so.0.3.0 -------------------------------------------------------------------------------- /usb-modeswitch/musl/usb_modeswitch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/usb-modeswitch/musl/usb_modeswitch -------------------------------------------------------------------------------- /usb-tethering.md: -------------------------------------------------------------------------------- 1 | ## Подключение смартфона или планшета на android для FPV-VR и прочих программ GS к NVR по usb 2 | 3 | USB Tethering, он же USB Ethernet - функция ОС Android для использования телефона в качестве USB-модема, представляющегося сетевой картой. Нам это дает возможность соединить телефон и NVR обычным usb-проводом и получить между ними быструю сеть. К сожалению, в большинстве случаев usb terhering доступен только на планшетах с модулем sim-карты. Если у вас его нет, и usb-модем не активируется, придется подключаться по [usb-ethernet](usb-eth-modem.md) или [wifi](note-nvr-tab-ap.md). 4 | 5 | Нужно [установить](notes_start_hi3536ev100.md#L47) [ядро](hi3536dv100/uImage.hi3536dv100) и [rootfs](hi3536dv100/rootfs.squashfs.hi3536dv100) с поддержкой rndis_host и залить [`/usr/bin/wifibroadcast`](hi3536dv100/usr/bin/wifibroadcast), [`/usr/bin/telemetry`](hi3536dv100/usr/bin/telemetry), и добавить в [`interfaces`](hi3536dv100/etc/network/interfaces) следующее: 6 | ``` 7 | #USB Tethering 8 | auto usb0 9 | iface usb0 inet dhcp 10 | pre-up modprobe rndis_host 11 | pre-up sleep 4 12 | ``` 13 | 14 | Для включения нужно: 15 | * Подключить смартфон или планшет кабелем к отключенному регистратору 16 | * Зайти в настройки - Сеть и Интернет - Точка доступа и модем 17 | * Включить регистратор 18 | * Как только в меню android появится активным пункт USB-модем, включить его. 19 | * Запустить FPV-VR, выбрать в настройках секцию Manually (stream), установить настройки видео на используемый кодек (rtp/264, rtp/265) и настройки телеметрии на mavlink. 20 | * Выйти из настроек и запустить "Start video and osd". 21 | 22 | Альтернативно, можно использовать приложение QOpenHD с аналогичным функционалом. 23 | 24 | Также доступен [вариант без перезапуска](nvr_gpio.md) регистратора. 25 | 26 | -------------------------------------------------------------------------------- /user_TipoMan/.dot: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /user_TipoMan/gkrcparams: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/user_TipoMan/gkrcparams -------------------------------------------------------------------------------- /user_TipoMan/mavfwd_mavlink2.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/user_TipoMan/mavfwd_mavlink2.tar -------------------------------------------------------------------------------- /wfb.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/wfb.zip -------------------------------------------------------------------------------- /wfbopenhd.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenIPC/sandbox-fpv/0c0325b5536ab6dce07427b58326a3b45bf2b1fe/wfbopenhd.zip --------------------------------------------------------------------------------