Merge pull request #793 from XPila/MK3-new_lang

Mk3 new lang
This commit is contained in:
PavelSindler 2018-06-08 14:43:02 +02:00 committed by GitHub
commit 1d9ce20b74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 12250 additions and 2064 deletions

View file

@ -543,4 +543,171 @@ void LiquidCrystal_Prusa::write8bits(uint8_t value) {
}
pulseEnable();
}
}
void LiquidCrystal_Prusa::print(const char* s)
{
while (*s) write(*(s++));
}
void LiquidCrystal_Prusa::print(char c, int base)
{
print((long) c, base);
}
void LiquidCrystal_Prusa::print(unsigned char b, int base)
{
print((unsigned long) b, base);
}
void LiquidCrystal_Prusa::print(int n, int base)
{
print((long) n, base);
}
void LiquidCrystal_Prusa::print(unsigned int n, int base)
{
print((unsigned long) n, base);
}
void LiquidCrystal_Prusa::print(long n, int base)
{
if (base == 0) {
write(n);
} else if (base == 10) {
if (n < 0) {
print('-');
n = -n;
}
printNumber(n, 10);
} else {
printNumber(n, base);
}
}
void LiquidCrystal_Prusa::print(unsigned long n, int base)
{
if (base == 0) write(n);
else printNumber(n, base);
}
void LiquidCrystal_Prusa::print(double n, int digits)
{
printFloat(n, digits);
}
void LiquidCrystal_Prusa::println(void)
{
print('\r');
print('\n');
}
/*void LiquidCrystal_Prusa::println(const String &s)
{
print(s);
println();
}*/
void LiquidCrystal_Prusa::println(const char c[])
{
print(c);
println();
}
void LiquidCrystal_Prusa::println(char c, int base)
{
print(c, base);
println();
}
void LiquidCrystal_Prusa::println(unsigned char b, int base)
{
print(b, base);
println();
}
void LiquidCrystal_Prusa::println(int n, int base)
{
print(n, base);
println();
}
void LiquidCrystal_Prusa::println(unsigned int n, int base)
{
print(n, base);
println();
}
void LiquidCrystal_Prusa::println(long n, int base)
{
print(n, base);
println();
}
void LiquidCrystal_Prusa::println(unsigned long n, int base)
{
print(n, base);
println();
}
void LiquidCrystal_Prusa::println(double n, int digits)
{
print(n, digits);
println();
}
void LiquidCrystal_Prusa::printNumber(unsigned long n, uint8_t base)
{
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
unsigned long i = 0;
if (n == 0) {
print('0');
return;
}
while (n > 0) {
buf[i++] = n % base;
n /= base;
}
for (; i > 0; i--)
print((char) (buf[i - 1] < 10 ?
'0' + buf[i - 1] :
'A' + buf[i - 1] - 10));
}
void LiquidCrystal_Prusa::printFloat(double number, uint8_t digits)
{
// Handle negative numbers
if (number < 0.0)
{
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0)
print(".");
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
remainder -= toPrint;
}
}

View file

@ -2,7 +2,8 @@
#define LiquidCrystal_Prusa_h
#include <inttypes.h>
#include "Print.h"
#include <stddef.h>
//#include "Print.h"
// commands
#define LCD_CLEARDISPLAY 0x01
@ -42,7 +43,7 @@
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
class LiquidCrystal_Prusa : public Print {
class LiquidCrystal_Prusa/* : public Print */{
public:
LiquidCrystal_Prusa(uint8_t rs, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
@ -81,10 +82,34 @@ public:
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
virtual size_t write(uint8_t);
// virtual size_t write(uint8_t);
size_t write(uint8_t);
void command(uint8_t);
using Print::write;
void print(const char*);
void print(char, int = 0);
void print(unsigned char, int = 0);
void print(int, int = 10);
void print(unsigned int, int = 10);
void print(long, int = 10);
void print(unsigned long, int = 10);
void print(double, int = 2);
// void println(const String &s);
void println(const char[]);
void println(char, int = 0);
void println(unsigned char, int = 0);
void println(int, int = 10);
void println(unsigned int, int = 10);
void println(long, int = 10);
void println(unsigned long, int = 10);
void println(double, int = 2);
void println(void);
void printNumber(unsigned long n, uint8_t base);
void printFloat(double number, uint8_t digits);
// using Print::write;
private:
void send(uint8_t, uint8_t);
void write4bits(uint8_t);

View file

@ -259,11 +259,11 @@ void MarlinSerial::println(void)
print('\n');
}
void MarlinSerial::println(const String &s)
/*void MarlinSerial::println(const String &s)
{
print(s);
println();
}
}*/
void MarlinSerial::println(const char c[])
{

View file

@ -197,12 +197,12 @@ class MarlinSerial //: public Stream
write(*buffer++);
}
static FORCE_INLINE void print(const String &s)
/* static FORCE_INLINE void print(const String &s)
{
for (int i = 0; i < (int)s.length(); i++) {
write(s[i]);
}
}
}*/
static FORCE_INLINE void print(const char *str)
{

View file

@ -99,6 +99,9 @@
#include "tmc2130.h"
#endif //TMC2130
#ifdef W25X20CL
#include "w25x20cl.h"
#endif //W25X20CL
#ifdef BLINKM
#include "BlinkM.h"
@ -1003,6 +1006,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))
@ -1020,15 +1025,58 @@ 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
// upgrade_sec_lang_from_external_flash();
upgrade_sec_lang_from_external_flash();
lcd_splash();
setup_killpin();
@ -1178,9 +1226,6 @@ void setup()
#endif //TMC2130
#ifdef NEW_SPI
spi_init();
#endif //NEW_SPI
st_init(); // Initialize stepper, this enables interrupts!
@ -1324,33 +1369,36 @@ 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);
puts_P(_n("\nNew ML support"));
printf_P(_n(" lang_selected = %d\n"), lang_selected);
printf_P(_n(" &_SEC_LANG = 0x%04x\n"), &_SEC_LANG);
printf_P(_n(" sizeof(_SEC_LANG) = 0x%04x\n"), sizeof(_SEC_LANG));
uint16_t ptr_lang_table0 = ((uint16_t)(&_SEC_LANG) + 0xff) & 0xff00;
printf_P(_n(" &_lang_table0 = 0x%04x\n"), ptr_lang_table0);
uint32_t _lt_magic = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 0)));
uint16_t _lt_size = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 4)));
uint16_t _lt_count = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 6)));
uint16_t _lt_chsum = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 8)));
uint16_t _lt_resv0 = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 10)));
uint32_t _lt_resv1 = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 12)));
printf_P(_n(" _lt_magic = 0x%08lx %S\n"), _lt_magic, (_lt_magic==0x4bb45aa5)?_n("OK"):_n("NA"));
printf_P(_n(" _lt_size = 0x%04x (%d)\n"), _lt_size, _lt_size);
printf_P(_n(" _lt_count = 0x%04x (%d)\n"), _lt_count, _lt_count);
printf_P(_n(" _lt_chsum = 0x%04x\n"), _lt_chsum);
printf_P(_n(" _lt_resv0 = 0x%04x\n"), _lt_resv0);
printf_P(_n(" _lt_resv1 = 0x%08lx\n"), _lt_resv1);
puts_P(_n("\n"));
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
if (eeprom_read_byte((uint8_t*)EEPROM_TEMP_CAL_ACTIVE) == 255) {
eeprom_write_byte((uint8_t*)EEPROM_TEMP_CAL_ACTIVE, 0);
@ -4427,7 +4475,7 @@ void process_commands()
KEEPALIVE_STATE(IN_HANDLER);
}
if (IS_SD_PRINTING)
LCD_MESSAGERPGM(_i("Resuming print"));////MSG_RESUMING c=0 r=0
LCD_MESSAGERPGM(_T(MSG_RESUMING_PRINT));
else
LCD_MESSAGERPGM(_T(WELCOME_MSG));
}

View file

@ -25,7 +25,7 @@
#ifdef SDSUPPORT
#include "SdBaseFile.h"
#include <Print.h>
//#include <Print.h>
#ifndef SdFile_h
#define SdFile_h
//------------------------------------------------------------------------------
@ -33,7 +33,7 @@
* \class SdFile
* \brief SdBaseFile with Print.
*/
class SdFile : public SdBaseFile, public Print {
class SdFile : public SdBaseFile/*, public Print*/ {
public:
SdFile() {}
SdFile(const char* name, uint8_t oflag);

View file

@ -20,10 +20,17 @@ void bootapp_print_vars()
void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
{
cli();
// uint16_t ui; for (ui = 0; ui < size; ui++)
// ram_array[ui+rptr] = 0xff;
boot_app_magic = 0x55aa55aa;
boot_app_flags = BOOT_APP_FLG_ERASE | BOOT_APP_FLG_COPY;
boot_app_flags |= BOOT_APP_FLG_COPY;
uint16_t ui; for (ui = 0; ui < size; ui++)
{
uint8_t uc = ram_array[ui+rptr];
if (pgm_readbyte(ui+fptr) & uc != uc)
{
boot_app_flags |= BOOT_APP_FLG_ERASE;
break;
}
}
boot_copy_size = (uint16_t)size;
boot_src_addr = (uint32_t)rptr;
boot_dst_addr = (uint32_t)fptr;

View file

@ -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

View file

@ -1,55 +1,47 @@
//language.c
#include "language.h"
#include <inttypes.h>
#include <avr/pgmspace.h>
#include "bootapp.h"
// Currectly active language selection.
unsigned char lang_selected = 0;
#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_t structure - 16byte header
typedef struct
{
struct
{
uint32_t magic;
uint16_t size;
uint16_t count;
uint16_t checksum;
uint16_t reserved0;
uint32_t reserved1;
} 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
@ -57,41 +49,145 @@ const char* lang_get_sec_lang_str(const char* s)
return (const char*)((char*)_lang_table + ui); //return calculated pointer
}
const char* lang_select(unsigned char 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;
}
#ifdef W25X20CL
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;
}
#else //W25X20CL
#endif //W25X20CL
/*
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
*/
return 0;
}
uint8_t lang_get_count()
{
#ifdef W25X20CL
uint8_t count = 2; //count = 1+n (primary + secondary + 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;
#else //W25X20CL
#endif //W25X20CL
}
uint16_t lang_get_code(uint8_t lang)
{
#ifdef W25X20CL
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) return LANG_CODE_XX; //magic not valid
return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem
}
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
}
#else //W25X20CL
#endif //W25X20CL
// 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;
}
const char* lang_get_name_by_code(uint16_t code)
{
switch (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 _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);
printf_P(_n("sizeof(_SEC_LANG) = 0x%04x\n"), sizeof(_SEC_LANG));
uint16_t ptr_lang_table0 = ((uint16_t)(&_SEC_LANG) + 0xff) & 0xff00;
printf_P(_n("&_lang_table0 = 0x%04x\n"), ptr_lang_table0);
uint32_t _lt_magic = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 0)));
uint16_t _lt_size = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 4)));
uint16_t _lt_count = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 6)));
uint16_t _lt_chsum = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 8)));
uint16_t _lt_resv0 = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 10)));
uint32_t _lt_resv1 = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 12)));
printf_P(_n(" _lt_magic = 0x%08lx %S\n"), _lt_magic, (_lt_magic==LANG_MAGIC)?_n("OK"):_n("NA"));
printf_P(_n(" _lt_size = 0x%04x (%d)\n"), _lt_size, _lt_size);
printf_P(_n(" _lt_count = 0x%04x (%d)\n"), _lt_count, _lt_count);
printf_P(_n(" _lt_chsum = 0x%04x\n"), _lt_chsum);
printf_P(_n(" _lt_resv0 = 0x%04x\n"), _lt_resv0);
printf_P(_n(" _lt_resv1 = 0x%08lx\n"), _lt_resv1);
if (_lt_magic != LANG_MAGIC) return 0;
puts_P(_n(" strings:\n"));
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
for (ui = 0; ui < _lt_count; ui++)
fprintf_P(out, _n(" %3d %S\n"), ui, lang_get_sec_lang_str_by_id(ui));
return _lt_count;
}
#endif //DEBUG_SEC_LANG
#endif //(LANG_MODE == 0)
}
unsigned char 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))) == 0x4bb45aa5) return 2;
return 1;
}
const char* lang_get_name(unsigned char lang)
{
if (lang == 0) return MSG_LANGUAGE_NAME + 2;
return lang_get_sec_lang_str(MSG_LANGUAGE_NAME);
}
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

