2012年9月19日水曜日

オーディオ信号処理で学ぶDSP


堀江誠一さんのお書きになったInterfaceの記事についてバックナンバーを調べました。

現在、BlueTank BF592を使ったごにょごにょ信号処理をしているのですが、知りたかったあれやこれやがこの連載に満載になっていました。

Jan. 2007 第1回:DSPでループバックとカラオケを作ろう
Feb. 2007 第2回:FIRフィルタを使ってみよう
Mar. 2007 第3回:高速なIIRフィルタの解説と実装
Apr. 2007 第4回:Blackfinの周辺機能制御と割り込み
July 2007 第5回:I2CポートでA-Dコンバータを制御する
Sept. 2007 第6回:エフェクタを作ってみる(あふれと飽和)
Oct. 2007 第7回:Sin波を作る(テーブル参照のテクニック)
Dec. 2007 第8回:複素信号処理
Feb. 2008 第9回:DSPでソフトウェア無線を実現する(複素信号処理に基づいたSDRの作成)

DSPを使った信号処理に興味のある人は必見です。
Interface誌のバックナンバーはこちらからどうぞ。

2012年9月17日月曜日

KOZOS拡張基板KOZOS EXPBRDを使ったミュージック・プレイヤー

いよいよ2012年9月29日に「茶室で楽しむKOZOS拡張基板」を開催します。

例えばどんな事ができる拡張基板なのかイメージが掴んで頂く為に、応用例としてミュージック・プレイヤーを仕立ててみました。



アプリケーションはブートローダ経由でDRAM上に展開してブートしています。
SDカードからブートできるのでパソコンなしでKOZOSの実行が可能!

ブートローダもアプリケーションもソースコードを公開しますので御安心下さい。
どんどん改造して自分好みに仕立て上げる事ができます。

既に定員に達している本企画ですが、見学も大歓迎です。
http://atnd.org/events/30481で見学希望の旨を書いて登録して下さい。

2012年9月15日土曜日

テキストLCDをグラフィックLCDのように扱うギミック ~テキストLCDでもここまでできる!~

今回はちょっとお遊び休憩ネタです。

Analog Devices社Blackfin BF592搭載オーディオ・プラットフォームBlueTank BF592を使ったお遊び。
まずは動作をご覧下さい。



上記で使用しているテキストLCDは2行8文字の表示が可能なLCDです。

殆どのテキストLCDにはHD44780互換のLCDコントローラが搭載されています。
ユーザ登録可能な文字は8つあります。

しかし、普通に考えるとユーザ登録文字を使って全画面を一度に表示する事はできません。
なぜなら2行x8文字で、16文字のユーザ登録文字が必要になるからです。

では「どうしているのか?」というと簡単で、時分割で細かく切り替えて表示を行なっています。
以下にステップ毎の動作の様子を示します。

1文字目は普通に考えてもいけます。


もちろん2文字目も。


3文字。


4文字。


5文字。


6文字。


7文字。


8文字。

ここで、ユーザ登録文字の8文字を使い切りました。
まだ画面の半分しか描画できていません。


で、どうするのかというと・・・。

新たに描画の必要がある領域のために一番最初に書いた文字を消します。
これなら使っているユーザ登録文字は依然として8文字です。


同様にして。


どんどん上側を消して下側を書きます。


どんどん上側を消して下側を書きます。


どんどん上側を消して下側を書きます。


どんどん上側を消して下側を書きます。


どんどん上側を消して下側を書きます。


これで下側の画面描画が完了しました。


上記を非常に細かい時間で繰り返すと以下のように見えるというのが今回のギミック。
まぁ、飛び越し走査とは違いますが、あえて言うならば「なんちゃってインターレース」でしょうか?


実はこのデモ、48KHzステレオオーディオの処理をしながらの動作です。
先日のFFTスペアナと合わせればもっと楽しい見た目を提供できそう。

