SSブログ

日本語であそぼう [Arduino]

シリアルモニターで漢字を入力すると、シフトJISでArduinoにコードが送られます。
そこで日本語を処理するためには、シフトJISを恵梨沙フォント上での位置、つまりJISコード順で未使用領域を除いたものに変換しなければなりません。
また、半角文字は恵梨沙フォントに収載されていないので、別にフォントを用意する必要がありますが、用意できなかったので半角英数記号を全角に変換することで対応しました。(半角カナは使用しないことにしました。)

#include <Wire.h> //I2C library

byte buf[8];

void setup() 
{
  Wire.begin(); // initialise the connection
  Serial.begin(9600);
  delay(10); //add a small delay
}

void loop() 
{
  unsigned int sjisH, sjisL;
  signed int elisa;
  while( !Serial.available() );   // なにか文字がくるまで待機
  sjisH = Serial.read();          // 1byte 読み込む
  elisa = asciiToElisa ( sjisH );  // ASCII文字 → ELISAでの位置
  if( elisa == -1 ) {              // シフトJIS上位1バイトなら漢字を表示
    while( !Serial.available() );   // 下位1バイトが届くのを待つ
    sjisL = Serial.read();
    elisa = sjisToElisa( (sjisH << 8) + sjisL );
    if( elisa == -1 ) return;        // 対応文字コードがなければ終了
  } else if( elisa < -1 ) return;    // 制御コード、半角カナなどなら終了
  i2c_eeprom_read_buffer( 0x50, elisa * 8, buf, 8 );
  for(int i=0; i<8; i++) {
    for(int j=7; j>=0; j--) {
      Serial.print( bitRead(buf[i], j) ? "**":"  " );
    }
    Serial.println("");
  }
  Serial.println("");             // 1文字毎に1行あける
}

  // maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  int c = 0;
  for ( c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}

signed int sjisToElisa(unsigned int sjiscode) {    // シフトJISからELISAフォント上の位置に
  byte jisH, jisL;
  int sp, jiscode;
    // まず、シフトJISをJISに変換
  jisH = sjiscode / 256;    // 上位バイト
  jisL = sjiscode % 256;    // 下位バイト
  jisH = (jisH - ((jisH <= 0x9F) ? 0x71:0xB1)) * 2 + 1;
  if( jisL > 0x7F ) jisL--;
  if( jisL >= 0x9E ) jisH++;
  jisL -= ((jisL >= 0x9E) ? 0x7D:0x1F);
  jiscode = (jisH << 8) + jisL;
    // JISから ELISAフォントでの文字位置を計算
  if     (jiscode>=0x2121 && jiscode<=0x222e) sp =   0;  // 一般記号
  else if(jiscode>=0x223a && jiscode<=0x2241) sp =  11;  // 集合記号
  else if(jiscode>=0x224a && jiscode<=0x2250) sp =  19;  // 論理記号
  else if(jiscode>=0x225c && jiscode<=0x226a) sp =  30;  // 幾何記号
  else if(jiscode>=0x2272 && jiscode<=0x2279) sp =  37;  // 音楽記号
  else if(jiscode==0x227e)                    sp =  41;  // 丸記号
  else if(jiscode>=0x2330 && jiscode<=0x2339) sp =  56;  // 数字
  else if(jiscode>=0x2341 && jiscode<=0x235a) sp =  63;  // 英大文字
  else if(jiscode>=0x2361 && jiscode<=0x237a) sp =  69;  // 英小文字 
  else if(jiscode>=0x2421 && jiscode<=0x2473) sp =  73;  // ひらがな
  else if(jiscode>=0x2521 && jiscode<=0x2576) sp =  84;  // カタカナ
  else if(jiscode>=0x2621 && jiscode<=0x2638) sp =  92;  // ギリシャ大文字
  else if(jiscode>=0x2641 && jiscode<=0x2658) sp = 100;  // ギリシャ小文字
  else if(jiscode>=0x2721 && jiscode<=0x2741) sp = 138;  // キリル大文字
  else if(jiscode>=0x2751 && jiscode<=0x2771) sp = 153;  // キリル小文字
  else if(jiscode>=0x2821 && jiscode<=0x2840) sp = 166;  // 罫線
  else if(jiscode>=0x3021 && jiscode<=0x4f53) sp = 886;  // 第一水準漢字
  else if(jiscode>=0x5021 && jiscode<=0x7426) sp = 929;  // 第二水準漢字
  else return -1;              // 対応文字コードがなければ -1
  return (jiscode / 256 - 0x21) * 94 + (jiscode % 256) - 0x21 - sp;
}

signed int asciiToElisa(unsigned int code) {  // 半角を全角ELISAに変換 (半角カナはごめんなさい)
  static byte ElisaMark[] = {  0,  9, 40, 83, 79, 82, 84, 38, 41, 42, 85, 59,
                               3, 60,  4, 30,  6,  7, 66, 64, 67,  8, 86, 45,
                              78, 46, 15, 17, 13, 47, 34, 48, 16};
  if((code>=0x81 && code<=0x9f) || (code>=0xe0 && code<=0xef))
                  return -1;                    // ★ シフトJIS上位1バイトは -1 ★
  if(code  <  32) return -2;                    // 制御文字
  if(code <=  47) return ElisaMark[code-32];    // 記号 SP ! " # $ % & ' ( ) * + , - . /
  if(code <=  57) return code + 99;             // 数字
  if(code <=  64) return ElisaMark[code-42];    // 記号 : ; < = > ?
  if(code <=  90) return code + 92;             // 英大文字
  if(code <=  96) return ElisaMark[code-68];    // 記号 [ \ ] ^ _
  if(code <= 122) return code + 86;             // 英小文字
  if(code <= 126) return ElisaMark[code-94];    // 記号 { | } ~
  if(code == 127) return -2;                    // 制御文字 DEL
  if(code >= 0xa1 && code <= 0x9f) return -4;   // 半角カタカナで
  return -3;                                    // 未使用またはシフトJIS下位1バイト
}

このスケッチをアップロードして、シリアルモニター(9600 baud)に「こんにちは世界」と入力すると
konnichiha.png
こんな感じで表示されます。
LED POV (Persistence of Vision) や、マトリックスLEDで使えそうになってきました。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。