2012-02-19
iPodから音楽データを取り出すという夢を見た。
先日突然、使っているMacBookのHDが音を立て、動かなくなりました…orz
CD-ROMブートさえもできない状況で、
仕方がないので、HDを換装しました。
バックアップを取ってなかったので、データは無くなっちゃいました。
自分の中で無くなって悲しいデータといえば、この3つ。
- 写真
- 音楽
- 開発中のアプリのソース
特に、音楽データは、量がそこそこあったし、
iTunes Storeで買ったものもあったので、
なかなか痛手だなぁ、と思っていたのですが、
使っていたiPod nano(第6世代)をPCにつないで、
認証すると、あらまぁ!
購入していた曲は元通りiTunesに。
ですが、もちろんCDから取り込んだ曲は入らず。
あきらめきれないので、方策を探した結果、いろんなツールがあるもんですねぇ。
(グレーゾーンじゃないかと思うので、紹介は控えますが…)
でも、iPodから音楽データを取り出すためだけにインストールしたくないので、
ツール類をインストールせずに自力でなんとかしてみよう…
という夢を見ました。
以下では、夢の内容を記します。
2012-01-27
NSArrayのindexOfObjectの戻り値とNSNotFoundについて
最近、Objective-cについて勉強し始めました。
参考にさせていただいてるのはコチラ!
Cocoaの素、Objective-Cを知ろう − @IT
分かりやすくて、とても勉強になります!ありがとうございます!!
今のところ、(4)まで進んだのですが、
サンプルプログラムを動かしてみるとWarningが出てくる。
バージョンも変わってるだろうし、仕方がない。
具体的には、リンク先の下記の部分。
配列とループ処理を理解しよう - @IT
//(4)ある要素のインデックスを取得
int objectIndex = [array indexOfObject:@"pqr"];
if (objectIndex == NSNotFound) {
NSLog(@"'pqr' is not found.\n");
}
出力されるWarningはこんな感じ。
$ gcc -o main main.m -framework Foundation
main.m: In function ‘main’:
main.m:20: warning: comparison is always false due to limited range of data type
調べてみたら「比較が常にfalseになってるよ」的なことだということで、
実行ファイルを実行してみると、案の定「NSLog(@"'pqr' is not found.\n");」が出てない。
ググると似たような人発見!
NSNotFoundにはまった。 - メソッド屋の日記
なるほどー!
難しいことはさておきw、
NSNotFoundの値が変わっちゃってるっていうことね。
で、どうすりゃいいんだ、っていうことでさらに調べたところ、
リファレンスによると、indexOfObjectの戻り値はNSUIntegerなので、以下のように修正。
// int objectIndex = [array indexOfObject:@"pqr"]; NSUInteger objectIndex = [array indexOfObject:@"pqr"];
無事、Warningも出なくなり、
「'pqr' is not found.」も出力されるようになりましたとさ。
めでたしめでたし。
2011-06-13
職業訓練47日目 H8マイコン制御技術(LCD-SCI制御技術)
LCDの制御
使用したLCDはコチラ!(多分…)
LCDキャラクタディスプレイモジュール(16×2行バックライト無): ディスプレイ関連 秋月電子通商 電子部品 ネット通販
16文字×2行のアスキー文字を1文字につき5×7ドットあるいは5×10ドットで表示する。
外部との接続には、12本(2列6本)のピンヘッダを利用する。
LCDの基本構造
パス…。
またWikipediaで逃げよう…。
液晶ディスプレイ - Wikipedia
市販LCDの使用方法
表示データはアスキーコード形式で8ビットのまま、
あるいは8ビットを4ビットずつ2回に分けて読み込む。
表示データの読み込みは、すべて外部からの制御により行われる。
内部に読み込まれたデータは、文字表示位置に対応するメモリに書き込まれ、
書き改められるまで内容は保持され、表示され続ける。
LCDの駆動方法
●LCDの初期設定
- ソフトウェアリセット
- ファンクションセット
- ディスプレイON/OFF制御
- エントリーモードの設定
細かい話は抜きで…。
ここでの話は全部、実習で使ったマザーボードとLCD上でのお話ですし。
データの転送と表示
初期設定完了後、表示データをLCDに転送可能な状態になる。
表示データはRAM領域の特定の場所を定義し、そこに書き込む。
そのデータを中継用RAM領域に1バイトずつ順番に読み出し、LCDに転送し、表示させる。
LCD表示プログラムの流れ
使用したテキストでは、LCDにSWのON/OFF状態を表示させたり、LEDをチカチカさせたり、
わざと?冗長なプログラムにしていたので、
バッサリ表示処理にしぼって、かつ、同じ処理を自分が勝手にまとめたプログラムをお送ります。
.CPU 300HA .SECTION VECT, CODE, LOCATE=H'000000 LCD_D: .EQU H'FFEF12 P3DR: .EQU H'FFFFC6 P3DDR: .EQU H'FFFFC4 RS: .BEQU 4,P3DR E_SIG .BEQU 5,P3DR LCD162 .EQU H'FFEF13 .SECTION ROM, CODE, LOCATE=H'000100 MOV.L #H'FFFF00, ER7 MOV.B #H'FF, R0H MOV.B R0H, @P3DDR ; LCDのソフトウェアリセット JSR @TIME5MS JSR @TIME5MS JSR @TIME5MS MOV.B #B'00100011, R0L JSR @LCD_RST JSR @LCD_RST JSR @LCD_RST MOV.B #B'00100010, R0L JSR @LCD_RST ; LCDの初期設定 MOV.B #B'00101000, R0L JSR @LCD_SET MOV.B #B'00001110, R0L JSR @LCD_SET MOV.B #B'00000110, R0L JSR @LCD_SET ; LCDの初期画面表示 MOV.B #B'00000001, R0L JSR @LCD_SET MOV.B #32, R0L MOV.L #LCD162, ER1 MOV.L #MOJI, ER2 INIT_DISP: MOV.B @ER2+, R0H MOV.B R0H, @ER1 INC.L #1, ER1 DEC.B R0L BNE INIT_DISP JSR @LCDDSP LOOP: JMP @LOOP ; ------------------------ ; サブルーチン ; ------------------------ ; LCD文字出力16文字×2行転送サブルーチン LCDDSP: PUSH.L ER0 PUSH.L ER1 MOV.B #B'00000010, R0L JSR @LCD_SET ; LCD表示1行目の16文字転送 MOV.B #16, R0L MOV.L #LCD162, ER1 LCDDSP1: MOV.B @ER1+, R0H MOV.B R0H, @LCD_D BSET RS JSR @LCD_OUT4 BCLR RS DEC.B R0L BNE LCDDSP1 MOV.B #B'11000000, R0L MOV.B R0L, @LCD_D BCLR RS JSR @LCD_OUT4 ; LCD表示2行目の16文字転送 MOV.B #16, R0L MOV.L #LCD162 + 16, ER1 LCDDSP2: MOV.B @ER1+, R0H MOV.B R0H, @LCD_D BSET RS JSR @LCD_OUT4 BCLR RS DEC.B R0L BNE LCDDSP2 POP.L ER1 POP.L ER0 RTS ; LCDにデータを転送 LCD_SET: MOV.B R0L, @LCD_D BCLR RS JSR @LCD_OUT4 JSR @TIME5MS RTS ; LCDのソフトウェアリセットサブルーチン LCD_RST: MOV.B R0L, @LCD_D BCLR RS JSR @LCD_OUT8 JSR @TIME5MS RTS ; LCDへのデータ/コマンドの転送(8ビット) LCD_OUT8: PUSH.L ER0 BSET E_SIG MOV.B @LCD_D, R0L MOV.B R0L, @P3DR JSR @TIME100US BCLR E_SIG JSR @TIME100US POP.L ER0 RTS ; LCDへのデータ/コマンドの転送(4ビット) ; 上位4ビット送出 LCD_OUT4: PUSH.L ER0 BSET E_SIG MOV.B @LCD_D, R0L SHLR.B R0L SHLR.B R0L SHLR.B R0L SHLR.B R0L JSR @OUT4 ; 上位4ビット送出 BSET E_SIG MOV.B @LCD_D, R0L JSR @OUT4 POP.L ER0 RTS ; 4ビット送出サブルーチン OUT4: AND.B #B'00001111, R0L MOV.B @P3DR, R0H AND.B #B'11110000, R0H OR.B R0H, R0L MOV.B R0L, @P3DR JSR @TIME5MS BCLR E_SIG JSR @TIME5MS RTS ; 5msのタイマ TIME5MS: MOV.L #10000, ER6 ER6DEC: DEC.L #1, ER6 NOP BNE ER6DEC RTS ; 100usのタイマ TIME100US: MOV.L #200, ER6 JSR @ER6DEC RTS .ALIGN 2 .SECTION LCDDATA, DATA, LOCATE=H'000B00 MOJI: .SDATA "H8/3048F TEST BD 1111 11111111 " .END
これでLCDに、
H8/3048F TEST BD 1111 11111111
って表示されるはず…。
手元に実機がないのにソースいじちゃったから動かない可能性大だけど…。
そして、本来は"1"の部分がSWのON/OFFで変化するんだけど…。
本当は、
(・ω・)ノ Hello, world!
って表示したかったんだけど、アスキーコードの転送の仕方が分からず、断念しました。
アァー、残念…orz
2011-06-07
職業訓練46日目 H8マイコン入門(アセンブラ言語による実習)
割込み制御
割込み
実行中の処理を一時停止して、他の処理を行った後に最下位する機能。
●割込み動作の流れ
- PCとCCRをスタックに待避(必要であれば、汎用レジスタのデータもスタックに待避)
- CCRの割込みマスクビットに"1"をセット(他の割込みを禁止する)
- メモリの割込みベクタアドレスから、割込みプログラムの開始アドレスをPCに読み込む
- 割込みプログラムを実行
- RTE命令で割込みプログラムから復帰する
- 待避していたPCとCCRを復元して、元の処理を再開する
IRQ端子を使った割込み
IRQ0〜5端子に"0"を入力することで、割込みが発生する。
→使用するピンによって6種類の割込みプログラムを選択できる。
IRQイネーブルレジスタ(IER):端子別に許可/禁止の設定
IRQセンスコントロールレジスタ(ISCR):割込み信号の有効な動作タイミングを設定
実際に製作した回路は、
プッシュSWからシュミットトリガゲート(74LS19)を介して、
IRQ0端子に信号を入力する。
.CPU 300HA .SECTION PROG13, CODE, LOCATE=H'000000 .DATA.L MAIN ; メイン処理は、000000番地から .ORG H'000030 ; IRQ0の割込みベクタアドレス .DATA.L IRQ0 ; 割込みプログラムの開始アドレス IER .EQU H'FFFFF5 ; IRQイネーブルレジスタ ISCR .EQU H'FFFFF4 ; IRQセンスコントロールレジスタ P1DR .EQU H'FFFFC2 P1DDR .EQU H'FFFFC0 P5DR .EQU H'FFFFC8 P5DDR .EQU H'FFFFCA .SECTION ROM, CODE, LOCATE=H'000100 MAIN: MOV.L #H'FFF00, ER7 MOV.B #H'FF, R0L MOV.B R0L, @P1DDR MOV.B R0L, @P5DDR BSET #0, @IER ; IRQ0の割込みを許可 BSET #0, @ISCR ; 割込みパルスの立下がりエッジで割込みを行う LDC #0, CCR ; 割込み許可 MOV.B #B'01111111, R0L ; LED点灯データ(ポート1) LOOP: MOV.B R0L, @P1DR JSR @TIM2 ROTR.B R0L JMP @LOOP ;----- 割込み処理 ----- IRQ0: PUSH.W R0 ; レジスタの待避 PUSH.L ER5 PUSH.L ER6 MOV.B #D'3, R0H ; LED点灯回数データ YET: MOV.B #H'FF, R0L ; LED点灯データ(ポート5) JSR @TIM2 MOV.B #H'00, R0L MOV.B R0L, @P5DR JSR @TIM2 DEC.B R0H ; 点灯回数 - 1 BNE YET ; 点灯回数が0でなければ、YETへ POP.L ER6 ; レジスタの回復 POP.L ER5 POP.W R0 RTE ; 割込みから復旧 ;---------------------- TIM2: MOV.W #D'50, E5 ; 0.5秒のタイマサブルーチン L2: JSR @TIM1 DEC.W #1, E5 BNE L2 RTS TIM1: MOV.L #D'20000, ER6 ; 10msのタイマサブルーチン L1: DEC.L #1, ER6 NOP BNE L1 RTS .END
上記のプログラムを実行すると、
0.5秒ごとにポート1の点灯するLEDが1個ずつ移動していき、
プッシュSWが押されると、ポート1のLEDが停止し、ポート5のLEDが3回点滅、
その後、またポート1のLEDが移動し始めるはず。
NMI端子を使った割込み
NMIとは、マスク(禁止)できない「ノンマスカブル割込み」のこと。
CCRの割込みマスクビットを"0"にしても禁止できない、優先度の高い割込み。
NMI端子の入力エッジは、システムコントロールレジスタ(SYSCR)で設定。
製作した回路は、上記のIRQ端子を使った回路と一緒で、
割込み信号を入力する端子がNMI端子になっただけ。
.CPU 300HA .SECTION PROG14, CODE, LOCATE=H'000000 .DATA.L MAIN ; メイン処理は、000000番地から .ORG H'00001C ; NMIの割込みベクタアドレス .DATA.L IRQ0 ; 割込みプログラムの開始アドレス SYSCR .EQU H'FFFFF2 ; システムコントロールレジスタ P1DR .EQU H'FFFFC2 P1DDR .EQU H'FFFFC0 P5DR .EQU H'FFFFC8 P5DDR .EQU H'FFFFCA .SECTION ROM, CODE, LOCATE=H'000100 MAIN: MOV.L #H'FFF00, ER7 MOV.B #H'FF, R0L MOV.B R0L, @P1DDR MOV.B R0L, @P5DDR BCLR #2, @SYSCR ; 割込みパルスの立下がりエッジで割込みを行う MOV.B #B'11111110, R0L ; LED点灯データ(ポート1) LOOP: MOV.B R0L, @P1DR JSR @TIM2 ROTL.B R0L ; IRQ端子のプログラムとは逆の向き JMP @LOOP ;----- 割込み処理 ----- IRQ0: PUSH.W R0 ; レジスタの待避 PUSH.L ER5 PUSH.L ER6 MOV.B #D'3, R0H ; LED点灯回数データ YET: MOV.B #H'FF, R0L ; LED点灯データ(ポート5) JSR @TIM2 MOV.B #H'00, R0L MOV.B R0L, @P5DR JSR @TIM2 DEC.B R0H ; 点灯回数 - 1 BNE YET ; 点灯回数が0でなければ、YETへ POP.L ER6 ; レジスタの回復 POP.L ER5 POP.W R0 RTE ; 割込みから復旧 ;---------------------- TIM2: MOV.W #D'50, E5 ; 0.5秒のタイマサブルーチン L2: JSR @TIM1 DEC.W #1, E5 BNE L2 RTS TIM1: MOV.L #D'20000, ER6 ; 10msのタイマサブルーチン L1: DEC.L #1, ER6 NOP BNE L1 RTS .END
IRQ端子の例とやってることは一緒ですね。
2011-06-02
職業訓練45日目 H8マイコン入門(アセンブラ言語による実習)
A-D, D-Aコンバータの制御
A-Dコンバータ
アナログデータをデジタルデータに変換する装置。
複数の入力を扱う場合、入力端子を切り替えながら順次変換を行う。
- 単一モード:1チャネルのみを扱う
- スキャンモード:指定した最大4チャネルを扱う
変換の実行→A-Dコントロール/ステータスレジスタのADST(ビット5)を"1"にセット
変換の終了→A-Dコントロール/ステータスレジスタのADF(ビット7)が"1"にセットされる
分解能が10ビットで、0〜5Vの電圧を入力した場合
5V / 2^10 = 5 / 1024 = 0.00488...V ≒ 4.88mV
→アナログ電圧がおよそ4.88mV変化するごとに、デジタルデータが"1"変化する
実習で製作した回路は、
5V電源→10kΩの可変抵抗→チャネル0のAN0端子に入力
ポート1のLED0〜7に変換結果を出力
といった感じ。
では、A-Dコンバータを利用したプログラムを。
.CPU 300HA .SECTION PROG11, CODE, LOCATE=H'000000 ADCSR .EQU H'FFFFE8 ; ADコントロール/ステータスレジスタ ADDRA .EQU H'FFFFE0 ; ADデータレジスタ P1DR .EQU H'FFFFC2 P1DDR .EQU H'FFFFC0 .SECTION ROM, CODE, LOCATE=H'000100 MOV.L #H'FFFF00, ER7 MOV.B #H'FF, R0L MOV.B R0L, @P1DDR ; ポート1を出力に設定 MOV.B #H'00, R0H ; 単一モード、チャネル選択(AN0)データ MOV.B R0H, @ADCSR ; ADCSR設定 LOOP: BSET #5, @ADCSR ; AD変換スタート L1: BTST #7, @ADCSR ; 変換終了チェック BEQ L1 MOV.B @ADDRA, R1L ; 変換結果の取り出し NOT.B R1L ; "1"で点灯するように反転 MOV.B R1L, @P1DR BCLR #7, @ADCSR ; AD変換終了フラグのリセット JMP @LOOP .END
上記のプログラムを実行すると、
可変抵抗をクルクル回すと、LEDがチカチカするはず。
アナログの量(電圧)が、デジタル(LED)に変換されているわけですね。
D-Aコンバータ
デジタルデータをアナログデータに変換する装置。
- 分解能:8ビット
- チャネル数:2
分解能が8ビットで、0〜5Vの電圧を出力する場合
5V / 2^8 = 5 / 256 = 0.0195...V ≒ 19.5mV
→デジタルデータが"1"変化するごとに、アナログ電圧がおよそ19.5mV変化する
製作した回路は、
ポート2のDIPスイッチ8ビットを入力、
ポート1のLED8ビットにデジタルデータを出力、
ポート7にテスタを接続し、アナログデータを測定しました。
では、プログラムはこちら。
.CPU 300HA .SECTION PROG12, CODE, LOCATE=H'000000 DACR .EQU H'FFFFDE ; DAコントロールレジスタ DADR0 .EQU H'FFFFDC ; DAデータレジスタ P1DR .EQU H'FFFFC2 P1DDR .EQU H'FFFFC0 P2DR .EQU H'FFFFC1 P2DDR .EQU H'FFFFC3 P2PCR .EQU H'FFFFD8 .SECTION ROM, CODE, LOCATE=H'000100 MOV.L #H'FFFF00, ER7 MOV.B #H'00, R0L MOV.B #H'FF, R0H MOV.B R0H, @P1DDR MOV.B R0L, @P2DDR MOV.B R0H, @P2PCR ; ポート2のプルアップ有効 LOOP: MOV.B @P2DR, R1L ; ポート2からデータ入力 MOV.B R1L, @P1DR NOT.B R1L MOV.B R1L, @DADR0 ; DAデータレジスタに転送 MOV.B #H'40, R1H ; DA変換設定データ MOV.B R1H, @DACR ; DA変換スタート JMP @LOOP .END
DIPスイッチを上げたり下げたりすると、テスタの値が変化するのが観測できるはず。