;----------------------------------------------------- ; マトリクスLED 8X8 worm_v2 ;----------------------------------------------------- ; ; ;----------------------------------------------------- ; I/Oポート ; (1). RA0?2 [out] : 74LS138(A-C) CLUM ; (2). RB0?7 [out] : 74LS245(b0-b7)ROW ; (3). RA3 [out] : 表示 0=green 1=red :割り込みで使用 ; (4). RA4 [out] : 空 ; ; ;----------------------------------------------------- ;----------------------------------------------------- ; デバイス定義 ;----------------------------------------------------- LIST P=PIC16F84A INCLUDE "P16F84A.INC" __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC ;コードプロテクトOFF、ウォッチドッグタイマOFF、パワーアップタイマOFF、クロック発振モードHS(セラミック4-20MHz) ;------------------------------------------------------ ; 変数レジスタの定義(BANK0) ;------------------------------------------------------ DSPBUFG EQU 00CH ; 表示バッファ緑 8バイト(0CH?13H, 14H) ; ; 14HはLEDなし(スクロール時の次の列データ) ; DSPBUFR EQU 015H ; 表示バッファ赤 8バイト(15H?1CH, 1DH) ; ; 1DHはLEDなし(スクロール時の次の列データ) LEDCHG EQU 01FH ; 緑、赤LED切り替えフラグ  0:緑  1:赤  割り込み用 ROWCNT EQU 020H ; マトリックスLEDのROWカウンタ FLAG EQU 021H ; 各種フラグ 0ビット:LED点灯:1,消灯:0 ; 1ビット:BR-ON:1,OFF:0 ; 2ビット: ; 3ビット:LED赤制御:1,LED緑制御:0 BKUPW EQU 022H ; Wレジ待避用 BKUPS EQU 023H ; STATUSレジ待避用 BKUPFR EQU 024H ; FSRレジ待避用 BKUPPCL EQU 025H ; PCLHレジ待避用 BKPORTA EQU 026H ; PORTA状態(ビープ音用) ; POSX EQU 027H ; LED座標X POSY EQU 028H ; LED座標Y ; WCNT1 EQU 029H ; ウェイトカウンタ WCNT2 EQU 02AH ; ウェイトカウンタ WCNT3 EQU 02BH ; ウェイトカウンタ BCNT1 EQU 02CH ; ビープ用 BWCNT1 EQU 02DH ; ビープ用 ; WMBODY EQU 030H ; ワーム胴体 5バイト(30H?34H) ; 各1バイトの上位4bit:X座標,下位4bit:Y座標 NOWDIR EQU 036H ; ワームの頭が向かっている方向 ; NXTPOSX EQU 037H ; 次にワームの頭が移る位置X座標 NXTPOSY EQU 038H ; 次にワームの頭が移る位置Y座標 NXTDIR EQU 039H ; 次にワームの頭が向かう方向 ; WKPOSX EQU 03AH ; 作業用X座標 WKPOSY EQU 03BH ; 作業用Y座標 WK1 EQU 03CH ; 作業用 WK2 EQU 03DH ; 作業用 ; RNDVAL EQU 03EH ; 乱数 WDCNT EQU 03FH ; ワッチドッグカウンタ(袋小路脱出用) SPCNT EQU 040H ; スピード(Wait時間再計算カウンタ) SPDAT EQU 041H ; スピード(Wait時間) ; MOVCNT EQU 042H ; 移動カウンタ ; ;--------------------------------------------------------------------- ; マクロ定義 ;--------------------------------------------------------------------- BANK0 MACRO BCF STATUS,RP0 ;BANK0に切り替える BCF STATUS,RP1 ; ENDM BANK1 MACRO BSF STATUS,RP0 ;BANK1に切り替える BCF STATUS,RP1 ; ENDM BANK2 MACRO BCF STATUS,RP0 ;BANK2に切り替える BSF STATUS,RP1 ; ENDM ; ;------------------------------------------------------ ; 割り込みベクタ ;------------------------------------------------------ ORG 0 GOTO MAIN ORG 4 GOTO INTRPT ORG 08H ;--------------------------------------------------------------------- ; メイン処理 ;--------------------------------------------------------------------- MAIN CALL INIT ; 初期化 MAINLOOP INCF MOVCNT,F CALL SETSPEED ; スピード設定 CALL WAIT CALL NXTPOS ; 次の方向と座標決定 CALL MOVWORM ; ワーム移動 GOTO MAINLOOP ; ;--------------------------------------------------------------------- ; 初期化 ;--------------------------------------------------------------------- INIT BCF INTCON,GIE ;Interrupt Disable BSF STATUS,RP0 ;Set page 1 CLRF TRISA ;ポートA 0-4 OUTPUT CLRF TRISB ;ポートB 0-7 OUTPUT ; 割り込みタイマーセット MOVLW 081H ;プリスケーラを4倍にセット MOVWF OPTION_REG ;TIMER mode set BCF STATUS,RP0 ; ; CLRF PORTA ; PORTクリア CLRF PORTB ; CLRF ROWCNT ; LED ROWカウンタクリア CALL CLRDPBUF ; LEDバッファクリア CALL RANDINT ; 乱数初期化 CLRF FLAG ; 各種フラグクリア CLRF MOVCNT ; 移動カウンタ CLRF LEDCHG ; 色切り替えフラグクリア  0=緑 ; CLRF TMR0 ;RTCC timer clear BSF INTCON,T0IE ; タイマ0割り込みイネーブル BSF INTCON,GIE ; 割り込み許可 ; CALL SETSPINT ; スピード設定の初期化 CALL FPOSDIR ; 最初の位置と方向を決める RETURN ; ;-------------------------------- ; 割り込み処理 ;-------------------------------- INTRPT MOVWF BKUPW ;Wレジスタのセーブ SWAPF STATUS,W ;STATUSのセーブ MOVWF BKUPS MOVF FSR,W ;FSRのセーブ MOVWF BKUPFR ; BCF INTCON,T0IF ; 割り込みフラグリセット ; ;緑LEDの表示 ; DSPLEDG BTFSC LEDCHG,0 ; 0であったら次命令スキップ GOTO DSPLEDR ; 赤表示へ ; MOVLW DSPBUFG ; 表示バッファの先頭アドレス ADDWF ROWCNT,W ; 現在の列カウンタを足す MOVWF FSR ; FSR にアドレスをセット MOVF INDF,W ; 該当パターンを読み出す MOVWF PORTB ; PortBに出力 ; MOVF ROWCNT,W ; IORLW 000H ; MOVWF PORTA ; 列カウンタ値をポートAへ出力 ; INCF ROWCNT,F ; 列カウンタ +1 MOVLW 08H ; SUBWF ROWCNT,W ; カウンタが8か比較 BTFSS STATUS,Z ; ゼロフラグが1なら次命令をスキップ GOTO POPRTN CLRF ROWCNT ; カウンタが8ならば0クリア(ROWは0-7) MOVLW 01H ; MOVWF LEDCHG ; 赤LED表示フラグセット GOTO POPRTN ; ; ;赤LEDの表示 ; DSPLEDR MOVLW DSPBUFR ; 表示バッファの先頭アドレス ADDWF ROWCNT,W ; 現在の列カウンタを足す MOVWF FSR ; FSR にアドレスをセット MOVF INDF,W ; 該当パターンを読み出す MOVWF PORTB ; PortBに出力 ; MOVF ROWCNT,W ; IORLW 08H ; MOVWF PORTA ; 列カウンタ値をポートAへ出力 ; INCF ROWCNT,F ; 列カウンタ +1 MOVLW 08H ; SUBWF ROWCNT,W ; カウンタが8か比較 BTFSS STATUS,Z ; ゼロフラグが1なら次命令をスキップ GOTO POPRTN CLRF ROWCNT ; カウンタが8ならば0クリア(ROWは0-7) CLRF LEDCHG ; 赤LED表示フラグリセット(緑ACTへ) GOTO POPRTN ; ; POPRTN MOVF BKUPFR,W ;FSRの取り出し MOVWF FSR SWAPF BKUPS,W ;STATUSの取り出し MOVWF STATUS SWAPF BKUPW,F ;Wレジスタの取り出し SWAPF BKUPW,W RETFIE ; ;--------------------------------------------------------------------- ; スピード(遅延時間)設定 ;--------------------------------------------------------------------- SETSPINT MOVLW D'1' MOVWF SPCNT SETSPEED DECFSZ SPCNT,F RETURN ; CALL RANDOM ; 1?255の乱数 ANDLW H'07' ; 1?7の範囲を取り出す MOVWF SPCNT ; 速度変更までのカウンタ BCF STATUS,C RLF SPCNT,F RLF SPCNT,F RLF SPCNT,F ; 8,16,24,32,40,48,56の7段階 MOVF SPCNT,W SUBLW D'255' ; 80 - SPCNT MOVWF SPDAT ; 24?72 RETURN ; ;--------------------------------------------------------------------- ; Wレジ値をビット位置にデコード ;--------------------------------------------------------------------- DECBIT CLRF PCLATH ADDWF PCL,F DECBIT1 RETLW B'00000001' ;0 RETLW B'00000010' ;1 RETLW B'00000100' ;2 RETLW B'00001000' ;3 RETLW B'00010000' ;4 RETLW B'00100000' ;5 RETLW B'01000000' ;6 RETLW B'10000000' ;7 ; ;--------------------------------------------------------------------- ; M系列乱数(1?255) ;--------------------------------------------------------------------- RANDINT MOVLW B'00101010' ; MOVLW B'00000001' MOVWF RNDVAL RANDOM MOVF RNDVAL,W MOVWF WK1 RRF WK1,F RRF WK1,F XORWF WK1,W RRF WK1,F RRF WK1,F XORWF WK1,W RRF WK1,F RRF WK1,F RRF WK1,F XORWF WK1,F BCF STATUS,C BTFSC WK1,0 BSF STATUS,C RLF RNDVAL,F MOVF RNDVAL,W ; XORWF TMR0,W XORWF MOVCNT,W RETURN ; ;--------------------------------------------------------------------- ; LEDの指定座標を点灯(Wレジ上位4ビット:X座標、下位4ビット:Y座標) ; ; DSPBUF_H 1 2 3 4 5 6 7 ; ○○○○○○○○ 7 ; ○○○○○○○○ 6 3 ; ○○○○○○○○ 5 ↑ ; ○○○○○○○○ 4 方向 0 ←○→2 ; ○○○○○○○○ 3 ↓ ; ○○○○○○○○ 2 1 ; ○○○○○○○○ 1 ; ○○○○○○○○ 0:Y(ROW) ; 0 1 2 3 4 5 6 7:X(COL) ;------------------------------------------------------------ ; ; OUTPUT:NXTPOSX ; NXTPOSY ; NXTDIR ;------------------------------------------------------------- NXTPOS MOVLW D'5' MOVWF WDCNT NXTPOS1 ; MOVLW 001H ; CALL RANDOM ; 乱数を得る MOVWF WK2 BTFSS WK2,2 GOTO NXTPOS2 MOVF NOWDIR,W MOVWF NXTDIR GOTO CLCPOS ; ; NXTPOS2 ANDLW H'03' ; 下位2ビット採用 MOVWF NXTDIR ; 下位2ビットをNXTDIRへ ; ; 現在の方向と比べ、逆方向なら現在の方向 ; ANDLW H'02' ; 1ビット目のみ取り出す XORLW H'02' ; 1ビット目が1なら0,1なら0  XOR MOVWF WK2 ; 結果をWK2へ MOVF NXTDIR,W ; NXTDIR→W ANDLW H'01' ; 下位1ビット採用 IORWF WK2,F ; これが次の方向と逆方向。 MOVF NOWDIR,W ; SUBWF WK2,W ;現在方向と次方向の逆方向の比較 BTFSS STATUS,Z ; GOTO CLCPOS ;等しくない時 MOVF NOWDIR,W ;等しいとき MOVWF NXTDIR ;現在の方向を次方向へ代入 CLCPOS MOVF WMBODY,W ; ワームボディアドレス ANDLW H'0F' ; 上位4ビットマスク MOVWF NXTPOSY ; Y座標(ビット位置) ; SWAPF WMBODY,W ; ワームボディアドレス、上位下位入れ替え ANDLW H'0F' ; 上位4ビットマスク MOVWF NXTPOSX ; X座標(ビット位置) ; ;次の方向のチェック ; ; 0の時 ← ; NXTDIR_H MOVF NXTDIR,W ; BTFSS STATUS,Z ; GOTO DIR_R ; MOVF NXTPOSX,F ; BTFSC STATUS,Z ; X=0の時 ; GOTO NXTPOS1 ; 行けない方向なので再度方向選定 GOTO NXTPOSD ; 考えるパフォーマンスが不要の時、NXTPOS1へジャンプ DECF NXTPOSX,F ; 0でなければ NXTPOSX-1 GOTO CHKNXT ; ; ; 2の時 → ; DIR_R MOVF NXTDIR,W ; SUBLW D'2' ; BTFSS STATUS,Z ; GOTO DIR_U ; 0でなければ’→’へ MOVF NXTPOSX,W ; SUBLW D'7' ; BTFSC STATUS,Z ; X=7の時 ; GOTO NXTPOS1 ; 行けない方向なので再度方向選定 GOTO NXTPOSD ; 考えるパフォーマンスが不要の時、NXTPOS1へジャンプ INCF NXTPOSX,F ; 7でなければ NXTPOSX+1 GOTO CHKNXT ; ; ; 3の時 ↑ ; DIR_U MOVF NXTDIR,W ; SUBLW D'3' ; BTFSS STATUS,Z ; GOTO DIR_D ; MOVF NXTPOSY,W ; SUBLW D'7' ; BTFSC STATUS,Z ; Y=7の時 ; GOTO NXTPOS1 ; 行けない方向なので再度方向選定 GOTO NXTPOSD ; 考えるパフォーマンスが不要の時、NXTPOS1へジャンプ INCF NXTPOSY,F ; GOTO CHKNXT ; ; ; 1の時 ↓ ; DIR_D MOVF NXTPOSY,F ; BTFSC STATUS,Z ; Y=0の時? ; GOTO NXTPOS1 ; 行けない方向なので再度方向選定 GOTO NXTPOSD ; 考えるパフォーマンスが不要の時、NXTPOS1へジャンプ DECF NXTPOSY,F ; ; ;------------------------------------------------ ;「例」 ;●●○ ;●◎○ ;●○○ ;○○○ ;頭が0←の方向になった時の判定 ;------------------------------------------------ CHKNXT SWAPF NXTPOSX,W ; IORWF NXTPOSY,W ; 次のX座標とY座標 SUBWF WMBODY+3,W ; WORM本体頭から4番目と重なる? BTFSS STATUS,Z ; RETURN ; 重ならない DECFSZ WDCNT,F ; 重なるのでワッチドックデクリメント ; GOTO NXTPOS1 ; 行けない方向なので再度方向選定 GOTO NXTPOSD ; 考えるパフォーマンスが不要の時、NXTPOS1へジャンプ RETURN ; 5回だめなら袋小路なので抜ける ; ;どっちに行こうか考えるパフォーマンス ;行けない方向で再度方向選定をする時に頭の赤が点滅する NXTPOSD CALL WAIT10MS CALL WAIT10MS CALL WAIT10MS CALL WAIT10MS ; MOVF WMBODY,W ; 先頭を消灯 BSF FLAG,3 ; 赤LED設定 CALL TURNOFF ; 赤LED点灯 ; CALL WAIT10MS CALL WAIT10MS CALL WAIT10MS CALL WAIT10MS ; MOVF WMBODY,W ; 旧頭の赤を点灯 BSF FLAG,3 ; 赤LED設定 CALL TURNON ; 赤LED消灯 ; CALL WAIT10MS CALL WAIT10MS CALL WAIT10MS CALL WAIT10MS ; GOTO NXTPOS1 ;--------------------------------------------------------------------- ; ; 位置を一つづつ後ろへずらし、表示する ; ;--------------------------------------------------------------------- MOVWORM MOVF NXTDIR,W ; MOVWF NOWDIR ; MOVF WMBODY+4,W ;最後尾 MOVWF WMBODY+5 ; MOVF WMBODY+3,W ;最後尾 MOVWF WMBODY+4 ; MOVF WMBODY+2,W ; MOVWF WMBODY+3 ; MOVF WMBODY+1,W ; MOVWF WMBODY+2 ; MOVF WMBODY,W ; MOVWF WMBODY+1 ; ; SWAPF NXTPOSX,W ; IORWF NXTPOSY,W ; 次のX座標とY座標 MOVWF WMBODY ; 頭 ; ;表示バッファへ書き込み MOVF WMBODY,W ; 先頭を点灯 BSF FLAG,3 ; 赤LED設定 CALL TURNON ; 赤LED点灯 ; MOVF WMBODY+1,W ; 旧頭の赤を消灯 BSF FLAG,3 ; 赤LED設定 CALL TURNOFF ; 赤LED消灯 ; MOVF WMBODY+1,W ; ワーム本体アドレス+1 BCF FLAG,3 ; 二番目の緑を設定 CALL TURNON ; 緑LED点灯 ; ;尻を消す MOVF WMBODY+5,W ; ワーム本体アドレス+5 BCF FLAG,3 ; 緑LED設定 CALL TURNOFF ; 尻(緑)を消灯 RETURN ; ;--------------------------------------------------------------------- ; 最初の出現位置と方向を決める(X:7, Y:0, DIR:2) ;--------------------------------------------------------------------- FPOSDIR MOVLW H'70' ; 座標 X=7,Y=0 MOVWF WMBODY ; BSF FLAG,3 ; 赤LED設定 CALL TURNON ; 頭点灯 ; MOVLW D'2' ;移動方向 → の設定 MOVWF NOWDIR ; ; RETURN ; ;-------------------------------------------- ; ; LED指定座標の点灯、消灯 ; ;-------------------------------------------- ; TURNON BCF INTCON,T0IF ; 割り込みフラグリセット BSF FLAG,0 ; 点灯 GOTO $+2 TURNOFF BCF FLAG,0 ; 消灯 ; MOVWF POSY ; SWAPF POSY,W ; ANDLW H'0F' ; 上位4ビットマスク MOVWF POSX ; X座標(ビット位置) MOVLW H'0F' ANDWF POSY,F ; Y座標(バイト位置) ; BTFSC FLAG,3 ; 赤1 or 緑0 GOTO TURNA ; 赤バッファ制御へ MOVLW DSPBUFG ; 緑バッファの先頭アドレス GOTO TURNB ; TURNA MOVLW DSPBUFR ; 赤バッファの先頭アドレス TURNB ADDWF POSY,W ; Y座標加算 MOVWF FSR ; インデックスレジスタへ格納 ; MOVF POSX,W CALL DECBIT ; ビット位置に変換 ; BTFSS FLAG,0 ; 点灯1 or 消灯0 GOTO TURNOFF2 IORWF INDF,F ; 指定位置を表示ON BSF INTCON,GIE ; 割り込み許可 RETURN TURNOFF2 XORLW H'FF' ; ビット位置を反転しマスク ANDWF INDF,F ; 指定位置を表示OFF BSF INTCON,GIE ; 割り込み許可 RETURN ; ;--------------------------------------------------------------------- ; 表示用バッファクリア ;--------------------------------------------------------------------- CLRDPBUF CLRF DSPBUFG ; LED BUFG 緑表示エリアクリア CLRF DSPBUFG+1 ; CLRF DSPBUFG+2 ; CLRF DSPBUFG+3 ; CLRF DSPBUFG+4 ; CLRF DSPBUFG+5 ; CLRF DSPBUFG+6 ; CLRF DSPBUFG+7 ; CLRF DSPBUFG+8 ; ; CLRF DSPBUFR ; LED BUFR 赤表示エリアクリア CLRF DSPBUFR+1 ; CLRF DSPBUFR+2 ; CLRF DSPBUFR+3 ; CLRF DSPBUFR+4 ; CLRF DSPBUFR+5 ; CLRF DSPBUFR+6 ; CLRF DSPBUFR+7 ; CLRF DSPBUFR+8 ; RETURN ; ;----------------------------------------------- ; Waitルーチン ;----------------------------------------------- WAIT1MS MOVLW D'250' MOVWF WCNT1 W1MSLP ; NOP ; NOP ; NOP NOP NOP NOP NOP DECFSZ WCNT1,F GOTO W1MSLP RETURN ; WAIT10MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS RETURN WAIT01S ;0.1秒 MOVLW D'97' MOVWF WCNT2 W01SLP CALL WAIT1MS DECFSZ WCNT2,F GOTO W01SLP RETURN ; WAIT025S ;0.25秒 MOVLW D'242' MOVWF WCNT3 W025SLP CALL WAIT1MS DECFSZ WCNT3,F GOTO W025SLP RETURN ; WAIT ; ワームの移動スピードを決める待ち時間 MOVF SPDAT,W MOVWF WCNT2 WAITLP CALL WAIT1MS DECFSZ WCNT2,F GOTO WAITLP NOP RETURN ; ; ;--------------------------------------------------------------------- END ;--------------------------------------------------------------------- ; 終わり ;---------------------------------------------------------------------