Browse Source

New ML support - W25X20CL external spi flash support

Robert Pelnar 5 years ago
parent
commit
bd1e410228
10 changed files with 468 additions and 113 deletions
  1. 68 4
      Firmware/Marlin_main.cpp
  2. 3 0
      Firmware/config.h
  3. 94 64
      Firmware/language.c
  4. 31 11
      Firmware/language.h
  5. 1 0
      Firmware/pins_Einsy_1_0.h
  6. 11 3
      Firmware/spi.h
  7. 41 30
      Firmware/ultralcd.cpp
  8. 1 1
      Firmware/ultralcd.h
  9. 178 0
      Firmware/w25x20cl.c
  10. 40 0
      Firmware/w25x20cl.h

+ 68 - 4
Firmware/Marlin_main.cpp

@@ -83,6 +83,9 @@
 #include "tmc2130.h"
 #endif //TMC2130
 
+#ifdef W25X20CL
+#include "w25x20cl.h"
+#endif //W25X20CL
 
 #ifdef BLINKM
 #include "BlinkM.h"
@@ -982,6 +985,8 @@ void __test()
 	while(1);
 }
 
+#ifdef W25X20CL
+
 void upgrade_sec_lang_from_external_flash()
 {
 	if ((boot_app_magic == 0x55aa55aa) && (boot_app_flags & BOOT_APP_FLG_USER0))
@@ -999,11 +1004,54 @@ void upgrade_sec_lang_from_external_flash()
 	boot_app_flags &= ~BOOT_APP_FLG_USER0;
 }
 
