GAL Writerの制作 ― 2025年04月14日 17:30
ハードウェアの制作にGALを使用できると、とても便利です。特にアドレスデコーダーの 類などは、とてもすっきりしますし、後からの変更も簡単にできますので、重宝します。 これまで、いくつかの機器の制作で使用してきました。
GALを作成するには、PALASMでヒューズデータを作成し、XGecuのTL866 II Plus
で書き込みをしていました。
これはこれで、いいのですが、PALASMはDOSのプログラムで、 TL866II PlusはWindosのコントルールプログラムでした。そうです。ヒューズデータのやりとりが めんどうだったのです。できれば、DOS環境だけで完結したく思ってました。
調べてみると、GAL Writerの制作例をいくつか発見できました。その中でも、 ELM氏の発表なされた「お手GAL」は、以前より気にかけていたのですが、とてもシンプルで、 DOSの環境で使うことができ、私の悩みを解決するものです。思い切って制作することにしました。 ELM氏の「お手GAL」は ここ にありますのでご参照ください。
実際の制作にあったって、手持ちの部品を優先して使用したので、 古い大型の部品やオーバースッペクの部品が見受けられます。 また、抵抗内蔵のディジタルトランジスタは、抵抗と手持ちのトランジスタで構成しました。 デバッグをしていて、プリンタポートの出力電圧が低かったのでバッファーを追加する必要が でてしまいましたが、大きめのボードだったのでいれることができました。
これが、完成した私の「お手GAL GAL Writer」です。
これで、16V8,20V8,22V10をプログラムできます。今後とも、重宝しそうです。
高速キャリージェネレター付き8ビット加算・減算器の製作 ― 2025年02月06日 21:36
高速キャリージェネレター付き8ビット加算・減算器の製作
デジタル回路の学び直しをしています。テキストは、大川喜邦著「デジタル回路」です。組合せ回路の部分が終わりました。組合せ回路のまとめとして、高速キャリージェネレーター付きの8ビット加算・減算器を基本的なTTLだけで設計、製作しました。最終的には、TTLが30個でできました。
。
ウラ面はこんな感じです。
手ハンダなので、スパゲティボールです。
基板上の"Value A"と"Value B"のスイッチに-128から127までの数値を設定し、加算・減算した結果を"Result"LEDに表示します。負の数は2の補数表現です。
回路図は、ここ にあります。
CPUの中のALUの一部を解析するとこんな感じになるのでしょうね。
Modula-2 でプログラミング -- 文字列探索プログラム find の製作 (その3) -- ― 2025年01月05日 21:19
前回紹介したfindプログラムは、FileSearchモジュールの不備で、ファイル一覧の構造が 丸見えになっていました。FileSearchモジュールに2つ手続きを追加して不具合を解消しました。
新しいFileSearchモジュールの定義モジュールは以下の通り。
DEFINITION MODULE FileSearch;
FROM OpSys IMPORT FCB,FCBFileName;
EXPORT QUALIFIED pFileList,FileNameNode,
GetNextFile,GetFileName,LoginDisk,MakeFileList,DumpFileList;
CONST
DMABufferSize = 128;
FileNameSize = 14;
TYPE
pFileList = POINTER TO FileNameNode;
FileNameNode = RECORD
FileName: ARRAY [0..FileNameSize] OF CHAR;
Next: pFileList
END;
DMA = ARRAY [0..DMABufferSize-1] OF CHAR;
PROCEDURE GetNextFile(FileLIst: pFileList): pFileList;
PROCEDURE GetFileName(FileList: pFileList;VAR FileName: ARRAY OF CHAR);
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
PROCEDURE MakeFileList(FIleMatch: ARRAY OF CHAR): pFileList;
PROCEDURE DumpFileList(pList: pFileList);
END FileSearch.
手続き、次のファイルを取り出すGetNextFileとファイル名を取り出すGetFileNameを追加しました。
実現モジュールは以下の通り。
IMPLEMENTATION MODULE FileSearch;
FROM InOut IMPORT WriteHex,Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,FCBFileName,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,TSIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,FCBToStr,NameState;
CONST
EOS = 0C;
PROCEDURE GetNextFile(FileList: pFileList): pFileList;
BEGIN
RETURN FileList^.Next
END GetNextFile;
PROCEDURE GetFileName(FileList: pFileList; VAR FileName: ARRAY OF CHAR);
VAR
i: CARDINAL;
BEGIN
i := 0;
WHILE ( FileList^.FileName[i] # EOS ) DO
FileName[i] := FileList^.FileName[i];
INC(i)
END;
FileName[i] := EOS
END GetFileName;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
VAR
DiskCode: CARDINAL;
Junk: WORD;
BEGIN
IF FCBBuf.name.disk = 0C THEN
Bdos(retCDsk,Junk,DiskCode);
RETURN (CHR(ORD(DiskCode)+ORD('A')));
ELSE
RETURN (CHR(ORD(FCBBuf.name.disk)+ORD('A')-1));
END;
END LoginDisk;
PROCEDURE MakeFileList(FileMatch: ARRAY OF CHAR): pFileList;
VAR
Disk: CHAR;
FCBBuffer: FCB;
BdosRc: CARDINAL;
DMABuffer: DMA;
CPos: CARDINAL;
NameStatus: NameState;
pList: pFileList;
pNewFileName: pFileList;
FCBFile: FCBFileName;
Formatted: BOOLEAN;
Junk: WORD;
BEGIN
pList := NIL;
(* Clear FCB Buffer and set file name *)
FCBBuffer.name.text := '';
FCBBuffer.rest := '';
NameStatus := StrToFCB(FileMatch,FCBBuffer.name);
Disk := LoginDisk(FCBBuffer);
(* set DMA Bufer *)
Bdos(setDMA,ADR(DMABuffer),Junk);
(* find first much file *)
Bdos(searchFst,ADR(FCBBuffer),BdosRc);
WHILE BdosRc # 255 DO
ALLOCATE(pNewFileName,TSIZE(FileNameNode));
FOR CPos := 0 TO 11 DO
FCBFile.text[CPos]
:= DMABuffer[CPos+BdosRc*32]
END;
FCBFile.disk := CHR(ORD(Disk) - ORD('A') + 1);
FCBToStr(FCBFile,pNewFileName^.FileName,FALSE);
pNewFileName^.Next := pList;
pList := pNewFileName;
(* find next file *)
Bdos(searchNxt,Junk,BdosRc);
END;
RETURN pList
END MakeFileList;
PROCEDURE WriteFileName(FileName: ARRAY OF CHAR);
BEGIN
WriteString(FileName);
WriteLn
END WriteFileName;
PROCEDURE DumpFileList(pList: pFileList);
BEGIN
WHILE pList # NIL DO
WriteFileName(pList^.FileName);
pList := pList^.Next;
END;
END DumpFileList;
END FileSearch.
これらの変更を反映したfindは、以下のとおり。
MODULE Find;
FROM InOut IMPORT Write,WriteCard,WriteString,WriteLn;
FROM Files IMPORT FILE,FileState,Open,Close,Read;
FROM CmdArgs IMPORT Argc,Argv;
FROM FileSearch IMPORT GetFileName,GetNextFile,
FileNameNode,MakeFileList,pFileList;
FROM BasicFileIO IMPORT FileIOStruct,pFileIOStruct,
OpenFile,CloseFile,EOFFile,FileIOStatus;
FROM StdFileIO IMPORT GetLine;
CONST
EOS = 0C;
MAXLINE = 128;
FILENAMESIZE = 14;
EOFMARK = 32C;
VAR
FileName: ARRAY [0..FILENAMESIZE] OF CHAR;
FileMatch: ARRAY [0..FILENAMESIZE] OF CHAR;
Target: ARRAY [0..MAXLINE] OF CHAR;
CPos,FileNumber,LineNumber,nArgc: CARDINAL;
pList: pFileList;
PROCEDURE putLine(FileName:ARRAY OF CHAR;Line:CARDINAL;
Buffer: ARRAY OF CHAR);
BEGIN
WriteString(FileName);
Write(' ');WriteCard(Line,1);Write(':');
WriteString(Buffer);
WriteLn
END putLine;
PROCEDURE findTarget(Target,Line:ARRAY OF CHAR): BOOLEAN;
VAR
t,l: CARDINAL;
found: BOOLEAN;
BEGIN
found := FALSE;
t := 0; l := 0;
WHILE (Line[l] # EOS) AND (NOT found) DO
IF Line[l] = Target[0] THEN
t := 1;
WHILE Line[l+t] = Target[t] DO
INC(t);
END;
IF Target[t] = EOS THEN
found := TRUE;
END;
END;
INC(l);
END;
RETURN found
END findTarget;
PROCEDURE Usage();
BEGIN
WriteString('find');WriteLn;
WriteString(' TargetString File1 File2 FIle3,,,,');WriteLn
END Usage;
PROCEDURE MatchLines(FileName,TargetString: ARRAY OF CHAR);
VAR
pFileIO: pFileIOStruct;
Line: ARRAY [0..MAXLINE-1] OF CHAR;
Chars: CARDINAL;
NLines: CARDINAL;
Junk: FileIOStatus;
BEGIN
IF OpenFile(FileName,pFileIO) = Success THEN
NLines := 1;
WHILE NOT EOFFile(pFileIO) DO
Chars := GetLine(pFileIO,Line);
IF findTarget(TargetString,Line) THEN
putLine(FileName,NLines,Line);
END;
INC(NLines);
END;
Junk := CloseFile(pFileIO)
END
END MatchLines;
BEGIN
nArgc := Argc();
IF nArgc < 1 THEN
Usage();
HALT
END;
Argv(0,Target);
FileNumber := 1;
WHILE FileNumber < nArgc DO
Argv(FileNumber,FileMatch);
pList := MakeFileList(FileMatch);
WHILE pList # NIL DO
GetFileName(pList,FileName);
MatchLines(FileName,Target);
pList := GetNextFile(pList)
END;
INC(FileNumber)
END
END Find.
これで、FileSearchモジュール内部のデータ構造をFindが知る必要がなくなりました。
Modula-2 でプログラミング -- 文字列探索プログラム find の製作 (その2) ― 2024年12月28日 21:13
BasicFileIO モジュール、StdFileIO モジュールをつかった find プログラムは、以下のとおりです。
MODULE Find;
FROM InOut IMPORT Write,WriteCard,WriteString,WriteLn;
FROM Files IMPORT FILE,FileState,Open,Close,Read;
FROM CmdArgs IMPORT Argc,Argv;
FROM FileSearch IMPORT pFileList,FileNameNode,MakeFileList;
FROM BasicFileIO IMPORT FileIOStruct,pFileIOStruct,
OpenFile,CloseFile,EOFFile,FileIOStatus;
FROM StdFileIO IMPORT GetLine;
CONST
EOS = 0C;
MAXLINE = 128;
FILENAMESIZE = 14;
EOFMARK = 32C;
VAR
FileMatch: ARRAY [0..FILENAMESIZE] OF CHAR;
Target: ARRAY [0..MAXLINE] OF CHAR;
CPos,FileNumber,LineNumber,nArgc: CARDINAL;
pList: pFileList;
PROCEDURE putLine(FileName:ARRAY OF CHAR;Line:CARDINAL;
Buffer: ARRAY OF CHAR);
BEGIN
WriteString(FileName);
Write(' ');WriteCard(Line,1);Write(':');
WriteString(Buffer);
WriteLn
END putLine;
PROCEDURE findTarget(Target,Line:ARRAY OF CHAR): BOOLEAN;
VAR
t,l: CARDINAL;
found: BOOLEAN;
BEGIN
found := FALSE;
t := 0; l := 0;
WHILE (Line[l] # EOS) AND (NOT found) DO
IF Line[l] = Target[0] THEN
t := 1;
WHILE Line[l+t] = Target[t] DO
INC(t);
END;
IF Target[t] = EOS THEN
found := TRUE;
END;
END;
INC(l);
END;
RETURN found
END findTarget;
PROCEDURE Usage();
BEGIN
WriteString('find');WriteLn;
WriteString(' TargetString File1 File2 FIle3,,,,');WriteLn
END Usage;
PROCEDURE MatchLines(FileName,TargetString: ARRAY OF CHAR);
VAR
pFileIO: pFileIOStruct;
Line: ARRAY [0..MAXLINE-1] OF CHAR;
Chars: CARDINAL;
NLines: CARDINAL;
Junk: FileIOStatus;
BEGIN
IF OpenFile(FileName,pFileIO) = Success THEN
NLines := 1;
WHILE NOT EOFFile(pFileIO) DO
Chars := GetLine(pFileIO,Line);
IF findTarget(TargetString,Line) THEN
putLine(FileName,NLines,Line);
END;
INC(NLines);
END;
Junk := CloseFile(pFileIO)
END
END MatchLines;
BEGIN
nArgc := Argc();
IF nArgc < 1 THEN
Usage();
HALT
END;
Argv(0,Target);
FileNumber := 1;
WHILE FileNumber < nArgc DO
Argv(FileNumber,FileMatch);
pList := MakeFileList(FileMatch);
WHILE pList # NIL DO
MatchLines(pList^.FileName,Target);
pList := pList^.Next
END;
INC(FileNumber)
END
END Find.
MachLine で、指定された文字列が読み込んだ行に存在するかを検査し、存在したら書き出します。
ファイル名のリスト構造が丸見えなのでひと工夫する必要がありますが、今回は見送りました。
Modula-2でプログラミング -- 文字列探索プログラム find の制作(その1) ― 2024年12月28日 21:00
指定された文字列を 指定されたファイルの中から探し出すプログラム find を紹介します。 このように使います。
C0#find
arguments>GetLine *.def *.mod
C:STDFILEI.DEF 6: GetLine;
C:STDFILEI.DEF 8:PROCEDURE GetLine(VAR pFileIO: pFileIOStruct;
C:STDFILEI.MOD 10:PROCEDURE GetLine(VAR pFileIO: pFileIOStruct;
C:STDFILEI.MOD 36:END GetLine;
C:FIND.MOD 8:FROM StdFileIO IMPORT GetLine;
C:FIND.MOD 71: Chars := GetLine(pFileIO,Line);
63K QP/M VER 2.7 (BIOS VER 1.0)
(C) 1988.12.1. K.YOSHIDA
2018.10.28. MODEFIED BY H.KIDA
C0#find
arguments>GetChar *.def *.mod
C:BASICFIL.DEF 7: ReadFile,GetChar;
C:BASICFIL.DEF 28:PROCEDURE GetChar(VAR pFileIO: pFileIOStruct): CHAR;
C:STDFILEI.MOD 3: pFileIOStruct,GetChar;
C:STDFILEI.MOD 20: C := GetChar(pFileIO);
C:BASICFIL.MOD 65:PROCEDURE GetChar(VAR pFileIO: pFileIOStruct): CHAR;
C:BASICFIL.MOD 89:END GetChar;
63K QP/M VER 2.7 (BIOS VER 1.0)
(C) 1988.12.1. K.YOSHIDA
2018.10.28. MODEFIED BY H.KIDA
C0#
find は、ファイルを読みますので、ファイルアクセスのルーチンが必要になります。 Bdosを直接使うことができるので、かんたんなファイル読み込みモジュール BasicFileIO を作成しました。 更に、行単位のファイル読み出しが必要なので、上位のモジュール StdFileIO を作成しました。StdFileIOは、 Bdosとは、独立しています。
まず、 BasicFileIO です。基本的なファイルアクセスルーチンの集まりです。 今回は、読み出せれば良いので、書き込み関係のルーチンは作成していません。基本的なファイルのアクセスは、 一文字単位です、 定義モジュールは、以下のとおりです。
DEFINITION MODULE BasicFileIO; FROM OpSys IMPORT FCB,FCBFileName; EXPORT QUALIFIED FileIOStatus,FileIOStruct,pFileIOStruct, OpenFile,CloseFile,EOFFile, ReadFile,GetChar; CONST DMASize = 128; TYPE FileIOStatus = (Success,InvalidFileName, OpenError,CloseError,IOError); DMA = ARRAY [0..DMASize-1] OF CHAR; pFileIOStruct = POINTER TO FileIOStruct; FileIOStruct = RECORD FCBBuf: FCB; DMABuf: DMA; ReadPos: CARDINAL; WritePos: CARDINAL; EOFFlag: BOOLEAN; END; PROCEDURE OpenFile(FileName: ARRAY OF CHAR; VAR pFileIO: pFileIOStruct): FileIOStatus; PROCEDURE CloseFile(VAR pFileIO: pFileIOStruct): FileIOStatus; PROCEDURE ReadFile(VAR pFileIO: pFileIOStruct): FileIOStatus; PROCEDURE GetChar(VAR pFileIO: pFileIOStruct): CHAR; PROCEDURE EOFFile(pFileIO: pFileIOStruct): BOOLEAN; END BasicFileIO.
実装モジュールは、以下のとおりです。手続き GetChar では、CR LF と連続した場合、 LF を読み飛ばします。
IMPLEMENTATION MODULE BasicFileIO; FROM InOut IMPORT Write,WriteString,WriteLn; FROM OpSys IMPORT BdosFunctions,FCBFileName,Bdos,FCB; FROM FileNames IMPORT StrToFCB,NameState; FROM SYSTEM IMPORT ALLOCATE,ADR,TSIZE,WORD; CONST CR = 15C; LF = 12C; EOFMARK = 32C; PROCEDURE OpenFile(FileName: ARRAY OF CHAR; VAR pFileIO: pFileIOStruct): FileIOStatus; VAR BdosRc: CARDINAL; Junk: WORD; BEGIN (* Allocate FCB and DMA / pre-Set *) ALLOCATE(pFileIO,TSIZE(FileIOStruct)); pFileIO^.FCBBuf.name.text := ''; pFileIO^.FCBBuf.rest := ''; pFileIO^.DMABuf := ''; IF StrToFCB(FileName,pFileIO^.FCBBuf.name) # NameOK THEN RETURN InvalidFileName END; Bdos(setDMA,ADR(pFileIO^.DMABuf),Junk); Bdos(openF,ADR(pFileIO^.FCBBuf),BdosRc); IF BdosRc # 255 THEN pFileIO^.ReadPos := DMASize; pFileIO^.WritePos := 0; pFileIO^.EOFFlag := FALSE; RETURN Success ELSE RETURN OpenError END END OpenFile; PROCEDURE CloseFile(VAR pFileIO: pFileIOStruct): FileIOStatus; VAR BdosRc: CARDINAL; BEGIN Bdos(closeF,ADR(pFileIO^.FCBBuf),BdosRc); IF BdosRc = 0 THEN RETURN Success ELSE RETURN CloseError END END CloseFile; PROCEDURE ReadFile(VAR pFileIO: pFileIOStruct): FileIOStatus; VAR BdosRc: CARDINAL; BEGIN Bdos(readSeq,ADR(pFileIO^.FCBBuf),BdosRc); IF BdosRc = 0 THEN RETURN Success ELSE RETURN IOError END END ReadFile; PROCEDURE GetChar(VAR pFileIO: pFileIOStruct): CHAR; VAR C: CHAR; BEGIN IF DMASize = pFileIO^.ReadPos THEN IF ReadFile(pFileIO) = Success THEN pFileIO^.ReadPos := 0 ELSE pFileIO^.ReadPos := 0; pFileIO^.DMABuf[pFileIO^.ReadPos] := EOFMARK END END; C := pFileIO^.DMABuf[pFileIO^.ReadPos]; IF C = CR THEN IF pFileIO^.DMABuf[pFileIO^.ReadPos+1] = LF THEN INC(pFileIO^.ReadPos) END END; INC(pFileIO^.ReadPos); IF C = EOFMARK THEN pFileIO^.EOFFlag := TRUE END; RETURN C END GetChar; PROCEDURE EOFFile(pFileIO: pFileIOStruct): BOOLEAN; BEGIN RETURN pFileIO^.EOFFlag END EOFFile; END BasicFileIO.
GetChar で、 LF を読み飛ばす以外は、面倒くさいところは、ないでしょう。
この、 BasicFileIO モジュールをつかって、行単位の読み出しルーチンを作ってます。 StdFileIO モジュールです。 このモジュールは、 CP/M のファイル構造と独立です。必要最低限の行単位の読み出ししか作成していません。
定義モジュールは、以下の通り。
DEFINITION MODULE StdFileIO; FROM BasicFileIO IMPORT pFileIOStruct; EXPORT QUALIFIED GetLine; PROCEDURE GetLine(VAR pFileIO: pFileIOStruct; VAR LineBuffer: ARRAY OF CHAR): CARDINAL; END StdFileIO.
実装モジュールは、以下の通りです。
IMPLEMENTATION MODULE StdFileIO; FROM BasicFileIO IMPORT pFileIOStruct,GetChar; CONST EOS = 0C; EOFMARK = 32C; CR = 15C; PROCEDURE GetLine(VAR pFileIO: pFileIOStruct; VAR LineBuffer: ARRAY OF CHAR): CARDINAL; VAR C: CHAR; CPos: CARDINAL; BEGIN CPos := 0; LOOP C := GetChar(pFileIO); CASE C OF EOFMARK: LineBuffer[CPos] := EOS; RETURN CPos | CR: LineBuffer[CPos] := EOS; RETURN CPos END; LineBuffer[CPos] := C; INC(CPos); IF CPos = HIGH(LineBuffer) THEN LineBuffer[CPos] := EOS; RETURN CPos END END END GetLine; END StdFileIO.
GetLine は、一文字読み出しを繰り返し、 CR または EOF が来たら、その一文字前の文字までを一行とします。 また、バッファーのサイズ以上に読み取ろうとした場合は、強制的に一行にしてしまいます。溢れてしまうと困りますので。
find 本体の紹介は次回にします。
Modula-2でプログラミング -- FileFindの制作 ― 2024年11月02日 11:36
FIleSearche"モジュールを利用した、ファイマッチで指定されたファイル一覧を書き出すプログラム "FileFind"を作ってみました。
使い方は、このようにします。
C0#filefind arguments>f*.mod *.def C:FIND.MOD C:FILEFIND.MOD C:FILESEAR.MOD C:CONIO.DEF C:ADD16.DEF C:SILLY.DEF C:FILESEAR.DEF C:STDFILEI.DEF C:BDOSSTRU.DEF C:BASICFIL.DEF C:CMDARGS.DEF C:SCREEN.DEF
探すファイル名は、ファイルマッチを指定できます。複数指定できます。 この引数を受け取るには、以前紹介した自作の"CmdArgs"モジュール を使用しています。
プログラムは、このようになりました。
MODULE FileFind;
FROM InOut IMPORT WriteString,WriteLn;
FROM CmdArgs IMPORT Argc,Argv;
FROM FileSearch IMPORT MakeFileList,DumpFileList;
CONST
MAXLINE = 128;
VAR
FileMatch: ARRAY [0..MAXLINE-1] OF CHAR;
nArgc: CARDINAL;
NthFile: CARDINAL;
PROCEDURE Usage();
BEGIN
WriteString('Usage: filefind filematch');WriteLn;
END Usage;
BEGIN
nArgc := Argc();
IF nArgc < 1 THEN
Usage();
HALT;
END;
NthFile := 0;
WHILE NthFile < nArgc DO
Argv(NthFile,FileMatch);
DumpFileList(MakeFileList(FileMatch));
INC(NthFile);
END;
END FileFind.
次々にファイルマッチを取り出し、該当するファイル名のリストを"MakeFileList"で作成し、 そのリストを"DumpFileLIst"で書き出します。"DumpFileList"は、"FileSearch"モジュールに実装しました。 こうすることで、ファイル名の保持のしかたをメインルーチンが知る必要がありません。
Modula-2でプログラミング -- FileSearch ファイルを探すモジュールの修正 ― 2024年11月02日 10:29
前回、ファイルを探すモジュール"FileSearch"を制作しました。これを利用したプログラムを
いくつか作成して見た所、ファイル名リストのデータ構造の使い勝手が良くないことがわかりました
ので"FileSearch"モジュールを修正しました。
修正した"FileSearch"モジュールのDefinition Moduleです。
DEFINITION MODULE FileSearch;
FROM OpSys IMPORT FCB,FCBFileName;
EXPORT QUALIFIED pFileList,FileNameNode,DMA,
LoginDisk,MakeFileList,DumpFileList;
CONST
DMABufferSize = 128;
FileNameSize = 14;
TYPE
pFileList = POINTER TO FileNameNode;
FileNameNode = RECORD
FileName: ARRAY [0..FileNameSize] OF CHAR;
Next: pFileList
END;
DMA = ARRAY [0..DMABufferSize-1] OF CHAR;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
PROCEDURE MakeFileList(FIleMatch: ARRAY OF CHAR): pFileList;
PROCEDURE DumpFileList(pList: pFileList);
END FileSearch.
大きな変更点は、ファイル名の持ち方をべたな文字列にした点です。
修正したImprementation Moduleは、このとおり。
IMPLEMENTATION MODULE FileSearch;
FROM InOut IMPORT WriteHex,Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,FCBFileName,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,TSIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,FCBToStr,NameState;
CONST
EOS = 0C;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
VAR
DiskCode: CARDINAL;
Junk: WORD;
BEGIN
IF FCBBuf.name.disk = 0C THEN
Bdos(retCDsk,Junk,DiskCode);
RETURN (CHR(ORD(DiskCode)+ORD('A')));
ELSE
RETURN (CHR(ORD(FCBBuf.name.disk)+ORD('A')-1));
END;
END LoginDisk;
PROCEDURE MakeFileList(FileMatch: ARRAY OF CHAR): pFileList;
VAR
Disk: CHAR;
FCBBuffer: FCB;
BdosRc: CARDINAL;
DMABuffer: DMA;
CPos: CARDINAL;
NameStatus: NameState;
pList: pFileList;
pNewFileName: pFileList;
FCBFile: FCBFileName;
Formatted: BOOLEAN;
Junk: WORD;
BEGIN
pList := NIL;
(* Clear FCB Buffer and set file name *)
FCBBuffer.name.text := '';
FCBBuffer.rest := '';
NameStatus := StrToFCB(FileMatch,FCBBuffer.name);
Disk := LoginDisk(FCBBuffer);
(* set DMA Bufer *)
Bdos(setDMA,ADR(DMABuffer),Junk);
(* find first much file *)
Bdos(searchFst,ADR(FCBBuffer),BdosRc);
WHILE BdosRc # 255 DO
ALLOCATE(pNewFileName,TSIZE(FileNameNode));
FOR CPos := 0 TO 11 DO
FCBFile.text[CPos]
:= DMABuffer[CPos+BdosRc*32]
END;
FCBFile.disk := CHR(ORD(Disk) - ORD('A') + 1);
FCBToStr(FCBFile,pNewFileName^.FileName,FALSE);
pNewFileName^.Next := pList;
pList := pNewFileName;
(* find next file *)
Bdos(searchNxt,Junk,BdosRc);
END;
RETURN pList
END MakeFileList;
PROCEDURE WriteFileName(FileName: ARRAY OF CHAR);
BEGIN
WriteString(FileName);
WriteLn
END WriteFileName;
PROCEDURE DumpFileList(pList: pFileList);
BEGIN
WHILE pList # NIL DO
WriteFileName(pList^.FileName);
pList := pList^.Next;
END;
END DumpFileList;
END FileSearch.
大きな修正点は、見つかったファイルの名前をFCB形式からべたな文字列のファイル名に変換し、 それを保存している点です。 ファイル名の持ち方をべたな文字列にしたので、ファイル名を書き出すPROCEDURE "WriteFileName"を 修正しています。
他には、"BdosStruct"モジュールの使用をやめました。処理系が提供する Bdos関連機能の"OpSys"モジュールを一部修正し、"BdosStruct"モジュールが無くてもコンパイル できるようにしました。
Modula-2でプログラミング -- FileSearch ファイルを探すモジュールの制作 ― 2024年10月19日 09:49
ファイルを探すことは、結構よくあることです。CP/Mでプログラムを作る場合でも同じこと。 今回は、Modula-2からBDOSの機能を呼び出し、ファイルを探す"FileSearch"モジュールを紹介します。
"FileSearch"モジュールは、処理系が提供するモジュールをいくつか使用しています。
- "OpSys"モジュールは、BDOSやBIOSを呼び出すためのBdos手続きやFCBなどのレコード型などを提供しています。
- "FileNames"モジュールは、FCBのファイル名領域にファイル名を設定する手続きや、その手続きの戻り値の型を提供しています。
- "SYSTEM"モジュールは、メモリーの動的確保や変数のサイズなどを調べる手続きを提供しています。
このほかに自作モジュール"BdosStruct"があります。これは、BDOSを呼び出すBdos手続きがちょっと使いにくかったので、
処理系を騙す仕組みを作り込みました。
"FileSearch"モジュールのDefinition Moduleです。
DEFINITION MODULE FileSearch;
FROM InOut IMPORT Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,CPMStringBuffer,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,SIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,NameState;
FROM BdosStruct IMPORT BdosCommand,BdosReturn;
EXPORT QUALIFIED pFileList,FileList,FileStruct,DMA,
LoginDisk,MakeFileList,DumpFileList;
CONST
DMABufferSize = 128;
TYPE
FileStruct = RECORD
CASE BOOLEAN OF
TRUE: Disk: CHAR;
Fill1: CHAR;
Name: ARRAY [0..7] OF CHAR;
Fill2: CHAR;
Extention: ARRAY [0..2] OF CHAR;
| FALSE: Text: ARRAY [0..13] OF CHAR;
END;
END;
pFileList = POINTER TO FileList;
FileList = RECORD
File: FileStruct;
Next: pFileList;
END;
DMA = ARRAY [0..DMABufferSize-1] OF CHAR;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
PROCEDURE MakeFileList(FileMatch: ARRAY OF CHAR): pFileList;
PROCEDURE DumpFileList(pList: pFileList);
END FileSearch.
Imprementation Moduleは、このとおり。
IMPLEMENTATION MODULE FileSearch;
FROM InOut IMPORT Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,SIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,NameState;
FROM BdosStruct IMPORT BdosCommand,BdosReturn,FileStruct,DMA;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
VAR
BdosCmd: BdosCommand;
Junk: WORD;
DiskCode: BdosReturn;
BEGIN
IF FCBBuf.name.disk = 0C THEN
BdosCmd.Func := retCDsk;
Bdos(BdosCmd.Cmd,Junk,DiskCode.Rc);
RETURN (CHR(ORD(DiskCode.Cc)+ORD('A')));
ELSE
RETURN (CHR(ORD(FCBBuf.name.disk)+ORD('A')-1));
END;
END LoginDisk;
PROCEDURE MakeFileList(FileMatch: ARRAY OF CHAR): pFileList;
VAR
Disk: CHAR;
FCBBuffer: FCB;
BdosFunc: BdosCommand;
BdosRc: BdosReturn;
DMABuffer: DMA;
ToPos, FromPos: CARDINAL;
NameStatus: NameState;
pList: pFileList;
pNewFile: pFileList;
NewFile: FileList;
Junk: WORD;
BEGIN
(* Clear FCB Buffer and set file name *)
FCBBuffer.name.text := '';
FCBBuffer.rest := '';
NameStatus := StrToFCB(FileMatch,FCBBuffer.name);
(* get target disk *)
Disk := LoginDisk(FCBBuffer);
(* set DMA Bufer *)
BdosFunc.Func := setDMA;
Bdos(BdosFunc.Cmd,ADR(DMABuffer),Junk);
(* initialize File Name List pointer *)
pList := NIL;
(* find first much file *)
BdosFunc.Func := searchFst;
Bdos(BdosFunc.Cmd,ADR(FCBBuffer),BdosRc.Rc);
WHILE BdosRc.Cc # 255 DO
(* copy from FCB buffer to file struct *)
ALLOCATE(pNewFile,SIZE(NewFile));
pNewFile^.File.Disk := Disk;
pNewFile^.File.Fill1 := ':';
ToPos := 0;
FOR FromPos := 1 TO 8 DO
pNewFile^.File.Name[ToPos]
:= DMABuffer[FromPos+BdosRc.Cc*32];
INC(ToPos);
END;
pNewFile^.File.Fill2 := '.';
ToPos := 0;
FOR FromPos := 9 TO 11 DO
pNewFile^.File.Extention[ToPos]
:= DMABuffer[FromPos+BdosRc.Cc*32];
INC(ToPos);
END;
(* insert new one *)
pNewFile^.Next := pList;
pList := pNewFile;
(* find next file *)
BdosFunc.Func := searchNxt;
Bdos(BdosFunc.Cmd,Junk,BdosRc.Rc);
END;
RETURN pList
END MakeFileList;
PROCEDURE WriteFileStruc(FileStruc: FileStruct);
BEGIN
Write(FileStruc.Disk);
Write(FileStruc.Fill1);
WriteString(FileStruc.Name);
Write(FileStruc.Fill2);
WriteString(FileStruc.Extention);
WriteLn;
END WriteFileStruc;
PROCEDURE DumpFileList(pList: pFileList);
BEGIN
WHILE pList # NIL DO
WriteFileStruc(pList^.File);
pList := pList^.Next;
END;
END DumpFileList;
END FileSearch.
MakeFileList手続きが処理の中心です。ファイルを探すにはBDOSの機能番号16 最初のデータを探す(SearchFirst)、 機能番号17 次にデータを探す(SearchNext)を使います。 はじめに、FCBとDMAを準備します。そして、FCB領域を初期化します。
(* Clear FCB Buffer and set file name *)
FCBBuffer.name.text := '';
FCBBuffer.rest := '';
NameStatus := StrToFCB(FileMatch,FCBBuffer.name);
ここで躓きました。"FCBBuffer.rest"を初期化をしなかったために、
最初のデータを取得できたりできなかったりと、動作が不安定でした。
アセンブラでテストルーチンを書くとうまく動作します。悩みました。
使用したアセンブラでは、確保したデータ領域を自動的に0を埋め込んでいました。
しかし、Modula-2処理系では領域内の値は不定になるため、動作がおかしくなった様です。
最初のデータを見つけてしまえば、後は順に見つけることができました。
見つけたファイル名をリスト構造にして、返します。
DumpFileList手続きは、ファイル名リストを表示します。下受けルーチンとして、WriteFileStruc手続きを 使っています。
特に難しいロジックはありません。
BdosStructは、Definition Moduleだけです。以下のようになっています。
DEFINITION MODULE BdosStruct;
FROM OpSys IMPORT BdosFunctions;
FROM SYSTEM IMPORT WORD;
EXPORT QUALIFIED
BdosCommand,BdosReturn;2
TYPE
BdosCommand = RECORD
CASE BOOLEAN OF
TRUE: Func: BdosFunctions;
| FALSE: Cmd: WORD;
END;
END;
BdosReturn = RECORD
CASE BOOLEAN OF
TRUE: Rc: WORD;
| FALSE: Cc: CARDINAL;
END;
END;
END BdosStruct.
次回は、これを応用したファイルマッチで指定されたファイルをリストするコマンド"FileFind"紹介します。
TIのTL497を使ったStep-Down コンバーターの制作 ― 2024年04月21日 09:10
自作のボードコンピュター用に、出力16VのACアダプターをTA7805で5Vに落とした電源器を使っていました。 とても発熱がとてもひどいので、対策を考えていました。今回は、TIのスイッチングレギュレータ用IC TL497を使ったStep-Downコンバーターを 使って、発熱の少ない電源を作ってみました。
TL497をStep-Downコンバータとして使うのは、初めてなので3タイプを制作してみました。
- TL497単体で制作した、12V入力で5V/0.5A出力の電源
- 上の回路に外付けトランジスタを追加して出力電流を多くした電源
- 更に、入力電源電圧を16V用にした電源。TL497の最大電源電圧は15Vなのでひと工夫が必要です。
まずは、TL497単体で制作した電源です。回路図と外観はこのとおり。
(手持ちのパーツを使用したため、一部に大げさな規格のパーツを使用しています。)
回路はデータシートどおりです。
外付けトランジスタを追加して出力電流を増やしました。これで、1Aまで取れます。
15V以上の入力電圧に対応できるようにしたのが、これです。入力電圧を78L12で受けてTL497の電源にしています。
実際に長時間連続で使用しても発熱は少なくなり、当初の目的を達成できました。
ヴィルト先生 ― 2024年01月06日 13:10
チューリッヒ連邦工科大学のOberonチームから、悲しい知らせが届きました。Pascal, Modulaといった プログラミング言語を世に送り出し、更にOberonという言語で記述したテキスト指向のオペレーティングシステムの開発者でもある ニクラウス ヴィルト先生が、なくなりました。
私が、ヴィルト先生のことを知ったのは、学生時代に参加したPascalの勉強会ででした。使用したテキストが、 ヴィルト先生らが書いた「Pascal(原題 Pascal User Manual and Report)」でした。この勉強会を通じて、Fortranとは違う プログラミング・パラダイムを知り、構造化されたプログラミングスタイルを身につけることができました。 このことは、仕事についてから、Cでのプログラム開発に、大いに役立ちました。 また、その後の、仕事においても、趣味においてでも、Pascalは重要な位置を締めてきました。
ヴィルト先生の著作を もう2冊持っています。「アルゴリズム+データ構造=プログラム(原題 ALGORITHMS+DATA STRUCTURES=PROGRAM)」と「アルゴリズムとデータ構造(原題 ALGORITHMS & DATA STRUCTURES)」です。この2冊は 兄弟になる著作でしょう。前者は、Pascalで、後者はModula-2でアルゴリズムの選択やそれに適したデータ構造の構築について 議論がなされています。これら3冊は、私にとってバイブル的存在であり、すぐに手に取れるところにおいています。
私がプログラマーとして成長するのに、大きな影響を受けたヴィルト先生のご冥福をお祈りましす。

最近のコメント