== 日本語フォントROM GT20L16J1Y の使い方 == [https://www.switch-science.com/catalog/1610/ 日本語フォントROM GT20L16J1Y Breakout]でも販売している日本語フォントROM「[http://www.genitop.com/Products/indexlist_GT20L16J1Y.html GT20L16J1Y]」の詳細説明と、サンプルプログラムです。[[BR]] [http://www.genitop.com/admin/upload/20150511144125736.pdf データシートもあります]が、中国語でわかりにくいのと内容に若干不足があるので補足説明をします。 [http://pdf.dzsc.com/99999/2011418133835134.pdf こちらのpdf]は出所が不明ですが、上記のデータシートより一部詳しい情報が乗っています。[[BR]] 検索によって出てくるデータシートごとに記載内容が若干異なりますが、[[BR]] 本ページに記載されているROMの内容は実際の商品を用いて調べたものです。[[BR]] ---- == 収録内容 == === 1.全角文字 === 1文字あたり32byteの容量を持ちます。[[BR]] JIS X 0208の第一水準及び第二水準の漢字に対応しています。[[BR]] JIS X 0208に含まれない、いわゆる機種依存文字(全角1文字の「メートル」やローマ数字などの表外字)も収録されていますが、[[BR]] 独自のアドレスに配置されているようでJISコードと同じ変換プログラムではうまく任意の文字を読み出せませんでした。 ||番号||アドレス(10進数)||内容||説明|| ||0||0||(空白)||JISX 1区1点|| ||1||32||、||JISX 1区2点|| ||・||・||・||・|| ||1361||43552||ヲ||JISX 15区46点|| ||1261||43584||亜||JISX 16区1点|| ||・||・||・||・|| ||7716||246912||熙||JISX 84区6点|| ||7717||246944||(空白)||1区と同等の内容|| ||・||・||・||||| ||7810||249920||◇||↓|| ||7811||249952||あ||4区と同等の内容|| ||・||・||・||↓|| ||7905||252960||ア||5区と同等の内容|| ||・||・||。||↓|| ||7998||255936||(空白)||↓|| ==== アドレスの計算式 ==== メーカーPDFより抜粋です。一部記載ミスと思われる点を変更しています。(138463->138464)[[BR]] JIS X 0208の区をMSB、点をLSBとしたときのアドレスを求めています。[[BR]] アドレスは最大18bitになるので、変数の宣言は32bitで行うほうが安全です。(Arduinoのintは16bit)[[BR]] {{{ if(MSB >=1 && MSB <= 15 && LSB >=1 && LSB <= 94) Address =( (MSB - 1) * 94 + (LSB - 01))*32; else if(MSB >=16 && MSB <= 47 && LSB >=1 && LSB <= 94) Address =( (MSB - 16) * 94 + (LSB - 1))*32+43584; else if(MSB >=48 && MSB <=84 && LSB >=1 && LSB <= 94) Address = ((MSB - 48) * 94 + (LSB - 1))*32+ 138464; else if(MSB ==85 && LSB >=0x01 && LSB <= 94) Address = ((MSB - 85) * 94 + (LSB - 1))*32+ 246944; else if(MSB >=88 && MSB <=89 && LSB >=1 && LSB <= 94) Address = ((MSB - 88) * 94 + (LSB - 1))*32+ 249952; }}} === 2.半角文字 === 一文字あたり16byteの容量を持ちます。[[BR]] 独自の配列(?)で半角ひらがなと半角カタカナに対応しています。[[BR]] メモリアドレスのオフセットは10進数で255968です。下記の表にはアドレスを通しで載せてあります。[[BR]] ||番号||アドレス(10進数)||内容||説明|| ||0||255968||(空白)||ASCIIコード準拠|| ||・||・||・||||| ||95||257488||(空白)||↓|| |||||||||| ||0||257504||0||下記の表1を参照してください|| ||・||・||・||↓|| ||128||259536||0||下記の表2を参照してください|| ||・||・||・||||| ||261||261680||)||↓|| ==== アドレスの計算式 ==== メーカーpdfより抜粋です。ASCIIコードを与えるとアドレスを返します。[[BR]] {{{ if(ASCIICODE >=0x20 && ASCIICODE <=0x7F) Address =( ASCIICODE - 0x20)*16+255968; }}} ==== 表1 ==== 左上から順番に記録されています。「空」となっているところは空です。[[BR]] 全部半角サイズです。全128文字。 ||0||1||2||3||4||5||6||7||8||9||、||。||:||;||(||)|| ||ゃ||ゅ||ょ||ャ||ュ||ョ||ァ||ィ||ゥ||ェ||ォ||「||」||*||#||/|| ||空||あ||い||う||え||お||か||き||く||け||こ||さ||し||す||せ||そ|| ||っ||た||ち||つ||て||と||な||に||ぬ||ね||の||は||ひ||ふ||へ||ほ|| ||ま||み||む||め||も||や||ゆ||よ||ら||り||る||れ||ろ||わ||を||ん|| ||ー||ア||イ||ウ||エ||オ||カ||キ||ク||ケ||コ||サ||シ||ス||セ||ソ|| ||ッ||タ||チ||ツ||テ||ト||ナ||ニ||ヌ||ネ||ノ||ハ||ヒ||フ||ヘ||ホ|| ||マ||ミ||ム||メ||モ||ヤ||ユ||ヨ||ラ||リ||ル||レ||ロ||ワ||ヲ||ン|| ==== 表2 ==== 左上から順番に記録されています。「空」となっているところは空です。[[BR]] 全部半角サイズです。全134文字。[[BR]] こちらに記録されているアルファベットはサンセリフです。(ASCII互換の部分はセリフ体)[[BR]] ||0||1||2||3||4||5||6||7||8||9||^||_||:||;||,||.|| ||ー||ア||イ||ウ||エ||オ||カ||キ||ク||ケ||コ||サ||シ||ス||セ||ソ|| ||空||タ||チ||ツ||テ||ト||ナ||ニ||ヌ||ネ||ノ||ハ||ヒ||フ||ヘ||ホ|| ||マ||ミ||ム||メ||モ||ヤ||ユ||ヨ||ラ||リ||ル||レ||ロ||ワ||ヲ||ン|| ||*||A||B||C||D||E||F||G||H||I||J||K||L||M||N||O|| ||P||Q||R||S||T||U||V||W||X||Y||Z||ッ||ャ||ュ||ョ||■|| ||#||a||b||c||d||e||f||g||h||i||j||k||l||m||n||o|| ||p||q||r||s||t||u||v||w||x||y||z||゛||゜||@||! ||?|| ||゛||゜||&||/||(||)|| ---- == 接続方法 == 本製品は3.3V動作なので、下の配線図では1.8KΩと3.3KΩで分圧して入力につないでいます。 [[Image(kanji_board.png,500px)]] ---- == 通信方法 == 本製品におけるSPI通信では、MODE0またはMODE3に対応しています。[[BR]] 動作速度は最大30MHzです。[[BR]] 1.SPI通信で0x03を書き込みます。[[BR]]これによりROMがデータ読み出しモードになります。[[BR]] 2.SPI通信でデータを読みたいアドレスを8bit*3回で送ります。最下位ビット詰めです。[[BR]] 3.送ったデータにしたがってダミーデータ0x00を16回又は32回送ります。この時に受信されるデータがROMの内容です。[[BR]]最初に書き込んだ0x03のモードでの説明です。0x0Bを書き込んだ際の「高速読み出しモード」ではこの通りではありません。 == 受信内容 == 半角または全角によって受信するデータのサイズが違います。半角は16Byte、全角は32Byteです。[[BR]] どちらも少し変わった配列になっていますので、表示先によって一工夫必要になります。[[BR]] === 全角文字 === 左上から縦に8ドット(=1Byte分)ずつ送られてきます。[[BR]] 今回のサンプルプログラムでは、「送られてきた1~16Byte目のLSBから順に表示→17~32Byte目のLSBから順に表示」としています。[[BR]] [[Image(16x16.png,180px)]] [[BR]] === 半角文字 === 左上から縦に8ドット(=1Byte分)ずつ送られてきます。[[BR]] 今回のサンプルプログラムでは、「送られてきた1~8Byte目のLSBから順に表示→9~16Byte目のLSBから順に表示」としています。[[BR]] [[Image(16x8.png,180px)]] [[BR]] ---- == サンプルプログラム == Arduino IDE のシリアルモニタから送った日本語を、 ROMから読みだしてシリアルモニタに返すプログラムです。 半角カナには対応していません。 ~~[attachment:GT20L16J1Y_sample.zip]~~ 下記の全角小文字oフォントの改善を行ったスケッチを[https://github.com/SWITCHSCIENCE/samplecodes/tree/master/GT20L16J1Y_breakout/Arduino/GT20L16J1Y_sample GitHubで公開しています]。 {{{ /* GT20L16J1Y用サンプルプログラム * Arduinoのシリアルモニタから送信されたSJISの文字を * ROMから読みだしてシリアルモニタに返す * 半角カナまわりはデータにはあるがROM内の順とJISX規格での順が * 一致しないため未実装 * * memo:9/30 00:00 * memo:10/7 18:30 */ #include unsigned char matrixdata32[32]; //16×16用表示データ unsigned char matrixdata16[16]; //16×8用表示データ void setup (void) { pinMode (SS, OUTPUT); Serial.begin(115200); /*SPI通信の設定*/ SPI.begin (); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(3); SPI.setClockDivider(SPI_CLOCK_DIV16); Serial.println("input word which you want to show"); } void loop (void) { if (Serial.available() > 0) { /*Arduinoのシリアルモニタから送られてくる日本語がSJISであることに注意*/ delayMicroseconds(200);//最低でも2文字受信したい uint8_t msbdata = Serial.read();//1バイト目 //10/07 /*SJISの1バイトコードか否か*/ if ( (msbdata < 0x80) || ((0xA0 < msbdata) && (msbdata <= 0xdF)) ) { showSJIS1byte(msbdata); } else { uint8_t lsbdata = Serial.read();//2バイト目 //10/07 uint16_t data = ((msbdata << 8) + lsbdata); //2 showSJIS2byte(data); } } } /*1byteのSJISを表示する*/ void showSJIS1byte(uint8_t code) { readFontASCII(code); sendDotsToSerial16(); } /*2byteのSJISを表示する*/ //showSJIS2byte(SJIS文字コード) void showSJIS2byte(unsigned short code) { /*Arduinoのシリアルで日本語はSJIS送信なのでSJIS->JISx0208変換をする*/ Serial.print("SJIS, 0x"); Serial.print(code, HEX); Serial.print("\t"); uint8_t c1 = ((code & 0xff00) >> 8); uint8_t c2 = (code & 0xFF); if (c1 >= 0xe0) { c1 = c1 - 0x40; } if (c2 >= 0x80) { c2 = c2 - 1; } if (c2 >= 0x9e) { c1 = (c1 - 0x70) * 2; c2 = c2 - 0x7d; } else { c1 = ((c1 - 0x70) * 2) - 1; c2 = c2 - 0x1f; } /*読み出し*/ readFontJIS(c1, c2); /*表示*/ sendDotsToSerial32(); } /*漢字ROMとやりとり*/ //readFontJIS(JIS上位8bit,JIS下位8bit); void readFontJIS(uint8_t c1, uint8_t c2) { /*jisx変換後の表示*/ Serial.print("jisx up8 = 0x"); Serial.print(c1, HEX); Serial.print("\t"); Serial.print("jisx down8 = 0x"); Serial.print(c2, HEX); Serial.print("\t"); /*jisxの区点を求める*/ uint32_t MSB = c1 - 0x20;//区 uint32_t LSB = c2 - 0x20;//点 /*JISの句点番号で分類*/ uint32_t Address = 0; Serial.print("MSB = d"); Serial.print(MSB, DEC); Serial.print("\t"); Serial.print("LSB = d"); Serial.print(LSB, DEC); Serial.print("\t"); /*各種記号・英数字・かな(一部機種依存につき注意,㍍などWindowsと互換性なし)*/ if (MSB >= 1 && MSB <= 15 && LSB >= 1 && LSB <= 94) { Address = ( (MSB - 1) * 94 + (LSB - 1)) * 32; } /*第一水準*/ if (MSB >= 16 && MSB <= 47 && LSB >= 1 && LSB <= 94) { Address = ( (MSB - 16) * 94 + (LSB - 1)) * 32 + 43584; } /*第二水準*/ if (MSB >= 48 && MSB <= 84 && LSB >= 1 && LSB <= 94) { Address = ((MSB - 48) * 94 + (LSB - 1)) * 32 + 138464; } // /*GT20L16J1Y内部では1区と同等の内容が収録されている*/ if (MSB == 85 && LSB >= 0x01 && LSB <= 94) { Address = ((MSB - 85) * 94 + (LSB - 1)) * 32 + 246944; } /*GT20L16J1Y内部では2区、3区と同等の内容が収録されている*/ if (MSB >= 88 && MSB <= 89 && LSB >= 1 && LSB <= 94) { Address = ((MSB - 88) * 94 + (LSB - 1)) * 32 + 249952; } /*漢字ROMにデータを送信*/ digitalWrite(SS, HIGH); Serial.print("Address = "); Serial.println(Address, HEX); digitalWrite(SS, LOW); //通信開始 SPI.transfer(0x03); SPI.transfer(Address >> 16 & 0xff); SPI.transfer(Address >> 8 & 0xff); SPI.transfer(Address & 0xff); /*漢字ROMからデータを受信*/ for (int i = 0; i < 32; i++) { matrixdata32[i] = SPI.transfer(0x00); } digitalWrite(SS, HIGH); //通信終了 }//spireadfont /*漢字ROMとやりとり*/ //readFontASCII(ASCIIコード); void readFontASCII(uint8_t ASCIICODE) { Serial.print("ASCII,0x");Serial.print(ASCIICODE, HEX); //10/07 uint32_t Address = 0; /*ASCII文字*/ if (ASCIICODE >= 0x20 && ASCIICODE <= 0x7F) { Address = ( ASCIICODE - 0x20) * 16 + 255968; } /*漢字ROMにデータを送信*/ digitalWrite(SS, HIGH); Serial.print(" Address = "); Serial.println(Address, HEX); digitalWrite(SS, LOW); //通信開始 SPI.transfer(0x03); SPI.transfer(Address >> 16 & 0xff); SPI.transfer(Address >> 8 & 0xff); SPI.transfer(Address & 0xff); /*漢字ROMからデータを受信*/ for (int i = 0; i < 16; i++) { matrixdata16[i] = SPI.transfer(0x00); } digitalWrite(SS, HIGH); //通信終了 } /*シリアルモニタへ16*16のデータを表示する*/ void sendDotsToSerial32() { /*上半分*/ for (int i = 0; i < 8; i++) { for (int b = 0; b < 16; b++) { char byteDigit = (1 << i); if (matrixdata32[b] & byteDigit) { Serial.write("XX"); } else { Serial.write("--"); } } Serial.println(); } /*下半分*/ for (int i = 0; i < 8; i++) { for (int b = 16; b < 32 ; b++) { char byteDigit = (1 << i); if (matrixdata32[b] & byteDigit) { Serial.write("XX"); } else { Serial.write("--"); } } Serial.println(); } Serial.println(); }//sendDataToSerial16 /*シリアルモニタへ16*8のデータを表示する*/ void sendDotsToSerial16() { /*上半分*/ for (int i = 0; i < 8; i++) { for (int b = 0; b < 8; b++) { char byteDigit = (1 << i); if (matrixdata16[b] & byteDigit) { Serial.write("XX"); } else { Serial.write("--"); } } Serial.println(); } /*下半分*/ for (int i = 0; i < 8; i++) { for (int b = 8; b < 16; b++) { char byteDigit = (1 << i); if (matrixdata16[b] & byteDigit) { Serial.write("XX"); } else { Serial.write("--"); } } Serial.println(); } Serial.println(); }//sendDataToSerial32 }}} ---- === 動作サンプル === ==== Sample1 ==== 「技術」と入力してEnterを押した時の動作です。[[BR]] [[Image(sample.png,180px)]] ==== Sample2 ==== 「Ss」と入力してEnterを押した時の動作です。[[BR]] [[Image(sample2.png,180px)]] ==== Sample3 ==== ASCII準拠の部分に収録されている「K」と、表2で示されるアドレスの「K」の表示の違いです。[[BR]] [[Image(diff_kk.png,180px)]] === サンプルプログラムの修正(2016/07/25) === 全角小文字の`o`のサイズが、大文字のものと変わらないというROM内部のフォントのデザインミスがあるようです。 以下のコードを追加することで正しいサイズの`o`を描画できます。 プログラム冒頭の方に以下の配列を追加してください。 変更済スケッチは[https://github.com/SWITCHSCIENCE/samplecodes/tree/master/GT20L16J1Y_breakout/Arduino/GT20L16J1Y_sample GitHubで公開しています]。 {{{ const unsigned char matrixdata32_o[32] = { B00000000, B00000000, B00000000, B00000000, B11000000, B00100000, B00010000, B00010000, B00010000, B00100000, B11000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000011, B00000100, B00001000, B00001000, B00001000, B00000100, B00000011, B00000000, B00000000, B00000000, B00000000, B00000000, }; }}} また、`void showSJIS2byte(unsigned short code)`を以下のコードに置き換えてください。 {{{ /*2byteのSJISを表示する*/ //showSJIS2byte(SJIS文字コード) void showSJIS2byte(unsigned short code) { if(code == 0x828F) { for(int i=0;i<32;i++) { matrixdata32[i] = matrixdata32_o[i]; } sendDotsToSerial32(); }else{ /*Arduinoのシリアルで日本語はSJIS送信なのでSJIS->JISx0208変換をする*/ Serial.print("SJIS, 0x"); Serial.print(code, HEX); Serial.print("\t"); uint8_t c1 = ((code & 0xff00) >> 8); uint8_t c2 = (code & 0xFF); if (c1 >= 0xe0) { c1 = c1 - 0x40; } if (c2 >= 0x80) { c2 = c2 - 1; } if (c2 >= 0x9e) { c1 = (c1 - 0x70) * 2; c2 = c2 - 0x7d; } else { c1 = ((c1 - 0x70) * 2) - 1; c2 = c2 - 0x1f; } /*読み出し*/ readFontJIS(c1, c2); /*表示*/ sendDotsToSerial32(); } } }}} === 付録 === mbed - Components[https://developer.mbed.org/components/GT20L16J16Y-Japanese-font-ROM/ https://developer.mbed.org/...]