+uint8_t lang_xflash_enum_codes(uint16_t* codes)
+{
+	lang_table_header_t header;
+	uint8_t count = 0;
+	uint32_t addr = 0x00000;
+	while (1)
+	{
+		printf_P(_n("LANGTABLE%d:"), count);
+		w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t));
+		if (header.magic != LANG_MAGIC)
+		{
+			printf_P(_n("NG!\n"));
+			break;
+		}
+		printf_P(_n("OK\n"));
+		printf_P(_n(" _lt_magic        = 0x%08lx %S\n"), header.magic, (header.magic==LANG_MAGIC)?_n("OK"):_n("NA"));
+		printf_P(_n(" _lt_size         = 0x%04x (%d)\n"), header.size, header.size);
+		printf_P(_n(" _lt_count        = 0x%04x (%d)\n"), header.count, header.count);
+		printf_P(_n(" _lt_chsum        = 0x%04x\n"), header.checksum);
+		printf_P(_n(" _lt_code         = 0x%04x\n"), header.code);
+		printf_P(_n(" _lt_resv1        = 0x%08lx\n"), header.reserved1);
+
+		addr += header.size;
+		codes[count] = header.code;
+		count ++;
+	}
+	return count;
+}
+
+void list_sec_lang_from_external_flash()
+{
+	uint16_t codes[8];
+	uint8_t count = lang_xflash_enum_codes(codes);
+	printf_P(_n("XFlash lang count = %hhd\n"), count);
+}
+
+#endif //W25X20CL
+
+
 // "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 
 // are initialized by the main() routine provided by the Arduino framework.
 void setup()
 {
+#ifdef NEW_SPI
+	spi_init();
+#endif //NEW_SPI
+
     lcd_init();
 	fdev_setup_stream(lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); //setup lcdout stream
 
@@ -1157,9 +1205,6 @@ void setup()
 
 #endif //TMC2130
 
-#ifdef NEW_SPI
-	spi_init();
-#endif //NEW_SPI
 
 	st_init();    // Initialize stepper, this enables interrupts!
 
@@ -1303,16 +1348,35 @@ void setup()
   // If they differ, an update procedure may need to be performed. At the end of this block, the current firmware version
   // is being written into the EEPROM, so the update procedure will be triggered only once.
 
+	spi_setup(TMC2130_SPCR, TMC2130_SPSR);
+	puts_P(_n("w25x20cl init: "));
+	if (w25x20cl_ini())
+	{
+		uint8_t uid[8]; // 64bit unique id
+		w25x20cl_rd_uid(uid);
+		puts_P(_n("OK, UID="));
+		for (uint8_t i = 0; i < 8; i ++)
+			printf_P(PSTR("%02hhx"), uid[i]);
+		putchar('\n');
+		list_sec_lang_from_external_flash();
+	}
+	else
+		puts_P(_n("NG!\n"));
+
+
 	lang_selected = eeprom_read_byte((uint8_t*)EEPROM_LANG);
 	if (lang_selected >= LANG_NUM)
 	{
-		lcd_mylang();
+//		lcd_mylang();
+		lang_selected = 0;
 	}
 	lang_select(lang_selected);
 
 	uint16_t sec_lang_code=lang_get_code(1);
 	printf_P(_n("SEC_LANG_CODE=0x%04x (%c%c)\n"), sec_lang_code, sec_lang_code >> 8, sec_lang_code & 0xff);
 
+
+
 #ifdef DEBUG_SEC_LANG
 	lang_print_sec_lang(uartout);
 #endif //DEBUG_SEC_LANG

+ 3 - 0
Firmware/config.h

@@ -18,6 +18,9 @@
 #define TMC2130_SPCR           SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0)
 #define TMC2130_SPSR           SPI_SPSR(TMC2130_SPI_RATE)
 
+//W25X20CL configuration
+#define W25X20CL_PIN_CS        32
+
 //LANG - Multi-language support
 //#define LANG_MODE               0 // primary language only
 #define LANG_MODE               1 // sec. language support

+ 94 - 64
Firmware/language.c

@@ -4,54 +4,44 @@
 #include "bootapp.h"
 
 
-// Currectly active language selection.
+#ifdef W25X20CL
+#include "w25x20cl.h"
+#endif //W25X20CL
+
+// Currently active language selection.
 uint8_t lang_selected = 0;
 
+
 #if (LANG_MODE == 0) //primary language only
-#else //(LANG_MODE == 0)
+
+uint8_t lang_select(uint8_t lang) { return 0; }
+uint8_t lang_get_count() { return 1; }
+uint16_t lang_get_code(uint8_t lang) { return LANG_CODE_EN; }
+const char* lang_get_name_by_code(uint16_t code) { return _n("English"); }
+
+#else //(LANG_MODE == 0) //secondary languages in progmem or xflash
+
 //reserved xx kbytes for secondary language table
 const char _SEC_LANG[LANG_SIZE_RESERVED] PROGMEM_I2 = "_SEC_LANG";
-#endif //(LANG_MODE == 0)
-
-//lang_table_header_t structure - (size= 16byte)
-typedef struct
-{
-	uint32_t magic;      //+0 
-	uint16_t size;       //+4
-	uint16_t count;      //+6
-	uint16_t checksum;   //+8
-	uint16_t code;       //+10
-	uint32_t reserved1;  //+12
-} lang_table_header_t;
-
-//lang_table_t structure - (size= 16byte + 2*count)
-typedef struct
-{
-	lang_table_header_t header;
-	uint16_t table[];
-} lang_table_t;
 
 //lang_table pointer
 lang_table_t* lang_table = 0;
 
-
 const char* lang_get_translation(const char* s)
 {
-	if (lang_selected == 0) return s + 2; //primary language selected
-	if (lang_table == 0) return s + 2; //sec. lang table not found
+	if (lang_selected == 0) return s + 2; //primary language selected, return orig. str.
+	if (lang_table == 0) return s + 2; //sec. lang table not found, return orig. str.
 	uint16_t ui = pgm_read_word(((uint16_t*)s)); //read string id
-	if (ui == 0xffff) return s + 2; //translation not found
+	if (ui == 0xffff) return s + 2; //translation not found, return orig. str.
 	ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16 + ui*2)))); //read relative offset
-	if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0)
-		return s + 2;//not translated string
+	if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0) //read first character
+		return s + 2;//zero length string == not translated, return orig. str.
 	return (const char*)((char*)lang_table + ui); //return calculated pointer
 }
 
 const char* lang_get_sec_lang_str(const char* s)
 {
-	uint16_t ui = (uint16_t)&_SEC_LANG; //pointer to _SEC_LANG reserved space
-	ui += 0x00ff; //add 1 page
-	ui &= 0xff00; //align to page
+	uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
 	lang_table_t* _lang_table = ui; //table pointer
 	ui = pgm_read_word(((uint16_t*)s)); //read string id
 	if (ui == 0xffff) return s + 2; //translation not found
@@ -59,69 +49,108 @@ const char* lang_get_sec_lang_str(const char* s)
 	return (const char*)((char*)_lang_table + ui); //return calculated pointer
 }
 
