マイコンを使った工作

midimon.asm

最終更新:

匿名ユーザー

- view
管理者のみ編集可
midimon.asm
;**********************************************************************
;   Template file assembled with MPLAB V3.99.18 and MPASM V2.15.06.   *
;**********************************************************************
;                                                                     *
;       MIDI monitor program                                          *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:          midimon.asm                                   *
;    Date:              2001/03/24                                    *
;    File Version:                                                    *
;                                                                     *
;    Author:            Chuck                                         *
;    Company:                                                         *
;                                                                     * 
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;      MIDI monitor program                                           *
;      receive MIDI & display on 16x2 LCD w/ ISR receiving            *
;                                                                     *
;                                                                     *
;**********************************************************************

        list    p=16F84a                ; list directive to define processor
        #include           ; processor specific variable definitions

        __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
        __IDLOCS H'0100'                ;V1.00, 24 MAR 2001

; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.


;**********************************************************************
;       Definition to switches, ports, flags, registar files          *
;**********************************************************************
;
;       Debugging information
#DEFINE         DEBUG
#UNDEFINE       DEBUG

;       Presentation switch
;               ifdef RICH,  "strings" expression comes.
;               ifndef RICH, "Hex format" expression selected
#DEFINE         RICH

; Setting for LCD control
; modified Akizuki kit implementation
lcdRW           EQU     1       ; RA1
lcdRS           EQU     2       ; RA2
lcdE            EQU     3       ; RA3

; MIDI in
midiIN          EQU     4       ; RA4

#DEFINE         MIDIIN  PORTA,midiIN

; RESULT Flag
#DEFINE         RXBUSY  RESULT,2        ; bit2 RX busy
#DEFINE         ERROR   RESULT,4        ; bit4 receive error


;***** VARIABLE DEFINITIONS
w_temp          EQU     0x0C    ; variable used for context saving 
status_temp     EQU     0x0D    ; variable used for context saving
fsr_temp        EQU     0x0E    ; variable used for context saving

CNT             EQU     0x0F    ; for 10u, 100usec counter use
CNT5m           EQU     0x10    ; for 5msec counter use
LCDBUF          EQU     0x11    ; LCD command buffer
RESULT          EQU     0x12    ; serial I/F Result flag
CNT9BIT         EQU     0x13    ; MIDI: 1start, 8data, 1stop bits
RXBUF           EQU     0x14    ; receiving buffer
SWTMP           EQU     0x15    ; temp. for swap
MIDIBUF         EQU     0x16    ; MIDI data buffer
STR_CNT         EQU     0x17    ; counter for strings output
STR_PTR         EQU     0x18    ; pointer to strings
WAITCNT         EQU     0x19    ; display timer counter (strings mode)
                                ; display position marker (hex mode)
CLRCNT          EQU     0x1A    ; counter for LCD clear

; 0x30 - 0x4F MIDI receive FIFO (circular buffer)
        #IFNDEF DEBUG
READP           EQU     0x1E    ; read pointer
WRITEP          EQU     0x1F    ; write pointer
BUFBASE         EQU     0x20    ; MIDI buffer top address
BUFEND          EQU     0x50    ;
        #ELSE
READP           EQU     0x1E    ; read pointer
WRITEP          EQU     0x1F    ; write pointer
BUFBASE         EQU     0x20    ; MIDI buffer top address
BUFEND          EQU     0x30    ;
        #ENDIF

;**********************************************************************
;       EEPROM initial value                                          *
;**********************************************************************
;
        ORG     0x2100
        #IFDEF  RICH
        de      "MIDI monitor (strings) by S.Takagi",0
        #ELSE
        de      "MIDI monitor (hex code) by S.Takagi",0
        #ENDIF


;**********************************************************************
;       Program code starts here                                      *
;**********************************************************************
;
        ORG     0x000           ; processor reset vector
        goto    main            ; go to beginning of program

;**********************************************************************
;       Interrupt Service Routine                                     *
;**********************************************************************
        ORG     0x004           ; interrupt vector location
;
ISR
        BTFSS   INTCON,T0IF     ; TMR0 interrupt?
        RETFIE                  ;    if not, return
        BCF     INTCON,T0IF     ; reset T0IF bit
