1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 20:35:33 +03:00

sdcard dma config, adc config, bluejayf4 hardware revision

Moved ADC to configuration stored in masterConfig.
 - can remove features for vbat etc in future (perhaps param groups)
 - allows adc to be turned off completely (freeing up dma)

Added feature SDCARD
 - enables it to be turned off.
 - allows for DMA to be turned off (set sdcard_dma=OFF)

Fixed hardware revision to allow BJF4 mini to use the same target (no need for an additional target).
This commit is contained in:
blckmn 2016-11-13 14:25:33 +11:00
parent 7942765ada
commit 17facbea84
19 changed files with 264 additions and 202 deletions

View file

@ -23,9 +23,11 @@
#include "cms/cms.h" #include "cms/cms.h"
#include "drivers/adc.h"
#include "drivers/pwm_rx.h" #include "drivers/pwm_rx.h"
#include "drivers/sound_beeper.h" #include "drivers/sound_beeper.h"
#include "drivers/sonar_hcsr04.h" #include "drivers/sonar_hcsr04.h"
#include "drivers/sdcard.h"
#include "fc/rc_controls.h" #include "fc/rc_controls.h"
@ -154,6 +156,10 @@ typedef struct master_s {
pwmConfig_t pwmConfig; pwmConfig_t pwmConfig;
#endif #endif
#ifdef USE_ADC
adcConfig_t adcConfig;
#endif
#ifdef BEEPER #ifdef BEEPER
beeperConfig_t beeperConfig; beeperConfig_t beeperConfig;
#endif #endif
@ -178,6 +184,10 @@ typedef struct master_s {
#ifdef OSD #ifdef OSD
osd_profile_t osdProfile; osd_profile_t osdProfile;
#endif #endif
#ifdef USE_SDCARD
sdcardConfig_t sdcardConfig;
#endif
profile_t profile[MAX_PROFILE_COUNT]; profile_t profile[MAX_PROFILE_COUNT];
uint8_t current_profile_index; uint8_t current_profile_index;
@ -209,8 +219,8 @@ typedef struct master_s {
uint8_t magic_ef; // magic number, should be 0xEF uint8_t magic_ef; // magic number, should be 0xEF
uint8_t chk; // XOR checksum uint8_t chk; // XOR checksum
/* /*
do not add properties after the CHK do not add properties after the MAGIC_EF and CHK
as it is assumed to exist at length-1 as it is assumed to exist at length-2 and length-1
*/ */
} master_t; } master_t;

View file

@ -27,19 +27,19 @@
static uint32_t activeFeaturesLatch = 0; static uint32_t activeFeaturesLatch = 0;
void intFeatureSet(uint32_t mask, master_t *config) void intFeatureSet(uint32_t mask, uint32_t *features)
{ {
config->enabledFeatures |= mask; *features |= mask;
} }
void intFeatureClear(uint32_t mask, master_t *config) void intFeatureClear(uint32_t mask, uint32_t *features)
{ {
config->enabledFeatures &= ~(mask); *features &= ~(mask);
} }
void intFeatureClearAll(master_t *config) void intFeatureClearAll(uint32_t *features)
{ {
config->enabledFeatures = 0; *features = 0;
} }
void latchActiveFeatures() void latchActiveFeatures()
@ -59,17 +59,17 @@ bool feature(uint32_t mask)
void featureSet(uint32_t mask) void featureSet(uint32_t mask)
{ {
intFeatureSet(mask, &masterConfig); intFeatureSet(mask, &masterConfig.enabledFeatures);
} }
void featureClear(uint32_t mask) void featureClear(uint32_t mask)
{ {
intFeatureClear(mask, &masterConfig); intFeatureClear(mask, &masterConfig.enabledFeatures);
} }
void featureClearAll() void featureClearAll()
{ {
intFeatureClearAll(&masterConfig); intFeatureClearAll(&masterConfig.enabledFeatures);
} }
uint32_t featureMask(void) uint32_t featureMask(void)

View file

@ -24,3 +24,7 @@ void featureSet(uint32_t mask);
void featureClear(uint32_t mask); void featureClear(uint32_t mask);
void featureClearAll(void); void featureClearAll(void);
uint32_t featureMask(void); uint32_t featureMask(void);
void intFeatureClearAll(uint32_t *features);
void intFeatureSet(uint32_t mask, uint32_t *features);
void intFeatureClear(uint32_t mask, uint32_t *features);

View file

@ -33,7 +33,7 @@
//#define DEBUG_ADC_CHANNELS //#define DEBUG_ADC_CHANNELS
#ifdef USE_ADC #ifdef USE_ADC
adc_config_t adcConfig[ADC_CHANNEL_COUNT]; adcOperatingConfig_t adcOperatingConfig[ADC_CHANNEL_COUNT];
volatile uint16_t adcValues[ADC_CHANNEL_COUNT]; volatile uint16_t adcValues[ADC_CHANNEL_COUNT];
uint8_t adcChannelByTag(ioTag_t ioTag) uint8_t adcChannelByTag(ioTag_t ioTag)
@ -61,7 +61,7 @@ uint16_t adcGetChannel(uint8_t channel)
debug[3] = adcValues[adcConfig[3].dmaIndex]; debug[3] = adcValues[adcConfig[3].dmaIndex];
} }
#endif #endif
return adcValues[adcConfig[channel].dmaIndex]; return adcValues[adcOperatingConfig[channel].dmaIndex];
} }
#else #else