View file

@ -2,13 +2,15 @@
#ifndef LANGUAGE_H
#define LANGUAGE_H
#define W25X20CL
#include "config.h"
#include <inttypes.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
@ -42,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
@ -49,6 +68,7 @@
// Language is not defined and it shall be selected from the menu.
#define LANG_ID_FORCE_SELECTION 254
// Language is not defined on a virgin RAMBo board.
#define LANG_ID_UNDEFINED 255
@ -58,24 +78,43 @@
// Number of languages available in the language table.
#define LANG_NUM 2
// Magic number at begin of lang table.
#define LANG_MAGIC 0x4bb45aa5
// Language codes (ISO639-1)
#define LANG_CODE_XX 0x3f3f //'??'
#define LANG_CODE_EN 0x656e //'en'
#define LANG_CODE_CZ 0x6373 //'cs'
#define LANG_CODE_DE 0x6465 //'de'
#define LANG_CODE_ES 0x6573 //'es'
#define LANG_CODE_IT 0x6974 //'it'
#define LANG_CODE_PL 0x706c //'pl'
#if defined(__cplusplus)
extern "C" {
#endif //defined(__cplusplus)
// Currectly active language selection.
extern unsigned char lang_selected;
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_select(unsigned char lang);
extern unsigned char lang_get_count();
extern const char* lang_get_name(unsigned char 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 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)
}
@ -84,7 +123,8 @@ extern const char* lang_get_name(unsigned char lang);
#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"

View file

