;****************************************************************************************;
;*		Direct Digital Synthesizer VFO using AD9850/51									*;
;*																						*;
;*		Date				: Sunday, 18 Jun 2006										*;
;* 		Author				: C.V.Niras/VU3CNS											*;
;*		Copyright			: (C) 2005 C. V. Niras 										*;
;*		Email				: cvniras@hamradio.in										*;
;*																						*;
;*	This program is free software; you can redistribute it and/or modify it under the	*;
;*	terms of the GNU General Public License as published by the Free Software 			*;
;*	Foundation; either version 2, or (at your option) any later version.				*;
;*																						*;
;*	This program is distributed in the hope that it will be useful, but WITHOUT ANY		*;
;*	WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 	*;
;*	PARTICULAR PURPOSE. See the GNU General Public License for more details.			*;
;*																						*;
;****************************************************************************************;

;****************************************************************************************;
;*	This is the program for PIC 2 in DDS circuit. PIC 1 sends data in syncronous 9 bit 	*;
;*	mode. PIC1 uses 32 bit for the freq, but sending only one byte (, i.e Freq/ 0x20000)*;
;*	Only this is necessary for selecting bands up to 30MHz.								*;
;*	For selecting MODE (i.e. LSB/USB..) PIC 1 sends another byte data, and we need olny	*;
;*	the first two bits																	*;
;*		00 = No offset																	*;
;*		01 = CW offset																	*;
;*		10 = -SB offset 																*;
;*		11 = +SB offset																	*;
;*	If 9th bit is set, it means the data sent was for MODE selection else BAND selection*;
;****************************************************************************************;


		list p=16F628A				;		list directive to define processor
		#include <P16F628A.INC>		;		processor specific definitions
		errorlevel -302				;		suppress "not in bank 0" message

 __CONFIG _WDT_OFF & _LVP_OFF & _INTOSC_OSC_NOCLKOUT & _BODEN_ON & _PWRTE_ON & _MCLRE_OFF
;----------------------------------------------------------------------------
;Constants

SPBRG_VAL	EQU		.25				;		set baud rate 9600 for 4Mhz clock
RX_BUF_LEN	EQU		.1				;		length of receive buffer
TX_BUF_LEN	EQU		RX_BUF_LEN		;		length of transmit buffer

;----------------------------------------------------------------------------
#DEFINE	NO_BAND_OP		PORTB,0		;
#DEFINE	BANDS 9

#DEFINE BAND1 ((.1810000 + .2000000) / 2)    ; 160m [ Calculate band centre in
#DEFINE BAND2 ((.3500000 + .3800000) / 2)    ;  80m [ Hz, based on upper and lower
#DEFINE BAND3 ((.7000000 + .7100000) / 2)    ;  40m [ frequency limits for that
#DEFINE BAND4 ((.10100000 + .10150000) / 2)  ;  30m [ band.
#DEFINE BAND5 ((.14000000 + .14350000) / 2)  ;  20m
#DEFINE BAND6 ((.18068000 + .18168000) / 2)  ;  17m
#DEFINE BAND7 ((.21000000 + .21450000) / 2)  ;  15m
#DEFINE BAND8 ((.24890000 + .24990000) / 2)  ;  12m
#DEFINE BAND9 ((.28000000 + .29700000) / 2)  ;  10m

#DEFINE	MODE			FLAG,0		;

;----------------------------------------------------------------------------
;			Variables
;----------------------------------------------------------------------------	
			CBLOCK	0x020			;		Bnak 0 bytes 0x20 to 0x6F(80 bytes)

			ENDC
			
			CBLOCK 0x70				;		Bank 0 cont. 0x70 to 0x7F 16 bytes
									;		General purposes
			FLAG					;		byte to store indicator flags
			COUNT					;
			RX_DATA					;
			MODE_DATA				;
			SAVE_STATUS				;
			SAVE_W_REG				;
			OLD_COUNT				;
			OLD_RX_DATA				;
			ENDC
	
			CBLOCK	0x0A0			;		Bank 1 bytes 0xA0 to 0xEF
			ENDC

;----------------------------------------------------------------------------
;		Macros to select the register bank
;		Many bank changes can be optimized when only one STATUS bit changes

