LIST P=PIC16F88; INCLUDE "P16f88.inc" ; あいうえお ; CONFIG1 ; __config 0xFFFF __CONFIG _CONFIG1, _FOSC_INTOSCIO & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CCPMX_RB0 & _CP_OFF ; CONFIG2 ; __config 0xFFFF __CONFIG _CONFIG2, _FCMEN_ON & _IESO_ON errorlevel -302 ; suppress message 302 from list file ;__CONFIG _CCP1_RB0 & _LVP_OFF & _BOREN_ON & _MCLR_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_IO ; INTRC oscillator, RA6 and RA7 are IO pin ; ; ;***** VARIABLE DEFINITIONS (examples) ; example of using Shared Uninitialized Data Section W_TEMP EQU 0x70 ; variable used for context saving ST_TMP EQU 0x71 ; variable used for context saving WAIT_CN EQU 0x22 CN2 EQU 0x23 D4 EQU 0x24 D8 EQU 0x25 D0 EQU 0x26 CC EQU 0x27 RABUF EQU 0x28 RBBUF EQU 0x29 DN EQU 0x2A VN EQU 0x2B MDE EQU 0x2C CI EQU 0x2D FDL EQU 0x2E FDH EQU 0x2F PIL EQU 0x30 PIH EQU 0x31 DD EQU 0x32 SN EQU 0x33 DH EQU 0x34 DL EQU 0x35 CN EQU 0x36 NJ0 EQU 0x37 NJ1 EQU 0x38 NJ2 EQU 0x39 VNC EQU 0x3A NC EQU 0x3B TWDH EQU 0x3C ; 3線設定値H TWDL EQU 0x3D ; 3線設定値L TWC EQU 0x3E ; 3線シリアルカウンター T0BUF EQU 0x3F ; next TMR0 RABB EQU 0x40 ; PORTA real buffer RBBB EQU 0x41 ; PORTB real buffer LRFLG EQU 0x42 ; LEFT(01),RIGHT(10),OTHER(00) FLAG TH EQU 0x43 TM EQU 0x44 TL EQU 0x45 TFH EQU 0x46 TFL EQU 0x48 CA EQU 0x49 CB EQU 0x4A ZS EQU 0x4B ; REG78 EQU 0x78 ; I2C nackを示す REGA0 EQU 0x20 ; I2C slave address(Bank1) REGA1 EQU 0x21 ; I2C sel address(Bank1) REGA2 EQU 0x22 ; I2C data(Bank1) REGA3 EQU 0x23 ; I2C output buffer(Bank1) REGA4 EQU 0x24 ; (Bank1) REGA5 EQU 0x25 ; (Bank1) ICK EQU 0x01 IDA EQU 0x02 ; ; ORG 0 CLRF PCLATH GOTO INIT ; ORG 4 MOVWF W_TEMP MOVF STATUS, W MOVWF ST_TMP ; CALL INT HANDLER HERE MOVF ST_TMP, W MOVWF STATUS SWAPF W_TEMP, F SWAPF W_TEMP, W RETFIE ; ; INIT CLRF STATUS CLRF TMR0 CLRF INTCON ; 割り込み制御レジスタ CLRF PIR1 ; 割り込みフラグ MOVLW B'00000000' MOVWF ADCON0 ; ADON=0 ; BSF STATUS, RP0 ; BANK1 MOVLW B'00000000' MOVWF ANSEL ; PORTA all pins set as digital MOVLW B'10000000' MOVWF ADCON1 ; 設定不要(過去の残り) MOVLW B'00100011' ; EN RS NC {AFS ASC ASD} RDT RCK MOVWF TRISA MOVLW B'00001110' ; DB7 DB6 DB5 DB4 RSW IDA ICK TMG MOVWF TRISB MOVLW B'01000111' MOVWF OPTION_REG ; TMR0 Prescaler 1:256, weak pull-up ON MOVLW B'01110100' MOVWF OSCCON ; 8MHz BCF STATUS, RP0 ; BANK0 MOVLW B'00011100' MOVWF PORTA ; AFS=1, ASC=1, ASD=1 ; CALL INILCD CALL FVSINI ; DN, VN, SN, MDE初期化 ; MOVF PORTA, W MOVWF RABUF MOVF PORTB, W MOVWF RBBUF MOVF TMR0, W ADDLW .2 MOVWF T0BUF ; ; LOOP BCF PORTB, 0 ; 実行中フラグOFF MOVF TMR0, W SUBWF T0BUF, W BTFSS STATUS, Z GOTO LOOP MOVF TMR0, W ADDLW .63 MOVWF T0BUF BSF PORTB, 0 ; 実行中フラグON CALL SWCHK ; SWをスキャンし押されていたら実行 GOTO LOOP ; ; ; MDE: mode=0:Freq, 1:Volume, 2:Tone ; SWCHK CLRF LRFLG ; LEFT(01),RIGHT(10) FLAG MOVF PORTA, W MOVWF RABB ; 今回の値をsave ; BTFSC RABUF, 0 ; 前回CK==0? GOTO RPUSH BTFSS RABB, 0 ; 今回のCK==1? GOTO RPUSH BTFSS RABUF, 1 GOTO LL3 ; 前回のDT==0 BTFSS RABB, 1 GOTO RPUSH ; 前回のDT=1で今回DT=0はエラー BSF LRFLG, 1 ; RIGHT(10) GOTO LL1 ; LL3 BTFSC RABB, 1 GOTO RPUSH ; 前回のDT=0で今回DT=1はエラー BSF LRFLG, 0 ; LEFT(01) LL1 MOVLW .1 SUBWF MDE, W BTFSS STATUS, C GOTO DNUD ; CY=0 MDE=0→DNup/down BTFSC STATUS, Z GOTO VNUD ; MDE=1→VNUD GOTO SNUD ; MDE=2→SNUD ; ; PORTA1に応じて、DNを±1(0以下、204以上はそのまま) DNUD BTFSC LRFLG, 1 ; 左右(どちらか) GOTO SWCK3 ; LRFLG[1]==1 MOVLW .204 SUBWF DN, W BTFSC STATUS, C GOTO DNU1 ; CY==1→DN>=204 max limit INCF DN, F GOTO SWCK4 ; DNU1 BTFSC STATUS, Z GOTO RPUSH MOVLW .204 MOVWF DN ; DN:204でLIMIT GOTO RPUSH ; SWCK3 MOVF DN, F BTFSC STATUS, Z GOTO RPUSH ; DN==0 min limit DECF DN, F SWCK4 CALL FCAL CALL FDSP CALL FSSUB ; BANK, PIL, PIH, 0e-regだけ設定 GOTO RPUSH ; ; PORTA1に応じて、VNを±1(0以下、105以上はそのまま) VNUD BTFSC LRFLG, 1 GOTO VND1 ; LRFLG[1]==1 MOVLW .105 SUBWF VN, W BTFSC STATUS, C GOTO VNU1 ; CY==1→VN>=105 max limit INCF VN, F GOTO SWCK6 ; VNU1 BTFSC STATUS, Z GOTO RPUSH MOVLW .105 MOVWF VN ; VN:105でLIMIT GOTO RPUSH ; VND1 MOVF VN, F BTFSC STATUS, Z GOTO RPUSH ; DN==0 min limit DECF VN, F SWCK6 CALL VCAL CALL VDSP CALL VSET GOTO RPUSH ; ; PORTA1に応じて、SNをINC/DEC(0xFF、0x00~0B、0x10~1B、…、0x90~9B) ; SNUD BTFSC LRFLG, 1 GOTO SND0 ; DEC INCF SN, W BTFSS STATUS, Z GOTO SNU1 SNU0 INCF SN, F GOTO SND3 SNU1 MOVF SN, W ANDLW 0x0F MOVWF D0 ; DOはワークレジスタ MOVLW .11 SUBWF D0, W BTFSS STATUS, C GOTO SNU0 ; DO<11 MOVF SN, W ANDLW 0xF0 MOVWF D0 ; DOはワークレジスタ SWAPF D0, F MOVLW .9 SUBWF D0, W BTFSS STATUS, C GOTO SNU2 ; D0<9 MOVLW 0x9B MOVWF SN GOTO RPUSH ; Upper Limit→No Change ; SNU2 INCF D0, F ; 上位INC SWAPF D0, F MOVF D0,W MOVWF SN GOTO SND3 ; SND0 INCF SN, W BTFSC STATUS, Z GOTO RPUSH ; SN==0xFF MOVF SN, F BTFSS STATUS, Z GOTO SND2 ; SN!=0 SND1 DECF SN, F GOTO SND3 ; SND2 MOVF SN, W ANDLW 0x0F BTFSS STATUS, Z GOTO SND1 ; 下位4bit !=0 SWAPF SN, F DECF SN, F ; 上位4bitをDEC SWAPF SN, F MOVLW 0x0B IORWF SN, F ; SND3 CALL SCAL ; SN→{TH,TM,TL}と{TFH,TFL}, CA,CBを算出 CALL SDSP ; LCDにトーン周波数とキーを表示 CALL SSET ; AD9833に{TH,TM,TL}を設定 ; ; GOTO RPUSH ; ; ; ロータリーエンコーダーのPUSH ; RBBUF ; ROTARY-PUSH: RB3 ; ; RPUSH MOVF RABB, W MOVWF RABUF ; MOVF PORTB, W MOVWF RBBB ; real値 BTFSC RBBB, 3 GOTO SWCK7 ; B3==1 BTFSS RBBUF, 3 ; 前回値 GOTO SWCK7 ; BB3==0 ; MOVLW .1 SUBWF MDE, W BTFSS STATUS, C GOTO DNST ; CY=0 MDE=0→DNSet BTFSC STATUS, Z GOTO VNST ; MDE=1→VNSet GOTO SNST ; MDE=2→SNSet ; DNST MOVLW .0 CALL EEWRT INCF MDE, F ; mode: Freq→Volume MOVLW B'10001001' ; LOCATE(9,0) CALL LLOC GOTO SWCK7 ; VNST MOVLW .1 CALL EEWRT INCF MDE, F ; mode: Volume→Tone MOVLW B'11000000' ; LOCATE(0,1) CALL LLOC GOTO SWCK7 ; SNST MOVLW .2 CALL EEWRT CLRF MDE ; mode: Tone→Freq MOVLW B'10000000' ; LOCATE(0,0) CALL LLOC ; SWCK7 MOVF RBBB, W MOVWF RBBUF RETURN ; ; FVSINI MOVLW .0 ; DN restore CALL EEREA MOVWF DN CALL FCAL CALL FDSP CALL FSET ; MOVLW .1 ; VN restore CALL EEREA MOVWF VN CALL VCAL CALL VDSP CALL VSET ; MOVLW .2 ; SN restore CALL EEREA MOVWF SN CALL SCAL CALL SDSP CALL SSET ; CLRF MDE ; mode: Freq MOVLW B'10000000' ; LOCATE(0,0) CALL LLOC RETURN ; ; ; FCAL ; DN(0~204)を持って来て、表示用の875~1079と、 ; NS73Mへの設定値((FREQx1e5+304e3)÷8192)を作る。 ; 引数:DN(出したい周波数番号、0=87.5M、204=107.9M) ; FCAL MOVLW .92 SUBWF DN, W BTFSS STATUS, C GOTO L10 ; DN<92 MOVLW .150 SUBWF DN, W BTFSS STATUS, C GOTO L11 ; 92≦DN<150 MOVLW .179 SUBWF DN, W BTFSS STATUS, C GOTO L12 ; 150≦DN<179 MOVLW .179 ; 179≦DN MOVWF CI MOVLW 0x32 MOVWF PIH MOVLW 0x67 MOVWF PIL GOTO RCAL00 ; L12 MOVLW .150 ; 150≦DN<179 MOVWF CI MOVLW 0x31 MOVWF PIH MOVLW 0x05 MOVWF PIL GOTO RCAL00 ; L11 MOVLW .121 ; 92≦DN<150 SUBWF DN, W BTFSS STATUS, C GOTO L13 MOVLW .121 ; 121≦DN<150 MOVWF CI MOVLW 0x2F MOVWF PIH MOVLW 0xA3 MOVWF PIL GOTO RCAL00 ; L13 MOVLW .92 ; 92≦DN<121 MOVWF CI MOVLW 0x2E MOVWF PIH MOVLW 0x41 MOVWF PIL GOTO RCAL00 ; L10 MOVLW .34 ; DN<92 SUBWF DN, W BTFSS STATUS, C GOTO L14 ; DN<34 MOVLW .63 SUBWF DN, W BTFSS STATUS, C GOTO L15 MOVLW .63 ; 63≦DN<92 MOVWF CI MOVLW 0x2C MOVWF PIH MOVLW 0xDF MOVWF PIL GOTO RCAL00 ; L15 MOVLW .34 ; 34≦DN<63 MOVWF CI MOVLW 0x2B MOVWF PIH MOVLW 0x7D MOVWF PIL GOTO RCAL00 ; L14 MOVLW .5 ; DN<34 SUBWF DN, W BTFSS STATUS, C GOTO L16 ; DN<5 MOVLW .5 ; 5≦DN<34 MOVWF CI MOVLW 0x2A MOVWF PIH MOVLW 0x1B MOVWF PIL GOTO RCAL00 ; L16 MOVF DN, W BTFSC STATUS, Z GOTO L17 MOVLW .1 ; 1≦DN<4 MOVWF CI MOVLW 0x29 MOVWF PIH MOVLW 0xEA MOVWF PIL GOTO RCAL00 ; L17 CLRF CI ; DN==0 MOVLW 0x29 MOVWF PIH MOVLW 0xDE MOVWF PIL ; RCAL00 MOVLW .1 MOVWF DD ; DD: 5回に1回+13(残りは+12)にするためのカウンタ RCAL01 MOVF CI, W SUBWF DN, W BTFSC STATUS, Z RETURN ; END OF FCAL {PIH, PIL}出来た DECF DD, F BTFSS STATUS, Z GOTO RCAL03 ; DD!=0->+12 MOVLW .5 ; DD==0->+13 MOVWF DD MOVLW .13 GOTO RCAL04 RCAL03 MOVLW .12 RCAL04 ADDWF PIL, F BTFSC STATUS, C INCF PIH, F INCF CI, F GOTO RCAL01 ; ; ; 1234567890123456 ; F:107.9M V:-20dB ; T:14080Hz A ; FDSP MOVLW B'10000000' ; LOCATE(0,0) CALL LLOC MOVLW A'F' MOVWF D4 CALL WRITE_LCD4 MOVLW A':' MOVWF D4 CALL WRITE_LCD4 ; MOVLW 0x03 MOVWF FDH ; {FDH,FDL}の初期値=875(0x36B) MOVLW 0x6B ADDWF DN, W MOVWF FDL BTFSC STATUS, C INCF FDH, F ; {FDH,FDL} =+ DN MOVLW 0x03 MOVWF DH MOVLW 0xE8 MOVWF DL ; {DH,HL} <= 1000(0x3E8) CALL DIVW ; {FDH,FDL}÷1000→CN 余りは{FDH,FDL}に残る MOVLW A' ' MOVF CN, F BTFSS STATUS, Z MOVLW A'1' MOVWF D4 CALL WRITE_LCD4 ; 千の桁は' ' or '1' CLRF DH MOVLW 0x64 MOVWF DL ; {DH,HL} <= 100(0x64) CALL DIVW ; {FDH,FDL}÷100→CN、余りは{FDH,FDL}に残る MOVF CN, W MOVWF D4 CALL NUMOUT ; 100の桁表示 MOVLW 0x0A MOVWF DL ; {DH,HL} <= 10(0x0A) CALL DIVW ; {FDH,FDL}÷10→CN、余りは{FDH,FDL}に残る MOVF CN, W MOVWF D4 CALL NUMOUT ; 10の桁表示 MOVLW A'.' ; 小数点 MOVWF D4 CALL WRITE_LCD4 MOVF FDL, W MOVWF D4 CALL NUMOUT ; 1の桁表示 MOVLW A'M' MOVWF D4 CALL WRITE_LCD4 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 ; MOVLW B'10000000' ; LOCATE(0,0) CALL LLOC RETURN ; ; ; {FDH,FDL}÷{DH,DL}(符号なし) ; 結果は1BYTE以内を想定=>CNに入る ; 余りが{FDH,FDL}に残る ; DIVW CLRF CN DV01 INCF CN, F MOVF DL, W SUBWF FDL, F BTFSS STATUS, C DECF FDH, F ; CY==0; borrowあり MOVF DH, W SUBWF FDH, F BTFSS FDH, 7 GOTO DV01 ; まだプラス DECF CN, F ; 引き過ぎたので1回分戻す MOVF DL, W ADDWF FDL, F BTFSC STATUS, C INCF FDH, F MOVF DH, W ADDWF FDH, F RETURN ; ; ; I2Cで周波数をNS73MのPIH→R4, PIL→R3に設定 (全レジスタ設定) ; FSET MOVLW 0xCC ; NS73M:0e-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x0e MOVWF REGA1 MOVLW 0x05 ; 機能不明 MOVWF REGA2 CALL I2CO2 ; MOVLW 0xCC ; NS73M:01-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x01 MOVWF REGA1 MOVLW 0xb4 ; PilotOn MOVWF REGA2 CALL I2CO2 ; MOVLW 0xCC ; NS73M:02-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x02 MOVWF REGA1 MOVLW 0x05 ; 0.5mW MOVWF REGA2 CALL I2CO2 ; CALL FSSUB ; Band, PIL, PIH, 0e-reg ; MOVLW 0xCC ; NS73M:00-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x00 MOVWF REGA1 MOVLW 0x01 ; PowerOn他 MOVWF REGA2 CALL I2CO2 ; MOVLW 0xCC ; NS73M:06-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x06 ; ChargePump MOVWF REGA1 MOVLW 0x1a ; 1.25uA MOVWF REGA2 CALL I2CO2 ; RETURN ; ; FSSUB MOVLW 0xCC ; NS73M:08-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x08 MOVWF REGA1 BCF STATUS, RP0 ; Bank0 MOVLW .86 SUBWF DN, W BTFSC STATUS, C GOTO L086 ; DN≧86 MOVLW .26 SUBWF DN, W BTFSC STATUS, C GOTO L026 ; 86>DN≧26 MOVLW 0x1b ; B3(87.5-90.0M) GOTO LA08 L026 MOVLW 0x1A ; B2(90.1-96.0M) GOTO LA08 L086 MOVLW .146 SUBWF DN, W BTFSC STATUS, C GOTO L146 ; DN≧146 MOVLW 0x19 ; B1(96.1-102.0M) GOTO LA08 L146 MOVLW 0x18 ; B0(102.1-108.0M) LA08 BSF STATUS, RP0 ; Bank1 MOVWF REGA2 CALL I2CO2 ; MOVLW 0xCC ; NS73M:03-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x03 MOVWF REGA1 BCF STATUS, RP0 ; Bank0 MOVF PIL, W BSF STATUS, RP0 ; Bank1 MOVWF REGA2 CALL I2CO2 ; MOVLW 0xCC ; NS73M:04-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x04 MOVWF REGA1 BCF STATUS, RP0 ; Bank0 MOVF PIH, W BSF STATUS, RP0 ; Bank1 MOVWF REGA2 CALL I2CO2 ; MOVLW 0xCC ; NS73M:0e-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x0e ; 機能不明 MOVWF REGA1 MOVLW 0x05 MOVWF REGA2 CALL I2CO2 ; RETURN ; ; ; VN(0-105)からNJU72341の設定値を生成(ステレオは共通設定) ; ; 0: mute, 1: -95dB, 2: -94dB, .. ,96:0dB, ; 97~99: +1~+3dB, 100~102: +4~+6dB, ; 103~105: +7~+9dB ; VCAL MOVLW .96 SUBWF VN, W BTFSC STATUS, C ; GOTO NL2 ; CY=1、VN≧96 CLRF NJ0 MOVF VN, W ADDLW 0x17 ; +23(VN=1…-95dB…0x18) IORLW 0x80 MOVWF NJ1 MOVWF NJ2 RETURN ; NL2 MOVWF VNC DECF VNC, F ; VN-96-1→VNC(テンポラリ) MOVLW .3 CLRF NC ; ÷3スタート NL3 INCF NC, F SUBWF VNC, F BTFSS VNC, 7 GOTO NL3 ; MSB==0 ADDWF VNC, F ; MSB==1 DECF NC, F MOVF VNC, W ; VNCには余りが入ってる ADDLW 0x75 ; 0→0x75、1→0x76、2→0x77 IORLW 0x80 MOVWF NJ1 MOVWF NJ2 INCF NC, F ; NCには、商が入ってる MOVF NC, W ; 97~99→01、100~102→10、103~105→11 BCF STATUS, C RLF NC, F RLF NC, F IORWF NC, W ; D[3:2]=VOLUME 2A、D[1:0]=VOLUME 1A MOVWF NJ0 RETURN ; ; VDSP MOVLW B'10001001' ; LOCATE(9,0) CALL LLOC MOVLW A'V' MOVWF D4 CALL WRITE_LCD4 MOVLW A':' MOVWF D4 CALL WRITE_LCD4 ; MOVLW .96 SUBWF VN, W BTFSS STATUS, C GOTO NL5 ; CY=0、VN<96 BTFSC STATUS, Z GOTO NL4 ; Z=1、VN==96 MOVWF VNC ; VNC:VN-96のテンポラリ収納 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 MOVLW A'+' MOVWF D4 CALL WRITE_LCD4 MOVF VNC, W MOVWF D4 CALL NUMOUT GOTO NL6 ; NL4 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 MOVLW A'0' MOVWF D4 CALL WRITE_LCD4 GOTO NL6 ; NL5 MOVWF VNC ; テンポラリレジスタVNCに(VN-96)(マイナスの値)を収納 COMF VNC, F INCF VNC, F ; 2の補数を取ってプラスの値 MOVLW .96 SUBWF VNC, W BTFSC STATUS, Z GOTO NL7 ; VNC==96→Mute CALL DIVV ; VNC÷10→商:CN、余り:VNC MOVF CN, F BTFSS STATUS, Z GOTO NL8 ; CN!=0 MOVLW A' ' ; 10の桁が0なので、ゼロサプレス MOVWF D4 CALL WRITE_LCD4 MOVLW A'-' MOVWF D4 CALL WRITE_LCD4 GOTO NL9 ; NL8 MOVLW A'-' MOVWF D4 CALL WRITE_LCD4 MOVF CN, W MOVWF D4 CALL NUMOUT ; 10の桁を印字 NL9 MOVF VNC, W MOVWF D4 CALL NUMOUT ; 1の桁を印字 NL6 MOVLW A'd' MOVWF D4 CALL WRITE_LCD4 MOVLW A'B' MOVWF D4 CALL WRITE_LCD4 GOTO NL10 ; NL7 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 MOVLW A'M' MOVWF D4 CALL WRITE_LCD4 MOVLW A'u' MOVWF D4 CALL WRITE_LCD4 MOVLW A't' MOVWF D4 CALL WRITE_LCD4 MOVLW A'e' MOVWF D4 CALL WRITE_LCD4; ; NL10 MOVLW B'10001001' ; LOCATE(9,0) CALL LLOC RETURN ; ; DIVV CLRF CN MOVLW .10 DVV1 INCF CN, F SUBWF VNC, F BTFSS VNC, 7 ; MSB==1? GOTO DVV1 ; MSB==0; まだプラス DECF CN, F ; 引き過ぎたので1回分戻す ADDWF VNC, F RETURN ; ; ; NJU72341 I2Cで設定 ; VSET MOVLW 0x88 ; NJU72341:00-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x00 MOVWF REGA1 BCF STATUS, RP0 ; Bank0 MOVF NJ0, W BSF STATUS, RP0 ; Bank1 MOVWF REGA2 CALL I2CO2 ; MOVLW 0x88 ; NJU72341:01-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x01 MOVWF REGA1 BCF STATUS, RP0 ; Bank0 MOVF NJ1, W BSF STATUS, RP0 ; Bank1 MOVWF REGA2 CALL I2CO2 ; MOVLW 0x88 ; NJU72341:02-reg BSF STATUS, RP0 ; Bank1 MOVWF REGA0 MOVLW 0x02 MOVWF REGA1 BCF STATUS, RP0 ; Bank0 MOVF NJ2, W BSF STATUS, RP0 ; Bank1 MOVWF REGA2 CALL I2CO2 RETURN ; ; ; SNからAD9833への設定値, 表示用周波数値とキーの文字を算出 ; SCAL INCF SN, W BTFSS STATUS, Z GOTO SCAL0 MOVLW 0x00 MOVWF TH MOVLW 0x29 MOVWF TM MOVLW 0xF1 MOVWF TL MOVLW 0x03 ; {TFH,TFL} <= 0x03E8(1000Hz) MOVWF TFH MOVLW 0xE8 MOVWF TFL MOVLW A'1' MOVWF CA MOVLW A'K' MOVWF CB RETURN ; SCAL0 MOVF SN, W MOVWF CI ; CIはワークレジスタ SWAPF CI, F MOVLW 0x0F ; SNの上位bitは、オクターブ(0~9)。一番高い9で表引きして差分は÷2 ANDWF CI, W SUBLW .9 ;W=9-W MOVWF CI CALL TTBL ; SN(0-11)→{TH,TM,TL}と{TFH,TFL},{CA,CB} INCF CI, F ; CIオクターブ差分の数2で割る MOVF CI, W MOVWF D8 ; D8もワークレジスタ TOCT1 DECF CI, F BTFSC STATUS, Z GOTO TOCT2 ; シフト終了 BCF STATUS, C RRF TH, F RRF TM, F RRF TL, F GOTO TOCT1 ; TOCT2 BTFSS STATUS, C GOTO TOCT3 INCF TL, F ; round BTFSS STATUS, Z GOTO TOCT3 INCF TM, F BTFSS STATUS, Z GOTO TOCT3 INCF TH, F ; TOCT3 DECF D8, F ; 表示用の{TFH,TFL}もCIオクターブ差分の数2で割る BTFSC STATUS, Z GOTO TOCT4 BCF STATUS, C RRF TFH, F RRF TFL, F GOTO TOCT3 ; TOCT4 BTFSS STATUS, C GOTO TOCT5 INCF TFL, F ; round BTFSS STATUS, Z GOTO TOCT5 INCF TFH, F TOCT5 RETURN ; ; ; TONE TABLE SN(0-11)→最高オクターブの{TH,TM,TL}(AD98設定用)と{TFH,TFL}(表示用) ; SNは保持する ; TTBL MOVF SN, W MOVWF D8 ; D8はワークレジスタ MOVLW 0x0F ANDWF D8, F ; 下4bit:0~11がラ~ソ# MOVLW .6 SUBWF D8, W BTFSC STATUS, C GOTO TTBL6 ; D8>=6 ; D8=0-5 BTFSC D8, 0 ; D8のLSB GOTO TTBL3 ; D8は奇数 ; D8=0,2,4 BCF STATUS, C RRF D8, F ; D8=0(0), 1(2) ,2(4) MOVLW .1 SUBWF D8, W BTFSC STATUS, Z GOTO TTBL1 ; D8=1(2) BTFSC STATUS, C GOTO TTBL2 ; D8=2(4) ; D8=0(0) MOVLW 0x02 MOVWF TH MOVLW 0x4E MOVWF TM MOVLW 0x8F MOVWF TL MOVLW 0x37 ; {TFH,TFL} <= 0x3700(14080Hz) MOVWF TFH MOVLW 0x00 MOVWF TFL MOVLW A'A' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; D8=1(2) TTBL1 MOVLW 0x02 MOVWF TH MOVLW 0x96 MOVWF TM MOVLW 0xE1 MOVWF TL MOVLW 0x3D ; {TFH,TFL} <= 0x3DBC(15804Hz) MOVWF TFH MOVLW 0xBC MOVWF TFL MOVLW A'B' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; D8=2(4) TTBL2 MOVLW 0x02 MOVWF TH MOVLW 0xE8 MOVWF TM MOVLW 0x0E MOVWF TL MOVLW 0x45 ; {TFH,TFL} <= 0x454C(17740Hz) MOVWF TFH MOVLW 0x4C MOVWF TFL MOVLW A'C' MOVWF CA MOVLW A'#' MOVWF CB RETURN ; TTBL3 BCF STATUS, C RRF D8, F ; D8=0(1), 1(3) ,2(5) MOVLW .1 SUBWF D8, W BTFSC STATUS, Z GOTO TTBL4 ; D8=1(3) BTFSC STATUS, C GOTO TTBL5 ; D8=2(5) ; D8=0(1) MOVLW 0x02 MOVWF TH MOVLW 0x71 MOVWF TM MOVLW 0xAD MOVWF TL MOVLW 0x3A ; {TFH,TFL} <= 0x3A45(14917Hz) MOVWF TFH MOVLW 0x45 MOVWF TFL MOVLW A'A' MOVWF CA MOVLW A'#' MOVWF CB RETURN ; D8=1(3) TTBL4 MOVLW 0x02 MOVWF TH MOVLW 0xBE MOVWF TM MOVLW 0x4C MOVWF TL MOVLW 0x41 ; {TFH,TFL} <= 0x4168(16744Hz) MOVWF TFH MOVLW 0x68 MOVWF TFL MOVLW A'C' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; D8=2(5) TTBL5 MOVLW 0x03 MOVWF TH MOVLW 0x14 MOVWF TM MOVLW 0x4D MOVWF TL MOVLW 0x49 ; {TFH,TFL} <= 0x496B(18795Hz) MOVWF TFH MOVLW 0x6B MOVWF TFL MOVLW A'D' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; TTBL6 MOVLW .6 SUBWF D8, F ; 実際に引く BTFSC D8, 0 ; D8のLSB GOTO TTBL9 ; D8は奇数 ; D8=0(6),2(8),4(10) BCF STATUS, C RRF D8, F ; D8=0(6), 1(8) ,2(10) MOVLW .1 SUBWF D8, W BTFSC STATUS, Z GOTO TTBL7 ; D8=1(8) BTFSC STATUS, C GOTO TTBL8 ; D8=2(10) ; D8=0(6) MOVLW 0x03 MOVWF TH MOVLW 0x43 MOVWF TM MOVLW 0x2D MOVWF TL MOVLW 0x4D ; {TFH,TFL} <= 0x4DC8(19912Hz) MOVWF TFH MOVLW 0xC8 MOVWF TFL MOVLW A'D' MOVWF CA MOVLW A'#' MOVWF CB RETURN ; D8=1(8) TTBL7 MOVLW 0x03 MOVWF TH MOVLW 0xA9 MOVWF TM MOVLW 0x74 MOVWF TL MOVLW 0x57 ; {TFH,TFL} <= 0x574F(22351Hz) MOVWF TFH MOVLW 0x4F MOVWF TFL MOVLW A'F' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; D8=2(10) TTBL8 MOVLW 0x04 MOVWF TH MOVLW 0x1C MOVWF TM MOVLW 0x41 MOVWF TL MOVLW 0x62 ; {TFH,TFL} <= 0x6200(25088Hz) MOVWF TFH MOVLW 0x00 MOVWF TFL MOVLW A'G' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; TTBL9 BCF STATUS, C RRF D8, F ; D8=0(7), 1(9) ,2(11) MOVLW .1 SUBWF D8, W BTFSC STATUS, Z GOTO TTBL10 ; D8=1(9) BTFSC STATUS, C GOTO TTBL11 ; D8=2(11) ; D8=0(7) MOVLW 0x03 MOVWF TH MOVLW 0x74 MOVWF TM MOVLW 0xD6 MOVWF TL MOVLW 0x52 ; {TFH,TFL} <= 0x5268(21096Hz) MOVWF TFH MOVLW 0x68 MOVWF TFL MOVLW A'E' MOVWF CA MOVLW A' ' MOVWF CB RETURN ; D8=1(9) TTBL10 MOVLW 0x03 MOVWF TH MOVLW 0xE1 MOVWF TM MOVLW 0x32 MOVWF TL MOVLW 0x5C ; {TFH,TFL} <= 0x5C80(23680Hz) MOVWF TFH MOVLW 0x80 MOVWF TFL MOVLW A'F' MOVWF CA MOVLW A'#' MOVWF CB RETURN ; D8=2(11) TTBL11 MOVLW 0x04 MOVWF TH MOVLW 0x5A MOVWF TM MOVLW 0xD3 MOVWF TL MOVLW 0x67 ; {TFH,TFL} <= 0x67D4(26580Hz) MOVWF TFH MOVLW 0xD4 MOVWF TFL MOVLW A'G' MOVWF CA MOVLW A'#' MOVWF CB RETURN ; ;{TFH,TFL}をシフトして、LCDにトーン周波数を表示 (28~26581Hz) ; SDSP CLRF ZS ; ZeroSuppless=yes MOVLW B'11000000' ; LOCATE(0.1) CALL LLOC MOVLW A'T' MOVWF D4 CALL WRITE_LCD4 MOVLW A':' MOVWF D4 CALL WRITE_LCD4 ; MOVF TFH, W MOVWF FDH MOVF TFL, W ;{TFH,TFL}→{{FDH,FDL} MOVWF FDL MOVLW 0x27 MOVWF DH MOVLW 0x10 MOVWF DL ; {DH,HL} <= 10000(0x2710) CALL DIVW ; {FDH,FDL}÷{DH,HL}→CN 余りは{FDH,FDL}に残る MOVF CN, W BTFSS STATUS, Z GOTO SD01 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 ; 10000の桁はゼロサプレス GOTO SD02 ; SD01 MOVWF D4 CALL NUMOUT ; 10000の桁表示 BSF ZS, 0 ; ZeroSuppless=no SD02 MOVLW 0x03 MOVWF DH MOVLW 0xE8 MOVWF DL ; {DH,HL} <= 1000(0x3E8) CALL DIVW ; {FDH,FDL}÷{DH,HL}→CN 余りは{FDH,FDL}に残る MOVF CN, W BTFSS STATUS, Z GOTO SD03 BTFSC ZS, 0 GOTO SD03 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 ; 1000の桁もゼロサプレス GOTO SD04 ; SD03 MOVWF D4 CALL NUMOUT ; 1000の桁表示 BSF ZS, 0 ; ZeroSuppless=no SD04 CLRF DH MOVLW 0x64 MOVWF DL ; {DH,HL} <= 100(0x64) CALL DIVW ; {FDH,FDL}÷100→CN、余りは{FDH,FDL}に残る MOVF CN, W BTFSS STATUS, Z GOTO SD05 BTFSC ZS, 0 GOTO SD05 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 ; 100の桁もゼロサプレス GOTO SD06 ; SD05 MOVWF D4 CALL NUMOUT ; 100の桁表示 BSF ZS, 0 ; ZeroSuppless=no SD06 MOVLW 0x0A MOVWF DL ; {DH,HL} <= 10(0x0A) CALL DIVW ; {FDH,FDL}÷10→CN、余りは{FDH,FDL}に残る MOVF CN, W MOVWF D4 CALL NUMOUT ; 10の桁表示 MOVF FDL, W MOVWF D4 CALL NUMOUT ; 1の桁表示 MOVLW A'H' MOVWF D4 CALL WRITE_LCD4 MOVLW A'z' MOVWF D4 CALL WRITE_LCD4 MOVLW A' ' MOVWF D4 CALL WRITE_LCD4 MOVF CA, W MOVWF D4 CALL WRITE_LCD4 ; CA表示 MOVF CB, W MOVWF D4 CALL WRITE_LCD4 ; CB表示 ; MOVLW B'11000000' ; LOCATE(0.1) CALL LLOC RETURN ; ; AD9833に{TH,TM,TL}を設定 ; SSET MOVLW 0x20 MOVWF TWDH MOVLW 0x00 MOVWF TWDL CALL TWOUT MOVLW .160 MOVWF WAIT_CN ; 160 *1.5us=240us CALL WAIT_US MOVF TM, W ANDLW 0x3F ; LOWER 14bit IORLW 0x40 MOVWF TWDH MOVF TL, W MOVWF TWDL CALL TWOUT MOVLW .160 MOVWF WAIT_CN ; 160 *1.5us=240us CALL WAIT_US MOVLW 0x40 MOVWF TWDH MOVF TH, W MOVWF TWDL BCF STATUS, C BTFSC TM, 7 BSF STATUS, C RLF TWDL, F BCF STATUS, C BTFSC TM, 6 BSF STATUS, C RLF TWDL, F CALL TWOUT MOVLW .160 MOVWF WAIT_CN ; 160 *1.5us=240us CALL WAIT_US RETURN ; ; ; シリアル出力。16ビットデータを{TWDH, TWDL}に入れて来る TWOUT MOVLW .16 MOVWF TWC ; カウンタ BCF PORTA, 4 ; FSYNC<=0 TW01 BCF STATUS, C ; CY<=0(不要かも) RLF TWDL, F RLF TWDH, F ; 16bitを左1bitシフト→CYに入れる CALL TWSUB ; CYを出力。CLKをHigh→Low DECFSZ TWC, F GOTO TW01 BSF PORTA, 4 ; FSYNC<=1 BSF PORTA, 3 ; SCLK<=1 RETURN ; ; 3線シリアル1ビット出力サブ(ThreeWireSubroutine) TWSUB BSF PORTA, 3 ; SCLK<=1 BTFSC STATUS, C ; CYを出力 GOTO TWS1 BCF PORTA, 2 ; ASD<=0 GOTO TWS2 TWS1 BSF PORTA, 2 ; ASD<=1 TWS2 MOVLW .5 MOVWF WAIT_CN ; 5 *1.5us=7.5us CALL WAIT_US BCF PORTA, 3 ; SCLK<=0 MOVLW .5 ; BaudRate:66kHz MOVWF WAIT_CN ; 5 *1.5us=7.5us CALL WAIT_US RETURN ; ; ; I2C出力、{REGA0, REGA1, REGA2}に送る値を入れてCALL ; IDAは、PORTB, 2 ; ICKは、PORTB, 1 ; TEB(PLL UNLOCK)は、テストピン。(PICへの入力なし) ; I2COUT BSF STATUS, RP0 ; (Bank1) I2CO2 BSF TRISB, IDA ; DA=IN HIGHを出力 NOP BSF TRISB, ICK ; CK=IN HIGHを出力 NOP BCF STATUS, RP0 ; (Bank0) BCF PORTB, IDA ; DA=0 BSF STATUS, RP0 ; (Bank1) BCF TRISB, IDA ; DA=0(OUT) LOWを出力 NOP BCF STATUS, RP0 ; (Bank0) BCF PORTB, ICK ; CK=0 BSF STATUS, RP0 BCF TRISB, ICK ; CK=0(OUT) LOWを出力 MOVF REGA0, W MOVWF REGA4 ; REGA4は Bank1。 BCF STATUS, RP0 ; (Bank0) CALL I2CBT ; 0xCCを出力 MOVF REG78, W BSF STATUS, RP0 ; (Bank1) MOVWF REGA3 ; REG78(NAKで1)=>0xA3レジスタ MOVF REGA1, W MOVWF REGA4 ; 0xA1レジスタ=>0xA4レジスタ BCF STATUS, RP0 ; (Bank0) CALL I2CBT ; 2byte目、A1レジの内容を出力 MOVF REG78, W BSF STATUS, RP0 ; (Bank1) MOVWF REGA3 ; REG78(NAKで1)=>0xA3レジスタ MOVF REGA2, W MOVWF REGA4 ; 0xA2レジスタ=>0xA4レジスタ BCF STATUS, RP0 ; (Bank0) CALL I2CBT ; 3byte目出力 MOVF REG78, W BSF STATUS, RP0 ; (Bank1) MOVWF REGA3 ; REG78(NAKで1)=>0xA3レジスタ BCF TRISB, IDA ; DA=OUT NOP BSF TRISB, ICK ; CK=IN L511 BCF STATUS, RP0 ; (Bank0) BTFSC PORTB, ICK ; CK=1? GOTO L516 BSF STATUS, RP0 ; (Bank1) GOTO L511 L516 NOP NOP NOP NOP BSF STATUS, RP0 ; (Bank1) BSF TRISB, IDA ; DA=IN NOP MOVLW 0x01 BCF STATUS, RP0 ; (Bank0) MOVWF WAIT_CN ; WAIT PARAM=1ms CALL WAIT_MS ; wait 1ms BSF STATUS, RP0 ; (Bank1) MOVF REGA3, F BTFSS STATUS, Z GOTO L527 ; A3reg==0 MOVLW 0x01 GOTO L528 L527 MOVLW 0x00 L528 MOVWF REG78 ; REG78に正常なら00、NGなら01を入れてリターン BCF STATUS, RP0 ; (Bank0) RETLW 0x00 ; ; ; CKをLOWにして5us待ってデータを入れ替え5us待ってCKをHIGH、10us待つ。 ; I2CBT MOVLW 0x08 ; DA=0で呼ばれる(前提) MOVWF CC ; counter I2C00 NOP ; 22 NOP ; 23 BCF PORTB, ICK ; 24 CK=0 BSF STATUS, RP0 ; 25 BCF TRISB, ICK ; 26 CK=0(OUT) NOP ; 1 RLF REGA4, F ; 2 BCF STATUS, RP0 ; 3 BCF PORTB, IDA ; 4 DA=0 BTFSS STATUS, C ; 5 GOTO I2C01 ; 6 BSF STATUS, RP0 ; 7 1を出力 BSF TRISB, IDA ; 8 DA=1(IN) BCF STATUS, RP0 ; 9 I2C01 BTFSC STATUS, C ; 10 8 GOTO I2C02 ; 11 9 BSF STATUS, RP0 ; 10 BCF TRISB, IDA ; 11 DA=0(OUT) BCF STATUS, RP0 ; 12 I2C02 BSF STATUS, RP0 ; 13 13 BSF TRISB, ICK ; 14 CK=1(IN) I2C03 BCF STATUS, RP0 ; 15 BTFSC PORTB, ICK ; 16 自分はHi-Zにした→実際に1になるのを待つ GOTO I2C04 ; 17 BSF STATUS, RP0 ; ?? GOTO I2C03 I2C04 DECFSZ CC, F ; 19 GOTO I2C00 ; 20 NOP ; 21 NOP ; 22 NOP ; 23 BCF PORTB, ICK ; 24 CK=0 BSF STATUS, RP0 ; 25 BCF TRISB, ICK ; 26 CK=0(OUT) MOVLW .3 ; 1 MOVWF CC ; 2 I2C05 DECFSZ CC, F GOTO I2C05 BSF TRISB, IDA ; 11 DA=1(IN) NOP ; 12 NOP ; 13 BSF TRISB, ICK ; 14 CK=1(IN) I2C06 BCF STATUS, RP0 ; 15 BTFSC PORTB, ICK ; 16 GOTO I2C07 ; 17 BSF STATUS, RP0 ; ?? GOTO I2C06 I2C07 CLRF REG78 ; 19 ACK=0 NOP ; 20 BTFSC PORTB, IDA ; 21 DA? BSF REG78, 0 ; 22 NAK=1 BCF PORTB, ICK ; 23 CK=0 BSF STATUS, RP0 ; 24 BCF TRISB, ICK ; 25 CK=0(OUT) BCF STATUS, RP0 ; 26 BCF PORTB, IDA ; DA=0 BSF STATUS, RP0 BCF TRISB, IDA ; DA=0(OUT) BCF STATUS, RP0 ; CK,DAをLOWにしてリターン RETURN ; ; ; EEPROM書き込み。データEEPROMは256BYTE ; W=0 => DNをアドレス0にセーブ ; W=1 => VNをアドレス1にセーブ ; W=2 => SNをアドレス2にセーブ。D0はワークレジスタ ; EEWRT MOVWF D0 ; 来る時はBANK0 BSF STATUS, RP0 BSF STATUS, RP1 ; BANK3 EEW1 BTFSC EECON1, WR GOTO EEW1 BCF STATUS, RP0 ; BANK2 MOVWF EEADR ; WをEEADRにしまう BCF STATUS, RP1 ; BANK0 MOVF D0, F MOVLW .1 SUBWF D0, W BTFSS STATUS, C GOTO EEW0 ; CY=0→minus BTFSS STATUS, Z GOTO EEW2 MOVF VN, W ; W=1→VNをWに入れる GOTO EEW3 EEW2 MOVF SN, W ; W=2 GOTO EEW3 EEW0 MOVF DN, W EEW3 BSF STATUS, RP1 ; BANK2 MOVWF EEDATA BSF STATUS, RP0 ; BANK3 BCF EECON1, EEPGD BSF EECON1, WREN ; BCF INTCON, GIE ; INT Disable MOVLW 0x55 MOVWF EECON2 MOVLW 0xAA MOVWF EECON2 BSF EECON1, WR ; begin write(ハードが自動的に降ろす) ; BSF INTCON, GIE ; INT Re-Enable BCF EECON1, WREN BCF STATUS, RP0 BCF STATUS, RP1 ; BANK0で戻る RETURN ; ; EEPROM読み出し ; Wに読みたいアドレス、0:DN, 1:VN, 2:SNを持って来て、Wに戻り値を持って帰る ; EEREA BSF STATUS, RP1 ; BANK2 MOVWF EEADR ; 読みたいアドレス設定 BSF STATUS, RP0 ; BANK3 BCF EECON1, EEPGD ; Select Data memory BSF EECON1, RD ; 読み出し制御ビットセット(次のサイクルで読み出されハードが自動的に降ろす) BCF STATUS, RP0 ; BANK2 MOVF EEDATA, W BCF STATUS, RP1 ; BANK0で戻る RETURN ; ; LLOC BCF PORTA, 6 ; RS=0 MOVWF D4 CALL WRITE_LCD4 BSF PORTA, 6 ; RS=1 RETURN ; ; D4の下4bit(0x00-0x0F)を16進1文字としてLCD出力。 ; 10進数(0-9)でも使える。WとD4は壊れる。 ; NUMOUT MOVLW 0x0F ANDWF D4, F ; 表示する値(下4bit) MOVLW 0x30 ADDWF D4, F MOVLW 0x3A SUBWF D4, W BTFSS STATUS, C GOTO ND1 ; D4 < 10 MOVLW 7 ADDWF D4, F ND1 BSF PORTA, 6 ; RS=1 CALL WRITE_LCD4 ; char out RETURN ; ; INILCD MOVLW .15 ; wait 15ms MOVWF WAIT_CN CALL WAIT_MS BCF PORTA, 6 ; RS=0 MOVLW 0x30 MOVWF D8 CALL WRITE_LCD8 MOVLW .5 ; wait 4.1ms MOVWF WAIT_CN CALL WAIT_MS MOVLW 0x30 MOVWF D8 CALL WRITE_LCD8 MOVLW .100 ; wait 100us MOVWF WAIT_CN CALL WAIT_US MOVLW 0x30 MOVWF D8 CALL WRITE_LCD8 MOVLW 0x20 MOVWF D8 ; 4bit CALL WRITE_LCD8 MOVLW 0x28 MOVWF D4 ; duty,font set9 CALL WRITE_LCD4 MOVLW 0x01 MOVWF D4 ; clear command CALL WRITE_LCD4 MOVLW .2 ; wait 2ms MOVWF WAIT_CN CALL WAIT_MS MOVLW 0x06 MOVWF D4 ; entry mode set CALL WRITE_LCD4 MOVLW 0x0D MOVWF D4 ; display on, cursor position on CALL WRITE_LCD4 RETURN ; WRITE_LCD8 MOVLW 0x0F ANDWF PORTB, W MOVWF D0 MOVLW 0xF0 ANDWF D8, W IORWF D0, W MOVWF PORTB ; RB[7:4]に出力 BSF PORTA, 7 ; EN=1 NOP BCF PORTA, 7 ; EN=0 MOVLW .40 ; wait 40us MOVWF WAIT_CN CALL WAIT_US NOP RETURN ; WRITE_LCD4 MOVF D4, W MOVWF D8 CALL WRITE_LCD8 MOVF D4, W MOVWF D8 SWAPF D8, F CALL WRITE_LCD8 RETURN ; ; WAIT_MS CLRF CN2 MS1 NOP NOP NOP NOP NOP DECFSZ CN2, F ; 8inst=4us@8MHz GOTO MS1 ; 4us*256=1.024ms DECFSZ WAIT_CN, F GOTO MS1 RETURN ; WAIT_US DECFSZ WAIT_CN, F ; 8MHz => 2inst=1us GOTO WAIT_US ; 本ループはGOTOが2instなので1.5us RETURN ; ; END