1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-24 08:45:36 +03:00

MAX7456 driver - add support for SPI DMA

This commit is contained in:
Evgeny Sychov 2016-06-27 10:55:41 -07:00
parent 5d385d0019
commit 224043be4e
6 changed files with 301 additions and 147 deletions

View file

@ -122,6 +122,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;
@ -194,6 +199,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) {
@ -400,7 +422,7 @@ osd_page_t menu_pages[] = {
{
.title = "VTX SETTINGS",
.cols_number = 1,
.rows_number = 3,
.rows_number = 4,
.cols = {
{
.title = NULL,
@ -422,6 +444,11 @@ osd_page_t menu_pages[] = {
.title = "FREQUENCY",
.update = NULL,
.print = print_vtx_freq
},
{
.title = "POWER",
.update = update_vtx_power,
.print = print_vtx_power
}
}
},
@ -628,6 +655,49 @@ 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;
@ -645,86 +715,84 @@ void updateOsd(void)
if ( !(skip % 2))
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 && 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) {
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);
@ -732,7 +800,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);