BANK0		MACRO					;		macro to select data RAM bank 0
			BCF		STATUS,RP0
			ENDM

BANK1		MACRO					;		macro to select data RAM bank 1
			BSF		STATUS,RP0
			ENDM
;----------------------------------------------------------------------------
#DEFINE		SCALE_FACTOR	0x20000	;		20000 hex = 2 ^ 17
									; 		Note - setBand() makes assumptions about
									; 		this value - if it is changed then setBand
									; 		must be changed to match.
			ORG	0x05				;		Location after interruptvector				
BAND_LO:
			ADDWF   PCL,F
			RETLW   ((BAND1 * .9) / .10) / SCALE_FACTOR
			RETLW   ((BAND2 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND3 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND4 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND5 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND6 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND7 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND8 * .19) / .20) / SCALE_FACTOR
			RETLW   ((BAND9 * .19) / .20) / SCALE_FACTOR

BAND_HI:
			ADDWF   PCL,F
			RETLW   ((BAND1 * .11) / .10) / SCALE_FACTOR
			RETLW   ((BAND2 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND3 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND4 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND5 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND6 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND7 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND8 * .21) / .20) / SCALE_FACTOR
			RETLW   ((BAND9 * .21) / .20) / SCALE_FACTOR
			
BAND_SELECT:
			ADDWF	PCL,F
			RETLW	0x08			; BAND 1
			RETLW	0x10			; BAND 2
			RETLW	0x20			; BAND 3
			RETLW	0x40			; BAND 4
			RETLW	0x80			; BAND 5
			
			RETLW	0x00			; BAND 6
			RETLW	0x00			; BAND 7
			RETLW	0x00			; BAND 8
			RETLW	0x00			; BAND 9
			
			RETLW	0x01			; NO BAND

BAND_SELECT_HI:
			ADDWF	PCL,F			
			RETLW	0x00			; BAND 1
			RETLW	0x00			; BAND 2
			RETLW	0x00			; BAND 3
			RETLW	0x00			; BAND 4
			RETLW	0x00			; BAND 5
						
			RETLW	0x40			; BAND 6
			RETLW	0x80			; BAND 7
			RETLW	0x01			; BAND 8
			RETLW	0x02			; BAND 9
			
			RETLW	0x00			; NO BAND
			
MODE_SELECT:	
			ADDWF	PCL,F
			RETLW	0x00
			RETLW	0x04
			RETLW	0x08
			RETLW	0x10
			
#IF ($ > 255)
	MESSG	ERR0R : TABLE OVERFLOWS
#ENDIF			
TABLE_END
;----------------------------------------------------------------------------
;This code executes when a reset occurs.

			ORG     0x0000			;		place code at reset vector
RESET:		CLRF	PORTA			;
			CLRF	PORTB			;
		    BSF		STATUS,RP0		;		Select Bank 1
		    GOTO	CONTINUE		;

;----------------------------------------------------------------------------
;			Interrupt Vector
			ORG	0x0004				;		place code at interrupt vector
			GOTO	INTERRUPT		;	
;----------------------------------------------------------------------------
			ORG		TABLE_END			
			
CONTINUE:	MOVLW	0x00			;
			MOVWF	TRISA			;
			MOVLW	0x06			;
			MOVWF	TRISB			;
			MOVLW	B'00010000'		;		Slave, TX dis, Sync mode
			MOVWF	TXSTA			;
			MOVLW	B'00100000'		;		Enable RCIE Interrupt
			MOVWF	PIE1			;
			BANK0					;		Select Bank0
			MOVLW	0x07			;
			MOVWF	CMCON			;
			MOVLW	B'01000000'		;
			MOVWF	INTCON			;		Enable Peripheral interrupt
			MOVLW	B'11000000'		;		Enable serial port, and Enable RX
			MOVWF	RCSTA			;
			
			CLRF	COUNT			;
			MOVLW	BANDS			;		Load OLD_COUNT = No Band 
			MOVWF	OLD_COUNT		;
			CLRF	FLAG			;
			CLRF	RX_DATA			;
			CLRF	OLD_RX_DATA		;
			
			BSF		NO_BAND_OP		;
			
			BSF		INTCON,GIE		;
			BSF		RCSTA,CREN		;
			
			