-const char* lang_get_sec_lang_str_by_id(uint16_t id)
-{
-	uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
-	return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
-}
-
-const char* lang_select(uint8_t lang)
+uint8_t lang_select(uint8_t lang)
 {
-#if (LANG_MODE == 0) //primary language only
-	return 0;
-#else //(LANG_MODE == 0)
-	if (lang == 0) //primary language
+	if (lang == LANG_ID_PRI) //primary language
 	{
 		lang_table = 0;
 		lang_selected = 0;
-		return;
+		return 1;
+	}
+	if (lang == LANG_ID_SEC) //current secondary language
+	{
+		uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
+		if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return 0; //magic not valid
+		lang_table = ui; // set table pointer
+		lang_selected = 1; // set language id
+		return 1;
 	}
+/*
 	uint16_t ui = (uint16_t)&_SEC_LANG; //pointer to _SEC_LANG reserved space
 	ui += 0x00ff; //add 1 page
 	ui &= 0xff00; //align to page
 	lang_table = ui; //set table pointer
 	ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16)))); //read relative offset of first string (language name)
 	return (const char*)((char*)lang_table + ui); //return calculated pointer
-#endif //(LANG_MODE == 0)
+*/
 }
 
 uint8_t lang_get_count()
 {
-	uint16_t ui = (uint16_t)&_SEC_LANG; //pointer to _SEC_LANG reserved space
-	ui += 0x00ff; //add 1 page
-	ui &= 0xff00; //align to page
-	lang_table_t* _lang_table = ui; //table pointer
-	if (pgm_read_dword(((uint32_t*)(_lang_table + 0))) == LANG_MAGIC) return 2;
-	return 1;
+//#ifdef W25X20CL
+	uint8_t count = 1; //count = 1+n (primary + all in xflash)
+	uint32_t addr = 0x00000; //start of xflash
+	lang_table_header_t header; //table header structure
+	while (1)
+	{
+		w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
+		if (header.magic != LANG_MAGIC) break; //break if magic not valid
+		addr += header.size; //calc address of next table
+		count++; //inc counter
+	}
+	return count;
 }
 
-const char* lang_get_name(uint8_t lang)
+uint16_t lang_get_code(uint8_t lang)
 {
-	if (lang == LANG_ID_UNDEFINED) lang = lang_selected;
-	if (lang == LANG_ID_PRI) return MSG_LANGUAGE_NAME + 2;
+	if (lang == LANG_ID_PRI) return LANG_CODE_EN; //primary lang = EN
 	if (lang == LANG_ID_SEC)
 	{
 		uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
-		if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
-			return lang_get_sec_lang_str(MSG_LANGUAGE_NAME);
+		if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return LANG_CODE_XX; //magic not valid
+		return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem
 	}
-	return 0;
+	uint32_t addr = 0x00000; //start of xflash
+	lang_table_header_t header; //table header structure
+	lang--;
+	while (1)
+	{
+		w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
+		if (header.magic != LANG_MAGIC) break; //break if not valid
+		if (--lang == 0) return header.code;
+		addr += header.size; //calc address of next table
+	}
+
+//	if (lang == LANG_ID_SEC)
+//	{
+//		uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
+//		if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
+//			return pgm_read_word(((uint16_t*)(ui + 10))); //read language code
+//	}
+	return LANG_CODE_XX;
 }
 
-uint16_t lang_get_code(uint8_t lang)
+const char* lang_get_name_by_code(uint16_t code)
 {
-	if (lang == LANG_ID_UNDEFINED) lang = lang_selected;
-	if (lang == LANG_ID_PRI) return LANG_CODE_EN;
-	if (lang == LANG_ID_SEC)
+	switch (code)
 	{
-		uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
-		if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
-			return pgm_read_word(((uint16_t*)(ui + 10))); //read language code
+	case LANG_CODE_EN: return _n("English");
+	case LANG_CODE_CZ: return _n("Cestina");
+	case LANG_CODE_DE: return _n("Deutsch");
+	case LANG_CODE_ES: return _n("Espanol");
+	case LANG_CODE_IT: return _n("Italiano");
+	case LANG_CODE_PL: return _n("Polski");
 	}
-	return LANG_CODE_XX;
+	return _n("??");
+
+//	if (lang == LANG_ID_UNDEFINED) lang = lang_selected;
+//	if (lang == LANG_ID_PRI) return _T(MSG_LANGUAGE_NAME + 2);
+//	if (lang == LANG_ID_SEC)
+//	{
+//		uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
+//		if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
+//			return lang_get_sec_lang_str(MSG_LANGUAGE_NAME);
+//	}
+//	return 0;
 }
 
 #ifdef DEBUG_SEC_LANG
