diff --git a/lang/lang_en.txt b/lang/lang_en.txt index 71bcfe77..170eb8ea 100644 --- a/lang/lang_en.txt +++ b/lang/lang_en.txt @@ -638,7 +638,8 @@ "Please clean the nozzle for calibration. Click when done." #MSG_SELFTEST_PLEASECHECK c=0 r=0 -"Please check :" +"Please check :" + #MSG_WIZARD_CALIBRATION_FAILED c=20 r=8 "Please check our handbook and fix the problem. Then resume the Wizard by rebooting the printer." diff --git a/lang/postbuild.sh b/lang/postbuild.sh index 43fe8c8a..0d96315d 100644 --- a/lang/postbuild.sh +++ b/lang/postbuild.sh @@ -1,5 +1,20 @@ #!/bin/sh -# postbuild.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.dat +# $PROGMEM.chr +# $PROGMEM.var +# $PROGMEM.txt +# textaddr.txt # # Output folder and elf file: OUTDIR="../../output" @@ -7,93 +22,85 @@ 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 + function finish { echo - echo "postbuild.sh finished... press enter key" - read - exit + 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..." +echo "postbuild.sh started" >&2 #check input files -echo " checking files:" -if [ ! -e $OUTDIR ]; then echo " folder '$OUTDIR' not found!"; finish; fi -echo " folder OK" -if [ ! -e $OUTELF ]; then echo " elf file '$OUTELF' not found!"; finish; fi -echo " elf OK" -if ! ls $OUTDIR/sketch/*.o >/dev/null 2>&1; then echo " no object files in '$OUTDIR/sketch/'!"; finish; fi -echo " objects OK" +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 to examine content of progmem1 -./progmem.sh 1 +#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 -#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 to file textaddr.txt -echo "compiling progmem1.var and lang_en.txt" -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 +#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 "checking textaddr.txt..." -if cat textaddr.txt | grep "^ADDR NF"; then echo "Some strings not found in lang_en.txt!"; finish; fi +echo -n " checking textaddr.txt..." >&2 +if cat textaddr.txt | grep "^ADDR NF"; then echo "NG! - some strings not found in lang_en.txt!"; finish 1; fi +echo "OK" >&2 #update progmem1 id entries in binary file -echo "extracting binary..." +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 "updating binary..." -#dd if=/dev/zero of=test.bin bs=512 count=64 2>/dev/null -time cat textaddr.txt | grep "^ADDR OK" | cut -f3- -d' ' | sed "s/^0000/0x/" |\ - awk '{ hi = int($2 / 256); lo = int($2 - 256 * hi); printf("%d \\\\x%02x\\\\x%02x\n", strtonum($1), hi, lo); }' |\ +echo -n " primary language ids..." >&2 +cat textaddr.txt | grep "^ADDR OK" | cut -f3- -d' ' | sed "s/^0000/0x/" |\ + awk '{ hi = int($2 / 256); lo = int($2 - 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 progmem1 id entries in binary file -echo "converting to hex..." +#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 +finish 0 diff --git a/lang/progmem.sh b/lang/progmem.sh index ea22e5a7..a9f677a9 100644 --- a/lang/progmem.sh +++ b/lang/progmem.sh @@ -1,19 +1,10 @@ #!/bin/sh -# -# Multi-language support postbuild script -# Description of proces: -# 0. remove output files -# 1. list symbol table of section '.text' from output elf file to text.sym (sorted by address) -# 2. list symbol table of section '.$PROGMEM' from all output object files to $PROGMEM.sym -# 3. filter only $PROGMEM symbols from text.sym and store it back to $PROGMEM.sym with absolute address -# 4. calculate start and stop address of section '.$PROGMEM' -# 5. extract string data from elf file to $PROGMEM.dat -# 6. prepare string data for character check and conversion (output to $PROGMEM.chr) -# 7. perform character check and conversion (output to $PROGMEM.var and $PROGMEM.txt) +# progmem.sh - multi-language support low-level script +# for examining content of progmem sections (default is progmem1) # # Input files: -# Firmware.ino.elf -# *.o (all object files) +# $OUTDIR/Firmware.ino.elf +# $OUTDIR/sketch/*.o (all object files) # # Output files: # text.sym @@ -34,11 +25,28 @@ OUTELF="$OUTDIR/Firmware.ino.elf" # # AVR gcc tools used: OBJDUMP=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-objdump.exe -#READELF=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-readelf.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.dat +# 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 "step 0 - removing output files" +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 @@ -49,21 +57,21 @@ if [ -e $PROGMEM.var ]; then rm $PROGMEM.var; fi if [ -e $PROGMEM.txt ]; then rm $PROGMEM.txt; fi # (1) -echo "step 1 - listing symbol table of section '.text'" +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 # (2) -echo "step 2 - listing symbol table of section '.$PROGMEM'" +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" + echo " processing $fn" >&2 #list symbols from section $PROGMEM (only address, size and name) - $OBJDUMP -t -j ".$PROGMEM" $fn | tail -n +5 | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> $PROGMEM.sym -done 2>/dev/null + $OBJDUMP -t -j ".$PROGMEM" $fn 2>/dev/null | tail -n +5 | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> $PROGMEM.sym +done #exit # (3) -echo "step 3 - filtering $PROGMEM symbols" +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") @@ -72,16 +80,16 @@ progmem='\b'$progmem'\b' cat text.sym | grep $progmem > $PROGMEM.sym # (4) -echo "step 4 - calculating start and stop address" +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 -echo " STOP address = "$PROGMEM_END +echo " START address = "$PROGMEM_BEG >&2 +echo " STOP address = "$PROGMEM_END >&2 # (5) -echo "step 5 - extracting string data from elf" +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.dat: @@ -94,7 +102,7 @@ cat $PROGMEM.lss | tail -n +7 | sed -E 's/^$/|/;s/^........:\t/ /;s/:/ / tr -d '\n' | sed "s/[|]/\n/g" | grep $progmem > $PROGMEM.dat # (6) -echo "step 6 - preparing string data" +echo " progmem.sh (7) - preparing string data" >&2 #convert $PROGMEM.dat to $PROGMEM.chr (prepare string data for character check and conversion) # replace first space with tab # replace second space with tab and space @@ -104,6 +112,7 @@ cat $PROGMEM.dat | sed 's/ /\t/;s/ /\t /;s/ /\\x/g;s/\t/ /g' > $PROGMEM.chr # (7) #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;' | \ @@ -113,4 +122,6 @@ cat $PROGMEM.chr | \ 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 -read +echo "progmem.sh finished" >&2 + +exit 0 \ No newline at end of file diff --git a/lang/textaddr.sh b/lang/textaddr.sh new file mode 100644 index 00000000..46b2123c --- /dev/null +++ b/lang/textaddr.sh @@ -0,0 +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 + +exit 0 \ No newline at end of file diff --git a/lang/update_lang.sh b/lang/update_lang.sh new file mode 100644 index 00000000..3e884bfa --- /dev/null +++ b/lang/update_lang.sh @@ -0,0 +1,68 @@ +#!/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_cz.bin file size +lang_file_size=$(wc -c lang_cz.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_cz.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