@ -2479,7 +2479,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
// Print the decrasing ID of the measurement point.
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
lcd_implementation_print_at(0, next_line, mesh_point+1);
lcd_printPGM(_i(" of 4"));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
lcd_printPGM(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
// Move up.

View file

@ -71,6 +71,7 @@ const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20 r=0
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////c=20 r=4
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////c=20 r=2
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\xF8" "Refresh"); ////c=0 r=0
const char MSG_RESUMING_PRINT[] PROGMEM_I1 = ISTR("Resuming print"); ////c=0 r=0
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////c=20 r=4
const char MSG_SD_ERR_WRITE_TO_FILE[] PROGMEM_I1 = ISTR("error writing to file"); ////c=0 r=0
const char MSG_SD_OPEN_FILE_FAIL[] PROGMEM_I1 = ISTR("open failed, File: "); ////c=0 r=0

View file

@ -69,6 +69,7 @@ extern const char MSG_PULL_OUT_FILAMENT[];
extern const char MSG_RECOVER_PRINT[];
extern const char MSG_REFRESH[];
extern const char MSG_REMOVE_STEEL_SHEET[];
extern const char MSG_RESUMING_PRINT[];
extern const char MSG_SD_ERR_WRITE_TO_FILE[];
extern const char MSG_SD_OPEN_FILE_FAIL[];
extern const char MSG_SD_WORKDIR_FAIL[];

View file

@ -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

View file

@ -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

View file

@ -702,7 +702,7 @@ void lcd_commands()
strcat(cmd1, ftostr32(pause_lastpos[Y_AXIS]));
enquecommand(cmd1);
lcd_setstatuspgm(_i("Resuming print"));////MSG_RESUMING_PRINT c=20 r=1
lcd_setstatuspgm(_T(MSG_RESUMING_PRINT));
lcd_commands_step = 3;
}
}
@ -1721,9 +1721,9 @@ static void lcd_menu_temperatures()
static void lcd_menu_voltages()
{
float volt_pwr = VOLT_DIV_REF * ((float)current_voltage_raw_pwr / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
//float volt_bed = VOLT_DIV_REF * ((float)current_voltage_raw_bed / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
//fprintf_P(lcdout, PSTR(ESC_H(1,1) "PWR: %d.%01dV" ESC_H(1,2) "BED: %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr)), (int)volt_bed, (int)(10*fabs(volt_bed - (int)volt_bed)));
fprintf_P(lcdout, PSTR( ESC_H(1,1) "PWR: %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr))) ;
// float volt_bed = VOLT_DIV_REF * ((float)current_voltage_raw_bed / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
// fprintf_P(lcdout, PSTR(ESC_H(1,1)"PWR: %d.%01dV" ESC_H(1,2)"BED: %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr)), (int)volt_bed, (int)(10*fabs(volt_bed - (int)volt_bed)));
fprintf_P(lcdout, PSTR( ESC_H(1,1)"PWR: %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr))) ;
if (lcd_clicked())
{
menu_action_back();
@ -3714,14 +3714,25 @@ 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)
{
if (lang > LANG_ID_SEC)
if (!lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Copy selected language from XFLASH?"), false, true))
{
lcd_return_to_status();
lcd_update_enable(true);
return;
}
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
@ -3755,17 +3766,22 @@ 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);
// MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(1)), 1);
for (int i = 2; i < lang_get_count(); i++) //skip seconday language - solved in menu_action_setlang
MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(i)), i);
END_MENU();
}
#endif //(LANG_MODE != 0)
void lcd_mesh_bedleveling()
{
@ -4231,7 +4247,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
@ -4590,7 +4609,7 @@ void lcd_mylang_drawmenu(int cursor) {
}
}
*/
/*
void lcd_mylang_drawmenu(int cursor)
{
unsigned char lang_cnt = lang_get_count();
@ -4641,7 +4660,8 @@ void lcd_mylang_drawmenu(int cursor)
lcd.print("^");
}
}
*/
/*
void lcd_mylang_drawcursor(int cursor) {
unsigned char lang_cnt = lang_get_count();
@ -4651,8 +4671,9 @@ void lcd_mylang_drawcursor(int cursor) {
lcd.print(">");
}
}
*/
/*
void lcd_mylang()
{
int enc_dif = 0;
@ -4709,15 +4730,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){
@ -4730,7 +4749,7 @@ void lcd_mylang()
lcd_return_to_status();
}
*/
void bowden_menu() {
int enc_dif = encoderDiff;
int cursor_pos = 0;
@ -5638,6 +5657,13 @@ void lcd_confirm_print()
}
extern void __test();
static void lcd_test_menu()
{
__test();
}
static void lcd_main_menu()
{
@ -5807,6 +5833,7 @@ static void lcd_main_menu()
#endif
MENU_ITEM(submenu, _i("Support"), lcd_support_menu);////MSG_SUPPORT c=0 r=0
// MENU_ITEM(submenu, _i("Test"), lcd_test_menu);////MSG_SUPPORT c=0 r=0
END_MENU();
@ -7315,9 +7342,23 @@ static void menu_action_submenu(menuFunc_t data) {
static void menu_action_gcode(const char* pgcode) {
enquecommand_P(pgcode);
}
static void menu_action_setlang(unsigned char lang) {
lcd_set_lang(lang);
static void menu_action_setlang(unsigned char lang)
{
if (lang <= LANG_ID_SEC)
{
lcd_set_lang(lang);
return;
}
uint16_t code = lang_get_code(lang);
if (code == lang_get_code(1))
{
lcd_set_lang(1);
return;
}
lcd_set_lang(lang);
}
static void menu_action_function(menuFunc_t data) {
(*data)();
}

View file

@ -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();

View file

@ -973,7 +973,7 @@ if (print_sd_status)
lcd.setCursor(0, 3);
lcd_printPGM(PSTR(" "));
lcd.setCursor(0, 3);
lcd_printPGM(_i("Calibrating Z"));////MSG_HOMEYZ_PROGRESS c=0 r=0
lcd_printPGM(_T(MSG_CALIBRATE_Z_AUTO));
lcd_printPGM(PSTR(" : "));
lcd.print(custom_message_state-10);
}

View file

@ -148,6 +148,7 @@
#define MINTEMP_MINAMBIENT_RAW 978
//#define DEBUG_BUILD
//#define DEBUG_SEC_LANG //secondary language debug output at startup
#ifdef DEBUG_BUILD
//#define _NO_ASM
#define DEBUG_DCODES //D codes

178
Firmware/w25x20cl.c Normal file
View file

@ -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
Firmware/w25x20cl.h Normal file
View file

@ -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

64
lang/config.sh Normal file
View file

@ -0,0 +1,64 @@
#!/bin/sh
#
# config.sh - multi-language support configuration script
# Definition of absolute paths etc.
# This file is 'included' in all scripts.
#
# Arduino main folder:
export ARDUINO=C:/arduino-1.6.8
#
# Arduino builder:
export BUILDER=$ARDUINO/arduino_debug.exe
#
# AVR gcc tools:
export OBJCOPY=$ARDUINO/hardware/tools/avr/bin/avr-objcopy.exe
export OBJDUMP=$ARDUINO/hardware/tools/avr/bin/avr-objdump.exe
#
# Output folder:
export OUTDIR="../../output"
#
# Objects folder:
export OBJDIR="$OUTDIR/sketch"
#
# Generated elf file:
export INOELF="$OUTDIR/Firmware.ino.elf"
#
# Generated hex file:
export INOHEX="$OUTDIR/Firmware.ino.hex"
echo "config.sh started" >&2
_err=0
echo -n " Arduino main folder: " >&2
if [ -e $ARDUINO ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=1; fi
echo -n " Arduino builder: " >&2
if [ -e $BUILDER ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=2; fi
echo " AVR gcc tools:" >&2
echo -n " objcopy " >&2
if [ -e $OBJCOPY ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=3; fi
echo -n " objdump " >&2
if [ -e $OBJDUMP ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=4; fi
echo -n " Output folder: " >&2
if [ -e $OUTDIR ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=5; fi
echo -n " Objects folder: " >&2
if [ -e $OBJDIR ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=6; fi
echo -n " Generated elf file: " >&2
if [ -e $INOELF ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=7; fi
echo -n " Generated hex file: " >&2
if [ -e $INOHEX ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=8; fi
if [ $_err -eq 0 ]; then
echo "config.sh finished with success" >&2
export CONFIG_OK=1
else
echo "config.sh finished with errors!" >&2
export CONFIG_OK=0
fi

View file

@ -22,9 +22,6 @@
#MSG_CONFIGURATION_VER c=0 r=0
" Last Updated: "
#MSG_FIND_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
#MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
@ -139,9 +136,6 @@
#MSG_CALIBRATE_Z_AUTO c=20 r=2
"Calibrating Z"
#MSG_HOMEYZ_PROGRESS c=0 r=0
"Calibrating Z"
#MSG_MOVE_CARRIAGE_TO_THE_TOP_Z c=20 r=8
"Calibrating Z. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
@ -253,9 +247,6 @@
#MSG_INFO_EXTRUDER c=15 r=1
"Extruder info"
#MSG_EXTRUDER c=17 r=1
"Extruder"
#MSG_MOVE_E c=0 r=0
"Extruder"
@ -751,9 +742,6 @@
#MSG_RESUME_PRINT c=0 r=0
"Resume print"
#MSG_RESUMING c=0 r=0
"Resuming print"
#MSG_RESUMING_PRINT c=20 r=1
"Resuming print"

View file

@ -34,10 +34,6 @@
" of 4"
" z 4"
#MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
" z 4"
#MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 c=14 r=0
" of 9"
" z 9"
@ -182,11 +178,7 @@
"Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
"Kalibrace XYZ. Otacenim tlacitka posunte Z osu az k~hornimu dorazu. Potvrdte tlacitkem."
#MSG_HOMEYZ_PROGRESS c=0 r=0
"Calibrating Z"
"Kalibruji Z"
#MSG_HOMEYZ_PROGRESS c=0 r=0
#MSG_CALIBRATE_Z_AUTO c=0 r=0
"Calibrating Z"
"Kalibruji Z"
@ -342,10 +334,6 @@
"Extruder"
"Extruder"
#MSG_MOVE_E c=0 r=0
"Extruder"
"Extruder"
#MSG_FSENS_AUTOLOAD_ON c=17 r=1
"F. autoload [on]"
"F. autozav. [zap]"
@ -1002,11 +990,7 @@
"Resume print"
"Pokracovat"
#MSG_RESUMING c=0 r=0
"Resuming print"
"Obnoveni tisku"
#MSG_RESUMING c=0 r=0
#MSG_RESUMING_PRINT c=0 r=0
"Resuming print"
"Obnoveni tisku"

View file

@ -34,10 +34,6 @@
" of 4"
" von 4"
#MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
" von 4"
#MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 c=14 r=0
" of 9"
" von 9"
@ -182,11 +178,7 @@
"Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
"Kalibrieren von XYZ. Drehen Sie den Knopf bis der obere Anschlag erreicht wird. Klicken Sie den Knopf wenn es ganz oben wird."
#MSG_HOMEYZ_PROGRESS c=0 r=0
"Calibrating Z"
"Kalibriere Z"
#MSG_HOMEYZ_PROGRESS c=0 r=0
#MSG_CALIBRATE_Z_AUTO c=0 r=0
"Calibrating Z"
"Kalibriere Z"
@ -296,7 +288,7 @@
#MSG_Enqueing c=0 r=0
"enqueing \x22"
"enqueuing \x22
"enqueuing \x22"
#MSG_STACK_ERROR c=20 r=4
"Error - static memory has been overwritten"
@ -342,10 +334,6 @@
"Extruder"
"Extruder"
#MSG_MOVE_E c=0 r=0
"Extruder"
"Extruder"
#MSG_FSENS_AUTOLOAD_ON c=17 r=1
"F. autoload [on]"
"\x00"
@ -1002,11 +990,7 @@
"Resume print"
"Fortsetzen"
#MSG_RESUMING c=0 r=0
"Resuming print"
"Druck fortgesetzt"
#MSG_RESUMING c=0 r=0
#MSG_RESUMING_PRINT c=0 r=0
"Resuming print"
"Druck fortgesetzt"

View file

@ -34,10 +34,6 @@
" of 4"
" de 4"
#MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
" de 4"
#MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 c=14 r=0
" of 9"
" de 9"
@ -182,11 +178,7 @@
"Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
"Calibrando XYZ. Gira el boton para subir el extrusor hasta tocar los topes superiores. Despues haz clic."
#MSG_HOMEYZ_PROGRESS c=0 r=0
"Calibrating Z"
"Calibrando Z"
#MSG_HOMEYZ_PROGRESS c=0 r=0
#MSG_CALIBRATE_Z_AUTO c=0 r=0
"Calibrating Z"
"Calibrando Z"
@ -342,10 +334,6 @@
"Extruder"
"Extruir"
#MSG_MOVE_E c=0 r=0
"Extruder"
"Extruir"
#MSG_FSENS_AUTOLOAD_ON c=17 r=1
"F. autoload [on]"
"\x00"
@ -1002,11 +990,7 @@
"Resume print"
"Reanudar impres."
#MSG_RESUMING c=0 r=0
"Resuming print"
"Resumiendo impresion"
#MSG_RESUMING c=0 r=0
#MSG_RESUMING_PRINT c=0 r=0
"Resuming print"
"Resumiendo impresion"

View file

@ -34,10 +34,6 @@
" of 4"
" su 4"
#MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
" su 4"
#MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 c=14 r=0
" of 9"
" su 9"
@ -182,11 +178,7 @@
"Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
"Calibrazione XYZ. Ruotare la manopola per alzare il carrello Z fino all'altezza massima. Click per terminare."
#MSG_HOMEYZ_PROGRESS c=0 r=0
"Calibrating Z"
"Calibrando Z"
#MSG_HOMEYZ_PROGRESS c=0 r=0
#MSG_CALIBRATE_Z_AUTO c=0 r=0
"Calibrating Z"
"Calibrando Z"
@ -342,10 +334,6 @@
"Extruder"
"Muovi Estrusore"
#MSG_MOVE_E c=0 r=0
"Extruder"
"Muovi Estrusore"
#MSG_FSENS_AUTOLOAD_ON c=17 r=1
"F. autoload [on]"
"\x00"
@ -1002,11 +990,7 @@
"Resume print"
"Riprendi stampa"
#MSG_RESUMING c=0 r=0
"Resuming print"
"Riprendi stampa"
#MSG_RESUMING c=0 r=0
#MSG_RESUMING_PRINT c=0 r=0
"Resuming print"
"Riprendi stampa"

View file

@ -34,10 +34,6 @@
" of 4"
" z 4"
#MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
" of 4"
" z 4"
#MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 c=14 r=0
" of 9"
" z 9"
@ -182,11 +178,7 @@
"Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
"Kalibracja XYZ. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic."
#MSG_HOMEYZ_PROGRESS c=0 r=0
"Calibrating Z"
"Kalibruje Z"
#MSG_HOMEYZ_PROGRESS c=0 r=0
#MSG_CALIBRATE_Z_AUTO c=0 r=0
"Calibrating Z"
"Kalibruje Z"
@ -342,10 +334,6 @@
"Extruder"
"Extruder"
#MSG_MOVE_E c=0 r=0
"Extruder"
"Extruder"
#MSG_FSENS_AUTOLOAD_ON c=17 r=1
"F. autoload [on]"
"\x00"
@ -1002,11 +990,7 @@
"Resume print"
"Kontynuowac"
#MSG_RESUMING c=0 r=0
"Resuming print"
"Wznowienie druku"
#MSG_RESUMING c=0 r=0
#MSG_RESUMING_PRINT c=0 r=0
"Resuming print"
"Wznowienie druku"

View file

@ -1,138 +1,160 @@
#!/bin/sh
# makelang.sh - multi-language support high-level script
# for generating lang_xx.bin (secondary language binary file)
#
# Input files:
# lang_en.txt
# lang_en_$LANG.txt
#
# Output files:
# lang_en.tmp (temporary, will be removed when finished)
# lang_en_$LANG.tmp ==||==
# lang_en_$LANG.dif ==||==
# lang_$LANG.txt
#
#
# Selected language:
LANG=$1
if [ -z "$LANG" ]; then LANG='cz'; fi
#
#
function finish
{
if [ "$1" == "0" ]; then
if [ -e lang_en.tmp ]; then rm lang_en.tmp; fi
if [ -e lang_en_$LANG.tmp ]; then rm lang_en_$LANG.tmp; fi
if [ -e lang_en_$LANG.dif ]; then rm lang_en_$LANG.dif; fi
fi
echo
if [ "$1" == "0" ]; then
echo "make_lang.sh finished with success" >&2
else
echo "make_lang.sh finished with errors!" >&2
fi
case "$-" in
*i*) echo "press enter key"; read ;;
esac
exit $1
}
echo "make_lang.sh started" >&2
echo "selected language=$LANG" >&2
#check if input files exists
echo -n " checking input files..." >&2
if [ ! -e lang_en.txt ]; then echo "NG! file lang_en.txt not found!" >&2; exit 1; fi
if [ ! -e lang_en_$LANG.txt ]; then echo "NG! file lang_en_$LANG.txt not found!" >&2; exit 1; fi
echo "OK" >&2
#filter comment and empty lines from key and dictionary files, create temporary files
echo -n " creating tmp files..." >&2
cat lang_en.txt | sed "/^$/d;/^#/d" > lang_en.tmp
cat lang_en_$LANG.txt | sed "/^$/d;/^#/d" > lang_en_$LANG.tmp
echo "OK" >&2
#cat lang_en_$LANG.tmp | sed 'n;d' >test1.txt
#compare files using diff and check for differences
echo -n " comparing tmp files..." >&2
if ! cat lang_en_$LANG.tmp | sed 'n;d' | diff lang_en.tmp - > lang_en_$LANG.dif; then
echo "NG!" >&2
echo "Entries in lang_en_$LANG.txt are different from lang_en.txt!" >&2
echo "please check lang_en_$LANG.dif" >&2
finish 1
fi
echo "OK" >&2
#generate lang_xx.txt (secondary language text data sorted by ids)
echo -n " generating lang_$LANG.txt..." >&2
cat lang_en_$LANG.tmp | sed '1~2d' | sed "s/^\"\\\\x00/\"/" > lang_$LANG.txt
echo "OK" >&2
#generate lang_xx.dat (secondary language text data in binary form)
echo -n " generating lang_$LANG.dat..." >&2
cat lang_$LANG.txt | sed "s/\\\\/\\\\\\\\/g" | while read s; do
s=${s#\"}
s=${s%\"}
echo -n -e "$s"'\x00'
done >lang_$LANG.dat
echo "OK" >&2
#calculate variables
lt_magic='\xa5\x5a\xb4\x4b'
lt_count=$(grep -c '^' lang_$LANG.txt)
lt_data_size=$(wc -c lang_$LANG.dat | cut -f1 -d' ')
lt_offs_size=$((2 * $lt_count))
lt_size=$((16 + $lt_offs_size + $lt_data_size))
lt_chsum=1
lt_resv0='\xff\xff'
lt_resv1='\xff\xff\xff\xff'
#generate lang_xx.ofs (secondary language text data offset table)
echo -n " generating lang_$LANG.ofs..." >&2
cat lang_$LANG.txt | sed "s/\\\\x[0-9a-f][0-9a-f]/\./g;s/\\\\[0-7][0-7][0-7]/\./g" |\
awk 'BEGIN { o='$((16 + $lt_offs_size))';} { printf("%d\n",o); o+=(length($0)-1); }' > lang_$LANG.ofs
echo "OK" >&2
#generate lang_xx.bin (secondary language result binary file)
echo " generating lang_$LANG.bin:" >&2
#create empty file
dd if=/dev/zero of=lang_$LANG.bin bs=1 count=$lt_size 2>/dev/null
#awk code to format ui16 variables for dd
awk_ui16='{ h=int($1/256); printf("\\x%02x\\x%02x\n", int($1-256*h), h); }'
#write data to binary file with dd
echo -n " writing header (16 bytes)..." >&2
echo -n -e "$lt_magic" |\
dd of=lang_$LANG.bin bs=1 count=4 seek=0 conv=notrunc 2>/dev/null
echo -n -e $(echo -n "$lt_size" | awk "$awk_ui16") |\
dd of=lang_$LANG.bin bs=1 count=2 seek=4 conv=notrunc 2>/dev/null
echo -n -e $(echo -n "$lt_count" | awk "$awk_ui16") |\
dd of=lang_$LANG.bin bs=1 count=2 seek=6 conv=notrunc 2>/dev/null
echo -n -e $(echo -n "$lt_chsum" | awk "$awk_ui16") |\
dd of=lang_$LANG.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
echo -n -e "$lt_resv0" |\
dd of=lang_$LANG.bin bs=1 count=2 seek=10 conv=notrunc 2>/dev/null
echo -n -e "$lt_resv1" |\
dd of=lang_$LANG.bin bs=1 count=4 seek=12 conv=notrunc 2>/dev/null
echo "OK" >&2
echo -n " writing offset table ($lt_offs_size bytes)..." >&2
echo -n -e $(cat lang_$LANG.ofs | awk "$awk_ui16" | tr -d '\n'; echo) |\
dd of=./lang_$LANG.bin bs=1 count=$lt_offs_size seek=16 conv=notrunc 2>/dev/null
echo "OK" >&2
echo -n " writing text data ($lt_data_size bytes)..." >&2
dd if=./lang_$LANG.dat of=./lang_$LANG.bin bs=1 count=$lt_data_size seek=$((16 + $lt_offs_size)) conv=notrunc 2>/dev/null
echo "OK" >&2
echo " lang_table details:" >&2
echo " lt_count = $lt_count" >&2
echo " lt_size = $lt_size" >&2
echo " lt_chsum = $lt_chsum" >&2
finish 0
#!/bin/sh
#
# makelang.sh - multi-language support script
# for generating lang_xx.bin (secondary language binary file)
#
# Input files:
# lang_en.txt
# lang_en_$LANG.txt
#
# Output files:
# lang_en.tmp (temporary, will be removed when finished)
# lang_en_$LANG.tmp ==||==
# lang_en_$LANG.dif ==||==
# lang_$LANG.txt
#
#
# Selected language:
LANG=$1
if [ -z "$LANG" ]; then LANG='cz'; fi
#
#
finish()
{
if [ $1 -eq 0 ]; then
if [ -e lang_en.tmp ]; then rm lang_en.tmp; fi
if [ -e lang_en_$LANG.tmp ]; then rm lang_en_$LANG.tmp; fi
if [ -e lang_en_$LANG.dif ]; then rm lang_en_$LANG.dif; fi
fi
# echo >&2
if [ $1 -eq 0 ]; then
echo "make_lang.sh finished with success" >&2
else
echo "make_lang.sh finished with errors!" >&2
fi
exit $1
}
make_lang()
{
LANG=$1
echo "make_lang.sh started" >&2
echo "selected language=$LANG" >&2
#check if input files exists
echo -n " checking input files..." >&2
if [ ! -e lang_en.txt ]; then echo "NG! file lang_en.txt not found!" >&2; exit 1; fi
if [ ! -e lang_en_$LANG.txt ]; then echo "NG! file lang_en_$LANG.txt not found!" >&2; exit 1; fi
echo "OK" >&2
#filter comment and empty lines from key and dictionary files, create temporary files
echo -n " creating tmp files..." >&2
cat lang_en.txt | sed "/^$/d;/^#/d" > lang_en.tmp
cat lang_en_$LANG.txt | sed "/^$/d;/^#/d" > lang_en_$LANG.tmp
echo "OK" >&2
#cat lang_en_$LANG.tmp | sed 'n;d' >test1.txt
#compare files using diff and check for differences
echo -n " comparing tmp files..." >&2
if ! cat lang_en_$LANG.tmp | sed 'n;d' | diff lang_en.tmp - > lang_en_$LANG.dif; then
echo "NG!" >&2
echo "Entries in lang_en_$LANG.txt are different from lang_en.txt!" >&2
echo "please check lang_en_$LANG.dif" >&2
finish 1
fi
echo "OK" >&2
#generate lang_xx.txt (secondary language text data sorted by ids)
echo -n " generating lang_$LANG.txt..." >&2
cat lang_en_$LANG.tmp | sed '1~2d' | sed "s/^\"\\\\x00/\"/" > lang_$LANG.txt
echo "OK" >&2
#generate lang_xx.dat (secondary language text data in binary form)
echo -n " generating lang_$LANG.dat..." >&2
cat lang_$LANG.txt | sed "s/\\\\/\\\\\\\\/g" | while read s; do
s=${s#\"}
s=${s%\"}
/bin/echo -e -n "$s\x00"
done >lang_$LANG.dat
echo "OK" >&2
#calculate variables
lt_magic='\xa5\x5a\xb4\x4b'
lt_count=$(grep -c '^' lang_$LANG.txt)
lt_data_size=$(wc -c lang_$LANG.dat | cut -f1 -d' ')
lt_offs_size=$((2 * $lt_count))
lt_size=$((16 + $lt_offs_size + $lt_data_size))
lt_chsum=1
lt_code='\xff\xff'
lt_resv1='\xff\xff\xff\xff'
case "$LANG" in
*en*) lt_code='\x6e\x65' ;;
*cz*) lt_code='\x73\x63' ;;
*de*) lt_code='\x65\x64' ;;
*es*) lt_code='\x73\x65' ;;
*it*) lt_code='\x74\x69' ;;
*pl*) lt_code='\x6c\x70' ;;
esac
#generate lang_xx.ofs (secondary language text data offset table)
echo -n " generating lang_$LANG.ofs..." >&2
cat lang_$LANG.txt | sed "s/\\\\x[0-9a-f][0-9a-f]/\./g;s/\\\\[0-7][0-7][0-7]/\./g" |\
awk 'BEGIN { o='$((16 + $lt_offs_size))';} { printf("%d\n",o); o+=(length($0)-1); }' > lang_$LANG.ofs
echo "OK" >&2
#generate lang_xx.bin (secondary language result binary file)
echo " generating lang_$LANG.bin:" >&2
#create empty file
dd if=/dev/zero of=lang_$LANG.bin bs=1 count=$lt_size 2>/dev/null
#awk code to format ui16 variables for dd
awk_ui16='{ h=int($1/256); printf("\\x%02x\\x%02x\n", int($1-256*h), h); }'
#write data to binary file with dd
echo -n " writing header (16 bytes)..." >&2
/bin/echo -n -e "$lt_magic" |\
dd of=lang_$LANG.bin bs=1 count=4 seek=0 conv=notrunc 2>/dev/null
/bin/echo -n -e $(echo -n "$lt_size" | awk "$awk_ui16") |\
dd of=lang_$LANG.bin bs=1 count=2 seek=4 conv=notrunc 2>/dev/null
/bin/echo -n -e $(echo -n "$lt_count" | awk "$awk_ui16") |\
dd of=lang_$LANG.bin bs=1 count=2 seek=6 conv=notrunc 2>/dev/null
/bin/echo -n -e $(echo -n "$lt_chsum" | awk "$awk_ui16") |\
dd of=lang_$LANG.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
/bin/echo -n -e "$lt_code" |\
dd of=lang_$LANG.bin bs=1 count=2 seek=10 conv=notrunc 2>/dev/null
/bin/echo -n -e "$lt_resv1" |\
dd of=lang_$LANG.bin bs=1 count=4 seek=12 conv=notrunc 2>/dev/null
echo "OK" >&2
echo -n " writing offset table ($lt_offs_size bytes)..." >&2
/bin/echo -n -e $(cat lang_$LANG.ofs | awk "$awk_ui16" | tr -d '\n'; echo) |\
dd of=./lang_$LANG.bin bs=1 count=$lt_offs_size seek=16 conv=notrunc 2>/dev/null
echo "OK" >&2
echo -n " writing text data ($lt_data_size bytes)..." >&2
dd if=./lang_$LANG.dat of=./lang_$LANG.bin bs=1 count=$lt_data_size seek=$((16 + $lt_offs_size)) conv=notrunc 2>/dev/null
echo "OK" >&2
echo " lang_table details:" >&2
echo " lt_count = $lt_count" >&2
echo " lt_size = $lt_size" >&2
echo " lt_chsum = $lt_chsum" >&2
}
echo $LANG
if [ "$LANG" = "all" ]; then
make_lang cz
make_lang de
make_lang es
make_lang it
make_lang pl
exit 0
else
make_lang $LANG
fi
finish 0

1717
lang/po/lang.pot Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,61 +1,114 @@
#!/bin/sh
#
# make_po.sh - multi-language support script
# for generating lang_xx.po
#
SRCDIR="../../Firmware"
#
LANG=$1
if [ -z "$LANG" ]; then LANG=cz; fi
#
echo "make_po.sh started" >&2
#remove output file if exists
if [ -e lang_$LANG.po ]; then rm lang_$LANG.po; fi
langname=$(\
case "$LANG" in
*en*) echo "English" ;;
*cz*) echo "Czech" ;;
*de*) echo "German" ;;
*it*) echo "Italian" ;;
*es*) echo "Spanish" ;;
*pl*) echo "Polish" ;;
esac)
#write po header
echo "# Translation into $langname." > lang_$LANG.po
echo "#" >> lang_$LANG.po
echo 'msgid ""' >> lang_$LANG.po
echo 'msgstr ""' >> lang_$LANG.po
echo '"MIME-Version: 1.0\n"' >> lang_$LANG.po
echo '"Content-Type: text/plain; charset=UTF-8\n"' >> lang_$LANG.po
echo '"Content-Transfer-Encoding: 8bit\n"' >> lang_$LANG.po
echo >> lang_$LANG.po
#list .cpp, .c and .h files
files=$(ls "$SRCDIR"/*.cpp "$SRCDIR"/*.c "$SRCDIR"/*.h)
#loop over all messages, print only untranslated (=="\x00")
s0=''
s1=''
s2=''
cat ../lang_en_$LANG.txt | sed "s/\\\\/\\\\\\\\/g;s/^#/#: /" | while read -r s; do
if [ "$s" == "" ]; then
if [ "$s0" == "\"\\\\x00\"" ]; then
search=$(echo -e "$s1")
found=$(grep -m1 -n -F "$search" $files | head -n1 | cut -f1-2 -d':' | sed "s/^.*\///")
echo "#: $found"
echo -e "msgid $s1"
echo 'msgstr ""'
echo
fi
fi
s2=$s1
s1=$s0
s0=$s
done >> lang_$LANG.po
echo "make_po.sh finished" >&2
exit 0
#!/bin/sh
#
# make_po.sh - multi-language support script
# for generating lang_xx.po
#
SRCDIR="../../Firmware"
#
LANG=$1
if [ -z "$LANG" ]; then LANG=cz; fi
#
if [ "$LANG" == "all" ]; then
./make_po.sh cz
./make_po.sh de
./make_po.sh es
./make_po.sh it
./make_po.sh pl
exit 0
fi
echo "make_po.sh started" >&2
echo " selected language=$LANG" >&2
#remove output file if exists
if [ -e lang_$LANG.po ]; then rm lang_$LANG.po; fi
lang_name=$(\
case "$LANG" in
*en*) echo "English" ;;
*cz*) echo "Czech" ;;
*de*) echo "German" ;;
*es*) echo "Spanish" ;;
*it*) echo "Italian" ;;
*pl*) echo "Polish" ;;
esac)
lang_short=$(\
case "$LANG" in
*en*) echo "en" ;;
*cz*) echo "cs" ;;
*de*) echo "de" ;;
*it*) echo "it" ;;
*es*) echo "es" ;;
*pl*) echo "pl" ;;
esac)
po_date=$(date)
#write po header
echo "# Translation of Prusa-Firmware into $lang_name." > lang_$LANG.po
echo "#" >> lang_$LANG.po
echo 'msgid ""' >> lang_$LANG.po
echo 'msgstr ""' >> lang_$LANG.po
echo '"MIME-Version: 1.0\n"' >> lang_$LANG.po
echo '"Content-Type: text/plain; charset=UTF-8\n"' >> lang_$LANG.po
echo '"Content-Transfer-Encoding: 8bit\n"' >> lang_$LANG.po
echo '"Language: '$lang_short'\n"' >> lang_$LANG.po
echo '"Project-Id-Version: Prusa-Firmware\n"' >> lang_$LANG.po
echo '"POT-Creation-Date: '$po_date'\n"' >> lang_$LANG.po
echo '"PO-Revision-Date: '$po_date'\n"' >> lang_$LANG.po
echo '"Language-Team: \n"' >> lang_$LANG.po
echo '"X-Generator: Poedit 2.0.7\n"' >> lang_$LANG.po
echo '"X-Poedit-SourceCharset: UTF-8\n"' >> lang_$LANG.po
echo '"Last-Translator: \n"' >> lang_$LANG.po
echo '"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"' >> lang_$LANG.po
echo >> lang_$LANG.po
#list .cpp, .c and .h files
files=$(ls "$SRCDIR"/*.cpp "$SRCDIR"/*.c "$SRCDIR"/*.h)
num_texts=$(grep '^#' -c ../lang_en_$LANG.txt)
num_texts_nt=$(grep '^\"\\x00\"' -c ../lang_en_$LANG.txt)
echo " $num_texts texts, $num_texts_nt not translated" >&2
#loop over all messages
s0=''
s1=''
s2=''
num=1
cat ../lang_en_$LANG.txt | sed "s/\\\\/\\\\\\\\/g" | while read -r s; do
if [ "$s" == "" ]; then
echo " processing $num of $num_texts" >&2
if [ "$s0" == "\"\\\\x00\"" ]; then
search=$(/bin/echo -e "$s1")
found=$(grep -m1 -n -F "$search" $files | head -n1 | cut -f1-2 -d':' | sed "s/^.*\///")
echo "$s2" | sed 's/ c=0//;s/ r=0//;s/^#/# /'
echo "#: $found"
echo "#, fuzzy"
/bin/echo -e "msgid $s1"
echo 'msgstr ""'
echo
else
search=$(/bin/echo -e "$s1")
found=$(grep -m1 -n -F "$search" $files | head -n1 | cut -f1-2 -d':' | sed "s/^.*\///")
echo "$s2" | sed 's/ c=0//;s/ r=0//;s/^#/# /'
echo "#: $found"
/bin/echo -e "msgid $s1"
/bin/echo -e "msgstr $s0"
echo
fi
num=$((num+1))
fi
s2=$s1
s1=$s0
s0=$s
done >> lang_$LANG.po
#replace LF with CRLF
sync
sed -i 's/$/\r/' lang_$LANG.po
echo "make_po.sh finished" >&2
#read
exit 0

86
lang/po/make_pot.sh Normal file
View file

@ -0,0 +1,86 @@
#!/bin/sh
#
# make_pot.sh - multi-language support script
# Generate lang.pot
#
SRCDIR="../../Firmware"
#
#
echo "make_pot.sh started" >&2
#remove output file if exists
if [ -e lang.pot ]; then rm lang.pot; fi
lang_name="English"
lang_short="en"
po_date=$(date)
#cat ../lang_en_cz.txt | sed "/^$/d;/^#/d" | sed '{N;s/\n/ /}' | sed -n '/\"\\x00\"$/p' | sed 's/ \"\\x00\"$//' > lang_pot_cz.tmp
#cat ../lang_en_de.txt | sed "/^$/d;/^#/d" | sed '{N;s/\n/ /}' | sed -n '/\"\\x00\"$/p' | sed 's/ \"\\x00\"$//' > lang_pot_de.tmp
#cat ../lang_en_es.txt | sed "/^$/d;/^#/d" | sed '{N;s/\n/ /}' | sed -n '/\"\\x00\"$/p' | sed 's/ \"\\x00\"$//' > lang_pot_es.tmp
#cat ../lang_en_it.txt | sed "/^$/d;/^#/d" | sed '{N;s/\n/ /}' | sed -n '/\"\\x00\"$/p' | sed 's/ \"\\x00\"$//' > lang_pot_it.tmp
#cat ../lang_en_pl.txt | sed "/^$/d;/^#/d" | sed '{N;s/\n/ /}' | sed -n '/\"\\x00\"$/p' | sed 's/ \"\\x00\"$//' > lang_pot_pl.tmp
#cat lang_pot_cz.tmp lang_pot_de.tmp lang_pot_es.tmp lang_pot_it.tmp lang_pot_pl.tmp | sort -u > lang_pot.tmp
#cat ../lang_en.txt | sed "/^$/d;/^#/d" > lang_pot.tmp
#write po header
echo "# Translation of Prusa-Firmware into $lang_name." > lang.pot
echo "#" >> lang.pot
echo 'msgid ""' >> lang.pot
echo 'msgstr ""' >> lang.pot
echo '"MIME-Version: 1.0\n"' >> lang.pot
echo '"Content-Type: text/plain; charset=UTF-8\n"' >> lang.pot
echo '"Content-Transfer-Encoding: 8bit\n"' >> lang.pot
echo '"Language: '$lang_short'\n"' >> lang.pot
echo '"Project-Id-Version: Prusa-Firmware\n"' >> lang.pot
echo '"POT-Creation-Date: '$po_date'\n"' >> lang.pot
echo '"PO-Revision-Date: '$po_date'\n"' >> lang.pot
echo '"Language-Team: \n"' >> lang.pot
echo '"X-Generator: Poedit 2.0.7\n"' >> lang.pot
echo '"X-Poedit-SourceCharset: UTF-8\n"' >> lang.pot
echo '"Last-Translator: \n"' >> lang.pot
echo '"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"' >> lang.pot
echo >> lang.pot
#list .cpp, .c and .h files
files=$(ls "$SRCDIR"/*.cpp "$SRCDIR"/*.c "$SRCDIR"/*.h)
num_texts=$(grep '^#' -c ../lang_en.txt)
#num_texts_nt=$(grep '^"' -c lang_en.txt)
#echo " $num_texts texts, $num_texts_nt not translated" >&2
echo " $num_texts texts" >&2
#loop over all messages
s0=''
s1=''
num=1
cat ../lang_en.txt | sed "s/\\\\/\\\\\\\\/g" | while read -r s; do
if [ -z "$s" ]; then
echo " processing $num of $num_texts" >&2
search=$(/bin/echo -e "$s0")
found=$(grep -m1 -n -F "$search" $files | head -n1 | cut -f1-2 -d':' | sed "s/^.*\///")
echo "$s1" | sed 's/ c=0//;s/ r=0//;s/^#/# /'
echo "#: $found"
#echo "#, fuzzy"
/bin/echo -e "msgid $s0"
echo 'msgstr ""'
echo
num=$((num+1))
fi
s1=$s0
s0=$s
done >> lang.pot
#replace LF with CRLF
sync
sed -i 's/$/\r/' lang.pot
echo "make_pot.sh finished" >&2
read
exit 0

View file

@ -1,116 +1,142 @@
#!/bin/sh
# postbuild.sh - multi-language support high-level script
# for generating binary with secondary language
#
# Input files:
# $OUTDIR/Firmware.ino.elf
# $OUTDIR/sketch/*.o (all object files)
#
# Output files:
# text.sym
# $PROGMEM.sym (progmem1.sym)
# $PROGMEM.lss (...)
# $PROGMEM.hex
# $PROGMEM.chr
# $PROGMEM.var
# $PROGMEM.txt
# textaddr.txt
#
# Output folder and elf file:
OUTDIR="../../output"
OUTELF="$OUTDIR/Firmware.ino.elf"
#
# AVR gcc tools used:
OBJCOPY=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-objcopy.exe
#
# Selected language:
LANG=$1
#if [ -z "$LANG" ]; then LANG='cz'; fi
#
# Params:
IGNORE_MISSING_TEXT=1
function finish
{
echo
if [ "$1" == "0" ]; then
echo "postbuild.sh finished with success" >&2
else
echo "postbuild.sh finished with errors!" >&2
fi
case "$-" in
*i*) echo "press enter key"; read ;;
esac
exit $1
}
echo "postbuild.sh started" >&2
#check input files
echo " checking files:" >&2
if [ ! -e $OUTDIR ]; then echo " folder '$OUTDIR' not found!" >&2; finish 1; fi
echo " folder OK" >&2
if [ ! -e $OUTELF ]; then echo " elf file '$OUTELF' not found!" >&2; finish 1; fi
echo " elf OK" >&2
if ! ls $OUTDIR/sketch/*.o >/dev/null 2>&1; then echo " no object files in '$OUTDIR/sketch/'!" >&2; finish 1; fi
echo " objects OK" >&2
#run progmem.sh - examine content of progmem1
echo -n " running progmem.sh..." >&2
./progmem.sh 1 2>progmem.out
if [ $? -ne 0 ]; then echo "NG! - check progmem.out file" >&2; finish 1; fi
echo "OK" >&2
#run textaddr.sh - map progmem addreses to text identifiers
echo -n " running textaddr.sh..." >&2
./textaddr.sh 2>textaddr.out
if [ $? -ne 0 ]; then echo "NG! - check progmem.out file" >&2; finish 1; fi
echo "OK" >&2
#check for messages declared in progmem1, but not found in lang_en.txt
echo -n " checking textaddr.txt..." >&2
if cat textaddr.txt | grep "^ADDR NF" >/dev/null; then
echo "NG! - some texts not found in lang_en.txt!"
if [ $(("0$IGNORE_MISSING_TEXT")) -eq 0 ]; then
finish 1
else
echo " missing text ignored!" >&2
fi
else
echo "OK" >&2
fi
#update progmem1 id entries in binary file
echo -n " extracting binary..." >&2
$OBJCOPY -I ihex -O binary $OUTDIR/Firmware.ino.hex ./firmware.bin
echo "OK" >&2
#update binary file
echo " updating binary:" >&2
#update progmem1 id entries in binary file
echo -n " primary language ids..." >&2
cat textaddr.txt | grep "^ADDR OK" | cut -f3- -d' ' | sed "s/^0000/0x/" |\
awk '{ id = $2 - 1; hi = int(id / 256); lo = int(id - 256 * hi); printf("%d \\\\x%02x\\\\x%02x\n", strtonum($1), lo, hi); }' |\
while read addr data; do
echo -n -e $data | dd of=./firmware.bin bs=1 count=2 seek=$addr conv=notrunc oflag=nonblock 2>/dev/null
done
echo "OK" >&2
#update _SEC_LANG in binary file if language is selected
echo -n " secondary language data..." >&2
if [ ! -z "$LANG" ]; then
./update_lang.sh $LANG 2>./update_lang.out
if [ $? -ne 0 ]; then echo "NG! - check update_lang.out file" >&2; finish 1; fi
echo "OK" >&2
finish 0
else
echo "skipped" >&2
fi
#convert bin to hex
echo -n " converting to hex..." >&2
$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware.hex
echo "OK" >&2
finish 0
#!/bin/sh
#
# postbuild.sh - multi-language support script
# Generate binary with secondary language.
#
# Input files:
# $OUTDIR/Firmware.ino.elf
# $OUTDIR/sketch/*.o (all object files)
#
# Output files:
# text.sym
# $PROGMEM.sym (progmem1.sym)
# $PROGMEM.lss (...)
# $PROGMEM.hex
# $PROGMEM.chr
# $PROGMEM.var
# $PROGMEM.txt
# textaddr.txt
#
#
# Config:
if [ -z "$CONFIG_OK" ]; then eval "$(cat config.sh)"; fi
if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi
#
# Selected language:
LANG=$1
#if [ -z "$LANG" ]; then LANG='cz'; fi
#
# Params:
IGNORE_MISSING_TEXT=1
finish()
{
echo
if [ "$1" = "0" ]; then
echo "postbuild.sh finished with success" >&2
else
echo "postbuild.sh finished with errors!" >&2
fi
case "$-" in
*i*) echo "press enter key"; read ;;
esac
exit $1
}
echo "postbuild.sh started" >&2
#check input files
echo " checking files:" >&2
if [ ! -e $OUTDIR ]; then echo " folder '$OUTDIR' not found!" >&2; finish 1; fi
echo " folder OK" >&2
if [ ! -e $INOELF ]; then echo " elf file '$INOELF' not found!" >&2; finish 1; fi
echo " elf OK" >&2
if ! ls $OBJDIR/*.o >/dev/null 2>&1; then echo " no object files in '$OBJDIR/'!" >&2; finish 1; fi
echo " objects OK" >&2
#run progmem.sh - examine content of progmem1
echo -n " running progmem.sh..." >&2
./progmem.sh 1 2>progmem.out
if [ $? -ne 0 ]; then echo "NG! - check progmem.out file" >&2; finish 1; fi
echo "OK" >&2
#run textaddr.sh - map progmem addreses to text identifiers
echo -n " running textaddr.sh..." >&2
./textaddr.sh 2>textaddr.out
if [ $? -ne 0 ]; then echo "NG! - check progmem.out file" >&2; finish 1; fi
echo "OK" >&2
#check for messages declared in progmem1, but not found in lang_en.txt
echo -n " checking textaddr.txt..." >&2
if cat textaddr.txt | grep "^ADDR NF" >/dev/null; then
echo "NG! - some texts not found in lang_en.txt!"
if [ $IGNORE_MISSING_TEXT -eq 0 ]; then
finish 1
else
echo " missing text ignored!" >&2
fi
else
echo "OK" >&2
fi
#update progmem1 id entries in binary file
echo -n " extracting binary..." >&2
$OBJCOPY -I ihex -O binary $INOHEX ./firmware.bin
echo "OK" >&2
#update binary file
echo " updating binary:" >&2
#update progmem1 id entries in binary file
echo -n " primary language ids..." >&2
cat textaddr.txt | grep "^ADDR OK" | cut -f3- -d' ' | sed "s/^0000/0x/" |\
awk '{ id = $2 - 1; hi = int(id / 256); lo = int(id - 256 * hi); printf("%d \\\\x%02x\\\\x%02x\n", strtonum($1), lo, hi); }' |\
while read addr data; do
/bin/echo -n -e $data | dd of=./firmware.bin bs=1 count=2 seek=$addr conv=notrunc oflag=nonblock 2>/dev/null
done
echo "OK" >&2
#update _SEC_LANG in binary file if language is selected
echo -n " secondary language data..." >&2
if [ ! -z "$LANG" ]; then
./update_lang.sh $LANG 2>./update_lang.out
if [ $? -ne 0 ]; then echo "NG! - check update_lang.out file" >&2; finish 1; fi
echo "OK" >&2
finish 0
else
echo "Updating languages:" >&2
if [ -e lang_cz.bin ]; then
echo -n " Czech : " >&2
./update_lang.sh cz 2>./update_lang_cz.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
if [ -e lang_de.bin ]; then
echo -n " German : " >&2
./update_lang.sh de 2>./update_lang_de.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
if [ -e lang_it.bin ]; then
echo -n " Italian: " >&2
./update_lang.sh it 2>./update_lang_it.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
if [ -e lang_es.bin ]; then
echo -n " Spanish: " >&2
./update_lang.sh es 2>./update_lang_es.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
if [ -e lang_pl.bin ]; then
echo -n " Polish : " >&2
./update_lang.sh pl 2>./update_lang_pl.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
# echo "skipped" >&2
fi
#convert bin to hex
#echo -n " converting to hex..." >&2
#$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware.hex
#echo "OK" >&2
finish 0

View file

@ -1,127 +1,132 @@
#!/bin/sh
# progmem.sh - multi-language support low-level script
# for examining content of progmem sections (default is progmem1)
#
# Input files:
# $OUTDIR/Firmware.ino.elf
# $OUTDIR/sketch/*.o (all object files)
#
# Output files:
# text.sym
# $PROGMEM.sym
# $PROGMEM.lss
# $PROGMEM.hex
# $PROGMEM.chr
# $PROGMEM.var
# $PROGMEM.txt
#
# Program memory used
PROGMEM=progmem$1
if [ -z "$1" ]; then PROGMEM=progmem1; fi
#
# Output folder and elf file:
OUTDIR="../../output"
OUTELF="$OUTDIR/Firmware.ino.elf"
#
# AVR gcc tools used:
OBJDUMP=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-objdump.exe
#
#
# Description of process:
# 0. check input files
# 1. remove output files
# 2. list symbol table of section '.text' from output elf file to text.sym (sorted by address)
# 3. list symbol table of section '.$PROGMEM' from all output object files to $PROGMEM.sym
# 4. filter only $PROGMEM symbols from text.sym and store it back to $PROGMEM.sym with absolute address
# 5. calculate start and stop address of section '.$PROGMEM'
# 6. extract string data from elf file to $PROGMEM.hex
# 7. prepare string data for character check and conversion (output to $PROGMEM.chr)
# 8. perform character check and conversion (output to $PROGMEM.var and $PROGMEM.txt)
#
echo "progmem.sh started" >&2
# (0)
echo " progmem.sh (0) - checking input files" >&2
if [ ! -e $OUTDIR ]; then echo "progmem.sh - file '$OUTELF' not found!" >&2; exit 1; fi
# (1)
echo " progmem.sh (1) - removing output files" >&2
#remove output files if exists
if [ -e text.sym ]; then rm text.sym; fi
if [ -e $PROGMEM.sym ]; then rm $PROGMEM.sym; fi
if [ -e $PROGMEM.lss ]; then rm $PROGMEM.lss; fi
if [ -e $PROGMEM.hex ]; then rm $PROGMEM.hex; fi
if [ -e $PROGMEM.chr ]; then rm $PROGMEM.chr; fi
if [ -e $PROGMEM.var ]; then rm $PROGMEM.var; fi
if [ -e $PROGMEM.txt ]; then rm $PROGMEM.txt; fi
# (2)
echo " progmem.sh (2) - listing symbol table of section '.text'" >&2
#list symbols from section '.text' into file text.sym (only address, size and name)
$OBJDUMP -t -j ".text" $OUTELF | tail -n +5 | grep -E "^[0-9a-f]{8} [gl] O" | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> text.sym
# (3)
echo " progmem.sh (3) - listing symbol table of section '.$PROGMEM'" >&2
#loop over all object files
ls "$OUTDIR"/sketch/*.o | while read fn; do
echo " processing $fn" >&2
#list symbols from section $PROGMEM (only address, size and name)
$OBJDUMP -t -j ".$PROGMEM" $fn 2>/dev/null | tail -n +5 | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> $PROGMEM.sym
done
# (4)
echo " progmem.sh (4) - filtering $PROGMEM symbols" >&2
#create list of $PROGMEM symbol names separated by '\|'
progmem=$(cut -c19- $PROGMEM.sym)
progmem=$(echo $progmem | sed "s/ /\\\b\\\|\\\b/g")
progmem='\b'$progmem'\b'
#filter $PROGMEM symbols from section '.text' (result file will contain list sorted by absolute address)
cat text.sym | grep $progmem > $PROGMEM.sym
# (5)
echo " progmem.sh (5) - calculating start and stop address" >&2
#calculate start addres of section ".$PROGMEM"
PROGMEM_BEG=$(head -n1 $PROGMEM.sym | while read offs size name; do echo "0x"$offs; done)
#calculate stop addres of section ".$PROGMEM"
PROGMEM_END=$(tail -n1 $PROGMEM.sym | while read offs size name; do printf "0x%x" $(("0x"$offs + "0x"$size)); done)
echo " START address = "$PROGMEM_BEG >&2
echo " STOP address = "$PROGMEM_END >&2
# (6)
echo " progmem.sh (6) - extracting string data from elf" >&2
#dump $PROGMEM data in hex format, cut textual data (keep hex data only)
$OBJDUMP -d -j ".text" -w -z --start-address=$PROGMEM_BEG --stop-address=$PROGMEM_END $OUTELF | cut -c1-57 > $PROGMEM.lss
#convert $PROGMEM.lss to $PROGMEM.hex:
# replace empty lines with '|' (variables separated by empty lines)
# remove address from multiline variables (keep address at first variable line only)
# remove '<' and '>:', remove whitespace at end of lines
# remove line-endings, replace separator with '\n' (join hex data lines - each line will contain single variable)
# filter progmem symbols
cat $PROGMEM.lss | tail -n +7 | sed -E 's/^$/|/;s/^........:\t/ /;s/<//g;s/>:/ /g;s/[ \t]*$//' |\
tr -d '\n' | sed "s/[|]/\n/g" | grep $progmem > $PROGMEM.hex
# (7)
echo " progmem.sh (7) - preparing string data" >&2
#convert $PROGMEM.hex to $PROGMEM.chr (prepare string data for character check and conversion)
# replace first space with tab
# replace second space with tab and space
# replace all remaining spaces with '\x'
# replace all tabs with spaces
cat $PROGMEM.hex | sed 's/ /\t/;s/ /\t /;s/ /\\x/g;s/\t/ /g' > $PROGMEM.chr
# (8)
#convert $PROGMEM.chr to $PROGMEM.var (convert data to text)
echo " progmem.sh (8) - converting string data" >&2
cat $PROGMEM.chr | \
sed 's/ \\xff\\xff/ /;' | \
sed 's/\\x22/\\\\\\x22/g;' | \
sed 's/\\x1b/\\\\\\x1b/g;' | \
sed 's/\\x01/\\\\\\x01/g;' | \
sed 's/\\xf8/\\\\\\xf8/g;' | \
sed 's/\\x00$/\\x0a/;s/^/printf "/;s/$/"/' | sh > $PROGMEM.var
cat $PROGMEM.var | sed 's/\r/\n/g' |sed -E 's/^[0-9a-f]{8} [^ ]* //' >$PROGMEM.txt
echo "progmem.sh finished" >&2
#!/bin/sh
#
# progmem.sh - multi-language support script
# Examine content of progmem sections (default is progmem1).
#
# Input files:
# $OUTDIR/Firmware.ino.elf
# $OUTDIR/sketch/*.o (all object files)
#
# Output files:
# text.sym - formated symbol listing of section '.text'
# $PROGMEM.sym - formated symbol listing of section '.progmemX'
# $PROGMEM.lss - disassembly listing file
# $PROGMEM.hex - variables - hex
# $PROGMEM.chr - variables - char escape
# $PROGMEM.var - variables - strings
# $PROGMEM.txt - text data only (not used)
#
#
# Config:
if [ -z "$CONFIG_OK" ]; then eval "$(cat config.sh)"; fi
if [ -z "$OUTDIR" ]; then echo 'variable OUTDIR not set!' >&2; exit 1; fi
if [ -z "$OBJDIR" ]; then echo 'variable OBJDIR not set!' >&2; exit 1; fi
if [ -z "$INOELF" ]; then echo 'variable INOELF not set!' >&2; exit 1; fi
if [ -z "$OBJDUMP" ]; then echo 'variable OBJDUMP not set!' >&2; exit 1; fi
if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi
#
# Program memory used
PROGMEM=progmem$1
if [ -z "$1" ]; then PROGMEM=progmem1; fi
#
# Description of process:
# 0. check input files
# 1. remove output files
# 2. list symbol table of section '.text' from output elf file to text.sym (sorted by address)
# 3. list symbol table of section '.$PROGMEM' from all output object files to $PROGMEM.sym
# 4. filter only $PROGMEM symbols from text.sym and store it back to $PROGMEM.sym with absolute address
# 5. calculate start and stop address of section '.$PROGMEM'
# 6. extract string data from elf file to $PROGMEM.hex
# 7. prepare string data for character check and conversion (output to $PROGMEM.chr)
# 8. perform character check and conversion (output to $PROGMEM.var and $PROGMEM.txt)
#
echo "progmem.sh started" >&2
# (0)
echo " progmem.sh (0) - checking input files" >&2
if [ ! -e $OUTDIR ]; then echo "progmem.sh - file '$INOELF' not found!" >&2; exit 1; fi
# (1)
echo " progmem.sh (1) - removing output files" >&2
#remove output files if exists
if [ -e text.sym ]; then rm text.sym; fi
if [ -e $PROGMEM.sym ]; then rm $PROGMEM.sym; fi
if [ -e $PROGMEM.lss ]; then rm $PROGMEM.lss; fi
if [ -e $PROGMEM.hex ]; then rm $PROGMEM.hex; fi
if [ -e $PROGMEM.chr ]; then rm $PROGMEM.chr; fi
if [ -e $PROGMEM.var ]; then rm $PROGMEM.var; fi
if [ -e $PROGMEM.txt ]; then rm $PROGMEM.txt; fi
# (2)
echo " progmem.sh (2) - listing symbol table of section '.text'" >&2
#list symbols from section '.text' into file text.sym (only address, size and name)
$OBJDUMP -t -j ".text" $INOELF | tail -n +5 | grep -E "^[0-9a-f]{8} [gl] O" | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> text.sym
# (3)
echo " progmem.sh (3) - listing symbol table of section '.$PROGMEM'" >&2
#loop over all object files
ls "$OBJDIR"/*.o | while read fn; do
echo " processing $fn" >&2
#list symbols from section $PROGMEM (only address, size and name)
$OBJDUMP -t -j ".$PROGMEM" $fn 2>/dev/null | tail -n +5 | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> $PROGMEM.sym
done
# (4)
echo " progmem.sh (4) - filtering $PROGMEM symbols" >&2
#create list of $PROGMEM symbol names separated by '\|'
progmem=$(cut -c19- $PROGMEM.sym)
progmem=$(echo $progmem | sed "s/ /\\\b\\\|\\\b/g")
progmem='\b'$progmem'\b'
#filter $PROGMEM symbols from section '.text' (result file will contain list sorted by absolute address)
cat text.sym | grep $progmem > $PROGMEM.sym
# (5)
echo " progmem.sh (5) - calculating start and stop address" >&2
#calculate start addres of section ".$PROGMEM"
PROGMEM_BEG=$(head -n1 $PROGMEM.sym | while read offs size name; do echo "0x"$offs; done)
#calculate stop addres of section ".$PROGMEM"
PROGMEM_END=$(tail -n1 $PROGMEM.sym | while read offs size name; do printf "0x%x" $((0x$offs + 0x$size)); done)
echo " START address = "$PROGMEM_BEG >&2
echo " STOP address = "$PROGMEM_END >&2
# (6)
echo " progmem.sh (6) - extracting string data from elf" >&2
#dump $PROGMEM data in hex format, cut textual data (keep hex data only)
$OBJDUMP -d -j ".text" -w -z --start-address=$PROGMEM_BEG --stop-address=$PROGMEM_END $INOELF | cut -c1-57 > $PROGMEM.lss
#convert $PROGMEM.lss to $PROGMEM.hex:
# replace empty lines with '|' (variables separated by empty lines)
# remove address from multiline variables (keep address at first variable line only)
# remove '<' and '>:', remove whitespace at end of lines
# remove line-endings, replace separator with '\n' (join hex data lines - each line will contain single variable)
# filter progmem symbols
cat $PROGMEM.lss | tail -n +7 | sed -E 's/^$/|/;s/^........:\t/ /;s/<//g;s/>:/ /g;s/[ \t]*$//' |\
tr -d '\n' | sed "s/[|]/\n/g" | grep $progmem > $PROGMEM.hex
# (7)
echo " progmem.sh (7) - preparing string data" >&2
#convert $PROGMEM.hex to $PROGMEM.chr (prepare string data for character check and conversion)
# replace first space with tab
# replace second space with tab and space
# replace all remaining spaces with '\x'
# replace all tabs with spaces
cat $PROGMEM.hex | sed 's/ /\t/;s/ /\t /;s/ /\\x/g;s/\t/ /g' > $PROGMEM.chr
# (8)
#convert $PROGMEM.chr to $PROGMEM.var (convert data to text, TODO: rewrite as awk script)
echo " progmem.sh (8) - converting string data" >&2
cat $PROGMEM.chr | \
sed 's/ \\xff\\xff/ /;' | \
sed 's/\\x22/\\\\\\x22/g;' | \
sed 's/\\x1b/\\\\\\x1b/g;' | \
sed 's/\\x01/\\\\\\x01/g;' | \
sed 's/\\xf8/\\\\\\xf8/g;' | \
sed 's/\\x00$//;s/^/\/bin\/echo -e "/;s/$/"/' | sh > $PROGMEM.var
#this step can be omitted because .txt file is not used
#cat $PROGMEM.var | sed 's/\r/\n/g' | sed -E 's/^[0-9a-f]{8} [^ ]* //' >$PROGMEM.txt
echo "progmem.sh finished" >&2
exit 0

View file

@ -1,68 +1,68 @@
#!/bin/sh
# textaddr.sh - multi-language support low level script
# for compiling progmem1.var and lang_en.txt files
# to textaddr.txt file (mapping of progmem addreses to text idenifiers)
#
# Input files:
# progmem1.var
# lang_en.txt
#
# Output files:
# textaddr.txt
#
#
# Dscription of process:
# check if input files exists
# create sorted list of strings from progmem1.var and lang_en.txt
# lines from progmem1.var will contain addres (8 chars) and english text
# lines from lang_en.txt will contain linenumber and english text
# after sort this will generate pairs of lines (line from progmem1 first)
# result of sort is compiled with simple script and stored into file textaddr.txt
#
echo "textaddr.sh started" >&2
if [ ! -e progmem1.var ]; then echo 'textaddr.sh - file progmem1.var not found!' >&2; exit 1; fi
if [ ! -e lang_en.txt ]; then echo 'textaddr.sh - file lang_en.txt not found!' >&2; exit 1; fi
addr=''
text=''
(cat progmem1.var | sed -E "s/^([^ ]*) ([^ ]*) (.*)/\1 \"\3\"/";\
cat lang_en.txt | sed "/^$/d;/^#/d" | sed = | sed '{N;s/\n/ /}') |\
sort -k2 |\
sed "s/\\\/\\\\\\\/g" | while read num txt; do
if [ ${#num} -eq 8 ]; then
if [ -z "$addr" ]; then
addr=$num
else
if [ "$text" == "$txt" ]; then
addr="$addr $num"
else
echo "ADDR NF $addr $text"
addr=$num
fi
fi
text=$txt
else
if [ -z "$addr" ]; then
echo "TEXT NF $num $txt"
else
if [ "$text" == "$txt" ]; then
if [ ${#addr} -eq 8 ]; then
echo "ADDR OK $addr $num"
else
echo "$addr" | sed "s/ /\n/g" | while read ad; do
echo "ADDR OK $ad $num"
done
fi
addr=''
text=''
else
echo "TEXT NF $num $txt"
fi
fi
fi
done > textaddr.txt
echo "textaddr.sh finished" >&2
#!/bin/sh
#
# textaddr.sh - multi-language support script
# Compile progmem1.var and lang_en.txt files to textaddr.txt file (mapping of progmem addreses to text idenifiers)
#
# Input files:
# progmem1.var
# lang_en.txt
#
# Output files:
# textaddr.txt
#
#
# Dscription of process:
# check if input files exists
# create sorted list of strings from progmem1.var and lang_en.txt
# lines from progmem1.var will contain addres (8 chars) and english text
# lines from lang_en.txt will contain linenumber and english text
# after sort this will generate pairs of lines (line from progmem1 first)
# result of sort is compiled with simple script and stored into file textaddr.txt
#
echo "textaddr.sh started" >&2
if [ ! -e progmem1.var ]; then echo 'textaddr.sh - file progmem1.var not found!' >&2; exit 1; fi
if [ ! -e lang_en.txt ]; then echo 'textaddr.sh - file lang_en.txt not found!' >&2; exit 1; fi
addr=''
text=''
(cat progmem1.var | sed -E "s/^([^ ]*) ([^ ]*) (.*)/\1 \"\3\"/";\
cat lang_en.txt | sed "/^$/d;/^#/d" | sed = | sed '{N;s/\n/ /}') |\
sort -k2 |\
sed "s/\\\/\\\\\\\/g" | while read num txt; do
if [ ${#num} -eq 8 ]; then
if [ -z "$addr" ]; then
addr=$num
else
if [ "$text" = "$txt" ]; then
addr="$addr $num"
else
echo "ADDR NF $addr $text"
addr=$num
fi
fi
text=$txt
else
if [ -z "$addr" ]; then
echo "TEXT NF $num $txt"
else
if [ "$text" = "$txt" ]; then
if [ ${#addr} -eq 8 ]; then
echo "ADDR OK $addr $num"
else
echo "$addr" | sed "s/ /\n/g" | while read ad; do
echo "ADDR OK $ad $num"
done
fi
addr=''
text=''
else
echo "TEXT NF $num $txt"
fi
fi
fi
done > textaddr.txt
echo "textaddr.sh finished" >&2
exit 0

View file

@ -1,68 +1,71 @@
#!/bin/sh
# update_lang.sh - multi-language support low level script
# for updating secondary language in binary file
#
# AVR gcc tools used:
OBJCOPY=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-objcopy.exe
#
# Selected language:
LANG=$1
if [ -z "$LANG" ]; then LANG='cz'; fi
#
function finish
{
echo
if [ "$1" == "0" ]; then
echo "update_lang.sh finished with success" >&2
else
echo "update_lang.sh finished with errors!" >&2
fi
case "$-" in
*i*) echo "press enter key"; read ;;
esac
exit $1
}
echo "update_lang.sh started" >&2
echo "selected language=$LANG" >&2
echo -n " checking files..." >&2
if [ ! -e text.sym ]; then echo "NG! file text.sym not found!" >&2; finish 1; fi
if [ ! -e lang_$LANG.bin ]; then echo "NG! file lang_$LANG.bin not found!" >&2; finish 1; fi
if [ ! -e firmware.bin ]; then echo "NG! file firmware.bin not found!" >&2; finish 1; fi
echo "OK" >&2
echo -n " checking symbols..." >&2
#find symbol _SEC_LANG in section '.text'
sec_lang=$(cat text.sym | grep -E "\b_SEC_LANG\b")
if [ -z "$sec_lang" ]; then echo "NG!\n symbol _SEC_LANG not found!" >&2; finish 1; fi
echo "OK" >&2
echo " calculating vars:" >&2
#get addres and size
sec_lang_addr='0x'$(echo $sec_lang | cut -f1 -d' ')
sec_lang_size='0x'$(echo $sec_lang | cut -f2 -d' ')
echo " sec_lang_addr =$sec_lang_addr" >&2
echo " sec_lang_size =$sec_lang_size" >&2
#calculate lang_table_addr (aligned to 256byte page)
lang_table_addr=$((256*$((($sec_lang_addr + 255) / 256))))
printf " lang_table_addr =0x%04x\n" $lang_table_addr >&2
#calculate lang_table_size
lang_table_size=$((256*$((($sec_lang_size - ($lang_table_addr - $sec_lang_addr))/256))))
printf " lang_table_size =0x%04x (=%d bytes)\n" $lang_table_size $lang_table_size >&2
#get lang_xx.bin file size
lang_file_size=$(wc -c lang_$LANG.bin | cut -f1 -d' ')
printf " lang_file_size =0x%04x (=%d bytes)\n" $lang_file_size $lang_file_size >&2
if [ $lang_file_size -gt $lang_table_size ]; then echo "Lanaguage binary file size too big!"; finish 1; fi
echo "updating 'firmware.bin'..." >&2
dd if=lang_$LANG.bin of=firmware.bin bs=1 seek=$lang_table_addr conv=notrunc 2>/dev/null
#convert bin to hex
echo "converting to hex..." >&2
$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware.hex
finish 0
#!/bin/sh
#
# update_lang.sh - multi-language support script
# Update secondary language in binary file.
#
# Config:
if [ -z "$CONFIG_OK" ]; then eval "$(cat config.sh)"; fi
if [ -z "$OBJCOPY" ]; then echo 'variable OBJCOPY not set!' >&2; exit 1; fi
if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi
#
# Selected language:
LANG=$1
if [ -z "$LANG" ]; then LANG='cz'; fi
#
finish()
{
echo
if [ "$1" = "0" ]; then
echo "update_lang.sh finished with success" >&2
else
echo "update_lang.sh finished with errors!" >&2
fi
case "$-" in
*i*) echo "press enter key" >&2; read ;;
esac
exit $1
}
echo "update_lang.sh started" >&2
echo " selected language=$LANG" >&2
echo -n " checking files..." >&2
if [ ! -e text.sym ]; then echo "NG! file text.sym not found!" >&2; finish 1; fi
if [ ! -e lang_$LANG.bin ]; then echo "NG! file lang_$LANG.bin not found!" >&2; finish 1; fi
if [ ! -e firmware.bin ]; then echo "NG! file firmware.bin not found!" >&2; finish 1; fi
echo "OK" >&2
echo -n " checking symbols..." >&2
#find symbol _SEC_LANG in section '.text'
sec_lang=$(cat text.sym | grep -E "\b_SEC_LANG\b")
if [ -z "$sec_lang" ]; then echo "NG!\n symbol _SEC_LANG not found!" >&2; finish 1; fi
echo "OK" >&2
echo " calculating vars:" >&2
#get addres and size
sec_lang_addr='0x'$(echo $sec_lang | cut -f1 -d' ')
sec_lang_size='0x'$(echo $sec_lang | cut -f2 -d' ')
echo " sec_lang_addr =$sec_lang_addr" >&2
echo " sec_lang_size =$sec_lang_size" >&2
#calculate lang_table_addr (aligned to 256byte page)
lang_table_addr=$((256*$((($sec_lang_addr + 255) / 256))))
printf " lang_table_addr =0x%04x\n" $lang_table_addr >&2
#calculate lang_table_size
lang_table_size=$((256*$((($sec_lang_size - ($lang_table_addr - $sec_lang_addr))/256))))
printf " lang_table_size =0x%04x (=%d bytes)\n" $lang_table_size $lang_table_size >&2
#get lang_xx.bin file size
lang_file_size=$(wc -c lang_$LANG.bin | cut -f1 -d' ')
printf " lang_file_size =0x%04x (=%d bytes)\n" $lang_file_size $lang_file_size >&2
if [ $lang_file_size -gt $lang_table_size ]; then echo "Lanaguage binary file size too big!" >&2; finish 1; fi
echo "updating 'firmware.bin'..." >&2
dd if=lang_$LANG.bin of=firmware.bin bs=1 seek=$lang_table_addr conv=notrunc 2>/dev/null
#convert bin to hex
echo "converting to hex..." >&2
$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware_$LANG.hex
finish 0