;********************************************************************** ; alpha.asm 010915 by K.I NPC * ;********************************************************************** ; ePLL writer for PIC16F873 * ; * ;********************************************************************** list p=16f873 ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF ; CP : flash program memory Code Protect [ALL,HALF,UPPER_256,OFF] ; CPD : data memory Code Protect [ON,OFF] ; WDT : Watch Dog Timer [ON,OFF] ; BODEN : BrownOut reset ENable [ON,OFF] ; PWRTE : PoWeR up Timer Enable (72ms) [ON,OFF] ; HS OSC : High Speed mode OSC ; XT OSC ; XT OSC (normal speed) ; LP OSC ; Low Power OSC ; RC OSC : RC mode OSC ; WRT_ENABLE : flash program memory WRiTe ENABLE [ON,OFF] ; LVP : Low Voltage Programming [ON,OFF] ; DEBUG : incircuit DEBUG mode [ON,OFF] ;***** MACRO DEFINITIONS ;---------------------------------------------------------------------- Message MACRO TABLE movlw low(TABLE) call print_lcd ENDM ;***** CONSTANT DEFINITIONS ;---------------------------------------------------------------------- PADIR EQU B'00000000' ;TRISA 1:In, 0:Out PBDIR EQU B'00000000' ;TRISB 1:In, 0:Out PCDIR EQU B'10111111' ;TRISC 1:In, 0:Out PAINI EQU B'00000000' ;PORTA Initial value PBINI EQU B'00000000' ;PORTB Initial value PCINI EQU B'00000000' ;PORTC Initial value ADCON0_INI EQU B'00000000' ;ADCON0 Initial value ADCON1_INI EQU B'00000111' ;ADCON1 Initial value OPTION_INI EQU B'10000000' ;OPTION Initial value LED EQU 0 ;LCD port bit RW EQU 1 ;LCD port bit RS EQU 2 E EQU 3 DOWN EQU 0 ;PUSH button LEFT EQU 1 RIGHT EQU 2 UP EQU 3 CANCEL EQU 4 OK EQU 5 LE EQU 0 ;ePLL interface DAT EQU 1 CLK EQU 2 EPCLK EQU 3 VPP EQU 4 VPPCON EQU 5 ;---------------------------------------------------------------------- RADIX DEC CBLOCK 20H ;---------------------------------------------------------------------- w_temp status_temp pclath_temp table_index ; table index wait_cn ; wait routine counter wait_cn2 ; wait routine counter2 lcd_adrs ; LCD address lcd_data ; LCD data lcd_rdata ; LCD read data sw_data ; Switch data line ; general buffer cnt ; general counter cnt2 ; general counter ee_adrs ; EEPROM address ee_data ; EEPROM data s_data ; send data n0,n1,n2,n3,n4,n5,n6,n7 ; N-counter r0,r1,r2,r3,r4,r5,r6,r7 ; R-counter ;---------------------------------------------------------------------- ENDC ;********************************************************************** ORG 0x000 ; processor reset vector clrf PCLATH ; ensure page bits are cleared goto main ; go to beginning of program ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register bcf STATUS,RP0 ; ensure file register bank set to 0 movwf status_temp ; save off contents of STATUS register ;---------------------------------------------------------------------- ; interrupt routine ;---------------------------------------------------------------------- ; interrupt routine here! bcf STATUS,RP0 ; ensure file register bank set to 0 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 ;---------------------------------------------------------------------- ; Main routine ;---------------------------------------------------------------------- main call setup_port call setup_lcd call setup_counter Message msg_start movlw 1 call blink_led call test_switch set_count movlw 2 call blink_led call clear_lcd clrf PORTA Message msg_set_count movlw 16 movwf cnt movlw n0 movwf FSR set_count_loop movf INDF,0 call write_lcd incf FSR,1 decfsz cnt,1 goto set_count_loop call input_lcd write_count movlw 3 call blink_led call clear_lcd bsf PORTA,VPP Message msg_write call test_switch btfsc sw_data,CANCEL goto set_count btfss sw_data,OK goto write_count call send_ncount call send_rcount call send_vpp rec_count movlw 16 movwf cnt movlw n0 movwf FSR rec_count_loop movf INDF,0 movwf ee_data movf FSR,0 addlw -n0 movwf ee_adrs call write_eeprom incf FSR,1 decfsz cnt,1 goto rec_count_loop goto set_count ;----------------------------------------------------------------------------------- ; Setup Port ;----------------------------------------------------------------------------------- setup_port movlw ADCON0_INI movwf ADCON0 movlw PAINI movwf PORTA movlw PBINI movwf PORTB movlw PCINI movwf PORTC bsf STATUS,RP0 movlw ADCON1_INI movwf ADCON1 movlw PADIR movwf TRISA movlw PBDIR movwf TRISB movlw PCDIR movwf TRISC movlw OPTION_INI movwf OPTION_REG bcf STATUS,RP0 return ;----------------------------------------------------------------------------------- ; Setup LCD module (SC1602) ;----------------------------------------------------------------------------------- setup_lcd movlw 15 ; wait 15ms call wait_ms bcf PORTB,RS ; RS='L' movlw 00110000b call write_lcdx movlw 5 ; wait 4.1ms call wait_ms movlw 00110000b call write_lcdx call wait_100us ; wait 100us movlw 00110000b call write_lcdx movlw 00100000b call write_lcdx ; movlw 00101000b ;4bit,2line,5x7dot call write_lcd movlw 00001000b ;display off call write_lcd movlw 00000001b ;Clear display call write_lcd call wait_2ms ; wait 2ms movlw 00000110b ;000001IS, Inc/Dec,Shift call write_lcd movlw 00001111b ;00001DCB, Disp,Curs,Blink call write_lcd movlw 0 movwf lcd_adrs return ;----------------------------------------------------------------------------------- ; Setup Counter ;----------------------------------------------------------------------------------- setup_counter movlw 16 movwf line movlw n0 movwf FSR movlw ee_ncounter movwf ee_adrs setup_c_loop call read_eeprom ;copy EEPROM-->File Reg. movwf INDF incf FSR incf ee_adrs decfsz line,1 goto setup_c_loop return ;----------------------------------------------------------------------------------- ; Blink LED ;----------------------------------------------------------------------------------- blink_led movwf line blink_led_loop bsf PORTB,0 ; LED ON call wait_250ms ; wait 250ms bcf PORTB,0 ; LED OFF call wait_250ms ; wait 250ms decfsz line,1 goto blink_led_loop return ;----------------------------------------------------------------------------------- ; LCD write routine half ;----------------------------------------------------------------------------------- write_lcdx movwf lcd_data write_lcdx0 movf PORTB,0 movwf line movlw 0x0f andwf line,1 movlw 0xf0 andwf lcd_data,0 iorwf line,0 movwf PORTB ; output PORTB bsf PORTB,E ; E='H' bcf PORTB,E ; E='L' lcd_skip call wait_40us ; wait 40us return ;----------------------------------------------------------------------------------- ; LCD write routine ;----------------------------------------------------------------------------------- write_lcd movwf lcd_data write_lcd0 call write_lcdx0 swapf lcd_data,1 call write_lcdx0 swapf lcd_data,1 return ;----------------------------------------------------------------------------------- ; LCD read routine half ;----------------------------------------------------------------------------------- read_lcdx movlw 0x0f andwf lcd_rdata,1 bsf PORTB,E ; E='H' call wait_40us ; wait 40us movlw 0xf0 andwf PORTB,0 iorwf lcd_rdata,1 bcf PORTB,E ; E='L' return ;----------------------------------------------------------------------------------- ; LCD read routine (TEST, Don't use) ;----------------------------------------------------------------------------------- read_lcd bsf PORTB,RS ; RS='H' bsf PORTB,RW ; RW='H' clrf lcd_rdata read_lcd0 call read_lcdx swapf lcd_rdata,1 call read_lcdx swapf lcd_rdata,1 bcf PORTB,RW ; RW='L' return ;----------------------------------------------------------------------------------- ; LCD clear display ;----------------------------------------------------------------------------------- clear_lcd bcf PORTB,RS ; RS='L' movlw 00000001b call write_lcd call wait_2ms ; wait 2ms return ;----------------------------------------------------------------------------------- ; Move cursor ;----------------------------------------------------------------------------------- curs_lcd movwf lcd_adrs curs_lcd0 bcf PORTB,RS ; RS='L' movlw 0x4f andwf lcd_adrs,1 movlw 0x80 ; DDRAM adrs set mode iorwf lcd_adrs,0 call write_lcd call wait_40us ; wait 40us bsf PORTB,RS ; RS='H' return ;----------------------------------------------------------------------------------- ; repair hex ;----------------------------------------------------------------------------------- repair_hex movlw ':' subwf INDF,0 skpnz retlw 'A' movlw '/' subwf INDF,0 skpnz retlw 'F' movlw '@' subwf INDF,0 skpnz retlw '9' movlw 'G' subwf INDF,0 skpnz retlw '0' movfw INDF return ;----------------------------------------------------------------------------------- ; repair FSR ;----------------------------------------------------------------------------------- repair_fsr movlw n0-1 subwf FSR,0 skpnz retlw n0+11 movlw n0+4 subwf FSR,0 skpnz retlw n0+8 movlw n0+7 subwf FSR,0 skpnz retlw n0+3 movlw n0+12 subwf FSR,0 skpnz retlw n0 movfw FSR return ;----------------------------------------------------------------------------------- ; clk one shot (CLK : about 25kHz) ;----------------------------------------------------------------------------------- clk_one ; call wait_100ms ;>>>>>>>> for DEBUG call wait_40us ; wait 40us bsf PORTA,CLK ; call wait_100ms ;>>>>>>>> for DEBUG call wait_40us ; wait 40us bcf PORTA,CLK return ;----------------------------------------------------------------------------------- ; send hex MSB first ;----------------------------------------------------------------------------------- send_hex clrw btfsc INDF,6 movlw -7 addwf INDF,0 movwf s_data movlw 4 ;send 4bit = 1nibble movwf cnt send_hex_loop btfsc s_data,3 bsf PORTA,DAT btfss s_data,3 bcf PORTA,DAT call clk_one rlf s_data,1 decfsz cnt,1 goto send_hex_loop return ;----------------------------------------------------------------------------------- ; send hex MSB first ;----------------------------------------------------------------------------------- send_hex4 movlw 4 ; send 4nibble = 2byte movwf cnt2 send_hex4_loop call send_hex incf FSR,1 decfsz cnt2,1 goto send_hex4_loop return ;----------------------------------------------------------------------------------- ; send LE ;----------------------------------------------------------------------------------- send_le call wait_100us ; wait 100us bsf PORTA,LE ; call wait_100ms ;>>>>>>>> for DEBUG call wait_40us ; wait 40us bcf PORTA,LE call wait_100us ; wait 100us return ;----------------------------------------------------------------------------------- ; send counter ;----------------------------------------------------------------------------------- send_ncount movlw n0 movwf FSR call send_hex4 bcf PORTA,DAT call clk_one call send_le Message msg_wr_ncount call wait_500ms return ;----------------------------------------------------------------------------------- ; send counter ;----------------------------------------------------------------------------------- send_rcount movlw r0 movwf FSR call send_hex4 bsf PORTA,DAT call clk_one bcf PORTA,DAT call send_le Message msg_wr_rcount call wait_500ms return ;----------------------------------------------------------------------------------- ; send vpp (EPCLK : about 800Hz) ;----------------------------------------------------------------------------------- send_vpp bsf PORTA,VPPCON call wait_100us ; wait 100us movlw 4 ; 4 pulse movwf cnt send_vpp_loop bsf PORTA,EPCLK ; call wait_100ms ;>>>>>>>> for DEBUG call wait_625us ; wait 625us bcf PORTA,EPCLK ; call wait_100ms ;>>>>>>>> for DEBUG call wait_625us ; wait 625us decfsz cnt,1 goto send_vpp_loop call wait_100us ; wait 100us bcf PORTA,VPPCON Message msg_wr_vpp call wait_500ms return ;----------------------------------------------------------------------------------- ; wait ;----------------------------------------------------------------------------------- wait_40us movlw 40/5 ; wait 40us goto wait_us wait_100us movlw 100/5 ; wait 100us goto wait_us wait_625us movlw 625/5 ; wait 625us goto wait_us wait_2ms movlw 2 ; wait 2ms goto wait_ms wait_100ms movlw 100 ; wait 100ms goto wait_ms wait_1s call wait_500ms ; wait 1s wait_500ms call wait_250ms ; wait 500ms wait_250ms movlw 250 ; wait 250ms goto wait_ms ;----------------------------------------------------------------------------------- ; LCD input (HEX data in Line 2) ;----------------------------------------------------------------------------------- input_lcd movlw 0x40 call curs_lcd movlw n0 movwf FSR input_lcd0 call test_switch btfsc sw_data,UP incf INDF,1 btfsc sw_data,DOWN decf INDF,1 btfsc sw_data,RIGHT incf FSR,1 btfsc sw_data,LEFT decf FSR,1 btfsc sw_data,OK return call repair_hex movwf INDF call repair_fsr movwf FSR addlw -n0 addlw 0x40 call curs_lcd movf INDF,0 call write_lcd call curs_lcd0 goto input_lcd0 ;----------------------------------------------------------------------------------- ; get table data ;----------------------------------------------------------------------------------- get_table movlw 0x0f movwf PCLATH movfw table_index movwf PCL ;----------------------------------------------------------------------------------- ; print LCD ;----------------------------------------------------------------------------------- print_lcd movwf table_index print_lcd0 bsf PORTB,RS ; RS='H' call get_table movwf lcd_data movlw $>>8 movwf PCLATH movf lcd_data,0 skpnz return addlw -1 skpnz goto lcd_line1 addlw -1 skpnz goto lcd_line2 call write_lcd0 incf table_index,1 goto print_lcd0 lcd_line2 movlw 0x40 lcd_line1 call curs_lcd incf table_index,1 goto print_lcd0 ;----------------------------------------------------------------------------------- ; wait ms ;----------------------------------------------------------------------------------- wait_ms movwf wait_cn wait_ms0 movlw 247 ;1;249 movwf wait_cn2 ;1; wait_ms1 nop ;1; decfsz wait_cn2,1 ;1; goto wait_ms1 ;2;4usx249 decfsz wait_cn,1 ;1; goto wait_ms0 ;2;wait_cn*1001us return ;----------------------------------------------------------------------------------- ; wait us ;----------------------------------------------------------------------------------- wait_us movwf wait_cn wait_us0 goto $+1 ;2; decfsz wait_cn,1 ;1; goto wait_us0 ;2;wait_cn*5us return ;----------------------------------------------------------------------------------- ; Test Switch sw-->line ;----------------------------------------------------------------------------------- test_switch test_sw_on comf PORTC,0 andlw 0x3f skpnz goto test_sw_on movwf sw_data movlw 30 call wait_ms comf PORTC,0 andlw 0x3f xorwf sw_data,0 skpz goto test_sw_on test_sw_off comf PORTC,0 andlw 0x3f skpz goto test_sw_off movlw 30 call wait_ms comf PORTC,0 andlw 0x3f skpz goto test_sw_off return ;----------------------------------------------------------------------------------- ; Read EEPROM ;----------------------------------------------------------------------------------- read_eeprom movf ee_adrs,0 bsf STATUS, RP1 ; bcf STATUS, RP0 ; Bank 2 movwf EEADR ; Data Memory Address to read bsf STATUS, RP0 ; Bank 3 bcf EECON1, EEPGD ; Point to DATA memory bsf EECON1, RD ; EEPROM Read bcf STATUS, RP0 ; Bank 2 movf EEDATA, 0 ; W = EEDATA bcf STATUS, RP1 ; Bank 0 return ;----------------------------------------------------------------------------------- ; Write EEPROM ;----------------------------------------------------------------------------------- write_eeprom bsf STATUS, RP1 ; bcf STATUS, RP0 ; Bank 2 movf ee_adrs,0 ; movwf EEADR ; Data Memory Address to write movf ee_data,0 ; movwf EEDATA ; Data Memory Value to write bsf STATUS, RP0 ; Bank 3 bcf EECON1, EEPGD ; Point to DATA memory bsf EECON1, WREN ; Enable writes bcf INTCON, GIE ; Disable Interrupts movlw 0x55 ; movwf EECON2 ; Write 55h movlw 0xAA ; movwf EECON2 ; Write AAh bsf EECON1, WR ; Set WR bit to begin write bsf INTCON, GIE ; Enable Interrupts bcf EECON1, WREN ; Disable writes btfsc EECON1, WR ; if WR=0 then skip goto $-1 ; bcf EECON1,EEIF ; ; btfss EECON1,WRERR ; if error then skip bcf STATUS, RP0 ; bcf STATUS, RP1 ; Bank 0 Message msg_wr_eeprom return ;----------------------------------------------------------------------------------- ORG 0x0f00 ; Message string ;----------------------------------------------------------------------------------- msg_start DT 1,"NPC ePLL writer",2," v.011008 by K.I",0 msg_set_count DT 1,"Ncount Rcount",2,0 msg_write DT 1,"Write ePLL data?",2,0 msg_wr_ncount DT 2," write Ncounter!",0 msg_wr_rcount DT 2," write Rcounter!",0 msg_wr_vpp DT 2," write Vpp! ",0 msg_wr_eeprom DT 2," write EEPROM! ",0 ;----------------------------------------------------------------------------------- ORG 0x2100 ; (EEPROM default data) ;----------------------------------------------------------------------------------- ee_ncounter DE "0123 ABCD " ;----------------------------------------------------------------------------------- END