動作を見ると実装は複雑なんじゃないか?と思うかもしれません。
でも、きちんと設計すればそんな事はありません。

以下のような定義でざざっと絵を作れるようにしました。


で、実際の描画は下層のglcdモジュールにお任せという具合です。

glcd_clear(&(w->glcd));
for (px = 0; px < GLCD_PX; px++) {
  for (py = 0; py < GLCD_PY; py++) {
    glcd_set_pixel(&(w->glcd), px, py, (img1[py][px + (VOL_MAX - w->volume)] == 'o') ? 1 : 0);
  }
}

gcld_blitを呼ぶと、内部でうまい具合に1シーケンス分の処理をしてくれるという設計です。

glcd_blit(&w->glcd);

上記の画像は「リアルなLCD画像ファイルが得られるLCD Toolの改良」で取り上げたlcdtoolを使って生成しました。
LCDプロファイルとLCDフォントに少し手を入れるだけで好みの出力が得られます。
BMP画像ファイルの生成はスクリプトで一発自動生成。
#!/bin/sh
LCDTOOL=lcdtool
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq01.bmp '\x00' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq02.bmp '\x00\x02' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq03.bmp '\x00\x02\x04' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq04.bmp '\x00\x02\x04\x06' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq05.bmp '\x00\x02\x04\x06\x08' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq06.bmp '\x00\x02\x04\x06\x08\x0A' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq07.bmp '\x00\x02\x04\x06\x08\x0A\x0C' '        '
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq08.bmp '\x00\x02\x04\x06\x08\x0A\x0C\x0E' '        '

$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq09.bmp ' \x02\x04\x06\x08\x0A\x0C\x0E' '\x01'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq10.bmp '  \x04\x06\x08\x0A\x0C\x0E' '\x01\x03'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq11.bmp '   \x06\x08\x0A\x0C\x0E' '\x01\x03\x05'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq12.bmp '    \x08\x0A\x0C\x0E' '\x01\x03\x05\x07'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq13.bmp '     \x0A\x0C\x0E' '\x01\x03\x05\x07\x09'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq14.bmp '      \x0C\x0E' '\x01\x03\x05\x07\x09\x0B'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq15.bmp '       \x0E' '\x01\x03\x05\x07\x09\x0B\x0D'
$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont seq16.bmp '        ' '\x01\x03\x05\x07\x09\x0B\x0D\x0F'

$LCDTOOL  bluetank.lcdprof glcd_demo.lcdfont view.bmp '\x00\x02\x04\x06\x08\x0A\x0C\x0E' '\x01\x03\x05\x07\x09\x0B\x0D\x0F'
自動化してあるので、画面数が多くても操作が苦になる事はありません。
また、出力が間違っていても、スクリプトさえ残しておけば後で何度も修正する事ができます。

2012年9月13日木曜日

BlueTank BF592 FFT Graphical Spectrum Analyzer

Analog Devices社Blackfin BF592搭載オーディオ・プラットフォームBlueTank BF592を使ったグラフィカル・スペクトラム・アナライザーです。



2x8文字のLCDですが、都合の良い事に8文字のユーザ・フォントを登録する事ができます。
1文字1バンドで考えてしまうと8バンドしか表示できません。

でも、1ピクセル1バンドとして考えると5ドットx8文字で最大40バンドの表示が可能になります。
この基板設計時に考えた事をようやく実現する事ができました。
8文字表示のLCDを選択したのは、単に「コンパクトだから」というわけではなかったのです。

今回のサンプリング周波数は48,000[Hz]でFFT計算サイズは64です。
なので周波数軸での分解能は750[Hz]という事になります。

750[Hz]の分解能で40バンドまで表示できる事を考えると、ナイキスト周波数の範囲まで十分に表示できる事がわかります。
FFT計算サイズの内部定義を一行書きかえるだけで、表示側も連動するように実装しました。
折り返し成分を表示しないようなガードも入れてあります。

