Emacs Lisp で無線機の情報を取得する

前回の記事でウェブブラウザから CW キーイングができることが確認できました。次は無線機から情報を取得したり制御ができるかを試してみたいのですが、その前に CI-V の復習をしたいと思います。

以前、Twitter に次のようなツイートをしました。Emacs Lisp で IC-7100 から周波数、モード、フィルタの情報を取得しました。

そのときのコードを少し手直ししたものが次のコードです。Emacs Lisp 初心者であるため書き方には自信がありません。前回は Linux 上で動かしましたが、今回は Windows 上で動作させるためシリアルポートのパスを変更しました。

;; Linux /dev/ttyACM0, /dev/USB0 etc.
(defconst dit-civ-port "\\\\.\\COM4")

(defconst dit-civ-port-speed 19200)

(defvar dit-civ-mode-hook nil)
(defconst dit-civ-buffer-name "*dit-civ*")

(defvar dit-civ-frequency "0000000000")
(defvar dit-civ-mode "")
(defvar dit-civ-filter "")

(defvar dit-civ-mode-map
  (let ((map (make-sparse-keymap)))
    map) "")

(setq dit-civ-font-lock-keywords
      (let* ((fields '("Mode" "Freq" "Filter"))
             (fields-re (regexp-opt fields))
             (modes '("LSB" "USB" "AM" "CW" "RTTY"
                      "FM" "WFM" "CW-R" "RTTY-R" "DV"))
             (modes-re (regexp-opt modes 'words)))
        `((,fields-re . font-lock-comment-face)
          (,modes-re . font-lock-keyword-face))))

(defun dit-civ-recv (proc raw)
  (let ((daddr (elt raw 2))
        (saddr (elt raw 3))
        (cmd   (elt raw 4))
        (data  (substring raw 5 nil)))
    (cond ((equal cmd #x00)
           (setq dit-civ-frequency
                 (with-temp-buffer
                   (insert
                    (mapconcat 'identity
                               (mapcar (lambda (e)
                                         (number-to-string e))
                                       (list (logand (lsh (elt data 4) -4) #x0f)
                                             (logand (elt data 4) #x0f)
                                             (logand (lsh (elt data 3) -4) #x0f)
                                             (logand (elt data 3) #x0f)
                                             (logand (lsh (elt data 2) -4) #x0f)
                                             (logand (elt data 2) #x0f)
                                             (logand (lsh (elt data 1) -4) #x0f)
                                             (logand (elt data 1) #x0f)
                                             (logand (lsh (elt data 0) -4) #x0f)
                                             (logand (elt data 0) #x0f))) ""))
                   (buffer-string))))
          ((equal cmd #x01)
           (setq dit-civ-mode
                 (let ((mode (elt data 0)))
                   (cond ((equal mode 0) "LSB")
                         ((equal mode 1) "USB")
                         ((equal mode 2) "AM")
                         ((equal mode 3) "CW")
                         ((equal mode 4) "RTTY")
                         ((equal mode 5) "FM")
                         ((equal mode 6) "WFM")
                         ((equal mode 7) "CW-R")
                         ((equal mode 8) "RTTY-R")
                         ((equal mode 23) "DV"))))
           (setq dit-civ-filter
                 (let ((fil (elt data 1)))
                   (cond ((equal fil 1) "FIL1")
                         ((equal fil 2) "FIL2")
                         ((equal fil 3) "FIL3"))))))
    )
  (dit-civ-update))

(defun dit-civ-init ()
  (switch-to-buffer (get-buffer-create dit-civ-buffer-name))
  (let ((proc (make-serial-process :port dit-civ-port
                                   :speed dit-civ-port-speed
                                   :filter 'dit-civ-recv))))
  (dit-civ-update))

(defun dit-civ-update ()
  (erase-buffer)
  (insert "\n")
  (insert (format "   Freq: %d.%s.%s\n"
                  (string-to-number (substring dit-civ-frequency 0 4))
                  (substring dit-civ-frequency 4 7)
                  (substring dit-civ-frequency 7 nil)))
  (insert (format "   Mode: %s\n" dit-civ-mode))
  (insert (format " Filter: %s\n" dit-civ-filter)))

(defun dit-civ-mode ()
  (interactive)
  (kill-all-local-variables)
  (use-local-map dit-civ-mode-map)
  (setq major-mode 'dit-civ-mode)
  (setq mode-name "dit-civ")
  (setq font-lock-defaults '((dit-civ-font-lock-keywords)))
  (run-hooks 'dit-civ-mode-hook))

(defun dit-civ ()
  (interactive)
  (dit-civ-init)
  (dit-civ-mode))

(provide 'dit-civ)

無線機(IC-705)側は CI-V トランシーブを有効にしておきます。次のコマンドで Emacs を起動して、M-x dit-civ で実行します。

> emacs -l dit-civ.cl

無線機の周波数、モード、フィルターを変更すると、次のように Emacs のバッファ内に表示されます。

CI-V については ICOM の各無線機の補足説明書として公開されています。IC-705 の場合は次のページからダウンロードできます。コマンド体系、フォーマットは各機種共通です。

補足説明書(CI-Vコマンド説明) ダウンロード www.icom.co.jp

JI1JDI

ゆるく楽しくアマチュア無線とプログラミングを楽しんでいます。 scrapbox.io