lynxeyedの電音鍵盤

MBDとFPGAと車載で使うデバイスの備忘録

LPC1115

LPC1115 LPCXpressoを極秘裏に入手

LPC1115というflash容量が64kBに増えたCortex-M0を某所にて入手しました。品名から察しが付くようにLPC1114互換品です。
f:id:Lynx-EyED:20120721234144j:plain
先代のLPCXpressoに載っていたLPC1114F/301と相違点は64kBフラッシュだけではなく、より徹底した低消費電力、インプットキャプチャ・PWMや、UARTの出力ピンが選択可能なところでしょう。

eXodusinoも追ってこのデバイスに対応しようと思います。
これから下半期でeXodusino対応を予定しているるCPU一覧です。

  • LPC1115F/303
  • LPC11U14
  • LPC11U30
  • LPC4330(TFBGA100のみ)


■参考URL
LPC4330:LPCZone:NXP LPCマイコン情報・・LPC4300 - Cortex-M4 & M0 デュアルコア、最速204MHz、最強Cortex-M
LPC4330-Xplorer:NGX Technologies Online Store
LPC1114とLPC1115の比較:http://www.microbuilder.eu/Blog/12-05-06/LPC1114_to_LPC1115_Comparison_QFP48.aspx

秋月I2C液晶をeXodusinoで使う

Cortex-M0 Arduino互換環境 eXodusinoではArduino I2C(Wireクラス)をソフトウェアでエミュレートしています。*1
が、、時々ACKを取りこぼしたりする現象が確認できたので、Wireクラスのデバッグもかねて動作させてみました。

秋月I2C液晶はこれを使ってます↓
http://akizukidenshi.com/catalog/g/gP-05693/
I2C接続キャラクタLCDモジュール[16x2行]白色バックライト付
[ACM1602NI-FLW-FBW-M01]

液晶制御用のソースコード1から書くのがスーパーめんどくさかったので、実績のあるコードを拝借することに。

参考ブログ:
ThinkAboutPCB::ワンチップArduinoで秋月I2C LCDを使う (orion_cosmo さん)
構想100年::秋月のI2C接続キャラクタLCDモジュールACM1602NIをArduinoで使う (まりす さん)
ありがとうございます。
どちらでもArduino向け秋月I2C液晶クラスが手に入ります。

まりすさんはArduino 1.0以降とArduino-0023以前のどちらのクラスにも対応されている上、ご自身のLiquidCrystalクラスを継承されている模様で、使っているインターフェースに関わらずキャラクタ液晶をポータブルに取り扱うことができます。

さて、今回はorion_cosmoさんのAkiI2CLcdクラスを使わせていただきました。
オリジナルとの変更点としては、

  • インクルードファイルをarduino.h から libmary.hに変更した
  • byte型変数をuint8_t型に直した
  • eXodusinoはArduino-0023ベースなのでWire.writeをWire.sendに変更した

これだけで、特に大きな変更は加えませんでした。なお、ライセンスが不明なのでこの変更を加えたAkiI2CLcdクラスを公表することは致しません。orion_cosmo氏のページから頂いてきて各自変更ができると思います。