PUSH    movwf   w_temp          ; save off current W register contents
        movf    STATUS,w        ;
        movwf   status_temp     ; save off contents of STATUS register
        MOVF    FSR,W           ;
        MOVWF   fsr_temp        ; save off FSR register content
        BCF     STATUS,RP0      ; surely switching to bank0

; isr code can go here or be located as a call subroutine elsewhere

        BTFSC   RXBUSY          ; receive process on-going?
        GOTO    RXDATA          ;   yes, proc data bits
        GOTO    STARTBIT        ;   no. new data coming. proc start-bit


POP     MOVF    fsr_temp,W      ;
        MOVWF   FSR             ; restore pre-FSR register content
        movf    status_temp,w   ; retrieve copy of STATUS register
        movwf   STATUS          ; restore pre-isr STATUS register contents
        swapf   w_temp,f
        swapf   w_temp,w        ; restore pre-isr W register contents
        retfie                  ; return from interrupt


;**********************************************************************
;                                                                     *
;    Receiving MIDI data (part of ISR)                                *
;                                                                     *
;       MIDI physical layer:                                          *
;         31.25kbps, 1-start bit(Low), 8-data bit, 1-stop bit(Hi)     *
;         MIDI cycle  31.25kbps => 80cycles (10MHz external clock)    *
;                                                                     *
;**********************************************************************
;
STARTBIT
        CALL    TIME10u         ; wait 10usec
        BTFSC   MIDIIN          ; double check MIDI-IN port
        GOTO    NOISE           ; would be noise
        BCF     ERROR
        BSF     RXBUSY          ; Start bit comes in
        CLRF    RXBUF           ; clear receive buffer
;
        BSF     STATUS,RP0      ; bank1
        MOVLW   b'10011000'     ; b'1000-1000' PSA:WDT, 1:1
        MOVWF   OPTION_REG      ;        use internal clock
        BCF     STATUS,RP0      ; bank0
        MOVLW   d'255'-d'46'    ;
        MOVWF   TMR0            ;     pre scaler WDT, 1:1
        MOVLW   9               ; 8bit data + 1stop bit counter
        MOVWF   CNT9BIT         ;
                                ; [start bit edge -> TMR0 count up = 53]
        GOTO    POP
NOISE
        MOVLW   0xFF            ; wait start bit again
        MOVWF   TMR0
        GOTO    POP             ; escaping ISR


RXDATA
        MOVLW   d'255'-d'62'    ; 62 = 80 - 17
                                ; 80 => 32usec
                                ; 17 => cycles from ISR->TMR0cnt
        MOVWF   TMR0            ;     pre scaler WDT, 1:1
        DECFSZ  CNT9BIT,F       ; dec. counter
        GOTO    NEXTRXBIT       ;
STOPBIT         ; stop bit processing
        BTFSS   MIDIIN          ; make sure STOP bit
        BSF     ERROR
        BCF     RXBUSY
        MOVF    WRITEP,W
        MOVWF   FSR
        MOVF    RXBUF,W
        MOVWF   INDF
        INCF    WRITEP,W        ; wp++
        SUBLW   BUFEND          ; wp > buffer upper bound?
        BTFSC   STATUS,Z        ;
        GOTO    WADR0           ;   yes
        INCF    WRITEP,W        ;   no
        GOTO    SSKIP
WADR0   MOVLW   BUFBASE         ; write address rewind
SSKIP   MOVWF   WRITEP
;
        BSF     STATUS,RP0      ; bank1
        MOVLW   b'10111000'     ; b'1011-1000' PSA:WDT, 1:1
        MOVWF   OPTION_REG      ;      use T0CKI, down edge
        BCF     STATUS,RP0      ; bank0
        MOVLW   0xFF
        MOVWF   TMR0            ; set full count to TMR0
;
        GOTO    POP

NEXTRXBIT
        BCF     STATUS,C        ; clear Carry
        BTFSC   MIDIIN          ; test midiIN
        BSF     STATUS,C        ;    set Carry
        RRF     RXBUF,F         ;
                                ; Overhead  ISR->data sampling  =  22
        
        GOTO    POP

;************** remaining code goes here **************

;**********************************************************************
;       "PCL" related subroutines placed here (before 0x0FF)          *
;           because 'addwf PCL' is limited to 8bit result             *
;**********************************************************************
;
;***** return ASCII code *****
ASCII
        ANDLW   0x0F
        addwf   PCL,F
        DT      "0123456789ABCDEF"
