;
; Micro Scout リモコン
;  for LEGO MINDSTORMS DDK
;
;  PIC16F84@10MHz
;
; 本プログラムはレゴ・マインドストームシリーズ Droid Developer Kitの
; Micro Scout(マイクロスカウト)の操作およびスクリプトプログラミングを
; 行うためのリモコン用です。
; 本ソースは秋月のPA.EXE拡張インストラクションを使用しております。
;   2000.12 (c) RUU
;
; 変更履歴
;       2001.01.12 (1.2) ra.2=通常LED、ra.3=赤外線LEDに分ける
;       2000.12.30 (1.1) 赤外線送信モード追加
;       2000.12.28 (1.0) 最初のバージョン
;

            .include    16F84.h
            .osc        hs
            .wdt        off
            .pwrt       on
            .protect    off

RS          equ     ra.0
E           equ     ra.1
LED         equ     ra.2
IR_LED      equ     ra.3
SW_PREV     equ     rb.4
SW_NEXT     equ     rb.5
SW_SEND     equ     rb.6
SW_MODE     equ     rb.7

            org     0ch
cmd_id      ds  1           ; コマンド番号 0 to 27
vll_code    ds  1           ; VLLコード・データ部
c_sum       ds  1           ; VLLコード・チェックサム
bit_buf     ds  1           ; bit送信用バッファ
ir_mode     ds  1           ; 赤外線モード(キャリア有無 0:変調なし 1:38kHz)
cnt         ds  1           ; カウンタ
work        ds  1
p_ptr       ds  1           ; pcl待避用

tx          ds  1           ; LCDカーソル x
ty          ds  1           ; LCDカーソル y
d4          ds  1           ; LCD送信データ
d8          ds  1
wait_cn     ds  1           ; waitカウンタ
wait_cn2    ds  1


            org     0
            goto    main
            org     4
            goto    main

;;;;;;;;;;;;;;;; モード表示msg ;;;;;;;;;;;;;;;;
mode_tbl
            jmp     pc+w
            retw    'DirectMode  [  ]'
            retw    'ScriptMode  [  ]'
;           retw    'ﾀﾞｲﾚｸﾄﾓｰﾄﾞ  [  ]'
;           retw    'ﾌﾟﾛｸﾞﾗﾑﾓｰﾄﾞ [  ]'

;;;;;;;;;;;;;;;; VLLコードテーブル ;;;;;;;;;;;;;;;;
vll_tbl
            jmp     pc+w
            retw    33      ;  0 D:Run
            retw    0       ;  1 D:Motor Forward
            retw    1       ;  2 D:Motor Reverse
            retw    4       ;  3 D:Beep 1
            retw    5       ;  4 D:Beep 2
            retw    6       ;  5 D:Beep 3
            retw    7       ;  6 D:Beep 4
            retw    8       ;  7 D:Beep 5
            retw    10      ;  8 D:Motor Stop
            retw    34      ;  9 D:Delete Script
            retw    255     ; 10 D:Emit Light(Not VLL)
            retw    16      ; 11 S:Motor Forward 0.5
            retw    17      ; 12 S:Motor Forward 1.0
            retw    18      ; 13 S:Motor Forward 2.0
            retw    19      ; 14 S:Motor Forward 5.0
            retw    20      ; 15 S:Motor Reverse 0.5
            retw    21      ; 16 S:Motor Reverse 1.0
            retw    22      ; 17 S:Motor Reverse 2.0
            retw    23      ; 18 S:Motor Reverse 5.0
            retw    24      ; 19 S:Beep 1
            retw    25      ; 20 S:Beep 2
            retw    26      ; 21 S:Beep 3
            retw    27      ; 22 S:Beep 4
            retw    28      ; 23 S:Beep 5
            retw    29      ; 24 S:Wait for Light
            retw    30      ; 25 S:Seek Light
            retw    31      ; 26 S:Code
            retw    32      ; 27 S:Keep Alive

;;;;;;;;;;;;;;;; main ;;;;;;;;;;;;;;;;
main
            mov     !ra,#00000000b          ; OUT
            mov     !rb,#11110000b          ; SWをINに
            clr     ra
            clr     rb
            setb    rp0
            clrb    rbpu                    ; Bポートは内部プルアップ
            clrb    rp0
            mov     intcon,#00001000b       ; Bポート割り込み許可,グローバル割り込み禁止

            clr     cmd_id
            clr     vll_code
            mov     ir_mode,#1
            snb     SW_MODE                 ; 電源ON時、modeキーが押されていたら赤外線モード(38kHzキャリア)
            clr     ir_mode

            call    init_lcd                ; LCD初期化
            call    clr_lcd
            call    disp_mode               ; msg表示
            call    disp_msg

mainloop
            sleep                           ; クロック停止
            nop                             ; Bポート4～7入力変化(キー押下)でウェイクアップ
key_chk
            jnb     SW_SEND,send_cmd        ; キーによる分岐
            jnb     SW_NEXT,id_inc
            jnb     SW_PREV,id_dec
            jnb     SW_MODE,mode_cng
            goto    mainloop

send_cmd                                    ; VLL送信
            mov     w,cmd_id
            call    vll_tbl                 ; idをVLL番号に変換
            mov     vll_code,w
            cje     vll_code,#255,led_on    ; code255はLED点灯のみ
            call    send_vll
            cjae    vll_code,#3,w_sw_off    ; 0,1,以外はSWリリースまで待つ
            goto    key_chk                 ; 0と1はリピート
mode_cng                                    ; Direct/Script切替え
            cjbe    cmd_id,#10,id_11
            goto    id_0
id_inc                                      ; id++
            cje     cmd_id,#10,id_0
            cje     cmd_id,#27,id_11
            inc     cmd_id
            goto    re_dsp
id_dec                                      ; id--
            cje     cmd_id,#0,id_10
            cje     cmd_id,#11,id_27
            dec     cmd_id
            goto    re_dsp
id_0
            clr     cmd_id
            goto    re_dsp
id_10
            mov     cmd_id,#10
            goto    re_dsp
id_11
            mov     cmd_id,#11
            goto    re_dsp
id_27
            mov     cmd_id,#27
re_dsp                                      ; msg再表示
            call    disp_mode
            call    disp_msg
w_sw_off                                    ; SWがoffされるまで待つ
            mov     work,rb
            and     work,#0f0h
            cjne    work,#0f0h,w_sw_off
            mov     wait_cn,#50
            call    wait_ms
            clrb    LED
            goto    mainloop
led_on                                      ; Emit Light
            jb      ir_mode.0,led_on_r
            setb    LED
            goto    w_sw_off
led_on_r
            mov     wait_cn,#255
            call    led_on_38
            jnb     SW_SEND,led_on_r
            goto    mainloop


;;;;;;;;;;;; send_vll ;;;;;;;;;;;;;;
send_vll                                    ; VLL(vll_code)を送信する
            call    create_sum
            mov     wait_cn,#40             ; Start bit
            call    led_on_38
            mov     wait_cn,#10
            call    wait_ms
            mov     bit_buf,c_sum           ; CheckSum
            mov     cnt,#3
            call    send_bit
            mov     bit_buf,vll_code        ; VLL Code
            rl      bit_buf
            mov     cnt,#7
            call    send_bit
            mov     wait_cn,#10             ; Stop bit
            call    led_on_38
            mov     wait_cn,#50
            call    wait_ms
            ret

;;;;;;;;;;;; create_sum ;;;;;;;;;;;;;;
create_sum                                  ; CheckSumを生成する
            mov     c_sum,vll_code          ; sum = 7-(n+n/4+n/16)
            mov     work,vll_code
            rr      work
            rr      work
            add     c_sum,work
            rr      work
            rr      work
            add     c_sum,work
            not     c_sum
            swap    c_sum
            rl      c_sum
            and     c_sum,#0e0h             ; c_sumの7,6,5bitに格納
            ret

;;;;;;;;;;;; send_bit ;;;;;;;;;;;;;;
send_bit                                    ; bit_bufの内容をcntビット分送信する
            rl      bit_buf
            jc      send_1
send_0                                      ; ビット 0
            mov     wait_cn,#20             ; 'H'=20ms
            call    led_on_38
            mov     wait_cn,#10             ; 'L'=10ms
            call    wait_ms
            goto    nxt_bit
send_1                                      ; ビット 1
            mov     wait_cn,#10             ; 'H'=10ms
            call    led_on_38
            mov     wait_cn,#20             ; 'L'=20ms
            call    wait_ms
nxt_bit
            djnz    cnt,send_bit
            ret

