Big5中文字输出
目的
把想要輸出的字型,寫到一個File裡面,再利用讀檔的方式,透過倚天字碼查表,然後轉換成一連串的101010101,設計成一個testbench使第二組能夠接受
Step1:輸入測資(中文字)
Step2:讀出輸入字的內碼(Big 5)
Step3:以內碼尋找該字在stdfont.15內的位置
Step4:將stdfont.15裡的資料取出成為bitmap
Step5:將bitmap轉成vwf檔(讓Quartus II能夠讀取)
Step6:寫一個testbench(VHDL)讀取bitmap轉出來的vwf檔
以”永”字為例
先在input檔案內輸入”永”,然後用指令” trans_big5 < test.txt > out.vwf ”讓輸入檔案導入C code執行檔中然後將結果導出至vwf檔
然後下圖為取出之bitmap:
以下為導出的out.vwf檔
如何找出Big 5 code?
有4種方法:
1.在code中使用現成轉Big
2.自己從input的中文字找出該字的Big
3.直接在程式中建立一個Big
4.由輸入字的value計算出Big
Code:
in = (word[0] << 8) + ( word[1] & 0xFF );
in = in & 0xFFFF; //word = 輸入(中文字),in = Big
Make Bitmap
stdfont.15中存有大部分Big 5碼中文字的bitmap
Step1:以Big 5碼找出中文字的序列碼
HI = in/256; // HI = 高位碼
LO = in%256; // LO = 低位碼
if(LO >= 161)
SerCode = (HI - 161) * 157 + (LO - 161) + 1 + 63
else
SerCode = (HI - 161) * 157 + (LO - 64) + 1
Step2:以序列碼找出該字在stdfont.15中的檔案位置位移量(Offset)
Step3:該字的bitmap即存在stdfont.15中的第Offset個byte開始的30 bites。
Code:
if(Ser >= 472 && Ser <= 5872)
Offset = (Ser-472)*30; //常用字
else if(Ser >= 6281 && Ser <= 13973)
Offset = (Ser-6281)*30+162030; //非常用字
else
Offset=-1000000; //該字的bitmap沒有出現在stdfont.15中
以”一”為例:
“一”的Big 5碼為0xA440
HI = 0xA4 = 164, LO = 0x40 = 64
LO < 161
SerCode = (HI - 161) * 157 + (LO - 64) + 1 = 472
SerCode >= 472 && SerCode <= 5872
OffSet = (SerCode - 472) * 30 = 0
“一”的bitmap就存在stdfount.15的第0 ~ 29byte中
Transfor Bitmap
將取出來的bitmap改成以1 bit為單位的儲存格式(否則Quartus II無法讀取)
Code:
for(i = 0;i<15;++i){
for(j = 0;j<2;++j){
Wait_to_trans[i][(8*j)+0] = ( bmap[i][j] >> 7 ) & 1 ;
Wait_to_trans[i][(8*j)+1] = ( bmap[i][j] >> 6 ) & 1 ;
Wait_to_trans[i][(8*j)+2] = ( bmap[i][j] >> 5 ) & 1 ;
Wait_to_trans[i][(8*j)+3] = ( bmap[i][j] >> 4 ) & 1 ;
Wait_to_trans[i][(8*j)+4] = ( bmap[i][j] >> 3 ) & 1 ;
Wait_to_trans[i][(8*j)+5] = ( bmap[i][j] >> 2 ) & 1 ;
Wait_to_trans[i][(8*j)+6] = ( bmap[i][j] >> 1 ) & 1 ;
Wait_to_trans[i][(8*j)+7] = bmap[i][j] & 1 ;
}
} // bmap = 原來的bitmap Wait_to_trans = 轉換後的bitmap
Make Testbench
有兩種方法:
1.用VHDL讀出前面轉出來的bitmap
2.使用C code印出VHDL的testbench(the chosen way)
Code:
printf(“……………”);
while((c = fgetc(fptr)) != EOF){
if(c == '0'){
printf(" LEVEL 0 FOR 4000000.0;\n");
i=i+4 ;
k++ ;
}
else if(c == '1'){
printf(" LEVEL 1 FOR 4000000.0;\n");
i=i+4 ;
k++ ;
}
}
printf(“……………”);
輸入/輸出格式:
input : in std_logic ;
inclk : in std_logic ;
inset : in std_logic ;
output : out std_logic_vector( 0 to 14 ) ;
clk_48MHz : in std_logic );
輸入資料格式:
每筆輸入的資料包含:速度(2 bits)、反白(1 bit)、閃爍(1 bit)與8個15*16 dots的陣列,合計1924 bits。
速度的表示方式為:
00最快(1秒跳2次)
01中快(1秒1次)
10中慢(1.5秒1次)
11最慢(2秒1次)
反白bit設成0代表不反白正常, 設成1代表全部反白。
閃爍bit設成0代表不閃爍, 設成1時移動字的時候會有閃爍特效。
啟動/資料輸入方式:
Inset在資料輸入的過程中設定為1,輸入完成後設定為0,並開始平移字幕。
Input即為輸入的資料,每當inclk跳成1的時候接收1個bit的資料。
輸出方式與頻率:
每次送出15個bits(即為一直行的dots)。頻率為每秒送出8個字,即為每秒共送出 16 * 8 * 30 = 3840次資料,每次15 bits。
Difficulty:
為了能夠調整速度就需要設定一個shiftclk。但是若input也設定一個clock,就需要有兩個clocks,則buffer會有multiple drive的問題。
Solution:
讓buffer只聽一個clock的指令,不過這個clock在inset = 0和1時分別為的shiftclk 與inclk訊號:
process ( inset , mixclk , inclk , shiftclk )
begin
if ( inset = '1' ) then
mixclk <= inclk;
else
mixclk <= shiftclk;
end if;
end process;
如此一來buffer只要mixclk的訊號即可。
Difficulty:閃爍
要達成閃爍的效果,必須要將顯示的文字與位置記錄下來,並且和空白畫面交互顯示。因此,必須每次更動顯示的文字,在執行上有相當程度的困難。
Solution:
另設一twinkleclk_count,配合shiftclk來控制twinkleclk:
process
begin
wait until ( shiftclk'event and shiftclk = '1' );
if ( twinkleclk_count < "01" ) then
twinkleclk_count <= twinkleclk_count + 1;
else
twinkleclk_count <= "00";
twinkleclk <= not twinkleclk;
end if;
end process;
並將allzero和outputbuffer交互顯示:
-- empty
if ( twinkleclk = '0' ) then
output <= allzero;
-- show
else
output <= outputbuffer;
end if;
http://www.solutioninside.com/~jackiekan/2007/Project/LED_Board/Home.html