View file

@ -35,14 +35,19 @@ typedef struct adc_config_s {
uint8_t dmaIndex; // index into DMA buffer in case of sparse channels uint8_t dmaIndex; // index into DMA buffer in case of sparse channels
bool enabled; bool enabled;
uint8_t sampleTime; uint8_t sampleTime;
} adc_config_t; } adcOperatingConfig_t;
typedef struct drv_adc_config_s { typedef struct adcChannelConfig_t {
bool enableVBat; bool enabled;
bool enableRSSI; ioTag_t ioTag;
bool enableCurrentMeter; } adcChannelConfig_t;
bool enableExternal1;
} drv_adc_config_t;
void adcInit(drv_adc_config_t *init); typedef struct adcConfig_s {
adcChannelConfig_t vbat;
adcChannelConfig_t rssi;
adcChannelConfig_t currentMeter;
adcChannelConfig_t external1;
} adcConfig_t;
void adcInit(adcConfig_t *config);
uint16_t adcGetChannel(uint8_t channel); uint16_t adcGetChannel(uint8_t channel);

View file

@ -61,7 +61,7 @@ typedef struct adcDevice_s {
extern const adcDevice_t adcHardware[]; extern const adcDevice_t adcHardware[];
extern const adcTagMap_t adcTagMap[ADC_TAG_MAP_COUNT]; extern const adcTagMap_t adcTagMap[ADC_TAG_MAP_COUNT];
extern adc_config_t adcConfig[ADC_CHANNEL_COUNT]; extern adcOperatingConfig_t adcOperatingConfig[ADC_CHANNEL_COUNT];
extern volatile uint16_t adcValues[ADC_CHANNEL_COUNT]; extern volatile uint16_t adcValues[ADC_CHANNEL_COUNT];
uint8_t adcChannelByTag(ioTag_t ioTag); uint8_t adcChannelByTag(ioTag_t ioTag);

View file

@ -77,7 +77,7 @@ const adcTagMap_t adcTagMap[] = {
// NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board // NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board
// //
void adcInit(drv_adc_config_t *init) void adcInit(adcConfig_t *config)
{ {
#if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN) #if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN)
@ -86,31 +86,23 @@ void adcInit(drv_adc_config_t *init)
uint8_t configuredAdcChannels = 0; uint8_t configuredAdcChannels = 0;
memset(&adcConfig, 0, sizeof(adcConfig)); memset(&adcOperatingConfig, 0, sizeof(adcOperatingConfig));
#ifdef VBAT_ADC_PIN if (config->vbat.enabled) {
if (init->enableVBat) { adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN);
} }
#endif
#ifdef RSSI_ADC_PIN if (config->rssi.enabled) {
if (init->enableRSSI) { adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN);
} }
#endif
#ifdef EXTERNAL1_ADC_PIN if (config->external1.enabled) {
if (init->enableExternal1) { adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN);
} }
#endif
#ifdef CURRENT_METER_ADC_PIN if (config->currentMeter.enabled) {
if (init->enableCurrentMeter) { adcOperatingConfig[ADC_CURRENT].tag = config->currentMeter.ioTag; //CURRENT_METER_ADC_CHANNEL;
adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN);
} }
#endif
ADCDevice device = adcDeviceByInstance(ADC_INSTANCE); ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
if (device == ADCINVALID) if (device == ADCINVALID)
@ -118,16 +110,22 @@ void adcInit(drv_adc_config_t *init)
const adcDevice_t adc = adcHardware[device]; const adcDevice_t adc = adcHardware[device];
bool adcActive = false;
for (int i = 0; i < ADC_CHANNEL_COUNT; i++) { for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].tag) if (!adcOperatingConfig[i].tag)
continue; continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC_BATT + i, 0); adcActive = true;
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AIN, 0)); IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag); IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_Mode_AIN, 0));
adcConfig[i].dmaIndex = configuredAdcChannels++; adcOperatingConfig[i].adcChannel = adcChannelByTag(adcOperatingConfig[i].tag);
adcConfig[i].sampleTime = ADC_SampleTime_239Cycles5; adcOperatingConfig[i].dmaIndex = configuredAdcChannels++;
adcConfig[i].enabled = true; adcOperatingConfig[i].sampleTime = ADC_SampleTime_239Cycles5;
adcOperatingConfig[i].enabled = true;
}
if (!adcActive) {
return;
} }
RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI) RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI)
@ -164,10 +162,10 @@ void adcInit(drv_adc_config_t *init)
uint8_t rank = 1; uint8_t rank = 1;
for (int i = 0; i < ADC_CHANNEL_COUNT; i++) { for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].enabled) { if (!adcOperatingConfig[i].enabled) {
continue; continue;
} }
ADC_RegularChannelConfig(adc.ADCx, adcConfig[i].adcChannel, rank++, adcConfig[i].sampleTime); ADC_RegularChannelConfig(adc.ADCx, adcOperatingConfig[i].adcChannel, rank++, adcOperatingConfig[i].sampleTime);
} }
ADC_DMACmd(adc.ADCx, ENABLE); ADC_DMACmd(adc.ADCx, ENABLE);

