2017年7月18日火曜日

Arduino でモールス信号

中華通販で買ったArduino。封も切らずに保管していていざ使おうとした不良品だったなんてことが何回かありまして商品が届くごとにとりあえずLチカだけはしていたわけですが、最初から Blink.ino が入っているものもあるので、見分けるためにちょっと凝った BlinkMorse.ino を作ってみました。

その際にモールス信号を生成するクラスを作成しました。このクラスは KyaMorseBase クラスと KyaMorse というテンプレートから構成されています。

KyaMorseBase は与えられた文字列からモールス信号を作成、ONとすべきタイミングで音にすべき時間を引数として KyaMorseBase::callback() を呼び出します。callback() は virtual となっていますのでこのクラスを基本クラスとしてやることにより LED を点灯するなり ブザーを鳴らすなり自由な処理を行えます。

また、KyaMorse はテンプレートでメンバー変数として KyaMorse<クラス名> とすることによりメンバー関数をコールバックとする事ができます。多重継承がお嫌いな方にはこちらが良いかもしれません。

KyaMorse.h

/**
 * モールス信号処理
 *
 * filename:  KyaMorse.h
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date      2017-07-15
 * @author    木屋 善夫
 */
#ifndef _KyaMorse_h_
#define _KyaMorse_h_
#include

class KyaMorseBase {
public:
  // モールス符号情報
  static const uint16_t morses[59];

  // 短点の時間(msec)
  uint32_t mTime = 100;

  /**
   * 構築
   */
  KyaMorseBase() {
  }

  /**
   * 構築
   * @param  uint32_t time 短点の時間(msec)
   */
  KyaMorseBase(uint32_t time) : mTime(time) {
  }

  /**
   * モールス信号送信処理
   *
   * @access public
   * @param  char* str 送信する文字列
   * @return
   * @throw
   */
  void send(char* str);

  /**
   * コールバック処理
   * ※派生クラス(テンプレート)でオーバーライドするためのメンバー関数
   *
   * @access public
   * @param  uint32_t time 待ち時間(msec)
   */
   virtual void callback(uint32_t time) {}
};

template
class KyaMorse : public KyaMorseBase {
public:
  typedef void (T::*CALLBACK)(uint32_t);

protected:
  T* mObj;
  CALLBACK mMethod;

public:
  /**
   * 構築
   */
  KyaMorse( ) : KyaMorseBase() {
  }

  /**
   * 構築
   * @param  uint32_t time 短点の時間(msec)
   */
  KyaMorse(uint32_t time) : KyaMorseBase(time) {
  }

  /**
   * モールス信号送信処理
   *
   * @access public
   * @param  char* str 送信する文字列
   * @return
   * @throw
   */
  void send(char* str, T* obj, CALLBACK method) {
    mObj = obj;
    mMethod = method;
    KyaMorseBase::send(str);
  }

  /**
   * コールバック処理
   * ※派生クラス(テンプレート)でオーバーライドするためのメンバー関数
   *
   * @access public
   * @param  uint32_t time 待ち時間(msec)
   */
   virtual void callback(uint32_t time) {
    (mObj->*mMethod)(time);
   }
};

#endif

KyaMorse.cpp

/**
 * モールス信号処理
 *
 * filename:  KyaMorse.cpp
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date    2017-07-15
 * @author    木屋 善夫
 */

/**
 * インクルード
 */
#include "KyaMorse.h"

/**
 * モールス信号送信処理
 *
 * @access public
 * @param  char* str 送信する文字列
 * @return
 * @throw
 */
void KyaMorseBase::send(char* str) {
  for (; *str; ++ str) {
    char c = *str;
    if ((c >= ' ') && (c <= 'Z')) {
      uint16_t b = morses[c - 0x20];
      for (; b; b <<= 2) {
        switch (b & 0xC000) {
          // エンドマーク
        case 0x0000:
          b = 0;
          break;
          // 語間 短点7つ分の無音
        case 0x4000:
          delay(mTime * (7-1-3));
          break;
          // 短点
        case 0x8000:
          callback(mTime * 1);
          break;
          // 長点
        case 0xC000:
          callback(mTime * 3);
          break;
        }

        // 文字間 短点1つ分の無音
        delay(mTime * 1);
      }
      // 文字間 短点3つ分の無音
      delay(mTime * 3);
    }
  }
}

// MSBから2ビットずつ取り出す(最大8点)
// 00 = 終了
// 01 = 語間 短点7つ分の無音
// 10 = 短点 + 文字間の短点1つ分の無音
// 11 = 長点 短点3つ分 + 文字間の短点1つ分の無音
const uint16_t KyaMorseBase::morses[59] = {
  (B01000000 * 256) + B00000000,    // " "  0x20   xxxxxxx
  (B00000000 * 256) + B00000000,    // "!"  0x21  xxxxxxxx
  (B00000000 * 256) + B00000000,    // """  0x22  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "#"  0x23  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "$"  0x24  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "%"  0x25  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "&"  0x26  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "'"  0x27  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "("  0x28  xxxxxxxx
  (B00000000 * 256) + B00000000,    // ")"  0x29  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "*"  0x2A  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "+"  0x2B  xxxxxxxx
  (B11111010 * 256) + B11110000,    // ","  0x2C  --・・--xx
  (B11101010 * 256) + B10110000,    // "-"  0x2D  -・・・・-xx
  (B10111011 * 256) + B10110000,    // "."  0x2E  ・-・-・-xx
  (B11101011 * 256) + B10000000,    // "/"  0x2F  -・・-・xxx
  (B11111111 * 256) + B11000000,    // "0"  0x30  -----xxx
  (B10111111 * 256) + B11000000,    // "1"  0x31  ・----xxx
  (B10101111 * 256) + B11000000,    // "2"  0x32  ・・---xxx
  (B10101011 * 256) + B11000000,    // "3"  0x33  ・・・--xxx
  (B10101010 * 256) + B11000000,    // "4"  0x34  ・・・・-xxx
  (B10101010 * 256) + B10000000,    // "5"  0x35  ・・・・・xxx
  (B11101010 * 256) + B10000000,    // "6"  0x36  -・・・・xxx
  (B11111010 * 256) + B10000000,    // "7"  0x37  --・・・xxx
  (B11111110 * 256) + B10000000,    // "8"  0x38  ---・・xxx
  (B11111111 * 256) + B10000000,    // "9"  0x39  ----・xxx
  (B00000000 * 256) + B00000000,    // ":"  0x3A  xxxxxxxx
  (B00000000 * 256) + B00000000,    // ";"  0x3B  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "<"  0x3C  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "="  0x3D  xxxxxxxx
  (B00000000 * 256) + B00000000,    // ">"  0x3E  xxxxxxxx
  (B10101111 * 256) + B10100000,    // "?"  0x3F  ・・--・・xx
  (B10111110 * 256) + B11100000,    // "@"  0x40  ・--・-・xx
  (B10110000 * 256) + B00000000,    // "A"  0x41  ・-xxxxxx
  (B11101010 * 256) + B00000000,    // "B"  0x42  -・・・xxxx
  (B11101110 * 256) + B00000000,    // "C"  0x43  -・-・xxxx
  (B11101000 * 256) + B00000000,    // "D"  0x44  -・・xxxxx
  (B10000000 * 256) + B00000000,    // "E"  0x45  ・xxxxxxx
  (B10101110 * 256) + B00000000,    // "F"  0x46  ・・-・xxxx
  (B11111000 * 256) + B00000000,    // "G"  0x47  --・xxxxx
  (B10101010 * 256) + B00000000,    // "H"  0x48  ・・・・xxxx
  (B10100000 * 256) + B00000000,    // "I"  0x49  ・・xxxxxx
  (B10111111 * 256) + B00000000,    // "J"  0x4A  ・---xxxx
  (B11101100 * 256) + B00000000,    // "K"  0x4B  -・-xxxxx
  (B10111010 * 256) + B00000000,    // "L"  0x4C  ・-・・xxxx
  (B11110000 * 256) + B00000000,    // "M"  0x4D  --xxxxxx
  (B11100000 * 256) + B00000000,    // "N"  0x4E  -・xxxxxx
  (B11111100 * 256) + B00000000,    // "O"  0x4F  ---xxxxx
  (B10111110 * 256) + B00000000,    // "P"  0x50  ・--・xxxx
  (B11111011 * 256) + B00000000,    // "Q"  0x51  --・-xxxx
  (B10111000 * 256) + B00000000,    // "R"  0x52  ・-・xxxxx
  (B10101000 * 256) + B00000000,    // "S"  0x53  ・・・xxxxx
  (B11000000 * 256) + B00000000,    // "T"  0x54  -xxxxxxx
  (B10101100 * 256) + B00000000,    // "U"  0x55  ・・-xxxxx
  (B10101011 * 256) + B00000000,    // "V"  0x56  ・・・-xxxx
  (B10111100 * 256) + B00000000,    // "W"  0x57  ・--xxxxx
  (B11101011 * 256) + B00000000,    // "X"  0x58  -・・-xxxx
  (B11101111 * 256) + B00000000,    // "Y"  0x59  -・--xxxx
  (B11111010 * 256) + B00000000,    // "Z"  0x5A  --・・xxxx
};

0 件のコメント: