;--------------------------------------------------------------------- ; フリスクケースでペントミノを解く ; 2011.2.11 naka ; ; PIC16F887 (20MHz) ; ; (1). RD0〜7,RE0〜1 [out] : 列(スキャン)LEDアノード(ドライブTr)側 ; (2). RA0〜5,RB0〜5,RC0〜5 [out] : 行(各ポートR,G,B) LEDカソード側 ; (3). RE2 [in] : タクトスイッチ ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ; デバイス定義 ;--------------------------------------------------------------------- LIST P=PIC16F887 INCLUDE "P16F887.INC" __CONFIG _CONFIG1, _DEBUG_OFF & _LVP_OFF & _MCLRE_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC __CONFIG _CONFIG2 ERRORLEVEL -302 ;アセンブル時のバンク警告メッセージ抑制 ;--------------------------------------------------------------------- ; 変数レジスタの定義(BANK0) ;--------------------------------------------------------------------- BOARD EQU 020H ;ピースを置く盤面 20H〜4AH(43バイト) ;各バイトを4bitずつ使用 | 1 | 0 | ; | 3 | 2 | SWTIML EQU 04BH ; タクトスイッチの押されている時間カウンタ SWTIMH EQU 04CH ; 〃 上位バイト ODDEVN EQU 04DH OFFSET EQU 04EH BUFF EQU 04FH ; データの読み書き用 CNT EQU 050H WK EQU 051H GETUSE EQU 052H USENO EQU 053H TMP EQU 054H OFFSETP EQU 055H USEPCEL EQU 056H ;使用済みピース管理(__654321) USEPCEH EQU 057H ; 〃 (__CBA987) SUF_X EQU 058H DIR_NO EQU 059H ROWCNT EQU 05AH ; 列カウンタ(0〜19; 1列あたり2(PWM)) PWMCNT EQU 05BH WAIT1 EQU 05CH WAIT2 EQU 05DH FLAG0 EQU 05EH ; 0ビット:空き ; 1ビット:空き ; 2ビット:実行モード(0:step, 1:cont) ; 3ビット:モード切替トリガ(1:on) ; 4ビット:前回のスイッチの状態(0:off, 1:on) ; 5ビット:割り込み時のbank=0 ; 6ビット:割り込み時のbank=1 ; 7ビット:割り込み時のbank=2 BKUPW EQU 060H ;Wレジ待避用 BKUPS EQU 061H ;STATUSレジ待避用 BKUPFR EQU 062H ;FSRレジ待避用 BKUPPCL EQU 063H ;PCLHレジ待避用 SOLNO1 EQU 064H SOLNO2 EQU 065H SOLNO3 EQU 066H SOLNO4 EQU 067H ; BANK間共通(70-7F) SUF_I EQU 070H SUF_J EQU 071H SUF_K EQU 072H POS EQU 073H DIRNUM EQU 074H ;ピースの方向数 WKPCE0 EQU 075H ;取り出したピース座標(一時記憶) WKPCE1 EQU 076H ;取り出したピース座標(一時記憶) WKPCE2 EQU 077H ;取り出したピース座標(一時記憶) WKPCE3 EQU 078H ;取り出したピース座標(一時記憶) STACKP EQU 079H ROWDECL EQU 07AH ROWDECH EQU 07BH FLAG EQU 07CH ; 0ビット:set/unset ; 1ビット:ゼロサプレス ; 最後は 07FH ;--------------------------------------------------------------------- ; 変数レジスタの定義(BANK1) ;--------------------------------------------------------------------- BUFF1 EQU 0A0H ; データの読み書き用 BRDWK1 EQU 0A1H OFFSET1 EQU 0A2H CNT1 EQU 0A3H LINCNT EQU 0A4H WK1 EQU 0A5H TMP1 EQU 0A7H ; ; 0A8Hから0EFHはSTACKに利用 ; 0A8H ;A8H〜EFH(72バイト) STACK EQU 0EFH ;stack先頭 ; ;--------------------------------------------------------------------- ; 変数レジスタの定義(BANK2) ;--------------------------------------------------------------------- LEDBUF EQU 0120H ; 0120H〜015BH:60バイト ; 1列あたりRGB 3バイト×2(PWM) = 6バイト ; 0H: Red0 暗い赤 ; 1H: Green0 暗い緑 ; 2H: Blue0 暗い青 ; 3H: Red1 赤 ; 4H: Green1 緑 ; 5H: Blue1 青 ; ... LEDBUFR EQU 0159H ; R LEDBUFG EQU 015AH ; G LEDBUFB EQU 015BH ; B ; CNT2 EQU 015CH WK2 EQU 015DH WK3 EQU 015EH COUNT2 EQU 015FH COLOR2 EQU 0160H BITPOS2 EQU 0161H POS2 EQU 0162H PWMFLG EQU 0163H TMP2 EQU 0164H ; ;--------------------------------------------------------------------- ; マクロ定義 ;--------------------------------------------------------------------- BANK0 MACRO BCF STATUS,RP0 ;BANK0に切り替える BCF STATUS,RP1 ; BCF STATUS,IRP ;間接アドレス用 ENDM BANK1 MACRO BSF STATUS,RP0 ;BANK1に切り替える BCF STATUS,RP1 ; BCF STATUS,IRP ;間接アドレス用 ENDM BANK2 MACRO BCF STATUS,RP0 ;BANK2に切り替える BSF STATUS,RP1 ; BSF STATUS,IRP ;間接アドレス用 ENDM BANK3 MACRO BSF STATUS,RP0 ;BANK3に切り替える BSF STATUS,RP1 ; ENDM ;--------------------------------------------------------------------- ; リセット ;--------------------------------------------------------------------- ORG 00H ; リセット時の飛び込み先 RESET GOTO MAIN ; ;--------------------------------------------------------------------- ; 割り込み処理でダイナミック表示を行う。 ; ・約4882Hz(205us)の割り込みで表示バッファを順次ポート出力する。 ; ・タクトスイッチの状態監視も行う ; 通常押しと長押しを判定 ;--------------------------------------------------------------------- ORG 04H ; 割り込み時の飛び込み先 INTRUPT BTFSS STATUS,RP0 ;bankを調べる GOTO INTR02 ;bank0か2 ;bank1なのでbank0に切り替え BANK0 ;bank0に切り替え BSF FLAG0,6 ;元はbank1だったことを記録 GOTO INTR ; INTR02 BTFSS STATUS,RP1 ;bank0か2か調べる GOTO INTR0 ;bank0か2 ;bank2なのでbank0に切り替え BANK0 BSF FLAG0,7 ;元はbank2だったことを記録 GOTO INTR INTR0 BSF FLAG0,5 ;元はbank0だったことを記録 INTR ;レジスタ待避 MOVWF BKUPW ;バックアップ(Wレジ) SWAPF STATUS,W ;バックアップ(STATUSレジ) MOVWF BKUPS MOVF FSR,W ;バックアップ(FSRレジ) MOVWF BKUPFR MOVF PCLATH,W MOVWF BKUPPCL ; BCF INTCON,T0IF ;割り込みフラグリセット ; BTFSC PWMCNT,1 ; GOTO NEXT ; CHECK MOVLW H'FF' ; LED消灯 MOVWF PORTA MOVWF PORTB MOVWF PORTC ; MOVF ROWDECL,W ; 列(アノード側)設定 MOVWF PORTD MOVF ROWDECH,W MOVWF PORTE ; BCF STATUS,C ; LEDBUFアドレス計算(列カウンタ 3倍) RLF ROWCNT,W ADDWF ROWCNT,W ADDLW LEDBUF ; 基点アドレス加算 MOVWF FSR BANK2 COMF INDF,W ; ROW位置の赤 BANK0 MOVWF PORTA BANK2 INCF FSR,F COMF INDF,W ; ROW位置の緑 BANK0 MOVWF PORTB BANK2 INCF FSR,F COMF INDF,W ; ROW位置の青 BANK0 MOVWF PORTC ; BTFSS ROWCNT,0 ; ROWCNTが奇数のときに1列シフト GOTO INCROW BSF STATUS,C RLF ROWDECL,F RLF ROWDECH,F INCROW INCF ROWCNT,F MOVF ROWCNT,W ; 列カウンタ最大値チェック SUBLW D'20' ; 20になったら0に戻す BTFSS STATUS,Z GOTO NEXT CLRF ROWCNT MOVLW H'FE' MOVWF ROWDECL MOVLW H'FF' MOVWF ROWDECH ; NEXT INCF PWMCNT,W ANDLW H'03' MOVWF PWMCNT ; CHKSW ; タクトスイッチの状態確認 ; BTFSC PORTE,2 ;タクトスイッチポート(押された:0) GOTO CHKSW1 ; 押されていない ; ; SWが押されたときの処理 BTFSS FLAG0,4 ; 前回のSWの状態 GOTO CHKSW0 ; 今回初めて ; INCF SWTIML,F ; タイマの下位カウントアップ BTFSC STATUS,Z INCF SWTIMH,F ; タイマの上位カウントアップ ; MOVF SWTIMH,F ; 上位が0か判断 BTFSS STATUS,Z GOTO CHKSWLG ; 長押し確認 MOVLW D'50' SUBWF SWTIML,W ; 下位が50か判断 BTFSS STATUS,Z GOTO CHKSWLG ; 長押し確認 ; 50回≒10ms押された(チャタリング防止) BCF FLAG0,2 ; step実行モード:0 BSF FLAG0,3 ; トリガon GOTO CHKSWEND ; CHKSWLG ; 長押し確認 MOVF SWTIML,F ; 下位が0か判断 BTFSS STATUS,Z GOTO CHKSWEND MOVLW D'20' SUBWF SWTIMH,W ; 上位が20か判断 BTFSS STATUS,Z GOTO CHKSWEND ; 256*20=5,120回≒約1秒押された(長押し) BSF FLAG0,2 ; 連続実行モード:1 BSF FLAG0,3 ; トリガon GOTO CHKSWEND ; CHKSW0 ; 今回初めてSWが押された BSF FLAG0,4 ; 今回のスイッチの状態on INCF SWTIML,F GOTO CHKSWEND ; CHKSW1 ; SWが押されていないときの処理 BCF FLAG0,4 ; 今回のスイッチの状態off CLRF SWTIML ; カウンタ(タイマ)クリア CLRF SWTIMH ; カウンタ(タイマ)クリア CHKSWEND ; ;レジスタ復元 MOVF BKUPPCL,W ;復元(PCLATH) MOVWF PCLATH MOVF BKUPFR,W ;復元(FSRレジ) MOVWF FSR SWAPF BKUPS,W ;復元(STATUSレジ) MOVWF STATUS SWAPF BKUPW,F ;復元(Wレジ) SWAPF BKUPW,W ; BTFSS FLAG0,5 ;bank0確認 GOTO RETBNK01 BCF FLAG0,5 ;フラグクリア RETFIE ;bank0ならそのまま RETBNK01 BTFSS FLAG0,6 ;bank1確認 GOTO RETBNK02 BCF FLAG0,6 ;フラグクリア BANK1 ;bank1に戻す RETFIE RETBNK02 BCF FLAG0,7 ;フラグクリア BANK2 ;bank2に戻す RETFIE ;割り込みから復帰 ; ;--------------------------------------------------------------------- ; 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 ; ;--------------------------------------------------------------------- ; MAIN ;--------------------------------------------------------------------- MAIN CALL INIT ; デバイス・変数初期化 MSGLOOP CALL MESSAGE ; 起動メッセージ BTFSS FLAG0,3 ; タクトスイッチのトリガ確認 GOTO MSGLOOP CALL START ; 解の探索開始(完了するとスリープ) GOTO MAIN ;--------------------------------------------------------------------- ; ポート、割り込み関係の初期化 ;--------------------------------------------------------------------- INIT BCF INTCON,GIE ;全割込み禁止 BANK3 CLRF ANSEL CLRF ANSELH BANK1 CLRF TRISA ; ポートAは全て出力 CLRF TRISB ; ポートBは全て出力 CLRF TRISC ; ポートCは全て出力 CLRF TRISD ; ポートDは全て出力 MOVLW B'00000100' MOVWF TRISE ; ポートEはBIT2入力端子、他は出力 ;割り込みタイマーセット MOVLW H'01' ;プリスケーラを1:4にする MOVWF OPTION_REG ;約4882Hz(205us)で割り込み BANK0 ;clock20MHz -> 5Mcycle ;5Mcycle/256/4 = 4882Hz ; (1画面10列×4PWM表示 = 40なので、1画面61Hzで表示) MOVLW H'FF' MOVWF PORTA ; LED OFF MOVWF PORTB ; LED OFF MOVWF PORTC ; LED OFF MOVWF PORTD ; LED OFF MOVWF PORTE ; LED OFF CLRF ROWCNT MOVLW H'FE' MOVWF ROWDECL ; LEDマトリクスの1桁目オン MOVLW H'FF' MOVWF ROWDECH CLRF PWMCNT CLRF FLAG0 BANK2 CALL CLRBUF ; 表示バッファクリア BANK0 ; CLRF SWTIML ; カウンタ(タイマ)クリア CLRF SWTIMH ; カウンタ(タイマ)クリア ; BSF INTCON,T0IE ; RTCCマスクイネーブル BSF INTCON,GIE ; 割り込み許可 ; RETURN ; ;----------------------------------------------------------------------- ; 探索開始 ;----------------------------------------------------------------------- START BCF FLAG0,3 ; トリガクリア CLRF POS CLRF SUF_I CLRF SUF_J CLRF SUF_K CALL INTBRD ; 盤面の初期化 CLRF USENO ; 使用ピースカウンタクリア CLRF USEPCEL ; 使用済みピーステーブルクリア CLRF USEPCEH ; CLRF SOLNO1 CLRF SOLNO2 CLRF SOLNO3 CLRF SOLNO4 ; MOVLW STACK ; スタックポインタ初期化 MOVWF STACKP ; ; BANK2 CALL CLRBUF ; 表示バッファクリア BANK0 ;----------------------------------------------------------------------- ; 探索のメインループ ; Xピースを置いた後、 ; i:ピース番号,j:ピースの向きをループさせ、全ての探索枝を探す。 ; 12個のピースが置けたら表示する ;----------------------------------------------------------------------- SEARCH CLRF SUF_X ; Xピース(7通り)カウンタクリア SEARCH_X MOVLW D'1' MOVWF SUF_I ; ピース番号1番(Xピース) CLRF SUF_J ; ピース番号0番の方向クリア CLRF USENO ; 使用ピースカウンタクリア CALL XPIECE ; Xピースの基点座標を取り出し ; Wに基点座標が返ってくる MOVWF POS ; POSに設定 CALL PUTPIECE ; SUF_Iピース(Xピース)を置く MOVF SUF_I,W ; 使用済みピースフラグを立てる CALL USEPCE CALL PUSHSTACK ; スタックに積む ; ; 2番ピースから順次置いていく ; CLRF POS ; 配置座標カウンタクリア DECF POS,F ; 最初は-1にする SEARCH_L CALL NEXTPOS ; 次の空き座標を探す ; CALL CHKSPACE ; この場所が閉じていないかチェック BTFSS STATUS,Z ; Z=0なら閉じているので戻る(SEARCH_RET) GOTO SEARCH_RET ; ; MOVLW D'2' MOVWF SUF_I ; i=2 SEARCH_I CALL CHKPCE ; i番目のピースは未使用か調べる BTFSS STATUS,Z ; Z=1 なら空き GOTO NEXT_I ; 空いていなければ次のピース ; CLRF SUF_J ; j=0 SEARCH_J CALL PUTPIECE ; ピースを置く BTFSS STATUS,Z ; 置けたら(Z=1)次のピース GOTO NEXT_J ; 置けないのでj++ ; MOVF SUF_I,W ; 置けたので使用済みピースフラグを立てる CALL USEPCE CALL PUSHSTACK ; スタックに積む ; MOVLW D'12' ; 12個目のピースを置いたか? SUBWF USENO,W BTFSS STATUS,Z ; Z=1 なら終わり GOTO SEARCH_L ; 次のピースにトライ ; COMPLETE ; ピースが全て収まった CALL SOLCNTUP ; 解のカウントアップ ; BTFSS FLAG0,2 ; 実行モード確認(0:ステップ、1:連続) GOTO STEPMODE CONTMODE ; 連続実行モード時の表示 CALL DSPBRD ; 盤面の表示 GOTO SEARCH_RET STEPMODE CALL DSPDIGIT ; 解の番号表示 CALL DSPBRD ; 盤面の表示 BTFSS FLAG0,3 ; トリガがかかったときは次を探す GOTO $-1 GOTO SRCHNEXT ; 次の解を探す GOTO STEPMODE ; SRCHNEXT BCF FLAG0,3 ; トリガクリア ; SEARCH_RET ; 置けなくなったらココに戻る ; ; 配置済みのピースを引きはがす ; MOVLW STACK-6 ; スタック確認 SUBWF STACKP,W ; BTFSC STATUS,Z ; Z=1 (スタックが空)ならNEXT_Xへ GOTO NEXT_X ; CALL POPSTACK ; スタックを戻す MOVF SUF_I,W CALL UNUSEPCE ; 使用済みピースフラグを降ろす ; NEXT_J INCF SUF_J,F MOVF SUF_J,W SUBWF DIRNUM,W ; j==ピースの方向数の確認 BTFSS STATUS,Z ; Z=1ならjループを抜ける GOTO SEARCH_J ; j<ピースの方向数なら次を探索 ; NEXT_I INCF SUF_I,F MOVLW D'13' ; ピースは12迄 SUBWF SUF_I,W ; i==13の確認 BTFSS STATUS,Z ; Z=1ならiループを抜ける GOTO SEARCH_I ; I<=12なら次を探索 ; GOTO SEARCH_RET ; ; Xピース番号のインクリメント&ループ脱出 NEXT_X CALL POPSTACK ; スタックから除く MOVF SUF_I,W CALL UNUSEPCE ; 使用済みピースフラグを降ろす INCF SUF_X,F MOVLW D'7' SUBWF SUF_X,W BTFSS STATUS,Z ;0なら(x=7なら)終わり GOTO SEARCH_X ; LAST CALL WAIT5S ; 5秒待って、 CALL DSPDIGIT ; 解の番号表示 CALL MSGFIN ; 終了メッセージ ; SLEEP ; スリープモード RETURN ; 復帰は電源再投入 ; ;--------------------------------------------------------------------- ; Xピースの配置座標を返す(7通り) ;--------------------------------------------------------------------- XPIECE MOVLW H'01' MOVWF PCLATH MOVF SUF_X,W ADDWF PCL,F ; RETLW D'2' ;Xピースの置き場所は以下の7箇所 RETLW D'9' RETLW D'10' RETLW D'17' RETLW D'18' RETLW D'25' RETLW D'26' ; ;--------------------------------------------------------------------- ; W-regで指示された座標のビットを表示バッファにセットする。 ; ; 7 6 5 4 3 2 1 0 ; +-----+-----------------+ ; 1 | 7 6| 5 4 3 2 1 0| ; 2 |15 14|13 12 11 10 9 8| ; | | : : | ; 10 |79 78|77 76 75 74 73 72| ; + +-----------------+ ; 11 |87 86 85 84 83 82 81 80| ←番兵 ; +-----+-----------------+ ; ;--------------------------------------------------------------------- SETPOS: ; 座標が何バイト目か確認 ; 8で割った商がバイト位置になる。 MOVWF BRDWK1 ; ANDLW H'07' ; Wの下位3bitを取り出し、ビット位置確定 MOVWF OFFSET1 ; BCF STATUS,C ; Carry bitをクリア RLF BRDWK1,F ; 左にbit shift(2倍) SWAPF BRDWK1,W ; ニブルスワップで1/16して、元の1/8 ANDLW H'0F' ; Wの下位4bitを取り出し、バイト位置確定 MOVWF BRDWK1 ; MOVF OFFSET1,W CALL DECBIT ; デコードしたビットの位置がWで返される ; MOVWF BUFF1 ; DSPBUF[DSPPOS] |= BUFFF1 ; MOVF BRDWK1,W ; DSPPOS = BRDWK1 ; MOVWF FSR ; FSR にアドレスをセット BTFSC FLAG,0 ; set:1/unset:0フラグ GOTO SETPOS1 ; UNSET処理 COMF BUFF1,W ; マスクを反転 ANDWF INDF,F ; (FSR) 番地とBUFF1の反転をANDすることでアンセット RETURN ; SETPOS1 MOVF BUFF1,W ; (FSR) 番地とBUFF1のORでセット IORWF INDF,F ; RETURN ; ;--------------------------------------------------------------------- ; 次の場所(POSで指される場所)が閉じていないか確認(以下の2ケース) ; (閉じている場合には Z=0 で戻る) ; 1) 2) ; pos pos ; ↓ ↓ ; □■←(b) □■←(b) ; ■←(a) □■←(d) ; ■←(c) ;--------------------------------------------------------------------- CHKSPACE MOVLW D'8' ADDWF POS,W ;w=pos+8 (b)の位置 CALL CHKPOS ;w位置が空きか調べる BTFSC STATUS,Z ;Z=1なら空き RETURN ;空きなのでリターン(Z=1) ; INCF POS,W ;w=pos+1 (a)の位置 CALL CHKPOS ;w位置が空きか調べる BTFSS STATUS,Z ;Z=1なら空き RETURN ;空いてないのでリターン(Z=0) ; MOVLW D'2' ADDWF POS,W ;w=pos+2 (c)の位置 CALL CHKPOS ;w位置が空きか調べる BTFSC STATUS,Z ;Z=1なら空き RETURN ;空きなのでリターン(Z=1) ; MOVLW D'9' ADDWF POS,W ;w=pos+9 (d)の位置 CALL CHKPOS ;w位置が空きか調べる RETURN ;Zフラグを持ってリターン ; ;--------------------------------------------------------------------- ; 指定されたピース番号は未使用か調べる ; SUF_I:ピース番号, Z=1なら未使用 ;--------------------------------------------------------------------- CHKPCE MOVF SUF_I,W MOVWF WK MOVLW D'7' ;7以上か調べる SUBWF WK,W BTFSC STATUS,C GOTO CHKPCE1 ;7以上 DECF WK,W CALL DECBIT ; ANDWF USEPCEL,W ;フラグを確認 RETURN CHKPCE1 CALL DECBIT ; ANDWF USEPCEH,W ;フラグを確認 RETURN ;--------------------------------------------------------------------- ; 使用済みピースに使用済みフラグを立てる ; w:ピース番号 ;--------------------------------------------------------------------- USEPCE MOVWF WK MOVLW D'7' ;7以上か調べる SUBWF WK,W BTFSC STATUS,C GOTO USEPCE1 ;7以上 DECF WK,W CALL DECBIT ; IORWF USEPCEL,F ;フラグを立てる RETURN USEPCE1 CALL DECBIT ; IORWF USEPCEH,F ;フラグを立てる RETURN ;--------------------------------------------------------------------- ; 使用済みフラグを降ろす ; w:ピース番号 ;--------------------------------------------------------------------- UNUSEPCE MOVWF WK MOVLW D'7' ;7以上か調べる SUBWF WK,W BTFSC STATUS,C GOTO UNUSEPCE1 ;7以上 DECF WK,W CALL DECBIT ; XORLW H'FF' ANDWF USEPCEL,F ;フラグを降ろす RETURN UNUSEPCE1 CALL DECBIT ; XORLW H'FF' ANDWF USEPCEH,F ;フラグを降ろす RETURN ;--------------------------------------------------------------------- ; 次に置くピース(未使用ピース)番号を探す ; ピース番号をwに入れて返す ;--------------------------------------------------------------------- NEXTPCE MOVLW B'00111111' ;1〜6番で空きがあるか調べる SUBWF USEPCEL,W BTFSC STATUS,C ;1〜6の中で探す GOTO NEXTPCE1 ;7〜12の中で探す ;1〜6の中で探す BTFSS USEPCEL,0 ;0ビット目が0なら次のビット RETLW D'1' ; BTFSS USEPCEL,1 ;1ビット目が0なら次のビット RETLW D'2' ; BTFSS USEPCEL,2 ;2ビット目が0なら次のビット RETLW D'3' ; BTFSS USEPCEL,3 ;3ビット目が0なら次のビット RETLW D'4' ; BTFSS USEPCEL,4 ;4ビット目が0なら次のビット RETLW D'5' ; RETLW D'6' ; NEXTPCE1 ;7〜12の中で探す BTFSS USEPCEH,0 ;0ビット目が0なら次のビット RETLW D'7' ; BTFSS USEPCEH,1 ;1ビット目が0なら次のビット RETLW D'8' ; BTFSS USEPCEH,2 ;2ビット目が0なら次のビット RETLW D'9' ; BTFSS USEPCEH,3 ;3ビット目が0なら次のビット RETLW D'10' ; BTFSS USEPCEH,4 ;4ビット目が0なら次のビット RETLW D'11' ; RETLW D'12' ; ; ;--------------------------------------------------------------------- ; ピースの配置可否チェックと配置ルーチン ; 以下の場所が空いているか確認し、空いていれば置く ; board[ pos + piece[i][j][0] ] ; board[ pos + piece[i][j][1] ] ; board[ pos + piece[i][j][2] ] ; board[ pos + piece[i][j][3] ] ; ; 結果: Zフラグ 0:置いた、1:置けない ; ; 検査のためにピース座標を取り出したら、仮に現在のピース番号の場所に ; データを記憶し、置くためと、置いたピースを剥がすために利用する。 ;--------------------------------------------------------------------- PUTPIECE CLRF SUF_K ;k=0 CALL PIECE ;w=piece[i][j][k] ADDWF POS,W ;w+=pos MOVWF WKPCE0 ;pos+座標 CALL CHKPOS ;WK(pos+座標)が空いているかチェック BTFSS STATUS,Z ;Z=1なら空きなので、次のセルの位置をチェック RETURN ;Z=0なので置けない ; ;-------- k=1 ---------- INCF SUF_K,F ;k=1の座標を取り出す CALL PIECE ;w=piece[i][j][k] ADDWF POS,W ;w+=pos MOVWF WKPCE1 ;pos+座標 CALL CHKPOS ;WK(pos+座標)が空いているかチェック BTFSS STATUS,Z ;Z=1なら空きなので、次のセルの位置をチェック RETURN ;Z=0なので置けない ; ;-------- k=2 ---------- INCF SUF_K,F ;k=1の座標を取り出す CALL PIECE ;w=piece[i][j][k] ADDWF POS,W ;w+=pos MOVWF WKPCE2 ;pos+座標 CALL CHKPOS ;WK(pos+座標)が空いているかチェック BTFSS STATUS,Z ;Z=1なら空きなので、次のセルの位置をチェック RETURN ;Z=0なので置けない ; ;-------- k=3 ---------- INCF SUF_K,F ;k=1の座標を取り出す CALL PIECE ;w=piece[i][j][k] ADDWF POS,W ;w+=pos MOVWF WKPCE3 ;pos+座標 CALL CHKPOS ;WK(pos+座標)が空いているかチェック BTFSS STATUS,Z ;Z=1なら空きなので、ピースは置ける RETURN ;Z=0なので置けない ; ;----------------------- ; 4箇所のチェックが完了 ; 空いているので置く。 ;----------------------- MOVF POS,W ;座標POSに書き込む CALL PUTPOS MOVF WKPCE0,W ;座標WKPCE0に書き込む CALL PUTPOS MOVF WKPCE1,W ;座標WKPCE1に書き込む CALL PUTPOS MOVF WKPCE2,W ;座標WKPCE2に書き込む CALL PUTPOS MOVF WKPCE3,W ;座標WKPCE3に書き込む CALL PUTPOS INCF USENO,F BSF STATUS,Z ;Zフラグを1にしてリターン RETURN ; ;--------------------------------------------------------------------- ; 次にピースを置ける座標を探す ; POSに座標を入れてリターン ;--------------------------------------------------------------------- NEXTPOS INCF POS,F MOVF POS,W CALL CHKPOS BTFSS STATUS,Z ;Z=1なら空き GOTO NEXTPOS ;Z=0なら1座標進め、次を探す RETURN ; ;--------------------------------------------------------------------- ; 配置したピースを引きはがすルーチン ; スタックに積んである1ピース分のピース番号(i),方向(j),配置座標(pos) ; を取り出し、各変数を復元する。残り4座標データは特にクリアせず、 ; スタックポインタのみ6アドレス分戻す。 ;--------------------------------------------------------------------- POPSTACK BANK1 MOVF STACKP,W ; MOVWF FSR ;FSR=stackp INCF FSR,F ;FSR++ ; MOVF INDF,W ;w=(FSR) ANDLW H'F0' ;上位だけ取り出す MOVWF SUF_I SWAPF SUF_I,F ;上位と下位を反転し、iを復元 ; ;ピースの方向数dirnum(1,2,4,8)を復元 BTFSC SUF_I,3 ;3ビット目が1ならピース番号8〜12→方向8 GOTO POPSTACK8 ;なので8へジャンプ ; MOVLW D'3' SUBWF SUF_I,W ;ピース番号3〜7なら4へジャンプ BTFSC STATUS,C GOTO POPSTACK4 ; MOVLW D'2' SUBWF SUF_I,W ;ピース番号2なら2へジャンプ BTFSC STATUS,Z GOTO POPSTACK2 ; MOVLW D'1' GOTO POPSTACK0 POPSTACK2 MOVLW D'2' GOTO POPSTACK0 POPSTACK4 MOVLW D'4' GOTO POPSTACK0 POPSTACK8 MOVLW D'8' POPSTACK0 MOVWF DIRNUM ;復元 ; MOVF INDF,W ;w=(FSR) ANDLW H'0F' ;下位だけ取り出す MOVWF SUF_J ;jを復元 ; cell-1座標 INCF FSR,F ;FSR++ MOVF FSR,W ;FSR待避 MOVWF WK1 ; MOVWF FSR MOVF INDF,W ;w=(FSR) CALL CLRPOS ;cell-1座標クリア ; cell-2座標 INCF WK1,F ;FSRインクリメント MOVF WK1,W MOVWF FSR MOVF INDF,W ;w=(FSR) CALL CLRPOS ;cell-2座標クリア ; cell-3座標 INCF WK1,F ;FSRインクリメント MOVF WK1,W MOVWF FSR MOVF INDF,W ;w=(FSR) CALL CLRPOS ;cell-3座標クリア ; cell-4座標 INCF WK1,F ;FSRインクリメント MOVF WK1,W MOVWF FSR MOVF INDF,W ;w=(FSR) CALL CLRPOS ;cell-4座標クリア ; pos座標 INCF WK1,F ;FSRインクリメント MOVF WK1,W MOVWF FSR MOVF INDF,W ;w=(FSR) MOVWF POS ;pos座標復元 CALL CLRPOS ;board上のpos座標クリア ; MOVLW D'6' ;6バイト分stackpを戻す ADDWF STACKP,F BANK0 DECF USENO,F RETURN ; ;--------------------------------------------------------------------- ; 当該座標(W)にピース番号(SUF_I)を書き込む ;--------------------------------------------------------------------- PUTPOS MOVWF FSR BTFSC FSR,0 ; 座標の0ビット目が0なら奇数なので下位4ビットへ GOTO PUTPOSH ; BCF STATUS,C ; キャリークリア RRF FSR,F ; 1/2 MOVLW BOARD ; board[0]アドレス ADDWF FSR,F ; w = board[0]アドレス+pos/2 MOVF SUF_I,W ; w=iの下位 IORWF INDF,F ; board[pos]|=iの下位 RETURN ; PUTPOSH BCF STATUS,C ; キャリークリア RRF FSR,F ; 1/2 MOVLW BOARD ; board[0]アドレス ADDWF FSR,F ; w = board[0]アドレス+pos/2 SWAPF SUF_I,W ; w=iの上位 IORWF INDF,F ; board[pos]|=iの上位 RETURN ; ; ;--------------------------------------------------------------------- ; 当該座標(W)をクリア(未使用)する ;--------------------------------------------------------------------- CLRPOS MOVWF FSR BTFSC FSR,0 ; 座標の0ビット目が0なら奇数なので下位4ビットへ GOTO CLRPOSH ; BCF STATUS,C ; キャリークリア RRF FSR,F ; 1/2 MOVLW BOARD ; board[0]アドレス ADDWF FSR,F ; w = board[0]アドレス+pos/2 MOVLW H'F0' ; 下位4ビットクリア ANDWF INDF,F RETURN ; CLRPOSH BCF STATUS,C ; キャリークリア RRF FSR,F ; 1/2 MOVLW BOARD ; board[0]アドレス ADDWF FSR,F ; w = board[0]アドレス+pos/2 MOVLW H'0F' ; 上位4ビットクリア ANDWF INDF,F RETURN ; ; ;--------------------------------------------------------------------- ; 使ったピースの番号(i)、方向(j)、配置座標をスタックに記録 (BANK1) ; (stackpは初期化時にstackテーブルアドレスを設定) ; stack[stakp] = WKPCE3 ; stack[stakp--] = WKPCE2 ; stack[stakp--] = WKPCE1 ; stack[stakp--] = WKPCE0 ; stack[stakp--] = POS ; stack[stakp--] = i,j (上位4ビットにi,下位4ビットにj) ;--------------------------------------------------------------------- PUSHSTACK BANK1 MOVF STACKP,W ; 現在のstackpをw-regへ MOVWF FSR ; FSRにセット ; MOVF POS,W ; w=pos MOVWF INDF ; stack[stackptr--]=w DECF FSR,F ; MOVF WKPCE3,W ; w=wkpce3 MOVWF INDF ; stack[stackptr--]=w DECF FSR,F ; MOVF WKPCE2,W ; w=wkpce2 MOVWF INDF ; stack[stackptr--]=w DECF FSR,F ; MOVF WKPCE1,W ; w=wkpce1 MOVWF INDF ; stack[stackptr--]=w DECF FSR,F ; MOVF WKPCE0,W ; w=wkpce0 MOVWF INDF ; stack[stackptr--]=w DECF FSR,F ; ; i,j を1バイトにまとめる SWAPF SUF_I,W ; w=i(上位/下位入れ替え) ANDLW H'F0' ; 上位だけ取り出す MOVWF INDF MOVF SUF_J,W ; w=j ANDLW H'0F' ; 下位だけ取り出す IORWF INDF,F ; w = i|j ; DECF FSR,W ; stack[stackptr--]=w MOVWF STACKP ; stackp更新 BANK0 RETURN ; ;--------------------------------------------------------------------- ; ピース定義と取り出しルーチン ; piece[i][j][k]を返す ; i:ピース番号(1〜12) ; j:方向(0〜7;0,1,3,7の4通り) ; k:W-regピース内の個片:■□□□□ ; ↑↑↑↑ ; 0123 ; k=0のときにoffsetpを計算し、offsetpは位置を記憶し、 ; k=1以降のoffset計算はincで済ます。 ; また、k=0のときにiピースの方向数をDIRNUMに格納し、呼び出し元側で ; ピースの向きのループを抜けるのに使う。 ;--------------------------------------------------------------------- ORG H'2D2' ; H'2D1' = H'300' - D'46' ; ピーステーブルがH'300'〜'3FF'になる。 PIECE MOVF SUF_K,F ; k=0か判定 BTFSC STATUS,Z ; GOTO CALC_I ; k=0 ならoffsetp計算 INCF OFFSETP,F ; k!=0ならoffsetp++して、 GOTO PIECETB ; ピーステーブルへ CALC_I ; OFFSET計算(まず、piece[i][0][0]の位置を計算) MOVF SUF_I,W ; SUF_I を OFFSETP にコピー MOVWF OFFSETP ; BTFSC SUF_I,3 ;iが8以上なら GOTO PIECE8 ; 8以上の場合のoffset計算へ BTFSC SUF_I,2 ;iが4以上なら GOTO PIECE3 ; 3以上の場合のoffset計算へ BTFSS SUF_I,1 ;iが2未満なら GOTO PIECE1 ; 1の場合は1のoffset計算へ BTFSS SUF_I,0 ;0ビット目が0ならiが2なので、 GOTO PIECE2 ; 2の場合のoffset計算へ PIECE3 ;piece3〜7のoffset = 12+(i-3)*16 MOVLW D'3' SUBWF OFFSETP,F ; offsetp=i-3 SWAPF OFFSETP,F ; offsetp*=16 MOVLW D'12' ADDWF OFFSETP,F ; offsetp+=12 MOVLW D'4' ; ピースの方向数 MOVWF DIRNUM GOTO CALC_J PIECE8 ;piece8〜12のoffset = 92+(i-8)*32 MOVLW D'8' MOVWF DIRNUM ; ピースの方向数 SUBWF OFFSETP,F ; offsetp=i-8 SWAPF OFFSETP,F ; offsetp*=16 BCF STATUS,C ; Carry bitをクリア RLF OFFSETP,F ; offsetp*=2 (32倍) MOVLW D'92' ADDWF OFFSETP,F ; offsetp+=92 GOTO CALC_J PIECE2 ;piece2のoffsetp = 4 MOVLW D'4' MOVWF OFFSETP ; offsetp=4 MOVLW D'2' ; ピースの方向数 MOVWF DIRNUM GOTO CALC_J ; PIECE1 ;piece1のoffsetp = 0 DECF OFFSETP,F ; offset=i-1 MOVLW D'1' ; ピースの方向数 MOVWF DIRNUM ; CALC_J ;OFFSETP計算(piece[i][j][0]の位置を計算) ;offsetp+=j*4 MOVF SUF_J,W MOVWF WK BCF STATUS,C ; Carry bitをクリア RLF WK,F ; offset*=2 RLF WK,W ; offset*=2 (4倍) ADDWF OFFSETP,F PIECETB ; ここがH'300'番地になること。 MOVLW H'03' MOVWF PCLATH MOVF OFFSETP,W ADDWF PCL,F ; Xピース ; RETLW D'7' ; piece[1][0][0] RETLW D'8' RETLW D'9' RETLW D'16' ; Iピース ; RETLW D'32' ; piece[2][0][0] RETLW D'16' RETLW D'8' RETLW D'24' ; RETLW D'2' ; piece[2][1][0] RETLW D'4' RETLW D'3' RETLW D'1' ; Tピース ; RETLW D'2' ; piece[3][0][0] RETLW D'1' RETLW D'17' RETLW D'9' ; RETLW D'10' ; piece[3][1][0] RETLW D'16' RETLW D'9' RETLW D'8' ; RETLW D'15' ; piece[3][2][0] RETLW D'17' RETLW D'8' RETLW D'16' ; RETLW D'6' ; piece[3][3][0] RETLW D'7' RETLW D'16' RETLW D'8' ; Uピース ; RETLW D'2' ; piece[4][0][0] RETLW D'9' RETLW D'8' RETLW D'10' ; RETLW D'2' ; piece[4][1][0] RETLW D'1' RETLW D'8' RETLW D'10' ; RETLW D'1' ; piece[4][2][0] RETLW D'16' RETLW D'8' RETLW D'17' ; RETLW D'1' ; piece[4][3][0] RETLW D'16' RETLW D'9' RETLW D'17' ; Wピース ; RETLW D'7' ; piece[5][0][0] RETLW D'15' RETLW D'14' RETLW D'8' ; RETLW D'18' ; piece[5][1][0] RETLW D'9' RETLW D'8' RETLW D'17' ; RETLW D'10' ; piece[5][2][0] RETLW D'1' RETLW D'18' RETLW D'9' ; RETLW D'7' ; piece[5][3][0] RETLW D'1' RETLW D'15' RETLW D'8' ; Vピース ; RETLW D'14' ; piece[6][0][0] RETLW D'15' RETLW D'8' RETLW D'16' ; RETLW D'18' ; piece[6][1][0] RETLW D'16' RETLW D'17' RETLW D'8' ; RETLW D'2' ; piece[6][2][0] RETLW D'1' RETLW D'8' RETLW D'16' ; RETLW D'2' ; piece[6][3][0] RETLW D'1' RETLW D'18' RETLW D'10' ; Zピース ; RETLW D'1' ; piece[7][0][0] RETLW D'15' RETLW D'8' RETLW D'16' ; RETLW D'1' ; piece[7][1][0] RETLW D'18' RETLW D'9' RETLW D'17' ; RETLW D'7' ; piece[7][2][0] RETLW D'6' RETLW D'14' RETLW D'8' ; RETLW D'10' ; piece[7][3][0] RETLW D'9' RETLW D'8' RETLW D'18' ; Lピース ; RETLW D'23' ; piece[8][0][0] RETLW D'16' RETLW D'8' RETLW D'24' ; RETLW D'25' ; piece[8][1][0] RETLW D'16' RETLW D'8' RETLW D'24' ; RETLW D'1' ; piece[8][2][0] RETLW D'24' RETLW D'8' RETLW D'16' ; RETLW D'1' ; piece[8][3][0] RETLW D'25' RETLW D'17' RETLW D'9' ; RETLW D'6' ; piece[8][4][0] RETLW D'7' RETLW D'5' RETLW D'8' ; RETLW D'10' ; piece[8][5][0] RETLW D'11' RETLW D'9' RETLW D'8' ; RETLW D'1' ; piece[8][6][0] RETLW D'8' RETLW D'2' RETLW D'3' ; RETLW D'2' ; piece[8][7][0] RETLW D'1' RETLW D'3' RETLW D'11' ; fピース ; RETLW D'10' ; piece[9][0][0] RETLW D'1' RETLW D'17' RETLW D'9' ; RETLW D'7' ; piece[9][1][0] RETLW D'1' RETLW D'16' RETLW D'8' ; RETLW D'15' ; piece[9][2][0] RETLW D'9' RETLW D'8' RETLW D'16' ; RETLW D'7' ; piece[9][3][0] RETLW D'17' RETLW D'16' RETLW D'8' ; RETLW D'10' ; piece[9][4][0] RETLW D'9' RETLW D'17' RETLW D'8' ; RETLW D'7' ; piece[9][5][0] RETLW D'6' RETLW D'15' RETLW D'8' ; RETLW D'7' ; piece[9][6][0] RETLW D'9' RETLW D'15' RETLW D'8' ; RETLW D'7' ; piece[9][7][0] RETLW D'9' RETLW D'17' RETLW D'8' ; yピース ; RETLW D'9' ; piece[10][0][0] RETLW D'24' RETLW D'16' RETLW D'8' ; RETLW D'7' ; piece[10][1][0] RETLW D'24' RETLW D'16' RETLW D'8' ; RETLW D'17' ; piece[10][2][0] RETLW D'24' RETLW D'16' RETLW D'8' ; RETLW D'15' ; piece[10][3][0] RETLW D'24' RETLW D'8' RETLW D'16' ; RETLW D'3' ; piece[10][4][0] RETLW D'2' RETLW D'1' RETLW D'10' ; RETLW D'7' ; piece[10][5][0] RETLW D'6' RETLW D'9' RETLW D'8' ; RETLW D'3' ; piece[10][6][0] RETLW D'2' RETLW D'1' RETLW D'9' ; RETLW D'7' ; piece[10][7][0] RETLW D'10' RETLW D'9' RETLW D'8' ; Nピース ; RETLW D'25' ; piece[11][0][0] RETLW D'9' RETLW D'8' RETLW D'17' ; RETLW D'7' ; piece[11][1][0] RETLW D'23' RETLW D'15' RETLW D'8' ; RETLW D'25' ; piece[11][2][0] RETLW D'16' RETLW D'8' RETLW D'17' ; RETLW D'15' ; piece[11][3][0] RETLW D'23' RETLW D'8' RETLW D'16' ; RETLW D'11' ; piece[11][4][0] RETLW D'1' RETLW D'10' RETLW D'9' ; RETLW D'7' ; piece[11][5][0] RETLW D'6' RETLW D'1' RETLW D'8' ; RETLW D'2' ; piece[11][6][0] RETLW D'7' RETLW D'1' RETLW D'8' ; RETLW D'2' ; piece[11][7][0] RETLW D'11' RETLW D'1' RETLW D'10' ; Pピース ; RETLW D'1' ; piece[12][0][0] RETLW D'8' RETLW D'17' RETLW D'9' ; RETLW D'1' ; piece[12][1][0] RETLW D'16' RETLW D'8' RETLW D'9' ; RETLW D'7' ; piece[12][2][0] RETLW D'15' RETLW D'16' RETLW D'8' ; RETLW D'9' ; piece[12][3][0] RETLW D'16' RETLW D'8' RETLW D'17' ; RETLW D'2' ; piece[12][4][0] RETLW D'1' RETLW D'8' RETLW D'9' ; RETLW D'2' ; piece[12][5][0] RETLW D'1' RETLW D'9' RETLW D'10' ; RETLW D'10' ; piece[12][6][0] RETLW D'1' RETLW D'8' RETLW D'9' ; RETLW D'7' ; piece[12][7][0] RETLW D'1' RETLW D'9' RETLW D'8' ; ピース定義終わり。ここがH'3FF'になる。 ; ; ;--------------------------------------------------------------------- ; 当該(W)座標が空いているか確認 ;--------------------------------------------------------------------- CHKPOS MOVWF FSR BTFSC FSR,0 ; 座標の0ビット目が0なら奇数なので下位4ビットへ GOTO CHKPOSH ; BCF STATUS,C ; キャリークリア RRF FSR,F ; 1/2 MOVLW BOARD ; board[0]アドレス ADDWF FSR,F ; w = board[0]アドレス+pos/2 MOVF INDF,W ; w=(FSR)番地の内容 ANDLW H'0F' ; 下位4ビットを確認 RETURN ; Zフラグを持ってリターン CHKPOSH BCF STATUS,C ; キャリークリア RRF FSR,F ; 1/2 MOVLW BOARD ; board[0]アドレス ADDWF FSR,F ; w = board[0]アドレス+pos/2 MOVF INDF,W ; w=(FSR)番地の内容 ANDLW H'F0' ; 上位4ビットを確認 RETURN ; Zフラグを持ってリターン ; ;--------------------------------------------------------------------- ; 表示バッファシフト ;--------------------------------------------------------------------- DSPBUFST BANK2 MOVLW LEDBUF MOVWF WK2 ; コピー先のアドレス MOVLW LEDBUF+6 MOVWF WK3 ; コピー元のアドレス MOVLW D'54' ; 6x9=54バイト MOVWF CNT2 DSPBUFS1 MOVF WK3,W MOVWF FSR MOVF INDF,W ; Wレジに読み込み MOVWF TMP2 MOVF WK2,W MOVWF FSR MOVF TMP2,W MOVWF INDF INCF WK2,F INCF WK3,F ; DECFSZ CNT2,F GOTO DSPBUFS1 ; MOVLW D'6' MOVWF CNT2 DSPBUF2 INCF FSR,F CLRF INDF ; 最後の行をクリアして戻る DECFSZ CNT2,F GOTO DSPBUF2 BANK1 RETURN ; ;--------------------------------------------------------------------- ; 解数をカウントアップする ;--------------------------------------------------------------------- SOLCNTUP INCF SOLNO1,F MOVLW D'10' SUBWF SOLNO1,W BTFSC STATUS,Z GOTO SOLCNTUP2 RETURN SOLCNTUP2 CLRF SOLNO1 INCF SOLNO2,F MOVLW D'10' SUBWF SOLNO2,W BTFSC STATUS,Z GOTO SOLCNTUP3 RETURN SOLCNTUP3 CLRF SOLNO2 INCF SOLNO3,F MOVLW D'10' SUBWF SOLNO3,W BTFSC STATUS,Z GOTO SOLCNTUP4 RETURN SOLCNTUP4 CLRF SOLNO3 INCF SOLNO4,F MOVLW D'10' SUBWF SOLNO4,W BTFSC STATUS,Z GOTO SOLCNTUP5 RETURN SOLCNTUP5 CLRF SOLNO4 ; 最後はSTATUS,Zが1で返る RETURN ; ;--------------------------------------------------------------------- ; 表示パターン(w)をLEDBUFに格納 ; 1バイト(カラー2ビット+パターン6ビット)をRGBでLEDバッファに格納 ; カラー:00:赤、01:緑、10:青、11:白 ;--------------------------------------------------------------------- SETPTN BANK2 MOVWF WK2 ; パターン保存 ANDLW H'C0' MOVWF WK3 ; カラー SUBLW H'C0' BTFSC STATUS,Z GOTO SETPTNW ; 白 MOVF WK3,W SUBLW H'80' BTFSC STATUS,Z GOTO SETPTNB ; 青 MOVF WK3,W SUBLW H'40' BTFSC STATUS,Z GOTO SETPTNG ; 緑 ; 赤 MOVF WK2,W MOVWF LEDBUFR GOTO SETPRNE SETPTNG MOVF WK2,W MOVWF LEDBUFG GOTO SETPRNE SETPTNB MOVF WK2,W MOVWF LEDBUFB GOTO SETPRNE SETPTNW MOVF WK2,W MOVWF LEDBUFR MOVWF LEDBUFG MOVWF LEDBUFB SETPRNE BANK1 RETURN ;--------------------------------------------------------------------- ; Message : Pentomino Solver in FRISK. ;--------------------------------------------------------------------- ORG H'500' MESSAGE BANK1 MOVLW D'91' MOVWF WK1 CLRF OFFSET1 MSG1 CALL DSPBUFST ; 表示バッファを1行分シフト CALL MSGTXT ; メッセージ1行分(1バイト)取り出し CALL SETPTN ; パターンをLEDBUFに書き込む BANK0 CALL WAIT01S BTFSC FLAG0,3 ; トリガがあれば表示を終了 GOTO MSG3 ; BANK1 INCF OFFSET1,F ; 1行進める DECFSZ WK1,F GOTO MSG1 ; MSG3 BANK1 MOVLW D'9' ; 最後に1画面分シフトする MOVWF WK1 MSG2 CALL DSPBUFST ; 表示バッファを1行分シフト BANK0 BTFSS FLAG0,3 ; トリガがある場合にはwaitしない CALL WAIT01S BANK1 DECFSZ WK1,F GOTO MSG2 ; BANK0 RETURN MSGTXT MOVLW H'05' MOVWF PCLATH MOVF OFFSET1,W ADDWF PCL,F ; ; 上位2bit カラー:00:赤、01:緑、10:青、11:白 RETLW B'01011111' ; P RETLW B'01000101' RETLW B'01000111' RETLW B'00000000' RETLW B'01011100' ; e RETLW B'01101010' RETLW B'01101100' RETLW B'00000000' RETLW B'01011100' ; n RETLW B'01000100' RETLW B'01011000' RETLW B'00000000' RETLW B'01000100' ; t RETLW B'01011110' RETLW B'01010100' RETLW B'00000000' RETLW B'01011100' ; o RETLW B'01010100' RETLW B'01011100' RETLW B'00000000' RETLW B'01011100' ; m RETLW B'01000010' RETLW B'01011100' RETLW B'01000010' RETLW B'01011100' RETLW B'00000000' RETLW B'01011101' ; i RETLW B'00000000' RETLW B'01011100' ; n RETLW B'01000100' RETLW B'01011000' RETLW B'00000000' RETLW B'01011100' ; o RETLW B'01010100' RETLW B'01011100' RETLW B'00000000' RETLW B'00000000' RETLW B'00000000' RETLW B'00010111' ; S RETLW B'00010101' RETLW B'00011101' RETLW B'00000000' RETLW B'00011100' ; o RETLW B'00010100' RETLW B'00011100' RETLW B'00000000' RETLW B'00011111' ; l RETLW B'00000000' RETLW B'00001100' ; v RETLW B'00010000' RETLW B'00001100' RETLW B'00000000' RETLW B'00011100' ; e RETLW B'00101010' RETLW B'00101100' RETLW B'00000000' RETLW B'00011100' ; r RETLW B'00000100' RETLW B'00000000' RETLW B'00000000' RETLW B'00000000' RETLW B'11011101' ; i RETLW B'00000000' RETLW B'11011100' ; n RETLW B'11000100' RETLW B'11011000' RETLW B'00000000' RETLW B'00000000' RETLW B'00000000' RETLW B'10011111' ; F RETLW B'10000101' RETLW B'10000101' RETLW B'00000000' RETLW B'10011111' ; R RETLW B'10000101' RETLW B'10001101' RETLW B'10010111' RETLW B'00000000' RETLW B'10010001' RETLW B'10011111' ; I RETLW B'10010001' RETLW B'00000000' RETLW B'10010111' ; S RETLW B'10010101' RETLW B'10011101' RETLW B'00000000' RETLW B'10011111' ; K RETLW B'10000100' RETLW B'10001010' RETLW B'10010001' RETLW B'00000000' ; ;--------------------------------------------------------------------- ; Message : FINISH! ;--------------------------------------------------------------------- MSGFIN BANK1 MOVLW D'22' MOVWF WK1 CLRF OFFSET1 MSGFIN1 CALL DSPBUFST ; 表示バッファを1行分シフト CALL MSGFINDT ; メッセージ1行分(1バイト)取り出し CALL SETPTN ; パターンをLEDBUFに書き込む BANK0 CALL WAIT01S BANK1 INCF OFFSET1,F ; 1行進める DECFSZ WK1,F GOTO MSGFIN1 ; MOVLW D'9' ; 最後に1画面分シフトする MOVWF WK1 MSGFIN2 CALL DSPBUFST ; 表示バッファを1行分シフト BANK0 CALL WAIT01S BANK1 DECFSZ WK1,F GOTO MSGFIN2 ; BANK0 RETURN MSGFINDT MOVLW H'05' MOVWF PCLATH MOVF OFFSET1,W ADDWF PCL,F ; RETLW B'00111110' RETLW B'00001010' RETLW B'00001010' RETLW B'00000000' RETLW B'00111010' RETLW B'00000000' RETLW B'00111000' RETLW B'00001000' RETLW B'00111000' RETLW B'00000000' RETLW B'00111010' RETLW B'00000000' RETLW B'00101100' RETLW B'00110100' RETLW B'00000000' RETLW B'00111110' RETLW B'00001000' RETLW B'00111000' RETLW B'00000000' RETLW B'00000000' RETLW B'00101110' RETLW B'00000000' ; ;--------------------------------------------------------------------- ; 解番号を表示する(3x5ドットの数字4桁をスクロール;ゼロサプレス) ;--------------------------------------------------------------------- DSPDIGIT ; "No."文字列 表示 BANK1 MOVLW D'12' MOVWF WK1 CLRF OFFSET1 DSPDGTNOL CALL DSPBUFST ; 表示バッファを1行分シフト CALL DSPDGTNO ; No.メッセージ取り出し IORLW H'40' ; 緑色で表示 CALL SETPTN ; パターンをLEDBUFに書き込む BANK0 CALL WAIT01S BTFSC FLAG0,3 ; トリガがあれば表示を終了 GOTO DSPDGTE ; BANK1 INCF OFFSET1,F ; 1行進める DECFSZ WK1,F GOTO DSPDGTNOL ; ; 数字を表示 ; BCF FLAG,1 ;ゼロサプレス用のフラグクリア ; 4桁目から調べる(0なら表示しない) BANK0 MOVF SOLNO4,W ; 数字をWへ BANK1 MOVWF TMP1 BTFSS STATUS,Z CALL DSPDGT ; 4桁目を表示 BANK0 BTFSC FLAG0,3 ; トリガがあれば表示終了 GOTO DSPDGTE ; DSPDGT3 BANK0 MOVF SOLNO3,W ; 数字をWへ BANK1 MOVWF TMP1 BTFSS STATUS,Z GOTO DSPDGT3D ; 0ではないので3桁目を表示 BTFSC FLAG,1 ; 0なのでゼロサプレスフラグ確認 DSPDGT3D CALL DSPDGT ; 3桁目を表示 BANK0 BTFSC FLAG0,3 ; トリガがあれば表示終了 GOTO DSPDGTE ; DSPDGT2 BANK0 MOVF SOLNO2,W ; 数字をWへ BANK1 MOVWF TMP1 BTFSS STATUS,Z GOTO DSPDGT2D ; 0ではないので3桁目を表示 BTFSC FLAG,1 ; 0なのでゼロサプレスフラグ確認 DSPDGT2D CALL DSPDGT ; 2桁目を表示 BANK0 BTFSC FLAG0,3 ; トリガがあれば表示終了 GOTO DSPDGTE ; DSPDGT1 BANK0 MOVF SOLNO1,W ; 数字をWへ BANK1 MOVWF TMP1 CALL DSPDGT ; 1桁目を表示 ; DSPDGTE ; 解番号の表示終了 BANK1 MOVLW D'9' ; 表示バッファを1画面分シフト MOVWF TMP1 DSPDGT0 CALL DSPBUFST ; 表示バッファを1行分シフト BANK0 BTFSS FLAG0,3 ; トリガがかかったときはwaitしない CALL WAIT01S BANK1 DECFSZ TMP1,F GOTO DSPDGT0 ; BANK0 RETURN ; DSPDGTNO MOVLW H'06' MOVWF PCLATH MOVF OFFSET1,W ADDWF PCL,F ; strings "No." (12列) RETLW B'00000000' RETLW B'00111110' RETLW B'00000100' RETLW B'00001000' RETLW B'00111110' RETLW B'00000000' RETLW B'00111000' RETLW B'00101000' RETLW B'00111000' RETLW B'00000000' RETLW B'00100000' RETLW B'00000000' ; ;--------------------------------------------------------------------- ; 一桁分の数字(3x5ドット)を表示する ;--------------------------------------------------------------------- DSPDGT BSF FLAG,1 ;ゼロサプレス用のフラグセット(これ以降は0でも表示) CLRF OFFSET1 ; 列カウンタクリア MOVLW D'4' MOVWF WK1 DSPDGTL CALL DSPBUFST ; 表示バッファを1列分シフト CALL DIGITDT ; TMP1の数値の先頭1列分を取り出す INCF OFFSET1,F ; 1列進める IORLW H'40' ; 緑色で表示 CALL SETPTN ; パターンをLEDBUFに書き込む BANK0 CALL WAIT01S BTFSC FLAG0,3 ; トリガがあれば表示終了 RETURN ; BANK1 DECFSZ WK1,F GOTO DSPDGTL RETURN ; DIGITDT ;数字の1列分のデータを取り出し MOVF OFFSET1,F ;offsetが0か判断 BTFSS STATUS,Z ; 0ならスキップ GOTO DIGITDT1 ; 0以外ならoffsetをインクリメント ; 0でない→その数字の最初の1列 ; 数値を4倍してoffsetへ BCF STATUS,C ;キャリークリア RLF TMP1,F RLF TMP1,W MOVWF OFFSET1 DIGITDT1 MOVLW H'06' MOVWF PCLATH MOVF OFFSET1,W ADDWF PCL,F ; digit 0 RETLW B'00111110' RETLW B'00100010' RETLW B'00111110' RETLW B'00000000' ; digit 1 RETLW B'00100100' RETLW B'00111110' RETLW B'00100000' RETLW B'00000000' ; digit 2 RETLW B'00111010' RETLW B'00101010' RETLW B'00101110' RETLW B'00000000' ; digit 3 RETLW B'00101010' RETLW B'00101010' RETLW B'00111110' RETLW B'00000000' ; digit 4 RETLW B'00001110' RETLW B'00001000' RETLW B'00111110' RETLW B'00000000' ; digit 5 RETLW B'00101110' RETLW B'00101010' RETLW B'00111010' RETLW B'00000000' ; digit 6 RETLW B'00111110' RETLW B'00101010' RETLW B'00111010' RETLW B'00000000' ; digit 7 RETLW B'00000010' RETLW B'00111010' RETLW B'00000110' RETLW B'00000000' ; digit 8 RETLW B'00111110' RETLW B'00101010' RETLW B'00111110' RETLW B'00000000' ; digit 9 RETLW B'00101110' RETLW B'00101010' RETLW B'00111110' RETLW B'00000000' ; ; ;--------------------------------------------------------------------- ; Waitルーチン(割り込みがあるので誤差あり) ;--------------------------------------------------------------------- WAIT02MS ;0.2ミリ秒(998cycle) CALLと合わせて0.2ms MOVLW D'248' ;1cycle MOVWF WAIT1 ;1cycle W02MSLP NOP ;1cycle*248 DECFSZ WAIT1,F ;1cycle*247+2cycle GOTO W02MSLP ;2cycle*247 GOTO $+1 ;2cycle NOP ;1cycle RETURN ;2cycle ; WAIT01S ; ;; MOVLW D'249' ;0.1秒(499,998cycle)CALLと合わせて0.1s MOVLW D'187' ;0.075秒 MOVWF WAIT2 ;1cycle W01SLP CALL WAIT02MS ;(2cycle+998cycle)*249 CALL WAIT02MS ;(2cycle+998cycle)*249 GOTO $+1 ;2cycle*249 GOTO $+1 ;2cycle*249 NOP ;1cycle*249 DECFSZ WAIT2,F ;1cycle*248+2cycle GOTO W01SLP ;2cycle*248 NOP ;1cycle GOTO $+1 ;2cycle RETURN ;2cycle ; WAIT5S MOVLW D'66' ;約5秒 MOVWF WK W5SLP CALL WAIT01S DECFSZ WK,F GOTO W5SLP RETURN ; ;--------------------------------------------------------------------- ; 盤面を初期化(クリア、番兵設定) ; ; 7 6 5 4 3 2 1 0 ; +-----+-----------------+ ; 1 | 7 6| 5 4 3 2 1 0| ; 2 |15 14|13 12 11 10 9 8| ; | | : : | ; 10 |79 78|77 76 75 74 73 72| ; + +-----------------+ ; 11 |87 86 85 84 83 82 81 80| ←番兵 ; +-----+-----------------+ ; ;--------------------------------------------------------------------- INTBRD MOVLW D'40' MOVWF CNT MOVLW BOARD MOVWF FSR CLRF WK INTBRDL INCF WK,F CLRF INDF ; 0クリア BTFSS WK,2 ; 4バイト毎に番兵 GOTO INTBRDN MOVLW H'FF' ; 番兵'FF'の設定 MOVWF INDF CLRF WK INTBRDN INCF FSR,F DECFSZ CNT,F GOTO INTBRDL ; MOVLW D'4' MOVWF CNT MOVLW H'FF' ; 番兵'FF'の設定 INTBRDL2 MOVWF INDF INCF FSR,F DECFSZ CNT,F GOTO INTBRDL2 RETURN ; ;--------------------------------------------------------------------- ; 盤面を表示する(BOARDのピース情報からLEDBUFを設定) ;--------------------------------------------------------------------- DSPBRD BANK2 CALL CLRBUF MOVLW D'78' ; 座標0〜77までループ MOVWF CNT2 CLRF POS2 DSPBRDL MOVF POS2,W ANDLW B'00000110' ; 6,7,14,15などの番兵部はスキップ SUBLW D'6' BTFSC STATUS,Z GOTO DSPBRDN ; スキップ CALL CHKPCE2 CALL GETCOL CALL SETDSP DSPBRDN INCF POS2,F DECFSZ CNT2,F GOTO DSPBRDL BANK0 RETURN ; ;--------------------------------------------------------------------- ; LEDBUFをクリア ;--------------------------------------------------------------------- CLRBUF MOVLW D'60' MOVWF CNT2 MOVLW LEDBUF MOVWF FSR CLRBUFL CLRF INDF INCF FSR,F DECFSZ CNT2,F GOTO CLRBUFL RETURN ;--------------------------------------------------------------------- ; BOARD座標のピース番号を調べる ; (座標:0,1,2,3,4,5,X,X,8,9 ...)Xは番兵セル ;--------------------------------------------------------------------- CHKPCE2 MOVF POS2,W BANK0 MOVWF FSR MOVWF ODDEVN ; BCF STATUS,C RRF FSR,F ;1/2 MOVLW BOARD ADDWF FSR,F MOVF INDF,W ;w=(FSR)番地の内容 BTFSC ODDEVN,0 ;座標の0ビット目が1なら奇数なので上位4ビット取得 SWAPF INDF,W ;w=(FSR)番地をニブルスワップ ANDLW H'0F' ;下位4ビットを確認 BANK2 RETURN ;--------------------------------------------------------------------- ; ピース番号の色を取得 ;--------------------------------------------------------------------- ORG H'700' GETCOL MOVWF WK2 MOVLW H'07' MOVWF PCLATH MOVF WK2,W ADDWF PCL,F ; ; --BGRBGR ; 暗いBGR, 明るいBGRの順 ; ピース番号 RETLW B'00000000' ; 0 ... ピースが置いてない(黒) RETLW B'00001001' ; 1 ... 赤 RETLW B'00100100' ; 2 ... 青 RETLW B'00011011' ; 3 ... 黄 RETLW B'00100101' ; 4 ... 青紫 RETLW B'00010010' ; 5 ... 緑 RETLW B'00110110' ; 6 ... 水色 RETLW B'00000100' ; 7 ... 暗い青 RETLW B'00001010' ; 8 ... 橙 RETLW B'00111111' ; 9 ... 白 RETLW B'00000010' ; 10 ... 暗い緑 RETLW B'00001100' ; 11 ... 赤紫 RETLW B'00000011' ; 12 ... 暗い黄色 ;--------------------------------------------------------------------- ; BOARD座標のピース番号の色を表示バッファに設定 ; 座標:POS, 色:W ;--------------------------------------------------------------------- SETDSP ; 座標を1/8して6倍(RGB*2)すると表示バッファの列先頭バイト MOVWF COLOR2 MOVF POS2,W MOVWF WK2 BCF STATUS,C RRF WK2,F ; 1/2 BCF STATUS,C RRF WK2,F ; 1/4 BCF STATUS,C RRF WK2,F ; 1/8 BCF STATUS,C RLF WK2,F ; 2倍 MOVF WK2,W BCF STATUS,C RLF WK2,F ; 4倍 ADDWF WK2,W ; 6倍 ADDLW LEDBUF ; LEDバッファの先頭を足す MOVWF FSR ; INDEXレジスタへ ; ; xx543210 MOVF POS2,W ANDLW H'07' ; 下位 0-5 からビット位置算出 CALL DECBIT MOVWF BITPOS2 ;0 なら 0ビット目 ; ループ RGB x 2回(6回) ; SETDSP0 ; 0ビット目(R) BTFSS COLOR2,0 GOTO SETDSP1 MOVF BITPOS2,W IORWF INDF,F ; 1 -> (FSR),0 SETDSP1 ; 1ビット目(G) INCF FSR,F BTFSS COLOR2,1 GOTO SETDSP2 MOVF BITPOS2,W IORWF INDF,F SETDSP2 ; 2ビット目(B) INCF FSR,F BTFSS COLOR2,2 GOTO SETDSP3 MOVF BITPOS2,W IORWF INDF,F SETDSP3 ; 3ビット目(R) INCF FSR,F BTFSS COLOR2,3 GOTO SETDSP4 MOVF BITPOS2,W IORWF INDF,F SETDSP4 ; 4ビット目(G) INCF FSR,F BTFSS COLOR2,4 GOTO SETDSP5 MOVF BITPOS2,W IORWF INDF,F SETDSP5 ; 5ビット目(B) INCF FSR,F BTFSS COLOR2,5 GOTO SETDSP6 MOVF BITPOS2,W IORWF INDF,F SETDSP6 RETURN ; ;--------------------------------------------------------------------- ; LEDBUFをクリア ;--------------------------------------------------------------------- CLRBUFW MOVLW D'60' MOVWF CNT2 MOVLW LEDBUF MOVWF FSR CLRBUFWL MOVLW H'FF' MOVWF INDF INCF FSR,F DECFSZ CNT2,F GOTO CLRBUFWL RETURN ;--------------------------------------------------------------------- END ;--------------------------------------------------------------------- ; 終わり ;---------------------------------------------------------------------