BlueTank BF592に対するオーディオ・フレームワークの実装もかなり進みました。
上記のコードはフレームワーク層のコードを除くとコメントを含んで約300行の実装で済みます。
(コメントが何行なんだ!)

アプリケーション共通の処理は全てオーディオ・フレームワーク側に隠ぺいしました。
main.cみたいな小さなアプリケーションの実装のみで上記のような処理を実現する事ができます。

ちなみに、上記のアプリケーションは天ノ岩戸のmayaさんが実装したFFTアナライザを改造して作りました。この場を借りてお礼申し上げます。

そして、オーディオ・フレームワークについてはDSP空挺団の酔漢さんの作られたUZUMEにかなり影響を受けています。最初はUZUMEのミニマム・プラットフォームとしてBlueTank BF592を仕立てる計画でしたが、似ても似つかない物になってしまったのでもじってUZURAというフレームワーク名を付けました。変なフレームワークで本家や市場に混乱や迷惑をかけない措置です。

ちょっと借り物競走みたいなプロジェクトになってきましたが、まだまだBlueTank BF592遊びは続けようと考えています。

2012年9月8日土曜日

Natural Tiny Basic (NT-Basic) ~WindowsでもLinuxでもMac OSでも組み込み機器でも楽しめるBASICインタプリタ~

まつもとゆきひろさんから得た刺激

先日のSWEST14でまつもとゆきひろさんの講演を聞いてからというものの、言語処理系にとても興味が湧いてきました。

何から手を付けて良いかわからなかったので、手始めに既存のBASICインタプリタに手を入れるところから始めました。
オーディオプラットフォームであるBlueTank BF592で動作させた時の様子が以下の動画です。

 

NT-Basicのアプリケーションコード

NT-Basicを使用するアプリケーションコードは至ってシンプルです。

ntbasic_ ntbasic;
ntbasic_execute(&ntbasic, your_program);

上記のようにntbasicハンドラとプログラム文字列をntbasic_execute関数に渡してあげるだけです。
先ほどの動画の動作は以下のコードから実現しています。

#include "ntbasic.h"
#include "uart.h"
#include "lcd.h"
#include "bfin_util.h"

int main(void)
{
  ntbasic_t ntbasic;
  char *prog1 =
    "100 FOR I = 1 TO 8\n" \
    "110 C = 65 + I - 1\n" \
    "120 WRITE 1, C\n" \
    "130 NEXT\n" \
    "140 END\n";
  char *prog2 =
    "100 FOR I = 1 TO 8\n" \
    "110 C = 97 + I - 1\n" \
    "120 WRITE 1, C\n" \
    "130 NEXT\n" \
    "140 END\n";

  uart_init();
  lcd_init();

  while (1) {
    /*
     * プログラム1を実行する。
     */
    lcd_goto(0, 0);
    ntbasic_execute(&ntbasic, prog1);
    bfin_util_usleep(1000000);

    /*
     * プログラム1で書いた表示を消去する。
     */
    lcd_clear();
    bfin_util_usleep(1000000);

    /*
     * プログラム2を実行する。
     */
    lcd_goto(0, 1);
    ntbasic_execute(&ntbasic, prog2);
    bfin_util_usleep(1000000);

    /*
     * プログラム2で書いた表示を消去する。
     */
    lcd_clear();
    bfin_util_usleep(1000000);
  }

  return 0;
}

今回のターゲットは組み込み装置でしたが、実際にLinuxやWindowsやMac OSでもビルドできるようにしました。

なので、「パソコン上でインタプリタ側のプログラムを動作確認」して「実機で動作」という流れでインタプリタを楽しむ事ができます。

「いつでもどこでもインタプリタ」がキーワードです。

組み込み装置で使うためのHAL構造

この手のソフトウェアで重要なのは構造です。
I/Oは最下層のHAL(Hardware Abstract Layer)が実行するようにしてあります。



