;*************************************** ;*** U6223B u_pll - micro PLL *** ;*** Assembler AS (public domain) *** ;*************************************** CPU 16C54 ident macro DATA "u_PLL 1.1 08.03.96 DF1OG" endm ;*************************************** ;allocation special registers: ;*************************************** Indirect SFR $00 ;virtual indirect register RTCC SFR $01 ;realtime clock/counter PClo SFR $02 ;program counter low Status SFR $03 ;status register FSR SFR $04 ;file select register Port_A SFR $05 ;port A Port_B SFR $06 ;port B ;--------------------------------------- ;allocation status register flags: ;--------------------------------------- Flag_C EQU 0 ;carry flag Flag_DC EQU 1 ;digit carry flag Flag_Z EQU 2 ;zero flag ;--------------------------------------- ;destination register: ;--------------------------------------- w EQU 0 ;destination w register f EQU 1 ;destination f register LISTING OFF ;--------------------------------------- ;some flag operations... ;--------------------------------------- clrc macro ;clear carry flag bcf Status,Flag_C endm setc macro ;set carry flag bsf Status,Flag_C endm clrdc macro ;clear digit carry flag bcf Status,Flag_DC endm setdc macro ;set digit carry flag bsf Status,Flag_DC endm clrz macro ;clear zero flag bcf Status,Flag_Z endm setz macro ;set zero flag bcf Status,Flag_Z endm ;--------------------------------------- ;simple program skips... ;--------------------------------------- skpc macro ;skip on carry=1 btfss Status,Flag_C endm skpnc macro ;skip on carry=0 btfsc Status,Flag_C endm skpdc macro ;skip on digit carry=1 btfss Status,Flag_DC endm skpndc macro ;skip on digit carry=0 btfsc Status,Flag_DC endm skpz macro ;skip on zero=1 btfss Status,Flag_Z endm skpnz macro ;skip on zero=0 btfsc Status,Flag_Z endm ;--------------------------------------- ;conditional branches... ;be careful! multiple byte code, not skipable! ;--------------------------------------- b macro target ;branch always goto target endm bc macro target ;branch on carry=1 btfsc Status,Flag_C goto target endm bnc macro target ;branch on carry=0 btfss Status,Flag_C goto target endm bdc macro target ;branch on digit carry=1 btfsc Status,Flag_DC goto target endm bndc macro target ;branch on digit carry=0 btfss Status,Flag_DC goto target endm bz macro target ;branch on zero=1 btfsc Status,Flag_Z goto target endm bnz macro target ;branch on zero=0 btfss Status,Flag_Z goto target endm bbs macro source,bit,target ;branch on bit set btfsc source,bit goto target endm bbns macro source,bit,target ;branch on bit not set btfss source,bit goto target endm ;--------------------------------------- ;loops... ;be careful again! ;--------------------------------------- dfbnz macro source,target ;decrement and branch if not zero decfsz source,f goto target endm ;--------------------------------------- ;carry arithmetic... ;be careful again! ;--------------------------------------- addcf macro reg,dest ;add carry to register btfsc Status,Flag_C incf reg,dest endm subcf macro reg,dest ;subtract carry from register btfsc Status,Flag_C decf reg,dest endm adddcf macro reg,dest ;add digit carry to register btfsc Status,Flag_DC incf reg,dest endm subdcf macro reg,dest ;subtract digit carry from register btfsc Status,Flag_DC decf reg,dest endm ;--------------------------------------- ;misancelous... ;--------------------------------------- movfw macro reg ;transfer register --> w movf reg,w endm negf macro reg,dest ;two's complement comf reg,f incf reg,dest endm tstf macro reg ;set flags due to register movf reg,f endm LISTING ON ;*************************************** ;constant and storage definitions ;*************************************** kc100_10l EQU $0a ;100 kc binary conversion kc100_10h EQU $00 kc100_100l EQU $64 kc100_100h EQU $00 kc100_1000l EQU $e8 kc100_1000h EQU $03 kc100_10000l EQU $10 kc100_10000h EQU $27 kc125_10l EQU $08 ;125 kc binary conversion kc125_10h EQU $00 kc125_100l EQU $50 kc125_100h EQU $00 kc125_1000l EQU $20 kc125_1000h EQU $03 kc125_10000l EQU $40 kc125_10000h EQU $1F AdrByte EQU $c2 ;pll address byte: device address open CtrlByte1 EQU $c6 ;control byte 1: hi current, scale 512 CtrlByte2 EQU $00 ;control byte 2: hi impedance outputs ;--------------------------------------- SEGMENT DATA ORG $08 R0 RES 1 ;general purpose register 0 R1 RES 1 ;general purpose register 1 R2 RES 1 ;general purpose register 2 Kc100 RES 1 ;frequency bcd values 100/125 kc Mc1 RES 1 ; 1 mc Mc10 RES 1 ; 10 mc Mc100 RES 1 ; 100 mc Mc1000 RES 1 ; 1000 mc Control RES 1 ;bit 2 off 100 kc steps ; on 125 kc steps SwChange RES 1 ;switch change check DevAdr RES 1 ;device address PDB1 RES 1 ;program divider byte 1 PDB2 RES 1 ;program divider byte 2 CB1 RES 1 ;control byte 1 CB2 RES 1 ;control byte 2 ;*************************************** SEGMENT CODE ORG $000 Start: b Init ;subroutines in first 256 code bytes ;*************************************** ;scan switches ;*************************************** ScanSw: movlw Kc100 ;set pointer to freq. registers movwf FSR movlw 5 ;five switches to scan movwf R0 movlw %11111110 ;start with low significant switch movwf R1 ScanSw10: movfw R1 ;put scan information onto port movwf Port_B tris Port_B movfw Port_B ;read scan information bits 0-2 andlw %11100000 movwf Indirect swapf Indirect,f clrc rrf Indirect,f movfw Port_A ;read scan information bit 3 movwf R2 rlf R2,w andlw %00001000 iorwf Indirect,f ;combine bits to negative logic movlw %00001111 xorwf Indirect,f setc ;prepare next scan rlf R1,f incf FSR,f dfbnz R0,ScanSw10 ;all switches scaned? ScanSw99: retlw 0 ;*************************************** ;set pll data using i2c protocol ;*************************************** SetPLL: movlw DevAdr ;set pointer to pll data movwf FSR movlw 5 ;5 bytes have to be transfered movwf R0 movlw %11111101 ;start condition tris Port_A nop nop nop movlw %11111100 tris Port_A SetPLL10: movlw 8 ;set bit counter movwf R1 SetPLL20: rlf Indirect,f ;carry flag stores the bit bc SetPLL30 movlw %11111100 ;set data low tris Port_A call ClkOut b SetPLL40 SetPLL30: movlw %11111110 ;set data high tris Port_A call ClkOut SetPLL40: dfbnz R1,SetPLL20 ;one byte transfered? movlw %11111110 ;handle acknowledge tris Port_A call ClkOut rlf Indirect,f ;now all has left correctly again incf FSR,f ;set pointer to next byte dfbnz R0,SetPLL10 ;all bytes transfered? movlw %11111100 ;stop condition tris Port_A movlw %11111101 tris Port_A nop nop nop movlw %11111111 tris Port_A SetPLL99: retlw 0 ;*************************************** ClkOut: iorlw %00000001 ;set clock high tris Port_A nop nop nop andlw %11111110 ;set clock low tris Port_A retlw 0 ;*************************************** SwChk: movlw -10 ;check for greater than nine addwf Indirect,w bnc SwChk99 movlw 9 ;if greater set to nine movwf Indirect SwChk99: retlw 0 ;*************************************** AddPDB: movfw R0 ;do while not zero... bz AddPDB99 movfw R2 ;add LSBs addwf PDB2,f addcf PDB1,f ;add carry to MSB movfw R1 ;add MSBs addwf PDB1,f decf R0,f ;decrement loop count b AddPDB ;loop... AddPDB99: retlw 0 ;*************************************** ident ;include identification ;*************************************** ;start of main program... ;*************************************** ORG $100 Init: movlw %11111100 ;prepare SDA and SCL ports movwf Port_A clrf Kc100 ;clear freq. registers clrf Mc1 clrf Mc10 clrf Mc100 clrf Mc1000 clrf Control clrf SwChange ;initiate freq. setting decf SwChange,f ;--------------------------------------- ;main program loop ;--------------------------------------- Main: call ScanSw ;scan switches ;....................................... movlw Mc1000 ;mask out 1000 mc movwf FSR movfw Indirect movwf Control andlw %00000011 ;bit 0-1 frequency movwf Indirect movlw %00000100 ;bit 2 control andwf Control,f decf FSR,f ;check for valid BCD call SwChk ;100 mc decf FSR,f call SwChk ;10 mc decf FSR,f call SwChk ;1 mc decf FSR,f ;Kc100 mustn't exceed 9 at 100 kc bbs Control,2,Main10 ;and mustn't exceed 7 at 125 kc steps call SwChk ;100 kc steps b Main20 Main10: movlw -8 ;125 kc steps addwf Indirect,w bnc Main20 movlw 7 ;if greater than seven set to seven movwf Indirect ;....................................... Main20: movlw Kc100 ;check for switch change movwf FSR clrw ;add frequency and control values addwf Indirect,w ;100 kc incf FSR,f addwf Indirect,w ;1 mc incf FSR,f addwf Indirect,w ;10 mc incf FSR,f addwf Indirect,w ;100 mc incf FSR,f addwf Indirect,w ;1000 mc incf FSR,f addwf Indirect,w ;control incf FSR,f xorwf Indirect,f ;compare to old switch change check movwf Indirect ;store new change check bz Main ;no change, back to main loop... ;....................................... clrf PDB1 ;convert 100/125 kc into binary format movfw Kc100 ;100/125 kc movwf PDB2 bbs Control,2,Main30 ;100/125 kc steps? movfw Mc1 ;100 kc steps 1 mc movwf R0 movlw kc100_10h movwf R1 movlw kc100_10l movwf R2 call AddPDB movfw Mc10 ;10 mc movwf R0 movlw kc100_100h movwf R1 movlw kc100_100l movwf R2 call AddPDB movfw Mc100 ;100 mc movwf R0 movlw kc100_1000h movwf R1 movlw kc100_1000l movwf R2 call AddPDB movfw Mc1000 ;1000 mc movwf R0 movlw kc100_10000h movwf R1 movlw kc100_10000l movwf R2 call AddPDB b Main40 Main30: movfw Mc1 ;125 kc steps 1 mc movwf R0 movlw kc125_10h movwf R1 movlw kc125_10l movwf R2 call AddPDB movfw Mc10 ;10 mc movwf R0 movlw kc125_100h movwf R1 movlw kc125_100l movwf R2 call AddPDB movfw Mc100 ;100 mc movwf R0 movlw kc125_1000h movwf R1 movlw kc125_1000l movwf R2 call AddPDB movfw Mc1000 ;1000 mc movwf R0 movlw kc125_10000h movwf R1 movlw kc125_10000l movwf R2 call AddPDB ;....................................... Main40: movlw AdrByte ;load pll parameter movwf DevAdr movlw CtrlByte1 movwf CB1 movlw CtrlByte2 movwf CB2 call SetPLL ;transfer pll data b Main ;main loop... ;*************************************** ORG $1ff b Start ;program start on reset ;*************************************** END