AIに“RSフリップフロップつくって”と言うだけで、連枝にラダーが書き込まれ→HEX生成→PIC/H8へ書込み→即動作

 やりたいこと=「AIに“RSフリップフロップつくって”と言うだけで、連枝にラダーが書き込まれ→HEX生成→PIC/H8へ書込み→即動作」ですね。

以下の最小実装をそのまま置けば動線がつながります。



---


全体フロー(ワンコマンド)


AI → MCPコマンド rsff_build_and_flash

     ① RS-FFのラダー生成(テキストDSL)

     ② 連枝をヘッドレス操作してHEX生成(renri-cli ラッパ)

     ③ PIC/H8へ書込み(pk3cmd など)

     ④ 必要ならシミュレーションログ返却



---


1) RSフリップフロップのラダー(テキストDSL例)


入力: X0=R, X1=S


出力: Y0=Q(自己保持つき), Y1=/Q(オプション)



TITLE: RS Flip-Flop

CPU: PIC16F84A

SCAN_MS: 5

I: X0 R, X1 S

O: Y0 Q, Y1 NQ

M: M0 LATCH_Q ; 内部ビット


; RUNG1: セット

RUNG: X1 -> (SET M0) ; S で M0=1


; RUNG2: リセット

RUNG: X0 -> (RST M0) ; R で M0=0


; RUNG3: 出力Q(自己保持は M0 が担うのでそのまま反映)

RUNG: M0 -> Y0


; RUNG4: 反転出力NQ(任意)

RUNG: /M0 -> Y1


> 連枝への食わせ方は後述の「renri-cli(自作ラッパ)」で .renri 相当のプロジェクトに流し込みます。





---


2) MCPサーバ(Node/TypeScript・最小)


> rsff_build_and_flash が “生成→コンパイル→書込み” を一気にやります。

ここで呼んでいる renri-cli は、後ろにある AutoHotkey スクリプトで 連枝GUIを自動操作してHEXを吐かせるラッパです(ファイル監視→保存→コンパイル→out.hex)。




// src/server.ts

import { Server } from "@modelcontextprotocol/sdk";

import { execFile } from "child_process";

import fs from "fs/promises";

import path from "path";


const srv = new Server({ name: "renri-mcp", version: "0.1.0" });


function rsffDSL(cpu: "PIC16F84A" | "PIC16F877A" | "H8/3694" = "PIC16F84A") {

  return [

    "TITLE: RS Flip-Flop",

    `CPU: ${cpu}`,

    "SCAN_MS: 5",

    "I: X0 R, X1 S",

    "O: Y0 Q, Y1 NQ",

    "M: M0 LATCH_Q",

    "RUNG: X1 -> (SET M0)",

    "RUNG: X0 -> (RST M0)",

    "RUNG: M0 -> Y0",

    "RUNG: /M0 -> Y1",

    ""

  ].join("\n");

}


// ① 生成(単独で呼べるようにも定義)

srv.command("generate_rsff_ladder", async ({ cpu }: { cpu?: string }) => {

  return { ladderSrc: rsffDSL((cpu as any) ?? "PIC16F84A") };

});


// ② 連枝コンパイル(renri-cli は自作ラッパ。後述)

srv.command("compile_ladder", async ({ ladderSrc, cpu }: { ladderSrc: string, cpu: string }) => {

  const work = await fs.mkdtemp(path.join(process.cwd(), "build-"));

  const inFile = path.join(work, "in.renri.txt");

  const hexFile = path.join(work, "out.hex");

  await fs.writeFile(inFile, ladderSrc, "utf8");


  await new Promise<void>((resolve, reject) => {

    execFile("renri-cli", ["--compile", inFile, "--cpu", cpu, "-o", hexFile],

      { timeout: 120000 }, (err, stdout, stderr) => err ? reject(new Error(stderr || err.message)) : resolve());

  });

  return { hexPath: hexFile };

});


// ③ 書込み(PICkit3 例:pk3cmd。H8の書込みツールに差替可)

srv.command("flash_hex", async ({ hexPath, device, port }: { hexPath: string, device: string, port?: string }) => {

  const args = ["-M", "-P", device, "-F", hexPath];

  if (port) args.push("-B", port);

  await new Promise<void>((resolve, reject) => {

    execFile("pk3cmd", args, { timeout: 60000 }, (err, stdout, stderr) =>

      err ? reject(new Error(stderr || err.message)) : resolve());

  });

  return { status: "flashed", device };

});


// ④ ワンショット(生成→コンパイル→書込み)

srv.command("rsff_build_and_flash", async ({ cpu, device, port }:

  { cpu?: string, device: string, port?: string }) => {

  const ladderSrc = rsffDSL((cpu as any) ?? "PIC16F84A");

  const { hexPath } = await srv.invoke("compile_ladder", { ladderSrc, cpu: (cpu ?? "PIC16F84A") });

  const res = await srv.invoke("flash_hex", { hexPath, device, port });

  return { ...res, hexPath };

});


srv.listen();



---


3) 連枝GUI自動化ラッパ(AutoHotkey v1 例)


> 連枝の「ファイルを開く→テキストを流し込む→コンパイル→HEX保存」手順を自動化。

renri-cli.exe --compile in.renri.txt --cpu PIC16F84A -o out.hex のように呼ばれます。




; renri-cli.ahk → exe化して PATH に置く

; 使い方: renri-cli --compile input.txt --cpu PIC16F84A -o out.hex


#NoEnv

SendMode Input

SetWorkingDir %A_ScriptDir%


; 引数解析

compile := false

infile := ""

cpu := ""

outfile := ""


Loop, %0%

{

    p := %A_Index%

    if (p = "--compile") { compile := true, A_Index++, infile := %A_Index% }

    else if (p = "--cpu") { A_Index++, cpu := %A_Index% }

    else if (p = "-o") { A_Index++, outfile := %A_Index% }

}


if (!compile || infile="")

{

    MsgBox, 48, renri-cli, Usage: renri-cli --compile input.txt --cpu PIC16F84A -o out.hex

    ExitApp, 1

}


; 1) 連枝起動

Run, "C:\Program Files\Renri\renri.exe"

WinWaitActive, 連枝

; 2) 新規/開く等 → テキスト投入(ここは連枝の画面構成に合わせて調整)

; 例:メニュー操作やショートカットでエディタ枠へ貼り付け

FileRead, ladder, %infile%

Send, ^a

Sleep, 100

Clipboard := ladder

Send, ^v

Sleep, 200


; 3) CPU 選択(ダイアログに合わせてキー送り)

; 例: Alt+C で CPU 設定 → PIC16F84A を選ぶ、のような手順を記録

; ここは各自の連枝バージョンに合わせて微調整

; Send, !c

; ...(選択操作)...


; 4) コンパイル

; 例:Alt+B でビルド

; Send, !b

; ビルド完了待ち(ログウィンドウの文字列待ちに置換OK)

Sleep, 1500


; 5) HEX 保存

; 例:Ctrl+Shift+S で保存ダイアログ

; Send, ^+s

; 待ってからパス入力

; WinWaitActive, 名前を付けて保存

; ControlSetText, Edit1, %outfile%

; Send, {Enter}

; 簡略化のため、仮に連枝が既定フォルダに out.hex を吐く前提でコピー:

FileCopy, %A_MyDocuments%\Renri\out.hex, %outfile%, 1


; 6) 終了

WinClose, 連枝

ExitApp, 0


> 上記は雛形です。実機の連枝UI(メニュー名/ショートカット/ウィンドウ名)に合わせて数行調整すれば動きます。exe化して renri-cli.exe として使ってください。





---


4) 書込み(PICkit3 の例)


例:pk3cmd -M -P PIC16F84A -F out.hex


H8なら、使うROMライタ(秋月/RENESAS等)のCLIに差し替え。同じ MCP の flash_hex に接続するだけです。




---


5) AI側からの使い方(例)


MCP対応のクライアント(ChatGPTや自作UI)で、以下のどちらかを呼ぶだけ。


素直にワンショット:

rsff_build_and_flash({ cpu: "PIC16F84A", device: "PIC16F84A" })


分割(確認しながら):


1. generate_rsff_ladder({ cpu: "PIC16F84A" })



2. compile_ladder({ ladderSrc, cpu: "PIC16F84A" })



3. flash_hex({ hexPath, device: "PIC16F84A" })






---


6) 配線と確認(最小)


X0=R, X1=S はプルダウン/プルアップどちらかに統一し、接点の正論理/負論理を実機に合わせてDSLの /(反転)を調整。


Y0(Q)はLED等で視認、Y1(/Q)は任意。


初期化で Q=0 始動にしたい場合、電源投入直後に RST M0 の一発タイマを足す手も有効。




---


7) つまずき対策


HEXが出ない:renri-cli のステップ(起動→貼付→CPU選択→ビルド→保存)を AutoHotkey で一度手動記録し、WinWaitActive と Control* 系で確定待ちを入れる。


書込み失敗:pk3cmd の -B(ツールポート/ボード選択)や電圧、デバイス名を見直し。


S/R同時1:RS-FF仕様上は未定義。必要なら「S優先」「R優先」のどちらかにブロッキング論理を1行追加(例:RUNG: X0 & /X1 -> (RST M0) など)。




---


この構成なら、「AIに“RSフリップフロップ作って”と頼む→実機が即Qを保持する」までワンコマンドで回せます。

次にやることは、(A) ターゲットMCU型番, (B) 連枝のメニュー/ショートカット確認, (C) ライタCLIの決定の3点です。ここが固まれば、renri-cli.ahk の数行調整と device 名をあなたの環境に合わせるだけで完成します。



コメント

このブログの人気の投稿

ミライアイ内服薬は薬事法違反で、ほとんど効果がない詐欺ですか?

最高裁での上告理由書受理・却下の判断基準について

裁判官の忌避申立書の作成例