+const char* lang_get_sec_lang_str_by_id(uint16_t id)
+{
+	uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
+	return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
+}
+
 uint16_t lang_print_sec_lang(FILE* out)
 {
 	printf_P(_n("&_SEC_LANG        = 0x%04x\n"), &_SEC_LANG);
@@ -149,6 +178,7 @@ uint16_t lang_print_sec_lang(FILE* out)
 }
 #endif //DEBUG_SEC_LANG
 
+#endif //(LANG_MODE == 0)
 
-const char MSG_LANGUAGE_NAME[] PROGMEM_I1 = ISTR("English"); ////c=0 r=0
+//const char MSG_LANGUAGE_NAME[] PROGMEM_I1 = ISTR("English"); ////c=0 r=0
 

+ 31 - 11
Firmware/language.h

@@ -2,15 +2,15 @@
 #ifndef LANGUAGE_H
 #define LANGUAGE_H
 
+#define W25X20CL
+
 #include "config.h"
 #include <inttypes.h>
-#include <stdio.h>
+//#include <stdio.h>
 
 #define PROTOCOL_VERSION "1.0"
 
-#ifdef CUSTOM_MENDEL_NAME
-   // #define CUSTOM_MENDEL_NAME CUSTOM_MENDEL_NAME
-#else
+#ifndef CUSTOM_MENDEL_NAME
     #define MACHINE_NAME "Mendel"
 #endif
 
@@ -44,6 +44,23 @@
 #define _N(s) (__extension__({static const char __c[] PROGMEM_N1 = s; &__c[0];}))
 #define _n(s) _N(s)
 
+//lang_table_header_t structure - (size= 16byte)
+typedef struct
+{
+	uint32_t magic;      //+0 
+	uint16_t size;       //+4
+	uint16_t count;      //+6
+	uint16_t checksum;   //+8
+	uint16_t code;       //+10
+	uint32_t reserved1;  //+12
+} lang_table_header_t;
+
+//lang_table_t structure - (size= 16byte + 2*count)
+typedef struct
+{
+	lang_table_header_t header;
+	uint16_t table[];
+} lang_table_t;
 
 // Language indices into their particular symbol tables.
 #define LANG_ID_PRI 0
@@ -82,21 +99,23 @@ extern uint8_t lang_selected;
 
 #if (LANG_MODE != 0)
 extern const char _SEC_LANG[LANG_SIZE_RESERVED];
-#endif //(LANG_MODE == 0)
-
 extern const char* lang_get_translation(const char* s);
 extern const char* lang_get_sec_lang_str(const char* s);
-extern const char* lang_get_sec_lang_str_by_id(uint16_t id);
-extern const char* lang_select(uint8_t lang);
+#endif //(LANG_MODE != 0)
+
+//selects 
+extern uint8_t lang_select(uint8_t lang);
+
+//get total number of languages (primary + all in xflash)
 extern uint8_t lang_get_count();
-extern const char* lang_get_name(uint8_t lang);
 extern uint16_t lang_get_code(uint8_t lang);
+extern const char* lang_get_name_by_code(uint16_t code);
 
 #ifdef DEBUG_SEC_LANG
+extern const char* lang_get_sec_lang_str_by_id(uint16_t id);
 extern uint16_t lang_print_sec_lang(FILE* out);
 #endif //DEBUG_SEC_LANG
 
-
 #if defined(__cplusplus)
 }
 #endif //defined(__cplusplus)
@@ -104,7 +123,8 @@ extern uint16_t lang_print_sec_lang(FILE* out);
 #define CAT2(_s1, _s2) _s1
 #define CAT4(_s1, _s2, _s3, _s4) _s1
 
-extern const char MSG_LANGUAGE_NAME[];
+//Localized language name
+//extern const char MSG_LANGUAGE_NAME[];
 
 #include "messages.h"
 

+ 1 - 0
Firmware/pins_Einsy_1_0.h

