Created
November 20, 2022 17:22
-
-
Save nerdCopter/70860db0df4f9a4d0add1a942d8476f5 to your computer and use it in GitHub Desktop.
diff_of_port_roberts_HESP_to_BF411.diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/make/mcu/STM32F7.mk b/make/mcu/STM32F7.mk | |
index 6d8f71568..e3c747612 100644 | |
--- a/make/mcu/STM32F7.mk | |
+++ b/make/mcu/STM32F7.mk | |
@@ -14,8 +14,6 @@ STDPERIPH_DIR = $(ROOT)/lib/main/STM32F7/Drivers/STM32F7xx_HAL_Driver | |
STDPERIPH_SRC = $(notdir $(wildcard $(STDPERIPH_DIR)/Src/*.c)) | |
EXCLUDES = stm32f7xx_hal_can.c \ | |
stm32f7xx_hal_cec.c \ | |
- stm32f7xx_hal_crc.c \ | |
- stm32f7xx_hal_crc_ex.c \ | |
stm32f7xx_hal_cryp.c \ | |
stm32f7xx_hal_cryp_ex.c \ | |
stm32f7xx_hal_dcmi.c \ | |
diff --git a/src/main/cli/cli.c b/src/main/cli/cli.c | |
old mode 100644 | |
new mode 100755 | |
index b55bca0f5..17fe0e58b | |
--- a/src/main/cli/cli.c | |
+++ b/src/main/cli/cli.c | |
@@ -71,6 +71,7 @@ bool cliMode = false; | |
#include "drivers/compass/compass.h" | |
#include "drivers/display.h" | |
#include "drivers/dma.h" | |
+#include "drivers/dma_spi.h" | |
#include "drivers/flash.h" | |
#include "drivers/inverter.h" | |
#include "drivers/io.h" | |
@@ -174,6 +175,10 @@ bool cliMode = false; | |
#include "cli.h" | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+#endif | |
+ | |
static serialPort_t *cliPort = NULL; | |
#ifdef STM32F1 | |
@@ -214,6 +219,15 @@ static bool signatureUpdated = false; | |
static const char* const emptyName = "-"; | |
static const char* const emptyString = ""; | |
+#ifdef USE_GYRO_IMUF9001 | |
+#define IMUF_CUSTOM_BUFF_LENGTH 26000 | |
+static uint8_t imuf_custom_buff[IMUF_CUSTOM_BUFF_LENGTH]; | |
+static uint32_t imuf_buff_ptr = 0; | |
+static uint32_t imuf_checksum = 0; | |
+static int imuf_bin_safe = 0; | |
+ | |
+#endif | |
+ | |
#if !defined(USE_CUSTOM_DEFAULTS) | |
#define CUSTOM_DEFAULTS_START ((char*)0) | |
#define CUSTOM_DEFAULTS_END ((char *)0) | |
@@ -3392,6 +3406,64 @@ void cliRxBind(char *cmdline){ | |
} | |
#endif | |
+static void hex2byte(char *string, uint8_t *output) | |
+{ | |
+ char tempBuff[3]; | |
+ tempBuff[0] = string[0]; | |
+ tempBuff[1] = string[1]; | |
+ tempBuff[2] = 0; | |
+ *output = (uint8_t)strtol(tempBuff, NULL, 16); | |
+} | |
+ | |
+ | |
+#ifdef MSP_OVER_CLI | |
+sbuf_t buft; | |
+uint8_t bufPtr[256]; | |
+ | |
+void cliMsp(char *cmdline){ | |
+ int len = strlen(cmdline); | |
+ if (len == 0) { | |
+ cliPrintLine("No MSP command present"); | |
+ | |
+ return; | |
+ } else { | |
+ uint8_t mspCommand = atoi(cmdline); | |
+ uint8_t start = 2; | |
+ if (mspCommand > 99) { | |
+ start = 4; | |
+ } else if (mspCommand > 9) { | |
+ start= 3; | |
+ } | |
+ uint8_t inBuff[len]; | |
+ uint8_t output; | |
+ for (int i = 0; i < len; i++) { | |
+ hex2byte(&cmdline[(i*2) + start], &output); | |
+ inBuff[i] = output; | |
+ } | |
+ sbuf_t inBuf = {.ptr = inBuff, .end = &inBuff[len-1]}; | |
+ //TODO need to fill inPtr with the rest of the bytes from the command line | |
+ | |
+ buft.ptr = buft.end = bufPtr; | |
+ if (mspCommonProcessOutCommand(mspCommand, &buft, NULL) || mspProcessOutCommand(mspCommand, &buft) | |
+ || mspCommonProcessInCommand(mspCommand, &inBuf, NULL) > -1 || mspProcessInCommand(mspCommand, &inBuf) > -1) | |
+ { | |
+ | |
+ bufWriterAppend(cliWriter, '.'); //"." is success | |
+ bufWriterAppend(cliWriter, mspCommand); //msp command sent | |
+ bufWriterAppend(cliWriter, inBuf.ptr - inBuf.end); //msp command sent | |
+ bufWriterAppend(cliWriter, buft.ptr - buft.end); //number of chars | |
+ | |
+ while (buft.end <= buft.ptr) | |
+ bufWriterAppend(cliWriter, *(buft.end)++); //send data | |
+ } | |
+ else | |
+ { | |
+ bufWriterAppend(cliWriter, '!'); //"!" is failure | |
+ } | |
+ } | |
+} | |
+#endif | |
+ | |
static void printMap(dumpFlags_t dumpMask, const rxConfig_t *rxConfig, const rxConfig_t *defaultRxConfig, const char *headingStr) | |
{ | |
bool equalsDefault = true; | |
@@ -3546,6 +3618,116 @@ static void cliExit(char *cmdline) | |
cliReboot(); | |
} | |
+ | |
+#ifdef USE_GYRO_IMUF9001 | |
+ | |
+ | |
+static void cliImufBootloaderMode(char *cmdline) | |
+{ | |
+ (void)(cmdline); | |
+ if(imufBootloader()) | |
+ { | |
+ cliPrintLine("BOOTLOADER"); | |
+ } | |
+ else | |
+ { | |
+ cliPrintLine("FAIL"); | |
+ } | |
+} | |
+ | |
+ | |
+static void cliImufLoadBin(char *cmdline) | |
+{ | |
+ #define TEMP_BUFF 256 | |
+ uint32_t dataSize; | |
+ uint8_t output; | |
+ uint8_t dataBuff[TEMP_BUFF] = {0,}; | |
+ uint32_t x; | |
+ | |
+ if(cmdline[0] == '!') | |
+ { | |
+ imuf_bin_safe = 1; | |
+ imuf_buff_ptr = 0; | |
+ imuf_checksum = 0; | |
+ memset(imuf_custom_buff, 0, IMUF_CUSTOM_BUFF_LENGTH); | |
+ cliPrintLine("SUCCESS"); | |
+ } | |
+ else if(cmdline[0] == '.') | |
+ { | |
+ cliPrintLinef("%d", imuf_buff_ptr); | |
+ } | |
+ else if(cmdline[0] == 'c') | |
+ { | |
+ cliPrintLinef("%d", imuf_checksum); | |
+ } | |
+ else if(cmdline[0] == 'l') | |
+ { | |
+ if (imuf_bin_safe) | |
+ { | |
+ //get the datasize | |
+ hex2byte(&cmdline[1], &output); | |
+ dataSize = ((output & 0xff) << 0 ); | |
+ hex2byte(&cmdline[3], &output); | |
+ dataSize += ((output & 0xff) << 8 ); | |
+ hex2byte(&cmdline[5], &output); | |
+ dataSize += ((output & 0xff) << 16); | |
+ hex2byte(&cmdline[7], &output); | |
+ dataSize += ((output & 0xff) << 24); | |
+ | |
+ if(dataSize < TEMP_BUFF) | |
+ { | |
+ //fill the temp buffer | |
+ for(x=0; x< dataSize; x++) | |
+ { | |
+ hex2byte(&cmdline[(x*2)+9], &output); | |
+ dataBuff[x] = output; | |
+ imuf_checksum += output; | |
+ //cliPrintLinef("out:%d:%d:%d:%d", dataSize, x, (x*2)+9, output, checksum); | |
+ } | |
+ if ( (imuf_buff_ptr+dataSize) < IMUF_CUSTOM_BUFF_LENGTH ) | |
+ { | |
+ memcpy(imuf_custom_buff+imuf_buff_ptr, dataBuff, dataSize); | |
+ imuf_buff_ptr += dataSize; | |
+ cliPrintLine("LOADED"); | |
+ } | |
+ else | |
+ { | |
+ cliPrintLine("WOAH!"); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ cliPrintLine("CRAP!"); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ cliPrintLine("PFFFT!"); | |
+ } | |
+ } | |
+} | |
+ | |
+static void cliImufFlashBin(char *cmdline) | |
+{ | |
+ (void)(cmdline); | |
+ if (imufUpdate(imuf_custom_buff, imuf_buff_ptr)) | |
+ { | |
+ cliPrintLine("SUCCESS"); | |
+ bufWriterFlush(cliWriter); | |
+ delay(5000); | |
+ | |
+ *cliBuffer = '\0'; | |
+ bufferIndex = 0; | |
+ cliMode = 0; | |
+ // incase a motor was left running during motortest, clear it here | |
+ mixerResetDisarmedMotors(); | |
+ cliReboot(); | |
+ | |
+ cliWriter = NULL; | |
+ } | |
+} | |
+#endif | |
+ | |
#ifdef USE_GPS | |
static void cliGpsPassthrough(char *cmdline) | |
{ | |
@@ -4627,7 +4809,7 @@ static void cliStatus(char *cmdline) | |
// Sensors | |
-#if defined(USE_SENSOR_NAMES) | |
+#if defined(USE_SENSOR_NAMES) && !defined(USE_GYRO_IMUF9001) | |
const uint32_t detectedSensorsMask = sensorsMask(); | |
for (uint32_t i = 0; ; i++) { | |
if (sensorTypeNames[i] == NULL) { | |
@@ -4649,6 +4831,12 @@ static void cliStatus(char *cmdline) | |
} | |
} | |
cliPrintLinefeed(); | |
+#else | |
+ #if defined(USE_GYRO_IMUF9001) | |
+ UNUSED(sensorHardwareNames); | |
+ UNUSED(sensorTypeNames); | |
+ cliPrintf(" | IMU-F Version: %lu", imufCurrentVersion); | |
+ #endif | |
#endif /* USE_SENSOR_NAMES */ | |
// Uptime and wall clock | |
@@ -4783,6 +4971,10 @@ static void cliVersion(char *cmdline) | |
cliPrintLinefeed(); | |
#endif | |
+#ifdef USE_GYRO_IMUF9001 | |
+ cliPrintLinef("# IMU-F Version: %lu", imufCurrentVersion); | |
+#endif | |
+ | |
#ifdef USE_UNIFIED_TARGET | |
cliPrint("# "); | |
#ifdef USE_BOARD_INFO | |
@@ -6239,6 +6431,10 @@ typedef struct { | |
} | |
#endif | |
+#ifdef USE_GYRO_IMUF9001 | |
+static void cliReportImufErrors(char *cmdline); | |
+#endif | |
+ | |
static void cliHelp(char *cmdline); | |
// should be sorted a..z for bsearch() | |
@@ -6319,6 +6515,11 @@ const clicmd_t cmdTable[] = { | |
CLI_COMMAND_DEF("gyroregisters", "dump gyro config registers contents", NULL, cliDumpGyroRegisters), | |
#endif | |
CLI_COMMAND_DEF("help", NULL, NULL, cliHelp), | |
+#ifdef USE_GYRO_IMUF9001 | |
+ CLI_COMMAND_DEF("imufbootloader", NULL, NULL, cliImufBootloaderMode), | |
+ CLI_COMMAND_DEF("imufloadbin", NULL, NULL, cliImufLoadBin), | |
+ CLI_COMMAND_DEF("imufflashbin", NULL, NULL, cliImufFlashBin), | |
+#endif | |
#ifdef USE_LED_STRIP_STATUS_MODE | |
CLI_COMMAND_DEF("led", "configure leds", NULL, cliLed), | |
#endif | |
@@ -6353,6 +6554,9 @@ const clicmd_t cmdTable[] = { | |
#endif // USE_RC_SMOOTHING_FILTER | |
#ifdef USE_RESOURCE_MGMT | |
CLI_COMMAND_DEF("resource", "show/set resources", "<> | <resource name> <index> [<pin>|none] | show [all]", cliResource), | |
+#endif | |
+#ifdef USE_GYRO_IMUF9001 | |
+ CLI_COMMAND_DEF("reportimuferrors", "report imu-f comm errors", NULL, cliReportImufErrors), | |
#endif | |
CLI_COMMAND_DEF("rxfail", "show/set rx failsafe settings", NULL, cliRxFailsafe), | |
CLI_COMMAND_DEF("rxrange", "configure rx channel ranges", NULL, cliRxRange), | |
@@ -6401,6 +6605,15 @@ const clicmd_t cmdTable[] = { | |
#endif | |
}; | |
+#ifdef USE_GYRO_IMUF9001 | |
+static void cliReportImufErrors(char *cmdline) | |
+{ | |
+ UNUSED(cmdline); | |
+ cliPrintf("Current Comm Errors: %lu", crcErrorCount); | |
+ cliPrintLinefeed(); | |
+} | |
+#endif | |
+ | |
static void cliHelp(char *cmdline) | |
{ | |
UNUSED(cmdline); | |
diff --git a/src/main/cms/cms_menu_imu.c b/src/main/cms/cms_menu_imu.c | |
index 13d089c1f..c1fe7bb45 100644 | |
--- a/src/main/cms/cms_menu_imu.c | |
+++ b/src/main/cms/cms_menu_imu.c | |
@@ -73,6 +73,11 @@ static uint8_t rateProfileIndex; | |
static char rateProfileIndexString[MAX_RATE_PROFILE_NAME_LENGTH + 5]; | |
static controlRateConfig_t rateProfile; | |
+// HELIOSPRING | |
+static const char * const cms_offOnLabels[] = { | |
+ "OFF", "ON" | |
+}; | |
+ | |
static const char * const osdTableThrottleLimitType[] = { | |
"OFF", "SCALE", "CLIP" | |
}; | |
@@ -373,6 +378,53 @@ static uint8_t cmsx_iterm_relax_type; | |
static uint8_t cmsx_iterm_relax_cutoff; | |
#endif | |
+// HELIOSPRING | |
+#if defined(USE_GYRO_IMUF9001) | |
+static uint16_t gyroConfig_imuf_roll_q; | |
+static uint16_t gyroConfig_imuf_pitch_q; | |
+static uint16_t gyroConfig_imuf_yaw_q; | |
+static uint16_t gyroConfig_imuf_w; | |
+static uint16_t gyroConfig_imuf_pitch_lpf_cutoff_hz; | |
+static uint16_t gyroConfig_imuf_roll_lpf_cutoff_hz; | |
+static uint16_t gyroConfig_imuf_yaw_lpf_cutoff_hz; | |
+static uint8_t gyroConfig_imuf_roll_af; | |
+static uint8_t gyroConfig_imuf_pitch_af; | |
+static uint8_t gyroConfig_imuf_yaw_af; | |
+#endif | |
+#if defined(USE_GYRO_IMUF9001) | |
+static long cmsx_menuImuf_onEnter(void) | |
+{ | |
+ gyroConfig_imuf_roll_q = gyroConfig()->imuf_roll_q; | |
+ gyroConfig_imuf_pitch_q = gyroConfig()->imuf_pitch_q; | |
+ gyroConfig_imuf_yaw_q = gyroConfig()->imuf_yaw_q; | |
+ gyroConfig_imuf_w = gyroConfig()->imuf_w; | |
+ gyroConfig_imuf_pitch_lpf_cutoff_hz = gyroConfig()->imuf_pitch_lpf_cutoff_hz; | |
+ gyroConfig_imuf_roll_lpf_cutoff_hz = gyroConfig()->imuf_roll_lpf_cutoff_hz; | |
+ gyroConfig_imuf_yaw_lpf_cutoff_hz = gyroConfig()->imuf_yaw_lpf_cutoff_hz; | |
+ gyroConfig_imuf_roll_af = gyroConfigMutable()->imuf_roll_af; | |
+ gyroConfig_imuf_pitch_af = gyroConfigMutable()->imuf_pitch_af; | |
+ gyroConfig_imuf_yaw_af = gyroConfigMutable()->imuf_yaw_af; | |
+ return 0; | |
+} | |
+#endif | |
+#if defined(USE_GYRO_IMUF9001) | |
+static long cmsx_menuImuf_onExit(const OSD_Entry *self) | |
+{ | |
+ UNUSED(self); | |
+ gyroConfigMutable()->imuf_roll_q = gyroConfig_imuf_roll_q; | |
+ gyroConfigMutable()->imuf_pitch_q = gyroConfig_imuf_pitch_q; | |
+ gyroConfigMutable()->imuf_yaw_q = gyroConfig_imuf_yaw_q; | |
+ gyroConfigMutable()->imuf_w = gyroConfig_imuf_w; | |
+ gyroConfigMutable()->imuf_roll_lpf_cutoff_hz = gyroConfig_imuf_roll_lpf_cutoff_hz; | |
+ gyroConfigMutable()->imuf_pitch_lpf_cutoff_hz = gyroConfig_imuf_pitch_lpf_cutoff_hz; | |
+ gyroConfigMutable()->imuf_yaw_lpf_cutoff_hz = gyroConfig_imuf_yaw_lpf_cutoff_hz; | |
+ gyroConfigMutable()->imuf_roll_af = gyroConfig_imuf_roll_af; | |
+ gyroConfigMutable()->imuf_pitch_af = gyroConfig_imuf_pitch_af; | |
+ gyroConfigMutable()->imuf_yaw_af = gyroConfig_imuf_yaw_af; | |
+ return 0; | |
+} | |
+#endif | |
+ | |
static long cmsx_profileOtherOnEnter(void) | |
{ | |
setProfileIndexString(pidProfileIndexString, pidProfileIndex, currentPidProfile->profileName); | |
@@ -485,6 +537,39 @@ static const OSD_Entry cmsx_menuProfileOtherEntries[] = { | |
{ NULL, OME_END, NULL, NULL, 0 } | |
}; | |
+// HELIOSPRING | |
+#if defined(USE_GYRO_IMUF9001) | |
+static OSD_Entry cmsx_menuImufEntries[] = | |
+{ | |
+ { "-- SPRING IMU-F --", OME_Label, NULL, NULL, 0 }, | |
+ { "-- CHANGES REQUIRE REBOOT --", OME_Label, NULL, NULL, 0 }, | |
+ { "IMUF W", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_w, 0, 300, 1 }, 0 }, | |
+ { "ROLL Q", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_roll_q, 0, 16000, 50 }, 0 }, | |
+ { "PITCH Q", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_pitch_q, 0, 16000, 50 }, 0 }, | |
+ { "YAW Q", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_yaw_q, 0, 16000, 50 }, 0 }, | |
+ { "ROLL LPF", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_roll_lpf_cutoff_hz, 0, 450, 1 }, 0 }, | |
+ { "PITCH LPF", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_pitch_lpf_cutoff_hz, 0, 450, 1 }, 0 }, | |
+ { "YAW LPF", OME_UINT16, NULL, &(OSD_UINT16_t) { &gyroConfig_imuf_yaw_lpf_cutoff_hz, 0, 450, 1 }, 0 }, | |
+ { "ROLL AF", OME_TAB, NULL, &(OSD_TAB_t) { &gyroConfig_imuf_roll_af, 0, cms_offOnLabels}, 0 }, | |
+ { "PITCH AF", OME_TAB, NULL, &(OSD_TAB_t) { &gyroConfig_imuf_pitch_af, 0, cms_offOnLabels}, 0 }, | |
+ { "YAW AF", OME_TAB, NULL, &(OSD_TAB_t) { &gyroConfig_imuf_yaw_af, 0, cms_offOnLabels}, 0 }, | |
+ { "BACK", OME_Back, NULL, NULL, 0}, | |
+ { "SAVE&REBOOT", OME_OSD_Exit, cmsMenuExit, (void *)CMS_EXIT_SAVEREBOOT, 0}, | |
+ { NULL, OME_END, NULL, NULL, 0 } | |
+}; | |
+#endif | |
+#if defined(USE_GYRO_IMUF9001) | |
+static CMS_Menu cmsx_menuImuf = { | |
+#ifdef CMS_MENU_DEBUG | |
+ .GUARD_text = "XIMUF", | |
+ .GUARD_type = OME_MENU, | |
+#endif | |
+ .onEnter = cmsx_menuImuf_onEnter, | |
+ .onExit = cmsx_menuImuf_onExit, | |
+ .entries = cmsx_menuImufEntries, | |
+}; | |
+#endif | |
+ | |
static CMS_Menu cmsx_menuProfileOther = { | |
#ifdef CMS_MENU_DEBUG | |
.GUARD_text = "XPROFOTHER", | |
@@ -794,6 +879,12 @@ static const OSD_Entry cmsx_menuImuEntries[] = | |
{"RATE", OME_Submenu, cmsMenuChange, &cmsx_menuRateProfile, 0}, | |
{"FILT GLB", OME_Submenu, cmsMenuChange, &cmsx_menuFilterGlobal, 0}, | |
+ | |
+// HELIOSPRING | |
+#if defined(USE_GYRO_IMUF9001) | |
+ {"IMUF", OME_Submenu, cmsMenuChange, &cmsx_menuImuf, 0}, | |
+#endif | |
+ | |
#if (defined(USE_GYRO_DATA_ANALYSE) || defined(USE_DYN_LPF)) && defined(USE_EXTENDED_CMS_MENUS) | |
{"DYN FILT", OME_Submenu, cmsMenuChange, &cmsx_menuDynFilt, 0}, | |
#endif | |
diff --git a/src/main/common/sensor_alignment.h b/src/main/common/sensor_alignment.h | |
index e158c6052..8ed6af449 100644 | |
--- a/src/main/common/sensor_alignment.h | |
+++ b/src/main/common/sensor_alignment.h | |
@@ -37,8 +37,18 @@ typedef enum { | |
CW90_DEG_FLIP = 6, // 00,10,01 | |
CW180_DEG_FLIP = 7, // 00,10,10 | |
CW270_DEG_FLIP = 8, // 00,10,11 | |
- | |
- ALIGN_CUSTOM = 9, // arbitrary sensor angles, e.g. for external sensors | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ CW45_DEG = 9, | |
+ CW135_DEG = 10, | |
+ CW225_DEG = 11, | |
+ CW315_DEG = 12, | |
+ CW45_DEG_FLIP = 13, | |
+ CW135_DEG_FLIP = 14, | |
+ CW225_DEG_FLIP = 15, | |
+ CW315_DEG_FLIP = 16, | |
+#endif | |
+ ALIGN_CUSTOM = 17, // arbitrary sensor angles, e.g. for external sensors | |
} sensor_align_e; | |
typedef union sensorAlignment_u { | |
diff --git a/src/main/drivers/accgyro/accgyro.h b/src/main/drivers/accgyro/accgyro.h | |
index d2f7f6ee2..a21082761 100644 | |
--- a/src/main/drivers/accgyro/accgyro.h | |
+++ b/src/main/drivers/accgyro/accgyro.h | |
@@ -53,6 +53,7 @@ typedef enum { | |
GYRO_ICM20649, | |
GYRO_ICM20689, | |
GYRO_BMI160, | |
+ GYRO_IMUF9001, // HELIOSPRING | |
GYRO_FAKE | |
} gyroHardware_e; | |
diff --git a/src/main/drivers/accgyro/accgyro_imuf9001.c b/src/main/drivers/accgyro/accgyro_imuf9001.c | |
new file mode 100755 | |
index 000000000..7f903fd26 | |
--- /dev/null | |
+++ b/src/main/drivers/accgyro/accgyro_imuf9001.c | |
@@ -0,0 +1,655 @@ | |
+/* | |
+ * 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 <stdbool.h> | |
+#include <stdint.h> | |
+#include <stdlib.h> | |
+#include <stdio.h> | |
+#include <string.h> | |
+ | |
+#include "platform.h" | |
+ | |
+#include "sensors/gyro.h" | |
+#include "accgyro.h" | |
+#include "accgyro_mpu.h" | |
+#include "accgyro_imuf9001.h" | |
+ | |
+#include "common/axis.h" | |
+#include "build/debug.h" | |
+#include "common/maths.h" | |
+#include "drivers/serial.h" | |
+#include "drivers/bus_spi.h" | |
+#include "drivers/dma_spi.h" | |
+#include "drivers/exti.h" | |
+#include "drivers/io.h" | |
+#include "drivers/light_led.h" | |
+#include "drivers/sensor.h" | |
+#include "drivers/time.h" | |
+#include "fc/config.h" | |
+#include "fc/runtime_config.h" | |
+ | |
+#include "sensors/boardalignment.h" | |
+#include "sensors/gyro.h" | |
+#include "sensors/acceleration.h" | |
+ | |
+#ifdef USE_HAL_F7_CRC | |
+//CRC stuff should really go in a separate CRC driver, but only IMUF uses it | |
+#include "stm32f7xx_hal.h" | |
+#include "drivers/system.h" | |
+#endif | |
+ | |
+ | |
+#ifdef USE_GYRO_IMUF9001 | |
+ | |
+#define MPU_INT_EXTI PB0 | |
+ | |
+volatile uint16_t imufCurrentVersion = IMUF_FIRMWARE_MIN_VERSION; | |
+FAST_RAM_ZERO_INIT volatile uint32_t isImufCalibrating; | |
+FAST_RAM_ZERO_INIT volatile imuFrame_t imufQuat; | |
+FAST_RAM_ZERO_INIT busDevice_t *imufDev; | |
+ | |
+#ifdef USE_HAL_F7_CRC | |
+//CRC stuff should really go in a separate CRC driver, but only IMUF uses it | |
+FAST_RAM_ZERO_INIT CRC_HandleTypeDef CrcHandle; | |
+#endif | |
+ | |
+void crcConfig(void) | |
+{ | |
+ #ifdef USE_HAL_F7_CRC | |
+ __HAL_RCC_CRC_CLK_ENABLE(); | |
+ CrcHandle.Instance = CRC; | |
+ CrcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE; | |
+ CrcHandle.Init.GeneratingPolynomial = 0x04C11DB7; | |
+ CrcHandle.Init.CRCLength = CRC_POLYLENGTH_32B; | |
+ CrcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS; | |
+ | |
+ HAL_CRC_Init(&CrcHandle); | |
+ #endif | |
+ //F4 std per doesn't need to be init | |
+ return; | |
+} | |
+ | |
+FAST_CODE uint32_t getCrcImuf9001(uint32_t* data, uint32_t size) | |
+{ | |
+ #ifdef USE_HAL_F7_CRC | |
+ return HAL_CRC_Calculate(&CrcHandle, data, size); | |
+ #else | |
+ CRC_ResetDR(); //reset data register | |
+ for(uint32_t x=0; x<size; x++ ) | |
+ { | |
+ CRC_CalcCRC(data[x]); | |
+ } | |
+ return CRC_GetCRC(); | |
+ #endif | |
+} | |
+ | |
+FAST_CODE void appendCrcToData(uint32_t* data, uint32_t size) | |
+{ | |
+ data[size] = getCrcImuf9001(data, size);; | |
+} | |
+ | |
+FAST_CODE static void gpio_write_pin(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, gpioState_t pinState) | |
+{ | |
+ //GPIO manipulation should go into a fast GPIO driver and should be separate from the befhal | |
+ | |
+ #ifdef USE_HAL_F7_CRC | |
+ HAL_GPIO_WritePin(GPIOx, GPIO_Pin, pinState); | |
+ #else | |
+ if (pinState == GPIO_HI) | |
+ { | |
+ GPIOx->BSRRL = (uint32_t)GPIO_Pin; | |
+ } | |
+ else | |
+ { | |
+ GPIOx->BSRRH = (uint32_t)GPIO_Pin; | |
+ } | |
+ #endif | |
+} | |
+ | |
+void resetImuf9001(void) | |
+{ | |
+ gpio_write_pin(IMUF_RST_PORT, IMUF_RST_PIN, GPIO_LO); | |
+ //blink | |
+ for(uint32_t x = 0; x<40; x++) | |
+ { | |
+ LED0_TOGGLE; | |
+ delay(20); | |
+ } | |
+ LED0_OFF; | |
+ gpio_write_pin(IMUF_RST_PORT, IMUF_RST_PIN, GPIO_HI); | |
+ delay(100); | |
+} | |
+ | |
+ | |
+#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) | |
+#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ | |
+ ((__GPIOx__) == (GPIOB))? 1U :\ | |
+ ((__GPIOx__) == (GPIOC))? 2U :\ | |
+ ((__GPIOx__) == (GPIOD))? 3U :\ | |
+ ((__GPIOx__) == (GPIOE))? 4U :\ | |
+ ((__GPIOx__) == (GPIOF))? 5U :\ | |
+ ((__GPIOx__) == (GPIOG))? 6U :\ | |
+ ((__GPIOx__) == (GPIOH))? 7U : 8U) | |
+#endif | |
+ | |
+void imufDeinitGpio(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) | |
+{ | |
+ uint32_t position; | |
+ uint32_t ioposition = 0x00U; | |
+ uint32_t iocurrent = 0x00U; | |
+ uint32_t tmp = 0x00U; | |
+ | |
+ /* Configure the port pins */ | |
+ for(position = 0U; position < 16; position++) | |
+ { | |
+ /* Get the IO position */ | |
+ ioposition = 0x01U << position; | |
+ /* Get the current IO position */ | |
+ iocurrent = (GPIO_Pin) & ioposition; | |
+ | |
+ if(iocurrent == ioposition) | |
+ { | |
+ /*------------------------- GPIO Mode Configuration --------------------*/ | |
+ /* Configure IO Direction in Input Floating Mode */ | |
+ GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (position * 2U)); | |
+ | |
+ /* Configure the default Alternate Function in current IO */ | |
+ GPIOx->AFR[position >> 3U] &= ~(0xFU << ((uint32_t)(position & 0x07U) * 4U)) ; | |
+ | |
+ /* Configure the default value for IO Speed */ | |
+ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U)); | |
+ | |
+ /* Configure the default value IO Output Type */ | |
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT_0 << position) ; | |
+ | |
+ /* Deactivate the Pull-up and Pull-down resistor for the current IO */ | |
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U)); | |
+ | |
+ /*------------------------- EXTI Mode Configuration --------------------*/ | |
+ tmp = SYSCFG->EXTICR[position >> 2U]; | |
+ tmp &= (0x0FU << (4U * (position & 0x03U))); | |
+ if(tmp == ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4U * (position & 0x03U)))) | |
+ { | |
+ /* Configure the External Interrupt or event for the current IO */ | |
+ tmp = 0x0FU << (4U * (position & 0x03U)); | |
+ SYSCFG->EXTICR[position >> 2U] &= ~tmp; | |
+ | |
+ /* Clear EXTI line configuration */ | |
+ EXTI->IMR &= ~((uint32_t)iocurrent); | |
+ EXTI->EMR &= ~((uint32_t)iocurrent); | |
+ | |
+ /* Clear Rising Falling edge configuration */ | |
+ EXTI->RTSR &= ~((uint32_t)iocurrent); | |
+ EXTI->FTSR &= ~((uint32_t)iocurrent); | |
+ } | |
+ } | |
+ } | |
+} | |
+ | |
+void initImuf9001(void) | |
+{ | |
+ //GPIO manipulation should go into a fast GPIO driver and should be separate from the befhal | |
+ #ifdef USE_HAL_F7_CRC | |
+ HAL_GPIO_DeInit(IMUF_RST_PORT, IMUF_RST_PIN); | |
+ GPIO_InitTypeDef GPIO_InitStruct; | |
+ GPIO_InitStruct.Pin = IMUF_RST_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; | |
+ GPIO_InitStruct.Pull = GPIO_NOPULL; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; | |
+ | |
+ HAL_GPIO_Init(IMUF_RST_PORT, &GPIO_InitStruct); | |
+ #else | |
+ //GPIO_DeInit(IMUF_RST_PORT); | |
+ imufDeinitGpio(IMUF_RST_PORT, IMUF_RST_PIN); | |
+ GPIO_InitTypeDef gpioInitStruct; | |
+ gpioInitStruct.GPIO_Pin = IMUF_RST_PIN; | |
+ gpioInitStruct.GPIO_Mode = GPIO_Mode_OUT; | |
+ gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz; | |
+ gpioInitStruct.GPIO_OType = GPIO_OType_OD; | |
+ gpioInitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; | |
+ GPIO_Init(IMUF_RST_PORT, &gpioInitStruct); | |
+ #endif | |
+ | |
+ resetImuf9001(); | |
+} | |
+ | |
+FAST_CODE bool imufSendReceiveSpiBlocking(const busDevice_t *bus, uint8_t *dataTx, uint8_t *daRx, uint8_t length) | |
+{ | |
+ spiBusTransfer(bus, dataTx, daRx, length); | |
+ return true; | |
+} | |
+ | |
+FAST_CODE static int imuf9001SendReceiveCommand(const busDevice_t *gyro, gyroCommands_t commandToSend, imufCommand_t *reply, imufCommand_t *data) | |
+{ | |
+ | |
+ imufCommand_t command; | |
+ volatile uint32_t attempt, crcCalc; | |
+ int failCount = 5000; | |
+ | |
+ memset(reply, 0, sizeof(command)); | |
+ | |
+ if (data) | |
+ { | |
+ memcpy(&command, data, sizeof(command)); | |
+ } | |
+ else | |
+ { | |
+ memset(&command, 0, sizeof(command)); | |
+ } | |
+ | |
+ command.command = commandToSend; | |
+ command.crc = getCrcImuf9001((uint32_t *)&command, 11);; | |
+ | |
+ | |
+ while (failCount-- > 0) | |
+ { | |
+ delayMicroseconds(1000); | |
+ if( IORead(IOGetByTag(IO_TAG(MPU_INT_EXTI))) ) //IMU is ready to talk | |
+ { | |
+ failCount -= 100; | |
+ if (imufSendReceiveSpiBlocking(gyro, (uint8_t *)&command, (uint8_t *)reply, sizeof(imufCommand_t))) | |
+ { | |
+ crcCalc = getCrcImuf9001((uint32_t *)reply, 11); | |
+ //this is the only valid reply we'll get if we're in BL mode | |
+ if(crcCalc == reply->crc && (reply->command == IMUF_COMMAND_LISTENING || reply->command == BL_LISTENING)) //this tells us the IMU was listening for a command, else we need to reset synbc | |
+ { | |
+ for (attempt = 0; attempt < 100; attempt++) | |
+ { | |
+ //reset command, just waiting for reply data now | |
+ command.command = IMUF_COMMAND_NONE; | |
+ command.crc = getCrcImuf9001((uint32_t *)&command, 11); | |
+ if (commandToSend == BL_ERASE_ALL){ | |
+ delay(600); | |
+ } | |
+ if(commandToSend == BL_WRITE_FIRMWARES) | |
+ { | |
+ delay(10); | |
+ } | |
+ delayMicroseconds(1000); //give pin time to set | |
+ | |
+ if( IORead(IOGetByTag(IO_TAG(MPU_INT_EXTI))) ) //IMU is ready to talk | |
+ { | |
+ //reset attempts | |
+ attempt = 100; | |
+ | |
+ delayMicroseconds(1000); //give pin time to set | |
+ imufSendReceiveSpiBlocking(gyro, (uint8_t *)&command, (uint8_t *)reply, sizeof(imufCommand_t)); | |
+ crcCalc = getCrcImuf9001((uint32_t *)reply, 11); | |
+ | |
+ if(crcCalc == reply->crc && reply->command == commandToSend ) //this tells us the IMU understood the last command | |
+ { | |
+ return 1; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ return 0; | |
+} | |
+ | |
+int imufBootloader() | |
+{ | |
+ | |
+ imufCommand_t reply; | |
+ imufCommand_t data; | |
+ memset(&data, 0, sizeof(data)); | |
+ | |
+ //config BL pin as output (shared with EXTI, this happens before EXTI init though) | |
+ //config pins | |
+ #ifdef USE_HAL_F7_CRC | |
+ HAL_GPIO_DeInit(IMUF_EXTI_PORT, IMUF_EXTI_PIN); | |
+ GPIO_InitTypeDef GPIO_InitStruct; | |
+ GPIO_InitStruct.Pin = IMUF_EXTI_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; | |
+ GPIO_InitStruct.Pull = GPIO_NOPULL; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; | |
+ | |
+ HAL_GPIO_Init(IMUF_EXTI_PORT, &GPIO_InitStruct); | |
+ #else | |
+ //GPIO_DeInit(IMUF_EXTI_PORT); | |
+ imufDeinitGpio(IMUF_EXTI_PORT, IMUF_EXTI_PIN); | |
+ GPIO_InitTypeDef gpioInitStruct; | |
+ gpioInitStruct.GPIO_Pin = IMUF_EXTI_PIN; | |
+ gpioInitStruct.GPIO_Mode = GPIO_Mode_OUT; | |
+ gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz; | |
+ gpioInitStruct.GPIO_OType = GPIO_OType_PP; | |
+ gpioInitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; | |
+ GPIO_Init(IMUF_EXTI_PORT, &gpioInitStruct); | |
+ #endif | |
+ //config pins | |
+ delay(200); | |
+ | |
+ gpio_write_pin(IMUF_EXTI_PORT, IMUF_EXTI_PIN, 1); //set bl pin Hi | |
+ initImuf9001(); //reset imuf, make three blinks | |
+ resetImuf9001(); //reset imuf, make three blinks | |
+ resetImuf9001(); //reset imuf, make three blinks | |
+ delay(1000); //delay 100 ms. give IMUF BL time to look for bl init pin | |
+ gpio_write_pin(IMUF_EXTI_PORT, IMUF_EXTI_PIN, 0); //set bl pin Lo | |
+ | |
+ //config EXTI as input so we can check imuf status | |
+ //config pins | |
+ #ifdef USE_HAL_F7_CRC | |
+ HAL_GPIO_DeInit(IMUF_EXTI_PORT, IMUF_EXTI_PIN); | |
+ GPIO_InitStruct.Pin = IMUF_EXTI_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; | |
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; | |
+ | |
+ HAL_GPIO_Init(IMUF_EXTI_PORT, &GPIO_InitStruct); | |
+ #else | |
+ imufDeinitGpio(IMUF_EXTI_PORT, IMUF_EXTI_PIN); | |
+ gpioInitStruct.GPIO_Pin = IMUF_EXTI_PIN; | |
+ gpioInitStruct.GPIO_Mode = GPIO_Mode_IN; | |
+ gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz; | |
+ gpioInitStruct.GPIO_OType = GPIO_OType_PP; | |
+ gpioInitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; | |
+ GPIO_Init(IMUF_EXTI_PORT, &gpioInitStruct); | |
+ #endif | |
+ //config pins | |
+ delay(200); | |
+ | |
+ if (imuf9001SendReceiveCommand(imufDev, BL_REPORT_INFO, &reply, &data)) | |
+ { | |
+ return 1; | |
+ } | |
+ else | |
+ { | |
+ return 0; | |
+ } | |
+} | |
+ | |
+volatile int checkCount = 0; | |
+ | |
+int imufUpdate(uint8_t *buff, uint32_t bin_length) | |
+{ | |
+ imufCommand_t reply; | |
+ imufCommand_t data; | |
+ memset(&data, 0, sizeof(data)); | |
+ | |
+ //check if BL is active | |
+ if (imuf9001SendReceiveCommand(imufDev, BL_REPORT_INFO, &reply, &data)) | |
+ { | |
+ //erase firmware on MCU | |
+ if( imuf9001SendReceiveCommand(imufDev, BL_ERASE_ALL, &reply, &data) ) | |
+ { | |
+ //good data | |
+ if( imuf9001SendReceiveCommand(imufDev, BL_PREPARE_PROGRAM, &reply, &data) ) | |
+ { | |
+ | |
+ //blink | |
+ for(uint32_t x = 0; x<10; x++) | |
+ { | |
+ LED0_TOGGLE; | |
+ delay(200); | |
+ } | |
+ LED0_OFF; | |
+ | |
+ volatile uint32_t chunk_start = (uint32_t)buff; | |
+ for(uint32_t x=0;x<(bin_length);x+=32) | |
+ { | |
+ data.param1 = 0x08002000+x; | |
+ data.param2 = (*(__IO uint32_t *)(chunk_start+x)); | |
+ data.param3 = (*(__IO uint32_t *)(chunk_start+x+4)); | |
+ data.param4 = (*(__IO uint32_t *)(chunk_start+x+8)); | |
+ data.param5 = (*(__IO uint32_t *)(chunk_start+x+12)); | |
+ data.param6 = (*(__IO uint32_t *)(chunk_start+x+16)); | |
+ data.param7 = (*(__IO uint32_t *)(chunk_start+x+20)); | |
+ data.param8 = (*(__IO uint32_t *)(chunk_start+x+24)); | |
+ data.param9 = (*(__IO uint32_t *)(chunk_start+x+28)); | |
+ | |
+ if( imuf9001SendReceiveCommand(imufDev, BL_WRITE_FIRMWARES, &reply, &data) ) | |
+ { | |
+ //continue writing | |
+ LED0_TOGGLE; | |
+ } | |
+ else | |
+ { | |
+ //error handler | |
+ for(uint32_t x = 0; x<40; x++) | |
+ { | |
+ LED0_TOGGLE; | |
+ delay(200); | |
+ } | |
+ LED0_OFF; | |
+ return 0; | |
+ } | |
+ } | |
+ | |
+ if (imuf9001SendReceiveCommand(imufDev, BL_END_PROGRAM, &reply, &data) ) | |
+ { | |
+ //blink | |
+ for (uint32_t x = 0; x<40; x++) | |
+ { | |
+ LED0_TOGGLE; | |
+ delay(20); | |
+ } | |
+ LED0_OFF; | |
+ return 1; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ checkCount++; | |
+ if (checkCount > 40) | |
+ { | |
+ checkCount = 0; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+int imuf9001Whoami(const busDevice_t *gyro) | |
+{ | |
+ imufDev = (busDevice_t *)gyro; | |
+ uint32_t attempt; | |
+ imufCommand_t reply; | |
+ | |
+ for (attempt = 0; attempt < 5; attempt++) | |
+ { | |
+ if (imuf9001SendReceiveCommand(gyro, IMUF_COMMAND_REPORT_INFO, &reply, NULL)) | |
+ { | |
+ imufCurrentVersion = (*(imufVersion_t *)&(reply.param1)).firmware; | |
+ if (imufCurrentVersion >= IMUF_FIRMWARE_MIN_VERSION) { | |
+ return IMUF_9001_SPI; | |
+ } | |
+ } | |
+ } | |
+ imufCurrentVersion = 9999; | |
+ return 0; | |
+} | |
+ | |
+uint8_t imuf9001SpiDetect(const busDevice_t *gyro) | |
+{ | |
+ static bool hardwareInitialised = false; | |
+ int returnCheck; | |
+ | |
+ if (hardwareInitialised) { | |
+ return(0); | |
+ } | |
+ | |
+ //config crc | |
+ crcConfig(); | |
+ | |
+ //config exti as input, not exti for now | |
+ IOInit(IOGetByTag( IO_TAG(MPU_INT_EXTI) ), OWNER_GYRO_EXTI, 0); | |
+ IOConfigGPIO(IOGetByTag( IO_TAG(MPU_INT_EXTI) ), IOCFG_IPD); | |
+ | |
+ delayMicroseconds(100); | |
+ | |
+ IOInit(gyro->busdev_u.spi.csnPin, OWNER_GYRO_CS, 0); | |
+ IOConfigGPIO(gyro->busdev_u.spi.csnPin, SPI_IO_CS_CFG); | |
+ IOHi(gyro->busdev_u.spi.csnPin); | |
+ | |
+ hardwareInitialised = true; | |
+ | |
+ for (int x=0; x<3; x++) | |
+ { | |
+ if (x) | |
+ { | |
+ initImuf9001(); | |
+ delay(200 * x); | |
+ } | |
+ | |
+ returnCheck = imuf9001Whoami(gyro); | |
+ if(returnCheck) | |
+ { | |
+ return returnCheck; | |
+ } | |
+ } | |
+ return 0; | |
+} | |
+ | |
+void imufSpiAccInit(accDev_t *acc) | |
+{ | |
+ acc->acc_1G = 512 * 4; | |
+} | |
+ | |
+static gyroToBoardCommMode_t VerifyAllowedCommMode(uint32_t commMode) | |
+{ | |
+ switch (commMode) | |
+ { | |
+ case GTBCM_SETUP: | |
+ case GTBCM_GYRO_ONLY_PASSTHRU: | |
+ case GTBCM_GYRO_ACC_PASSTHRU: | |
+ case GTBCM_GYRO_ONLY_FILTER_F: | |
+ case GTBCM_GYRO_ACC_FILTER_F: | |
+ case GTBCM_GYRO_ACC_QUAT_FILTER_F: | |
+ return (gyroToBoardCommMode_t)commMode; | |
+ break; | |
+ default: | |
+ return GTBCM_DEFAULT; | |
+ } | |
+} | |
+ | |
+uint16_t imufGyroAlignment(void) | |
+{ | |
+ if (isBoardAlignmentStandard(boardAlignment())) | |
+ { | |
+ if(gyroConfig()->gyro_align <= 1) | |
+ { | |
+ return 0; | |
+ } | |
+ else | |
+ { | |
+ return (uint16_t)(gyroConfig()->gyro_align - 1); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ return (uint16_t)IMU_CW0; | |
+ } | |
+} | |
+ | |
+void setupImufParams(imufCommand_t * data) | |
+{ | |
+ if (imufCurrentVersion < 107) { | |
+ //backwards compatibility for Caprica | |
+ data->param2 = ( (uint16_t)(gyroConfig()->imuf_rate+1) << 16 ); | |
+ data->param3 = ( (uint16_t)gyroConfig()->imuf_pitch_q << 16 ) | (uint16_t)constrain(gyroConfig()->imuf_w, 6, 10); | |
+ data->param4 = ( (uint16_t)gyroConfig()->imuf_roll_q << 16 ) | (uint16_t)constrain(gyroConfig()->imuf_w, 6, 10); | |
+ data->param5 = ( (uint16_t)gyroConfig()->imuf_yaw_q << 16 ) | (uint16_t)constrain(gyroConfig()->imuf_w, 6, 10); | |
+ data->param6 = ( (uint16_t)gyroConfig()->imuf_pitch_lpf_cutoff_hz << 16) | (uint16_t)gyroConfig()->imuf_roll_lpf_cutoff_hz; | |
+ data->param7 = ( (uint16_t)gyroConfig()->imuf_yaw_lpf_cutoff_hz << 16) | (uint16_t)0; | |
+ data->param8 = ( (int16_t)boardAlignment()->rollDegrees << 16 ) | imufGyroAlignment(); | |
+ data->param9 = ( (int16_t)boardAlignment()->yawDegrees << 16 ) | (int16_t)boardAlignment()->pitchDegrees; | |
+ } else { | |
+ //Odin contract. | |
+ data->param2 = ( (uint16_t)(gyroConfig()->imuf_rate+1) << 16) | (uint16_t)gyroConfig()->imuf_w; | |
+ data->param3 = ( (uint16_t)gyroConfig()->imuf_roll_q << 16) | (uint16_t)gyroConfig()->imuf_pitch_q; | |
+ data->param4 = ( (uint16_t)gyroConfig()->imuf_yaw_q << 16) | (uint16_t)gyroConfig()->imuf_roll_lpf_cutoff_hz; | |
+ data->param5 = ( (uint16_t)gyroConfig()->imuf_pitch_lpf_cutoff_hz << 16) | (uint16_t)gyroConfig()->imuf_yaw_lpf_cutoff_hz; | |
+ data->param6 = ( (uint32_t)((gyroConfig()->imuf_roll_af & 1) | | |
+ (gyroConfig()->imuf_pitch_af & 1) << 1 | | |
+ (gyroConfig()->imuf_yaw_af & 1) << 2 )); | |
+ data->param7 = ( (uint16_t)0 << 16) | (uint16_t)0; | |
+ data->param8 = ( (int16_t)boardAlignment()->rollDegrees << 16 ) | imufGyroAlignment(); | |
+ data->param9 = ( (int16_t)boardAlignment()->yawDegrees << 16 ) | (int16_t)boardAlignment()->pitchDegrees; | |
+ } | |
+} | |
+ | |
+void imufSpiGyroInit(gyroDev_t *gyro) | |
+{ | |
+ uint32_t attempt = 0; | |
+ imufCommand_t txData; | |
+ imufCommand_t rxData; | |
+ | |
+ rxData.param1 = VerifyAllowedCommMode(gyroConfig()->imuf_mode); | |
+ | |
+ setupImufParams(&rxData); | |
+ | |
+ for (attempt = 0; attempt < 10; attempt++) | |
+ { | |
+ if(attempt) | |
+ { | |
+ resetImuf9001(); | |
+ delay(300 * attempt); | |
+ } | |
+ | |
+ if (imuf9001SendReceiveCommand(&(gyro->bus), IMUF_COMMAND_SETUP, &txData, &rxData)) | |
+ { | |
+ //enable EXTI | |
+ mpuGyroInit(gyro); | |
+ return; | |
+ } | |
+ } | |
+ setArmingDisabled(ARMING_DISABLED_NO_GYRO); | |
+} | |
+ | |
+FAST_CODE bool imufReadAccData(accDev_t *acc) { | |
+ UNUSED(acc); | |
+ return true; | |
+} | |
+ | |
+bool imufSpiAccDetect(accDev_t *acc) | |
+{ | |
+ acc->initFn = imufSpiAccInit; | |
+ acc->readFn = imufReadAccData; | |
+ | |
+ return true; | |
+} | |
+ | |
+bool imufSpiGyroDetect(gyroDev_t *gyro) | |
+{ | |
+ // MPU6500 is used as a equivalent of other gyros by some flight controllers | |
+ switch (gyro->mpuDetectionResult.sensor) { | |
+ case IMUF_9001_SPI: | |
+ break; | |
+ default: | |
+ return false; | |
+ } | |
+ | |
+ gyro->initFn = imufSpiGyroInit; | |
+ gyro->scale = 1.0f; | |
+ return true; | |
+} | |
+ | |
+FAST_CODE void imufStartCalibration(void) | |
+{ | |
+ isImufCalibrating = IMUF_IS_CALIBRATING; //reset by EXTI | |
+} | |
+ | |
+FAST_CODE void imufEndCalibration(void) | |
+{ | |
+ isImufCalibrating = IMUF_NOT_CALIBRATING; //reset by EXTI | |
+} | |
+ | |
+#endif | |
diff --git a/src/main/drivers/accgyro/accgyro_imuf9001.h b/src/main/drivers/accgyro/accgyro_imuf9001.h | |
new file mode 100755 | |
index 000000000..4ae8ae079 | |
--- /dev/null | |
+++ b/src/main/drivers/accgyro/accgyro_imuf9001.h | |
@@ -0,0 +1,235 @@ | |
+/* | |
+ * 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 | |
+ | |
+#include "drivers/bus.h" | |
+ | |
+uint8_t imuf9001SpiDetect(const busDevice_t *bus); | |
+ | |
+bool imufSpiAccDetect(accDev_t *acc); | |
+bool imufSpiGyroDetect(gyroDev_t *gyro); | |
+ | |
+void imufSpiGyroInit(gyroDev_t *gyro); | |
+void imufSpiAccInit(accDev_t *acc); | |
+ | |
+void imufStartCalibration(void); | |
+void imufEndCalibration(void); | |
+ | |
+#ifndef IMUF_DEFAULT_PITCH_Q | |
+#define IMUF_DEFAULT_PITCH_Q 3000 | |
+#endif | |
+#ifndef IMUF_DEFAULT_ROLL_Q | |
+#define IMUF_DEFAULT_ROLL_Q 3000 | |
+#endif | |
+#ifndef IMUF_DEFAULT_YAW_Q | |
+#define IMUF_DEFAULT_YAW_Q 3000 | |
+#endif | |
+#ifndef IMUF_IMUF_W | |
+#define IMUF_IMUF_W 32 | |
+#endif | |
+#ifndef IMUF_DEFAULT_ROLL_AF | |
+#define IMUF_DEFAULT_ROLL_AF 0 | |
+#endif | |
+#ifndef IMUF_DEFAULT_PITCH_AF | |
+#define IMUF_DEFAULT_PITCH_AF 0 | |
+#endif | |
+#ifndef IMUF_DEFAULT_YAW_AF | |
+#define IMUF_DEFAULT_YAW_AF 0 | |
+#endif | |
+ | |
+ | |
+#define IMUF_FIRMWARE_MIN_VERSION 106 | |
+extern volatile uint16_t imufCurrentVersion; | |
+typedef struct imufVersion | |
+{ | |
+ uint32_t hardware; | |
+ uint32_t firmware; | |
+ uint32_t bootloader; | |
+ uint32_t uid1; | |
+ uint32_t uid2; | |
+ uint32_t uid3; | |
+} __attribute__((__packed__)) imufVersion_t; | |
+ | |
+typedef struct imufCommand { | |
+ uint32_t command; | |
+ uint32_t param1; | |
+ uint32_t param2; | |
+ uint32_t param3; | |
+ uint32_t param4; | |
+ uint32_t param5; | |
+ uint32_t param6; | |
+ uint32_t param7; | |
+ uint32_t param8; | |
+ uint32_t param9; | |
+ uint32_t param10; | |
+ uint32_t crc; | |
+ uint32_t tail; | |
+} __attribute__ ((__packed__)) imufCommand_t; | |
+ | |
+typedef struct imufData | |
+{ | |
+ float gyroX; | |
+ float gyroY; | |
+ float gyroZ; | |
+ float accX; | |
+ float accY; | |
+ float accZ; | |
+ float tempC; | |
+ float quaternionW; | |
+ float quaternionX; | |
+ float quaternionY; | |
+ float quaternionZ; | |
+ uint32_t crc; | |
+ uint32_t tail; | |
+} __attribute__((__packed__)) imufData_t; | |
+ | |
+typedef enum gyroCommands | |
+{ | |
+ BL_ERASE_ALL = 22, | |
+ BL_REPORT_INFO = 24, | |
+ BL_WRITE_FIRMWARES = 29, | |
+ BL_PREPARE_PROGRAM = 30, | |
+ BL_END_PROGRAM = 31, | |
+ BL_LISTENING = 32, | |
+ IMUF_COMMAND_NONE = 0, | |
+ IMUF_COMMAND_CALIBRATE = 99, | |
+ IMUF_COMMAND_LISTENING = 108, | |
+ IMUF_COMMAND_REPORT_INFO = 121, | |
+ IMUF_COMMAND_SETUP = 122, | |
+ IMUF_COMMAND_SETPOINT = 126, | |
+ IMUF_COMMAND_RESTART = 127 | |
+} gyroCommands_t; | |
+ | |
+typedef struct gyroFrame | |
+{ | |
+ float gyroX; | |
+ float gyroY; | |
+ float gyroZ; | |
+ float accelX; | |
+ float accelY; | |
+ float accelZ; | |
+ float temp; | |
+} __attribute__((__packed__)) gyroFrame_t; | |
+ | |
+typedef struct imuFrame | |
+{ | |
+ float w; | |
+ float x; | |
+ float y; | |
+ float z; | |
+} __attribute__((__packed__)) imuFrame_t; | |
+ | |
+typedef struct imuCommFrame | |
+{ | |
+ gyroFrame_t gyroFrame; | |
+ imuFrame_t imuFrame; | |
+ uint32_t tail; | |
+} __attribute__((__packed__)) imuCommFrame_t; | |
+ | |
+typedef enum imufLoopHz | |
+{ | |
+ IMUF_32000 = 0, | |
+ IMUF_16000 = 1, | |
+ IMUF_8000 = 2, | |
+ IMUF_4000 = 3, | |
+ IMUF_2000 = 4, | |
+ IMUF_1000 = 5, | |
+ IMUF_500 = 6, | |
+ IMUF_250 = 7, | |
+} imufLoopHz_t; | |
+ | |
+typedef enum imufOutput | |
+{ | |
+ IMUF_GYRO_OUTPUT = 1 << 0, | |
+ IMUF_TEMP_OUTPUT = 1 << 1, | |
+ IMUF_ACC_OUTPUT = 1 << 2, | |
+ IMUF_QUAT_OUTPUT = 1 << 3, | |
+} imufOutput_t; | |
+ | |
+typedef enum imufOreintation | |
+{ | |
+ IMU_CW0 = 0, | |
+ IMU_CW90 = 1, | |
+ IMU_CW180 = 2, | |
+ IMU_CW270 = 3, | |
+ IMU_CW0_INV = 4, | |
+ IMU_CW90_INV = 5, | |
+ IMU_CW180_INV = 6, | |
+ IMU_CW270_INV = 7, | |
+ IMU_CW45 = 8, | |
+ IMU_CW135 = 9, | |
+ IMU_CW225 = 10, | |
+ IMU_CW315 = 11, | |
+ IMU_CW45_INV = 12, | |
+ IMU_CW135_INV = 13, | |
+ IMU_CW225_INV = 14, | |
+ IMU_CW315_INV = 15, | |
+ IMU_CUSTOM = 16, | |
+} imufOrientation_t; | |
+ | |
+typedef struct imufMode | |
+{ | |
+ uint8_t command; //output Hz | |
+ uint8_t hz; //output Hz | |
+ uint8_t dataOut; //what data to send | |
+ uint8_t filterLevelX; //what filter level, 0% to 100% as a uint8_t | |
+ uint8_t filterLevelY; //what filter level, 0% to 100% as a uint8_t | |
+ uint8_t filterLevelZ; //what filter level, 0% to 100% as a uint8_t | |
+ uint8_t orientation; //what orienetation is the IMU? 0 gives raw output, if you want to use quats this must be set right | |
+ uint16_t rotationX; //custom orientation X, used when orientation is set to IMU_CUSTOM | |
+ uint16_t rotationY; //custom orientation Y, used when orientation is set to IMU_CUSTOM | |
+ uint16_t rotationZ; //custom orientation Z, used when orientation is set to IMU_CUSTOM | |
+ uint8_t param4; //future parameters | |
+ uint8_t param5; //future parameters | |
+ uint8_t param6; //future parameters | |
+ uint8_t param7; //future parameters | |
+ uint8_t param8; //future parameters | |
+} __attribute__((__packed__)) imufMode_t; | |
+ | |
+typedef enum gyroToBoardCommMode | |
+{ | |
+ GTBCM_SETUP = 53, //setup | |
+ GTBCM_GYRO_ONLY_PASSTHRU = 6, //no crc, gyro, 3*2 bytes | |
+ GTBCM_GYRO_ACC_PASSTHRU = 14, //no crc, acc, temp, gyro, 3*2, 1*2, 3*2 bytes | |
+ GTBCM_GYRO_ONLY_FILTER_F = 20, //gyro filtered, 3*4 bytes, 4 bytes crc | |
+ GTBCM_GYRO_ACC_FILTER_F = 32, //gyro filtered, acc filtered, temp, crc | |
+ GTBCM_GYRO_ACC_QUAT_FILTER_F = 48, //gyro filtered, acc filtered, temp, quaternions filtered, crc | |
+ GTBCM_DEFAULT = GTBCM_GYRO_ACC_QUAT_FILTER_F, //default mode | |
+} gyroToBoardCommMode_t; | |
+ | |
+typedef enum imufCalibrationSteps | |
+{ | |
+ IMUF_NOT_CALIBRATING = 0, | |
+ IMUF_IS_CALIBRATING = 1, | |
+ IMUF_DONE_CALIBRATING = 2 | |
+ | |
+} imufCalibrationSteps_t; | |
+ | |
+typedef enum gpioState | |
+{ | |
+ GPIO_LO = 0, | |
+ GPIO_HI = 1 | |
+} gpioState_t; | |
+ | |
+extern volatile imuFrame_t imufQuat; | |
+extern volatile uint32_t isImufCalibrating; | |
+ | |
+extern void initImuf9001(void); | |
+extern uint32_t getCrcImuf9001(uint32_t* data, uint32_t size); | |
+extern int imufUpdate(uint8_t *buff, uint32_t bin_length); | |
+extern int imufBootloader(void); | |
\ No newline at end of file | |
diff --git a/src/main/drivers/accgyro/accgyro_mpu.c b/src/main/drivers/accgyro/accgyro_mpu.c | |
index 5f0dfae6c..e3b608aa7 100644 | |
--- a/src/main/drivers/accgyro/accgyro_mpu.c | |
+++ b/src/main/drivers/accgyro/accgyro_mpu.c | |
@@ -42,6 +42,13 @@ | |
#include "drivers/system.h" | |
#include "drivers/time.h" | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+#include "drivers/dma_spi.h" | |
+#include "sensors/gyro.h" | |
+#include "sensors/acceleration.h" | |
+#endif //USE_DMA_SPI_DEVICE | |
+ | |
#include "drivers/accgyro/accgyro.h" | |
#include "drivers/accgyro/accgyro_mpu3050.h" | |
#include "drivers/accgyro/accgyro_mpu6050.h" | |
@@ -55,9 +62,22 @@ | |
#include "drivers/accgyro/accgyro_spi_l3gd20.h" | |
#include "drivers/accgyro/accgyro_mpu.h" | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+#include "rx/rx.h" | |
+#include "fc/rc.h" | |
+#include "fc/runtime_config.h" | |
+#endif //USE_GYRO_IMUF9001 | |
+ | |
#include "pg/pg.h" | |
#include "pg/gyrodev.h" | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ imufData_t imufData; | |
+#endif | |
+ | |
#ifndef MPU_ADDRESS | |
#define MPU_ADDRESS 0x68 | |
#endif | |
@@ -106,6 +126,11 @@ static void mpu6050FindRevision(gyroDev_t *gyro) | |
#ifdef USE_GYRO_EXTI | |
static void mpuIntExtiHandler(extiCallbackRec_t *cb) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ //start dma read | |
+ (void)(cb); | |
+ gyroDmaSpiStartRead(); | |
+#else // not HELIOSPRING | |
#ifdef DEBUG_MPU_DATA_READY_INTERRUPT | |
static uint32_t lastCalledAtUs = 0; | |
const uint32_t nowUs = micros(); | |
@@ -118,6 +143,7 @@ static void mpuIntExtiHandler(extiCallbackRec_t *cb) | |
const uint32_t now2Us = micros(); | |
debug[1] = (uint16_t)(now2Us - nowUs); | |
#endif | |
+#endif // USE_DMA_SPI_DEVICE // HELIOSPRING | |
} | |
static void mpuIntExtiInit(gyroDev_t *gyro) | |
@@ -134,8 +160,34 @@ static void mpuIntExtiInit(gyroDev_t *gyro) | |
return; | |
} | |
#endif | |
- | |
+ // original code | |
+ // IOInit(mpuIntIO, OWNER_GYRO_EXTI, 0); | |
+ // EXTIHandlerInit(&gyro->exti, mpuIntExtiHandler); | |
+ // EXTIConfig(mpuIntIO, &gyro->exti, NVIC_PRIO_MPU_INT_EXTI, IOCFG_IN_FLOATING, EXTI_TRIGGER_RISING); | |
+ // EXTIEnable(mpuIntIO, true); | |
+ | |
+ // robert's spaghetti | |
+// #if defined (STM32F7) | |
+// IOInit(mpuIntIO, OWNER_GYRO_EXTI, 0); | |
+// EXTIHandlerInit(&gyro->exti, mpuIntExtiHandler); | |
+// // EXTIConfig(mpuIntIO, &gyro->exti, NVIC_PRIO_MPU_INT_ | |
+// GPIO_MODE_INPUT,0,GPIO_NOPULL)); // TODO - maybe pull | |
+// EXTIConfig(mpuIntIO, &gyro->exti, NVIC_PRIO_MPU_INT_EX | |
+// EXTI_TRIGGER_RISING); | |
+// #else | |
+// IOInit(mpuIntIO, OWNER_GYRO_EXTI, 0); | |
+// IOConfigGPIO(mpuIntIO, IOCFG_IN_FLOATING); // TODO - | |
+// EXTIHandlerInit(&gyro->exti, mpuIntExtiHandler); | |
+// EXTIConfig(mpuIntIO, &gyro->exti, NVIC_PRIO_MPU_INT_EX | |
+// EXTI_TRIGGER_RISING); | |
+// #endif | |
+// EXTIEnable(mpuIntIO, true); | |
+ | |
+// Fixed logic based on robert's | |
IOInit(mpuIntIO, OWNER_GYRO_EXTI, 0); | |
+#if !defined (STM32F7) | |
+ IOConfigGPIO(mpuIntIO, IOCFG_IN_FLOATING); // TODO - maybe pullup / pulldown ? | |
+#endif | |
EXTIHandlerInit(&gyro->exti, mpuIntExtiHandler); | |
EXTIConfig(mpuIntIO, &gyro->exti, NVIC_PRIO_MPU_INT_EXTI, IOCFG_IN_FLOATING, EXTI_TRIGGER_RISING); | |
EXTIEnable(mpuIntIO, true); | |
@@ -174,6 +226,84 @@ bool mpuGyroRead(gyroDev_t *gyro) | |
return true; | |
} | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+FAST_CODE bool mpuGyroDmaSpiReadStart(gyroDev_t * gyro) | |
+{ | |
+ (void)(gyro); ///not used at this time | |
+ //no reason not to get acc and gyro data at the same time | |
+#ifdef USE_GYRO_IMUF9001 | |
+ if (isImufCalibrating == IMUF_IS_CALIBRATING) //calibrating | |
+ { | |
+ //two steps | |
+ //step 1 is isImufCalibrating=1, this starts the calibration command and sends it to the IMU-f | |
+ //step 2 is isImufCalibrating=2, this sets the tx buffer back to 0 so we don't keep sending the calibration command over and over | |
+ memset(dmaTxBuffer, 0, sizeof(imufCommand_t)); //clear buffer | |
+ //set calibration command with CRC, typecast the dmaTxBuffer as imufCommand_t | |
+ (*(imufCommand_t *)(dmaTxBuffer)).command = IMUF_COMMAND_CALIBRATE; | |
+ (*(imufCommand_t *)(dmaTxBuffer)).crc = getCrcImuf9001((uint32_t *)dmaTxBuffer, 11); //typecast the dmaTxBuffer as a uint32_t array which is what the crc command needs | |
+ //set isImufCalibrating to step 2, which is just used so the memset to 0 runs after the calibration commmand is sent | |
+ isImufCalibrating = IMUF_DONE_CALIBRATING; //go to step two | |
+ } | |
+ else if (isImufCalibrating == IMUF_DONE_CALIBRATING) | |
+ { | |
+ // step 2, memset of the tx buffer has run, set isImufCalibrating to 0. | |
+ (*(imufCommand_t *)(dmaTxBuffer)).command = 0; | |
+ (*(imufCommand_t *)(dmaTxBuffer)).crc = 0; //typecast the dmaTxBuffer as a uint32_t array which is what the crc command needs | |
+ imufEndCalibration(); | |
+ } | |
+ else | |
+ { | |
+ if (isSetpointNew) { | |
+ //send setpoint and arm status | |
+ (*(imufCommand_t *)(dmaTxBuffer)).command = IMUF_COMMAND_SETPOINT; | |
+ (*(imufCommand_t *)(dmaTxBuffer)).param1 = getSetpointRateInt(0); | |
+ (*(imufCommand_t *)(dmaTxBuffer)).param2 = getSetpointRateInt(1); | |
+ (*(imufCommand_t *)(dmaTxBuffer)).param3 = getSetpointRateInt(2); | |
+ (*(imufCommand_t *)(dmaTxBuffer)).crc = getCrcImuf9001((uint32_t *)dmaTxBuffer, 11); //typecast the dmaTxBuffer as a uint32_t array which is what the crc command needs | |
+ isSetpointNew = 0; | |
+ } | |
+ } | |
+ memset(dmaRxBuffer, 0, gyroConfig()->imuf_mode); //clear buffer | |
+ //send and receive data using SPI and DMA | |
+ dmaSpiTransmitReceive(dmaTxBuffer, dmaRxBuffer, gyroConfig()->imuf_mode, 0); | |
+#else | |
+ dmaTxBuffer[0] = MPU_RA_ACCEL_XOUT_H | 0x80; | |
+ dmaSpiTransmitReceive(dmaTxBuffer, dmaRxBuffer, 15, 0); | |
+#endif // USE_GYRO_IMUF9001 | |
+ return true; | |
+} | |
+FAST_CODE void mpuGyroDmaSpiReadFinish(gyroDev_t * gyro) | |
+{ | |
+ //spi rx dma callback | |
+#ifdef USE_GYRO_IMUF9001 | |
+ memcpy(&imufData, dmaRxBuffer, sizeof(imufData_t)); | |
+ acc.dev.ADCRaw[X] = (int16_t)(imufData.accX * acc.dev.acc_1G); | |
+ acc.dev.ADCRaw[Y] = (int16_t)(imufData.accY * acc.dev.acc_1G); | |
+ acc.dev.ADCRaw[Z] = (int16_t)(imufData.accZ * acc.dev.acc_1G); | |
+ gyro->gyroADC[X] = imufData.gyroX; | |
+ gyro->gyroADC[Y] = imufData.gyroY; | |
+ gyro->gyroADC[Z] = imufData.gyroZ; | |
+ gyro->gyroADCRaw[X] = (int16_t)(imufData.gyroX * 16.4f); | |
+ gyro->gyroADCRaw[Y] = (int16_t)(imufData.gyroY * 16.4f); | |
+ gyro->gyroADCRaw[Z] = (int16_t)(imufData.gyroZ * 16.4f); | |
+ if (gyroConfig()->imuf_mode == GTBCM_GYRO_ACC_QUAT_FILTER_F) { | |
+ imufQuat.w = imufData.quaternionW; | |
+ imufQuat.x = imufData.quaternionX; | |
+ imufQuat.y = imufData.quaternionY; | |
+ imufQuat.z = imufData.quaternionZ; | |
+ } | |
+#else | |
+ acc.dev.ADCRaw[X] = (int16_t)((dmaRxBuffer[1] << 8) | dmaRxBuffer[2]); | |
+ acc.dev.ADCRaw[Y] = (int16_t)((dmaRxBuffer[3] << 8) | dmaRxBuffer[4]); | |
+ acc.dev.ADCRaw[Z] = (int16_t)((dmaRxBuffer[5] << 8) | dmaRxBuffer[6]); | |
+ gyro->gyroADCRaw[X] = (int16_t)((dmaRxBuffer[9] << 8) | dmaRxBuffer[10]); | |
+ gyro->gyroADCRaw[Y] = (int16_t)((dmaRxBuffer[11] << 8) | dmaRxBuffer[12]); | |
+ gyro->gyroADCRaw[Z] = (int16_t)((dmaRxBuffer[13] << 8) | dmaRxBuffer[14]); | |
+#endif // USE_GYRO_IMUF9001 | |
+} | |
+#endif | |
+ | |
#ifdef USE_SPI_GYRO | |
bool mpuGyroReadSPI(gyroDev_t *gyro) | |
{ | |
@@ -201,6 +331,9 @@ static gyroSpiDetectFn_t gyroSpiDetectFnTable[] = { | |
#ifdef USE_GYRO_SPI_MPU6500 | |
mpu6500SpiDetect, // some targets using MPU_9250_SPI, ICM_20608_SPI or ICM_20602_SPI state sensor is MPU_65xx_SPI | |
#endif | |
+#ifdef USE_GYRO_IMUF9001 // HELIOSPRING | |
+ imuf9001SpiDetect, | |
+#endif | |
#ifdef USE_GYRO_SPI_MPU9250 | |
mpu9250SpiDetect, | |
#endif | |
@@ -280,7 +413,7 @@ bool mpuDetect(gyroDev_t *gyro, const gyroDeviceConfig_t *config) | |
gyro->bus.bustype = config->bustype; | |
} | |
-#ifdef USE_I2C_GYRO | |
+#ifdef USE_I2C_GYRO && !defined(USE_DMA_SPI_DEVICE) // HELIOSPRING (&& !def) | |
if (gyro->bus.bustype == BUSTYPE_I2C) { | |
gyro->bus.busdev_u.i2c.device = I2C_CFG_TO_DEV(config->i2cBus); | |
gyro->bus.busdev_u.i2c.address = config->i2cAddress ? config->i2cAddress : MPU_ADDRESS; | |
diff --git a/src/main/drivers/accgyro/accgyro_mpu.h b/src/main/drivers/accgyro/accgyro_mpu.h | |
index a90fa2f01..285ea8f67 100644 | |
--- a/src/main/drivers/accgyro/accgyro_mpu.h | |
+++ b/src/main/drivers/accgyro/accgyro_mpu.h | |
@@ -200,6 +200,7 @@ typedef enum { | |
ICM_20689_SPI, | |
BMI_160_SPI, | |
L3GD20_SPI, | |
+ IMUF_9001_SPI, // HELIOSPRING | |
} mpuSensor_e; | |
typedef enum { | |
@@ -224,3 +225,9 @@ uint8_t mpuGyroReadRegister(const busDevice_t *bus, uint8_t reg); | |
struct accDev_s; | |
bool mpuAccRead(struct accDev_s *acc); | |
+ | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+extern bool mpuGyroDmaSpiReadStart(struct gyroDev_s *gyro); | |
+extern void mpuGyroDmaSpiReadFinish(struct gyroDev_s *gyro); | |
+#endif | |
diff --git a/src/main/drivers/bus.c b/src/main/drivers/bus.c | |
index 45ec93683..b2b20e2a0 100644 | |
--- a/src/main/drivers/bus.c | |
+++ b/src/main/drivers/bus.c | |
@@ -29,6 +29,9 @@ | |
bool busWriteRegister(const busDevice_t *busdev, uint8_t reg, uint8_t data) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ return spiBusWriteRegister(busdev, reg & 0x7f, data); | |
+#else // not HELIOSPRING | |
#if !defined(USE_SPI) && !defined(USE_I2C) | |
UNUSED(reg); | |
UNUSED(data); | |
@@ -50,8 +53,10 @@ bool busWriteRegister(const busDevice_t *busdev, uint8_t reg, uint8_t data) | |
default: | |
return false; | |
} | |
+#endif // not HELIOSPRING | |
} | |
+ | |
bool busWriteRegisterStart(const busDevice_t *busdev, uint8_t reg, uint8_t data) | |
{ | |
#if !defined(USE_SPI) && !defined(USE_I2C) | |
@@ -157,6 +162,11 @@ bool busBusy(const busDevice_t *busdev, bool *error) | |
uint8_t busReadRegister(const busDevice_t *busdev, uint8_t reg) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ uint8_t data; | |
+ busReadRegisterBuffer(busdev, reg, &data, 1); | |
+ return data; | |
+#else // not HELIOSPRING | |
#if !defined(USE_SPI) && !defined(USE_I2C) | |
UNUSED(busdev); | |
UNUSED(reg); | |
@@ -166,4 +176,5 @@ uint8_t busReadRegister(const busDevice_t *busdev, uint8_t reg) | |
busReadRegisterBuffer(busdev, reg, &data, 1); | |
return data; | |
#endif | |
+#endif // HELIOSPRING | |
} | |
diff --git a/src/main/drivers/bus_spi.c b/src/main/drivers/bus_spi.c | |
index 5f869b37f..e3bd5093a 100644 | |
--- a/src/main/drivers/bus_spi.c | |
+++ b/src/main/drivers/bus_spi.c | |
@@ -33,6 +33,15 @@ | |
#include "drivers/io.h" | |
#include "drivers/rcc.h" | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+#ifndef GYRO_READ_TIMEOUT | |
+ #define GYRO_READ_TIMEOUT 20 | |
+#endif //GYRO_READ_TIMEOUT | |
+#include "drivers/dma_spi.h" | |
+#include "drivers/time.h" | |
+#endif //USE_DMA_SPI_DEVICE | |
+ | |
spiDevice_t spiDevice[SPIDEV_COUNT]; | |
SPIDevice spiDeviceByInstance(SPI_TypeDef *instance) | |
@@ -138,9 +147,37 @@ uint32_t spiTimeoutUserCallback(SPI_TypeDef *instance) | |
bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ if(USE_DMA_SPI_DEVICE == bus->busdev_u.spi.instance) | |
+ { | |
+ uint32_t timeoutCheck = millis(); | |
+ memcpy(dmaTxBuffer, (uint8_t *)txData, length); | |
+ dmaSpiTransmitReceive(dmaTxBuffer, dmaRxBuffer, length, 1); | |
+ while(dmaSpiReadStatus != DMA_SPI_READ_DONE) | |
+ { | |
+ if(millis() - timeoutCheck > GYRO_READ_TIMEOUT) | |
+ { | |
+ //GYRO_READ_TIMEOUT ms max, read failed, cleanup spi and return 0 | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ #ifndef STM32F7 | |
+ dmaSpicleanupspi(); | |
+ #endif //STM32F7 | |
+ return false; | |
+ } | |
+ } | |
+ memcpy((uint8_t *)rxData, dmaRxBuffer, length); | |
+ } | |
+ else | |
+ { | |
+ IOLo(bus->busdev_u.spi.csnPin); | |
+ spiTransfer(bus->busdev_u.spi.instance, txData, rxData, length); | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ } | |
+#else // not HELIOSPRING | |
IOLo(bus->busdev_u.spi.csnPin); | |
spiTransfer(bus->busdev_u.spi.instance, txData, rxData, length); | |
IOHi(bus->busdev_u.spi.csnPin); | |
+#endif // HELIOSPRING | |
return true; | |
} | |
@@ -185,21 +222,77 @@ bool spiBusRawTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *r | |
bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ if(USE_DMA_SPI_DEVICE == bus->busdev_u.spi.instance) | |
+ { | |
+ uint32_t timeoutCheck = millis(); | |
+ dmaTxBuffer[0] = reg; | |
+ dmaTxBuffer[1] = data; | |
+ dmaSpiTransmitReceive(dmaTxBuffer, dmaRxBuffer, 2, 1); | |
+ while(dmaSpiReadStatus != DMA_SPI_READ_DONE) | |
+ { | |
+ if(millis() - timeoutCheck > GYRO_READ_TIMEOUT) | |
+ { | |
+ //GYRO_READ_TIMEOUT ms max, read failed, cleanup spi and return 0 | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ #ifndef STM32F7 | |
+ dmaSpicleanupspi(); | |
+ #endif //STM32F7 | |
+ return false; | |
+ } | |
+ } | |
+ } | |
+ else | |
+ { | |
+ IOLo(bus->busdev_u.spi.csnPin); | |
+ spiTransferByte(bus->busdev_u.spi.instance, reg); | |
+ spiTransferByte(bus->busdev_u.spi.instance, data); | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ } | |
+#else // not HELIOSPRING | |
IOLo(bus->busdev_u.spi.csnPin); | |
spiTransferByte(bus->busdev_u.spi.instance, reg); | |
spiTransferByte(bus->busdev_u.spi.instance, data); | |
IOHi(bus->busdev_u.spi.csnPin); | |
- | |
+#endif // not HELIOSPRING | |
return true; | |
} | |
bool spiBusRawReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ if(USE_DMA_SPI_DEVICE == bus->busdev_u.spi.instance) | |
+ { | |
+ uint32_t timeoutCheck = millis(); | |
+ dmaTxBuffer[0] = reg | 0x80; | |
+ dmaSpiTransmitReceive(dmaTxBuffer, dmaRxBuffer, length+1, 1); | |
+ while(dmaSpiReadStatus != DMA_SPI_READ_DONE) | |
+ { | |
+ if(millis() - timeoutCheck > GYRO_READ_TIMEOUT) | |
+ { | |
+ //GYRO_READ_TIMEOUT ms max, read failed, cleanup spi and return 0 | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ #ifndef STM32F7 | |
+ dmaSpicleanupspi(); | |
+ #endif //STM32F7 | |
+ return false; | |
+ } | |
+ } | |
+ memcpy(data, dmaRxBuffer+1, length); | |
+ } | |
+ else | |
+ { | |
+ IOLo(bus->busdev_u.spi.csnPin); | |
+ spiTransferByte(bus->busdev_u.spi.instance, reg); | |
+ spiTransfer(bus->busdev_u.spi.instance, NULL, data, length); | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ } | |
+#else //not HELIOSPRING | |
IOLo(bus->busdev_u.spi.csnPin); | |
spiTransferByte(bus->busdev_u.spi.instance, reg); | |
spiTransfer(bus->busdev_u.spi.instance, NULL, data, length); | |
IOHi(bus->busdev_u.spi.csnPin); | |
- | |
+#endif // not HELIOSPRING | |
return true; | |
} | |
@@ -218,6 +311,36 @@ void spiBusWriteRegisterBuffer(const busDevice_t *bus, uint8_t reg, const uint8_ | |
uint8_t spiBusRawReadRegister(const busDevice_t *bus, uint8_t reg) | |
{ | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ if(USE_DMA_SPI_DEVICE == bus->busdev_u.spi.instance) | |
+ { | |
+ uint32_t timeoutCheck = millis(); | |
+ dmaTxBuffer[0] = reg | 0x80; | |
+ dmaSpiTransmitReceive(dmaTxBuffer, dmaRxBuffer, 2, 1); | |
+ while(dmaSpiReadStatus != DMA_SPI_READ_DONE) | |
+ { | |
+ if(millis() - timeoutCheck > GYRO_READ_TIMEOUT) | |
+ { | |
+ //GYRO_READ_TIMEOUT ms max, read failed, cleanup spi and return 0 | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ #ifndef STM32F7 | |
+ dmaSpicleanupspi(); | |
+ #endif //STM32F7 | |
+ return 0; | |
+ } | |
+ } | |
+ return dmaRxBuffer[1]; | |
+ } | |
+ else | |
+ { | |
+ uint8_t data; | |
+ IOLo(bus->busdev_u.spi.csnPin); | |
+ spiTransferByte(bus->busdev_u.spi.instance, reg); | |
+ spiTransfer(bus->busdev_u.spi.instance, NULL, &data, 1); | |
+ IOHi(bus->busdev_u.spi.csnPin); | |
+ return data; | |
+ } | |
+#else // not HELIOSPRING | |
uint8_t data; | |
IOLo(bus->busdev_u.spi.csnPin); | |
spiTransferByte(bus->busdev_u.spi.instance, reg); | |
@@ -225,6 +348,7 @@ uint8_t spiBusRawReadRegister(const busDevice_t *bus, uint8_t reg) | |
IOHi(bus->busdev_u.spi.csnPin); | |
return data; | |
+#endif // not HELIOSPRING | |
} | |
uint8_t spiBusReadRegister(const busDevice_t *bus, uint8_t reg) | |
diff --git a/src/main/drivers/dma_spi.c b/src/main/drivers/dma_spi.c | |
new file mode 100755 | |
index 000000000..d475840d5 | |
--- /dev/null | |
+++ b/src/main/drivers/dma_spi.c | |
@@ -0,0 +1,227 @@ | |
+#include <stdbool.h> | |
+#include <stdint.h> | |
+#include <string.h> | |
+ | |
+#include "platform.h" | |
+#include "dma_spi.h" | |
+#include "common/time.h" | |
+#include "sensors/gyro.h" | |
+#include "drivers/accgyro/accgyro.h" | |
+#include "drivers/accgyro/accgyro_mpu.h" | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+volatile uint32_t crcErrorCount = 0; | |
+#endif | |
+ | |
+ | |
+#ifdef USE_DMA_SPI_DEVICE | |
+ | |
+volatile bool dmaSpiDeviceDataReady = false; | |
+volatile dma_spi_read_status_t dmaSpiReadStatus = DMA_SPI_READ_UNKNOWN; | |
+ | |
+//must be static to avoid overflow/corruption by DMA | |
+uint8_t dmaTxBuffer[58]; | |
+uint8_t dmaRxBuffer[58]; | |
+ | |
+static inline void gpio_write_pin(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, uint32_t pinState) | |
+{ | |
+ if (pinState != 0) | |
+ { | |
+ GPIOx->BSRRL = (uint32_t)GPIO_Pin; | |
+ } | |
+ else | |
+ { | |
+ GPIOx->BSRRH = (uint32_t)GPIO_Pin; | |
+ } | |
+} | |
+ | |
+static inline void dmaSpiCsLo(void) | |
+{ | |
+ gpio_write_pin(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN, 0); | |
+} | |
+ | |
+static inline void dmaSpiCsHi(void) | |
+{ | |
+ gpio_write_pin(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN, 1); | |
+} | |
+ | |
+void dmaSpicleanupspi(void) | |
+{ | |
+ //clear DMA flags | |
+ DMA_ClearFlag(DMA_SPI_TX_DMA_STREAM, DMA_SPI_TX_DMA_FLAG_ALL); | |
+ DMA_ClearFlag(DMA_SPI_RX_DMA_STREAM, DMA_SPI_RX_DMA_FLAG_ALL); | |
+ | |
+ //disable DMAs | |
+ DMA_Cmd(DMA_SPI_TX_DMA_STREAM,DISABLE); | |
+ DMA_Cmd(DMA_SPI_RX_DMA_STREAM,DISABLE); | |
+ | |
+ //disable SPI DMA requests | |
+ SPI_I2S_DMACmd(DMA_SPI_SPI, SPI_I2S_DMAReq_Tx, DISABLE); | |
+ SPI_I2S_DMACmd(DMA_SPI_SPI, SPI_I2S_DMAReq_Rx, DISABLE); | |
+ | |
+ // Reset SPI (clears TXFIFO). | |
+ | |
+ //disable SPI | |
+ SPI_Cmd(DMA_SPI_SPI, DISABLE); | |
+} | |
+ | |
+void DMA_SPI_RX_DMA_HANDLER(void) | |
+{ | |
+ dmaSpiCsHi(); | |
+ dmaSpicleanupspi(); | |
+ | |
+ //spi rx dma callback | |
+ #ifdef USE_GYRO_IMUF9001 | |
+ volatile uint32_t crc1 = ( (*(uint32_t *)(dmaRxBuffer+gyroConfig()->imuf_mode-4)) & 0xFF ); | |
+ volatile uint32_t crc2 = ( getCrcImuf9001((uint32_t *)(dmaRxBuffer), (gyroConfig()->imuf_mode >> 2)-1) & 0xFF ); | |
+ if(crc1 == crc2) | |
+ { | |
+ if(dmaSpiReadStatus != DMA_SPI_BLOCKING_READ_IN_PROGRESS) | |
+ { | |
+ gyroDmaSpiFinishRead(); | |
+ } | |
+ dmaSpiDeviceDataReady = true; | |
+ } | |
+ else | |
+ { | |
+ if (crcErrorCount > 100000) | |
+ { | |
+ crcErrorCount = 0; | |
+ } | |
+ //error handler | |
+ crcErrorCount++; //check every so often and cause a failsafe is this number is above a certain amount | |
+ } | |
+ #else | |
+ if(dmaSpiReadStatus != DMA_SPI_BLOCKING_READ_IN_PROGRESS) | |
+ { | |
+ gyroDmaSpiFinishRead(); | |
+ } | |
+ dmaSpiDeviceDataReady = true; | |
+ #endif | |
+ DMA_ClearITPendingBit(DMA_SPI_RX_DMA_STREAM, DMA_SPI_RX_DMA_FLAG_TC); | |
+ dmaSpiReadStatus = DMA_SPI_READ_DONE; | |
+} | |
+ | |
+bool isDmaSpiDataReady(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs) | |
+{ | |
+ (void)(currentTimeUs); | |
+ (void)(currentDeltaTimeUs); | |
+ return dmaSpiDeviceDataReady; | |
+} | |
+ | |
+void dmaSpiInit(void) | |
+{ | |
+ GPIO_InitTypeDef gpioInitStruct; | |
+ SPI_InitTypeDef spiInitStruct; | |
+ DMA_InitTypeDef dmaInitStruct; | |
+ NVIC_InitTypeDef nvicInitStruct; | |
+ | |
+ //reset SPI periphreal | |
+ DMA_SPI_PER |= DMA_SPI_RST_MSK; | |
+ DMA_SPI_PER &= ~DMA_SPI_RST_MSK; | |
+ | |
+ //config pins | |
+ gpioInitStruct.GPIO_Pin = DMA_SPI_NSS_PIN; | |
+ gpioInitStruct.GPIO_Mode = GPIO_Mode_OUT; | |
+ gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz; | |
+ gpioInitStruct.GPIO_OType = GPIO_OType_PP; | |
+ gpioInitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; | |
+ GPIO_Init(DMA_SPI_NSS_PORT, &gpioInitStruct); | |
+ | |
+ //set default CS state (high) | |
+ GPIO_SetBits(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN); | |
+ | |
+ gpioInitStruct.GPIO_Mode = GPIO_Mode_AF; | |
+ gpioInitStruct.GPIO_Pin = DMA_SPI_SCK_PIN; | |
+ GPIO_Init(DMA_SPI_SCK_PORT, &gpioInitStruct); | |
+ | |
+ gpioInitStruct.GPIO_Pin = DMA_SPI_MISO_PIN; | |
+ GPIO_Init(DMA_SPI_MISO_PORT, &gpioInitStruct); | |
+ | |
+ gpioInitStruct.GPIO_Pin = DMA_SPI_MOSI_PIN; | |
+ GPIO_Init(DMA_SPI_MOSI_PORT, &gpioInitStruct); | |
+ | |
+ //set AF map | |
+ GPIO_PinAFConfig(DMA_SPI_SCK_PORT, DMA_SPI_SCK_PIN_SRC, DMA_SPI_SCK_AF); | |
+ GPIO_PinAFConfig(DMA_SPI_MISO_PORT, DMA_SPI_MISO_PIN_SRC, DMA_SPI_MISO_AF); | |
+ GPIO_PinAFConfig(DMA_SPI_MOSI_PORT, DMA_SPI_MOSI_PIN_SRC, DMA_SPI_MOSI_AF); | |
+ | |
+ //config SPI | |
+ SPI_StructInit(&spiInitStruct); | |
+ spiInitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; | |
+ spiInitStruct.SPI_Mode = SPI_Mode_Master; | |
+ spiInitStruct.SPI_DataSize = SPI_DataSize_8b; | |
+ spiInitStruct.SPI_CPOL = DMA_SPI_CPOL; | |
+ spiInitStruct.SPI_CPHA = DMA_SPI_CPHA; | |
+ spiInitStruct.SPI_NSS = SPI_NSS_Soft; | |
+ spiInitStruct.SPI_BaudRatePrescaler = DMA_SPI_BAUDRATE; | |
+ spiInitStruct.SPI_FirstBit = SPI_FirstBit_MSB; | |
+ SPI_Init(DMA_SPI_SPI, &spiInitStruct); | |
+ | |
+ //set DMA to default state | |
+ DMA_DeInit(DMA_SPI_TX_DMA_STREAM); | |
+ DMA_DeInit(DMA_SPI_RX_DMA_STREAM); | |
+ | |
+ DMA_StructInit(&dmaInitStruct); | |
+ dmaInitStruct.DMA_Channel = DMA_SPI_TX_DMA_CHANNEL; | |
+ dmaInitStruct.DMA_Mode = DMA_Mode_Normal; | |
+ dmaInitStruct.DMA_Priority = DMA_Priority_VeryHigh; | |
+ dmaInitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral; | |
+ | |
+ dmaInitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; | |
+ dmaInitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; | |
+ dmaInitStruct.DMA_PeripheralBaseAddr = (uint32_t)&DMA_SPI_SPI->DR; | |
+ | |
+ dmaInitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; | |
+ dmaInitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; | |
+ dmaInitStruct.DMA_Memory0BaseAddr = 0; //this is set later when we fire the DMA | |
+ | |
+ dmaInitStruct.DMA_BufferSize = 1; //this is set later when we fire the DMA, can't be 0 | |
+ | |
+ DMA_Init(DMA_SPI_TX_DMA_STREAM, &dmaInitStruct); | |
+ | |
+ dmaInitStruct.DMA_Channel = DMA_SPI_RX_DMA_CHANNEL; | |
+ dmaInitStruct.DMA_Priority = DMA_Priority_High; | |
+ dmaInitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory; | |
+ | |
+ DMA_Init(DMA_SPI_RX_DMA_STREAM, &dmaInitStruct); | |
+ | |
+ //setup interrupt | |
+ nvicInitStruct.NVIC_IRQChannel = DMA_SPI_RX_DMA_IRQn; | |
+ nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0; | |
+ nvicInitStruct.NVIC_IRQChannelSubPriority = 2; | |
+ nvicInitStruct.NVIC_IRQChannelCmd = ENABLE; | |
+ NVIC_Init(&nvicInitStruct); | |
+ DMA_ITConfig(DMA_SPI_RX_DMA_STREAM, DMA_IT_TC, ENABLE); | |
+} | |
+ | |
+void dmaSpiTransmitReceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint32_t size, uint32_t blockingRead) | |
+{ | |
+ //set buffer size | |
+ DMA_SetCurrDataCounter(DMA_SPI_TX_DMA_STREAM, size); | |
+ DMA_SetCurrDataCounter(DMA_SPI_RX_DMA_STREAM, size); | |
+ | |
+ //set buffer | |
+ DMA_SPI_TX_DMA_STREAM->M0AR = (uint32_t)txBuffer; | |
+ DMA_SPI_RX_DMA_STREAM->M0AR = (uint32_t)rxBuffer; | |
+ | |
+ //enable DMA SPI streams | |
+ DMA_Cmd(DMA_SPI_TX_DMA_STREAM, ENABLE); | |
+ DMA_Cmd(DMA_SPI_RX_DMA_STREAM, ENABLE); | |
+ | |
+ //enable CS | |
+ dmaSpiCsLo(); | |
+ | |
+ //enable DMA SPI requests | |
+ SPI_I2S_DMACmd(DMA_SPI_SPI, SPI_I2S_DMAReq_Tx, ENABLE); | |
+ SPI_I2S_DMACmd(DMA_SPI_SPI, SPI_I2S_DMAReq_Rx, ENABLE); | |
+ | |
+ //enable and send | |
+ SPI_Cmd(DMA_SPI_SPI, ENABLE); | |
+ | |
+ if(!blockingRead) | |
+ dmaSpiReadStatus = DMA_SPI_READ_IN_PROGRESS; | |
+ else | |
+ dmaSpiReadStatus = DMA_SPI_BLOCKING_READ_IN_PROGRESS; | |
+} | |
+#endif | |
diff --git a/src/main/drivers/dma_spi.h b/src/main/drivers/dma_spi.h | |
new file mode 100755 | |
index 000000000..ea73a365b | |
--- /dev/null | |
+++ b/src/main/drivers/dma_spi.h | |
@@ -0,0 +1,24 @@ | |
+#pragma once | |
+ | |
+#include "common/time.h" | |
+ | |
+#ifdef USE_DMA_SPI_DEVICE | |
+ | |
+typedef enum dma_spi_read_status_e { | |
+ DMA_SPI_READ_UNKNOWN = 0, | |
+ DMA_SPI_READ_IN_PROGRESS = 1, | |
+ DMA_SPI_READ_DONE = 2, | |
+ DMA_SPI_BLOCKING_READ_IN_PROGRESS = 3, | |
+} dma_spi_read_status_t; | |
+ | |
+extern volatile uint32_t crcErrorCount; | |
+extern volatile dma_spi_read_status_t dmaSpiReadStatus; | |
+extern volatile bool dmaSpiDeviceDataReady; | |
+extern uint8_t dmaTxBuffer[58]; | |
+extern uint8_t dmaRxBuffer[58]; | |
+extern bool isDmaSpiDataReady(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs); | |
+extern void dmaSpicleanupspi(void); | |
+extern void dmaSpiInit(void); | |
+extern void dmaSpiTransmitReceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint32_t size, uint32_t blockingRead); | |
+ | |
+#endif | |
\ No newline at end of file | |
diff --git a/src/main/drivers/dma_spi_hal.c b/src/main/drivers/dma_spi_hal.c | |
new file mode 100755 | |
index 000000000..6960b7b57 | |
--- /dev/null | |
+++ b/src/main/drivers/dma_spi_hal.c | |
@@ -0,0 +1,226 @@ | |
+ | |
+ | |
+#include <stdbool.h> | |
+#include <stdint.h> | |
+#include <string.h> | |
+ | |
+#include "platform.h" | |
+#include "dma_spi.h" | |
+#include "common/time.h" | |
+#include "sensors/gyro.h" | |
+#include "drivers/accgyro/accgyro.h" | |
+#include "drivers/accgyro/accgyro_mpu.h" | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+FAST_RAM_ZERO_INIT volatile uint32_t crcErrorCount; | |
+#endif | |
+ | |
+#ifdef USE_DMA_SPI_DEVICE | |
+ | |
+FAST_RAM_ZERO_INIT SPI_HandleTypeDef dmaSpiHandle; | |
+FAST_RAM_ZERO_INIT DMA_HandleTypeDef SpiRxDmaHandle; | |
+FAST_RAM_ZERO_INIT DMA_HandleTypeDef SpiTxDmaHandle; | |
+FAST_RAM_ZERO_INIT volatile dma_spi_read_status_t dmaSpiReadStatus; | |
+FAST_RAM_ZERO_INIT volatile bool dmaSpiDeviceDataReady = false; | |
+FAST_RAM_ZERO_INIT uint8_t dmaTxBuffer[58]; | |
+FAST_RAM_ZERO_INIT uint8_t dmaRxBuffer[58]; | |
+ | |
+ | |
+FAST_CODE static inline void dmaSpiCsLo(void) | |
+{ | |
+ HAL_GPIO_WritePin(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN, 0); | |
+} | |
+ | |
+FAST_CODE static inline void dmaSpiCsHi(void) | |
+{ | |
+ HAL_GPIO_WritePin(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN, 1); | |
+} | |
+ | |
+ | |
+// FAST_CODE void dmaSpicleanupspi(void) | |
+// { | |
+// } | |
+ | |
+FAST_CODE_NOINLINE void DMA_SPI_TX_DMA_HANDLER(void) | |
+{ | |
+ HAL_NVIC_ClearPendingIRQ(DMA_SPI_TX_DMA_IRQn); | |
+ HAL_DMA_IRQHandler(&SpiTxDmaHandle); | |
+} | |
+ | |
+FAST_CODE_NOINLINE void DMA_SPI_RX_DMA_HANDLER(void) | |
+{ | |
+ HAL_NVIC_ClearPendingIRQ(DMA_SPI_RX_DMA_IRQn); | |
+ HAL_DMA_IRQHandler(&SpiRxDmaHandle); | |
+ | |
+ if (HAL_DMA_GetState(&SpiRxDmaHandle) == HAL_DMA_STATE_READY) | |
+ { | |
+ dmaSpiCsHi(); | |
+ //spi rx dma callback | |
+ #ifdef USE_GYRO_IMUF9001 | |
+ volatile uint32_t crc1 = ( (*(uint32_t *)(dmaRxBuffer+gyroConfig()->imuf_mode-4)) & 0xFF ); | |
+ volatile uint32_t crc2 = ( getCrcImuf9001((uint32_t *)(dmaRxBuffer), (gyroConfig()->imuf_mode >> 2)-1) & 0xFF ); | |
+ if(crc1 == crc2) | |
+ { | |
+ if(dmaSpiReadStatus != DMA_SPI_BLOCKING_READ_IN_PROGRESS) | |
+ { | |
+ gyroDmaSpiFinishRead(); | |
+ } | |
+ dmaSpiDeviceDataReady = true; | |
+ } | |
+ else | |
+ { | |
+ if (crcErrorCount > 100000) | |
+ { | |
+ crcErrorCount = 0; | |
+ } | |
+ //error handler | |
+ crcErrorCount++; //check every so often and cause a failsafe is this number is above a certain ammount | |
+ } | |
+ #else | |
+ if(dmaSpiReadStatus != DMA_SPI_BLOCKING_READ_IN_PROGRESS) | |
+ { | |
+ gyroDmaSpiFinishRead(); | |
+ } | |
+ dmaSpiDeviceDataReady = true; | |
+ #endif | |
+ } | |
+ | |
+ dmaSpiCsHi(); | |
+ // dmaSpicleanupspi(); | |
+ | |
+ dmaSpiReadStatus = DMA_SPI_READ_DONE; | |
+} | |
+ | |
+FAST_CODE inline bool isDmaSpiDataReady(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs) | |
+{ | |
+ (void)(currentTimeUs); | |
+ (void)(currentDeltaTimeUs); | |
+ return dmaSpiDeviceDataReady; | |
+} | |
+ | |
+void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) | |
+{ | |
+ GPIO_InitTypeDef GPIO_InitStruct; | |
+ | |
+ DMA_SPI_CLOCK_INIT_FUNC; | |
+ | |
+ HAL_GPIO_WritePin(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN, 1); | |
+ HAL_GPIO_DeInit(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN); | |
+ GPIO_InitStruct.Pin = DMA_SPI_NSS_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; | |
+ GPIO_InitStruct.Pull = GPIO_NOPULL; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
+ HAL_GPIO_Init(DMA_SPI_NSS_PORT, &GPIO_InitStruct); | |
+ HAL_GPIO_WritePin(DMA_SPI_NSS_PORT, DMA_SPI_NSS_PIN, 1); | |
+ | |
+ HAL_GPIO_DeInit(DMA_SPI_SCK_PORT, DMA_SPI_SCK_PIN); | |
+ HAL_GPIO_DeInit(DMA_SPI_MISO_PORT, DMA_SPI_MISO_PIN); | |
+ HAL_GPIO_DeInit(DMA_SPI_MOSI_PORT, DMA_SPI_MOSI_PIN); | |
+ | |
+ GPIO_InitStruct.Pin = DMA_SPI_SCK_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | |
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
+ GPIO_InitStruct.Alternate = DMA_SPI_SCK_AF; | |
+ HAL_GPIO_Init(DMA_SPI_SCK_PORT, &GPIO_InitStruct); | |
+ | |
+ GPIO_InitStruct.Pin = DMA_SPI_MISO_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | |
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
+ GPIO_InitStruct.Alternate = DMA_SPI_MISO_AF; | |
+ HAL_GPIO_Init(DMA_SPI_MISO_PORT, &GPIO_InitStruct); | |
+ | |
+ GPIO_InitStruct.Pin = DMA_SPI_MOSI_PIN; | |
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | |
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN; | |
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
+ GPIO_InitStruct.Alternate = DMA_SPI_MOSI_AF; | |
+ HAL_GPIO_Init(DMA_SPI_MOSI_PORT, &GPIO_InitStruct); | |
+ | |
+ | |
+ SpiRxDmaHandle.Instance = DMA_SPI_RX_DMA_STREAM; | |
+ SpiRxDmaHandle.Init.Channel = DMA_SPI_RX_DMA_CHANNEL; | |
+ SpiRxDmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; | |
+ SpiRxDmaHandle.Init.PeriphInc = DMA_PINC_DISABLE; | |
+ SpiRxDmaHandle.Init.MemInc = DMA_MINC_ENABLE; | |
+ SpiRxDmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; | |
+ SpiRxDmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | |
+ SpiRxDmaHandle.Init.Mode = DMA_NORMAL; | |
+ SpiRxDmaHandle.Init.Priority = DMA_PRIORITY_HIGH; | |
+ SpiRxDmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; | |
+ | |
+ HAL_DMA_UnRegisterCallback(&SpiRxDmaHandle, HAL_DMA_XFER_ALL_CB_ID); | |
+ | |
+ HAL_DMA_Init(&SpiRxDmaHandle); | |
+ | |
+ __HAL_LINKDMA(hspi, hdmarx, SpiRxDmaHandle); | |
+ | |
+ HAL_NVIC_SetPriority(DMA_SPI_RX_DMA_IRQn, DMA_SPI_DMA_RX_PRE_PRI, DMA_SPI_DMA_RX_SUB_PRI); | |
+ HAL_NVIC_EnableIRQ(DMA_SPI_RX_DMA_IRQn); | |
+ | |
+ SpiTxDmaHandle.Instance = DMA_SPI_TX_DMA_STREAM; | |
+ SpiTxDmaHandle.Init.Channel = DMA_SPI_TX_DMA_CHANNEL; | |
+ SpiTxDmaHandle.Init.Direction = DMA_MEMORY_TO_PERIPH; | |
+ SpiTxDmaHandle.Init.PeriphInc = DMA_PINC_DISABLE; | |
+ SpiTxDmaHandle.Init.MemInc = DMA_MINC_ENABLE; | |
+ SpiTxDmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; | |
+ SpiTxDmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | |
+ SpiTxDmaHandle.Init.Mode = DMA_NORMAL; | |
+ SpiTxDmaHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH; | |
+ SpiTxDmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; | |
+ | |
+ HAL_DMA_UnRegisterCallback(&SpiTxDmaHandle, HAL_DMA_XFER_ALL_CB_ID); | |
+ | |
+ HAL_DMA_Init(&SpiTxDmaHandle); | |
+ | |
+ __HAL_LINKDMA(hspi, hdmatx, SpiTxDmaHandle); | |
+ | |
+ HAL_NVIC_SetPriority(DMA_SPI_TX_DMA_IRQn, DMA_SPI_DMA_TX_PRE_PRI, DMA_SPI_DMA_TX_SUB_PRI); | |
+ HAL_NVIC_EnableIRQ(DMA_SPI_TX_DMA_IRQn); | |
+ | |
+} | |
+ | |
+void dmaSpiInit(void) | |
+{ | |
+ dmaSpiHandle.Instance = DMA_SPI_SPI; | |
+ HAL_SPI_DeInit(&dmaSpiHandle); | |
+ | |
+ dmaSpiHandle.Init.Mode = SPI_MODE_MASTER; | |
+ dmaSpiHandle.Init.Direction = SPI_DIRECTION_2LINES; | |
+ dmaSpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; | |
+ dmaSpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; | |
+ dmaSpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; | |
+ dmaSpiHandle.Init.NSS = SPI_NSS_SOFT; | |
+ dmaSpiHandle.Init.BaudRatePrescaler = DMA_SPI_BAUDRATE; | |
+ dmaSpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; | |
+ dmaSpiHandle.Init.TIMode = SPI_TIMODE_DISABLE; | |
+ dmaSpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; | |
+ dmaSpiHandle.Init.CRCPolynomial = 7; | |
+ | |
+ HAL_SPI_Init(&dmaSpiHandle); | |
+ | |
+} | |
+ | |
+FAST_CODE_NOINLINE void dmaSpiTransmitReceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint32_t size, uint32_t blockingRead) | |
+{ | |
+ | |
+ if (HAL_SPI_GetState(&dmaSpiHandle) == HAL_SPI_STATE_READY) | |
+ { | |
+ dmaSpiCsLo(); | |
+ if(!blockingRead) | |
+ { | |
+ dmaSpiReadStatus = DMA_SPI_READ_IN_PROGRESS; | |
+ HAL_SPI_TransmitReceive_DMA(&dmaSpiHandle, txBuffer, rxBuffer, size); | |
+ } | |
+ else | |
+ { | |
+ dmaSpiReadStatus = DMA_SPI_BLOCKING_READ_IN_PROGRESS; | |
+ HAL_SPI_TransmitReceive(&dmaSpiHandle, txBuffer, rxBuffer, size, 40); | |
+ dmaSpiCsHi(); | |
+ dmaSpiReadStatus = DMA_SPI_READ_DONE; | |
+ } | |
+ } | |
+} | |
+ | |
+#endif // USE_HAL_DMA_SPI_DEVICE | |
diff --git a/src/main/drivers/dma_spi_hal.h b/src/main/drivers/dma_spi_hal.h | |
new file mode 100755 | |
index 000000000..81b90be35 | |
--- /dev/null | |
+++ b/src/main/drivers/dma_spi_hal.h | |
@@ -0,0 +1,24 @@ | |
+#pragma once | |
+ | |
+#include "common/time.h" | |
+ | |
+#ifdef USE_DMA_SPI_DEVICE | |
+ | |
+typedef enum dma_spi_read_status_e { | |
+ DMA_SPI_READ_UNKNOWN = 0, | |
+ DMA_SPI_READ_IN_PROGRESS = 1, | |
+ DMA_SPI_READ_DONE = 2, | |
+ DMA_SPI_BLOCKING_READ_IN_PROGRESS = 3, | |
+} dma_spi_read_status_t; | |
+ | |
+extern volatile uint32_t crcErrorCount; | |
+extern volatile dma_spi_read_status_t dmaSpiReadStatus; | |
+extern volatile bool dmaSpiDeviceDataReady; | |
+extern uint8_t dmaTxBuffer[58]; | |
+extern uint8_t dmaRxBuffer[58]; | |
+extern bool isDmaSpiDataReady(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs); | |
+// extern void dmaSpicleanupspi(void); | |
+extern void dmaSpiInit(void); | |
+extern void dmaSpiTransmitReceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint32_t size, uint32_t blockingRead); | |
+ | |
+#endif | |
\ No newline at end of file | |
diff --git a/src/main/drivers/dma_stm32f4xx.c b/src/main/drivers/dma_stm32f4xx.c | |
index 25359bc37..a62b5a6f7 100644 | |
--- a/src/main/drivers/dma_stm32f4xx.c | |
+++ b/src/main/drivers/dma_stm32f4xx.c | |
@@ -66,7 +66,9 @@ DEFINE_DMA_IRQ_HANDLER(1, 6, DMA1_ST6_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(1, 7, DMA1_ST7_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 0, DMA2_ST0_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 1, DMA2_ST1_HANDLER) | |
+#ifndef USE_DMA_SPI_DEVICE // modded for HELIOSPRING | |
DEFINE_DMA_IRQ_HANDLER(2, 2, DMA2_ST2_HANDLER) | |
+#endif | |
DEFINE_DMA_IRQ_HANDLER(2, 3, DMA2_ST3_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 4, DMA2_ST4_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 5, DMA2_ST5_HANDLER) | |
diff --git a/src/main/drivers/dma_stm32f7xx.c b/src/main/drivers/dma_stm32f7xx.c | |
index 38a0b653d..22f435201 100644 | |
--- a/src/main/drivers/dma_stm32f7xx.c | |
+++ b/src/main/drivers/dma_stm32f7xx.c | |
@@ -67,8 +67,10 @@ DEFINE_DMA_IRQ_HANDLER(1, 6, DMA1_ST6_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(1, 7, DMA1_ST7_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 0, DMA2_ST0_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 1, DMA2_ST1_HANDLER) | |
+#ifndef USE_DMA_SPI_DEVICE // modded for HELIOSPRING | |
DEFINE_DMA_IRQ_HANDLER(2, 2, DMA2_ST2_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 3, DMA2_ST3_HANDLER) | |
+#endif | |
DEFINE_DMA_IRQ_HANDLER(2, 4, DMA2_ST4_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 5, DMA2_ST5_HANDLER) | |
DEFINE_DMA_IRQ_HANDLER(2, 6, DMA2_ST6_HANDLER) | |
diff --git a/src/main/fc/config.c b/src/main/fc/config.c | |
index 73e47962d..08712b451 100644 | |
--- a/src/main/fc/config.c | |
+++ b/src/main/fc/config.c | |
@@ -82,6 +82,11 @@ | |
#include "common/sensor_alignment.h" | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+#endif | |
+ | |
static bool configIsDirty; /* someone indicated that the config is modified and it is not yet saved */ | |
static bool rebootRequired = false; // set if a config change requires a reboot to take effect | |
@@ -179,6 +184,33 @@ static void adjustFilterLimit(uint16_t *parm, uint16_t resetValue) | |
} | |
} | |
+// HELIOPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+int getImufRateFromGyroSyncDenom(int gyroSyncDenom){ | |
+ switch (gyroSyncDenom) { | |
+ case 1: | |
+ return IMUF_RATE_32K; | |
+ break; | |
+ case 2: | |
+ default: | |
+ return IMUF_RATE_16K; | |
+ break; | |
+ case 4: | |
+ return IMUF_RATE_8K; | |
+ break; | |
+ case 8: | |
+ return IMUF_RATE_4K; | |
+ break; | |
+ case 16: | |
+ return IMUF_RATE_2K; | |
+ break; | |
+ case 32: | |
+ return IMUF_RATE_1K; | |
+ break; | |
+ } | |
+} | |
+#endif | |
+ | |
static void validateAndFixConfig(void) | |
{ | |
#if !defined(USE_QUAD_MIXER_ONLY) | |
@@ -558,6 +590,18 @@ void validateAndFixGyroConfig(void) | |
} | |
#endif | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ //keeop imuf_rate in sync with the gyro. | |
+ uint8_t imuf_rate = getImufRateFromGyroSyncDenom(gyroConfigMutable()->gyro_sync_denom); | |
+ gyroConfigMutable()->imuf_rate = imuf_rate; | |
+ if (imuf_rate == IMUF_RATE_32K) { | |
+ gyroConfigMutable()->imuf_mode = GTBCM_GYRO_ACC_FILTER_F; | |
+ } else { | |
+ gyroConfigMutable()->imuf_mode = GTBCM_DEFAULT; | |
+ } | |
+#endif | |
+ | |
// Fix gyro filter settings to handle cases where an older configurator was used that | |
// allowed higher cutoff limits from previous firmware versions. | |
adjustFilterLimit(&gyroConfigMutable()->gyro_lowpass_hz, FILTER_FREQUENCY_MAX); | |
diff --git a/src/main/fc/init.c b/src/main/fc/init.c | |
index 42888336d..fb1c50bfb 100644 | |
--- a/src/main/fc/init.c | |
+++ b/src/main/fc/init.c | |
@@ -67,6 +67,7 @@ | |
#include "drivers/serial.h" | |
#include "drivers/serial_softserial.h" | |
#include "drivers/serial_uart.h" | |
+#include "drivers/serial_usb_vcp.h" // HELIOSPRING | |
#include "drivers/sdcard.h" | |
#include "drivers/sdio.h" | |
#include "drivers/sound_beeper.h" | |
@@ -82,6 +83,14 @@ | |
#include "drivers/vtx_rtc6705.h" | |
#include "drivers/vtx_table.h" | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+#include "drivers/dma_spi.h" | |
+#endif //USE_DMA_SPI_DEVICE | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+#endif //USE_GYRO_IMUF9001 | |
+ | |
#include "fc/board_info.h" | |
#include "fc/config.h" | |
#include "fc/dispatch.h" | |
@@ -223,6 +232,9 @@ static void configureSPIAndQuadSPI(void) | |
#ifdef USE_SPI_DEVICE_1 | |
spiInit(SPIDEV_1); | |
#endif | |
+#ifdef USE_DMA_SPI_DEVICE // HELIOSPRING | |
+ dmaSpiInit(); | |
+#endif | |
#ifdef USE_SPI_DEVICE_2 | |
spiInit(SPIDEV_2); | |
#endif | |
@@ -264,6 +276,14 @@ void init(void) | |
systemInit(); | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ if (isMPUSoftReset()) { | |
+ // reset imuf before befhal mucks with the pins | |
+ initImuf9001(); | |
+ } | |
+#endif | |
+ | |
// initialize IO (needed for all IO operations) | |
IOInitGlobal(); | |
@@ -486,6 +506,23 @@ void init(void) | |
#endif | |
#ifdef USE_OVERCLOCK | |
+// HELIOSPRING | |
+#if defined(STM32F3) && defined(USE_VCP) | |
+ if (systemConfig()->cpu_overclock > OVERCLOCK_128MHZ) { | |
+ usbVcpOpen(); | |
+ uint32_t us = micros(); | |
+ bool usbConnected = false; | |
+ while(cmpTimeUs(micros(), us) < 1500000 && !usbConnected) { | |
+ usbConnected = usbVcpIsConnected() != 0; | |
+ } | |
+ | |
+ /* void indicate(uint8_t count, uint16_t duration); */ | |
+ /* indicate((RCC->CFGR & (0xf << 18)) >> 18, 500); */ | |
+ if (!usbConnected) { | |
+ OverclockRebootIfNecessary(systemConfig()->cpu_overclock); | |
+ } | |
+ } else | |
+#endif | |
OverclockRebootIfNecessary(systemConfig()->cpu_overclock); | |
#endif | |
diff --git a/src/main/fc/rc.c b/src/main/fc/rc.c | |
index 869458698..1affbeaf9 100644 | |
--- a/src/main/fc/rc.c | |
+++ b/src/main/fc/rc.c | |
@@ -20,6 +20,7 @@ | |
#include <stdbool.h> | |
#include <stdint.h> | |
+#include <string.h> // HELIOSPRING | |
#include <math.h> | |
#include "platform.h" | |
@@ -62,6 +63,7 @@ static float oldRcCommand[XYZ_AXIS_COUNT]; | |
static bool isDuplicateFrame; | |
#endif | |
static float setpointRate[3], rcDeflection[3], rcDeflectionAbs[3]; | |
+static volatile uint32_t setpointRateInt[3]; // HELIOSPRING | |
static float throttlePIDAttenuation; | |
static bool reverseMotors = false; | |
static applyRatesFn *applyRates; | |
@@ -70,6 +72,11 @@ uint16_t currentRxRefreshRate; | |
FAST_RAM_ZERO_INIT uint8_t interpolationChannels; | |
static FAST_RAM_ZERO_INIT uint32_t rcFrameNumber; | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ volatile bool isSetpointNew; | |
+#endif | |
+ | |
enum { | |
ROLL_FLAG = 1 << ROLL, | |
PITCH_FLAG = 1 << PITCH, | |
@@ -101,6 +108,12 @@ float getSetpointRate(int axis) | |
return setpointRate[axis]; | |
} | |
+// HELIOSPRING | |
+uint32_t getSetpointRateInt(int axis) | |
+{ | |
+ return setpointRateInt[axis]; | |
+} | |
+ | |
float getRcDeflection(int axis) | |
{ | |
return rcDeflection[axis]; | |
@@ -228,6 +241,8 @@ static void calculateSetpointRate(int axis) | |
// Rate limit from profile (deg/sec) | |
setpointRate[axis] = constrainf(angleRate, -1.0f * currentControlRateProfile->rate_limit[axis], 1.0f * currentControlRateProfile->rate_limit[axis]); | |
+ memcpy((uint32_t*)&setpointRateInt[axis], (uint32_t*)&setpointRate[axis], sizeof(float)); // HELIOSPRING | |
+ | |
DEBUG_SET(DEBUG_ANGLERATE, axis, angleRate); | |
} | |
@@ -652,6 +667,11 @@ FAST_CODE void processRcCommand(void) | |
calculateSetpointRate(axis); | |
} | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ isSetpointNew = 1; | |
+#endif | |
+ | |
DEBUG_SET(DEBUG_RC_INTERPOLATION, 3, setpointRate[0]); | |
// Scaling of AngleRate to camera angle (Mixing Roll and Yaw) | |
diff --git a/src/main/fc/rc.h b/src/main/fc/rc.h | |
index d28f5d31a..5a3c3a8e9 100644 | |
--- a/src/main/fc/rc.h | |
+++ b/src/main/fc/rc.h | |
@@ -30,10 +30,16 @@ typedef enum { | |
INTERPOLATION_CHANNELS_RPT, | |
} interpolationChannels_e; | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+extern volatile bool isSetpointNew; | |
+#endif | |
+ | |
extern uint16_t currentRxRefreshRate; | |
void processRcCommand(void); | |
float getSetpointRate(int axis); | |
+uint32_t getSetpointRateInt(int axis); // HELIOSPRING | |
float getRcDeflection(int axis); | |
float getRcDeflectionAbs(int axis); | |
float getThrottlePIDAttenuation(void); | |
diff --git a/src/main/fc/tasks.c b/src/main/fc/tasks.c | |
index a1ed90677..f0e7938e3 100644 | |
--- a/src/main/fc/tasks.c | |
+++ b/src/main/fc/tasks.c | |
@@ -391,8 +391,13 @@ cfTask_t cfTasks[TASK_COUNT] = { | |
[TASK_GYROPID] = DEFINE_TASK("PID", "GYRO", NULL, taskMainPidLoop, TASK_GYROPID_DESIRED_PERIOD, TASK_PRIORITY_REALTIME), | |
#ifdef USE_ACC | |
+#ifdef USE_ACC_IMUF9001 // HELIOSPRING | |
[TASK_ACCEL] = DEFINE_TASK("ACC", NULL, NULL, taskUpdateAccelerometer, TASK_PERIOD_HZ(1000), TASK_PRIORITY_MEDIUM), | |
- [TASK_ATTITUDE] = DEFINE_TASK("ATTITUDE", NULL, NULL, imuUpdateAttitude, TASK_PERIOD_HZ(100), TASK_PRIORITY_MEDIUM), | |
+ [TASK_ATTITUDE] = DEFINE_TASK("ATTITUDE", NULL, NULL, imuUpdateAttitude, TASK_PERIOD_HZ(500), TASK_PRIORITY_MEDIUM), | |
+#else // not HELIOSPRING | |
+ [TASK_ACCEL] = DEFINE_TASK("ACC", NULL, NULL, taskUpdateAccelerometer, TASK_PERIOD_HZ(1000), TASK_PRIORITY_MEDIUM), | |
+ [TASK_ATTITUDE] = DEFINE_TASK("ATTITUDE", NULL, NULL, imuUpdateAttitude, TASK_PERIOD_HZ(1000), TASK_PRIORITY_MEDIUM), | |
+#endif | |
#endif | |
[TASK_RX] = DEFINE_TASK("RX", NULL, rxUpdateCheck, taskUpdateRxMain, TASK_PERIOD_HZ(33), TASK_PRIORITY_HIGH), // If event-based scheduling doesn't work, fallback to periodic scheduling | |
[TASK_DISPATCH] = DEFINE_TASK("DISPATCH", NULL, NULL, dispatchProcess, TASK_PERIOD_HZ(1000), TASK_PRIORITY_HIGH), | |
diff --git a/src/main/flight/imu.c b/src/main/flight/imu.c | |
index 053cdd9c1..f05b554ef 100644 | |
--- a/src/main/flight/imu.c | |
+++ b/src/main/flight/imu.c | |
@@ -38,6 +38,8 @@ | |
#include "fc/runtime_config.h" | |
+#include "fc/rc_controls.h" // HELIOSPRING | |
+ | |
#include "flight/gps_rescue.h" | |
#include "flight/imu.h" | |
#include "flight/mixer.h" | |
diff --git a/src/main/sensors/acceleration.c b/src/main/sensors/acceleration.c | |
index a57f8294e..1720797d7 100644 | |
--- a/src/main/sensors/acceleration.c | |
+++ b/src/main/sensors/acceleration.c | |
@@ -65,6 +65,11 @@ | |
#include "drivers/accgyro_legacy/accgyro_mma845x.h" | |
#endif | |
+// HELIOSPRING | |
+#ifdef USE_ACC_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+#endif //USE_ACC_IMUF9001 | |
+ | |
#include "drivers/bus_spi.h" | |
#include "fc/config.h" | |
@@ -260,6 +265,16 @@ retry: | |
FALLTHROUGH; | |
#endif | |
+// HELIOSPRING | |
+#ifdef USE_ACC_IMUF9001 | |
+ case ACC_IMUF9001: | |
+ if (imufSpiAccDetect(dev)) { | |
+ accHardware = ACC_IMUF9001; | |
+ break; | |
+ } | |
+ FALLTHROUGH; | |
+#endif | |
+ | |
#ifdef USE_ACC_SPI_ICM20689 | |
case ACC_ICM20689: | |
if (icm20689SpiAccDetect(dev)) { | |
@@ -309,6 +324,12 @@ retry: | |
return true; | |
} | |
+// HELIOSPRING | |
+int accGetSamplingIntervall(void) | |
+{ | |
+ return acc.accSamplingInterval; | |
+} | |
+ | |
bool accInit(uint32_t gyroSamplingInverval) | |
{ | |
memset(&acc, 0, sizeof(acc)); | |
@@ -351,6 +372,11 @@ bool accInit(uint32_t gyroSamplingInverval) | |
default: | |
acc.accSamplingInterval = 1000; | |
} | |
+ | |
+#ifdef USE_ACC_IMUF9001 // HELIOSPRING | |
+ acc.accSamplingInterval = 500; | |
+#endif | |
+ | |
if (accLpfCutHz) { | |
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) { | |
biquadFilterInitLPF(&accFilter[axis], accLpfCutHz, acc.accSamplingInterval); | |
diff --git a/src/main/sensors/acceleration.h b/src/main/sensors/acceleration.h | |
index 4ad1b1642..29b1f176e 100644 | |
--- a/src/main/sensors/acceleration.h | |
+++ b/src/main/sensors/acceleration.h | |
@@ -43,6 +43,7 @@ typedef enum { | |
ACC_ICM20649, | |
ACC_ICM20689, | |
ACC_BMI160, | |
+ ACC_IMUF9001, // HELIOSPRING | |
ACC_FAKE | |
} accelerationSensor_e; | |
@@ -87,3 +88,5 @@ union flightDynamicsTrims_u; | |
void setAccelerationTrims(union flightDynamicsTrims_u *accelerationTrimsToUse); | |
void accInitFilters(void); | |
void applyAccelerometerTrimsDelta(union rollAndPitchTrims_u *rollAndPitchTrimsDelta); | |
+ | |
+int accGetSamplingIntervall(void); // HELIOSPRING | |
\ No newline at end of file | |
diff --git a/src/main/sensors/boardalignment.c b/src/main/sensors/boardalignment.c | |
index de312b070..d081e2711 100644 | |
--- a/src/main/sensors/boardalignment.c | |
+++ b/src/main/sensors/boardalignment.c | |
@@ -43,7 +43,8 @@ static fp_rotationMatrix_t boardRotation; | |
// no template required since defaults are zero | |
PG_REGISTER(boardAlignment_t, boardAlignment, PG_BOARD_ALIGNMENT, 0); | |
-static bool isBoardAlignmentStandard(const boardAlignment_t *boardAlignment) | |
+//static bool isBoardAlignmentStandard(const boardAlignment_t *boardAlignment) | |
+bool isBoardAlignmentStandard(const boardAlignment_t *boardAlignment) | |
{ | |
return !boardAlignment->rollDegrees && !boardAlignment->pitchDegrees && !boardAlignment->yawDegrees; | |
} | |
diff --git a/src/main/sensors/boardalignment.h b/src/main/sensors/boardalignment.h | |
index e2be2ba84..58051ad09 100644 | |
--- a/src/main/sensors/boardalignment.h | |
+++ b/src/main/sensors/boardalignment.h | |
@@ -37,3 +37,5 @@ void alignSensorViaMatrix(float *dest, fp_rotationMatrix_t* rotationMatrix); | |
void alignSensorViaRotation(float *dest, uint8_t rotation); | |
void initBoardAlignment(const boardAlignment_t *boardAlignment); | |
+ | |
+bool isBoardAlignmentStandard(const boardAlignment_t *boardAlignment); // HELIOSPRING | |
diff --git a/src/main/sensors/gyro.c b/src/main/sensors/gyro.c | |
index 2eae9232f..548b08d2a 100644 | |
--- a/src/main/sensors/gyro.c | |
+++ b/src/main/sensors/gyro.c | |
@@ -51,6 +51,12 @@ | |
#include "drivers/accgyro/accgyro_spi_mpu6500.h" | |
#include "drivers/accgyro/accgyro_spi_mpu9250.h" | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+#include "drivers/accgyro/accgyro_imuf9001.h" | |
+#include "drivers/time.h" | |
+#endif //USE_GYRO_IMUF9001 | |
+ | |
#ifdef USE_GYRO_L3GD20 | |
#include "drivers/accgyro/accgyro_spi_l3gd20.h" | |
#endif | |
@@ -196,6 +202,24 @@ void pgResetFn_gyroConfig(gyroConfig_t *gyroConfig) | |
gyroConfig->dyn_notch_q = 120; | |
gyroConfig->dyn_notch_min_hz = 150; | |
gyroConfig->gyro_filter_debug_axis = FD_ROLL; | |
+ | |
+// HELIOSPRING | |
+#if defined(USE_GYRO_IMUF9001) | |
+ gyroConfig->imuf_mode = GTBCM_DEFAULT; | |
+ gyroConfig->imuf_rate = IMUF_RATE_16K; | |
+ gyroConfig->imuf_roll_q = IMUF_DEFAULT_ROLL_Q; | |
+ gyroConfig->imuf_pitch_q = IMUF_DEFAULT_PITCH_Q; | |
+ gyroConfig->imuf_yaw_q = IMUF_DEFAULT_YAW_Q; | |
+ gyroConfig->imuf_w = IMUF_DEFAULT_W; | |
+ gyroConfig->imuf_roll_lpf_cutoff_hz = IMUF_DEFAULT_LPF_HZ; | |
+ gyroConfig->imuf_pitch_lpf_cutoff_hz = IMUF_DEFAULT_LPF_HZ; | |
+ gyroConfig->imuf_yaw_lpf_cutoff_hz = IMUF_DEFAULT_LPF_HZ; | |
+ gyroConfig->imuf_roll_af = IMUF_DEFAULT_ROLL_AF; | |
+ gyroConfig->imuf_pitch_af = IMUF_DEFAULT_PITCH_AF; | |
+ gyroConfig->imuf_yaw_af = IMUF_DEFAULT_YAW_AF; | |
+ gyroConfig->gyro_offset_yaw = 0; | |
+ gyroConfig->gyro_align = ALIGN_DEFAULT; | |
+#endif | |
} | |
#ifdef USE_MULTI_GYRO | |
@@ -330,6 +354,16 @@ STATIC_UNIT_TESTED gyroHardware_e gyroDetect(gyroDev_t *dev) | |
FALLTHROUGH; | |
#endif | |
+// HELIOSPRING | |
+#ifdef USE_GYRO_IMUF9001 | |
+ case GYRO_IMUF9001: | |
+ if (imufSpiGyroDetect(dev)) { | |
+ gyroHardware = GYRO_IMUF9001; | |
+ break; | |
+ } | |
+ FALLTHROUGH; | |
+#endif //USE_GYRO_IMUF9001 | |
+ | |
#ifdef USE_GYRO_SPI_ICM20689 | |
case GYRO_ICM20689: | |
if (icm20689SpiGyroDetect(dev)) { | |
@@ -372,7 +406,7 @@ STATIC_UNIT_TESTED gyroHardware_e gyroDetect(gyroDev_t *dev) | |
static void gyroPreInitSensor(const gyroDeviceConfig_t *config) | |
{ | |
#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \ | |
- || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) | |
+ || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_IMUF9001) | |
mpuPreInit(config); | |
#else | |
UNUSED(config); | |
@@ -382,7 +416,7 @@ static void gyroPreInitSensor(const gyroDeviceConfig_t *config) | |
static bool gyroDetectSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config) | |
{ | |
#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \ | |
- || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20) | |
+ || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20) || defined(USE_GYRO_IMUF9001) | |
bool gyroFound = mpuDetect(&gyroSensor->gyroDev, config); | |
@@ -429,6 +463,7 @@ static void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *c | |
case GYRO_MPU6000: | |
case GYRO_MPU6500: | |
case GYRO_MPU9250: | |
+ case GYRO_IMUF9001: // HELIOSPRING | |
gyroSensor->gyroDev.gyroHasOverflowProtection = true; | |
break; | |
@@ -808,6 +843,9 @@ static bool isOnFirstGyroCalibrationCycle(const gyroCalibration_t *gyroCalibrati | |
static void gyroSetCalibrationCycles(gyroSensor_t *gyroSensor) | |
{ | |
+#ifdef USE_GYRO_IMUF9001 // HELIOSPRING | |
+ imufStartCalibration(); | |
+#endif | |
#if defined(USE_FAKE_GYRO) && !defined(UNIT_TEST) | |
if (gyroSensor->gyroDev.gyroHardware == GYRO_FAKE) { | |
gyroSensor->calibration.cyclesRemaining = 0; | |
@@ -821,6 +859,9 @@ void gyroStartCalibration(bool isFirstArmingCalibration) | |
{ | |
if (!(isFirstArmingCalibration && firstArmingCalibrationWasStarted)) { | |
gyroSetCalibrationCycles(&gyroSensor1); | |
+#ifdef USE_GYRO_IMUF9001 // HELIOSPRING | |
+ imufStartCalibration(); | |
+#endif | |
#ifdef USE_MULTI_GYRO | |
gyroSetCalibrationCycles(&gyroSensor2); | |
#endif | |
@@ -1005,11 +1046,32 @@ static FAST_CODE void checkForYawSpin(timeUs_t currentTimeUs) | |
static FAST_CODE FAST_CODE_NOINLINE void gyroUpdateSensor(gyroSensor_t *gyroSensor) | |
{ | |
+#ifndef USE_DMA_SPI_DEVICE // HELIORING | |
if (!gyroSensor->gyroDev.readFn(&gyroSensor->gyroDev)) { | |
return; | |
} | |
+#endif | |
gyroSensor->gyroDev.dataReady = false; | |
+#ifdef USE_GYRO_IMUF9001 // HELIOSPRING | |
+ for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) { | |
+ // NOTE: this branch optimized for when there is no gyro debugging, ensure it is kept in step with non-optimized branch | |
+ DEBUG_SET(DEBUG_GYRO_SCALED, axis, lrintf(gyroSensor->gyroDev.gyroADC[axis])); | |
+ if (!overflowDetected) { | |
+ // integrate using trapezium rule to avoid bias | |
+ accumulatedMeasurements[axis] += 0.5f * (gyroPrevious[axis] + gyroSensor->gyroDev.gyroADC[axis]) * gyro.targetLooptime; | |
+ gyroPrevious[axis] = gyroSensor->gyroDev.gyroADC[axis]; | |
+ } | |
+ } | |
+ if (!isGyroSensorCalibrationComplete(gyroSensor)) { | |
+ performGyroCalibration(gyroSensor, gyroConfig()->gyroMovementCalibrationThreshold); | |
+ // Reset gyro values to zero to prevent other code from using uncalibrated data | |
+ gyroSensor->gyroDev.gyroADC[X] = 0.0f; | |
+ gyroSensor->gyroDev.gyroADC[Y] = 0.0f; | |
+ gyroSensor->gyroDev.gyroADC[Z] = 0.0f; | |
+ // still calibrating, so no need to further process gyro data | |
+ } | |
+#else // not HELIOSPRING | |
if (isGyroSensorCalibrationComplete(gyroSensor)) { | |
// move 16-bit gyro data into 32-bit variables to avoid overflows in calculations | |
@@ -1031,7 +1093,22 @@ static FAST_CODE FAST_CODE_NOINLINE void gyroUpdateSensor(gyroSensor_t *gyroSens | |
} else { | |
performGyroCalibration(gyroSensor, gyroConfig()->gyroMovementCalibrationThreshold); | |
} | |
+#endif // not HELIOSPRING | |
+} | |
+ | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+FAST_CODE_NOINLINE void gyroDmaSpiFinishRead(void) | |
+{ | |
+ //called by dma callback | |
+ mpuGyroDmaSpiReadFinish(&gyroSensor1.gyroDev); | |
+} | |
+FAST_CODE_NOINLINE void gyroDmaSpiStartRead(void) | |
+{ | |
+ //called by exti | |
+ mpuGyroDmaSpiReadStart(&gyroSensor1.gyroDev); | |
} | |
+#endif // HELIOSPRING | |
#define GYRO_FILTER_FUNCTION_NAME filterGyro | |
#define GYRO_FILTER_DEBUG_SET(mode, index, value) { UNUSED(mode); UNUSED(index); UNUSED(value); } | |
@@ -1052,9 +1129,15 @@ FAST_CODE void gyroUpdate(timeUs_t currentTimeUs) | |
case GYRO_CONFIG_USE_GYRO_1: | |
gyroUpdateSensor(&gyroSensor1); | |
if (isGyroSensorCalibrationComplete(&gyroSensor1)) { | |
+#ifdef USE_GYRO_IMUF9001 // HELIOSPRING | |
+ gyro.gyroADC[X] = gyroSensor1.gyroDev.gyroADC[X]; | |
+ gyro.gyroADC[Y] = gyroSensor1.gyroDev.gyroADC[Y]; | |
+ gyro.gyroADC[Z] = gyroSensor1.gyroDev.gyroADC[Z]; | |
+#else // not HELIOSPRING | |
gyro.gyroADC[X] = gyroSensor1.gyroDev.gyroADC[X] * gyroSensor1.gyroDev.scale; | |
gyro.gyroADC[Y] = gyroSensor1.gyroDev.gyroADC[Y] * gyroSensor1.gyroDev.scale; | |
gyro.gyroADC[Z] = gyroSensor1.gyroDev.gyroADC[Z] * gyroSensor1.gyroDev.scale; | |
+#endif | |
} | |
break; | |
#ifdef USE_MULTI_GYRO | |
@@ -1203,7 +1286,11 @@ int16_t gyroGetTemperature(void) | |
int16_t gyroRateDps(int axis) | |
{ | |
+#if defined(USE_GYRO_IMUF9001) // HELIOSPRING | |
+ return lrintf(gyro.gyroADCf[axis]); | |
+#else // not HELIOSPRING | |
return lrintf(gyro.gyroADCf[axis] / ACTIVE_GYRO->gyroDev.scale); | |
+#endif | |
} | |
bool gyroOverflowDetected(void) | |
diff --git a/src/main/sensors/gyro.h b/src/main/sensors/gyro.h | |
index fc8351173..f614d2028 100644 | |
--- a/src/main/sensors/gyro.h | |
+++ b/src/main/sensors/gyro.h | |
@@ -36,6 +36,18 @@ | |
#define FILTER_FREQUENCY_MAX 4000 // maximum frequency for filter cutoffs (nyquist limit of 8K max sampling) | |
+// HELIOSPRING | |
+#if defined(USE_GYRO_IMUF9001) | |
+typedef enum { | |
+ IMUF_RATE_32K = 0, | |
+ IMUF_RATE_16K = 1, | |
+ IMUF_RATE_8K = 2, | |
+ IMUF_RATE_4K = 3, | |
+ IMUF_RATE_2K = 4, | |
+ IMUF_RATE_1K = 5 | |
+} imufRate_e; | |
+#endif | |
+ | |
typedef union gyroLowpassFilter_u { | |
pt1Filter_t pt1FilterState; | |
biquadFilter_t biquadFilterState; | |
@@ -152,6 +164,22 @@ typedef struct gyroConfig_s { | |
uint16_t dyn_notch_q; | |
uint16_t dyn_notch_min_hz; | |
uint8_t gyro_filter_debug_axis; | |
+ | |
+#if defined(USE_GYRO_IMUF9001) // HELIOSPRING | |
+ uint16_t imuf_mode; | |
+ uint16_t imuf_rate; | |
+ uint16_t imuf_pitch_q; | |
+ uint16_t imuf_roll_q; | |
+ uint16_t imuf_yaw_q; | |
+ uint16_t imuf_w; | |
+ uint16_t imuf_pitch_lpf_cutoff_hz; | |
+ uint16_t imuf_roll_lpf_cutoff_hz; | |
+ uint16_t imuf_yaw_lpf_cutoff_hz; | |
+ uint8_t imuf_pitch_af; | |
+ uint8_t imuf_roll_af; | |
+ uint8_t imuf_yaw_af; | |
+ uint8_t gyro_align; // gyro alignment | |
+#endif | |
} gyroConfig_t; | |
PG_DECLARE(gyroConfig_t, gyroConfig); | |
@@ -180,3 +208,9 @@ gyroDetectionFlags_t getGyroDetectionFlags(void); | |
float dynThrottle(float throttle); | |
void dynLpfGyroUpdate(float throttle); | |
#endif | |
+ | |
+// HELIOSPRING | |
+#ifdef USE_DMA_SPI_DEVICE | |
+void gyroDmaSpiFinishRead(void); | |
+void gyroDmaSpiStartRead(void); | |
+#endif | |
diff --git a/src/main/startup/stm32f7xx_hal_conf.h b/src/main/startup/stm32f7xx_hal_conf.h | |
index c6c2504d9..eca6bee1f 100644 | |
--- a/src/main/startup/stm32f7xx_hal_conf.h | |
+++ b/src/main/startup/stm32f7xx_hal_conf.h | |
@@ -52,7 +52,7 @@ | |
#define HAL_ADC_MODULE_ENABLED | |
/* #define HAL_CAN_MODULE_ENABLED */ | |
/* #define HAL_CEC_MODULE_ENABLED */ | |
-/* #define HAL_CRC_MODULE_ENABLED */ | |
+#define HAL_CRC_MODULE_ENABLED // HELIOSPRING | |
/* #define HAL_CRYP_MODULE_ENABLED */ | |
#define HAL_DAC_MODULE_ENABLED | |
/* #define HAL_DCMI_MODULE_ENABLED */ | |
diff --git a/src/main/target/HELIOSPRING/config.c b/src/main/target/HELIOSPRING/config.c | |
new file mode 100755 | |
index 000000000..908717998 | |
--- /dev/null | |
+++ b/src/main/target/HELIOSPRING/config.c | |
@@ -0,0 +1,57 @@ | |
+/* | |
+ * 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> | |
+ | |
+#include <platform.h> | |
+ | |
+#include "config/config_eeprom.h" | |
+#include "drivers/pwm_output.h" | |
+#include "common/filter.h" | |
+#include "sensors/acceleration.h" | |
+#include "sensors/gyro.h" | |
+#include "sensors/battery.h" | |
+#include "telemetry/telemetry.h" | |
+#include "flight/mixer.h" | |
+#include "flight/pid.h" | |
+#include "fc/config.h" | |
+#include "fc/rc.h" | |
+#include "fc/rc_controls.h" | |
+#include "rx/rx.h" | |
+#include "drivers/pwm_output.h" | |
+#include "pg/motor.h" | |
+ | |
+ | |
+void targetConfiguration(void) { | |
+ telemetryConfigMutable()->halfDuplex = false; | |
+ voltageSensorADCConfigMutable(VOLTAGE_SENSOR_ADC_VBAT)->vbatscale = VBAT_SCALE; | |
+ rxConfigMutable()->rcInterpolation = RC_SMOOTHING_MANUAL; | |
+ rxConfigMutable()->rcInterpolationInterval = 14; | |
+ rxConfigMutable()->rcInterpolationChannels = INTERPOLATION_CHANNELS_RPYT; | |
+ motorConfigMutable()->dev.motorPwmProtocol = PWM_TYPE_DSHOT300; | |
+// gyroConfigMutable()->gyro_sync_denom = 1; // 8kHz gyro | |
+// pidConfigMutable()->pid_process_denom = 1; // 8kHz PID | |
+ gyroConfigMutable()->gyro_sync_denom = 2; // 16KHZ GYRO | |
+ pidConfigMutable()->pid_process_denom = 1; // 16KHZ PID | |
+ systemConfigMutable()->cpu_overclock = 1; //192MHz makes Multishot run a little better because of maths. | |
+ | |
+// for (uint8_t pidProfileIndex = 0; pidProfileIndex < MAX_PROFILE_COUNT; pidProfileIndex++) { | |
+// pidProfile_t *pidProfile = pidProfilesMutable(pidProfileIndex); | |
+// pidProfile->dterm_notch_cutoff = 0; | |
+// } | |
+} | |
+ | |
diff --git a/src/main/target/HELIOSPRING/target.c b/src/main/target/HELIOSPRING/target.c | |
new file mode 100755 | |
index 000000000..e4f0434fa | |
--- /dev/null | |
+++ b/src/main/target/HELIOSPRING/target.c | |
@@ -0,0 +1,40 @@ | |
+/* | |
+ * 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> | |
+ | |
+#include <platform.h> | |
+#include "drivers/io.h" | |
+ | |
+#include "drivers/dma.h" | |
+#include "drivers/timer.h" | |
+#include "drivers/timer_def.h" | |
+ | |
+const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { | |
+ | |
+ DEF_TIM(TIM4, CH1, PB6, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN | |
+ DEF_TIM(TIM12, CH1, PB14, TIM_USE_PWM | TIM_USE_PPM, 0, 0), | |
+ | |
+ // Motors | |
+ DEF_TIM(TIM8, CH1, PC6, TIM_USE_MOTOR, 0, 0), // S1_OUT D1_ST7 | |
+ DEF_TIM(TIM8, CH2, PC7, TIM_USE_MOTOR, 0, 0), // S2_OUT D1_ST2 | |
+ DEF_TIM(TIM8, CH3, PC8, TIM_USE_MOTOR, 0, 1), // S3_OUT D1_ST6 | |
+ DEF_TIM(TIM8, CH4, PC9, TIM_USE_MOTOR, 0, 0), // S4_OUT D1_ST1 | |
+ | |
+ // LED strip | |
+ DEF_TIM(TIM1, CH1, PA8, TIM_USE_LED, 0, 0), // D1_ST0 | |
+}; | |
diff --git a/src/main/target/HELIOSPRING/target.h b/src/main/target/HELIOSPRING/target.h | |
new file mode 100755 | |
index 000000000..a9f157c3f | |
--- /dev/null | |
+++ b/src/main/target/HELIOSPRING/target.h | |
@@ -0,0 +1,232 @@ | |
+/* | |
+ * 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 "HESP" | |
+#define USBD_PRODUCT_STRING "HELIOSPRING" | |
+ | |
+//#define MSP_OVER_CLI | |
+//#define USE_DYN_LPF | |
+ | |
+#define LED0_PIN PB7 | |
+ | |
+#define USE_BEEPER | |
+#define BEEPER_PIN PC15 | |
+#define BEEPER_INVERTED | |
+ | |
+ | |
+#define USE_GYRO | |
+#define USE_ACC | |
+#define GYRO_1_SPI_INSTANCE SPI1 | |
+#define GYRO_1_CS_PIN PB1 | |
+#define GYRO_1_ALIGN CW0_DEG | |
+#define GYRO_1_EXTI_PIN PB0 | |
+ | |
+#define USE_SPI | |
+#define USE_SPI_DEVICE_1 | |
+ | |
+#define GYRO_CONFIG_USE_GYRO_DEFAULT GYRO_CONFIG_USE_GYRO_1 | |
+ | |
+#define DEFAULT_ATTITUDE_UPDATE_INTERVAL 1000 | |
+#define DEFAULT_ACC_SAMPLE_INTERVAL 1000 | |
+ | |
+#define USE_FAST_SPI_DRIVER | |
+#define USE_GYRO_IMUF9001 | |
+#define USE_QUAT_IMUF9001 | |
+#define USE_ACC_IMUF9001 | |
+#define IMUF9001_CS_PIN PB1 | |
+#define IMUF9001_RST_PIN PA4 | |
+#define IMUF9001_SPI_INSTANCE SPI1 | |
+#define USE_EXTI | |
+ | |
+#define USE_MPU_DATA_READY_SIGNAL | |
+ | |
+#define ENABLE_DSHOT_DMAR DSHOT_DMAR_ON | |
+ | |
+#define FLASH_CS_PIN PC14 | |
+#define FLASH_SPI_INSTANCE SPI3 | |
+#define USE_FLASHFS | |
+#define USE_FLASH_M25P16 | |
+ | |
+#define USE_VCP | |
+ | |
+#define VBUS_SENSING_PIN PC5 | |
+ | |
+#define USE_OSD | |
+#define USE_MAX7456 | |
+#define MAX7456_SPI_INSTANCE SPI3 | |
+#define MAX7456_SPI_CS_PIN PA15 | |
+#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD) // 10MHz | |
+#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) | |
+ | |
+#define USE_UART1 | |
+#define UART1_RX_PIN PA10 | |
+#define UART1_TX_PIN PA9 | |
+ | |
+#define USE_UART2 | |
+#define UART2_RX_PIN PA3 | |
+#define UART2_TX_PIN PA2 | |
+ | |
+#define USE_UART3 | |
+#define UART3_RX_PIN PB11 | |
+#define UART3_TX_PIN PB10 | |
+ | |
+#define USE_UART4 | |
+#define UART4_RX_PIN PC11 | |
+//#define UART4_TX_PIN NONE // defaults to the vbat adc pin | |
+ | |
+#define USE_UART5 | |
+#define UART5_RX_PIN PD2 | |
+#define UART5_TX_PIN PC12 | |
+ | |
+#define SERIAL_PORT_COUNT 6 //VCP, USART1, USART2, USART3, UART4, USART5 | |
+ | |
+#define USE_SPI | |
+ | |
+#define USE_SPI_DEVICE_1 | |
+#define SPI1_NSS_PIN PB1 | |
+#define SPI1_SCK_PIN PB3 | |
+#define SPI1_MISO_PIN PA6 | |
+#define SPI1_MOSI_PIN PA7 | |
+ | |
+#define USE_DMA_SPI_DEVICE SPI1 | |
+ | |
+#define DMA_SPI_NSS_PIN_SRC GPIO_PinSource1 | |
+#define DMA_SPI_NSS_PIN GPIO_Pin_1 | |
+#define DMA_SPI_NSS_PORT GPIOB | |
+#define DMA_SPI_NSS_AF GPIO_AF_SPI1 | |
+#define DMA_SPI_SCK_PIN_SRC GPIO_PinSource3 | |
+#define DMA_SPI_SCK_PIN GPIO_Pin_3 | |
+#define DMA_SPI_SCK_PORT GPIOB | |
+#define DMA_SPI_SCK_AF GPIO_AF_SPI1 | |
+#define DMA_SPI_MISO_PIN_SRC GPIO_PinSource6 | |
+#define DMA_SPI_MISO_PIN GPIO_Pin_6 | |
+#define DMA_SPI_MISO_PORT GPIOA | |
+#define DMA_SPI_MISO_AF GPIO_AF_SPI1 | |
+#define DMA_SPI_MOSI_PIN_SRC GPIO_PinSource7 | |
+#define DMA_SPI_MOSI_PIN GPIO_Pin_7 | |
+#define DMA_SPI_MOSI_PORT GPIOA | |
+#define DMA_SPI_MOSI_AF GPIO_AF_SPI1 | |
+#define DMA_SPI_RST_MSK RCC_APB2RSTR_SPI1RST | |
+#define DMA_SPI_PER RCC->APB2RSTR | |
+ | |
+#define DMA_SPI_SPI SPI1 | |
+#define DMA_SPI_BAUDRATE SPI_BaudRatePrescaler_4 | |
+#define DMA_SPI_CPOL SPI_CPOL_Low | |
+#define DMA_SPI_CPHA SPI_CPHA_1Edge | |
+ | |
+#define DMA_SPI_DMA DMA2 | |
+#define DMA_SPI_TX_DMA_STREAM DMA2_Stream3 | |
+#define DMA_SPI_RX_DMA_STREAM DMA2_Stream2 | |
+#define DMA_SPI_TX_DMA_CHANNEL DMA_Channel_3 | |
+#define DMA_SPI_RX_DMA_CHANNEL DMA_Channel_3 | |
+#define DMA_SPI_TX_DMA_HANDLER DMA2_Stream3_IRQHandler | |
+#define DMA_SPI_RX_DMA_HANDLER DMA2_Stream2_IRQHandler | |
+#define DMA_SPI_TX_DMA_IRQn DMA2_Stream3_IRQn | |
+#define DMA_SPI_RX_DMA_IRQn DMA2_Stream2_IRQn | |
+ | |
+#define DMA_SPI_DMA_RX_PRE_PRI 0x0E | |
+#define DMA_SPI_DMA_RX_SUB_PRI 0x0E | |
+ | |
+#define DMA_SPI_TX_DMA_FLAG_ALL DMA_FLAG_FEIF3 | DMA_FLAG_DMEIF3 | DMA_FLAG_TEIF3 | DMA_FLAG_HTIF3 | DMA_FLAG_TCIF3 | |
+#define DMA_SPI_TX_DMA_FLAG_GL DMA_FLAG_TCIF3 | |
+#define DMA_SPI_TX_DMA_FLAG_TC DMA_FLAG_TCIF3 | |
+#define DMA_SPI_RX_DMA_FLAG_ALL DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2 | DMA_FLAG_TCIF2 | |
+#define DMA_SPI_RX_DMA_FLAG_TC DMA_FLAG_TCIF2 | |
+#define DMA_SPI_RX_DMA_FLAG_GL DMA_FLAG_TCIF2 | |
+ | |
+ | |
+#define USE_SPI_DEVICE_2 | |
+#define SPI2_NSS_PIN PB12 | |
+#define SPI2_SCK_PIN PB13 | |
+#define SPI2_MISO_PIN PC2 | |
+#define SPI2_MOSI_PIN PC3 | |
+ | |
+#define USE_SPI_DEVICE_3 | |
+#define SPI3_NSS_PIN PA15 | |
+#define SPI3_SCK_PIN PC10 | |
+#define SPI3_MISO_PIN PB4 | |
+#define SPI3_MOSI_PIN PB5 | |
+ | |
+#define USE_I2C | |
+#define USE_I2C_DEVICE_2 | |
+#define I2C2_SCL NONE // PB10, UART3_TX | |
+#define I2C2_SDA NONE // PB11, UART3_RX | |
+#define I2C_DEVICE (I2CDEV_2) | |
+ | |
+#define USE_TARGET_CONFIG | |
+#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT | |
+ | |
+#define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL | |
+#define SERIALRX_PROVIDER SERIALRX_SBUS | |
+#define SERIALRX_UART SERIAL_PORT_USART2 | |
+#define DEFAULT_FEATURES (FEATURE_TELEMETRY | FEATURE_OSD | FEATURE_AIRMODE) | |
+ | |
+#define USE_GPS | |
+#define USE_MAG | |
+#define USE_ESCSERIAL | |
+#define ESCSERIAL_TIMER_TX_PIN NONE // (HARDARE=0,PPM) | |
+//#define USE_SERIAL_4WAY_BLHELI_INTERFACE | |
+ | |
+#define TARGET_IO_PORTA 0xffff | |
+#define TARGET_IO_PORTB 0xffff | |
+#define TARGET_IO_PORTC 0xffff | |
+#define TARGET_IO_PORTD (BIT(2)) | |
+ | |
+#define USABLE_TIMER_CHANNEL_COUNT 7 | |
+#define USED_TIMERS ( TIM_N(1) | TIM_N(8) | TIM_N(4) | TIM_N(12) ) | |
+ | |
+#define USE_ACC_IMUF9001 | |
+#define IMUF_RST_PIN GPIO_Pin_4 | |
+#define IMUF_RST_PORT GPIOA | |
+#define IMUF_EXTI_PIN GPIO_Pin_0 | |
+#define IMUF_EXTI_PORT GPIOB | |
+ | |
+#define USE_ADC | |
+#define ADC_INSTANCE ADC1 | |
+#define ADC1_DMA_OPT 0 // DMA 2 Stream 0 Channel 0 | |
+ | |
+#define DEFAULT_VOLTAGE_METER_SOURCE VOLTAGE_METER_ADC | |
+#define DEFAULT_CURRENT_METER_SOURCE CURRENT_METER_ADC | |
+#define CURRENT_METER_ADC_PIN PA1 | |
+#define VBAT_ADC_PIN PA0 | |
+#define CURRENT_METER_SCALE_DEFAULT 250 | |
+#define VBAT_SCALE 109 | |
+ | |
+#define VBAT_SCALE 109 | |
+ | |
+#define CAMERA_CONTROL_PIN PB6 // define dedicated camera_osd_control pin | |
+ | |
+#define IMUF_DEFAULT_PITCH_Q 3000 | |
+#define IMUF_DEFAULT_ROLL_Q 3000 | |
+#define IMUF_DEFAULT_YAW_Q 3000 | |
+#define IMUF_DEFAULT_W 32 | |
+#define IMUF_DEFAULT_LPF_HZ 120.0f | |
+ | |
+#define USE_BUTTERED_PIDS true | |
+ | |
+#define GYRO_1_CS_PIN PB1 | |
+#define GYRO_1_RST_PIN PA4 | |
+#define GYRO_1_SPI_INSTANCE SPI1 | |
+#define USE_SPI_GYRO | |
+#define USE_EXTI | |
+#define USE_GYRO_EXTI | |
+#define GYRO_1_EXTI_PIN PB0 | |
+#define GYRO_1_ALIGN CW0_DEG | |
+//#define ACC_1_ALIGN CW0_DEG | |
+#define TARGET_MANUFACTURER_IDENTIFIER "HESP" | |
diff --git a/src/main/target/HELIOSPRING/target.mk b/src/main/target/HELIOSPRING/target.mk | |
new file mode 100755 | |
index 000000000..ced109e6f | |
--- /dev/null | |
+++ b/src/main/target/HELIOSPRING/target.mk | |
@@ -0,0 +1,8 @@ | |
+ | |
+F405_TARGETS += $(TARGET) | |
+FEATURES += VCP ONBOARDFLASH | |
+ | |
+TARGET_SRC = stm32f4xx_crc.c \ | |
+ drivers/dma_spi.c \ | |
+ drivers/accgyro/accgyro_imuf9001.c \ | |
+ drivers/max7456.c | |
\ No newline at end of file | |
diff --git a/src/main/target/STRIXF10/config.c b/src/main/target/STRIXF10/config.c | |
new file mode 100755 | |
index 000000000..d4be21f6d | |
--- /dev/null | |
+++ b/src/main/target/STRIXF10/config.c | |
@@ -0,0 +1,57 @@ | |
+/* | |
+ * 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> | |
+ | |
+#include <platform.h> | |
+ | |
+#include "config/config_eeprom.h" | |
+#include "drivers/pwm_output.h" | |
+#include "common/filter.h" | |
+#include "sensors/acceleration.h" | |
+#include "sensors/gyro.h" | |
+#include "sensors/battery.h" | |
+#include "telemetry/telemetry.h" | |
+#include "flight/mixer.h" | |
+#include "flight/pid.h" | |
+#include "fc/config.h" | |
+#include "fc/rc.h" | |
+#include "fc/rc_controls.h" | |
+#include "rx/rx.h" | |
+ | |
+#include "pg/motor.h" | |
+ | |
+#include "config_helper.h" | |
+ | |
+ | |
+void targetConfiguration(void) { | |
+ telemetryConfigMutable()->halfDuplex = false; | |
+ voltageSensorADCConfigMutable(VOLTAGE_SENSOR_ADC_VBAT)->vbatscale = VBAT_SCALE; | |
+ rxConfigMutable()->rcInterpolation = RC_SMOOTHING_MANUAL; | |
+ rxConfigMutable()->rcInterpolationInterval = 14; | |
+ rxConfigMutable()->rcInterpolationChannels = INTERPOLATION_CHANNELS_RPYT; | |
+ motorConfigMutable()->dev.motorPwmProtocol = PWM_TYPE_DSHOT600; | |
+ gyroConfigMutable()->gyro_sync_denom = 2; // 16KHZ GYRO | |
+ pidConfigMutable()->pid_process_denom = 1; // 16KHZ PID | |
+ systemConfigMutable()->cpu_overclock = 0; //192MHz makes Multishot run a little better because of maths. | |
+ | |
+// for (uint8_t pidProfileIndex = 0; pidProfileIndex < MAX_PROFILE_COUNT; pidProfileIndex++) { | |
+// pidProfile_t *pidProfile = pidProfilesMutable(pidProfileIndex); | |
+// pidProfile->dterm_notch_cutoff = 0; | |
+// } | |
+} | |
+ | |
diff --git a/src/main/target/STRIXF10/target.c b/src/main/target/STRIXF10/target.c | |
new file mode 100755 | |
index 000000000..e4f0434fa | |
--- /dev/null | |
+++ b/src/main/target/STRIXF10/target.c | |
@@ -0,0 +1,40 @@ | |
+/* | |
+ * 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> | |
+ | |
+#include <platform.h> | |
+#include "drivers/io.h" | |
+ | |
+#include "drivers/dma.h" | |
+#include "drivers/timer.h" | |
+#include "drivers/timer_def.h" | |
+ | |
+const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { | |
+ | |
+ DEF_TIM(TIM4, CH1, PB6, TIM_USE_ANY, 0, 0), // CAMERA_CONTROL_PIN | |
+ DEF_TIM(TIM12, CH1, PB14, TIM_USE_PWM | TIM_USE_PPM, 0, 0), | |
+ | |
+ // Motors | |
+ DEF_TIM(TIM8, CH1, PC6, TIM_USE_MOTOR, 0, 0), // S1_OUT D1_ST7 | |
+ DEF_TIM(TIM8, CH2, PC7, TIM_USE_MOTOR, 0, 0), // S2_OUT D1_ST2 | |
+ DEF_TIM(TIM8, CH3, PC8, TIM_USE_MOTOR, 0, 1), // S3_OUT D1_ST6 | |
+ DEF_TIM(TIM8, CH4, PC9, TIM_USE_MOTOR, 0, 0), // S4_OUT D1_ST1 | |
+ | |
+ // LED strip | |
+ DEF_TIM(TIM1, CH1, PA8, TIM_USE_LED, 0, 0), // D1_ST0 | |
+}; | |
diff --git a/src/main/target/STRIXF10/target.h b/src/main/target/STRIXF10/target.h | |
new file mode 100755 | |
index 000000000..ea68f9119 | |
--- /dev/null | |
+++ b/src/main/target/STRIXF10/target.h | |
@@ -0,0 +1,228 @@ | |
+/* | |
+ * 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 "SX10" | |
+#define USBD_PRODUCT_STRING "STRIX Binary F10 by Helio" | |
+ | |
+#define STM32F7 | |
+//#undef USE_DSHOT_BITBANG | |
+ | |
+#define LED0_PIN PB7 | |
+ | |
+#define BEEPER PC15 | |
+#define BEEPER_INVERTED | |
+ | |
+#define USE_GYRO | |
+#define USE_ACC | |
+#define GYRO_1_SPI_INSTANCE SPI1 | |
+#define GYRO_1_CS_PIN PB1 | |
+#define GYRO_1_ALIGN CW0_DEG | |
+#define GYRO_1_EXTI_PIN PB0 | |
+ | |
+#define USE_SPI | |
+#define USE_SPI_DEVICE_1 | |
+ | |
+#define GYRO_CONFIG_USE_GYRO_DEFAULT GYRO_CONFIG_USE_GYRO_1 | |
+ | |
+#define DEFAULT_ATTITUDE_UPDATE_INTERVAL 1000 | |
+#define DEFAULT_ACC_SAMPLE_INTERVAL 1000 | |
+ | |
+#define USE_FAST_SPI_DRIVER | |
+#define USE_GYRO_IMUF9001 | |
+#define USE_QUAT_IMUF9001 | |
+#define USE_ACC_IMUF9001 | |
+#define IMUF9001_CS_PIN PB1 | |
+#define IMUF9001_RST_PIN PA4 | |
+#define IMUF9001_SPI_INSTANCE SPI1 | |
+#define USE_EXTI | |
+ | |
+#define USE_MPU_DATA_READY_SIGNAL | |
+ | |
+#define IMUF_RST_PIN GPIO_PIN_4 | |
+#define IMUF_RST_PORT GPIOA | |
+#define IMUF_EXTI_PIN GPIO_PIN_0 | |
+#define IMUF_EXTI_PORT GPIOB | |
+ | |
+#define ENABLE_DSHOT_DMAR DSHOT_DMAR_ON | |
+ | |
+#define FLASH_CS_PIN PC14 | |
+#define M25P16_CS_PIN PC14 | |
+#define FLASH_SPI_INSTANCE SPI3 | |
+#define M25P16_SPI_INSTANCE SPI3 | |
+#define USE_FLASH | |
+#define USE_FLASHFS | |
+#define USE_FLASH_M25P16 | |
+ | |
+#define USE_VCP | |
+ | |
+#define VBUS_SENSING_PIN PC5 | |
+ | |
+#define USE_OSD | |
+#define USE_MAX7456 | |
+#define MAX7456_SPI_INSTANCE SPI3 | |
+#define MAX7456_SPI_CS_PIN PA15 | |
+#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD) // 10MHz | |
+#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) | |
+ | |
+#define USE_UART1 | |
+#define UART1_RX_PIN PA10 | |
+#define UART1_TX_PIN PA9 | |
+ | |
+#define USE_UART2 | |
+#define UART2_RX_PIN PA3 | |
+#define UART2_TX_PIN PA2 | |
+ | |
+#define USE_UART3 | |
+#define UART3_RX_PIN PB11 | |
+#define UART3_TX_PIN PB10 | |
+ | |
+#define USE_UART4 | |
+#define UART4_RX_PIN PC11 | |
+#define UART4_TX_PIN NONE | |
+ | |
+#define USE_UART5 | |
+#define UART5_RX_PIN PD2 | |
+#define UART5_TX_PIN PC12 | |
+ | |
+#define SERIAL_PORT_COUNT 6 //VCP, USART1, USART2, USART3, UART4, USART5 | |
+ | |
+#define USE_SPI | |
+ | |
+#define USE_SPI_DEVICE_1 | |
+#define SPI1_NSS_PIN PB1 | |
+#define SPI1_SCK_PIN PB3 | |
+#define SPI1_MISO_PIN PA6 | |
+#define SPI1_MOSI_PIN PA7 | |
+ | |
+#define USE_HAL_F7_CRC | |
+ | |
+#define USE_DMA_SPI_DEVICE SPI1 | |
+ | |
+#define DMA_SPI_NSS_PIN GPIO_PIN_1 | |
+#define DMA_SPI_NSS_PORT GPIOB | |
+#define DMA_SPI_SCK_PIN GPIO_PIN_3 | |
+#define DMA_SPI_SCK_PORT GPIOB | |
+#define DMA_SPI_SCK_AF GPIO_AF5_SPI1 | |
+#define DMA_SPI_MISO_PIN GPIO_PIN_6 | |
+#define DMA_SPI_MISO_PORT GPIOA | |
+#define DMA_SPI_MISO_AF GPIO_AF5_SPI1 | |
+#define DMA_SPI_MOSI_PIN GPIO_PIN_7 | |
+#define DMA_SPI_MOSI_PORT GPIOA | |
+#define DMA_SPI_MOSI_AF GPIO_AF5_SPI1 | |
+ | |
+#define DMA_SPI_SPI SPI1 | |
+#define DMA_SPI_CLOCK_INIT_FUNC __HAL_RCC_SPI1_CLK_ENABLE() | |
+ | |
+#define DMA_SPI_DMA DMA2 | |
+#define DMA_SPI_TX_DMA_STREAM DMA2_Stream3 | |
+#define DMA_SPI_RX_DMA_STREAM DMA2_Stream2 | |
+#define DMA_SPI_TX_DMA_CHANNEL DMA_CHANNEL_3 | |
+#define DMA_SPI_RX_DMA_CHANNEL DMA_CHANNEL_3 | |
+#define DMA_SPI_TX_DMA_HANDLER DMA2_Stream3_IRQHandler | |
+#define DMA_SPI_RX_DMA_HANDLER DMA2_Stream2_IRQHandler | |
+#define DMA_SPI_TX_DMA_IRQn DMA2_Stream3_IRQn | |
+#define DMA_SPI_RX_DMA_IRQn DMA2_Stream2_IRQn | |
+ | |
+#define DMA_SPI_DMA_RX_PRE_PRI 0x0E | |
+#define DMA_SPI_DMA_RX_SUB_PRI 0x0E | |
+#define DMA_SPI_DMA_TX_PRE_PRI 0x0D | |
+#define DMA_SPI_DMA_TX_SUB_PRI 0x0D | |
+ | |
+#define DMA_SPI_BAUDRATE SPI_BAUDRATEPRESCALER_4 | |
+ | |
+#define USE_SPI_DEVICE_2 | |
+#define SPI2_NSS_PIN PB12 | |
+#define SPI2_SCK_PIN PB13 | |
+#define SPI2_MISO_PIN PC2 | |
+#define SPI2_MOSI_PIN PC3 | |
+ | |
+#define USE_SPI_DEVICE_3 | |
+#define SPI3_NSS_PIN PA15 | |
+#define SPI3_SCK_PIN PC10 | |
+#define SPI3_MISO_PIN PB4 | |
+#define SPI3_MOSI_PIN PB5 | |
+ | |
+#define USE_I2C | |
+#define USE_I2C_DEVICE_2 | |
+#define I2C2_SCL NONE // PB10, UART3_TX | |
+#define I2C2_SDA NONE // PB11, UART3_RX | |
+#define I2C_DEVICE (I2CDEV_2) | |
+ | |
+#define USE_TARGET_CONFIG | |
+#define ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT | |
+ | |
+#define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL | |
+#define SERIALRX_PROVIDER SERIALRX_SBUS | |
+#define SERIALRX_UART SERIAL_PORT_USART2 | |
+#define DEFAULT_FEATURES (FEATURE_TELEMETRY | FEATURE_OSD | FEATURE_AIRMODE) | |
+ | |
+#define USE_GPS | |
+#define USE_MAG | |
+#define USE_ESCSERIAL | |
+#define ESCSERIAL_TIMER_TX_PIN NONE // (HARDARE=0,PPM) | |
+//#define USE_SERIAL_4WAY_BLHELI_INTERFACE | |
+ | |
+#define TARGET_IO_PORTA 0xffff | |
+#define TARGET_IO_PORTB 0xffff | |
+#define TARGET_IO_PORTC 0xffff | |
+#define TARGET_IO_PORTD (BIT(2)) | |
+ | |
+#define USABLE_TIMER_CHANNEL_COUNT 7 | |
+#define USED_TIMERS ( TIM_N(1) | TIM_N(8) | TIM_N(4) | TIM_N(12) ) | |
+ | |
+#define IMUF_BIT_I2C_IF_DIS (1 << 4) | |
+ | |
+ | |
+#define USE_ADC | |
+#define ADC_INSTANCE ADC1 | |
+#define ADC1_DMA_OPT 0 // DMA 2 Stream 0 Channel 0 | |
+ | |
+#define DEFAULT_VOLTAGE_METER_SOURCE VOLTAGE_METER_ADC | |
+#define DEFAULT_CURRENT_METER_SOURCE CURRENT_METER_ADC | |
+#define CURRENT_METER_ADC_PIN PA1 | |
+#define VBAT_ADC_PIN PA0 | |
+#define CURRENT_METER_SCALE_DEFAULT 250 | |
+#define VBAT_SCALE 109 | |
+ | |
+#define CAMERA_CONTROL_PIN PB6 // define dedicated camera_osd_control pin | |
+ | |
+#define IMUF_DEFAULT_PITCH_Q 3000 | |
+#define IMUF_DEFAULT_ROLL_Q 3000 | |
+#define IMUF_DEFAULT_YAW_Q 3000 | |
+#define IMUF_DEFAULT_W 32 | |
+#define IMUF_DEFAULT_LPF_HZ 120.0f | |
+ | |
+#define USE_BUTTERED_PIDS true | |
+ | |
+#define DEFAULT_PIDS_ROLL {45, 50, 30, 0} | |
+#define DEFAULT_PIDS_PITCH {45, 50, 30, 0} | |
+#define DEFAULT_PIDS_YAW {45, 50, 30, 0} | |
+ | |
+ | |
+#define GYRO_1_CS_PIN PB1 | |
+#define GYRO_1_RST_PIN PA4 | |
+#define GYRO_1_SPI_INSTANCE SPI1 | |
+#define USE_SPI_GYRO | |
+#define USE_EXTI | |
+#define USE_GYRO_EXTI | |
+#define GYRO_1_EXTI_PIN PB0 | |
+#define GYRO_1_ALIGN CW0_DEG | |
+//#define ACC_1_ALIGN CW0_DEG | |
+ | |
+#define TARGET_MANUFACTURER_IDENTIFIER "SF10" | |
diff --git a/src/main/target/STRIXF10/target.mk b/src/main/target/STRIXF10/target.mk | |
new file mode 100755 | |
index 000000000..c0dc166ec | |
--- /dev/null | |
+++ b/src/main/target/STRIXF10/target.mk | |
@@ -0,0 +1,6 @@ | |
+F7X2RE_TARGETS += $(TARGET) | |
+FEATURES += VCP ONBOARDFLASH | |
+ | |
+TARGET_SRC = drivers/dma_spi_hal.c \ | |
+ drivers/accgyro/accgyro_imuf9001.c \ | |
+ drivers/max7456.c | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment