ノリタケ伊勢電子のVFDモジュールに PowerShell からビットマップファイルを表示してみたテスト

function initializeVfd
{
    $a = [byte]0x1b, [byte]0x40
    $serialPort.write($a, 0 ,$a.Length)
}

function clearVfd
{
    $serialPort.write( [char]0x0c )
}

function displayCursorVfd
{
    $a = [byte]0x1f, [byte]0x43, [byte]1
    $serialPort.write($a,0,$a.Length)
}

function moveCursorVfd([int]$x, [int]$y)
{
    $a = [byte]0x1f, [byte]0x24, [byte]5, [byte]0, [byte]1, [byte]0
    $serialPort.write($a,0,$a.Length)

}

function drawBitmapVfd
{
    $a = [byte]0x1f, [byte]0x28, [byte]0x66, [byte]0x11, [byte]128, [byte]0, [byte]8, [byte]0, [byte]1
    $a.Length
    $serialPort.Write($a, 0, $a.Length)
    $serialPort.write($vfdimg, 0, $vfdimg.Length)
}

$serialPort = New-Object System.IO.Ports.SerialPort "COM1", 38400
$serialPort.Open()
initializeVfd
clearVfd
displayCursorVfd
#moveCursorVfd
$img = [System.Drawing.Image]::FromFile("D:\mkusunoki\Documents\i-tron128X64.bmp")
$vfdimg = New-Object byte[] ($img.Width * $img.Height / 8)
for($i = 0; $i -lt $img.Width; $i++)
{
    for($j = 0; $j -lt ($img.Height / 8); $j++)
    {
        $bb = 0
        if($img.GetPixel($i, $j * 8).G -gt 127)
        {
            $bb = 1
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 1).G -gt 127)
        {
            $bb++
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 2).G -gt 127)
        {
            $bb++
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 3).G -gt 127)
        {
            $bb++
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 4).G -gt 127)
        {
            $bb++
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 5).G -gt 127)
        {
            $bb++
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 6).G -gt 127)
        {
            $bb++
        }
        $bb += $bb
        if($img.GetPixel($i, $j * 8 + 7).G -gt 127)
        {
            $bb++
        }
        $vfdimg[$i * ($img.Height / 8) + $j] = $bb
    }
}
drawBitmapVfd
# $serialPort.Write("HHHHH")
$serialPort.Close()
$serialPort.Dispose()

ということで、128×64ドットのディスプレイになんか表示しましょうということです。とりあえず、付属のCDROM に入っていたサンプルに i-tron128X64.bmp というビットマップファイルがあったのでこれを表示させてみることにしました。

今回は Windows の PowerShell というやつを使いまして、ビットマップファイルをロードして、シリアルポートに投げるというものです。まだ試行錯誤中のアプリケーションノートからロジック丸パクしたソースは以下に掲載します。あとは、ビットマップオジェクトをいじれば漢字だろうが何だろうが描画出来るので少しだけ前に進んだかな?

PowerShell の勉強

正直よくわかっていませんがちょっと使ってみようということで、簡単なスクリプトが書ける程度にはなっておきましょうというやつですね。

Windows PowerShell は Windows7 には標準で入っているようです。またそれ以前のOSでは、Windows update か、Microsoft の Webサイトからダウンロード可能なようです。

PowerShell の基本的な書き方を理解しないといけません。あとは、.NETFramework などのオジェクトを使うのでこっちは、MSDN にあるクラス名とかのリファレンス見れば大体のところはいけるでしょうというやつです。

まずは、シリアルポート一覧を取得

PS > $serialPorts = [System.IO.Ports.SerialPort]::GetPortNames();

のように書けば、実行出来ました。これはスタティックなメソッドだから実行出来たような気がする。

java で言う new するのは

PS > $port = New-Object System.IO.Ports.SerialPort("COM1");

そうすることで、インスタンスが作成されたと理解していいのかな?

PS > $port.BaudRate
9600

のように返ってくるのでオブジェクトは生成されたと思う。
となれば、あとは .net framework の話なのでこれは一旦おわり。

PowerShell の制御構造(if 文とかそういうやつ) をこされから探してみたいと思います。

PowerShell のヘルプは、get-help コマンドらしい
また、UNIX 系の OS さわってた人向けなのかどうかは置いといて、Alias で UNIX のコマンド名も用意されていました。なので、 ls コマンドと叩けばGet-ChildItemというコマンレットが実行されるようになってます。
何があるのか調べるのは

PS > Get-Command

を実行すれば調べられます。

Windows PoerShell ISE のヘルプも入門に必要なことが書いてありましたので、こちらも参照

Windows PowerShell のスクリプトは拡張子 .ps1 とからしいですが、初期状態ではスクリプトファイルをダブルクリックしても起動しないようです。get-executionpolicy というので現在の設定の確認や実行時のポリシーを変更出来るようです。またスクリプトの実行にはc:\script\script.ps1 のようにフルパスか、.\zzz.ps1 のようにパス必要とのことです。パス通っていてもスクリプト名だけでは走らせられないようです。

PS > Get-ExecutionPolicy
Restricted

WINDOWS POWERSHELL 実行ポリシー
-------------------------------

Windows PowerShell の実行ポリシーを次に示します。

既定のポリシーは "Restricted" です。

Restricted
- 既定の実行ポリシーです。

- 個々のコマンドは許可されますが、スクリプトは実行されません。

- 書式設定ファイルと構成ファイル (.ps1xml)、モジュール スクリプト ファイル
(.psm1)、および Windows PowerShell プロファイル (.ps1) を含む、すべてのスクリプト
ファイルの実行が禁止されます。

AllSigned
- スクリプトを実行できます。

- すべてのスクリプトと構成ファイルが信頼された発行元によって署名されていることが
要求されます (ユーザーがローカル コンピューターで作成するスクリプトを含む)。

- 信頼されているかどうかが分類されていない発行元からのスクリプトを実行する前に、プ
ロンプトが表示されます。

- インターネット以外のソースによる署名なしスクリプトや署名済みの悪意のあるスクリ
プトを実行する危険性があります。

RemoteSigned
- スクリプトを実行できます。

- インターネットからダウンロードされたスクリプトおよび構成ファイル (電子メール プ
ログラムとインスタント メッセージング プログラムを含む) に対して、信頼された発行元
によるデジタル署名が必要です。

- (インターネットからダウンロードしたのではなく) ローカル コンピューターで実行され
たスクリプトおよび作成されたスクリプトにはデジタル署名は不要です。

- 署名済みの悪意のあるスクリプトを実行する危険性があります。

Unrestricted
- 署名なしスクリプトを実行できます (悪意のあるスクリプトを実行する危険性があります)。

- インターネットからダウンロードしたスクリプトおよび構成ファイルを実行する前にユ
ーザーに警告します。

Bypass
- 何もブロックされず、警告またはプロンプトも表示されません。

- この実行ポリシーは、Windows PowerShell スクリプトが大きいアプリケーションに組み
込まれる構成や、独自のセキュリティ モデルを備えたプログラムの基礎として Windows
PowerShell が使用される構成を対象に設計されています。

Undefined
- 現在のスコープで設定されている実行ポリシーはありません。

- すべてのスコープの実行ポリシーが Undefined である場合、効力を持つ実行ポリシーは
既定の実行ポリシーである Restricted となります。

ということで、ローカルでスクリプト実行するなら

PS > Set-ExecutionPolicy RemoteSigned

これは一回やっておけば、レジストリに記録されるので都度実行しなくても良いようです。

いずれにしても、ヘルプのWindows PowerShell の About ヘルプ トピックには基本的な制御構造などのサンプルがあるので一旦は見ておく。

変数のスコープはわかりません。Get-Variable -scope global もしくは local で表示されますが、まだ理解出来てません。

Windows PowerShell から .NetFramework のオブジェクトとかを使うときに、標準でロードされていないものはロードしないといけません。しかし、何がロードされてるかを調べる方法は

PS > [Appdomain]::CurrentDomain.GetAssemblies() | %{$_.GetName().Name}

mscorlib
Microsoft.PowerShell.ConsoleHost
System
System.Management.Automation
Microsoft.PowerShell.Commands.Diagnostics
System.Core
System.Configuration.Install
Microsoft.WSMan.Management
System.Transactions
Microsoft.PowerShell.Commands.Utility
Microsoft.PowerShell.Commands.Management
Microsoft.PowerShell.Security
Microsoft.PowerShell.ConsoleHost.resources
System.Management
System.DirectoryServices
System.Xml
System.Management.Automation.resources
Microsoft.WSMan.Management.resources
Microsoft.PowerShell.Security.resources
System.Data
mscorlib.resources

のように、確認出来るようです。

で、

PS> [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")


GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll

というふうに、 .NetFramework のロードしたいものを指定すると使用出来るようになる

どこぞのページから拾ってきたスクリプトサンプル。ビットマップイメージにテキストを描画してファイル出力するサンプル。これと blog の記事で書いたノリタケVFDモジュールへの出力を組合せれば、好きなフォントで文字表示出来るようになります。ただし、VFDモジュールの横幅が短いのでスクロールをどうするかか工夫しないと。ピクセルは $bmp.GetPixcel(x,y).G とかで緑とかが取得出来ます。

[PowerShell]
Add-Type -AssemblyName System.Drawing
$outFile = “$home\outimage.png”
$bmp = new-object System.Drawing.Bitmap 512,16
$font = new-object System.Drawing.Font “MS ゴシック”,9
$brushBg = [System.Drawing.Brushes]::Black
$brushFg = [System.Drawing.Brushes]::White
$graphics = [System.Drawing.Graphics]::FromImage($bmp)
$graphics.FillRectangle($brushBg,0,0,$bmp.Width,$bmp.Height)
$graphics.DrawString(‘Hello World 漢字ファイル’,$font,$brushFg,0,0)
$bmp.Save($outFile)
#Invoke-Item $outFile
$graphics.Dispose()
[/PowerShell]