@@ -15,6 +15,7 @@
 #define AMBIENT_THERMISTOR
 #define PINDA_THERMISTOR
 
+#define W25X20CL                 // external 256kB flash
 
 #define SWI2C                    // enable software i2c
 #define SWI2C_A8                 // 8bit address functions

+ 11 - 3
Firmware/spi.h

@@ -15,7 +15,11 @@
 #define DD_MOSI 2
 #define DD_MISO 3
 
-inline void spi_init()
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
+static inline void spi_init()
 {
 	DDRB &= ~((1 << DD_SCK) | (1 << DD_MOSI) | (1 << DD_MISO));
 	DDRB |= (1 << DD_SS) | (1 << DD_SCK) | (1 << DD_MOSI);
@@ -25,17 +29,21 @@ inline void spi_init()
 	SPSR = 0x00;
 }
 
-inline void spi_setup(uint8_t spcr, uint8_t spsr)
+static inline void spi_setup(uint8_t spcr, uint8_t spsr)
 {
 	SPCR = spcr;
 	SPSR = spsr;
 }
 
-inline uint8_t spi_txrx(uint8_t tx)
+static inline uint8_t spi_txrx(uint8_t tx)
 {
 	SPDR = tx;
 	while (!(SPSR & (1 << SPIF)));
 	return SPDR;
 }
 
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+
 #endif //SPI_H

+ 41 - 30
Firmware/ultralcd.cpp

@@ -3715,14 +3715,18 @@ static void lcd_crash_mode_set()
 #endif //TMC2130
  
 
-static void lcd_set_lang(unsigned char lang) {
-  lang_selected = lang;
-  firstrun = 1;
-  eeprom_update_byte((unsigned char *)EEPROM_LANG, lang);
-  /*langsel=0;*/
-  if (langsel == LANGSEL_MODAL)
-    // From modal mode to an active mode? This forces the menu to return to the setup menu.
-    langsel = LANGSEL_ACTIVE;
+static void lcd_set_lang(unsigned char lang)
+{
+	lang_select(lang);
+/*
+	lang_selected = lang;
+	firstrun = 1;
+	eeprom_update_byte((unsigned char *)EEPROM_LANG, lang);
+	// langsel=0;
+	if (langsel == LANGSEL_MODAL)
+	// From modal mode to an active mode? This forces the menu to return to the setup menu.
+	langsel = LANGSEL_ACTIVE;
+*/
 }
 
 #ifdef PAT9125
@@ -3756,17 +3760,21 @@ void lcd_force_language_selection() {
   eeprom_update_byte((unsigned char *)EEPROM_LANG, LANG_ID_FORCE_SELECTION);
 }
 
+#if (LANG_MODE != 0)
 static void lcd_language_menu()
 {
-  START_MENU();
-  if (langsel == LANGSEL_OFF)
-    MENU_ITEM(back, _T(MSG_SETTINGS), 0);
-  else if (langsel == LANGSEL_ACTIVE)
-    MENU_ITEM(back, _T(MSG_WATCH), 0);
-  for (int i=0; i < lang_get_count(); i++)
-    MENU_ITEM(setlang, lang_get_name(i), i);
-  END_MENU();
+	START_MENU();
+	if (langsel == LANGSEL_OFF)
+		MENU_ITEM(back, _T(MSG_SETTINGS), 0);
+	else if (langsel == LANGSEL_ACTIVE)
+		MENU_ITEM(back, _T(MSG_WATCH), 0);
+	MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(0)), 0);
+	for (int i = 1; i < lang_get_count(); i++)
+		MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(i+1)), i);
+	END_MENU();
 }