akiI2Clcd.cpp/.hの各ファイルをeXodusinoプロジェクトに追加し、実機動作させてみます。
なお、eXodusinoでは任意のIOピンをI2Cに利用することができます。ただし、諸事情により1chのみです。(ぉぃ
user_application.cppを以下のように変更します。

#include "libmary.h"
#include <Wire.h>
#include <akiI2Clcd.h>

akiI2Clcd AKI=akiI2Clcd(0x50); //スレーブアドレス指定

void setup()
{
	Wire.begin(2,4); 	// SDA=2番ピン,scl=4番ピンを指定する
	Serial.begin(9600);
	Serial.println("Start!");
	AKI.I2CLCD_init();
	AKI.I2CLCD_clear();
}

void loop()
{
	char a[] = "Hello World!";
	char b[] = "ACM1602NI";
	AKI.I2CLCD_setCursor(0,0);
	AKI.I2CLCD_print(a);
	AKI.I2CLCD_setCursor(0,1);
	AKI.I2CLCD_print(b);
	Serial.println("end");
	for(;;);
}

これを、TeraTermやCuteComをつかってeXodusino本体に書き込むと、、

f:id:Lynx-EyED:20120607210550j:image
はい、ドーーーーーーーーーーーーーン。

おしまい。*2

*1:現状ではI2Cマスタのみ

*2:eXodusinoプロジェクトはこちらからダウンロードできます。 http://github.com/lynxeyed-atsu/eXodusino/

ArduinoインタプリタiArduinoのeXodusinoへの移植(その1)

@nnmtng氏Arduino向けのインタプリタを作っておられることを聞いたので、使ってみた次第です。

iArduinoの本家さまに詳細があります

iArduino: Arduino上で動くインタプリタ言語

自分はAVRマイコンのオリジナルArduinoが手元にないので(ぉぃ)、eXodusinoでも少しの変更で動くのではないかと、移植をしてみたわけです。

変更する部分は以下の部分です

  • 算術関数
    • eXodusinoではコードサイズの肥大化を避けるべく、一部の算術関数の対応をしていません。乱数などは今のところ対応するつもりがないので、return 0にしてしまってます。
  • Arduino1.0特有の記述方法
    • Serial.printlnなど
  • EEPROMクラス
    • LPC1114F/301にはユーザ用EEPROMがありません。したがって、IAPをもちいてプログラムフラッシュ領域に記録するか、外部EEPROMに記録することになると思います。外部EEPROM必須だと、ハード構成に制約をかけてしまうことになります。一方、プログラムフラッシュ領域に記録する方法だと、プログラム領域が減ってしまいます。ここはまだ検討中です。

とりあえず、動くところまで、動かしてみたのが以下のスクリーンショット。先ほどの理由のため、EEPROMからのインタプリタ起動にはまだ対応してません。
f:id:Lynx-EyED:20120424004240p:image


ちゃんと、GPIOの設定もできています。

■なんでインタプリタなのか
統合開発環境として申し分のないLPCXpresso IDEが準備されているものの、これを使うにはEclipseを使った経験がある人でないと、使いづらいという面があると思います。とてもArduinoライクな開発はできません。また、Mac OSXには対応していません。
かといって、Arduino IDEをLPC1114向けに改良するのも時間がかかります。
というわけで、eXodusinoとシリアルコンソールで、限定的でもいいから簡単に開発できればと思っていたところ、このiArduinoを見つけた次第です。

■これから
中間言語を出力させる仕組みを確立し、OSX、Linuxといったデスクトップだけでなく、Android、WP7.5、iPhone用のeXodusino VM出力アプリを用意しようと思います。スマホで「digitalWrite(hoge,ababa)」と打つのは面倒なので、なにかうまい事考えないと。。。

LPC1114のDIPを極秘裏に入手

悪い人がオランダから密輸してきたLPC1114FN28/102がやってきました。
f:id:Lynx-EyED:20120330220546j:image
ES品だそうです。うひょひょ

ピンアサインは以下のとおりです。

f:id:Lynx-EyED:20120401200908p:image
LPC1114F/301と比較すると

  • DIPで28pin
  • SPIが1つになった
  • RAMが4kに減った
  • AVDD,AGNDとアナログ電源が分離できるようになった
  • WAKEUP端子が追加された(通常はプルアップ) すみません、間違いでした。48pinにもWAKEUPあります

が大きな相違点ではないかと思います。Flashは32kと変わりません。

■eXodusinoブートローダの対応
せっかくなので、eXodusinoのブートローダを移植してみました。RAMが4kに減ったものの、リンカスクリプトを修正して移植に成功しました。
ブートローダも含めこちらにアップしました。
http://github.com/lynxeyed-atsu/eXodusino/

ブートローダはプロジェクトフォルダ直下の

Bootloader_DIP28_.axf

をLPCXpressoボードなどSWDが使えるハードで書き込んで使用して下さい。
なお、LPCXpresso 4.2以降のIDEを使用して下さい
このブートローダを一旦書き込んでしまえば、Flash MagicやLPCXpressoを使わなくてもLPC1114FN28/102マイコンのシリアル端子*1でプログラムの書き込みが出来ます。透過モードのXBeeやUSB-シリアルケーブルで書き込みが出来ます。
f:id:Lynx-EyED:20120331163149j:image

なお、テスト用のバイナリを

Release/exodusino_sample1_DIP_28_.bin

に用意しました。
バイナリ書き込みにはTeraTermなどのシリアルコンソールを使います。
具体的な方法はこちらを参照して下さい。
書き込みに成功すると、ターミナルエミュレータへ1秒ごとにカウントアップを送信します。

■eXodusinoとして使う場合の設定
ここからはeXodusinoのユーザアプリケーションの開発するにあたっての注意点です。

eXodusinoライブラリはLPC1114F/301,LPC1114L/302のみに対応しているため、RAMの少ないLPC1114FN28/102に対応するには設定をし直す必要があります。
eXodusinoブートローダはフラッシュメモリの始めの4kByte、RAMの32byteを占有してしまいます。この領域を潰さないようにバイナリを書き込む必要があります。*2
通常はリンカスクリプトをガリガリ書き換えるのですが、LPCXpresso IDEの力を借りるとちょっとした設定だけで済みます。

◇MCU Settings
LPCXpresso IDEの左側、

 Project Explorer→exodusinoフォルダを右クリック→
Property→C/C++ Build → MCU Settings → LPC1114FN/102

を選択。
f:id:Lynx-EyED:20120401204256p:image

◇リンカスクリプトの設定
次に、RAMが4kBなので、[eXosusinoプロジェクトトップ]/Release/eXodusino_Release_mem.ldを以下の図のように書き換えます。LPC1114F/301のRAMの部分2行分をコメントアウトして、LPC1114FN28/102の部分の2行分のコメントアウトを外せばいいだけです。
f:id:Lynx-EyED:20120401204257p:image

◇クロックの設定
最後に、eXodusinoは12MHzの外部クロックでの動作が前提となっています。内蔵クロックで動かしたい場合は、[eXosusinoプロジェクトトップ]/src/core/system_LPC11xx.cppの128,134行目をコメントアウト、129,135行目のコメントアウトを外します。
f:id:Lynx-EyED:20120401205307p:image


これで、Project->Cleanすると、一旦クリーンした後にバイナリを作ってくれるはず。
exodusino.binをシリアルコンソール越しに書き込んで成功。
f:id:Lynx-EyED:20120401205308p:image

*1:9600baud,8N1で通信します

*2:ブート領域が潰れるようなコードを書いてしまっても、ブートローダは消えません。書き込んだバイナリが正しく動作しないだけです

LPC1114で音声再生

◆eXodusino量産向け試作品とピン配置
前回のエントリの続きです
f:id:Lynx-EyED:20120225144503j:image

ピン配置は以下の通りです。
f:id:Lynx-EyED:20120311230948p:image
◆ピン名称と入出力設定の関係
eXodusinoはArduino標準API互換*1なので、上記のD2ピンを出力ピンかつ、HIGHにしたい場合、

pinMode(2,OUTPUT);
digitalWrite(2,HIGH);

あるいは、LPC1114のオリジナルのピン名称を使って

pinMode(P0_3,OUTPUT);
digitalWrite(P0_3,HIGH);

とすることも可能です。

◆書き込み方法
eXodusinoにプログラムを書き込む方法はこちらをご覧ください。

◆アプリケーション例:非圧縮wav音声データの再生
ローム製音声用DAC BU9480Fか浜松ホトニクス製カラーセンサS9706どちらか1つを実装できるパターンに設計してある訳ですが、
今回はBU9480F版で音を出してみようと思います。音源は16bit、ステレオ、22.050kHzサンプリング非圧縮wavファイルとしました。
48pinのLPC1114はSPIが2chあるのでSDカードをSPIモードで読み込みつつ、同時にもう一方のSPIでBU9480FなどのSPI DACを駆動することができます。

↓BU9480F版eXodusino
f:id:Lynx-EyED:20120225143203j:image

BU9480FはDFも出力段用アンプも内蔵していないため、外部にフィルタ付きアンプを設計して接続してやる必要がありますが、
取り急ぎの音声の確認くらいならイヤホンジャック直結みたいな横着してもOK(一応ボード上の1uFでバイアスカットしてるので)
でも、インピーダンスくらいは計算しとかないとぶっ壊れるかも。。。オススメはしません。

f:id:Lynx-EyED:20120225143518j:image

コードはこちら。eXodusinoプロジェクトのuser_application.cppにコピペで動くはず。

#include <libmary.h>
#include <SD.h>
#include <SPI1.h>		// BU9480FのSPI

#define LRCLK		6					// LRCLK(BU9480F) -> D6(eXodusino)
#define AudioBufRow	256					// length of proc_r
volatile uint16_t	empty_c	= 0;		// Column
volatile uint16_t	proc_r	= 0;		// Row
uint16_t	AudioBuf[2][AudioBufRow];	//AudioBuf[empty_c][proc_r]
bool dac_semp;							// オーディオバッファ書き込み完了フラグ true:完了, false:まだ


uint16_t br;
FRESULT rc;

void readSound(void)
{
	volatile int16_t i=0,j=0;
	while(1){
		if(i != empty_c)
		{
			if(j >= AudioBufRow - 1)
			{
				i = empty_c;			// DACが使用してない(使い終わった)バッファを選択
				j = 0;
			}
		}

		if (j < AudioBufRow - 1)
		{
			rc = pf_read(AudioBuf[i], sizeof(uint16_t)*256, &br);	// Read a chunk of file
			if (rc || !br)break;

			j = j + 256;

		}
		if(j >= AudioBufRow - 1)
		{				// 音声バッファは満タン?(DACがリードしてもOK?)
			dac_semp = true;
		}
	}
}


void playSound(void)
{
	static uint16_t i,j;					// AudioBuf[j][i]
	uint16_t k;
	if(i >= AudioBufRow - 1)
	{
		if(dac_semp)						// empty_cカラムは書き込み完了?(=true?)
		{
			i = 0;
			empty_c =(empty_c == 1)?0:1;	// DACが使い終えたバッファをempty_cとする
			j = (empty_c == 1)?0:1;			// decode()関数がデータを貯めているバッファに切り替え
			dac_semp = false;				// empty_cは空なのでfalse

		}else
		{									// 書き込み完了してない?
			return;
		}
	}
	//DACへデータ送信
	k =(AudioBuf[j][i++]);
	digitalWrite(LRCLK,HIGH);
	SPI1.transfer(k);

	k =(AudioBuf[j][i++]);
	digitalWrite(LRCLK,LOW);
	SPI1.transfer(k);

	return;
}

void setup()
{
	// XBeeの初期化
	Serial.begin(9600);

	//BU9480Fの初期化
	pinMode(LRCLK,OUTPUT);
	SPI1.setBitLength(16);
	SPI1.setClockDivider(SPI_CLOCK_DIV2);
	SPI1.begin();

	// SDCard初期化のtry&catch
	if (!SDFile.begin())
	{
		Serial.println("Cannot detect SDCard") ;
		return ;
	}

	Serial.println("card initialized.") ;
	rc = SDFile.open("hoge.wav") ;

	if (rc)
	{
		// ファイルオープン失敗
		Serial.println("Failed to open...") ;
		SDFile.close() ;
		while(1);		//ここに動作停止処理を記述
	}

}

void loop(void)
{
	Serial.println("play start");

	// 45マイクロ秒ごと=22.05kHzごとにplaySound()をコールする
	attachMicroseconds(playSound,45);
	readSound();

	SDFile.close() ;		// ファイルをクローズ
	detachMicroseconds();	// 割り込みを停止

	Serial.println(""); 			//改行
	Serial.println("play end.");
	while(1);				//ここに動作停止処理を記述


}


microSDカードに16bit、ステレオ、22.050kHzサンプリング非圧縮wavをhoge.wavというファイル名で保存します。
eXodusinoのmicroSDソケットにセットします。
eXodusinoに上記のプロジェクトのバイナリを書き込み。(自動で再起動します。)

クリスタルイヤホンや、アンプを接続したスピーカから音声が確認できたら成功です。
f:id:Lynx-EyED:20120225140132j:image

*1:ただしソフトの開発はLPCXpresso IDE4となります

Cortex-M0 Arduino互換環境 eXodusinoとブートローダの改良

前回紹介したeXodusino[エクソダシノ]量産先行品はブートローダを改良しました。
XMODEMを廃止し、無手順UARTによりバイナリを書き込むシンプルな方式です。

eXodusinoプロジェクトはgithubから一式をダウンロードできます。
http://github.com/lynxeyed-atsu/eXodusino/
注意:プロジェクトに含まれているBootloader.axfは評価版扱いです。書き込みファイルサイズに15kB制限があります。
特別な事情がない限りeXodusinoに出荷時に書き込まれているブートローダをご利用ください。なお、書き込みにはLPCXpressoやSWDに対応しだデバッガが必要になります

※制限はなくなりました

  • eXodusinoを使うのに用意する機材
    • eXodusino本体
    • Windowsかubuntuが動作するPC
    • XBee Series2 2台(お互いが透過モードで通信できるように、あらかじめX-CTUなどで設定しておいて下さい。速度は9600baudです)
    • XBee エクスプローラ、MARY-XBボード、XBee FRISKなどPCとXBeeをシリアル接続できるデバイス1台
    • バイナリファイルがシリアルで送信できるターミナル(TeraTerm,ハイパーターミナルなど)
    • LPCXpresso IDE4
  • 基本的にXBeeを接続して使う
    • 書き込みやデバッグメッセージ送信など、基本的にXBee経由で行います。用意した2台のXBee Series2を一方はeXodusinoに、他方はXBeeエクスプローラでPCと接続して下さい。
    • ターミナルソフトとは9600baud 8bit,ノンパリティ,ストップビット 1で接続してください。
  • ソフト
    • 基本的にLPCXpresso IDEを使います。CUIerな方々はarm-none-eabi-gccリンカスクリプトを調教してコンパイルするのもいいと思います。

開発のスナップショット...(クリック→オリジナルサイズを表示で拡大します)
f:id:Lynx-EyED:20120204161539p:image

ご覧のとおり、Arduino語で開発が可能です。写真のツリーの/src/user_application.cppがAdruinoスケッチ(.pde)に相当する部分です。コンパイルはメニューのProject→Build allで可能ですが、ショートカットキーの[Ctrl]+[B]の方が使いやすいです。

  • 書き込み
    • まず、eXodusinoにUSB mini-Bケーブル、または他の方法で給電します。
    • ターミナルソフトを使います。例ではTeraTermを使っています。
    • eXodusinoのCPUリセットボタンを押します

f:id:Lynx-EyED:20120311224839j:image

    • TeraTermの画面でキーボードの[z]を押し続けます。(連打ではなく、押し続けます)
    • リセットボタンから手を離してから、[z]キーからも手を離します

するとこんな画面が出てくるはず
f:id:Lynx-EyED:20120204163014p:image
これでプログラム待ち受け状態になりました。
CUTECOMなど、キーを押したときだけ1文字送信するタイプのターミナルをお使いの方へ:eXodusinoはリセット後、約1秒間待機状態になります。この間にzを1文字入力すればBootloaderモードに遷移します。

  • バイナリファイルを書き込む
    • TeraTermでは[ファイル(F)]→[ファイル送信(S)...]でバイナリを選択できます。

f:id:Lynx-EyED:20120204163015p:image

    • Releaseフォルダの[exodusino.bin]を選択し一番下のオプションメニューの[バイナリ(B)]に必ずチェックを入れます

f:id:Lynx-EyED:20120204163919p:image

    • しばらく書き込みを待ちます。256バイト書き込むごとに[o]の文字が羅列されていきます。もしこれが[x]と表示された場合、書き込みが失敗しています。書き込んだファイルが正しいか確認して下さい。

f:id:Lynx-EyED:20120204163920p:image

最後の[Program end. Rebooting...]というメッセージが少し遅れて(2,3秒程かかる)表示されます。これは続くデータが無いかの確認と、チェックサムを計算しているためです。
f:id:Lynx-EyED:20120204163921p:image
マイコンは自動で再起動します。例ではボード上のカラーセンサーS9706からデータを読み出しています。

なおこのチェックサムが失敗しているか、マイコンが再起動時にキーボードから[z]キーを押していると、再起動時に再び[Welcome to eXodusino..]が表示されます。ご注意下さい。