
今では入手困難になってしまった赤外線リモコン制御モーター付きレゴテクニックシリーズ。赤外線LEDを1つ使って、IchigoJamから制御してみました。
10 POKE#700,240,181,114,182,80,35,27,2,1,51,27,4,4,51,1,36,0,37,0,240,18,248,1,34,210,3,0,240,23,248,156,38,20,39,16,66,0,208,42,39,126,67,0,240,28,248,82,8,243,209,0,240,2,248,98,182,240,189,0,181
20 POKE#73C,0,240,6,248,78,39,156,38,126,67,0,240,14,248,0,189,0,181,6,33,28,96,156,38,0,240,7,248,29,96,156,38,0,240,3,248,1,57,245,209,0,189,1,62,253,209,112,71
100 INPUT A
105 FORO=0TO1
110 T=!T:C=0
120 N=T<<3|C:M=4|O
130 L=#F^N^M^A
140 N=N<<12|M<<8|A<<4|L
150 U=USR(#700,N)
155 NEXT
160 GOTO 100
0から15までの数を入れると、繋がっているモーター2つを同時に正転逆転7段階で制御できます。

赤外線LEDをOUT1とGNDに挿し込み、リモコン受信モジュールに向けるだけ!
上記、プログラムの10-20行は赤外線送信用のマシン語です。アセンブリ言語、asm15によるソースコードはこちらです。
' SEND LTECH IR R0=data(16bit)
' R0 送信データ
' R1 @ONカウンタ
' R2 データカウンタ
' R3 GPIOアドレス
' R4 GPIO ON用
' R5 GPIO OFF用
' R6 WAITカウンタ
' R7 掛け算用
PUSH {LR,R4,R5,R6,R7} ' レジスタ保存
CPSID ' 割り込み禁止
' R0 MSBから16bit送るデータ
R3=#50 ' OUT1 の address PIO1_0
R3=R3<<8
R3+=1
R3=R3<<16
R3+=`00000100 'GPIO1_0
R4=1 'GPIOオン用
R5=0 'GPIOオフ用
GOSUB @SEND_START_STOP
R2=1 ' カウンタ 16bit分
R2=R2<<15 ' MSBからスタート
@LOOP
GOSUB @SEND_ON
R6=156
R7=10*2 ' 0のとき10, 1のとき21 IR cycle
R0&R2
IF 0 GOTO @LOOP_SKIP
R7=21*2
@LOOP_SKIP
R6*=R7
GOSUB @WAIT
R2=R2>>1
IF !0 GOTO @LOOP
GOSUB @SEND_START_STOP
CPSIE ' 割り込み許可
POP {PC,R4,R5,R6,R7} ' RET
@SEND_START_STOP
PUSH {LR}
GOSUB @SEND_ON
R7=39*2
R6=156
R6*=R7
GOSUB @WAIT
POP {PC}
@SEND_ON ' use R1
PUSH {LR}
R1=6
@SEND_ON_LOOP
' len in duty 1/2, 48_000_000 / 38_000 / 2 = 631(cycle), (631 - 2 - 1 - 3) / 4 = 156.25
[R3]L=R4 ' 2cycle
R6=156 ' 1cycle
GOSUB @WAIT ' 3cycle
[R3]L=R5
R6=156 ' 1cycle
GOSUB @WAIT
R1-=1
IF !0 GOTO @SEND_ON_LOOP
POP {PC}
@WAIT 'use R6, 4*R6+1 (cycles)
R6-=1 ' 1 cycle
IF !0 GOTO -1 ' 分岐するとき3、しないとき1cycle
RET ' 3cycle
ひさびさのマシン語。サブルーチン内で更にGOSUBで呼び出すときには、LR(R14、リンクレジスタ)を PUSH {LR} で、保存する必要があることを忘れていました。RETの代わりに POP {PC}。
links
- レジスタ不足に上位レジスタとスタック操作 / IchigoJamではじめるArmマシン語その12