;       no RETURN needed


        #IFDEF  RICH
;------------------------------------------------ Strings expression
;***** return ASCII code *****
;CH_ASCII
;       MOVF    MIDIBUF,W
;       ANDLW   0x0F
;       addwf   PCL,F
;       DT      "0123456789ABCDEF"
;       no RETURN needed

;***** return ASCII code *****
CH_ASCII2
        addwf   PCL,F
        DT      " 1 2 3 4 5 6 7 8 910111213141516"
;       no RETURN needed

;***** return character *****
GET_CHAR
        MOVWF   PCL
;
STR_TBL         ;       "0123456789ABCDEF"
STR_NOTEON      DT      "Note On   ", 0
STR_NOTEOFF     DT      "Note Off  ", 0
STR_POLYPRE     DT      "Poly Pres.", 0
STR_CTRLCHG     DT      "Ctrl Chnge", 0
STR_PROGCHG     DT      "Prog Chnge", 0
STR_CHPRES      DT      "Ch. Press.", 0
STR_PITBEND     DT      "Pitch Bend", 0
STR_SYSTEM      DT      "System RTM", 0
;       no RETURN needed


GET_STR
        SWAPF   MIDIBUF,W
        ANDLW   b'00000111'
        ADDWF   PCL,F
        RETLW   STR_NOTEON      ; 0     8x
        RETLW   STR_NOTEOFF     ; 1     9x
        RETLW   STR_POLYPRE     ; 2     Ax
        RETLW   STR_CTRLCHG     ; 3     Bx
        RETLW   STR_PROGCHG     ; 4     Cx
        RETLW   STR_CHPRES      ; 5     Dx
        RETLW   STR_PITBEND     ; 6     Ex
        RETLW   STR_SYSTEM      ; 7     Fx


;***** display MIDI status & parameter *****
;
;       0123456789ABCEDF  <- LCD DDRAM address
;       ----------------
;       Ch:__ Prog Chnge
;       C0 14
;       ----------------
;
DISPMIDI
        MOVLW   d'100'          ; display timer  500msec
        MOVWF   WAITCNT
WAIT    CALL    TIME5m
        DECFSZ  WAITCNT,F
        GOTO    WAIT

        MOVLW   'C'
        CALL    LCD_DATA
        MOVLW   'h'
        CALL    LCD_DATA
        MOVLW   ':'
        CALL    LCD_DATA

;       MOVLW   0x83            ; DDRAM addr = 03
;       CALL    LCD_CMD

        ; Disp channel
        RLF     MIDIBUF,W       ; x2 MIDI ch.
        ANDLW   b'00011110'
        CALL    CH_ASCII2       ; get channel char (10^0)
        CALL    LCD_DATA
        BSF     STATUS,C
        RLF     MIDIBUF,W       ; x2 + 1 MIDI ch.
        ANDLW   b'00011111'
        CALL    CH_ASCII2       ; get channel char (10^1)
        CALL    LCD_DATA

        ; Disp message strings
        MOVLW   0x86            ; DDRAM addr = 06
        CALL    LCD_CMD
        CALL    DISP_MSG        ; display MIDI message

        MOVLW   0xC0            ; clean up 2nd line
        CALL    LCD_CMD
        MOVLW   d'16'
        MOVWF   CLRCNT
CLRS    MOVLW   ' '
        CALL    LCD_DATA
        DECFSZ  CLRCNT,F
        GOTO    CLRS

        MOVLW   0xC0            ; put disp pointer = DDRAM 0x40
        CALL    LCD_CMD

        RETURN


;***** Display MIDI message *****
DISP_MSG
        CALL    GET_STR         ; get string table top address
        MOVWF   STR_PTR         ; set strings pointer to the top
        MOVLW   d'10'           ; 10 letters display counter
        MOVWF   STR_CNT
NEXTCHAR
        MOVF    STR_PTR,W
        CALL    GET_CHAR        ; get character from the table
        ADDLW   0               ; check end of strings
        BTFSC   STATUS,Z        ;
        RETURN                  ; 
        CALL    LCD_DATA
        INCF    STR_PTR,F
        DECFSZ  STR_CNT,F
        GOTO    NEXTCHAR
        RETURN

