mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-11 00:59:28 +00:00
Multi screen support, with dyn alignment (#2801)
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#pragma pack(push, 1)
|
||||
struct bmp_header_t {
|
||||
uint16_t signature;
|
||||
|
||||
@@ -102,6 +102,56 @@ void lcd_init() {
|
||||
// LCDs are configured for IM[2:0] = 001
|
||||
// 8080-I system, 16-bit parallel bus
|
||||
|
||||
io.lcd_data_write_command_and_data(0xE0, {0x00, 0x09, 0x0C, 0x03, 0x10, 0x06, 0x34, 0x68,
|
||||
0x49, 0x02, 0x0A, 0x07, 0x2C, 0x31, 0x0F});
|
||||
|
||||
io.lcd_data_write_command_and_data(0xE1, {0x00, 0x12, 0x15, 0x02, 0x10, 0x06, 0x35, 0x35,
|
||||
0x4A, 0x05, 0x10, 0x0C, 0x2F, 0x33, 0x0F});
|
||||
|
||||
io.lcd_data_write_command_and_data(0xC0, {0x0F, 0x0F}); // Vreg1out=4.5 Vreg2out=-4.5
|
||||
|
||||
io.lcd_data_write_command_and_data(0xC1, {0x44}); // VGH = 5*VCI VGL = -4*VCI
|
||||
|
||||
io.lcd_data_write_command_and_data(0xC5, {0x00, 0x66, 0x80}); // VCOM
|
||||
|
||||
io.lcd_data_write_command_and_data(0x36, {
|
||||
(1 << 7) | // MY=1
|
||||
(0 << 6) | // MX=0
|
||||
(0 << 5) | // MV=0
|
||||
(1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic
|
||||
(1 << 3) // BGR=1: For Kingtech LCD, BGR filter.
|
||||
});
|
||||
|
||||
// io.lcd_data_write_command_and_data(0x36, {0x48});
|
||||
io.lcd_data_write_command_and_data(0x3A, {0x65}); // 0x55 was the original
|
||||
// 这里的刷新率过低?
|
||||
// io.lcd_data_write_command_and_data(0xB1, {0x40, 0x1F}); // fix 60 fps
|
||||
io.lcd_data_write_command_and_data(0xB1, {0xA0, 0x11}); // Frame rate source is 11fps
|
||||
|
||||
io.lcd_data_write_command_and_data(0xB4, {0x02}); // 2 dot inversion
|
||||
|
||||
io.lcd_data_write_command_and_data(0xEE, {0x00, 0x04});
|
||||
|
||||
io.lcd_data_write_command_and_data(0xE9, {0x00});
|
||||
|
||||
io.lcd_data_write_command_and_data(0xF7, {0xA9, 0x51, 0x2C, 0x82});
|
||||
|
||||
io.lcd_data_write_command_and_data(0x21, {}); // Display Inversion On
|
||||
|
||||
io.lcd_data_write_command_and_data(0x11, {}); // Sleep Out
|
||||
chThdSleepMilliseconds(120); // Delay 120ms
|
||||
|
||||
io.lcd_data_write_command_and_data(0x29, {}); // Display On
|
||||
chThdSleepMilliseconds(50); // Delay 50ms
|
||||
|
||||
// Turn on Tearing Effect Line (TE) output signal.
|
||||
io.lcd_data_write_command_and_data(0x35, {0b00000000});
|
||||
}
|
||||
|
||||
void lcd_init_pp() {
|
||||
// LCDs are configured for IM[2:0] = 001
|
||||
// 8080-I system, 16-bit parallel bus
|
||||
|
||||
//
|
||||
// 0x3a: DBI[2:0] = 101
|
||||
// MDT[1:0] = XX (if not in 18-bit mode, right?)
|
||||
@@ -281,6 +331,16 @@ void lcd_vertical_scrolling_start_address(
|
||||
|
||||
} // namespace
|
||||
|
||||
uint32_t ILI9341::lcd_read_display_id() {
|
||||
io.lcd_data_write_command_and_data(0x04, {});
|
||||
io.lcd_read_data_raw();
|
||||
|
||||
uint32_t value3 = io.lcd_read_data_raw();
|
||||
uint32_t value4 = io.lcd_read_data_raw();
|
||||
uint32_t value5 = io.lcd_read_data_raw();
|
||||
return value5 + (value4 << 8) + (value3 << 16);
|
||||
}
|
||||
|
||||
bool ILI9341::read_display_status() {
|
||||
lcd_reset();
|
||||
uint32_t display_status = lcd_read_display_status();
|
||||
@@ -302,7 +362,32 @@ bool ILI9341::read_display_status() {
|
||||
|
||||
void ILI9341::init() {
|
||||
lcd_reset();
|
||||
lcd_init();
|
||||
bool hpp = false;
|
||||
// detect method 1
|
||||
uint32_t id = lcd_read_display_id();
|
||||
if (id == 5537894) hpp = true;
|
||||
|
||||
// detect method 2 - not working!
|
||||
if (!hpp) {
|
||||
draw_pixel({318, 478}, ui::Color::red());
|
||||
fill_rectangle_unrolled8({0, 0, 240, 320}, ui::Color::black());
|
||||
std::vector<ui::ColorRGB888> checker(1);
|
||||
read_pixels({318, 478, 1, 1}, checker.data(), 1);
|
||||
if (checker[0].b <= 10 && checker[0].g <= 10 && checker[0].r >= 100)
|
||||
hpp = true;
|
||||
}
|
||||
// init screen
|
||||
if (hpp) {
|
||||
device_type = DEV_PORTARF;
|
||||
lcd_init();
|
||||
screen_width = 320;
|
||||
screen_height = 480;
|
||||
} else {
|
||||
device_type = DEV_PORTAPACK;
|
||||
lcd_init_pp();
|
||||
screen_width = 240;
|
||||
screen_height = 320;
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::shutdown() {
|
||||
@@ -335,7 +420,7 @@ void ILI9341::fill_rectangle_unrolled8(ui::Rect r, const ui::Color c) {
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::render_line(const ui::Point p, const uint8_t count, const ui::Color* line_buffer) {
|
||||
void ILI9341::render_line(const ui::Point p, const uint16_t count, const ui::Color* line_buffer) {
|
||||
lcd_start_ram_write(p, {count, 1});
|
||||
io.lcd_write_pixels(line_buffer, count);
|
||||
}
|
||||
@@ -473,8 +558,8 @@ bool ILI9341::draw_bmp_from_sdcard_file(const ui::Point p, const std::filesystem
|
||||
bmp_header_t bmp_header;
|
||||
uint8_t type = 0;
|
||||
char buffer[257];
|
||||
ui::Color line_buffer[240];
|
||||
|
||||
ui::Color line_buffer[320];
|
||||
int16_t start_x = p.x();
|
||||
auto result = bmpimage.open(file);
|
||||
if (result.is_valid())
|
||||
return false;
|
||||
@@ -508,8 +593,8 @@ bool ILI9341::draw_bmp_from_sdcard_file(const ui::Point p, const std::filesystem
|
||||
|
||||
width = bmp_header.width;
|
||||
height = bmp_header.height;
|
||||
|
||||
if (width != 240)
|
||||
start_x = (screen_width - start_x - width) / 2 + start_x; // center horizontally
|
||||
if (width > screen_width || width > 320)
|
||||
return false;
|
||||
|
||||
file_pos = bmp_header.image_data;
|
||||
@@ -560,7 +645,7 @@ bool ILI9341::draw_bmp_from_sdcard_file(const ui::Point p, const std::filesystem
|
||||
if (read_size.value() != 256)
|
||||
break;
|
||||
}
|
||||
render_line({p.x(), p.y() + py}, px, line_buffer);
|
||||
render_line({start_x, p.y() + py}, px, line_buffer);
|
||||
px = 0;
|
||||
py--;
|
||||
|
||||
@@ -668,7 +753,7 @@ void ILI9341::draw_bitmap(
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const auto pixel = pixels[i >> 3] & (1U << (i & 0x7));
|
||||
if (pixel) {
|
||||
draw_pixel(ui::Point(x, y), foreground);
|
||||
if (x <= screen_width && y <= screen_height) draw_pixel(ui::Point(x, y), foreground);
|
||||
}
|
||||
// move to next px
|
||||
x++;
|
||||
@@ -740,8 +825,12 @@ ui::Coord ILI9341::scroll_area_y(const ui::Coord y) const {
|
||||
}
|
||||
|
||||
void ILI9341::scroll_disable() {
|
||||
lcd_vertical_scrolling_definition(0, height(), 0);
|
||||
lcd_vertical_scrolling_start_address(0);
|
||||
if (device_type == DEV_PORTAPACK) {
|
||||
lcd_vertical_scrolling_definition(0, height(), 0);
|
||||
lcd_vertical_scrolling_start_address(0);
|
||||
} else {
|
||||
io.lcd_data_write_command_and_data(0x13, {}); // normal mode
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace lcd */
|
||||
|
||||
@@ -43,6 +43,7 @@ class ILI9341 {
|
||||
void operator=(const ILI9341&) = delete;
|
||||
|
||||
bool read_display_status();
|
||||
uint32_t lcd_read_display_id();
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
@@ -62,7 +63,7 @@ class ILI9341 {
|
||||
void draw_pixel(const ui::Point p, const ui::Color color);
|
||||
void draw_bmp_from_bmp_hex_arr(const ui::Point p, const uint8_t* bitmap, const uint8_t* transparency_color);
|
||||
bool draw_bmp_from_sdcard_file(const ui::Point p, const std::filesystem::path& file);
|
||||
void render_line(const ui::Point p, const uint8_t count, const ui::Color* line_buffer);
|
||||
void render_line(const ui::Point p, const uint16_t count, const ui::Color* line_buffer);
|
||||
void render_box(const ui::Point p, const ui::Size s, const ui::Color* line_buffer);
|
||||
|
||||
template <size_t N>
|
||||
@@ -163,7 +164,6 @@ class ILI9341 {
|
||||
ui::Dim height;
|
||||
ui::Coord current_position;
|
||||
};
|
||||
|
||||
scroll_t scroll_state;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,42 @@ using namespace lpc43xx;
|
||||
|
||||
namespace portapack {
|
||||
|
||||
DeviceType device_type = DEV_PORTAPACK;
|
||||
|
||||
void IO::lcd_read_bytes(uint8_t* byte, size_t byte_count) {
|
||||
if (portapack::device_type == portapack::DeviceType::DEV_PORTAPACK) {
|
||||
size_t word_count = byte_count / 2;
|
||||
while (word_count) {
|
||||
const auto word = lcd_read_data();
|
||||
*(byte++) = word >> 8;
|
||||
*(byte++) = word >> 0;
|
||||
word_count--;
|
||||
}
|
||||
if (byte_count & 1) {
|
||||
const auto word = lcd_read_data();
|
||||
*(byte++) = word >> 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// prf
|
||||
//--dummy read:
|
||||
dir_read();
|
||||
lcd_rd_assert();
|
||||
halPolledDelay(71);
|
||||
data_read();
|
||||
lcd_rd_deassert();
|
||||
size_t word_count = byte_count / 3;
|
||||
for (size_t i = 0; i < word_count; i++) {
|
||||
uint32_t word = lcd_read_data(); // reads 3 byte of data
|
||||
uint8_t r = ((word >> 16) & 0xff);
|
||||
uint8_t g = ((word >> 8) & 0xff);
|
||||
uint8_t b = ((word >> 0) & 0xff);
|
||||
*(byte++) = r;
|
||||
*(byte++) = g << 2;
|
||||
*(byte++) = b;
|
||||
}
|
||||
}
|
||||
|
||||
void IO::init() {
|
||||
data_mask_set();
|
||||
data_write_high(0);
|
||||
|
||||
@@ -52,6 +52,12 @@ static const uint16_t darken_mask[4] = {
|
||||
|
||||
namespace portapack {
|
||||
|
||||
enum DeviceType {
|
||||
DEV_PORTAPACK,
|
||||
DEV_PORTARF
|
||||
};
|
||||
extern DeviceType device_type;
|
||||
|
||||
class IO {
|
||||
public:
|
||||
enum class TouchPinsConfig : uint8_t {
|
||||
@@ -140,12 +146,43 @@ class IO {
|
||||
lcd_write_data(d);
|
||||
}
|
||||
}
|
||||
uint32_t lcd_read_data_raw() {
|
||||
// NOTE: Assumes ADDR=1 from command phase.
|
||||
dir_read();
|
||||
|
||||
/* Start read operation */
|
||||
lcd_rd_assert();
|
||||
/* Wait for passthrough data(15:8) to settle -- ~16ns (3 cycles) typical */
|
||||
/* Wait for read control L duration (355ns) */
|
||||
halPolledDelay(71); // 355ns
|
||||
const auto value_high = data_read();
|
||||
|
||||
/* Latch data[7:0] */
|
||||
lcd_rd_deassert();
|
||||
/* Wait for latched data[7:0] to settle -- ~26ns (5 cycles) typical */
|
||||
/* Wait for read control H duration (90ns) */
|
||||
halPolledDelay(18); // 90ns
|
||||
|
||||
const auto value_low = data_read();
|
||||
uint32_t original_value = (value_high << 8) | value_low;
|
||||
|
||||
return original_value;
|
||||
}
|
||||
|
||||
void lcd_data_read_command_and_data(
|
||||
const uint_fast8_t command,
|
||||
uint16_t* const data,
|
||||
const size_t data_count) {
|
||||
lcd_command(command);
|
||||
if (device_type == DEV_PORTARF) {
|
||||
// dummy read
|
||||
dir_read();
|
||||
lcd_rd_assert();
|
||||
halPolledDelay(71);
|
||||
data_read();
|
||||
lcd_rd_deassert();
|
||||
halPolledDelay(71);
|
||||
}
|
||||
for (size_t i = 0; i < data_count; i++) {
|
||||
data[i] = lcd_read_data();
|
||||
}
|
||||
@@ -205,19 +242,7 @@ class IO {
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_read_bytes(uint8_t* byte, size_t byte_count) {
|
||||
size_t word_count = byte_count / 2;
|
||||
while (word_count) {
|
||||
const auto word = lcd_read_data();
|
||||
*(byte++) = word >> 8;
|
||||
*(byte++) = word >> 0;
|
||||
word_count--;
|
||||
}
|
||||
if (byte_count & 1) {
|
||||
const auto word = lcd_read_data();
|
||||
*(byte++) = word >> 8;
|
||||
}
|
||||
}
|
||||
void lcd_read_bytes(uint8_t* byte, size_t byte_count);
|
||||
|
||||
uint32_t io_read() {
|
||||
io_stb_assert();
|
||||
@@ -400,32 +425,40 @@ class IO {
|
||||
}
|
||||
|
||||
uint32_t lcd_read_data() {
|
||||
// NOTE: Assumes ADDR=1 from command phase.
|
||||
dir_read();
|
||||
|
||||
/* Start read operation */
|
||||
lcd_rd_assert();
|
||||
/* Wait for passthrough data(15:8) to settle -- ~16ns (3 cycles) typical */
|
||||
/* Wait for read control L duration (355ns) */
|
||||
halPolledDelay(71); // 355ns
|
||||
const auto value_high = data_read();
|
||||
if (portapack::device_type == portapack::DeviceType::DEV_PORTAPACK) {
|
||||
const auto value_high = data_read();
|
||||
/* Latch data[7:0] */
|
||||
lcd_rd_deassert();
|
||||
/* Wait for latched data[7:0] to settle -- ~26ns (5 cycles) typical */
|
||||
/* Wait for read control H duration (90ns) */
|
||||
halPolledDelay(71); // 90ns
|
||||
const auto value_low = data_read();
|
||||
uint32_t original_value = (value_high << 8) | value_low;
|
||||
|
||||
if (lcd_normally_black) return original_value;
|
||||
|
||||
if (dark_cover_enabled) {
|
||||
// this is read data, so if the fake brightness is enabled AKA get_dark_cover() == true,
|
||||
// then shift to back side AKA UNDARKENED_PIXEL, to prevent read shifted darkern info
|
||||
original_value = UNDARKENED_PIXEL(original_value, brightness);
|
||||
}
|
||||
return original_value;
|
||||
}
|
||||
const auto value_high = data_read();
|
||||
/* Latch data[7:0] */
|
||||
lcd_rd_deassert();
|
||||
/* Wait for latched data[7:0] to settle -- ~26ns (5 cycles) typical */
|
||||
/* Wait for read control H duration (90ns) */
|
||||
halPolledDelay(18); // 90ns
|
||||
|
||||
halPolledDelay(71);
|
||||
const auto value_low = data_read();
|
||||
uint32_t original_value = (value_high << 8) | value_low;
|
||||
|
||||
if (lcd_normally_black) return original_value;
|
||||
|
||||
if (dark_cover_enabled) {
|
||||
// this is read data, so if the fake brightness is enabled AKA get_dark_cover() == true,
|
||||
// then shift to back side AKA UNDARKENED_PIXEL, to prevent read shifted darkern info
|
||||
original_value = UNDARKENED_PIXEL(original_value, brightness);
|
||||
}
|
||||
lcd_rd_deassert();
|
||||
halPolledDelay(71);
|
||||
const auto value_last_low = data_read();
|
||||
uint32_t original_value = (value_high << 16) | value_low << 8 | value_last_low;
|
||||
return original_value;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace ui {
|
||||
#define UI_POS_X_RIGHT(charnum) ((int)(screen_width - ((charnum)*UI_POS_DEFAULT_WIDTH)))
|
||||
// px position of the left character from the center of the screen (X) (for N character wide string)
|
||||
#define UI_POS_X_CENTER(charnum) ((int)((screen_width / 2) - ((charnum)*UI_POS_DEFAULT_WIDTH / 2)))
|
||||
// px position of the currcol in a table with colnum number of columns, where one coloumn is charnum characters wide maximum
|
||||
#define UI_POS_X_TABLE(colnum, currcol) ((currcol) * (screen_width / (colnum)))
|
||||
// px width of N characters
|
||||
#define UI_POS_WIDTH(charnum) ((int)((charnum)*UI_POS_DEFAULT_WIDTH))
|
||||
// px width of the screen
|
||||
@@ -57,6 +59,8 @@ namespace ui {
|
||||
#define UI_POS_HEIGHT_REMAINING(linenum) ((int)(screen_height - ((linenum)*UI_POS_DEFAULT_HEIGHT)))
|
||||
// remaining px from the charnum-th character to the right of the screen
|
||||
#define UI_POS_WIDTH_REMAINING(charnum) ((int)(screen_width - ((charnum)*UI_POS_DEFAULT_WIDTH)))
|
||||
// px width of the screen's percent
|
||||
#define UI_POS_WIDTH_PERCENT(percent) ((int)(screen_width * (percent) / 100))
|
||||
// px width of the screen
|
||||
#define UI_POS_MAXHEIGHT (screen_height)
|
||||
|
||||
|
||||
@@ -534,7 +534,7 @@ void BigFrequency::paint(Painter& painter) {
|
||||
_previous_frequency = _frequency;
|
||||
|
||||
rf::Frequency frequency{_frequency};
|
||||
const auto rect = screen_rect();
|
||||
const auto rect = screen_rect(); // why not use screen_rect() directly for width, ...? it may be too small, but ...
|
||||
|
||||
// Erase
|
||||
painter.fill_rectangle(
|
||||
@@ -544,7 +544,7 @@ void BigFrequency::paint(Painter& painter) {
|
||||
// Prepare digits
|
||||
if (!frequency) {
|
||||
digits.fill(10); // ----.---
|
||||
digit_pos = {0, rect.location().y()};
|
||||
digit_pos = {(screen_width - ((7 * digit_width) + 8)) / 2, rect.location().y()};
|
||||
} else {
|
||||
frequency /= 1000; // GMMM.KKK(uuu)
|
||||
|
||||
@@ -561,7 +561,7 @@ void BigFrequency::paint(Painter& painter) {
|
||||
break;
|
||||
}
|
||||
|
||||
digit_pos = {(Coord)(240 - ((7 * digit_width) + 8) - (i * digit_width)) / 2, rect.location().y()};
|
||||
digit_pos = {(Coord)(screen_width - ((7 * digit_width) + 8) - (i * digit_width)) / 2, rect.location().y()};
|
||||
}
|
||||
|
||||
segment_color = style().foreground;
|
||||
@@ -1334,24 +1334,57 @@ void NewButton::paint(Painter& painter) {
|
||||
style.background);
|
||||
|
||||
int y = r.top();
|
||||
if (bitmap_) {
|
||||
int offset_y = vertical_center_ ? (r.height() / 2) - (bitmap_->size.height() / 2) : 6;
|
||||
Point bmp_pos = {r.left() + (r.width() / 2) - (bitmap_->size.width() / 2), r.top() + offset_y};
|
||||
y += bitmap_->size.height() - offset_y;
|
||||
if (vertical_center_) {
|
||||
const int bmp_h = bitmap_ ? bitmap_->size.height() : 0;
|
||||
const int txt_h = !text_.empty() ? style.font.line_height() : 0;
|
||||
int spacing = 0;
|
||||
if (bmp_h > 0 && txt_h > 0) {
|
||||
const int content_height = bmp_h + txt_h;
|
||||
const int remaining_space = r.height() - content_height;
|
||||
spacing = std::max(4, remaining_space / 3);
|
||||
}
|
||||
const int total_height = bmp_h + txt_h + spacing;
|
||||
y += (r.height() - total_height) / 2;
|
||||
|
||||
painter.draw_bitmap(
|
||||
bmp_pos,
|
||||
*bitmap_,
|
||||
color_,
|
||||
style.background);
|
||||
}
|
||||
if (bitmap_) {
|
||||
Point bmp_pos = {r.left() + (r.width() / 2) - (bitmap_->size.width() / 2), y};
|
||||
y += bitmap_->size.height();
|
||||
|
||||
if (!text_.empty()) {
|
||||
const auto label_r = style.font.size_of(text_);
|
||||
painter.draw_string(
|
||||
{r.left() + (r.width() - label_r.width()) / 2, y + (r.height() - label_r.height()) / 2},
|
||||
style,
|
||||
text_);
|
||||
painter.draw_bitmap(
|
||||
bmp_pos,
|
||||
*bitmap_,
|
||||
color_,
|
||||
style.background);
|
||||
}
|
||||
|
||||
if (!text_.empty()) {
|
||||
const auto label_r = style.font.size_of(text_);
|
||||
if (bitmap_) {
|
||||
y += spacing;
|
||||
}
|
||||
painter.draw_string(
|
||||
{r.left() + (r.width() - label_r.width()) / 2, y},
|
||||
style,
|
||||
text_);
|
||||
}
|
||||
} else { // no valign
|
||||
if (bitmap_) {
|
||||
Point bmp_pos = {r.left() + (r.width() / 2) - (bitmap_->size.width() / 2), r.top() + 6};
|
||||
y += bitmap_->size.height() - 6;
|
||||
painter.draw_bitmap(
|
||||
bmp_pos,
|
||||
*bitmap_,
|
||||
color_,
|
||||
style.background);
|
||||
}
|
||||
|
||||
if (!text_.empty()) {
|
||||
const auto label_r = style.font.size_of(text_);
|
||||
painter.draw_string(
|
||||
{r.left() + (r.width() - label_r.width()) / 2, y + (r.height() - label_r.height()) / 2},
|
||||
style,
|
||||
text_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2722,6 +2755,13 @@ bool Waveform::on_touch(const TouchEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
void Waveform::set_data(int16_t* new_data) {
|
||||
if (new_data != data_) {
|
||||
data_ = new_data;
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
void Waveform::paint(Painter& painter) {
|
||||
// previously it's upside down , low level is up and high level is down, which doesn't make sense,
|
||||
// if that was made for a reason, feel free to revert.
|
||||
|
||||
@@ -989,7 +989,7 @@ class Waveform : public Widget {
|
||||
void set_offset(const uint32_t new_offset);
|
||||
void set_length(const uint32_t new_length);
|
||||
void set_cursor(const uint32_t i, const int16_t position);
|
||||
|
||||
void set_data(int16_t* new_data);
|
||||
bool is_paused() const;
|
||||
void set_paused(bool paused);
|
||||
bool is_clickable() const;
|
||||
@@ -1110,7 +1110,7 @@ class OptionTabView : public View {
|
||||
|
||||
private:
|
||||
Checkbox check_enable{
|
||||
{2 * 8, 0 * 16},
|
||||
{2 * 8, UI_POS_Y(0)},
|
||||
20,
|
||||
"",
|
||||
false};
|
||||
|
||||
@@ -127,9 +127,11 @@ struct is_flags_type {
|
||||
template <typename TEnum>
|
||||
constexpr bool is_flags_type_v = is_flags_type<TEnum>::value;
|
||||
|
||||
#define ENABLE_FLAGS_OPERATORS(type) \
|
||||
template <> \
|
||||
struct is_flags_type<type> { static constexpr bool value = true; };
|
||||
#define ENABLE_FLAGS_OPERATORS(type) \
|
||||
template <> \
|
||||
struct is_flags_type<type> { \
|
||||
static constexpr bool value = true; \
|
||||
};
|
||||
|
||||
template <typename TEnum>
|
||||
constexpr std::enable_if_t<is_flags_type_v<TEnum>, TEnum> operator|(TEnum a, TEnum b) {
|
||||
|
||||
Reference in New Issue
Block a user