インタプリタ上のプログラムは、ハードウェア抽象化層を介し、実際のデバイスを制御します。
ターゲット依存部は単に小さなハードウェア抽象化層に対する実装を加えるのみで済みます。

int hal_getc(void);
int hal_putc(int c);
int hal_read(const int port, int *data);
int hal_write(const int port, const int data);
int hal_halt(void);

hal_getc(void)とhal_putc(int c)は標準入出力系を担います。
ポート番号を指定してデータをI/Oするのが、hal_read(const int port, int *data)とhal_write(const int port, const int data)です。

先ほどお見せした動画は、このHALの層で「ポート番号1に対する出力はLCD」という実装を追加したわけです。

int hal_write(const int port, const int data)
{
  switch (port) {
    case 0:
      /*
       * Port 0 is UART in this port.
       */
      hal_putc(data);
      return 0;
    case 1:
      /*
       * Port 1 is LCD in this port.
       */
      lcd_putc((char)data);
      return 0;
  }
  return -1;
}

実際に動作させてみると結構楽しいおもちゃです。
「茶室で楽しむKOZOS拡張基板」のように何か一つ企画をやりたいなぁと考えています。

リソース

ソースコードは以下からダウンロードできます。

2012年9月1日土曜日

SWEST14参加報告

勢い余って参加申し込みしておいたSWESTですが、あっという間に過ぎ去っていきました。
下呂までは長い道のりでしたが、コードを書いていたらあっという間です。


参加者数は200名弱でしょうか。
水明館はなかなか素敵な宿でした。


初参加という事もあって意味もわからず出したので、ちょっと場違いな感じもします。
次回以降、参加するなら再考したいです。


ポスターはズームランドさんに印刷を頼みました。
これはなかなか良かったかも。印刷内容はともかく。


今回は金子システムさんのところのDSP基板を搭載したBlueTankでNT-Loggerを、LPCXpressoを使った基板でNT-Shellのデモでお届けしました。

今回のDSP基板、とても気に入ったのでちょこっと宣伝もさせて頂きました。


NT-Loggerのデモでは、リアルタイム性を維持しながらシステムのロギングを実行する様子を展示しました。48KHzステレオサンプリングの音声を処理しながらロギングしてシステムの挙動を観察できます。


NT-Shellのデモは、「適当に作ったシェル」と「NT-Shell」による動作の違いを示し、適当に作ると何が問題なのか、NT-Shellで何を解決したのかを提示しました。


お越しいただいた皆様ありがとうございました。
様々な方と色々な意見交換ができてとても有用でした。

リアルなLCD画像ファイルが得られるLCD Toolの改良

先日からの改良点

先日適当に作ったLCD Toolですが、なかなか便利に使えそうなので本格的に便利になるように改良しました。
以下に改良点を示します。

機能改良前改良後
LCD形状プログラムにハードコーディングLCDプロファイルで指定可能
LCD描画色プログラムにハードコーディングLCDプロファイルで指定可能
ドット形状等プログラムにハードコーディングLCDプロファイルで指定可能
ユーザーフォントプログラムにハードコーディングフォントファイルで指定可能
出力画像サイズプログラムにハードコーディングプログラム内部で自動計算
非文字コード指定シェル機能に期待(Windowsでは困難)エスケープ文字による指定が可能
動作プラットフォームLinuxを前提に実装LinuxとWindowsで動作確認済み

適当にプログラムでハードコーディングしていた部分を外部から与えられるようにしました。
LCDプロファイルとフォントデータについては後述します。

入力と出力の関係

以下に入力と出力の関係を示します。


LCDプロファイルとは、LCD形状、LCD描画色、ドットサイズ、キャラクタ間隔などを定義したテキストファイルです。
このテキストファイルを編集する事で手持ちのLCDとそっくりの出力を得ることができるようになります。
ファイルの中身は以下のようになっています。
幾つかのLCDに対するサンプルを完備しています。