;-------------------------------------------------- end of selection
        #ENDIF


;**** Get MIDI data from FIFO *****
GETMIDI
        MOVF    READP,W         ;   no, get data from FIFO
        MOVWF   FSR             ;
        MOVF    INDF,W          ;
        MOVWF   MIDIBUF         ; store MIDI buffer
        INCF    READP,W         ; rp++
        SUBLW   BUFEND          ; rp > buffer upper bound
        BTFSC   STATUS,Z        ; zero?
        GOTO    RADR0           ;   yes
        INCF    READP,W         ;   no
        GOTO    GSKIP
RADR0   MOVLW   BUFBASE         ; write address rewind
GSKIP   MOVWF   READP
;
        RETURN
;


;**********************************************************************
;                                                                     *
;                               MAIN                                  *
;                                                                     *
;**********************************************************************
main
        ;  Initialization
        BCF     INTCON,GIE      ; make sure disalbe Interrupt
        CALL    PORT_INIT       ; port A/B initialization
        CALL    LCD_INIT        ; LCD initialization
        CALL    LCD_CLR
        CALL    MIDI_INIT       ; MIDI related parameter init.
        CALL    ISR_INIT        ; Iunterrupt related parameter init.
        BSF     INTCON,GIE      ; enable interrupt

        #IFDEF  RICH
;------------------------------------------------ Strings expression
INIT_OUT        
        MOVLW   0x0C            ; Display on (no Cursor,Blink)
        CALL    LCD_CMD

INFINITE        
        MOVF    READP,W         ; compare READ & WRITE pointer
        SUBWF   WRITEP,W
        BTFSC   STATUS,Z        ; READP == WRITEP ?
        GOTO    INFINITE        ;   yes, then loop
        CALL    GETMIDI         ; get MIDI data in FIFO

        BTFSC   MIDIBUF,7       ; test MSB
        CALL    DISPMIDI        ;   it's a MIDI status

        SWAPF   MIDIBUF,W       ;
        ANDLW   0x0F            ; display upper 4bit
        CALL    ASCII
        CALL    LCD_DATA
        MOVF    MIDIBUF,W
        ANDLW   0x0F            ; display lower 4bit
        CALL    ASCII
        CALL    LCD_DATA
        MOVLW   ' '             ; put space
        CALL    LCD_DATA
        
        GOTO    INFINITE

        #ELSE
;----------------------------------------------- HEX code expression
INIT_OUT        
        MOVLW   0x0F            ; Display on (Cursor,Blink)
        CALL    LCD_CMD
        MOVLW   0x80            ; DDRAM addr = 00
        CALL    LCD_CMD

        CLRF    WAITCNT         ; display positioner
INFINITE
        MOVF    READP,W
        SUBWF   WRITEP,W
        BTFSC   STATUS,Z        ; READP == WRITEP ?
        GOTO    INFINITE        ;   yes, then loop
        CALL    GETMIDI         ; get MIDI data in FIFO

        SWAPF   MIDIBUF,W       ; disp MIDI data (hex form)
        ANDLW   0x0F            ;   upper hex
        CALL    ASCII
        CALL    LCD_DATA
        MOVF    MIDIBUF,W       ;   lower hex
        ANDLW   0x0F
        CALL    ASCII
        CALL    LCD_DATA
        MOVLW   ' '             ;   put space
        CALL    LCD_DATA

        INCF    WAITCNT,F
        MOVF    WAITCNT,W
        SUBLW   d'5'            ; if display pos = 5
        BTFSC   STATUS,Z
        GOTO    INF5            ;   move cursor to second line
        MOVF    WAITCNT,W
        SUBLW   d'10'           ; if display pos = 10
        BTFSC   STATUS,Z
        GOTO    INF10           ;   move cursor to first line
        GOTO    INFINITE

INF5                            ; move cursor to second line
        MOVLW   h'C0'           ; DDRAM <- 0x40
        CALL    LCD_CMD
        GOTO    INFINITE
        
INF10                           ; move cursor to first line
        MOVLW   h'80'           ; DDRAM <- 0x00
        CALL    LCD_CMD
        CLRF    WAITCNT         ; and clear positioner
        GOTO    INFINITE

        #ENDIF
