[Horus] GUI continued
|
@ -134,7 +134,7 @@ namespace NAMESPACE {
|
|||
#include "radio/src/trainer_input.cpp"
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#include "radio/src/bmp.cpp"
|
||||
#include "radio/src/gui/horus/bitmapbuffer.cpp"
|
||||
#include "radio/src/gui/horus/bitmaps.cpp"
|
||||
#include "radio/src/gui/horus/curves.cpp"
|
||||
#include "radio/src/gui/horus/fonts.cpp"
|
||||
|
@ -224,7 +224,7 @@ namespace NAMESPACE {
|
|||
#include "radio/src/gui/Flamenco/splash.cpp"
|
||||
#include "radio/src/targets/flamenco/tw8823_driver.cpp"
|
||||
#elif defined(PCBTARANIS)
|
||||
#include "radio/src/bmp.cpp"
|
||||
#include "radio/src/gui/taranis/bmp.cpp"
|
||||
#include "radio/src/gui/taranis/fonts.cpp"
|
||||
#include "radio/src/gui/taranis/widgets.cpp"
|
||||
#include "radio/src/gui/taranis/navigation.cpp"
|
||||
|
|
BIN
radio/sdcard/horus/THEMES/Darkblue/thumb.bmp
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
radio/sdcard/horus/THEMES/Darkblue/topmenu_opentx.bmp
Normal file
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 510 KiB After Width: | Height: | Size: 510 KiB |
Before Width: | Height: | Size: 510 KiB After Width: | Height: | Size: 510 KiB |
BIN
radio/sdcard/horus/THEMES/Default/sleep.bmp
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
radio/sdcard/horus/THEMES/Default/thumb.bmp
Normal file
After Width: | Height: | Size: 6.3 KiB |
19
radio/sdcard/horus/WIDGETS/Counter/main.lua
Normal file
|
@ -0,0 +1,19 @@
|
|||
local options = {
|
||||
{ "Source", SOURCE, 1 },
|
||||
{ "Min", VALUE, -1024 },
|
||||
{ "Max", VALUE, 1024 },
|
||||
{ "Color", COLOR, RED }
|
||||
}
|
||||
|
||||
local function create(zone, options)
|
||||
local pie = { zone=zone, options=options, counter=0 }
|
||||
print(options.Source)
|
||||
return pie
|
||||
end
|
||||
|
||||
function refresh(pie)
|
||||
pie.counter = pie.counter + 1
|
||||
lcd.drawNumber(pie.zone.x, pie.zone.y, pie.counter, LEFT + DBLSIZE + TEXT_COLOR);
|
||||
end
|
||||
|
||||
return { name="Counter", options=options, create=create, refresh=refresh }
|
|
@ -70,6 +70,7 @@ if(PCB STREQUAL HORUS)
|
|||
file(GLOB WIDGETS_SRC RELATIVE ${RADIO_SRC_DIRECTORY}/gui/horus ${RADIO_SRC_DIRECTORY}/gui/horus/widgets/*.cpp)
|
||||
set(GUI_SRC
|
||||
${GUI_SRC}
|
||||
bitmapbuffer.cpp
|
||||
curves.cpp
|
||||
bitmaps.cpp
|
||||
menu_general_hardware.cpp
|
||||
|
@ -87,7 +88,7 @@ if(PCB STREQUAL HORUS)
|
|||
${LAYOUTS_SRC}
|
||||
${WIDGETS_SRC}
|
||||
)
|
||||
set(SRC ${SRC} bmp.cpp targets/taranis/rtc_driver.cpp)
|
||||
set(SRC ${SRC} targets/taranis/rtc_driver.cpp)
|
||||
set(TARGET_SRC ${TARGET_SRC} board_horus.cpp)
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
|
@ -146,8 +147,7 @@ elseif(PCB STREQUAL TARANIS)
|
|||
add_definitions(-DPCBTARANIS)
|
||||
add_definitions(-DAUDIO -DVOICE -DRTCLOCK)
|
||||
add_definitions(-DDBLKEYS -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DVARIO)
|
||||
set(SRC ${SRC} bmp.cpp)
|
||||
set(GUI_SRC ${GUI_SRC} menu_model_inputs.cpp menu_model_mixes.cpp menu_general_diagkeys.cpp menu_general_diaganas.cpp menu_general_hardware.cpp view_channels.cpp view_telemetry.cpp view_text.cpp view_about.cpp)
|
||||
set(GUI_SRC ${GUI_SRC} bmp.cpp menu_model_inputs.cpp menu_model_mixes.cpp menu_general_diagkeys.cpp menu_general_diaganas.cpp menu_general_hardware.cpp view_channels.cpp view_telemetry.cpp view_text.cpp view_about.cpp)
|
||||
set(TARGET_SRC ${TARGET_SRC} board_taranis.cpp rtc_driver.cpp)
|
||||
set(FIRMWARE_SRC ${FIRMWARE_SRC} loadboot.cpp)
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
|
@ -767,6 +767,7 @@ foreach(FILE ${PULSES_SRC})
|
|||
endforeach()
|
||||
|
||||
add_definitions(-DCORRECT_NEGATIVE_SHIFTS)
|
||||
add_definitions(-Wall -Wno-strict-aliasing -Wformat -Wreturn-type -Wunused -Wuninitialized -Wunknown-pragmas -Wno-switch -Wtype-limits)
|
||||
|
||||
if(NOT WIN32)
|
||||
add_subdirectory(targets/simu)
|
||||
|
@ -775,8 +776,6 @@ endif()
|
|||
|
||||
set(SRC ${SRC} ${FIRMWARE_SRC})
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wno-strict-aliasing -Wformat -Wreturn-type -Wunused -Wuninitialized -Wunknown-pragmas -Wno-switch -Wtype-limits")
|
||||
|
||||
# trick to remove the -rdynamic and --out-implib issues
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
@ -798,7 +797,7 @@ if(ARCH STREQUAL ARM)
|
|||
set(COMMON_FLAGS "-mcpu=${MCU} -mthumb -fomit-frame-pointer -fverbose-asm -Wa,-ahlms=firmware.lst -O${OPT} -gdwarf-2 -DHSE_VALUE=${HSE_VALUE} -fno-exceptions -fdata-sections -ffunction-sections ${WARNING_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${COMMON_FLAGS} -Wimplicit")
|
||||
set(CMAKE_CXX_FLAGS "${COMMON_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-mcpu=${MCU} -mthumb -nostartfiles -lm -T${RADIO_SRC_DIRECTORY}/${LINKER_SCRIPT} -Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-mcpu=${MCU} -mthumb -lm -T${RADIO_SRC_DIRECTORY}/${LINKER_SCRIPT} -Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections")
|
||||
|
||||
if(PCB STREQUAL TARANIS)
|
||||
add_subdirectory(targets/${TARGET_DIR}/bootloader)
|
||||
|
|
|
@ -979,7 +979,7 @@ ifeq ($(PCB), TARANIS)
|
|||
PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp pulses/crossfire.cpp
|
||||
CPPSRC += tasks_arm.cpp audio_arm.cpp sbus.cpp telemetry/telemetry.cpp
|
||||
CPPSRC += targets/taranis/pulses_driver.cpp targets/taranis/keys_driver.cpp targets/taranis/adc_driver.cpp targets/taranis/trainer_driver.cpp targets/taranis/audio_driver.cpp targets/taranis/serial2_driver.cpp targets/taranis/telemetry_driver.cpp
|
||||
CPPSRC += bmp.cpp gui/$(GUIDIRECTORY)/view_channels.cpp gui/$(GUIDIRECTORY)/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp debug.cpp
|
||||
CPPSRC += gui/$(GUIDIRECTORY)/bmp.cpp gui/$(GUIDIRECTORY)/view_channels.cpp gui/$(GUIDIRECTORY)/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp debug.cpp
|
||||
EXTRABOARDSRC += loadboot.cpp
|
||||
ifeq ($(PCBREV), REV9E)
|
||||
CPPSRC += targets/taranis/top_lcd_driver.cpp
|
||||
|
|
|
@ -8,9 +8,9 @@ add_custom_target(ttf_horus_fonts DEPENDS ttf_horus_tinsize ttf_horus_smlsize tt
|
|||
|
||||
add_bitmaps_target(horus_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/bmp_*.png" 480 5/6/5)
|
||||
add_bitmaps_target(horus_calibration_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/calibration/bmp_*.png" 480 5/6/5)
|
||||
add_bitmaps_target(horus_button_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/button/alpha_*.png" 480 5/6/5/8)
|
||||
add_bitmaps_target(horus_alpha_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/alpha_*.png" 480 5/6/5/8)
|
||||
add_bitmaps_target(horus_alpha_calibration_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/calibration/alpha_*.png" 480 5/6/5/8)
|
||||
add_bitmaps_target(horus_button_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/button/alpha_*.png" 480 4/4/4/4)
|
||||
add_bitmaps_target(horus_alpha_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/alpha_*.png" 480 4/4/4/4)
|
||||
add_bitmaps_target(horus_alpha_calibration_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/horus/calibration/alpha_*.png" 480 4/4/4/4)
|
||||
add_bitmaps_target(horus_masks ${RADIO_SRC_DIRECTORY}/bitmaps/horus/mask_*.png 480 8bits)
|
||||
add_bitmaps_target(horus_slider_masks "${RADIO_SRC_DIRECTORY}/bitmaps/horus/slider/*.png" 480 8bits)
|
||||
add_bitmaps_target(horus_layouts_masks "${RADIO_SRC_DIRECTORY}/gui/horus/layouts/*.png" 480 8bits)
|
||||
|
|
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.1 KiB |
BIN
radio/src/bitmaps/horus/mask_about_headico.png
Normal file
After Width: | Height: | Size: 664 B |
|
@ -1,516 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
uint8_t * bmpLoad(uint8_t * bmp, const char * filename, uint16_t width, uint16_t height)
|
||||
{
|
||||
FIL bmpFile;
|
||||
UINT read;
|
||||
uint8_t palette[16];
|
||||
uint8_t bmpBuf[LCD_W]; /* maximum with LCD_W */
|
||||
uint8_t * buf = &bmpBuf[0];
|
||||
|
||||
if (width > LCD_W) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f_size(&bmpFile) < 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = f_read(&bmpFile, buf, 14, &read);
|
||||
if (result != FR_OK || read != 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buf[0] != 'B' || buf[1] != 'M') {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t fsize = *((uint32_t *)&buf[2]);
|
||||
uint32_t hsize = *((uint32_t *)&buf[10]); /* header size */
|
||||
|
||||
uint32_t len = limit((uint32_t)4, (uint32_t)(hsize-14), (uint32_t)32);
|
||||
result = f_read(&bmpFile, buf, len, &read);
|
||||
if (result != FR_OK || read != len) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t ihsize = *((uint32_t *)&buf[0]); /* more header size */
|
||||
|
||||
/* invalid header size */
|
||||
if (ihsize + 14 > hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sometimes file size is set to some headers size, set a real size in that case */
|
||||
if (fsize == 14 || fsize == ihsize + 14)
|
||||
fsize = f_size(&bmpFile) - 2;
|
||||
|
||||
/* declared file size less than header size */
|
||||
if (fsize <= hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t w, h;
|
||||
|
||||
switch (ihsize){
|
||||
case 40: // windib
|
||||
case 56: // windib v3
|
||||
case 64: // OS/2 v2
|
||||
case 108: // windib v4
|
||||
case 124: // windib v5
|
||||
w = *((uint32_t *)&buf[4]);
|
||||
h = *((uint32_t *)&buf[8]);
|
||||
buf += 12;
|
||||
break;
|
||||
case 12: // OS/2 v1
|
||||
w = *((uint16_t *)&buf[4]);
|
||||
h = *((uint16_t *)&buf[6]);
|
||||
buf += 8;
|
||||
break;
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*((uint16_t *)&buf[0]) != 1) { /* planes */
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (w > width || h > height) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t depth = *((uint16_t *)&buf[2]);
|
||||
|
||||
buf = &bmpBuf[0];
|
||||
|
||||
if (depth == 4) {
|
||||
if (f_lseek(&bmpFile, hsize-64) != FR_OK || f_read(&bmpFile, buf, 64, &read) != FR_OK || read != 64) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t i=0; i<16; i++) {
|
||||
palette[i] = buf[4*i] >> 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (f_lseek(&bmpFile, hsize) != FR_OK) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * dest = bmp;
|
||||
|
||||
*dest++ = w;
|
||||
*dest++ = h;
|
||||
|
||||
memset(dest, 0, BITMAP_BUFFER_SIZE(w, h) - 2);
|
||||
|
||||
uint32_t rowSize;
|
||||
|
||||
switch (depth) {
|
||||
case 1:
|
||||
rowSize = ((w+31)/32)*4;
|
||||
for (uint32_t i=0; i<h; i+=2) {
|
||||
result = f_read(&bmpFile, buf, rowSize*2, &read);
|
||||
if (result != FR_OK || read != rowSize*2) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint32_t j=0; j<w; j++) {
|
||||
uint8_t * dst = dest + (h-i-2)/2 * w + j;
|
||||
if (!(buf[j/8] & (1<<(7-(j%8)))))
|
||||
*dst |= 0xF0;
|
||||
if (!(buf[rowSize+j/8] & (1<<(7-(j%8)))))
|
||||
*dst |= 0x0F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rowSize = ((4*w+31)/32)*4;
|
||||
for (int32_t i=h-1; i>=0; i--) {
|
||||
result = f_read(&bmpFile, buf, rowSize, &read);
|
||||
if (result != FR_OK || read != rowSize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t * dst = dest + (i/2)*w;
|
||||
for (uint32_t j=0; j<w; j++) {
|
||||
uint8_t index = (buf[j/2] >> ((j & 1) ? 0 : 4)) & 0x0F;
|
||||
uint8_t val = palette[index] << ((i & 1) ? 4 : 0);
|
||||
*dst++ |= val ^ ((i & 1) ? 0xF0 : 0x0F);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_close(&bmpFile);
|
||||
return bmp;
|
||||
}
|
||||
#elif defined(PCBHORUS)
|
||||
uint8_t * bmpLoad(const char * filename)
|
||||
{
|
||||
FIL bmpFile;
|
||||
UINT read;
|
||||
uint8_t palette[16];
|
||||
uint8_t bmpBuf[LCD_W]; /* maximum with LCD_W */
|
||||
uint8_t * buf = &bmpBuf[0];
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f_size(&bmpFile) < 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = f_read(&bmpFile, buf, 14, &read);
|
||||
if (result != FR_OK || read != 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buf[0] != 'B' || buf[1] != 'M') {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t fsize = *((uint32_t *)&buf[2]);
|
||||
uint32_t hsize = *((uint32_t *)&buf[10]); /* header size */
|
||||
|
||||
uint32_t len = limit((uint32_t)4, (uint32_t)(hsize-14), (uint32_t)32);
|
||||
result = f_read(&bmpFile, buf, len, &read);
|
||||
if (result != FR_OK || read != len) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t ihsize = *((uint32_t *)&buf[0]); /* more header size */
|
||||
|
||||
/* invalid header size */
|
||||
if (ihsize + 14 > hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sometimes file size is set to some headers size, set a real size in that case */
|
||||
if (fsize == 14 || fsize == ihsize + 14)
|
||||
fsize = f_size(&bmpFile) - 2;
|
||||
|
||||
/* declared file size less than header size */
|
||||
if (fsize <= hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t w, h;
|
||||
|
||||
switch (ihsize){
|
||||
case 40: // windib
|
||||
case 56: // windib v3
|
||||
case 64: // OS/2 v2
|
||||
case 108: // windib v4
|
||||
case 124: // windib v5
|
||||
w = *((uint32_t *)&buf[4]);
|
||||
h = *((uint32_t *)&buf[8]);
|
||||
buf += 12;
|
||||
break;
|
||||
case 12: // OS/2 v1
|
||||
w = *((uint16_t *)&buf[4]);
|
||||
h = *((uint16_t *)&buf[6]);
|
||||
buf += 8;
|
||||
break;
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*((uint16_t *)&buf[0]) != 1) { /* planes */
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t depth = *((uint16_t *)&buf[2]);
|
||||
|
||||
buf = &bmpBuf[0];
|
||||
|
||||
if (depth == 4) {
|
||||
if (f_lseek(&bmpFile, hsize-64) != FR_OK || f_read(&bmpFile, buf, 64, &read) != FR_OK || read != 64) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t i=0; i<16; i++) {
|
||||
palette[i] = buf[4*i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (f_lseek(&bmpFile, hsize) != FR_OK) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * bmp = (uint8_t *)malloc(BITMAP_BUFFER_SIZE(w, h));
|
||||
uint16_t * dest = (uint16_t *)bmp;
|
||||
if (bmp == NULL) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dest++ = w;
|
||||
*dest++ = h;
|
||||
memset(dest, 0, BITMAP_BUFFER_SIZE(w, h) - 4);
|
||||
|
||||
uint32_t rowSize;
|
||||
|
||||
switch (depth) {
|
||||
case 32:
|
||||
for (int i=h-1; i>=0; i--) {
|
||||
uint8_t * dst = ((uint8_t *)dest) + i*w*2;
|
||||
for (unsigned int j=0; j<w; j++) {
|
||||
uint32_t pixel;
|
||||
result = f_read(&bmpFile, (uint8_t *)&pixel, 4, &read);
|
||||
if (result != FR_OK || read != 4) {
|
||||
f_close(&bmpFile);
|
||||
free(bmp);
|
||||
return NULL;
|
||||
}
|
||||
*((uint16_t *)dst) = RGB((pixel>>24) & 0xff, (pixel>>16) & 0xff, (pixel>>8) & 0xff);
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rowSize = ((4*w+31)/32)*4;
|
||||
for (int32_t i=h-1; i>=0; i--) {
|
||||
result = f_read(&bmpFile, buf, rowSize, &read);
|
||||
if (result != FR_OK || read != rowSize) {
|
||||
f_close(&bmpFile);
|
||||
free(bmp);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t * dst = ((uint8_t *)dest) + i*w*2;
|
||||
for (uint32_t j=0; j<w; j++) {
|
||||
uint8_t index = (buf[j/2] >> ((j & 1) ? 0 : 4)) & 0x0F;
|
||||
uint8_t val = palette[index];
|
||||
*((uint16_t *)dst) = RGB(val, val, val);
|
||||
dst += 2;
|
||||
// *dst++ = 0x0F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
free(bmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_close(&bmpFile);
|
||||
return bmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint8_t bmpHeader[] = {
|
||||
0x42, 0x4d, 0xF8, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 212, 0x00, 0x00, 0x00, 64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0xbc, 0x38, 0x00, 0x00, 0xbc, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xee, 0xee, 0xee, 0x00, 0xdd, 0xdd,
|
||||
0xdd, 0x00, 0xcc, 0xcc, 0xcc, 0x00, 0xbb, 0xbb, 0xbb, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x99, 0x99,
|
||||
0x99, 0x00, 0x88, 0x88, 0x88, 0x00, 0x77, 0x77, 0x77, 0x00, 0x66, 0x66, 0x66, 0x00, 0x55, 0x55,
|
||||
0x55, 0x00, 0x44, 0x44, 0x44, 0x00, 0x33, 0x33, 0x33, 0x00, 0x22, 0x22, 0x22, 0x00, 0x11, 0x11,
|
||||
0x11, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
inline display_t getPixel(unsigned int x, unsigned int y)
|
||||
{
|
||||
if (x>=LCD_W || y>=LCD_H)
|
||||
return 0;
|
||||
display_t * p = &displayBuf[y / 2 * LCD_W + x];
|
||||
return (y & 1) ? (*p >> 4) : (*p & 0x0F);
|
||||
}
|
||||
|
||||
const char *writeScreenshot()
|
||||
{
|
||||
FIL bmpFile;
|
||||
UINT written;
|
||||
char filename[42]; // /SCREENSHOTS/screen-2013-01-01-123540.bmp
|
||||
|
||||
// check and create folder here
|
||||
strcpy_P(filename, SCREENSHOTS_PATH);
|
||||
const char * error = sdCheckAndCreateDirectory(filename);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char * tmp = strAppend(&filename[sizeof(SCREENSHOTS_PATH)-1], "/screen");
|
||||
tmp = strAppendDate(tmp, true);
|
||||
strcpy(tmp, BITMAPS_EXT);
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
result = f_write(&bmpFile, bmpHeader, sizeof(bmpHeader), &written);
|
||||
if (result != FR_OK || written != sizeof(bmpHeader)) {
|
||||
f_close(&bmpFile);
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
for (int y=LCD_H-1; y>=0; y-=1) {
|
||||
for (int x=0; x<8*((LCD_W+7)/8); x+=2) {
|
||||
uint8_t byte = getPixel(x+1, y) + (getPixel(x, y) << 4);
|
||||
f_write(&bmpFile, &byte, 1, &written);
|
||||
if (result != FR_OK || written != 1) {
|
||||
f_close(&bmpFile);
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f_close(&bmpFile);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_ONLY_JPEG
|
||||
#define STBI_ONLY_BMP
|
||||
#define STBI_NO_STDIO
|
||||
#include "thirdparty/Stb/stb_image.h"
|
||||
|
||||
|
||||
// fill 'data' with 'size' bytes. return number of bytes actually read
|
||||
int stbc_read(void *user, char *data, int size)
|
||||
{
|
||||
FIL * fp = (FIL *)user;
|
||||
UINT br = 0;
|
||||
FRESULT res = f_read(fp, data, size, &br);
|
||||
if (res == FR_OK) {
|
||||
return (int)br;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip the next 'n' bytes, or 'unget' the last -n bytes if negative
|
||||
void stbc_skip(void *user, int n)
|
||||
{
|
||||
FIL * fp = (FIL *)user;
|
||||
f_lseek(fp, f_tell(fp) + n);
|
||||
}
|
||||
|
||||
// returns nonzero if we are at end of file/data
|
||||
int stbc_eof(void *user)
|
||||
{
|
||||
FIL * fp = (FIL *)user;
|
||||
return f_eof(fp);
|
||||
}
|
||||
|
||||
// callbacks for stb-image
|
||||
const stbi_io_callbacks stbCallbacks = {
|
||||
stbc_read,
|
||||
stbc_skip,
|
||||
stbc_eof
|
||||
};
|
||||
|
||||
|
||||
const char * imgLoad(uint8_t * bmp, const char * filename, uint16_t width, uint16_t height)
|
||||
{
|
||||
FIL imgFile;
|
||||
|
||||
// if (width > LCD_W) {
|
||||
// return STR_INCOMPATIBLE;
|
||||
// }
|
||||
|
||||
FRESULT result = f_open(&imgFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
// if (f_size(&bmpFile) < 14) {
|
||||
// f_close(&bmpFile);
|
||||
// return STR_INCOMPATIBLE;
|
||||
// }
|
||||
|
||||
int x,y,n;
|
||||
unsigned char *data = stbi_load_from_callbacks(&stbCallbacks, &imgFile, &x, &y, &n, 3);
|
||||
f_close(&imgFile);
|
||||
|
||||
if (!data) {
|
||||
return "stb error";
|
||||
}
|
||||
|
||||
//convert to 565 fromat
|
||||
// todo use dma2d for conversion from 888 to 565
|
||||
unsigned char *p = data;
|
||||
uint16_t * dest = (uint16_t *)bmp;
|
||||
|
||||
*dest++ = min<int>(width, x);
|
||||
*dest++ = min<int>(height, y);
|
||||
|
||||
for(int row = 0; row < min<int>(height, y); ++row) {
|
||||
unsigned char *l = p;
|
||||
for(int col = 0; col < min<int>(width, x); ++col) {
|
||||
*dest = RGB(l[0], l[1], l[2]);
|
||||
++dest;
|
||||
l += 3;
|
||||
}
|
||||
p += 3 * x;
|
||||
}
|
||||
stbi_image_free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // if defined(PCBHORUS)
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
typedef bool (*IsValueAvailable)(int);
|
||||
|
||||
int circularIncDec(int current, int inc, int min, int max, IsValueAvailable isValueAvailable);
|
||||
int circularIncDec(int current, int inc, int min, int max, IsValueAvailable isValueAvailable=NULL);
|
||||
int getFirstAvailable(int min, int max, IsValueAvailable isValueAvailable);
|
||||
|
||||
#if defined(VIRTUALINPUTS)
|
||||
|
|
640
radio/src/gui/horus/bitmapbuffer.cpp
Normal file
|
@ -0,0 +1,640 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "opentx.h"
|
||||
|
||||
void BitmapBuffer::drawAlphaPixel(display_t * p, uint8_t opacity, uint16_t color)
|
||||
{
|
||||
if (opacity == OPACITY_MAX) {
|
||||
drawPixel(p, color);
|
||||
}
|
||||
else if (opacity != 0) {
|
||||
uint8_t bgWeight = OPACITY_MAX - opacity;
|
||||
COLOR_SPLIT(color, red, green, blue);
|
||||
COLOR_SPLIT(*p, bgRed, bgGreen, bgBlue);
|
||||
uint16_t r = (bgRed * bgWeight + red * opacity) / OPACITY_MAX;
|
||||
uint16_t g = (bgGreen * bgWeight + green * opacity) / OPACITY_MAX;
|
||||
uint16_t b = (bgBlue * bgWeight + blue * opacity) / OPACITY_MAX;
|
||||
drawPixel(p, COLOR_JOIN(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawHorizontalLine(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (y >= height) return;
|
||||
if (x+w > width) { w = width - x; }
|
||||
|
||||
display_t * p = getPixelPtr(x, y);
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
uint8_t opacity = 0x0F - (att >> 24);
|
||||
|
||||
if (pat == SOLID) {
|
||||
while (w--) {
|
||||
drawAlphaPixel(p, opacity, color);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (w--) {
|
||||
if (pat & 1) {
|
||||
drawAlphaPixel(p, opacity, color);
|
||||
pat = (pat >> 1) | 0x80;
|
||||
}
|
||||
else {
|
||||
pat = pat >> 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (x >= width) return;
|
||||
if (y >= height) return;
|
||||
if (h<0) { y+=h; h=-h; }
|
||||
if (y<0) { h+=y; y=0; if (h<=0) return; }
|
||||
if (y+h > height) { h = height - y; }
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
uint8_t opacity = 0x0F - (att >> 24);
|
||||
|
||||
if (pat == SOLID) {
|
||||
while (h--) {
|
||||
drawAlphaPixel(x, y, opacity, color);
|
||||
y++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pat==DOTTED && !(y%2)) {
|
||||
pat = ~pat;
|
||||
}
|
||||
while (h--) {
|
||||
if (pat & 1) {
|
||||
drawAlphaPixel(x, y, opacity, color);
|
||||
pat = (pat >> 1) | 0x80;
|
||||
}
|
||||
else {
|
||||
pat = pat >> 1;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
for (coord_t i=y; i<y+h; i++) {
|
||||
if ((att & ROUND) && (i==y || i==y+h-1))
|
||||
drawHorizontalLine(x+1, i, w-2, pat, att);
|
||||
else
|
||||
drawHorizontalLine(x, i, w, pat, att);
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::invertRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags att)
|
||||
{
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
COLOR_SPLIT(color, red, green, blue);
|
||||
|
||||
for (int i=y; i<y+h; i++) {
|
||||
display_t * p = getPixelPtr(x, i);
|
||||
for (int j=0; j<w; j++) {
|
||||
// TODO ASSERT_IN_DISPLAY(p);
|
||||
COLOR_SPLIT(*p, bgRed, bgGreen, bgBlue);
|
||||
drawPixel(p++, COLOR_JOIN(0x1F + red - bgRed, 0x3F + green - bgGreen, 0x1F + blue - bgBlue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void BitmapBuffer::drawCircle(int x0, int y0, int radius)
|
||||
{
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
int decisionOver2 = 1 - x;
|
||||
|
||||
while (y <= x) {
|
||||
drawPixel(x+x0, y+y0, WHITE);
|
||||
drawPixel(y+x0, x+y0, WHITE);
|
||||
drawPixel(-x+x0, y+y0, WHITE);
|
||||
drawPixel(-y+x0, x+y0, WHITE);
|
||||
drawPixel(-x+x0, -y+y0, WHITE);
|
||||
drawPixel(-y+x0, -x+y0, WHITE);
|
||||
drawPixel(x+x0, -y+y0, WHITE);
|
||||
drawPixel(y+x0, -x+y0, WHITE);
|
||||
y++;
|
||||
if (decisionOver2 <= 0) {
|
||||
decisionOver2 += 2*y + 1;
|
||||
}
|
||||
else {
|
||||
x--;
|
||||
decisionOver2 += 2 * (y-x) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
bool evalSlopes(int * slopes, int startAngle, int endAngle)
|
||||
{
|
||||
if (startAngle >= 360 || endAngle <= 0)
|
||||
return false;
|
||||
|
||||
if (startAngle == 0) {
|
||||
slopes[1] = 100000;
|
||||
slopes[2] = -100000;
|
||||
}
|
||||
else {
|
||||
float angle1 = float(startAngle) * PI / 180;
|
||||
if (startAngle >= 180) {
|
||||
slopes[1] = -100000;
|
||||
slopes[2] = cos(angle1) * 100 / sin(angle1);
|
||||
}
|
||||
else {
|
||||
slopes[1] = cos(angle1) * 100 / sin(angle1);
|
||||
slopes[2] = -100000;
|
||||
}
|
||||
}
|
||||
|
||||
if (endAngle == 360) {
|
||||
slopes[0] = -100000;
|
||||
slopes[3] = 100000;
|
||||
}
|
||||
else {
|
||||
float angle2 = float(endAngle) * PI / 180;
|
||||
if (endAngle >= 180) {
|
||||
slopes[0] = -100000;
|
||||
slopes[3] = -cos(angle2) * 100 / sin(angle2);
|
||||
}
|
||||
else {
|
||||
slopes[0] = cos(angle2) * 100 / sin(angle2);
|
||||
slopes[3] = -100000;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawPie(int x0, int y0, int radius, int startAngle, int endAngle)
|
||||
{
|
||||
int slopes[4];
|
||||
if (!evalSlopes(slopes, startAngle, endAngle))
|
||||
return;
|
||||
|
||||
for (int y=0; y<=radius; y++) {
|
||||
for (int x=0; x<=radius; x++) {
|
||||
if (x*x+y*y <= radius*radius) {
|
||||
int slope = (x==0 ? (y<0 ? -99000 : 99000) : y*100/x);
|
||||
if (slope >= slopes[0] && slope < slopes[1]) {
|
||||
drawPixel(x0+x, y0-y, WHITE);
|
||||
}
|
||||
if (-slope >= slopes[0] && -slope < slopes[1]) {
|
||||
drawPixel(x0+x, y0+y, WHITE);
|
||||
}
|
||||
if (slope >= slopes[2] && slope < slopes[3]) {
|
||||
drawPixel(x0-x, y0-y, WHITE);
|
||||
}
|
||||
if (-slope >= slopes[2] && -slope < slopes[3]) {
|
||||
drawPixel(x0-x, y0+y, WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset, coord_t width)
|
||||
{
|
||||
coord_t w = *((uint16_t *)bmp);
|
||||
coord_t height = *(((uint16_t *)bmp)+1);
|
||||
|
||||
if (!width || width > w) {
|
||||
width = w;
|
||||
}
|
||||
|
||||
if (x+width > this->width) {
|
||||
width = this->width-x;
|
||||
}
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(flags)];
|
||||
|
||||
for (coord_t row=0; row<height; row++) {
|
||||
display_t * p = getPixelPtr(x, y+row);
|
||||
const uint8_t * q = bmp + 4 + row*w + offset;
|
||||
for (coord_t col=0; col<width; col++) {
|
||||
drawAlphaPixel(p, *q, color);
|
||||
p++; q++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FONT_MAX_HEIGHT 42
|
||||
void BitmapBuffer::drawFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags)
|
||||
{
|
||||
coord_t offset = spec[index];
|
||||
coord_t width = spec[index+1] - offset;
|
||||
if (width > 0) drawBitmapPattern(x, y, font, flags, offset, width);
|
||||
lcdNextPos = x + width;
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags flags)
|
||||
{
|
||||
int width = getTextWidth(s, len, flags);
|
||||
int height = getFontHeight(flags);
|
||||
int fontindex = FONTSIZE(flags) >> 8;
|
||||
const pm_uchar * font = fontsTable[fontindex];
|
||||
const uint16_t * fontspecs = fontspecsTable[fontindex];
|
||||
|
||||
if (flags & RIGHT)
|
||||
x -= width;
|
||||
else if (flags & CENTERED)
|
||||
x -= width/2;
|
||||
|
||||
if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) {
|
||||
flags = TEXT_INVERTED_COLOR | (flags & 0x0ffff);
|
||||
if (FONTSIZE(flags) == TINSIZE)
|
||||
drawSolidFilledRect(x-INVERT_HORZ_MARGIN+2, y-INVERT_VERT_MARGIN+2, width+2*INVERT_HORZ_MARGIN-5, INVERT_LINE_HEIGHT-7, TEXT_INVERTED_BGCOLOR);
|
||||
else if (FONTSIZE(flags) == SMLSIZE)
|
||||
drawSolidFilledRect(x-INVERT_HORZ_MARGIN+1, y-INVERT_VERT_MARGIN, width+2*INVERT_HORZ_MARGIN-2, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
else
|
||||
drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y/*-INVERT_VERT_MARGIN*/, width+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
|
||||
char str[256];
|
||||
if (flags & ZCHAR)
|
||||
strcat_zchar(str, s, len);
|
||||
else
|
||||
strAppend(str, s, len);
|
||||
|
||||
const coord_t orig_x = x;
|
||||
bool setx = false;
|
||||
while (len--) {
|
||||
unsigned char c;
|
||||
if (flags & ZCHAR)
|
||||
c = idx2char(*s);
|
||||
else
|
||||
c = pgm_read_byte(s);
|
||||
if (setx) {
|
||||
x = c;
|
||||
setx = false;
|
||||
}
|
||||
else if (!c) {
|
||||
break;
|
||||
}
|
||||
else if (c >= 0x20) {
|
||||
drawFontPattern(x, y, font, fontspecs, getMappedChar(c), flags);
|
||||
x = lcdNextPos;
|
||||
}
|
||||
else if (c == 0x1F) { // X-coord prefix
|
||||
setx = true;
|
||||
}
|
||||
else if (c == 0x1E) {
|
||||
x = orig_x;
|
||||
y += height;
|
||||
}
|
||||
else if (c == 1) {
|
||||
x += 1;
|
||||
}
|
||||
else {
|
||||
x += 2*(c-1);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
lcdNextPos = x;
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawBitmapPie(int x0, int y0, const uint16_t * img, int startAngle, int endAngle)
|
||||
{
|
||||
const uint16_t * q = img;
|
||||
coord_t width = *q++;
|
||||
coord_t height = *q++;
|
||||
|
||||
int slopes[4];
|
||||
if (!evalSlopes(slopes, startAngle, endAngle))
|
||||
return;
|
||||
|
||||
int w2 = width/2;
|
||||
int h2 = height/2;
|
||||
|
||||
for (int y=h2-1; y>=0; y--) {
|
||||
for (int x=w2-1; x>=0; x--) {
|
||||
int slope = (x==0 ? (y<0 ? -99000 : 99000) : y*100/x);
|
||||
if (slope >= slopes[0] && slope < slopes[1]) {
|
||||
*getPixelPtr(x0+w2+x, y0+h2-y) = q[(h2-y)*width + w2+x];
|
||||
}
|
||||
if (-slope >= slopes[0] && -slope < slopes[1]) {
|
||||
*getPixelPtr(x0+w2+x, y0+h2+y) = q[(h2+y)*width + w2+x];
|
||||
}
|
||||
if (slope >= slopes[2] && slope < slopes[3]) {
|
||||
*getPixelPtr(x0+w2-x, y0+h2-y) = q[(h2-y)*width + w2-x];
|
||||
}
|
||||
if (-slope >= slopes[2] && -slope < slopes[3]) {
|
||||
*getPixelPtr(x0+w2-x, y0+h2+y) = q[(h2+y)*width + w2-x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * img, LcdFlags flags, int startAngle, int endAngle)
|
||||
{
|
||||
coord_t width = *((uint16_t *)img);
|
||||
coord_t height = *(((uint16_t *)img)+1);
|
||||
const uint8_t * q = img+4;
|
||||
|
||||
int slopes[4];
|
||||
if (!evalSlopes(slopes, startAngle, endAngle))
|
||||
return;
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(flags)];
|
||||
|
||||
int w2 = width/2;
|
||||
int h2 = height/2;
|
||||
|
||||
for (int y=h2-1; y>=0; y--) {
|
||||
for (int x=w2-1; x>=0; x--) {
|
||||
int slope = (x==0 ? (y<0 ? -99000 : 99000) : y*100/x);
|
||||
if (slope >= slopes[0] && slope < slopes[1]) {
|
||||
drawAlphaPixel(x0+w2+x, y0+h2-y, q[(h2-y)*width + w2+x], color);
|
||||
}
|
||||
if (-slope >= slopes[0] && -slope < slopes[1]) {
|
||||
drawAlphaPixel(x0+w2+x, y0+h2+y, q[(h2+y)*width + w2+x], color);
|
||||
}
|
||||
if (slope >= slopes[2] && slope < slopes[3]) {
|
||||
drawAlphaPixel(x0+w2-x, y0+h2-y, q[(h2-y)*width + w2-x], color);
|
||||
}
|
||||
if (-slope >= slopes[2] && -slope < slopes[3]) {
|
||||
drawAlphaPixel(x0+w2-x, y0+h2+y, q[(h2+y)*width + w2-x], color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BitmapBuffer * BitmapBuffer::load(const char * filename)
|
||||
{
|
||||
FIL bmpFile;
|
||||
UINT read;
|
||||
uint8_t palette[16];
|
||||
uint8_t bmpBuf[LCD_W]; /* maximum with LCD_W */
|
||||
uint8_t * buf = &bmpBuf[0];
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f_size(&bmpFile) < 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = f_read(&bmpFile, buf, 14, &read);
|
||||
if (result != FR_OK || read != 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buf[0] != 'B' || buf[1] != 'M') {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t fsize = *((uint32_t *)&buf[2]);
|
||||
uint32_t hsize = *((uint32_t *)&buf[10]); /* header size */
|
||||
|
||||
uint32_t len = limit((uint32_t)4, (uint32_t)(hsize-14), (uint32_t)32);
|
||||
result = f_read(&bmpFile, buf, len, &read);
|
||||
if (result != FR_OK || read != len) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t ihsize = *((uint32_t *)&buf[0]); /* more header size */
|
||||
|
||||
/* invalid header size */
|
||||
if (ihsize + 14 > hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sometimes file size is set to some headers size, set a real size in that case */
|
||||
if (fsize == 14 || fsize == ihsize + 14)
|
||||
fsize = f_size(&bmpFile) - 2;
|
||||
|
||||
/* declared file size less than header size */
|
||||
if (fsize <= hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t w, h;
|
||||
|
||||
switch (ihsize){
|
||||
case 40: // windib
|
||||
case 56: // windib v3
|
||||
case 64: // OS/2 v2
|
||||
case 108: // windib v4
|
||||
case 124: // windib v5
|
||||
w = *((uint32_t *)&buf[4]);
|
||||
h = *((uint32_t *)&buf[8]);
|
||||
buf += 12;
|
||||
break;
|
||||
case 12: // OS/2 v1
|
||||
w = *((uint16_t *)&buf[4]);
|
||||
h = *((uint16_t *)&buf[6]);
|
||||
buf += 8;
|
||||
break;
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*((uint16_t *)&buf[0]) != 1) { /* planes */
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t depth = *((uint16_t *)&buf[2]);
|
||||
|
||||
buf = &bmpBuf[0];
|
||||
|
||||
if (depth == 4) {
|
||||
if (f_lseek(&bmpFile, hsize-64) != FR_OK || f_read(&bmpFile, buf, 64, &read) != FR_OK || read != 64) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t i=0; i<16; i++) {
|
||||
palette[i] = buf[4*i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (f_lseek(&bmpFile, hsize) != FR_OK) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BitmapBuffer * bmp = new BitmapBuffer(w, h);
|
||||
if (bmp == NULL) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t * dest = bmp->data;
|
||||
uint32_t rowSize;
|
||||
|
||||
switch (depth) {
|
||||
case 32:
|
||||
for (int i=h-1; i>=0; i--) {
|
||||
uint8_t * dst = ((uint8_t *)dest) + i*w*2;
|
||||
for (unsigned int j=0; j<w; j++) {
|
||||
uint32_t pixel;
|
||||
result = f_read(&bmpFile, (uint8_t *)&pixel, 4, &read);
|
||||
if (result != FR_OK || read != 4) {
|
||||
f_close(&bmpFile);
|
||||
free(bmp);
|
||||
return NULL;
|
||||
}
|
||||
*((uint16_t *)dst) = RGB((pixel>>24) & 0xff, (pixel>>16) & 0xff, (pixel>>8) & 0xff);
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rowSize = ((4*w+31)/32)*4;
|
||||
for (int32_t i=h-1; i>=0; i--) {
|
||||
result = f_read(&bmpFile, buf, rowSize, &read);
|
||||
if (result != FR_OK || read != rowSize) {
|
||||
f_close(&bmpFile);
|
||||
free(bmp);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t * dst = ((uint8_t *)dest) + i*w*2;
|
||||
for (uint32_t j=0; j<w; j++) {
|
||||
uint8_t index = (buf[j/2] >> ((j & 1) ? 0 : 4)) & 0x0F;
|
||||
uint8_t val = palette[index];
|
||||
*((uint16_t *)dst) = RGB(val, val, val);
|
||||
dst += 2;
|
||||
// *dst++ = 0x0F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
free(bmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_close(&bmpFile);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_ONLY_JPEG
|
||||
#define STBI_ONLY_BMP
|
||||
#define STBI_NO_STDIO
|
||||
#include "thirdparty/Stb/stb_image.h"
|
||||
|
||||
|
||||
// fill 'data' with 'size' bytes. return number of bytes actually read
|
||||
int stbc_read(void *user, char *data, int size)
|
||||
{
|
||||
FIL * fp = (FIL *)user;
|
||||
UINT br = 0;
|
||||
FRESULT res = f_read(fp, data, size, &br);
|
||||
if (res == FR_OK) {
|
||||
return (int)br;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip the next 'n' bytes, or 'unget' the last -n bytes if negative
|
||||
void stbc_skip(void *user, int n)
|
||||
{
|
||||
FIL * fp = (FIL *)user;
|
||||
f_lseek(fp, f_tell(fp) + n);
|
||||
}
|
||||
|
||||
// returns nonzero if we are at end of file/data
|
||||
int stbc_eof(void *user)
|
||||
{
|
||||
FIL * fp = (FIL *)user;
|
||||
return f_eof(fp);
|
||||
}
|
||||
|
||||
// callbacks for stb-image
|
||||
const stbi_io_callbacks stbCallbacks = {
|
||||
stbc_read,
|
||||
stbc_skip,
|
||||
stbc_eof
|
||||
};
|
||||
|
||||
const char * imgLoad(uint8_t * bmp, const char * filename, uint16_t width, uint16_t height)
|
||||
{
|
||||
FIL imgFile;
|
||||
|
||||
FRESULT result = f_open(&imgFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
int x,y,n;
|
||||
unsigned char *data = stbi_load_from_callbacks(&stbCallbacks, &imgFile, &x, &y, &n, 3);
|
||||
f_close(&imgFile);
|
||||
|
||||
if (!data) {
|
||||
return "stb error";
|
||||
}
|
||||
|
||||
//convert to 565 fromat
|
||||
// todo use dma2d for conversion from 888 to 565
|
||||
unsigned char *p = data;
|
||||
uint16_t * dest = (uint16_t *)bmp;
|
||||
|
||||
*dest++ = min<int>(width, x);
|
||||
*dest++ = min<int>(height, y);
|
||||
|
||||
for(int row = 0; row < min<int>(height, y); ++row) {
|
||||
unsigned char *l = p;
|
||||
for(int col = 0; col < min<int>(width, x); ++col) {
|
||||
*dest = RGB(l[0], l[1], l[2]);
|
||||
++dest;
|
||||
l += 3;
|
||||
}
|
||||
p += 3 * x;
|
||||
}
|
||||
stbi_image_free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float getBitmapScale(const BitmapBuffer * bitmap, int width, int height)
|
||||
{
|
||||
float widthScale = float(width) / bitmap->getWidth();
|
||||
float heightScale = float(height) / bitmap->getHeight();
|
||||
return min(widthScale, heightScale);
|
||||
}
|
242
radio/src/gui/horus/bitmapbuffer.h
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#ifndef _BITMAP_BUFFER_H_
|
||||
#define _BITMAP_BUFFER_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "colors.h"
|
||||
|
||||
// TODO should go to lcd.h again
|
||||
typedef int coord_t;
|
||||
typedef uint32_t LcdFlags;
|
||||
typedef uint16_t display_t;
|
||||
|
||||
inline int getBitmapScaledSize(int size, float scale)
|
||||
{
|
||||
if (scale == 0.0)
|
||||
return size;
|
||||
else
|
||||
return (0.5 + size) * scale;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class BitmapBufferBase
|
||||
{
|
||||
public:
|
||||
BitmapBufferBase(int width, int height, T * data):
|
||||
width(width),
|
||||
height(height),
|
||||
data(data)
|
||||
{
|
||||
}
|
||||
|
||||
int getWidth() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
int getHeight() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
protected:
|
||||
int width;
|
||||
int height;
|
||||
|
||||
public: // TODO protected
|
||||
T * data;
|
||||
};
|
||||
|
||||
typedef BitmapBufferBase<const uint16_t> Bitmap;
|
||||
|
||||
class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
||||
{
|
||||
public:
|
||||
|
||||
BitmapBuffer(int width, int height):
|
||||
BitmapBufferBase<uint16_t>(width, height, NULL)
|
||||
{
|
||||
data = (uint16_t *)malloc(width*height*sizeof(uint16_t));
|
||||
}
|
||||
|
||||
BitmapBuffer(int width, int height, uint16_t * data):
|
||||
BitmapBufferBase<uint16_t>(width, height, data)
|
||||
{
|
||||
}
|
||||
|
||||
~BitmapBuffer()
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
drawSolidFilledRect(0, 0, width, height, 0);
|
||||
}
|
||||
|
||||
inline void drawPixel(display_t * p, display_t value)
|
||||
{
|
||||
*p = value;
|
||||
}
|
||||
|
||||
inline display_t * getPixelPtr(coord_t x, coord_t y)
|
||||
{
|
||||
return &data[y*width + x];
|
||||
}
|
||||
|
||||
inline void drawPixel(coord_t x, coord_t y, display_t value)
|
||||
{
|
||||
display_t * p = getPixelPtr(x, y);
|
||||
drawPixel(p, value);
|
||||
}
|
||||
|
||||
void drawAlphaPixel(display_t * p, uint8_t opacity, uint16_t color);
|
||||
|
||||
inline void drawAlphaPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t color)
|
||||
{
|
||||
display_t * p = getPixelPtr(x, y);
|
||||
drawAlphaPixel(p, opacity, color);
|
||||
}
|
||||
|
||||
void drawHorizontalLine(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att);
|
||||
|
||||
void drawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags att);
|
||||
|
||||
inline void drawSolidFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags flags)
|
||||
{
|
||||
DMAFillRect(data, width, x, y, w, h, lcdColorTable[COLOR_IDX(flags)]);
|
||||
}
|
||||
|
||||
void drawFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att);
|
||||
|
||||
void invertRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags att);
|
||||
|
||||
void drawCircle(int x0, int y0, int radius);
|
||||
|
||||
void drawPie(int x0, int y0, int radius, int startAngle, int endAngle);
|
||||
|
||||
void drawBitmapPie(int x0, int y0, const uint16_t * img, int startAngle, int endAngle);
|
||||
|
||||
void drawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * img, LcdFlags flags, int startAngle, int endAngle);
|
||||
|
||||
static BitmapBuffer * load(const char * filename);
|
||||
|
||||
void drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset=0, coord_t width=0);
|
||||
|
||||
void drawFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags);
|
||||
|
||||
void drawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags flags);
|
||||
|
||||
template<class T>
|
||||
void drawBitmap(coord_t x, coord_t y, const T * bmp, coord_t srcx=0, coord_t srcy=0, coord_t w=0, coord_t h=0, float scale=0)
|
||||
{
|
||||
int srcw = bmp->getWidth();
|
||||
int srch = bmp->getHeight();
|
||||
|
||||
if (w == 0)
|
||||
w = srcw;
|
||||
if (h == 0)
|
||||
h = srch;
|
||||
if (srcx+w > srcw)
|
||||
w = srcw - srcx;
|
||||
if (srcy+h > srch)
|
||||
h = srch - srcy;
|
||||
|
||||
if (scale == 0) {
|
||||
if (x + w > width) {
|
||||
w = width - x;
|
||||
}
|
||||
if (y + h > height) {
|
||||
h = height - y;
|
||||
}
|
||||
if (srcw == w) {
|
||||
DMACopyBitmap(data, width, x, y, &bmp->data[srcw*srcy], srcw, h);
|
||||
}
|
||||
else {
|
||||
for (int i=0; i<h; i++) {
|
||||
DMACopyBitmap(data, width, x, y+i, &bmp->data[srcw*(srcy+i)+srcx], w, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int scaledw = w * scale;
|
||||
int scaledh = h * scale;
|
||||
|
||||
if (x + scaledw > width)
|
||||
scaledw = width - x;
|
||||
if (y + scaledh > height)
|
||||
scaledh = height - y;
|
||||
|
||||
for (int i = 0; i < scaledh; i++) {
|
||||
uint16_t * p = &data[(y + i) * width + x];
|
||||
const uint16_t * qstart = &bmp->data[(srcy + int(i / scale)) * bmp->getWidth() + srcx];
|
||||
for (int j = 0; j < scaledw; j++) {
|
||||
const uint16_t * q = qstart + int(j / scale);
|
||||
*p = *q;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void drawScaledBitmap(const T * bitmap, coord_t x, coord_t y, coord_t w, coord_t h)
|
||||
{
|
||||
coord_t bitmapWidth = bitmap->getWidth();
|
||||
|
||||
float scale = float(h) / bitmap->getHeight();
|
||||
int width = getBitmapScaledSize(bitmapWidth, scale);
|
||||
if (width > w) {
|
||||
int ww = (0.5 + w) / scale;
|
||||
drawBitmap(x, y, bitmap, (bitmapWidth - ww)/2, 0, ww, 0, scale);
|
||||
}
|
||||
else {
|
||||
drawBitmap(x+(w-width)/2, y, bitmap, 0, 0, 0, 0, scale);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void drawAlphaBitmap(coord_t x, coord_t y, const T * bmp)
|
||||
{
|
||||
int width = bmp->getWidth();
|
||||
int height = bmp->getHeight();
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (coord_t line=0; line<height; line++) {
|
||||
display_t * p = getPixelPtr(x, y+line);
|
||||
const uint8_t * q = ((uint8_t *)bmp->data) + line*width*2;
|
||||
for (coord_t col=0; col<width; col++) {
|
||||
drawAlphaPixel(p, q[1] >> 4, ((q[1] & 0x0f) << 12) + ((q[0] & 0xf0) << 3) + ((q[0] & 0x0f) << 1));
|
||||
p++; q+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
float getBitmapScale(const BitmapBuffer * bitmap, int width, int height);
|
||||
|
||||
extern BitmapBuffer * lcd;
|
||||
|
||||
#endif // _BITMAP_BUFFER_H_
|
|
@ -18,7 +18,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
#include "opentx.h"
|
||||
|
||||
/*
|
||||
* Header bitmaps
|
||||
|
@ -268,30 +268,10 @@ const uint8_t LBM_STAR1[] = {
|
|||
#include "mask_library_star_1.lbm"
|
||||
};
|
||||
|
||||
/*
|
||||
* Calibration screen
|
||||
*/
|
||||
|
||||
const uint8_t LBM_HORUS[] = {
|
||||
#include "alpha_horus.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_STICK_BACKGROUND[] = {
|
||||
#include "alpha_stick_background.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_STICK_POINTER[] = {
|
||||
#include "alpha_stick_pointer.lbm"
|
||||
};
|
||||
|
||||
/*
|
||||
* Other
|
||||
*/
|
||||
|
||||
const uint8_t LBM_ASTERISK[] = {
|
||||
#include "alpha_asterisk.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_POINT[] = {
|
||||
#include "mask_point.lbm"
|
||||
};
|
||||
|
@ -308,14 +288,6 @@ const uint8_t LBM_CURVE_COORD_SHADOW[] = {
|
|||
#include "mask_coord_shadow.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_SHUTDOWN[] = {
|
||||
#include "alpha_shutdown.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_SLEEP[] __ALIGNED = {
|
||||
#include "bmp_sleep.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_SHUTDOWN_CIRCLE[] = {
|
||||
#include "mask_shutdown_circle.lbm"
|
||||
};
|
||||
|
@ -348,14 +320,6 @@ const uint8_t LBM_CARROUSSEL_RIGHT[] = {
|
|||
#include "mask_carroussel_right.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_BUTTON_ON[] = {
|
||||
#include "alpha_button_on.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_BUTTON_OFF[] = {
|
||||
#include "alpha_button_off.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_SWIPE_CIRCLE[] = {
|
||||
#include "mask_swipe_circle.lbm"
|
||||
};
|
||||
|
@ -367,4 +331,3 @@ const uint8_t LBM_SWIPE_LEFT[] = {
|
|||
const uint8_t LBM_SWIPE_RIGHT[] = {
|
||||
#include "mask_swipe_right.lbm"
|
||||
};
|
||||
|
||||
|
|
|
@ -65,20 +65,12 @@ extern const uint8_t LBM_SCORE1[];
|
|||
extern const uint8_t LBM_STAR0[];
|
||||
extern const uint8_t LBM_STAR1[];
|
||||
|
||||
// Calibration screen
|
||||
extern const uint8_t LBM_HORUS[];
|
||||
extern const uint8_t LBM_STICK_BACKGROUND[];
|
||||
extern const uint8_t LBM_STICK_POINTER[];
|
||||
|
||||
// Other icons
|
||||
extern const uint8_t LBM_SPLASH[];
|
||||
extern const uint8_t LBM_ASTERISK[];
|
||||
extern const uint8_t LBM_POINT[];
|
||||
extern const uint8_t LBM_CURVE_POINT[];
|
||||
extern const uint8_t LBM_CURVE_POINT_CENTER[];
|
||||
extern const uint8_t LBM_CURVE_COORD_SHADOW[];
|
||||
extern const uint8_t LBM_SHUTDOWN[];
|
||||
extern const uint8_t LBM_SLEEP[];
|
||||
extern const uint8_t LBM_SHUTDOWN_CIRCLE[];
|
||||
|
||||
// Slider bitmaps
|
||||
|
@ -92,10 +84,6 @@ extern const uint8_t LBM_SLIDER_POINT_IN[];
|
|||
extern const uint8_t LBM_CARROUSSEL_LEFT[];
|
||||
extern const uint8_t LBM_CARROUSSEL_RIGHT[];
|
||||
|
||||
// Button bitmaps
|
||||
extern const uint8_t LBM_BUTTON_ON[];
|
||||
extern const uint8_t LBM_BUTTON_OFF[];
|
||||
|
||||
extern const uint8_t LBM_SWIPE_CIRCLE[];
|
||||
extern const uint8_t LBM_SWIPE_LEFT[];
|
||||
extern const uint8_t LBM_SWIPE_RIGHT[];
|
||||
|
|
116
radio/src/gui/horus/colors.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#ifndef _COLORS_H_
|
||||
#define _COLORS_H_
|
||||
|
||||
// remove windows default definitions
|
||||
#undef OPAQUE
|
||||
#undef RGB
|
||||
|
||||
#define TO5BITS(x) ((x) >> 3)
|
||||
#define TO6BITS(x) ((x) >> 2)
|
||||
#define RGB(r, g, b) ((TO5BITS(r) << 11) + (TO6BITS(g) << 5) + (TO5BITS(b) << 0))
|
||||
#define WHITE RGB(0xFF, 0xFF, 0xFF)
|
||||
#define BLACK RGB(0, 0, 0)
|
||||
#define YELLOW RGB(0xF0, 0xD0, 0x10)
|
||||
#define BLUE RGB(0x30, 0xA0, 0xE0)
|
||||
#define GREY RGB(96, 96, 96)
|
||||
#define DARKGREY RGB(64, 64, 64)
|
||||
#define LIGHTGREY RGB(180, 180, 180)
|
||||
#define RED RGB(229, 32, 30)
|
||||
#define DARKRED RGB(160, 0, 6)
|
||||
|
||||
#define OPACITY_MAX 0x0F
|
||||
#define OPACITY(x) ((x)<<24)
|
||||
|
||||
enum LcdColorIndex
|
||||
{
|
||||
TEXT_COLOR_INDEX,
|
||||
TEXT_BGCOLOR_INDEX,
|
||||
TEXT_INVERTED_COLOR_INDEX,
|
||||
TEXT_INVERTED_BGCOLOR_INDEX,
|
||||
LINE_COLOR_INDEX,
|
||||
SCROLLBOX_COLOR_INDEX,
|
||||
MENU_TITLE_BGCOLOR_INDEX,
|
||||
MENU_TITLE_COLOR_INDEX,
|
||||
MENU_TITLE_DISABLE_COLOR_INDEX,
|
||||
HEADER_COLOR_INDEX,
|
||||
ALARM_COLOR_INDEX,
|
||||
WARNING_COLOR_INDEX,
|
||||
TEXT_DISABLE_COLOR_INDEX,
|
||||
CURVE_AXIS_COLOR_INDEX,
|
||||
CURVE_COLOR_INDEX,
|
||||
CURVE_CURSOR_COLOR_INDEX,
|
||||
HEADER_BGCOLOR_INDEX,
|
||||
HEADER_ICON_BGCOLOR_INDEX,
|
||||
HEADER_CURRENT_BGCOLOR_INDEX,
|
||||
TITLE_BGCOLOR_INDEX,
|
||||
TRIM_BGCOLOR_INDEX,
|
||||
TRIM_SHADOW_COLOR_INDEX,
|
||||
MAINVIEW_PANES_COLOR_INDEX,
|
||||
MAINVIEW_GRAPHICS_COLOR_INDEX,
|
||||
OVERLAY_COLOR_INDEX,
|
||||
CUSTOM_COLOR_INDEX,
|
||||
LCD_COLOR_COUNT
|
||||
};
|
||||
|
||||
extern uint16_t lcdColorTable[LCD_COLOR_COUNT];
|
||||
|
||||
#define COLOR(index) ((index) << 16)
|
||||
#define COLOR_IDX(att) uint8_t((att) >> 16)
|
||||
|
||||
#define TEXT_COLOR COLOR(TEXT_COLOR_INDEX)
|
||||
#define TEXT_BGCOLOR COLOR(TEXT_BGCOLOR_INDEX)
|
||||
#define TEXT_INVERTED_COLOR COLOR(TEXT_INVERTED_COLOR_INDEX)
|
||||
#define TEXT_INVERTED_BGCOLOR COLOR(TEXT_INVERTED_BGCOLOR_INDEX)
|
||||
#define LINE_COLOR COLOR(LINE_COLOR_INDEX)
|
||||
#define SCROLLBOX_COLOR COLOR(SCROLLBOX_COLOR_INDEX)
|
||||
#define HEADER_SEPARATOR_COLOR COLOR(HEADER_SEPARATOR_COLOR_INDEX)
|
||||
#define MENU_TITLE_BGCOLOR COLOR(MENU_TITLE_BGCOLOR_INDEX)
|
||||
#define MENU_TITLE_COLOR COLOR(MENU_TITLE_COLOR_INDEX)
|
||||
#define MENU_TITLE_DISABLE_COLOR COLOR(MENU_TITLE_DISABLE_COLOR_INDEX)
|
||||
#define HEADER_COLOR COLOR(HEADER_COLOR_INDEX)
|
||||
#define ALARM_COLOR COLOR(ALARM_COLOR_INDEX)
|
||||
#define WARNING_COLOR COLOR(WARNING_COLOR_INDEX)
|
||||
#define TEXT_DISABLE_COLOR COLOR(TEXT_DISABLE_COLOR_INDEX)
|
||||
#define CURVE_AXIS_COLOR COLOR(CURVE_AXIS_COLOR_INDEX)
|
||||
#define CURVE_COLOR COLOR(CURVE_COLOR_INDEX)
|
||||
#define CURVE_CURSOR_COLOR COLOR(CURVE_CURSOR_COLOR_INDEX)
|
||||
#define TITLE_BGCOLOR COLOR(TITLE_BGCOLOR_INDEX)
|
||||
#define TRIM_BGCOLOR COLOR(TRIM_BGCOLOR_INDEX)
|
||||
#define TRIM_SHADOW_COLOR COLOR(TRIM_SHADOW_COLOR_INDEX)
|
||||
#define HEADER_BGCOLOR COLOR(HEADER_BGCOLOR_INDEX)
|
||||
#define HEADER_ICON_BGCOLOR COLOR(HEADER_ICON_BGCOLOR_INDEX)
|
||||
#define HEADER_CURRENT_BGCOLOR COLOR(HEADER_CURRENT_BGCOLOR_INDEX)
|
||||
#define MAINVIEW_PANES_COLOR COLOR(MAINVIEW_PANES_COLOR_INDEX)
|
||||
#define MAINVIEW_GRAPHICS_COLOR COLOR(MAINVIEW_GRAPHICS_COLOR_INDEX)
|
||||
#define OVERLAY_COLOR COLOR(OVERLAY_COLOR_INDEX)
|
||||
#define CUSTOM_COLOR COLOR(CUSTOM_COLOR_INDEX)
|
||||
|
||||
#define COLOR_SPLIT(color, r, g, b) \
|
||||
uint16_t r = ((color) & 0xF800) >> 11; \
|
||||
uint16_t g = ((color) & 0x07E0) >> 5; \
|
||||
uint16_t b = ((color) & 0x001F)
|
||||
|
||||
#define COLOR_JOIN(r, g, b) \
|
||||
(((r) << 11) + ((g) << 5) + (b))
|
||||
|
||||
#endif // _COLORS_H_
|
|
@ -26,6 +26,7 @@
|
|||
display_t displayBuf[DISPLAY_BUFFER_SIZE];
|
||||
#endif
|
||||
|
||||
|
||||
uint16_t lcdColorTable[LCD_COLOR_COUNT];
|
||||
|
||||
coord_t lcdNextPos;
|
||||
|
@ -52,31 +53,6 @@ int getCharWidth(char c, const uint16_t * spec)
|
|||
return getFontPatternWidth(spec, getMappedChar(c));
|
||||
}
|
||||
|
||||
void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags, coord_t offset, coord_t width)
|
||||
{
|
||||
coord_t w = *((uint16_t *)img);
|
||||
coord_t height = *(((uint16_t *)img)+1);
|
||||
|
||||
if (!width || width > w) {
|
||||
width = w;
|
||||
}
|
||||
|
||||
if (x+width > LCD_W) {
|
||||
width = LCD_W-x;
|
||||
}
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(flags)];
|
||||
|
||||
for (coord_t row=0; row<height; row++) {
|
||||
display_t * p = PIXEL_PTR(x, y+row);
|
||||
const uint8_t * q = img + 4 + row*w + offset;
|
||||
for (coord_t col=0; col<width; col++) {
|
||||
lcdDrawAlphaPixel(p, *q, color);
|
||||
p++; q++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FONT_MAX_HEIGHT 42
|
||||
void lcdPutFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags)
|
||||
{
|
||||
|
@ -109,20 +85,6 @@ int getFontHeight(LcdFlags flags)
|
|||
return heightTable[FONTSIZE(flags) >> 8];
|
||||
}
|
||||
|
||||
float getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight)
|
||||
{
|
||||
int bmpWidth = getBitmapWidth(bmp);
|
||||
int bmpHeight = getBitmapHeight(bmp);
|
||||
|
||||
if (bmpWidth == 0 || bmpHeight == 0)
|
||||
return 0;
|
||||
|
||||
float widthScale = float(dstWidth) / bmpWidth;
|
||||
float heightScale = float(dstHeight) / bmpHeight;
|
||||
|
||||
return min(widthScale, heightScale);
|
||||
}
|
||||
|
||||
int getTextWidth(const char * s, int len, LcdFlags flags)
|
||||
{
|
||||
const uint16_t * specs = fontspecsTable[FONTSIZE(flags) >> 8];
|
||||
|
@ -142,79 +104,12 @@ int getTextWidth(const char * s, int len, LcdFlags flags)
|
|||
return result;
|
||||
}
|
||||
|
||||
void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags flags)
|
||||
{
|
||||
int width = getTextWidth(s, len, flags);
|
||||
int height = getFontHeight(flags);
|
||||
int fontindex = FONTSIZE(flags) >> 8;
|
||||
const pm_uchar * font = fontsTable[fontindex];
|
||||
const uint16_t * fontspecs = fontspecsTable[fontindex];
|
||||
|
||||
if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) {
|
||||
flags = TEXT_INVERTED_COLOR | (flags & 0x0ffff);
|
||||
if (FONTSIZE(flags) == TINSIZE)
|
||||
lcdDrawSolidFilledRect(x-INVERT_HORZ_MARGIN+2, y-INVERT_VERT_MARGIN+2, width+2*INVERT_HORZ_MARGIN-5, INVERT_LINE_HEIGHT-7, TEXT_INVERTED_BGCOLOR);
|
||||
else if (FONTSIZE(flags) == SMLSIZE)
|
||||
lcdDrawSolidFilledRect(x-INVERT_HORZ_MARGIN+1, y-INVERT_VERT_MARGIN, width+2*INVERT_HORZ_MARGIN-2, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
else
|
||||
lcdDrawSolidFilledRect(x-INVERT_HORZ_MARGIN, y/*-INVERT_VERT_MARGIN*/, width+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
|
||||
char str[256];
|
||||
if (flags & ZCHAR)
|
||||
strcat_zchar(str, s, len);
|
||||
else
|
||||
strAppend(str, s, len);
|
||||
|
||||
const coord_t orig_x = x;
|
||||
bool setx = false;
|
||||
while (len--) {
|
||||
unsigned char c;
|
||||
if (flags & ZCHAR)
|
||||
c = idx2char(*s);
|
||||
else
|
||||
c = pgm_read_byte(s);
|
||||
if (setx) {
|
||||
x = c;
|
||||
setx = false;
|
||||
}
|
||||
else if (!c) {
|
||||
break;
|
||||
}
|
||||
else if (c >= 0x20) {
|
||||
lcdPutFontPattern(x, y, font, fontspecs, getMappedChar(c), flags);
|
||||
x = lcdNextPos;
|
||||
}
|
||||
else if (c == 0x1F) { // X-coord prefix
|
||||
setx = true;
|
||||
}
|
||||
else if (c == 0x1E) {
|
||||
x = orig_x;
|
||||
y += height;
|
||||
}
|
||||
else if (c == 1) {
|
||||
x += 1;
|
||||
}
|
||||
else {
|
||||
x += 2*(c-1);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
lcdNextPos = x;
|
||||
}
|
||||
|
||||
void lcdDrawText(coord_t x, coord_t y, const pm_char * s, LcdFlags flags)
|
||||
{
|
||||
lcdDrawSizedText(x, y, s, 255, flags);
|
||||
}
|
||||
|
||||
void lcd_putsCenter(coord_t y, const pm_char * s, LcdFlags attr)
|
||||
{
|
||||
int x = (LCD_W - getTextWidth(s)) / 2;
|
||||
lcdDrawText(x, y, s, attr);
|
||||
}
|
||||
|
||||
void lcdDrawTextAtIndex(coord_t x, coord_t y, const pm_char * s,uint8_t idx, LcdFlags flags)
|
||||
void lcdDrawTextAtIndex(coord_t x, coord_t y, const pm_char * s, uint8_t idx, LcdFlags flags)
|
||||
{
|
||||
uint8_t length;
|
||||
length = pgm_read_byte(s++);
|
||||
|
@ -230,10 +125,6 @@ void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags flags)
|
|||
val >>= 4;
|
||||
}
|
||||
s[4] = '\0';
|
||||
if (!(flags & LEFT))
|
||||
x -= getTextWidth(s);
|
||||
else
|
||||
flags -= LEFT;
|
||||
lcdDrawText(x, y, s, flags);
|
||||
}
|
||||
|
||||
|
@ -261,8 +152,7 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags, uint8_t le
|
|||
}
|
||||
} while (val!=0 || mode>0 || (mode==MODE(LEADING0) && idx<len));
|
||||
if (neg) *--s = '-';
|
||||
if (!(flags & LEFT))
|
||||
x -= getTextWidth(s, 0, flags);
|
||||
|
||||
// TODO needs check on all string lengths ...
|
||||
if (prefix) {
|
||||
int len = strlen(prefix);
|
||||
|
@ -274,7 +164,7 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags, uint8_t le
|
|||
if (suffix) {
|
||||
strncpy(&str[32], suffix, 16);
|
||||
}
|
||||
flags &= ~(LEADING0|LEFT);
|
||||
flags &= ~LEADING0;
|
||||
lcdDrawText(x, y, s, flags);
|
||||
}
|
||||
|
||||
|
@ -353,18 +243,6 @@ void lcdDrawSolidFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcdDrawFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
for (coord_t i=y; i<y+h; i++) {
|
||||
if ((att & ROUND) && (i==y || i==y+h-1))
|
||||
lcdDrawHorizontalLine(x+1, i, w-2, pat, att);
|
||||
else
|
||||
lcdDrawHorizontalLine(x, i, w, pat, att);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void putsRtcTime(coord_t x, coord_t y, LcdFlags att)
|
||||
{
|
||||
putsTimer(x, y, getValue(MIXSRC_TX_TIME), att);
|
||||
|
@ -766,39 +644,6 @@ void lcdSetContrast()
|
|||
lcdSetRefVolt(g_eeGeneral.contrast);
|
||||
}
|
||||
|
||||
void lcdInvertRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags att)
|
||||
{
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
COLOR_SPLIT(color, red, green, blue);
|
||||
|
||||
for (int i=y; i<y+h; i++) {
|
||||
display_t * p = PIXEL_PTR(x, i);
|
||||
for (int j=0; j<w; j++) {
|
||||
ASSERT_IN_DISPLAY(p);
|
||||
COLOR_SPLIT(*p, bgRed, bgGreen, bgBlue);
|
||||
lcdDrawPixel(p++, COLOR_JOIN(0x1F + red - bgRed, 0x3F + green - bgGreen, 0x1F + blue - bgBlue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawAlphaPixel(display_t * p, uint8_t opacity, uint16_t color)
|
||||
{
|
||||
ASSERT_IN_DISPLAY(p);
|
||||
|
||||
if (opacity == OPACITY_MAX) {
|
||||
lcdDrawPixel(p, color);
|
||||
}
|
||||
else if (opacity != 0) {
|
||||
uint8_t bgWeight = OPACITY_MAX - opacity;
|
||||
COLOR_SPLIT(color, red, green, blue);
|
||||
COLOR_SPLIT(*p, bgRed, bgGreen, bgBlue);
|
||||
uint16_t r = (bgRed * bgWeight + red * opacity) / OPACITY_MAX;
|
||||
uint16_t g = (bgGreen * bgWeight + green * opacity) / OPACITY_MAX;
|
||||
uint16_t b = (bgBlue * bgWeight + blue * opacity) / OPACITY_MAX;
|
||||
lcdDrawPixel(p, COLOR_JOIN(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att)
|
||||
{
|
||||
display_t * p = PIXEL_PTR(x, y);
|
||||
|
@ -808,294 +653,28 @@ void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att)
|
|||
}
|
||||
}
|
||||
|
||||
void lcdDrawHorizontalLine(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (y >= LCD_H) return;
|
||||
if (x+w > LCD_W) { w = LCD_W - x; }
|
||||
|
||||
display_t * p = PIXEL_PTR(x, y);
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
uint8_t opacity = 0x0F - (att >> 24);
|
||||
|
||||
if (pat == SOLID) {
|
||||
while (w--) {
|
||||
lcdDrawAlphaPixel(p, opacity, color);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (w--) {
|
||||
if (pat & 1) {
|
||||
lcdDrawAlphaPixel(p, opacity, color);
|
||||
pat = (pat >> 1) | 0x80;
|
||||
}
|
||||
else {
|
||||
pat = pat >> 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (x >= LCD_W) return;
|
||||
if (y >= LCD_H) return;
|
||||
if (h<0) { y+=h; h=-h; }
|
||||
if (y<0) { h+=y; y=0; if (h<=0) return; }
|
||||
if (y+h > LCD_H) { h = LCD_H - y; }
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
uint8_t opacity = 0x0F - (att >> 24);
|
||||
|
||||
if (pat == SOLID) {
|
||||
while (h--) {
|
||||
lcdDrawAlphaPixel(x, y, opacity, color);
|
||||
y++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pat==DOTTED && !(y%2)) {
|
||||
pat = ~pat;
|
||||
}
|
||||
while (h--) {
|
||||
if (pat & 1) {
|
||||
lcdDrawAlphaPixel(x, y, opacity, color);
|
||||
pat = (pat >> 1) | 0x80;
|
||||
}
|
||||
else {
|
||||
pat = pat >> 1;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SIMU)
|
||||
inline void lcdDrawBitmapDMA(coord_t x, coord_t y, coord_t width, coord_t height, const uint8_t * img)
|
||||
{
|
||||
lcdDrawBitmap(x, y, img-4, 0, 0, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcdDrawAlphaBitmap(coord_t x, coord_t y, const uint8_t * bmp)
|
||||
{
|
||||
int width = getBitmapWidth(bmp);
|
||||
int height = getBitmapHeight(bmp);
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (coord_t line=0; line<height; line++) {
|
||||
display_t * p = &displayBuf[(y+line)*LCD_W + x];
|
||||
const uint8_t * q = bmp + 4 + line*width*3;
|
||||
for (coord_t col=0; col<width; col++) {
|
||||
lcdDrawAlphaPixel(p, q[2]>>4, *((uint16_t *)q));
|
||||
p++; q+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * bmp, coord_t offset, coord_t height, float scale)
|
||||
{
|
||||
int width = getBitmapWidth(bmp);
|
||||
int h = getBitmapHeight(bmp);
|
||||
|
||||
if (!height || height > h) {
|
||||
height = h;
|
||||
}
|
||||
|
||||
if (x+height > LCD_W) {
|
||||
height = LCD_W-x;
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (scale == 0) {
|
||||
lcdDrawBitmapDMA(x, y, width, height, bmp + 4 + offset * width * 2);
|
||||
}
|
||||
else {
|
||||
int dstwidth = width * scale;
|
||||
int dstheight = height * scale;
|
||||
for (coord_t i=0; i<dstheight; i++) {
|
||||
display_t * p = &displayBuf[(y+i)*LCD_W + x];
|
||||
const uint8_t * qs = bmp + 4 + (offset+int(i/scale))*width*2;
|
||||
for (coord_t j=0; j<dstwidth; j++) {
|
||||
const uint8_t * q = qs + int(j/scale) * 2;
|
||||
lcdDrawPixel(p, *((uint16_t *)q));
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void lcdDrawBlackOverlay()
|
||||
{
|
||||
lcdDrawFilledRect(0, 0, LCD_W, LCD_H, SOLID, OVERLAY_COLOR | OPACITY(8));
|
||||
}
|
||||
|
||||
void lcdDrawCircle(int x0, int y0, int radius)
|
||||
{
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
int decisionOver2 = 1 - x;
|
||||
#if defined(SIMU)
|
||||
BitmapBuffer _lcd(LCD_W, LCD_H, displayBuf);
|
||||
BitmapBuffer * lcd = &_lcd;
|
||||
|
||||
while (y <= x) {
|
||||
lcdDrawPixel(x+x0, y+y0, WHITE);
|
||||
lcdDrawPixel(y+x0, x+y0, WHITE);
|
||||
lcdDrawPixel(-x+x0, y+y0, WHITE);
|
||||
lcdDrawPixel(-y+x0, x+y0, WHITE);
|
||||
lcdDrawPixel(-x+x0, -y+y0, WHITE);
|
||||
lcdDrawPixel(-y+x0, -x+y0, WHITE);
|
||||
lcdDrawPixel(x+x0, -y+y0, WHITE);
|
||||
lcdDrawPixel(y+x0, -x+y0, WHITE);
|
||||
y++;
|
||||
if (decisionOver2 <= 0) {
|
||||
decisionOver2 += 2*y + 1;
|
||||
}
|
||||
else {
|
||||
x--;
|
||||
decisionOver2 += 2 * (y-x) + 1;
|
||||
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
|
||||
{
|
||||
for (int i=0; i<h; i++) {
|
||||
for (int j=0; j<w; j++) {
|
||||
dest[(y+i)*destw+x+j] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
bool evalSlopes(int * slopes, int startAngle, int endAngle)
|
||||
void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t h)
|
||||
{
|
||||
if (startAngle >= 360 || endAngle <= 0)
|
||||
return false;
|
||||
|
||||
if (startAngle == 0) {
|
||||
slopes[1] = 100000;
|
||||
slopes[2] = -100000;
|
||||
}
|
||||
else {
|
||||
float angle1 = float(startAngle) * PI / 180;
|
||||
if (startAngle >= 180) {
|
||||
slopes[1] = -100000;
|
||||
slopes[2] = cos(angle1) * 100 / sin(angle1);
|
||||
}
|
||||
else {
|
||||
slopes[1] = cos(angle1) * 100 / sin(angle1);
|
||||
slopes[2] = -100000;
|
||||
}
|
||||
}
|
||||
|
||||
if (endAngle == 360) {
|
||||
slopes[0] = -100000;
|
||||
slopes[3] = 100000;
|
||||
}
|
||||
else {
|
||||
float angle2 = float(endAngle) * PI / 180;
|
||||
if (endAngle >= 180) {
|
||||
slopes[0] = -100000;
|
||||
slopes[3] = -cos(angle2) * 100 / sin(angle2);
|
||||
}
|
||||
else {
|
||||
slopes[0] = cos(angle2) * 100 / sin(angle2);
|
||||
slopes[3] = -100000;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lcdDrawPie(int x0, int y0, int radius, int startAngle, int endAngle)
|
||||
{
|
||||
int slopes[4];
|
||||
if (!evalSlopes(slopes, startAngle, endAngle))
|
||||
return;
|
||||
|
||||
for (int y=0; y<=radius; y++) {
|
||||
for (int x=0; x<=radius; x++) {
|
||||
if (x*x+y*y <= radius*radius) {
|
||||
int slope = (x==0 ? (y<0 ? -99000 : 99000) : y*100/x);
|
||||
if (slope >= slopes[0] && slope < slopes[1]) {
|
||||
lcdDrawPixel(x0+x, y0-y, WHITE);
|
||||
}
|
||||
if (-slope >= slopes[0] && -slope < slopes[1]) {
|
||||
lcdDrawPixel(x0+x, y0+y, WHITE);
|
||||
}
|
||||
if (slope >= slopes[2] && slope < slopes[3]) {
|
||||
lcdDrawPixel(x0-x, y0-y, WHITE);
|
||||
}
|
||||
if (-slope >= slopes[2] && -slope < slopes[3]) {
|
||||
lcdDrawPixel(x0-x, y0+y, WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawBitmapPie(int x0, int y0, const uint16_t * img, int startAngle, int endAngle)
|
||||
{
|
||||
const uint16_t * q = img;
|
||||
coord_t width = *q++;
|
||||
coord_t height = *q++;
|
||||
|
||||
int slopes[4];
|
||||
if (!evalSlopes(slopes, startAngle, endAngle))
|
||||
return;
|
||||
|
||||
int w2 = width/2;
|
||||
int h2 = height/2;
|
||||
|
||||
for (int y=h2-1; y>=0; y--) {
|
||||
for (int x=w2-1; x>=0; x--) {
|
||||
int slope = (x==0 ? (y<0 ? -99000 : 99000) : y*100/x);
|
||||
if (slope >= slopes[0] && slope < slopes[1]) {
|
||||
displayBuf[(y0+h2-y)*LCD_W + x0+w2+x] = q[(h2-y)*width + w2+x];
|
||||
}
|
||||
if (-slope >= slopes[0] && -slope < slopes[1]) {
|
||||
displayBuf[(y0+h2+y)*LCD_W + x0+w2+x] = q[(h2+y)*width + w2+x];
|
||||
}
|
||||
if (slope >= slopes[2] && slope < slopes[3]) {
|
||||
displayBuf[(y0+h2-y)*LCD_W + x0+w2-x] = q[(h2-y)*width + w2-x];
|
||||
}
|
||||
if (-slope >= slopes[2] && -slope < slopes[3]) {
|
||||
displayBuf[(y0+h2+y)*LCD_W + x0+w2-x] = q[(h2+y)*width + w2-x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * img, LcdFlags flags, int startAngle, int endAngle)
|
||||
{
|
||||
coord_t width = *((uint16_t *)img);
|
||||
coord_t height = *(((uint16_t *)img)+1);
|
||||
const uint8_t * q = img+4;
|
||||
|
||||
int slopes[4];
|
||||
if (!evalSlopes(slopes, startAngle, endAngle))
|
||||
return;
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(flags)];
|
||||
|
||||
int w2 = width/2;
|
||||
int h2 = height/2;
|
||||
|
||||
for (int y=h2-1; y>=0; y--) {
|
||||
for (int x=w2-1; x>=0; x--) {
|
||||
int slope = (x==0 ? (y<0 ? -99000 : 99000) : y*100/x);
|
||||
if (slope >= slopes[0] && slope < slopes[1]) {
|
||||
lcdDrawAlphaPixel(x0+w2+x, y0+h2-y, q[(h2-y)*width + w2+x], color);
|
||||
}
|
||||
if (-slope >= slopes[0] && -slope < slopes[1]) {
|
||||
lcdDrawAlphaPixel(x0+w2+x, y0+h2+y, q[(h2+y)*width + w2+x], color);
|
||||
}
|
||||
if (slope >= slopes[2] && slope < slopes[3]) {
|
||||
lcdDrawAlphaPixel(x0+w2-x, y0+h2-y, q[(h2-y)*width + w2-x], color);
|
||||
}
|
||||
if (-slope >= slopes[2] && -slope < slopes[3]) {
|
||||
lcdDrawAlphaPixel(x0+w2-x, y0+h2+y, q[(h2+y)*width + w2-x], color);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<h; i++) {
|
||||
memcpy(dest+(y+i)*destw+x, src+i*srcw, 2*srcw);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,14 +21,12 @@
|
|||
#ifndef _LCD_H_
|
||||
#define _LCD_H_
|
||||
|
||||
#include "bitmapbuffer.h"
|
||||
|
||||
#define LCD_W 480
|
||||
#define LCD_H 272
|
||||
|
||||
#define coord_t int
|
||||
#define CENTER
|
||||
#define CENTER_OFS 0
|
||||
#define CONTRAST_MIN 0
|
||||
#define CONTRAST_MAX 45
|
||||
|
||||
#define lcdint_t int32_t
|
||||
|
||||
|
@ -40,17 +38,20 @@
|
|||
/* lcd common flags */
|
||||
#define BLINK 0x01
|
||||
|
||||
/* lcdDrawText flags */
|
||||
/* drawText flags */
|
||||
#define INVERS 0x02
|
||||
#define LEFT 0x08 /* align left */
|
||||
#define ZCHAR 0x04
|
||||
#define LEFT 0x00
|
||||
#define CENTERED 0x04 /* align left */
|
||||
#define RIGHT 0x08 /* align left */
|
||||
|
||||
/* lcdDrawNumber flags */
|
||||
/* drawNumber flags */
|
||||
#define LEADING0 0x10
|
||||
#define PREC1 0x20
|
||||
#define PREC2 0x30
|
||||
#define MODE(flags) ((((int8_t)(flags) & 0x30) - 0x10) >> 4)
|
||||
|
||||
#define ZCHAR 0x10
|
||||
|
||||
/* rect, square flags */
|
||||
#define ROUND 0x04
|
||||
|
||||
|
@ -69,109 +70,14 @@
|
|||
#define TIMEHOUR 0x2000
|
||||
#define STREXPANDED 0x4000
|
||||
|
||||
// remove windows default definitions
|
||||
#undef OPAQUE
|
||||
#undef RGB
|
||||
|
||||
#define TO5BITS(x) ((x) >> 3)
|
||||
#define TO6BITS(x) ((x) >> 2)
|
||||
#define RGB(r, g, b) ((TO5BITS(r) << 11) + (TO6BITS(g) << 5) + (TO5BITS(b) << 0))
|
||||
#define WHITE RGB(0xFF, 0xFF, 0xFF)
|
||||
#define BLACK RGB(0, 0, 0)
|
||||
#define YELLOW RGB(0xF0, 0xD0, 0x10)
|
||||
#define BLUE RGB(0x30, 0xA0, 0xE0)
|
||||
#define GREY RGB(96, 96, 96)
|
||||
#define DARKGREY RGB(64, 64, 64)
|
||||
#define LIGHTGREY RGB(180, 180, 180)
|
||||
#define RED RGB(229, 32, 30)
|
||||
#define DARKRED RGB(160, 0, 6)
|
||||
|
||||
#define LcdFlags uint32_t
|
||||
|
||||
#define OPACITY_MAX 0x0F
|
||||
#define OPACITY(x) ((x)<<24)
|
||||
|
||||
enum LcdColorIndex
|
||||
{
|
||||
TEXT_COLOR_INDEX,
|
||||
TEXT_BGCOLOR_INDEX,
|
||||
TEXT_INVERTED_COLOR_INDEX,
|
||||
TEXT_INVERTED_BGCOLOR_INDEX,
|
||||
LINE_COLOR_INDEX,
|
||||
SCROLLBOX_COLOR_INDEX,
|
||||
MENU_TITLE_BGCOLOR_INDEX,
|
||||
MENU_TITLE_COLOR_INDEX,
|
||||
MENU_TITLE_DISABLE_COLOR_INDEX,
|
||||
HEADER_COLOR_INDEX,
|
||||
ALARM_COLOR_INDEX,
|
||||
WARNING_COLOR_INDEX,
|
||||
TEXT_DISABLE_COLOR_INDEX,
|
||||
CURVE_AXIS_COLOR_INDEX,
|
||||
CURVE_COLOR_INDEX,
|
||||
CURVE_CURSOR_COLOR_INDEX,
|
||||
HEADER_BGCOLOR_INDEX,
|
||||
HEADER_ICON_BGCOLOR_INDEX,
|
||||
HEADER_CURRENT_BGCOLOR_INDEX,
|
||||
TITLE_BGCOLOR_INDEX,
|
||||
TRIM_BGCOLOR_INDEX,
|
||||
TRIM_SHADOW_COLOR_INDEX,
|
||||
MAINVIEW_PANES_COLOR_INDEX,
|
||||
MAINVIEW_GRAPHICS_COLOR_INDEX,
|
||||
OVERLAY_COLOR_INDEX,
|
||||
CUSTOM_COLOR_INDEX,
|
||||
LCD_COLOR_COUNT
|
||||
};
|
||||
|
||||
extern uint16_t lcdColorTable[LCD_COLOR_COUNT];
|
||||
|
||||
#define COLOR(index) ((index) << 16)
|
||||
#define COLOR_IDX(att) uint8_t((att) >> 16)
|
||||
|
||||
#define TEXT_COLOR COLOR(TEXT_COLOR_INDEX)
|
||||
#define TEXT_BGCOLOR COLOR(TEXT_BGCOLOR_INDEX)
|
||||
#define TEXT_INVERTED_COLOR COLOR(TEXT_INVERTED_COLOR_INDEX)
|
||||
#define TEXT_INVERTED_BGCOLOR COLOR(TEXT_INVERTED_BGCOLOR_INDEX)
|
||||
#define LINE_COLOR COLOR(LINE_COLOR_INDEX)
|
||||
#define SCROLLBOX_COLOR COLOR(SCROLLBOX_COLOR_INDEX)
|
||||
#define HEADER_SEPARATOR_COLOR COLOR(HEADER_SEPARATOR_COLOR_INDEX)
|
||||
#define MENU_TITLE_BGCOLOR COLOR(MENU_TITLE_BGCOLOR_INDEX)
|
||||
#define MENU_TITLE_COLOR COLOR(MENU_TITLE_COLOR_INDEX)
|
||||
#define MENU_TITLE_DISABLE_COLOR COLOR(MENU_TITLE_DISABLE_COLOR_INDEX)
|
||||
#define HEADER_COLOR COLOR(HEADER_COLOR_INDEX)
|
||||
#define ALARM_COLOR COLOR(ALARM_COLOR_INDEX)
|
||||
#define WARNING_COLOR COLOR(WARNING_COLOR_INDEX)
|
||||
#define TEXT_DISABLE_COLOR COLOR(TEXT_DISABLE_COLOR_INDEX)
|
||||
#define CURVE_AXIS_COLOR COLOR(CURVE_AXIS_COLOR_INDEX)
|
||||
#define CURVE_COLOR COLOR(CURVE_COLOR_INDEX)
|
||||
#define CURVE_CURSOR_COLOR COLOR(CURVE_CURSOR_COLOR_INDEX)
|
||||
#define TITLE_BGCOLOR COLOR(TITLE_BGCOLOR_INDEX)
|
||||
#define TRIM_BGCOLOR COLOR(TRIM_BGCOLOR_INDEX)
|
||||
#define TRIM_SHADOW_COLOR COLOR(TRIM_SHADOW_COLOR_INDEX)
|
||||
#define HEADER_BGCOLOR COLOR(HEADER_BGCOLOR_INDEX)
|
||||
#define HEADER_ICON_BGCOLOR COLOR(HEADER_ICON_BGCOLOR_INDEX)
|
||||
#define HEADER_CURRENT_BGCOLOR COLOR(HEADER_CURRENT_BGCOLOR_INDEX)
|
||||
#define MAINVIEW_PANES_COLOR COLOR(MAINVIEW_PANES_COLOR_INDEX)
|
||||
#define MAINVIEW_GRAPHICS_COLOR COLOR(MAINVIEW_GRAPHICS_COLOR_INDEX)
|
||||
#define OVERLAY_COLOR COLOR(OVERLAY_COLOR_INDEX)
|
||||
#define CUSTOM_COLOR COLOR(CUSTOM_COLOR_INDEX)
|
||||
|
||||
#define COLOR_SPLIT(color, r, g, b) \
|
||||
uint16_t r = ((color) & 0xF800) >> 11; \
|
||||
uint16_t g = ((color) & 0x07E0) >> 5; \
|
||||
uint16_t b = ((color) & 0x001F)
|
||||
|
||||
#define COLOR_JOIN(r, g, b) \
|
||||
(((r) << 11) + ((g) << 5) + (b))
|
||||
|
||||
#define display_t uint16_t
|
||||
#include "colors.h"
|
||||
#define DISPLAY_PIXELS_COUNT (LCD_W*LCD_H)
|
||||
#define DISPLAY_BUFFER_SIZE (sizeof(display_t)*DISPLAY_PIXELS_COUNT)
|
||||
|
||||
#if defined(SIMU)
|
||||
extern display_t displayBuf[DISPLAY_BUFFER_SIZE];
|
||||
#else
|
||||
extern uint8_t * CurrentFrameBuffer;
|
||||
#define displayBuf ((uint16_t *)CurrentFrameBuffer)
|
||||
#define displayBuf lcd->data
|
||||
#endif
|
||||
|
||||
#define lcdRefreshWait()
|
||||
|
@ -184,9 +90,17 @@ extern coord_t lcdNextPos;
|
|||
void lcdDrawChar(coord_t x, coord_t y, const unsigned char c, LcdFlags attr=0);
|
||||
void lcdDrawText(coord_t x, coord_t y, const pm_char * s, LcdFlags attr=0);
|
||||
void lcdDrawTextAtIndex(coord_t x, coord_t y, const pm_char * s, uint8_t idx, LcdFlags attr=0);
|
||||
void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags attr=0);
|
||||
void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, unsigned char len);
|
||||
void lcd_putsCenter(coord_t y, const pm_char * s, LcdFlags attr=0);
|
||||
|
||||
inline void lcdClear()
|
||||
{
|
||||
lcd->clear();
|
||||
}
|
||||
|
||||
inline void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags attr=0)
|
||||
{
|
||||
lcd->drawSizedText(x, y, s, len, attr);
|
||||
}
|
||||
|
||||
void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0);
|
||||
void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags=0, uint8_t len=0, const char * prefix=NULL, const char * suffix=NULL);
|
||||
|
||||
|
@ -220,21 +134,18 @@ void putsTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att=0);
|
|||
|
||||
#define PIXEL_PTR(x, y) &displayBuf[(y)*LCD_W + (x)]
|
||||
|
||||
inline void lcdDrawPixel(display_t * p, display_t value)
|
||||
{
|
||||
*p = value;
|
||||
}
|
||||
|
||||
inline void lcdDrawPixel(coord_t x, coord_t y, display_t value)
|
||||
{
|
||||
display_t * p = PIXEL_PTR(x, y);
|
||||
lcdDrawPixel(p, value);
|
||||
}
|
||||
|
||||
void lcdDrawAlphaPixel(display_t * p, uint8_t opacity, uint16_t color);
|
||||
void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att=0);
|
||||
void lcdDrawHorizontalLine(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att=0);
|
||||
void lcdDrawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags att=0);
|
||||
inline void lcdDrawHorizontalLine(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att=0)
|
||||
{
|
||||
lcd->drawHorizontalLine(x, y, w, pat, att);
|
||||
}
|
||||
|
||||
inline void lcdDrawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags att=0)
|
||||
{
|
||||
lcd->drawVerticalLine(x, y, h, pat, att);
|
||||
}
|
||||
|
||||
void lcdDrawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
|
||||
inline void lcdDrawAlphaPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t color)
|
||||
|
@ -246,7 +157,7 @@ inline void lcdDrawAlphaPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t co
|
|||
#if !defined(SIMU)
|
||||
inline void lcdDrawSolidFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags flags)
|
||||
{
|
||||
lcdDrawSolidFilledRectDMA(x, y, w, h, lcdColorTable[COLOR_IDX(flags)]);
|
||||
DMAFillRect(lcd->data, LCD_W, x, y, w, h, lcdColorTable[COLOR_IDX(flags)]);
|
||||
}
|
||||
#else
|
||||
void lcdDrawSolidFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags flags);
|
||||
|
@ -257,13 +168,6 @@ inline void lcdSetColor(uint16_t color)
|
|||
lcdColorTable[CUSTOM_COLOR_INDEX] = color;
|
||||
}
|
||||
|
||||
inline void lcdClear()
|
||||
{
|
||||
lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, 0);
|
||||
}
|
||||
|
||||
void lcdInvertRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags flags);
|
||||
|
||||
inline void lcdDrawSolidHorizontalLine(coord_t x, coord_t y, coord_t w, LcdFlags att)
|
||||
{
|
||||
lcdDrawSolidFilledRect(x, y, w, 1, att);
|
||||
|
@ -283,13 +187,21 @@ inline void lcdDrawSolidRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t
|
|||
lcdDrawSolidFilledRect(x, y+h-thickness, w, thickness, att);
|
||||
}
|
||||
|
||||
void lcdDrawFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att=0);
|
||||
inline void lcdDrawFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att=0)
|
||||
{
|
||||
lcd->drawFilledRect(x, y, w, h, pat, att);
|
||||
}
|
||||
|
||||
void lcdDrawBlackOverlay();
|
||||
void lcdDrawRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t thickness=1, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
void lcdDrawCircle(int x0, int y0, int radius);
|
||||
void lcdDrawPie(int x0, int y0, int radius, int angle1=0, int angle2=360);
|
||||
void lcdDrawBitmapPie(int x0, int y0, const uint16_t * img, int startAngle, int endAngle);
|
||||
void lcdDrawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * img, LcdFlags flags=0, int startAngle=0, int endAngle=360);
|
||||
|
||||
inline void lcdDrawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * bmp, LcdFlags flags=0, int startAngle=0, int endAngle=360)
|
||||
{
|
||||
lcd->drawBitmapPatternPie(x0, y0, bmp, flags, startAngle, endAngle);
|
||||
}
|
||||
|
||||
inline void lcdDrawSquare(coord_t x, coord_t y, coord_t w, LcdFlags att=0)
|
||||
{
|
||||
|
@ -306,27 +218,19 @@ inline int getBitmapHeight(const uint8_t * bmp)
|
|||
return *(((const uint16_t *)bmp)+1);
|
||||
}
|
||||
|
||||
inline int getBitmapScaledSize(int size, float scale)
|
||||
{
|
||||
if (scale == 0.0)
|
||||
return size;
|
||||
else
|
||||
return size * scale;
|
||||
}
|
||||
|
||||
float getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight);
|
||||
char getMappedChar(unsigned char c);
|
||||
int getFontHeight(LcdFlags flags);
|
||||
int getTextWidth(const pm_char *s, int len=0, LcdFlags flags=0);
|
||||
void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset=0, coord_t height=0, float scale=0);
|
||||
void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags=0, coord_t offset=0, coord_t width=0);
|
||||
void lcdDrawAlphaBitmap(coord_t x, coord_t y, const uint8_t * bmp);
|
||||
|
||||
inline void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags=0, coord_t offset=0, coord_t width=0)
|
||||
{
|
||||
lcd->drawBitmapPattern(x, y, img, flags, offset, width);
|
||||
}
|
||||
|
||||
#define lcdSetRefVolt(...)
|
||||
void lcdSetContrast();
|
||||
#define lcdOff(...)
|
||||
|
||||
uint8_t * bmpLoad(const char * filename);
|
||||
const char * imgLoad(uint8_t * dest, const char * filename, uint16_t width, uint16_t height);
|
||||
|
||||
#if defined(BOOT)
|
||||
#define BLINK_ON_PHASE (0)
|
||||
#else
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define XPOT_DELTA 10
|
||||
#define XPOT_DELAY 10 /* cycles */
|
||||
|
@ -55,6 +55,8 @@ void drawPots()
|
|||
OPTION_SLIDER_SQUARE_BUTTON);
|
||||
}
|
||||
|
||||
#include "alpha_horus.lbm"
|
||||
|
||||
bool menuCommonCalib(evt_t event)
|
||||
{
|
||||
drawScreenTemplate(NULL, LBM_CALIBRATION_ICON, OPTION_MENU_NO_FOOTER);
|
||||
|
@ -182,7 +184,7 @@ bool menuCommonCalib(evt_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
lcdDrawAlphaBitmap((LCD_W-206)/2, LCD_H-220, LBM_HORUS);
|
||||
lcd->drawAlphaBitmap((LCD_W-206)/2, LCD_H-220, &ALPHA_HORUS);
|
||||
drawSticks();
|
||||
drawPots();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define IS_FILE(fname) ((bool)(NODE_TYPE(fname)))
|
||||
|
||||
int currentBitmapIndex = 0;
|
||||
uint8_t * currentBitmap = NULL;
|
||||
BitmapBuffer * currentBitmap = NULL;
|
||||
|
||||
bool menuGeneralSdManagerInfo(evt_t event)
|
||||
{
|
||||
|
@ -365,12 +365,12 @@ bool menuGeneralSdManager(evt_t _event)
|
|||
if (ext && (!strcasecmp(ext, BITMAPS_EXT) || !strcasecmp(ext, PNG_EXT) || !strcasecmp(ext, JPG_EXT))) {
|
||||
if (currentBitmapIndex != menuVerticalPosition) {
|
||||
currentBitmapIndex = menuVerticalPosition;
|
||||
free(currentBitmap);
|
||||
currentBitmap = bmpLoad(reusableBuffer.sdmanager.lines[index]);
|
||||
delete currentBitmap;
|
||||
currentBitmap = BitmapBuffer::load(reusableBuffer.sdmanager.lines[index]);
|
||||
// TODO scale in case of a too large bitmap
|
||||
}
|
||||
if (currentBitmap) {
|
||||
// TODO scale in case of a too large bitmap
|
||||
lcdDrawBitmap(LCD_W / 2, LCD_H / 2, currentBitmap);
|
||||
lcd->drawBitmap(LCD_W / 2, LCD_H / 2, currentBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define RADIO_SETUP_2ND_COLUMN 220
|
||||
#define YEAR_SEPARATOR_OFFSET 42
|
||||
|
|
|
@ -33,7 +33,7 @@ bool menuGeneralTrainer(evt_t event)
|
|||
MENU(STR_MENUTRAINER, LBM_RADIO_ICONS, menuTabGeneral, e_Trainer, (slave ? 0 : 6), { 2, 2, 2, 2, 0/*, 0*/ });
|
||||
|
||||
if (slave) {
|
||||
lcd_putsCenter(5*FH, STR_SLAVE, TEXT_COLOR);
|
||||
// TODO lcd_putsCenter(5*FH, STR_SLAVE, TEXT_COLOR);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,9 +238,9 @@ bool menuModelCurveOne(evt_t event)
|
|||
if (crv.type==CURVE_TYPE_CUSTOM && i>0 && i<5+crv.points-1) x = points[5+crv.points+i-1];
|
||||
|
||||
if (i>=pointsOfs && i<pointsOfs+5) {
|
||||
lcdDrawNumber(posX, MENU_CONTENT_TOP + 5*FH-12, i+1, TEXT_DISABLE_COLOR);
|
||||
lcdDrawNumber(posX, MENU_CONTENT_TOP + 6*FH-10, x, (selectionMode==1 ? attr : 0));
|
||||
lcdDrawNumber(posX, MENU_CONTENT_TOP + 7*FH-6, points[i], (selectionMode==2 ? attr : 0));
|
||||
lcdDrawNumber(posX, MENU_CONTENT_TOP + 5*FH-12, i+1, TEXT_DISABLE_COLOR|RIGHT);
|
||||
lcdDrawNumber(posX, MENU_CONTENT_TOP + 6*FH-10, x, RIGHT|(selectionMode==1 ? attr : 0));
|
||||
lcdDrawNumber(posX, MENU_CONTENT_TOP + 7*FH-6, points[i], RIGHT|(selectionMode==2 ? attr : 0));
|
||||
posX += 45;
|
||||
}
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ bool menuCustomFunctions(evt_t event, CustomFunctionData * functions, CustomFunc
|
|||
lcdDrawText(MODEL_CUSTOM_FUNC_4TH_COLUMN-1, y, "!1x", attr);
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(MODEL_CUSTOM_FUNC_4TH_COLUMN+12, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr, 0, NULL, "s");
|
||||
lcdDrawNumber(MODEL_CUSTOM_FUNC_4TH_COLUMN+12, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr|RIGHT, 0, NULL, "s");
|
||||
}
|
||||
}
|
||||
else if (attr) {
|
||||
|
|
|
@ -121,7 +121,7 @@ bool menuModelFlightModesAll(evt_t event)
|
|||
}
|
||||
char s[32];
|
||||
sprintf(s, "Check FM%d Trims", mixerCurrentFlightMode);
|
||||
lcd_putsCenter(y, s, attr);
|
||||
// lcd_putsCenter(y, s, attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -161,12 +161,12 @@ bool menuModelFlightModesAll(evt_t event)
|
|||
|
||||
case ITEM_FLIGHT_MODES_FADE_IN:
|
||||
if (active) p->fadeIn = checkIncDec(event, p->fadeIn, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS);
|
||||
lcdDrawNumber(FLIGHT_MODES_FADEIN_COLUMN, y, (10/DELAY_STEP)*p->fadeIn, attr|PREC1);
|
||||
lcdDrawNumber(FLIGHT_MODES_FADEIN_COLUMN, y, (10/DELAY_STEP)*p->fadeIn, attr|PREC1|RIGHT);
|
||||
break;
|
||||
|
||||
case ITEM_FLIGHT_MODES_FADE_OUT:
|
||||
if (active) p->fadeOut = checkIncDec(event, p->fadeOut, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS);
|
||||
lcdDrawNumber(FLIGHT_MODES_FADEOUT_COLUMN, y, (10/DELAY_STEP)*p->fadeOut, attr|PREC1);
|
||||
lcdDrawNumber(FLIGHT_MODES_FADEOUT_COLUMN, y, (10/DELAY_STEP)*p->fadeOut, attr|PREC1|RIGHT);
|
||||
break;
|
||||
|
||||
}
|
||||
|
|
|
@ -76,9 +76,9 @@ bool menuModelGVars(evt_t event)
|
|||
}
|
||||
else {
|
||||
if (abs(v) >= 1000)
|
||||
lcdDrawNumber(x, y+1, v, TINSIZE|attr);
|
||||
lcdDrawNumber(x, y+1, v, TINSIZE|attr|RIGHT);
|
||||
else
|
||||
lcdDrawNumber(x, y, v, attr);
|
||||
lcdDrawNumber(x, y, v, attr|RIGHT);
|
||||
vmin = -GVAR_MAX; vmax = GVAR_MAX;
|
||||
}
|
||||
if (attr) {
|
||||
|
|
|
@ -295,7 +295,7 @@ bool menuModelExpoOne(evt_t event)
|
|||
#define _STR_MAX(x) PSTR("/" #x)
|
||||
#define STR_MAX(x) _STR_MAX(x)
|
||||
|
||||
#define EXPO_LINE_WEIGHT_POS 92
|
||||
#define EXPO_LINE_WEIGHT_POS 110
|
||||
#define EXPO_LINE_SRC_POS 115
|
||||
#define EXPO_LINE_CURVE_POS 162
|
||||
#define EXPO_LINE_SWITCH_POS 210
|
||||
|
@ -527,7 +527,7 @@ bool menuModelExposAll(evt_t event)
|
|||
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
|
||||
LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
|
||||
|
||||
GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0);
|
||||
GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, RIGHT | attr | (isExpoActive(i) ? BOLD : 0), 0, 0);
|
||||
displayExpoLine(y, ed);
|
||||
|
||||
if (s_copyMode) {
|
||||
|
|
|
@ -169,9 +169,9 @@ bool menuModelLimits(evt_t event)
|
|||
}
|
||||
|
||||
#if defined(PPM_UNIT_US)
|
||||
lcdDrawNumber(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1);
|
||||
lcdDrawNumber(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1|RIGHT);
|
||||
#else
|
||||
lcdDrawNumber(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1);
|
||||
lcdDrawNumber(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1|RIGHT);
|
||||
#endif
|
||||
if (active) {
|
||||
ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL, NULL, stops1000);
|
||||
|
@ -187,7 +187,7 @@ bool menuModelLimits(evt_t event)
|
|||
ld->min = GVAR_MENU_ITEM(LIMITS_MIN_POS, y, ld->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, attr|PREC1, 0, event);
|
||||
break;
|
||||
}
|
||||
lcdDrawNumber(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), attr|PREC1);
|
||||
lcdDrawNumber(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), attr|PREC1|RIGHT);
|
||||
if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL, NULL, stops1000);
|
||||
break;
|
||||
|
||||
|
@ -196,7 +196,7 @@ bool menuModelLimits(evt_t event)
|
|||
ld->max = GVAR_MENU_ITEM(LIMITS_MAX_POS, y, ld->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, attr|PREC1, 0, event);
|
||||
break;
|
||||
}
|
||||
lcdDrawNumber(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), attr|PREC1);
|
||||
lcdDrawNumber(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), attr|PREC1|RIGHT);
|
||||
if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL, NULL, stops1000);
|
||||
break;
|
||||
|
||||
|
@ -231,7 +231,7 @@ bool menuModelLimits(evt_t event)
|
|||
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
case ITEM_LIMITS_PPM_CENTER:
|
||||
lcdDrawNumber(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr);
|
||||
lcdDrawNumber(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr|RIGHT);
|
||||
if (active) {
|
||||
CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -PPM_CENTER_MAX, +PPM_CENTER_MAX);
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ bool menuModelMixOne(evt_t event)
|
|||
#define _STR_MAX(x) PSTR("/" #x)
|
||||
#define STR_MAX(x) _STR_MAX(x)
|
||||
|
||||
#define MIX_LINE_WEIGHT_POS 92
|
||||
#define MIX_LINE_WEIGHT_POS 110
|
||||
#define MIX_LINE_SRC_POS 115
|
||||
#define MIX_LINE_CURVE_POS 162
|
||||
#define MIX_LINE_SWITCH_POS 210
|
||||
|
@ -502,7 +502,7 @@ bool menuModelMixAll(evt_t event)
|
|||
|
||||
putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw);
|
||||
|
||||
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event);
|
||||
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, RIGHT | attr | (isMixActive(i) ? BOLD : 0), event);
|
||||
|
||||
displayMixLine(y, md);
|
||||
|
||||
|
|
|
@ -61,10 +61,11 @@ void drawModel(coord_t x, coord_t y, const char * name, bool selected)
|
|||
for (int i=0; i<4; i++) {
|
||||
lcdDrawBitmapPattern(x+104+i*11, y+25, LBM_SCORE0, TITLE_BGCOLOR);
|
||||
}
|
||||
uint8_t * bitmap = bmpLoad(header.bitmap);
|
||||
GET_FILENAME(filename, BITMAPS_PATH, header.bitmap, BITMAPS_EXT);
|
||||
const BitmapBuffer * bitmap = BitmapBuffer::load(filename);
|
||||
if (bitmap) {
|
||||
lcdDrawBitmap(x+5, y+24, bitmap, 0, 0, getBitmapScale(bitmap, 64, 32));
|
||||
free(bitmap);
|
||||
lcd->drawScaledBitmap(bitmap, x+5, y+24, 64, 32);
|
||||
delete bitmap;
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(x+5, y+23, LBM_LIBRARY_SLOT, TEXT_COLOR);
|
||||
|
|
|
@ -612,7 +612,7 @@ bool menuModelSetup(evt_t event)
|
|||
if (IS_MODULE_PPM(moduleIdx)) {
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PPMFRAME);
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppmFrameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT, 0, NULL, STR_MS);
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+90, y, (moduleData.ppmDelay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0, 0, NULL, "us");
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+90, y, (moduleData.ppmDelay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr|RIGHT : RIGHT, 0, NULL, "us");
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+120, y, moduleData.ppmPulsePol ? "+" : "-", (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0);
|
||||
|
||||
if (attr && s_editMode>0) {
|
||||
|
@ -641,7 +641,7 @@ bool menuModelSetup(evt_t event)
|
|||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RXNUM);
|
||||
}
|
||||
if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) {
|
||||
if (xOffsetBind) lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
|
||||
if (xOffsetBind) lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0 | LEFT, 2);
|
||||
if (attr && l_posHorz==0 && s_editMode>0) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], IS_MODULE_DSM2(moduleIdx) ? 20 : 63);
|
||||
}
|
||||
|
@ -770,13 +770,13 @@ bool menuModelFailsafe(evt_t event)
|
|||
}
|
||||
#if defined(PPM_UNIT_US)
|
||||
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags|RIGHT);
|
||||
#elif defined(PPM_UNIT_PERCENT_PREC1)
|
||||
uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags|RIGHT);
|
||||
#else
|
||||
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags|RIGHT);
|
||||
#endif
|
||||
|
||||
// Gauge
|
||||
|
|
|
@ -269,7 +269,12 @@ bool check_submenu_simple(check_event_t event, uint8_t maxrow);
|
|||
MENU_TAB(__VA_ARGS__); \
|
||||
if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", title); \
|
||||
if (!check(event, menu, tab, tabCount, mstate_tab, DIM(mstate_tab)-1, lines_count)) return false; \
|
||||
drawMenuTemplate(title, icons); \
|
||||
drawMenuTemplate(title, icons);
|
||||
|
||||
#define CUSTOM_MENU_WITH_OPTIONS(title, icons, tab, tabCount, menu, lines_count) \
|
||||
if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", title); \
|
||||
if (!check(event, menu, tab, tabCount, mstate_tab, DIM(mstate_tab)-1, lines_count)) return false; \
|
||||
drawMenuTemplate(title, icons);
|
||||
|
||||
#define MENU(title, icons, tab, menu, lines_count, ...) \
|
||||
MENU_WITH_OPTIONS(title, icons, tab, DIM(tab), menu, lines_count, __VA_ARGS__)
|
||||
|
|
|
@ -39,15 +39,17 @@ void (*popupMenuHandler)(const char * result);
|
|||
|
||||
void displayWarningBox()
|
||||
{
|
||||
lcdDrawSolidFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
lcdDrawSolidRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, 2, ALARM_COLOR);
|
||||
// theme->drawMessageBox("", "", "", MESSAGEBOX_TYPE_WARNING);
|
||||
// lcdDrawSolidFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
// lcdDrawSolidRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, 2, ALARM_COLOR);
|
||||
// lcdDrawBitmap(POPUP_X+15, POPUP_Y+20, LBM_WARNING);
|
||||
}
|
||||
|
||||
void displayMessageBox()
|
||||
{
|
||||
lcdDrawSolidFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
lcdDrawSolidRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, 2, WARNING_COLOR);
|
||||
// theme->drawMessageBox("", "", "", MESSAGEBOX_TYPE_INFO);
|
||||
// lcdDrawSolidFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
// lcdDrawSolidRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, 2, WARNING_COLOR);
|
||||
// lcdDrawBitmap(POPUP_X+15, POPUP_Y+20, LBM_MESSAGE);
|
||||
}
|
||||
|
||||
|
@ -75,11 +77,12 @@ void displayPopup(const char * title)
|
|||
void displayWarning(evt_t event)
|
||||
{
|
||||
warningResult = false;
|
||||
|
||||
if (warningType == WARNING_TYPE_INPUT)
|
||||
displayMessageBox();
|
||||
theme->drawMessageBox(warningText, "", "", MESSAGEBOX_TYPE_INFO);
|
||||
else
|
||||
displayWarningBox();
|
||||
lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y, warningText, WARNING_LINE_LEN, DBLSIZE | (warningType == WARNING_TYPE_INPUT ? WARNING_COLOR : ALARM_COLOR));
|
||||
theme->drawMessageBox(warningText, "", "", MESSAGEBOX_TYPE_WARNING);
|
||||
|
||||
if (warningInfoText) {
|
||||
lcdDrawSizedText(WARNING_LINE_X, WARNING_INFOLINE_Y, warningInfoText, warningInfoLength, WARNING_INFO_FLAGS);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,16 @@ void onZoneOptionFileSelectionMenu(const char * result)
|
|||
}
|
||||
}
|
||||
|
||||
int getZoneOptionColumns(const ZoneOption * option)
|
||||
{
|
||||
if (option->type == ZoneOption::Color) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue * value, LcdFlags attr, uint32_t i_flags, evt_t event)
|
||||
{
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, option->name);
|
||||
|
@ -115,11 +125,29 @@ void editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue * valu
|
|||
}
|
||||
}
|
||||
else if (option->type == ZoneOption::Color) {
|
||||
COLOR_SPLIT(value->unsignedValue, r, g, b);
|
||||
|
||||
lcdSetColor(value->unsignedValue);
|
||||
lcdDrawSolidRect(SCREENS_SETUP_2ND_COLUMN, y, 40, 15, 1, attr ? TEXT_INVERTED_BGCOLOR : TEXT_COLOR);
|
||||
lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN + 1, y + 1, 38, 13, CUSTOM_COLOR);
|
||||
if (attr) {
|
||||
value->unsignedValue = checkIncDec(event, value->unsignedValue, i_flags, 65535, 0);
|
||||
lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN-1, y-1, 42, 17, TEXT_COLOR);
|
||||
lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN, y, 40, 15, CUSTOM_COLOR);
|
||||
|
||||
lcdDrawText(SCREENS_SETUP_2ND_COLUMN + 50, y, "R:", TEXT_COLOR);
|
||||
lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN + 70, y, r << 3, LEFT|TEXT_COLOR|((attr && menuHorizontalPosition == 0) ? attr : 0));
|
||||
if (attr && menuHorizontalPosition == 0) {
|
||||
r = checkIncDec(event, r, 0, (1<<5)-1, i_flags);
|
||||
}
|
||||
lcdDrawText(SCREENS_SETUP_2ND_COLUMN + 110, y, "G:", TEXT_COLOR);
|
||||
lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN + 130, y, g << 2, LEFT|TEXT_COLOR|((attr && menuHorizontalPosition == 1) ? attr : 0));
|
||||
if (attr && menuHorizontalPosition == 1) {
|
||||
g = checkIncDec(event, g, 0, (1<<6)-1, i_flags);
|
||||
}
|
||||
lcdDrawText(SCREENS_SETUP_2ND_COLUMN + 170, y, "B:", TEXT_COLOR);
|
||||
lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN + 190, y, b << 3, LEFT|TEXT_COLOR|((attr && menuHorizontalPosition == 2) ? attr : 0));
|
||||
if (attr && menuHorizontalPosition == 2) {
|
||||
b = checkIncDec(event, b, 0, (1<<5)-1, i_flags);
|
||||
}
|
||||
if (attr && checkIncDec_Ret) {
|
||||
value->unsignedValue = COLOR_JOIN(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,11 +183,6 @@ bool menuWidgetSettings(evt_t event)
|
|||
return menuSettings<Widget>("Widget settings", currentWidget, EE_MODEL, event);
|
||||
}
|
||||
|
||||
bool menuThemeSettings(evt_t event)
|
||||
{
|
||||
return menuSettings<Theme>("Theme settings", theme, EE_GENERAL, event);
|
||||
}
|
||||
|
||||
bool menuWidgetChoice(evt_t event)
|
||||
{
|
||||
static Widget * previousWidget;
|
||||
|
@ -328,7 +351,7 @@ T * editThemeChoice(coord_t x, coord_t y, T * array[], uint8_t count, T * curren
|
|||
}
|
||||
if (attr) {
|
||||
if (menuHorizontalPosition < 0) {
|
||||
lcdDrawSolidFilledRect(x-3, y-2, min<uint8_t>(4, count)*56+1, 2*FH-5, TEXT_INVERTED_BGCOLOR);
|
||||
lcdDrawSolidFilledRect(x-3, y-1, min<uint8_t>(4, count)*56+1, 2*FH-5, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
else {
|
||||
if (needsOffsetCheck) {
|
||||
|
@ -345,15 +368,15 @@ T * editThemeChoice(coord_t x, coord_t y, T * array[], uint8_t count, T * curren
|
|||
unsigned int last = min<int>(menuHorizontalOffset + 4, count);
|
||||
for (unsigned int i=menuHorizontalOffset, pos=x; i<last; i++, pos += 56) {
|
||||
T * element = array[i];
|
||||
element->drawThumb(pos, y, current == element ? ((attr && menuHorizontalPosition < 0) ? TEXT_INVERTED_COLOR : TEXT_INVERTED_BGCOLOR) : LINE_COLOR);
|
||||
element->drawThumb(pos, y+1, current == element ? ((attr && menuHorizontalPosition < 0) ? TEXT_INVERTED_COLOR : TEXT_INVERTED_BGCOLOR) : LINE_COLOR);
|
||||
}
|
||||
if (count > 4) {
|
||||
lcdDrawBitmapPattern(x - 12, y, LBM_CARROUSSEL_LEFT, menuHorizontalOffset > 0 ? LINE_COLOR : CURVE_AXIS_COLOR);
|
||||
lcdDrawBitmapPattern(x + 4 * 56, y, LBM_CARROUSSEL_RIGHT, last < countRegisteredLayouts ? LINE_COLOR : CURVE_AXIS_COLOR);
|
||||
lcdDrawBitmapPattern(x - 12, y+1, LBM_CARROUSSEL_LEFT, menuHorizontalOffset > 0 ? LINE_COLOR : CURVE_AXIS_COLOR);
|
||||
lcdDrawBitmapPattern(x + 4 * 56, y+1, LBM_CARROUSSEL_RIGHT, last < countRegisteredLayouts ? LINE_COLOR : CURVE_AXIS_COLOR);
|
||||
}
|
||||
if (attr && menuHorizontalPosition >= 0) {
|
||||
lcdDrawSolidRect(x + (menuHorizontalPosition - menuHorizontalOffset) * 56 - 3, y - 2, 57, 35, 1, TEXT_INVERTED_BGCOLOR);
|
||||
if (menuHorizontalPosition != currentIndex && event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
lcdDrawSolidRect(x + (menuHorizontalPosition - menuHorizontalOffset) * 56 - 3, y - 1, 57, 35, 1, TEXT_INVERTED_BGCOLOR);
|
||||
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
return array[menuHorizontalPosition];
|
||||
}
|
||||
|
@ -361,19 +384,39 @@ T * editThemeChoice(coord_t x, coord_t y, T * array[], uint8_t count, T * curren
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int getOptionsCount(const ZoneOption * options)
|
||||
{
|
||||
if (options == NULL) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
int count = 0;
|
||||
for (const ZoneOption * option = options; option->name; option++) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
enum menuScreensThemeItems {
|
||||
ITEM_SCREEN_SETUP_THEME,
|
||||
ITEM_SCREEN_SETUP_THEME_SETTINGS = ITEM_SCREEN_SETUP_THEME+2,
|
||||
ITEM_SCREEN_SETUP_TOPBAR,
|
||||
ITEM_SCREEN_SETUP_MAX
|
||||
ITEM_SCREEN_SETUP_THEME_OPTION1 = ITEM_SCREEN_SETUP_THEME+2
|
||||
};
|
||||
|
||||
bool menuScreensTheme(evt_t event)
|
||||
{
|
||||
bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0);
|
||||
const ZoneOption * options = theme->getOptions();
|
||||
int optionsCount = getOptionsCount(options);
|
||||
linesCount = ITEM_SCREEN_SETUP_THEME_OPTION1 + optionsCount + 1;
|
||||
|
||||
menuPageCount = updateMainviewsMenu();
|
||||
MENU_WITH_OPTIONS("User interface", LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, 0, ITEM_SCREEN_SETUP_MAX, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredThemes-1)), ORPHAN_ROW, 0, 0, 0, 0 });
|
||||
uint8_t mstate_tab[2 + MAX_THEME_OPTIONS + 1] = { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredThemes-1)), ORPHAN_ROW };
|
||||
for (int i=0; i<optionsCount; i++) {
|
||||
mstate_tab[2+i] = getZoneOptionColumns(&options[i]);
|
||||
}
|
||||
mstate_tab[2+optionsCount] = 0; // The button for the Topbar setup
|
||||
CUSTOM_MENU_WITH_OPTIONS("User interface", LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, 0, linesCount);
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i * FH;
|
||||
|
@ -383,7 +426,7 @@ bool menuScreensTheme(evt_t event)
|
|||
switch (k) {
|
||||
case ITEM_SCREEN_SETUP_THEME: {
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y + FH / 2, "Theme");
|
||||
const Theme * new_theme = editThemeChoice<const Theme>(SCREENS_SETUP_2ND_COLUMN, y, registeredThemes, countRegisteredThemes, theme, needsOffsetCheck, attr, event);
|
||||
Theme * new_theme = editThemeChoice<Theme>(SCREENS_SETUP_2ND_COLUMN, y, registeredThemes, countRegisteredThemes, theme, needsOffsetCheck, attr, event);
|
||||
if (new_theme) {
|
||||
new_theme->init();
|
||||
loadTheme(new_theme);
|
||||
|
@ -393,31 +436,35 @@ bool menuScreensTheme(evt_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
case ITEM_SCREEN_SETUP_THEME_SETTINGS:
|
||||
drawButton(SCREENS_SETUP_2ND_COLUMN, y, "Theme settings", attr);
|
||||
if (attr && event == EVT_KEY_BREAK(KEY_ENTER) && theme->getOptions()) {
|
||||
s_editMode = 0;
|
||||
pushMenu(menuThemeSettings);
|
||||
}
|
||||
case ITEM_SCREEN_SETUP_THEME+1:
|
||||
break;
|
||||
|
||||
case ITEM_SCREEN_SETUP_TOPBAR:
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Top bar");
|
||||
drawButton(SCREENS_SETUP_2ND_COLUMN, y, "Setup", attr);
|
||||
if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
currentScreen = customScreens[0];
|
||||
currentContainer = topbar;
|
||||
pushMenu(menuWidgetsSetup);
|
||||
default:
|
||||
{
|
||||
uint8_t index = k - ITEM_SCREEN_SETUP_THEME_OPTION1;
|
||||
if (index < optionsCount) {
|
||||
const ZoneOption * option = &options[index];
|
||||
ZoneOptionValue * value = theme->getOptionValue(index);
|
||||
editZoneOption(y, option, value, attr, EE_GENERAL, event);
|
||||
}
|
||||
else if (index == optionsCount) {
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Top bar");
|
||||
drawButton(SCREENS_SETUP_2ND_COLUMN, y, "Setup", attr);
|
||||
if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
currentScreen = customScreens[0];
|
||||
currentContainer = topbar;
|
||||
pushMenu(menuWidgetsSetup);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum menuScreenSetup {
|
||||
enum MenuScreenSetupItems {
|
||||
ITEM_SCREEN_SETUP_LAYOUT,
|
||||
ITEM_SCREEN_SETUP_WIDGETS_SETUP = ITEM_SCREEN_SETUP_LAYOUT+2,
|
||||
ITEM_SCREEN_SETUP_LAYOUT_OPTION1,
|
||||
|
@ -433,16 +480,20 @@ bool menuScreenSetup(int index, evt_t event)
|
|||
currentContainer = currentScreen;
|
||||
bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0);
|
||||
|
||||
linesCount = ITEM_SCREEN_SETUP_LAYOUT_OPTION1;
|
||||
const ZoneOption * options = currentScreen->getFactory()->getOptions();
|
||||
for (const ZoneOption * option = options; option->name; option++) {
|
||||
linesCount++;
|
||||
}
|
||||
int optionsCount = getOptionsCount(options);
|
||||
linesCount = ITEM_SCREEN_SETUP_LAYOUT_OPTION1 + optionsCount;
|
||||
|
||||
char title[] = "Main view X";
|
||||
title[sizeof(title)-2] = '1' + index;
|
||||
menuPageCount = updateMainviewsMenu();
|
||||
MENU_WITH_OPTIONS(title, LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, index+1, linesCount, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredLayouts-1)), ORPHAN_ROW, 0, 0, 0, 0 });
|
||||
|
||||
uint8_t mstate_tab[2 + MAX_LAYOUT_OPTIONS] = { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredLayouts-1)), ORPHAN_ROW };
|
||||
for (int i=0; i<optionsCount; i++) {
|
||||
mstate_tab[2+i] = getZoneOptionColumns(&options[i]);
|
||||
}
|
||||
|
||||
CUSTOM_MENU_WITH_OPTIONS(title, LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, index+1, linesCount);
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i * FH;
|
||||
|
@ -474,13 +525,15 @@ bool menuScreenSetup(int index, evt_t event)
|
|||
break;
|
||||
|
||||
default:
|
||||
if (k < linesCount) {
|
||||
uint8_t index = k - ITEM_SCREEN_SETUP_LAYOUT_OPTION1;
|
||||
{
|
||||
uint8_t index = k - ITEM_SCREEN_SETUP_LAYOUT_OPTION1;
|
||||
if (index < optionsCount) {
|
||||
const ZoneOption * option = &options[index];
|
||||
ZoneOptionValue * value = currentScreen->getOptionValue(index);
|
||||
editZoneOption(y, option, value, attr, EE_MODEL, event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,18 +18,14 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
|
||||
const uint8_t LBM_SPLASH[] __ALIGNED = {
|
||||
#include "opentx.h"
|
||||
#include "bmp_splash.lbm"
|
||||
};
|
||||
|
||||
#if defined(SPLASH)
|
||||
void drawSplash()
|
||||
{
|
||||
lcdClear();
|
||||
|
||||
lcdDrawBitmap((LCD_W-256)/2, (LCD_H-256)/2, LBM_SPLASH);
|
||||
lcd->clear();
|
||||
lcd->drawBitmap((LCD_W-BMP_SPLASH.getWidth())/2, (LCD_H-BMP_SPLASH.getHeight())/2, &BMP_SPLASH);
|
||||
|
||||
#if MENUS_LOCK == 1
|
||||
if (readonly == false) {
|
||||
|
|
|
@ -37,9 +37,29 @@ ZoneOptionValue * Theme::getOptionValue(unsigned int index) const
|
|||
return &g_eeGeneral.themeData.options[index];
|
||||
}
|
||||
|
||||
void Theme::drawThumb(uint16_t x, uint16_t y, uint32_t flags) const
|
||||
const char * Theme::getFilePath(const char * filename) const
|
||||
{
|
||||
lcdDrawBitmap(x, y, bitmap);
|
||||
static char path[_MAX_LFN+1] = THEMES_PATH "/";
|
||||
strcpy(path + sizeof(THEMES_PATH), getName());
|
||||
int len = sizeof(THEMES_PATH) + strlen(path + sizeof(THEMES_PATH));
|
||||
path[len] = '/';
|
||||
strcpy(path+len+1, filename);
|
||||
return path;
|
||||
}
|
||||
|
||||
void Theme::drawThumb(uint16_t x, uint16_t y, uint32_t flags)
|
||||
{
|
||||
#define THUMB_WIDTH 51
|
||||
#define THUMB_HEIGHT 31
|
||||
if (!thumb) {
|
||||
thumb = BitmapBuffer::load(getFilePath("thumb.bmp"));
|
||||
}
|
||||
if (thumb) {
|
||||
lcd->drawBitmap(x, y, thumb);
|
||||
}
|
||||
if (flags == LINE_COLOR) {
|
||||
lcdDrawFilledRect(x, y, THUMB_WIDTH, THUMB_HEIGHT, SOLID, OVERLAY_COLOR | OPACITY(10));
|
||||
}
|
||||
}
|
||||
|
||||
void Theme::drawBackground() const
|
||||
|
@ -47,6 +67,13 @@ void Theme::drawBackground() const
|
|||
lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR);
|
||||
}
|
||||
|
||||
void Theme::drawAboutBackground() const
|
||||
{
|
||||
drawBackground();
|
||||
}
|
||||
|
||||
#include "alpha_asterisk.lbm"
|
||||
|
||||
void Theme::drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const
|
||||
{
|
||||
//if (flags & MESSAGEBOX_TYPE_ALERT) {
|
||||
|
@ -55,7 +82,10 @@ void Theme::drawMessageBox(const char * title, const char * text, const char * a
|
|||
//}
|
||||
|
||||
if ((flags & MESSAGEBOX_TYPE_ALERT) || (flags & MESSAGEBOX_TYPE_WARNING)) {
|
||||
lcdDrawAlphaBitmap(POPUP_X-80, POPUP_Y+12, LBM_ASTERISK);
|
||||
lcd->drawAlphaBitmap(POPUP_X-80, POPUP_Y+12, &ALPHA_ASTERISK);
|
||||
}
|
||||
else {
|
||||
lcd->drawAlphaBitmap(POPUP_X-80, POPUP_Y+12, &ALPHA_ASTERISK);
|
||||
}
|
||||
|
||||
#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ)
|
||||
|
@ -79,9 +109,9 @@ void Theme::drawMessageBox(const char * title, const char * text, const char * a
|
|||
}
|
||||
}
|
||||
|
||||
const Theme * registeredThemes[MAX_REGISTERED_THEMES]; // TODO dynamic
|
||||
Theme * registeredThemes[MAX_REGISTERED_THEMES]; // TODO dynamic
|
||||
unsigned int countRegisteredThemes = 0;
|
||||
void registerTheme(const Theme * theme)
|
||||
void registerTheme(Theme * theme)
|
||||
{
|
||||
if (countRegisteredThemes < MAX_REGISTERED_THEMES) {
|
||||
TRACE("register theme %s", theme->getName());
|
||||
|
@ -89,10 +119,10 @@ void registerTheme(const Theme * theme)
|
|||
}
|
||||
}
|
||||
|
||||
const Theme * getTheme(const char * name)
|
||||
Theme * getTheme(const char * name)
|
||||
{
|
||||
for (unsigned int i=0; i<countRegisteredThemes; i++) {
|
||||
const Theme * theme = registeredThemes[i];
|
||||
Theme * theme = registeredThemes[i];
|
||||
if (!strcmp(name, theme->getName())) {
|
||||
return theme;
|
||||
}
|
||||
|
@ -100,7 +130,7 @@ const Theme * getTheme(const char * name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void loadTheme(const Theme * new_theme)
|
||||
void loadTheme(Theme * new_theme)
|
||||
{
|
||||
TRACE("load theme %s", new_theme->getName());
|
||||
theme = new_theme;
|
||||
|
@ -112,7 +142,7 @@ void loadTheme()
|
|||
char name[sizeof(g_eeGeneral.themeName)+1];
|
||||
memset(name, 0, sizeof(name));
|
||||
strncpy(name, g_eeGeneral.themeName, sizeof(g_eeGeneral.themeName));
|
||||
const Theme * new_theme = getTheme(name);
|
||||
Theme * new_theme = getTheme(name);
|
||||
if (new_theme) {
|
||||
loadTheme(new_theme);
|
||||
}
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
#ifndef _THEME_H_
|
||||
#define _THEME_H_
|
||||
|
||||
#include "bitmapbuffer.h"
|
||||
|
||||
#define MAX_THEME_OPTIONS 5
|
||||
|
||||
class Theme;
|
||||
void registerTheme(const Theme * theme);
|
||||
void registerTheme(Theme * theme);
|
||||
|
||||
#define MESSAGEBOX_TYPE_INFO 0
|
||||
#define MESSAGEBOX_TYPE_QUESTION 1
|
||||
|
@ -38,10 +40,10 @@ class Theme
|
|||
ZoneOptionValue options[MAX_THEME_OPTIONS];
|
||||
};
|
||||
|
||||
Theme(const char * name, const uint8_t * bitmap, const ZoneOption * options=NULL):
|
||||
Theme(const char * name, const ZoneOption * options=NULL):
|
||||
name(name),
|
||||
bitmap(bitmap),
|
||||
options(options)
|
||||
options(options),
|
||||
thumb(NULL)
|
||||
{
|
||||
registerTheme(this);
|
||||
}
|
||||
|
@ -51,6 +53,10 @@ class Theme
|
|||
return name;
|
||||
}
|
||||
|
||||
const char * getFilePath(const char * filename) const;
|
||||
|
||||
void drawThumb(uint16_t x, uint16_t y, uint32_t flags);
|
||||
|
||||
inline const ZoneOption * getOptions() const
|
||||
{
|
||||
return options;
|
||||
|
@ -60,31 +66,36 @@ class Theme
|
|||
|
||||
ZoneOptionValue * getOptionValue(unsigned int index) const;
|
||||
|
||||
virtual void drawThumb(uint16_t x, uint16_t y, uint32_t flags) const;
|
||||
|
||||
virtual void load() const = 0;
|
||||
|
||||
virtual void drawBackground() const;
|
||||
|
||||
virtual void drawAboutBackground() const;
|
||||
|
||||
virtual void drawTopbarBackground(const uint8_t * icon) const = 0;
|
||||
|
||||
virtual void drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const;
|
||||
|
||||
protected:
|
||||
const char * name;
|
||||
const uint8_t * bitmap;
|
||||
const ZoneOption * options;
|
||||
BitmapBuffer * thumb;
|
||||
};
|
||||
|
||||
extern const Theme * theme;
|
||||
extern Theme * theme;
|
||||
|
||||
inline const char * getThemePath(const char * filename)
|
||||
{
|
||||
return theme->getFilePath(filename);
|
||||
}
|
||||
|
||||
#define MAX_REGISTERED_THEMES 10
|
||||
extern unsigned int countRegisteredThemes;
|
||||
void registerTheme(const Theme * theme);
|
||||
extern const Theme * registeredThemes[MAX_REGISTERED_THEMES]; // TODO dynamic
|
||||
void registerTheme(Theme * theme);
|
||||
extern Theme * registeredThemes[MAX_REGISTERED_THEMES]; // TODO dynamic
|
||||
|
||||
const Theme * getTheme(const char * name);
|
||||
void loadTheme(const Theme * theme);
|
||||
Theme * getTheme(const char * name);
|
||||
void loadTheme(Theme * theme);
|
||||
void loadTheme();
|
||||
|
||||
#endif // _THEME_H_
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.3 KiB |
|
@ -20,19 +20,11 @@
|
|||
|
||||
#include "opentx.h"
|
||||
|
||||
const uint8_t LBM_TOPMENU_BMP_OPENTX[] __ALIGNED = {
|
||||
#include "bmp_topmenu_opentx.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_THEME_DARKBLUE[] __ALIGNED = {
|
||||
#include "bmp_darkblue.lbm"
|
||||
};
|
||||
|
||||
class DarkblueTheme: public Theme
|
||||
{
|
||||
public:
|
||||
DarkblueTheme():
|
||||
Theme("Darkblue", LBM_THEME_DARKBLUE)
|
||||
Theme("Darkblue")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -74,11 +66,12 @@ class DarkblueTheme: public Theme
|
|||
lcdDrawBitmapPattern(5, 7, icon, MENU_TITLE_COLOR);
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmap(5, 7, LBM_TOPMENU_BMP_OPENTX);
|
||||
static BitmapBuffer * thumb = BitmapBuffer::load(getFilePath("topmenu_opentx.bmp"));
|
||||
lcd->drawBitmap(5, 7, thumb);
|
||||
}
|
||||
|
||||
drawTopbarDatetime();
|
||||
}
|
||||
};
|
||||
|
||||
DarkblueTheme darkblueTheme;
|
||||
const DarkblueTheme darkblueTheme;
|
||||
|
|
|
@ -24,17 +24,7 @@ const uint8_t LBM_TOPMENU_MASK_OPENTX[] = {
|
|||
#include "mask_topmenu_opentx.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_MAINVIEW_BACKGROUND[] __ALIGNED = {
|
||||
#include "bmp_background.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_THEME_DEFAULT[] __ALIGNED = {
|
||||
#include "bmp_default.lbm"
|
||||
};
|
||||
|
||||
const ZoneOption OPTIONS_THEME_DEFAULT[] = {
|
||||
{ "Default background", ZoneOption::Bool, { .boolValue = 1 } },
|
||||
{ "Background file", ZoneOption::File, { .stringValue = "\0\0\0\0\0\0\0" } },
|
||||
{ "Background color", ZoneOption::Color, { .unsignedValue = WHITE } },
|
||||
{ NULL, ZoneOption::Bool }
|
||||
};
|
||||
|
@ -43,7 +33,7 @@ class DefaultTheme: public Theme
|
|||
{
|
||||
public:
|
||||
DefaultTheme():
|
||||
Theme("Default", LBM_THEME_DEFAULT, OPTIONS_THEME_DEFAULT)
|
||||
Theme("Default", OPTIONS_THEME_DEFAULT)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -78,15 +68,24 @@ class DefaultTheme: public Theme
|
|||
|
||||
virtual void drawBackground() const
|
||||
{
|
||||
if (g_eeGeneral.themeData.options[0].boolValue) {
|
||||
lcdDrawBitmap(0, 0, LBM_MAINVIEW_BACKGROUND);
|
||||
static BitmapBuffer * backgroundBitmap = BitmapBuffer::load(getThemePath("mainbg.bmp"));
|
||||
if (backgroundBitmap) {
|
||||
lcd->drawBitmap(0, 0, backgroundBitmap);
|
||||
}
|
||||
else {
|
||||
lcdSetColor(g_eeGeneral.themeData.options[2].unsignedValue);
|
||||
lcdSetColor(g_eeGeneral.themeData.options[0].unsignedValue);
|
||||
lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, CUSTOM_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void drawAboutBackground() const
|
||||
{
|
||||
static BitmapBuffer * backgroundBitmap = BitmapBuffer::load(getThemePath("aboutbg.bmp"));
|
||||
if (backgroundBitmap) {
|
||||
lcd->drawBitmap(0, 0, backgroundBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void drawTopbarBackground(const uint8_t * icon) const
|
||||
{
|
||||
lcdDrawSolidFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
|
||||
|
@ -103,5 +102,5 @@ class DefaultTheme: public Theme
|
|||
}
|
||||
};
|
||||
|
||||
const DefaultTheme defaultTheme;
|
||||
const Theme * theme = &defaultTheme;
|
||||
DefaultTheme defaultTheme;
|
||||
Theme * theme = &defaultTheme;
|
||||
|
|
|
@ -62,7 +62,8 @@ bool menuAboutView(evt_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
drawScreenTemplate("About", NULL);
|
||||
theme->drawAboutBackground();
|
||||
theme->drawTopbarBackground(NULL);
|
||||
|
||||
uint8_t screenDuration = 150;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define TRIM_LH_X 10
|
||||
#define TRIM_LV_X 24
|
||||
|
@ -80,14 +80,6 @@ void drawTrims(uint8_t flightMode)
|
|||
}
|
||||
}
|
||||
|
||||
bool isViewAvailable(int index)
|
||||
{
|
||||
if (index <= VIEW_CHANNELS)
|
||||
return true;
|
||||
else
|
||||
return TELEMETRY_SCREEN_TYPE(index-VIEW_TELEM1) != TELEMETRY_SCREEN_TYPE_NONE;
|
||||
}
|
||||
|
||||
void onMainViewMenu(const char *result)
|
||||
{
|
||||
if (result == STR_MODEL_SELECT) {
|
||||
|
@ -129,6 +121,16 @@ void onMainViewMenu(const char *result)
|
|||
}
|
||||
}
|
||||
|
||||
int getMainViewsCount()
|
||||
{
|
||||
for (int index=1; index<MAX_CUSTOM_SCREENS; index++) {
|
||||
if (!customScreens[index]) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return MAX_CUSTOM_SCREENS;
|
||||
}
|
||||
|
||||
bool menuMainView(evt_t event)
|
||||
{
|
||||
switch (event) {
|
||||
|
@ -166,13 +168,13 @@ bool menuMainView(evt_t event)
|
|||
|
||||
case EVT_KEY_BREAK(KEY_DOWN):
|
||||
storageDirty(EE_GENERAL);
|
||||
g_eeGeneral.view = circularIncDec(g_eeGeneral.view, +1, 0, VIEW_COUNT-1, isViewAvailable);
|
||||
g_eeGeneral.view = circularIncDec(g_eeGeneral.view, +1, 0, getMainViewsCount()-1);
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_UP):
|
||||
killEvents(event);
|
||||
storageDirty(EE_GENERAL);
|
||||
g_eeGeneral.view = circularIncDec(g_eeGeneral.view, -1, 0, VIEW_COUNT-1, isViewAvailable);
|
||||
g_eeGeneral.view = circularIncDec(g_eeGeneral.view, -1, 0, getMainViewsCount()-1);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
|
@ -185,8 +187,8 @@ bool menuMainView(evt_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (customScreens[0]) {
|
||||
customScreens[0]->refresh();
|
||||
if (customScreens[g_eeGeneral.view]) {
|
||||
customScreens[g_eeGeneral.view]->refresh();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -140,7 +140,7 @@ bool menuStatisticsDebug(evt_t event)
|
|||
lcdDrawText(MENU_DEBUG_COL1_OFS+120, MENU_DEBUG_Y_RTOS+1, "[Audio]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(MENU_DEBUG_COL1_OFS+150, MENU_DEBUG_Y_RTOS, audioStack.available(), LEFT);
|
||||
|
||||
lcd_putsCenter(7*FH+1, STR_MENUTORESET);
|
||||
// TODO lcd_putsCenter(7*FH+1, STR_MENUTORESET);
|
||||
// lcdInvertLastLine();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define _WIDGET_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_WIDGET_OPTIONS 5
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ const char * const STR_MONTHS[] = { "Jan", "Fev", "Mar", "Apr", "May", "Jun", "J
|
|||
#define DATETIME_SEPARATOR_X 425
|
||||
#define DATETIME_LINE1 9
|
||||
#define DATETIME_LINE2 23
|
||||
#define DATETIME_LEFT(s) (LCD_W+DATETIME_SEPARATOR_X+8-getTextWidth(s, SMLSIZE))/2
|
||||
#define DATETIME_MIDDLE (LCD_W+DATETIME_SEPARATOR_X+8)/2
|
||||
|
||||
void drawTopbarDatetime()
|
||||
{
|
||||
|
@ -41,19 +41,24 @@ void drawTopbarDatetime()
|
|||
gettime(&t);
|
||||
char str[10];
|
||||
sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]);
|
||||
lcdDrawText(DATETIME_LEFT(str), DATETIME_LINE1, str, SMLSIZE|TEXT_INVERTED_COLOR);
|
||||
lcdDrawText(DATETIME_MIDDLE, DATETIME_LINE1, str, SMLSIZE|TEXT_INVERTED_COLOR|CENTERED);
|
||||
|
||||
getTimerString(str, getValue(MIXSRC_TX_TIME));
|
||||
lcdDrawText(DATETIME_LEFT(str), DATETIME_LINE2, str, SMLSIZE|TEXT_INVERTED_COLOR);
|
||||
lcdDrawText(DATETIME_MIDDLE, DATETIME_LINE2, str, SMLSIZE|TEXT_INVERTED_COLOR|CENTERED);
|
||||
}
|
||||
|
||||
#include "alpha_stick_background.lbm"
|
||||
#include "alpha_stick_pointer.lbm"
|
||||
#define STICK_PANEL_WIDTH 68
|
||||
void drawStick(coord_t x, coord_t y, int16_t xval, int16_t yval)
|
||||
{
|
||||
lcdDrawAlphaBitmap(x, y, LBM_STICK_BACKGROUND);
|
||||
lcdDrawAlphaBitmap(x + 2 + STICK_PANEL_WIDTH/2 + STICK_PANEL_WIDTH/2 * xval/RESX, y + 2 + STICK_PANEL_WIDTH/2 - STICK_PANEL_WIDTH/2 * yval/RESX, LBM_STICK_POINTER);
|
||||
lcd->drawAlphaBitmap(x, y, &ALPHA_STICK_BACKGROUND);
|
||||
lcd->drawAlphaBitmap(x + 2 + STICK_PANEL_WIDTH/2 + STICK_PANEL_WIDTH/2 * xval/RESX, y + 2 + STICK_PANEL_WIDTH/2 - STICK_PANEL_WIDTH/2 * yval/RESX, &ALPHA_STICK_POINTER);
|
||||
}
|
||||
|
||||
#include "alpha_button_on.lbm"
|
||||
#include "alpha_button_off.lbm"
|
||||
|
||||
void drawButton(coord_t x, coord_t y, const char * label, LcdFlags attr)
|
||||
{
|
||||
int width = getTextWidth(label, 0, attr);
|
||||
|
@ -70,9 +75,9 @@ void drawButton(coord_t x, coord_t y, const char * label, LcdFlags attr)
|
|||
lcdDrawText(x+padding+8, y, label, TEXT_COLOR);
|
||||
}
|
||||
if (attr & BUTTON_OFF)
|
||||
lcdDrawAlphaBitmap(x-6, y+3, LBM_BUTTON_OFF);
|
||||
lcd->drawAlphaBitmap(x-6, y+3, &ALPHA_BUTTON_OFF);
|
||||
else if (attr & BUTTON_ON)
|
||||
lcdDrawAlphaBitmap(x-6, y+3, LBM_BUTTON_ON);
|
||||
lcd->drawAlphaBitmap(x-6, y+3, &ALPHA_BUTTON_ON);
|
||||
}
|
||||
|
||||
void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr)
|
||||
|
@ -383,11 +388,6 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int
|
|||
}
|
||||
|
||||
if (GV_IS_GV_VALUE(value, min, max)) {
|
||||
if (attr & LEFT)
|
||||
attr -= LEFT; /* because of ZCHAR */
|
||||
else
|
||||
x -= 20;
|
||||
|
||||
attr &= ~PREC1;
|
||||
|
||||
int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta);
|
||||
|
@ -421,25 +421,26 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int
|
|||
}
|
||||
#endif
|
||||
|
||||
#define SLEEP_BITMAP_WIDTH 150
|
||||
#define SLEEP_BITMAP_HEIGHT 150
|
||||
void drawSleepBitmap()
|
||||
{
|
||||
lcdClear();
|
||||
lcdDrawBitmap((LCD_W-SLEEP_BITMAP_WIDTH)/2, (LCD_H-SLEEP_BITMAP_HEIGHT)/2, LBM_SLEEP);
|
||||
lcd->clear();
|
||||
const BitmapBuffer * bitmap = BitmapBuffer::load(getThemePath("sleep.bmp"));
|
||||
if (bitmap) {
|
||||
lcd->drawBitmap((LCD_W-bitmap->getWidth())/2, (LCD_H-bitmap->getHeight())/2, bitmap);
|
||||
}
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
#define SHUTDOWN_BITMAP_WIDTH 110
|
||||
#define SHUTDOWN_BITMAP_HEIGHT 110
|
||||
#include "alpha_shutdown.lbm"
|
||||
|
||||
#define SHUTDOWN_CIRCLE_DIAMETER 150
|
||||
void drawShutdownBitmap(uint32_t index)
|
||||
{
|
||||
static uint32_t last_index = 0xffffffff;
|
||||
|
||||
if (index < last_index) {
|
||||
lcdDrawBlackOverlay();
|
||||
lcdDrawAlphaBitmap((LCD_W-SHUTDOWN_BITMAP_WIDTH)/2, (LCD_H-SHUTDOWN_BITMAP_HEIGHT)/2, LBM_SHUTDOWN);
|
||||
theme->drawBackground();
|
||||
lcd->drawAlphaBitmap((LCD_W-ALPHA_SHUTDOWN.getWidth())/2, (LCD_H-ALPHA_SHUTDOWN.getHeight())/2, &ALPHA_SHUTDOWN);
|
||||
lcdStoreBackupBuffer();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -64,8 +64,8 @@ void GaugeWidget::refresh()
|
|||
// Gauge
|
||||
lcdSetColor(color);
|
||||
lcdDrawSolidFilledRect(zone.x, zone.y + 16, zone.w, 16, TEXT_INVERTED_COLOR);
|
||||
lcdDrawNumber((percent >= 100 ? 20 : (percent >= 10 ? 10 : 0)) + zone.x+zone.w/2, zone.y + 17, percent, SMLSIZE | CUSTOM_COLOR, 0, NULL, "%");
|
||||
lcdInvertRect(zone.x + w, zone.y + 16, zone.w - w, 16, CUSTOM_COLOR);
|
||||
lcdDrawNumber(zone.x+zone.w/2, zone.y + 17, percent, SMLSIZE | CUSTOM_COLOR | CENTERED, 0, NULL, "%");
|
||||
lcd->invertRect(zone.x + w, zone.y + 16, zone.w - w, 16, CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
BaseWidgetFactory<GaugeWidget> gaugeWidget("Gauge", GaugeWidget::options);
|
||||
|
|
|
@ -25,57 +25,60 @@ class ModelBitmapWidget: public Widget
|
|||
public:
|
||||
ModelBitmapWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData),
|
||||
bitmap(NULL)
|
||||
buffer(NULL)
|
||||
{
|
||||
memset(bitmapFilename, 0, sizeof(bitmapFilename));
|
||||
}
|
||||
|
||||
void loadBitmap()
|
||||
{
|
||||
char filename[] = BITMAPS_PATH "/xxxxxxxxxx.bmp";
|
||||
strncpy(filename+sizeof(BITMAPS_PATH), g_model.header.bitmap, sizeof(g_model.header.bitmap));
|
||||
strcat(filename+sizeof(BITMAPS_PATH), BITMAPS_EXT);
|
||||
bitmap = bmpLoad(filename);
|
||||
memcpy(bitmapFilename, g_model.header.bitmap, sizeof(g_model.header.bitmap));
|
||||
// TODO rescale the bitmap here instead of every refresh!
|
||||
memset(bitmapFilename, 255, sizeof(bitmapFilename));
|
||||
}
|
||||
|
||||
virtual ~ModelBitmapWidget()
|
||||
{
|
||||
free(bitmap);
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
virtual void refresh();
|
||||
#define DRAW_SCALED_BITMAP_FIT_WIDTH 1
|
||||
#define DRAW_SCALED_BITMAP_FIT_HEIGHT 2
|
||||
|
||||
void refreshBuffer()
|
||||
{
|
||||
delete buffer;
|
||||
buffer = new BitmapBuffer(zone.w, zone.h);
|
||||
if (buffer) {
|
||||
buffer->drawBitmap(0, 0, lcd, zone.x, zone.y, zone.w, zone.h);
|
||||
GET_FILENAME(filename, BITMAPS_PATH, g_model.header.bitmap, BITMAPS_EXT);
|
||||
BitmapBuffer * bitmap = BitmapBuffer::load(filename);
|
||||
if (zone.h >= 96 && zone.w >= 120) {
|
||||
buffer->drawFilledRect(0, 0, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
buffer->drawBitmapPattern(6, 4, LBM_MODEL_ICON, MAINVIEW_GRAPHICS_COLOR);
|
||||
buffer->drawSizedText(45, 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | SMLSIZE);
|
||||
buffer->drawSolidFilledRect(39, 27, zone.w - 48, 2, MAINVIEW_GRAPHICS_COLOR);
|
||||
if (bitmap) {
|
||||
buffer->drawScaledBitmap(bitmap, 0, 38, zone.w, zone.h - 38);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bitmap) {
|
||||
buffer->drawScaledBitmap(bitmap, 0, 0, zone.w, zone.h);
|
||||
}
|
||||
}
|
||||
delete bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void refresh()
|
||||
{
|
||||
if (memcmp(bitmapFilename, g_model.header.bitmap, sizeof(g_model.header.bitmap)) != 0) {
|
||||
refreshBuffer();
|
||||
memcpy(bitmapFilename, g_model.header.bitmap, sizeof(g_model.header.bitmap));
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
lcd->drawBitmap(zone.x, zone.y, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
char bitmapFilename[sizeof(g_model.header.bitmap)];
|
||||
uint8_t * bitmap;
|
||||
BitmapBuffer * buffer;
|
||||
};
|
||||
|
||||
void ModelBitmapWidget::refresh()
|
||||
{
|
||||
if (memcmp(bitmapFilename, g_model.header.bitmap, sizeof(g_model.header.bitmap)) != 0) {
|
||||
loadBitmap();
|
||||
}
|
||||
|
||||
if (zone.h >= 96) {
|
||||
lcdDrawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
lcdDrawBitmapPattern(zone.x + 6, zone.y + 4, LBM_MODEL_ICON, MAINVIEW_GRAPHICS_COLOR);
|
||||
lcdDrawSizedText(zone.x + 45, zone.y + 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | SMLSIZE);
|
||||
lcdDrawSolidFilledRect(zone.x + 39, zone.y + 27, zone.w - 48, 2, MAINVIEW_GRAPHICS_COLOR);
|
||||
if (bitmap) {
|
||||
float scale = getBitmapScale(bitmap, zone.w, zone.h - 25);
|
||||
int width = getBitmapScaledSize(getBitmapWidth(bitmap), scale);
|
||||
int height = getBitmapScaledSize(getBitmapHeight(bitmap), scale);
|
||||
lcdDrawBitmap(zone.x + (zone.w - width) / 2, zone.y + zone.h - height / 2 - height / 2, bitmap, 0, 0, scale);
|
||||
}
|
||||
}
|
||||
else if (bitmap) {
|
||||
float scale = getBitmapScale(bitmap, 1000, zone.h);
|
||||
int width = getBitmapScaledSize(getBitmapWidth(bitmap), scale);
|
||||
int height = getBitmapScaledSize(getBitmapHeight(bitmap), scale);
|
||||
lcdDrawBitmap(zone.x + (zone.w - width) / 2, zone.y + (zone.h - height) / 2, bitmap, 0, 0, scale);
|
||||
}
|
||||
}
|
||||
|
||||
BaseWidgetFactory<ModelBitmapWidget> modelBitmapWidget("ModelBmp", NULL);
|
||||
|
|
252
radio/src/gui/taranis/bmp.cpp
Normal file
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
uint8_t * lcdLoadBitmap(uint8_t * bmp, const char * filename, uint16_t width, uint16_t height)
|
||||
{
|
||||
FIL bmpFile;
|
||||
UINT read;
|
||||
uint8_t palette[16];
|
||||
uint8_t bmpBuf[LCD_W]; /* maximum with LCD_W */
|
||||
uint8_t * buf = &bmpBuf[0];
|
||||
|
||||
if (width > LCD_W) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f_size(&bmpFile) < 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = f_read(&bmpFile, buf, 14, &read);
|
||||
if (result != FR_OK || read != 14) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buf[0] != 'B' || buf[1] != 'M') {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t fsize = *((uint32_t *)&buf[2]);
|
||||
uint32_t hsize = *((uint32_t *)&buf[10]); /* header size */
|
||||
|
||||
uint32_t len = limit((uint32_t)4, (uint32_t)(hsize-14), (uint32_t)32);
|
||||
result = f_read(&bmpFile, buf, len, &read);
|
||||
if (result != FR_OK || read != len) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t ihsize = *((uint32_t *)&buf[0]); /* more header size */
|
||||
|
||||
/* invalid header size */
|
||||
if (ihsize + 14 > hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sometimes file size is set to some headers size, set a real size in that case */
|
||||
if (fsize == 14 || fsize == ihsize + 14)
|
||||
fsize = f_size(&bmpFile) - 2;
|
||||
|
||||
/* declared file size less than header size */
|
||||
if (fsize <= hsize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t w, h;
|
||||
|
||||
switch (ihsize){
|
||||
case 40: // windib
|
||||
case 56: // windib v3
|
||||
case 64: // OS/2 v2
|
||||
case 108: // windib v4
|
||||
case 124: // windib v5
|
||||
w = *((uint32_t *)&buf[4]);
|
||||
h = *((uint32_t *)&buf[8]);
|
||||
buf += 12;
|
||||
break;
|
||||
case 12: // OS/2 v1
|
||||
w = *((uint16_t *)&buf[4]);
|
||||
h = *((uint16_t *)&buf[6]);
|
||||
buf += 8;
|
||||
break;
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*((uint16_t *)&buf[0]) != 1) { /* planes */
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (w > width || h > height) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t depth = *((uint16_t *)&buf[2]);
|
||||
|
||||
buf = &bmpBuf[0];
|
||||
|
||||
if (depth == 4) {
|
||||
if (f_lseek(&bmpFile, hsize-64) != FR_OK || f_read(&bmpFile, buf, 64, &read) != FR_OK || read != 64) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t i=0; i<16; i++) {
|
||||
palette[i] = buf[4*i] >> 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (f_lseek(&bmpFile, hsize) != FR_OK) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * dest = bmp;
|
||||
|
||||
*dest++ = w;
|
||||
*dest++ = h;
|
||||
|
||||
memset(dest, 0, BITMAP_BUFFER_SIZE(w, h) - 2);
|
||||
|
||||
uint32_t rowSize;
|
||||
|
||||
switch (depth) {
|
||||
case 1:
|
||||
rowSize = ((w+31)/32)*4;
|
||||
for (uint32_t i=0; i<h; i+=2) {
|
||||
result = f_read(&bmpFile, buf, rowSize*2, &read);
|
||||
if (result != FR_OK || read != rowSize*2) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint32_t j=0; j<w; j++) {
|
||||
uint8_t * dst = dest + (h-i-2)/2 * w + j;
|
||||
if (!(buf[j/8] & (1<<(7-(j%8)))))
|
||||
*dst |= 0xF0;
|
||||
if (!(buf[rowSize+j/8] & (1<<(7-(j%8)))))
|
||||
*dst |= 0x0F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rowSize = ((4*w+31)/32)*4;
|
||||
for (int32_t i=h-1; i>=0; i--) {
|
||||
result = f_read(&bmpFile, buf, rowSize, &read);
|
||||
if (result != FR_OK || read != rowSize) {
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t * dst = dest + (i/2)*w;
|
||||
for (uint32_t j=0; j<w; j++) {
|
||||
uint8_t index = (buf[j/2] >> ((j & 1) ? 0 : 4)) & 0x0F;
|
||||
uint8_t val = palette[index] << ((i & 1) ? 4 : 0);
|
||||
*dst++ |= val ^ ((i & 1) ? 0xF0 : 0x0F);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
f_close(&bmpFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_close(&bmpFile);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
const uint8_t bmpHeader[] = {
|
||||
0x42, 0x4d, 0xF8, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 212, 0x00, 0x00, 0x00, 64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0xbc, 0x38, 0x00, 0x00, 0xbc, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xee, 0xee, 0xee, 0x00, 0xdd, 0xdd,
|
||||
0xdd, 0x00, 0xcc, 0xcc, 0xcc, 0x00, 0xbb, 0xbb, 0xbb, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x99, 0x99,
|
||||
0x99, 0x00, 0x88, 0x88, 0x88, 0x00, 0x77, 0x77, 0x77, 0x00, 0x66, 0x66, 0x66, 0x00, 0x55, 0x55,
|
||||
0x55, 0x00, 0x44, 0x44, 0x44, 0x00, 0x33, 0x33, 0x33, 0x00, 0x22, 0x22, 0x22, 0x00, 0x11, 0x11,
|
||||
0x11, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
inline display_t getPixel(unsigned int x, unsigned int y)
|
||||
{
|
||||
if (x>=LCD_W || y>=LCD_H)
|
||||
return 0;
|
||||
display_t * p = &displayBuf[y / 2 * LCD_W + x];
|
||||
return (y & 1) ? (*p >> 4) : (*p & 0x0F);
|
||||
}
|
||||
|
||||
const char * writeScreenshot()
|
||||
{
|
||||
FIL bmpFile;
|
||||
UINT written;
|
||||
char filename[42]; // /SCREENSHOTS/screen-2013-01-01-123540.bmp
|
||||
|
||||
// check and create folder here
|
||||
strcpy_P(filename, SCREENSHOTS_PATH);
|
||||
const char * error = sdCheckAndCreateDirectory(filename);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char * tmp = strAppend(&filename[sizeof(SCREENSHOTS_PATH)-1], "/screen");
|
||||
tmp = strAppendDate(tmp, true);
|
||||
strcpy(tmp, BITMAPS_EXT);
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
result = f_write(&bmpFile, bmpHeader, sizeof(bmpHeader), &written);
|
||||
if (result != FR_OK || written != sizeof(bmpHeader)) {
|
||||
f_close(&bmpFile);
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
for (int y=LCD_H-1; y>=0; y-=1) {
|
||||
for (int x=0; x<8*((LCD_W+7)/8); x+=2) {
|
||||
uint8_t byte = getPixel(x+1, y) + (getPixel(x, y) << 4);
|
||||
f_write(&bmpFile, &byte, 1, &written);
|
||||
if (result != FR_OK || written != 1) {
|
||||
f_close(&bmpFile);
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f_close(&bmpFile);
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -54,7 +54,6 @@ struct MenuItem {
|
|||
const MenuHandlerFunc action;
|
||||
};
|
||||
|
||||
int circularIncDec(int current, int inc, int min, int max, IsValueAvailable isValueAvailable=NULL);
|
||||
void drawSplash();
|
||||
void drawScreenIndex(uint8_t index, uint8_t count, uint8_t attr);
|
||||
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
|
||||
|
|
|
@ -220,7 +220,7 @@ void lcdSetContrast();
|
|||
void lcdRefresh();
|
||||
#endif
|
||||
|
||||
uint8_t * bmpLoad(uint8_t * dest, const char * filename, uint16_t width, uint16_t height);
|
||||
uint8_t * lcdLoadBitmap(uint8_t * dest, const char * filename, uint16_t width, uint16_t height);
|
||||
const char * writeScreenshot();
|
||||
|
||||
#if defined(BOOT)
|
||||
|
|
|
@ -458,7 +458,7 @@ void menuGeneralSdManager(evt_t _event)
|
|||
char * ext = getFileExtension(reusableBuffer.sdmanager.lines[index], SD_SCREEN_FILE_LENGTH+1);
|
||||
if (ext && !strcasecmp(ext, BITMAPS_EXT)) {
|
||||
if (lastPos != menuVerticalPosition) {
|
||||
if (!bmpLoad(modelBitmap, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) {
|
||||
if (!lcdLoadBitmap(modelBitmap, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) {
|
||||
memcpy(modelBitmap, logo_taranis, MODEL_BITMAP_SIZE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,11 +355,11 @@ static int luaLcdDrawPixmap(lua_State *L)
|
|||
|
||||
#if defined(PCBTARANIS)
|
||||
uint8_t bitmap[BITMAP_BUFFER_SIZE(LCD_W/2, LCD_H)]; // width max is LCD_W/2 pixels for saving stack and avoid a malloc here
|
||||
if (bmpLoad(bitmap, filename, LCD_W/2, LCD_H)) {
|
||||
if (lcdLoadBitmap(bitmap, filename, LCD_W/2, LCD_H)) {
|
||||
lcdDrawBitmap(x, y, bitmap);
|
||||
}
|
||||
#else
|
||||
uint8_t * bitmap = bmpLoad(filename);
|
||||
uint8_t * bitmap = lcdLoadBitmap(filename);
|
||||
if (bitmap) {
|
||||
lcdDrawBitmap(x, y, bitmap);
|
||||
free(bitmap);
|
||||
|
|
|
@ -829,8 +829,8 @@ class LuaTheme: public Theme
|
|||
friend void luaLoadThemeCallback();
|
||||
|
||||
public:
|
||||
LuaTheme(const char * name, const uint8_t * bitmap, int options):
|
||||
Theme(name, bitmap, createOptionsArray(options)),
|
||||
LuaTheme(const char * name, int options):
|
||||
Theme(name, createOptionsArray(options)),
|
||||
loadFunction(0),
|
||||
drawBackgroundFunction(0),
|
||||
drawTopbarBackgroundFunction(0),
|
||||
|
@ -870,7 +870,7 @@ class LuaTheme: public Theme
|
|||
|
||||
void luaLoadThemeCallback()
|
||||
{
|
||||
const char * name=NULL, * bitmap=NULL;
|
||||
const char * name=NULL;
|
||||
int themeOptions=0, loadFunction=0, drawBackgroundFunction=0, drawTopbarBackgroundFunction=0;
|
||||
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
|
@ -880,9 +880,6 @@ void luaLoadThemeCallback()
|
|||
if (!strcmp(key, "name")) {
|
||||
name = luaL_checkstring(L, -1);
|
||||
}
|
||||
else if (!strcmp(key, "bitmap")) {
|
||||
bitmap = luaL_checkstring(L, -1);
|
||||
}
|
||||
else if (!strcmp(key, "options")) {
|
||||
themeOptions = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(L);
|
||||
|
@ -901,12 +898,8 @@ void luaLoadThemeCallback()
|
|||
}
|
||||
}
|
||||
|
||||
if (name && bitmap) {
|
||||
char path[LUA_FULLPATH_MAXLEN+1];
|
||||
strcpy(path, THEMES_PATH "/");
|
||||
strcpy(path+sizeof(THEMES_PATH), bitmap);
|
||||
uint8_t * bitmap = bmpLoad(path/*, 51, 31*/); // TODO rescale
|
||||
LuaTheme * theme = new LuaTheme(name, bitmap, themeOptions);
|
||||
if (name) {
|
||||
LuaTheme * theme = new LuaTheme(name, themeOptions);
|
||||
theme->loadFunction = loadFunction;
|
||||
theme->drawBackgroundFunction = drawBackgroundFunction;
|
||||
theme->drawTopbarBackgroundFunction = drawTopbarBackgroundFunction;
|
||||
|
@ -1070,21 +1063,24 @@ void luaLoadFiles(const char * directory, void (*callback)())
|
|||
fno.lfsize = sizeof(lfn);
|
||||
|
||||
strcpy(path, directory);
|
||||
int pathlen = strlen(path);
|
||||
|
||||
FRESULT res = f_opendir(&dir, path); /* Open the directory */
|
||||
|
||||
if (res == FR_OK) {
|
||||
int pathlen = strlen(path);
|
||||
path[pathlen++] = '/';
|
||||
for (;;) {
|
||||
res = f_readdir(&dir, &fno); /* Read a directory item */
|
||||
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
|
||||
fn = * fno.lfname ? fno.lfname : fno.fname;
|
||||
uint8_t len = strlen(fn);
|
||||
// Eliminates directories / non scripts files
|
||||
if (len < 5 || strcasecmp(fn+len-4, SCRIPTS_EXT) || (fno.fattrib & AM_DIR)) continue;
|
||||
strcpy(&path[pathlen], fn);
|
||||
luaLoadFile(path, callback);
|
||||
if (len > 0 && fn[0]!='.' && (fno.fattrib & AM_DIR)) {
|
||||
strcpy(&path[pathlen], fn);
|
||||
strcat(&path[pathlen], "/main.lua");
|
||||
if (isFileAvailable(path)) {
|
||||
luaLoadFile(path, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -38,7 +38,7 @@ bool loadModelBitmap(char * name, uint8_t * bitmap)
|
|||
char lfn[] = BITMAPS_PATH "/xxxxxxxxxx.bmp";
|
||||
strncpy(lfn+sizeof(BITMAPS_PATH), name, len);
|
||||
strcpy(lfn+sizeof(BITMAPS_PATH)+len, BITMAPS_EXT);
|
||||
if (bmpLoad(bitmap, lfn, MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) {
|
||||
if (lcdLoadBitmap(bitmap, lfn, MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2606,7 +2606,7 @@ int main(void)
|
|||
// lcdSetRefVolt(25);
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
drawSplash();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -203,7 +203,11 @@
|
|||
#define ROTARY_ENCODER_NAVIGATION
|
||||
#endif
|
||||
|
||||
#define __ALIGNED __attribute__((aligned(32)))
|
||||
#if defined(SIMU)
|
||||
#define __ALIGNED
|
||||
#else
|
||||
#define __ALIGNED __attribute__((aligned(32)))
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
#define __DMA
|
||||
|
@ -213,7 +217,7 @@
|
|||
#define __DMA __ALIGNED
|
||||
#endif
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#if defined(PCBHORUS) && !defined(SIMU)
|
||||
#define __SDRAM __attribute__((section(".sdram"), aligned(32)))
|
||||
#else
|
||||
#define __SDRAM __DMA
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
#define EEPROMS_PATH ROOT_PATH "EEPROMS"
|
||||
#define SCRIPTS_PATH ROOT_PATH "SCRIPTS"
|
||||
#define WIZARD_PATH SCRIPTS_PATH "/WIZARD"
|
||||
#define THEMES_PATH SCRIPTS_PATH "/THEMES"
|
||||
#define LAYOUTS_PATH SCRIPTS_PATH "/LAYOUTS"
|
||||
#define WIDGETS_PATH SCRIPTS_PATH "/WIDGETS"
|
||||
#define THEMES_PATH ROOT_PATH "THEMES"
|
||||
#define LAYOUTS_PATH ROOT_PATH "LAYOUTS"
|
||||
#define WIDGETS_PATH ROOT_PATH "WIDGETS"
|
||||
#define WIZARD_NAME "wizard.lua"
|
||||
#define TEMPLATES_PATH SCRIPTS_PATH "/TEMPLATES"
|
||||
#define SCRIPTS_MIXES_PATH SCRIPTS_PATH "/MIXES"
|
||||
|
@ -57,6 +57,13 @@
|
|||
#define EEPROM_EXT ".bin"
|
||||
#define SPORT_FIRMWARE_EXT ".frk"
|
||||
|
||||
#define GET_FILENAME(filename, path, var, ext) \
|
||||
char filename[sizeof(path) + sizeof(var) + sizeof(ext)]; \
|
||||
memcpy(filename, path, sizeof(path) - 1); \
|
||||
filename[sizeof(path) - 1] = '/'; \
|
||||
memcpy(&filename[sizeof(path)], var, sizeof(var)); \
|
||||
strcat(&filename[sizeof(path)], ext)
|
||||
|
||||
extern FATFS g_FATFS_Obj;
|
||||
extern FIL g_oLogFile;
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ extern int _getpid ( void )
|
|||
return -1 ;
|
||||
}
|
||||
|
||||
void _init (void)
|
||||
{
|
||||
//void _init (void)
|
||||
//{
|
||||
|
||||
}
|
||||
//}
|
||||
|
|
|
@ -259,8 +259,8 @@ void ledBlue(void);
|
|||
// LCD driver
|
||||
void lcdInit(void);
|
||||
void lcdRefresh(void);
|
||||
void lcdDrawSolidFilledRectDMA(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
|
||||
void lcdDrawBitmapDMA(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t * bitmap);
|
||||
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
|
||||
void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t h);
|
||||
void lcdStoreBackupBuffer(void);
|
||||
int lcdRestoreBackupBuffer(void);
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ uint8_t LCD_FIRST_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
|
|||
uint8_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
|
||||
uint8_t LCD_BACKUP_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
|
||||
|
||||
uint8_t * CurrentFrameBuffer = LCD_FIRST_FRAME_BUFFER;
|
||||
uint32_t CurrentLayer = LCD_FIRST_LAYER;
|
||||
|
||||
#define NRST_LOW() do { LCD_GPIO_NRST->BSRRH = LCD_GPIO_PIN_NRST; } while(0)
|
||||
|
@ -381,6 +380,10 @@ void LCD_Init(void)
|
|||
LCD_ControlLight(100);
|
||||
}
|
||||
|
||||
BitmapBuffer lcdBuffer1(LCD_W, LCD_H, (uint16_t *)LCD_FIRST_FRAME_BUFFER);
|
||||
BitmapBuffer lcdBuffer2(LCD_W, LCD_H, (uint16_t *)LCD_SECOND_FRAME_BUFFER);
|
||||
BitmapBuffer * lcd = &lcdBuffer1;
|
||||
|
||||
/**
|
||||
* @brief Sets the LCD Layer.
|
||||
* @param Layerx: specifies the Layer foreground or background.
|
||||
|
@ -389,11 +392,11 @@ void LCD_Init(void)
|
|||
void LCD_SetLayer(uint32_t Layerx)
|
||||
{
|
||||
if (Layerx == LCD_FIRST_LAYER) {
|
||||
CurrentFrameBuffer = LCD_FIRST_FRAME_BUFFER;
|
||||
lcd = &lcdBuffer1;
|
||||
CurrentLayer = LCD_FIRST_LAYER;
|
||||
}
|
||||
else {
|
||||
CurrentFrameBuffer = LCD_SECOND_FRAME_BUFFER;
|
||||
lcd = &lcdBuffer2;
|
||||
CurrentLayer = LCD_SECOND_LAYER;
|
||||
}
|
||||
}
|
||||
|
@ -431,28 +434,23 @@ void lcdInit(void)
|
|||
|
||||
/* Set Foreground layer */
|
||||
LCD_SetLayer(LCD_SECOND_LAYER);
|
||||
lcdClear();
|
||||
lcd->clear();
|
||||
LCD_SetTransparency(255);
|
||||
}
|
||||
|
||||
void lcdDrawSolidFilledRectDMA(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
|
||||
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
|
||||
{
|
||||
uint32_t addr = (uint32_t)CurrentFrameBuffer + 2*(LCD_W*y + x);
|
||||
uint8_t red = (0xF800 & color) >> 11;
|
||||
uint8_t blue = 0x001F & color;
|
||||
uint8_t green = (0x07E0 & color) >> 5;
|
||||
|
||||
DMA2D_DeInit();
|
||||
|
||||
DMA2D_InitTypeDef DMA2D_InitStruct;
|
||||
DMA2D_InitStruct.DMA2D_Mode = DMA2D_R2M;
|
||||
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
|
||||
DMA2D_InitStruct.DMA2D_OutputGreen = green;
|
||||
DMA2D_InitStruct.DMA2D_OutputBlue = blue;
|
||||
DMA2D_InitStruct.DMA2D_OutputRed = red;
|
||||
DMA2D_InitStruct.DMA2D_OutputGreen = (0x07E0 & color) >> 5;
|
||||
DMA2D_InitStruct.DMA2D_OutputBlue = 0x001F & color;
|
||||
DMA2D_InitStruct.DMA2D_OutputRed = (0xF800 & color) >> 11;
|
||||
DMA2D_InitStruct.DMA2D_OutputAlpha = 0x0F;
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = addr;
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = (LCD_W - w);
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest) + 2*(destw*y + x);
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = (destw - w);
|
||||
DMA2D_InitStruct.DMA2D_NumberOfLine = h;
|
||||
DMA2D_InitStruct.DMA2D_PixelPerLine = w;
|
||||
DMA2D_Init(&DMA2D_InitStruct);
|
||||
|
@ -464,31 +462,26 @@ void lcdDrawSolidFilledRectDMA(uint16_t x, uint16_t y, uint16_t w, uint16_t h, u
|
|||
while (DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET);
|
||||
}
|
||||
|
||||
void lcdDrawBitmapDMA(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t * bitmap)
|
||||
void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t h)
|
||||
{
|
||||
if ((uint32_t(bitmap) & 0x03) != 0)
|
||||
return;
|
||||
|
||||
uint32_t addr = (uint32_t)CurrentFrameBuffer + 2*(LCD_W*y + x);
|
||||
|
||||
DMA2D_DeInit();
|
||||
|
||||
DMA2D_InitTypeDef DMA2D_InitStruct;
|
||||
DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M;
|
||||
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = addr;
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest) + 2*(destw*y + x);
|
||||
DMA2D_InitStruct.DMA2D_OutputGreen = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputBlue = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputRed = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputAlpha = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = (LCD_W - w);
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = (destw - srcw);
|
||||
DMA2D_InitStruct.DMA2D_NumberOfLine = h;
|
||||
DMA2D_InitStruct.DMA2D_PixelPerLine = w;
|
||||
DMA2D_InitStruct.DMA2D_PixelPerLine = srcw;
|
||||
DMA2D_Init(&DMA2D_InitStruct);
|
||||
|
||||
DMA2D_FG_InitTypeDef DMA2D_FG_InitStruct;
|
||||
DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGMA = CONVERT_PTR_UINT(bitmap);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGMA = CONVERT_PTR_UINT(src);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGO = 0;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGCM = CM_RGB565;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = NO_MODIF_ALPHA_VALUE;
|
||||
|
@ -537,12 +530,12 @@ void DMAcopy(void * src, void * dest, int len)
|
|||
|
||||
void lcdStoreBackupBuffer()
|
||||
{
|
||||
DMAcopy(CurrentFrameBuffer, LCD_BACKUP_FRAME_BUFFER, DISPLAY_BUFFER_SIZE);
|
||||
DMAcopy(lcd->data, LCD_BACKUP_FRAME_BUFFER, DISPLAY_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
int lcdRestoreBackupBuffer()
|
||||
{
|
||||
DMAcopy(LCD_BACKUP_FRAME_BUFFER, CurrentFrameBuffer, DISPLAY_BUFFER_SIZE);
|
||||
DMAcopy(LCD_BACKUP_FRAME_BUFFER, lcd->data, DISPLAY_BUFFER_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@ TEST(Lcd, BMPWrapping)
|
|||
{
|
||||
lcdClear();
|
||||
uint8_t bitmap[2+40*40/2];
|
||||
bmpLoad(bitmap, TESTS_PATH "/tests/plane.bmp", 40, 40);
|
||||
lcdLoadBitmap(bitmap, TESTS_PATH "/tests/plane.bmp", 40, 40);
|
||||
lcdDrawBitmap(200, 0, bitmap);
|
||||
lcdDrawBitmap(200, 60, bitmap);
|
||||
lcdDrawBitmap(240, 60, bitmap); // x too big
|
||||
|
@ -365,31 +365,31 @@ TEST(Lcd, lcdDrawBitmapLoadAndDisplay)
|
|||
// Test proper BMP files, they should display correctly
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(7, 32));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), TESTS_PATH "/tests/4b_7x32.bmp", 7, 32) != NULL);
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), TESTS_PATH "/tests/4b_7x32.bmp", 7, 32) != NULL);
|
||||
bitmap.leakCheck();
|
||||
lcdDrawBitmap(10, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(6, 32));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), TESTS_PATH "/tests/1b_6x32.bmp", 6, 32) != NULL);
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), TESTS_PATH "/tests/1b_6x32.bmp", 6, 32) != NULL);
|
||||
bitmap.leakCheck();
|
||||
lcdDrawBitmap(20, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(31, 31));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), TESTS_PATH "/tests/4b_31x31.bmp", 31, 31) != NULL);
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), TESTS_PATH "/tests/4b_31x31.bmp", 31, 31) != NULL);
|
||||
bitmap.leakCheck();
|
||||
lcdDrawBitmap(30, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(39, 32));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), TESTS_PATH "/tests/1b_39x32.bmp", 39, 32) != NULL);
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), TESTS_PATH "/tests/1b_39x32.bmp", 39, 32) != NULL);
|
||||
bitmap.leakCheck();
|
||||
lcdDrawBitmap(70, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(20, 20));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), TESTS_PATH "/tests/4b_20x20.bmp", 20, 20) != NULL);
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), TESTS_PATH "/tests/4b_20x20.bmp", 20, 20) != NULL);
|
||||
bitmap.leakCheck();
|
||||
lcdDrawBitmap(120, 2, bitmap.buffer());
|
||||
}
|
||||
|
@ -398,12 +398,12 @@ TEST(Lcd, lcdDrawBitmapLoadAndDisplay)
|
|||
// Test various bad BMP files, they should not display
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(LCD_W+1, 32));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), "", LCD_W+1, 32) == NULL) << "to wide";
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), "", LCD_W+1, 32) == NULL) << "to wide";
|
||||
bitmap.leakCheck();
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(10, 10));
|
||||
EXPECT_TRUE(bmpLoad(bitmap.buffer(), TESTS_PATH "/tests/1b_39x32.bmp", 10, 10) == NULL) << "to small buffer";
|
||||
EXPECT_TRUE(lcdLoadBitmap(bitmap.buffer(), TESTS_PATH "/tests/1b_39x32.bmp", 10, 10) == NULL) << "to small buffer";
|
||||
bitmap.leakCheck();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -873,10 +873,17 @@
|
|||
#define TR_DELAY "Delay"
|
||||
#define TR_SD_CARD "SD CARD"
|
||||
#define TR_SDHC_CARD "SD-HC CARD"
|
||||
#if defined(COLORLCD)
|
||||
#define TR_NO_SOUNDS_ON_SD "No Sounds"
|
||||
#define TR_NO_MODELS_ON_SD "No Models"
|
||||
#define TR_NO_BITMAPS_ON_SD "No Bitmaps"
|
||||
#define TR_NO_SCRIPTS_ON_SD "No Scripts"
|
||||
#else
|
||||
#define TR_NO_SOUNDS_ON_SD "No Sounds" BREAKSPACE "on SD"
|
||||
#define TR_NO_MODELS_ON_SD "No Models" BREAKSPACE "on SD"
|
||||
#define TR_NO_BITMAPS_ON_SD "No Bitmaps" BREAKSPACE "on SD"
|
||||
#define TR_NO_SCRIPTS_ON_SD "No Scripts" BREAKSPACE "on SD"
|
||||
#endif
|
||||
#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
|
||||
#define TR_SCRIPT_PANIC "Script panic"
|
||||
#define TR_SCRIPT_KILLED "Script killed"
|
||||
|
|
|
@ -41,29 +41,32 @@ with open(sys.argv[2], "w") as f:
|
|||
f.write("0x%02x," % value)
|
||||
f.write("\n")
|
||||
elif what == "4/4/4/4":
|
||||
colors = []
|
||||
f.write("%d,%d,\n" % (width, height))
|
||||
constant = sys.argv[2].upper()[:-4]
|
||||
values = []
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
pixel = image.pixel(x, y)
|
||||
f.write("0x%1x%1x%1x%1x," % (Qt.qAlpha(pixel) // 16, Qt.qRed(pixel) // 16, Qt.qGreen(pixel) // 16, Qt.qBlue(pixel) // 16))
|
||||
f.write("\n")
|
||||
val = ((Qt.qAlpha(pixel) // 16) << 12) + ((Qt.qRed(pixel) // 16) << 8) + ((Qt.qGreen(pixel) // 16) << 4) + ((Qt.qBlue(pixel) // 16) << 0)
|
||||
values.append(str(val))
|
||||
f.write("const uint16_t __%s[] __ALIGNED = { %s };\n" % (constant, ",".join(values)))
|
||||
f.write("const Bitmap %s(%d, %d, __%s);\n" % (constant, width, height, constant))
|
||||
elif what == "5/6/5":
|
||||
colors = []
|
||||
writeSize(f, width, height)
|
||||
constant = sys.argv[2].upper()[:-4]
|
||||
values = []
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
pixel = image.pixel(x, y)
|
||||
val = ((Qt.qRed(pixel) >> 3) << 11) + ((Qt.qGreen(pixel) >> 2) << 5) + ((Qt.qBlue(pixel) >> 3) << 0)
|
||||
f.write("%d,%d," % (val % 256, val // 256))
|
||||
f.write("\n")
|
||||
values.append(str(val))
|
||||
f.write("const uint16_t __%s[] __ALIGNED = { %s };\n" % (constant, ",".join(values)))
|
||||
f.write("const Bitmap %s(%d, %d, __%s);\n" % (constant, width, height, constant))
|
||||
elif what == "5/6/5/8":
|
||||
colors = []
|
||||
writeSize(f, width, height)
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
pixel = image.pixel(x, y)
|
||||
val = ((Qt.qRed(pixel) >> 3) << 11) + ((Qt.qGreen(pixel) >> 2) << 5) + ((Qt.qBlue(pixel) >> 3) << 0)
|
||||
val = ((Qt.qRed(pixel) >> 4) << 12) + ((Qt.qGreen(pixel) >> 4) << 7) + ((Qt.qBlue(pixel) >> 4) << 1)
|
||||
f.write("%d,%d,%d," % (val % 256, val // 256, Qt.qAlpha(pixel)))
|
||||
f.write("\n")
|
||||
elif what == "4bits":
|
||||
|
|