#
# SC1602BBWB-XA-GB-G
#
CHCNT_X  =  16  # Character Count (X)
CHCNT_Y  =   2  # Character Count (Y)
CHOFS_X  =  16  # Character Offset (X)
CHOFS_Y  =  16  # Character Offset (Y)
CHGAP_X  =   2  # Character Gap (X)
CHGAP_Y  =   2  # Character Gap (Y)
PIXSIZ_X =   4  # Pixel Size (X)
PIXSIZ_Y =   4  # Pixel Size (Y)
PIXGAP_X =   1  # Pixel Gap (X)
PIXGAP_Y =   1  # Pixel Gap (Y)
FGCOL.R  = 220  # Foreground Color (Red)
FGCOL.G  = 220  # Foreground Color (Green)
FGCOL.B  = 220  # Foreground Color (Blue)
BGCOL.R  = 120  # Background Color (Red)
BGCOL.G  = 120  # Background Color (Green)
BGCOL.B  = 230  # Background Color (Blue)
CONTRAST =  96  # Contrast

初版では「ユーザフォントはプログラム中のデータを書き換えてね」という冷たい仕様でした。
実際にユーザフォントを定義しようとすると結構面倒でした。

新しいバージョンでは、フォントファイルを与えるだけで内部のフォントデータを書き換えてくれます。

###########
CODE = 0x00
###########
.....
.o.o.
ooooo
ooooo
ooooo
.ooo.
..o..
.....

###########
CODE = 0x01
###########
.....
.o.o.
ooooo
ooooo
ooooo
.ooo.
..o..
.....

###########
CODE = 0x08
###########
.....
.o.o.
ooooo
ooooo
ooooo
.ooo.
..o..
.....

###########
CODE = 0x09
###########
.....
.o.o.
ooooo
ooooo
ooooo
.ooo.
..o..
.....

プログラム内部のフォントデータは16進数で記述されています。
点灯させたいドットをイメージしながら16進数を操作させるのは不親切です。

上記のように人間がイメージできる形式で記述すれば済むようにしました。

実行例

以下に実行例を示します。

lcdtool ACM0802C-NLW-BBH.lcdprof UserFontSample.lcdfont test1.bmp "ABCDEFGH" "abcdefgh" 



lcdtool SC1602BBWB-XA-GB-G.lcdprof UserFontSample.lcdfont test2.bmp "ABCDEFGHIJKLMNOP" "abcdefghijklmnop" 



lcdtool SC2004CSLB-XA-LB-G.lcdprof UserFontSample.lcdfont test3.bmp "Line 1: LCD Tool" "Line 2: Sample" "Line 3: LCD Tool" "Line 4: Sample"


上記の実行例を見てわかるように、LCDプロファイルとユーザフォント、出力画像ファイル名、メッセージを与えさえすればBMP画像ファイルが得られます。

LCDプロファイルをどんどんカスタマイズしてVFD版を作ったりしても面白そうです。

ユーザフォントを使った出力の指定方法

ユーザフォントを使った出力の指定は、バックスラッシュを使って指定する事ができます。


例えば、上記のCGRAM(3)を表示させたい場合、「\x02」とコマンドラインに与えます。
「\」を表示させたい場合、 「\\」と入力して下さい。
Linuxの端末で与える場合、シェルに解釈させないためにシングルクォートで囲ってから指定する必要があります。

リソースのダウンロード

本記事執筆段階でのスナップショットをこちらからダウンロードできます。
ドキュメントはこちらからダウンロードできます。

Visual C++ 2010 Expressのプロジェクトファイルも同梱してあります。
Windowsでビルドして使用する事もできます。

追記

2012/09/04追記:v0.0.2にはバグがありました。上記から最新のv0.0.3をダウンロードして下さい。
2012/09/15追記:http://shinta.main.jp/software/lcdtool/lcdtool_ja.htmlに最新版があります。