;-------------------------------------------------- end of selection




;**********************************************************************
;       Followings are Initializer routines                           *
;**********************************************************************
;
;****  ISR Initialize *****
ISR_INIT
        CLRF    TMR0
        CLRWDT
        BSF     STATUS,RP0      ; bank1
        MOVLW   b'10111000'     ; b'1011-1000' PSA:WDT, 1:1
        MOVWF   OPTION_REG      ;      use T0CKI, down edge
        BCF     STATUS,RP0      ; bank0
        MOVLW   0xFF
        MOVWF   TMR0            ; set full count to TMR0
        BCF     INTCON,T0IF     ; reset TMRO INT flag
        BSF     INTCON,T0IE     ; enable TMR0 interrupt
        RETURN


;****  MIDI related status INIT *****
MIDI_INIT
        CLRF    RESULT          ; clear comm RESULT flag
        MOVLW   BUFBASE         ; init pointers
        MOVWF   READP
        MOVWF   WRITEP
        RETURN


;****  PORTA/B Initialize *****
PORT_INIT
        BSF     STATUS,RP0      ; bank1
        MOVLW   b'00000000'     ; RB[7:0] output
        MOVWF   TRISB
        MOVLW   b'00010000'     ; RA4 input
        MOVWF   TRISA
        BCF     STATUS,RP0      ; bank0
        CLRF    PORTA
        CLRF    PORTB
        RETURN


;**********************************************************************
;       LCD related subroutines                                       *
;**********************************************************************
;
;****  LCD clear command *****
LCD_CLR
        MOVLW   0x01            ; LCD CLEAR command
        CALL    LCD_CMD
        RETURN

;****  LCD command out  *****
LCD_CMD
        MOVWF   LCDBUF          ; Store command data
        ANDLW   0F0H            ; output upper 4bits
;       MOVWF   PORTB           ; output to RB[7:4]
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BCF     PORTA,lcdRW     ; R/~W -> 0
        BCF     PORTA,lcdRS     ; RS -> 0
        BSF     PORTA,lcdE      ; E high/output strobe
        BCF     PORTA,lcdE      ; E low
        SWAPF   LCDBUF,W        ;
        ANDLW   0F0H            ; output lower 4bits
;       MOVWF   PORTB           ; output to RB[7:4]
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        CALL    LCD_BUSY        ; wait while Busy
;
        RETURN

;****  LCD Data Write  ****
LCD_DATA
        MOVWF   LCDBUF          ; store display data
        ANDLW   0F0H            ; xfer upper 4bits
;       MOVWF   PORTB
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BCF     PORTA,lcdRW     ; R/~W -> 0
        BSF     PORTA,lcdRS     ; RS -> 1
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        SWAPF   LCDBUF,W        ; get lower 4bits
        ANDLW   0xF0            ; xfer lower 4bits
;       MOVWF   PORTB           ; PORTB[7:4]
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        CALL    LCD_BUSY        ; wait while Busy
;
        RETURN


;****  LCD Busy Check  ************
LCD_BUSY
        CLRF    LCDBUF          ; clear data buffer
        BSF     STATUS,RP0      ; bank1
;       BSF     OPTION_REG,7    ; PORTB pull-up off
;       MOVLW   0xFE            ; PORTB[7:1] input
        MOVLW   b'00001111'     ; PORTB[3:0] input
        MOVWF   TRISB
        BCF     STATUS,RP0      ; bank0
        BCF     PORTA,lcdRS     ; RS -> 0
        BSF     PORTA,lcdRW     ; R/~W -> 1, Busy In mode
        BSF     PORTA,lcdE      ; E high/strobe
        MOVF    PORTB,W         ; get upper data to RB[3:0]
        BCF     PORTA,lcdE      ; E low
;       ANDLW   0xF0            ; mask out upper 4bits
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       RB[3:0] -> [7:4]
        ANDLW   0xF0            ; get upper 4bits
        MOVWF   LCDBUF          ; store temporarily
        BSF     PORTA,lcdE      ; E high/strobe
        MOVF    PORTB,W         ; get lower 4bits to RB[3:0]
        BCF     PORTA,lcdE      ; E low
