mbedのオンラインコンパイラでLPC1114のGPIOをレジスターで叩くときの注意点

LPC1114マイコンをライブラリの DigitalOut 等を使うことなく、mbedのオンラインコンパイラ上でレジスターを叩いて高速なGPIOを実現するさいの注意点です。レジスターを叩くことについては、以下のリンク先に詳しい解析が載っています。

monoist.atmarkit.co.jp

こちらのページのように LPC_GPIO0->DIR で GPIO ピンの入出力の方向を設定できますが、設定が反映されないピンがあります。
反映されないピンは以下の通りでした。

  • 3 (P0_10 / SWCLK)
  • 4 (P0_11 / R)
  • 9 (P1_0 / R)
  • 10 (P1_1 / R)
  • 11 (P1_2 / R)
  • 12 (P1_3 / SWDIO)
  • 23 (P0_0 / RESET)

ピンアサイン参考:Beginning LPC1114FN28 with Arch | Mbed

ピンアサインを見ると、SWCLK、R、SWDIO、RESET の機能を有するピンだけ入出力設定が反映されないことがわかります。
また、リンク先のピンアサイン表の「PIOx_y」の左側に何かが書かれているピンだけ設定が反映されない、とも言えます。

ピンの設定について調べていくと、以下のページが見つかりました。

http://digimono-boys.blogspot.jp/2011/12/armcortex-m0iocon.htmldigimono-boys.blogspot.jp
white-clouds-in-sky.blogspot.jp

どうやら、ピンアサイン表の一番左側にある機能がデフォルトの設定になるようです。

  • 例えば、ピン3はデフォルトで SWCLK が有効になっているので、入出力の方向を設定(LPC_GPIO0->DIR に代入する)しても GPIO の機能にはなりません。
  • また、ピン1は PIO0_8 が一番左側にあるので、このピンのデフォルトの設定は GPIO であることもわかります。

この GPIO や R、AD変換 などといった機能を設定するレジスターがあります。


以下は、ピン23以外(理由は後述)の全てのピンでLチカができるプログラムです。

#include "mbed.h"
int main(){
    LPC_IOCON->SWCLK_PIO0_10 = 0xd1;
    LPC_IOCON->R_PIO0_11 = 0xd1;
    LPC_IOCON->R_PIO1_0 = 0xd1;
    LPC_IOCON->R_PIO1_1 = 0xd1;
    LPC_IOCON->R_PIO1_2 = 0xd1;
    LPC_IOCON->SWDIO_PIO1_3 = 0xd1;
    //LPC_IOCON->RESET_PIO0_0 = 0xd1;
    
    LPC_GPIO0->DIR = 0xFFFF;
    LPC_GPIO1->DIR = 0xFFFF;
    while(1){
        LPC_GPIO0->DATA = 0xFFFF;
        LPC_GPIO1->DATA = 0xFFFF;
        wait(0.5);
        LPC_GPIO0->DATA = 0x0000;
        LPC_GPIO1->DATA = 0x0000;
        wait(0.5);
    }
}

問題のピンは、以下の行で GPIO モードに設定しています。設定値の 0xd1 はたまたま全てのピンで共通の値でした。

    LPC_IOCON->SWCLK_PIO0_10 = 0xd1;
    LPC_IOCON->R_PIO0_11 = 0xd1;
    LPC_IOCON->R_PIO1_0 = 0xd1;
    LPC_IOCON->R_PIO1_1 = 0xd1;
    LPC_IOCON->R_PIO1_2 = 0xd1;
    LPC_IOCON->SWDIO_PIO1_3 = 0xd1;
    //LPC_IOCON->RESET_PIO0_0 = 0xd1;

