はじめに
Ninune-wa さんの IoT BASIC サンプルを『Turbo Pascal』へ移植してみます。
MSX0VIBE.BAS
BASIC のソースコードは GitHub で公開されています。
| 項目 | 説明 |
|---|---|
| 概要 | 内蔵振動モーターを 2 秒間振動させます。 |
| ファイル名 | MSX0VIBE.BAS |
| 対応デバイス | |
| コメント | Face Bottom Base や Battery Bottoms を装着して、プログラムを実行してください。 |
See also:
MSX0 Stack での挙動
MSX0VIBE.BAS をロードして、
実行してみました。
内蔵振動モーターが 2 秒振動し、その後停止しました。
ただ、当方の環境では連続して実行すると振動モーターが停止しなかったり AXP192 が見つからなくなったりする事がありました。
プログラムは〔Ctrl〕+〔Stop〕(リモートコントロールパネルからは〔Ctrl〕+〔F12〕)で中断できます。
Turbo Pascal へ移植
別途、SYSUTILS.LIB と IOT.LIB が必要です。
(* Test Code: MSX0Stack Vibration motor *)
program MSX0VIBE;
type
LibStr = string[80];
{$I SYSUTILS.LIB}
{$I IOT.LIB}
var
node: LibStr;
function FindNode(var node: LibStr; addr: LibStr): Boolean;
var
List, Last, p: PItem;
Flg: Boolean;
begin
List := nil;
Flg := IoTFindCount(node) < 0; { Always False }
IoTFind(node, List, Last);
p := List;
while (p <> nil) and (not Flg) do
if p^.Data = addr then
begin
Flg := True;
node := node + '/' + p^.Data;
end
else
p := p^.Next;
ClearListItem(List);
FindNode := Flg;
end; { FindNode() }
procedure Vibe(node: LibStr; Mode: Boolean);
const
MStr: array [Boolean] of String[3] = ('OFF', 'ON');
var
v: Integer;
begin
Writeln('Vibration ', MStr[Mode]);
IotPutStr(node, #$12); { REG 12H:DC-DC1/3 & LDO2/3 output control }
v := IotGetInt(node);
if Mode then
v := v or $08 { Vibration ON :REG 12H LDO3 switch cotrol Bit3 (1:enable) }
else
v := v and $F7; { Vibration OFF:REG 12H LDO3 switch cotrol Bit3 (0:disable) }
IotPutStr(node, #$12 + Chr(v));
end; { Vibe() }
procedure Wait(n: Integer);
begin
Writeln('Wait ', n , ' Second');
Delay(n * 894); { 1sec = 3.579545 / 4 * 1000 }
end; { Wait() }
begin
(* Init *)
ClrScr;
node := 'device/i2c_i'; { Device Tree }
if not FindNode(node, '34') then { I2C Address for AXP192 }
begin
Writeln('Internal I2C device not found...');
Exit;
end;
(* Vibrator ON *)
Vibe(node, True);
(* Wait n Second *)
Wait(2);
(* Vibrator OFF *)
Vibe(node, False);
end.
実行してみました。
やはり、当方の環境では連続して実行すると振動モーターが停止しなかったり AXP192 が見つからなくなったりする事がありました。うまく動作する時はうまく動作するのですが...。
解説
サブルーチン
サブルーチンを手続きと関数で書き替えました。コードの総量は増えましたが、読みやすくはなったかもしれません。
結果を利用しない関数
Turbo Pascal 3.0 や標準 Pascal では結果を利用しない関数を呼び出すことができません。例えば Integer 型の結果を返す関数 foo() は、次のような呼び出しはできません。
foo(123);
つまり、手続きや関数のパラメータとして使うか、結果を変数に取るしかありません...まぁ、「関数」とは本来そういうものですけれど。
Bar(foo(123));
var
n: Integer;
begin
n := foo(123);
end;
IoTFind() の前に必ず IoTFindCount() 関数を呼び出す必要があるのですが、この結果は必要ありません。つまり、普通に書くと次のようなコードになります。
var
Flg: Boolean;
n: Integer;
begin
Flg := False;
n := IoTFindCount(node);
...
-
Flgは False で初期化したい -
IoTFindCount()は常に実行したい -
IoTFindCount()が返す結果は利用しない
この条件を満たすように短く書くと、次のようなコードになる訳です。
var
Flg: Boolean;
begin
Flg := IoTFindCount(node) < 0; // IoTFindCount() は負数を返さないため、常に False
...
短くできましたが、初見では何をやっているのか理解できないかもしれませんね。あまりいいコードではないです。
なお、結果を無視して関数を実行できる拡張構文 {$X+} は Turbo Pascal 6.0 以降で利用可能です。
おわりに
今回の移植に関して難しい所は特にありませんでした。
See also:



