; WRITTEN BY: TOM SCARFF ; DATE: 20/03/2001 ; ITERATION: 1.0 ; FILE SAVED AS: anal2mid.ASM ; FOR: PIC16F877 ; CLOCK: 4.00 MHz CRYSTAL ; INSTRUCTION CLOCK: 1.00 MHz T= luS ; PROGRAMME FUNCTION: 4-Bit LCD test program for PIC16F877 ; 8 analogue i/ps to MIDI out list p=16F877 ; list directive to define processor #include "p16f877.inc" ; processor specific variable definitions #DEFINE PAGE0 BCF 3,5 #DEFINE PAGE1 BSF 3,5 lcd_data equ PORTC lcd_data_tris equ TRISC lcd_cntl equ PORTC ;************************************************************* ; Constant Assignments ;************************************************************* e equ 4 ; lcd enable control line r_w equ 1 ; lcd read/write control line rs equ 5 ; lcd register select control line CARRY EQU 0 ; CARRY BIT ;************************************************************** ; Variable Assignment Addresses ;************************************************************** ; disp_on equ 0x0c clr_disp equ 0x01 entry_inc equ 0x06 dd_ram_addr equ 0x80 ; ; temp1 equ 0x20 temp equ 0x21 char equ 0x22 msd equ 0x23 lsd equ 0x24 ; BCD0 equ 25h BCD1 equ 26h BCD2 equ 27h CHARACTER equ 28h midich equ 29h input1 equ 2Ah input2 equ 2Bh input3 equ 2Ch input4 equ 2Dh input5 equ 2Eh input6 equ 2Fh input7 equ 30h input8 equ 31h base_addr equ 32h temp_data equ 33h AD_DATA equ 34h dlyreg2 equ 35h dlyreg3 equ 36h tab0 equ 3Ah tab1 equ 3Bh tab2 equ 3Ch tab3 equ 3Dh tab4 equ 3Eh tab5 equ 3Fh tab6 equ 40h tab7 equ 41h ctrller equ 42h ; ;************************************************************ ; PROGRAMME Reset Point ;************************************************************ org 00 ; reset vector goto init ;**************************************************************** ; Initilize the lcd display module ;**************************************************************** ;-------------------------------------------------------------------- ;RS R/W B7 B6 B5 B4 B3 B2 B1 B0 ; ;0 0 0 0 0 0 0 0 0 1 Clear Display ; ;0 0 0 0 0 0 0 0 1 X Return Home ; ;0 0 0 0 0 0 0 1 D S Entry Mode Set ; D: 0=direction -, 1=direction + ; S: 0=no shift, 1=shift ; ;0 0 0 0 0 0 1 D C B Display on/off ; D: 0=disply off, 1=on ; C: 0=cursor off, 1=on ; B: 0=blink off, 1=on ; ;0 0 0 0 0 1 S R X X Display or Cursor Shift ; S: 0=cursor only, 1=both ; R: 0=right; 1=left ; ; ;0 0 0 0 1 D N F X X Set data interface ; D: 0=8 bit, 1=4 bit ; N: 0=F works, 1=F is ignored ; F: 0=5x7 dots, 1=5x10 dots ; ;0 0 0 1 A A A A A A Set char gen RAM address ; Lets you select one of 64 ; chars for loading a bit map ; ;0 0 1 A A A A A A A Set display RAM address ; Lets you select an address ; in the display buffer. With ; this you can write in a pos- ; ition that is off the viewable ; display. ; ;0 1 B A A A A A A A Read busy flag, address pointer ; If B=1, display is updating. ; Also returns address of last ; data transfer. ; ;1 0 D D D D D D D D Write Data ; Writes to Display if previous ; instruction was SET DISPLAY ; RAM ADDR. Writes to char gen if ; previous instruction was SET ; CHAR GEN RAM ADDR. ; ;1 1 D D D D D D D D Read Data ; Reads from Display if previous ; instruction was SET DISPLAY ; RAM ADDR. Reads from char gen if ; previous instruction was SET ; CHAR GEN RAM ADDR. ; ;-------------------------------------------------------------------------- init PAGE1 movlw 0FFh movwf TRISB ;all pins inputs movwf TRISA ;all inputs clrf ADCON1 ; Set porta as analogue I/P's PAGE0 clrf lcd_cntl ; all port output should output low. ; Set up USART PAGE1 bsf STATUS,RP0 ; goto page 1 movlw b'10000000' ; RC7 is RX input movwf TRISC movlw 01h ; 31250 baud for MIDI movwf SPBRG movlw b'00100000' ; async tx 8 bit movwf TXSTA bcf STATUS,RP0 ; return to page 0 movlw b'10010000' ; async rx 8 bit movwf RCSTA bsf STATUS,RP0 ; enable weak pull-up resistors movlw 07h ; rtcc/256 movwf OPTION_REG bcf STATUS,RP0 goto main ;------------------------------------------------------------------------- ;************************************ ; Switch Debounce Delay (100mS) ;************************************ sw_dbnc movlw 80h ; Delay routine movwf dlyreg2 debnce call delay3 decfsz dlyreg2 goto debnce return ;************************************* ; Delay Subroutine (770uS) ;************************************* delay3 movlw .255 movwf dlyreg3 dly3 decfsz dlyreg3 goto dly3 nop return ;____________________________________________ display_init call lcd_delay call lcd_delay call lcd_delay movlw 0x33 call send_cmd0 movlw 0x32 call send_cmd0 movlw 0x28 ;2 line LCD call send_cmd0 movlw 0x0C ; Display on, cursor off call send_cmd0 movlw 0x02 call send_cmd0 movlw 0x01 call send_cmd0 return ;************************************************************* ; Delay of 15 mS with 1 MHz clock ;************************************************************* lcd_delay movlw .20 ; movwf msd ; clrf lsd ; dly0 decfsz lsd, f ; delay time = msd * ((3 * 256) + 3) * tcy goto dly0 ; decfsz msd, f ; goto dly0 ; return ;************************************************************* ; Delay of ?? with 1 MHz clock ;************************************************************* lcd_delay1 movlw .40 ; movwf msd ; clrf lsd ; dly1 decfsz lsd, f ; delay time = msd * ((3 * 256) + 3) * tcy goto dly1 ; decfsz msd, f ; goto dly1 ; return ;************************************ ; EEPROM Read ;************************************ ee_read bcf STATUS,RP0 bsf STATUS,RP1 ; bank 2 movwf EEADR bsf STATUS,RP0 bsf STATUS,RP1 ; bank 3 bsf EECON1,RD r1 btfsc EECON1,RD ; Wait to finish read. goto r1 bcf STATUS,RP0 ; now bank 2 movf EEDATA,W andlw 07Fh ; prevent value >127 bcf STATUS,RP1 ; now bank 0 return ;************************************ ; EEPROM Read ;************************************ ee_write movf base_addr,W; start addr. EEPROM bsf STATUS,RP1 ; bank 2 movwf EEADR bcf STATUS,RP1 ; bank 0 movf temp_data,W andlw 07Fh bsf STATUS,RP1 ; bank 2 movwf EEDATA bsf STATUS,RP0 ;writing to eeprom, bank 3 bsf EECON1,WREN movlw 55h movwf EECON2 movlw 0AAh movwf EECON2 bsf EECON1,WR test_wr btfsc EECON1,WR; is write finished? goto test_wr bcf STATUS,RP0 bcf STATUS,RP1 ; now bank 0 return ;******************************************************************* ;*sendchar - sends character to lcd * ;*this routine splits the character into the upper and lower * ;*nibbles and sends them to the lcd, upper nibble first. * ;******************************************************************* ; send_char movwf char ;character to be sent is in w swapf char, w andlw 0x0F ;get upper nibble movwf lcd_data ;send data to lcd bsf lcd_cntl, rs ;set lcd to data mode bsf lcd_cntl, e ;toggle e for lcd bcf lcd_cntl, e call lcd_delay1 movf char, w andlw 0x0F ;get lower nibble movwf lcd_data ;send data to lcd bsf lcd_cntl, rs ;set lcd to data mode bsf lcd_cntl, e ;toggle e for lcd bcf lcd_cntl, e call lcd_delay1 return ;******************************************************************* ;* send_cmd - sends command to lcd * ;* this routine splits the command into the upper and lower * ;* nibbles and sends them to the lcd, upper nibble first. * ;******************************************************************* send_cmd0 movwf char ; character to be sent is in w swapf char,w andlw 0x0F ; get upper nibble movwf lcd_data ; send data to lcd bsf lcd_cntl,e ; toggle e for lcd bcf lcd_cntl,e call lcd_delay movf char,w andlw 0x0F ; get lower nibble movwf lcd_data ; send data to lcd bsf lcd_cntl,e ; toggle e for lcd bcf lcd_cntl,e call lcd_delay return ; ;******************************************************************* ;* send_cmd - sends command to lcd * ;* this routine splits the command into the upper and lower * ;* nibbles and sends them to the lcd, upper nibble first. * ;******************************************************************* send_cmd movwf char ; character to be sent is in w swapf char,w andlw 0x0F ; get upper nibble movwf lcd_data ; send data to lcd bsf lcd_cntl,e ; toggle e for lcd bcf lcd_cntl,e call lcd_delay1 movf char,w andlw 0x0F ; get lower nibble movwf lcd_data ; send data to lcd bsf lcd_cntl,e ; toggle e for lcd bcf lcd_cntl,e call lcd_delay1 return ;****************************************** ; transmission complete subroutine ;***************+************************** txchar bsf STATUS,RP0 btfss TXSTA,1 ; test for end of transmission goto $-1 bcf STATUS,RP0 return ;********************************************* ; Start A/D conversion Subroutine ;********************************************* convert bsf ADCON0,2 ;set GO/DONE Bit btfsc ADCON0,2 goto $-1 rrf ADRESH,W andlw 07Fh movwf AD_DATA return ;************************************** ; Output MIDI Controller data ;************************************** control movf midich,W addlw 0B0h ; Control Change ch. from midich movwf TXREG ; send character from W call txchar movf ctrller,W andlw 07Fh movwf TXREG ; send character from W call txchar movf AD_DATA,W movwf TXREG ; send character from W call txchar return ;******************************************************************* ; Binary To BCD Conversion Routine ; This routine converts the 8 bit binary number in the W Register ; to a 3 digit BCD number, in locations BCD0, BCD1 and BCD2. ; Converts from 00 to 255. (00 to FF hex). Adds 30h to get ASCII. ;******************************************************************* BINBCD clrf BCD2 clrf BCD1 movwf BCD0 hundrd movlw .100 subwf BCD0,W btfss STATUS,CARRY goto gtenth movwf BCD0 incf BCD2 goto hundrd gtenth movlw .10 subwf BCD0,W BTFSS STATUS,CARRY goto over movwf BCD0 incf BCD1 goto gtenth over movlw 030h ;convert to ASCII addwf BCD0,F ;by adding 30h addwf BCD1,F addwf BCD2,F return ;**************************************************************** ; Display Number+1 as 2 Characters for MIDI Channels 1-16 ;**************************************************************** disp2char movf CHARACTER,W addlw .01 call BINBCD movf BCD1,W CALL send_char movf BCD0,W CALL send_char return ;**************************************************************** ; Display Number as 3 Characters from 000-121 ;**************************************************************** disp3char MOVf CHARACTER,W call BINBCD movf BCD2,W CALL send_char movf BCD1,W CALL send_char movf BCD0,W CALL send_char return ;**************************************************************** ; Increment MIDI Channel Value ;**************************************************************** inc_chan movlw 0Fh ; is value 16 xorwf midich,W btfsc STATUS,Z ; is value already 16 ? return ; Yes, so return incf midich,F MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf midich,W movwf CHARACTER call disp2char return ;**************************************************************** ; Deccrement MIDI Channel Value ;**************************************************************** dec_chan movlw 00h xorwf midich,W btfsc STATUS,Z ; is value already 0 ? return ; Yes, so return decf midich,F ; No, so decrement MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf midich,W movwf CHARACTER call disp2char return ;**************************************************************** ; Increment MIDI Channel Value ;**************************************************************** inc_val movlw .121 ; is value 121? max. controller value xorwf temp,W btfsc STATUS,Z ; is value already 16 ? return ; Yes, so return incf temp,F MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf temp,W movwf CHARACTER call disp3char return ;**************************************************************** ; Deccrement MIDI Channel Value ;**************************************************************** dec_val movlw 00h xorwf temp,W btfsc STATUS,Z ; is value already 0 ? return ; Yes, so return decf temp,F ; No, so decrement MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf temp,W movwf CHARACTER call disp3char return ;**************************************************************** ; Menus ;**************************************************************** menu0 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg2 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf midich,W movwf CHARACTER ; Display initial/previous value call disp2char loop0 btfss PORTB,6 call inc_chan btfss PORTB,5 call dec_chan btfss PORTB,7 return goto loop0 ;------------------------------------------------------------- menu1 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_1 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input1,W movwf CHARACTER ; Display initial/previous value call disp3char loop1 movf input1,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input1 btfss PORTB,7 return goto loop1 ;----------------------------------------------------------------- menu2 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_2 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input2,W movwf CHARACTER ; Display initial/previous value call disp3char loop2 movf input2,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input2 btfss PORTB,7 return goto loop2 ;----------------------------------------------------------------- menu3 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_3 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input3,W movwf CHARACTER ; Display initial/previous value call disp3char loop3 movf input3,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input3 btfss PORTB,7 return goto loop3 ;----------------------------------------------------------------- menu4 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_4 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input4,W movwf CHARACTER ; Display initial/previous value call disp3char loop4 movf input4,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input4 btfss PORTB,7 return goto loop4 ;----------------------------------------------------------------- menu5 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_5 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input5,W movwf CHARACTER ; Display initial/previous value call disp3char loop5 movf input5,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input5 btfss PORTB,7 return goto loop5 ;----------------------------------------------------------------- menu6 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_6 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input6,W movwf CHARACTER ; Display initial/previous value call disp3char loop6 movf input6,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input6 btfss PORTB,7 return goto loop6 ;----------------------------------------------------------------- menu7 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_7 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input7,W movwf CHARACTER ; Display initial/previous value call disp3char loop7 movf input7,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input7 btfss PORTB,7 return goto loop7 ;----------------------------------------------------------------- menu8 MOVLW 0C0h ; SET LINE CALL send_cmd ; SET IT movlw .03 ; For address org 0300h movwf PCLATH call msg3_8 clrw movwf PCLATH MOVLW 0CDh ; SET LINE 2, start char. 14 CALL send_cmd ; SET IT movf input8,W movwf CHARACTER ; Display initial/previous value call disp3char loop8 movf input8,W movwf temp btfss PORTB,6 call inc_val btfss PORTB,5 call dec_val movf temp,W movwf input8 btfss PORTB,7 return goto loop8 ;----------------------------------------------------------------- ;----------------------------------------------------------------- ;**************************************************************** ; Main Programme ;**************************************************************** main call display_init btfsc PORTB,7 ; is Menu+ sw. pressed? goto main1 ; No, so go to Normal Mode main0 movlw 0x02 ; return home call send_cmd0 movlw 0x01 ; clear display call send_cmd0 movlw .03 ; For address org 0300h movwf PCLATH call msg1 ; Programme Mode clrw movwf PCLATH ;----------------------------------------------------------- ; Read previous variables midich and input 1-8 from EE_PROM ;----------------------------------------------------------- clrf base_addr ; start addr. of EEPROM at 00h? movf base_addr,W call ee_read movwf midich incf base_addr,F movf base_addr,W call ee_read movwf input1 incf base_addr,F movf base_addr,W call ee_read movwf input2 incf base_addr,F movf base_addr,W call ee_read movwf input3 incf base_addr,F movf base_addr,W call ee_read movwf input4 incf base_addr,F movf base_addr,W call ee_read movwf input5 incf base_addr,F movf base_addr,W call ee_read movwf input6 incf base_addr,F movf base_addr,W call ee_read movwf input7 incf base_addr,F movf base_addr,W call ee_read movwf input8 incf base_addr,F ;+++++++++++++++++++++++++++++++++++++++++++++++++++++ sw0 btfsc PORTB,7 goto sw0 call menu0 sw1 btfsc PORTB,7 goto sw1 call menu1 sw2 btfsc PORTB,7 goto sw2 call menu2 sw3 btfsc PORTB,7 goto sw3 call menu3 sw4 btfsc PORTB,7 goto sw4 call menu4 sw5 btfsc PORTB,7 goto sw5 call menu5 sw6 btfsc PORTB,7 goto sw6 call menu6 sw7 btfsc PORTB,7 goto sw7 call menu7 sw8 btfsc PORTB,7 goto sw8 call menu8 ;;;;;;sw9 btfsc PORTB,7 ;;;;;;;; goto sw9 ;------------------------------------------------------------- ; Write the variables midich and input 1-8 to EE_PROM ;------------------------------------------------------------- clrf base_addr ; start addr. of EEPROM at 00h? movf midich,W movwf temp_data call ee_write incf base_addr,F movf input1,W movwf temp_data call ee_write incf base_addr,F movf input2,W movwf temp_data call ee_write incf base_addr,F movf input3,W movwf temp_data call ee_write incf base_addr,F movf input4,W movwf temp_data call ee_write incf base_addr,F movf input5,W movwf temp_data call ee_write incf base_addr,F movf input6,W movwf temp_data call ee_write incf base_addr,F movf input7,W movwf temp_data call ee_write incf base_addr,F movf input8,W movwf temp_data call ee_write incf base_addr,F ;************************************** ; Main Programme Start in Normal Mode ; Read EEPROM and write to input1 to 8 ;************************************** main1 movlw 0x02 ; return home call send_cmd0 movlw 0x01 ; clear display call send_cmd0 movlw .04 ; For address org 0400h movwf PCLATH call msg4 ; Normal Mode clrw movwf PCLATH ;---------------------------------------------------- ; Read the variables midich and input 1-8 from EE_PROM ;----------------------------------------------------- clrf base_addr ; start addr. of EEPROM at 00h? movf base_addr,W call ee_read movwf midich incf base_addr,F movf base_addr,W call ee_read movwf input1 incf base_addr,F movf base_addr,W call ee_read movwf input2 incf base_addr,F movf base_addr,W call ee_read movwf input3 incf base_addr,F movf base_addr,W call ee_read movwf input4 incf base_addr,F movf base_addr,W call ee_read movwf input5 incf base_addr,F movf base_addr,W call ee_read movwf input6 incf base_addr,F movf base_addr,W call ee_read movwf input7 incf base_addr,F movf base_addr,W call ee_read movwf input8 incf base_addr,F ;+++++++++++++++++++++++++++++++++++++++++++++++++++++ main2 clrf tab0 clrf tab1 clrf tab2 clrf tab3 clrf tab4 clrf tab5 clrf tab6 clrf tab7 ch0 movlw B'01000001' ; channel 0 movwf ADCON0 call convert call convert movf tab0,W subwf AD_DATA,W ; (f) - (W)--> (dest) btfsc STATUS,Z ; Skip if result -Ve. ie f (dest) btfsc STATUS,Z ; Skip if result not same goto ch2 ; no change, so do not o/p data movf AD_DATA,W movwf tab1 movf input2,W movwf ctrller movlw 07Fh andwf AD_DATA call control call sw_dbnc ch2 movlw B'01010001' ; channel 2 movwf ADCON0 call convert call convert movf tab2,W subwf AD_DATA,W ; (f) - (W)--> (dest) btfsc STATUS,Z ; Skip if result -Ve. ie f