View file

@ -100,40 +100,31 @@ ADCDevice adcDeviceByInstance(ADC_TypeDef *instance)
return ADCINVALID; return ADCINVALID;
} }
void adcInit(drv_adc_config_t *init) void adcInit(adcConfig_t *config)
{ {
UNUSED(init);
ADC_InitTypeDef ADC_InitStructure; ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint8_t adcChannelCount = 0; uint8_t adcChannelCount = 0;
memset(&adcConfig, 0, sizeof(adcConfig)); memset(&adcOperatingConfig, 0, sizeof(adcOperatingConfig));
#ifdef VBAT_ADC_PIN if (config->vbat.enabled) {
if (init->enableVBat) { adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN);
} }
#endif
#ifdef RSSI_ADC_PIN if (config->rssi.enabled) {
if (init->enableRSSI) { adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN);
} }
#endif
#ifdef CURRENT_METER_ADC_PIN if (config->external1.enabled) {
if (init->enableCurrentMeter) { adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN);
} }
#endif
#ifdef EXTERNAL1_ADC_PIN if (config->currentMeter.enabled) {
if (init->enableExternal1) { adcOperatingConfig[ADC_CURRENT].tag = config->currentMeter.ioTag; //CURRENT_METER_ADC_CHANNEL;
adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN);
} }
#endif
ADCDevice device = adcDeviceByInstance(ADC_INSTANCE); ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
if (device == ADCINVALID) if (device == ADCINVALID)
return; return;
@ -143,18 +134,24 @@ void adcInit(drv_adc_config_t *init)
#endif #endif
adcDevice_t adc = adcHardware[device]; adcDevice_t adc = adcHardware[device];
bool adcActive = false;
for (int i = 0; i < ADC_CHANNEL_COUNT; i++) { for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].tag) if (!adcOperatingConfig[i].tag)
continue; continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC_BATT + i,0); adcActive = true;
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL)); IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag); IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[i].dmaIndex = adcChannelCount++; adcOperatingConfig[i].adcChannel = adcChannelByTag(adcOperatingConfig[i].tag);
adcConfig[i].sampleTime = ADC_SampleTime_601Cycles5; adcOperatingConfig[i].dmaIndex = adcChannelCount++;
adcConfig[i].enabled = true; adcOperatingConfig[i].sampleTime = ADC_SampleTime_601Cycles5;
adcOperatingConfig[i].enabled = true;
} }
if (!adcActive) {
return;
}
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256); // 72 MHz divided by 256 = 281.25 kHz RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256); // 72 MHz divided by 256 = 281.25 kHz
RCC_ClockCmd(adc.rccADC, ENABLE); RCC_ClockCmd(adc.rccADC, ENABLE);
@ -213,10 +210,10 @@ void adcInit(drv_adc_config_t *init)
uint8_t rank = 1; uint8_t rank = 1;
for (int i = 0; i < ADC_CHANNEL_COUNT; i++) { for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].enabled) { if (!adcOperatingConfig[i].enabled) {
continue; continue;
} }
ADC_RegularChannelConfig(adc.ADCx, adcConfig[i].adcChannel, rank++, adcConfig[i].sampleTime); ADC_RegularChannelConfig(adc.ADCx, adcOperatingConfig[i].adcChannel, rank++, adcOperatingConfig[i].sampleTime);
} }
ADC_Cmd(adc.ADCx, ENABLE); ADC_Cmd(adc.ADCx, ENABLE);

View file