MAIN:		BTFSC	MODE			;		
			GOTO	MODE_SEL		;
					
SET_BAND:	MOVLW	BANDS			;
			MOVWF   COUNT			;

BAND_LOOP:	DECF    COUNT,F
			BTFSC   COUNT,7			;		Check for counter 'underflow'
			GOTO	NO_BAND			;		We've run out of bands to check!
		
			MOVF    COUNT,W
			CALL    BAND_LO
			SUBWF   RX_DATA,W		;		Compare with lower freq of band
			BTFSS	STATUS,C		;
			GOTO	BAND_LOOP		;		If below bottom of this band, skip to next
		
			MOVF	COUNT,W			;
			CALL	BAND_HI
			SUBWF   RX_DATA,W       ;		Compare with upper freq of band
			BTFSC	STATUS,Z		;
			GOTO	BAND_FOUND		;		If equal to...
			BTFSS	STATUS,C		;		...or less than, we have a match.
			GOTO	BAND_FOUND		;
			
NO_BAND:	MOVLW	BANDS			;		Load Count for NO band o/p
			MOVWF	COUNT			;

BAND_FOUND:	MOVF	COUNT,W			;		check, any band changes
			XORWF	OLD_COUNT,F		;
			MOVWF	OLD_COUNT		;
			BTFSC	STATUS,Z		;		
			GOTO	END_SEL			;		N. Exit
			
			MOVLW	B'00111100'		;		Clear band selection bits in PORTA
			ANDWF	PORTA,F			;
;			CLRF	PORTB			;		Clear band selection bits of PORTB
			
;			MOVF	COUNT,W			;		check the band is higher than 5
;			SUBLW	0x04			;		( i.e. count > 4)
;			MOVF	COUNT,W			;
;			BTFSS	STATUS,C		;
;			GOTO	USE_PORTA		;
;			
;			CALL	BAND_SELECT		;
;			MOVWF	PORTB			;
;			GOTO	END_SEL			;
;
;USE_PORTA:	CALL	BAND_SELECT		;
;			IORWF	PORTA,F			;			
;			GOTO	END_SEL			;
			MOVF	COUNT,W			;
			CALL	BAND_SELECT		;
			MOVWF	PORTB			;
			MOVF	COUNT,W			;
			CALL	BAND_SELECT_HI	;
			IORWF	PORTA,F			;
			GOTO	END_SEL			;
			
;NO_BAND:	MOVF	COUNT,W			;	
;			XORWF	OLD_COUNT,F		;
;			MOVWF	OLD_COUNT		;
;			BTFSC	STATUS,Z		;
;			GOTO	END_SEL			;

;			MOVLW	B'00111100'		;		Clear band selection bits in PORTA
;			ANDWF	PORTA,F			;
;			CLRF	PORTB			;
;			BSF		NO_BAND_OP		;
;			GOTO	END_SEL			;
			
MODE_SEL:	MOVF	RX_DATA,W		;
			ANDLW	0x03			;
			XORWF	OLD_RX_DATA,F	;
			MOVWF	OLD_RX_DATA		;
			BTFSC	STATUS,Z		;
			GOTO	END_SEL			;
			
			MOVLW	B'11100011'		;
			ANDWF	PORTA,F			;
			MOVF	OLD_RX_DATA,W	;
			CALL	MODE_SELECT		;
			IORWF	PORTA,F			;

			GOTO	END_SEL			;
		
END_SEL:	SLEEP					;		All work done! Go to sleep
			NOP						;
			GOTO	MAIN			;


INTERRUPT:
			MOVWF   SAVE_W_REG      ;       Save W reg.
            SWAPF   STATUS,W        ;
            MOVWF   SAVE_STATUS     ;       Save STATUS reg.	
;			BANK0					;
			BCF		MODE			;
			BTFSC	RCSTA,RX9D		;
			BSF		MODE			;
			
			MOVF	RCREG,W			;
			MOVWF	RX_DATA			;

INT_EXIT:	SWAPF   SAVE_STATUS,W   ;
            MOVWF   STATUS          ;       Restore STATUS reg.
            SWAPF   SAVE_W_REG,F    ;
            SWAPF   SAVE_W_REG,W    ;       Restore W reg without changing STATUS.
			RETFIE	
;----------------------------------------------------------------------------

		END

