Merge pull request #2 from nathantsoi/sirinfpv-max-osd-development
Sirinfpv max osd development
This commit is contained in:
commit
7a4d996318
|
@ -8,6 +8,7 @@ targets=("PUBLISHMETA=True" \
|
||||||
"TARGET=SPRACINGF3" \
|
"TARGET=SPRACINGF3" \
|
||||||
"TARGET=SPRACINGF3EVO" \
|
"TARGET=SPRACINGF3EVO" \
|
||||||
"TARGET=SPRACINGF3MINI" \
|
"TARGET=SPRACINGF3MINI" \
|
||||||
|
"TARGET=OMNIBUS" \
|
||||||
"TARGET=NAZE" \
|
"TARGET=NAZE" \
|
||||||
"TARGET=AFROMINI" \
|
"TARGET=AFROMINI" \
|
||||||
"TARGET=RMDO" \
|
"TARGET=RMDO" \
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "drivers/gyro_sync.h"
|
#include "drivers/gyro_sync.h"
|
||||||
#include "drivers/pwm_output.h"
|
#include "drivers/pwm_output.h"
|
||||||
|
#include "drivers/max7456.h"
|
||||||
|
|
||||||
#include "sensors/sensors.h"
|
#include "sensors/sensors.h"
|
||||||
#include "sensors/gyro.h"
|
#include "sensors/gyro.h"
|
||||||
|
@ -420,17 +421,7 @@ static void resetConf(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OSD
|
#ifdef OSD
|
||||||
featureSet(FEATURE_OSD);
|
resetOsdConfig();
|
||||||
masterConfig.osdProfile.system = 0;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] = -29;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] = -59;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_TIMER] = -39;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] = -9;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] = 26;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_VTX_CHANNEL] = 1;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING] = -80;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_ARMED] = -107;
|
|
||||||
masterConfig.osdProfile.item_pos[OSD_DISARMED] = -109;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_RTC6705
|
#ifdef USE_RTC6705
|
||||||
|
|
|
@ -27,22 +27,27 @@
|
||||||
#ifdef USE_MAX7456
|
#ifdef USE_MAX7456
|
||||||
|
|
||||||
#include "drivers/bus_spi.h"
|
#include "drivers/bus_spi.h"
|
||||||
|
#include "drivers/light_led.h"
|
||||||
#include "drivers/system.h"
|
#include "drivers/system.h"
|
||||||
|
|
||||||
#include "max7456.h"
|
#include "max7456.h"
|
||||||
|
#include "max7456_symbols.h"
|
||||||
|
|
||||||
#define DISABLE_MAX7456 GPIO_SetBits(MAX7456_CS_GPIO, MAX7456_CS_PIN)
|
#define DISABLE_MAX7456 IOHi(max7456CsPin)
|
||||||
#define ENABLE_MAX7456 GPIO_ResetBits(MAX7456_CS_GPIO, MAX7456_CS_PIN)
|
#define ENABLE_MAX7456 IOLo(max7456CsPin)
|
||||||
|
|
||||||
/** PAL or NTSC, value is number of chars total */
|
static IO_t max7456CsPin = IO_NONE;
|
||||||
#define VIDEO_BUFFER_CHARS_NTSC 390
|
|
||||||
#define VIDEO_BUFFER_CHARS_PAL 480
|
|
||||||
|
|
||||||
|
/** Artificial Horizon limits **/
|
||||||
|
#define AHIPITCHMAX 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees
|
||||||
|
#define AHIROLLMAX 400 // Specify maximum AHI roll value displayed. Default 400 = 40.0 degrees
|
||||||
|
#define AHISIDEBARWIDTHPOSITION 7
|
||||||
|
#define AHISIDEBARHEIGHTPOSITION 3
|
||||||
|
|
||||||
uint16_t max_screen_size;
|
uint16_t max_screen_size;
|
||||||
uint8_t video_signal_type = 0;
|
uint8_t video_signal_type = 0;
|
||||||
uint8_t max7456_lock = 0;
|
uint8_t max7456_lock = 0;
|
||||||
char screen[VIDEO_BUFFER_CHARS_PAL];
|
char max7456_screen[VIDEO_BUFFER_CHARS_PAL];
|
||||||
|
|
||||||
|
|
||||||
uint8_t max7456_send(uint8_t add, uint8_t data) {
|
uint8_t max7456_send(uint8_t add, uint8_t data) {
|
||||||
|
@ -51,11 +56,17 @@ uint8_t max7456_send(uint8_t add, uint8_t data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void max7456_init(uint8_t system) {
|
void max7456_init(uint8_t video_system) {
|
||||||
uint8_t max_screen_rows;
|
uint8_t max_screen_rows;
|
||||||
uint8_t srdata = 0;
|
uint8_t srdata = 0;
|
||||||
uint16_t x;
|
uint16_t x;
|
||||||
char buf[30];
|
char buf[LINE];
|
||||||
|
|
||||||
|
#ifdef MAX7456_SPI_CS_PIN
|
||||||
|
max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN));
|
||||||
|
#endif
|
||||||
|
IOInit(max7456CsPin, OWNER_SYSTEM, RESOURCE_SPI);
|
||||||
|
IOConfigGPIO(max7456CsPin, SPI_IO_CS_CFG);
|
||||||
|
|
||||||
//Minimum spi clock period for max7456 is 100ns (10Mhz)
|
//Minimum spi clock period for max7456 is 100ns (10Mhz)
|
||||||
spiSetDivisor(MAX7456_SPI_INSTANCE, SPI_9MHZ_CLOCK_DIVIDER);
|
spiSetDivisor(MAX7456_SPI_INSTANCE, SPI_9MHZ_CLOCK_DIVIDER);
|
||||||
|
@ -75,21 +86,21 @@ void max7456_init(uint8_t system) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override detected type: 0-AUTO, 1-PAL, 2-NTSC
|
// Override detected type: 0-AUTO, 1-PAL, 2-NTSC
|
||||||
switch(system) {
|
switch(video_system) {
|
||||||
case 1:
|
case PAL:
|
||||||
video_signal_type = VIDEO_MODE_PAL;
|
video_signal_type = VIDEO_MODE_PAL;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case NTSC:
|
||||||
video_signal_type = VIDEO_MODE_NTSC;
|
video_signal_type = VIDEO_MODE_NTSC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_signal_type) { //PAL
|
if (video_signal_type) { //PAL
|
||||||
max_screen_size = VIDEO_BUFFER_CHARS_PAL;
|
max_screen_size = VIDEO_BUFFER_CHARS_PAL;
|
||||||
max_screen_rows = 16;
|
max_screen_rows = VIDEO_LINES_PAL;
|
||||||
} else { // NTSC
|
} else { // NTSC
|
||||||
max_screen_size = VIDEO_BUFFER_CHARS_NTSC;
|
max_screen_size = VIDEO_BUFFER_CHARS_NTSC;
|
||||||
max_screen_rows = 13;
|
max_screen_rows = VIDEO_LINES_NTSC;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set all rows to same charactor black/white level
|
// set all rows to same charactor black/white level
|
||||||
|
@ -106,13 +117,13 @@ void max7456_init(uint8_t system) {
|
||||||
x = 160;
|
x = 160;
|
||||||
for (int i = 1; i < 5; i++) {
|
for (int i = 1; i < 5; i++) {
|
||||||
for (int j = 3; j < 27; j++)
|
for (int j = 3; j < 27; j++)
|
||||||
screen[i * 30 + j] = (char)x++;
|
max7456_screen[i * LINE + j] = (char)x++;
|
||||||
}
|
}
|
||||||
tfp_sprintf(buf, "BF VERSION: %s", FC_VERSION_STRING);
|
tfp_sprintf(buf, "BF VERSION: %s", FC_VERSION_STRING);
|
||||||
max7456_write_string(buf, 5*30+5);
|
max7456_write_string(buf, LINE06+5);
|
||||||
max7456_write_string("MENU: THRT MID", 6*30+7);
|
max7456_write_string("MENU: THRT MID", LINE07+7);
|
||||||
max7456_write_string("YAW RIGHT", 7*30+13);
|
max7456_write_string("YAW RIGHT", LINE08+13);
|
||||||
max7456_write_string("PITCH UP", 8*30+13);
|
max7456_write_string("PITCH UP", LINE09+13);
|
||||||
max7456_draw_screen();
|
max7456_draw_screen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,14 +132,52 @@ void max7456_write_string(const char *string, int16_t address) {
|
||||||
char *dest;
|
char *dest;
|
||||||
|
|
||||||
if (address >= 0)
|
if (address >= 0)
|
||||||
dest = screen + address;
|
dest = max7456_screen + address;
|
||||||
else
|
else
|
||||||
dest = screen + (max_screen_size + address);
|
dest = max7456_screen + (max_screen_size + address);
|
||||||
|
|
||||||
while(*string && dest < (screen + max_screen_size))
|
while(*string && dest < (max7456_screen + max_screen_size))
|
||||||
*dest++ = *string++;
|
*dest++ = *string++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Write the artifical horizon to the screen buffer
|
||||||
|
void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars) {
|
||||||
|
uint16_t position = 194;
|
||||||
|
|
||||||
|
if(pitchAngle>AHIPITCHMAX) pitchAngle=AHIPITCHMAX;
|
||||||
|
if(pitchAngle<-AHIPITCHMAX) pitchAngle=-AHIPITCHMAX;
|
||||||
|
if(rollAngle>AHIROLLMAX) rollAngle=AHIROLLMAX;
|
||||||
|
if(rollAngle<-AHIROLLMAX) rollAngle=-AHIROLLMAX;
|
||||||
|
|
||||||
|
for(uint8_t X=0; X<=8; X++) {
|
||||||
|
if (X==4) X=5;
|
||||||
|
int Y = (rollAngle * (4-X)) / 64;
|
||||||
|
Y -= pitchAngle / 8;
|
||||||
|
Y += 41;
|
||||||
|
if(Y >= 0 && Y <= 81) {
|
||||||
|
uint16_t pos = position -7 + LINE*(Y/9) + 3 - 4*LINE + X;
|
||||||
|
max7456_screen[pos] = SYM_AH_BAR9_0+(Y%9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
max7456_screen[position-1] = SYM_AH_CENTER_LINE;
|
||||||
|
max7456_screen[position+1] = SYM_AH_CENTER_LINE_RIGHT;
|
||||||
|
max7456_screen[position] = SYM_AH_CENTER;
|
||||||
|
|
||||||
|
if (show_sidebars) {
|
||||||
|
// Draw AH sides
|
||||||
|
int8_t hudwidth = AHISIDEBARWIDTHPOSITION;
|
||||||
|
int8_t hudheight = AHISIDEBARHEIGHTPOSITION;
|
||||||
|
for(int8_t X=-hudheight; X<=hudheight; X++) {
|
||||||
|
max7456_screen[position-hudwidth+(X*LINE)] = SYM_AH_DECORATION;
|
||||||
|
max7456_screen[position+hudwidth+(X*LINE)] = SYM_AH_DECORATION;
|
||||||
|
}
|
||||||
|
// AH level indicators
|
||||||
|
max7456_screen[position-hudwidth+1] = SYM_AH_LEFT;
|
||||||
|
max7456_screen[position+hudwidth-1] = SYM_AH_RIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void max7456_draw_screen(void) {
|
void max7456_draw_screen(void) {
|
||||||
uint16_t xx;
|
uint16_t xx;
|
||||||
if (!max7456_lock) {
|
if (!max7456_lock) {
|
||||||
|
@ -136,8 +185,8 @@ void max7456_draw_screen(void) {
|
||||||
for (xx = 0; xx < max_screen_size; ++xx) {
|
for (xx = 0; xx < max_screen_size; ++xx) {
|
||||||
max7456_send(MAX7456ADD_DMAH, xx>>8);
|
max7456_send(MAX7456ADD_DMAH, xx>>8);
|
||||||
max7456_send(MAX7456ADD_DMAL, xx);
|
max7456_send(MAX7456ADD_DMAL, xx);
|
||||||
max7456_send(MAX7456ADD_DMDI, screen[xx]);
|
max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]);
|
||||||
screen[xx] = ' ';
|
max7456_screen[xx] = ' ';
|
||||||
}
|
}
|
||||||
DISABLE_MAX7456;
|
DISABLE_MAX7456;
|
||||||
}
|
}
|
||||||
|
@ -151,8 +200,8 @@ void max7456_draw_screen_fast(void) {
|
||||||
max7456_send(MAX7456ADD_DMAL, 0);
|
max7456_send(MAX7456ADD_DMAL, 0);
|
||||||
max7456_send(MAX7456ADD_DMM, 1);
|
max7456_send(MAX7456ADD_DMM, 1);
|
||||||
for (xx = 0; xx < max_screen_size; ++xx) {
|
for (xx = 0; xx < max_screen_size; ++xx) {
|
||||||
max7456_send(MAX7456ADD_DMDI, screen[xx]);
|
max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]);
|
||||||
screen[xx] = ' ';
|
max7456_screen[xx] = ' ';
|
||||||
}
|
}
|
||||||
max7456_send(MAX7456ADD_DMDI, 0xFF);
|
max7456_send(MAX7456ADD_DMDI, 0xFF);
|
||||||
max7456_send(MAX7456ADD_DMM, 0);
|
max7456_send(MAX7456ADD_DMM, 0);
|
||||||
|
@ -175,6 +224,11 @@ void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) {
|
||||||
for(x = 0; x < 54; x++) {
|
for(x = 0; x < 54; x++) {
|
||||||
max7456_send(MAX7456ADD_CMAL, x); //set start address low
|
max7456_send(MAX7456ADD_CMAL, x); //set start address low
|
||||||
max7456_send(MAX7456ADD_CMDI, font_data[x]);
|
max7456_send(MAX7456ADD_CMDI, font_data[x]);
|
||||||
|
#ifdef LED0_TOGGLE
|
||||||
|
LED0_TOGGLE;
|
||||||
|
#else
|
||||||
|
LED1_TOGGLE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer 54 bytes from shadow ram to NVM
|
// transfer 54 bytes from shadow ram to NVM
|
||||||
|
|
|
@ -114,12 +114,41 @@
|
||||||
#define WRITE_NVR 0xA0
|
#define WRITE_NVR 0xA0
|
||||||
#define STATUS_REG_NVR_BUSY 0x20
|
#define STATUS_REG_NVR_BUSY 0x20
|
||||||
|
|
||||||
|
/** Line multiples, for convenience & one less op at runtime **/
|
||||||
|
#define LINE 30
|
||||||
|
#define LINE01 0
|
||||||
|
#define LINE02 30
|
||||||
|
#define LINE03 60
|
||||||
|
#define LINE04 90
|
||||||
|
#define LINE05 120
|
||||||
|
#define LINE06 150
|
||||||
|
#define LINE07 180
|
||||||
|
#define LINE08 210
|
||||||
|
#define LINE09 240
|
||||||
|
#define LINE10 270
|
||||||
|
#define LINE11 300
|
||||||
|
#define LINE12 330
|
||||||
|
#define LINE13 360
|
||||||
|
#define LINE14 390
|
||||||
|
#define LINE15 420
|
||||||
|
#define LINE16 450
|
||||||
|
|
||||||
|
|
||||||
|
/** PAL or NTSC, value is number of chars total */
|
||||||
|
#define VIDEO_BUFFER_CHARS_NTSC 390
|
||||||
|
#define VIDEO_BUFFER_CHARS_PAL 480
|
||||||
|
#define VIDEO_LINES_NTSC 13
|
||||||
|
#define VIDEO_LINES_PAL 16
|
||||||
|
|
||||||
|
enum VIDEO_TYPES { AUTO = 0, PAL, NTSC };
|
||||||
|
|
||||||
extern uint16_t max_screen_size;
|
extern uint16_t max_screen_size;
|
||||||
char screen[480];
|
char max7456_screen[VIDEO_BUFFER_CHARS_PAL];
|
||||||
|
|
||||||
|
|
||||||
void max7456_init(uint8_t system);
|
void max7456_init(uint8_t system);
|
||||||
void max7456_draw_screen(void);
|
void max7456_draw_screen(void);
|
||||||
void max7456_draw_screen_fast(void);
|
void max7456_draw_screen_fast(void);
|
||||||
|
void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars);
|
||||||
void max7456_write_string(const char *string, int16_t address);
|
void max7456_write_string(const char *string, int16_t address);
|
||||||
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data);
|
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data);
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
/* @file max7456_symbols.h
|
||||||
|
* @brief max7456 symbols for the mwosd font set
|
||||||
|
*
|
||||||
|
* @author Nathan Tsoi nathan@vertile.com
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Nathan Tsoi
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef USE_MAX7456
|
||||||
|
|
||||||
|
// Character Symbols
|
||||||
|
#define SYM_BLANK 0x20
|
||||||
|
|
||||||
|
// Satellite Graphics
|
||||||
|
#define SYM_SAT_L 0x1E
|
||||||
|
#define SYM_SAT_R 0x1F
|
||||||
|
//#define SYM_SAT 0x0F // Not used
|
||||||
|
|
||||||
|
// Degrees Icon for HEADING/DIRECTION HOME
|
||||||
|
#define SYM_DEGREES 0xBD
|
||||||
|
|
||||||
|
// Direction arrows
|
||||||
|
#define SYM_ARROW_SOUTH 0x60
|
||||||
|
#define SYM_ARROW_2 0x61
|
||||||
|
#define SYM_ARROW_3 0x62
|
||||||
|
#define SYM_ARROW_4 0x63
|
||||||
|
#define SYM_ARROW_EAST 0x64
|
||||||
|
#define SYM_ARROW_6 0x65
|
||||||
|
#define SYM_ARROW_7 0x66
|
||||||
|
#define SYM_ARROW_8 0x67
|
||||||
|
#define SYM_ARROW_NORTH 0x68
|
||||||
|
#define SYM_ARROW_10 0x69
|
||||||
|
#define SYM_ARROW_11 0x6A
|
||||||
|
#define SYM_ARROW_12 0x6B
|
||||||
|
#define SYM_ARROW_WEST 0x6C
|
||||||
|
#define SYM_ARROW_14 0x6D
|
||||||
|
#define SYM_ARROW_15 0x6E
|
||||||
|
#define SYM_ARROW_16 0x6F
|
||||||
|
|
||||||
|
// Heading Graphics
|
||||||
|
#define SYM_HEADING_N 0x18
|
||||||
|
#define SYM_HEADING_S 0x19
|
||||||
|
#define SYM_HEADING_E 0x1A
|
||||||
|
#define SYM_HEADING_W 0x1B
|
||||||
|
#define SYM_HEADING_DIVIDED_LINE 0x1C
|
||||||
|
#define SYM_HEADING_LINE 0x1D
|
||||||
|
|
||||||
|
// FRSKY HUB
|
||||||
|
#define SYM_CELL0 0xF0
|
||||||
|
#define SYM_CELL1 0xF1
|
||||||
|
#define SYM_CELL2 0xF2
|
||||||
|
#define SYM_CELL3 0xF3
|
||||||
|
#define SYM_CELL4 0xF4
|
||||||
|
#define SYM_CELL5 0xF5
|
||||||
|
#define SYM_CELL6 0xF6
|
||||||
|
#define SYM_CELL7 0xF7
|
||||||
|
#define SYM_CELL8 0xF8
|
||||||
|
#define SYM_CELL9 0xF9
|
||||||
|
#define SYM_CELLA 0xFA
|
||||||
|
#define SYM_CELLB 0xFB
|
||||||
|
#define SYM_CELLC 0xFC
|
||||||
|
#define SYM_CELLD 0xFD
|
||||||
|
#define SYM_CELLE 0xFE
|
||||||
|
#define SYM_CELLF 0xC3
|
||||||
|
|
||||||
|
// Map mode
|
||||||
|
#define SYM_HOME 0x04
|
||||||
|
#define SYM_AIRCRAFT 0x05
|
||||||
|
#define SYM_RANGE_100 0x21
|
||||||
|
#define SYM_RANGE_500 0x22
|
||||||
|
#define SYM_RANGE_2500 0x23
|
||||||
|
#define SYM_RANGE_MAX 0x24
|
||||||
|
#define SYM_DIRECTION 0x72
|
||||||
|
|
||||||
|
// GPS Coordinates and Altitude
|
||||||
|
#define SYM_LAT 0xCA
|
||||||
|
#define SYM_LON 0xCB
|
||||||
|
#define SYM_ALT 0xCC
|
||||||
|
|
||||||
|
// GPS Mode and Autopilot
|
||||||
|
#define SYM_3DFIX 0xDF
|
||||||
|
#define SYM_HOLD 0xEF
|
||||||
|
#define SYM_G_HOME 0xFF
|
||||||
|
#define SYM_GHOME 0x9D
|
||||||
|
#define SYM_GHOME1 0x9E
|
||||||
|
#define SYM_GHOLD 0xCD
|
||||||
|
#define SYM_GHOLD1 0xCE
|
||||||
|
#define SYM_GMISSION 0xB5
|
||||||
|
#define SYM_GMISSION1 0xB6
|
||||||
|
#define SYM_GLAND 0xB7
|
||||||
|
#define SYM_GLAND1 0xB8
|
||||||
|
|
||||||
|
// Gimbal active Mode
|
||||||
|
#define SYM_GIMBAL 0x16
|
||||||
|
#define SYM_GIMBAL1 0x17
|
||||||
|
|
||||||
|
|
||||||
|
// Sensor´s Presence
|
||||||
|
#define SYM_ACC 0xA0
|
||||||
|
#define SYM_MAG 0xA1
|
||||||
|
#define SYM_BAR 0xA2
|
||||||
|
#define SYM_GPS 0xA3
|
||||||
|
#define SYM_MAN 0xC0
|
||||||
|
#define SYM_MAN1 0xC1
|
||||||
|
#define SYM_MAN2 0xC2
|
||||||
|
#define SYM_CHECK 0xBE
|
||||||
|
#define SYM_BARO10 0xB7
|
||||||
|
#define SYM_BARO11 0xB8
|
||||||
|
#define SYM_MAG10 0xB5
|
||||||
|
#define SYM_MAG11 0xB6
|
||||||
|
|
||||||
|
// AH Center screen Graphics
|
||||||
|
//#define SYM_AH_CENTER 0x01
|
||||||
|
#ifdef ALT_CENTER
|
||||||
|
#define SYM_AH_CENTER_LINE 0xB0
|
||||||
|
#define SYM_AH_CENTER 0xB1
|
||||||
|
#define SYM_AH_CENTER_LINE_RIGHT 0xB2
|
||||||
|
#else
|
||||||
|
#define SYM_AH_CENTER_LINE 0x26
|
||||||
|
#define SYM_AH_CENTER 0x7E
|
||||||
|
#define SYM_AH_CENTER_LINE_RIGHT 0xBC
|
||||||
|
#endif
|
||||||
|
#define SYM_AH_RIGHT 0x02
|
||||||
|
#define SYM_AH_LEFT 0x03
|
||||||
|
#define SYM_AH_DECORATION_UP 0xC9
|
||||||
|
#define SYM_AH_DECORATION_DOWN 0xCF
|
||||||
|
|
||||||
|
|
||||||
|
// AH Bars
|
||||||
|
#define SYM_AH_BAR9_0 0x80
|
||||||
|
|
||||||
|
|
||||||
|
// Temperature
|
||||||
|
#define SYM_TEMP_F 0x0D
|
||||||
|
#define SYM_TEMP_C 0x0E
|
||||||
|
|
||||||
|
// Batt evolution
|
||||||
|
#define SYM_BATT_FULL 0x90
|
||||||
|
#define SYM_BATT_5 0x91
|
||||||
|
#define SYM_BATT_4 0x92
|
||||||
|
#define SYM_BATT_3 0x93
|
||||||
|
#define SYM_BATT_2 0x94
|
||||||
|
#define SYM_BATT_1 0x95
|
||||||
|
#define SYM_BATT_EMPTY 0x96
|
||||||
|
|
||||||
|
// Vario
|
||||||
|
#define SYM_VARIO 0x7F
|
||||||
|
|
||||||
|
// Glidescope
|
||||||
|
#define SYM_GLIDESCOPE 0xE0
|
||||||
|
|
||||||
|
// Batt Icon´s
|
||||||
|
#define SYM_MAIN_BATT 0x97
|
||||||
|
#define SYM_VID_BAT 0xBF
|
||||||
|
|
||||||
|
// Unit Icon´s (Metric)
|
||||||
|
#define SYM_MS 0x9F
|
||||||
|
#define SYM_KMH 0xA5
|
||||||
|
#define SYM_ALTM 0xA7
|
||||||
|
#define SYM_DISTHOME_M 0xBB
|
||||||
|
#define SYM_M 0x0C
|
||||||
|
|
||||||
|
// Unit Icon´s (Imperial)
|
||||||
|
#define SYM_FTS 0x99
|
||||||
|
#define SYM_MPH 0xA6
|
||||||
|
#define SYM_ALTFT 0xA8
|
||||||
|
#define SYM_DISTHOME_FT 0xB9
|
||||||
|
#define SYM_FT 0x0F
|
||||||
|
|
||||||
|
// Voltage and amperage
|
||||||
|
#define SYM_VOLT 0xA9
|
||||||
|
#define SYM_AMP 0x9A
|
||||||
|
#define SYM_MAH 0xA4
|
||||||
|
#define SYM_WATT 0x57
|
||||||
|
|
||||||
|
// Flying Mode
|
||||||
|
#define SYM_ACRO 0xAE
|
||||||
|
#define SYM_ACROGY 0x98
|
||||||
|
#define SYM_ACRO1 0xAF
|
||||||
|
#define SYM_STABLE 0xAC
|
||||||
|
#define SYM_STABLE1 0xAD
|
||||||
|
#define SYM_HORIZON 0xC4
|
||||||
|
#define SYM_HORIZON1 0xC5
|
||||||
|
#define SYM_PASS 0xAA
|
||||||
|
#define SYM_PASS1 0xAB
|
||||||
|
#define SYM_AIR 0xEA
|
||||||
|
#define SYM_AIR1 0xEB
|
||||||
|
#define SYM_PLUS 0x89
|
||||||
|
|
||||||
|
// Note, these change with scrolling enabled (scrolling is TODO)
|
||||||
|
//#define SYM_AH_DECORATION_LEFT 0x13
|
||||||
|
//#define SYM_AH_DECORATION_RIGHT 0x13
|
||||||
|
#define SYM_AH_DECORATION 0x13
|
||||||
|
|
||||||
|
// Time
|
||||||
|
#define SYM_ON_M 0x9B
|
||||||
|
#define SYM_FLY_M 0x9C
|
||||||
|
#define SYM_ON_H 0x70
|
||||||
|
#define SYM_FLY_H 0x71
|
||||||
|
|
||||||
|
// Throttle Position (%)
|
||||||
|
#define SYM_THR 0xC8
|
||||||
|
#define SYM_THR1 0xC9
|
||||||
|
|
||||||
|
// RSSI
|
||||||
|
#define SYM_RSSI 0xBA
|
||||||
|
|
||||||
|
// Menu cursor
|
||||||
|
#define SYM_CURSOR SYM_AH_LEFT
|
||||||
|
|
||||||
|
//Misc
|
||||||
|
#define SYM_COLON 0x2D
|
||||||
|
|
||||||
|
//sport
|
||||||
|
#define SYM_MIN 0xB3
|
||||||
|
#define SYM_AVG 0xB4
|
||||||
|
|
||||||
|
#endif
|
|
@ -237,7 +237,7 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
|
||||||
type = MAP_TO_SERVO_OUTPUT;
|
type = MAP_TO_SERVO_OUTPUT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SPRACINGF3MINI)
|
#if defined(SPRACINGF3MINI) || defined(OMNIBUS)
|
||||||
// remap PWM6+7 as servos
|
// remap PWM6+7 as servos
|
||||||
if ((timerIndex == PWM6 || timerIndex == PWM7) && timerHardwarePtr->tim == TIM15)
|
if ((timerIndex == PWM6 || timerIndex == PWM7) && timerHardwarePtr->tim == TIM15)
|
||||||
type = MAP_TO_SERVO_OUTPUT;
|
type = MAP_TO_SERVO_OUTPUT;
|
||||||
|
|
|
@ -22,7 +22,8 @@ typedef enum {
|
||||||
OWNER_SDCARD,
|
OWNER_SDCARD,
|
||||||
OWNER_FLASH,
|
OWNER_FLASH,
|
||||||
OWNER_USB,
|
OWNER_USB,
|
||||||
OWNER_BEEPER
|
OWNER_BEEPER,
|
||||||
|
OWNER_OSD
|
||||||
} resourceOwner_t;
|
} resourceOwner_t;
|
||||||
|
|
||||||
// Currently TIMER should be shared resource (softserial dualtimer and timerqueue needs to allocate timer channel, but pin can be used for other function)
|
// Currently TIMER should be shared resource (softserial dualtimer and timerqueue needs to allocate timer channel, but pin can be used for other function)
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#include "io/gimbal.h"
|
#include "io/gimbal.h"
|
||||||
#include "io/serial.h"
|
#include "io/serial.h"
|
||||||
#include "io/gps.h"
|
#include "io/gps.h"
|
||||||
|
#include "io/osd.h"
|
||||||
#include "io/vtx.h"
|
#include "io/vtx.h"
|
||||||
|
|
||||||
#include "flight/failsafe.h"
|
#include "flight/failsafe.h"
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
#ifdef OSD
|
#ifdef OSD
|
||||||
|
|
||||||
#include "drivers/max7456.h"
|
#include "drivers/max7456.h"
|
||||||
|
#include "drivers/max7456_symbols.h"
|
||||||
|
|
||||||
#ifdef USE_RTC6705
|
#ifdef USE_RTC6705
|
||||||
#include "drivers/vtx_soft_spi_rtc6705.h"
|
#include "drivers/vtx_soft_spi_rtc6705.h"
|
||||||
|
@ -668,30 +669,39 @@ void updateOsd(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] != -1) {
|
if (masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] != -1) {
|
||||||
sprintf(line, "\x01%d.%1d", vbat / 10, vbat % 10);
|
line[0] = SYM_VOLT;
|
||||||
|
sprintf(line+1, "%d.%1d", vbat / 10, vbat % 10);
|
||||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE]);
|
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE]);
|
||||||
}
|
}
|
||||||
if (masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] != -1) {
|
if (masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] != -1) {
|
||||||
sprintf(line, "\x02%d", rssi / 10);
|
line[0] = SYM_RSSI;
|
||||||
|
sprintf(line+1, "%d", rssi / 10);
|
||||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE]);
|
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE]);
|
||||||
}
|
}
|
||||||
if (masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] != -1) {
|
if (masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] != -1) {
|
||||||
sprintf(line, "\x03%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN));
|
line[0] = SYM_THR;
|
||||||
|
line[1] = SYM_THR1;
|
||||||
|
sprintf(line+2, "%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN));
|
||||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS]);
|
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS]);
|
||||||
}
|
}
|
||||||
if (masterConfig.osdProfile.item_pos[OSD_TIMER] != -1) {
|
if (masterConfig.osdProfile.item_pos[OSD_TIMER] != -1) {
|
||||||
if (armed) {
|
if (armed) {
|
||||||
seconds = armed_seconds + ((now-armed_at) / 1000000);
|
seconds = armed_seconds + ((now-armed_at) / 1000000);
|
||||||
sprintf(line, "\x04 %02d:%02d", seconds / 60, seconds % 60);
|
line[0] = SYM_FLY_M;
|
||||||
|
sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60);
|
||||||
} else {
|
} else {
|
||||||
|
line[0] = SYM_ON_M;
|
||||||
seconds = now / 1000000;
|
seconds = now / 1000000;
|
||||||
sprintf(line, "\x05 %02d:%02d", seconds / 60, seconds % 60);
|
sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60);
|
||||||
}
|
}
|
||||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_TIMER]);
|
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_TIMER]);
|
||||||
}
|
}
|
||||||
if (masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] != -1) {
|
if (masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] != -1) {
|
||||||
print_average_system_load(masterConfig.osdProfile.item_pos[OSD_CPU_LOAD], 0);
|
print_average_system_load(masterConfig.osdProfile.item_pos[OSD_CPU_LOAD], 0);
|
||||||
}
|
}
|
||||||
|
if (masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON] != -1) {
|
||||||
|
max7456_artificial_horizon(attitude.values.roll, attitude.values.pitch, masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS] != -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
max7456_draw_screen_fast();
|
max7456_draw_screen_fast();
|
||||||
|
@ -707,8 +717,25 @@ void osdInit(void)
|
||||||
rtc6705_soft_spi_set_channel(vtx_freq[current_vtx_channel]);
|
rtc6705_soft_spi_set_channel(vtx_freq[current_vtx_channel]);
|
||||||
rtc6705_soft_spi_set_rf_power(masterConfig.vtx_power);
|
rtc6705_soft_spi_set_rf_power(masterConfig.vtx_power);
|
||||||
#endif
|
#endif
|
||||||
max7456_init(masterConfig.osdProfile.system);
|
max7456_init(masterConfig.osdProfile.video_system);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetOsdConfig(void)
|
||||||
|
{
|
||||||
|
featureSet(FEATURE_OSD);
|
||||||
|
masterConfig.osdProfile.video_system = AUTO;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] = -29;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] = -59;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_TIMER] = -39;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] = -9;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] = 26;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_VTX_CHANNEL] = 1;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING] = -80;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_ARMED] = -107;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_DISARMED] = -109;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON] = -1;
|
||||||
|
masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,14 +48,18 @@ typedef enum {
|
||||||
OSD_VOLTAGE_WARNING,
|
OSD_VOLTAGE_WARNING,
|
||||||
OSD_ARMED,
|
OSD_ARMED,
|
||||||
OSD_DISARMED,
|
OSD_DISARMED,
|
||||||
|
OSD_ARTIFICIAL_HORIZON,
|
||||||
|
OSD_HORIZON_SIDEBARS,
|
||||||
OSD_MAX_ITEMS, // MUST BE LAST
|
OSD_MAX_ITEMS, // MUST BE LAST
|
||||||
} osd_items_t;
|
} osd_items_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t system;
|
// AUTO / PAL / NTSC in VIDEO_TYPES enum
|
||||||
|
uint8_t video_system;
|
||||||
int16_t item_pos[OSD_MAX_ITEMS];
|
int16_t item_pos[OSD_MAX_ITEMS];
|
||||||
} osd_profile;
|
} osd_profile;
|
||||||
|
|
||||||
void updateOsd(void);
|
void updateOsd(void);
|
||||||
void osdInit(void);
|
void osdInit(void);
|
||||||
|
void resetOsdConfig(void);
|
||||||
|
|
|
@ -204,7 +204,7 @@ static const char * const featureNames[] = {
|
||||||
"SONAR", "TELEMETRY", "CURRENT_METER", "3D", "RX_PARALLEL_PWM",
|
"SONAR", "TELEMETRY", "CURRENT_METER", "3D", "RX_PARALLEL_PWM",
|
||||||
"RX_MSP", "RSSI_ADC", "LED_STRIP", "DISPLAY", "ONESHOT125",
|
"RX_MSP", "RSSI_ADC", "LED_STRIP", "DISPLAY", "ONESHOT125",
|
||||||
"BLACKBOX", "CHANNEL_FORWARDING", "TRANSPONDER", "AIRMODE", "SUPEREXPO_RATES",
|
"BLACKBOX", "CHANNEL_FORWARDING", "TRANSPONDER", "AIRMODE", "SUPEREXPO_RATES",
|
||||||
NULL
|
"OSD", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
// sync this with rxFailsafeChannelMode_e
|
// sync this with rxFailsafeChannelMode_e
|
||||||
|
@ -809,7 +809,7 @@ const clivalue_t valueTable[] = {
|
||||||
{ "vtx_power", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_power, .config.minmax = { 0, 1 } },
|
{ "vtx_power", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_power, .config.minmax = { 0, 1 } },
|
||||||
#endif
|
#endif
|
||||||
#ifdef OSD
|
#ifdef OSD
|
||||||
{ "osd_system", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.system, .config.minmax = { 0, 2 } },
|
{ "osd_video_system", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.video_system, .config.minmax = { 0, 2 } },
|
||||||
{ "osd_main_voltage_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE], .config.minmax = { -480, 480 } },
|
{ "osd_main_voltage_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE], .config.minmax = { -480, 480 } },
|
||||||
{ "osd_rssi_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE], .config.minmax = { -480, 480 } },
|
{ "osd_rssi_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE], .config.minmax = { -480, 480 } },
|
||||||
{ "osd_timer_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_TIMER], .config.minmax = { -480, 480 } },
|
{ "osd_timer_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_TIMER], .config.minmax = { -480, 480 } },
|
||||||
|
@ -819,6 +819,8 @@ const clivalue_t valueTable[] = {
|
||||||
{ "osd_voltage_warning_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING], .config.minmax = { -480, 480 } },
|
{ "osd_voltage_warning_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING], .config.minmax = { -480, 480 } },
|
||||||
{ "osd_armed_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_ARMED], .config.minmax = { -480, 480 } },
|
{ "osd_armed_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_ARMED], .config.minmax = { -480, 480 } },
|
||||||
{ "osd_disarmed_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_DISARMED], .config.minmax = { -480, 480 } },
|
{ "osd_disarmed_pos", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_DISARMED], .config.minmax = { -480, 480 } },
|
||||||
|
{ "osd_artificial_horizon", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON], .config.minmax = { -1, 0 } },
|
||||||
|
{ "osd_horizon_sidebars", VAR_INT16 | MASTER_VALUE, &masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS], .config.minmax = { -1, 0 } },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1214,6 +1214,21 @@ static bool processOutCommand(uint8_t cmdMSP)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSP_OSD_CONFIG:
|
||||||
|
#ifdef OSD
|
||||||
|
headSerialReply(2 + (OSD_MAX_ITEMS * 2));
|
||||||
|
serialize8(1); // OSD supported
|
||||||
|
// send video system (AUTO/PAL/NTSC)
|
||||||
|
serialize8(masterConfig.osdProfile.video_system);
|
||||||
|
for (i = 0; i < OSD_MAX_ITEMS; i++) {
|
||||||
|
serialize16(masterConfig.osdProfile.item_pos[i]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
headSerialReply(1);
|
||||||
|
serialize8(0); // OSD not supported
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
case MSP_BF_BUILD_INFO:
|
case MSP_BF_BUILD_INFO:
|
||||||
headSerialReply(11 + 4 + 4);
|
headSerialReply(11 + 4 + 4);
|
||||||
for (i = 0; i < 11; i++)
|
for (i = 0; i < 11; i++)
|
||||||
|
@ -1524,9 +1539,15 @@ static bool processInCommand(void)
|
||||||
#endif
|
#endif
|
||||||
#ifdef OSD
|
#ifdef OSD
|
||||||
case MSP_SET_OSD_CONFIG:
|
case MSP_SET_OSD_CONFIG:
|
||||||
masterConfig.osdProfile.system = read8();
|
addr = read8();
|
||||||
for (i = 0; i < OSD_MAX_ITEMS; i++)
|
// set all the other settings
|
||||||
masterConfig.osdProfile.item_pos[i] = read16();
|
if ((int8_t)addr == -1) {
|
||||||
|
masterConfig.osdProfile.video_system = read8();
|
||||||
|
}
|
||||||
|
// set a position setting
|
||||||
|
else {
|
||||||
|
masterConfig.osdProfile.item_pos[addr] = read16();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSP_OSD_CHAR_WRITE:
|
case MSP_OSD_CHAR_WRITE:
|
||||||
addr = read8();
|
addr = read8();
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
#define MSP_PROTOCOL_VERSION 0
|
#define MSP_PROTOCOL_VERSION 0
|
||||||
|
|
||||||
#define API_VERSION_MAJOR 1 // increment when major changes are made
|
#define API_VERSION_MAJOR 1 // increment when major changes are made
|
||||||
#define API_VERSION_MINOR 16 // increment when any change is made, reset to zero when major changes are released after changing API_VERSION_MAJOR
|
#define API_VERSION_MINOR 17 // increment when any change is made, reset to zero when major changes are released after changing API_VERSION_MAJOR
|
||||||
|
|
||||||
#define API_VERSION_LENGTH 2
|
#define API_VERSION_LENGTH 2
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ void init(void)
|
||||||
EXTIInit();
|
EXTIInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPRACINGF3MINI
|
#if defined(SPRACINGF3MINI) || defined(OMNIBUS)
|
||||||
gpio_config_t buttonAGpioConfig = {
|
gpio_config_t buttonAGpioConfig = {
|
||||||
BUTTON_A_PIN,
|
BUTTON_A_PIN,
|
||||||
Mode_IPU,
|
Mode_IPU,
|
||||||
|
@ -416,11 +416,13 @@ void init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SPRACINGF3MINI) && defined(SONAR) && defined(USE_SOFTSERIAL1)
|
#if defined(SPRACINGF3MINI) || defined(OMNIBUS)
|
||||||
|
#if defined(SONAR) && defined(USE_SOFTSERIAL1)
|
||||||
if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) {
|
if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) {
|
||||||
serialRemovePort(SERIAL_PORT_SOFTSERIAL1);
|
serialRemovePort(SERIAL_PORT_SOFTSERIAL1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_I2C
|
#ifdef USE_I2C
|
||||||
#if defined(NAZE)
|
#if defined(NAZE)
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
#include "drivers/pwm_mapping.h"
|
||||||
|
|
||||||
|
const uint16_t multiPPM[] = {
|
||||||
|
PWM1 | (MAP_TO_PPM_INPUT << 8), // PPM input
|
||||||
|
|
||||||
|
PWM2 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM3 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM4 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM5 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM6 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM7 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM8 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM9 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM10 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM11 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
0xFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t multiPWM[] = {
|
||||||
|
PWM2 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM3 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM4 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM5 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM6 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM7 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM8 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM9 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM10 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
PWM11 | (MAP_TO_MOTOR_OUTPUT << 8),
|
||||||
|
0xFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t airPPM[] = {
|
||||||
|
PWM1 | (MAP_TO_PPM_INPUT << 8), // PPM input
|
||||||
|
PWM2 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #1
|
||||||
|
PWM3 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #2
|
||||||
|
PWM4 | (MAP_TO_SERVO_OUTPUT << 8), // servo #1
|
||||||
|
PWM5 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM6 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM7 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM8 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM9 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM10 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM11 | (MAP_TO_SERVO_OUTPUT << 8), // servo #8
|
||||||
|
0xFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t airPWM[] = {
|
||||||
|
PWM2 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #1
|
||||||
|
PWM3 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #2
|
||||||
|
PWM4 | (MAP_TO_SERVO_OUTPUT << 8), // servo #1
|
||||||
|
PWM5 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM6 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM7 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM8 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM9 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM10 | (MAP_TO_SERVO_OUTPUT << 8),
|
||||||
|
PWM11 | (MAP_TO_SERVO_OUTPUT << 8), // servo #8
|
||||||
|
0xFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {
|
||||||
|
// PPM Pad
|
||||||
|
{ TIM3, IO_TAG(PB4), TIM_Channel_1, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, 0}, // PPM - PB4
|
||||||
|
// PB5 / TIM3 CH2 is connected to USBPresent
|
||||||
|
|
||||||
|
// Used by SPI1, MAX7456
|
||||||
|
//{ TIM16, IO_TAG(PA6), TIM_Channel_1, TIM1_UP_TIM16_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, 0}, // PWM1 - PA6
|
||||||
|
//{ TIM17, IO_TAG(PA7), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, 0}, // PWM2 - PA7
|
||||||
|
|
||||||
|
{ TIM4, IO_TAG(PB8), TIM_Channel_3, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, 0}, // PWM3 - PB8
|
||||||
|
{ TIM4, IO_TAG(PB9), TIM_Channel_4, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, 0}, // PWM4 - PB9
|
||||||
|
{ TIM15, IO_TAG(PA2), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, 1, IOCFG_AF_PP, GPIO_AF_9, 0}, // PWM5 - PA2
|
||||||
|
{ TIM15, IO_TAG(PA3), TIM_Channel_2, TIM1_BRK_TIM15_IRQn, 1, IOCFG_AF_PP, GPIO_AF_9, 0}, // PWM6 - PA3
|
||||||
|
{ TIM2, IO_TAG(PA0), TIM_Channel_1, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, 0}, // PWM7 - PA0
|
||||||
|
{ TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, 0}, // PWM8 - PA1
|
||||||
|
|
||||||
|
// UART3 RX/TX
|
||||||
|
{ TIM2, IO_TAG(PB10), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, 0}, // PWM9 - PB10 - TIM2_CH3 / USART3_TX (AF7)
|
||||||
|
{ TIM2, IO_TAG(PB11), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, 0}, // PWM10 - PB11 - TIM2_CH4 / USART3_RX (AF7)
|
||||||
|
|
||||||
|
// LED Strip Pad
|
||||||
|
{ TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_6, 0}, // GPIO_TIMER / LED_STRIP
|
||||||
|
};
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Cleanflight.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define TARGET_BOARD_IDENTIFIER "OMNI" // https://en.wikipedia.org/wiki/Omnibus
|
||||||
|
|
||||||
|
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_NONE
|
||||||
|
|
||||||
|
#define LED0 PB3
|
||||||
|
|
||||||
|
#define BEEPER PC15
|
||||||
|
#define BEEPER_INVERTED
|
||||||
|
|
||||||
|
#define USABLE_TIMER_CHANNEL_COUNT 10 // 6 Outputs; PPM; LED Strip; 2 additional PWM pins also on UART3 RX/TX pins.
|
||||||
|
|
||||||
|
#define EXTI15_10_CALLBACK_HANDLER_COUNT 2 // MPU_INT, SDCardDetect
|
||||||
|
|
||||||
|
#define USE_EXTI
|
||||||
|
#define MPU_INT_EXTI PC13
|
||||||
|
#define USE_MPU_DATA_READY_SIGNAL
|
||||||
|
#define ENSURE_MPU_DATA_READY_IS_LOW
|
||||||
|
|
||||||
|
#define USE_MAG_DATA_READY_SIGNAL
|
||||||
|
#define ENSURE_MAG_DATA_READY_IS_HIGH
|
||||||
|
|
||||||
|
|
||||||
|
#define GYRO
|
||||||
|
//#define USE_FAKE_GYRO
|
||||||
|
#define USE_GYRO_MPU6500
|
||||||
|
|
||||||
|
#define ACC
|
||||||
|
//#define USE_FAKE_ACC
|
||||||
|
#define USE_ACC_MPU6500
|
||||||
|
|
||||||
|
#define ACC_MPU6500_ALIGN CW180_DEG
|
||||||
|
#define GYRO_MPU6500_ALIGN CW180_DEG
|
||||||
|
|
||||||
|
#define BARO
|
||||||
|
#define USE_BARO_BMP280
|
||||||
|
|
||||||
|
#define MAG
|
||||||
|
#define USE_MPU9250_MAG // Enables bypass configuration
|
||||||
|
#define USE_MAG_AK8975
|
||||||
|
#define USE_MAG_HMC5883 // External
|
||||||
|
|
||||||
|
#define MAG_AK8975_ALIGN CW90_DEG_FLIP
|
||||||
|
|
||||||
|
#define SONAR
|
||||||
|
#define SONAR_ECHO_PIN PB1
|
||||||
|
#define SONAR_TRIGGER_PIN PB0
|
||||||
|
|
||||||
|
#define USB_IO
|
||||||
|
#define USB_CABLE_DETECTION
|
||||||
|
|
||||||
|
#define USB_DETECT_PIN PB5
|
||||||
|
|
||||||
|
#define USE_VCP
|
||||||
|
#define USE_USART1
|
||||||
|
#define USE_USART2
|
||||||
|
#define USE_USART3
|
||||||
|
#define USE_SOFTSERIAL1
|
||||||
|
#define SERIAL_PORT_COUNT 5
|
||||||
|
|
||||||
|
#ifndef UART1_GPIO
|
||||||
|
#define UART1_TX_PIN GPIO_Pin_9 // PA9
|
||||||
|
#define UART1_RX_PIN GPIO_Pin_10 // PA10
|
||||||
|
#define UART1_GPIO GPIOA
|
||||||
|
#define UART1_GPIO_AF GPIO_AF_7
|
||||||
|
#define UART1_TX_PINSOURCE GPIO_PinSource9
|
||||||
|
#define UART1_RX_PINSOURCE GPIO_PinSource10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UART2_TX_PIN GPIO_Pin_14 // PA14 / SWCLK
|
||||||
|
#define UART2_RX_PIN GPIO_Pin_15 // PA15
|
||||||
|
#define UART2_GPIO GPIOA
|
||||||
|
#define UART2_GPIO_AF GPIO_AF_7
|
||||||
|
#define UART2_TX_PINSOURCE GPIO_PinSource14
|
||||||
|
#define UART2_RX_PINSOURCE GPIO_PinSource15
|
||||||
|
|
||||||
|
#ifndef UART3_GPIO
|
||||||
|
#define UART3_TX_PIN GPIO_Pin_10 // PB10 (AF7)
|
||||||
|
#define UART3_RX_PIN GPIO_Pin_11 // PB11 (AF7)
|
||||||
|
#define UART3_GPIO_AF GPIO_AF_7
|
||||||
|
#define UART3_GPIO GPIOB
|
||||||
|
#define UART3_TX_PINSOURCE GPIO_PinSource10
|
||||||
|
#define UART3_RX_PINSOURCE GPIO_PinSource11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SOFTSERIAL_1_TIMER TIM2
|
||||||
|
#define SOFTSERIAL_1_TIMER_RX_HARDWARE 9 // PA0 / PAD3
|
||||||
|
#define SOFTSERIAL_1_TIMER_TX_HARDWARE 10 // PA1 / PAD4
|
||||||
|
|
||||||
|
#define USE_I2C
|
||||||
|
#define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA
|
||||||
|
|
||||||
|
|
||||||
|
#define USE_SPI
|
||||||
|
#define USE_SPI_DEVICE_1
|
||||||
|
|
||||||
|
#define SPI1_NSS_PIN PA4
|
||||||
|
#define SPI1_SCK_PIN PA5
|
||||||
|
#define SPI1_MISO_PIN PA6
|
||||||
|
#define SPI1_MOSI_PIN PA7
|
||||||
|
|
||||||
|
// OSD define info:
|
||||||
|
// feature name (includes source) -> MAX_OSD, used in target.mk
|
||||||
|
// include the osd code
|
||||||
|
#define OSD
|
||||||
|
// include the max7456 driver
|
||||||
|
#define USE_MAX7456
|
||||||
|
#define MAX7456_SPI_INSTANCE SPI1
|
||||||
|
#define MAX7456_SPI_CS_PIN SPI1_NSS_PIN
|
||||||
|
|
||||||
|
|
||||||
|
#define USE_SPI
|
||||||
|
#define USE_SPI_DEVICE_2 // PB12,13,14,15 on AF5
|
||||||
|
#define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA
|
||||||
|
|
||||||
|
#define SPI2_NSS_PIN PB12
|
||||||
|
#define SPI2_SCK_PIN PB13
|
||||||
|
#define SPI2_MISO_PIN PB14
|
||||||
|
#define SPI2_MOSI_PIN PB15
|
||||||
|
|
||||||
|
#define USE_SDCARD
|
||||||
|
#define USE_SDCARD_SPI2
|
||||||
|
|
||||||
|
#define SDCARD_DETECT_INVERTED
|
||||||
|
|
||||||
|
#define SDCARD_DETECT_PIN PC14
|
||||||
|
#define SDCARD_SPI_INSTANCE SPI2
|
||||||
|
#define SDCARD_SPI_CS_PIN SPI2_NSS_PIN
|
||||||
|
|
||||||
|
// SPI2 is on the APB1 bus whose clock runs at 36MHz. Divide to under 400kHz for init:
|
||||||
|
#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER 128
|
||||||
|
// Divide to under 25MHz for normal operation:
|
||||||
|
#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER 2
|
||||||
|
|
||||||
|
// Note, this is the same DMA channel as USART1_RX. Luckily we don't use DMA for USART Rx.
|
||||||
|
#define SDCARD_DMA_CHANNEL_TX DMA1_Channel5
|
||||||
|
#define SDCARD_DMA_CHANNEL_TX_COMPLETE_FLAG DMA1_FLAG_TC5
|
||||||
|
|
||||||
|
// Performance logging for SD card operations:
|
||||||
|
// #define AFATFS_USE_INTROSPECTIVE_LOGGING
|
||||||
|
|
||||||
|
#define USE_ADC
|
||||||
|
#define BOARD_HAS_VOLTAGE_DIVIDER
|
||||||
|
|
||||||
|
|
||||||
|
#define ADC_INSTANCE ADC2
|
||||||
|
#define ADC_DMA_CHANNEL DMA2_Channel1
|
||||||
|
#define ADC_AHB_PERIPHERAL RCC_AHBPeriph_DMA2
|
||||||
|
|
||||||
|
#define VBAT_ADC_GPIO GPIOA
|
||||||
|
#define VBAT_ADC_GPIO_PIN GPIO_Pin_4
|
||||||
|
#define VBAT_ADC_CHANNEL ADC_Channel_1
|
||||||
|
|
||||||
|
#define CURRENT_METER_ADC_GPIO GPIOA
|
||||||
|
#define CURRENT_METER_ADC_GPIO_PIN GPIO_Pin_5
|
||||||
|
#define CURRENT_METER_ADC_CHANNEL ADC_Channel_2
|
||||||
|
|
||||||
|
#define RSSI_ADC_GPIO GPIOB
|
||||||
|
#define RSSI_ADC_GPIO_PIN GPIO_Pin_2
|
||||||
|
#define RSSI_ADC_CHANNEL ADC_Channel_12
|
||||||
|
|
||||||
|
#define LED_STRIP
|
||||||
|
#define LED_STRIP_TIMER TIM1
|
||||||
|
|
||||||
|
#define WS2811_GPIO GPIOA
|
||||||
|
#define WS2811_GPIO_AHB_PERIPHERAL RCC_AHBPeriph_GPIOA
|
||||||
|
#define WS2811_GPIO_AF GPIO_AF_6
|
||||||
|
#define WS2811_PIN GPIO_Pin_8
|
||||||
|
#define WS2811_PIN_SOURCE GPIO_PinSource8
|
||||||
|
#define WS2811_TIMER TIM1
|
||||||
|
#define WS2811_TIMER_APB2_PERIPHERAL RCC_APB2Periph_TIM1
|
||||||
|
#define WS2811_DMA_CHANNEL DMA1_Channel2
|
||||||
|
#define WS2811_IRQ DMA1_Channel2_IRQn
|
||||||
|
#define WS2811_DMA_TC_FLAG DMA1_FLAG_TC2
|
||||||
|
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH2_HANDLER
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRANSPONDER
|
||||||
|
//#define TRANSPONDER_GPIO GPIOA
|
||||||
|
//#define TRANSPONDER_GPIO_AHB_PERIPHERAL RCC_AHBPeriph_GPIOA
|
||||||
|
//#define TRANSPONDER_GPIO_AF GPIO_AF_6
|
||||||
|
//#define TRANSPONDER_PIN GPIO_Pin_8
|
||||||
|
//#define TRANSPONDER_PIN_SOURCE GPIO_PinSource8
|
||||||
|
//#define TRANSPONDER_TIMER TIM1
|
||||||
|
//#define TRANSPONDER_TIMER_APB2_PERIPHERAL RCC_APB2Periph_TIM1
|
||||||
|
//#define TRANSPONDER_DMA_CHANNEL DMA1_Channel2
|
||||||
|
//#define TRANSPONDER_IRQ DMA1_Channel2_IRQn
|
||||||
|
//#define TRANSPONDER_DMA_TC_FLAG DMA1_FLAG_TC2
|
||||||
|
//#define TRANSPONDER_DMA_HANDLER_IDENTIFER DMA1_CH2_HANDLER
|
||||||
|
|
||||||
|
//#define REDUCE_TRANSPONDER_CURRENT_DRAW_WHEN_USB_CABLE_PRESENT
|
||||||
|
|
||||||
|
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
|
||||||
|
#define DEFAULT_RX_FEATURE FEATURE_RX_PPM
|
||||||
|
|
||||||
|
#define BUTTONS
|
||||||
|
#define BUTTON_A_PORT GPIOB
|
||||||
|
#define BUTTON_A_PIN Pin_1
|
||||||
|
#define BUTTON_B_PORT GPIOB
|
||||||
|
#define BUTTON_B_PIN Pin_0
|
||||||
|
|
||||||
|
#define SPEKTRUM_BIND
|
||||||
|
// USART3,
|
||||||
|
#define BIND_PIN PB11
|
||||||
|
|
||||||
|
#define HARDWARE_BIND_PLUG
|
||||||
|
#define BINDPLUG_PIN PB0
|
||||||
|
|
||||||
|
#define USE_SERIAL_4WAY_BLHELI_INTERFACE
|
||||||
|
|
||||||
|
#define TARGET_IO_PORTA 0xffff
|
||||||
|
#define TARGET_IO_PORTB 0xffff
|
||||||
|
#define TARGET_IO_PORTC (BIT(13)|BIT(14)|BIT(15))
|
||||||
|
#define TARGET_IO_PORTF (BIT(0)|BIT(1)|BIT(4))
|
||||||
|
|
||||||
|
#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(15))
|
||||||
|
|
||||||
|
#define TIMER_APB1_PERIPHERALS (RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4)
|
||||||
|
#define TIMER_APB2_PERIPHERALS (RCC_APB2Periph_TIM1 | RCC_APB2Periph_TIM15)
|
||||||
|
#define TIMER_AHB_PERIPHERALS (RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB)
|
|
@ -0,0 +1,16 @@
|
||||||
|
F3_TARGETS += $(TARGET)
|
||||||
|
FEATURES = VCP SDCARD MAX_OSD
|
||||||
|
|
||||||
|
TARGET_SRC = \
|
||||||
|
drivers/accgyro_mpu.c \
|
||||||
|
drivers/accgyro_mpu6500.c \
|
||||||
|
drivers/barometer_bmp280.c \
|
||||||
|
drivers/compass_ak8975.c \
|
||||||
|
drivers/compass_hmc5883l.c \
|
||||||
|
drivers/flash_m25p16.c \
|
||||||
|
drivers/light_ws2811strip.c \
|
||||||
|
drivers/light_ws2811strip_stm32f30x.c \
|
||||||
|
drivers/serial_softserial.c \
|
||||||
|
drivers/serial_usb_vcp.c \
|
||||||
|
drivers/sonar_hcsr04.c
|
||||||
|
|
|
@ -109,9 +109,8 @@
|
||||||
#define SPI3_MOSI_PIN PB5
|
#define SPI3_MOSI_PIN PB5
|
||||||
|
|
||||||
#define USE_MAX7456
|
#define USE_MAX7456
|
||||||
#define MAX7456_CS_GPIO GPIOA
|
|
||||||
#define MAX7456_CS_PIN GPIO_Pin_15
|
|
||||||
#define MAX7456_SPI_INSTANCE SPI3
|
#define MAX7456_SPI_INSTANCE SPI3
|
||||||
|
#define MAX7456_SPI_CS_PIN PA15
|
||||||
|
|
||||||
#define USE_RTC6705
|
#define USE_RTC6705
|
||||||
#define RTC6705_SPIDATA_GPIO GPIOC
|
#define RTC6705_SPIDATA_GPIO GPIOC
|
||||||
|
@ -155,11 +154,7 @@
|
||||||
#define VBAT_ADC_CHANNEL ADC_Channel_1
|
#define VBAT_ADC_CHANNEL ADC_Channel_1
|
||||||
|
|
||||||
//#define USE_QUAD_MIXER_ONLY
|
//#define USE_QUAD_MIXER_ONLY
|
||||||
#define BLACKBOX
|
|
||||||
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
|
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
|
||||||
#define TELEMETRY
|
|
||||||
#define SERIAL_RX
|
|
||||||
#define USE_CLI
|
|
||||||
#define OSD
|
#define OSD
|
||||||
|
|
||||||
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT
|
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT
|
||||||
|
|
|
@ -1,18 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of Cleanflight.
|
* Supports the GY-91 MPU9250 and BMP280 development board via SPI1
|
||||||
*
|
*
|
||||||
* Cleanflight is free software: you can redistribute it and/or modify
|
* Put the MAX7456 on SPI2 instead of an SDCARD
|
||||||
|
* MAX7456 CS -> PB12 (default)
|
||||||
|
* Uses the default pins for SPI2:
|
||||||
|
* #define SPI2_NSS_PIN PB12
|
||||||
|
* #define SPI2_SCK_PIN PB13
|
||||||
|
* #define SPI2_MISO_PIN PB14
|
||||||
|
* #define SPI2_MOSI_PIN PB15
|
||||||
|
*
|
||||||
|
* @author Nathan Tsoi
|
||||||
|
*
|
||||||
|
* This software is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Cleanflight is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* 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
|
#pragma once
|
||||||
|
@ -38,11 +48,11 @@
|
||||||
#define SPI2_MISO_PIN PB14
|
#define SPI2_MISO_PIN PB14
|
||||||
#define SPI2_MOSI_PIN PB15
|
#define SPI2_MOSI_PIN PB15
|
||||||
|
|
||||||
#define USE_SD_CARD
|
//#define USE_SD_CARD
|
||||||
|
//
|
||||||
#define SD_DETECT_PIN PC14
|
//#define SD_DETECT_PIN PC14
|
||||||
#define SD_CS_PIN PB12
|
//#define SD_CS_PIN PB12
|
||||||
#define SD_SPI_INSTANCE SPI2
|
//#define SD_SPI_INSTANCE SPI2
|
||||||
|
|
||||||
//#define USE_FLASHFS
|
//#define USE_FLASHFS
|
||||||
//#define USE_FLASH_M25P16
|
//#define USE_FLASH_M25P16
|
||||||
|
@ -64,31 +74,50 @@
|
||||||
|
|
||||||
#define GYRO
|
#define GYRO
|
||||||
#define USE_GYRO_L3GD20
|
#define USE_GYRO_L3GD20
|
||||||
|
|
||||||
#define L3GD20_SPI SPI1
|
#define L3GD20_SPI SPI1
|
||||||
#define L3GD20_CS_PIN PE3
|
#define L3GD20_CS_PIN PE3
|
||||||
|
|
||||||
#define GYRO_L3GD20_ALIGN CW270_DEG
|
#define GYRO_L3GD20_ALIGN CW270_DEG
|
||||||
|
|
||||||
#define USE_SDCARD
|
// Support the GY-91 MPU9250 dev board
|
||||||
#define USE_SDCARD_SPI2
|
#define USE_GYRO_MPU6500
|
||||||
|
#define USE_GYRO_SPI_MPU6500
|
||||||
#define SDCARD_SPI_INSTANCE SPI2
|
#define MPU6500_CS_PIN PC14
|
||||||
#define SDCARD_SPI_CS_PIN PB12
|
#define MPU6500_SPI_INSTANCE SPI2
|
||||||
// SPI2 is on the APB1 bus whose clock runs at 36MHz. Divide to under 400kHz for init:
|
#define GYRO_MPU6500_ALIGN CW270_DEG_FLIP
|
||||||
#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER 128
|
|
||||||
// Divide to under 25MHz for normal operation:
|
|
||||||
#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER 2
|
|
||||||
|
|
||||||
// Note, this is the same DMA channel as USART1_RX. Luckily we don't use DMA for USART Rx.
|
|
||||||
#define SDCARD_DMA_CHANNEL_TX DMA1_Channel5
|
|
||||||
#define SDCARD_DMA_CHANNEL_TX_COMPLETE_FLAG DMA1_FLAG_TC5
|
|
||||||
|
|
||||||
// Performance logging for SD card operations:
|
|
||||||
// #define AFATFS_USE_INTROSPECTIVE_LOGGING
|
|
||||||
|
|
||||||
#define ACC
|
#define ACC
|
||||||
#define USE_ACC_LSM303DLHC
|
#define USE_ACC_LSM303DLHC
|
||||||
|
#define USE_ACC_MPU6500
|
||||||
|
#define USE_ACC_SPI_MPU6500
|
||||||
|
#define ACC_MPU6500_ALIGN CW270_DEG_FLIP
|
||||||
|
|
||||||
|
//#define BARO
|
||||||
|
//#define BMP280_CS_PIN PB12
|
||||||
|
//#define BMP280_SPI_INSTANCE SPI2
|
||||||
|
//#define USE_BARO_BMP280
|
||||||
|
//#define USE_BARO_SPI_BMP280
|
||||||
|
|
||||||
|
#define OSD
|
||||||
|
#define USE_MAX7456
|
||||||
|
#define MAX7456_SPI_INSTANCE SPI2
|
||||||
|
#define MAX7456_SPI_CS_PIN SPI2_NSS_PIN
|
||||||
|
|
||||||
|
//#define USE_SDCARD
|
||||||
|
//#define USE_SDCARD_SPI2
|
||||||
|
//
|
||||||
|
//#define SDCARD_SPI_INSTANCE SPI2
|
||||||
|
//#define SDCARD_SPI_CS_PIN PB12
|
||||||
|
//// SPI2 is on the APB1 bus whose clock runs at 36MHz. Divide to under 400kHz for init:
|
||||||
|
//#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER 128
|
||||||
|
//// Divide to under 25MHz for normal operation:
|
||||||
|
//#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER 2
|
||||||
|
//
|
||||||
|
//// Note, this is the same DMA channel as USART1_RX. Luckily we don't use DMA for USART Rx.
|
||||||
|
//#define SDCARD_DMA_CHANNEL_TX DMA1_Channel5
|
||||||
|
//#define SDCARD_DMA_CHANNEL_TX_COMPLETE_FLAG DMA1_FLAG_TC5
|
||||||
|
|
||||||
|
// Performance logging for SD card operations:
|
||||||
|
// #define AFATFS_USE_INTROSPECTIVE_LOGGING
|
||||||
|
|
||||||
#define MAG
|
#define MAG
|
||||||
#define USE_MAG_HMC5883
|
#define USE_MAG_HMC5883
|
||||||
|
@ -98,6 +127,14 @@
|
||||||
#define USE_USART2
|
#define USE_USART2
|
||||||
#define SERIAL_PORT_COUNT 3
|
#define SERIAL_PORT_COUNT 3
|
||||||
|
|
||||||
|
// uart2 gpio for shared serial rx/ppm
|
||||||
|
//#define UART2_TX_PIN GPIO_Pin_5 // PD5
|
||||||
|
//#define UART2_RX_PIN GPIO_Pin_6 // PD6
|
||||||
|
//#define UART2_GPIO GPIOD
|
||||||
|
//#define UART2_GPIO_AF GPIO_AF_7
|
||||||
|
//#define UART2_TX_PINSOURCE GPIO_PinSource5
|
||||||
|
//#define UART2_RX_PINSOURCE GPIO_PinSource6
|
||||||
|
|
||||||
#define USE_I2C
|
#define USE_I2C
|
||||||
#define I2C_DEVICE (I2CDEV_1)
|
#define I2C_DEVICE (I2CDEV_1)
|
||||||
|
|
||||||
|
|
|
@ -1,407 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Cleanflight.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "platform.h"
|
|
||||||
#include "scheduler/scheduler.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "unittest_macros.h"
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
enum {
|
|
||||||
systemTime = 10,
|
|
||||||
pidLoopCheckerTime = 650,
|
|
||||||
updateAccelerometerTime = 192,
|
|
||||||
handleSerialTime = 30,
|
|
||||||
updateBeeperTime = 1,
|
|
||||||
updateBatteryTime = 1,
|
|
||||||
updateRxCheckTime = 34,
|
|
||||||
updateRxMainTime = 10,
|
|
||||||
processGPSTime = 10,
|
|
||||||
updateCompassTime = 195,
|
|
||||||
updateBaroTime = 201,
|
|
||||||
updateSonarTime = 10,
|
|
||||||
calculateAltitudeTime = 154,
|
|
||||||
updateDisplayTime = 10,
|
|
||||||
telemetryTime = 10,
|
|
||||||
ledStripTime = 10,
|
|
||||||
transponderTime = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
cfTask_t * unittest_scheduler_selectedTask;
|
|
||||||
uint8_t unittest_scheduler_selectedTaskDynPrio;
|
|
||||||
uint16_t unittest_scheduler_waitingTasks;
|
|
||||||
uint32_t unittest_scheduler_timeToNextRealtimeTask;
|
|
||||||
bool unittest_outsideRealtimeGuardInterval;
|
|
||||||
|
|
||||||
// set up micros() to simulate time
|
|
||||||
uint32_t simulatedTime = 0;
|
|
||||||
uint32_t micros(void) {return simulatedTime;}
|
|
||||||
// set up tasks to take a simulated representative time to execute
|
|
||||||
void taskMainPidLoopChecker(void) {simulatedTime+=pidLoopCheckerTime;}
|
|
||||||
void taskUpdateAccelerometer(void) {simulatedTime+=updateAccelerometerTime;}
|
|
||||||
void taskHandleSerial(void) {simulatedTime+=handleSerialTime;}
|
|
||||||
void taskUpdateBeeper(void) {simulatedTime+=updateBeeperTime;}
|
|
||||||
void taskUpdateBattery(void) {simulatedTime+=updateBatteryTime;}
|
|
||||||
bool taskUpdateRxCheck(uint32_t currentDeltaTime) {UNUSED(currentDeltaTime);simulatedTime+=updateRxCheckTime;return false;}
|
|
||||||
void taskUpdateRxMain(void) {simulatedTime+=updateRxMainTime;}
|
|
||||||
void taskProcessGPS(void) {simulatedTime+=processGPSTime;}
|
|
||||||
void taskUpdateCompass(void) {simulatedTime+=updateCompassTime;}
|
|
||||||
void taskUpdateBaro(void) {simulatedTime+=updateBaroTime;}
|
|
||||||
void taskUpdateSonar(void) {simulatedTime+=updateSonarTime;}
|
|
||||||
void taskCalculateAltitude(void) {simulatedTime+=calculateAltitudeTime;}
|
|
||||||
void taskUpdateDisplay(void) {simulatedTime+=updateDisplayTime;}
|
|
||||||
void taskTelemetry(void) {simulatedTime+=telemetryTime;}
|
|
||||||
void taskLedStrip(void) {simulatedTime+=ledStripTime;}
|
|
||||||
void taskTransponder(void) {simulatedTime+=transponderTime;}
|
|
||||||
|
|
||||||
extern cfTask_t* taskQueueArray[];
|
|
||||||
|
|
||||||
extern void queueClear(void);
|
|
||||||
extern int queueSize();
|
|
||||||
extern bool queueContains(cfTask_t *task);
|
|
||||||
extern bool queueAdd(cfTask_t *task);
|
|
||||||
extern bool queueRemove(cfTask_t *task);
|
|
||||||
extern cfTask_t *queueFirst(void);
|
|
||||||
extern cfTask_t *queueNext(void);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestPriorites)
|
|
||||||
{
|
|
||||||
EXPECT_EQ(14, TASK_COUNT);
|
|
||||||
// if any of these fail then task priorities have changed and ordering in TestQueue needs to be re-checked
|
|
||||||
EXPECT_EQ(TASK_PRIORITY_HIGH, cfTasks[TASK_SYSTEM].staticPriority);
|
|
||||||
EXPECT_EQ(TASK_PRIORITY_REALTIME, cfTasks[TASK_GYROPID].staticPriority);
|
|
||||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM, cfTasks[TASK_ACCEL].staticPriority);
|
|
||||||
EXPECT_EQ(TASK_PRIORITY_LOW, cfTasks[TASK_SERIAL].staticPriority);
|
|
||||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM, cfTasks[TASK_BATTERY].staticPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestQueueInit)
|
|
||||||
{
|
|
||||||
queueClear();
|
|
||||||
EXPECT_EQ(0, queueSize());
|
|
||||||
EXPECT_EQ(0, queueFirst());
|
|
||||||
EXPECT_EQ(0, queueNext());
|
|
||||||
for (int ii = 0; ii <= TASK_COUNT; ++ii) {
|
|
||||||
EXPECT_EQ(0, taskQueueArray[ii]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cfTask_t *deadBeefPtr = reinterpret_cast<cfTask_t*>(0xDEADBEEF);
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestQueue)
|
|
||||||
{
|
|
||||||
queueClear();
|
|
||||||
taskQueueArray[TASK_COUNT + 1] = deadBeefPtr;
|
|
||||||
|
|
||||||
queueAdd(&cfTasks[TASK_SYSTEM]); // TASK_PRIORITY_HIGH
|
|
||||||
EXPECT_EQ(1, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueFirst());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
queueAdd(&cfTasks[TASK_GYROPID]); // TASK_PRIORITY_REALTIME
|
|
||||||
EXPECT_EQ(2, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], queueFirst());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueNext());
|
|
||||||
EXPECT_EQ(NULL, queueNext());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
queueAdd(&cfTasks[TASK_SERIAL]); // TASK_PRIORITY_LOW
|
|
||||||
EXPECT_EQ(3, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], queueFirst());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
|
||||||
EXPECT_EQ(NULL, queueNext());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
queueAdd(&cfTasks[TASK_BATTERY]); // TASK_PRIORITY_MEDIUM
|
|
||||||
EXPECT_EQ(4, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], queueFirst());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_BATTERY], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
|
||||||
EXPECT_EQ(NULL, queueNext());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
queueAdd(&cfTasks[TASK_RX]); // TASK_PRIORITY_HIGH
|
|
||||||
EXPECT_EQ(5, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], queueFirst());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_RX], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_BATTERY], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
|
||||||
EXPECT_EQ(NULL, queueNext());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
queueRemove(&cfTasks[TASK_SYSTEM]); // TASK_PRIORITY_HIGH
|
|
||||||
EXPECT_EQ(4, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], queueFirst());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_RX], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_BATTERY], queueNext());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
|
||||||
EXPECT_EQ(NULL, queueNext());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestQueueAddAndRemove)
|
|
||||||
{
|
|
||||||
queueClear();
|
|
||||||
taskQueueArray[TASK_COUNT + 1] = deadBeefPtr;
|
|
||||||
|
|
||||||
// fill up the queue
|
|
||||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
|
||||||
const bool added = queueAdd(&cfTasks[taskId]);
|
|
||||||
EXPECT_EQ(true, added);
|
|
||||||
EXPECT_EQ(taskId + 1, queueSize());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
}
|
|
||||||
// double check end of queue
|
|
||||||
EXPECT_EQ(TASK_COUNT, queueSize());
|
|
||||||
EXPECT_NE(static_cast<cfTask_t*>(0), taskQueueArray[TASK_COUNT - 1]); // last item was indeed added to queue
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]); // null pointer at end of queue is preserved
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]); // there hasn't been an out by one error
|
|
||||||
|
|
||||||
// and empty it again
|
|
||||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
|
||||||
const bool removed = queueRemove(&cfTasks[taskId]);
|
|
||||||
EXPECT_EQ(true, removed);
|
|
||||||
EXPECT_EQ(TASK_COUNT - taskId - 1, queueSize());
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - taskId]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
}
|
|
||||||
// double check size and end of queue
|
|
||||||
EXPECT_EQ(0, queueSize()); // queue is indeed empty
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[0]); // there is a null pointer at the end of the queueu
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]); // no accidental overwrites past end of queue
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestQueueArray)
|
|
||||||
{
|
|
||||||
// test there are no "out by one" errors or buffer overruns when items are added and removed
|
|
||||||
queueClear();
|
|
||||||
taskQueueArray[TASK_COUNT + 1] = deadBeefPtr; // note, must set deadBeefPtr after queueClear
|
|
||||||
|
|
||||||
for (int taskId = 0; taskId < TASK_COUNT - 1; ++taskId) {
|
|
||||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), true);
|
|
||||||
EXPECT_EQ(taskId + 1, queueSize());
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
}
|
|
||||||
EXPECT_EQ(TASK_COUNT - 1, queueSize());
|
|
||||||
EXPECT_NE(static_cast<cfTask_t*>(0), taskQueueArray[TASK_COUNT - 2]);
|
|
||||||
const cfTask_t *lastTaskPrev = taskQueueArray[TASK_COUNT - 2];
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
setTaskEnabled(TASK_SYSTEM, false);
|
|
||||||
EXPECT_EQ(TASK_COUNT - 2, queueSize());
|
|
||||||
EXPECT_EQ(lastTaskPrev, taskQueueArray[TASK_COUNT - 3]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 2]); // NULL at end of queue
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
taskQueueArray[TASK_COUNT - 2] = 0;
|
|
||||||
setTaskEnabled(TASK_SYSTEM, true);
|
|
||||||
EXPECT_EQ(TASK_COUNT - 1, queueSize());
|
|
||||||
EXPECT_EQ(lastTaskPrev, taskQueueArray[TASK_COUNT - 2]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
cfTaskInfo_t taskInfo;
|
|
||||||
getTaskInfo(static_cast<cfTaskId_e>(TASK_COUNT - 1), &taskInfo);
|
|
||||||
EXPECT_EQ(false, taskInfo.isEnabled);
|
|
||||||
setTaskEnabled(static_cast<cfTaskId_e>(TASK_COUNT - 1), true);
|
|
||||||
EXPECT_EQ(TASK_COUNT, queueSize());
|
|
||||||
EXPECT_EQ(lastTaskPrev, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]); // check no buffer overrun
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
setTaskEnabled(TASK_SYSTEM, false);
|
|
||||||
EXPECT_EQ(TASK_COUNT - 1, queueSize());
|
|
||||||
//EXPECT_EQ(lastTaskPrev, taskQueueArray[TASK_COUNT - 3]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
setTaskEnabled(TASK_ACCEL, false);
|
|
||||||
EXPECT_EQ(TASK_COUNT - 2, queueSize());
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 2]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
|
|
||||||
setTaskEnabled(TASK_BATTERY, false);
|
|
||||||
EXPECT_EQ(TASK_COUNT - 3, queueSize());
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 3]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 2]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - 1]);
|
|
||||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]);
|
|
||||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestSchedulerInit)
|
|
||||||
{
|
|
||||||
schedulerInit();
|
|
||||||
EXPECT_EQ(1, queueSize());
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueFirst());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestScheduleEmptyQueue)
|
|
||||||
{
|
|
||||||
queueClear();
|
|
||||||
simulatedTime = 4000;
|
|
||||||
// run the with an empty queue
|
|
||||||
scheduler();
|
|
||||||
EXPECT_EQ(NULL, unittest_scheduler_selectedTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestSingleTask)
|
|
||||||
{
|
|
||||||
schedulerInit();
|
|
||||||
// disable all tasks except TASK_GYROPID
|
|
||||||
for (int taskId=0; taskId < TASK_COUNT; ++taskId) {
|
|
||||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
|
||||||
}
|
|
||||||
setTaskEnabled(TASK_GYROPID, true);
|
|
||||||
cfTasks[TASK_GYROPID].lastExecutedAt = 1000;
|
|
||||||
simulatedTime = 4000;
|
|
||||||
// run the scheduler and check the task has executed
|
|
||||||
scheduler();
|
|
||||||
EXPECT_NE(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(3000, cfTasks[TASK_GYROPID].taskLatestDeltaTime);
|
|
||||||
EXPECT_EQ(4000, cfTasks[TASK_GYROPID].lastExecutedAt);
|
|
||||||
EXPECT_EQ(pidLoopCheckerTime, cfTasks[TASK_GYROPID].totalExecutionTime);
|
|
||||||
// task has run, so its dynamic priority should have been set to zero
|
|
||||||
EXPECT_EQ(0, cfTasks[TASK_GYROPID].dynamicPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestTwoTasks)
|
|
||||||
{
|
|
||||||
// disable all tasks except TASK_GYROPID and TASK_ACCEL
|
|
||||||
for (int taskId=0; taskId < TASK_COUNT; ++taskId) {
|
|
||||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
|
||||||
}
|
|
||||||
setTaskEnabled(TASK_ACCEL, true);
|
|
||||||
setTaskEnabled(TASK_GYROPID, true);
|
|
||||||
|
|
||||||
// set it up so that TASK_ACCEL ran just before TASK_GYROPID
|
|
||||||
static const uint32_t startTime = 4000;
|
|
||||||
simulatedTime = startTime;
|
|
||||||
cfTasks[TASK_GYROPID].lastExecutedAt = simulatedTime;
|
|
||||||
cfTasks[TASK_ACCEL].lastExecutedAt = cfTasks[TASK_GYROPID].lastExecutedAt - updateAccelerometerTime;
|
|
||||||
EXPECT_EQ(0, cfTasks[TASK_ACCEL].taskAgeCycles);
|
|
||||||
// run the scheduler
|
|
||||||
scheduler();
|
|
||||||
// no tasks should have run, since neither task's desired time has elapsed
|
|
||||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
|
||||||
|
|
||||||
// NOTE:
|
|
||||||
// TASK_GYROPID desiredPeriod is 1000 microseconds
|
|
||||||
// TASK_ACCEL desiredPeriod is 10000 microseconds
|
|
||||||
// 500 microseconds later
|
|
||||||
simulatedTime += 500;
|
|
||||||
// no tasks should run, since neither task's desired time has elapsed
|
|
||||||
scheduler();
|
|
||||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(0, unittest_scheduler_waitingTasks);
|
|
||||||
|
|
||||||
// 500 microseconds later, TASK_GYROPID desiredPeriod has elapsed
|
|
||||||
simulatedTime += 500;
|
|
||||||
// TASK_GYROPID should now run
|
|
||||||
scheduler();
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(1, unittest_scheduler_waitingTasks);
|
|
||||||
EXPECT_EQ(5000 + pidLoopCheckerTime, simulatedTime);
|
|
||||||
|
|
||||||
simulatedTime += 1000 - pidLoopCheckerTime;
|
|
||||||
scheduler();
|
|
||||||
// TASK_GYROPID should run again
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], unittest_scheduler_selectedTask);
|
|
||||||
|
|
||||||
scheduler();
|
|
||||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(0, unittest_scheduler_waitingTasks);
|
|
||||||
|
|
||||||
simulatedTime = startTime + 10500; // TASK_GYROPID and TASK_ACCEL desiredPeriods have elapsed
|
|
||||||
// of the two TASK_GYROPID should run first
|
|
||||||
scheduler();
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_GYROPID], unittest_scheduler_selectedTask);
|
|
||||||
// and finally TASK_ACCEL should now run
|
|
||||||
scheduler();
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestRealTimeGuardInNoTaskRun)
|
|
||||||
{
|
|
||||||
// disable all tasks except TASK_GYROPID and TASK_SYSTEM
|
|
||||||
for (int taskId=0; taskId < TASK_COUNT; ++taskId) {
|
|
||||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
|
||||||
}
|
|
||||||
setTaskEnabled(TASK_GYROPID, true);
|
|
||||||
cfTasks[TASK_GYROPID].lastExecutedAt = 200000;
|
|
||||||
simulatedTime = 200700;
|
|
||||||
|
|
||||||
setTaskEnabled(TASK_SYSTEM, true);
|
|
||||||
cfTasks[TASK_SYSTEM].lastExecutedAt = 100000;
|
|
||||||
|
|
||||||
scheduler();
|
|
||||||
|
|
||||||
EXPECT_EQ(false, unittest_outsideRealtimeGuardInterval);
|
|
||||||
EXPECT_EQ(300, unittest_scheduler_timeToNextRealtimeTask);
|
|
||||||
|
|
||||||
// Nothing should be scheduled in guard period
|
|
||||||
EXPECT_EQ(NULL, unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(100000, cfTasks[TASK_SYSTEM].lastExecutedAt);
|
|
||||||
|
|
||||||
EXPECT_EQ(200000, cfTasks[TASK_GYROPID].lastExecutedAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SchedulerUnittest, TestRealTimeGuardOutTaskRun)
|
|
||||||
{
|
|
||||||
// disable all tasks except TASK_GYROPID and TASK_SYSTEM
|
|
||||||
for (int taskId=0; taskId < TASK_COUNT; ++taskId) {
|
|
||||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
|
||||||
}
|
|
||||||
setTaskEnabled(TASK_GYROPID, true);
|
|
||||||
cfTasks[TASK_GYROPID].lastExecutedAt = 200000;
|
|
||||||
simulatedTime = 200699;
|
|
||||||
|
|
||||||
setTaskEnabled(TASK_SYSTEM, true);
|
|
||||||
cfTasks[TASK_SYSTEM].lastExecutedAt = 100000;
|
|
||||||
|
|
||||||
scheduler();
|
|
||||||
|
|
||||||
EXPECT_EQ(true, unittest_outsideRealtimeGuardInterval);
|
|
||||||
EXPECT_EQ(301, unittest_scheduler_timeToNextRealtimeTask);
|
|
||||||
|
|
||||||
// System should be scheduled as not in guard period
|
|
||||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], unittest_scheduler_selectedTask);
|
|
||||||
EXPECT_EQ(200699, cfTasks[TASK_SYSTEM].lastExecutedAt);
|
|
||||||
|
|
||||||
EXPECT_EQ(200000, cfTasks[TASK_GYROPID].lastExecutedAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// STUBS
|
|
||||||
extern "C" {
|
|
||||||
}
|
|
Loading…
Reference in New Issue