@ -83,7 +83,7 @@ ADCDevice adcDeviceByInstance(ADC_TypeDef *instance)
return ADCINVALID; return ADCINVALID;
} }
void adcInit(drv_adc_config_t *init) void adcInit(adcConfig_t *config)
{ {
ADC_InitTypeDef ADC_InitStructure; ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
@ -91,37 +91,27 @@ void adcInit(drv_adc_config_t *init)
uint8_t i; uint8_t i;
uint8_t configuredAdcChannels = 0; uint8_t configuredAdcChannels = 0;
memset(&adcConfig, 0, sizeof(adcConfig)); memset(&adcOperatingConfig, 0, sizeof(adcOperatingConfig));
#if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN) #if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN)
UNUSED(init); UNUSED(init);
#endif #endif
#ifdef VBAT_ADC_PIN if (config->vbat.enabled) {
if (init->enableVBat) { adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN); //VBAT_ADC_CHANNEL;
} }
#endif
#ifdef RSSI_ADC_PIN if (config->rssi.enabled) {
if (init->enableRSSI) { adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN); //RSSI_ADC_CHANNEL;
} }
#endif
#ifdef EXTERNAL1_ADC_PIN if (config->external1.enabled) {
if (init->enableExternal1) { adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN); //EXTERNAL1_ADC_CHANNEL;
} }
#endif
#ifdef CURRENT_METER_ADC_PIN if (config->currentMeter.enabled) {
if (init->enableCurrentMeter) { adcOperatingConfig[ADC_CURRENT].tag = config->currentMeter.ioTag; //CURRENT_METER_ADC_CHANNEL;
adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN); //CURRENT_METER_ADC_CHANNEL;
} }
#endif
//RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256); // 72 MHz divided by 256 = 281.25 kHz
ADCDevice device = adcDeviceByInstance(ADC_INSTANCE); ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
if (device == ADCINVALID) if (device == ADCINVALID)
@ -129,18 +119,24 @@ void adcInit(drv_adc_config_t *init)
adcDevice_t adc = adcHardware[device]; adcDevice_t adc = adcHardware[device];
for (uint8_t i = 0; i < ADC_CHANNEL_COUNT; i++) { bool adcActive = false;
if (!adcConfig[i].tag) for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcOperatingConfig[i].tag)
continue; continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC_BATT + i, 0); adcActive = true;
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL)); IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag); IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[i].dmaIndex = configuredAdcChannels++; adcOperatingConfig[i].adcChannel = adcChannelByTag(adcOperatingConfig[i].tag);
adcConfig[i].sampleTime = ADC_SampleTime_480Cycles; adcOperatingConfig[i].dmaIndex = configuredAdcChannels++;
adcConfig[i].enabled = true; adcOperatingConfig[i].sampleTime = ADC_SampleTime_480Cycles;
adcOperatingConfig[i].enabled = true;
} }
if (!adcActive) {
return;
}
RCC_ClockCmd(adc.rccADC, ENABLE); RCC_ClockCmd(adc.rccADC, ENABLE);
dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0); dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0);
@ -186,10 +182,10 @@ void adcInit(drv_adc_config_t *init)
uint8_t rank = 1; uint8_t rank = 1;
for (i = 0; i < ADC_CHANNEL_COUNT; i++) { for (i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].enabled) { if (!adcOperatingConfig[i].enabled) {
continue; continue;
} }
ADC_RegularChannelConfig(adc.ADCx, adcConfig[i].adcChannel, rank++, adcConfig[i].sampleTime); ADC_RegularChannelConfig(adc.ADCx, adcOperatingConfig[i].adcChannel, rank++, adcOperatingConfig[i].sampleTime);
} }
ADC_DMARequestAfterLastTransferCmd(adc.ADCx, ENABLE); ADC_DMARequestAfterLastTransferCmd(adc.ADCx, ENABLE);

View file

@ -83,7 +83,7 @@ ADCDevice adcDeviceByInstance(ADC_TypeDef *instance)
return ADCINVALID; return ADCINVALID;
} }
void adcInit(drv_adc_config_t *init) void adcInit(adcConfig_t *config)
{ {
DMA_HandleTypeDef DmaHandle; DMA_HandleTypeDef DmaHandle;
ADC_HandleTypeDef ADCHandle; ADC_HandleTypeDef ADCHandle;
@ -91,35 +91,27 @@ void adcInit(drv_adc_config_t *init)
uint8_t i; uint8_t i;
uint8_t configuredAdcChannels = 0; uint8_t configuredAdcChannels = 0;
memset(&adcConfig, 0, sizeof(adcConfig)); memset(&adcOperatingConfig, 0, sizeof(adcOperatingConfig));
#if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN) #if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN)
UNUSED(init); UNUSED(init);
#endif #endif
#ifdef VBAT_ADC_PIN if (config->vbat.enabled) {
if (init->enableVBat) { adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN); //VBAT_ADC_CHANNEL;
} }
#endif
#ifdef RSSI_ADC_PIN if (config->rssi.enabled) {
if (init->enableRSSI) { adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN); //RSSI_ADC_CHANNEL;
} }
#endif
#ifdef EXTERNAL1_ADC_PIN if (config->external1.enabled) {
if (init->enableExternal1) { adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN); //EXTERNAL1_ADC_CHANNEL;
} }
#endif
#ifdef CURRENT_METER_ADC_PIN if (config->currentMeter.enabled) {
if (init->enableCurrentMeter) { adcOperatingConfig[ADC_CURRENT].tag = config->currentMeter.ioTag; //CURRENT_METER_ADC_CHANNEL;
adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN); //CURRENT_METER_ADC_CHANNEL;
} }
#endif
ADCDevice device = adcDeviceByInstance(ADC_INSTANCE); ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
if (device == ADCINVALID) if (device == ADCINVALID)
@ -127,18 +119,23 @@ void adcInit(drv_adc_config_t *init)
adcDevice_t adc = adcHardware[device]; adcDevice_t adc = adcHardware[device];
for (uint8_t i = 0; i < ADC_CHANNEL_COUNT; i++) { bool adcActive = false;
if (!adcConfig[i].tag) for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcOperatingConfig[i].tag)
continue; continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC_BATT + i, 0); adcActive = true;
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_MODE_ANALOG, 0, GPIO_NOPULL)); IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag); IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_MODE_ANALOG, 0, GPIO_NOPULL));
adcConfig[i].dmaIndex = configuredAdcChannels++; adcOperatingConfig[i].adcChannel = adcChannelByTag(adcOperatingConfig[i].tag);
adcConfig[i].sampleTime = ADC_SAMPLETIME_480CYCLES; adcOperatingConfig[i].dmaIndex = configuredAdcChannels++;
adcConfig[i].enabled = true; adcOperatingConfig[i].sampleTime = ADC_SAMPLETIME_480CYCLES;
adcOperatingConfig[i].enabled = true;
} }
if (!adcActive) {
return;
}
RCC_ClockCmd(adc.rccADC, ENABLE); RCC_ClockCmd(adc.rccADC, ENABLE);
dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0); dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0);
@ -187,13 +184,13 @@ void adcInit(drv_adc_config_t *init)
uint8_t rank = 1; uint8_t rank = 1;
for (i = 0; i < ADC_CHANNEL_COUNT; i++) { for (i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].enabled) { if (!adcOperatingConfig[i].enabled) {
continue; continue;
} }
ADC_ChannelConfTypeDef sConfig; ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = adcConfig[i].adcChannel; sConfig.Channel = adcOperatingConfig[i].adcChannel;
sConfig.Rank = rank++; sConfig.Rank = rank++;
sConfig.SamplingTime = adcConfig[i].sampleTime; sConfig.SamplingTime = adcOperatingConfig[i].sampleTime;
sConfig.Offset = 0; sConfig.Offset = 0;
/*##-3- Configure ADC regular channel ######################################*/ /*##-3- Configure ADC regular channel ######################################*/

