diff --git a/src/main/drivers/dma.c b/src/main/drivers/dma.c index cd17553e08..4b6cace0e5 100644 --- a/src/main/drivers/dma.c +++ b/src/main/drivers/dma.c @@ -23,61 +23,66 @@ #include "build_config.h" +#include "drivers/nvic.h" #include "drivers/dma.h" /* - * DMA handlers for DMA resources that are shared between different features depending on run-time configuration. + * DMA descriptors. */ -static dmaHandlers_t dmaHandlers; +static dmaChannelDescriptor_t dmaDescriptors[] = { + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel1, 0, DMA1_Channel1_IRQn, RCC_AHBPeriph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel2, 4, DMA1_Channel2_IRQn, RCC_AHBPeriph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel3, 8, DMA1_Channel3_IRQn, RCC_AHBPeriph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel4, 12, DMA1_Channel4_IRQn, RCC_AHBPeriph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel5, 16, DMA1_Channel5_IRQn, RCC_AHBPeriph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel6, 20, DMA1_Channel6_IRQn, RCC_AHBPeriph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel7, 24, DMA1_Channel7_IRQn, RCC_AHBPeriph_DMA1), +#if defined(STM32F3) || defined(STM32F10X_CL) + DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel1, 0, DMA2_Channel1_IRQn, RCC_AHBPeriph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel2, 4, DMA2_Channel2_IRQn, RCC_AHBPeriph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel3, 8, DMA2_Channel3_IRQn, RCC_AHBPeriph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel4, 12, DMA2_Channel4_IRQn, RCC_AHBPeriph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel5, 16, DMA2_Channel5_IRQn, RCC_AHBPeriph_DMA2), +#endif +}; -void dmaNoOpHandler(DMA_Channel_TypeDef *channel) -{ - UNUSED(channel); -} +/* + * DMA IRQ Handlers + */ +DEFINE_DMA_IRQ_HANDLER(1, 1, DMA1_CH1_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 2, DMA1_CH2_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 3, DMA1_CH3_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 4, DMA1_CH4_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 5, DMA1_CH5_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 6, DMA1_CH6_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 7, DMA1_CH7_HANDLER) -void DMA1_Channel2_IRQHandler(void) -{ - dmaHandlers.dma1Channel2IRQHandler(DMA1_Channel2); -} +#if defined(STM32F3) || defined(STM32F10X_CL) +DEFINE_DMA_IRQ_HANDLER(2, 1, DMA2_CH1_HANDLER) +DEFINE_DMA_IRQ_HANDLER(2, 2, DMA2_CH2_HANDLER) +DEFINE_DMA_IRQ_HANDLER(2, 3, DMA2_CH3_HANDLER) +DEFINE_DMA_IRQ_HANDLER(2, 4, DMA2_CH4_HANDLER) +DEFINE_DMA_IRQ_HANDLER(2, 5, DMA2_CH5_HANDLER) +#endif -void DMA1_Channel3_IRQHandler(void) -{ - dmaHandlers.dma1Channel3IRQHandler(DMA1_Channel3); -} - -void DMA1_Channel6_IRQHandler(void) -{ - dmaHandlers.dma1Channel6IRQHandler(DMA1_Channel6); -} - -void DMA1_Channel7_IRQHandler(void) -{ - dmaHandlers.dma1Channel7IRQHandler(DMA1_Channel7); -} void dmaInit(void) { - memset(&dmaHandlers, 0, sizeof(dmaHandlers)); - dmaHandlers.dma1Channel2IRQHandler = dmaNoOpHandler; - dmaHandlers.dma1Channel3IRQHandler = dmaNoOpHandler; - dmaHandlers.dma1Channel6IRQHandler = dmaNoOpHandler; - dmaHandlers.dma1Channel7IRQHandler = dmaNoOpHandler; + // TODO: Do we need this? } -void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback) +void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback, uint32_t priority, uint32_t userParam) { - switch (identifier) { - case DMA1_CH2_HANDLER: - dmaHandlers.dma1Channel2IRQHandler = callback; - break; - case DMA1_CH3_HANDLER: - dmaHandlers.dma1Channel3IRQHandler = callback; - break; - case DMA1_CH6_HANDLER: - dmaHandlers.dma1Channel6IRQHandler = callback; - break; - case DMA1_CH7_HANDLER: - dmaHandlers.dma1Channel7IRQHandler = callback; - break; - } + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHBPeriphClockCmd(dmaDescriptors[identifier].rcc, ENABLE); + dmaDescriptors[identifier].irqHandlerCallback = callback; + dmaDescriptors[identifier].userParam = userParam; + + NVIC_InitStructure.NVIC_IRQChannel = dmaDescriptors[identifier].irqN; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(priority); + NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(priority); + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); } + diff --git a/src/main/drivers/dma.h b/src/main/drivers/dma.h index 9cb34c7665..4f0dabdfff 100644 --- a/src/main/drivers/dma.h +++ b/src/main/drivers/dma.h @@ -15,37 +15,97 @@ * along with Cleanflight. If not, see . */ + +struct dmaChannelDescriptor_s; +typedef void (*dmaCallbackHandlerFuncPtr)(struct dmaChannelDescriptor_s *channelDescriptor); + #ifdef STM32F4 -typedef void(*dmaCallbackHandlerFuncPtr)(DMA_Stream_TypeDef *stream); typedef enum { - DMA1_ST2_HANDLER = 0, + DMA1_ST1_HANDLER = 0, + DMA1_ST2_HANDLER, + DMA1_ST3_HANDLER, + DMA1_ST4_HANDLER, + DMA1_ST5_HANDLER, + DMA1_ST6_HANDLER, DMA1_ST7_HANDLER, + DMA2_ST1_HANDLER, + DMA2_ST2_HANDLER, + DMA2_ST3_HANDLER, + DMA2_ST4_HANDLER, + DMA2_ST5_HANDLER, + DMA2_ST6_HANDLER, + DMA2_ST7_HANDLER, } dmaHandlerIdentifier_e; -typedef struct dmaHandlers_s { - dmaCallbackHandlerFuncPtr dma1Stream2IRQHandler; - dmaCallbackHandlerFuncPtr dma1Stream7IRQHandler; -} dmaHandlers_t; +typedef struct dmaChannelDescriptor_s { + DMA_TypeDef* dma; + DMA_Stream_TypeDef* stream; + dmaCallbackHandlerFuncPtr irqHandlerCallback; + uint8_t flagsShift; + IRQn_Type irqN; + uint32_t rcc; + uint32_t userParam; +} dmaChannelDescriptor_t; + +#define DEFINE_DMA_CHANNEL(d, s, f, i, r) {.dma = d, .stream = s, .irqHandlerCallback = NULL, .flagsShift = f, .irqN = i, .rcc = r, .userParam = 0} +#define DEFINE_DMA_IRQ_HANDLER(d, s, i) void DMA ## d ## _Stream ## s ## _IRQHandler(void) {\ + if (dmaDescriptors[i].irqHandlerCallback)\ + dmaDescriptors[i].irqHandlerCallback(&dmaDescriptors[i]);\ + } + +#define DMA_CLEAR_FLAG(d, flag) if(d->flagsShift > 31) d->dma->HIFCR = (flag << (d->flagsShift - 32)); else d->dma->LIFCR = (flag << d->flagsShift) +#define DMA_GET_FLAG_STATUS(d, flag) (d->flagsShift > 31 ? d->dma->HISR & (flag << (d->flagsShift - 32)): d->dma->LISR & (flag << d->flagsShift)) + + +#define DMA_IT_TCIF ((uint32_t)0x00000020) +#define DMA_IT_HTIF ((uint32_t)0x00000010) +#define DMA_IT_TEIF ((uint32_t)0x00000008) +#define DMA_IT_DMEIF ((uint32_t)0x00000004) +#define DMA_IT_FEIF ((uint32_t)0x00000001) #else -typedef void (*dmaCallbackHandlerFuncPtr)(DMA_Channel_TypeDef *channel); - typedef enum { - DMA1_CH2_HANDLER = 0, + DMA1_CH1_HANDLER = 0, + DMA1_CH2_HANDLER, DMA1_CH3_HANDLER, + DMA1_CH4_HANDLER, + DMA1_CH5_HANDLER, DMA1_CH6_HANDLER, DMA1_CH7_HANDLER, + DMA2_CH1_HANDLER, + DMA2_CH2_HANDLER, + DMA2_CH3_HANDLER, + DMA2_CH4_HANDLER, + DMA2_CH5_HANDLER, } dmaHandlerIdentifier_e; -typedef struct dmaHandlers_s { - dmaCallbackHandlerFuncPtr dma1Channel2IRQHandler; - dmaCallbackHandlerFuncPtr dma1Channel3IRQHandler; - dmaCallbackHandlerFuncPtr dma1Channel6IRQHandler; - dmaCallbackHandlerFuncPtr dma1Channel7IRQHandler; -} dmaHandlers_t; +typedef struct dmaChannelDescriptor_s { + DMA_TypeDef* dma; + DMA_Channel_TypeDef* channel; + dmaCallbackHandlerFuncPtr irqHandlerCallback; + uint8_t flagsShift; + IRQn_Type irqN; + uint32_t rcc; + uint32_t userParam; +} dmaChannelDescriptor_t; + +#define DEFINE_DMA_CHANNEL(d, c, f, i, r) {.dma = d, .channel = c, .irqHandlerCallback = NULL, .flagsShift = f, .irqN = i, .rcc = r, .userParam = 0} +#define DEFINE_DMA_IRQ_HANDLER(d, c, i) void DMA ## d ## _Channel ## c ## _IRQHandler(void) {\ + if (dmaDescriptors[i].irqHandlerCallback)\ + dmaDescriptors[i].irqHandlerCallback(&dmaDescriptors[i]);\ + } + +#define DMA_CLEAR_FLAG(d, flag) d->dma->IFCR = (flag << d->flagsShift) +#define DMA_GET_FLAG_STATUS(d, flag) (d->dma->ISR & (flag << d->flagsShift)) + +#define DMA_IT_TCIF ((uint32_t)0x00000002) +#define DMA_IT_HTIF ((uint32_t)0x00000004) +#define DMA_IT_TEIF ((uint32_t)0x00000008) + #endif void dmaInit(void); -void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback); +void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback, uint32_t priority, uint32_t userParam); + diff --git a/src/main/drivers/dma_stm32f4xx.c b/src/main/drivers/dma_stm32f4xx.c index fefbae2801..bf2d2ec582 100644 --- a/src/main/drivers/dma_stm32f4xx.c +++ b/src/main/drivers/dma_stm32f4xx.c @@ -23,43 +23,67 @@ #include "build_config.h" +#include "drivers/nvic.h" #include "drivers/dma.h" /* - * DMA handlers for DMA resources that are shared between different features depending on run-time configuration. + * DMA descriptors. */ -static dmaHandlers_t dmaHandlers; +static dmaChannelDescriptor_t dmaDescriptors[] = { + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream0, 0, DMA1_Stream0_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream1, 6, DMA1_Stream1_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream2, 16, DMA1_Stream2_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream3, 22, DMA1_Stream3_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream4, 32, DMA1_Stream4_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream5, 38, DMA1_Stream5_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream6, 48, DMA1_Stream6_IRQn, RCC_AHB1Periph_DMA1), + DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream7, 54, DMA1_Stream7_IRQn, RCC_AHB1Periph_DMA1), -void dmaNoOpHandler(DMA_Stream_TypeDef *stream) -{ - UNUSED(stream); -} + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream0, 0, DMA2_Stream0_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream1, 6, DMA2_Stream1_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream2, 16, DMA2_Stream2_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream3, 22, DMA2_Stream3_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream4, 32, DMA2_Stream4_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream5, 38, DMA2_Stream5_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream6, 48, DMA2_Stream6_IRQn, RCC_AHB1Periph_DMA2), + DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream7, 54, DMA2_Stream7_IRQn, RCC_AHB1Periph_DMA2), -void DMA1_Stream2_IRQHandler(void) -{ - dmaHandlers.dma1Stream2IRQHandler(DMA1_Stream2); -} +}; + +/* + * DMA IRQ Handlers + */ +DEFINE_DMA_IRQ_HANDLER(1, 1, DMA1_ST1_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 2, DMA1_ST2_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 3, DMA1_ST3_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 4, DMA1_ST4_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 5, DMA1_ST5_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 6, DMA1_ST6_HANDLER) +DEFINE_DMA_IRQ_HANDLER(1, 7, DMA1_ST7_HANDLER) +DEFINE_DMA_IRQ_HANDLER(2, 1, DMA2_ST1_HANDLER) +DEFINE_DMA_IRQ_HANDLER(2, 2, DMA2_ST2_HANDLER) +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) -void DMA1_Stream7_IRQHandler(void) -{ - dmaHandlers.dma1Stream7IRQHandler(DMA1_Stream7); -} void dmaInit(void) { - memset(&dmaHandlers, 0, sizeof(dmaHandlers)); - dmaHandlers.dma1Stream2IRQHandler = dmaNoOpHandler; - dmaHandlers.dma1Stream7IRQHandler = dmaNoOpHandler; + // TODO: Do we need this? } -void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback) +void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback, uint32_t priority, uint32_t userParam) { - switch (identifier) { - case DMA1_ST2_HANDLER: - dmaHandlers.dma1Stream2IRQHandler = callback; - break; - case DMA1_ST7_HANDLER: - dmaHandlers.dma1Stream7IRQHandler = callback; - break; - } + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(dmaDescriptors[identifier].rcc, ENABLE); + dmaDescriptors[identifier].irqHandlerCallback = callback; + dmaDescriptors[identifier].userParam = userParam; + + NVIC_InitStructure.NVIC_IRQChannel = dmaDescriptors[identifier].irqN; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(priority); + NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(priority); + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); } + diff --git a/src/main/drivers/light_ws2811strip.c b/src/main/drivers/light_ws2811strip.c index 5bd5857b56..05f0998927 100644 --- a/src/main/drivers/light_ws2811strip.c +++ b/src/main/drivers/light_ws2811strip.c @@ -163,4 +163,4 @@ void ws2811UpdateStrip(void) ws2811LedStripDMAEnable(); } -#endif \ No newline at end of file +#endif diff --git a/src/main/drivers/light_ws2811strip_stm32f10x.c b/src/main/drivers/light_ws2811strip_stm32f10x.c index 63c76baec4..96bb85fd26 100644 --- a/src/main/drivers/light_ws2811strip_stm32f10x.c +++ b/src/main/drivers/light_ws2811strip_stm32f10x.c @@ -32,12 +32,11 @@ static IO_t ws2811IO = IO_NONE; bool ws2811Initialised = false; -void ws2811DMAHandler(DMA_Channel_TypeDef *channel) -{ - if (DMA_GetFlagStatus(WS2811_DMA_TC_FLAG)) { +static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { ws2811LedDataTransferInProgress = 0; - DMA_Cmd(channel, DISABLE); - DMA_ClearFlag(WS2811_DMA_TC_FLAG); + DMA_Cmd(descriptor->channel, DISABLE); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); } } @@ -49,7 +48,7 @@ void ws2811LedStripHardwareInit(void) uint16_t prescalerValue; - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, ws2811DMAHandler); + dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ @@ -106,14 +105,6 @@ void ws2811LedStripHardwareInit(void) DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE); - NVIC_InitTypeDef NVIC_InitStructure; - - NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_WS2811_DMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - ws2811Initialised = true; setStripColor(&hsv_white); ws2811UpdateStrip(); @@ -130,4 +121,4 @@ void ws2811LedStripDMAEnable(void) DMA_Cmd(DMA1_Channel6, ENABLE); } -#endif \ No newline at end of file +#endif diff --git a/src/main/drivers/light_ws2811strip_stm32f30x.c b/src/main/drivers/light_ws2811strip_stm32f30x.c index 782be0a98d..ff52a64836 100644 --- a/src/main/drivers/light_ws2811strip_stm32f30x.c +++ b/src/main/drivers/light_ws2811strip_stm32f30x.c @@ -35,20 +35,17 @@ #define WS2811_PIN PB8 // TIM16_CH1 #define WS2811_TIMER TIM16 #define WS2811_DMA_CHANNEL DMA1_Channel3 -#define WS2811_IRQ DMA1_Channel3_IRQn -#define WS2811_DMA_TC_FLAG DMA1_FLAG_TC3 #define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH3_HANDLER #endif static IO_t ws2811IO = IO_NONE; bool ws2811Initialised = false; -void ws2811DMAHandler(DMA_Channel_TypeDef *channel) -{ - if (DMA_GetFlagStatus(WS2811_DMA_TC_FLAG)) { +static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { ws2811LedDataTransferInProgress = 0; - DMA_Cmd(channel, DISABLE); - DMA_ClearFlag(WS2811_DMA_TC_FLAG); + DMA_Cmd(descriptor->channel, DISABLE); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); } } @@ -60,7 +57,7 @@ void ws2811LedStripHardwareInit(void) uint16_t prescalerValue; - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, ws2811DMAHandler); + dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ @@ -92,9 +89,6 @@ void ws2811LedStripHardwareInit(void) TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); /* configure DMA */ - /* DMA clock enable */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); - /* DMA1 Channel Config */ DMA_DeInit(WS2811_DMA_CHANNEL); @@ -117,14 +111,6 @@ void ws2811LedStripHardwareInit(void) DMA_ITConfig(WS2811_DMA_CHANNEL, DMA_IT_TC, ENABLE); - NVIC_InitTypeDef NVIC_InitStructure; - - NVIC_InitStructure.NVIC_IRQChannel = WS2811_IRQ; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_WS2811_DMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - ws2811Initialised = true; setStripColor(&hsv_white); ws2811UpdateStrip(); @@ -141,4 +127,4 @@ void ws2811LedStripDMAEnable(void) DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE); } -#endif \ No newline at end of file +#endif diff --git a/src/main/drivers/light_ws2811strip_stm32f4xx.c b/src/main/drivers/light_ws2811strip_stm32f4xx.c index 1b4c646a45..3a888bd21b 100644 --- a/src/main/drivers/light_ws2811strip_stm32f4xx.c +++ b/src/main/drivers/light_ws2811strip_stm32f4xx.c @@ -22,8 +22,8 @@ #include "common/color.h" #include "light_ws2811strip.h" -#include "dma.h" #include "nvic.h" +#include "dma.h" #include "io.h" #include "system.h" #include "rcc.h" @@ -36,10 +36,8 @@ #define WS2811_TIMER TIM5 #define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER #define WS2811_DMA_STREAM DMA1_Stream2 -#define WS2811_DMA_FLAG DMA_FLAG_TCIF2 #define WS2811_DMA_IT DMA_IT_TCIF2 #define WS2811_DMA_CHANNEL DMA_Channel_6 -#define WS2811_DMA_IRQ DMA1_Stream2_IRQn #define WS2811_TIMER_CHANNEL TIM_Channel_1 #endif @@ -47,13 +45,13 @@ static IO_t ws2811IO = IO_NONE; static uint16_t timDMASource = 0; bool ws2811Initialised = false; -void ws2811DMAHandler(DMA_Stream_TypeDef *stream) +static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { - if (DMA_GetFlagStatus(stream, WS2811_DMA_FLAG)) { + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { ws2811LedDataTransferInProgress = 0; - DMA_ClearITPendingBit(stream, WS2811_DMA_IT); - DMA_Cmd(stream, DISABLE); - TIM_DMACmd(WS2811_TIMER, timDMASource, DISABLE); + DMA_Cmd(descriptor->stream, DISABLE); + TIM_DMACmd(TIM5, TIM_DMA_CC1, DISABLE); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); } } @@ -129,8 +127,6 @@ void ws2811LedStripHardwareInit(void) TIM_CCxCmd(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_CCx_Enable); TIM_Cmd(WS2811_TIMER, ENABLE); - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, ws2811DMAHandler); - /* configure DMA */ DMA_Cmd(WS2811_DMA_STREAM, DISABLE); DMA_DeInit(WS2811_DMA_STREAM); @@ -151,20 +147,12 @@ void ws2811LedStripHardwareInit(void) DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; - - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); DMA_Init(WS2811_DMA_STREAM, &DMA_InitStructure); DMA_ITConfig(WS2811_DMA_STREAM, DMA_IT_TC, ENABLE); DMA_ClearITPendingBit(WS2811_DMA_STREAM, WS2811_DMA_IT); - NVIC_InitTypeDef NVIC_InitStructure; - - NVIC_InitStructure.NVIC_IRQChannel = WS2811_DMA_IRQ; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_WS2811_DMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); ws2811Initialised = true; setStripColor(&hsv_white); diff --git a/src/main/drivers/max7456.c b/src/main/drivers/max7456.c index d71a933a5b..793f6f77eb 100644 --- a/src/main/drivers/max7456.c +++ b/src/main/drivers/max7456.c @@ -29,6 +29,8 @@ #include "drivers/bus_spi.h" #include "drivers/light_led.h" #include "drivers/system.h" +#include "drivers/nvic.h" +#include "drivers/dma.h" #include "max7456.h" #include "max7456_symbols.h" @@ -36,25 +38,116 @@ #define DISABLE_MAX7456 IOHi(max7456CsPin) #define ENABLE_MAX7456 IOLo(max7456CsPin) -/** Artificial Horizon limits **/ -#define AHIPITCHMAX 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees -#define AHIROLLMAX 400 // Specify maximum AHI roll value displayed. Default 400 = 40.0 degrees -#define AHISIDEBARWIDTHPOSITION 7 -#define AHISIDEBARHEIGHTPOSITION 3 - uint16_t max_screen_size; -char max7456_screen[VIDEO_BUFFER_CHARS_PAL]; +static MAX7456_CHAR_TYPE max7456_screen[VIDEO_BUFFER_CHARS_PAL + 5]; +#define SCREEN_BUFFER ((MAX7456_CHAR_TYPE*)&max7456_screen[3]) + +#ifdef MAX7456_DMA_CHANNEL_TX +volatile uint8_t dma_transaction_in_progress = 0; +#endif static uint8_t video_signal_type = 0; static uint8_t max7456_lock = 0; static IO_t max7456CsPin = IO_NONE; -uint8_t max7456_send(uint8_t add, uint8_t data) + +MAX7456_CHAR_TYPE* max7456_get_screen_buffer(void) { + return SCREEN_BUFFER; +} + +static uint8_t max7456_send(uint8_t add, uint8_t data) { spiTransferByte(MAX7456_SPI_INSTANCE, add); return spiTransferByte(MAX7456_SPI_INSTANCE, data); } +#ifdef MAX7456_DMA_CHANNEL_TX +static void max7456_send_dma(void* tx_buffer, void* rx_buffer, uint16_t buffer_size) { + DMA_InitTypeDef DMA_InitStructure; +#ifdef MAX7456_DMA_CHANNEL_RX + static uint16_t dummy[] = {0xffff}; +#else + UNUSED(rx_buffer); +#endif + while (dma_transaction_in_progress); // Wait for prev DMA transaction + + DMA_DeInit(MAX7456_DMA_CHANNEL_TX); +#ifdef MAX7456_DMA_CHANNEL_RX + DMA_DeInit(MAX7456_DMA_CHANNEL_RX); +#endif + + // Common to both channels + DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(MAX7456_SPI_INSTANCE->DR)); + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_BufferSize = buffer_size; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_Priority = DMA_Priority_Low; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + +#ifdef MAX7456_DMA_CHANNEL_RX + // Rx Channel + DMA_InitStructure.DMA_MemoryBaseAddr = rx_buffer ? (uint32_t)rx_buffer : (uint32_t)(dummy); + DMA_InitStructure.DMA_MemoryInc = rx_buffer ? DMA_MemoryInc_Enable : DMA_MemoryInc_Disable; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; + + DMA_Init(MAX7456_DMA_CHANNEL_RX, &DMA_InitStructure); + DMA_Cmd(MAX7456_DMA_CHANNEL_RX, ENABLE); +#endif + // Tx channel + + DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buffer; //max7456_screen; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; + + DMA_Init(MAX7456_DMA_CHANNEL_TX, &DMA_InitStructure); + DMA_Cmd(MAX7456_DMA_CHANNEL_TX, ENABLE); + +#ifdef MAX7456_DMA_CHANNEL_RX + DMA_ITConfig(MAX7456_DMA_CHANNEL_RX, DMA_IT_TC, ENABLE); +#else + DMA_ITConfig(MAX7456_DMA_CHANNEL_TX, DMA_IT_TC, ENABLE); +#endif + + // Enable SPI TX/RX request + ENABLE_MAX7456; + dma_transaction_in_progress = 1; + + SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE, +#ifdef MAX7456_DMA_CHANNEL_RX + SPI_I2S_DMAReq_Rx | +#endif + SPI_I2S_DMAReq_Tx, ENABLE); +} + +void max7456_dma_irq_handler(dmaChannelDescriptor_t* descriptor) { + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { +#ifdef MAX7456_DMA_CHANNEL_RX + DMA_Cmd(MAX7456_DMA_CHANNEL_RX, DISABLE); +#else + //Empty RX buffer. RX DMA takes care of it if enabled + while (SPI_I2S_GetFlagStatus(MAX7456_SPI_INSTANCE, SPI_I2S_FLAG_RXNE) == SET) { + MAX7456_SPI_INSTANCE->DR; + } +#endif + DMA_Cmd(MAX7456_DMA_CHANNEL_TX, DISABLE); + + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); + + SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE, +#ifdef MAX7456_DMA_CHANNEL_RX + SPI_I2S_DMAReq_Rx | +#endif + SPI_I2S_DMAReq_Tx, DISABLE); + + DISABLE_MAX7456; + for (uint16_t x = 0; x < max_screen_size; x++) + max7456_screen[x + 3] = MAX7456_CHAR(' '); + dma_transaction_in_progress = 0; + } +} +#endif void max7456_init(uint8_t video_system) { @@ -113,94 +206,66 @@ void max7456_init(uint8_t video_system) DISABLE_MAX7456; delay(100); + + for (x = 0; x < max_screen_size; x++) + SCREEN_BUFFER[x] = MAX7456_CHAR(' '); + +#ifdef MAX7456_DMA_CHANNEL_TX + max7456_screen[0] = (uint16_t)(MAX7456ADD_DMAH | (0 << 8)); + max7456_screen[1] = (uint16_t)(MAX7456ADD_DMAL | (0 << 8)); + max7456_screen[2] = (uint16_t)(MAX7456ADD_DMM | (1 << 8)); + max7456_screen[max_screen_size + 3] = (uint16_t)(MAX7456ADD_DMDI | (0xFF << 8)); + max7456_screen[max_screen_size + 4] = (uint16_t)(MAX7456ADD_DMM | (0 << 8)); + + dmaSetHandler(MAX7456_DMA_IRQ_HANDLER_ID, max7456_dma_irq_handler, NVIC_PRIO_MAX7456_DMA, 0); +#endif } // Copy string from ram into screen buffer void max7456_write_string(const char *string, int16_t address) { - char *dest; + MAX7456_CHAR_TYPE *dest; if (address >= 0) - dest = max7456_screen + address; + dest = SCREEN_BUFFER + address; else - dest = max7456_screen + (max_screen_size + address); + dest = SCREEN_BUFFER + (max_screen_size + address); - while(*string && dest < (max7456_screen + max_screen_size)) - *dest++ = *string++; -} - - -// Write the artifical horizon to the screen buffer -void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars) { - uint16_t position = 194; - - if(pitchAngle>AHIPITCHMAX) pitchAngle=AHIPITCHMAX; - if(pitchAngle<-AHIPITCHMAX) pitchAngle=-AHIPITCHMAX; - if(rollAngle>AHIROLLMAX) rollAngle=AHIROLLMAX; - if(rollAngle<-AHIROLLMAX) rollAngle=-AHIROLLMAX; - - for(uint8_t X=0; X<=8; X++) { - if (X==4) X=5; - int Y = (rollAngle * (4-X)) / 64; - Y -= pitchAngle / 8; - Y += 41; - if(Y >= 0 && Y <= 81) { - uint16_t pos = position -7 + LINE*(Y/9) + 3 - 4*LINE + X; - max7456_screen[pos] = SYM_AH_BAR9_0+(Y%9); - } - } - max7456_screen[position-1] = SYM_AH_CENTER_LINE; - max7456_screen[position+1] = SYM_AH_CENTER_LINE_RIGHT; - max7456_screen[position] = SYM_AH_CENTER; - - if (show_sidebars) { - // Draw AH sides - int8_t hudwidth = AHISIDEBARWIDTHPOSITION; - int8_t hudheight = AHISIDEBARHEIGHTPOSITION; - for(int8_t X=-hudheight; X<=hudheight; X++) { - max7456_screen[position-hudwidth+(X*LINE)] = SYM_AH_DECORATION; - max7456_screen[position+hudwidth+(X*LINE)] = SYM_AH_DECORATION; - } - // AH level indicators - max7456_screen[position-hudwidth+1] = SYM_AH_LEFT; - max7456_screen[position+hudwidth-1] = SYM_AH_RIGHT; + while(*string && dest < (SCREEN_BUFFER + max_screen_size)) { + *dest++ = MAX7456_CHAR(*string++); } } void max7456_draw_screen(void) { - uint16_t xx; if (!max7456_lock) { - ENABLE_MAX7456; - for (xx = 0; xx < max_screen_size; ++xx) { - max7456_send(MAX7456ADD_DMAH, xx>>8); - max7456_send(MAX7456ADD_DMAL, xx); - max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]); - max7456_screen[xx] = ' '; - } - DISABLE_MAX7456; - } -} +#ifdef MAX7456_DMA_CHANNEL_TX + max7456_send_dma(max7456_screen, NULL, max_screen_size * 2 + 10); +#else + uint16_t xx; + max7456_lock = 1; -void max7456_draw_screen_fast(void) { - uint16_t xx; - if (!max7456_lock) { ENABLE_MAX7456; max7456_send(MAX7456ADD_DMAH, 0); max7456_send(MAX7456ADD_DMAL, 0); max7456_send(MAX7456ADD_DMM, 1); for (xx = 0; xx < max_screen_size; ++xx) { - max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]); - max7456_screen[xx] = ' '; + max7456_send(MAX7456ADD_DMDI, SCREEN_BUFFER[xx]); + SCREEN_BUFFER[xx] = MAX7456_CHAR(0); } max7456_send(MAX7456ADD_DMDI, 0xFF); max7456_send(MAX7456ADD_DMM, 0); DISABLE_MAX7456; + max7456_lock = 0; +#endif } } - void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) { uint8_t x; +#ifdef MAX7456_DMA_CHANNEL_TX + while (dma_transaction_in_progress); +#endif + while (max7456_lock); max7456_lock = 1; ENABLE_MAX7456; diff --git a/src/main/drivers/max7456.h b/src/main/drivers/max7456.h index 1e04320a88..5ba902ba5a 100644 --- a/src/main/drivers/max7456.h +++ b/src/main/drivers/max7456.h @@ -143,12 +143,18 @@ enum VIDEO_TYPES { AUTO = 0, PAL, NTSC }; extern uint16_t max_screen_size; -extern char max7456_screen[VIDEO_BUFFER_CHARS_PAL]; +#ifdef MAX7456_DMA_CHANNEL_TX + #define MAX7456_CHAR_TYPE uint16_t + #define MAX7456_CHAR(X) (MAX7456ADD_DMDI | ((X) << 8)) +#else + #define MAX7456_CHAR_TYPE char + #define MAX7456_CHAR(X) (X) +#endif void max7456_init(uint8_t system); void max7456_draw_screen(void); -void max7456_draw_screen_fast(void); -void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars); void max7456_write_string(const char *string, int16_t address); void max7456_write_nvm(uint8_t char_address, uint8_t *font_data); +MAX7456_CHAR_TYPE* max7456_get_screen_buffer(void); + diff --git a/src/main/drivers/nvic.h b/src/main/drivers/nvic.h index 7c4b9c7cd4..9712f89153 100644 --- a/src/main/drivers/nvic.h +++ b/src/main/drivers/nvic.h @@ -38,6 +38,7 @@ #define NVIC_PRIO_MPU_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f) #define NVIC_PRIO_MAG_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f) #define NVIC_PRIO_CALLBACK NVIC_BUILD_PRIORITY(0x0f, 0x0f) +#define NVIC_PRIO_MAX7456_DMA NVIC_BUILD_PRIORITY(3, 0) // utility macros to join/split priority #define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING>>8))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING>>8)))))<<4)&0xf0) diff --git a/src/main/drivers/serial_uart_stm32f10x.c b/src/main/drivers/serial_uart_stm32f10x.c index 0a8515dc88..330b3f837a 100644 --- a/src/main/drivers/serial_uart_stm32f10x.c +++ b/src/main/drivers/serial_uart_stm32f10x.c @@ -31,6 +31,7 @@ #include "system.h" #include "io.h" #include "nvic.h" +#include "dma.h" #include "rcc.h" #include "serial.h" @@ -76,6 +77,19 @@ void uartIrqCallback(uartPort_t *s) } } +// USART1 Tx DMA Handler +void uart_tx_dma_IRQHandler(dmaChannelDescriptor_t* descriptor) +{ + uartPort_t *s = (uartPort_t*)(descriptor->userParam); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); + DMA_Cmd(descriptor->channel, DISABLE); + + if (s->port.txBufferHead != s->port.txBufferTail) + uartStartTxDMA(s); + else + s->txDMAEmpty = true; +} + #ifdef USE_UART1 // USART1 - Telemetry (RX/TX by DMA) uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t options) @@ -84,8 +98,6 @@ uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t option static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE]; static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE]; - NVIC_InitTypeDef NVIC_InitStructure; - s = &uartPort1; s->port.vTable = uartVTable; @@ -127,14 +139,12 @@ uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t option } // DMA TX Interrupt - NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + dmaSetHandler(DMA1_CH4_HANDLER, uart_tx_dma_IRQHandler, NVIC_PRIO_SERIALUART1_TXDMA, (uint32_t)&uartPort1); #ifndef USE_UART1_RX_DMA // RX/TX Interrupt + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1); @@ -145,19 +155,6 @@ uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t option return s; } -// USART1 Tx DMA Handler -void DMA1_Channel4_IRQHandler(void) -{ - uartPort_t *s = &uartPort1; - DMA_ClearITPendingBit(DMA1_IT_TC4); - DMA_Cmd(s->txDMAChannel, DISABLE); - - if (s->port.txBufferHead != s->port.txBufferTail) - uartStartTxDMA(s); - else - s->txDMAEmpty = true; -} - // USART1 Rx/Tx IRQ Handler void USART1_IRQHandler(void) { diff --git a/src/main/drivers/serial_uart_stm32f30x.c b/src/main/drivers/serial_uart_stm32f30x.c index ae7516979c..ee65d54d2d 100644 --- a/src/main/drivers/serial_uart_stm32f30x.c +++ b/src/main/drivers/serial_uart_stm32f30x.c @@ -32,6 +32,7 @@ #include "system.h" #include "io.h" #include "nvic.h" +#include "dma.h" #include "rcc.h" #include "serial.h" @@ -99,6 +100,18 @@ static uartPort_t uartPort4; static uartPort_t uartPort5; #endif +static void handleUsartTxDma(dmaChannelDescriptor_t* descriptor) +{ + uartPort_t *s = (uartPort_t*)(descriptor->userParam); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); + DMA_Cmd(descriptor->channel, DISABLE); + + if (s->port.txBufferHead != s->port.txBufferTail) + uartStartTxDMA(s); + else + s->txDMAEmpty = true; +} + void serialUARTInit(IO_t tx, IO_t rx, portMode_t mode, portOptions_t options, uint8_t af, uint8_t index) { if (options & SERIAL_BIDIR) { @@ -132,7 +145,6 @@ uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t option uartPort_t *s; static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE]; static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE]; - NVIC_InitTypeDef NVIC_InitStructure; s = &uartPort1; s->port.vTable = uartVTable; @@ -159,14 +171,11 @@ uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t option serialUARTInit(IOGetByTag(IO_TAG(UART1_TX_PIN)), IOGetByTag(IO_TAG(UART1_RX_PIN)), mode, options, GPIO_AF_7, 1); - // DMA TX Interrupt - NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + dmaSetHandler(DMA1_CH4_HANDLER, handleUsartTxDma, NVIC_PRIO_SERIALUART1_TXDMA, (uint32_t)&uartPort1); #ifndef USE_UART1_RX_DMA + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_RXDMA); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_RXDMA); @@ -184,7 +193,6 @@ uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t option uartPort_t *s; static volatile uint8_t rx2Buffer[UART2_RX_BUFFER_SIZE]; static volatile uint8_t tx2Buffer[UART2_TX_BUFFER_SIZE]; - NVIC_InitTypeDef NVIC_InitStructure; s = &uartPort2; s->port.vTable = uartVTable; @@ -217,14 +225,12 @@ uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t option #ifdef USE_UART2_TX_DMA // DMA TX Interrupt - NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + dmaSetHandler(DMA1_CH7_HANDLER, handleUsartTxDma, NVIC_PRIO_SERIALUART2_TXDMA, (uint32_t)&uartPort2); #endif #ifndef USE_UART2_RX_DMA + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2_RXDMA); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2_RXDMA); @@ -242,7 +248,6 @@ uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t option uartPort_t *s; static volatile uint8_t rx3Buffer[UART3_RX_BUFFER_SIZE]; static volatile uint8_t tx3Buffer[UART3_TX_BUFFER_SIZE]; - NVIC_InitTypeDef NVIC_InitStructure; s = &uartPort3; s->port.vTable = uartVTable; @@ -275,14 +280,12 @@ uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t option #ifdef USE_UART3_TX_DMA // DMA TX Interrupt - NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART3_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART3_TXDMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + dmaSetHandler(DMA1_CH2_HANDLER, handleUsartTxDma, NVIC_PRIO_SERIALUART3_TXDMA, (uint32_t)&uartPort3); #endif #ifndef USE_UART3_RX_DMA + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART3_RXDMA); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART3_RXDMA); @@ -362,48 +365,6 @@ uartPort_t *serialUART5(uint32_t baudRate, portMode_t mode, portOptions_t option } #endif -static void handleUsartTxDma(uartPort_t *s) -{ - DMA_Cmd(s->txDMAChannel, DISABLE); - - if (s->port.txBufferHead != s->port.txBufferTail) - uartStartTxDMA(s); - else - s->txDMAEmpty = true; -} - -// USART1 Tx DMA Handler -void DMA1_Channel4_IRQHandler(void) -{ - uartPort_t *s = &uartPort1; - DMA_ClearITPendingBit(DMA1_IT_TC4); - DMA_Cmd(DMA1_Channel4, DISABLE); - handleUsartTxDma(s); -} - -#ifdef USE_UART2_TX_DMA -// USART2 Tx DMA Handler -void DMA1_Channel7_IRQHandler(void) -{ - uartPort_t *s = &uartPort2; - DMA_ClearITPendingBit(DMA1_IT_TC7); - DMA_Cmd(DMA1_Channel7, DISABLE); - handleUsartTxDma(s); -} -#endif - -// USART3 Tx DMA Handler -#ifdef USE_UART3_TX_DMA -void DMA1_Channel2_IRQHandler(void) -{ - uartPort_t *s = &uartPort3; - DMA_ClearITPendingBit(DMA1_IT_TC2); - DMA_Cmd(DMA1_Channel2, DISABLE); - handleUsartTxDma(s); -} -#endif - - void usartIrqHandler(uartPort_t *s) { uint32_t ISR = s->USARTx->ISR; diff --git a/src/main/drivers/serial_uart_stm32f4xx.c b/src/main/drivers/serial_uart_stm32f4xx.c index d689426215..91577628b0 100644 --- a/src/main/drivers/serial_uart_stm32f4xx.c +++ b/src/main/drivers/serial_uart_stm32f4xx.c @@ -25,6 +25,7 @@ #include "io.h" #include "rcc.h" #include "nvic.h" +#include "dma.h" #include "serial.h" #include "serial_uart.h" @@ -79,7 +80,7 @@ static uartDevice_t uart1 = .rcc_ahb1 = UART1_AHB1_PERIPHERALS, #endif .rcc_apb2 = RCC_APB2(USART1), - .txIrq = DMA2_Stream7_IRQn, + .txIrq = DMA2_ST7_HANDLER, .rxIrq = USART1_IRQn, .txPriority = NVIC_PRIO_SERIALUART1_TXDMA, .rxPriority = NVIC_PRIO_SERIALUART1 @@ -102,7 +103,7 @@ static uartDevice_t uart2 = .rcc_ahb1 = UART2_AHB1_PERIPHERALS, #endif .rcc_apb1 = RCC_APB1(USART2), - .txIrq = DMA1_Stream6_IRQn, + .txIrq = DMA1_ST6_HANDLER, .rxIrq = USART2_IRQn, .txPriority = NVIC_PRIO_SERIALUART2_TXDMA, .rxPriority = NVIC_PRIO_SERIALUART2 @@ -125,7 +126,7 @@ static uartDevice_t uart3 = .rcc_ahb1 = UART3_AHB1_PERIPHERALS, #endif .rcc_apb1 = RCC_APB1(USART3), - .txIrq = DMA1_Stream3_IRQn, + .txIrq = DMA1_ST3_HANDLER, .rxIrq = USART3_IRQn, .txPriority = NVIC_PRIO_SERIALUART3_TXDMA, .rxPriority = NVIC_PRIO_SERIALUART3 @@ -148,7 +149,7 @@ static uartDevice_t uart4 = .rcc_ahb1 = UART4_AHB1_PERIPHERALS, #endif .rcc_apb1 = RCC_APB1(UART4), - .txIrq = DMA1_Stream4_IRQn, + .txIrq = DMA1_ST4_HANDLER, .rxIrq = UART4_IRQn, .txPriority = NVIC_PRIO_SERIALUART4_TXDMA, .rxPriority = NVIC_PRIO_SERIALUART4 @@ -171,7 +172,7 @@ static uartDevice_t uart5 = .rcc_ahb1 = UART5_AHB1_PERIPHERALS, #endif .rcc_apb1 = RCC_APB1(UART5), - .txIrq = DMA2_Stream7_IRQn, + .txIrq = DMA2_ST7_HANDLER, .rxIrq = UART5_IRQn, .txPriority = NVIC_PRIO_SERIALUART5_TXDMA, .rxPriority = NVIC_PRIO_SERIALUART5 @@ -194,7 +195,7 @@ static uartDevice_t uart6 = .rcc_ahb1 = UART6_AHB1_PERIPHERALS, #endif .rcc_apb2 = RCC_APB2(USART6), - .txIrq = DMA2_Stream6_IRQn, + .txIrq = DMA2_ST6_HANDLER, .rxIrq = USART6_IRQn, .txPriority = NVIC_PRIO_SERIALUART6_TXDMA, .rxPriority = NVIC_PRIO_SERIALUART6 @@ -270,6 +271,29 @@ static void handleUsartTxDma(uartPort_t *s) s->txDMAEmpty = true; } +void dmaIRQHandler(dmaChannelDescriptor_t* descriptor) +{ + uartPort_t *s = &(((uartDevice_t*)(descriptor->userParam))->port); + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) + { + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); + DMA_CLEAR_FLAG(descriptor, DMA_IT_HTIF); + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_FEIF)) + { + DMA_CLEAR_FLAG(descriptor, DMA_IT_FEIF); + } + handleUsartTxDma(s); + } + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TEIF)) + { + DMA_CLEAR_FLAG(descriptor, DMA_IT_TEIF); + } + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_DMEIF)) + { + DMA_CLEAR_FLAG(descriptor, DMA_IT_DMEIF); + } +} + uartPort_t *serialUART(UARTDevice device, uint32_t baudRate, portMode_t mode, portOptions_t options) { uartPort_t *s; @@ -328,11 +352,7 @@ uartPort_t *serialUART(UARTDevice device, uint32_t baudRate, portMode_t mode, po } // DMA TX Interrupt - NVIC_InitStructure.NVIC_IRQChannel = uart->txIrq; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(uart->txPriority); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(uart->txPriority); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + dmaSetHandler(uart->txIrq, dmaIRQHandler, uart->txPriority, (uint32_t)uart); if (!(s->rxDMAChannel)) { NVIC_InitStructure.NVIC_IRQChannel = uart->rxIrq; @@ -351,30 +371,6 @@ uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t option return serialUART(UARTDEV_1, baudRate, mode, options); } -// USART1 Tx DMA Handler -void DMA2_Stream7_IRQHandler(void) -{ - uartPort_t *s = &(uartHardwareMap[UARTDEV_1]->port); - if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF7)) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF7); - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF7); - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF7)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF7); - } - handleUsartTxDma(s); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF7)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF7); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF7)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF7); - } -} - // USART1 Rx/Tx IRQ Handler void USART1_IRQHandler(void) { @@ -390,30 +386,6 @@ uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t option return serialUART(UARTDEV_2, baudRate, mode, options); } -// USART2 Tx DMA Handler -void DMA1_Stream6_IRQHandler(void) -{ - uartPort_t *s = &(uartHardwareMap[UARTDEV_2]->port); - if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF6)) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF6); - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF6); - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF6)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF6); - } - handleUsartTxDma(s); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF6)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF6); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF6)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF6); - } -} - void USART2_IRQHandler(void) { uartPort_t *s = &(uartHardwareMap[UARTDEV_2]->port); @@ -428,30 +400,6 @@ uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t option return serialUART(UARTDEV_3, baudRate, mode, options); } -// USART3 Tx DMA Handler -void DMA1_Stream3_IRQHandler(void) -{ - uartPort_t *s = &(uartHardwareMap[UARTDEV_3]->port); - if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF3)) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF3); - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF3); - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF3)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF3); - } - handleUsartTxDma(s); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF3)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF3); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF3)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF3); - } -} - void USART3_IRQHandler(void) { uartPort_t *s = &(uartHardwareMap[UARTDEV_3]->port); @@ -466,30 +414,6 @@ uartPort_t *serialUART4(uint32_t baudRate, portMode_t mode, portOptions_t option return serialUART(UARTDEV_4, baudRate, mode, options); } -// USART4 Tx DMA Handler -void DMA1_Stream4_IRQHandler(void) -{ - uartPort_t *s = &(uartHardwareMap[UARTDEV_4]->port); - if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF4)) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF4); - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF4); - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF4)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF4); - } - handleUsartTxDma(s); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF4)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF4); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF4)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF4); - } -} - void UART4_IRQHandler(void) { uartPort_t *s = &(uartHardwareMap[UARTDEV_4]->port); @@ -504,30 +428,6 @@ uartPort_t *serialUART5(uint32_t baudRate, portMode_t mode, portOptions_t option return serialUART(UARTDEV_5, baudRate, mode, options); } -// USART5 Tx DMA Handler -void DMA1_Stream7_IRQHandler(void) -{ - uartPort_t *s = &(uartHardwareMap[UARTDEV_5]->port); - if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF7)) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF7); - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF7); - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF7)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF7); - } - handleUsartTxDma(s); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF7)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF7); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF7)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF7); - } -} - void UART5_IRQHandler(void) { uartPort_t *s = &(uartHardwareMap[UARTDEV_5]->port); @@ -542,30 +442,6 @@ uartPort_t *serialUART6(uint32_t baudRate, portMode_t mode, portOptions_t option return serialUART(UARTDEV_6, baudRate, mode, options); } -// USART6 Tx DMA Handler -void DMA2_Stream6_IRQHandler(void) -{ - uartPort_t *s = &(uartHardwareMap[UARTDEV_6]->port); - if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF6)) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF6); - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF6); - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF6)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF6); - } - handleUsartTxDma(s); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF6)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF6); - } - if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF6)==SET) - { - DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF6); - } -} - void USART6_IRQHandler(void) { uartPort_t *s = &(uartHardwareMap[UARTDEV_6]->port); diff --git a/src/main/drivers/transponder_ir.c b/src/main/drivers/transponder_ir.c index 51d47e44e5..8e95ac33bf 100644 --- a/src/main/drivers/transponder_ir.c +++ b/src/main/drivers/transponder_ir.c @@ -38,19 +38,19 @@ uint8_t transponderIrDMABuffer[TRANSPONDER_DMA_BUFFER_SIZE]; volatile uint8_t transponderIrDataTransferInProgress = 0; -void transponderDMAHandler(DMA_Channel_TypeDef *channel) +void transponderDMAHandler(dmaChannelDescriptor_t* descriptor) { - if (DMA_GetFlagStatus(TRANSPONDER_DMA_TC_FLAG)) { + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { transponderIrDataTransferInProgress = 0; - DMA_Cmd(channel, DISABLE); - DMA_ClearFlag(TRANSPONDER_DMA_TC_FLAG); + DMA_Cmd(descriptor->channel, DISABLE); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); } } void transponderIrInit(void) { memset(&transponderIrDMABuffer, 0, TRANSPONDER_DMA_BUFFER_SIZE); - dmaSetHandler(TRANSPONDER_DMA_HANDLER_IDENTIFER, transponderDMAHandler); + dmaSetHandler(TRANSPONDER_DMA_HANDLER_IDENTIFER, transponderDMAHandler, NVIC_PRIO_TRANSPONDER_DMA, 0); transponderIrHardwareInit(); } diff --git a/src/main/drivers/transponder_ir_stm32f30x.c b/src/main/drivers/transponder_ir_stm32f30x.c index d41e3aa8c8..3962e1c999 100644 --- a/src/main/drivers/transponder_ir_stm32f30x.c +++ b/src/main/drivers/transponder_ir_stm32f30x.c @@ -86,7 +86,7 @@ void transponderIrHardwareInit(void) /* configure DMA */ /* DMA clock enable */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); + //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* DMA1 Channel6 Config */ DMA_DeInit(TRANSPONDER_DMA_CHANNEL); @@ -110,13 +110,6 @@ void transponderIrHardwareInit(void) DMA_ITConfig(TRANSPONDER_DMA_CHANNEL, DMA_IT_TC, ENABLE); - NVIC_InitTypeDef NVIC_InitStructure; - - NVIC_InitStructure.NVIC_IRQChannel = TRANSPONDER_IRQ; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_TRANSPONDER_DMA); - NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_TRANSPONDER_DMA); - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); } void transponderIrDMAEnable(void) diff --git a/src/main/io/osd.c b/src/main/io/osd.c index 69f3f56911..ea458e66ee 100644 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -121,6 +121,11 @@ #define STICKMIN 10 #define STICKMAX 90 +/** Artificial Horizon limits **/ +#define AHIPITCHMAX 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees +#define AHIROLLMAX 400 // Specify maximum AHI roll value displayed. Default 400 = 40.0 degrees +#define AHISIDEBARWIDTHPOSITION 7 +#define AHISIDEBARHEIGHTPOSITION 3 static uint32_t next_osd_update_at = 0; static uint32_t armed_seconds = 0; @@ -193,6 +198,23 @@ void print_vtx_freq(uint16_t pos, uint8_t col) { sprintf(string_buffer, "%d M", vtx_freq[current_vtx_channel]); max7456_write_string(string_buffer, pos); } + +void update_vtx_power(int value_change_direction, uint8_t col) { + UNUSED(col); + if (value_change_direction) { + masterConfig.vtx_power = 0; + } else { + masterConfig.vtx_power = 1; + } + rtc6705_soft_spi_set_rf_power(masterConfig.vtx_power); +} + +void print_vtx_power(uint16_t pos, uint8_t col) { + UNUSED(col); + sprintf(string_buffer, "%s", masterConfig.vtx_power ? "25MW" : "200MW"); + max7456_write_string(string_buffer, pos); +} + #endif void print_pid(uint16_t pos, uint8_t col, int pid_term) { @@ -399,7 +421,7 @@ osd_page_t menu_pages[] = { { .title = "VTX SETTINGS", .cols_number = 1, - .rows_number = 3, + .rows_number = 4, .cols = { { .title = NULL, @@ -421,6 +443,11 @@ osd_page_t menu_pages[] = { .title = "FREQUENCY", .update = NULL, .print = print_vtx_freq + }, + { + .title = "POWER", + .update = update_vtx_power, + .print = print_vtx_power } } }, @@ -627,10 +654,52 @@ void show_menu(void) { max7456_write_string(">", cursor_x + cursor_y * OSD_LINE_LENGTH); } +// Write the artifical horizon to the screen buffer +void osdDrawArtificialHorizon(int rollAngle, int pitchAngle, uint8_t show_sidebars) { + uint16_t position = 194; + MAX7456_CHAR_TYPE *screenBuffer = max7456_get_screen_buffer(); + + if (pitchAngle > AHIPITCHMAX) + pitchAngle = AHIPITCHMAX; + if (pitchAngle < -AHIPITCHMAX) + pitchAngle = -AHIPITCHMAX; + if (rollAngle > AHIROLLMAX) + rollAngle = AHIROLLMAX; + if (rollAngle < -AHIROLLMAX) + rollAngle = -AHIROLLMAX; + + for (uint8_t X = 0; X <= 8; X++) { + if (X == 4) + X = 5; + int Y = (rollAngle * (4 - X)) / 64; + Y -= pitchAngle / 8; + Y += 41; + if (Y >= 0 && Y <= 81) { + uint16_t pos = position - 7 + LINE * (Y / 9) + 3 - 4 * LINE + X; + screenBuffer[pos] = MAX7456_CHAR(SYM_AH_BAR9_0 + (Y % 9)); + } + } + screenBuffer[position - 1] = MAX7456_CHAR(SYM_AH_CENTER_LINE); + screenBuffer[position + 1] = MAX7456_CHAR(SYM_AH_CENTER_LINE_RIGHT); + screenBuffer[position] = MAX7456_CHAR(SYM_AH_CENTER); + + if (show_sidebars) { + // Draw AH sides + int8_t hudwidth = AHISIDEBARWIDTHPOSITION; + int8_t hudheight = AHISIDEBARHEIGHTPOSITION; + for (int8_t X = -hudheight; X <= hudheight; X++) { + screenBuffer[position - hudwidth + (X * LINE)] = MAX7456_CHAR(SYM_AH_DECORATION); + screenBuffer[position + hudwidth + (X * LINE)] = MAX7456_CHAR(SYM_AH_DECORATION); + } + // AH level indicators + screenBuffer[position-hudwidth+1] = MAX7456_CHAR(SYM_AH_LEFT); + screenBuffer[position+hudwidth-1] = MAX7456_CHAR(SYM_AH_RIGHT); + } +} + void updateOsd(void) { - static uint8_t skip = 0; - static bool blink = false; + static uint8_t blink = 0; static uint8_t arming = 0; uint32_t seconds; char line[30]; @@ -641,89 +710,86 @@ void updateOsd(void) return; } next_osd_update_at = now + OSD_UPDATE_FREQUENCY; - if ( !(skip % 2)) - blink = !blink; + blink++; - if (skip++ & 1) { - if (ARMING_FLAG(ARMED)) { - if (!armed) { - armed = true; - armed_at = now; - in_menu = false; - arming = 5; - } - } else { - if (armed) { - armed = false; - armed_seconds += ((now - armed_at) / 1000000); - } - for (uint8_t channelIndex = 0; channelIndex < 4; channelIndex++) { - sticks[channelIndex] = (constrain(rcData[channelIndex], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN); - } - if (!in_menu && sticks[YAW] > STICKMAX && sticks[THROTTLE] > STICKMIN && sticks[THROTTLE] < STICKMAX && sticks[ROLL] > STICKMIN && sticks[ROLL] < STICKMAX && sticks[PITCH] > STICKMAX) { - in_menu = true; - cursor_row = 255; - cursor_col = 2; - activating_menu = true; - } - } - if (in_menu) { - show_menu(); - } else { - if (batteryWarningVoltage > vbat && blink && masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING] != -1) { - max7456_write_string("LOW VOLTAGE", masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING]); - } - if (arming && blink && masterConfig.osdProfile.item_pos[OSD_ARMED] != -1) { - max7456_write_string("ARMED", masterConfig.osdProfile.item_pos[OSD_ARMED]); - arming--; - } - if (!armed && masterConfig.osdProfile.item_pos[OSD_DISARMED] != -1) { - max7456_write_string("DISARMED", masterConfig.osdProfile.item_pos[OSD_DISARMED]); - } - - if (masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] != -1) { - line[0] = SYM_VOLT; - sprintf(line+1, "%d.%1d", vbat / 10, vbat % 10); - max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE]); - } - if (masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] != -1) { - line[0] = SYM_RSSI; - sprintf(line+1, "%d", rssi / 10); - max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE]); - } - if (masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] != -1) { - line[0] = SYM_THR; - line[1] = SYM_THR1; - sprintf(line+2, "%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN)); - max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS]); - } - if (masterConfig.osdProfile.item_pos[OSD_TIMER] != -1) { - if (armed) { - seconds = armed_seconds + ((now-armed_at) / 1000000); - line[0] = SYM_FLY_M; - sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60); - } else { - line[0] = SYM_ON_M; - seconds = now / 1000000; - sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60); - } - max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_TIMER]); - } - if (masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] != -1) { - print_average_system_load(masterConfig.osdProfile.item_pos[OSD_CPU_LOAD], 0); - } - if (masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON] != -1) { - max7456_artificial_horizon(attitude.values.roll, attitude.values.pitch, masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS] != -1); - } + if (ARMING_FLAG(ARMED)) { + if (!armed) { + armed = true; + armed_at = now; + in_menu = false; + arming = 5; } } else { - max7456_draw_screen_fast(); + if (armed) { + armed = false; + armed_seconds += ((now - armed_at) / 1000000); + } + for (uint8_t channelIndex = 0; channelIndex < 4; channelIndex++) { + sticks[channelIndex] = (constrain(rcData[channelIndex], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN); + } + if (!in_menu && sticks[YAW] > STICKMAX && sticks[THROTTLE] > STICKMIN && sticks[THROTTLE] < STICKMAX && sticks[ROLL] > STICKMIN && sticks[ROLL] < STICKMAX && sticks[PITCH] > STICKMAX) { + in_menu = true; + cursor_row = 255; + cursor_col = 2; + activating_menu = true; + } } + if (in_menu) { + show_menu(); + } else { + if (batteryWarningVoltage > vbat && (blink & 1) && masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING] != -1) { + max7456_write_string("LOW VOLTAGE", masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING]); + } + if (arming && (blink & 1) && masterConfig.osdProfile.item_pos[OSD_ARMED] != -1) { + max7456_write_string("ARMED", masterConfig.osdProfile.item_pos[OSD_ARMED]); + arming--; + } + if (!armed && masterConfig.osdProfile.item_pos[OSD_DISARMED] != -1) { + max7456_write_string("DISARMED", masterConfig.osdProfile.item_pos[OSD_DISARMED]); + } + + if (masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] != -1) { + line[0] = SYM_VOLT; + sprintf(line+1, "%d.%1d", vbat / 10, vbat % 10); + max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE]); + } + if (masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] != -1) { + line[0] = SYM_RSSI; + sprintf(line+1, "%d", rssi / 10); + max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE]); + } + if (masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] != -1) { + line[0] = SYM_THR; + line[1] = SYM_THR1; + sprintf(line+2, "%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN)); + max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS]); + } + if (masterConfig.osdProfile.item_pos[OSD_TIMER] != -1) { + if (armed) { + seconds = armed_seconds + ((now-armed_at) / 1000000); + line[0] = SYM_FLY_M; + sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60); + } else { + line[0] = SYM_ON_M; + seconds = now / 1000000; + sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60); + } + max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_TIMER]); + } + if (masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] != -1) { + print_average_system_load(masterConfig.osdProfile.item_pos[OSD_CPU_LOAD], 0); + } + if (masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON] != -1) { + osdDrawArtificialHorizon(attitude.values.roll, attitude.values.pitch, masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS] != -1); + } + } + max7456_draw_screen(); } void osdInit(void) { uint16_t x; + MAX7456_CHAR_TYPE* screen_buffer = max7456_get_screen_buffer(); max7456_init(masterConfig.osdProfile.video_system); @@ -731,7 +797,8 @@ void osdInit(void) x = 160; for (int i = 1; i < 5; i++) { for (int j = 3; j < 27; j++) - max7456_screen[i * LINE + j] = (char)x++; + if (x != 255) + screen_buffer[(i * LINE + j)] = MAX7456_CHAR(x++); } sprintf(string_buffer, "BF VERSION: %s", FC_VERSION_STRING); max7456_write_string(string_buffer, LINE06 + 5); diff --git a/src/main/target/OMNIBUS/target.h b/src/main/target/OMNIBUS/target.h index dedb5de7ee..bab30522f7 100644 --- a/src/main/target/OMNIBUS/target.h +++ b/src/main/target/OMNIBUS/target.h @@ -109,7 +109,9 @@ #define USE_MAX7456 #define MAX7456_SPI_INSTANCE SPI1 #define MAX7456_SPI_CS_PIN SPI1_NSS_PIN - +#define MAX7456_DMA_CHANNEL_TX DMA1_Channel3 +//#define MAX7456_DMA_CHANNEL_RX DMA1_Channel2 // <- Conflicts with WS2811 DMA +#define MAX7456_DMA_IRQ_HANDLER_ID DMA1_CH3_HANDLER #define USE_SPI #define USE_SPI_DEVICE_2 // PB12,13,14,15 on AF5 diff --git a/src/main/target/SIRINFPV/target.h b/src/main/target/SIRINFPV/target.h index d48e37363c..42f2378c66 100644 --- a/src/main/target/SIRINFPV/target.h +++ b/src/main/target/SIRINFPV/target.h @@ -96,6 +96,10 @@ #define MAX7456_SPI_INSTANCE SPI3 #define MAX7456_SPI_CS_PIN PA15 +#define MAX7456_DMA_CHANNEL_TX DMA2_Channel2 +#define MAX7456_DMA_CHANNEL_RX DMA2_Channel1 +#define MAX7456_DMA_IRQ_HANDLER_ID DMA2_CH1_HANDLER + #define USE_RTC6705 #define RTC6705_SPIDATA_PIN PC15 #define RTC6705_SPILE_PIN PC14