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

[Horus] GUI continued

This commit is contained in:
Bertrand Songis 2016-02-25 23:10:58 +01:00
parent 83887f1532
commit 2b9242fac2
70 changed files with 1770 additions and 1474 deletions

View file

@ -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"

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

Before

Width:  |  Height:  |  Size: 510 KiB

After

Width:  |  Height:  |  Size: 510 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 510 KiB

After

Width:  |  Height:  |  Size: 510 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View 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 }

View file

@ -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)

View file

@ -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

View file

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

View file

@ -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)

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@ -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)

View 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);
}

View 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_

View file

@ -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"
};

View file

@ -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[];

View 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_

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@ -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;
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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;
}

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@ -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) {

View file

@ -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) {

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@ -334,7 +334,7 @@ bool menuModelSensor(evt_t event)
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_AUTOOFFSET);
sensor->autoOffset = editCheckBox(sensor->autoOffset, SENSOR_2ND_COLUMN, y, attr, event);
break;
case SENSOR_FIELD_ONLYPOSITIVE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ONLYPOSITIVE);
sensor->onlyPositive = editCheckBox(sensor->onlyPositive, SENSOR_2ND_COLUMN, y, attr, event);
@ -344,7 +344,7 @@ bool menuModelSensor(evt_t event)
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FILTER);
sensor->filter = editCheckBox(sensor->filter, SENSOR_2ND_COLUMN, y, attr, event);
break;
case SENSOR_FIELD_PERSISTENT:
lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_PERSISTENT));
sensor->persistent = editCheckBox(sensor->persistent, SENSOR_2ND_COLUMN, y, attr, event);
@ -381,7 +381,7 @@ void onSensorMenu(const char *result)
}
else if (result == STR_COPY) {
int newIndex = availableTelemetryIndex();
if (newIndex >= 0) {
TelemetrySensor & sourceSensor = g_model.telemetrySensors[index];
TelemetrySensor & newSensor = g_model.telemetrySensors[newIndex];
@ -390,7 +390,7 @@ void onSensorMenu(const char *result)
TelemetryItem & newItem = telemetryItems[newIndex];
newItem = sourceItem;
storageDirty(EE_MODEL);
}
}
else {
POPUP_WARNING(STR_TELEMETRYFULL);
}
@ -406,7 +406,7 @@ bool menuModelTelemetry(evt_t event)
delTelemetryIndex(i);
}
}
MENU(STR_MENUTELEMETRY, LBM_MODEL_ICONS, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX, { TELEMETRY_TYPE_ROWS RSSI_ROWS SENSORS_ROWS VARIO_ROWS });
for (int i=0; i<NUM_BODY_LINES; i++) {
@ -477,7 +477,7 @@ bool menuModelTelemetry(evt_t event)
allowNewSensors = !allowNewSensors;
}
break;
case ITEM_TELEMETRY_NEW_SENSOR:
lcdDrawText(MENUS_MARGIN_LEFT+INDENT_WIDTH, y, NO_INDENT(STR_TELEMETRY_NEWSENSOR), attr);
if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) {
@ -492,7 +492,7 @@ bool menuModelTelemetry(evt_t event)
}
}
break;
case ITEM_TELEMETRY_DELETE_ALL_SENSORS:
lcdDrawText(MENUS_MARGIN_LEFT+INDENT_WIDTH, y, NO_INDENT(STR_DELETE_ALL_SENSORS), attr);
if (attr)
@ -501,7 +501,7 @@ bool menuModelTelemetry(evt_t event)
killEvents(KEY_ENTER);
POPUP_CONFIRMATION(STR_CONFIRMDELETE);
}
break;
break;
case ITEM_TELEMETRY_IGNORE_SENSOR_INSTANCE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_IGNORE_INSTANCE);

View file

@ -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__)

View file

@ -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);
}

View file

@ -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;
}
}
}

View file

@ -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) {

View file

@ -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);
}

View file

@ -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_

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -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;

View file

@ -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;

View file

@ -62,7 +62,8 @@ bool menuAboutView(evt_t event)
break;
}
drawScreenTemplate("About", NULL);
theme->drawAboutBackground();
theme->drawTopbarBackground(NULL);
uint8_t screenDuration = 150;

View file

@ -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;

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@ -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;

View file

@ -22,6 +22,7 @@
#define _WIDGET_H_
#include <inttypes.h>
#include <string.h>
#define MAX_WIDGET_OPTIONS 5

View file

@ -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 {

View file

@ -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);

View file

@ -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);

View 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;
}

View file

@ -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);

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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);

View file

@ -781,7 +781,7 @@ ZoneOption * createOptionsArray(int reference)
if (reference == 0) {
return NULL;
}
int count = 0;
lua_rawgeti(L, LUA_REGISTRYINDEX, reference);
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -147,7 +147,7 @@ extern int _getpid ( void )
return -1 ;
}
void _init (void)
{
//void _init (void)
//{
}
//}

View file

@ -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);

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@ -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;
}
}
@ -428,31 +431,26 @@ void lcdInit(void)
LCD_SetLayer(LCD_FIRST_LAYER);
// lcdClear();
LCD_SetTransparency(0);
/* 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;
}

View file

@ -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();
}
}

View file

@ -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"

View file

@ -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":