+#endif //(LANG_MODE != 0)
+
 
 void lcd_mesh_bedleveling()
 {
@@ -4232,7 +4240,10 @@ static void lcd_settings_menu()
 	{
 		MENU_ITEM(submenu, _T(MSG_BABYSTEP_Z), lcd_babystep_z);
 	}
+
+#if (LANG_MODE != 0)
 	MENU_ITEM(submenu, _i("Select language"), lcd_language_menu);////MSG_LANGUAGE_SELECT c=0 r=0
+#endif //(LANG_MODE != 0)
 
   if (card.ToshibaFlashAir_isEnabled()) {
     MENU_ITEM(function, _i("SD card [FlshAir]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
@@ -4591,7 +4602,7 @@ void lcd_mylang_drawmenu(int cursor) {
   }  
 }
 */
-
+/*
 void lcd_mylang_drawmenu(int cursor)
 {
 	unsigned char lang_cnt = lang_get_count();
@@ -4642,7 +4653,8 @@ void lcd_mylang_drawmenu(int cursor)
     lcd.print("^");
   }
 }
- 
+*/
+/*
 void lcd_mylang_drawcursor(int cursor) {
   
 	unsigned char lang_cnt = lang_get_count();
@@ -4652,8 +4664,9 @@ void lcd_mylang_drawcursor(int cursor) {
 
   lcd.print(">");
   
-}  
-
+}
+*/
+/*
 void lcd_mylang()
 {
   int enc_dif = 0;
@@ -4710,15 +4723,13 @@ void lcd_mylang()
       delay(500);
 
     }
-    /*
-    if (++counter == 80) {
-      hlaska++;
-      if(hlaska>LANG_NUM) hlaska=1;
-      lcd_mylang_top(hlaska);
-      lcd_mylang_drawcursor(cursor_pos);
-      counter=0;
-    }
-    */
+//    if (++counter == 80) {
+//      hlaska++;
+//      if(hlaska>LANG_NUM) hlaska=1;
+//      lcd_mylang_top(hlaska);
+//      lcd_mylang_drawcursor(cursor_pos);
+//      counter=0;
+//    }
   };
 
   if(MYSERIAL.available() > 1){
@@ -4731,7 +4742,7 @@ void lcd_mylang()
   lcd_return_to_status();
 
 }
-
+*/
 void bowden_menu() {
 	int enc_dif = encoderDiff;
 	int cursor_pos = 0;

+ 1 - 1
Firmware/ultralcd.h

@@ -32,7 +32,7 @@
   void prusa_statistics(int _message, uint8_t _col_nr = 0);
   void lcd_confirm_print();
   unsigned char lcd_choose_color();
-void lcd_mylang();
+//void lcd_mylang();
   bool lcd_detected(void);
 
   static void lcd_selftest_v();

+ 178 - 0
Firmware/w25x20cl.c

@@ -0,0 +1,178 @@
+//w25x20cl.c
+
+#include "w25x20cl.h"
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include "io_atmega2560.h"
+#include "spi.h"
+
+#define _MFRID             0xEF
+#define _DEVID             0x11
+
+#define _CMD_ENABLE_WR     0x06
+#define _CMD_ENABLE_WR_VSR 0x50
+#define _CMD_DISABLE_WR    0x04
+#define _CMD_RD_STATUS_REG 0x05
+#define _CMD_WR_STATUS_REG 0x01
+#define _CMD_RD_DATA       0x03
+#define _CMD_RD_FAST       0x0b
+#define _CMD_RD_FAST_D_O   0x3b
+#define _CMD_RD_FAST_D_IO  0xbb
+#define _CMD_PAGE_PROGRAM  0x02
+#define _CMD_SECTOR_ERASE  0x20
+#define _CMD_BLOCK32_ERASE 0x52
+#define _CMD_BLOCK64_ERASE 0xd8
+#define _CMD_CHIP_ERASE    0xc7
+#define _CMD_CHIP_ERASE2   0x60
+#define _CMD_PWR_DOWN      0xb9
+#define _CMD_PWR_DOWN_REL  0xab
+#define _CMD_MFRID_DEVID   0x90
+#define _CMD_MFRID_DEVID_D 0x92
+#define _CMD_JEDEC_ID      0x9f
+#define _CMD_RD_UID        0x4b
+
+#define _CS_LOW()  PORT(W25X20CL_PIN_CS) &= ~__MSK(W25X20CL_PIN_CS)
+#define _CS_HIGH() PORT(W25X20CL_PIN_CS) |= __MSK(W25X20CL_PIN_CS)
+
+//#define _SPI_TX swspi_tx
+//#define _SPI_RX swspi_rx
+#define _SPI_TX(b) spi_txrx(b)
+#define _SPI_RX() spi_txrx(0xff)
+
+
+int w25x20cl_mfrid_devid(void);
+
+
+int8_t w25x20cl_ini(void)
+{
+	PIN_OUT(W25X20CL_PIN_CS);
+	_CS_HIGH();
+	if (!w25x20cl_mfrid_devid()) return 0;
+	return 1;
+}
+
+void w25x20cl_enable_wr(void)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_ENABLE_WR);             // send command 0x06
+	_CS_HIGH();
+}
+
+void w25x20cl_disable_wr(void)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_DISABLE_WR);            // send command 0x04
+	_CS_HIGH();
+}
+
+uint8_t w25x20cl_rd_status_reg(void)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_RD_STATUS_REG);         // send command 0x90
+	uint8_t val = _SPI_RX();             // receive value
+	_CS_HIGH();
+	return val;
+}
+
+void w25x20cl_wr_status_reg(uint8_t val)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_WR_STATUS_REG);         // send command 0x90
+	_SPI_TX(val);                        // send value
+	_CS_HIGH();
+}
+
+void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_RD_DATA);               // send command 0x03
+	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23
+	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15
+	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7
+	while (cnt--)                        // receive data
+		*(data++) = _SPI_RX();
+	_CS_HIGH();
+}
+
+void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_PAGE_PROGRAM);          // send command 0x02
+	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23
+	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15
+	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7
+	while (cnt--)                        // send data
+		_SPI_TX(*(data++));
+	_CS_HIGH();
+}
+
+void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_PAGE_PROGRAM);          // send command 0x02
+	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23
+	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15
+	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7
+	while (cnt--)                        // send data
+		_SPI_TX(pgm_read_byte(data++));
+	_CS_HIGH();
+}
+
+void w25x20cl_erase(uint8_t cmd, uint32_t addr)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_SECTOR_ERASE);          // send command 0x20
+	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23
+	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15
+	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7
+	_CS_HIGH();
+}
+
+void w25x20cl_sector_erase(uint32_t addr)
+{
+	return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);
+}
+
+void w25x20cl_block32_erase(uint32_t addr)
+{
+	return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);
+}
+
+void w25x20cl_block64_erase(uint32_t addr)
+{
+	return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);
+}
+
+void w25x20cl_chip_erase(void)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_CHIP_ERASE);            // send command 0xc7
+	_CS_HIGH();
+}
+
+
+void w25x20cl_rd_uid(uint8_t* uid)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_RD_UID);                // send command 0x4b
+	uint8_t cnt = 4;                     // 4 dummy bytes
+	while (cnt--)                        // receive dummy bytes
+		_SPI_RX();
+	cnt = 8;                             // 8 bytes UID
+	while (cnt--)                        // receive UID
+		uid[7 - cnt] = _SPI_RX();
+	_CS_HIGH();
+}
+
+int w25x20cl_mfrid_devid(void)
+{
+	_CS_LOW();
+	_SPI_TX(_CMD_MFRID_DEVID);           // send command 0x90
+	uint8_t cnt = 3;                     // 3 address bytes
+	while (cnt--)                        // send address bytes
+		_SPI_TX(0x00);
+	uint8_t w25x20cl_mfrid = _SPI_RX();  // receive mfrid
+	uint8_t w25x20cl_devid = _SPI_RX();  // receive devid
+	_CS_HIGH();
+	return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
+}

+ 40 - 0
Firmware/w25x20cl.h

@@ -0,0 +1,40 @@
+//w25x20cl.h
+#ifndef _W25X20CL_H
+#define _W25X20CL_H
+
+#include <inttypes.h>
+#include "config.h"
+
+
+#define W25_STATUS_BUSY   0x01
+#define W25_STATUS_WEL    0x02
+#define W25_STATUS_BP0    0x04
+#define W25_STATUS_BP1    0x08
+#define W25_STATUS_TB     0x20
+#define W25_STATUS_SRP    0x80
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
+
+extern int8_t w25x20cl_ini(void);
+extern void w25x20cl_enable_wr(void);
+extern void w25x20cl_disable_wr(void);
+extern uint8_t w25x20cl_rd_status_reg(void);
+extern void w25x20cl_wr_status_reg(uint8_t val);
+extern void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt);
+extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt);
+extern void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt);
+extern void w25x20cl_sector_erase(uint32_t addr);
+extern void w25x20cl_block32_erase(uint32_t addr);
+extern void w25x20cl_block64_erase(uint32_t addr);
+extern void w25x20cl_chip_erase(void);
+extern void w25x20cl_rd_uid(uint8_t* uid);
+
+
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+#endif //_W25X20CL_H