[2.0.x] Buffer overflow and scroll fix, UTF8 cleanup (#10844)
This commit is contained in:
parent
235facd545
commit
6f330f397e
|
@ -162,22 +162,15 @@ void spiBegin (void) {
|
||||||
// away. When clock is not known, use a loop instead, which generates
|
// away. When clock is not known, use a loop instead, which generates
|
||||||
// shorter code.
|
// shorter code.
|
||||||
if (__builtin_constant_p(spiClock)) {
|
if (__builtin_constant_p(spiClock)) {
|
||||||
if (spiClock >= F_CPU / 2) {
|
if (spiClock >= F_CPU / 2) clockDiv = 0;
|
||||||
clockDiv = 0;
|
else if (spiClock >= F_CPU / 4) clockDiv = 1;
|
||||||
} else if (spiClock >= F_CPU / 4) {
|
else if (spiClock >= F_CPU / 8) clockDiv = 2;
|
||||||
clockDiv = 1;
|
else if (spiClock >= F_CPU / 16) clockDiv = 3;
|
||||||
} else if (spiClock >= F_CPU / 8) {
|
else if (spiClock >= F_CPU / 32) clockDiv = 4;
|
||||||
clockDiv = 2;
|
else if (spiClock >= F_CPU / 64) clockDiv = 5;
|
||||||
} else if (spiClock >= F_CPU / 16) {
|
else clockDiv = 6;
|
||||||
clockDiv = 3;
|
}
|
||||||
} else if (spiClock >= F_CPU / 32) {
|
else {
|
||||||
clockDiv = 4;
|
|
||||||
} else if (spiClock >= F_CPU / 64) {
|
|
||||||
clockDiv = 5;
|
|
||||||
} else {
|
|
||||||
clockDiv = 6;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uint32_t clockSetting = F_CPU / 2;
|
uint32_t clockSetting = F_CPU / 2;
|
||||||
clockDiv = 0;
|
clockDiv = 0;
|
||||||
while (clockDiv < 6 && spiClock < clockSetting) {
|
while (clockDiv < 6 && spiClock < clockSetting) {
|
||||||
|
@ -187,8 +180,7 @@ void spiBegin (void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compensate for the duplicate fosc/64
|
// Compensate for the duplicate fosc/64
|
||||||
if (clockDiv == 6)
|
if (clockDiv == 6) clockDiv = 7;
|
||||||
clockDiv = 7;
|
|
||||||
|
|
||||||
// Invert the SPI2X bit
|
// Invert the SPI2X bit
|
||||||
clockDiv ^= 0x1;
|
clockDiv ^= 0x1;
|
||||||
|
|
|
@ -56,7 +56,6 @@ extern uint8_t ubl_cnt;
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if ENABLED(ULTRA_LCD)
|
#if ENABLED(ULTRA_LCD)
|
||||||
extern char lcd_status_message[];
|
|
||||||
void lcd_quick_feedback(const bool clear_buttons);
|
void lcd_quick_feedback(const bool clear_buttons);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -135,10 +135,6 @@
|
||||||
|
|
||||||
// External references
|
// External references
|
||||||
|
|
||||||
#if ENABLED(ULTRA_LCD)
|
|
||||||
extern char lcd_status_message[];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Private functions
|
// Private functions
|
||||||
|
|
||||||
static uint16_t circle_flags[16], horizontal_mesh_line_flags[16], vertical_mesh_line_flags[16];
|
static uint16_t circle_flags[16], horizontal_mesh_line_flags[16], vertical_mesh_line_flags[16];
|
||||||
|
@ -508,8 +504,6 @@ inline bool prime_nozzle() {
|
||||||
|
|
||||||
wait_for_release();
|
wait_for_release();
|
||||||
|
|
||||||
strcpy_P(lcd_status_message, PSTR("Done Priming")); // Hack to get the message up. May be obsolete.
|
|
||||||
|
|
||||||
lcd_setstatusPGM(PSTR("Done Priming"), 99);
|
lcd_setstatusPGM(PSTR("Done Priming"), 99);
|
||||||
lcd_quick_feedback(true);
|
lcd_quick_feedback(true);
|
||||||
lcd_external_control = false;
|
lcd_external_control = false;
|
||||||
|
|
|
@ -519,15 +519,12 @@ void GcodeSuite::G33() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report settings
|
// Report settings
|
||||||
|
const char* checkingac = PSTR("Checking... AC");
|
||||||
const char *checkingac = PSTR("Checking... AC");
|
|
||||||
serialprintPGM(checkingac);
|
serialprintPGM(checkingac);
|
||||||
if (verbose_level == 0) SERIAL_PROTOCOLPGM(" (DRY-RUN)");
|
if (verbose_level == 0) SERIAL_PROTOCOLPGM(" (DRY-RUN)");
|
||||||
if (set_up) SERIAL_PROTOCOLPGM(" (SET-UP)");
|
if (set_up) SERIAL_PROTOCOLPGM(" (SET-UP)");
|
||||||
SERIAL_EOL();
|
SERIAL_EOL();
|
||||||
char mess[11];
|
lcd_setstatusPGM(checkingac);
|
||||||
strcpy_P(mess, checkingac);
|
|
||||||
lcd_setstatus(mess);
|
|
||||||
|
|
||||||
print_calibration_settings(_endstop_results, _angle_results);
|
print_calibration_settings(_endstop_results, _angle_results);
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ FORCE_INLINE void _draw_centered_temp(const int16_t temp, const uint8_t x, const
|
||||||
const char * const str = itostr3(temp);
|
const char * const str = itostr3(temp);
|
||||||
lcd_moveto(x - (str[0] != ' ' ? 0 : str[1] != ' ' ? 1 : 2) * DOG_CHAR_WIDTH / 2, y);
|
lcd_moveto(x - (str[0] != ' ' ? 0 : str[1] != ' ' ? 1 : 2) * DOG_CHAR_WIDTH / 2, y);
|
||||||
lcd_put_u8str(str);
|
lcd_put_u8str(str);
|
||||||
lcd_put_u8str_rom(PSTR(LCD_STR_DEGREE " "));
|
lcd_put_u8str_P(PSTR(LCD_STR_DEGREE " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HEAT_INDICATOR_X
|
#ifndef HEAT_INDICATOR_X
|
||||||
|
@ -113,7 +113,7 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
|
||||||
else {
|
else {
|
||||||
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
||||||
if (!axis_known_position[axis])
|
if (!axis_known_position[axis])
|
||||||
lcd_put_u8str_rom(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
lcd_put_u8str_P(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
lcd_put_u8str(value);
|
lcd_put_u8str(value);
|
||||||
|
@ -124,36 +124,77 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
|
||||||
inline void lcd_implementation_status_message(const bool blink) {
|
inline void lcd_implementation_status_message(const bool blink) {
|
||||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||||
static bool last_blink = false;
|
static bool last_blink = false;
|
||||||
const uint8_t slen = utf8_strlen(lcd_status_message);
|
|
||||||
const char *stat = lcd_status_message + status_scroll_pos;
|
// Get the UTF8 character count of the string
|
||||||
if (slen <= LCD_WIDTH)
|
uint8_t slen = utf8_strlen(lcd_status_message);
|
||||||
lcd_put_u8str(stat); // The string isn't scrolling
|
|
||||||
|
// If the string fits into the LCD, just print it and do not scroll it
|
||||||
|
if (slen <= LCD_WIDTH) {
|
||||||
|
|
||||||
|
// The string isn't scrolling and may not fill the screen
|
||||||
|
lcd_put_u8str(lcd_status_message);
|
||||||
|
|
||||||
|
// Fill the rest with spaces
|
||||||
|
while (slen < LCD_WIDTH) {
|
||||||
|
lcd_put_wchar(' ');
|
||||||
|
++slen;
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (status_scroll_pos <= slen - LCD_WIDTH)
|
// String is larger than the available space in screen.
|
||||||
lcd_put_u8str(stat); // The string fills the screen
|
|
||||||
|
// Get a pointer to the next valid UTF8 character
|
||||||
|
const char *stat = lcd_status_message + status_scroll_offset;
|
||||||
|
|
||||||
|
// Get the string remaining length
|
||||||
|
const uint8_t rlen = utf8_strlen(stat);
|
||||||
|
|
||||||
|
// If we have enough characters to display
|
||||||
|
if (rlen >= LCD_WIDTH) {
|
||||||
|
// The remaining string fills the screen - Print it
|
||||||
|
lcd_put_u8str_max(stat, LCD_PIXEL_WIDTH);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
uint8_t chars = LCD_WIDTH;
|
// The remaining string does not completely fill the screen
|
||||||
if (status_scroll_pos < slen) { // First string still visible
|
lcd_put_u8str_max(stat, LCD_PIXEL_WIDTH); // The string leaves space
|
||||||
lcd_put_u8str(stat); // The string leaves space
|
uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters
|
||||||
chars -= slen - status_scroll_pos; // Amount of space left
|
|
||||||
}
|
lcd_put_wchar('.'); // Always at 1+ spaces left, draw a dot
|
||||||
lcd_put_wchar('.'); // Always at 1+ spaces left, draw a dot
|
if (--chars) { // Draw a second dot if there's space
|
||||||
if (--chars) {
|
lcd_put_wchar('.');
|
||||||
if (status_scroll_pos < slen + 1) // Draw a second dot if there's space
|
if (--chars) {
|
||||||
--chars, lcd_put_wchar('.');
|
// Print a second copy of the message
|
||||||
if (chars) lcd_put_u8str_max(lcd_status_message, chars); // Print a second copy of the message
|
lcd_put_u8str_max(lcd_status_message, LCD_PIXEL_WIDTH - ((rlen+2) * DOG_CHAR_WIDTH));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (last_blink != blink) {
|
if (last_blink != blink) {
|
||||||
last_blink = blink;
|
last_blink = blink;
|
||||||
// Skip any non-printing bytes
|
|
||||||
if (status_scroll_pos < slen) while (!PRINTABLE(lcd_status_message[status_scroll_pos])) status_scroll_pos++;
|
// Adjust by complete UTF8 characters
|
||||||
if (++status_scroll_pos >= slen + 2) status_scroll_pos = 0;
|
if (status_scroll_offset < slen) {
|
||||||
|
status_scroll_offset++;
|
||||||
|
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
|
||||||
|
status_scroll_offset++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
status_scroll_offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
UNUSED(blink);
|
UNUSED(blink);
|
||||||
lcd_put_u8str(lcd_status_message);
|
|
||||||
|
// Get the UTF8 character count of the string
|
||||||
|
uint8_t slen = utf8_strlen(lcd_status_message);
|
||||||
|
|
||||||
|
// Just print the string to the LCD
|
||||||
|
lcd_put_u8str_max(lcd_status_message, LCD_PIXEL_WIDTH);
|
||||||
|
|
||||||
|
// Fill the rest with spaces if there are missing spaces
|
||||||
|
while (slen < LCD_WIDTH) {
|
||||||
|
lcd_put_wchar(' ');
|
||||||
|
++slen;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +458,7 @@ static void lcd_implementation_status_screen() {
|
||||||
lcd_put_wchar('%');
|
lcd_put_wchar('%');
|
||||||
lcd_setFont(FONT_MENU);
|
lcd_setFont(FONT_MENU);
|
||||||
lcd_moveto(47, 50);
|
lcd_moveto(47, 50);
|
||||||
lcd_put_wchar(LCD_STR_FILAM_DIA[0]); // lcd_put_u8str_rom(PSTR(LCD_STR_FILAM_DIA));
|
lcd_put_wchar(LCD_STR_FILAM_DIA[0]); // lcd_put_u8str_P(PSTR(LCD_STR_FILAM_DIA));
|
||||||
lcd_moveto(93, 50);
|
lcd_moveto(93, 50);
|
||||||
lcd_put_wchar(LCD_STR_FILAM_MUL[0]);
|
lcd_put_wchar(LCD_STR_FILAM_MUL[0]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -437,10 +478,10 @@ static void lcd_implementation_status_screen() {
|
||||||
lcd_implementation_status_message(blink);
|
lcd_implementation_status_message(blink);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lcd_put_u8str_rom(PSTR(LCD_STR_FILAM_DIA));
|
lcd_put_u8str_P(PSTR(LCD_STR_FILAM_DIA));
|
||||||
lcd_put_wchar(':');
|
lcd_put_wchar(':');
|
||||||
lcd_put_u8str(wstring);
|
lcd_put_u8str(wstring);
|
||||||
lcd_put_u8str_rom(PSTR(" " LCD_STR_FILAM_MUL));
|
lcd_put_u8str_P(PSTR(" " LCD_STR_FILAM_MUL));
|
||||||
lcd_put_wchar(':');
|
lcd_put_wchar(':');
|
||||||
lcd_put_u8str(mstring);
|
lcd_put_u8str(mstring);
|
||||||
lcd_put_wchar('%');
|
lcd_put_wchar('%');
|
||||||
|
|
|
@ -615,36 +615,71 @@ void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint8_t percentag
|
||||||
void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
|
void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
|
||||||
set_ddram_address(DDRAM_LINE_4);
|
set_ddram_address(DDRAM_LINE_4);
|
||||||
begin_data();
|
begin_data();
|
||||||
|
const uint8_t lcd_len = 16;
|
||||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||||
const uint8_t lcd_len = 16;
|
|
||||||
const uint8_t padding = 2;
|
|
||||||
uint8_t str_len = strlen(str);
|
|
||||||
|
|
||||||
// Trim whitespace at the end of the str, as for some reason
|
uint8_t slen = utf8_strlen(str);
|
||||||
// messages like "Card Inserted" are padded with many spaces
|
|
||||||
while (str_len && str[str_len - 1] == ' ') str_len--;
|
|
||||||
|
|
||||||
if (str_len <= lcd_len) {
|
// If the string fits into the LCD, just print it and do not scroll it
|
||||||
// It all fits on the LCD without scrolling
|
if (slen <= lcd_len) {
|
||||||
|
|
||||||
|
// The string isn't scrolling and may not fill the screen
|
||||||
write_str(str);
|
write_str(str);
|
||||||
|
|
||||||
|
// Fill the rest with spaces
|
||||||
|
while (slen < lcd_len) {
|
||||||
|
write_byte(' ');
|
||||||
|
++slen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Print the message repeatedly until covering the LCD
|
// String is larger than the available space in screen.
|
||||||
uint8_t c = status_scroll_pos;
|
|
||||||
for (uint8_t n = 0; n < lcd_len; n++) {
|
// Get a pointer to the next valid UTF8 character
|
||||||
write_byte(c < str_len ? str[c] : ' ');
|
const char *stat = str + status_scroll_offset;
|
||||||
c++;
|
|
||||||
c %= str_len + padding; // Wrap around
|
// Get the string remaining length
|
||||||
|
const uint8_t rlen = utf8_strlen(stat);
|
||||||
|
|
||||||
|
// If we have enough characters to display
|
||||||
|
if (rlen >= lcd_len) {
|
||||||
|
// The remaining string fills the screen - Print it
|
||||||
|
write_str(stat, lcd_len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The remaining string does not completely fill the screen
|
||||||
|
write_str(stat); // The string leaves space
|
||||||
|
uint8_t chars = lcd_len - rlen; // Amount of space left in characters
|
||||||
|
|
||||||
|
write_byte('.'); // Always at 1+ spaces left, draw a dot
|
||||||
|
if (--chars) { // Draw a second dot if there's space
|
||||||
|
write_byte('.');
|
||||||
|
if (--chars)
|
||||||
|
write_str(str, chars); // Print a second copy of the message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll the message
|
// Adjust by complete UTF8 characters
|
||||||
if (status_scroll_pos == str_len + padding)
|
if (status_scroll_offset < slen) {
|
||||||
status_scroll_pos = 0;
|
status_scroll_offset++;
|
||||||
|
while (!START_OF_UTF8_CHAR(str[status_scroll_offset]))
|
||||||
|
status_scroll_offset++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
status_scroll_pos++;
|
status_scroll_offset = 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
write_str(str, 16);
|
// Get the UTF8 character count of the string
|
||||||
|
uint8_t slen = utf8_strlen(str);
|
||||||
|
|
||||||
|
// Just print the string to the LCD
|
||||||
|
write_str(str, lcd_len);
|
||||||
|
|
||||||
|
// Fill the rest with spaces if there are missing spaces
|
||||||
|
while (slen < lcd_len) {
|
||||||
|
write_byte(' ');
|
||||||
|
++slen;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,7 +827,7 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
|
||||||
*/
|
*/
|
||||||
if (forceUpdate || status_changed()) {
|
if (forceUpdate || status_changed()) {
|
||||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||||
status_scroll_pos = 0;
|
status_scroll_offset = 0;
|
||||||
#endif
|
#endif
|
||||||
#if STATUS_EXPIRE_SECONDS
|
#if STATUS_EXPIRE_SECONDS
|
||||||
countdown = lcd_status_message[0] ? STATUS_EXPIRE_SECONDS : 0;
|
countdown = lcd_status_message[0] ? STATUS_EXPIRE_SECONDS : 0;
|
||||||
|
|
|
@ -16,56 +16,14 @@
|
||||||
|
|
||||||
#include "fontutils.h"
|
#include "fontutils.h"
|
||||||
|
|
||||||
uint8_t read_byte_ram(uint8_t * str) { return *str; }
|
uint8_t read_byte_ram(uint8_t * str) {
|
||||||
uint8_t read_byte_rom(uint8_t * str) { return pgm_read_byte(str); }
|
return *str;
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
uint8_t read_byte_rom(uint8_t * str) {
|
||||||
#ifdef ARDUINO
|
return pgm_read_byte(str);
|
||||||
#include <Arduino.h>
|
}
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
void serial_printf_P(const char *format, ...) {
|
|
||||||
static char buff[128];
|
|
||||||
va_list args;
|
|
||||||
va_start(args,format);
|
|
||||||
vsnprintf_P(buff,sizeof(buff),format,args);
|
|
||||||
va_end(args);
|
|
||||||
buff[sizeof(buff)/sizeof(buff[0])-1]='\0';
|
|
||||||
|
|
||||||
//Serial.print(buff);
|
|
||||||
SERIAL_ECHO(buff); SERIAL_EOL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __WIN32__ // or whatever
|
|
||||||
#define PRIiSZ "ld"
|
|
||||||
#define PRIuSZ "Iu"
|
|
||||||
#else
|
|
||||||
#define PRIiSZ "zd"
|
|
||||||
#define PRIuSZ "zu"
|
|
||||||
#endif
|
|
||||||
#define PRIiOFF "lld"
|
|
||||||
#define PRIuOFF "llu"
|
|
||||||
|
|
||||||
|
|
||||||
#define DBGMSG(a,b, ...) TRACE( #__VA_ARGS__ )
|
|
||||||
|
|
||||||
//typedef int (* pf_bsearch_cb_comp_t)(void *userdata, size_t idx, void * data_pin); /*"data_list[idx] - *data_pin"*/
|
|
||||||
/**
|
|
||||||
* @brief 折半方式查找记录
|
|
||||||
*
|
|
||||||
* @param userdata : 用户数据指针
|
|
||||||
* @param num_data : 数据个数
|
|
||||||
* @param cb_comp : 比较两个数据的回调函数
|
|
||||||
* @param data_pinpoint : 所要查找的 匹配数据指针
|
|
||||||
* @param ret_idx : 查找到的位置;如果没有找到,则返回如添加该记录时其所在的位置。
|
|
||||||
*
|
|
||||||
* @return 找到则返回0,否则返回<0
|
|
||||||
*
|
|
||||||
* 折半方式查找记录, psl->marr 中指向的数据已经以先小后大方式排好序
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* @brief Using binary search to find the position by data_pin
|
* @brief Using binary search to find the position by data_pin
|
||||||
*
|
*
|
||||||
|
@ -82,21 +40,11 @@ uint8_t read_byte_rom(uint8_t * str) { return pgm_read_byte(str); }
|
||||||
int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp, void *data_pinpoint, size_t *ret_idx) {
|
int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp, void *data_pinpoint, size_t *ret_idx) {
|
||||||
int retcomp;
|
int retcomp;
|
||||||
|
|
||||||
FU_ASSERT(NULL != ret_idx);
|
|
||||||
/* 查找合适的位置 */
|
|
||||||
if (num_data < 1) {
|
if (num_data < 1) {
|
||||||
*ret_idx = 0;
|
*ret_idx = 0;
|
||||||
DBGMSG (PFDBG_CATLOG_PF, PFDBG_LEVEL_ERROR, "num_data(%" PRIuSZ ") < 1", num_data);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 折半查找 */
|
|
||||||
/* 为了不出现负数,以免缩小索引的所表示的数据范围
|
|
||||||
* (负数表明减少一位二进制位的使用),
|
|
||||||
* 内部 ileft 和 iright使用从1开始的下标,
|
|
||||||
* 即1表示C语言中的0, 2表示语言中的1,以此类推。
|
|
||||||
* 对外还是使用以 0 为开始的下标
|
|
||||||
*/
|
|
||||||
size_t i = 0, ileft = 1, iright = num_data;
|
size_t i = 0, ileft = 1, iright = num_data;
|
||||||
bool flg_found = false;
|
bool flg_found = false;
|
||||||
for (; ileft <= iright;) {
|
for (; ileft <= iright;) {
|
||||||
|
@ -122,28 +70,15 @@ int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp,
|
||||||
*ret_idx = i;
|
*ret_idx = i;
|
||||||
else if (ileft >= i + 2)
|
else if (ileft >= i + 2)
|
||||||
*ret_idx = i + 1;
|
*ret_idx = i + 1;
|
||||||
//DBGMSG (PFDBG_CATLOG_PF, PFDBG_LEVEL_DEBUG, "not found! num_data=%" PRIuSZ "; ileft=%" PRIuSZ ", iright=%" PRIuSZ ", i=%" PRIuSZ "", num_data, ileft, iright, i);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/* This function gets the character at the pstart position, interpreting UTF8 multybyte sequences
|
||||||
* @brief 转换 UTF-8 编码的一个字符为本地的 Unicode 字符(wchar_t)
|
and returns the pointer to the next character */
|
||||||
*
|
|
||||||
* @param pstart : 存储 UTF-8 字符的指针
|
|
||||||
* @param cb_read_byte : 读取字符的函数;用于8位MCU ROM
|
|
||||||
* @param pval : 需要返回的 Unicode 字符存放地址指针
|
|
||||||
*
|
|
||||||
* @return 成功返回下个 UTF-8 字符的位置
|
|
||||||
*
|
|
||||||
* 转换 UTF-8 编码的一个字符为本地的 Unicode 字符(wchar_t)
|
|
||||||
*/
|
|
||||||
uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval) {
|
uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
uint8_t *p = pstart;
|
uint8_t *p = pstart;
|
||||||
|
|
||||||
FU_ASSERT(NULL != pstart);
|
|
||||||
FU_ASSERT(NULL != cb_read_byte);
|
|
||||||
|
|
||||||
uint8_t valcur = cb_read_byte(p);
|
uint8_t valcur = cb_read_byte(p);
|
||||||
if (0 == (0x80 & valcur)) {
|
if (0 == (0x80 & valcur)) {
|
||||||
val = valcur;
|
val = valcur;
|
||||||
|
@ -215,113 +150,34 @@ uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t
|
||||||
val |= (valcur & 0x3F);
|
val |= (valcur & 0x3F);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
else if (0x80 == (0xC0 & valcur)) {
|
else if (0x80 == (0xC0 & valcur))
|
||||||
/* error? */
|
|
||||||
TRACE("ERR 1");
|
|
||||||
for (; 0x80 == (0xC0 & valcur); ) { p++; valcur = cb_read_byte(p); }
|
for (; 0x80 == (0xC0 & valcur); ) { p++; valcur = cb_read_byte(p); }
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
/* error */
|
|
||||||
TRACE("ERR 2");
|
|
||||||
for (; ((0xFE & valcur) > 0xFC); ) { p++; valcur = cb_read_byte(p); }
|
for (; ((0xFE & valcur) > 0xFC); ) { p++; valcur = cb_read_byte(p); }
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (val == 0) {
|
|
||||||
p = NULL;
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
}
|
|
||||||
else if (pstart + maxlen < p) {
|
|
||||||
p = pstart;
|
|
||||||
if (pval) *pval = 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (pval) *pval = val;
|
if (pval) *pval = val;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint8_t * get_utf8_value_cb (uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval);
|
static inline uint8_t utf8_strlen_cb(const char *pstart, read_byte_cb_t cb_read_byte) {
|
||||||
int utf8_strlen_cb(const char *pstart, read_byte_cb_t cb_read_byte) {
|
|
||||||
wchar_t ch;
|
|
||||||
uint8_t *pnext;
|
|
||||||
int cnt = 0;
|
|
||||||
|
|
||||||
for (pnext = (uint8_t *)pstart; ; ) {
|
uint8_t cnt = 0;
|
||||||
|
uint8_t *pnext = (uint8_t *)pstart;
|
||||||
|
for (;;) {
|
||||||
|
wchar_t ch;
|
||||||
pnext = get_utf8_value_cb(pnext, cb_read_byte, &ch);
|
pnext = get_utf8_value_cb(pnext, cb_read_byte, &ch);
|
||||||
if (pnext == NULL || ch == 0) break;
|
if (!ch) break;
|
||||||
cnt++;
|
cnt++;
|
||||||
TRACE("cnt=%d, ch=0x%X", cnt, (int)ch);
|
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
uint8_t utf8_strlen(const char *pstart) {
|
||||||
my_strlen_P(const char *pstart)
|
return utf8_strlen_cb(pstart, read_byte_ram);
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
FU_ASSERT(NULL != pstart);
|
|
||||||
p = pstart;
|
|
||||||
while (p && pgm_read_byte(p) != '\0') p ++;
|
|
||||||
return (p - pstart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t utf8_strlen(const char *pstart) { return utf8_strlen_cb(pstart, read_byte_ram); }
|
uint8_t utf8_strlen_P(const char *pstart) {
|
||||||
uint8_t utf8_strlen_P(const char *pstart) { return utf8_strlen_cb(pstart, read_byte_rom); }
|
return utf8_strlen_cb(pstart, read_byte_rom);
|
||||||
|
|
||||||
char* utf8_strncpy_cb( char * destination, const char *source, size_t num, int len_src, read_byte_cb_t cb_read_byte) {
|
|
||||||
uint8_t *p = (uint8_t *)source;
|
|
||||||
uint8_t *d = (uint8_t *)destination;
|
|
||||||
|
|
||||||
FU_ASSERT(NULL != destination);
|
|
||||||
FU_ASSERT(NULL != source);
|
|
||||||
FU_ASSERT(NULL != cb_read_byte);
|
|
||||||
|
|
||||||
uint8_t *pend = p + len_src;
|
|
||||||
|
|
||||||
while (p < pend) {
|
|
||||||
uint8_t valcur = cb_read_byte(p);
|
|
||||||
size_t len = 0;
|
|
||||||
if (0 == (0x80 & valcur))
|
|
||||||
len = 1;
|
|
||||||
else if (0xC0 == (0xE0 & valcur))
|
|
||||||
len = 2;
|
|
||||||
else if (0xE0 == (0xF0 & valcur))
|
|
||||||
len = 3;
|
|
||||||
else if (0xF0 == (0xF8 & valcur))
|
|
||||||
len = 4;
|
|
||||||
else if (0xF8 == (0xFC & valcur))
|
|
||||||
len = 5;
|
|
||||||
else if (0xFC == (0xFE & valcur))
|
|
||||||
len = 6;
|
|
||||||
else if (0x80 == (0xC0 & valcur)) {
|
|
||||||
/* error? */
|
|
||||||
for (; 0x80 == (0xC0 & valcur) && (p < pend); ) { p++; valcur = cb_read_byte(p); }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* error */
|
|
||||||
for (; ((0xFE & valcur) > 0xFC) && (p < pend); ) { p++; valcur = cb_read_byte(p); }
|
|
||||||
}
|
|
||||||
if (len < num) {
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
valcur = cb_read_byte(p);
|
|
||||||
*d = valcur;
|
|
||||||
d++;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*d = 0;
|
|
||||||
return destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* utf8_strncpy(char * destination, const char * source, size_t num) {
|
|
||||||
return utf8_strncpy_cb(destination, source, num, strlen(source), read_byte_ram);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* utf8_strncpy_P(char * destination, const char * source, size_t num) {
|
|
||||||
return utf8_strncpy_cb(destination, source, num, my_strlen_P(source), read_byte_rom);
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,151 +9,40 @@
|
||||||
#ifndef _FONT_UTILS_H
|
#ifndef _FONT_UTILS_H
|
||||||
#define _FONT_UTILS_H
|
#define _FONT_UTILS_H
|
||||||
|
|
||||||
#define DEBUG 0
|
#include <Arduino.h>
|
||||||
|
#include "../core/macros.h"
|
||||||
#ifdef ARDUINO
|
|
||||||
#include <Arduino.h>
|
|
||||||
#else // ARDUINO
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif // ARDUINO
|
|
||||||
|
|
||||||
#ifndef pgm_read_word_near // __AVR__
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
//#define pgm_read_word_near(a) *((uint16_t *)(a))
|
|
||||||
#define pgm_read_word_near(a) (*(a))
|
|
||||||
#define pgm_read_byte_near(a) *((uint8_t *)(a))
|
|
||||||
#define pgm_read_byte pgm_read_byte_near
|
|
||||||
#elif defined(__AVR__)
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PROGMEM
|
|
||||||
#define PROGMEM
|
|
||||||
#define strlen_P strlen
|
|
||||||
#define memcpy_P memcpy
|
|
||||||
#define vsnprintf_P vsnprintf
|
|
||||||
#endif // PROGMEM
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// read a byte from ROM or RAM
|
|
||||||
typedef uint8_t (* read_byte_cb_t)(uint8_t * str);
|
|
||||||
|
|
||||||
//inline uint8_t read_byte_ram(uint8_t * str) { return *str; }
|
|
||||||
//inline uint8_t read_byte_rom(uint8_t * str) { return pgm_read_byte(str); }
|
|
||||||
uint8_t read_byte_ram(uint8_t * str);
|
|
||||||
uint8_t read_byte_rom(uint8_t * str);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stddef.h> // wchar_t
|
#include <stddef.h> // wchar_t
|
||||||
#include <stdint.h> // uint32_t
|
#include <stdint.h> // uint32_t
|
||||||
|
|
||||||
#ifdef ARDUINO
|
// read a byte from ROM or RAM
|
||||||
|
typedef uint8_t (*read_byte_cb_t)(uint8_t * str);
|
||||||
|
|
||||||
// there's overflow of the wchar_t due to the 2-byte size in Arduino
|
uint8_t read_byte_ram(uint8_t * str);
|
||||||
// sizeof(wchar_t)=2; sizeof(size_t)=2; sizeof(uint32_t)=4;
|
uint8_t read_byte_rom(uint8_t * str);
|
||||||
// sizeof(int)=2; sizeof(long)=4; sizeof(unsigned)=2;
|
|
||||||
//#undef wchar_t
|
|
||||||
#define wchar_t uint32_t
|
|
||||||
//typedef uint32_t wchar_t;
|
|
||||||
|
|
||||||
#else
|
// there's overflow of the wchar_t due to the 2-byte size in Arduino
|
||||||
|
// sizeof(wchar_t)=2; sizeof(size_t)=2; sizeof(uint32_t)=4;
|
||||||
#include <sys/types.h> // ssize_t
|
// sizeof(int)=2; sizeof(long)=4; sizeof(unsigned)=2;
|
||||||
#include <assert.h>
|
//#undef wchar_t
|
||||||
// x86_64
|
#define wchar_t uint32_t
|
||||||
// sizeof(wchar_t)=4; sizeof(size_t)=8; sizeof(uint32_t)=4;
|
//typedef uint32_t wchar_t;
|
||||||
// sizeof(int)=4; sizeof(long)=8; sizeof(unsigned)=4;
|
|
||||||
//#define wchar_t uint32_t
|
|
||||||
#define wchar_t size_t
|
|
||||||
|
|
||||||
#ifndef PRIu32
|
|
||||||
#define PRIu32 "lu"
|
|
||||||
#endif
|
|
||||||
#ifndef PRIX32
|
|
||||||
#define PRIX32 "lX"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define UNUSED_VARIABLE(a) ((void)(a))
|
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a,b) (((a)>(b))?(b):(a))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NUM_ARRAY
|
#ifndef NUM_ARRAY
|
||||||
#define NUM_ARRAY(a) (sizeof(a)/sizeof((a)[0]))
|
#define NUM_ARRAY(a) (sizeof(a)/sizeof((a)[0]))
|
||||||
#endif // NUM_ARRAY
|
#endif // NUM_ARRAY
|
||||||
|
|
||||||
|
typedef uint16_t pixel_len_t;
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define pixel_len_t u8g_uint_t
|
|
||||||
#define pixel_len_t uint16_t
|
|
||||||
//#define pixel_len_t uint8_t
|
|
||||||
//typedef uint16_t pixel_len_t;
|
|
||||||
#define PIXEL_LEN_NOLIMIT ((pixel_len_t)(-1))
|
#define PIXEL_LEN_NOLIMIT ((pixel_len_t)(-1))
|
||||||
|
|
||||||
|
/* Perform binary search */
|
||||||
typedef int (* pf_bsearch_cb_comp_t)(void *userdata, size_t idx, void * data_pin); /*"data_list[idx] - *data_pin"*/
|
typedef int (* pf_bsearch_cb_comp_t)(void *userdata, size_t idx, void * data_pin); /*"data_list[idx] - *data_pin"*/
|
||||||
int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp, void *data_pinpoint, size_t *ret_idx);
|
int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp, void *data_pinpoint, size_t *ret_idx);
|
||||||
|
|
||||||
//wchar_t get_val_utf82uni(uint8_t *pstart);
|
/* Get the character, decoding multibyte UTF8 characters and returning a pointer to the start of the next UTF8 character */
|
||||||
//uint8_t * get_utf8_value(uint8_t *pstart, wchar_t *pval);
|
uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval);
|
||||||
uint8_t * get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval);
|
|
||||||
|
|
||||||
|
/* Returns lenght of string in CHARACTERS, NOT BYTES */
|
||||||
uint8_t utf8_strlen(const char *pstart);
|
uint8_t utf8_strlen(const char *pstart);
|
||||||
uint8_t utf8_strlen_P(const char *pstart);
|
uint8_t utf8_strlen_P(const char *pstart);
|
||||||
|
|
||||||
char * utf8_strncpy(char * destination, const char * source, size_t num);
|
|
||||||
char * utf8_strncpy_P(char * destination, const char * source, size_t num);
|
|
||||||
int my_strlen_P(const char *pstart);
|
|
||||||
|
|
||||||
#if 0 // DEBUG
|
|
||||||
#if 0 //defined(ARDUINO)
|
|
||||||
#if defined(__AVR__)
|
|
||||||
#define TRACE(fmt, ...) {static const PROGMEM char CONSTSTR[] = "%d %d " fmt " {ln:%d;}\n"; serial_printf_P(CONSTSTR, millis(), ##__VA_ARGS__, __LINE__); }
|
|
||||||
#else
|
|
||||||
#define TRACE(fmt, ...) {static const PROGMEM char CONSTSTR[] = "%d " fmt " {ln:%d, fn:" __FILE__ "}\n"; serial_printf_P(CONSTSTR, millis(), ##__VA_ARGS__, __LINE__); }
|
|
||||||
#endif
|
|
||||||
#define FU_ASSERT(a) if (!(a)) {TRACE("Assert: " # a ); }
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void serial_printf_P(const char *format, ...);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // ARDUINO
|
|
||||||
#include <stdio.h>
|
|
||||||
#define FU_ASSERT(a) if (!(a)) {printf("Assert: " # a); exit(1);}
|
|
||||||
#define TRACE(fmt, ...) fprintf(stdout, "[%s()] " fmt " {ln:%d, fn:" __FILE__ "}\n", __func__, ##__VA_ARGS__, __LINE__)
|
|
||||||
//#else
|
|
||||||
//#define FU_ASSERT(a)
|
|
||||||
//#define TRACE(...)
|
|
||||||
#endif // ARDUINO
|
|
||||||
|
|
||||||
#else // DEBUG
|
|
||||||
#define TRACE(fmt, ...)
|
|
||||||
#define FU_ASSERT(a)
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // _FONT_UTILS_H
|
#endif // _FONT_UTILS_H
|
||||||
|
|
|
@ -17,11 +17,7 @@
|
||||||
#include "u8g_fontutf8.h"
|
#include "u8g_fontutf8.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PRINTABLE(C) (((C) & 0xC0u) != 0x80u)
|
#define START_OF_UTF8_CHAR(C) (((C) & 0xC0u) != 0x80u)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int lcd_glyph_height(void);
|
int lcd_glyph_height(void);
|
||||||
|
|
||||||
|
@ -49,15 +45,11 @@ int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length);
|
||||||
*
|
*
|
||||||
* Draw a ROM UTF-8 string
|
* Draw a ROM UTF-8 string
|
||||||
*/
|
*/
|
||||||
int lcd_put_u8str_max_rom(const char * utf8_str_P, pixel_len_t max_length);
|
int lcd_put_u8str_max_P(const char * utf8_str_P, pixel_len_t max_length);
|
||||||
|
|
||||||
void lcd_moveto(int col, int row);
|
void lcd_moveto(int col, int row);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
inline int lcd_put_u8str_P(const char *str) { return lcd_put_u8str_max_P(str, PIXEL_LEN_NOLIMIT); }
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define lcd_put_u8str_rom(str) lcd_put_u8str_max_rom(str, PIXEL_LEN_NOLIMIT)
|
|
||||||
|
|
||||||
inline int lcd_put_u8str(const char* str) { return lcd_put_u8str_max(str, PIXEL_LEN_NOLIMIT); }
|
inline int lcd_put_u8str(const char* str) { return lcd_put_u8str_max(str, PIXEL_LEN_NOLIMIT); }
|
||||||
|
|
||||||
|
|
|
@ -24,20 +24,13 @@
|
||||||
#include "fontutils.h"
|
#include "fontutils.h"
|
||||||
#include "lcdprint.h"
|
#include "lcdprint.h"
|
||||||
|
|
||||||
#if defined(ARDUINO)
|
#include "ultralcd_common_HD44780.h"
|
||||||
#include "ultralcd_common_HD44780.h"
|
#ifndef LCD_CLASS
|
||||||
#ifndef LCD_CLASS
|
#include <LiquidCrystal.h>
|
||||||
#include <LiquidCrystal.h>
|
#define LCD_CLASS LiquidCrystal
|
||||||
#define LCD_CLASS LiquidCrystal
|
|
||||||
#endif
|
|
||||||
extern LCD_CLASS lcd;
|
|
||||||
LCD_CLASS *plcd = &lcd;
|
|
||||||
#define _lcd_write(a) plcd->write(a)
|
|
||||||
#define _lcd_setcursor(col, row) plcd->setCursor((col), (row));
|
|
||||||
#else
|
|
||||||
#define _lcd_write(a) TRACE("Write LCD: %c (%d)", (a), (int)(a));
|
|
||||||
#define _lcd_setcursor(col, row) TRACE("Set cursor LCD: (%d,%d)", (col), (row));
|
|
||||||
#endif
|
#endif
|
||||||
|
extern LCD_CLASS lcd;
|
||||||
|
LCD_CLASS *plcd = &lcd;
|
||||||
|
|
||||||
int lcd_glyph_height(void) { return 1; }
|
int lcd_glyph_height(void) { return 1; }
|
||||||
|
|
||||||
|
@ -878,25 +871,10 @@ static const hd44780_charmap_t g_hd44780_charmap_common[] PROGMEM = {
|
||||||
|
|
||||||
/* return v1 - v2 */
|
/* return v1 - v2 */
|
||||||
static int hd44780_charmap_compare(hd44780_charmap_t * v1, hd44780_charmap_t * v2) {
|
static int hd44780_charmap_compare(hd44780_charmap_t * v1, hd44780_charmap_t * v2) {
|
||||||
FU_ASSERT(NULL != v1);
|
if (v1->uchar < v2->uchar)
|
||||||
FU_ASSERT(NULL != v2);
|
|
||||||
TRACE("compare char1 %" PRIu32 "(0x%" PRIX32 ")", v1->uchar, v1->uchar);
|
|
||||||
TRACE("compare char2 %" PRIu32 "(0x%" PRIX32 ")", v2->uchar, v2->uchar);
|
|
||||||
if (v1->uchar < v2->uchar) {
|
|
||||||
TRACE("compare return -1");
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (v1->uchar > v2->uchar) {
|
else if (v1->uchar > v2->uchar)
|
||||||
TRACE("compare return 1");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
if (v1->idx < v2->idx) {
|
|
||||||
return -1;
|
|
||||||
} else if (v1->idx > v2->idx) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
TRACE("compare return 0");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,9 +887,7 @@ static int pf_bsearch_cb_comp_hd4map_pgm(void *userdata, size_t idx, void * data
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
||||||
int
|
int test_hd44780_charmap(hd44780_charmap_t *data, size_t size, char *name, char flg_show_contents) {
|
||||||
test_hd44780_charmap(hd44780_charmap_t *data, size_t size, char *name, char flg_show_contents)
|
|
||||||
{
|
|
||||||
int ret;
|
int ret;
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
hd44780_charmap_t preval = {0, 0, 0};
|
hd44780_charmap_t preval = {0, 0, 0};
|
||||||
|
@ -963,9 +939,7 @@ test_hd44780_charmap(hd44780_charmap_t *data, size_t size, char *name, char flg_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int test_hd44780_charmap_all(void) {
|
||||||
test_hd44780_charmap_all(void)
|
|
||||||
{
|
|
||||||
int flg_error = 0;
|
int flg_error = 0;
|
||||||
if (test_hd44780_charmap(g_hd44780_charmap_device, NUM_ARRAY(g_hd44780_charmap_device), "g_hd44780_charmap_device", 0) < 0) {
|
if (test_hd44780_charmap(g_hd44780_charmap_device, NUM_ARRAY(g_hd44780_charmap_device), "g_hd44780_charmap_device", 0) < 0) {
|
||||||
flg_error = 1;
|
flg_error = 1;
|
||||||
|
@ -986,18 +960,17 @@ test_hd44780_charmap_all(void)
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
void lcd_moveto(int col, int row) {
|
void lcd_moveto(int col, int row) {
|
||||||
TRACE("Move to: (%d,%d)", col, row);
|
plcd->setCursor(col, row);
|
||||||
_lcd_setcursor(col, row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return < 0 on error
|
// return < 0 on error
|
||||||
// return the advanced cols
|
// return the advanced cols
|
||||||
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
||||||
|
|
||||||
// find the HD44780 internal ROM first
|
// find the HD44780 internal ROM first
|
||||||
int ret;
|
int ret;
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
hd44780_charmap_t pinval;
|
hd44780_charmap_t pinval;
|
||||||
hd44780_charmap_t localval;
|
|
||||||
hd44780_charmap_t *copy_address = NULL;
|
hd44780_charmap_t *copy_address = NULL;
|
||||||
pinval.uchar = c;
|
pinval.uchar = c;
|
||||||
pinval.idx = -1;
|
pinval.idx = -1;
|
||||||
|
@ -1006,37 +979,33 @@ int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
||||||
|
|
||||||
// TODO: fix the '\\' that doesnt exist in the HD44870
|
// TODO: fix the '\\' that doesnt exist in the HD44870
|
||||||
if (c < 128) {
|
if (c < 128) {
|
||||||
//TRACE("draw char: regular %d", (int)c);
|
plcd->write((uint8_t)c);
|
||||||
_lcd_write((uint8_t)c);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
copy_address = NULL;
|
copy_address = NULL;
|
||||||
ret = pf_bsearch_r((void *)g_hd44780_charmap_device, NUM_ARRAY(g_hd44780_charmap_device), pf_bsearch_cb_comp_hd4map_pgm, (void *)&pinval, &idx);
|
ret = pf_bsearch_r((void *)g_hd44780_charmap_device, NUM_ARRAY(g_hd44780_charmap_device), pf_bsearch_cb_comp_hd4map_pgm, (void *)&pinval, &idx);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
copy_address = (hd44780_charmap_t *)(g_hd44780_charmap_device + idx);
|
copy_address = (hd44780_charmap_t *)(g_hd44780_charmap_device + idx);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ret = pf_bsearch_r((void *)g_hd44780_charmap_common, NUM_ARRAY(g_hd44780_charmap_common), pf_bsearch_cb_comp_hd4map_pgm, (void *)&pinval, &idx);
|
ret = pf_bsearch_r((void *)g_hd44780_charmap_common, NUM_ARRAY(g_hd44780_charmap_common), pf_bsearch_cb_comp_hd4map_pgm, (void *)&pinval, &idx);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) copy_address = (hd44780_charmap_t *)(g_hd44780_charmap_common + idx);
|
||||||
copy_address = (hd44780_charmap_t *)(g_hd44780_charmap_common + idx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
|
hd44780_charmap_t localval;
|
||||||
// found
|
// found
|
||||||
FU_ASSERT(NULL != copy_address);
|
|
||||||
memcpy_P(&localval, copy_address, sizeof(localval));
|
memcpy_P(&localval, copy_address, sizeof(localval));
|
||||||
FU_ASSERT((localval.uchar == c) && (localval.uchar == pinval.uchar));
|
plcd->write(localval.idx);
|
||||||
TRACE("draw char: %" PRIu32 "(0x%" PRIX32 ") at ROM %d(+%d)", c, c, (int)localval.idx, (int)localval.idx2);
|
|
||||||
_lcd_write(localval.idx);
|
|
||||||
if (max_length >= 2 && localval.idx2 > 0) {
|
if (max_length >= 2 && localval.idx2 > 0) {
|
||||||
_lcd_write(localval.idx2);
|
plcd->write(localval.idx2);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// print '?' instead
|
|
||||||
TRACE("draw char: Not found " PRIu32 "(0x%" PRIX32 ")", c, c);
|
// Not found, print '?' instead
|
||||||
_lcd_write((uint8_t)'?');
|
plcd->write((uint8_t)'?');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,7 +1013,6 @@ int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
||||||
* @brief Draw a UTF-8 string
|
* @brief Draw a UTF-8 string
|
||||||
*
|
*
|
||||||
* @param utf8_str : the UTF-8 string
|
* @param utf8_str : the UTF-8 string
|
||||||
* @param len : the byte length of the string (returned by strlen(utf8_str) or strlen_P(utf8_str) )
|
|
||||||
* @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM)
|
* @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM)
|
||||||
* @param max_length : the pixel length of the string allowed (or number of slots in HD44780)
|
* @param max_length : the pixel length of the string allowed (or number of slots in HD44780)
|
||||||
*
|
*
|
||||||
|
@ -1052,39 +1020,24 @@ int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
||||||
*
|
*
|
||||||
* Draw a UTF-8 string
|
* Draw a UTF-8 string
|
||||||
*/
|
*/
|
||||||
static int lcd_put_u8str_max_cb(const char * utf8_str, uint16_t len, uint8_t (*cb_read_byte)(uint8_t * str), pixel_len_t max_length) {
|
static int lcd_put_u8str_max_cb(const char * utf8_str, uint8_t (*cb_read_byte)(uint8_t * str), pixel_len_t max_length) {
|
||||||
wchar_t ch;
|
|
||||||
uint8_t *p, *pend;
|
|
||||||
pixel_len_t ret = 0;
|
pixel_len_t ret = 0;
|
||||||
|
uint8_t *p = (uint8_t *)utf8_str;
|
||||||
TRACE("BEGIN lcd_put_u8str_max_cb(len=%d, maxlen=%d)", len, max_length);
|
while (ret < max_length) {
|
||||||
pend = (uint8_t *)utf8_str + len;
|
wchar_t ch = 0;
|
||||||
for (p = (uint8_t *)utf8_str; (p < pend) && (ret < max_length); ) {
|
|
||||||
ch = 0;
|
|
||||||
p = get_utf8_value_cb(p, cb_read_byte, &ch);
|
p = get_utf8_value_cb(p, cb_read_byte, &ch);
|
||||||
if (NULL == p) {
|
if (!p) break;
|
||||||
TRACE("No more char, break ...");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
FU_ASSERT(ret < max_length);
|
|
||||||
ret += lcd_put_wchar_max(ch, max_length - ret);
|
ret += lcd_put_wchar_max(ch, max_length - ret);
|
||||||
}
|
}
|
||||||
return (int)ret;
|
return (int)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
|
int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
|
||||||
//TRACE("BEGIN lcd_put_u8str_max(str='%s', len=%d, maxlen=%d)", utf8_str, strlen(utf8_str), max_length);
|
return lcd_put_u8str_max_cb(utf8_str, read_byte_ram, max_length);
|
||||||
TRACE("BEGIN lcd_put_u8str_max(str='%s')", utf8_str);
|
|
||||||
TRACE("BEGIN lcd_put_u8str_max('len=%d)", strlen(utf8_str));
|
|
||||||
TRACE("BEGIN lcd_put_u8str_max(maxlen=%d)", max_length);
|
|
||||||
return lcd_put_u8str_max_cb(utf8_str, strlen(utf8_str), read_byte_ram, max_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int lcd_put_u8str_max_rom(const char * utf8_str_P, pixel_len_t max_length) {
|
int lcd_put_u8str_max_P(const char * utf8_str_P, pixel_len_t max_length) {
|
||||||
//TRACE("BEGIN lcd_put_u8str_max_rom('%s', len=%d, maxlen=%d)", utf8_str_P, strlen_P(utf8_str_P), max_length);
|
return lcd_put_u8str_max_cb(utf8_str_P, read_byte_rom, max_length);
|
||||||
TRACE("BEGIN lcd_put_u8str_max_rom(len=%d)", strlen_P(utf8_str_P));
|
|
||||||
TRACE("BEGIN lcd_put_u8str_max_rom(maxlen=%d)", max_length);
|
|
||||||
return lcd_put_u8str_max_cb(utf8_str_P, strlen_P(utf8_str_P), read_byte_rom, max_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // DOGLCD
|
#endif // DOGLCD
|
||||||
|
|
|
@ -25,25 +25,22 @@ extern U8GLIB *pu8g;
|
||||||
|
|
||||||
int lcd_glyph_height(void) {
|
int lcd_glyph_height(void) {
|
||||||
return u8g_GetFontBBXHeight(pu8g->getU8g());
|
return u8g_GetFontBBXHeight(pu8g->getU8g());
|
||||||
//return u8g_GetFontBBXOffY(pu8g->getU8g());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_moveto(int col, int row) {
|
void lcd_moveto(int col, int row) {
|
||||||
TRACE("Move to: (%d,%d)", col, row);
|
|
||||||
_lcd_setcursor(col, row);
|
_lcd_setcursor(col, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return < 0 on error
|
||||||
|
// return the advanced pixels
|
||||||
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
|
||||||
if (c < 256) {
|
if (c < 256) {
|
||||||
TRACE("draw char: regular %d", (int)c);
|
|
||||||
_lcd_write((char)c);
|
_lcd_write((char)c);
|
||||||
return u8g_GetFontBBXWidth(pu8g->getU8g());
|
return u8g_GetFontBBXWidth(pu8g->getU8g());
|
||||||
}
|
}
|
||||||
unsigned int x = pu8g->getPrintCol(),
|
unsigned int x = pu8g->getPrintCol(),
|
||||||
y = pu8g->getPrintRow(),
|
y = pu8g->getPrintRow(),
|
||||||
ret = uxg_DrawWchar(pu8g->getU8g(), x, y, c, max_length);
|
ret = uxg_DrawWchar(pu8g->getU8g(), x, y, c, max_length);
|
||||||
TRACE("uxg_DrawWchar(x=%d,y=%d,maxlen=%d", x, y, max_length);
|
|
||||||
TRACE("u8g->setPrintPos(x=%d + ret=%d,y=%d", x, ret, y);
|
|
||||||
pu8g->setPrintPos(x + ret, y);
|
pu8g->setPrintPos(x + ret, y);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -53,25 +50,16 @@ int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
|
||||||
unsigned int x = pu8g->getPrintCol(),
|
unsigned int x = pu8g->getPrintCol(),
|
||||||
y = pu8g->getPrintRow(),
|
y = pu8g->getPrintRow(),
|
||||||
ret = uxg_DrawUtf8Str(pu8g->getU8g(), x, y, utf8_str, max_length);
|
ret = uxg_DrawUtf8Str(pu8g->getU8g(), x, y, utf8_str, max_length);
|
||||||
TRACE("uxg_DrawUtf8Str(x=%d,y=%d,maxlen=%d", x, y, max_length);
|
|
||||||
TRACE("u8g->setPrintPos(x=%d + ret=%d,y=%d", x, ret, y);
|
|
||||||
pu8g->setPrintPos(x + ret, y);
|
pu8g->setPrintPos(x + ret, y);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lcd_put_u8str_max_rom(const char * utf8_str_P, pixel_len_t max_length) {
|
int lcd_put_u8str_max_P(const char * utf8_str_P, pixel_len_t max_length) {
|
||||||
unsigned int x = pu8g->getPrintCol(),
|
unsigned int x = pu8g->getPrintCol(),
|
||||||
y = pu8g->getPrintRow(),
|
y = pu8g->getPrintRow(),
|
||||||
ret = uxg_DrawUtf8StrP(pu8g->getU8g(), x, y, utf8_str_P, max_length);
|
ret = uxg_DrawUtf8StrP(pu8g->getU8g(), x, y, utf8_str_P, max_length);
|
||||||
TRACE("uxg_DrawUtf8StrP(x=%d,y=%d,maxlen=%d", x, y, max_length);
|
|
||||||
TRACE("u8g->setPrintPos(x=%d + ret=%d,y=%d", x, ret, y);
|
|
||||||
pu8g->setPrintPos(x + ret, y);
|
pu8g->setPrintPos(x + ret, y);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !DOGLCD
|
#endif // DOGLCD
|
||||||
|
|
||||||
#define _lcd_write(a) TRACE("Write LCD: %c (%d)", (a), (int)(a));
|
|
||||||
#define _lcd_setcursor(col, row) TRACE("Set cursor LCD: (%d,%d)", (col), (row));
|
|
||||||
|
|
||||||
#endif // !DOGLCD
|
|
||||||
|
|
|
@ -18,28 +18,6 @@
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
typedef void font_t;
|
typedef void font_t;
|
||||||
|
|
||||||
#ifndef PSTR
|
|
||||||
#define PSTR(a) a
|
|
||||||
|
|
||||||
void* memcpy_from_rom(void *dest, const void * rom_src, size_t sz) {
|
|
||||||
uint8_t * p;
|
|
||||||
uint8_t * s;
|
|
||||||
|
|
||||||
FU_ASSERT(NULL != dest);
|
|
||||||
p = (uint8_t*)dest;
|
|
||||||
s = (uint8_t*)rom_src;
|
|
||||||
uint8_t c;
|
|
||||||
while ((p - (uint8_t *)dest) < sz) {
|
|
||||||
*p = pgm_read_byte(s);
|
|
||||||
p ++;
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define memcpy_from_rom memcpy_P
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief the callback function to draw something
|
* @brief the callback function to draw something
|
||||||
*
|
*
|
||||||
|
@ -53,25 +31,14 @@ void* memcpy_from_rom(void *dest, const void * rom_src, size_t sz) {
|
||||||
*/
|
*/
|
||||||
typedef int (* fontgroup_cb_draw_t)(void *userdata, const font_t *fnt_current, const char *msg);
|
typedef int (* fontgroup_cb_draw_t)(void *userdata, const font_t *fnt_current, const char *msg);
|
||||||
|
|
||||||
//extern int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number);
|
|
||||||
//extern int fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, void *userdata, fontgroup_cb_draw_t cb_draw);
|
|
||||||
//extern uxg_fontinfo_t* fontgroup_first(font_group_t * root);
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/* return v1 - v2 */
|
/* return v1 - v2 */
|
||||||
static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) {
|
static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) {
|
||||||
FU_ASSERT(NULL != v1);
|
if (v1->page < v2->page) return -1;
|
||||||
FU_ASSERT(NULL != v2);
|
else if (v1->page > v2->page) return 1;
|
||||||
if (v1->page < v2->page)
|
|
||||||
return -1;
|
|
||||||
else if (v1->page > v2->page)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (v1->end < v2->begin)
|
if (v1->end < v2->begin) return -1;
|
||||||
return -1;
|
else if (v1->begin > v2->end) return 1;
|
||||||
else if (v1->begin > v2->end)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +47,7 @@ static int fontinfo_compare(uxg_fontinfo_t * v1, uxg_fontinfo_t * v2) {
|
||||||
static int pf_bsearch_cb_comp_fntifo_pgm (void *userdata, size_t idx, void *data_pin) {
|
static int pf_bsearch_cb_comp_fntifo_pgm (void *userdata, size_t idx, void *data_pin) {
|
||||||
uxg_fontinfo_t *fntinfo = (uxg_fontinfo_t*)userdata;
|
uxg_fontinfo_t *fntinfo = (uxg_fontinfo_t*)userdata;
|
||||||
uxg_fontinfo_t localval;
|
uxg_fontinfo_t localval;
|
||||||
memcpy_from_rom(&localval, fntinfo + idx, sizeof(localval));
|
memcpy_P(&localval, fntinfo + idx, sizeof(localval));
|
||||||
return fontinfo_compare(&localval, (uxg_fontinfo_t*)data_pin);
|
return fontinfo_compare(&localval, (uxg_fontinfo_t*)data_pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +59,6 @@ typedef struct _font_group_t {
|
||||||
static int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number) {
|
static int fontgroup_init(font_group_t * root, const uxg_fontinfo_t * fntinfo, int number) {
|
||||||
root->m_fntifo = fntinfo;
|
root->m_fntifo = fntinfo;
|
||||||
root->m_fntinfo_num = number;
|
root->m_fntinfo_num = number;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,26 +71,23 @@ static const font_t* fontgroup_find(font_group_t * root, wchar_t val) {
|
||||||
if (pf_bsearch_r((void*)root->m_fntifo, root->m_fntinfo_num, pf_bsearch_cb_comp_fntifo_pgm, (void*)&vcmp, &idx) < 0)
|
if (pf_bsearch_r((void*)root->m_fntifo, root->m_fntinfo_num, pf_bsearch_cb_comp_fntifo_pgm, (void*)&vcmp, &idx) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy_from_rom(&vcmp, root->m_fntifo + idx, sizeof(vcmp));
|
memcpy_P(&vcmp, root->m_fntifo + idx, sizeof(vcmp));
|
||||||
return vcmp.fntdata;
|
return vcmp.fntdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fontgroup_drawwchar(font_group_t *group, const font_t *fnt_default, wchar_t val, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
|
static void fontgroup_drawwchar(font_group_t *group, const font_t *fnt_default, wchar_t val, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
|
||||||
uint8_t buf[2] = {0, 0};
|
uint8_t buf[2] = {0, 0};
|
||||||
const font_t * fntpqm = NULL;
|
const font_t * fntpqm = (font_t*)fontgroup_find(group, val);
|
||||||
|
if (!fntpqm) {
|
||||||
TRACE("fontgroup_drawwchar char=%d(0x%X)", (int)val, (int)val);
|
// Unknown char, use default font
|
||||||
fntpqm = (font_t*)fontgroup_find(group, val);
|
|
||||||
if (NULL == fntpqm) {
|
|
||||||
buf[0] = (uint8_t)(val & 0xFF);
|
buf[0] = (uint8_t)(val & 0xFF);
|
||||||
fntpqm = fnt_default;
|
fntpqm = fnt_default;
|
||||||
TRACE("Unknown char %d(0x%X), use default font", (int)val, (int)val);
|
|
||||||
}
|
}
|
||||||
if (fnt_default != fntpqm) {
|
if (fnt_default != fntpqm) {
|
||||||
buf[0] = (uint8_t)(val & 0x7F);
|
buf[0] = (uint8_t)(val & 0x7F);
|
||||||
buf[0] |= 0x80; // use upper page to avoid 0x00 error in C. you may want to generate the font data
|
buf[0] |= 0x80; // use upper page to avoid 0x00 error in C. you may want to generate the font data
|
||||||
}
|
}
|
||||||
//TRACE("set font: %p; (default=%p)", fntpqm, UXG_DEFAULT_FONT);
|
|
||||||
cb_draw_ram (userdata, fntpqm, (char*) buf);
|
cb_draw_ram (userdata, fntpqm, (char*) buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,31 +105,27 @@ static void fontgroup_drawwchar(font_group_t *group, const font_t *fnt_default,
|
||||||
*
|
*
|
||||||
* Get the screen pixel width of a ROM UTF-8 string
|
* Get the screen pixel width of a ROM UTF-8 string
|
||||||
*/
|
*/
|
||||||
static void fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, int len_msg, read_byte_cb_t cb_read_byte, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
|
static void fontgroup_drawstring(font_group_t *group, const font_t *fnt_default, const char *utf8_msg, read_byte_cb_t cb_read_byte, void * userdata, fontgroup_cb_draw_t cb_draw_ram) {
|
||||||
uint8_t *pend = (uint8_t*)utf8_msg + len_msg;
|
uint8_t *p = (uint8_t*)utf8_msg;
|
||||||
for (uint8_t *p = (uint8_t*)utf8_msg; p < pend; ) {
|
for (;;) {
|
||||||
wchar_t val = 0;
|
wchar_t val = 0;
|
||||||
p = get_utf8_value_cb(p, cb_read_byte, &val);
|
p = get_utf8_value_cb(p, cb_read_byte, &val);
|
||||||
if (NULL == p) {
|
if (!val) break;
|
||||||
TRACE("No more char, break ...");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fontgroup_drawwchar(group, fnt_default, val, userdata, cb_draw_ram);
|
fontgroup_drawwchar(group, fnt_default, val, userdata, cb_draw_ram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static char flag_fontgroup_inited1 = 0;
|
static bool flag_fontgroup_was_inited = false;
|
||||||
#define flag_fontgroup_inited flag_fontgroup_inited1
|
|
||||||
static font_group_t g_fontgroup_root = {NULL, 0};
|
static font_group_t g_fontgroup_root = {NULL, 0};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief check if font is loaded
|
* @brief check if font is loaded
|
||||||
*/
|
*/
|
||||||
char uxg_Utf8FontIsInited(void) { return flag_fontgroup_inited; }
|
static inline bool uxg_Utf8FontIsInited(void) { return flag_fontgroup_was_inited; }
|
||||||
|
|
||||||
int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) {
|
int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) {
|
||||||
flag_fontgroup_inited = 1;
|
flag_fontgroup_was_inited = 1;
|
||||||
return fontgroup_init(&g_fontgroup_root, fntinfo, number);
|
return fontgroup_init(&g_fontgroup_root, fntinfo, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,22 +138,17 @@ struct _uxg_drawu8_data_t {
|
||||||
const void * fnt_prev;
|
const void * fnt_prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int fontgroup_cb_draw_u8g (void *userdata, const font_t *fnt_current, const char *msg) {
|
static int fontgroup_cb_draw_u8g(void *userdata, const font_t *fnt_current, const char *msg) {
|
||||||
struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
|
struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
|
||||||
|
|
||||||
FU_ASSERT(NULL != userdata);
|
|
||||||
if (pdata->fnt_prev != fnt_current) {
|
if (pdata->fnt_prev != fnt_current) {
|
||||||
u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
|
u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
|
||||||
//u8g_SetFontPosBottom(pdata->pu8g);
|
//u8g_SetFontPosBottom(pdata->pu8g);
|
||||||
pdata->fnt_prev = fnt_current;
|
pdata->fnt_prev = fnt_current;
|
||||||
}
|
}
|
||||||
if ((pdata->max_width != PIXEL_LEN_NOLIMIT) && (pdata->adv + u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg) > pdata->max_width)) {
|
if ((pdata->max_width != PIXEL_LEN_NOLIMIT) && (pdata->adv + u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg) > pdata->max_width))
|
||||||
TRACE("return end, adv=%d, width=%d, maxlen=%d", pdata->adv, u8g_GetStrPixelWidth(pdata->pu8g, (char*)msg), pdata->max_width);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
TRACE("Draw string 0x%X", (int)msg[0]);
|
|
||||||
pdata->adv += u8g_DrawStr(pdata->pu8g, pdata->x + pdata->adv, pdata->y, (char*) msg);
|
pdata->adv += u8g_DrawStr(pdata->pu8g, pdata->x + pdata->adv, pdata->y, (char*) msg);
|
||||||
//TRACE("adv pos= %d", pdata->adv);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +214,7 @@ unsigned int uxg_DrawUtf8Str(u8g_t *pu8g, unsigned int x, unsigned int y, const
|
||||||
data.adv = 0;
|
data.adv = 0;
|
||||||
data.max_width = max_width;
|
data.max_width = max_width;
|
||||||
data.fnt_prev = NULL;
|
data.fnt_prev = NULL;
|
||||||
fontgroup_drawstring(group, fnt_default, utf8_msg, strlen(utf8_msg), read_byte_ram, (void*)&data, fontgroup_cb_draw_u8g);
|
fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8g);
|
||||||
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
||||||
|
|
||||||
return data.adv;
|
return data.adv;
|
||||||
|
@ -285,7 +239,6 @@ unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, const
|
||||||
const font_t *fnt_default = uxg_GetFont(pu8g);
|
const font_t *fnt_default = uxg_GetFont(pu8g);
|
||||||
|
|
||||||
if (!uxg_Utf8FontIsInited()) {
|
if (!uxg_Utf8FontIsInited()) {
|
||||||
TRACE("Error, utf8string not inited!");
|
|
||||||
u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
|
u8g_DrawStrP(pu8g, x, y, (const u8g_pgm_uint8_t *)PSTR("Err: utf8 font not initialized."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -295,19 +248,15 @@ unsigned int uxg_DrawUtf8StrP(u8g_t *pu8g, unsigned int x, unsigned int y, const
|
||||||
data.adv = 0;
|
data.adv = 0;
|
||||||
data.max_width = max_width;
|
data.max_width = max_width;
|
||||||
data.fnt_prev = NULL;
|
data.fnt_prev = NULL;
|
||||||
TRACE("call fontgroup_drawstring");
|
fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8g);
|
||||||
fontgroup_drawstring(group, fnt_default, utf8_msg, my_strlen_P(utf8_msg), read_byte_rom, (void*)&data, fontgroup_cb_draw_u8g);
|
|
||||||
TRACE("restore font");
|
|
||||||
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
||||||
|
|
||||||
TRACE("return %d", data.adv);
|
|
||||||
return data.adv;
|
return data.adv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fontgroup_cb_draw_u8gstrlen(void *userdata, const font_t *fnt_current, const char *msg) {
|
static int fontgroup_cb_draw_u8gstrlen(void *userdata, const font_t *fnt_current, const char *msg) {
|
||||||
struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
|
struct _uxg_drawu8_data_t * pdata = (_uxg_drawu8_data_t*)userdata;
|
||||||
|
|
||||||
FU_ASSERT(NULL != userdata);
|
|
||||||
if (pdata->fnt_prev != fnt_current) {
|
if (pdata->fnt_prev != fnt_current) {
|
||||||
u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
|
u8g_SetFont(pdata->pu8g, (const u8g_fntpgm_uint8_t*)fnt_current);
|
||||||
u8g_SetFontPosBottom(pdata->pu8g);
|
u8g_SetFontPosBottom(pdata->pu8g);
|
||||||
|
@ -332,15 +281,12 @@ int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg) {
|
||||||
font_group_t *group = &g_fontgroup_root;
|
font_group_t *group = &g_fontgroup_root;
|
||||||
const font_t *fnt_default = uxg_GetFont(pu8g);
|
const font_t *fnt_default = uxg_GetFont(pu8g);
|
||||||
|
|
||||||
if (!uxg_Utf8FontIsInited()) {
|
if (!uxg_Utf8FontIsInited()) return -1;
|
||||||
TRACE("Err: utf8 font not initialized.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&data, 0, sizeof(data));
|
memset(&data, 0, sizeof(data));
|
||||||
data.pu8g = pu8g;
|
data.pu8g = pu8g;
|
||||||
data.adv = 0;
|
data.adv = 0;
|
||||||
fontgroup_drawstring(group, fnt_default, utf8_msg, strlen(utf8_msg), read_byte_ram, (void*)&data, fontgroup_cb_draw_u8gstrlen);
|
fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_ram, (void*)&data, fontgroup_cb_draw_u8gstrlen);
|
||||||
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
||||||
|
|
||||||
return data.adv;
|
return data.adv;
|
||||||
|
@ -361,14 +307,12 @@ int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, const char *utf8_msg) {
|
||||||
font_group_t *group = &g_fontgroup_root;
|
font_group_t *group = &g_fontgroup_root;
|
||||||
const font_t *fnt_default = uxg_GetFont(pu8g);
|
const font_t *fnt_default = uxg_GetFont(pu8g);
|
||||||
|
|
||||||
if (!uxg_Utf8FontIsInited()) {
|
if (!uxg_Utf8FontIsInited()) return -1;
|
||||||
TRACE("Err: utf8 font not initialized.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(&data, 0, sizeof(data));
|
memset(&data, 0, sizeof(data));
|
||||||
data.pu8g = pu8g;
|
data.pu8g = pu8g;
|
||||||
data.adv = 0;
|
data.adv = 0;
|
||||||
fontgroup_drawstring(group, fnt_default, utf8_msg, my_strlen_P(utf8_msg), read_byte_rom, (void*)&data, fontgroup_cb_draw_u8gstrlen);
|
fontgroup_drawstring(group, fnt_default, utf8_msg, read_byte_rom, (void*)&data, fontgroup_cb_draw_u8gstrlen);
|
||||||
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
u8g_SetFont(pu8g, (const u8g_fntpgm_uint8_t*)fnt_default);
|
||||||
return data.adv;
|
return data.adv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,6 @@
|
||||||
#include <U8glib.h>
|
#include <U8glib.h>
|
||||||
#include "fontutils.h"
|
#include "fontutils.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// the macro to indicate a UTF-8 string
|
// the macro to indicate a UTF-8 string
|
||||||
// You should to save the C/C++ source in UTF-8 encoding!
|
// You should to save the C/C++ source in UTF-8 encoding!
|
||||||
// Once you change your UTF-8 strings, you need to call the script uxggenpages.sh to create the font data file fontutf8-data.h
|
// Once you change your UTF-8 strings, you need to call the script uxggenpages.sh to create the font data file fontutf8-data.h
|
||||||
|
@ -30,21 +25,16 @@ typedef struct _uxg_fontinfo_t {
|
||||||
const u8g_fntpgm_uint8_t *fntdata;
|
const u8g_fntpgm_uint8_t *fntdata;
|
||||||
} uxg_fontinfo_t;
|
} uxg_fontinfo_t;
|
||||||
|
|
||||||
extern int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number); // fntinfo is type of PROGMEM
|
int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number); // fntinfo is type of PROGMEM
|
||||||
extern char uxg_Utf8FontIsInited(void);
|
|
||||||
|
|
||||||
extern unsigned int uxg_DrawWchar (u8g_t *pu8g, unsigned int x, unsigned int y, wchar_t ch, pixel_len_t max_length);
|
unsigned int uxg_DrawWchar (u8g_t *pu8g, unsigned int x, unsigned int y, wchar_t ch, pixel_len_t max_length);
|
||||||
|
|
||||||
extern unsigned int uxg_DrawUtf8Str (u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_length);
|
unsigned int uxg_DrawUtf8Str (u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_length);
|
||||||
extern unsigned int uxg_DrawUtf8StrP (u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_length);
|
unsigned int uxg_DrawUtf8StrP (u8g_t *pu8g, unsigned int x, unsigned int y, const char *utf8_msg, pixel_len_t max_length);
|
||||||
|
|
||||||
extern int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg);
|
int uxg_GetUtf8StrPixelWidth(u8g_t *pu8g, const char *utf8_msg);
|
||||||
extern int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, const char *utf8_msg);
|
int uxg_GetUtf8StrPixelWidthP(u8g_t *pu8g, const char *utf8_msg);
|
||||||
|
|
||||||
#define uxg_GetFont(puxg) ((puxg)->font)
|
#define uxg_GetFont(puxg) ((puxg)->font)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // _UXG_FONTUTF8_H
|
#endif // _UXG_FONTUTF8_H
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
#else
|
#else
|
||||||
#define MAX_MESSAGE_LENGTH CHARSIZE * 2 * (LCD_WIDTH)
|
#define MAX_MESSAGE_LENGTH CHARSIZE * 2 * (LCD_WIDTH)
|
||||||
#endif
|
#endif
|
||||||
uint8_t status_scroll_pos = 0;
|
uint8_t status_scroll_offset = 0;
|
||||||
#else
|
#else
|
||||||
#define MAX_MESSAGE_LENGTH CHARSIZE * (LCD_WIDTH)
|
#define MAX_MESSAGE_LENGTH CHARSIZE * (LCD_WIDTH)
|
||||||
#endif
|
#endif
|
||||||
|
@ -5360,30 +5360,8 @@ void lcd_update() {
|
||||||
} // ELAPSED(ms, next_lcd_update_ms)
|
} // ELAPSED(ms, next_lcd_update_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void pad_message_string() {
|
|
||||||
uint8_t i = 0, j = 0;
|
|
||||||
char c;
|
|
||||||
lcd_status_message[MAX_MESSAGE_LENGTH] = '\0';
|
|
||||||
while ((c = lcd_status_message[i]) && j < LCD_WIDTH) {
|
|
||||||
if (PRINTABLE(c)) j++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (true
|
|
||||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
|
||||||
&& j < LCD_WIDTH
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
// pad with spaces to fill up the line
|
|
||||||
while (j++ < LCD_WIDTH) lcd_status_message[i++] = ' ';
|
|
||||||
// chop off at the edge
|
|
||||||
lcd_status_message[i] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcd_finishstatus(const bool persist=false) {
|
void lcd_finishstatus(const bool persist=false) {
|
||||||
|
|
||||||
pad_message_string();
|
|
||||||
|
|
||||||
#if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
|
#if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
|
||||||
UNUSED(persist);
|
UNUSED(persist);
|
||||||
#endif
|
#endif
|
||||||
|
@ -5401,7 +5379,7 @@ void lcd_finishstatus(const bool persist=false) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||||
status_scroll_pos = 0;
|
status_scroll_offset = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5413,7 +5391,26 @@ bool lcd_hasstatus() { return (lcd_status_message[0] != '\0'); }
|
||||||
|
|
||||||
void lcd_setstatus(const char * const message, const bool persist) {
|
void lcd_setstatus(const char * const message, const bool persist) {
|
||||||
if (lcd_status_message_level > 0) return;
|
if (lcd_status_message_level > 0) return;
|
||||||
strncpy(lcd_status_message, message, MAX_MESSAGE_LENGTH);
|
|
||||||
|
// Here we have a problem. The message is encoded in UTF8, so
|
||||||
|
// arbitrarily cutting it will be a problem. We MUST be sure
|
||||||
|
// that there is no cutting in the middle of a multibyte character!
|
||||||
|
|
||||||
|
// Get a pointer to the null terminator
|
||||||
|
const char* pend = message + strlen(message);
|
||||||
|
|
||||||
|
// If length of supplied UTF8 string is greater than
|
||||||
|
// our buffer size, start cutting whole UTF8 chars
|
||||||
|
while ((pend - message) > MAX_MESSAGE_LENGTH) {
|
||||||
|
--pend;
|
||||||
|
while (!START_OF_UTF8_CHAR(*pend)) --pend;
|
||||||
|
};
|
||||||
|
|
||||||
|
// At this point, we have the proper cut point. Use it
|
||||||
|
uint8_t maxLen = pend - message;
|
||||||
|
strncpy(lcd_status_message, message, maxLen);
|
||||||
|
lcd_status_message[maxLen] = '\0';
|
||||||
|
|
||||||
lcd_finishstatus(persist);
|
lcd_finishstatus(persist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5421,7 +5418,26 @@ void lcd_setstatusPGM(const char * const message, int8_t level) {
|
||||||
if (level < 0) level = lcd_status_message_level = 0;
|
if (level < 0) level = lcd_status_message_level = 0;
|
||||||
if (level < lcd_status_message_level) return;
|
if (level < lcd_status_message_level) return;
|
||||||
lcd_status_message_level = level;
|
lcd_status_message_level = level;
|
||||||
strncpy_P(lcd_status_message, message, MAX_MESSAGE_LENGTH);
|
|
||||||
|
// Here we have a problem. The message is encoded in UTF8, so
|
||||||
|
// arbitrarily cutting it will be a problem. We MUST be sure
|
||||||
|
// that there is no cutting in the middle of a multibyte character!
|
||||||
|
|
||||||
|
// Get a pointer to the null terminator
|
||||||
|
const char* pend = message + strlen_P(message);
|
||||||
|
|
||||||
|
// If length of supplied UTF8 string is greater than
|
||||||
|
// our buffer size, start cutting whole UTF8 chars
|
||||||
|
while ((pend - message) > MAX_MESSAGE_LENGTH) {
|
||||||
|
--pend;
|
||||||
|
while (!START_OF_UTF8_CHAR(pgm_read_byte(pend))) --pend;
|
||||||
|
};
|
||||||
|
|
||||||
|
// At this point, we have the proper cut point. Use it
|
||||||
|
uint8_t maxLen = pend - message;
|
||||||
|
strncpy_P(lcd_status_message, message, maxLen);
|
||||||
|
lcd_status_message[maxLen] = '\0';
|
||||||
|
|
||||||
lcd_finishstatus(level > 0);
|
lcd_finishstatus(level > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -341,9 +341,9 @@ void lcd_kill_screen() {
|
||||||
lcd_moveto(0, h4 * 1);
|
lcd_moveto(0, h4 * 1);
|
||||||
lcd_put_u8str(lcd_status_message);
|
lcd_put_u8str(lcd_status_message);
|
||||||
lcd_moveto(0, h4 * 2);
|
lcd_moveto(0, h4 * 2);
|
||||||
lcd_put_u8str_rom(PSTR(MSG_HALTED));
|
lcd_put_u8str_P(PSTR(MSG_HALTED));
|
||||||
lcd_moveto(0, h4 * 3);
|
lcd_moveto(0, h4 * 3);
|
||||||
lcd_put_u8str_rom(PSTR(MSG_PLEASE_RESET));
|
lcd_put_u8str_P(PSTR(MSG_PLEASE_RESET));
|
||||||
} while (u8g.nextPage());
|
} while (u8g.nextPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
|
||||||
int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2;
|
int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2;
|
||||||
while (--pad >= 0) { lcd_put_wchar(' '); n--; }
|
while (--pad >= 0) { lcd_put_wchar(' '); n--; }
|
||||||
}
|
}
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
if (NULL != valstr) {
|
if (NULL != valstr) {
|
||||||
n -= lcd_put_u8str_max(valstr, n);
|
n -= lcd_put_u8str_max(valstr, n);
|
||||||
}
|
}
|
||||||
|
@ -431,7 +431,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
|
||||||
if (lcd_implementation_mark_as_selected(row, isSelected)) {
|
if (lcd_implementation_mark_as_selected(row, isSelected)) {
|
||||||
uint8_t n = LCD_WIDTH - (START_COL) - 2;
|
uint8_t n = LCD_WIDTH - (START_COL) - 2;
|
||||||
n *= DOG_CHAR_WIDTH;
|
n *= DOG_CHAR_WIDTH;
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
while (n - DOG_CHAR_WIDTH > 0) { n -= lcd_put_wchar(' '); }
|
while (n - DOG_CHAR_WIDTH > 0) { n -= lcd_put_wchar(' '); }
|
||||||
lcd_moveto(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), row_y2);
|
lcd_moveto(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), row_y2);
|
||||||
lcd_put_wchar(post_char);
|
lcd_put_wchar(post_char);
|
||||||
|
@ -451,11 +451,11 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
|
||||||
const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen((char*)data));
|
const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen((char*)data));
|
||||||
uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen;
|
uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen;
|
||||||
n *= DOG_CHAR_WIDTH;
|
n *= DOG_CHAR_WIDTH;
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
lcd_put_wchar(':');
|
lcd_put_wchar(':');
|
||||||
while (n - DOG_CHAR_WIDTH > 0) { n -= lcd_put_wchar(' '); }
|
while (n - DOG_CHAR_WIDTH > 0) { n -= lcd_put_wchar(' '); }
|
||||||
lcd_moveto(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, row_y2);
|
lcd_moveto(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, row_y2);
|
||||||
if (pgm) lcd_put_u8str_rom(data); else lcd_put_u8str((char*)data);
|
if (pgm) lcd_put_u8str_P(data); else lcd_put_u8str((char*)data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +499,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
|
||||||
bool onpage = PAGE_CONTAINS(baseline + 1 - (DOG_CHAR_HEIGHT_EDIT), baseline);
|
bool onpage = PAGE_CONTAINS(baseline + 1 - (DOG_CHAR_HEIGHT_EDIT), baseline);
|
||||||
if (onpage) {
|
if (onpage) {
|
||||||
lcd_moveto(0, baseline);
|
lcd_moveto(0, baseline);
|
||||||
lcd_put_u8str_rom(pstr);
|
lcd_put_u8str_P(pstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
|
@ -641,7 +641,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
|
||||||
if (!isnan(ubl.z_values[x_plot][y_plot]))
|
if (!isnan(ubl.z_values[x_plot][y_plot]))
|
||||||
lcd_put_u8str(ftostr43sign(ubl.z_values[x_plot][y_plot]));
|
lcd_put_u8str(ftostr43sign(ubl.z_values[x_plot][y_plot]));
|
||||||
else
|
else
|
||||||
lcd_put_u8str_rom(PSTR(" -----"));
|
lcd_put_u8str_P(PSTR(" -----"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,26 +347,51 @@ void lcd_implementation_clear() { lcd.clear(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll the PSTR 'text' in a 'len' wide field for 'time' milliseconds at position col,line
|
// Scroll the PSTR 'text' in a 'len' wide field for 'time' milliseconds at position col,line
|
||||||
void lcd_scroll(const int16_t col, const int16_t line, const char* const text, const int16_t len, const int16_t time) {
|
void lcd_scroll(const uint8_t col, const uint8_t line, const char* const text, const uint8_t len, const int16_t time) {
|
||||||
#if 1
|
uint8_t slen = utf8_strlen_P(text);
|
||||||
lcd_put_u8str(text);
|
if (slen < len) {
|
||||||
#else
|
// Fits into,
|
||||||
char tmp[LCD_WIDTH + 1] = {0};
|
lcd_moveto(col, line);
|
||||||
int16_t n = MAX(utf8_strlen_P(text) - len, 0);
|
lcd_put_u8str_max_P(text, len);
|
||||||
for (int16_t i = 0; i <= n; i++) {
|
while (slen < len) {
|
||||||
utf8_strncpy_p(tmp, text + i, MIN(len, LCD_WIDTH));
|
lcd_put_wchar(' ');
|
||||||
lcd_moveto(col, line);
|
++slen;
|
||||||
lcd_put_u8str(tmp);
|
|
||||||
delay(time / MAX(n, 1));
|
|
||||||
}
|
}
|
||||||
#endif
|
safe_delay(time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char* p = text;
|
||||||
|
int dly = time / MAX(slen, 1);
|
||||||
|
for (uint8_t i = 0; i <= slen; i++) {
|
||||||
|
|
||||||
|
// Go to the correct place
|
||||||
|
lcd_moveto(col, line);
|
||||||
|
|
||||||
|
// Print the text
|
||||||
|
lcd_put_u8str_max_P(p, len);
|
||||||
|
|
||||||
|
// Fill with spaces
|
||||||
|
uint8_t ix = slen - i;
|
||||||
|
while (ix < len) {
|
||||||
|
lcd_put_wchar(' ');
|
||||||
|
++ix;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay
|
||||||
|
safe_delay(dly);
|
||||||
|
|
||||||
|
// Advance to the next UTF8 valid position
|
||||||
|
p++;
|
||||||
|
while (!START_OF_UTF8_CHAR(pgm_read_byte(p))) p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void logo_lines(const char* const extra) {
|
static void logo_lines(const char* const extra) {
|
||||||
int16_t indent = (LCD_WIDTH - 8 - utf8_strlen_P(extra)) / 2;
|
int16_t indent = (LCD_WIDTH - 8 - utf8_strlen_P(extra)) / 2;
|
||||||
lcd_moveto(indent, 0); lcd_put_wchar('\x00'); lcd_put_u8str_rom(PSTR( "------" )); lcd_put_wchar('\x01');
|
lcd_moveto(indent, 0); lcd_put_wchar('\x00'); lcd_put_u8str_P(PSTR( "------" )); lcd_put_wchar('\x01');
|
||||||
lcd_moveto(indent, 1); lcd_put_u8str_rom(PSTR("|Marlin|")); lcd_put_u8str_rom(extra);
|
lcd_moveto(indent, 1); lcd_put_u8str_P(PSTR("|Marlin|")); lcd_put_u8str_P(extra);
|
||||||
lcd_moveto(indent, 2); lcd_put_wchar('\x02'); lcd_put_u8str_rom(PSTR( "------" )); lcd_put_wchar('\x03');
|
lcd_moveto(indent, 2); lcd_put_wchar('\x02'); lcd_put_u8str_P(PSTR( "------" )); lcd_put_wchar('\x03');
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_bootscreen() {
|
void lcd_bootscreen() {
|
||||||
|
@ -379,7 +404,7 @@ void lcd_implementation_clear() { lcd.clear(); }
|
||||||
lcd_erase_line(3); \
|
lcd_erase_line(3); \
|
||||||
if (utf8_strlen(STRING) <= LCD_WIDTH) { \
|
if (utf8_strlen(STRING) <= LCD_WIDTH) { \
|
||||||
lcd_moveto((LCD_WIDTH - utf8_strlen_P(PSTR(STRING))) / 2, 3); \
|
lcd_moveto((LCD_WIDTH - utf8_strlen_P(PSTR(STRING))) / 2, 3); \
|
||||||
lcd_put_u8str_rom(PSTR(STRING)); \
|
lcd_put_u8str_P(PSTR(STRING)); \
|
||||||
safe_delay(DELAY); \
|
safe_delay(DELAY); \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
|
@ -452,10 +477,10 @@ void lcd_kill_screen() {
|
||||||
lcd_moveto(0, 2);
|
lcd_moveto(0, 2);
|
||||||
#else
|
#else
|
||||||
lcd_moveto(0, 2);
|
lcd_moveto(0, 2);
|
||||||
lcd_put_u8str_rom(PSTR(MSG_HALTED));
|
lcd_put_u8str_P(PSTR(MSG_HALTED));
|
||||||
lcd_moveto(0, 3);
|
lcd_moveto(0, 3);
|
||||||
#endif
|
#endif
|
||||||
lcd_put_u8str_rom(PSTR(MSG_PLEASE_RESET));
|
lcd_put_u8str_P(PSTR(MSG_PLEASE_RESET));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -473,7 +498,7 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
|
||||||
else {
|
else {
|
||||||
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
||||||
if (!axis_known_position[axis])
|
if (!axis_known_position[axis])
|
||||||
lcd_put_u8str_rom(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
lcd_put_u8str_P(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
lcd_put_u8str(value);
|
lcd_put_u8str(value);
|
||||||
|
@ -634,11 +659,11 @@ static void lcd_implementation_status_screen() {
|
||||||
|
|
||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
lcd_moveto(0, 2);
|
lcd_moveto(0, 2);
|
||||||
lcd_put_u8str_rom(PSTR("SD"));
|
lcd_put_u8str_P(PSTR("SD"));
|
||||||
if (IS_SD_PRINTING)
|
if (IS_SD_PRINTING)
|
||||||
lcd_put_u8str(itostr3(card.percentDone()));
|
lcd_put_u8str(itostr3(card.percentDone()));
|
||||||
else
|
else
|
||||||
lcd_put_u8str_rom(PSTR("---"));
|
lcd_put_u8str_P(PSTR("---"));
|
||||||
lcd_put_wchar('%');
|
lcd_put_wchar('%');
|
||||||
#endif // SDSUPPORT
|
#endif // SDSUPPORT
|
||||||
|
|
||||||
|
@ -698,11 +723,11 @@ static void lcd_implementation_status_screen() {
|
||||||
#if LCD_WIDTH >= 20 && ENABLED(SDSUPPORT)
|
#if LCD_WIDTH >= 20 && ENABLED(SDSUPPORT)
|
||||||
|
|
||||||
lcd_moveto(7, 2);
|
lcd_moveto(7, 2);
|
||||||
lcd_put_u8str_rom(PSTR("SD"));
|
lcd_put_u8str_P(PSTR("SD"));
|
||||||
if (IS_SD_PRINTING)
|
if (IS_SD_PRINTING)
|
||||||
lcd_put_u8str(itostr3(card.percentDone()));
|
lcd_put_u8str(itostr3(card.percentDone()));
|
||||||
else
|
else
|
||||||
lcd_put_u8str_rom(PSTR("---"));
|
lcd_put_u8str_P(PSTR("---"));
|
||||||
lcd_put_wchar('%');
|
lcd_put_wchar('%');
|
||||||
|
|
||||||
#endif // LCD_WIDTH >= 20 && SDSUPPORT
|
#endif // LCD_WIDTH >= 20 && SDSUPPORT
|
||||||
|
@ -739,9 +764,9 @@ static void lcd_implementation_status_screen() {
|
||||||
// Show Filament Diameter and Volumetric Multiplier %
|
// Show Filament Diameter and Volumetric Multiplier %
|
||||||
// After allowing lcd_status_message to show for 5 seconds
|
// After allowing lcd_status_message to show for 5 seconds
|
||||||
if (ELAPSED(millis(), previous_lcd_status_ms + 5000UL)) {
|
if (ELAPSED(millis(), previous_lcd_status_ms + 5000UL)) {
|
||||||
lcd_put_u8str_rom(PSTR("Dia "));
|
lcd_put_u8str_P(PSTR("Dia "));
|
||||||
lcd_put_u8str(ftostr12ns(filament_width_meas));
|
lcd_put_u8str(ftostr12ns(filament_width_meas));
|
||||||
lcd_put_u8str_rom(PSTR(" V"));
|
lcd_put_u8str_P(PSTR(" V"));
|
||||||
lcd_put_u8str(itostr3(100.0 * (
|
lcd_put_u8str(itostr3(100.0 * (
|
||||||
parser.volumetric_enabled
|
parser.volumetric_enabled
|
||||||
? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
|
? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
|
||||||
|
@ -756,35 +781,76 @@ static void lcd_implementation_status_screen() {
|
||||||
|
|
||||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||||
static bool last_blink = false;
|
static bool last_blink = false;
|
||||||
const uint8_t slen = utf8_strlen(lcd_status_message);
|
|
||||||
const char *stat = lcd_status_message + status_scroll_pos;
|
// Get the UTF8 character count of the string
|
||||||
if (slen <= LCD_WIDTH)
|
uint8_t slen = utf8_strlen(lcd_status_message);
|
||||||
lcd_put_u8str(stat); // The string isn't scrolling
|
|
||||||
|
// If the string fits into the LCD, just print it and do not scroll it
|
||||||
|
if (slen <= LCD_WIDTH) {
|
||||||
|
|
||||||
|
// The string isn't scrolling and may not fill the screen
|
||||||
|
lcd_put_u8str(lcd_status_message);
|
||||||
|
|
||||||
|
// Fill the rest with spaces
|
||||||
|
while (slen < LCD_WIDTH) {
|
||||||
|
lcd_put_wchar(' ');
|
||||||
|
++slen;
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (status_scroll_pos <= slen - LCD_WIDTH)
|
// String is larger than the available space in screen.
|
||||||
lcd_put_u8str(stat); // The string fills the screen
|
|
||||||
|
// Get a pointer to the next valid UTF8 character
|
||||||
|
const char *stat = lcd_status_message + status_scroll_offset;
|
||||||
|
|
||||||
|
// Get the string remaining length
|
||||||
|
const uint8_t rlen = utf8_strlen(stat);
|
||||||
|
|
||||||
|
// If we have enough characters to display
|
||||||
|
if (rlen >= LCD_WIDTH) {
|
||||||
|
// The remaining string fills the screen - Print it
|
||||||
|
lcd_put_u8str_max(stat, LCD_WIDTH);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
uint8_t chars = LCD_WIDTH;
|
|
||||||
if (status_scroll_pos < slen) { // First string still visible
|
// The remaining string does not completely fill the screen
|
||||||
lcd_put_u8str(stat); // The string leaves space
|
lcd_put_u8str_max(stat, LCD_WIDTH); // The string leaves space
|
||||||
chars -= slen - status_scroll_pos; // Amount of space left
|
uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters
|
||||||
}
|
|
||||||
lcd_put_wchar('.'); // Always at 1+ spaces left, draw a dot
|
lcd_put_wchar('.'); // Always at 1+ spaces left, draw a dot
|
||||||
if (--chars) {
|
if (--chars) { // Draw a second dot if there's space
|
||||||
if (status_scroll_pos < slen + 1) // Draw a second dot if there's space
|
lcd_put_wchar('.');
|
||||||
--chars, lcd_put_wchar('.');
|
if (--chars)
|
||||||
if (chars) lcd_put_u8str_max(lcd_status_message, chars); // Print a second copy of the message
|
lcd_put_u8str_max(lcd_status_message, chars); // Print a second copy of the message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (last_blink != blink) {
|
if (last_blink != blink) {
|
||||||
last_blink = blink;
|
last_blink = blink;
|
||||||
// Skip any non-printing bytes
|
|
||||||
if (status_scroll_pos < slen) while (!PRINTABLE(lcd_status_message[status_scroll_pos])) status_scroll_pos++;
|
// Adjust by complete UTF8 characters
|
||||||
if (++status_scroll_pos >= slen + 2) status_scroll_pos = 0;
|
if (status_scroll_offset < slen) {
|
||||||
|
status_scroll_offset++;
|
||||||
|
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
|
||||||
|
status_scroll_offset++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
status_scroll_offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
lcd_put_u8str(lcd_status_message);
|
UNUSED(blink);
|
||||||
|
|
||||||
|
// Get the UTF8 character count of the string
|
||||||
|
uint8_t slen = utf8_strlen(lcd_status_message);
|
||||||
|
|
||||||
|
// Just print the string to the LCD
|
||||||
|
lcd_put_u8str_max(lcd_status_message, LCD_WIDTH);
|
||||||
|
|
||||||
|
// Fill the rest with spaces if there are missing spaces
|
||||||
|
while (slen < LCD_WIDTH) {
|
||||||
|
lcd_put_wchar(' ');
|
||||||
|
++slen;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +875,7 @@ static void lcd_implementation_status_screen() {
|
||||||
int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2;
|
int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2;
|
||||||
while (--pad >= 0) { lcd_put_wchar(' '); n--; }
|
while (--pad >= 0) { lcd_put_wchar(' '); n--; }
|
||||||
}
|
}
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
if (valstr) n -= lcd_put_u8str_max(valstr, n);
|
if (valstr) n -= lcd_put_u8str_max(valstr, n);
|
||||||
for (; n > 0; --n) lcd_put_wchar(' ');
|
for (; n > 0; --n) lcd_put_wchar(' ');
|
||||||
}
|
}
|
||||||
|
@ -818,7 +884,7 @@ static void lcd_implementation_status_screen() {
|
||||||
uint8_t n = LCD_WIDTH - 2;
|
uint8_t n = LCD_WIDTH - 2;
|
||||||
lcd_moveto(0, row);
|
lcd_moveto(0, row);
|
||||||
lcd_put_wchar(sel ? pre_char : ' ');
|
lcd_put_wchar(sel ? pre_char : ' ');
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
while (n--) lcd_put_wchar(' ');
|
while (n--) lcd_put_wchar(' ');
|
||||||
lcd_put_wchar(post_char);
|
lcd_put_wchar(post_char);
|
||||||
}
|
}
|
||||||
|
@ -827,7 +893,7 @@ static void lcd_implementation_status_screen() {
|
||||||
uint8_t n = LCD_WIDTH - 2 - utf8_strlen(data);
|
uint8_t n = LCD_WIDTH - 2 - utf8_strlen(data);
|
||||||
lcd_moveto(0, row);
|
lcd_moveto(0, row);
|
||||||
lcd_put_wchar(sel ? pre_char : ' ');
|
lcd_put_wchar(sel ? pre_char : ' ');
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
lcd_put_wchar(':');
|
lcd_put_wchar(':');
|
||||||
while (n--) lcd_put_wchar(' ');
|
while (n--) lcd_put_wchar(' ');
|
||||||
lcd_put_u8str(data);
|
lcd_put_u8str(data);
|
||||||
|
@ -836,10 +902,10 @@ static void lcd_implementation_status_screen() {
|
||||||
uint8_t n = LCD_WIDTH - 2 - utf8_strlen_P(data);
|
uint8_t n = LCD_WIDTH - 2 - utf8_strlen_P(data);
|
||||||
lcd_moveto(0, row);
|
lcd_moveto(0, row);
|
||||||
lcd_put_wchar(sel ? pre_char : ' ');
|
lcd_put_wchar(sel ? pre_char : ' ');
|
||||||
n -= lcd_put_u8str_max_rom(pstr, n);
|
n -= lcd_put_u8str_max_P(pstr, n);
|
||||||
lcd_put_wchar(':');
|
lcd_put_wchar(':');
|
||||||
while (n--) lcd_put_wchar(' ');
|
while (n--) lcd_put_wchar(' ');
|
||||||
lcd_put_u8str_rom(data);
|
lcd_put_u8str_P(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DRAWMENU_SETTING_EDIT_GENERIC(_src) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', _src)
|
#define DRAWMENU_SETTING_EDIT_GENERIC(_src) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', _src)
|
||||||
|
@ -847,7 +913,7 @@ static void lcd_implementation_status_screen() {
|
||||||
|
|
||||||
void lcd_implementation_drawedit(const char* pstr, const char* const value=NULL) {
|
void lcd_implementation_drawedit(const char* pstr, const char* const value=NULL) {
|
||||||
lcd_moveto(1, 1);
|
lcd_moveto(1, 1);
|
||||||
lcd_put_u8str_rom(pstr);
|
lcd_put_u8str_P(pstr);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
lcd_put_wchar(':');
|
lcd_put_wchar(':');
|
||||||
int len = utf8_strlen(value);
|
int len = utf8_strlen(value);
|
||||||
|
@ -1293,7 +1359,7 @@ static void lcd_implementation_status_screen() {
|
||||||
if (!isnan(ubl.z_values[x][inverted_y]))
|
if (!isnan(ubl.z_values[x][inverted_y]))
|
||||||
lcd_put_u8str(ftostr43sign(ubl.z_values[x][inverted_y]));
|
lcd_put_u8str(ftostr43sign(ubl.z_values[x][inverted_y]));
|
||||||
else
|
else
|
||||||
lcd_put_u8str_rom(PSTR(" -----"));
|
lcd_put_u8str_P(PSTR(" -----"));
|
||||||
|
|
||||||
#else // 16x4 or 20x4 display
|
#else // 16x4 or 20x4 display
|
||||||
|
|
||||||
|
@ -1312,7 +1378,7 @@ static void lcd_implementation_status_screen() {
|
||||||
if (!isnan(ubl.z_values[x][inverted_y]))
|
if (!isnan(ubl.z_values[x][inverted_y]))
|
||||||
lcd_put_u8str(ftostr43sign(ubl.z_values[x][inverted_y]));
|
lcd_put_u8str(ftostr43sign(ubl.z_values[x][inverted_y]));
|
||||||
else
|
else
|
||||||
lcd_put_u8str_rom(PSTR(" -----"));
|
lcd_put_u8str_P(PSTR(" -----"));
|
||||||
|
|
||||||
#endif // LCD_HEIGHT > 3
|
#endif // LCD_HEIGHT > 3
|
||||||
}
|
}
|
||||||
|
|
|
@ -563,8 +563,7 @@ uint32_t USB_DMA_Status (uint32_t EPNum) {
|
||||||
uint32_t ptr, val;
|
uint32_t ptr, val;
|
||||||
|
|
||||||
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */
|
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */
|
||||||
if (ptr == 0)
|
if (ptr == 0) return (USB_DMA_INVALID);
|
||||||
return (USB_DMA_INVALID);
|
|
||||||
|
|
||||||
val = *((uint32_t *)(ptr + 3*4)); /* Status Information */
|
val = *((uint32_t *)(ptr + 3*4)); /* Status Information */
|
||||||
switch ((val >> 1) & 0x0F) {
|
switch ((val >> 1) & 0x0F) {
|
||||||
|
@ -596,13 +595,8 @@ uint32_t USB_DMA_Status (uint32_t EPNum) {
|
||||||
|
|
||||||
uint32_t USB_DMA_BufAdr (uint32_t EPNum) {
|
uint32_t USB_DMA_BufAdr (uint32_t EPNum) {
|
||||||
uint32_t ptr, val;
|
uint32_t ptr, val;
|
||||||
|
|
||||||
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */
|
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */
|
||||||
if (ptr == 0)
|
if (ptr == 0) return ((uint32_t)(-1)); /* DMA Invalid */
|
||||||
{
|
|
||||||
return ((uint32_t)(-1)); /* DMA Invalid */
|
|
||||||
}
|
|
||||||
|
|
||||||
val = *((uint32_t *)(ptr + 2*4)); /* Buffer Address */
|
val = *((uint32_t *)(ptr + 2*4)); /* Buffer Address */
|
||||||
return (val); /* Current Address */
|
return (val); /* Current Address */
|
||||||
}
|
}
|
||||||
|
@ -619,12 +613,8 @@ uint32_t USB_DMA_BufAdr (uint32_t EPNum) {
|
||||||
|
|
||||||
uint32_t USB_DMA_BufCnt (uint32_t EPNum) {
|
uint32_t USB_DMA_BufCnt (uint32_t EPNum) {
|
||||||
uint32_t ptr, val;
|
uint32_t ptr, val;
|
||||||
|
|
||||||
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */
|
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */
|
||||||
if (ptr == 0)
|
if (ptr == 0) return ((uint32_t)(-1)); /* DMA Invalid */
|
||||||
{
|
|
||||||
return ((uint32_t)(-1)); /* DMA Invalid */
|
|
||||||
}
|
|
||||||
val = *((uint32_t *)(ptr + 3*4)); /* Status Information */
|
val = *((uint32_t *)(ptr + 3*4)); /* Status Information */
|
||||||
return (val >> 16); /* Current Count */
|
return (val >> 16); /* Current Count */
|
||||||
}
|
}
|
||||||
|
@ -695,7 +685,7 @@ void USB_IRQHandler (void) {
|
||||||
#if USB_SOF_EVENT
|
#if USB_SOF_EVENT
|
||||||
/* Start of Frame Interrupt */
|
/* Start of Frame Interrupt */
|
||||||
if (disr & FRAME_INT) {
|
if (disr & FRAME_INT) {
|
||||||
LPC_USB->USBDevIntClr = FRAME_INT;
|
LPC_USB->USBDevIntClr = FRAME_INT;
|
||||||
USB_SOF_Event();
|
USB_SOF_Event();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -703,7 +693,7 @@ void USB_IRQHandler (void) {
|
||||||
#if USB_ERROR_EVENT
|
#if USB_ERROR_EVENT
|
||||||
/* Error Interrupt */
|
/* Error Interrupt */
|
||||||
if (disr & ERR_INT) {
|
if (disr & ERR_INT) {
|
||||||
LPC_USB->USBDevIntClr = ERR_INT;
|
LPC_USB->USBDevIntClr = ERR_INT;
|
||||||
WrCmd(CMD_RD_ERR_STAT);
|
WrCmd(CMD_RD_ERR_STAT);
|
||||||
val = RdCmdDat(DAT_RD_ERR_STAT);
|
val = RdCmdDat(DAT_RD_ERR_STAT);
|
||||||
USB_Error_Event(val);
|
USB_Error_Event(val);
|
||||||
|
|
Loading…
Reference in a new issue