Browse Source

DOGLCD and LCD_PROGRESS_BAR to coexist

Small changes (and formatting to confuse the diff’er) which first
allows DOGLCD and LCD_PROGRESS_BAR to be enabled in tandem, then a
#warning (rather than error) that the extra progress bar / message
options don’t apply to graphical displays at this time. This leaves
open perhaps combining the progress bar and message area in some future
(or forked custom) graphical LCD display arrangement (at which time the
relevant variables may be moved into ultralcd.cpp with externs in
ultralcd.h). I also added a conditional error that the progress bar and
the filament display may not work well together.
pull/1/head
Scott Lahteine 10 years ago
parent
commit
326b925557
  1. 8
      Marlin/Configuration_adv.h
  2. 424
      Marlin/dogm_lcd_implementation.h
  3. 15
      Marlin/ultralcd.cpp
  4. 2
      Marlin/ultralcd.h

8
Marlin/Configuration_adv.h

@ -297,7 +297,7 @@
// using:
//#define MENU_ADDAUTOSTART
// Show a progress bar on the LCD when printing from SD?
// Show a progress bar on HD44780 LCDs for SD printing
//#define LCD_PROGRESS_BAR
#ifdef LCD_PROGRESS_BAR
@ -309,6 +309,12 @@
#define PROGRESS_MSG_EXPIRE 0
// Enable this to show messages for MSG_TIME then hide them
//#define PROGRESS_MSG_ONCE
#ifdef DOGLCD
#warning LCD_PROGRESS_BAR does not apply to graphical displays at this time.
#endif
#ifdef FILAMENT_LCD_DISPLAY
#error LCD_PROGRESS_BAR and FILAMENT_LCD_DISPLAY are not fully compatible. Comment out this line to use both.
#endif
#endif
// The hardware watchdog should reset the microcontroller disabling all outputs, in case the firmware gets stuck and doesn't do temperature regulation.

424
Marlin/dogm_lcd_implementation.h

@ -1,19 +1,20 @@
/**
*dogm_lcd_implementation.h
* dogm_lcd_implementation.h
*
*Graphics LCD implementation for 128x64 pixel LCDs by STB for ErikZalm/Marlin
*Demonstrator: http://www.reprap.org/wiki/STB_Electronics
*License: http://opensource.org/licenses/BSD-3-Clause
* Graphics LCD implementation for 128x64 pixel LCDs by STB for ErikZalm/Marlin
* Demonstrator: http://www.reprap.org/wiki/STB_Electronics
* License: http://opensource.org/licenses/BSD-3-Clause
*
*With the use of:
*u8glib by Oliver Kraus
*http://code.google.com/p/u8glib/
*License: http://opensource.org/licenses/BSD-3-Clause
* With the use of:
* u8glib by Oliver Kraus
* http://code.google.com/p/u8glib/
* License: http://opensource.org/licenses/BSD-3-Clause
*/
#ifndef DOGM_LCD_IMPLEMENTATION_H
#define DOGM_LCD_IMPLEMENTATION_H
#ifndef ULTRA_LCD_IMPLEMENTATION_DOGM_H
#define ULTRA_LCD_IMPLEMENTATION_DOGM_H
#define MARLIN_VERSION "1.0.2"
/**
* Implementation of the LCD display routines for a DOGM128 graphic display. These are common LCD 128x64 pixel graphic displays.
@ -51,12 +52,12 @@
*/
// DOGM parameters (size in pixels)
#define DOG_CHAR_WIDTH 6
#define DOG_CHAR_HEIGHT 12
#define DOG_CHAR_WIDTH_LARGE 9
#define DOG_CHAR_HEIGHT_LARGE 18
#define DOG_CHAR_WIDTH 6
#define DOG_CHAR_HEIGHT 12
#define DOG_CHAR_WIDTH_LARGE 9
#define DOG_CHAR_HEIGHT_LARGE 18
#define START_ROW 0
#define START_ROW 0
/* Custom characters defined in font font_6x10_marlin.c */
#define LCD_STR_DEGREE "\xB0"
@ -69,7 +70,7 @@
#define LCD_STR_BEDTEMP "\xFE"
#define LCD_STR_THERMOMETER "\xFF"
#define FONT_STATUSMENU u8g_font_6x9
#define FONT_STATUSMENU u8g_font_6x9
int lcd_contrast;
@ -82,78 +83,57 @@ U8GLIB_ST7920_128X64_RRD u8g(0);
U8GLIB_NHD_C12864 u8g(DOGLCD_CS, DOGLCD_A0);
#else
// for regular DOGM128 display with HW-SPI
U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0
U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0
#endif
static void lcd_implementation_init()
{
#ifdef LCD_PIN_BL
pinMode(LCD_PIN_BL, OUTPUT); // Enable LCD backlight
digitalWrite(LCD_PIN_BL, HIGH);
#endif
static void lcd_implementation_init() {
#ifdef LCD_PIN_BL
pinMode(LCD_PIN_BL, OUTPUT); // Enable LCD backlight
digitalWrite(LCD_PIN_BL, HIGH);
#endif
u8g.setContrast(lcd_contrast);
// Uncomment this if you have the first generation (V1.10) of STBs board
// pinMode(17, OUTPUT); // Enable LCD backlight
// digitalWrite(17, HIGH);
u8g.firstPage();
do {
u8g.setFont(u8g_font_6x10_marlin);
u8g.setColorIndex(1);
u8g.drawBox (0, 0, u8g.getWidth(), u8g.getHeight());
u8g.setColorIndex(1);
} while( u8g.nextPage() );
#ifdef LCD_SCREEN_ROT_90
u8g.setRot90(); // Rotate screen by 90°
#endif
u8g.setContrast(lcd_contrast);
#ifdef LCD_SCREEN_ROT_180
u8g.setRot180(); // Rotate screen by 180°
#endif
/*
// Uncomment this if you have the first generation (V1.10) of STBs board
#ifdef LCD_SCREEN_ROT_270
u8g.setRot270(); // Rotate screen by 270°
#endif
pinMode(17, OUTPUT); // Enable LCD backlight
digitalWrite(17, HIGH);
u8g.firstPage();
do {
// RepRap init bmp
u8g.drawBitmapP(7,7,START_BMPBYTEWIDTH,START_BMPHEIGHT,start_bmp);
// Welcome message
u8g.setFont(u8g_font_5x8);
u8g.drawStr(7,51,"V1.0.2 - marlin.reprap.org");
} while( u8g.nextPage() );
}
//*/
u8g.firstPage();
do {
u8g.setFont(u8g_font_6x10_marlin);
u8g.setColorIndex(1);
u8g.drawBox (0, 0, u8g.getWidth(), u8g.getHeight());
u8g.setColorIndex(1);
} while( u8g.nextPage() );
static void lcd_implementation_clear()
{
// NO NEED TO IMPLEMENT LIKE SO. Picture loop automatically clears the display.
//
// Check this article: http://arduino.cc/forum/index.php?topic=91395.25;wap2
//
// u8g.firstPage();
// do {
// u8g.setColorIndex(0);
// u8g.drawBox (0, 0, u8g.getWidth(), u8g.getHeight());
// u8g.setColorIndex(1);
// } while( u8g.nextPage() );
#if defined(LCD_SCREEN_ROT_90)
u8g.setRot90(); // Rotate screen by 90°
#elif defined(LCD_SCREEN_ROT_180)
u8g.setRot180(); // Rotate screen by 180°
#elif defined(LCD_SCREEN_ROT_270)
u8g.setRot270(); // Rotate screen by 270°
#endif
u8g.firstPage();
do {
// RepRap init bmp
u8g.drawBitmapP(7,7,START_BMPBYTEWIDTH,START_BMPHEIGHT,start_bmp);
// Welcome message
u8g.setFont(u8g_font_5x8);
u8g.drawStr(7, 51, "V" MARLIN_VERSION " - marlin.reprap.org");
} while( u8g.nextPage() );
}
static void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
static void lcd_printPGM(const char* str)
{
char c;
while((c = pgm_read_byte(str++)) != '\0')
{
u8g.print(c);
}
static void lcd_printPGM(const char* str) {
char c;
while ((c = pgm_read_byte(str++))) u8g.print(c);
}
static void _draw_heater_status(int x, int heater) {
@ -176,49 +156,44 @@ static void _draw_heater_status(int x, int heater) {
}
}
static void lcd_implementation_status_screen()
{
static void lcd_implementation_status_screen() {
static unsigned char fan_rot = 0;
u8g.setColorIndex(1); // black on white
static unsigned char fan_rot = 0;
// Symbols menu graphics, animated fan
u8g.drawBitmapP(9,1,STATUS_SCREENBYTEWIDTH,STATUS_SCREENHEIGHT, (blink % 2) && fanSpeed ? status_screen0_bmp : status_screen1_bmp);
#ifdef SDSUPPORT
//SD Card Symbol
u8g.drawBox(42,42,8,7);
u8g.drawBox(50,44,2,5);
u8g.drawFrame(42,49,10,4);
u8g.drawPixel(50,43);
// Progress bar
u8g.drawFrame(54,49,73,4);
u8g.setColorIndex(1); // black on white
// Symbols menu graphics, animated fan
u8g.drawBitmapP(9,1,STATUS_SCREENBYTEWIDTH,STATUS_SCREENHEIGHT, (blink % 2) && fanSpeed ? status_screen0_bmp : status_screen1_bmp);
// SD Card Progress bar and clock
u8g.setFont(FONT_STATUSMENU);
#ifdef SDSUPPORT
// SD Card Symbol
u8g.drawBox(42,42,8,7);
u8g.drawBox(50,44,2,5);
u8g.drawFrame(42,49,10,4);
u8g.drawPixel(50,43);
// Progress bar frame
u8g.drawFrame(54,49,73,4);
// SD Card Progress bar and clock
u8g.setFont(FONT_STATUSMENU);
if (IS_SD_PRINTING)
{
// Progress bar
u8g.drawBox(55,50, (unsigned int)( (71 * card.percentDone())/100) ,2);
}
if (IS_SD_PRINTING) {
// Progress bar solid part
u8g.drawBox(55, 50, (unsigned int)(71.f * card.percentDone() / 100.f), 2);
}
u8g.setPrintPos(80,47);
if (starttime != 0) {
uint16_t time = millis()/60000 - starttime/60000;
u8g.print(itostr2(time/60));
u8g.print(':');
u8g.print(itostr2(time%60));
}
else {
// do nothing
}
u8g.setPrintPos(80,47);
if(starttime != 0)
{
uint16_t time = millis()/60000 - starttime/60000;
u8g.print(itostr2(time/60));
u8g.print(':');
u8g.print(itostr2(time%60));
}else{
lcd_printPGM(PSTR("--:--"));
}
#endif
lcd_printPGM(PSTR("--:--"));
}
#endif
// Extruders
_draw_heater_status(6, 0);
@ -232,107 +207,101 @@ static void lcd_implementation_status_screen()
// Heatbed
_draw_heater_status(81, -1);
// Fan
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(104,27);
#if defined(FAN_PIN) && FAN_PIN > -1
u8g.print(itostr3(int((fanSpeed*100)/256 + 1)));
u8g.print("%");
#else
u8g.print("---");
#endif
// X, Y, Z-Coordinates
u8g.setFont(FONT_STATUSMENU);
u8g.drawBox(0,29,128,10);
u8g.setColorIndex(0); // white on black
u8g.setPrintPos(2,37);
u8g.print("X");
u8g.drawPixel(8,33);
u8g.drawPixel(8,35);
u8g.setPrintPos(10,37);
u8g.print(ftostr31ns(current_position[X_AXIS]));
u8g.setPrintPos(43,37);
lcd_printPGM(PSTR("Y"));
u8g.drawPixel(49,33);
u8g.drawPixel(49,35);
u8g.setPrintPos(51,37);
u8g.print(ftostr31ns(current_position[Y_AXIS]));
u8g.setPrintPos(83,37);
u8g.print("Z");
u8g.drawPixel(89,33);
u8g.drawPixel(89,35);
u8g.setPrintPos(91,37);
u8g.print(ftostr31(current_position[Z_AXIS]));
u8g.setColorIndex(1); // black on white
// Fan
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(104,27);
#if defined(FAN_PIN) && FAN_PIN > -1
u8g.print(itostr3(int((fanSpeed*100)/256 + 1)));
u8g.print("%");
#else
u8g.print("---");
#endif
// X, Y, Z-Coordinates
u8g.setFont(FONT_STATUSMENU);
u8g.drawBox(0,29,128,10);
u8g.setColorIndex(0); // white on black
u8g.setPrintPos(2,37);
u8g.print("X");
u8g.drawPixel(8,33);
u8g.drawPixel(8,35);
u8g.setPrintPos(10,37);
u8g.print(ftostr31ns(current_position[X_AXIS]));
u8g.setPrintPos(43,37);
lcd_printPGM(PSTR("Y"));
u8g.drawPixel(49,33);
u8g.drawPixel(49,35);
u8g.setPrintPos(51,37);
u8g.print(ftostr31ns(current_position[Y_AXIS]));
u8g.setPrintPos(83,37);
u8g.print("Z");
u8g.drawPixel(89,33);
u8g.drawPixel(89,35);
u8g.setPrintPos(91,37);
u8g.print(ftostr31(current_position[Z_AXIS]));
u8g.setColorIndex(1); // black on white
// Feedrate
u8g.setFont(u8g_font_6x10_marlin);
u8g.setPrintPos(3,49);
u8g.print(LCD_STR_FEEDRATE[0]);
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(12,48);
u8g.print(itostr3(feedmultiply));
u8g.print('%');
// Status line
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(0,61);
#ifndef FILAMENT_LCD_DISPLAY
u8g.print(lcd_status_message);
#else
if(message_millis+5000>millis()){ //Display both Status message line and Filament display on the last line
u8g.print(lcd_status_message);
}
else
{
lcd_printPGM(PSTR("dia:"));
u8g.print(ftostr12ns(filament_width_meas));
lcd_printPGM(PSTR(" factor:"));
u8g.print(itostr3(extrudemultiply));
u8g.print('%');
}
#endif
// Feedrate
u8g.setFont(u8g_font_6x10_marlin);
u8g.setPrintPos(3,49);
u8g.print(LCD_STR_FEEDRATE[0]);
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(12,48);
u8g.print(itostr3(feedmultiply));
u8g.print('%');
// Status line
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(0,61);
#ifndef FILAMENT_LCD_DISPLAY
u8g.print(lcd_status_message);
#else
if (millis() < message_millis + 5000) { //Display both Status message line and Filament display on the last line
u8g.print(lcd_status_message);
}
else {
lcd_printPGM(PSTR("dia:"));
u8g.print(ftostr12ns(filament_width_meas));
lcd_printPGM(PSTR(" factor:"));
u8g.print(itostr3(extrudemultiply));
u8g.print('%');
}
#endif
}
static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char)
{
char c;
uint8_t n = LCD_WIDTH - 1 - 2;
if ((pre_char == '>') || (pre_char == LCD_STR_UPLEVEL[0] ))
{
u8g.setColorIndex(1); // black on white
u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
u8g.setColorIndex(0); // following text must be white on black
} else u8g.setColorIndex(1); // unmarked text is black on white
u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
u8g.print(pre_char == '>' ? ' ' : pre_char); // Row selector is obsolete
while( (c = pgm_read_byte(pstr)) != '\0' )
{
u8g.print(c);
pstr++;
n--;
}
while(n--){
u8g.print(' ');
}
u8g.print(post_char);
u8g.print(' ');
u8g.setColorIndex(1); // restore settings to black on white
static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char) {
char c;
uint8_t n = LCD_WIDTH - 1 - 2;
if ((pre_char == '>') || (pre_char == LCD_STR_UPLEVEL[0] )) {
u8g.setColorIndex(1); // black on white
u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
u8g.setColorIndex(0); // following text must be white on black
}
else {
u8g.setColorIndex(1); // unmarked text is black on white
}
u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
u8g.print(pre_char == '>' ? ' ' : pre_char); // Row selector is obsolete
while((c = pgm_read_byte(pstr))) {
u8g.print(c);
pstr++;
n--;
}
while(n--) u8g.print(' ');
u8g.print(post_char);
u8g.print(' ');
u8g.setColorIndex(1); // restore settings to black on white
}
static void _drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, const char* data, bool pgm) {
char c;
uint8_t n = LCD_WIDTH - 1 - 2 - (pgm ? strlen_P(data) : strlen(data));
u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
u8g.print(pre_char);
@ -391,14 +360,13 @@ static void _drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char p
#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
void lcd_implementation_drawedit(const char* pstr, char* value)
{
u8g.setPrintPos(0 * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
u8g.setFont(u8g_font_9x18);
lcd_printPGM(pstr);
u8g.print(':');
u8g.setPrintPos((14 - strlen(value)) * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
u8g.print(value);
void lcd_implementation_drawedit(const char* pstr, char* value) {
u8g.setPrintPos(0 * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
u8g.setFont(u8g_font_9x18);
lcd_printPGM(pstr);
u8g.print(':');
u8g.setPrintPos((14 - strlen(value)) * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
u8g.print(value);
}
static void _drawmenu_sd(uint8_t row, const char* pstr, const char* filename, char * const longFilename, bool isDir, bool isSelected) {
@ -417,7 +385,7 @@ static void _drawmenu_sd(uint8_t row, const char* pstr, const char* filename, ch
}
u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
u8g.print(' '); // Indent by 1 char
u8g.print(' '); // Indent by 1 char
if (isDir) u8g.print(LCD_STR_FOLDER[0]);
@ -445,20 +413,16 @@ static void _drawmenu_sd(uint8_t row, const char* pstr, const char* filename, ch
#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
static void lcd_implementation_quick_feedback()
{
#if BEEPER > -1
static void lcd_implementation_quick_feedback() {
#if BEEPER > -1
SET_OUTPUT(BEEPER);
for(int8_t i=0;i<10;i++)
{
WRITE(BEEPER,HIGH);
delay(3);
WRITE(BEEPER,LOW);
delay(3);
for(int8_t i=0; i<10; i++) {
WRITE(BEEPER,HIGH);
delay(3);
WRITE(BEEPER,LOW);
delay(3);
}
#endif
#endif
}
#endif//ULTRA_LCD_IMPLEMENTATION_DOGM_H
#endif //__DOGM_LCD_IMPLEMENTATION_H

15
Marlin/ultralcd.cpp

@ -195,7 +195,7 @@ static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder=0, const bool
if (feedback) lcd_quick_feedback();
// For LCD_PROGRESS_BAR re-initialize the custom characters
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
lcd_set_custom_characters(menu == lcd_status_screen);
#endif
}
@ -204,7 +204,7 @@ static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder=0, const bool
/* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent */
static void lcd_status_screen()
{
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
uint16_t mil = millis();
#ifndef PROGRESS_MSG_ONCE
if (mil > progressBarTick + PROGRESS_BAR_MSG_TIME + PROGRESS_BAR_BAR_TIME) {
@ -236,11 +236,12 @@ static void lcd_status_screen()
lcd_status_update_delay--;
else
lcdDrawUpdate = 1;
if (lcdDrawUpdate)
{
if (lcdDrawUpdate) {
lcd_implementation_status_screen();
lcd_status_update_delay = 10; /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */
}
#ifdef ULTIPANEL
bool current_click = LCD_CLICKED;
@ -265,7 +266,7 @@ static void lcd_status_screen()
{
lcd_goto_menu(lcd_main_menu);
lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
currentMenu == lcd_status_screen
#endif
);
@ -1191,7 +1192,7 @@ void lcd_update()
lcdDrawUpdate = 2;
lcd_oldcardstatus = IS_SD_INSERTED;
lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
currentMenu == lcd_status_screen
#endif
);
@ -1294,7 +1295,7 @@ void lcd_finishstatus() {
}
}
lcd_status_message[LCD_WIDTH] = '\0';
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
#if PROGRESS_MSG_EXPIRE > 0
messageTick =
#endif

2
Marlin/ultralcd.h

@ -49,7 +49,7 @@
#ifdef FILAMENT_LCD_DISPLAY
extern unsigned long message_millis;
#endif
void lcd_buzz(long duration,uint16_t freq);
bool lcd_clicked();

Loading…
Cancel
Save