View file

@ -20,7 +20,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
typedef struct sdcardMetadata_t { typedef struct sdcardConfig_s {
uint8_t useDma;
} sdcardConfig_t;
typedef struct sdcardMetadata_s {
uint8_t manufacturerID; uint8_t manufacturerID;
uint16_t oemID; uint16_t oemID;

View file

@ -45,6 +45,7 @@
#include "drivers/max7456.h" #include "drivers/max7456.h"
#include "drivers/sound_beeper.h" #include "drivers/sound_beeper.h"
#include "drivers/light_ws2811strip.h" #include "drivers/light_ws2811strip.h"
#include "drivers/sdcard.h"
#include "fc/config.h" #include "fc/config.h"
#include "fc/rc_controls.h" #include "fc/rc_controls.h"
@ -101,18 +102,12 @@
#define BRUSHLESS_MOTORS_PWM_RATE 400 #define BRUSHLESS_MOTORS_PWM_RATE 400
#endif #endif
master_t masterConfig; // master config struct with data independent from profiles master_t masterConfig; // master config struct with data independent from profiles
profile_t *currentProfile; profile_t *currentProfile;
static uint8_t currentControlRateProfileIndex = 0; static uint8_t currentControlRateProfileIndex = 0;
controlRateConfig_t *currentControlRateProfile; controlRateConfig_t *currentControlRateProfile;
void intFeatureClearAll(master_t *config);
void intFeatureSet(uint32_t mask, master_t *config);
void intFeatureClear(uint32_t mask, master_t *config);
static void resetAccelerometerTrims(flightDynamicsTrims_t *accelerometerTrims) static void resetAccelerometerTrims(flightDynamicsTrims_t *accelerometerTrims)
{ {
accelerometerTrims->values.pitch = 0; accelerometerTrims->values.pitch = 0;
@ -314,6 +309,44 @@ void resetSonarConfig(sonarConfig_t *sonarConfig)
} }
#endif #endif
#ifdef USE_SDCARD
void resetsdcardConfig(sdcardConfig_t *sdcardConfig)
{
#if defined(SDCARD_DMA_CHANNEL_TX)
sdcardConfig->useDma = true;
#else
sdcardConfig->useDma = false;
#endif
}
#endif
#ifdef USE_ADC
void resetAdcConfig(adcConfig_t *adcConfig)
{
#ifdef VBAT_ADC_PIN
adcConfig->vbat.enabled = true;
adcConfig->vbat.ioTag = IO_TAG(VBAT_ADC_PIN);
#endif
#ifdef EXTERNAL1_ADC_PIN
adcConfig->external1.enabled = true;
adcConfig->external1.ioTag = IO_TAG(EXTERNAL1_ADC_PIN);
#endif
#ifdef CURRENT_METER_ADC_PIN
adcConfig->currentMeter.enabled = true;
adcConfig->currentMeter.ioTag = IO_TAG(CURRENT_METER_ADC_PIN);
#endif
#ifdef RSSI_ADC_PIN
adcConfig->rssi.enabled = true;
adcConfig->rssi.ioTag = IO_TAG(RSSI_ADC_PIN);
#endif
}
#endif
#ifdef BEEPER #ifdef BEEPER
void resetBeeperConfig(beeperConfig_t *beeperConfig) void resetBeeperConfig(beeperConfig_t *beeperConfig)
{ {
@ -490,30 +523,32 @@ void createDefaultConfig(master_t *config)
// Clear all configuration // Clear all configuration
memset(config, 0, sizeof(master_t)); memset(config, 0, sizeof(master_t));
intFeatureClearAll(config); uint32_t *featuresPtr = &config->enabledFeatures;
intFeatureSet(DEFAULT_RX_FEATURE | FEATURE_FAILSAFE , config);
intFeatureClearAll(featuresPtr);
intFeatureSet(DEFAULT_RX_FEATURE | FEATURE_FAILSAFE , featuresPtr);
#ifdef DEFAULT_FEATURES #ifdef DEFAULT_FEATURES
intFeatureSet(DEFAULT_FEATURES, config); intFeatureSet(DEFAULT_FEATURES, featuresPtr);
#endif #endif
#ifdef OSD #ifdef OSD
intFeatureSet(FEATURE_OSD, config); intFeatureSet(FEATURE_OSD, featuresPtr);
osdResetConfig(&config->osdProfile); osdResetConfig(&config->osdProfile);
#endif #endif
#ifdef BOARD_HAS_VOLTAGE_DIVIDER #ifdef BOARD_HAS_VOLTAGE_DIVIDER
// only enable the VBAT feature by default if the board has a voltage divider otherwise // only enable the VBAT feature by default if the board has a voltage divider otherwise
// the user may see incorrect readings and unexpected issues with pin mappings may occur. // the user may see incorrect readings and unexpected issues with pin mappings may occur.
intFeatureSet(FEATURE_VBAT, config); intFeatureSet(FEATURE_VBAT, featuresPtr);
#endif #endif
config->version = EEPROM_CONF_VERSION; config->version = EEPROM_CONF_VERSION;
config->mixerMode = MIXER_QUADX; config->mixerMode = MIXER_QUADX;
// global settings // global settings
config->current_profile_index = 0; // default profile config->current_profile_index = 0; // default profile
config->dcm_kp = 2500; // 1.0 * 10000 config->dcm_kp = 2500; // 1.0 * 10000
config->dcm_ki = 0; // 0.003 * 10000 config->dcm_ki = 0; // 0.003 * 10000
config->gyro_lpf = 0; // 256HZ default config->gyro_lpf = 0; // 256HZ default
#ifdef STM32F10X #ifdef STM32F10X
config->gyro_sync_denom = 8; config->gyro_sync_denom = 8;
@ -562,6 +597,10 @@ void createDefaultConfig(master_t *config)
resetTelemetryConfig(&config->telemetryConfig); resetTelemetryConfig(&config->telemetryConfig);
#endif #endif
#ifdef USE_ADC
resetAdcConfig(&config->adcConfig);
#endif
#ifdef BEEPER #ifdef BEEPER
resetBeeperConfig(&config->beeperConfig); resetBeeperConfig(&config->beeperConfig);
#endif #endif
@ -570,6 +609,11 @@ void createDefaultConfig(master_t *config)
resetSonarConfig(&config->sonarConfig); resetSonarConfig(&config->sonarConfig);
#endif #endif
#ifdef USE_SDCARD
intFeatureSet(FEATURE_SDCARD, featuresPtr);
resetsdcardConfig(&config->sdcardConfig);
#endif
#ifdef SERIALRX_PROVIDER #ifdef SERIALRX_PROVIDER
config->rxConfig.serialrx_provider = SERIALRX_PROVIDER; config->rxConfig.serialrx_provider = SERIALRX_PROVIDER;
#else #else
@ -708,10 +752,10 @@ void createDefaultConfig(master_t *config)
#ifdef BLACKBOX #ifdef BLACKBOX
#if defined(ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT) #if defined(ENABLE_BLACKBOX_LOGGING_ON_SPIFLASH_BY_DEFAULT)
intFeatureSet(FEATURE_BLACKBOX, config); intFeatureSet(FEATURE_BLACKBOX, featuresPtr);
config->blackbox_device = BLACKBOX_DEVICE_FLASH; config->blackbox_device = BLACKBOX_DEVICE_FLASH;
#elif defined(ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT) #elif defined(ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT)
intFeatureSet(FEATURE_BLACKBOX, config); intFeatureSet(FEATURE_BLACKBOX, featuresPtr);
config->blackbox_device = BLACKBOX_DEVICE_SDCARD; config->blackbox_device = BLACKBOX_DEVICE_SDCARD;
#else #else
config->blackbox_device = BLACKBOX_DEVICE_SERIAL; config->blackbox_device = BLACKBOX_DEVICE_SERIAL;
@ -735,7 +779,6 @@ void createDefaultConfig(master_t *config)
targetConfiguration(config); targetConfiguration(config);
#endif #endif
// copy first profile into remaining profile // copy first profile into remaining profile
for (int i = 1; i < MAX_PROFILE_COUNT; i++) { for (int i = 1; i < MAX_PROFILE_COUNT; i++) {
memcpy(&config->profile[i], &config->profile[0], sizeof(profile_t)); memcpy(&config->profile[i], &config->profile[0], sizeof(profile_t));
@ -940,6 +983,10 @@ void validateAndFixConfig(void)
if (!isSerialConfigValid(serialConfig)) { if (!isSerialConfigValid(serialConfig)) {
resetSerialConfig(serialConfig); resetSerialConfig(serialConfig);
} }
#if defined(TARGET_VALIDATECONFIG)
targetValidateConfiguration(&masterConfig);
#endif
} }
void readEEPROMAndNotify(void) void readEEPROMAndNotify(void)

View file

@ -51,7 +51,7 @@ typedef enum {
FEATURE_CHANNEL_FORWARDING = 1 << 20, FEATURE_CHANNEL_FORWARDING = 1 << 20,
FEATURE_TRANSPONDER = 1 << 21, FEATURE_TRANSPONDER = 1 << 21,
FEATURE_AIRMODE = 1 << 22, FEATURE_AIRMODE = 1 << 22,
//FEATURE_SUPEREXPO_RATES = 1 << 23, FEATURE_SDCARD = 1 << 23,
FEATURE_VTX = 1 << 24, FEATURE_VTX = 1 << 24,
FEATURE_RX_SPI = 1 << 25, FEATURE_RX_SPI = 1 << 25,
FEATURE_SOFTSPI = 1 << 26, FEATURE_SOFTSPI = 1 << 26,
@ -86,4 +86,6 @@ bool canSoftwareSerialBeUsed(void);
uint16_t getCurrentMinthrottle(void); uint16_t getCurrentMinthrottle(void);
struct master_s; struct master_s;
void targetConfiguration(struct master_s *config); void targetConfiguration(struct master_s *config);
void targetValidateConfiguration(struct master_s *config);

View file

@ -230,7 +230,7 @@ static const char * const featureNames[] = {
"SONAR", "TELEMETRY", "CURRENT_METER", "3D", "RX_PARALLEL_PWM", "SONAR", "TELEMETRY", "CURRENT_METER", "3D", "RX_PARALLEL_PWM",
"RX_MSP", "RSSI_ADC", "LED_STRIP", "DISPLAY", "OSD", "RX_MSP", "RSSI_ADC", "LED_STRIP", "DISPLAY", "OSD",
"BLACKBOX", "CHANNEL_FORWARDING", "TRANSPONDER", "AIRMODE", "BLACKBOX", "CHANNEL_FORWARDING", "TRANSPONDER", "AIRMODE",
" ", "VTX", "RX_SPI", "SOFTSPI", NULL "SDCARD", "VTX", "RX_SPI", "SOFTSPI", NULL
}; };
// sync this with rxFailsafeChannelMode_e // sync this with rxFailsafeChannelMode_e
@ -944,7 +944,9 @@ const clivalue_t valueTable[] = {
{ "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } }, { "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } },
{ "vtx_power", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_power, .config.minmax = { 0, 1 } }, { "vtx_power", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_power, .config.minmax = { 0, 1 } },
#endif #endif
#ifdef USE_SDCARD
{ "sdcard_dma", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.sdcardConfig.useDma, .config.lookup = { TABLE_OFF_ON } },
#endif
#ifdef OSD #ifdef OSD
{ "osd_video_system", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.video_system, .config.minmax = { 0, 2 } }, { "osd_video_system", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.video_system, .config.minmax = { 0, 2 } },
{ "osd_row_shiftdown", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.row_shiftdown, .config.minmax = { 0, 1 } }, { "osd_row_shiftdown", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.row_shiftdown, .config.minmax = { 0, 1 } },

View file

@ -373,21 +373,11 @@ void init(void)
#endif #endif
#ifdef USE_ADC #ifdef USE_ADC
drv_adc_config_t adc_params; /* these can be removed from features! */
masterConfig.adcConfig.vbat.enabled = feature(FEATURE_VBAT);
adc_params.enableVBat = feature(FEATURE_VBAT); masterConfig.adcConfig.currentMeter.enabled = feature(FEATURE_CURRENT_METER);
adc_params.enableRSSI = feature(FEATURE_RSSI_ADC); masterConfig.adcConfig.rssi.enabled = feature(FEATURE_RSSI_ADC);
adc_params.enableCurrentMeter = feature(FEATURE_CURRENT_METER); adcInit(&masterConfig.adcConfig);
adc_params.enableExternal1 = false;
#ifdef OLIMEXINO
adc_params.enableExternal1 = true;
#endif
#ifdef NAZE
// optional ADC5 input on rev.5 hardware
adc_params.enableExternal1 = (hardwareRevision >= NAZE32_REV5);
#endif
adcInit(&adc_params);
#endif #endif
@ -527,28 +517,11 @@ void init(void)
#endif #endif
#ifdef USE_SDCARD #ifdef USE_SDCARD
bool sdcardUseDMA = false; if (feature(FEATURE_SDCARD)) {
sdcardInsertionDetectInit();
sdcardInsertionDetectInit(); sdcard_init(masterConfig.sdcardConfig.useDma);
afatfs_init();
#ifdef SDCARD_DMA_CHANNEL_TX }
#if defined(LED_STRIP) && defined(WS2811_DMA_CHANNEL)
// Ensure the SPI Tx DMA doesn't overlap with the led strip
#if defined(STM32F4) || defined(STM32F7)
sdcardUseDMA = !feature(FEATURE_LED_STRIP) || SDCARD_DMA_CHANNEL_TX != WS2811_DMA_STREAM;
#else
sdcardUseDMA = !feature(FEATURE_LED_STRIP) || SDCARD_DMA_CHANNEL_TX != WS2811_DMA_CHANNEL;
#endif
#else
sdcardUseDMA = true;
#endif
#endif
sdcard_init(sdcardUseDMA);
afatfs_init();
#endif #endif
if (masterConfig.gyro_lpf > 0 && masterConfig.gyro_lpf < 7) { if (masterConfig.gyro_lpf > 0 && masterConfig.gyro_lpf < 7) {

View file

@ -21,6 +21,9 @@
#include <platform.h> #include <platform.h>
#include "config/config_master.h" #include "config/config_master.h"
#include "config/feature.h"
#include "blackbox/blackbox_io.h"
#include "hardware_revision.h" #include "hardware_revision.h"
@ -32,4 +35,24 @@ void targetConfiguration(master_t *config)
config->sensorAlignmentConfig.acc_align = CW180_DEG; config->sensorAlignmentConfig.acc_align = CW180_DEG;
config->beeperConfig.ioTag = IO_TAG(BEEPER_OPT); config->beeperConfig.ioTag = IO_TAG(BEEPER_OPT);
} }
if (hardwareRevision == BJF4_MINI_REV3A || hardwareRevision == BJF4_REV1) {
intFeatureClear(FEATURE_SDCARD, &config->enabledFeatures);
}
if (hardwareRevision == BJF4_MINI_REV3A) {
config->adcConfig.vbat.ioTag = IO_TAG(PA4);
}
}
void targetValidateConfiguration(master_t *config)
{
/* make sure the SDCARD cannot be turned on */
if (hardwareRevision == BJF4_MINI_REV3A || hardwareRevision == BJF4_REV1) {
intFeatureClear(FEATURE_SDCARD, &config->enabledFeatures);
if (config->blackbox_device == BLACKBOX_DEVICE_SDCARD) {
config->blackbox_device = BLACKBOX_DEVICE_FLASH;
}
}
} }

View file

@ -45,10 +45,6 @@ void detectHardwareRevision(void)
IOInit(pin1, OWNER_SYSTEM, 1); IOInit(pin1, OWNER_SYSTEM, 1);
IOConfigGPIO(pin1, IOCFG_IPU); IOConfigGPIO(pin1, IOCFG_IPU);
IO_t pin2 = IOGetByTag(IO_TAG(PB13));
IOInit(pin2, OWNER_SYSTEM, 2);
IOConfigGPIO(pin2, IOCFG_IPU);
// Check hardware revision // Check hardware revision
delayMicroseconds(10); // allow configuration to settle delayMicroseconds(10); // allow configuration to settle
@ -57,10 +53,17 @@ void detectHardwareRevision(void)
if only PB12 is tied to GND then it is a Rev3 (full size) if only PB12 is tied to GND then it is a Rev3 (full size)
*/ */
if (!IORead(pin1)) { if (!IORead(pin1)) {
if (!IORead(pin2)) {
hardwareRevision = BJF4_REV3A;
}
hardwareRevision = BJF4_REV3; hardwareRevision = BJF4_REV3;
} else {
IO_t pin2 = IOGetByTag(IO_TAG(PB13));
IOInit(pin2, OWNER_SYSTEM, 2);
IOConfigGPIO(pin2, IOCFG_OUT_PP);
IOWrite(pin2, false);
if (!IORead(pin1)) {
hardwareRevision = BJF4_MINI_REV3A;
}
} }
if (hardwareRevision == UNKNOWN) { if (hardwareRevision == UNKNOWN) {

View file

@ -21,7 +21,7 @@ typedef enum bjf4HardwareRevision_t {
BJF4_REV1, // Flash BJF4_REV1, // Flash
BJF4_REV2, // SDCard BJF4_REV2, // SDCard
BJF4_REV3, // SDCard + Flash BJF4_REV3, // SDCard + Flash
BJF4_REV3A, // Flash (20x20 mini format) BJF4_MINI_REV3A, // Flash (20x20 mini format)
} bjf4HardwareRevision_e; } bjf4HardwareRevision_e;
extern uint8_t hardwareRevision; extern uint8_t hardwareRevision;

View file

@ -18,6 +18,7 @@
#pragma once #pragma once
#define TARGET_BOARD_IDENTIFIER "BJF4" #define TARGET_BOARD_IDENTIFIER "BJF4"
#define TARGET_CONFIG #define TARGET_CONFIG
#define TARGET_VALIDATECONFIG
#define CONFIG_START_FLASH_ADDRESS (0x08080000) //0x08080000 to 0x080A0000 (FLASH_Sector_8) #define CONFIG_START_FLASH_ADDRESS (0x08080000) //0x08080000 to 0x080A0000 (FLASH_Sector_8)