;;;;;;;;;;;; led_on_38 ;;;;;;;;;;;;;;
led_on_38                                   ; wait_cn(ms)時間LED点灯or点滅
            jnb     ir_mode.0,on_norm       ; 通常モードは点灯
on_loop1                                    ; 赤外線モードでは38kHz点滅
            mov     work,#38
on_loop2
            setb    IR_LED                      ; ON = 33cycle(13.2us)
            mov     wait_cn2,#9                 ; 1
on_cnt
            djnz    wait_cn2,on_cnt             ; 29
            nop                                 ; 1
            nop                                 ; 1
            clrb    IR_LED                      ; OFF = 33cycle(13.2us)
            mov     wait_cn2,#8                 ; 1
off_cnt
            djnz    wait_cn2,off_cnt            ; 26
            nop                                 ; 1
            nop                                 ; 1
            djnz    work,on_loop2               ; 3
            djnz    wait_cn,on_loop1        ; ここで誤差が少し出るけど気にしない(^^;
            ret
on_norm
            setb    LED
            call    wait_ms
            clrb    LED
            ret


;;;;;;;;;;;; disp_mode ;;;;;;;;;;;;;;
disp_mode                                   ; モード種別(D/S)をLCD1行目に表示
            mov     tx,#0
            mov     ty,#0
            call    locate
            clr     p_ptr
            cjbe    cmd_id,#10,mode_d1      ; コマンド番号10まではDirect
            mov     p_ptr,#16               ; 11以上はScript
mode_d1
            mov     cnt,#16
            setb    RS
m_loop
            mov     w,p_ptr
            call    mode_tbl
            mov     d4,w
            call    write_lcd4
            inc     p_ptr
            djnz    cnt,m_loop
            jb      ir_mode.0,disp_r
            ret
disp_r                                      ; 赤外線モードは 'R'表示
            mov     tx,#11
            mov     ty,#0
            call    locate
            setb    RS
            mov     d4,#'R'
            call    write_lcd4
            ret

;;;;;;;;;;;; disp_msg ;;;;;;;;;;;;;;
disp_msg                                    ; コマンド名と番号をLCDに表示
            mov     p_ptr,cmd_id
            cjbe    p_ptr,#13,set_ptr       ; msg量が多いのでテーブルを分割
            sub     p_ptr,#14               ; 14msg毎
set_ptr
            swap    p_ptr
            mov     tx,#13
            mov     ty,#0
            call    locate
            mov     cnt,#2
            call    msg_sub                 ; 番号(2桁)を表示
            mov     tx,#0
            mov     ty,#1
            call    locate
            mov     cnt,#14
            call    msg_sub                 ; コマンド名(14桁)を表示
            mov     pclath,#0
            ret

msg_sub                                     ; 表示サブルーチン
            setb    RS                      ; cnt文字数分を表示
s_loop
            cjae    cmd_id,#14,str_2
str_1
            mov     w,p_ptr
            call    message1
            mov     d4,w
            goto    c_write
str_2
            mov     w,p_ptr
            call    message2
            mov     d4,w
c_write
            call    write_lcd4
            inc     p_ptr
            djnz    cnt,s_loop
            ret


;;;;;;;;;;;;;;;; LCD制御 ;;;;;;;;;;;;;;;;

init_lcd
            mov     wait_cn, #15
            call    wait_ms
            clrb    RS
            mov     d8, #00110000b
            call    write_lcd8
            mov     wait_cn,#5
            call    wait_ms
            mov     d8, #00110000b
            call    write_lcd8
            mov     wait_cn,#100
            call    wait_us
            mov     d8, #00110000b
            call    write_lcd8
            mov     d8, #00100000b
            call    write_lcd8
            mov     d4, #00101000b
            call    write_lcd4
            mov     d4, #00000001b
            call    write_lcd4
            mov     wait_cn,#2
            call    wait_ms
            mov     d4, #00000110b
            call    write_lcd4
            mov     d4, #00001100b  ; cursor off
            call    write_lcd4
            ret


clr_lcd
            clrb    RS
            mov     d4, #00000001b
            call    write_lcd4
            mov     wait_cn,#2
            call    wait_ms
            ret

locate
            cje     ty,#1,loc_1
            mov     d4,#080h
            goto    loc_e
loc_1
            mov     d4,#0c0h
loc_e
            add     d4,tx
            clrb    RS
            call    write_lcd4
            ret


write_lcd8
            swap    d8
            and     d8,#00001111b
            and     rb,#11110000b
            or      rb,d8
            nop
            setb    E
            nop
            clrb    E
            mov     wait_cn,#40
            call    wait_us
            ret


write_lcd4
            mov     d8,d4
            call    write_lcd8
            mov     d8,d4
            swap    d8
            call    write_lcd8
            ret

;;;;;;;;;;;;;;;; wait ;;;;;;;;;;;;;;;;

wait_ms
wait_ms0
            mov     wait_cn2,#0
wait_ms1
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            djnz    wait_cn2,wait_ms1
            djnz    wait_cn,wait_ms0
            ret

wait_us
wait_us0
            djnz    wait_cn,wait_us0
            ret


;;;;;;;;;;;;;;;; メッセージテーブル ;;;;;;;;;;;;;;;;

            org     200h
message1                                    ; テーブルはPCL範囲内(256ワード以内)で分割
            mov     pclath,#2
            mov     w,p_ptr
            jmp     pc+w
            retw    '01Run           '
            retw    '02Motor Forward '
            retw    '03Motor Reverse '
            retw    '04Beep 1        '
            retw    '05Beep 2        '
            retw    '06Beep 3        '
            retw    '07Beep 4        '
            retw    '08Beep 5        '
            retw    '09Motor Stop    '
            retw    '10Delete Script '
            retw    '11Emit Light    '
            retw    '01Forward 0.5   '
            retw    '02Forward 1.0   '
            retw    '03Forward 2.0   '

;           retw    '01*ｼﾞｯｺｳ        '
;           retw    '02*ﾏｴ ﾆ ｽｽﾑ     '
;           retw    '03*ｳｼﾛ ﾆ ﾓﾄﾞﾙ   '
;           retw    '04*ﾌﾞｻﾞｰ No.1   '
;           retw    '05*ﾌﾞｻﾞｰ No.2   '
;           retw    '06*ﾌﾞｻﾞｰ No.3   '
;           retw    '07*ﾌﾞｻﾞｰ No.4   '
;           retw    '08*ﾌﾞｻﾞｰ No.5   '
;           retw    '09*ﾌﾞﾚｰｷ        '
;           retw    '10*ﾌﾟﾛｸﾞﾗﾑ ｻｸｼﾞｮ'
;           retw    '11*ｶｲﾁｭｳﾃﾞﾝﾄｳ   '
;           retw    '01*ﾏｴ ﾆ 0.5     '
;           retw    '02*ﾏｴ ﾆ 1.0     '
;           retw    '03*ﾏｴ ﾆ 2.0     '

            org     300h
message2
            mov     pclath,#3
            mov     w,p_ptr
            jmp     pc+w
            retw    '04Forward 5.0   '
            retw    '05Reverse 0.5   '
            retw    '06Reverse 1.0   '
            retw    '07Reverse 2.0   '
            retw    '08Reverse 5.0   '
            retw    '09Beep 1        '
            retw    '10Beep 2        '
            retw    '11Beep 3        '
            retw    '12Beep 4        '
            retw    '13Beep 5        '
            retw    '14Wait for Light'
            retw    '15Seek Light    '
            retw    '16Code          '
            retw    '17Keep Alive    '

;           retw    '04*ﾏｴ ﾆ 5.0     '
;           retw    '05*ｳｼﾛ ﾆ 0.5    '
;           retw    '06*ｳｼﾛ ﾆ 1.0    '
;           retw    '07*ｳｼﾛ ﾆ 2.0    '
;           retw    '08*ｳｼﾛ ﾆ 5.0    '
;           retw    '09*ﾌﾞｻﾞｰ No.1   '
;           retw    '10*ﾌﾞｻﾞｰ No.2   '
;           retw    '11*ﾌﾞｻﾞｰ No.3   '
;           retw    '12*ﾌﾞｻﾞｰ No.4   '
;           retw    '13*ﾌﾞｻﾞｰ No.5   '
;           retw    '14*ﾋｶﾘ ｦ ﾏﾂ     '
;           retw    '15+ﾋｶﾘ ｦ ｻｶﾞｽ   '
;           retw    '16+ｱﾝｺﾞｳ        '
;           retw    '17+ｲｷﾉｺﾘ        '

;;;;;;;;;;;;;;;;;;; おしまい ;;;;;;;;;;;;;;;;;;;;;;
