;******************************************************************* ; ; Frequency display ; Crystal freq. 4.000MHz +/- a bit ; ;******************************************************************* ; ; FM000.TXT Originally from FM3/4 9:39pm 14 May 2002 ; As implemented in experimental 3.5MHz receiver ; ;******************************************************************* ; ; FM003 Fixed? major silliness in LO-IF code ; Re-wrote USB/LSB suffix code ; Added #defines for crook displays ; Added #defines for two line displays ; Wrapped #ifdef ... endif around debugging code ; ;******************************************************************* ;#define testing 1 ; Comment out when testing finished ;#define Bad_Display 1 ; Un-comment for "stop at 8" displays ;#define Two_Line 1 ; Un-comment for two line displays ;******************************************************************* ; ; CPU configuration ; It's a 16F84, HS oscillator, ; watchdog timer off, power-up timer on ; processor 16f84 include __config _HS_OSC & _PWRTE_ON & _WDT_OFF #define S_out PORTA,0x00 ; 9600 baud serial out #define PUFF PORTA,0x00 ; Future stabiliser #define HUFF PORTA,0x01 ; Ditto. #define ENA PORTA,0x02 ; Display "E" #define RS PORTA,0x03 ; Display "RS" #define PORTA4 PORTA,0x04 ; From LS393 divider chip #define RESET PORTB,0x01 ; Pin 7, Counter RESET #define UP_CNT PORTB,0x02 ; Pin 8, Counter FLUSH #define GATE PORTB,0x03 ; Pin 9, Counter GATE #define Store PORTB,0x04 ; Pin 10, 0 = Measure BFO #define Add_LO PORTB,0x05 ; Pin 11, 0 = RF := LO + IF ; 1 = RF := | LO + (-IF) | #define BFO_Lo PORTB,0x06 ; Pin 12, 0 = BFO on lower freq. #define BFO_Hi PORTB,0x07 ; Pin 13, 0 = BFO on higher freq. #define LOK_FLG FLAGS,0x06 #define Prg_FLG FLAGS,0x05 #define Ovr_Rng FLAGS,0x04 #define AMflag FLAGS,0x03 ; 0 = Don't print USB/LSB suffix #define BANKSEL STATUS,RP0 #define beq bz ; Motorola syntax branches #define BEQ bz #define BNE bnz #define bne bnz #define BCC bnc #define bcc bnc #define BCS bc #define bcs bc #define BRA goto #define bra goto ;******************************************************************* ; ; file register declarations: use only registers in bank0 ; bank 0 file registers begin at 0x0c in the 16F84 ; ;******************************************************************* cblock 0x0c COUNT ; Bin to BCD convert (bit count) TEMP cnt ; (BCD BYTES) COUNT1 ; Used by delay routines ; and "prescaler flush" COUNT2 ; Timing (100ms) COUNT3 ; Timing (100ms) COUNT4 ; Timing (400ms) CHR AccA:3 ; Binary, MSB first AccB:3 ; Intermediate frequency bcd:4 ; BCD, MSD first FLAGS SBflag ; 0 = Lower BFO frequency ; 1 = Higher W_TEMP ; W saved here by ISR STATUS_TEMP ; Status Register saved here by ISR dbg0:3 ; Debugging stuff dbg1:3 dbg2:3 dbg3:3 dbg4:3 dbg5:3 S_Wtemp ; "debug" Variables S_count D_Wtemp D_Stemp D_FSR D_hex endc ;********************************************************** ; ; Begin Executable Stuff(tm) ; org 0 GO clrwdt ; 0 << Reset call InitIO ; 1 INITIALISE PORTS CLRF PORTA ; 2 goto START ; 3 INTRUPT goto ISR ; 4 << Interrupt ;********************************************************** ; ; Text Strings (stored in RETLWs) ; mhz dt " MHz ",0 Spaces dt " ",0 USB dt "USB",0 LSB dt "LSB",0 Prog dt "PRG",0 adv1 dt "DFM 3.0 ",0 adv2 dt "- VK3BHR",0 ovr1 dt " Over ",0 ovr2 dt "Range ",0 #ifdef Two_Line adv3 dt "1234567890ABCDEF",0 endif ;********************************************************** ; ; Main Program ; START CLRF PORTB #ifdef testing bsf PUFF endif CALL LCDINIT ; INITIALIZE LCD MODULE MOVLW adv1 ; Sign on call pmsg #ifdef Bad_Display CALL LINE2 endif movlw adv2 call pmsg MOVLW 0x28 ; Delay for 4 sec. CALL DECI CALL CLEAR ; goto newbit ; fire up full thing ;CNT_AGN bcf INTCON,T0IF ; Clear timer interrupt ; bsf INTCON,T0IE ; Enable timer overflow interrupt ; bsf INTCON,GIE ; Global enable all enabled ints. ; ; call Measure ; call Display ; CALL HOME ; GOTO CNT_AGN ; ALL DONE , START AGAIN ;********************************************************** ; ; Begin a new measurement cycle ; newbit call HOME ; Display ready clrf SBflag ; 0 = Lower BFO frequency ; 1 = Higher bcf AMflag ; 0 = No USB/LSB suffix bcf INTCON,T0IF ; Clear timer interrupt bsf INTCON,T0IE ; Enable timer overflow interrupt bsf INTCON,GIE ; Global enable all enabled ints. bcf Prg_FLG btfsc Store ; Doing "BFO STORE"? goto GetOffs movlw 0x05 ; Delay 0.5 sec call DECI btfsc Store ; De-bounce goto GetOffs GetIf call Measure btfss Ovr_Rng ; Set = Counter overflow? goto GetIf1 MOVLW ovr1 ; Over-range message call pmsg #ifdef Bad_Display CALL LINE2 endif movlw ovr2 call pmsg CALL HOME goto GetIf ; & keep trying GetIf1 movf AccA+0,W ; Copy measurement movwf AccB+0 ; To "IF offset" movf AccA+1,W movwf AccB+1 movf AccA+2,W movwf AccB+2 call Display movlw Prog ; Say "we're programming" call pmsg CALL HOME btfss Store ; Ready to store it? goto GetIf movlw 0x05 ; Delay 0.5 sec call DECI btfss Store ; De-bounce goto GetIf bsf Prg_FLG ; Flag "to be stored" GetOffs btfss BFO_Hi ; Which Offset?? goto Get2 ; Point @ EEPROM btfss BFO_Lo ; 3 bytes each goto Ch2 ; BFO low link only goto Ch3 ; No links Get2 btfss BFO_Lo goto Ch0 ; Both links goto Ch1 ; BFO high link only Ch0 movlw 0x00 ; Offset channel 0 (both links fitted) goto EndOff Ch1 bsf AMflag ; We're gunna print comf SBflag,f ; that BFO is on higher frequency movlw 0x03 ; Offset channel 1 (BFO_Hi link fitted) goto EndOff Ch2 bsf AMflag ; We're gunna print ; that BFO is on lower frequency movlw 0x06 ; Offset channel 2 (BFO_Lo link fitted) goto EndOff Ch3 movlw 0x09 ; Offset channel 3 (no links fitted) ; goto EndOff EndOff btfsc Prg_FLG ; Storing Offset? goto Do_St ; If not, then call EE_RD ; must be reading. goto Do_Meas Do_St call EE_WR ; ; Now have IF in AccB ; Do_Meas call Measure ; Measure Local Osc Freq. btfss Ovr_Rng ; Set = Counter overflow? goto Add_Sub MOVLW ovr1 ; Over-range message call pmsg #ifdef Bad_Display CALL LINE2 endif movlw ovr2 goto EndMsg ; ; Now have LO in "AccA" ; and IF in "AccB" ; Add_Sub btfss Add_LO ; Add or Sub LO freq? goto AddLSB ; Clear = just add call MinusA ; RF := IF - LO ; SBflag is OK ; ; AccA := AccA + AccB ; AddLSB movf AccB+2,W ; Process LSB addwf AccA+2,F bcc AddISB ; If no carry,do next incf AccA+1,f ; Else roll over higher bne AddISB ; bytes as appropriate incf AccA+0,f ; may roll over MSByte AddISB movf AccB+1,W ; Process middle byte addwf AccA+1,F bcc AddMSB ; If no carry,do next incf AccA+0,f ; Else roll over higher AddMSB movf AccB+0,W ; Process MSB addwf AccA+0,F ; ; Fix overflow ; btfss AccA+0,7 ; Add Overflowed? goto OK2go ; Clear = OK 2 print call MinusA ; Make positive and comf SBflag,f ; Swap USB/LSB ; ; Display resulting number in AccA ; OK2go call Display ; display result at last ; ; Print suffix - USB, LSB or nuffin ; btfsc AMflag ; Do we print at all? goto trySBf movlw Spaces ; nuffin = spaces goto EndMsg trySBf btfsc SBflag,0 ; Which sideband? goto pLSB movlw USB ; USB obviously goto EndMsg pLSB movlw LSB ; LSB ; goto EndMsg EndMsg call pmsg ; Print selected trailer #ifdef Two_Line CALL LINE2 ; WRITE second LINE movlw adv3 call pmsg endif goto newbit ; Start next measurement ;********************************************************** ; ; Negate number in AccA (2's complement form) ; MinusA comf AccA+0,f ; Complement all bits comf AccA+1,f ; of number comf AccA+2,f incf AccA+2,f ; Add 1 bne N_xit incf AccA+1,f bne N_xit incf AccA+0,f N_xit return ;********************************************************** ; ; Print String addressed by W ; Note: Strings are in program space ; pmsg movwf EEADR ; Temp for pointer pm1 movf EEADR,W ; Get current pointer call pmsub andlw 0xff ; Test returned value beq pm_end ; NULL = All done call DATS incf EEADR,F goto pm1 pmsub movwf PCL ; Goto W nop ; Just in case nop ; Second may not be needed pm_end return ;********************************************************** ; ; Delay for W x 100ms (untrimmed) ; DECI MOVWF COUNT4 ;DELAY 100MS X CONTENTS (W) NXT6 CALL MS100 DECFSZ COUNT4,F GOTO NXT6 RETLW 0 ;********************************************************** ; ; Delay for 100ms (trimmed for actual clock freq) ; MS100 MOVLW 0xff ; 100 MS DELAY LOOP MOVWF COUNT1 ; 4 MHZ XTAL MOVLW 0x7e ; Count up MOVWF COUNT2 ; to roll-over MOVLW 0x19 ; (was 1B) MOVWF COUNT3 L3 INCFSZ COUNT3,F GOTO L3 INCFSZ COUNT2,F GOTO L3 INCFSZ COUNT1,F GOTO L3 RETLW 0 ;********************************************************** ; ; Put 4 bits to LCD & wait (untrimmed) ; PB_dly ANDLW 0x0F ; MASK OFF UPPER 4 BITS MOVWF PORTB ; SEND DATA TO DISPLAY BSF ENA ; ENA HIGH NOP BCF ENA ; ENA LOW ; Fall into DELAY subroutine ;********************************************************** ; ; Delay for 200us (untrimmed) ; D200us DELAY MOVLW 0x42 ; DELAY 200us MOVWF COUNT1 NXT5 DECFSZ COUNT1,F GOTO NXT5 RETLW 0 ;********************************************************** ; ; Delay for 2ms (untrimmed) ; MS2 MOVLW 0x0A ; DELAY 2ms MOVWF COUNT2 LP15 MOVLW 0x42 MOVWF COUNT1 LP16 DECFSZ COUNT1,F GOTO LP16 DECFSZ COUNT2,F GOTO LP15 RETLW 0 ;****************************************************************** ; ; Convert 24-bit binary number at into a bcd number ; at . Uses Mike Keitz's procedure for handling bcd ; adjust; Modified Microchip AN526 for 24-bits. ; B2_BCD b2bcd movlw .24 ; 24-bits movwf COUNT ; make cycle counter clrf bcd+0 ; clear result area clrf bcd+1 clrf bcd+2 clrf bcd+3 b2bcd2 movlw bcd ; make pointer movwf FSR movlw .4 movwf cnt ; Mike's routine: b2bcd3 movlw 0x33 addwf INDF,f ; add to both nybbles btfsc INDF,3 ; test if low result > 7 andlw 0xf0 ; low result >7 so take the 3 out btfsc INDF,7 ; test if high result > 7 andlw 0x0f ; high result > 7 so ok subwf INDF,f ; any results <= 7, subtract back incf FSR,f ; point to next decfsz cnt,f goto b2bcd3 rlf AccA+2,f ; get another bit rlf AccA+1,f rlf AccA+0,f rlf bcd+3,f ; put it into bcd rlf bcd+2,f rlf bcd+1,f rlf bcd+0,f decfsz COUNT,f ; all done? goto b2bcd2 ; no, loop return ; yes ;*********** INITIALISE LCD MODULE 4 BIT MODE *********************** LCDINIT CALL MS100 ; WAIT FOR LCD MODULE HARDWARE RESET BCF RS ; REGISTER SELECT LOW BCF ENA ; ENABLE LINE LOW MOVLW 0x03 ; 1 call PB_dly CALL MS100 ; WAIT FOR DISPLAY TO CATCH UP MOVLW 0x03 ; 2 call PB_dly MOVLW 0x03 ; 3 call PB_dly MOVLW 0x02 ; Fn set 4 bits call PB_dly MOVLW 0x0C ; 0x0C DISPLAY ON CALL STROBE CALL DELAY MOVLW 0x06 ; 0x06 ENTRY MODE SET CALL STROBE CALL DELAY MOVLW 0x01 ; 0x01 CLEAR DISPLAY CALL STROBE CALL MS2 RETLW 0 ;********************************************************** ; ; SENDS DATA TO LCD DISPLAY MODULE (4 BIT MODE) ; STROBE BCF RS ; SELECT COMMAND REGISTER GOTO CM ;********************************************************** ; ; Put a BCD nybble to display ; PutNyb ANDLW 0x0F ; MASK OFF OTHER PACKED BCD DIGIT ADDLW 0x30 ; Convert BIN to ASCII DATS BSF RS ; SELECT DATA REGISTER CM MOVWF CHR ; STORE CHAR TO DISPLAY SWAPF CHR,W ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE) call PutN_1 MOVF CHR,W ; GET CHAR AGAIN PutN_1 ANDLW 0x0F ; MASK OFF UPPER 4 BITS MOVWF PORTB ; SEND DATA TO DISPLAY BSF ENA ; ENA HIGH NOP BCF ENA ; ENA LOW goto D200us ; DELAY 200us ;************ MOVE TO START OF LINE 2 ***************** LINE2 MOVLW 0xC0 ; ADDRESS FOR SECOND LINE OF DISPLAY CALL STROBE goto DELAY ;************ CLEAR DISPLAY *************************** CLEAR MOVLW 0x01 ; COMMAND TO CLEAR DISPLAY CALL STROBE goto MS2 ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY ;*********** MOVE TO HOME ***************************** HOME MOVLW 0x02 ; COMMAND TO HOME DISPLAY CALL STROBE goto MS2 ;******************************************************************** ; Initialise Input & Output devices ;******************************************************************** InitIO bsf BANKSEL ; Select Bank1 movlw 0x37 ; Option register movwf OPTION_REG ; Port B weak pull-up enabled ; INTDEG Don't care ; Count RA4/T0CKI ; Count on falling edge ; Prescale Timer/counter ; divide Timer/counter by 256 ; PORTA:- movlw 0x10 ; initialise data direction ; 1 = input ; 0 = output ; ; PORTA has 5 pins 4 3 2 1 0 ; 0x10 = 0 0 0 1 0 0 0 0 ; movwf TRISA ; PORTA<0> = Huff'n puff ; PORTA<1> = Huff'n puff ; PORTA<2> = LCD "E" ; PORTA<3> = LCD "RS" ; PORTA<4> = Input ; PORTA<5:7> = not implemented in 16F84 ; ; PORTB:- movlw 0xf0 ; initialise data direction ; PORTB has 8 pins ; port pin 7 6 5 4 3 2 1 0 ; 0xf0 = 1 1 1 1 0 0 0 0 ; movwf TRISB ; PORTB<0> = LCD "DB4" ; PORTB<1> = "DB5" ; PORTB<2> = "DB6" ; PORTB<3> = "DB7" ; PORTB<4> = Input ; PORTB<5> = Input ; PORTB<6> = Input ; PORTB<7> = Input bcf BANKSEL ; Re-select Bank0 return ;********************************************************** ; ; Measure Frequency. Stash in "AccA:3" ; Measure bcf Ovr_Rng ; Declare "Not yet Over-range" BCF GATE ; Ready for counting BSF UP_CNT BSF RESET ; RESET EXTERNAL COUNTER (393) NOP BCF RESET CLRF TMR0 ; RESET INTERNAL COUNT (INCLUDING PRESCALER) ; See page 27 Section 6.0 CLRF AccA ; Ready to receive 24 bit number CLRF AccA+1 CLRF AccA+2 BSF GATE ; OPEN GATE'S #ifdef testing call ctest ; Test counter or else CALL MS100 ; 100MS DELAY CALL MS100 ; & again CALL MS100 CALL MS100 endif BCF GATE ; CLOSE GATE (COUNT COMPLETE) MOVF TMR0,W ; GET HIGH BYTE MOVWF AccA ; Copy to Big end of 24 bit result MT0_393 btfsc PORTA4 ; Test 393 output goto MT1_393 ; 128 <= count <=255 BCF UP_CNT ; Clock the 393 once NOP BSF UP_CNT DECF AccA+2,F ; Decrement the counter goto MT0_393 MT1_393 btfss PORTA4 ; Test 393 output goto Do_PSC ; It's Rolled over!( 255->0) BCF UP_CNT ; Clock the 393 once NOP BSF UP_CNT DECF AccA+2,F ; Decrement the counter goto MT1_393 ; At this point, we have got the MSbyte & the LS byte. ; ie. AccA:AccA+1:AccA+2 = MSbyte:??:LSbyte ; The 393 counter is outputting a 0 'cos we've just rolled ; it over, so T0CKI=0. Do_PSC MOVF TMR0,W ; Used only to check for MOVWF COUNT1 ; Prescaler roll over PSC1 bsf BANKSEL ; Select Bank1 bcf OPTION_REG,T0SE ; Clock the prescaler nop bsf OPTION_REG,T0SE bcf BANKSEL ; Re-select Bank0 DECF AccA+1,F ; Decrement the counter movf TMR0,W ; Has TMR0 changed? xorwf COUNT1,W ; if unchanged, XOR -> 0 bz PSC1 DECF AccA+1,F ; Because we flushed 393 ; AccA : AccA+1 : AccA+2 now holds 24 bit result rrf AccA+0,f ; Divide AccA:3 by 4 rrf AccA+1,f ; cos gate = 400ms rrf AccA+2,f bcf AccA+0,7 ; Possible bad carry in. rrf AccA+0,f rrf AccA+1,f rrf AccA+2,f bcf AccA+0,7 ; Possible bad carry in. return ;********************************************************** ; ; Display frequency ; ; Display contents of AccA...AccA+3 on LCD ; First convert to BCD, Then ASCII (nybble at a time) Display CALL B2_BCD ; CONVERT COUNT TO BCD MOVLW 0x30 MOVWF TEMP ; AMOUNT TO ADD TO CONVERT TO ASCII MOVF bcd,W ; GET FIRST BCD DIGIT. It's LSB of bcd ANDLW 0x0F ; MASK OFF OTHER PACKED BCD DIGIT BTFSS STATUS,Z ; IS IT A '0' ? GOTO NoBlank MOVLW 0x20 ; YES PRINT A BLANK SPACE CALL DATS GOTO NxtDig NoBlank CALL PutNyb NxtDig swapf bcd+1,W ; GET NEXT DIGIT CALL PutNyb ; DISPLAY IT MOVLW '.' ; Obvious! CALL DATS MOVF bcd+1,W ; GET OTHER BCD DIGIT CALL PutNyb SWAPF bcd+2,W ; GET NEXT DIGIT CALL PutNyb ; DISPLAY IT MOVF bcd+2,W ; GET OTHER BCD DIGIT CALL PutNyb SWAPF bcd+3,W ; GET NEXT DIGIT CALL PutNyb ; DISPLAY IT MOVF bcd+3,W ; GET OTHER BCD DIGIT CALL PutNyb ; DISPLAY IT #ifdef Bad_Display CALL LINE2 ; WRITE "Mhz" AT end OF LINE endif movlw mhz goto pmsg ; was CALL then RETURN ; call pmsg ; return ;******************************************************************** ; Read EEPROM into "AccB" ; W -> memory to read ;******************************************************************** EE_RD BCF BANKSEL ; Bank 0 MOVWF EEADR ; Address to read XORLW 0x09 ; Special case (no links) BEQ AVERAGE CALL EE_R MOVWF AccB INCF EEADR,F ; Address to read CALL EE_R MOVWF AccB+1 INCF EEADR,F ; Address to read CALL EE_R MOVWF AccB+2 RETURN AVERAGE movlw 0x03 ; AM - use avg BFO freq. call EE_RD ; Read in one BFO freq #ifdef testing movf AccB+0,w ; Debugging copy movwf dbg0+0 movf AccB+1,w ; Debugging copy movwf dbg0+1 movf AccB+2,w ; Debugging copy movwf dbg0+2 endif if_LSB movlw 0x08 ; Then add second movwf EEADR call EE_R #ifdef testing movwf dbg1+2 ; Debugging copy endif addwf AccB+2,f ; handle carry bcc if_ISB incf AccB+1,f bne if_ISB incf AccB+0,f if_ISB ; call debug decf EEADR,f call EE_R #ifdef testing movwf dbg1+1 ; Debugging copy endif addwf AccB+1,f ; & carry again bcc if_MSB incf AccB+0,f if_MSB ; call debug decf EEADR,f call EE_R #ifdef testing movwf dbg1+0 ; Debugging copy endif addwf AccB+0,f #ifdef testing movf AccB+0,w ; Debugging copy movwf dbg2+0 movf AccB+1,w ; Debugging copy movwf dbg2+1 movf AccB+2,w ; Debugging copy movwf dbg2+2 endif rrf AccB+0,f ; Divide by 2 rrf AccB+1,f rrf AccB+2,f bcf AccB+0,7 ; Clear carry in bit #ifdef testing movf AccB+0,w ; Debugging copy movwf dbg3+0 movf AccB+1,w ; Debugging copy movwf dbg3+1 movf AccB+2,w ; Debugging copy movwf dbg3+2 endif ; call debug return EE_R BSF BANKSEL ; Bank 1 BSF EECON1,RD ; EE Read BCF BANKSEL ; Bank 0 MOVF EEDATA,W ; W = EEDATA RETURN ;******************************************************************** ; Write EEPROM from "AccB" ; W -> memory to write ;******************************************************************** EE_WR BSF BANKSEL ; Bank 1 BCF INTCON,GIE ; Disable INTs. BCF BANKSEL ; Bank 0 MOVWF EEADR ; Address to write MOVF AccB+0,W ; Get data byte #1 CALL EE_W INCF EEADR,F ; Fix address MOVF AccB+1,W ; Get data byte #2 CALL EE_W INCF EEADR,F MOVF AccB+2,W ; Get data byte #3 CALL EE_W BSF BANKSEL ; Bank 1 BSF INTCON,GIE ; Enable INTs. BCF BANKSEL ; Bank 0 RETURN EE_W MOVWF EEDATA BSF BANKSEL ; Bank 1 BSF EECON1,WREN ; Enable Write MOVLW 0x55 ; MOVWF EECON2 ; Write 0x55 MOVLW 0xAA ; MOVWF EECON2 ; Write 0xAA BSF EECON1,WR ; Set WR bit (begin write) EE_W2 BTFSC EECON1,WR ; Wait for write to finish GOTO EE_W2 BCF EECON1,EEIF ; clear interrupts BCF BANKSEL ; Bank 0 RETURN ;******************************************************************** ; Timer Interrupt service. First save W and STATUS ;******************************************************************** ISR PUSH MOVWF W_TEMP ; Copy W to temp register, SWAPF STATUS,W ; Swap status to be saved into W MOVWF STATUS_TEMP ; Save status to STATUS_TEMP register ; Timer interrupt stuff btfsc INTCON,T0IF ; Has timer interrupted? bsf Ovr_Rng ; Yes = Over-range bcf INTCON,T0IF ; Clear timer interrupt anyway POP SWAPF STATUS_TEMP,W ; Swap nibbles in STATUS_TEMP register ; and place result into W MOVWF STATUS ; Move W into STATUS register ; (sets bank to original state) SWAPF W_TEMP,F ; Swap nibbles in W_TEMP and place result in W_TEMP SWAPF W_TEMP,W ; Swap nibbles in W_TEMP and place result into W bcf INTCON,2 ; Clear timer interrupt bit retfie ; TOS -> PC, 1 -> GIE ;******************************************************************** ; Testing counter ;******************************************************************** #ifdef testing ctest movlw 0xfe ; MS byte of loop count movwf COUNT2 ; Counted upward till it overflows movlw 0x1d movwf COUNT1 movlw 0xc0 movwf COUNT0 cloop bcf PUFF ; Toggle counter input once bsf PUFF incfsz COUNT0,f goto cloop incfsz COUNT1,f goto cloop incfsz COUNT2,f goto cloop return ;*********************************************************************** ; ; Debugging Memory & Register dump ; debug MOVWF D_Wtemp ; Copy W to temp register, SWAPF STATUS,W ; Swap status to be saved into W MOVWF D_Stemp ; Save status to D_Stemp register movf FSR,W ; Save FSR movwf D_FSR movlw 0x57 ; W= call putchr movlw 0x3d call putchr movf D_Wtemp,w call hex_2 movlw 0x20 ; 2 spaces, just to be neat call putchr movlw 0x20 call putchr movlw 0x53 ; SR= call putchr movlw 0x52 call putchr movlw 0x3d call putchr movf D_Stemp,w call hex_2 movlw 0x0d ; CRLF call putchr movlw 0x0a call putchr clrf FSR ; Ready for memory dump D_loop movf 0,W ; Read indirect call hex_2 movlw 0x20 call putchr incf FSR,f ; to next byte movf FSR,w ; end of line? andlw 0x0F bne next_ln movlw 0x0d ; CRLF call putchr movlw 0x0a call putchr bra chk4end next_ln andlw 0x03 ; Groups of 4 bne chk4end movlw 0x20 call putchr chk4end movf FSR,w ; All done? addlw 0xB0 bne D_loop movlw 0x0d ; CRLF call putchr movlw 0x0a call putchr movlw 0x0d ; CRLF call putchr movlw 0x0a call putchr movf D_FSR,W ; Restore FSR movwf FSR SWAPF D_Stemp,W ; Swap nibbles in D_Stemp register ; and place result into W MOVWF STATUS ; Move W into STATUS register ; (sets bank to original state) SWAPF D_Wtemp,F ; Swap nibbles in D_Wtemp and place result in D_Wtemp SWAPF D_Wtemp,W ; Swap nibbles in D_Wtemp and place result into W return ;*********************************************************************** ; ; Print W as 2 Hex digits ; hex_2 movwf D_hex swapf D_hex,w ; Get big bit call hex_3 movf D_hex,w ; Get little bit hex_3 andlw 0x0f ; keep bottom 4 bits addlw 0xF6 bcc hex_4 addlw 0x07 ; binary A -> ASCII A hex_4 addlw 0x3A ; binary 0 -> ASCII 0 ;******************************************************** ; ; Output Routines for PIC16F84 ; ; Clock is 4.0 MHz. ; ie. 1.0 us per cycle = 4/Fosc. ; ; 9600 Baud = 104.17 us ; = 104.17 CPU cycles ; ;******************************************************** ; ; Output the character in W. Assumes Mac is ready. ; ; Uses W ; putchr movwf S_Wtemp ; Character being output movlw 0x08 ; Bit count movwf S_count bcf S_out ; Send a 0 - Start bit put_clp movlw 0xE7 ; Delay "104" cycles txd_0 addlw 0x01 bne txd_0 rrf S_Wtemp,f ; Transmit a bit bcs t_0 bcf S_out ; Send a 0 bra tx_1 t_0 bsf S_out ; Send a 1 tx_1 decfsz S_count,f ; Done all bits? goto put_clp movlw 0xE7 ; Delay for last data txd_1 addlw 0x01 bne txd_1 bsf S_out ; Transmit two stop bit movlw 0xCD txd_9 addlw 0x01 bne txd_9 return endif ;******************************************************************** ; Tail End Charlie ;******************************************************************** END