;       ANDLW   0x0F0           ; mask out upper 4bits
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       RB[3:0] -> [7:4]
        ANDLW   0xF0            ; mask out upper 4bits
        MOVWF   SWTMP
        SWAPF   SWTMP,W
        IORWF   LCDBUF,F        ; combine upper & lower
        BTFSC   LCDBUF,7        ; check busy flag
        GOTO    LCD_BUSY        ; if busy, try again

        BCF     PORTA,lcdRW     ; R/~W -> 0 (output mode)
        BSF     STATUS,RP0      ; bank1
;       MOVLW   0x0E            ; output RB7,6,5,4,0
        MOVLW   b'00000000'     ; output RB[7:0]
        MOVWF   TRISB           ; PORTB mode set
        BCF     STATUS,RP0      ; bank0
        RETURN


;****  Initialize  *****
LCD_INIT
        CALL    TIME5m          ; wait 15msec
        CALL    TIME5m
        CALL    TIME5m
        MOVLW   0x30            ; 8bit mode setting control
;       MOVWF   PORTB
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BCF     PORTA,lcdRW     ; R/~W -> 0
        BCF     PORTA,lcdRS     ; RS -> 0
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        CALL    TIME5m          ; wait over 4.1msec
        MOVLW   0x30            ; 8bit mode setting again
;       MOVWF   PORTB
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BCF     PORTA,lcdRW     ; R/~W -> 0
        BCF     PORTA,lcdRS     ; RS -> 0
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        CALL    TIME100u        ; wait over 100usec
        MOVLW   0x30            ; 8bit mode setting 
;       MOVWF   PORTB
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BCF     PORTA,lcdRW     ; R/~W -> 0
        BCF     PORTA,lcdRS     ; RS -> 0
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        CALL    TIME100u        ; wait 100usec
        MOVLW   0x20            ; 4bit mode setting
;       MOVWF   PORTB           ; 
        MOVWF   SWTMP
        SWAPF   SWTMP,W         ;       [7:4] -> [3:0]
        MOVWF   PORTB           ; output to RB[3:0]
        BCF     PORTA,lcdRW     ; R/~W -> 0
        BCF     PORTA,lcdRS     ; RS -> 0
        BSF     PORTA,lcdE      ; E high/strobe
        BCF     PORTA,lcdE      ; E low
        CALL    TIME100u        ; wait 100usec
;After this, works 4bit mode, Busy flag available
        MOVLW   0x2C            ; Function Set (2lines,5x10Dot)
        CALL    LCD_CMD
        MOVLW   0x08            ; Display off (no Cursor,Blink)
        CALL    LCD_CMD
        MOVLW   0x0C            ; Display on (no Cursor,Blink)
        CALL    LCD_CMD
        MOVLW   0x06            ; Entry Mode Set(Incremental)
        CALL    LCD_CMD
        RETURN

;**********************************************************************
;       TIMER subroutines                                             *
;**********************************************************************
;       note: register CNT is commonly used in TIME10u, TIME100u.
;             so, DO NOT CALL TIME10u, TIME100u hybridly
;
;***** 10usec timer     w/ 10MHz clock *****
;
TIME10u
        MOVLW   7               ; 1 cycle
        MOVWF   CNT             ; 1
        NOP                     ; 1
LOOP10u                         ;
        DECFSZ  CNT,F           ; 1*6+2
        GOTO    LOOP10u         ; 2*6
        RETURN                  ; 2             total 25 cycles

;
;***** 100usec timer    w/ 10MHz clock *****
;
TIME100u
        MOVLW   0x52            ; 1 cycle, 52h = 82
        MOVWF   CNT             ; 1
        NOP                     ; 1
LOOP100u                        ;
        DECFSZ  CNT,F           ; 1*81+2
        GOTO    LOOP100u        ; 2*81
        RETURN                  ; 2             total 250 cycles

;
;***** 5msec timer      w/ 10MHz clock *****
;
TIME5m
        MOVLW   d'49'           ; 1
        MOVWF   CNT5m           ; 1
        GOTO    $+1             ; 2
LOOP5m                          ;
        CALL    TIME100u        ; 49*(250+2)
        DECFSZ  CNT5m,F         ; 48+2
        GOTO    LOOP5m          ; 2*48
        RETURN                  ; 2             total 12500 cycles

        END
目安箱バナー