Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void TOUCH_Handler(); // temporarily in main()
void VIDEO_Update();
void PAGE_Test();

#ifdef TEST
#if defined (TEST) || defined (PROFILE)
#define main _main
#endif

Expand Down
Binary file added src/target/qemu/.power.c.swp
Binary file not shown.
47 changes: 47 additions & 0 deletions src/target/qemu/Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
FILESYSTEMS := common base_fonts 320x240x16

SCREENSIZE := 320x240x16
FONTS = filesystem/$(FILESYSTEM)/media/15ascii.fon \
filesystem/$(FILESYSTEM)/media/23bold.fon

ifndef BUILD_TARGET
CROSS = arm-none-eabi-

ALL = $(LIBOPENCM3) $(TARGET).bin

NUM_MODELS ?= 10

LINKFILE = $(SDIR)/target/$(TARGET)/$(TARGET).ld
LIBOPENCM3 = $(SDIR)/libopencm3/lib/libopencm3_stm32f1.a

SRC_C := $(wildcard $(SDIR)/target/$(TARGET)/*.c) \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should create a Makefile.inc for all STM32 related parts. this makefile, the one under devo/common, and the one under at9 are largely duplicatd.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes probably. This was only meant to be a proof-of-concept. certainly not ready for inclusion

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also need an instruction on qemu as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some documentation now.

$(wildcard $(SDIR)/target/common/stm32/*.c) \
$(wildcard $(SDIR)/target/common/filesystems/*.c) \
$(wildcard $(SDIR)/target/common/filesystems/devofs/*.c) \
$(wildcard $(SDIR)/target/common/filesystems/petit_fat/*.c) \
$(wildcard $(SDIR)/target/common/devo/msc2/*.c) \
$(wildcard $(SDIR)/target/common/devo/msc2/lib/*.c) \
$(wildcard $(SDIR)/target/common/devo/hid/*.c) \
$(wildcard $(SDIR)/target/common/devo/protocol/*.c) \
$(wildcard $(SDIR)/target/common/devo/uart.c)

SRC_C := $(filter-out $(SDIR)/target/common/stm32/spi_flash.c, $(SRC_C))

CFLAGS = -DPROFILE -D"assert_param(x)=" -DSTM32F10X_HD -DSTM32F1 -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fdata-sections -ffunction-sections -I$(SDIR)/target/common/devo/msc2/lib -I$(SDIR)/target/common/devo/msc2 -I$(SDIR)/libopencm3/include -I$(SDIR)/target/common/filesystems -fno-builtin-printf -Os --specs=nano.specs
MODULE_FLAGS = -fno-builtin

LFLAGS = -nostartfiles -Wl,-gc-sections -Wl,-Map=$(TARGET).map,--cref -lc -lnosys -L$(SDIR) -Lobjs/$(TARGET)
LFLAGS2 = -Wl,-T$(LINKFILE)


else #BUILD_TARGET

$(TARGET).bin: $(TARGET).elf
$(CP) -O binary $< $@
$(DUMP) -S $< > $(TARGET).list

$(LIBOPENCM3):
+$(MAKE) -C $(SDIR)/libopencm3 TARGETS=stm32/f1 lib


endif #BUILD_TARGET
75 changes: 75 additions & 0 deletions src/target/qemu/backlight.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Deviation is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/

#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/timer.h>
#include "common.h"

// FIXME introduce constants for Timer (TIM4), compare (TIM_Oc4)
// timer clock (RCC_APB1ENR_TIM4EN), Port (GPIOB), Pin (GPIO9)
// Port clock RCC_APB2ENR_IOPBEN

void BACKLIGHT_Init()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cna u just include another real implementation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of these may be able to use a real implementation, but the qemu target does not have all STM32 features, and without proper SPI or clock support a lot of things won't work. Before I merge this, I'll clean up what can be done though.

{
// Pin PB9, Timer 4 channel 4
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
//Turn off backlight
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO9);

//Configure Backlight PWM
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN);
timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT,
TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_period(TIM4, 0x2CF);
timer_set_prescaler(TIM4, 0);
timer_generate_event(TIM4, TIM_EGR_UG);
//timer_set_repetition_counter(TIM3, 0);
timer_set_oc_mode(TIM4, TIM_OC4, TIM_OCM_PWM1);
timer_enable_oc_preload(TIM4, TIM_OC4);

timer_set_oc_polarity_high(TIM4, TIM_OC4);
timer_enable_oc_output(TIM4, TIM_OC4);

timer_enable_preload(TIM4);
}

void BACKLIGHT_Brightness(unsigned brightness)
{
timer_disable_counter(TIM4);
if (brightness == 0) {
// Turn off Backlight
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO9);
} else if(brightness > 9) {
// Turn on Backlight full
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO9);
gpio_set(GPIOB, GPIO9);
} else {
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9);
u32 duty_cycle = 720 * brightness / 10 ;
timer_set_oc_value(TIM4, TIM_OC4, duty_cycle);
timer_enable_counter(TIM4);
}
}

void LCD_Contrast(unsigned contrast)
{
(void)contrast; // dummy method for devo8. Only valid in devo10 now
}

62 changes: 62 additions & 0 deletions src/target/qemu/capabilities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifdef CHANDEF
CHANDEF(AILERON)
CHANDEF(ELEVATOR)
CHANDEF(THROTTLE)
CHANDEF(RUDDER)
CHANDEF(AUX4)
CHANDEF(AUX5)
CHANDEF(AUX6)
CHANDEF(AUX7)
CHANDEF(SWA0)
CHANDEF(SWA1)
CHANDEF(SWB0)
CHANDEF(SWB1)
CHANDEF(SWC0)
CHANDEF(SWC1)
CHANDEF(SWC2)
CHANDEF(SWD0)
CHANDEF(SWD1)
CHANDEF(SWE0)
CHANDEF(SWE1)
CHANDEF(SWE2)
CHANDEF(SWF0)
CHANDEF(SWF1)
CHANDEF(SWG0)
CHANDEF(SWG1)
CHANDEF(SWG2)
CHANDEF(SWH0)
CHANDEF(SWH1)
#endif

#ifdef UNDEF_INP
#define INP_RUD_DR0 INP_SWA0
#define INP_RUD_DR1 INP_SWA1
#define INP_ELE_DR0 INP_SWB0
#define INP_ELE_DR1 INP_SWB1
#define INP_AIL_DR0 INP_SWC0
#define INP_AIL_DR1 INP_SWC1
#define INP_FMOD0 INP_SWD0
#define INP_MIX0 INP_SWE0
#define INP_MIX1 INP_SWE1
#define INP_MIX2 INP_SWE2
#define INP_GEAR0 INP_SWF0
#define INP_GEAR1 INP_SWF1
#endif


#ifdef BUTTONDEF
BUTTONDEF(TRIM_LV_NEG) /* LEFT-VERTICAL */
BUTTONDEF(TRIM_LV_POS)
BUTTONDEF(TRIM_RV_NEG) /* RIGHT-VERTICAL */
BUTTONDEF(TRIM_RV_POS)
BUTTONDEF(TRIM_LH_NEG) /* LEFT-HORIZONTAL */
BUTTONDEF(TRIM_LH_POS)
BUTTONDEF(TRIM_RH_NEG) /* RIGHT-HORIZONTAL */
BUTTONDEF(TRIM_RH_POS)
BUTTONDEF(LEFT)
BUTTONDEF(RIGHT)
BUTTONDEF(DOWN)
BUTTONDEF(UP)
BUTTONDEF(ENTER)
BUTTONDEF(EXIT)
#endif
124 changes: 124 additions & 0 deletions src/target/qemu/channels.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Deviation is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include "common.h"
#include "mixer.h"
#include "config/tx.h"
#include "../common/devo/devo.h"

//Order is MODE1: AIL, ELE, THR, RUD, LeftDial, Right Dial, Left Shoulder, Right Shoulder, Vdd, Voltage
// PA0 PA1, PA2, PA3, PA5, PA6, PB0 PA4, PB1
const u8 adc_chan_sel[NUM_ADC_CHANNELS] =
{0, 1, 2, 3, 5, 6, 8, 4, 16, 9};

void CHAN_Init()
{
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
ADC_Init();

/* configure channels for analog */
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO2);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO3);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO4);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO5);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO6);
/* Enable Voltage measurement */
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0);
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1);

