mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-25 17:25:18 +03:00
Merge remote-tracking branch 'origin/development' into dzikuvx-zeezf7
This commit is contained in:
commit
299f34514c
252 changed files with 3590 additions and 2033 deletions
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
.vagrant/
|
||||
obj/
|
13
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
13
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
|
@ -7,6 +7,19 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
**PLEASE MAKE SURE YOU READ AND UNDERSTAND THE SOCIAL MEDIA SUPPORT CHANNELS. QUESTIONS ABOUT FLASHING, CONFIGURING, PILOTING MAY BE CLOSED WITHOUT FURTHER INTERACTION.**
|
||||
|
||||
* [Telegram channel](https://t.me/INAVFlight)
|
||||
* [Facebook group](https://www.facebook.com/groups/INAVOfficial)
|
||||
* [RC Groups thread](https://www.rcgroups.com/forums/showthread.php?2495732-Cleanflight-iNav-%28navigation-rewrite%29-project)
|
||||
|
||||
**Please double-check that nobody reported the issue before by using search in this bug tracker.**
|
||||
|
||||
**PLEASE DELETE THE TEXT ABOVE AFTER READING AND UNDERSTANDING IT**
|
||||
|
||||
****
|
||||
|
||||
|
||||
## Current Behavior
|
||||
<!-- If applicable, add screenshots, videos and blackbox logs to help explain your problem. -->
|
||||
|
||||
|
|
23
.github/ISSUE_TEMPLATE/Question.md
vendored
23
.github/ISSUE_TEMPLATE/Question.md
vendored
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
name: "❓Question"
|
||||
about: Have a question?
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
For immediate help, just ask your question on one of the following platforms:
|
||||
|
||||
* [Telegram channel](https://t.me/INAVFlight)
|
||||
* [Facebook group](https://www.facebook.com/groups/INAVOfficial)
|
||||
* [RC Groups thread](https://www.rcgroups.com/forums/showthread.php?2495732-Cleanflight-iNav-%28navigation-rewrite%29-project)
|
||||
|
||||
You can also read public documentations or watch video tutorials:
|
||||
|
||||
* [Official documentation](https://github.com/iNavFlight/inav/tree/master/docs)
|
||||
* [Official Wiki](https://github.com/iNavFlight/inav/wiki)
|
||||
* [Video series by Painless360](https://www.youtube.com/playlist?list=PLYsWjANuAm4qdXEGFSeUhOZ10-H8YTSnH)
|
||||
* [Video series by Paweł Spychalski](https://www.youtube.com/playlist?list=PLOUQ8o2_nCLloACrA6f1_daCjhqY2x0fB)
|
||||
* [How to setup INAV on a flying wing](https://www.youtube.com/playlist?list=PLOUQ8o2_nCLn_lCX7UB2OPLzR4w5G4el3)
|
||||
* [How to setup INAV on a 5" quad](https://www.youtube.com/playlist?list=PLOUQ8o2_nCLl9M6Vm-ZNLMCr6_9yNVHQG)
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -51,7 +51,7 @@ jobs:
|
|||
uses: actions/upload-artifact@v2-preview
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}.zip
|
||||
path: ./obj/*.hex
|
||||
path: ./obj/dist/*.hex
|
||||
|
||||
test:
|
||||
needs: [build]
|
||||
|
|
|
@ -21,3 +21,6 @@ RUN mkdir -p /opt && \
|
|||
chmod -R -w "/opt/gcc-arm-none-eabi-$TOOLCHAIN_VERSION_LONG"
|
||||
|
||||
ENV PATH="/opt/gcc-arm-none-eabi-$TOOLCHAIN_VERSION_LONG/bin:$PATH"
|
||||
|
||||
RUN useradd inav
|
||||
USER inav
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# INAV - navigation capable flight controller
|
||||
|
||||
## F3 based flight controllers
|
||||
|
||||
> STM32 F3 flight controllers like Omnibus F3 or SP Racing F3 are deprecated and soon they will reach the end of support in INAV. If you are still using F3 boards, please migrate to F4 or F7.
|
||||
|
||||

|
||||

|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ For most hobby-sized airplanes roll/pitch rate limits should be in range 70-120
|
|||
|
||||
Other things to check:
|
||||
|
||||
* It's highly recommended that you fly in PASTHROUGH and trim your servo midpoints for stable flight
|
||||
* It's highly recommended that you fly in MANUAL and trim your servo midpoints for stable flight
|
||||
* Make sure you have center of gravity according to manual to your aircraft
|
||||
* Check that your failsafe activates correctly (test on the ground with propeller off for safety)
|
||||
|
||||
|
@ -54,6 +54,6 @@ The more you fly the better it will get. Let autotune analyze how your airplane
|
|||
|
||||
## Completing the tune
|
||||
|
||||
Once you have tuned reasonable PIFF parameters with AUTOTUNE you should complete the tune by switching out of AUTOTUNE to ANGLE or PASTHROUGH and landing the airplane.
|
||||
Once you have tuned reasonable PIFF parameters with AUTOTUNE you should complete the tune by switching out of AUTOTUNE to ANGLE or MANUAL and landing the airplane.
|
||||
|
||||
Note that AUTOTUNE mode doesn't automatically save parameters to EEPROM. You need to disarm and issue a [stick command](Controls.md) to save configuration parameters.
|
||||
|
|
|
@ -26,7 +26,7 @@ On the first battery connection is always advisable to use a current limiter dev
|
|||
|
||||
### Sparky
|
||||
|
||||
See the [Sparky board chapter](Board - Sparky.md).
|
||||
See the [Sparky board chapter](Board%20-%20Sparky.md).
|
||||
|
||||
## Voltage measurement
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Full details on the MATEKSYS F722-SE can be found on the Matek Website: [mateksy
|
|||
|
||||
### Integrated PDB Specs
|
||||
|
||||
* *Input:* 6-36v (3-8S LiPo) w/TVS protection
|
||||
* *Input:* 6-36v (2-8S LiPo) w/TVS protection
|
||||
* *ESC Pads:* Rated 4x30A per ESC pad set (4x46A burst)
|
||||
* Voltage Regulators:
|
||||
* *5v BEC:* 2A continuous load (3A burst)
|
||||
|
|
11
docs/Cli.md
11
docs/Cli.md
|
@ -163,7 +163,7 @@ A shorter form is also supported to enable and disable functions using `serial <
|
|||
| inav_gravity_cal_tolerance | 5 | Unarmed gravity calibration tolerance level. Won't finish the calibration until estimated gravity error falls below this value. |
|
||||
| inav_use_gps_velned | ON | Defined if iNav should use velocity data provided by GPS module for doing position and speed estimation. If set to OFF iNav will fallback to calculating velocity from GPS coordinates. Using native velocity data may improve performance on some GPS modules. Some GPS modules introduce significant delay and using native velocity may actually result in much worse performance. |
|
||||
| inav_reset_altitude | FIRST_ARM | Defines when relative estimated altitude is reset to zero. Variants - `NEVER` (once reference is acquired it's used regardless); `FIRST_ARM` (keep altitude at zero until firstly armed), `EACH_ARM` (altitude is reset to zero on each arming) |
|
||||
| inav_reset_home | EACH_ARM | Allows to chose when the home position is reset. Can help prevent resetting home position after accidental mid-air disarm. Possible values are: NEVER, FIRST_ARM and EACH_ARM |
|
||||
| inav_reset_home | FIRST_ARM | Allows to chose when the home position is reset. Can help prevent resetting home position after accidental mid-air disarm. Possible values are: NEVER, FIRST_ARM and EACH_ARM |
|
||||
| inav_max_surface_altitude | 200 | Max allowed altitude for surface following mode. [cm] |
|
||||
| inav_w_z_baro_p | 0.350 | Weight of barometer measurements in estimated altitude and climb rate |
|
||||
| inav_w_z_gps_p | 0.200 | Weight of GPS altitude measurements in estimated altitude. Setting is used only of airplanes |
|
||||
|
@ -215,6 +215,7 @@ A shorter form is also supported to enable and disable functions using `serial <
|
|||
| nav_fw_climb_angle | 20 | Max pitch angle when climbing in GPS assisted modes, is also restrained by global max_angle_inclination_pit |
|
||||
| nav_fw_dive_angle | 15 | Max negative pitch angle when diving in GPS assisted modes, is also restrained by global max_angle_inclination_pit |
|
||||
| nav_fw_pitch2thr | 10 | Amount of throttle applied related to pitch attitude in GPS assisted modes. Throttle = nav_fw_cruise_throttle - (nav_fw_pitch2thr * pitch_angle). (notice that pitch_angle is in degrees and is negative when climbing and positive when diving, and throttle value is constrained between nav_fw_min_thr and nav_fw_max_thr) |
|
||||
| nav_fw_control_smoothness | 0 | How smoothly the autopilot controls the airplane to correct the navigation error |
|
||||
| nav_fw_loiter_radius | 5000 | PosHold radius. 3000 to 7500 is a good value (30-75m) [cm] |
|
||||
| nav_fw_launch_velocity | 300 | Forward velocity threshold for swing-launch detection [cm/s] |
|
||||
| nav_fw_launch_accel | 1863 | Forward acceleration threshold for bungee launch of throw launch [cm/s/s], 1G = 981 cm/s/s |
|
||||
|
@ -231,6 +232,7 @@ A shorter form is also supported to enable and disable functions using `serial <
|
|||
| nav_fw_launch_max_altitude | 0 | Altitude (centimeters) at which LAUNCH mode will be turned off and regular flight mode will take over [0-60000]. |
|
||||
| nav_fw_land_dive_angle | 2 | Dive angle that airplane will use during final landing phase. During dive phase, motor is stopped or IDLE and roll control is locked to 0 degrees |
|
||||
| nav_fw_cruise_yaw_rate | 20 | Max YAW rate when NAV CRUISE mode is enabled (0=disable control via yaw stick) [dps]|
|
||||
| nav_use_fw_yaw_control | OFF | Enables or Disables the use of the heading PID controller on fixed wing |
|
||||
| serialrx_provider | SPEK1024 | When feature SERIALRX is enabled, this allows connection to several receivers which output data via digital interface resembling serial. See RX section. |
|
||||
| serialrx_halfduplex | OFF | Allow serial receiver to operate on UART TX pin. With some receivers will allow control and telemetry over a single wire |
|
||||
| serialrx_inverted | OFF | Reverse the serial inversion of the serial RX protocol. When this value is OFF, each protocol will use its default signal (e.g. SBUS will use an inverted signal). Some OpenLRS receivers produce a non-inverted SBUS signal. This setting supports this type of receivers (including modified FrSKY). |
|
||||
|
@ -291,6 +293,7 @@ A shorter form is also supported to enable and disable functions using `serial <
|
|||
| alt_hold_deadband | 50 | Defines the deadband of throttle during alt_hold [r/c points] |
|
||||
| yaw_motor_direction | 1 | Use if you need to inverse yaw motor direction. |
|
||||
| tri_unarmed_servo | ON | On tricopter mix only, if this is set to ON, servo will always be correcting regardless of armed state. to disable this, set it to OFF. |
|
||||
| servo_protocol | PWM | An option to chose the protocol/option that would be used to output servo data. Possible options `PWM` (FC servo outputs), `SERVO_DRIVER` (I2C PCA9685 peripheral), `SBUS` (S.Bus protocol output via a configured serial port) |
|
||||
| servo_lpf_hz | 20 | Selects the servo PWM output cutoff frequency. Value is in [Hz] |
|
||||
| servo_center_pulse | 1500 | Servo midpoint |
|
||||
| servo_pwm_rate | 50 | Output frequency (in Hz) servo pins. When using tricopters or gimbal with digital servo, this rate can be increased. Max of 498Hz (for 500Hz pwm period), and min of 50Hz. Most digital servos will support for example 330Hz. |
|
||||
|
@ -339,12 +342,15 @@ A shorter form is also supported to enable and disable functions using `serial <
|
|||
| osd_gforce_axis_alarm_max | 5 | Value above which the OSD axis g force indicators will blink (g) |
|
||||
| osd_imu_temp_alarm_min | -200 | Temperature under which the IMU temperature OSD element will start blinking (decidegrees centigrade) |
|
||||
| osd_imu_temp_alarm_max | 600 | Temperature above which the IMU temperature OSD element will start blinking (decidegrees centigrade) |
|
||||
| osd_esc_temp_alarm_min | -200 | Temperature under which the IMU temperature OSD element will start blinking (decidegrees centigrade) |
|
||||
| osd_esc_temp_alarm_max | 900 | Temperature above which the IMU temperature OSD element will start blinking (decidegrees centigrade) |
|
||||
| osd_baro_temp_alarm_min | -200 | Temperature under which the baro temperature OSD element will start blinking (decidegrees centigrade) |
|
||||
| osd_baro_temp_alarm_max | 600 | Temperature above which the baro temperature OSD element will start blinking (decidegrees centigrade) |
|
||||
| osd_current_alarm | 0 | Value above which the OSD current consumption element will start blinking. Measured in full Amperes. |
|
||||
| osd_estimations_wind_compensation | ON | Use wind estimation for remaining flight time/distance estimation |
|
||||
| osd_failsafe_switch_layout | OFF | If enabled the OSD automatically switches to the first layout during failsafe |
|
||||
| osd_temp_label_align | LEFT | Allows to chose between left and right alignment for the OSD temperature sensor labels. Valid values are `LEFT` and `RIGHT` |
|
||||
| osd_ahi_style | DEFAULT | Sets OSD Artificial Horizon style "DEFAULT" or "LINE" for the FrSky Graphical OSD. |
|
||||
| display_force_sw_blink | OFF | OFF = OSD hardware blink / ON = OSD software blink. If OSD warning text/values are invisible, try setting this to ON |
|
||||
| magzero_x | 0 | Magnetometer calibration X offset. If its 0 none offset has been applied and calibration is failed. |
|
||||
| magzero_y | 0 | Magnetometer calibration Y offset. If its 0 none offset has been applied and calibration is failed. |
|
||||
|
@ -369,6 +375,9 @@ A shorter form is also supported to enable and disable functions using `serial <
|
|||
| nav_fw_pos_xy_p | 75 | P gain of 2D trajectory PID controller. Play with this to get a straight line between waypoints or a straight RTH |
|
||||
| nav_fw_pos_xy_i | 5 | I gain of 2D trajectory PID controller. Too high and there will be overshoot in trajectory. Better start tuning with zero |
|
||||
| nav_fw_pos_xy_d | 8 | D gain of 2D trajectory PID controller. Too high and there will be overshoot in trajectory. Better start tuning with zero |
|
||||
| nav_fw_pos_hdg_p | 60 | P gain of heading PID controller. (Fixedwing) |
|
||||
| nav_fw_pos_hdg_i | 0 | I gain of heading trajectory PID controller. (Fixedwing) |
|
||||
| nav_fw_pos_hdg_d | 0 | D gain of heading trajectory PID controller. (Fixedwing) |
|
||||
| nav_mc_heading_p | 60 | P gain of Heading Hold controller (Multirotor) |
|
||||
| nav_fw_heading_p | 60 | P gain of Heading Hold controller (Fixedwing) |
|
||||
| deadband | 5 | These are values (in us) by how much RC input can be different before it's considered valid. For transmitters with jitter on outputs, this value can be increased. Defaults are zero, but can be increased up to 10 or so if rc inputs twitch while idle. |
|
||||
|
|
|
@ -26,6 +26,8 @@ _Global Functions_ (abbr. GF) are a mechanism allowing to override certain fligh
|
|||
| 5 | INVERT_PITCH | Inverts PITCH axis input for PID/PIFF controller |
|
||||
| 6 | INVERT_YAW | Inverts YAW axis input for PID/PIFF controller |
|
||||
| 7 | OVERRIDE_THROTTLE | Override throttle value that is fed to the motors by mixer. Operand is scaled in us. `1000` means throttle cut, `1500` means half throttle |
|
||||
| 8 | SET_VTX_BAND | Sets VTX band. Accepted values are `1-5` |
|
||||
| 8 | SET_VTX_CHANNEL | Sets VTX channel. Accepted values are `1-8` |
|
||||
|
||||
## Flags
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ Each servo mixing rule has the following parameters:
|
|||
| 26 | Stabilized PITCH- | Clipped between -1000 and 0 |
|
||||
| 27 | Stabilized YAW+ | Clipped between 0 and 1000 |
|
||||
| 28 | Stabilized YAW- | Clipped between -1000 and 0 |
|
||||
| 29 | One | Constant value of 500 |
|
||||
| 29 | MAX | Constant value of 500 |
|
||||
|
||||
The `smix reset` command removes all the existing motor mixing rules.
|
||||
|
||||
|
|
16
docs/Rx.md
16
docs/Rx.md
|
@ -83,6 +83,22 @@ The bug prevents use of all 16 channels. Upgrade to the latest OpenTX version t
|
|||
without the fix you are limited to 8 channels regardless of the CH1-16/D16 settings.
|
||||
|
||||
|
||||
### F.Port
|
||||
|
||||
F.Port is a protocol running on async serial allowing 16 controls channels and telemetry on a single UART.
|
||||
|
||||
Supported receivers include FrSky R-XSR, X4R, X4R-SB, XSR, XSR-M, R9M Slim, R9M Slim+, R9 Mini. For ACCST receivers you need to flash the corresponding firmware for it to output F.Port. For ACCESS receivers the protocol output from the receiver can be switched between S.Bus and F.Port from the model's setup page in the RX options.
|
||||
|
||||
#### Connection
|
||||
|
||||
Just connect the S.Port wire from the receiver to the TX pad of a free UART on your flight controller
|
||||
|
||||
#### Configuration
|
||||
|
||||
```
|
||||
set serialrx_inverted = true
|
||||
set serialrx_halfduplex = true
|
||||
```
|
||||
|
||||
### XBUS
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ The following sensors are transmitted
|
|||
* **0420** : distance to GPS home fix, in meters
|
||||
* **0430** : if `frsky_pitch_roll = ON` set this will be pitch degrees*10
|
||||
* **0440** : if `frsky_pitch_roll = ON` set this will be roll degrees*10
|
||||
|
||||
* **0450** : 'Flight Path Vector' or 'Course over ground' in degrees*10
|
||||
### Compatible SmartPort/INAV telemetry flight status
|
||||
|
||||
To quickly and easily monitor these SmartPort sensors and flight modes, install [iNav LuaTelemetry](https://github.com/iNavFlight/LuaTelemetry) to your Taranis Q X7, X9D, X9D+ or X9E transmitter.
|
||||
|
|
|
@ -1,24 +1,34 @@
|
|||
# Building with Docker
|
||||
|
||||
Building in Docker is remarkably easy.
|
||||
Building with [Docker](https://www.docker.com/) is remarkably easy: an isolated container will hold all the needed compilation tools so that they won't interfere with your system and you won't need to install and manage them by yourself. You'll only need to have Docker itself [installed](https://docs.docker.com/install/).
|
||||
|
||||
## Build a container with toolchain
|
||||
The first time that you'll run a build it will take a little more time than following executions since it will be building its base image first. Once this initial process is completed, the firmware will be always built immediately.
|
||||
|
||||
If you want to start from scratch - _even if that's rarely needed_ - delete the `inav-build` image on your system (`docker image rm inav-build`).
|
||||
|
||||
## Linux
|
||||
|
||||
In the repo's root, run:
|
||||
|
||||
```
|
||||
docker build -t inav-build .
|
||||
./build.sh <TARGET>
|
||||
```
|
||||
|
||||
## Building firmware with Docker on Ubuntu
|
||||
Where `<TARGET>` must be replaced with the name of the target that you want to build. For example:
|
||||
|
||||
Build specified target
|
||||
```
|
||||
sh build.sh SPRACINGF3
|
||||
./build.sh MATEKF405SE
|
||||
```
|
||||
|
||||
## Building firmware with Docker on Windows 10
|
||||
## Windows 10
|
||||
|
||||
Path in Docker on Windows works in a _strange_ way, so you have to provide full path for `docker run` command. For example:
|
||||
Docker on Windows requires full paths for mounting volumes in `docker run` commands. For example: `c:\Users\pspyc\Documents\Projects\inav` becomes `//c/Users/pspyc/Documents/Projects/inav` .
|
||||
|
||||
`docker run --rm -v //c/Users/pspyc/Documents/Projects/inav:/home/src/ inav-build make TARGET=AIRBOTF4`
|
||||
You'll have to manually execute the same steps that the build script does:
|
||||
|
||||
So, `c:\Users\pspyc\Documents\Projects\inav` becomes `//c/Users/pspyc/Documents/Projects/inav`
|
||||
1. `docker build -t inav-build .`
|
||||
+ This step is only needed the first time.
|
||||
2. `docker run --rm -v <PATH_TO_REPO>:/home/src/ inav-build make TARGET=<TARGET>`
|
||||
+ Where `<PATH_TO_REPO>` must be replaced with the absolute path of where you cloned this repo (see above), and `<TARGET>` with the name of the target that you want to build.
|
||||
|
||||
Refer to the [Linux](#Linux) instructions or the [build script](/build.sh) for more details.
|
|
@ -74,7 +74,7 @@ If the CLI `log_topics` is non-zero, then all topics matching the mask will be d
|
|||
|
||||
## Code usage
|
||||
|
||||
A set of macros `LOG_S()` (log system) through `LOG_D()` (log debug) may be used, subject to compile time log level constraints. These provide `printf` style logging for a given topic.
|
||||
A set of macros `LOG_E()` (log error) through `LOG_D()` (log debug) may be used, subject to compile time log level constraints. These provide `printf` style logging for a given topic.
|
||||
|
||||
```
|
||||
// LOG_D(topic, fmt, ...)
|
||||
|
|
|
@ -2,35 +2,38 @@
|
|||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
Examples of behavior that contributes to creating a positive environment include but are not limited to:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall community
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
Examples of unacceptable behavior include but are not limited to:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Publishing others’ private information, such as a physical or email address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
* Acts of unacceptable behavior on other public resources outside of but in relation to this project
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
Project maintainers and community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
Project maintainers and community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
|
@ -40,7 +43,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
|
|||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
|
@ -1,4 +1,4 @@
|
|||
# INAV New Hardware policies
|
||||
# INAV Hardware Policy
|
||||
|
||||
## General
|
||||
|
||||
|
@ -10,33 +10,42 @@ To prevent explosive growth of different target and feature count and ensure rea
|
|||
|
||||
"Hardware" - physical hardware requiring support from firmware side.
|
||||
|
||||
"Requester" - manufacturer or community member seeking addition of new hardware or target
|
||||
|
||||
## New target additions
|
||||
|
||||
New targets are accepted into INAV code if any of the following conditions is satisfied:
|
||||
|
||||
1. Board manufacturer provides specs, schematics and production samples are provided to at least two core developers. In this case the new target becomes part of official INAV release.
|
||||
1. Requester is a manufacturer of the hardware or an affiliated community member. Requester provides specs, schematics and production samples are provided to at least two core developers. In this case the new target becomes part of official INAV release.
|
||||
|
||||
2. Community member or board manufacturer provides board samples to at least one core developer and the target already exists in official Cleanflight or Betaflight firmware. In this case the new target may or may not become part of official release based on the decision made by core developers.
|
||||
2. Requester is a community member not affiliated with a manufacturer of the hardware. Requester provides board samples to at least one core developer and the target is already supported in official Cleanflight or Betaflight firmware. In this case the new target may or may not become part of official release based on the decision made by core developers.
|
||||
|
||||
# New hardware support
|
||||
3. The new target must meet the following minimal requirements:
|
||||
|
||||
* On-board sensors include at least the IMU (gyroscope + accelerometer)
|
||||
* At least 2 hardware serial ports are available with both TX and RX pins
|
||||
* At least 512K of firmware flash memory and at least of 64K of RAM available
|
||||
* At least one I2C bus broken out (SCL and SDA pins) and not shared with other functions
|
||||
|
||||
## New hardware support
|
||||
|
||||
For the hardware which does not require a new target, but still require support from the firmware side the following rules apply:
|
||||
|
||||
1. Hardware manufacturer provides specs and production samples for the unsupported hardware to at least two core developers.
|
||||
1. Requester is a manufacturer of the hardware or an affiliated community member. Requester provides specs and production samples for the unsupported hardware to at least two core developers.
|
||||
|
||||
2. Community member or hardware manufacturer provides hardware samples to at least one core developer and the firmware support already exists in official Cleanflight or Betaflight firmware.
|
||||
2. Requester is a community member not affiliated with a manufacturer of the hardware. Requester provides hardware samples to at least one core developer and the firmware support already exists in official Cleanflight or Betaflight firmware.
|
||||
|
||||
# Using own hardware exception
|
||||
## Using own hardware exception
|
||||
|
||||
If one of the core developers has the hardware in possession they may opt in and submit support for it anyway. In this case the support is not official and is generally not included in official releases.
|
||||
If one of the core developers has the hardware in possession they may opt in and submit support for it anyway. In this case the support is not official and may not be included in official releases.
|
||||
|
||||
# Providing samples to developers
|
||||
## Providing samples to developers
|
||||
|
||||
1. Hardware provided to the developers would be considered a donation to the INAV project. Under no circumstances developer will be obliged to return the hardware.
|
||||
1. Hardware provided to the developers would be considered a donation to the INAV project. Under no circumstances developer will be obliged to return the hardware or pay for it.
|
||||
|
||||
2. Manufacturer or community member providing the hardware bears all the costs of the hardware, delivery and VAT/customs duties. Hardware manufacturer also assumes the responsibility to provide up to date specs, documentation and firmware (if applicable).
|
||||
2. Requester bears all the costs of the hardware, delivery and VAT/customs duties. Hardware manufacturer also assumes the responsibility to provide up to date specs, documentation and firmware (if applicable).
|
||||
|
||||
3. Before sending samples the providing party should reach out to developers and agree on specific terms of implementing support for the unsupported hardware. Developers may place additional requirements on a case by case basis and at their sole discretion.
|
||||
3. Before sending samples the Requester should reach out to developers and agree on specific terms of implementing support for the unsupported hardware. Developers may place additional requirements on a case by case basis and at their sole discretion.
|
||||
|
||||
4. The new target and new hardware policies do not apply in the following cases. Developers may still chose to apply the "own hardware exception" at their own discretion.
|
||||
|
||||
|
@ -46,4 +55,16 @@ If one of the core developers has the hardware in possession they may opt in and
|
|||
|
||||
5. It's advised to provide more than one sample to avoid issues with damaged or dead on arrival hardware.
|
||||
|
||||
## Implementing support for the new target or hardware
|
||||
|
||||
1. Pull request to add the new target or hardware may be authored by a contributor outside INAV team or by one of the core developers.
|
||||
|
||||
2. There is no obligation to accept a pull request made by an outside contributor. INAV team reserves the right to reject that pull request and re-implement the support or take that pull request as a baseline and amend it.
|
||||
|
||||
3. INAV team reserves the right to reject the new target or hardware or remove the support for an unforeseen reason including, but not limited to violation of [INAV Code of Conduct](CODE_OF_CONDUCT.md) by the manufacturer or an affiliated outside contributor.
|
||||
|
||||
## Guidelines on contacting the team
|
||||
|
||||
1. Requester is advised to open a feature request to add support for certain hardware to INAV by following [this link](https://github.com/iNavFlight/inav/issues/new/choose)
|
||||
|
||||
2. After opening a feature request, Requester is advised to contact the core development team by [email](mailto:coredev@inavflight.com) mentioning the open feature request and communicate with developer team via email to arrange hardware and specifications delivery.
|
||||
|
|
|
@ -29,7 +29,6 @@ EXCLUDES = stm32f4xx_crc.c \
|
|||
stm32f4xx_cryp_aes.c \
|
||||
stm32f4xx_hash_md5.c \
|
||||
stm32f4xx_cryp_des.c \
|
||||
stm32f4xx_rtc.c \
|
||||
stm32f4xx_hash.c \
|
||||
stm32f4xx_dbgmcu.c \
|
||||
stm32f4xx_cryp_tdes.c \
|
||||
|
|
|
@ -37,8 +37,6 @@ EXCLUDES = stm32f7xx_hal_can.c \
|
|||
stm32f7xx_hal_nor.c \
|
||||
stm32f7xx_hal_qspi.c \
|
||||
stm32f7xx_hal_rng.c \
|
||||
stm32f7xx_hal_rtc.c \
|
||||
stm32f7xx_hal_rtc_ex.c \
|
||||
stm32f7xx_hal_sai.c \
|
||||
stm32f7xx_hal_sai_ex.c \
|
||||
stm32f7xx_hal_sd.c \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
RELEASE_TARGETS = AIRHEROF3 AIRHEROF3_QUAD
|
||||
|
||||
RELEASE_TARGETS += LUX_RACE FURYF3 FURYF3_SPIFLASH RCEXPLORERF3 RMDO SPARKY KFC32F3_INAV FALCORE MOTOLAB ANYFC BLUEJAYF4 COLIBRI F4BY DALRCF405
|
||||
RELEASE_TARGETS += LUX_RACE FURYF3 FURYF3_SPIFLASH RCEXPLORERF3 RMDO SPARKY KFC32F3_INAV FALCORE MOTOLAB ANYFC BLUEJAYF4 COLIBRI F4BY DALRCF405 DALRCF722DUAL
|
||||
RELEASE_TARGETS += QUANTON REVO SPARKY2 PIKOBLX CLRACINGF4AIR CLRACINGF4AIRV2 PIXRACER BEEROTORF4 ANYFCF7 ANYFCF7_EXTERNAL_BARO
|
||||
RELEASE_TARGETS += ALIENFLIGHTNGF7
|
||||
|
||||
|
@ -10,7 +10,7 @@ RELEASE_TARGETS += KAKUTEF4 KAKUTEF4V2 KAKUTEF7 KAKUTEF7MINI KAKUTEF7HDV
|
|||
|
||||
RELEASE_TARGETS += SPRACINGF3 SPRACINGF3EVO SPRACINGF3EVO_1SS SPRACINGF3MINI SPRACINGF4EVO SPRACINGF7DUAL
|
||||
|
||||
RELEASE_TARGETS += OMNIBUS AIRBOTF4 ASGARD32F4 ASGARD32F7 FIREWORKSV2
|
||||
RELEASE_TARGETS += OMNIBUS AIRBOTF4 ASGARD32F4 ASGARD32F7 FIREWORKSV2 AIRBOTF7 OMNIBUSF7NANOV7
|
||||
RELEASE_TARGETS += OMNIBUSF4 OMNIBUSF4PRO OMNIBUSF4PRO_LEDSTRIPM5 DYSF4PRO DYSF4PROV2
|
||||
RELEASE_TARGETS += OMNIBUSF4V3 OMNIBUSF4V3_S6_SS OMNIBUSF4V3_S5S6_SS OMNIBUSF4V3_S5_S6_2SS
|
||||
RELEASE_TARGETS += OMNIBUSF7 OMNIBUSF7V2 OMNIBUSF7NXT YUPIF7
|
||||
|
|
|
@ -44,8 +44,10 @@ COMMON_SRC = \
|
|||
drivers/exti.c \
|
||||
drivers/io.c \
|
||||
drivers/io_pca9685.c \
|
||||
drivers/irlock.c \
|
||||
drivers/light_led.c \
|
||||
drivers/osd.c \
|
||||
drivers/persistent.c \
|
||||
drivers/resource.c \
|
||||
drivers/rx_nrf24l01.c \
|
||||
drivers/rx_spi.c \
|
||||
|
@ -63,7 +65,9 @@ COMMON_SRC = \
|
|||
drivers/sound_beeper.c \
|
||||
drivers/stack_check.c \
|
||||
drivers/system.c \
|
||||
drivers/time.c \
|
||||
drivers/timer.c \
|
||||
drivers/usb_msc.c \
|
||||
drivers/lights_io.c \
|
||||
drivers/1-wire.c \
|
||||
drivers/1-wire/ds_crc.c \
|
||||
|
@ -102,6 +106,7 @@ COMMON_SRC = \
|
|||
flight/dynamic_gyro_notch.c \
|
||||
io/beeper.c \
|
||||
io/esc_serialshot.c \
|
||||
io/servo_sbus.c \
|
||||
io/frsky_osd.c \
|
||||
io/osd_dji_hd.c \
|
||||
io/lights.c \
|
||||
|
@ -128,6 +133,7 @@ COMMON_SRC = \
|
|||
rx/nrf24_syma.c \
|
||||
rx/nrf24_v202.c \
|
||||
rx/pwm.c \
|
||||
rx/frsky_crc.c \
|
||||
rx/rx.c \
|
||||
rx/rx_spi.c \
|
||||
rx/sbus.c \
|
||||
|
@ -140,13 +146,14 @@ COMMON_SRC = \
|
|||
scheduler/scheduler.c \
|
||||
sensors/acceleration.c \
|
||||
sensors/battery.c \
|
||||
sensors/temperature.c \
|
||||
sensors/boardalignment.c \
|
||||
sensors/compass.c \
|
||||
sensors/diagnostics.c \
|
||||
sensors/gyro.c \
|
||||
sensors/initialisation.c \
|
||||
sensors/esc_sensor.c \
|
||||
sensors/irlock.c \
|
||||
sensors/temperature.c \
|
||||
uav_interconnect/uav_interconnect_bus.c \
|
||||
uav_interconnect/uav_interconnect_rangefinder.c \
|
||||
blackbox/blackbox.c \
|
||||
|
@ -236,6 +243,7 @@ TARGET_SRC := $(filter-out $(MCU_EXCLUDES), $(TARGET_SRC))
|
|||
|
||||
ifneq ($(filter ONBOARDFLASH,$(FEATURES)),)
|
||||
TARGET_SRC += \
|
||||
drivers/flash.c \
|
||||
drivers/flash_m25p16.c \
|
||||
io/flashfs.c \
|
||||
$(MSC_SRC)
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#include "sensors/pitotmeter.h"
|
||||
#include "sensors/rangefinder.h"
|
||||
#include "sensors/sensors.h"
|
||||
#include "sensors/esc_sensor.h"
|
||||
#include "flight/wind_estimator.h"
|
||||
#include "sensors/temperature.h"
|
||||
|
||||
|
@ -390,6 +391,10 @@ static const blackboxSimpleFieldDefinition_t blackboxSlowFields[] = {
|
|||
{"sens6Temp", -1, SIGNED, PREDICT(0), ENCODING(SIGNED_VB)},
|
||||
{"sens7Temp", -1, SIGNED, PREDICT(0), ENCODING(SIGNED_VB)},
|
||||
#endif
|
||||
#ifdef USE_ESC_SENSOR
|
||||
{"escRPM", -1, UNSIGNED, PREDICT(0), ENCODING(UNSIGNED_VB)},
|
||||
{"escTemperature", -1, SIGNED, PREDICT(PREVIOUS), ENCODING(SIGNED_VB)},
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef enum BlackboxState {
|
||||
|
@ -498,6 +503,10 @@ typedef struct blackboxSlowState_s {
|
|||
#ifdef USE_TEMPERATURE_SENSOR
|
||||
int16_t tempSensorTemperature[MAX_TEMP_SENSORS];
|
||||
#endif
|
||||
#ifdef USE_ESC_SENSOR
|
||||
uint32_t escRPM;
|
||||
int8_t escTemperature;
|
||||
#endif
|
||||
} __attribute__((__packed__)) blackboxSlowState_t; // We pack this struct so that padding doesn't interfere with memcmp()
|
||||
|
||||
//From rc_controls.c
|
||||
|
@ -866,7 +875,7 @@ static void writeIntraframe(void)
|
|||
blackboxLoggedAnyFrames = true;
|
||||
}
|
||||
|
||||
static void blackboxWriteMainStateArrayUsingAveragePredictor(int arrOffsetInHistory, int count)
|
||||
static void blackboxWriteArrayUsingAveragePredictor16(int arrOffsetInHistory, int count)
|
||||
{
|
||||
int16_t *curr = (int16_t*) ((char*) (blackboxHistory[0]) + arrOffsetInHistory);
|
||||
int16_t *prev1 = (int16_t*) ((char*) (blackboxHistory[1]) + arrOffsetInHistory);
|
||||
|
@ -880,6 +889,20 @@ static void blackboxWriteMainStateArrayUsingAveragePredictor(int arrOffsetInHist
|
|||
}
|
||||
}
|
||||
|
||||
static void blackboxWriteArrayUsingAveragePredictor32(int arrOffsetInHistory, int count)
|
||||
{
|
||||
int32_t *curr = (int32_t*) ((char*) (blackboxHistory[0]) + arrOffsetInHistory);
|
||||
int32_t *prev1 = (int32_t*) ((char*) (blackboxHistory[1]) + arrOffsetInHistory);
|
||||
int32_t *prev2 = (int32_t*) ((char*) (blackboxHistory[2]) + arrOffsetInHistory);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
// Predictor is the average of the previous two history states
|
||||
int32_t predictor = ((int64_t)prev1[i] + (int64_t)prev2[i]) / 2;
|
||||
|
||||
blackboxWriteSignedVB(curr[i] - predictor);
|
||||
}
|
||||
}
|
||||
|
||||
static void writeInterframe(void)
|
||||
{
|
||||
blackboxMainState_t *blackboxCurrent = blackboxHistory[0];
|
||||
|
@ -1014,16 +1037,16 @@ static void writeInterframe(void)
|
|||
blackboxWriteTag8_8SVB(deltas, optionalFieldCount);
|
||||
|
||||
//Since gyros, accs and motors are noisy, base their predictions on the average of the history:
|
||||
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, gyroADC), XYZ_AXIS_COUNT);
|
||||
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, accADC), XYZ_AXIS_COUNT);
|
||||
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, attitude), XYZ_AXIS_COUNT);
|
||||
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, gyroADC), XYZ_AXIS_COUNT);
|
||||
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, accADC), XYZ_AXIS_COUNT);
|
||||
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, attitude), XYZ_AXIS_COUNT);
|
||||
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_DEBUG)) {
|
||||
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, debug), DEBUG32_VALUE_COUNT);
|
||||
blackboxWriteArrayUsingAveragePredictor32(offsetof(blackboxMainState_t, debug), DEBUG32_VALUE_COUNT);
|
||||
}
|
||||
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, motor), getMotorCount());
|
||||
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, motor), getMotorCount());
|
||||
|
||||
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_SERVOS)) {
|
||||
blackboxWriteMainStateArrayUsingAveragePredictor(offsetof(blackboxMainState_t, servo), MAX_SUPPORTED_SERVOS);
|
||||
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, servo), MAX_SUPPORTED_SERVOS);
|
||||
}
|
||||
|
||||
#ifdef NAV_BLACKBOX
|
||||
|
@ -1104,6 +1127,10 @@ static void writeSlowFrame(void)
|
|||
blackboxWriteSigned16VBArray(slowHistory.tempSensorTemperature, MAX_TEMP_SENSORS);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
blackboxWriteUnsignedVB(slowHistory.escRPM);
|
||||
blackboxWriteSignedVB(slowHistory.escTemperature);
|
||||
#endif
|
||||
blackboxSlowFrameIterationTimer = 0;
|
||||
}
|
||||
|
||||
|
@ -1156,6 +1183,11 @@ static void loadSlowState(blackboxSlowState_t *slow)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
escSensorData_t * escSensor = escSensorGetData();
|
||||
slow->escRPM = escSensor->rpm;
|
||||
slow->escTemperature = escSensor->temperature;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,5 +70,6 @@ typedef enum {
|
|||
DEBUG_NAV_YAW,
|
||||
DEBUG_DYNAMIC_FILTER,
|
||||
DEBUG_DYNAMIC_FILTER_FREQUENCY,
|
||||
DEBUG_IRLOCK,
|
||||
DEBUG_COUNT
|
||||
} debugType_e;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "config/feature.h"
|
||||
|
||||
#include "drivers/flash.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
#include "fc/config.h"
|
||||
|
@ -53,7 +54,7 @@ static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr)
|
|||
displayResync(pDisplay); // Was max7456RefreshAll(); Why at this timing?
|
||||
|
||||
flashfsEraseCompletely();
|
||||
while (!flashfsIsReady()) {
|
||||
while (!flashIsReady()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ static const OSD_Entry cmsx_menuFixedWingEntries[] =
|
|||
OSD_SETTING_ENTRY("MAX DIVE ANGLE", SETTING_NAV_FW_DIVE_ANGLE),
|
||||
OSD_SETTING_ENTRY("PITCH TO THR RATIO", SETTING_NAV_FW_PITCH2THR),
|
||||
OSD_SETTING_ENTRY("LOITER RADIUS", SETTING_NAV_FW_LOITER_RADIUS),
|
||||
OSD_SETTING_ENTRY("CONTROL SMOOTHNESS", SETTING_NAV_FW_CONTROL_SMOOTHNESS),
|
||||
|
||||
OSD_BACK_AND_END_ENTRY,
|
||||
};
|
||||
|
|
|
@ -273,6 +273,7 @@ static const OSD_Entry menuOsdElemsEntries[] =
|
|||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
OSD_ELEMENT_ENTRY("ESC RPM", OSD_ESC_RPM),
|
||||
OSD_ELEMENT_ENTRY("ESC TEMPERATURE", OSD_ESC_TEMPERATURE),
|
||||
#endif
|
||||
|
||||
OSD_BACK_AND_END_ENTRY,
|
||||
|
|
|
@ -75,6 +75,7 @@ int bitArrayFindFirstSet(const bitarrayElement_t *array, unsigned start, size_t
|
|||
const uint32_t *end = ptr + (size / 4);
|
||||
const uint32_t *p = ptr + start / (8 * 4);
|
||||
int ret;
|
||||
if (p < end) {
|
||||
// First iteration might need to mask some bits
|
||||
uint32_t mask = 0xFFFFFFFF << (start % (8 * 4));
|
||||
if ((ret = __CTZ(*p & mask)) != 32) {
|
||||
|
@ -87,5 +88,6 @@ int bitArrayFindFirstSet(const bitarrayElement_t *array, unsigned start, size_t
|
|||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ float rateLimitFilterApply4(rateLimitFilter_t *filter, float input, float rate_l
|
|||
return filter->state;
|
||||
}
|
||||
|
||||
float filterGetNotchQ(uint16_t centerFrequencyHz, uint16_t cutoffFrequencyHz)
|
||||
float filterGetNotchQ(float centerFrequencyHz, float cutoffFrequencyHz)
|
||||
{
|
||||
return centerFrequencyHz * cutoffFrequencyHz / (centerFrequencyHz * centerFrequencyHz - cutoffFrequencyHz * cutoffFrequencyHz);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ void biquadFilterInit(biquadFilter_t *filter, uint16_t filterFreq, uint32_t samp
|
|||
float biquadFilterApply(biquadFilter_t *filter, float sample);
|
||||
float biquadFilterReset(biquadFilter_t *filter, float value);
|
||||
float biquadFilterApplyDF1(biquadFilter_t *filter, float input);
|
||||
float filterGetNotchQ(uint16_t centerFrequencyHz, uint16_t cutoffFrequencyHz);
|
||||
float filterGetNotchQ(float centerFrequencyHz, float cutoffFrequencyHz);
|
||||
void biquadFilterUpdate(biquadFilter_t *filter, float filterFreq, uint32_t refreshRate, float Q, biquadFilterType_e filterType);
|
||||
|
||||
void firFilterInit(firFilter_t *filter, float *buf, uint8_t bufLength, const float *coeffs);
|
||||
|
|
|
@ -98,6 +98,22 @@ void globalFunctionsProcess(int8_t functionId) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case GLOBAL_FUNCTION_ACTION_SET_VTX_BAND:
|
||||
if (conditionValue && !previousValue) {
|
||||
vtxDeviceCapability_t vtxDeviceCapability;
|
||||
if (vtxCommonGetDeviceCapability(vtxCommonDevice(), &vtxDeviceCapability)) {
|
||||
vtxSettingsConfigMutable()->band = constrain(globalFunctionsStates[functionId].value, VTX_SETTINGS_MIN_BAND, VTX_SETTINGS_MAX_BAND);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GLOBAL_FUNCTION_ACTION_SET_VTX_CHANNEL:
|
||||
if (conditionValue && !previousValue) {
|
||||
vtxDeviceCapability_t vtxDeviceCapability;
|
||||
if (vtxCommonGetDeviceCapability(vtxCommonDevice(), &vtxDeviceCapability)) {
|
||||
vtxSettingsConfigMutable()->channel = constrain(globalFunctionsStates[functionId].value, VTX_SETTINGS_MIN_CHANNEL, VTX_SETTINGS_MAX_CHANNEL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GLOBAL_FUNCTION_ACTION_INVERT_ROLL:
|
||||
if (conditionValue) {
|
||||
GLOBAL_FUNCTION_FLAG_ENABLE(GLOBAL_FUNCTION_FLAG_OVERRIDE_INVERT_ROLL);
|
||||
|
|
|
@ -29,14 +29,16 @@
|
|||
#define MAX_GLOBAL_FUNCTIONS 8
|
||||
|
||||
typedef enum {
|
||||
GLOBAL_FUNCTION_ACTION_OVERRIDE_ARMING_SAFETY = 0,
|
||||
GLOBAL_FUNCTION_ACTION_OVERRIDE_THROTTLE_SCALE,
|
||||
GLOBAL_FUNCTION_ACTION_SWAP_ROLL_YAW,
|
||||
GLOBAL_FUNCTION_ACTION_SET_VTX_POWER_LEVEL,
|
||||
GLOBAL_FUNCTION_ACTION_INVERT_ROLL,
|
||||
GLOBAL_FUNCTION_ACTION_INVERT_PITCH,
|
||||
GLOBAL_FUNCTION_ACTION_INVERT_YAW,
|
||||
GLOBAL_FUNCTION_ACTION_OVERRIDE_THROTTLE,
|
||||
GLOBAL_FUNCTION_ACTION_OVERRIDE_ARMING_SAFETY = 0, // 0
|
||||
GLOBAL_FUNCTION_ACTION_OVERRIDE_THROTTLE_SCALE, // 1
|
||||
GLOBAL_FUNCTION_ACTION_SWAP_ROLL_YAW, // 2
|
||||
GLOBAL_FUNCTION_ACTION_SET_VTX_POWER_LEVEL, // 3
|
||||
GLOBAL_FUNCTION_ACTION_INVERT_ROLL, // 4
|
||||
GLOBAL_FUNCTION_ACTION_INVERT_PITCH, // 5
|
||||
GLOBAL_FUNCTION_ACTION_INVERT_YAW, // 6
|
||||
GLOBAL_FUNCTION_ACTION_OVERRIDE_THROTTLE, // 7
|
||||
GLOBAL_FUNCTION_ACTION_SET_VTX_BAND, // 8
|
||||
GLOBAL_FUNCTION_ACTION_SET_VTX_CHANNEL, // 9
|
||||
GLOBAL_FUNCTION_ACTION_LAST
|
||||
} globalFunctionActions_e;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "sensors/battery.h"
|
||||
#include "sensors/pitotmeter.h"
|
||||
#include "flight/imu.h"
|
||||
#include "flight/pid.h"
|
||||
|
||||
#include "navigation/navigation.h"
|
||||
#include "navigation/navigation_private.h"
|
||||
|
@ -332,6 +333,18 @@ static int logicConditionGetFlightOperandValue(int operand) {
|
|||
return (failsafePhase() == FAILSAFE_RX_LOSS_MONITORING) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case LOGIC_CONDITION_OPERAND_FLIGHT_STABILIZED_YAW: //
|
||||
return axisPID[YAW];
|
||||
break;
|
||||
|
||||
case LOGIC_CONDITION_OPERAND_FLIGHT_STABILIZED_ROLL: //
|
||||
return axisPID[ROLL];
|
||||
break;
|
||||
|
||||
case LOGIC_CONDITION_OPERAND_FLIGHT_STABILIZED_PITCH: //
|
||||
return axisPID[PITCH];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
|
|
|
@ -90,6 +90,9 @@ typedef enum {
|
|||
LOGIC_CONDITION_OPERAND_FLIGHT_IS_WP, // 0/1 // 23
|
||||
LOGIC_CONDITION_OPERAND_FLIGHT_IS_LANDING, // 0/1 // 24
|
||||
LOGIC_CONDITION_OPERAND_FLIGHT_IS_FAILSAFE, // 0/1 // 25
|
||||
LOGIC_CONDITION_OPERAND_FLIGHT_STABILIZED_ROLL, // 26
|
||||
LOGIC_CONDITION_OPERAND_FLIGHT_STABILIZED_PITCH, // 27
|
||||
LOGIC_CONDITION_OPERAND_FLIGHT_STABILIZED_YAW, // 28
|
||||
} logicFlightOperands_e;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
#define CENTIMETERS_TO_FEET(cm) (cm * (328 / 10000.0))
|
||||
#define CENTIMETERS_TO_METERS(cm) (cm / 100)
|
||||
|
||||
#define METERS_TO_CENTIMETERS(m) (m * 100)
|
||||
|
||||
// copied from https://code.google.com/p/cxutil/source/browse/include/cxutil/utility.h#70
|
||||
#define _CHOOSE2(binoper, lexpr, lvar, rexpr, rvar) \
|
||||
( __extension__ ({ \
|
||||
|
|
|
@ -31,12 +31,13 @@ void latchActiveFeatures(void)
|
|||
|
||||
bool featureConfigured(uint32_t mask)
|
||||
{
|
||||
return featureConfig()->enabledFeatures & mask;
|
||||
return (featureConfig()->enabledFeatures & mask) == mask;
|
||||
}
|
||||
|
||||
bool feature(uint32_t mask)
|
||||
{
|
||||
return activeFeaturesLatch & mask;
|
||||
// Check for ALL masked features
|
||||
return (activeFeaturesLatch & mask) == mask;
|
||||
}
|
||||
|
||||
void featureSet(uint32_t mask)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "drivers/accgyro/accgyro.h"
|
||||
#include "drivers/accgyro/accgyro_adxl345.h"
|
||||
|
||||
#ifdef USE_ACC_ADXL345
|
||||
#ifdef USE_IMU_ADXL345
|
||||
|
||||
// ADXL345, Alternative address mode 0x53
|
||||
#define ADXL345_ADDRESS 0x53
|
||||
|
@ -110,6 +110,7 @@ bool adxl345Detect(accDev_t *acc)
|
|||
|
||||
acc->initFn = adxl345Init;
|
||||
acc->readFn = adxl345Read;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "drivers/accgyro/accgyro.h"
|
||||
#include "drivers/accgyro/accgyro_bma280.h"
|
||||
|
||||
#ifdef USE_ACC_BMA280
|
||||
#ifdef USE_IMU_BMA280
|
||||
|
||||
// BMA280, default I2C address mode 0x18
|
||||
#define BMA280_WHOAMI 0x00
|
||||
|
@ -86,6 +86,7 @@ bool bma280Detect(accDev_t *acc)
|
|||
|
||||
acc->initFn = bma280Init;
|
||||
acc->readFn = bma280Read;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "drivers/accgyro/accgyro.h"
|
||||
#include "drivers/accgyro/accgyro_bmi160.h"
|
||||
|
||||
#if defined(USE_GYRO_BMI160) || defined(USE_ACC_BMI160)
|
||||
#if defined(USE_IMU_BMI160)
|
||||
|
||||
/* BMI160 Registers */
|
||||
#define BMI160_REG_CHIPID 0x00
|
||||
|
@ -270,6 +270,7 @@ bool bmi160GyroDetect(gyroDev_t *gyro)
|
|||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->temperatureFn = NULL;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "drivers/accgyro/accgyro_fake.h"
|
||||
|
||||
|
||||
#ifdef USE_FAKE_GYRO
|
||||
#ifdef USE_IMU_FAKE
|
||||
|
||||
static int16_t fakeGyroADC[XYZ_AXIS_COUNT];
|
||||
|
||||
|
@ -71,6 +71,7 @@ bool fakeGyroDetect(gyroDev_t *gyro)
|
|||
gyro->readFn = fakeGyroRead;
|
||||
gyro->temperatureFn = fakeGyroReadTemperature;
|
||||
gyro->scale = 1.0f / 16.4f;
|
||||
gyro->gyroAlign = 0;
|
||||
return true;
|
||||
}
|
||||
#endif // USE_FAKE_GYRO
|
||||
|
@ -104,6 +105,7 @@ bool fakeAccDetect(accDev_t *acc)
|
|||
{
|
||||
acc->initFn = fakeAccInit;
|
||||
acc->readFn = fakeAccRead;
|
||||
acc->accAlign = 0;
|
||||
return true;
|
||||
}
|
||||
#endif // USE_FAKE_ACC
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include "drivers/accgyro/accgyro_mpu.h"
|
||||
#include "drivers/accgyro/accgyro_icm20689.h"
|
||||
|
||||
#if (defined(USE_GYRO_ICM20689) || defined(USE_ACC_ICM20689))
|
||||
#if defined(USE_IMU_ICM20689)
|
||||
|
||||
static uint8_t icm20689DeviceDetect(const busDevice_t *busDev)
|
||||
{
|
||||
|
@ -82,6 +82,7 @@ bool icm20689AccDetect(accDev_t *acc)
|
|||
|
||||
acc->initFn = icm20689AccInit;
|
||||
acc->readFn = mpuAccReadScratchpad;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -142,6 +143,7 @@ bool icm20689GyroDetect(gyroDev_t *gyro)
|
|||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->temperatureFn = mpuTemperatureReadScratchpad;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,5 @@
|
|||
|
||||
#define ICM20689_BIT_RESET (0x80)
|
||||
|
||||
#if (defined(USE_GYRO_ICM20689) || defined(USE_ACC_ICM20689))
|
||||
|
||||
bool icm20689AccDetect(accDev_t *acc);
|
||||
bool icm20689GyroDetect(gyroDev_t *gyro);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -139,6 +139,7 @@ bool l3g4200dDetect(gyroDev_t *gyro)
|
|||
gyro->initFn = l3g4200dInit;
|
||||
gyro->readFn = l3g4200dRead;
|
||||
gyro->scale = 1.0f / 14.2857f; // 14.2857dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "drivers/accgyro/accgyro.h"
|
||||
#include "drivers/accgyro/accgyro_l3gd20.h"
|
||||
|
||||
#ifdef USE_GYRO_L3GD20
|
||||
#ifdef USE_IMU_L3GD20
|
||||
|
||||
#define READ_CMD ((uint8_t)0x80)
|
||||
#define MULTIPLEBYTE_CMD ((uint8_t)0x40)
|
||||
|
@ -116,6 +116,7 @@ bool l3gd20Detect(gyroDev_t *gyro)
|
|||
|
||||
// Page 9 in datasheet, So - Sensitivity, Full Scale = 2000, 70 mdps/digit
|
||||
gyro->scale = 0.07f;
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef USE_ACC_LSM303DLHC
|
||||
#ifdef USE_IMU_LSM303DLHC
|
||||
|
||||
#include "build/debug.h"
|
||||
|
||||
|
@ -163,6 +163,7 @@ bool lsm303dlhcAccDetect(accDev_t *acc)
|
|||
|
||||
acc->initFn = lsm303dlhcAccInit;
|
||||
acc->readFn = lsm303dlhcAccRead;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -139,5 +139,6 @@ bool mma8452Detect(accDev_t *acc)
|
|||
|
||||
acc->initFn = mma8452Init;
|
||||
acc->readFn = mma8452Read;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "drivers/accgyro/accgyro_mpu.h"
|
||||
#include "drivers/accgyro/accgyro_mpu3050.h"
|
||||
|
||||
#ifdef USE_GYRO_MPU3050
|
||||
#ifdef USE_IMU_MPU3050
|
||||
|
||||
// MPU3050, Standard address 0x68
|
||||
#define MPU3050_ADDRESS 0x68
|
||||
|
@ -131,6 +131,7 @@ bool mpu3050Detect(gyroDev_t *gyro)
|
|||
gyro->readFn = mpu3050GyroRead;
|
||||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "drivers/accgyro/accgyro_mpu.h"
|
||||
#include "drivers/accgyro/accgyro_mpu6000.h"
|
||||
|
||||
#if (defined(USE_GYRO_MPU6000) || defined(USE_ACC_MPU6000))
|
||||
#if defined(USE_IMU_MPU6000)
|
||||
|
||||
// Bits
|
||||
#define BIT_H_RESET 0x80
|
||||
|
@ -150,6 +150,7 @@ bool mpu6000AccDetect(accDev_t *acc)
|
|||
|
||||
acc->initFn = mpu6000AccInit;
|
||||
acc->readFn = mpuAccReadScratchpad;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -218,6 +219,7 @@ bool mpu6000GyroDetect(gyroDev_t *gyro)
|
|||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->temperatureFn = mpuTemperatureReadScratchpad;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "drivers/accgyro/accgyro_mpu.h"
|
||||
#include "drivers/accgyro/accgyro_mpu6050.h"
|
||||
|
||||
#if defined(USE_GYRO_MPU6050) || defined(USE_ACC_MPU6050)
|
||||
#if defined(USE_IMU_MPU6050)
|
||||
|
||||
#define BIT_H_RESET 0x80
|
||||
#define MPU_CLK_SEL_PLLGYROZ 0x03
|
||||
|
@ -127,6 +127,7 @@ bool mpu6050AccDetect(accDev_t *acc)
|
|||
if (ctx->chipMagicNumber == 0x6850 || ctx->chipMagicNumber == 0x6050) {
|
||||
acc->initFn = mpu6050AccInit;
|
||||
acc->readFn = mpuAccReadScratchpad;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -213,6 +214,7 @@ bool mpu6050GyroDetect(gyroDev_t *gyro)
|
|||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->temperatureFn = mpuTemperatureReadScratchpad;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "drivers/accgyro/accgyro_mpu.h"
|
||||
#include "drivers/accgyro/accgyro_mpu6500.h"
|
||||
|
||||
#if defined(USE_GYRO_MPU6500) || defined(USE_ACC_MPU6500)
|
||||
#if defined(USE_IMU_MPU6500)
|
||||
|
||||
#define MPU6500_BIT_RESET (0x80)
|
||||
#define MPU6500_BIT_INT_ANYRD_2CLEAR (1 << 4)
|
||||
|
@ -60,6 +60,7 @@ bool mpu6500AccDetect(accDev_t *acc)
|
|||
|
||||
acc->initFn = mpu6500AccInit;
|
||||
acc->readFn = mpuAccReadScratchpad;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -163,6 +164,7 @@ bool mpu6500GyroDetect(gyroDev_t *gyro)
|
|||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->temperatureFn = mpuTemperatureReadScratchpad;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "drivers/accgyro/accgyro_mpu.h"
|
||||
#include "drivers/accgyro/accgyro_mpu9250.h"
|
||||
|
||||
#if defined(USE_GYRO_MPU9250) || defined(USE_ACC_MPU9250)
|
||||
#if defined(USE_IMU_MPU9250)
|
||||
|
||||
#define MPU9250_BIT_RESET (0x80)
|
||||
#define MPU9250_BIT_INT_ANYRD_2CLEAR (1 << 4)
|
||||
|
@ -60,6 +60,7 @@ bool mpu9250AccDetect(accDev_t *acc)
|
|||
|
||||
acc->initFn = mpu9250AccInit;
|
||||
acc->readFn = mpuAccReadScratchpad;
|
||||
acc->accAlign = acc->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -163,6 +164,7 @@ bool mpu9250GyroDetect(gyroDev_t *gyro)
|
|||
gyro->intStatusFn = gyroCheckDataReady;
|
||||
gyro->temperatureFn = mpuTemperatureReadScratchpad;
|
||||
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
|
||||
gyro->gyroAlign = gyro->busDev->param;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "drivers/bus.h"
|
||||
#include "drivers/io.h"
|
||||
|
||||
#define BUSDEV_MAX_DEVICES 8
|
||||
#define BUSDEV_MAX_DEVICES 16
|
||||
|
||||
#ifdef USE_SPI
|
||||
static void busDevPreInit_SPI(const busDeviceDescriptor_t * descriptor)
|
||||
|
@ -124,6 +124,7 @@ busDevice_t * busDeviceInit(busType_e bus, devHardwareType_e hw, uint8_t tag, re
|
|||
dev->descriptorPtr = descriptor;
|
||||
dev->busType = descriptor->busType;
|
||||
dev->flags = descriptor->flags;
|
||||
dev->param = descriptor->param;
|
||||
|
||||
switch (descriptor->busType) {
|
||||
default:
|
||||
|
|
|
@ -143,11 +143,14 @@ typedef enum {
|
|||
DEVHW_M25P16, // SPI NOR flash
|
||||
DEVHW_UG2864, // I2C OLED display
|
||||
DEVHW_SDCARD, // Generic SD-Card
|
||||
DEVHW_IRLOCK, // IR-Lock visual positioning hardware
|
||||
} devHardwareType_e;
|
||||
|
||||
typedef enum {
|
||||
DEVFLAGS_NONE = 0,
|
||||
DEVFLAGS_USE_RAW_REGISTERS = (1 << 0), // Don't manipulate MSB for R/W selection (SPI), allow using 0xFF register to raw i2c reads/writes
|
||||
|
||||
// SPI-only
|
||||
DEVFLAGS_USE_MANUAL_DEVICE_SELECT = (1 << 1), // (SPI only) Don't automatically select/deselect device
|
||||
DEVFLAGS_SPI_MODE_0 = (1 << 2), // (SPI only) Use CPOL=0/CPHA=0 (if unset MODE3 is used - CPOL=1/CPHA=1)
|
||||
} deviceFlags_e;
|
||||
|
@ -156,8 +159,9 @@ typedef struct busDeviceDescriptor_s {
|
|||
void * devicePtr;
|
||||
busType_e busType;
|
||||
devHardwareType_e devHwType;
|
||||
uint16_t flags;
|
||||
uint8_t flags;
|
||||
uint8_t tag;
|
||||
uint8_t param; // Driver-specific parameter
|
||||
union {
|
||||
#ifdef USE_SPI
|
||||
struct {
|
||||
|
@ -179,6 +183,7 @@ typedef struct busDevice_s {
|
|||
const busDeviceDescriptor_t * descriptorPtr;
|
||||
busType_e busType; // Copy of busType to avoid additional pointer dereferencing
|
||||
uint32_t flags; // Copy of flags
|
||||
uint32_t param; // Copy of param
|
||||
union {
|
||||
#ifdef USE_SPI
|
||||
struct {
|
||||
|
@ -209,7 +214,7 @@ extern const busDeviceDescriptor_t __busdev_registry_end[];
|
|||
#define BUSDEV_REGISTER_ATTRIBUTES __attribute__ ((section(".busdev_registry"), used, aligned(4)))
|
||||
#endif
|
||||
|
||||
#define BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags) \
|
||||
#define BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param) \
|
||||
extern const busDeviceDescriptor_t _name ## _registry; \
|
||||
static busDevice_t _name ## _memory; \
|
||||
const busDeviceDescriptor_t _name ## _registry BUSDEV_REGISTER_ATTRIBUTES = { \
|
||||
|
@ -218,6 +223,7 @@ extern const busDeviceDescriptor_t __busdev_registry_end[];
|
|||
.devHwType = _devHw, \
|
||||
.flags = _flags, \
|
||||
.tag = _tag, \
|
||||
.param = _param, \
|
||||
.busdev.spi = { \
|
||||
.spiBus = _spiBus, \
|
||||
.csnPin = IO_TAG(_csnPin) \
|
||||
|
@ -227,7 +233,7 @@ extern const busDeviceDescriptor_t __busdev_registry_end[];
|
|||
struct _dummy \
|
||||
/**/
|
||||
|
||||
#define BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags) \
|
||||
#define BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param) \
|
||||
extern const busDeviceDescriptor_t _name ## _registry; \
|
||||
static busDevice_t _name ## _memory; \
|
||||
const busDeviceDescriptor_t _name ## _registry BUSDEV_REGISTER_ATTRIBUTES = { \
|
||||
|
@ -236,6 +242,7 @@ extern const busDeviceDescriptor_t __busdev_registry_end[];
|
|||
.devHwType = _devHw, \
|
||||
.flags = _flags, \
|
||||
.tag = _tag, \
|
||||
.param = _param, \
|
||||
.busdev.i2c = { \
|
||||
.i2cBus = _i2cBus, \
|
||||
.address = _devAddr \
|
||||
|
@ -245,17 +252,17 @@ extern const busDeviceDescriptor_t __busdev_registry_end[];
|
|||
struct _dummy \
|
||||
/**/
|
||||
|
||||
#define BUSDEV_REGISTER_SPI(_name, _devHw, _spiBus, _csnPin, _irqPin, _flags) \
|
||||
BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, 0, _flags)
|
||||
#define BUSDEV_REGISTER_SPI(_name, _devHw, _spiBus, _csnPin, _irqPin, _flags, _param) \
|
||||
BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, 0, _flags, _param)
|
||||
|
||||
#define BUSDEV_REGISTER_SPI_TAG(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags) \
|
||||
BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags)
|
||||
#define BUSDEV_REGISTER_SPI_TAG(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param) \
|
||||
BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param)
|
||||
|
||||
#define BUSDEV_REGISTER_I2C(_name, _devHw, _i2cBus, _devAddr, _irqPin, _flags) \
|
||||
BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, 0, _flags)
|
||||
#define BUSDEV_REGISTER_I2C(_name, _devHw, _i2cBus, _devAddr, _irqPin, _flags, _param) \
|
||||
BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, 0, _flags, _param)
|
||||
|
||||
#define BUSDEV_REGISTER_I2C_TAG(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags) \
|
||||
BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags)
|
||||
#define BUSDEV_REGISTER_I2C_TAG(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param)\
|
||||
BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param)
|
||||
|
||||
|
||||
// busTransfer and busTransferMultiple are supported only on full-duplex SPI bus
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include "drivers/compass/compass.h"
|
||||
#include "drivers/compass/compass_mpu9250.h"
|
||||
|
||||
#if defined(USE_MAG_MPU9250) && defined(USE_GYRO_MPU9250)
|
||||
#if defined(USE_MAG_MPU9250) && defined(USE_IMU_MPU9250)
|
||||
|
||||
// No separate hardware descriptor needed. Hardware descriptor initialization is handled by GYRO driver
|
||||
|
||||
|
|
|
@ -192,9 +192,9 @@ int displayWriteCharWithAttr(displayPort_t *instance, uint8_t x, uint8_t y, uint
|
|||
return -1;
|
||||
}
|
||||
if (displayAttributesRequireEmulation(instance, attr)) {
|
||||
char ec;
|
||||
if (displayEmulateTextAttributes(instance, &ec, 1, &attr)) {
|
||||
c = ec;
|
||||
char ec[2];
|
||||
if (displayEmulateTextAttributes(instance, ec, 1, &attr)) {
|
||||
c = ec[0];
|
||||
}
|
||||
}
|
||||
instance->posX = x + 1;
|
||||
|
@ -317,4 +317,3 @@ void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable)
|
|||
instance->maxChar = 0;
|
||||
displayUpdateMaxChar(instance);
|
||||
}
|
||||
|
||||
|
|
292
src/main/drivers/flash.c
Normal file
292
src/main/drivers/flash.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* This file is part of iNav.
|
||||
*
|
||||
* iNav is free software. You can redistribute
|
||||
* this software and/or modify this software under the terms of the
|
||||
* GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* iNav is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software.
|
||||
*
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "build/debug.h"
|
||||
|
||||
#ifdef USE_FLASHFS
|
||||
|
||||
#include "flash.h"
|
||||
#include "flash_m25p16.h"
|
||||
#include "drivers/bus_spi.h"
|
||||
#include "drivers/io.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
static flashPartitionTable_t flashPartitionTable;
|
||||
static int flashPartitions = 0;
|
||||
|
||||
#ifdef USE_SPI
|
||||
static bool flashSpiInit(void)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_init(0);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif // USE_SPI
|
||||
|
||||
bool flashDeviceInit(void)
|
||||
{
|
||||
#ifdef USE_SPI
|
||||
return flashSpiInit();
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool flashIsReady(void)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_isReady();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool flashWaitForReady(uint32_t timeoutMillis)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_waitForReady(timeoutMillis);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void flashEraseSector(uint32_t address)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_eraseSector(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flashEraseCompletely(void)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_eraseCompletely();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
void flashPageProgramBegin(uint32_t address)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_pageProgramBegin(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flashPageProgramContinue(const uint8_t *data, int length)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_pageProgramContinue(data, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flashPageProgramFinish(void)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_pageProgramFinish();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t flashPageProgram(uint32_t address, const uint8_t *data, int length)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_pageProgram(address, data, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
int flashReadBytes(uint32_t address, uint8_t *buffer, int length)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_readBytes(address, buffer, length);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flashFlush(void)
|
||||
{
|
||||
}
|
||||
|
||||
const flashGeometry_t *flashGetGeometry(void)
|
||||
{
|
||||
#ifdef USE_FLASH_M25P16
|
||||
return m25p16_getGeometry();
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash partitioning
|
||||
*
|
||||
* Partition table is not currently stored on the flash, in-memory only.
|
||||
*
|
||||
* Partitions are required so that Badblock management (inc spare blocks), FlashFS (Blackbox Logging), Configuration and Firmware can be kept separate and tracked.
|
||||
*
|
||||
* XXX FIXME
|
||||
* XXX Note that Flash FS must start at sector 0.
|
||||
* XXX There is existing blackbox/flash FS code the relies on this!!!
|
||||
* XXX This restriction can and will be fixed by creating a set of flash operation functions that take partition as an additional parameter.
|
||||
*/
|
||||
|
||||
static __attribute__((unused)) void createPartition(flashPartitionType_e type, uint32_t size, flashSector_t *endSector)
|
||||
{
|
||||
const flashGeometry_t *flashGeometry = flashGetGeometry();
|
||||
flashSector_t partitionSectors = (size / flashGeometry->sectorSize);
|
||||
|
||||
if (size % flashGeometry->sectorSize > 0) {
|
||||
partitionSectors++; // needs a portion of a sector.
|
||||
}
|
||||
|
||||
flashSector_t startSector = (*endSector + 1) - partitionSectors; // + 1 for inclusive
|
||||
|
||||
flashPartitionSet(type, startSector, *endSector);
|
||||
|
||||
*endSector = startSector - 1;
|
||||
}
|
||||
|
||||
static void flashConfigurePartitions(void)
|
||||
{
|
||||
const flashGeometry_t *flashGeometry = flashGetGeometry();
|
||||
if (flashGeometry->totalSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
flashSector_t startSector = 0;
|
||||
flashSector_t endSector = flashGeometry->sectors - 1; // 0 based index
|
||||
|
||||
const flashPartition_t *badBlockPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_BADBLOCK_MANAGEMENT);
|
||||
if (badBlockPartition) {
|
||||
endSector = badBlockPartition->startSector - 1;
|
||||
}
|
||||
|
||||
#if defined(FIRMWARE_SIZE)
|
||||
createPartition(FLASH_PARTITION_TYPE_FIRMWARE, FIRMWARE_SIZE*1024, &endSector);
|
||||
#endif
|
||||
|
||||
#if defined(MSP_FIRMWARE_UPDATE)
|
||||
createPartition(FLASH_PARTITION_TYPE_FIRMWARE_UPDATE_META, flashGeometry->sectorSize, &endSector);
|
||||
createPartition(FLASH_PARTITION_TYPE_UPDATE_FIRMWARE, FLASH_SIZE*1024, &endSector);
|
||||
createPartition(FLASH_PARTITION_TYPE_FULL_BACKUP, FLASH_SIZE*1024, &endSector);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IN_EXTERNAL_FLASH)
|
||||
createPartition(FLASH_PARTITION_TYPE_CONFIG, EEPROM_SIZE, &endSector);
|
||||
#endif
|
||||
|
||||
#ifdef USE_FLASHFS
|
||||
flashPartitionSet(FLASH_PARTITION_TYPE_FLASHFS, startSector, endSector);
|
||||
#endif
|
||||
}
|
||||
|
||||
flashPartition_t *flashPartitionFindByType(uint8_t type)
|
||||
{
|
||||
for (int index = 0; index < FLASH_MAX_PARTITIONS; index++) {
|
||||
flashPartition_t *candidate = &flashPartitionTable.partitions[index];
|
||||
if (candidate->type == type) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const flashPartition_t *flashPartitionFindByIndex(uint8_t index)
|
||||
{
|
||||
if (index >= flashPartitions) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &flashPartitionTable.partitions[index];
|
||||
}
|
||||
|
||||
void flashPartitionSet(uint8_t type, uint32_t startSector, uint32_t endSector)
|
||||
{
|
||||
flashPartition_t *entry = flashPartitionFindByType(type);
|
||||
|
||||
if (!entry) {
|
||||
if (flashPartitions == FLASH_MAX_PARTITIONS - 1) {
|
||||
return;
|
||||
}
|
||||
entry = &flashPartitionTable.partitions[flashPartitions++];
|
||||
}
|
||||
|
||||
entry->type = type;
|
||||
entry->startSector = startSector;
|
||||
entry->endSector = endSector;
|
||||
}
|
||||
|
||||
// Must be in sync with FLASH_PARTITION_TYPE
|
||||
static const char *flashPartitionNames[] = {
|
||||
"UNKNOWN ",
|
||||
"PARTITION",
|
||||
"FLASHFS ",
|
||||
"BBMGMT ",
|
||||
"FIRMWARE ",
|
||||
"CONFIG ",
|
||||
"FW UPDT ",
|
||||
};
|
||||
|
||||
const char *flashPartitionGetTypeName(flashPartitionType_e type)
|
||||
{
|
||||
if (type < ARRAYLEN(flashPartitionNames)) {
|
||||
return flashPartitionNames[type];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool flashInit(void)
|
||||
{
|
||||
memset(&flashPartitionTable, 0x00, sizeof(flashPartitionTable));
|
||||
|
||||
bool haveFlash = flashDeviceInit();
|
||||
|
||||
flashConfigurePartitions();
|
||||
|
||||
return haveFlash;
|
||||
}
|
||||
|
||||
int flashPartitionCount(void)
|
||||
{
|
||||
return flashPartitions;
|
||||
}
|
||||
|
||||
uint32_t flashPartitionSize(flashPartition_t *partition)
|
||||
{
|
||||
const flashGeometry_t * const geometry = flashGetGeometry();
|
||||
return (partition->endSector - partition->startSector + 1) * geometry->sectorSize;
|
||||
}
|
||||
|
||||
void flashPartitionErase(flashPartition_t *partition)
|
||||
{
|
||||
const flashGeometry_t * const geometry = flashGetGeometry();
|
||||
|
||||
for (unsigned i = partition->startSector; i <= partition->endSector; i++) {
|
||||
uint32_t flashAddress = geometry->sectorSize * i;
|
||||
flashEraseSector(flashAddress);
|
||||
flashWaitForReady(0);
|
||||
}
|
||||
}
|
||||
#endif // USE_FLASH_CHIP
|
|
@ -1,31 +1,94 @@
|
|||
/*
|
||||
* This file is part of Cleanflight.
|
||||
* This file is part of iNav.
|
||||
*
|
||||
* Cleanflight is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* iNav is free software. You can redistribute
|
||||
* this software and/or modify this software under the terms of the
|
||||
* GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* Cleanflight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* iNav is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with this software.
|
||||
*
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//#include "drivers/io.h"
|
||||
|
||||
//#ifdef USE_FLASHFS
|
||||
|
||||
typedef uint16_t flashSector_t;
|
||||
|
||||
typedef struct flashGeometry_s {
|
||||
uint16_t sectors; // Count of the number of erasable blocks on the device
|
||||
|
||||
uint16_t pagesPerSector;
|
||||
const uint16_t pageSize; // In bytes
|
||||
|
||||
flashSector_t sectors; // Count of the number of erasable blocks on the device
|
||||
uint16_t pageSize; // In bytes
|
||||
uint32_t sectorSize; // This is just pagesPerSector * pageSize
|
||||
|
||||
uint32_t totalSize; // This is just sectorSize * sectors
|
||||
uint16_t pagesPerSector;
|
||||
} flashGeometry_t;
|
||||
|
||||
bool flashInit(void);
|
||||
|
||||
bool flashIsReady(void);
|
||||
bool flashWaitForReady(uint32_t timeoutMillis);
|
||||
void flashEraseSector(uint32_t address);
|
||||
void flashEraseCompletely(void);
|
||||
#if 0
|
||||
void flashPageProgramBegin(uint32_t address);
|
||||
void flashPageProgramContinue(const uint8_t *data, int length);
|
||||
void flashPageProgramFinish(void);
|
||||
#endif
|
||||
uint32_t flashPageProgram(uint32_t address, const uint8_t *data, int length);
|
||||
int flashReadBytes(uint32_t address, uint8_t *buffer, int length);
|
||||
void flashFlush(void);
|
||||
const flashGeometry_t *flashGetGeometry(void);
|
||||
|
||||
//
|
||||
// flash partitioning api
|
||||
//
|
||||
|
||||
typedef struct flashPartition_s {
|
||||
uint8_t type;
|
||||
flashSector_t startSector;
|
||||
flashSector_t endSector;
|
||||
} flashPartition_t;
|
||||
|
||||
#define FLASH_PARTITION_SECTOR_COUNT(partition) (partition->endSector + 1 - partition->startSector) // + 1 for inclusive, start and end sector can be the same sector.
|
||||
|
||||
// Must be in sync with flashPartitionTypeNames[]
|
||||
// Should not be deleted or reordered once the code is writing a table to a flash.
|
||||
typedef enum {
|
||||
FLASH_PARTITION_TYPE_UNKNOWN = 0,
|
||||
FLASH_PARTITION_TYPE_PARTITION_TABLE,
|
||||
FLASH_PARTITION_TYPE_FLASHFS,
|
||||
FLASH_PARTITION_TYPE_BADBLOCK_MANAGEMENT,
|
||||
FLASH_PARTITION_TYPE_FIRMWARE,
|
||||
FLASH_PARTITION_TYPE_CONFIG,
|
||||
FLASH_PARTITION_TYPE_FULL_BACKUP,
|
||||
FLASH_PARTITION_TYPE_FIRMWARE_UPDATE_META,
|
||||
FLASH_PARTITION_TYPE_UPDATE_FIRMWARE,
|
||||
FLASH_MAX_PARTITIONS
|
||||
} flashPartitionType_e;
|
||||
|
||||
typedef struct flashPartitionTable_s {
|
||||
flashPartition_t partitions[FLASH_MAX_PARTITIONS];
|
||||
} flashPartitionTable_t;
|
||||
|
||||
void flashPartitionSet(uint8_t index, uint32_t startSector, uint32_t endSector);
|
||||
flashPartition_t *flashPartitionFindByType(flashPartitionType_e type);
|
||||
const flashPartition_t *flashPartitionFindByIndex(uint8_t index);
|
||||
const char *flashPartitionGetTypeName(flashPartitionType_e type);
|
||||
int flashPartitionCount(void);
|
||||
uint32_t flashPartitionSize(flashPartition_t *partition);
|
||||
void flashPartitionErase(flashPartition_t *partition);
|
||||
|
||||
//#endif [> USE_FLASHFS <]
|
||||
|
|
|
@ -118,7 +118,7 @@ bool m25p16_waitForReady(uint32_t timeoutMillis)
|
|||
{
|
||||
uint32_t time = millis();
|
||||
while (!m25p16_isReady()) {
|
||||
if (millis() - time > timeoutMillis) {
|
||||
if (timeoutMillis && (millis() - time > timeoutMillis)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
88
src/main/drivers/irlock.c
Normal file
88
src/main/drivers/irlock.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* This file is part of iNav.
|
||||
*
|
||||
* iNav is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iNav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "drivers/sensor.h"
|
||||
#include "drivers/irlock.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
#define IRLOCK_OBJECT_SYNC ((uint16_t)0xaa55)
|
||||
#define IRLOCK_FRAME_SYNC ((uint32_t)(IRLOCK_OBJECT_SYNC | (IRLOCK_OBJECT_SYNC << 16)))
|
||||
|
||||
|
||||
#if defined(USE_NAV) && defined(USE_IRLOCK)
|
||||
|
||||
static bool irlockHealthy = false;
|
||||
|
||||
static bool irlockFrameSync(irlockDev_t *irlockDev)
|
||||
{
|
||||
uint32_t sync_word = 0;
|
||||
uint8_t count = 10;
|
||||
while (count-- && sync_word != IRLOCK_FRAME_SYNC) {
|
||||
uint8_t sync_byte;
|
||||
irlockHealthy = busRead(irlockDev->busDev, 0xFF, &sync_byte);
|
||||
if (!(irlockHealthy && sync_byte)) return false;
|
||||
sync_word = (sync_word >> 8) | (((uint32_t)sync_byte) << 24);
|
||||
}
|
||||
return sync_word == IRLOCK_FRAME_SYNC;
|
||||
}
|
||||
|
||||
static bool irlockRead(irlockDev_t *irlockDev, irlockData_t *irlockData)
|
||||
{
|
||||
if (irlockFrameSync(irlockDev) && busReadBuf(irlockDev->busDev, 0xFF, (void*)irlockData, sizeof(*irlockData))) {
|
||||
uint16_t cksum = irlockData->signature + irlockData->posX + irlockData->posY + irlockData->sizeX + irlockData->sizeY;
|
||||
if (irlockData->cksum == cksum) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool deviceDetect(irlockDev_t *irlockDev)
|
||||
{
|
||||
uint8_t buf;
|
||||
bool detected = busRead(irlockDev->busDev, 0xFF, &buf);
|
||||
return !!detected;
|
||||
}
|
||||
|
||||
bool irlockDetect(irlockDev_t *irlockDev)
|
||||
{
|
||||
irlockDev->busDev = busDeviceInit(BUSTYPE_I2C, DEVHW_IRLOCK, 0, OWNER_IRLOCK);
|
||||
if (irlockDev->busDev == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!deviceDetect(irlockDev)) {
|
||||
busDeviceDeInit(irlockDev->busDev);
|
||||
return false;
|
||||
}
|
||||
|
||||
irlockDev->read = irlockRead;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool irlockIsHealthy(void)
|
||||
{
|
||||
return irlockHealthy;
|
||||
}
|
||||
|
||||
#endif /* USE_IRLOCK */
|
45
src/main/drivers/irlock.h
Normal file
45
src/main/drivers/irlock.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This file is part of iNav.
|
||||
*
|
||||
* iNav is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iNav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "drivers/sensor.h"
|
||||
#include "drivers/io_types.h"
|
||||
|
||||
#if defined(USE_NAV) && defined(USE_IRLOCK)
|
||||
|
||||
#define IRLOCK_RES_X 320
|
||||
#define IRLOCK_RES_Y 200
|
||||
|
||||
typedef struct {
|
||||
uint16_t cksum;
|
||||
uint16_t signature;
|
||||
uint16_t posX;
|
||||
uint16_t posY;
|
||||
uint16_t sizeX;
|
||||
uint16_t sizeY;
|
||||
} irlockData_t;
|
||||
|
||||
typedef struct irlockDev_s {
|
||||
busDevice_t *busDev;
|
||||
bool (*read)(struct irlockDev_s *irlockDev, irlockData_t *irlockData);
|
||||
} irlockDev_t;
|
||||
|
||||
bool irlockDetect(irlockDev_t *irlockDev);
|
||||
bool irlockIsHealthy(void);
|
||||
|
||||
#endif /* USE_IRLOCK */
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#include "platform.h"
|
||||
|
||||
FILE_COMPILE_FOR_SPEED
|
||||
|
||||
#ifdef USE_MAX7456
|
||||
|
||||
#include "common/bitarray.h"
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
#define SYM_BARO_TEMP 0xF0 // 240
|
||||
#define SYM_IMU_TEMP 0xF1 // 241
|
||||
#define SYM_TEMP 0xF2 // 242
|
||||
#define SYM_ESC_TEMP 0xF3 // 243
|
||||
|
||||
#define SYM_TEMP_SENSOR_FIRST 0xF2 // 242
|
||||
#define SYM_TEMP_SENSOR_LAST 0xF7 // 247
|
||||
|
|
119
src/main/drivers/persistent.c
Normal file
119
src/main/drivers/persistent.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* This file is part of iNav.
|
||||
*
|
||||
* iNav free software. You can redistribute
|
||||
* this software and/or modify this software under the terms of the
|
||||
* GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* iNav distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software.
|
||||
*
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* An implementation of persistent data storage utilizing RTC backup data register.
|
||||
* Retains values written across software resets and boot loader activities.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
|
||||
#include "drivers/persistent.h"
|
||||
#include "drivers/system.h"
|
||||
|
||||
#define PERSISTENT_OBJECT_MAGIC_VALUE (('i' << 24)|('N' << 16)|('a' << 8)|('v' << 0))
|
||||
|
||||
#ifdef USE_HAL_DRIVER
|
||||
|
||||
uint32_t persistentObjectRead(persistentObjectId_e id)
|
||||
{
|
||||
RTC_HandleTypeDef rtcHandle = { .Instance = RTC };
|
||||
|
||||
uint32_t value = HAL_RTCEx_BKUPRead(&rtcHandle, id);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void persistentObjectWrite(persistentObjectId_e id, uint32_t value)
|
||||
{
|
||||
RTC_HandleTypeDef rtcHandle = { .Instance = RTC };
|
||||
|
||||
HAL_RTCEx_BKUPWrite(&rtcHandle, id, value);
|
||||
}
|
||||
|
||||
void persistentObjectRTCEnable(void)
|
||||
{
|
||||
RTC_HandleTypeDef rtcHandle = { .Instance = RTC };
|
||||
|
||||
#if !defined(STM32H7)
|
||||
__HAL_RCC_PWR_CLK_ENABLE(); // Enable Access to PWR
|
||||
#endif
|
||||
HAL_PWR_EnableBkUpAccess(); // Disable backup domain protection
|
||||
|
||||
#if defined(__HAL_RCC_RTC_CLK_ENABLE)
|
||||
// For those MCUs with RTCAPBEN bit in RCC clock enable register, turn it on.
|
||||
__HAL_RCC_RTC_CLK_ENABLE(); // Enable RTC module
|
||||
#endif
|
||||
|
||||
// We don't need a clock source for RTC itself. Skip it.
|
||||
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(&rtcHandle); // Reset sequence
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(&rtcHandle); // Apply sequence
|
||||
}
|
||||
|
||||
#else
|
||||
uint32_t persistentObjectRead(persistentObjectId_e id)
|
||||
{
|
||||
uint32_t value = RTC_ReadBackupRegister(id);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void persistentObjectWrite(persistentObjectId_e id, uint32_t value)
|
||||
{
|
||||
RTC_WriteBackupRegister(id, value);
|
||||
}
|
||||
|
||||
void persistentObjectRTCEnable(void)
|
||||
{
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Enable Access to PWR
|
||||
PWR_BackupAccessCmd(ENABLE); // Disable backup domain protection
|
||||
|
||||
// We don't need a clock source for RTC itself. Skip it.
|
||||
|
||||
RTC_WriteProtectionCmd(ENABLE); // Reset sequence
|
||||
RTC_WriteProtectionCmd(DISABLE); // Apply sequence
|
||||
}
|
||||
#endif
|
||||
|
||||
void persistentObjectInit(void)
|
||||
{
|
||||
// Configure and enable RTC for backup register access
|
||||
|
||||
persistentObjectRTCEnable();
|
||||
|
||||
// XXX Magic value checking may be sufficient
|
||||
|
||||
uint32_t wasSoftReset;
|
||||
|
||||
#ifdef STM32H7
|
||||
wasSoftReset = RCC->RSR & RCC_RSR_SFTRSTF;
|
||||
#else
|
||||
wasSoftReset = RCC->CSR & RCC_CSR_SFTRSTF;
|
||||
#endif
|
||||
|
||||
if (!wasSoftReset || (persistentObjectRead(PERSISTENT_OBJECT_MAGIC) != PERSISTENT_OBJECT_MAGIC_VALUE)) {
|
||||
for (int i = 1; i < PERSISTENT_OBJECT_COUNT; i++) {
|
||||
persistentObjectWrite(i, 0);
|
||||
}
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_MAGIC, PERSISTENT_OBJECT_MAGIC_VALUE);
|
||||
}
|
||||
}
|
43
src/main/drivers/persistent.h
Normal file
43
src/main/drivers/persistent.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of Cleanflight and Betaflight.
|
||||
*
|
||||
* Cleanflight and Betaflight are free software. You can redistribute
|
||||
* this software and/or modify this software under the terms of the
|
||||
* GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* Cleanflight and Betaflight are distributed in the hope that they
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software.
|
||||
*
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Available RTC backup registers (4-byte words) per MCU type
|
||||
// F4: 20 words
|
||||
// F7: 32 words
|
||||
// H7: 32 words
|
||||
|
||||
typedef enum {
|
||||
PERSISTENT_OBJECT_MAGIC = 0,
|
||||
PERSISTENT_OBJECT_RESET_REASON,
|
||||
PERSISTENT_OBJECT_COUNT,
|
||||
} persistentObjectId_e;
|
||||
|
||||
// Values for PERSISTENT_OBJECT_RESET_REASON
|
||||
#define RESET_NONE 0
|
||||
#define RESET_BOOTLOADER_REQUEST_ROM 1
|
||||
#define RESET_MSC_REQUEST 2 // MSC invocation was requested
|
||||
|
||||
void persistentObjectInit(void);
|
||||
uint32_t persistentObjectRead(persistentObjectId_e id);
|
||||
void persistentObjectWrite(persistentObjectId_e id, uint32_t value);
|
|
@ -268,7 +268,7 @@ static bool motorsUseHardwareTimers(void)
|
|||
|
||||
static bool servosUseHardwareTimers(void)
|
||||
{
|
||||
return !feature(FEATURE_PWM_SERVO_DRIVER);
|
||||
return servoConfig()->servo_protocol == SERVO_TYPE_PWM;
|
||||
}
|
||||
|
||||
static void pwmInitMotors(timMotorServoHardware_t * timOutputs)
|
||||
|
|
|
@ -49,6 +49,12 @@ typedef enum {
|
|||
PWM_TYPE_SERIALSHOT,
|
||||
} motorPwmProtocolTypes_e;
|
||||
|
||||
typedef enum {
|
||||
SERVO_TYPE_PWM = 0,
|
||||
SERVO_TYPE_SERVO_DRIVER,
|
||||
SERVO_TYPE_SBUS
|
||||
} servoProtocolType_e;
|
||||
|
||||
typedef enum {
|
||||
PWM_INIT_ERROR_NONE = 0,
|
||||
PWM_INIT_ERROR_TOO_MANY_MOTORS,
|
||||
|
|
|
@ -37,6 +37,7 @@ FILE_COMPILE_FOR_SPEED
|
|||
|
||||
#include "io/pwmdriver_i2c.h"
|
||||
#include "io/esc_serialshot.h"
|
||||
#include "io/servo_sbus.h"
|
||||
#include "sensors/esc_sensor.h"
|
||||
|
||||
#include "config/feature.h"
|
||||
|
@ -327,6 +328,10 @@ bool isMotorProtocolDigital(void)
|
|||
|
||||
void pwmRequestMotorTelemetry(int motorIndex)
|
||||
{
|
||||
if (!isMotorProtocolDigital()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int motorCount = getMotorCount();
|
||||
for (int index = 0; index < motorCount; index++) {
|
||||
if (motors[index].pwmPort && motors[index].pwmPort->configured && index == motorIndex) {
|
||||
|
@ -345,10 +350,6 @@ void pwmCompleteMotorUpdate(void)
|
|||
int motorCount = getMotorCount();
|
||||
timeUs_t currentTimeUs = micros();
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
escSensorUpdate(currentTimeUs);
|
||||
#endif
|
||||
|
||||
// Enforce motor update rate
|
||||
if ((digitalMotorUpdateIntervalUs == 0) || ((currentTimeUs - digitalMotorLastUpdateUs) <= digitalMotorUpdateIntervalUs)) {
|
||||
return;
|
||||
|
@ -387,6 +388,15 @@ void pwmCompleteMotorUpdate(void)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // digital motor protocol
|
||||
|
||||
// This stub is needed to avoid ESC_SENSOR dependency on DSHOT
|
||||
void pwmRequestMotorTelemetry(int motorIndex)
|
||||
{
|
||||
UNUSED(motorIndex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void pwmMotorPreconfigure(void)
|
||||
|
@ -417,10 +427,6 @@ void pwmMotorPreconfigure(void)
|
|||
case PWM_TYPE_DSHOT600:
|
||||
case PWM_TYPE_DSHOT300:
|
||||
case PWM_TYPE_DSHOT150:
|
||||
#ifdef USE_ESC_SENSOR
|
||||
// DSHOT supports a dedicated wire ESC telemetry. Kick off the ESC-sensor receiver initialization
|
||||
escSensorInitialize();
|
||||
#endif
|
||||
motorConfigDigitalUpdateInterval(motorConfig()->motorPwmRate);
|
||||
motorWritePtr = pwmWriteDigital;
|
||||
break;
|
||||
|
@ -507,14 +513,27 @@ static void pwmServoWriteExternalDriver(uint8_t index, uint16_t value)
|
|||
|
||||
void pwmServoPreconfigure(void)
|
||||
{
|
||||
// Protocol-specific configuration
|
||||
switch (servoConfig()->servo_protocol) {
|
||||
default:
|
||||
case SERVO_TYPE_PWM:
|
||||
servoWritePtr = pwmServoWriteStandard;
|
||||
break;
|
||||
|
||||
#ifdef USE_PWM_SERVO_DRIVER
|
||||
// If PCA9685 is enabled - switch the servo write function to external
|
||||
if (feature(FEATURE_PWM_SERVO_DRIVER)) {
|
||||
case SERVO_TYPE_SERVO_DRIVER:
|
||||
pwmDriverInitialize();
|
||||
servoWritePtr = pwmServoWriteExternalDriver;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERVO_SBUS
|
||||
case SERVO_TYPE_SBUS:
|
||||
sbusServoInitialize();
|
||||
servoWritePtr = sbusServoUpdate;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool pwmServoConfig(const timerHardware_t *timerHardware, uint8_t servoIndex, uint16_t servoPwmRate, uint16_t servoCenterPulse, bool enableOutput)
|
||||
|
|
|
@ -22,7 +22,7 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = {
|
|||
"RANGEFINDER", "SYSTEM", "SPI", "I2C", "SDCARD", "FLASH", "USB", "BEEPER", "OSD",
|
||||
"BARO", "MPU", "INVERTER", "LED STRIP", "LED", "RECEIVER", "TRANSMITTER",
|
||||
"NRF24", "VTX", "SPI_PREINIT", "COMPASS", "TEMPERATURE", "1-WIRE", "AIRSPEED", "OLED DISPLAY",
|
||||
"PINIO"
|
||||
"PINIO", "IRLOCK"
|
||||
};
|
||||
|
||||
const char * const resourceNames[RESOURCE_TOTAL_COUNT] = {
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef enum {
|
|||
OWNER_AIRSPEED,
|
||||
OWNER_OLED_DISPLAY,
|
||||
OWNER_PINIO,
|
||||
OWNER_IRLOCK,
|
||||
OWNER_TOTAL_COUNT
|
||||
} resourceOwner_e;
|
||||
|
||||
|
|
|
@ -20,12 +20,11 @@
|
|||
|
||||
#include "platform.h"
|
||||
|
||||
#include "drivers/light_led.h"
|
||||
#include "sound_beeper.h"
|
||||
#include "drivers/nvic.h"
|
||||
#include "build/atomic.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#include "drivers/light_led.h"
|
||||
#include "drivers/persistent.h"
|
||||
#include "drivers/sound_beeper.h"
|
||||
#include "drivers/system.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
|
@ -48,17 +47,12 @@ void registerExtiCallbackHandler(IRQn_Type irqn, extiCallbackHandlerFunc *fn)
|
|||
failureMode(FAILURE_DEVELOPER); // EXTI_CALLBACK_HANDLER_COUNT is too low for the amount of handlers required.
|
||||
}
|
||||
|
||||
// cycles per microsecond, this is deliberately uint32_t to avoid type conversions
|
||||
STATIC_UNIT_TESTED uint32_t usTicks = 0;
|
||||
// current uptime for 1kHz systick timer. will rollover after 49 days. hopefully we won't care.
|
||||
STATIC_UNIT_TESTED volatile timeMs_t sysTickUptime = 0;
|
||||
STATIC_UNIT_TESTED volatile uint32_t sysTickValStamp = 0;
|
||||
// cached value of RCC->CSR
|
||||
uint32_t cachedRccCsrValue;
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
void cycleCounterInit(void)
|
||||
{
|
||||
extern uint32_t usTicks; // From drivers/time.h
|
||||
#if defined(USE_HAL_DRIVER)
|
||||
usTicks = HAL_RCC_GetSysClockFreq() / 1000000;
|
||||
#else
|
||||
|
@ -72,137 +66,52 @@ void cycleCounterInit(void)
|
|||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
}
|
||||
#endif // UNIT_TEST
|
||||
|
||||
// SysTick
|
||||
|
||||
static volatile int sysTickPending = 0;
|
||||
|
||||
void SysTick_Handler(void)
|
||||
static inline void systemDisableAllIRQs(void)
|
||||
{
|
||||
ATOMIC_BLOCK(NVIC_PRIO_MAX) {
|
||||
sysTickUptime++;
|
||||
sysTickValStamp = SysTick->VAL;
|
||||
sysTickPending = 0;
|
||||
(void)(SysTick->CTRL);
|
||||
}
|
||||
#ifdef USE_HAL_DRIVER
|
||||
// used by the HAL for some timekeeping and timeouts, should always be 1ms
|
||||
HAL_IncTick();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t ticks(void)
|
||||
{
|
||||
#ifdef UNIT_TEST
|
||||
return 0;
|
||||
#else
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
return DWT->CYCCNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
timeDelta_t ticks_diff_us(uint32_t begin, uint32_t end)
|
||||
{
|
||||
return (end - begin) / usTicks;
|
||||
}
|
||||
|
||||
// Return system uptime in microseconds
|
||||
timeUs_t microsISR(void)
|
||||
{
|
||||
register uint32_t ms, pending, cycle_cnt;
|
||||
|
||||
ATOMIC_BLOCK(NVIC_PRIO_MAX) {
|
||||
cycle_cnt = SysTick->VAL;
|
||||
|
||||
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
|
||||
// Update pending.
|
||||
// Record it for multiple calls within the same rollover period
|
||||
// (Will be cleared when serviced).
|
||||
// Note that multiple rollovers are not considered.
|
||||
|
||||
sysTickPending = 1;
|
||||
|
||||
// Read VAL again to ensure the value is read after the rollover.
|
||||
|
||||
cycle_cnt = SysTick->VAL;
|
||||
}
|
||||
|
||||
ms = sysTickUptime;
|
||||
pending = sysTickPending;
|
||||
}
|
||||
|
||||
// XXX: Be careful to not trigger 64 bit division
|
||||
const uint32_t partial = (usTicks * 1000U - cycle_cnt) / usTicks;
|
||||
return ((timeUs_t)(ms + pending) * 1000LL) + ((timeUs_t)partial);
|
||||
}
|
||||
|
||||
timeUs_t micros(void)
|
||||
{
|
||||
register uint32_t ms, cycle_cnt;
|
||||
|
||||
// Call microsISR() in interrupt and elevated (non-zero) BASEPRI context
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) || (__get_BASEPRI())) {
|
||||
return microsISR();
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
ms = sysTickUptime;
|
||||
cycle_cnt = SysTick->VAL;
|
||||
} while (ms != sysTickUptime || cycle_cnt > sysTickValStamp);
|
||||
|
||||
// XXX: Be careful to not trigger 64 bit division
|
||||
const uint32_t partial = (usTicks * 1000U - cycle_cnt) / usTicks;
|
||||
return ((timeUs_t)ms * 1000LL) + ((timeUs_t)partial);
|
||||
}
|
||||
|
||||
// Return system uptime in milliseconds (rollover in 49 days)
|
||||
timeMs_t millis(void)
|
||||
{
|
||||
return sysTickUptime;
|
||||
}
|
||||
|
||||
#if 1
|
||||
void delayMicroseconds(timeUs_t us)
|
||||
{
|
||||
timeUs_t now = micros();
|
||||
while (micros() - now < us);
|
||||
}
|
||||
#else
|
||||
void delayMicroseconds(timeUs_t us)
|
||||
{
|
||||
uint32_t elapsed = 0;
|
||||
uint32_t lastCount = SysTick->VAL;
|
||||
|
||||
for (;;) {
|
||||
register uint32_t current_count = SysTick->VAL;
|
||||
timeUs_t elapsed_us;
|
||||
|
||||
// measure the time elapsed since the last time we checked
|
||||
elapsed += current_count - lastCount;
|
||||
lastCount = current_count;
|
||||
|
||||
// convert to microseconds
|
||||
elapsed_us = elapsed / usTicks;
|
||||
if (elapsed_us >= us)
|
||||
break;
|
||||
|
||||
// reduce the delay by the elapsed time
|
||||
us -= elapsed_us;
|
||||
|
||||
// keep fractional microseconds for the next iteration
|
||||
elapsed %= usTicks;
|
||||
// We access CMSIS NVIC registers directly here
|
||||
for (int x = 0; x < 8; x++) {
|
||||
// Mask all IRQs controlled by a ICERx
|
||||
NVIC->ICER[x] = 0xFFFFFFFF;
|
||||
// Clear all pending IRQs controlled by a ICPRx
|
||||
NVIC->ICPR[x] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void delay(timeMs_t ms)
|
||||
void systemReset(void)
|
||||
{
|
||||
while (ms--)
|
||||
delayMicroseconds(1000);
|
||||
__disable_irq();
|
||||
systemDisableAllIRQs();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void systemResetToBootloader(void)
|
||||
{
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_BOOTLOADER_REQUEST_ROM);
|
||||
systemReset();
|
||||
}
|
||||
|
||||
typedef void resetHandler_t(void);
|
||||
|
||||
typedef struct isrVector_s {
|
||||
uint32_t stackEnd;
|
||||
resetHandler_t *resetHandler;
|
||||
} isrVector_t;
|
||||
|
||||
|
||||
void checkForBootLoaderRequest(void)
|
||||
{
|
||||
uint32_t bootloaderRequest = persistentObjectRead(PERSISTENT_OBJECT_RESET_REASON);
|
||||
|
||||
if (bootloaderRequest != RESET_BOOTLOADER_REQUEST_ROM) {
|
||||
return;
|
||||
}
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
|
||||
|
||||
volatile isrVector_t *bootloaderVector = (isrVector_t *)systemBootloaderAddress();
|
||||
__set_MSP(bootloaderVector->stackEnd);
|
||||
bootloaderVector->resetHandler();
|
||||
while (1);
|
||||
}
|
||||
|
||||
#define SHORT_FLASH_DURATION 50
|
||||
|
|
|
@ -39,6 +39,7 @@ void failureMode(failureMode_e mode);
|
|||
// bootloader/IAP
|
||||
void systemReset(void);
|
||||
void systemResetToBootloader(void);
|
||||
uint32_t systemBootloaderAddress(void);
|
||||
bool isMPUSoftReset(void);
|
||||
void cycleCounterInit(void);
|
||||
void checkForBootLoaderRequest(void);
|
||||
|
|
|
@ -24,42 +24,8 @@
|
|||
#include "drivers/nvic.h"
|
||||
#include "drivers/system.h"
|
||||
|
||||
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
|
||||
void SetSysClock(uint8_t underclock);
|
||||
|
||||
inline static void NVIC_DisableAllIRQs(void)
|
||||
{
|
||||
// We access CMSIS NVIC registers directly here
|
||||
for (int x = 0; x < 8; x++) {
|
||||
// Mask all IRQs controlled by a ICERx
|
||||
NVIC->ICER[x] = 0xFFFFFFFF;
|
||||
// Clear all pending IRQs controlled by a ICPRx
|
||||
NVIC->ICPR[x] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void systemReset(void)
|
||||
{
|
||||
// Disable all NVIC interrupts
|
||||
__disable_irq();
|
||||
NVIC_DisableAllIRQs();
|
||||
|
||||
// Generate system reset
|
||||
SCB->AIRCR = AIRCR_VECTKEY_MASK | (uint32_t)0x04;
|
||||
}
|
||||
|
||||
void systemResetToBootloader(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_DisableAllIRQs();
|
||||
|
||||
*((uint32_t *)0x20009FFC) = 0xDEADBEEF; // 40KB SRAM STM32F30X
|
||||
|
||||
// Generate system reset
|
||||
SCB->AIRCR = AIRCR_VECTKEY_MASK | (uint32_t)0x04;
|
||||
}
|
||||
|
||||
|
||||
void enableGPIOPowerUsageAndNoiseReductions(void)
|
||||
{
|
||||
RCC_AHBPeriphClockCmd(
|
||||
|
@ -95,6 +61,11 @@ bool isMPUSoftReset(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t systemBootloaderAddress(void)
|
||||
{
|
||||
return 0x1FFFD800;
|
||||
}
|
||||
|
||||
static void systemTimekeepingSetup(void)
|
||||
{
|
||||
RCC_ClocksTypeDef clocks;
|
||||
|
@ -133,7 +104,3 @@ void systemInit(void)
|
|||
// Pre-setup SysTick and system time - final setup is done in systemClockSetup
|
||||
systemTimekeepingSetup();
|
||||
}
|
||||
|
||||
void checkForBootLoaderRequest(void)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -29,37 +29,8 @@
|
|||
#include "drivers/exti.h"
|
||||
|
||||
|
||||
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
|
||||
void SetSysClock(void);
|
||||
|
||||
inline static void NVIC_DisableAllIRQs(void)
|
||||
{
|
||||
// We access CMSIS NVIC registers directly here
|
||||
for (int x = 0; x < 8; x++) {
|
||||
// Mask all IRQs controlled by a ICERx
|
||||
NVIC->ICER[x] = 0xFFFFFFFF;
|
||||
// Clear all pending IRQs controlled by a ICPRx
|
||||
NVIC->ICPR[x] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void systemReset(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_DisableAllIRQs();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void systemResetToBootloader(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_DisableAllIRQs();
|
||||
|
||||
*((uint32_t *)0x2001FFFC) = 0xDEADBEEF; // 128KB SRAM STM32F4XX
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void enableGPIOPowerUsageAndNoiseReductions(void)
|
||||
{
|
||||
|
||||
|
@ -167,6 +138,11 @@ bool isMPUSoftReset(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t systemBootloaderAddress(void)
|
||||
{
|
||||
return 0x1FFF0000;
|
||||
}
|
||||
|
||||
void systemClockSetup(uint8_t cpuUnderclock)
|
||||
{
|
||||
(void)cpuUnderclock;
|
||||
|
|
|
@ -27,38 +27,8 @@
|
|||
#include "drivers/nvic.h"
|
||||
#include "drivers/system.h"
|
||||
|
||||
|
||||
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
|
||||
void SystemClock_Config(void);
|
||||
|
||||
inline static void NVIC_DisableAllIRQs(void)
|
||||
{
|
||||
// We access CMSIS NVIC registers directly here
|
||||
for (int x = 0; x < 8; x++) {
|
||||
// Mask all IRQs controlled by a ICERx
|
||||
NVIC->ICER[x] = 0xFFFFFFFF;
|
||||
// Clear all pending IRQs controlled by a ICPRx
|
||||
NVIC->ICPR[x] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void systemReset(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_DisableAllIRQs();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void systemResetToBootloader(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_DisableAllIRQs();
|
||||
|
||||
(*(__IO uint32_t *) (BKPSRAM_BASE + 4)) = 0xDEADBEEF; // flag that will be readable after reboot
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void enableGPIOPowerUsageAndNoiseReductions(void)
|
||||
{
|
||||
|
||||
|
@ -91,6 +61,11 @@ bool isMPUSoftReset(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t systemBootloaderAddress(void)
|
||||
{
|
||||
return 0x1FF00000;
|
||||
}
|
||||
|
||||
void systemClockSetup(uint8_t cpuUnderclock)
|
||||
{
|
||||
(void)cpuUnderclock;
|
||||
|
@ -128,26 +103,3 @@ void systemInit(void)
|
|||
|
||||
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
|
||||
}
|
||||
|
||||
void(*bootJump)(void);
|
||||
void checkForBootLoaderRequest(void)
|
||||
{
|
||||
uint32_t bt;
|
||||
__PWR_CLK_ENABLE();
|
||||
__BKPSRAM_CLK_ENABLE();
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
|
||||
bt = (*(__IO uint32_t *) (BKPSRAM_BASE + 4)) ;
|
||||
if ( bt == 0xDEADBEEF ) {
|
||||
(*(__IO uint32_t *) (BKPSRAM_BASE + 4)) = 0xCAFEFEED; // Reset our trigger
|
||||
|
||||
void (*SysMemBootJump)(void);
|
||||
__SYSCFG_CLK_ENABLE();
|
||||
SYSCFG->MEMRMP |= SYSCFG_MEM_BOOT_ADD0 ;
|
||||
uint32_t p = (*((uint32_t *) 0x1ff00000));
|
||||
__set_MSP(p); //Set the main stack pointer to its defualt values
|
||||
SysMemBootJump = (void (*)(void)) (*((uint32_t *) 0x1ff00004)); // Point the PC to the System Memory reset vector (+4)
|
||||
SysMemBootJump();
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
|
172
src/main/drivers/time.c
Normal file
172
src/main/drivers/time.c
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* This file is part of INAV.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms
|
||||
* of the GNU General Public License Version 3, as described below:
|
||||
*
|
||||
* This file is free software: you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
#include "build/atomic.h"
|
||||
|
||||
#include "drivers/nvic.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
// cycles per microsecond, this is deliberately uint32_t to avoid type conversions
|
||||
// This is not static so system.c can set it up for us.
|
||||
uint32_t usTicks = 0;
|
||||
// current uptime for 1kHz systick timer. will rollover after 49 days. hopefully we won't care.
|
||||
STATIC_UNIT_TESTED volatile timeMs_t sysTickUptime = 0;
|
||||
STATIC_UNIT_TESTED volatile uint32_t sysTickValStamp = 0;
|
||||
|
||||
// Return system uptime in milliseconds (rollover in 49 days)
|
||||
timeMs_t millis(void)
|
||||
{
|
||||
return sysTickUptime;
|
||||
}
|
||||
|
||||
// SysTick
|
||||
|
||||
static volatile int sysTickPending = 0;
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
ATOMIC_BLOCK(NVIC_PRIO_MAX) {
|
||||
sysTickUptime++;
|
||||
sysTickValStamp = SysTick->VAL;
|
||||
sysTickPending = 0;
|
||||
(void)(SysTick->CTRL);
|
||||
}
|
||||
#ifdef USE_HAL_DRIVER
|
||||
// used by the HAL for some timekeeping and timeouts, should always be 1ms
|
||||
HAL_IncTick();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t ticks(void)
|
||||
{
|
||||
#ifdef UNIT_TEST
|
||||
return 0;
|
||||
#else
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
return DWT->CYCCNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
timeDelta_t ticks_diff_us(uint32_t begin, uint32_t end)
|
||||
{
|
||||
return (end - begin) / usTicks;
|
||||
}
|
||||
|
||||
// Return system uptime in microseconds
|
||||
timeUs_t microsISR(void)
|
||||
{
|
||||
register uint32_t ms, pending, cycle_cnt;
|
||||
|
||||
ATOMIC_BLOCK(NVIC_PRIO_MAX) {
|
||||
cycle_cnt = SysTick->VAL;
|
||||
|
||||
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
|
||||
// Update pending.
|
||||
// Record it for multiple calls within the same rollover period
|
||||
// (Will be cleared when serviced).
|
||||
// Note that multiple rollovers are not considered.
|
||||
|
||||
sysTickPending = 1;
|
||||
|
||||
// Read VAL again to ensure the value is read after the rollover.
|
||||
|
||||
cycle_cnt = SysTick->VAL;
|
||||
}
|
||||
|
||||
ms = sysTickUptime;
|
||||
pending = sysTickPending;
|
||||
}
|
||||
|
||||
// XXX: Be careful to not trigger 64 bit division
|
||||
const uint32_t partial = (usTicks * 1000U - cycle_cnt) / usTicks;
|
||||
return ((timeUs_t)(ms + pending) * 1000LL) + ((timeUs_t)partial);
|
||||
}
|
||||
|
||||
timeUs_t micros(void)
|
||||
{
|
||||
register uint32_t ms, cycle_cnt;
|
||||
|
||||
// Call microsISR() in interrupt and elevated (non-zero) BASEPRI context
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) || (__get_BASEPRI())) {
|
||||
return microsISR();
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
ms = sysTickUptime;
|
||||
cycle_cnt = SysTick->VAL;
|
||||
} while (ms != sysTickUptime || cycle_cnt > sysTickValStamp);
|
||||
|
||||
// XXX: Be careful to not trigger 64 bit division
|
||||
const uint32_t partial = (usTicks * 1000U - cycle_cnt) / usTicks;
|
||||
return ((timeUs_t)ms * 1000LL) + ((timeUs_t)partial);
|
||||
}
|
||||
|
||||
#if 1
|
||||
void delayMicroseconds(timeUs_t us)
|
||||
{
|
||||
timeUs_t now = micros();
|
||||
while (micros() - now < us);
|
||||
}
|
||||
#else
|
||||
void delayMicroseconds(timeUs_t us)
|
||||
{
|
||||
uint32_t elapsed = 0;
|
||||
uint32_t lastCount = SysTick->VAL;
|
||||
|
||||
for (;;) {
|
||||
register uint32_t current_count = SysTick->VAL;
|
||||
timeUs_t elapsed_us;
|
||||
|
||||
// measure the time elapsed since the last time we checked
|
||||
elapsed += current_count - lastCount;
|
||||
lastCount = current_count;
|
||||
|
||||
// convert to microseconds
|
||||
elapsed_us = elapsed / usTicks;
|
||||
if (elapsed_us >= us)
|
||||
break;
|
||||
|
||||
// reduce the delay by the elapsed time
|
||||
us -= elapsed_us;
|
||||
|
||||
// keep fractional microseconds for the next iteration
|
||||
elapsed %= usTicks;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void delay(timeMs_t ms)
|
||||
{
|
||||
while (ms--)
|
||||
delayMicroseconds(1000);
|
||||
}
|
27
src/main/drivers/usb_msc.c
Normal file
27
src/main/drivers/usb_msc.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* This file is part of iNav
|
||||
*
|
||||
* iNav is free software. You can redistribute
|
||||
* this software and/or modify this software under the terms of the
|
||||
* GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* iNav is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software.
|
||||
*
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "drivers/persistent.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
bool mscCheckBoot(void)
|
||||
{
|
||||
return (persistentObjectRead(PERSISTENT_OBJECT_RESET_REASON) == RESET_MSC_REQUEST);
|
||||
}
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define MSC_MAGIC 0xDDDD1010
|
||||
|
||||
void mscInit(void);
|
||||
bool mscCheckBoot(void);
|
||||
uint8_t mscStart(void);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "drivers/io.h"
|
||||
#include "drivers/light_led.h"
|
||||
#include "drivers/nvic.h"
|
||||
#include "drivers/persistent.h"
|
||||
#include "drivers/sdmmc_sdio.h"
|
||||
#include "drivers/time.h"
|
||||
#include "drivers/usb_msc.h"
|
||||
|
@ -110,6 +111,8 @@ uint8_t mscStart(void)
|
|||
|
||||
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &MSC_desc, &USBD_MSC_cb, &USR_cb);
|
||||
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
|
||||
|
||||
// NVIC configuration for SYSTick
|
||||
NVIC_DisableIRQ(SysTick_IRQn);
|
||||
NVIC_SetPriority(SysTick_IRQn, 0);
|
||||
|
@ -118,14 +121,6 @@ uint8_t mscStart(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool mscCheckBoot(void)
|
||||
{
|
||||
if (*((uint32_t *)0x2001FFF0) == MSC_MAGIC) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mscCheckButton(void)
|
||||
{
|
||||
bool result = false;
|
||||
|
@ -150,7 +145,6 @@ void mscWaitForButton(void)
|
|||
while (true) {
|
||||
asm("NOP");
|
||||
if (mscCheckButton()) {
|
||||
*((uint32_t *)0x2001FFF0) = 0xFFFFFFFF;
|
||||
delay(1);
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "drivers/io.h"
|
||||
#include "drivers/light_led.h"
|
||||
#include "drivers/nvic.h"
|
||||
#include "drivers/persistent.h"
|
||||
#include "drivers/time.h"
|
||||
#include "drivers/usb_msc.h"
|
||||
|
||||
|
@ -108,6 +109,8 @@ uint8_t mscStart(void)
|
|||
|
||||
USBD_Start(&USBD_Device);
|
||||
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
|
||||
|
||||
// NVIC configuration for SYSTick
|
||||
NVIC_DisableIRQ(SysTick_IRQn);
|
||||
NVIC_SetPriority(SysTick_IRQn, 0);
|
||||
|
@ -116,14 +119,6 @@ uint8_t mscStart(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool mscCheckBoot(void)
|
||||
{
|
||||
if (*((__IO uint32_t *)BKPSRAM_BASE + 16) == MSC_MAGIC) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mscCheckButton(void)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
|
@ -56,9 +56,11 @@ extern uint8_t __config_end;
|
|||
#include "drivers/buf_writer.h"
|
||||
#include "drivers/bus_i2c.h"
|
||||
#include "drivers/compass/compass.h"
|
||||
#include "drivers/flash.h"
|
||||
#include "drivers/io.h"
|
||||
#include "drivers/io_impl.h"
|
||||
#include "drivers/osd_symbols.h"
|
||||
#include "drivers/persistent.h"
|
||||
#include "drivers/rx_pwm.h"
|
||||
#include "drivers/sdcard/sdcard.h"
|
||||
#include "drivers/sensor.h"
|
||||
|
@ -94,6 +96,8 @@ extern uint8_t __config_end;
|
|||
#include "io/osd.h"
|
||||
#include "io/serial.h"
|
||||
|
||||
#include "fc/fc_msp_box.h"
|
||||
|
||||
#include "navigation/navigation.h"
|
||||
#include "navigation/navigation_private.h"
|
||||
|
||||
|
@ -151,7 +155,7 @@ static const char * const featureNames[] = {
|
|||
"", "TELEMETRY", "CURRENT_METER", "REVERSIBLE_MOTORS", "",
|
||||
"", "RSSI_ADC", "LED_STRIP", "DASHBOARD", "",
|
||||
"BLACKBOX", "", "TRANSPONDER", "AIRMODE",
|
||||
"SUPEREXPO", "VTX", "", "", "PWM_SERVO_DRIVER", "PWM_OUTPUT_ENABLE",
|
||||
"SUPEREXPO", "VTX", "", "", "", "PWM_OUTPUT_ENABLE",
|
||||
"OSD", "FW_LAUNCH", NULL
|
||||
};
|
||||
|
||||
|
@ -646,17 +650,19 @@ static void printAux(uint8_t dumpMask, const modeActivationCondition_t *modeActi
|
|||
&& mac->auxChannelIndex == macDefault->auxChannelIndex
|
||||
&& mac->range.startStep == macDefault->range.startStep
|
||||
&& mac->range.endStep == macDefault->range.endStep;
|
||||
const box_t *box = findBoxByActiveBoxId(macDefault->modeId);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, format,
|
||||
i,
|
||||
macDefault->modeId,
|
||||
box->permanentId,
|
||||
macDefault->auxChannelIndex,
|
||||
MODE_STEP_TO_CHANNEL_VALUE(macDefault->range.startStep),
|
||||
MODE_STEP_TO_CHANNEL_VALUE(macDefault->range.endStep)
|
||||
);
|
||||
}
|
||||
const box_t *box = findBoxByActiveBoxId(mac->modeId);
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, format,
|
||||
i,
|
||||
mac->modeId,
|
||||
box->permanentId,
|
||||
mac->auxChannelIndex,
|
||||
MODE_STEP_TO_CHANNEL_VALUE(mac->range.startStep),
|
||||
MODE_STEP_TO_CHANNEL_VALUE(mac->range.endStep)
|
||||
|
@ -680,11 +686,14 @@ static void cliAux(char *cmdline)
|
|||
ptr = nextArg(ptr);
|
||||
if (ptr) {
|
||||
val = fastA2I(ptr);
|
||||
if (val >= 0 && val < CHECKBOX_ITEM_COUNT) {
|
||||
mac->modeId = val;
|
||||
if (val >= 0) {
|
||||
const box_t *box = findBoxByPermanentId(val);
|
||||
if (box != NULL) {
|
||||
mac->modeId = box->boxId;
|
||||
validArgumentCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr = nextArg(ptr);
|
||||
if (ptr) {
|
||||
val = fastA2I(ptr);
|
||||
|
@ -2115,12 +2124,32 @@ static void cliSdInfo(char *cmdline)
|
|||
|
||||
static void cliFlashInfo(char *cmdline)
|
||||
{
|
||||
const flashGeometry_t *layout = flashfsGetGeometry();
|
||||
|
||||
UNUSED(cmdline);
|
||||
|
||||
cliPrintLinef("Flash sectors=%u, sectorSize=%u, pagesPerSector=%u, pageSize=%u, totalSize=%u, usedSize=%u",
|
||||
layout->sectors, layout->sectorSize, layout->pagesPerSector, layout->pageSize, layout->totalSize, flashfsGetOffset());
|
||||
const flashGeometry_t *layout = flashGetGeometry();
|
||||
|
||||
cliPrintLinef("Flash sectors=%u, sectorSize=%u, pagesPerSector=%u, pageSize=%u, totalSize=%u",
|
||||
layout->sectors, layout->sectorSize, layout->pagesPerSector, layout->pageSize, layout->totalSize);
|
||||
|
||||
for (uint8_t index = 0; index < FLASH_MAX_PARTITIONS; index++) {
|
||||
const flashPartition_t *partition;
|
||||
if (index == 0) {
|
||||
cliPrintLine("Paritions:");
|
||||
}
|
||||
partition = flashPartitionFindByIndex(index);
|
||||
if (!partition) {
|
||||
break;
|
||||
}
|
||||
cliPrintLinef(" %d: %s %u %u", index, flashPartitionGetTypeName(partition->type), partition->startSector, partition->endSector);
|
||||
}
|
||||
#ifdef USE_FLASHFS
|
||||
const flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_FLASHFS);
|
||||
|
||||
cliPrintLinef("FlashFS size=%u, usedSize=%u",
|
||||
FLASH_PARTITION_SECTOR_COUNT(flashPartition) * layout->sectorSize,
|
||||
flashfsGetOffset()
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cliFlashErase(char *cmdline)
|
||||
|
@ -2130,7 +2159,7 @@ static void cliFlashErase(char *cmdline)
|
|||
cliPrintLine("Erasing...");
|
||||
flashfsEraseCompletely();
|
||||
|
||||
while (!flashfsIsReady()) {
|
||||
while (!flashIsReady()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
@ -3434,11 +3463,7 @@ static void cliMsc(char *cmdline)
|
|||
waitForSerialPortToFinishTransmitting(cliPort);
|
||||
stopPwmAllMotors();
|
||||
|
||||
#ifdef STM32F7
|
||||
*((__IO uint32_t*) BKPSRAM_BASE + 16) = MSC_MAGIC;
|
||||
#elif defined(STM32F4)
|
||||
*((uint32_t *)0x2001FFF0) = MSC_MAGIC;
|
||||
#endif
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_MSC_REQUEST);
|
||||
|
||||
__disable_irq();
|
||||
NVIC_SystemReset();
|
||||
|
|
|
@ -217,7 +217,15 @@ void validateAndFixConfig(void)
|
|||
#endif
|
||||
|
||||
#ifndef USE_PWM_SERVO_DRIVER
|
||||
featureClear(FEATURE_PWM_SERVO_DRIVER);
|
||||
if (servoConfig()->servo_protocol == SERVO_TYPE_SERVO_DRIVER) {
|
||||
servoConfigMutable()->servo_protocol = SERVO_TYPE_PWM;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef USE_SERVO_SBUS
|
||||
if (servoConfig()->servo_protocol == SERVO_TYPE_SBUS) {
|
||||
servoConfigMutable()->servo_protocol = SERVO_TYPE_PWM;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isSerialConfigValid(serialConfigMutable())) {
|
||||
|
|
|
@ -62,8 +62,8 @@ typedef enum {
|
|||
FEATURE_SUPEREXPO_RATES = 1 << 23,
|
||||
FEATURE_VTX = 1 << 24,
|
||||
FEATURE_UNUSED_8 = 1 << 25, // RX_SPI
|
||||
FEATURE_UNUSED_9 = 1 << 26, //SOFTSPI
|
||||
FEATURE_PWM_SERVO_DRIVER = 1 << 27,
|
||||
FEATURE_UNUSED_9 = 1 << 26, // SOFTSPI
|
||||
FEATURE_UNUSED_11 = 1 << 27, // FEATURE_PWM_SERVO_DRIVER
|
||||
FEATURE_PWM_OUTPUT_ENABLE = 1 << 28,
|
||||
FEATURE_OSD = 1 << 29,
|
||||
FEATURE_FW_LAUNCH = 1 << 30,
|
||||
|
|
|
@ -50,6 +50,7 @@ FILE_COMPILE_FOR_SPEED
|
|||
#include "sensors/battery.h"
|
||||
#include "sensors/rangefinder.h"
|
||||
#include "sensors/opflow.h"
|
||||
#include "sensors/esc_sensor.h"
|
||||
|
||||
#include "fc/fc_core.h"
|
||||
#include "fc/cli.h"
|
||||
|
@ -856,6 +857,10 @@ void taskRunRealtimeCallbacks(timeUs_t currentTimeUs)
|
|||
#ifdef USE_DSHOT
|
||||
pwmCompleteMotorUpdate();
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
escSensorUpdate(currentTimeUs);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool taskUpdateRxCheck(timeUs_t currentTimeUs, timeDelta_t currentDeltaTime)
|
||||
|
|
|
@ -54,9 +54,11 @@
|
|||
#include "drivers/flash_m25p16.h"
|
||||
#include "drivers/io.h"
|
||||
#include "drivers/io_pca9685.h"
|
||||
#include "drivers/flash.h"
|
||||
#include "drivers/light_led.h"
|
||||
#include "drivers/nvic.h"
|
||||
#include "drivers/osd.h"
|
||||
#include "drivers/persistent.h"
|
||||
#include "drivers/pwm_esc_detect.h"
|
||||
#include "drivers/pwm_mapping.h"
|
||||
#include "drivers/pwm_output.h"
|
||||
|
@ -136,6 +138,7 @@
|
|||
#include "sensors/pitotmeter.h"
|
||||
#include "sensors/rangefinder.h"
|
||||
#include "sensors/sensors.h"
|
||||
#include "sensors/esc_sensor.h"
|
||||
|
||||
#include "scheduler/scheduler.h"
|
||||
|
||||
|
@ -183,6 +186,10 @@ void flashLedsAndBeep(void)
|
|||
|
||||
void init(void)
|
||||
{
|
||||
#if defined(USE_FLASHFS) && defined(USE_FLASH_M25P16)
|
||||
bool flashDeviceInitialized = false;
|
||||
#endif
|
||||
|
||||
#ifdef USE_HAL_DRIVER
|
||||
HAL_Init();
|
||||
#endif
|
||||
|
@ -268,6 +275,12 @@ void init(void)
|
|||
// to run after the sensors have been detected.
|
||||
mspSerialInit();
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
// DSHOT supports a dedicated wire ESC telemetry. Kick off the ESC-sensor receiver initialization
|
||||
// We may, however, do listen_only, so need to init this anyway
|
||||
escSensorInitialize();
|
||||
#endif
|
||||
|
||||
#if defined(USE_DJI_HD_OSD)
|
||||
// DJI OSD uses a special flavour of MSP (subset of Betaflight 4.1.1 MSP) - process as part of serial task
|
||||
djiOsdSerialInit();
|
||||
|
@ -362,7 +375,10 @@ void init(void)
|
|||
if (blackboxConfig()->device == BLACKBOX_DEVICE_FLASH) {
|
||||
#ifdef USE_FLASH_M25P16
|
||||
// Must initialise the device to read _anything_
|
||||
m25p16_init(0);
|
||||
/*m25p16_init(0);*/
|
||||
if (!flashDeviceInitialized) {
|
||||
flashDeviceInitialized = flashInit();
|
||||
}
|
||||
#endif
|
||||
emfat_init_files();
|
||||
}
|
||||
|
@ -579,7 +595,9 @@ void init(void)
|
|||
#ifdef USE_FLASHFS
|
||||
case BLACKBOX_DEVICE_FLASH:
|
||||
#ifdef USE_FLASH_M25P16
|
||||
m25p16_init(0);
|
||||
if (!flashDeviceInitialized) {
|
||||
flashDeviceInitialized = flashInit();
|
||||
}
|
||||
#endif
|
||||
flashfsInit();
|
||||
break;
|
||||
|
@ -632,12 +650,6 @@ void init(void)
|
|||
if (feature(FEATURE_VBAT | FEATURE_CURRENT_METER))
|
||||
batteryInit();
|
||||
|
||||
#ifdef USE_PWM_SERVO_DRIVER
|
||||
if (feature(FEATURE_PWM_SERVO_DRIVER)) {
|
||||
pwmDriverInitialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_RCDEVICE
|
||||
rcdeviceInit();
|
||||
#endif // USE_RCDEVICE
|
||||
|
@ -661,5 +673,8 @@ void init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Considering that the persistent reset reason is only used during init
|
||||
persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
|
||||
|
||||
systemState |= SYSTEM_STATE_READY;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "drivers/bus_i2c.h"
|
||||
#include "drivers/compass/compass.h"
|
||||
#include "drivers/display.h"
|
||||
#include "drivers/flash.h"
|
||||
#include "drivers/osd.h"
|
||||
#include "drivers/osd_symbols.h"
|
||||
#include "drivers/pwm_mapping.h"
|
||||
|
@ -293,8 +294,8 @@ static void serializeSDCardSummaryReply(sbuf_t *dst)
|
|||
static void serializeDataflashSummaryReply(sbuf_t *dst)
|
||||
{
|
||||
#ifdef USE_FLASHFS
|
||||
const flashGeometry_t *geometry = flashfsGetGeometry();
|
||||
sbufWriteU8(dst, flashfsIsReady() ? 1 : 0);
|
||||
const flashGeometry_t *geometry = flashGetGeometry();
|
||||
sbufWriteU8(dst, flashIsReady() ? 1 : 0);
|
||||
sbufWriteU32(dst, geometry->sectors);
|
||||
sbufWriteU32(dst, geometry->totalSize);
|
||||
sbufWriteU32(dst, flashfsGetOffset()); // Effectively the current number of bytes stored on the volume
|
||||
|
@ -1272,7 +1273,6 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
|
|||
#endif
|
||||
|
||||
case MSP_CALIBRATION_DATA:
|
||||
#ifdef USE_ACC
|
||||
sbufWriteU8(dst, accGetCalibrationAxisFlags());
|
||||
sbufWriteU16(dst, accelerometerConfig()->accZero.raw[X]);
|
||||
sbufWriteU16(dst, accelerometerConfig()->accZero.raw[Y]);
|
||||
|
@ -1280,15 +1280,6 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
|
|||
sbufWriteU16(dst, accelerometerConfig()->accGain.raw[X]);
|
||||
sbufWriteU16(dst, accelerometerConfig()->accGain.raw[Y]);
|
||||
sbufWriteU16(dst, accelerometerConfig()->accGain.raw[Z]);
|
||||
#else
|
||||
sbufWriteU8(dst, 0);
|
||||
sbufWriteU16(dst, 0);
|
||||
sbufWriteU16(dst, 0);
|
||||
sbufWriteU16(dst, 0);
|
||||
sbufWriteU16(dst, 0);
|
||||
sbufWriteU16(dst, 0);
|
||||
sbufWriteU16(dst, 0);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MAG
|
||||
sbufWriteU16(dst, compassConfig()->magZero.raw[X]);
|
||||
|
@ -2206,21 +2197,12 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
|
|||
|
||||
case MSP_SET_CALIBRATION_DATA:
|
||||
if (dataSize >= 18) {
|
||||
#ifdef USE_ACC
|
||||
accelerometerConfigMutable()->accZero.raw[X] = sbufReadU16(src);
|
||||
accelerometerConfigMutable()->accZero.raw[Y] = sbufReadU16(src);
|
||||
accelerometerConfigMutable()->accZero.raw[Z] = sbufReadU16(src);
|
||||
accelerometerConfigMutable()->accGain.raw[X] = sbufReadU16(src);
|
||||
accelerometerConfigMutable()->accGain.raw[Y] = sbufReadU16(src);
|
||||
accelerometerConfigMutable()->accGain.raw[Z] = sbufReadU16(src);
|
||||
#else
|
||||
sbufReadU16(src);
|
||||
sbufReadU16(src);
|
||||
sbufReadU16(src);
|
||||
sbufReadU16(src);
|
||||
sbufReadU16(src);
|
||||
sbufReadU16(src);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MAG
|
||||
compassConfigMutable()->magZero.raw[X] = sbufReadU16(src);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "drivers/sensor.h"
|
||||
#include "drivers/serial.h"
|
||||
#include "drivers/stack_check.h"
|
||||
#include "drivers/pwm_mapping.h"
|
||||
|
||||
#include "fc/cli.h"
|
||||
#include "fc/config.h"
|
||||
|
@ -48,6 +49,7 @@
|
|||
#include "flight/pid.h"
|
||||
#include "flight/wind_estimator.h"
|
||||
#include "flight/rpm_filter.h"
|
||||
#include "flight/servos.h"
|
||||
|
||||
#include "navigation/navigation.h"
|
||||
|
||||
|
@ -62,6 +64,7 @@
|
|||
#include "io/rcdevice_cam.h"
|
||||
#include "io/vtx.h"
|
||||
#include "io/osd_dji_hd.h"
|
||||
#include "io/servo_sbus.h"
|
||||
|
||||
#include "msp/msp_serial.h"
|
||||
|
||||
|
@ -78,6 +81,7 @@
|
|||
#include "sensors/battery.h"
|
||||
#include "sensors/compass.h"
|
||||
#include "sensors/gyro.h"
|
||||
#include "sensors/irlock.h"
|
||||
#include "sensors/pitotmeter.h"
|
||||
#include "sensors/rangefinder.h"
|
||||
#include "sensors/opflow.h"
|
||||
|
@ -209,6 +213,14 @@ void taskUpdateRangefinder(timeUs_t currentTimeUs)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_NAV) && defined(USE_IRLOCK)
|
||||
void taskUpdateIrlock(timeUs_t currentTimeUs)
|
||||
{
|
||||
UNUSED(currentTimeUs);
|
||||
irlockUpdate();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPFLOW
|
||||
void taskUpdateOpticalFlow(timeUs_t currentTimeUs)
|
||||
{
|
||||
|
@ -249,17 +261,19 @@ void taskLedStrip(timeUs_t currentTimeUs)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PWM_SERVO_DRIVER
|
||||
void taskSyncPwmDriver(timeUs_t currentTimeUs)
|
||||
void taskSyncServoDriver(timeUs_t currentTimeUs)
|
||||
{
|
||||
UNUSED(currentTimeUs);
|
||||
|
||||
if (feature(FEATURE_PWM_SERVO_DRIVER)) {
|
||||
pwmDriverSync();
|
||||
}
|
||||
}
|
||||
#if defined(USE_SERVO_SBUS)
|
||||
sbusServoSendUpdate();
|
||||
#endif
|
||||
|
||||
#ifdef USE_PWM_SERVO_DRIVER
|
||||
pwmDriverSync();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_OSD
|
||||
void taskUpdateOsd(timeUs_t currentTimeUs)
|
||||
{
|
||||
|
@ -317,8 +331,8 @@ void fcTasksInit(void)
|
|||
#ifdef STACK_CHECK
|
||||
setTaskEnabled(TASK_STACK_CHECK, true);
|
||||
#endif
|
||||
#ifdef USE_PWM_SERVO_DRIVER
|
||||
setTaskEnabled(TASK_PWMDRIVER, feature(FEATURE_PWM_SERVO_DRIVER));
|
||||
#if defined(USE_PWM_SERVO_DRIVER) || defined(USE_SERVO_SBUS)
|
||||
setTaskEnabled(TASK_PWMDRIVER, (servoConfig()->servo_protocol == SERVO_TYPE_SERVO_DRIVER) || (servoConfig()->servo_protocol == SERVO_TYPE_SBUS));
|
||||
#endif
|
||||
#ifdef USE_CMS
|
||||
#ifdef USE_MSP_DISPLAYPORT
|
||||
|
@ -347,6 +361,9 @@ void fcTasksInit(void)
|
|||
#ifdef USE_GLOBAL_FUNCTIONS
|
||||
setTaskEnabled(TASK_GLOBAL_FUNCTIONS, true);
|
||||
#endif
|
||||
#ifdef USE_IRLOCK
|
||||
setTaskEnabled(TASK_IRLOCK, irlockHasBeenDetected());
|
||||
#endif
|
||||
}
|
||||
|
||||
cfTask_t cfTasks[TASK_COUNT] = {
|
||||
|
@ -454,6 +471,15 @@ cfTask_t cfTasks[TASK_COUNT] = {
|
|||
},
|
||||
#endif
|
||||
|
||||
#ifdef USE_IRLOCK
|
||||
[TASK_IRLOCK] = {
|
||||
.taskName = "IRLOCK",
|
||||
.taskFunc = taskUpdateIrlock,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(100),
|
||||
.staticPriority = TASK_PRIORITY_MEDIUM,
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef USE_DASHBOARD
|
||||
[TASK_DASHBOARD] = {
|
||||
.taskName = "DASHBOARD",
|
||||
|
@ -481,10 +507,10 @@ cfTask_t cfTasks[TASK_COUNT] = {
|
|||
},
|
||||
#endif
|
||||
|
||||
#ifdef USE_PWM_SERVO_DRIVER
|
||||
#if defined(USE_PWM_SERVO_DRIVER) || defined(USE_SERVO_SBUS)
|
||||
[TASK_PWMDRIVER] = {
|
||||
.taskName = "PWMDRIVER",
|
||||
.taskFunc = taskSyncPwmDriver,
|
||||
.taskName = "SERVOS",
|
||||
.taskFunc = taskSyncServoDriver,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(200), // 200 Hz
|
||||
.staticPriority = TASK_PRIORITY_HIGH,
|
||||
},
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "platform.h"
|
||||
|
||||
#include "common/utils.h"
|
||||
#include "fc/runtime_config.h"
|
||||
|
||||
#include "io/beeper.h"
|
||||
|
@ -39,16 +40,51 @@ const char *armingDisableFlagNames[]= {
|
|||
};
|
||||
#endif
|
||||
|
||||
const armingFlag_e armDisableReasonsChecklist[] = {
|
||||
ARMING_DISABLED_INVALID_SETTING,
|
||||
ARMING_DISABLED_HARDWARE_FAILURE,
|
||||
ARMING_DISABLED_PWM_OUTPUT_ERROR,
|
||||
ARMING_DISABLED_COMPASS_NOT_CALIBRATED,
|
||||
ARMING_DISABLED_ACCELEROMETER_NOT_CALIBRATED,
|
||||
ARMING_DISABLED_RC_LINK,
|
||||
ARMING_DISABLED_NAVIGATION_UNSAFE,
|
||||
ARMING_DISABLED_ARM_SWITCH,
|
||||
ARMING_DISABLED_BOXFAILSAFE,
|
||||
ARMING_DISABLED_BOXKILLSWITCH,
|
||||
ARMING_DISABLED_THROTTLE,
|
||||
ARMING_DISABLED_CLI,
|
||||
ARMING_DISABLED_CMS_MENU,
|
||||
ARMING_DISABLED_OSD_MENU,
|
||||
ARMING_DISABLED_ROLLPITCH_NOT_CENTERED,
|
||||
ARMING_DISABLED_SERVO_AUTOTRIM,
|
||||
ARMING_DISABLED_OOM
|
||||
};
|
||||
|
||||
armingFlag_e isArmingDisabledReason(void)
|
||||
{
|
||||
armingFlag_e flag;
|
||||
// Shortcut, if we don't block arming at all
|
||||
if (!isArmingDisabled()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
armingFlag_e reasons = armingFlags & ARMING_DISABLED_ALL_FLAGS;
|
||||
for (unsigned ii = 0; ii < sizeof(armingFlag_e) * 8; ii++) {
|
||||
flag = 1u << ii;
|
||||
|
||||
// First check for "more important reasons"
|
||||
for (unsigned ii = 0; ii < ARRAYLEN(armDisableReasonsChecklist); ii++) {
|
||||
armingFlag_e flag = armDisableReasonsChecklist[ii];
|
||||
if (flag & reasons) {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback, we ended up with a blocker flag not included in armDisableReasonsChecklist[]
|
||||
for (unsigned ii = 0; ii < sizeof(armingFlag_e) * 8; ii++) {
|
||||
armingFlag_e flag = 1u << ii;
|
||||
if (flag & reasons) {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ tables:
|
|||
values: ["SERIAL", "SPIFLASH", "SDCARD"]
|
||||
- name: motor_pwm_protocol
|
||||
values: ["STANDARD", "ONESHOT125", "ONESHOT42", "MULTISHOT", "BRUSHED", "DSHOT150", "DSHOT300", "DSHOT600", "DSHOT1200", "SERIALSHOT"]
|
||||
- name: servo_protocol
|
||||
values: ["PWM", "SERVO_DRIVER", "SBUS"]
|
||||
- name: failsafe_procedure
|
||||
values: ["SET-THR", "DROP", "RTH", "NONE"]
|
||||
- name: current_sensor
|
||||
|
@ -81,7 +83,8 @@ tables:
|
|||
values: ["NONE", "GYRO", "AGL", "FLOW_RAW",
|
||||
"FLOW", "SBUS", "FPORT", "ALWAYS", "SAG_COMP_VOLTAGE",
|
||||
"VIBE", "CRUISE", "REM_FLIGHT_TIME", "SMARTAUDIO", "ACC", "ITERM_RELAX",
|
||||
"ERPM", "RPM_FILTER", "RPM_FREQ", "NAV_YAW", "DYNAMIC_FILTER", "DYNAMIC_FILTER_FREQUENCY"]
|
||||
"ERPM", "RPM_FILTER", "RPM_FREQ", "NAV_YAW", "DYNAMIC_FILTER", "DYNAMIC_FILTER_FREQUENCY",
|
||||
"IRLOCK"]
|
||||
- name: async_mode
|
||||
values: ["NONE", "GYRO", "ALL"]
|
||||
- name: aux_operator
|
||||
|
@ -726,6 +729,9 @@ groups:
|
|||
type: servoConfig_t
|
||||
headers: ["flight/servos.h"]
|
||||
members:
|
||||
- name: servo_protocol
|
||||
field: servo_protocol
|
||||
table: servo_protocol
|
||||
- name: servo_center_pulse
|
||||
field: servoCenterPulse
|
||||
min: PWM_RANGE_MIN
|
||||
|
@ -1596,6 +1602,10 @@ groups:
|
|||
field: fw.cruise_speed
|
||||
min: 0
|
||||
max: 65535
|
||||
- name: nav_fw_control_smoothness
|
||||
field: fw.control_smoothness
|
||||
min: 0
|
||||
max: 9
|
||||
|
||||
- name: nav_fw_land_dive_angle
|
||||
field: fw.land_dive_angle
|
||||
|
@ -1892,6 +1902,14 @@ groups:
|
|||
field: imu_temp_alarm_max
|
||||
min: -550
|
||||
max: 1250
|
||||
- name: osd_esc_temp_alarm_max
|
||||
field: esc_temp_alarm_max
|
||||
min: -550
|
||||
max: 1500
|
||||
- name: osd_esc_temp_alarm_min
|
||||
field: esc_temp_alarm_min
|
||||
min: -550
|
||||
max: 1500
|
||||
- name: osd_baro_temp_alarm_min
|
||||
field: baro_temp_alarm_min
|
||||
condition: USE_BARO
|
||||
|
@ -2138,5 +2156,14 @@ groups:
|
|||
table: log_level
|
||||
- name: log_topics
|
||||
field: topics
|
||||
min: 0,
|
||||
min: 0
|
||||
max: UINT32_MAX
|
||||
|
||||
- name: PG_ESC_SENSOR_CONFIG
|
||||
type: escSensorConfig_t
|
||||
headers: ["sensors/esc_sensor.h"]
|
||||
condition: USE_ESC_SENSOR
|
||||
members:
|
||||
- name: esc_sensor_listen_only
|
||||
field: listenOnly
|
||||
type: bool
|
||||
|
|
|
@ -40,15 +40,14 @@ void dynamicGyroNotchFiltersInit(dynamicGyroNotchState_t *state) {
|
|||
state->looptime = getLooptime();
|
||||
|
||||
if (state->enabled) {
|
||||
const float notchQ = filterGetNotchQ(DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ); // any defaults OK here
|
||||
|
||||
/*
|
||||
* Step 1 - init all filters even if they will not be used further down the road
|
||||
*/
|
||||
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
|
||||
biquadFilterInit(&state->filters[axis][0], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, state->looptime, notchQ, FILTER_NOTCH);
|
||||
biquadFilterInit(&state->filters[axis][1], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, state->looptime, notchQ, FILTER_NOTCH);
|
||||
biquadFilterInit(&state->filters[axis][2], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, state->looptime, notchQ, FILTER_NOTCH);
|
||||
//Any initial notch Q is valid sice it will be updated immediately after
|
||||
biquadFilterInit(&state->filters[axis][0], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, state->looptime, 1.0f, FILTER_NOTCH);
|
||||
biquadFilterInit(&state->filters[axis][1], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, state->looptime, 1.0f, FILTER_NOTCH);
|
||||
biquadFilterInit(&state->filters[axis][2], DYNAMIC_NOTCH_DEFAULT_CENTER_HZ, state->looptime, 1.0f, FILTER_NOTCH);
|
||||
}
|
||||
|
||||
state->filtersApplyFn = (filterApplyFnPtr)biquadFilterApplyDF1;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "common/filter.h"
|
||||
|
||||
#define DYNAMIC_NOTCH_DEFAULT_CENTER_HZ 350
|
||||
#define DYNAMIC_NOTCH_DEFAULT_CUTOFF_HZ 300
|
||||
|
||||
typedef struct dynamicGyroNotchState_s {
|
||||
uint16_t frequency[XYZ_AXIS_COUNT];
|
||||
|
|
|
@ -477,14 +477,13 @@ void FAST_CODE mixTable(const float dT)
|
|||
int16_t rpyMixRange = rpyMixMax - rpyMixMin;
|
||||
int16_t throttleRange;
|
||||
int16_t throttleMin, throttleMax;
|
||||
// static int16_t throttlePrevious = 0; // Store the last throttle direction for deadband transitions
|
||||
|
||||
// Find min and max throttle based on condition.
|
||||
#ifdef USE_GLOBAL_FUNCTIONS
|
||||
if (GLOBAL_FUNCTION_FLAG(GLOBAL_FUNCTION_FLAG_OVERRIDE_THROTTLE)) {
|
||||
throttleRangeMin = throttleIdleValue;
|
||||
throttleRangeMax = motorConfig()->maxthrottle;
|
||||
mixerThrottleCommand = constrain(globalFunctionValues[GLOBAL_FUNCTION_ACTION_OVERRIDE_THROTTLE], throttleMin, throttleMax);
|
||||
mixerThrottleCommand = constrain(globalFunctionValues[GLOBAL_FUNCTION_ACTION_OVERRIDE_THROTTLE], throttleRangeMin, throttleRangeMax);
|
||||
} else
|
||||
#endif
|
||||
if (feature(FEATURE_REVERSIBLE_MOTORS)) {
|
||||
|
@ -516,13 +515,13 @@ void FAST_CODE mixTable(const float dT)
|
|||
|
||||
// Throttle scaling to limit max throttle when battery is full
|
||||
#ifdef USE_GLOBAL_FUNCTIONS
|
||||
mixerThrottleCommand = ((mixerThrottleCommand - throttleMin) * getThrottleScale(motorConfig()->throttleScale)) + throttleMin;
|
||||
mixerThrottleCommand = ((mixerThrottleCommand - throttleRangeMin) * getThrottleScale(motorConfig()->throttleScale)) + throttleRangeMin;
|
||||
#else
|
||||
mixerThrottleCommand = ((mixerThrottleCommand - throttleMin) * motorConfig()->throttleScale) + throttleMin;
|
||||
mixerThrottleCommand = ((mixerThrottleCommand - throttleRangeMin) * motorConfig()->throttleScale) + throttleRangeMin;
|
||||
#endif
|
||||
// Throttle compensation based on battery voltage
|
||||
if (feature(FEATURE_THR_VBAT_COMP) && isAmperageConfigured() && feature(FEATURE_VBAT)) {
|
||||
mixerThrottleCommand = MIN(throttleMin + (mixerThrottleCommand - throttleMin) * calculateThrottleCompensationFactor(), throttleMax);
|
||||
mixerThrottleCommand = MIN(throttleRangeMin + (mixerThrottleCommand - throttleRangeMin) * calculateThrottleCompensationFactor(), throttleRangeMax);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -716,18 +716,18 @@ static void FAST_CODE NOINLINE pidApplyMulticopterRateController(pidState_t *pid
|
|||
newDTerm = 0;
|
||||
} else {
|
||||
// Calculate delta for Dterm calculation. Apply filters before derivative to minimize effects of dterm kick
|
||||
float deltaFiltered = pidProfile()->dterm_setpoint_weight * pidState->rateTarget - pidState->gyroRate;
|
||||
|
||||
// Apply D-term notch
|
||||
deltaFiltered = notchFilterApplyFn(&pidState->deltaNotchFilter, deltaFiltered);
|
||||
|
||||
// Apply additional lowpass
|
||||
deltaFiltered = dTermLpfFilterApplyFn((filter_t *) &pidState->dtermLpfState, deltaFiltered);
|
||||
deltaFiltered = dTermLpf2FilterApplyFn((filter_t *) &pidState->dtermLpf2State, deltaFiltered);
|
||||
const float deltaFiltered = pidProfile()->dterm_setpoint_weight * pidState->rateTarget - pidState->gyroRate;
|
||||
|
||||
firFilterUpdate(&pidState->gyroRateFilter, deltaFiltered);
|
||||
newDTerm = firFilterApply(&pidState->gyroRateFilter);
|
||||
|
||||
// Apply D-term notch
|
||||
newDTerm = notchFilterApplyFn(&pidState->deltaNotchFilter, newDTerm);
|
||||
|
||||
// Apply additional lowpass
|
||||
newDTerm = dTermLpfFilterApplyFn((filter_t *) &pidState->dtermLpfState, newDTerm);
|
||||
newDTerm = dTermLpf2FilterApplyFn((filter_t *) &pidState->dtermLpf2State, newDTerm);
|
||||
|
||||
// Calculate derivative
|
||||
newDTerm = newDTerm * (pidState->kD / dT) * applyDBoost(pidState, dT);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "config/parameter_group_ids.h"
|
||||
|
||||
#include "drivers/pwm_output.h"
|
||||
#include "drivers/pwm_mapping.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
#include "fc/config.h"
|
||||
|
@ -53,12 +54,13 @@
|
|||
|
||||
#include "sensors/gyro.h"
|
||||
|
||||
PG_REGISTER_WITH_RESET_TEMPLATE(servoConfig_t, servoConfig, PG_SERVO_CONFIG, 0);
|
||||
PG_REGISTER_WITH_RESET_TEMPLATE(servoConfig_t, servoConfig, PG_SERVO_CONFIG, 1);
|
||||
|
||||
PG_RESET_TEMPLATE(servoConfig_t, servoConfig,
|
||||
.servoCenterPulse = 1500,
|
||||
.servoPwmRate = 50, // Default for analog servos
|
||||
.servo_lowpass_freq = 20, // Default servo update rate is 50Hz, everything above Nyquist frequency (25Hz) is going to fold and cause distortions
|
||||
.servo_protocol = SERVO_TYPE_PWM,
|
||||
.flaperon_throw_offset = FLAPERON_THROW_DEFAULT,
|
||||
.tri_unarmed_servo = 1
|
||||
);
|
||||
|
@ -263,7 +265,7 @@ void servoMixer(float dT)
|
|||
|
||||
input[INPUT_FEATURE_FLAPS] = FLIGHT_MODE(FLAPERON) ? servoConfig()->flaperon_throw_offset : 0;
|
||||
|
||||
input[INPUT_LOGIC_ONE] = 500;
|
||||
input[INPUT_MAX] = 500;
|
||||
#ifdef USE_LOGIC_CONDITIONS
|
||||
input[INPUT_GVAR_0] = constrain(gvGet(0), -1000, 1000);
|
||||
input[INPUT_GVAR_1] = constrain(gvGet(1), -1000, 1000);
|
||||
|
|
|
@ -53,7 +53,7 @@ typedef enum {
|
|||
INPUT_STABILIZED_PITCH_MINUS = 26,
|
||||
INPUT_STABILIZED_YAW_PLUS = 27,
|
||||
INPUT_STABILIZED_YAW_MINUS = 28,
|
||||
INPUT_LOGIC_ONE = 29,
|
||||
INPUT_MAX = 29,
|
||||
INPUT_GVAR_0 = 30,
|
||||
INPUT_GVAR_1 = 31,
|
||||
INPUT_GVAR_2 = 32,
|
||||
|
@ -132,7 +132,7 @@ typedef struct servoConfig_s {
|
|||
uint16_t servoPwmRate; // The update rate of servo outputs (50-498Hz)
|
||||
int16_t servo_lowpass_freq; // lowpass servo filter frequency selection; 1/1000ths of loop freq
|
||||
uint16_t flaperon_throw_offset;
|
||||
uint8_t __reserved;
|
||||
uint8_t servo_protocol; // See servoProtocolType_e
|
||||
uint8_t tri_unarmed_servo; // send tail servo correction pulses even when unarmed
|
||||
} servoConfig_t;
|
||||
|
||||
|
|
|
@ -259,14 +259,14 @@ static void setLineOutlineType(displayCanvas_t *displayCanvas, displayCanvasOutl
|
|||
{
|
||||
UNUSED(displayCanvas);
|
||||
|
||||
frskyOSDSetLineOutlineType(outlineType);
|
||||
frskyOSDSetLineOutlineType((frskyOSDLineOutlineType_e)outlineType);
|
||||
}
|
||||
|
||||
static void setLineOutlineColor(displayCanvas_t *displayCanvas, displayCanvasColor_e outlineColor)
|
||||
{
|
||||
UNUSED(displayCanvas);
|
||||
|
||||
frskyOSDSetLineOutlineColor(outlineColor);
|
||||
frskyOSDSetLineOutlineColor((frskyOSDColor_e)outlineColor);
|
||||
}
|
||||
|
||||
static void clipToRect(displayCanvas_t *displayCanvas, int x, int y, int w, int h)
|
||||
|
|
|
@ -24,18 +24,17 @@
|
|||
*
|
||||
* Note that bits can only be set to 0 when writing, not back to 1 from 0. You must erase sectors in order
|
||||
* to bring bits back to 1 again.
|
||||
*
|
||||
* In future, we can add support for multiple different flash chips by adding a flash device driver vtable
|
||||
* and make calls through that, at the moment flashfs just calls m25p16_* routines explicitly.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "drivers/flash_m25p16.h"
|
||||
#include "drivers/flash.h"
|
||||
#include "flashfs.h"
|
||||
|
||||
static flashPartition_t *flashPartition;
|
||||
|
||||
static uint8_t flashWriteBuffer[FLASHFS_WRITE_BUFFER_SIZE];
|
||||
|
||||
/* The position of our head and tail in the circular flash write buffer.
|
||||
|
@ -67,10 +66,8 @@ static void flashfsSetTailAddress(uint32_t address)
|
|||
|
||||
void flashfsEraseCompletely(void)
|
||||
{
|
||||
m25p16_eraseCompletely();
|
||||
|
||||
flashPartitionErase(flashPartition);
|
||||
flashfsClearBuffer();
|
||||
|
||||
flashfsSetTailAddress(0);
|
||||
}
|
||||
|
||||
|
@ -80,7 +77,7 @@ void flashfsEraseCompletely(void)
|
|||
*/
|
||||
void flashfsEraseRange(uint32_t start, uint32_t end)
|
||||
{
|
||||
const flashGeometry_t *geometry = m25p16_getGeometry();
|
||||
const flashGeometry_t *geometry = flashGetGeometry();
|
||||
|
||||
if (geometry->sectorSize <= 0)
|
||||
return;
|
||||
|
@ -97,7 +94,7 @@ void flashfsEraseRange(uint32_t start, uint32_t end)
|
|||
}
|
||||
|
||||
for (int i = startSector; i < endSector; i++) {
|
||||
m25p16_eraseSector(i * geometry->sectorSize);
|
||||
flashEraseSector(i * geometry->sectorSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,12 +103,12 @@ void flashfsEraseRange(uint32_t start, uint32_t end)
|
|||
*/
|
||||
bool flashfsIsReady(void)
|
||||
{
|
||||
return m25p16_isReady();
|
||||
return !!flashPartition;
|
||||
}
|
||||
|
||||
uint32_t flashfsGetSize(void)
|
||||
{
|
||||
return m25p16_getGeometry()->totalSize;
|
||||
return flashPartitionSize(flashPartition);
|
||||
}
|
||||
|
||||
static uint32_t flashfsTransmitBufferUsed(void)
|
||||
|
@ -138,11 +135,6 @@ uint32_t flashfsGetWriteBufferFreeSpace(void)
|
|||
return flashfsGetWriteBufferSize() - flashfsTransmitBufferUsed();
|
||||
}
|
||||
|
||||
const flashGeometry_t* flashfsGetGeometry(void)
|
||||
{
|
||||
return m25p16_getGeometry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the given buffers to flash sequentially at the current tail address, advancing the tail address after
|
||||
* each write.
|
||||
|
@ -164,6 +156,8 @@ const flashGeometry_t* flashfsGetGeometry(void)
|
|||
*/
|
||||
static uint32_t flashfsWriteBuffers(uint8_t const **buffers, uint32_t *bufferSizes, int bufferCount, bool sync)
|
||||
{
|
||||
const flashGeometry_t *geometry = flashGetGeometry();
|
||||
|
||||
uint32_t bytesTotal = 0;
|
||||
|
||||
int i;
|
||||
|
@ -172,7 +166,7 @@ static uint32_t flashfsWriteBuffers(uint8_t const **buffers, uint32_t *bufferSiz
|
|||
bytesTotal += bufferSizes[i];
|
||||
}
|
||||
|
||||
if (!sync && !m25p16_isReady()) {
|
||||
if (!sync && !flashIsReady()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -187,8 +181,8 @@ static uint32_t flashfsWriteBuffers(uint8_t const **buffers, uint32_t *bufferSiz
|
|||
* Each page needs to be saved in a separate program operation, so
|
||||
* if we would cross a page boundary, only write up to the boundary in this iteration:
|
||||
*/
|
||||
if (tailAddress % M25P16_PAGESIZE + bytesTotalRemaining > M25P16_PAGESIZE) {
|
||||
bytesTotalThisIteration = M25P16_PAGESIZE - tailAddress % M25P16_PAGESIZE;
|
||||
if (tailAddress % geometry->pageSize + bytesTotalRemaining > geometry->pageSize) {
|
||||
bytesTotalThisIteration = geometry->pageSize - tailAddress % geometry->pageSize;
|
||||
} else {
|
||||
bytesTotalThisIteration = bytesTotalRemaining;
|
||||
}
|
||||
|
@ -207,7 +201,7 @@ static uint32_t flashfsWriteBuffers(uint8_t const **buffers, uint32_t *bufferSiz
|
|||
if (bufferSizes[i] > 0) {
|
||||
// Is buffer larger than our write limit? Write our limit out of it
|
||||
if (bufferSizes[i] >= bytesRemainThisIteration) {
|
||||
currentFlashAddress = m25p16_pageProgram(currentFlashAddress, buffers[i], bytesRemainThisIteration);
|
||||
currentFlashAddress = flashPageProgram(currentFlashAddress, buffers[i], bytesRemainThisIteration);
|
||||
|
||||
buffers[i] += bytesRemainThisIteration;
|
||||
bufferSizes[i] -= bytesRemainThisIteration;
|
||||
|
@ -216,7 +210,7 @@ static uint32_t flashfsWriteBuffers(uint8_t const **buffers, uint32_t *bufferSiz
|
|||
break;
|
||||
} else {
|
||||
// We'll still have more to write after finishing this buffer off
|
||||
currentFlashAddress = m25p16_pageProgram(currentFlashAddress, buffers[i], bufferSizes[i]);
|
||||
currentFlashAddress = flashPageProgram(currentFlashAddress, buffers[i], bufferSizes[i]);
|
||||
|
||||
bytesRemainThisIteration -= bufferSizes[i];
|
||||
|
||||
|
@ -471,7 +465,7 @@ int flashfsReadAbs(uint32_t address, uint8_t *buffer, unsigned int len)
|
|||
// Since the read could overlap data in our dirty buffers, force a sync to clear those first
|
||||
flashfsFlushSync();
|
||||
|
||||
bytesRead = m25p16_readBytes(address, buffer, len);
|
||||
bytesRead = flashReadBytes(address, buffer, len);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -516,7 +510,7 @@ int flashfsIdentifyStartOfFreeSpace(void)
|
|||
while (left < right) {
|
||||
mid = (left + right) / 2;
|
||||
|
||||
if (m25p16_readBytes(mid * FREE_BLOCK_SIZE, testBuffer.bytes, FREE_BLOCK_TEST_SIZE_BYTES) < FREE_BLOCK_TEST_SIZE_BYTES) {
|
||||
if (flashReadBytes(mid * FREE_BLOCK_SIZE, testBuffer.bytes, FREE_BLOCK_TEST_SIZE_BYTES) < FREE_BLOCK_TEST_SIZE_BYTES) {
|
||||
// Unexpected timeout from flash, so bail early (reporting the device fuller than it really is)
|
||||
break;
|
||||
}
|
||||
|
@ -558,8 +552,9 @@ bool flashfsIsEOF(void)
|
|||
*/
|
||||
void flashfsInit(void)
|
||||
{
|
||||
// If we have a flash chip present at all
|
||||
if (flashfsGetSize() > 0) {
|
||||
flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_FLASHFS);
|
||||
|
||||
if (flashPartition) {
|
||||
// Start the file pointer off at the beginning of free space so caller can start writing immediately
|
||||
flashfsSeekAbs(flashfsIdentifyStartOfFreeSpace());
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ uint32_t flashfsGetOffset(void);
|
|||
uint32_t flashfsGetWriteBufferFreeSpace(void);
|
||||
uint32_t flashfsGetWriteBufferSize(void);
|
||||
int flashfsIdentifyStartOfFreeSpace(void);
|
||||
const flashGeometry_t* flashfsGetGeometry(void);
|
||||
|
||||
void flashfsSeekAbs(uint32_t offset);
|
||||
void flashfsSeekRel(int32_t offset);
|
||||
|
|
|
@ -198,7 +198,7 @@ static bool osdDisplayHasCanvas;
|
|||
#define AH_SIDEBAR_WIDTH_POS 7
|
||||
#define AH_SIDEBAR_HEIGHT_POS 3
|
||||
|
||||
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 11);
|
||||
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 12);
|
||||
|
||||
static int digitCount(int32_t value)
|
||||
{
|
||||
|
@ -2480,6 +2480,13 @@ static bool osdDrawSingleElement(uint8_t item)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OSD_ESC_TEMPERATURE:
|
||||
{
|
||||
escSensorData_t * escSensor = escSensorGetData();
|
||||
bool escTemperatureValid = escSensor && escSensor->dataAge <= ESC_DATA_MAX_AGE;
|
||||
osdDisplayTemperature(elemPosX, elemPosY, SYM_ESC_TEMP, NULL, escTemperatureValid, (escSensor->temperature)*10, osdConfig()->esc_temp_alarm_min, osdConfig()->esc_temp_alarm_max);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
@ -2695,6 +2702,7 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
|
||||
#if defined(USE_ESC_SENSOR)
|
||||
osdConfig->item_pos[0][OSD_ESC_RPM] = OSD_POS(1, 2);
|
||||
osdConfig->item_pos[0][OSD_ESC_TEMPERATURE] = OSD_POS(1, 3);
|
||||
#endif
|
||||
|
||||
#if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
|
||||
|
@ -2718,6 +2726,8 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
osdConfig->current_alarm = 0;
|
||||
osdConfig->imu_temp_alarm_min = -200;
|
||||
osdConfig->imu_temp_alarm_max = 600;
|
||||
osdConfig->esc_temp_alarm_min = -200;
|
||||
osdConfig->esc_temp_alarm_max = 900;
|
||||
osdConfig->gforce_alarm = 5;
|
||||
osdConfig->gforce_axis_alarm_min = -5;
|
||||
osdConfig->gforce_axis_alarm_max = 5;
|
||||
|
@ -2936,6 +2946,7 @@ static void osdShowStats(void)
|
|||
const uint8_t statValuesX = 20;
|
||||
char buff[10];
|
||||
|
||||
displayBeginTransaction(osdDisplayPort, DISPLAY_TRANSACTION_OPT_RESET_DRAWING);
|
||||
displayClearScreen(osdDisplayPort);
|
||||
if (IS_DISPLAY_PAL)
|
||||
displayWrite(osdDisplayPort, statNameX, top++, " --- STATS ---");
|
||||
|
@ -3031,6 +3042,7 @@ static void osdShowStats(void)
|
|||
|
||||
displayWrite(osdDisplayPort, statNameX, top, "DISARMED BY :");
|
||||
displayWrite(osdDisplayPort, statValuesX, top++, disarmReasonStr[getDisarmReason()]);
|
||||
displayCommitTransaction(osdDisplayPort);
|
||||
}
|
||||
|
||||
// called when motors armed
|
||||
|
|
|
@ -151,6 +151,7 @@ typedef enum {
|
|||
OSD_RC_SOURCE,
|
||||
OSD_VTX_POWER,
|
||||
OSD_ESC_RPM,
|
||||
OSD_ESC_TEMPERATURE,
|
||||
OSD_ITEM_COUNT // MUST BE LAST
|
||||
} osd_items_e;
|
||||
|
||||
|
@ -205,6 +206,8 @@ typedef struct osdConfig_s {
|
|||
uint8_t current_alarm; // current consumption in A
|
||||
int16_t imu_temp_alarm_min;
|
||||
int16_t imu_temp_alarm_max;
|
||||
int16_t esc_temp_alarm_min;
|
||||
int16_t esc_temp_alarm_max;
|
||||
float gforce_alarm;
|
||||
float gforce_axis_alarm_min;
|
||||
float gforce_axis_alarm_max;
|
||||
|
|
|
@ -104,64 +104,69 @@ const uint8_t djiPidIndexMap[] = {
|
|||
PID_HEADING // DJI: PID_MAG
|
||||
};
|
||||
|
||||
const int djiOSDItemIndexMap[] = {
|
||||
OSD_RSSI_VALUE, // DJI: OSD_RSSI_VALUE
|
||||
OSD_MAIN_BATT_VOLTAGE, // DJI: OSD_MAIN_BATT_VOLTAGE
|
||||
OSD_CROSSHAIRS, // DJI: OSD_CROSSHAIRS
|
||||
OSD_ARTIFICIAL_HORIZON, // DJI: OSD_ARTIFICIAL_HORIZON
|
||||
OSD_HORIZON_SIDEBARS, // DJI: OSD_HORIZON_SIDEBARS
|
||||
OSD_ONTIME, // DJI: OSD_ITEM_TIMER_1
|
||||
OSD_FLYTIME, // DJI: OSD_ITEM_TIMER_2
|
||||
OSD_FLYMODE, // DJI: OSD_FLYMODE
|
||||
OSD_CRAFT_NAME, // DJI: OSD_CRAFT_NAME
|
||||
OSD_THROTTLE_POS, // DJI: OSD_THROTTLE_POS
|
||||
OSD_VTX_CHANNEL, // DJI: OSD_VTX_CHANNEL
|
||||
OSD_CURRENT_DRAW, // DJI: OSD_CURRENT_DRAW
|
||||
OSD_MAH_DRAWN, // DJI: OSD_MAH_DRAWN
|
||||
OSD_GPS_SPEED, // DJI: OSD_GPS_SPEED
|
||||
OSD_GPS_SATS, // DJI: OSD_GPS_SATS
|
||||
OSD_ALTITUDE, // DJI: OSD_ALTITUDE
|
||||
OSD_ROLL_PIDS, // DJI: OSD_ROLL_PIDS
|
||||
OSD_PITCH_PIDS, // DJI: OSD_PITCH_PIDS
|
||||
OSD_YAW_PIDS, // DJI: OSD_YAW_PIDS
|
||||
OSD_POWER, // DJI: OSD_POWER
|
||||
-1, // DJI: OSD_PIDRATE_PROFILE
|
||||
-1, // DJI: OSD_WARNINGS
|
||||
OSD_MAIN_BATT_CELL_VOLTAGE, // DJI: OSD_AVG_CELL_VOLTAGE
|
||||
OSD_GPS_LON, // DJI: OSD_GPS_LON
|
||||
OSD_GPS_LAT, // DJI: OSD_GPS_LAT
|
||||
OSD_DEBUG, // DJI: OSD_DEBUG
|
||||
OSD_ATTITUDE_PITCH, // DJI: OSD_PITCH_ANGLE
|
||||
OSD_ATTITUDE_ROLL, // DJI: OSD_ROLL_ANGLE
|
||||
-1, // DJI: OSD_MAIN_BATT_USAGE
|
||||
-1, // DJI: OSD_DISARMED
|
||||
OSD_HOME_DIR, // DJI: OSD_HOME_DIR
|
||||
OSD_HOME_DIST, // DJI: OSD_HOME_DIST
|
||||
OSD_HEADING, // DJI: OSD_NUMERICAL_HEADING
|
||||
OSD_VARIO_NUM, // DJI: OSD_NUMERICAL_VARIO
|
||||
-1, // DJI: OSD_COMPASS_BAR
|
||||
-1, // DJI: OSD_ESC_TMP
|
||||
OSD_ESC_RPM, // DJI: OSD_ESC_RPM
|
||||
OSD_REMAINING_FLIGHT_TIME_BEFORE_RTH, // DJI: OSD_REMAINING_TIME_ESTIMATE
|
||||
OSD_RTC_TIME, // DJI: OSD_RTC_DATETIME
|
||||
-1, // DJI: OSD_ADJUSTMENT_RANGE
|
||||
-1, // DJI: OSD_CORE_TEMPERATURE
|
||||
-1, // DJI: OSD_ANTI_GRAVITY
|
||||
-1, // DJI: OSD_G_FORCE
|
||||
-1, // DJI: OSD_MOTOR_DIAG
|
||||
-1, // DJI: OSD_LOG_STATUS
|
||||
-1, // DJI: OSD_FLIP_ARROW
|
||||
-1, // DJI: OSD_LINK_QUALITY
|
||||
OSD_TRIP_DIST, // DJI: OSD_FLIGHT_DIST
|
||||
-1, // DJI: OSD_STICK_OVERLAY_LEFT
|
||||
-1, // DJI: OSD_STICK_OVERLAY_RIGHT
|
||||
-1, // DJI: OSD_DISPLAY_NAME
|
||||
-1, // DJI: OSD_ESC_RPM_FREQ
|
||||
-1, // DJI: OSD_RATE_PROFILE_NAME
|
||||
-1, // DJI: OSD_PID_PROFILE_NAME
|
||||
-1, // DJI: OSD_PROFILE_NAME
|
||||
-1, // DJI: OSD_RSSI_DBM_VALUE
|
||||
-1, // DJI: OSD_RC_CHANNELS
|
||||
typedef struct {
|
||||
int itemIndex; // INAV OSD item
|
||||
features_e depFeature; // INAV feature that item is dependent on
|
||||
} djiOsdMapping_t;
|
||||
|
||||
const djiOsdMapping_t djiOSDItemIndexMap[] = {
|
||||
{ OSD_RSSI_VALUE, 0 }, // DJI: OSD_RSSI_VALUE
|
||||
{ OSD_MAIN_BATT_VOLTAGE, FEATURE_VBAT }, // DJI: OSD_MAIN_BATT_VOLTAGE
|
||||
{ OSD_CROSSHAIRS, 0 }, // DJI: OSD_CROSSHAIRS
|
||||
{ OSD_ARTIFICIAL_HORIZON, 0 }, // DJI: OSD_ARTIFICIAL_HORIZON
|
||||
{ OSD_HORIZON_SIDEBARS, 0 }, // DJI: OSD_HORIZON_SIDEBARS
|
||||
{ OSD_ONTIME, 0 }, // DJI: OSD_ITEM_TIMER_1
|
||||
{ OSD_FLYTIME, 0 }, // DJI: OSD_ITEM_TIMER_2
|
||||
{ OSD_FLYMODE, 0 }, // DJI: OSD_FLYMODE
|
||||
{ OSD_CRAFT_NAME, 0 }, // DJI: OSD_CRAFT_NAME
|
||||
{ OSD_THROTTLE_POS, 0 }, // DJI: OSD_THROTTLE_POS
|
||||
{ OSD_VTX_CHANNEL, 0 }, // DJI: OSD_VTX_CHANNEL
|
||||
{ OSD_CURRENT_DRAW, FEATURE_CURRENT_METER }, // DJI: OSD_CURRENT_DRAW
|
||||
{ OSD_MAH_DRAWN, FEATURE_CURRENT_METER }, // DJI: OSD_MAH_DRAWN
|
||||
{ OSD_GPS_SPEED, FEATURE_GPS }, // DJI: OSD_GPS_SPEED
|
||||
{ OSD_GPS_SATS, FEATURE_GPS }, // DJI: OSD_GPS_SATS
|
||||
{ OSD_ALTITUDE, 0 }, // DJI: OSD_ALTITUDE
|
||||
{ OSD_ROLL_PIDS, 0 }, // DJI: OSD_ROLL_PIDS
|
||||
{ OSD_PITCH_PIDS, 0 }, // DJI: OSD_PITCH_PIDS
|
||||
{ OSD_YAW_PIDS, 0 }, // DJI: OSD_YAW_PIDS
|
||||
{ OSD_POWER, 0 }, // DJI: OSD_POWER
|
||||
{ -1, 0 }, // DJI: OSD_PIDRATE_PROFILE
|
||||
{ -1, 0 }, // DJI: OSD_WARNINGS
|
||||
{ OSD_MAIN_BATT_CELL_VOLTAGE, 0 }, // DJI: OSD_AVG_CELL_VOLTAGE
|
||||
{ OSD_GPS_LON, FEATURE_GPS }, // DJI: OSD_GPS_LON
|
||||
{ OSD_GPS_LAT, FEATURE_GPS }, // DJI: OSD_GPS_LAT
|
||||
{ OSD_DEBUG, 0 }, // DJI: OSD_DEBUG
|
||||
{ OSD_ATTITUDE_PITCH, 0 }, // DJI: OSD_PITCH_ANGLE
|
||||
{ OSD_ATTITUDE_ROLL, 0 }, // DJI: OSD_ROLL_ANGLE
|
||||
{ -1, 0 }, // DJI: OSD_MAIN_BATT_USAGE
|
||||
{ -1, 0 }, // DJI: OSD_DISARMED
|
||||
{ OSD_HOME_DIR, FEATURE_GPS }, // DJI: OSD_HOME_DIR
|
||||
{ OSD_HOME_DIST, FEATURE_GPS }, // DJI: OSD_HOME_DIST
|
||||
{ OSD_HEADING, 0 }, // DJI: OSD_NUMERICAL_HEADING
|
||||
{ OSD_VARIO_NUM, 0 }, // DJI: OSD_NUMERICAL_VARIO
|
||||
{ -1, 0 }, // DJI: OSD_COMPASS_BAR
|
||||
{ -1, 0 }, // DJI: OSD_ESC_TMP
|
||||
{ OSD_ESC_RPM, 0 }, // DJI: OSD_ESC_RPM
|
||||
{ OSD_REMAINING_FLIGHT_TIME_BEFORE_RTH, FEATURE_CURRENT_METER }, // DJI: OSD_REMAINING_TIME_ESTIMATE
|
||||
{ OSD_RTC_TIME, 0 }, // DJI: OSD_RTC_DATETIME
|
||||
{ -1, 0 }, // DJI: OSD_ADJUSTMENT_RANGE
|
||||
{ -1, 0 }, // DJI: OSD_CORE_TEMPERATURE
|
||||
{ -1, 0 }, // DJI: OSD_ANTI_GRAVITY
|
||||
{ -1, 0 }, // DJI: OSD_G_FORCE
|
||||
{ -1, 0 }, // DJI: OSD_MOTOR_DIAG
|
||||
{ -1, 0 }, // DJI: OSD_LOG_STATUS
|
||||
{ -1, 0 }, // DJI: OSD_FLIP_ARROW
|
||||
{ -1, 0 }, // DJI: OSD_LINK_QUALITY
|
||||
{ OSD_TRIP_DIST, FEATURE_GPS }, // DJI: OSD_FLIGHT_DIST
|
||||
{ -1, 0 }, // DJI: OSD_STICK_OVERLAY_LEFT
|
||||
{ -1, 0 }, // DJI: OSD_STICK_OVERLAY_RIGHT
|
||||
{ -1, 0 }, // DJI: OSD_DISPLAY_NAME
|
||||
{ -1, 0 }, // DJI: OSD_ESC_RPM_FREQ
|
||||
{ -1, 0 }, // DJI: OSD_RATE_PROFILE_NAME
|
||||
{ -1, 0 }, // DJI: OSD_PID_PROFILE_NAME
|
||||
{ -1, 0 }, // DJI: OSD_PROFILE_NAME
|
||||
{ -1, 0 }, // DJI: OSD_RSSI_DBM_VALUE
|
||||
{ -1, 0 }, // DJI: OSD_RC_CHANNELS
|
||||
};
|
||||
|
||||
const int djiOSDStatisticsMap[] = {
|
||||
|
@ -289,8 +294,12 @@ static void djiSerializeOSDConfigReply(sbuf_t *dst)
|
|||
|
||||
// OSD element position and visibility
|
||||
for (unsigned i = 0; i < ARRAYLEN(djiOSDItemIndexMap); i++) {
|
||||
int inavOSDIdx = djiOSDItemIndexMap[i];
|
||||
if (inavOSDIdx >= 0) {
|
||||
const int inavOSDIdx = djiOSDItemIndexMap[i].itemIndex;
|
||||
|
||||
// We call OSD item supported if it doesn't have dependencies or all feature-dependencies are satistied
|
||||
const bool itemIsSupported = ((djiOSDItemIndexMap[i].depFeature == 0) || feature(djiOSDItemIndexMap[i].depFeature));
|
||||
|
||||
if (inavOSDIdx >= 0 && itemIsSupported) {
|
||||
// Position & visibility encoded in 16 bits. Position encoding is the same between BF/DJI and INAV
|
||||
// However visibility is different. INAV has 3 layouts, while BF only has visibility profiles
|
||||
// Here we use only one OSD layout mapped to first OSD BF profile
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue