Browse Source

Print class printf function (experimental, disabled by default)
LiquidCrystal VT100 escape codes (EraseScreen, CursorHome, ...)
Stream support for lcd and uart, fprintf and printf (stdout=uartout)
Dcodes enabled, code reduced, printf used
Splash screen with esc codes

Robert Pelnar 7 years ago
parent
commit
b8525f8043

+ 45 - 0
ArduinoAddons/Arduino_1.6.x/hardware/marlin/avr/cores/arduino/Print.cpp

@@ -262,3 +262,48 @@ size_t Print::printFloat(double number, uint8_t digits)
   
   return n;
 }
+
+
+//printf
+#ifdef _Print_printf
+
+#include <stdarg.h>
+
+#define PRINTF_BUF 80 // define the tmp buffer size (change if desired)
+
+void Print::printf(const char *format, ...)
+{
+  char buf[PRINTF_BUF];
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(buf, sizeof(buf), format, ap);
+  for(char *p = &buf[0]; *p; p++) // emulate cooked mode for newlines
+  {
+    if(*p == '\n')
+      write('\r');
+    write(*p);
+  }
+  va_end(ap);
+}
+#ifdef F // check to see if F() macro is available
+void Print::printf(const __FlashStringHelper *format, ...)
+{
+  char buf[PRINTF_BUF];
+  va_list ap;
+  va_start(ap, format);
+#ifdef __AVR__
+  vsnprintf_P(buf, sizeof(buf), (const char *)format, ap); // progmem for AVR
+#else
+  vsnprintf(buf, sizeof(buf), (const char *)format, ap); // for the rest of the world
+#endif
+  for(char *p = &buf[0]; *p; p++) // emulate cooked mode for newlines
+  {
+    if(*p == '\n')
+      write('\r');
+    write(*p);
+  }
+  va_end(ap);
+}
+#endif
+
+#endif //_Print_printf

+ 11 - 1
ArduinoAddons/Arduino_1.6.x/hardware/marlin/avr/cores/arduino/Print.h

@@ -31,6 +31,8 @@
 #define OCT 8
 #define BIN 2
 
+//#define _Print_printf
+
 class Print
 {
   private:
@@ -79,6 +81,14 @@ class Print
     size_t println(double, int = 2);
     size_t println(const Printable&);
     size_t println(void);
-};
 
+//printf
+#ifdef _Print_printf
+	void printf(const char *format, ...);
+#ifdef F // check to see if F() macro is available
+    void printf(const __FlashStringHelper *format, ...);
 #endif
+#endif //_Print_printf
+};
+
+#endif

+ 1 - 1
Firmware/Configuration_prusa.h

@@ -82,7 +82,7 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 
 //DEBUG
 //#define _NO_ASM
-//#define DEBUG_DCODES //D codes
+#define DEBUG_DCODES //D codes
 #if 1
 //#define DEBUG_FSENSOR_LOG          //Reports fsensor status to serial
 //#define DEBUG_CRASHDET_COUNTERS  //Display crash-detection counters on LCD

+ 107 - 100
Firmware/Dcodes.cpp

@@ -9,6 +9,8 @@
 #include <avr/wdt.h>
 
 
+#define FLASHSIZE     0x40000
+
 #define RAMSIZE        0x2000
 #define boot_src_addr  (*((uint32_t*)(RAMSIZE - 16)))
 #define boot_dst_addr  (*((uint32_t*)(RAMSIZE - 12)))
@@ -25,23 +27,53 @@ extern float current_temperature_pinda;
 extern float axis_steps_per_unit[NUM_AXIS];
 
 
-inline void serial_print_hex_nibble(uint8_t val)
+inline void print_hex_nibble(uint8_t val)
 {
-	MYSERIAL.write((val > 9)?(val - 10 + 'a'):(val + '0'));
+	putchar((val > 9)?(val - 10 + 'a'):(val + '0'));
 }
 
-void serial_print_hex_byte(uint8_t val)
+void print_hex_byte(uint8_t val)
 {
-	serial_print_hex_nibble(val >> 4);
-	serial_print_hex_nibble(val & 15);
+	print_hex_nibble(val >> 4);
+	print_hex_nibble(val & 15);
 }
 
-void serial_print_hex_word(uint16_t val)
+void print_hex_word(uint16_t val)
 {
-	serial_print_hex_byte(val >> 8);
-	serial_print_hex_byte(val & 255);
+	print_hex_byte(val >> 8);
+	print_hex_byte(val & 255);
+}
+
+void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperline = 16)
+{
+	while (count)
+	{
+		if (type == 2)
+			print_hex_nibble(address >> 16);
+		print_hex_word(address);
+		putchar(' ');
+		uint8_t count_line = countperline;
+		while (count && count_line)
+		{
+			uint8_t data = 0;
+			switch (type)
+			{
+			case 0: data = *((uint8_t*)address++); break;
+			case 1: data = eeprom_read_byte((uint8_t*)address++); break;
+			case 2: data = pgm_read_byte_far((uint8_t*)address++); break;
+			}
+			putchar(' ');
+			print_hex_byte(data);
+			count_line--;
+			count--;
+		}
+		putchar('\n');
+	}
 }
 
+//#define LOG(args...) printf(args)
+#define LOG(args...)
+
 int parse_hex(char* hex, uint8_t* data, int count)
 {
 	int parsed = 0;
@@ -68,7 +100,7 @@ int parse_hex(char* hex, uint8_t* data, int count)
 void dcode_0()
 {
 	if (*(strchr_pointer + 1) == 0) return;
-	MYSERIAL.println("D0 - Reset");
+	LOG("D0 - Reset\n");
 	if (code_seen('B')) //bootloader
 	{
 		cli();
@@ -85,7 +117,7 @@ void dcode_0()
 
 void dcode_1()
 {
-	MYSERIAL.println("D1 - Clear EEPROM and RESET");
+	LOG("D1 - Clear EEPROM and RESET\n");
 	cli();
 	for (int i = 0; i < 8192; i++)
 		eeprom_write_byte((unsigned char*)i, (unsigned char)0xff);
@@ -95,7 +127,7 @@ void dcode_1()
 
 void dcode_2()
 {
-	MYSERIAL.println("D2 - Read/Write RAM");
+	LOG("D2 - Read/Write RAM\n");
 	uint16_t address = 0x0000; //default 0x0000
 	uint16_t count = 0x2000; //default 0x2000 (entire ram)
 	if (code_seen('A')) // Address (0x0000-0x1fff)
@@ -113,34 +145,32 @@ void dcode_2()
 		{
 			for (int i = 0; i < count; i++)
 				*((uint8_t*)(address + i)) =  data[i];
-			MYSERIAL.print(count, DEC);
-			MYSERIAL.println(" bytes written to RAM at address ");
-			serial_print_hex_word(address);
-			MYSERIAL.write('\n');
+			LOG("%d bytes written to RAM at address %04x", count, address);
 		}
 		else
 			count = 0;
 	}
-	while (count)
+	print_mem(address, count, 0);
+/*	while (count)
 	{
-		serial_print_hex_word(address);
-		MYSERIAL.write(' ');
+		print_hex_word(address);
+		putchar(' ');
 		uint8_t countperline = 16;
 		while (count && countperline)
 		{
 			uint8_t data = *((uint8_t*)address++);
-			MYSERIAL.write(' ');
-			serial_print_hex_byte(data);
+			putchar(' ');
+			print_hex_byte(data);
 			countperline--;
 			count--;
 		}
-		MYSERIAL.write('\n');
-	}
+		putchar('\n');
+	}*/
 }
 
 void dcode_3()
 {
-	MYSERIAL.println("D3 - Read/Write EEPROM");
+	LOG("D3 - Read/Write EEPROM\n");
 	uint16_t address = 0x0000; //default 0x0000
 	uint16_t count = 0x2000; //default 0x2000 (entire eeprom)
 	if (code_seen('A')) // Address (0x0000-0x1fff)
@@ -158,34 +188,35 @@ void dcode_3()
 		{
 			for (int i = 0; i < count; i++)
 				eeprom_write_byte((uint8_t*)(address + i), data[i]);
-			MYSERIAL.print(count, DEC);
-			MYSERIAL.println(" bytes written to EEPROM at address ");
-			serial_print_hex_word(address);
-			MYSERIAL.write('\n');
+			LOG(count, DEC);
+			LOG(" bytes written to EEPROM at address ");
+			print_hex_word(address);
+			putchar('\n');
 		}
 		else
 			count = 0;
 	}
-	while (count)
+	print_mem(address, count, 1);
+/*	while (count)
 	{
-		serial_print_hex_word(address);
-		MYSERIAL.write(' ');
+		print_hex_word(address);
+		putchar(' ');
 		uint8_t countperline = 16;
 		while (count && countperline)
 		{
 			uint8_t data = eeprom_read_byte((uint8_t*)address++);
-			MYSERIAL.write(' ');
-			serial_print_hex_byte(data);
+			putchar(' ');
+			print_hex_byte(data);
 			countperline--;
 			count--;
 		}
-		MYSERIAL.write('\n');
-	}
+		putchar('\n');
+	}*/
 }
 
 void dcode_4()
 {
-	MYSERIAL.println("D4 - Read/Write PIN");
+	LOG("D4 - Read/Write PIN\n");
 	if (code_seen('P')) // Pin (0-255)
 	{
 		int pin = (int)code_value();
@@ -206,18 +237,15 @@ void dcode_4()
 			else
 			{
 				int val = (digitalRead(pin) != LOW)?1:0;
-				MYSERIAL.print("PIN");
-				MYSERIAL.print(pin);
-				MYSERIAL.print("=");
-				MYSERIAL.println(val);
+				printf("PIN%d=%d", pin, val);
 			}
 		}
 	}
 }
-
+/*
 void dcode_5()
 {
-	MYSERIAL.println("D5 - Read/Write FLASH");
+	LOG("D5 - Read/Write FLASH\n");
 	uint32_t address = 0x0000; //default 0x0000
 	uint16_t count = 0x0400; //default 0x0400 (1kb block)
 	if (code_seen('A')) // Address (0x00000-0x3ffff)
@@ -241,17 +269,17 @@ void dcode_5()
 	{
 		if (bErase)
 		{
-			MYSERIAL.print(count, DEC);
-			MYSERIAL.println(" bytes of FLASH at address ");
-			serial_print_hex_word(address);
-			MYSERIAL.write(" will be erased\n");
+			LOG(count, DEC);
+			LOG(" bytes of FLASH at address ");
+			print_hex_word(address);
+			putchar(" will be erased\n");
 		}
 		if (bCopy)
 		{
-			MYSERIAL.print(count, DEC);
-			MYSERIAL.println(" bytes will be written to FLASH at address ");
-			serial_print_hex_word(address);
-			MYSERIAL.write('\n');
+			LOG(count, DEC);
+			LOG(" bytes will be written to FLASH at address ");
+			print_hex_word(address);
+			putchar('\n');
 		}
 		cli();
 		boot_app_magic = 0x55aa55aa;
@@ -264,30 +292,31 @@ void dcode_5()
 	}
 	while (count)
 	{
-		serial_print_hex_nibble(address >> 16);
-		serial_print_hex_word(address);
-		MYSERIAL.write(' ');
+		print_hex_nibble(address >> 16);
+		print_hex_word(address);
+		putchar(' ');
 		uint8_t countperline = 16;
 		while (count && countperline)
 		{
 			uint8_t data = pgm_read_byte_far((uint8_t*)address++);
-			MYSERIAL.write(' ');
-			serial_print_hex_byte(data);
+			putchar(' ');
+			print_hex_byte(data);
 			countperline--;
 			count--;
 		}
-		MYSERIAL.write('\n');
+		putchar('\n');
 	}
 }
+*/
 
 void dcode_6()
 {
-	MYSERIAL.println("D6 - Read/Write external FLASH");
+	LOG("D6 - Read/Write external FLASH\n");
 }
 
 void dcode_7()
 {
-	MYSERIAL.println("D7 - Read/Write Bootloader");
+	LOG("D7 - Read/Write Bootloader\n");
 /*
 	cli();
 	boot_app_magic = 0x55aa55aa;
@@ -302,23 +331,23 @@ void dcode_7()
 
 void dcode_8()
 {
-	MYSERIAL.println("D8 - Read/Write PINDA");
+	LOG("D8 - Read/Write PINDA\n");
 	uint8_t cal_status = calibration_status_pinda();
 	float temp_pinda = current_temperature_pinda;
 	float offset_z = temp_compensation_pinda_thermistor_offset(temp_pinda);
 	if ((strchr_pointer[1+1] == '?') || (strchr_pointer[1+1] == 0))
 	{
-		MYSERIAL.print("cal_status=");
-		MYSERIAL.println(cal_status?"1":"0");
+		LOG("cal_status=");
+		LOG(cal_status?"1\n":"0\n");
 		for (uint8_t i = 0; i < 6; i++)
 		{
-			MYSERIAL.print("temp_pinda=");
-			MYSERIAL.print(35 + i * 5, DEC);
-			MYSERIAL.print("C, temp_shift=");
+			LOG("temp_pinda=");
+			LOG(35 + i * 5, DEC);
+			LOG("C, temp_shift=");
 			uint16_t offs = 0;
 			if (i > 0) offs = eeprom_read_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + (i - 1));
-			MYSERIAL.print(((float)offs) / axis_steps_per_unit[Z_AXIS], 3);
-			MYSERIAL.println("mm");
+			LOG(((float)offs) / axis_steps_per_unit[Z_AXIS], 3);
+			LOG("mm\n");
 		}
 	}
 	else if (strchr_pointer[1+1] == '!')
@@ -341,21 +370,21 @@ void dcode_8()
 			offset_z = code_value();
 		}
 	}
-	MYSERIAL.print("temp_pinda=");
-	MYSERIAL.println(temp_pinda);
-	MYSERIAL.print("offset_z=");
-	MYSERIAL.println(offset_z, 3);
+	LOG("temp_pinda=");
+	LOG(temp_pinda);
+	LOG("offset_z=");
+	LOG(offset_z, 3);
 }
 
 void dcode_10()
 {//Tell the printer that XYZ calibration went OK
-	MYSERIAL.println("D10 - XYZ calibration = OK");
+	LOG("D10 - XYZ calibration = OK\n");
 	calibration_status_store(CALIBRATION_STATUS_LIVE_ADJUST); 
 }
 
 void dcode_12()
 {//Reset Filament error, Power loss and crash counter ( Do it before every print and you can get stats for the print )
-	MYSERIAL.println("D12 - Reset failstat counters");
+	LOG("D12 - Reset failstat counters\n");
     eeprom_update_byte((uint8_t*)EEPROM_CRASH_COUNT, 0x00);
     eeprom_update_byte((uint8_t*)EEPROM_FERROR_COUNT, 0x00);
     eeprom_update_byte((uint8_t*)EEPROM_POWER_COUNT, 0x00);
@@ -368,59 +397,37 @@ void dcode_2130()
 
 void dcode_9125()
 {
-	MYSERIAL.println("D9125 - PAT9125");
+	LOG("D9125 - PAT9125\n");
 	if ((strchr_pointer[1+4] == '?') || (strchr_pointer[1+4] == 0))
 	{
-		MYSERIAL.print("res_x=");
-		MYSERIAL.print(pat9125_xres, DEC);
-		MYSERIAL.print(" res_y=");
-		MYSERIAL.print(pat9125_yres, DEC);
-		MYSERIAL.print(" x=");
-		MYSERIAL.print(pat9125_x, DEC);
-		MYSERIAL.print(" y=");
-		MYSERIAL.print(pat9125_y, DEC);
-		MYSERIAL.print(" b=");
-		MYSERIAL.print(pat9125_b, DEC);
-		MYSERIAL.print(" s=");
-		MYSERIAL.println(pat9125_s, DEC);
+		printf("res_x=%d res_y=%d x=%d y=%d b=%d s=%d\n", pat9125_xres, pat9125_yres, pat9125_x, pat9125_y, pat9125_b, pat9125_s);
 		return;
 	}
 	if (strchr_pointer[1+4] == '!')
 	{
 		pat9125_update();
-		MYSERIAL.print("x=");
-		MYSERIAL.print(pat9125_x, DEC);
-		MYSERIAL.print(" y=");
-		MYSERIAL.print(pat9125_y, DEC);
-		MYSERIAL.print(" b=");
-		MYSERIAL.print(pat9125_b, DEC);
-		MYSERIAL.print(" s=");
-		MYSERIAL.println(pat9125_s, DEC);
+		printf("x=%d y=%d b=%d s=%d\n", pat9125_x, pat9125_y, pat9125_b, pat9125_s);
 		return;
 	}
 	if (code_seen('R'))
 	{
 		unsigned char res = (int)code_value();
-		MYSERIAL.print("pat9125_init(xres=yres=");
-		MYSERIAL.print(res, DEC);
-		MYSERIAL.print(")=");
-		MYSERIAL.println(pat9125_init(res, res), DEC);
+		LOG("pat9125_init(xres=yres=%d)=%d\n", res, pat9125_init(res, res));
 	}
 	if (code_seen('X'))
 	{
 		pat9125_x = (int)code_value();
-		MYSERIAL.print("pat9125_x=");
-		MYSERIAL.print(pat9125_x, DEC);
+		LOG("pat9125_x=%d\n", pat9125_x);
 	}
 	if (code_seen('Y'))
 	{
 		pat9125_y = (int)code_value();
-		MYSERIAL.print("pat9125_y=");
-		MYSERIAL.print(pat9125_y, DEC);
+		LOG("pat9125_y=%d\n", pat9125_y);
 	}
 	if (code_seen('L'))
 	{
 		fsensor_log = (int)code_value();
+		LOG("fsensor_log=%d\n", fsensor_log);
 	}
 }
 

+ 142 - 1
Firmware/LiquidCrystal.cpp

@@ -156,6 +156,8 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
   command(LCD_ENTRYMODESET | _displaymode);
   delayMicroseconds(60);
 
+  _escape[0] = 0;
+
 }
 
 
@@ -354,10 +356,149 @@ inline void LiquidCrystal::command(uint8_t value) {
 }
 
 inline size_t LiquidCrystal::write(uint8_t value) {
+  if (_escape[0] || (value == 0x1b))
+    return escape_write(value);
   send(value, HIGH);
   return 1; // assume sucess
 }
 
+//Supported VT100 escape codes:
+//EraseScreen  "\x1b[2J"
+//CursorHome   "\x1b[%d;%dH"
+//CursorShow   "\x1b[?25h"
+//CursorHide   "\x1b[?25l"
+
+inline size_t LiquidCrystal::escape_write(uint8_t chr)
+{
+#define escape_cnt (_escape[0])        //escape character counter
+#define is_num_msk (_escape[1])        //numeric character bit mask
+#define chr_is_num (is_num_msk & 0x01) //current character is numeric
+#define e_2_is_num (is_num_msk & 0x04) //escape char 2 is numeric
+#define e_3_is_num (is_num_msk & 0x08) //...
+#define e_4_is_num (is_num_msk & 0x10)
+#define e_5_is_num (is_num_msk & 0x20)
+#define e_6_is_num (is_num_msk & 0x40)
+#define e_7_is_num (is_num_msk & 0x80)
+#define e2_num (_escape[2] - '0')      //number from character 2
+#define e3_num (_escape[3] - '0')      //number from character 3
+#define e23_num (10*e2_num+e3_num)     //number from characters 2 and 3
+#define e4_num (_escape[4] - '0')      //number from character 4
+#define e5_num (_escape[5] - '0')      //number from character 5
+#define e45_num (10*e4_num+e5_num)     //number from characters 4 and 5
+#define e6_num (_escape[6] - '0')      //number from character 6
+#define e56_num (10*e5_num+e6_num)     //number from characters 5 and 6
+	if (escape_cnt > 1) // escape length > 1 = "\x1b["
+	{
+		_escape[escape_cnt] = chr; // store current char
+		if ((chr >= '0') && (chr <= '9')) // char is numeric
+			is_num_msk |= (1 | (1 << escape_cnt)); //set mask
+		else
+			is_num_msk &= ~1; //clear mask
+	}
+	switch (escape_cnt++)
+	{
+	case 0:
+		if (chr == 0x1b) return 1;  // escape = "\x1b"
+		break;
+	case 1:
+		is_num_msk = 0x00; // reset 'is number' bit mask
+		if (chr == '[') return 1; // escape = "\x1b["
+		break;
+	case 2:
+		switch (chr)
+		{
+		case '2': return 1; // escape = "\x1b[2"
+		case '?': return 1; // escape = "\x1b[?"
+		default:
+			if (chr_is_num) return 1; // escape = "\x1b[%1d"
+		}
+		break;
+	case 3:
+		switch (_escape[2])
+		{
+		case '?': // escape = "\x1b[?"
+			if (chr == '2') return 1; // escape = "\x1b[?2"
+			break;
+		case '2':
+			if (chr == 'J') // escape = "\x1b[2J"
+				{ clear(); break; } // EraseScreen
+		default:
+			if (e_2_is_num && // escape = "\x1b[%1d"
+				((chr == ';') || // escape = "\x1b[%1d;"
+				chr_is_num)) // escape = "\x1b[%2d"
+				return 1;
+		}
+		break;
+	case 4:
+		switch (_escape[2])
+		{
+		case '?': // "\x1b[?"
+			if ((_escape[3] == '2') && (chr == '5')) return 1; // escape = "\x1b[?25"
+			break;
+		default:
+			if (e_2_is_num) // escape = "\x1b[%1d"
+			{
+				if ((_escape[3] == ';') && chr_is_num) return 1; // escape = "\x1b[%1d;%1d"
+				else if (e_3_is_num && (chr == ';')) return 1; // escape = "\x1b[%2d;"
+			}
+		}
+		break;
+	case 5:
+		switch (_escape[2])
+		{
+		case '?':
+			if ((_escape[3] == '2') && (_escape[4] == '5')) // escape = "\x1b[?25"
+				switch (chr)
+				{
+				case 'h': // escape = "\x1b[?25h"
+  					void cursor(); // CursorShow
+					break;
+				case 'l': // escape = "\x1b[?25l"
+					noCursor(); // CursorHide
+					break;
+				}
+			break;
+		default:
+			if (e_2_is_num) // escape = "\x1b[%1d"
+			{
+				if ((_escape[3] == ';') && e_4_is_num) // escape = "\x1b%1d;%1dH"
+				{
+					if (chr == 'H') // escape = "\x1b%1d;%1dH"
+						setCursor(e4_num, e2_num); // CursorHome
+					else if (chr_is_num)
+						return 1; // escape = "\x1b%1d;%2d"
+				}
+				else if (e_3_is_num && (_escape[4] == ';') && chr_is_num)
+					return 1; // escape = "\x1b%2d;%1d"
+			}
+		}
+		break;
+	case 6:
+		if (e_2_is_num) // escape = "\x1b[%1d"
+		{
+			if ((_escape[3] == ';') && e_4_is_num && e_5_is_num && (chr == 'H')) // escape = "\x1b%1d;%2dH"
+				setCursor(e45_num, e2_num); // CursorHome
+			else if (e_3_is_num && (_escape[4] == ';') && e_5_is_num) // escape = "\x1b%2d;%1d"
+			{
+				if (chr == 'H') // escape = "\x1b%2d;%1dH"
+					setCursor(e5_num, e23_num); // CursorHome
+				else if (chr_is_num) // "\x1b%2d;%2d"
+					return 1;
+			}
+		}
+		break;
+	case 7:
+		if (e_2_is_num && e_3_is_num && (_escape[4] == ';')) // "\x1b[%2d;"
+			if (e_5_is_num && e_6_is_num && (chr == 'H')) // "\x1b[%2d;%2dH"
+				setCursor(e56_num, e23_num); // CursorHome
+		break;
+	}
+	escape_cnt = 0; // reset escape
+end:
+	return 1; // assume sucess
+}
+
+
 /************ low level data pushing commands **********/
 
 // write either command or data, with automatic 4/8-bit selection
@@ -402,4 +543,4 @@ void LiquidCrystal::write8bits(uint8_t value) {
   }
   
   pulseEnable();
-}
+}

+ 10 - 1
Firmware/LiquidCrystal.h

@@ -103,6 +103,15 @@ private:
   uint8_t _initialized;
 
   uint8_t _numlines,_currline;
+
+  uint8_t _escape[8];
+  size_t escape_write(uint8_t value);
+  
 };
 
-#endif
+#define ESC_2J     "\x1b[2J"
+#define ESC_25h    "\x1b[?25h"
+#define ESC_25l    "\x1b[?25l"
+#define ESC_H(c,r) "\x1b["#r";"#c"H"
+
+#endif

+ 6 - 0
Firmware/Marlin.h

@@ -62,6 +62,12 @@
   #define MYSERIAL MSerial
 #endif
 
+extern FILE _lcdout;
+#define lcdout (&_lcdout)
+
+extern FILE _uartout;
+#define uartout (&_uartout)
+
 #define SERIAL_PROTOCOL(x) (MYSERIAL.print(x))
 #define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y))
 #define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x)))

+ 37 - 6
Firmware/Marlin_main.cpp

@@ -720,7 +720,32 @@ void factory_reset(char level, bool quiet)
     
 
 }
+#include "LiquidCrystal.h"
+extern LiquidCrystal lcd;
 
+FILE _lcdout = {0};
+
+int lcd_putchar(char c, FILE *stream)
+{
+	lcd.write(c);
+	return 0;
+}
+
+FILE _uartout = {0};
+
+int uart_putchar(char c, FILE *stream)
+{
+	MYSERIAL.write(c);
+	return 0;
+}
+
+void lcd_splash()
+{
+//	lcd_print_at_PGM(0, 1, PSTR("   Original Prusa   "));
+//	lcd_print_at_PGM(0, 2, PSTR("    3D  Printers    "));
+//	lcd.print_P(PSTR("\x1b[1;3HOriginal Prusa\x1b[2;4H3D  Printers"));
+    fputs_P(PSTR(ESC_2J ESC_H(3,1) "Original Prusa" ESC_H(4,2) "3D  Printers"), lcdout);
+}
 
 // "Setup" function is called by the Arduino framework on startup.
 // Before startup, the Timers-functions (PWM)/Analog RW and HardwareSerial provided by the Arduino-code 
@@ -728,8 +753,8 @@ void factory_reset(char level, bool quiet)
 void setup()
 {
     lcd_init();
-	lcd_print_at_PGM(0, 1, PSTR("   Original Prusa   "));
-    lcd_print_at_PGM(0, 2, PSTR("    3D  Printers    "));
+	fdev_setup_stream(lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); //setup lcdout stream
+	lcd_splash();
 	setup_killpin();
 	setup_powerhold();
 	farm_mode = eeprom_read_byte((uint8_t*)EEPROM_FARM_MODE); 
@@ -744,6 +769,8 @@ void setup()
 	else
 		selectedSerialPort = 0;
 	MYSERIAL.begin(BAUDRATE);
+	fdev_setup_stream(uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); //setup uart out stream
+	stdout = uartout;
 	SERIAL_PROTOCOLLNPGM("start");
 	SERIAL_ECHO_START;
 
@@ -794,7 +821,11 @@ void setup()
 	// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)
 	Config_RetrieveSettings(EEPROM_OFFSET);
 	SdFatUtil::set_stack_guard(); //writes magic number at the end of static variables to protect against overwriting static memory by stack
+
 	tp_init();    // Initialize temperature loop
+
+	lcd_splash(); // we need to do this again, because tp_init() kills lcd
+
 	plan_init();  // Initialize planner;
 	watchdog_init();
 
@@ -833,12 +864,11 @@ void setup()
 	}
 
 #endif //PAT9125
-    
+
 	st_init();    // Initialize stepper, this enables interrupts!
     
 	setup_photpin();
-    lcd_print_at_PGM(0, 1, PSTR("   Original Prusa   ")); // we need to do this again for some reason, no time to research
-    lcd_print_at_PGM(0, 2, PSTR("    3D  Printers    ")); 
+
 	servo_init();
 	// Reset the machine correction matrix.
 	// It does not make sense to load the correction matrix until the machine is homed.
@@ -5853,7 +5883,8 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
 	case 4: // D4 - Read/Write PIN
 		dcode_4(); break;
 	case 5: // D5 - Read/Write FLASH
-		dcode_5(); break;
+//		dcode_5(); break;
+		break;
 	case 6: // D6 - Read/Write external FLASH
 		dcode_6(); break;
 	case 7: // D7 - Read/Write Bootloader