/* configure switches for digital I/O */
gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN,
GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 |
GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9);
gpio_set(GPIOC,
GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 |
GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO8);
gpio_set(GPIOA, GPIO8);
}

s32 CHAN_ReadRawInput(int channel)
{
s32 value = 0;
switch(channel) {
case INP_AILERON: value = adc_array_raw[0]; break; // bug fix: right vertical
case INP_ELEVATOR: value = adc_array_raw[1]; break; // bug fix: right horizon
case INP_THROTTLE: value = adc_array_raw[2]; break; // bug fix: left horizon
case INP_RUDDER: value = adc_array_raw[3]; break; // bug fix: left vertical
case INP_AUX4: value = adc_array_raw[4]; break;
case INP_AUX5: value = adc_array_raw[5]; break;
case INP_AUX6: value = adc_array_raw[6]; break;
case INP_AUX7: value = adc_array_raw[7]; break;
case INP_SWA0: value = gpio_get(GPIOC, GPIO0); break;
case INP_SWA1: value = ! gpio_get(GPIOC, GPIO0); break;
case INP_SWB0: value = gpio_get(GPIOC, GPIO1); break;
case INP_SWB1: value = ! gpio_get(GPIOC, GPIO1); break;
case INP_SWC0: value = ! gpio_get(GPIOC, GPIO2); break;
case INP_SWC1: value = (gpio_get(GPIOC, GPIO2) && gpio_get(GPIOC, GPIO3)); break;
case INP_SWC2: value = ! gpio_get(GPIOC, GPIO3); break;
case INP_SWD0: value = gpio_get(GPIOC, GPIO6); break;
case INP_SWD1: value = ! gpio_get(GPIOC, GPIO6); break;
case INP_SWE0: value = ! gpio_get(GPIOC, GPIO4); break;
case INP_SWE1: value = (gpio_get(GPIOC, GPIO4) && gpio_get(GPIOC, GPIO5)); break;
case INP_SWE2: value = ! gpio_get(GPIOC, GPIO5); break;
case INP_SWF0: value = gpio_get(GPIOC, GPIO7); break;
case INP_SWF1: value = ! gpio_get(GPIOC, GPIO7); break;
case INP_SWG0: value = ! gpio_get(GPIOC, GPIO8); break;
case INP_SWG1: value = (gpio_get(GPIOC, GPIO8) && gpio_get(GPIOC, GPIO9)); break;
case INP_SWG2: value = ! gpio_get(GPIOC, GPIO9); break;
case INP_SWH0: value = gpio_get(GPIOA, GPIO8); break;
case INP_SWH1: value = ! gpio_get(GPIOA, GPIO8); break;
}
return value;
}
s32 CHAN_ReadInput(int channel)
{
s32 value = CHAN_ReadRawInput(channel);
if(channel <= INP_HAS_CALIBRATION) {
s32 max = Transmitter.calibration[channel - 1].max;
s32 min = Transmitter.calibration[channel - 1].min;
s32 zero = Transmitter.calibration[channel - 1].zero;
if(! zero) {
//If this input doesn't have a zero, calculate from max/min
zero = ((u32)max + min) / 2;
}
// Derate min and max by 1% to ensure we can get all the way to 100%
max = (max - zero) * 99 / 100;
min = (min - zero) * 99 / 100;
if(value >= zero) {
value = (value - zero) * CHAN_MAX_VALUE / max;
} else {
value = (value - zero) * CHAN_MIN_VALUE / min;
}
//Bound output
if (value > CHAN_MAX_VALUE)
value = CHAN_MAX_VALUE;
if (value < CHAN_MIN_VALUE)
value = CHAN_MIN_VALUE;
} else {
value = value ? CHAN_MAX_VALUE : CHAN_MIN_VALUE;
}
if (channel == INP_AILERON || channel == INP_ELEVATOR ||
channel == INP_THROTTLE || channel == INP_RUDDER)
{
value = -value;
}
return value;
}
55 changes: 55 additions & 0 deletions src/target/qemu/lcd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Deviation is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/fsmc.h>
#include "common.h"
#include "lcd.h"

u8 screen_flip;
const struct lcdtype *disp_type;

void lcd_cmd(uint8_t addr, uint8_t data)
{
}

void lcd_set_pos(unsigned int x0, unsigned int y0)
{
}

void LCD_DrawPixel(unsigned int color)
{
}

void LCD_DrawPixelXY(unsigned int x, unsigned int y, unsigned int color)
{
}

void LCD_DrawStart(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, enum DrawDir dir)
{
}

void LCD_DrawStop(void)
{
}

void LCD_Sleep()
{
}

void LCD_Init()
{
}

Loading