設定の値はこちらのユーザーマニュアル(https://www.nxp.com/documents/user_manual/UM10398.pdf)で見ることができます(「SWCLK_PIO0_10」等でページ内検索を掛けると該当の部分が出てきます)。


ピン23(P0_0) の設定はコメントアウトしてあります。筆者はISPモードで bin を書き込む LPCISP というソフト(mbed LPC1114でLチカしてみた(2) - しなぷすのハード製作記)を使っています。このソフトは自動でリセットを掛けてISPモードに突入して書き込みを行ってくれます。そのため、ピン23を GPIO モードに設定するとマイコンの電源が入った直後にこのピンが GPIO として働いてしまい、自動リセットは掛かりません。

どうしてもピン23を GPIO として使いたい、ピン23を GPIO に設定してしまってプログラムを新しく書き込めない…といった状況なら、手動でリセットを掛けて書き込みをする方法で状況を解決します。

www.nxp-lpc.comこちらのサイトの「ISP」の欄の要約になりますが、

  1. 電源を落とす
  2. ピン23(RESET)、ピン24(ISPエントリーピン) を Low にして電源を入れる
  3. ピン23を High にする

という手順のあと、LPCISPを使って書き込みをします。電源を落とさなければならないので、面倒な手順を踏むことになります。

TmBoxのループ再生を止めるブックマークレット

タイトルの通りです。

javascript:TARGET.addEventListener('ended', function(){TARGET.pause();}, false);

本当は removeEventListener でループ再生イベントそのものを消したかったのですが、無名関数が登録されていたためどうにもなりませんでした。どうにか方法を調べていましたが、うまくいかなかったためイベントを消すのはあきらめました。妥協案としてイベントを消す代わりに一時停止をイベントのあとに挿入しました。
ループ再生イベントは

  1. 一時停止
  2. 再生
  3. repeat数(再生回数)を1増やす

となっているので、この妥協案ではrepeat数が1つ余分に増えてしまいます。そこは妥協ということです。

TmBoxの視聴履歴、お気に入り履歴のページ移動をするブックマークレット

タイトルの通りです。

  • 新しい方へ移動
javascript:void(function(isNext,l){ var pagenum = ~~l.search.substr(6); if( isNext ){ if( l.search === "" ){ l.href += "?page=2"; }else{ l.href = l.protocol + "//" + l.hostname + l.pathname + "?page=" + ( pagenum + 1 ); } }else{ if( pagenum > 1 ){ l.href = l.protocol + "//" + l.hostname + l.pathname + "?page=" + ( pagenum - 1 ); } } })(false,location);
  • 古い方へ移動
javascript:void(function(isNext,l){ var pagenum = ~~l.search.substr(6); if( isNext ){ if( l.search === "" ){ l.href += "?page=2"; }else{ l.href = l.protocol + "//" + l.hostname + l.pathname + "?page=" + ( pagenum + 1 ); } }else{ if( pagenum > 1 ){ l.href = l.protocol + "//" + l.hostname + l.pathname + "?page=" + ( pagenum - 1 ); } } })(true,location);


実は1箇所以外どちらも同じ共通のソースです。最適化したい方は各自でどうぞ。

HSPで擬似構造体

HSPというのは小規模なソフトを作るときに非常に使いやすいんですが、それ以上になってくるとソースがごちゃごちゃになってきますよね。いや、ソースの書き方が汚いだけかもしれませんが。
構造体が使えればソースがスッキリしそうですね。
早速見て行きましょう。


宣言するときはこちら。

#define volume 0
#define expression 1
dim midi,2

参照するときはこちら。

mes "volume : " + midi.volume
mes "expression : " + midi.expression

HSPには、配列を参照する方法が2つあります。

dim n,2,2
mes n(0,1)
mes n.0.1

2行目の n(0,1) はHSP3で追加された配列参照の方法です。
3行目の n.0.1 はHSP2からある方法です。
今回の擬似構造体では3行目の配列参照の方法を使っています。


例えば。

dim n,2
mes n.0

この場合で言えば、0の部分を定数に置き換えてしまえばいいわけです。

#define first 0
#define second 1
dim n,2
mes n.first

構造体っぽいですか?っぽいですね。「っぽい」っていうのは見た目に関わってくるので割と大事。

これをC言語で書くとこうなります。

struct{
    int first;
    int second;
}n;

わお簡潔。名前に意味はありません。

2次元配列でも同じことをすればいいわけです。


もう1つ例をあげると、時間の情報を格納する変数もこれを使えばスッキリまとまります。
こんな感じ。

#define sec 0
#define min 1
#define hour 2
dim time,3
mes time.hour + "時" + time.min + "分" + time.sec + "秒"

お好みで年月日も追加できます。



お疲れ様でした。

C言語のHelloWorldについて

よく入門サイトで見かけるHelloWorldはこれ。

#include <stdio.h>
int main(){
    printf("HelloWorld");
    return 0;
}

でもこれ、実行したらウィンドウが開いて一瞬で閉じられてしまうんですよ。
初心者の私はここでつまずきました。(諦めそうになりました)
そこでこれを入れましょう。

getchar();

このgetcharという関数はstdio.hで定義されているのでまた新しいファイルをインクルードする必要はありません。楽チン。
最終的にソースはこんなカタチになるんですね。

#include <stdio.h>
int main(){
    printf("HelloWorld");
    getchar();
    return 0;
}

これを実行するとウィンドウが開いて HelloWorld が表示されます。さっきと違うのはここでウィンドウが閉じられないところです。キーボードのボタン(どれでもいい)を押すと return 0 が実行されウィンドウが閉じられます( = プログラムを終了する)。

getchar という関数はその場でプログラムの進行を止めてくれる便利な関数です。と言うと簡単なんですが、本当は違います。getchar はキーボードのボタンが押されるまでプログラムの実行を止め、押されたならばそのキーボードの値を返すという2つの役割を持つ関数です。ここではプログラムの進行を止めるためだけに使っています。

C言語 入門」で検索をかけて出てきたサイトのソースで、printf(~) で計算結果を表示させて、直後に return文が書かれている、というのをよく見かけます。よく見かけるというか getchar 挟んでいるのを私は見たことがないです。
Visual Studio Express 2012 を私は使っていますが、何でしょうか、環境によって return文の前で止まったりするんですかね?よくわかりません。

[追記]

デバッグなしで開始」がありました。こうすることで「続行するには何かキーを押してください . . . 」が末尾に挿入されてキーボード入力待ちになるんですね。getchar いらず。
でもF5キーを押してパッと実行させたいのでやはり getchar は有効ではないかと思います。Releaseビルドで特に有効ですね。

C言語で構造体の動的確保

自分用のメモみたいなものです。

#include <stdio.h>
#include <stdlib.h>
typedef struct{
	int x;
	int y;
}STR;
void main(){
	STR *s;
	s = (STR*)malloc(sizeof(STR) * 10);// 10は確保したい1次元配列の数
	s[1].x = 15;
	s[9].y = 990;
	printf("%d,%d",s[1].x,s[9].y);
	getchar();
	free(s);
}

HSPでClearTypeの実験

HSPで画像を3分の1(辺)に縮小するスクリプトを組みました。
それだけではつまらないのでClearTypeと同じ仕組みで縮小するサンプルを作りました。ClearTypeとはWindowsのフォントの描画で使われている技術です。ClearTypeについて詳しいのはこのサイト→ http://www.atmarkit.co.jp/fpc/xp_feature/cleartype/cleartype.html

それではスクリプトです。

screen 0
dialog "",16
if stat==0:dialog "キャンセルされました":end
picload refstr
sw=ginfo(12)
sh=ginfo(13)
title "Orginal Image size: "+sw+","+sh

buffer 1,3,3

screen 2,sw/3,sh/3
title "Default"
redraw 0
repeat sh/3
	cnt1=cnt
	repeat sw/3
		cnt2=cnt
		gsel 1
		gcopy 0,cnt2*3,cnt1*3,3,3
		clr=0
		repeat 9
			pget cnt\3,cnt/3
			clr+=(ginfo_r+ginfo_g+ginfo_b)/3
		loop
		gsel 2
		color clr/9,clr/9,clr/9
		pset cnt2,cnt1
	loop
loop
redraw 1

screen 3,sw/3,sh/3
title "ClearType"
redraw 0
repeat sh/3
	cnt1=cnt
	repeat sw/3
		cnt2=cnt
		gsel 1
		gcopy 0,cnt2*3,cnt1*3,3,3
		dim clr,3
		repeat 3
			cnt3=cnt
			repeat 3
				pget cnt3,cnt
				clr.cnt3+=(ginfo_r+ginfo_g+ginfo_b)/3
			loop
		loop
		gsel 3
		color clr.0/3,clr.1/3,clr.2/3
		;color clr.2/3,clr.1/3,clr.0/3//←きれいに表示されないときはこちらのコメントアウトを外して真上の行をコメントアウトする
		pset cnt2,cnt1
	loop
loop
redraw 1

スクリプトが開始されたときに、まずファイルオープンのダイアログが出ますのでお好きな画像を選択してください。
選択されるとすぐに縮小が開始されます。
縮小作業は画像サイズが大きいほど時間がかかります。CPU依存なので縮小なのでCPUをそれなりに食います。

スクリーン0は元画像表示用のウィンドウ、バッファー1は作業用バッファ、スクリーン2は標準の方法での縮小の表示用ウィンドウ、スクリーン3はClearTypeでの縮小の表示用ウィンドウです。

使う画像によってClearTypeの効果が出たり出なかったりします。どういった画像でよく効果が出るのかというのを考えてみるのもいいかもしれません。