LoginSignup
0
0

More than 5 years have passed since last update.

WiringPi をISLispで記述

Last updated at Posted at 2017-05-31

はじめに

EISLのコンパイラにGCCソースの挿入機能を追加しました。これによりGCCの豊富な機能を取り込むことができます。従来、ラズパイ用のEISLには組み込み関数としてWirginPiの機能を取り込んでいました。今後はISLispとして記述できるのでテストを兼ねてやってみました。

void型関数の注意点

ISLispに限らずLisp系言語においては式はすべて、値を持ちます。一方、C言語ではvoid型がありこれは返り値を持ちません。void型をそのままISLispに埋め込むとエラーとなる場合があります。そこでGCCの拡張機能である式化を使ってこの問題を回避しています。

例えば、pwmSetMode関数はvoid型です。これを次のように記述すると値をもつ式とすることができ、エラーになりません。

({pwmSetMode(PWM_MODE_MS);T;})

TはISLispにおける t 真の値です。

拡張関数

FASTコンパイラには次の関数が追加されています。
(c-include str) 文字列strを #inlude 文としてCソースに埋め込みます。
(c-define str) 文字列strを #defin文としてCソースに埋め込みます。
(c-lang str) 文字列strを Cソースコードとして埋め込みます。
(c-option str) GCCでコンパイルするときにstrをコンパイラオプションに与えます。

ソースコード

小整数は即値になっています。0あるいは正数の場合には上位第二ビットを立てて、即値と識別しています。負数の場合にはセルの番地の範囲外でありそのまま即値と識別されます。これをC言語の中で利用する場合には INT_MASKとのandをとってください。 INT_MASK & x のようにして使います。ISLispの変数はすべて大文字に変換されてCソースになっていますので、大文字で記述してください。
FmakeintはCの整数をISLispのセルに変換するものです。Lisp側に値を返す場面で使用しています。

EISL ver0.65以後で利用可能です。

(注)cond節の帰結部分で式化をしています。これは本来不要でした。ver0.66以後は式化は要らなくなります。defun本体の最終行にCコードを挿入するときだけ式化が必要となります。

(c-include "<wiringPi.h>")
(c-include "<wiringPiSPI.h>")
(c-option "-lwiringPi")


(defun wiringpi-setup-gpio ()
  (c-lang "Fmakeint(wiringPiSetupGpio());"))

(defun wiringpi-spi-setup-ch-speed (x y)
  (if (not (integerp x)) (error "wiringgpi-spi-setup-ch-spped: not integer" x))
  (if (not (integerp y)) (error "wiringgpi-spi-setup-ch-spped: not integer" y))
  (c-lang "Fmakeint(wiringPiSPISetup( (INT_MASK & X), (INT_MASK & Y)));"))

(defun pwm-set-mode (x)
  (cond ((eq x 'pwm-mode-ms)
         (c-lang "({pwmSetMode(PWM_MODE_MS);T;})"))
        ((eq x 'pwm-mode-bal)
         (c-lang "({pwmSetMode(PWM_MODE_BAL);T;})"))
        (t (error "pwm-set-mode: not integer" x)))
  t)


(defun pwm-set-range (x)
  (if (not (integerp x)) (error "pwm-set-range: not integer" x))
  (c-lang "pwmSetRange(INT_MASK & X);")
  t)

(defun pwm-set-clock (x)
  (if (not (integerp x)) (error "pwm-set-clock: not integer" x))
  (c-lang "pwmSetClock(INT_MASK & X);")
  t)


(defun pin-mode (x y)
  (cond ((eq y 'input)
         (c-lang "({pinMode( (INT_MASK & X), INPUT);T;})"))
        ((eq y 'output)
         (c-lang "({pinMode( (INT_MASK & X), OUTPUT);T;})"))
        ((eq y 'pwm-output)
         (c-lang "({pinMode( (INT_MASK & X),PWM_OUTPUT);T;})"))
        (t (error "pin-mode: illegal argument" y)))
   t)


(defun digital-write (x y)
  (if (not (integerp x)) (error "digital-write: not integer" x))
  (if (not (integerp y)) (error "digital-write: not integer" y))

  (c-lang "digitalWrite((INT_MASK & X),(INT_MASK & Y));")
  t)

(defun digital-write-byte (x)
  (if (not (integerp x)) (error "digital-write-byte: not integer" x))
  (c-lang "digitalWriteByte(INT_MASK & X);")
  t)


(defun pwm-write (x y)
  (if (not (integerp x)) (error "pwm-write: not integer" x))
  (if (not (integerp y)) (error "pwm-write: not integer" y))
  (c-lang "pwmWrite((INT_MASK & X),(INT_MASK & Y));")
  t)

(defun pull-up-dn-control (x y)
  (if (not (integerp x)) (error "pull-up-dn-control" x))
  (if (not (integerp y)) (error "pull-up-dn-control" y))
  (c-lang "pullUpDnControl((INT_MASK & X),(INT_MASK & Y));")
  t)

(defun digital-read (x)
  (if (not (integerp x)) (error "digital-read: not integer" x))
  (c-lang "Fmakeint(digitalRead(INT_MASK & X));"))

(defun delay (x)
  (if (not (integerp x)) (error "delay: not integer" x))
  (c-lang "delay(INT_MASK & X);")
  t)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0