;********************************************************** ;* RDDSBeacon01,ASM Feb 26 2010 by G4NNS ;* Reverse DDS with Keyer for Beacons ;* This program is based on Andy Talbot's original work ;* Looks for RS232 line at start up and reads 2400 Baud data to ;* programme EE data this enables the frequencies to be ;* changed. Also, CW speed, interval between idents and ;* time delay to enable the beacon after power up can be changed. ;************************************************************* LIST P=16F628 ; 32 Bit AD9850/51 DDS register data for frequency locked microwave beacons ; DDS Clocked at the Master Oscillator frequency for locking to ; a Reference of between 5 and 20MHz ; The frequency Tuning Words are calculated using the spreadsheet ; available on the G4NNS Web site ; In this example the oscillator is 108.009948MHz ; multiplied by 96 for 10368.955MHz The reference is 10.000MHz ;***************************************************** ;* Note that this and the call sign and locator data ;* to be sent by the keyer are customised to the users requirement ;********************************************************* errorlevel 1 org 0x2100 de 0x17,0xB3,0x96,0xD9 ; 10368.955Hz - MARK de 0x17,0xB3,0x96,0xE9 ; 10368.9546MHz - SPACE EEelle de 0x05 ; default CW element length - 1/CW speed Pause de 0x04 ; 0x90 length of delay between identification EEendel de 0x03 ; 0x10 delay to enable after POWER ON EEmode de 0x00 ; Keying Mode 0 = F1A 1 = A1A de 0x00,0x00,0x00,0x00 ; NOT used de 0x00,0x00,0x00,0x00 ; __config 0x3F62 ; Note change to High Speed Crystal INCLUDE "p16F628a.inc" #define PllFlag D4 , 0 ;x6 PLL multiplier in AD9851 #define TXD PORTB , 0 ;Serial Data in #define RXD PORTB , 3 ;Serial Data out #define LED1 PORTB , 1 #define LED2 PORTB , 2 #define ENABLE PORTB , 2 ;optional enable for beacon #define keytype keymode , 0 ;type of keying #define HexFlag Flags , 0 FData = 0 ;DDS Data on port A WClk = 2 FQud = 1 Reset = 3 ;code starts here org 0 boot nop clrw movwf INTCON ;disable interrupts goto startup ;jump to main code ;..................................................... ints nop ;No interrupts are enabled retfie ;..................................................... startup clrf PORTA ;Special setup to disable comparator on 'F628 movlw b'00000111' movwf CMCON ; bcf STATUS,RP1 bsf STATUS,RP0 ;ram page 1 movlw 0x00 ; movwf TRISA ;set port A0,1,2,3,4 as outputs movlw b'11000001' ;B7/B6 Freq select inputs, B0 TXD In) movwf TRISB ; B1/2 LEDs, B3 RXD (out) clrf OPTION_REG ;enable pull ups bcf STATUS,RP0 ;ram page 0 movlw b'00000000' ;No interupts enabled movwf INTCON ; bcf INTCON, GIE ;disable interrupts bcf ENABLE ;dont enable TX in Prog mode btfss TXD ;Look for RS232 port connected goto ProgMode NormalOp movlw EEelle ;last saved speed is here call GetEE movwf ellen movlw EEendel call GetEE movwf Endel movlw EEmode call GetEE movwf keymode movlw d'200' ;initial start up delay to stabilise levels movwf DelCount2 StartDel bsf LED1 call delay500uS call delay500uS decfsz DelCount2 ; goto StartDel bcf PORTA , Reset clrf D4 ;in case control bits are invalid bcf PllFlag ;disable x 6 multiplier for this test call delay500uS ;Allow PLL to settle call delay500uS call delay500uS call delay500uS idle call KeyDown movlw d'10' movwf len1 idle1 call wait ;Variable delay between Idents decfsz len1 goto idle1 decfsz Endel goto idle3 bsf ENABLE ;ENABLE HI idle3 nop call KeyUp call space2 call space2 call _g ;Put your beacon call sign and location call _b ;identification message here call _3 call _l call _e call _x call space2 call _i call _o call _9 call _2 call _i call _q call space2 goto idle KeyDown bsf LED1 clrf FreqCode ;freq code 0 is MARK call ReadEeprom call SendDDS call delay500uS call delay500uS return KeyUp bcf LED1 btfsc keytype ;test for keying mode goto KeyUp1 ;1 = FSK 0 =A1A bcf LED1 movlw b'00000100' ;freq code 1 is SPACE movwf FreqCode call ReadEeprom call SendDDS call delay500uS call delay500uS KeyUp1 return ;----------------------------------------------------- ProgMode bsf LED1 movlw LOW(msg1) call DispMsg ProgMLoop movlw LOW(msg2) call DispMsg bcf LED1 call WaitData movlw "R" subwf RxChar , W btfsc STATUS , Z goto ReadBackAll movlw "r" subwf RxChar , W btfsc STATUS , Z goto ReadBackAll movlw "G" subwf RxChar , W btfsc STATUS , Z goto NormalOp ;Go to normal DDS operation movlw "g" subwf RxChar , W btfsc STATUS , Z goto GetOutProg movlw LOW(msg3) ;Intro and prompt for address call DispMsg call WaitData ;Includes echo back call DecodeHex movwf FreqCode movlw 0x03 andwf FreqCode ;Just in case movlw LOW(msg4) ;Prompt for hex data + [cr] call DispMsg clrf D0 clrf D1 clrf D2 clrf D3 call RecHexData ;Reads serial data into D3 - D0 until [cr] movlw LOW(ADDR) call DispMsg movf FreqCode , W addlw 0x30 call Send232 movlw " " call Send232 movlw " " call Send232 call SendBack movlw LOW(msg5) ;Prompt For Write / Go / Continue call DispMsg call WaitData movlw "W" subwf RxChar , W btfsc STATUS , Z goto WriteEeprom movlw "w" subwf RxChar , W btfsc STATUS , Z goto WriteEeprom goto ProgMLoop ;Any other key continue ;.............. GetOutProg movlw msg6 call DispMsg goto NormalOp ;------------------------- WriteEeprom ;save registers in EEPROM rlf FreqCode ;Multiply by 4 rlf FreqCode movlw b'00001100' andwf FreqCode ;Mask just in case movf FreqCode , W addlw 3 ;Stored this way round to make call moveadr ; readout look correct movf D0 , W call movedata call StoreEE movf FreqCode , W addlw 2 call moveadr movf D1 , W call movedata call StoreEE movf FreqCode , W addlw 1 call moveadr movf D2 , W call movedata call StoreEE movf FreqCode , W addlw 0 call moveadr movf D3 , W call movedata call StoreEE goto ProgMLoop ;------------------------- moveadr bsf STATUS, RP0 ;Page 1 movwf EEADR bcf STATUS, RP0 ;Page 0 return ;------------------------- movedata bsf STATUS, RP0 ;Page 1 movwf EEDATA bcf STATUS, RP0 ;Page 0 return ;------------------------- ReadBackAll call CrLf call CrLf movlw "0" call Send232 movlw " " call Send232 movlw 0 movwf FreqCode call ReadEeprom call SendBack call CrLf movlw "1" call Send232 movlw " " call Send232 movlw 0x04 movwf FreqCode call ReadEeprom call SendBack call CrLf movlw "2" call Send232 movlw " " call Send232 movlw 0x08 movwf FreqCode call ReadEeprom call SendBack call CrLf movlw "3" call Send232 movlw " " call Send232 movlw 0x0C movwf FreqCode call ReadEeprom call SendBack call CrLf goto ProgMLoop ;=========================================================== ReadEeprom ;read stored data and update registers movlw 3 ;Frequency addwf FreqCode ,W call GetEE movwf D0 movlw 2 addwf FreqCode ,W call GetEE movwf D1 movlw 1 addwf FreqCode ,W call GetEE movwf D2 movlw 0 addwf FreqCode ,W call GetEE movwf D3 return ;------------------------- GetEE bsf STATUS,RP0 ;ram page 1 movwf EEADR bsf EECON1 , RD movf EEDATA , W bcf STATUS , RP0 ;ram page 0 return ;----------------------- delay500uS movlw d'157' ;for 500uS movwf DelCount DelLoop nop nop nop nop ; 8 x 157 = 502 nop decfsz DelCount goto DelLoop return ;------------------------- SendDDS movf D0 , W call Write985x movf D1 , W call Write985x movf D2 , W call Write985x movf D3 , W call Write985x movf D4 , W ;Phase word call Write985x bcf PORTA , WClk bsf PORTA , FQud ;+ve edge of FQud sets 985x internal reg nop nop nop bcf PORTA , FQud bcf PORTA , FData nop return ;-------------------------- Write985x ;write 8 bits in W to 9851DDS movwf Temp movlw 8 movwf BitCount Loop985x nop bcf PORTA , WClk ;data changes with -ve edge of clock rrf Temp ;rotate through carry flag btfss STATUS , C bcf PORTA , FData btfsc STATUS , C bsf PORTA , FData nop nop bsf PORTA , WClk nop nop decfsz BitCount goto Loop985x return ;------------------------- RecHexData call WaitData movf RxChar , W sublw 0x0D btfsc STATUS , Z ;look for [cr] to terminate goto GetOutQ movf RxChar , W call DecodeHex ;generate binary equivalent movwf Temp bcf STATUS , C rlf Temp rlf Temp rlf Temp rlf Temp ; into 4 MSBs of RxChar movlw 4 movwf Counter bcf STATUS , C ;Shouldn't be necessary, but..... ShiftQLoop rlf Temp rlf D0 rlf D1 ;into 32 bit Freq register 4 bits at a time rlf D2 rlf D3 decfsz Counter ;any less than 4 chars are right justified goto ShiftQLoop ;any more, last 4 are taken goto RecHexData ;Loop until a [cr] is received GetOutQ return ;------------------------- WaitData btfss TXD ;look for start transition, low/high = 1/0 goto WaitData ; movlw d'80' ; ( may need to adjust this) movwf DelCount ; nop LoopStartBit ;this loop 5.N - 1 long = nop nop decfsz DelCount goto LoopStartBit btfss TXD ;make sure it's still high, now centre of bit goto WaitData ; movlw 8 ; movwf Counter clrf RxChar ; to here from transition = half bit ByteLoop call BitDelay nop bcf STATUS , C btfss TXD bsf STATUS , C rrf RxChar decfsz Counter goto ByteLoop ;this loop BitDelay + 8 movf RxChar , w ;Returns with stop bit+ slack period call UpCase movwf RxChar call Send232 ;Echo it back movf RxChar , W return ;received byte in RxChar and W ;------------------------- UpCase ;Converts ASCII char in W to upper case movwf Temp movlw "a" subwf Temp, W ;W = Char - "a" btfss STATUS, C ;if-ve (C=0) char < "a" so ignore goto UpCaseDone movf Temp, W sublw "z" ;W = "z" - Char btfsc STATUS, C ;if -ve (C=0) char > "z" so ignore bcf Temp, 5 ;Reset bit 5 to force upper case UpCaseDone movf Temp, W return ;----------------------- DecodeHex ;Single ASCII character to binary with error checking bsf HexFlag ;Flag for valid hex character movwf Temp ; movlw 0x30 subwf Temp ;subtract $30 and leave in Temp btfss STATUS , C ;if < $30, result -ve so C=0, error, set=0 bcf HexFlag movf Temp , W ;Test for residual from above > d54 ie > "G" sublw d'22' ;W = 22 - W, if < 22 invalid char, -ve, C=0 btfss STATUS , C ; bcf HexFlag btfss HexFlag clrf Temp ;Invalid character treat as zero movf Temp , W andlw 0x1F ;mask to 5 bits, resolves upper / lower case movwf Temp ;if 0 - 9 then Temp is correct, else 7 high movf Temp , W sublw d'9' ;W = 9 - W btfsc STATUS , C ;if -ve, C=0, char > 9, so subtract 7 goto ConvDone movlw d'7' subwf Temp ; ConvDone movf Temp , W ; andlw 0x0F ;mask out any rubbish left in return ;flag set if partly valid ;------------------------- SendHex ;Sends single nibble of data as hex char. addlw 0x30 movwf Temp sublw 0x39 btfsc STATUS , C goto CharDone movlw 7 addwf Temp CharDone movf Temp , W call Send232 return ;------------------------- Send232 ;Enter with data in W, send it to PC movwf Temp bsf RXD ;start bit call BitDelay ; movlw 8 movwf Counter nop nop SendDatLoop rrf Temp ;bit into C btfsc STATUS , C bcf RXD btfss STATUS , C bsf RXD ;could have 2us jitter depending on 1/0 call BitDelay decfsz Counter goto SendDatLoop ;loop 8 + BitDelay long bcf RXD ;stop bit call BitDelay nop nop nop nop nop nop return ;------------------------- SendBack movf D3 , W ;Transfer register contents to SD so they movwf SD ;don't get corrupted swapf SD , W ;Send High nibble first andlw 0x0F call HexToAscii call Send232 movf SD , W ;Now do the low nibble andlw 0x0F call HexToAscii call Send232 movf D2 , W movwf SD swapf SD , W andlw 0x0F call HexToAscii call Send232 movf SD , W andlw 0x0F call HexToAscii call Send232 movf D1 , W movwf SD swapf SD , W andlw 0x0F call HexToAscii call Send232 movf SD , W andlw 0x0F call HexToAscii call Send232 movf D0 , W movwf SD swapf SD , W andlw 0x0F call HexToAscii call Send232 movf SD , W andlw 0x0F call HexToAscii call Send232 return ;-------------------------- BitDelay ;Was 825us change to 412 for 2400 movlw d'200' ;412.5 = ((5/2.5) x N + 5/2.5) = 205 movwf DelCount ;baud period delay LoopBit ;decreased by 5% for testing nop nop decfsz DelCount goto LoopBit return ;-------------------------- HexToAscii addlw 0x30 movwf Temp sublw 0x39 btfsc STATUS , C goto AsciiDone movlw 7 addwf Temp AsciiDone movf Temp , W return ;-------------------------- StoreEE ;writes the data byte in Data reg to EEprom EEADR bsf STATUS, RP0 ;must be in bank 1 bsf EECON1 , WREN ;Enable EEprom writing bcf INTCON, GIE ;disable interrupts movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1 , WR bsf INTCON, GIE ;Re enable interrupts bcf STATUS, RP0 ; EEwaitW btfss PIR1 , EEIF ;set when write is complete goto EEwaitW bcf PIR1 , EEIF ;has to be cleared manually bsf STATUS, RP0 ; bcf EECON1 , WR bcf STATUS , RP0 ;back to bank 0 return ;------------------------- CrLf movlw 0x0D call Send232 movlw 0x0A call Send232 return ;------------------------- ;Generating a message from data stored in programme memory ; Uses AddrHold, MsgCount org 0x300 ;Ensure this code and MsgTable are in the same segment DispMsg ;Enter with address of Text in W eg. 'MOVLW LOW(TextLabel)' movwf AddrHold ;Store offset of text string movlw high(MsgTable) movwf PCLATH movlw low(MsgTable) addlw 1 subwf AddrHold , W ;W = AddrTextString - TableStart - 1 ; = Offset of string start in table MsgLoop movwf MsgCount call MsgTable andlw 0xFF ;end of message btfsc STATUS , Z goto MsgDone call Send232 movf MsgCount, W addlw 1 goto MsgLoop MsgDone return ;......... MsgTable addwf PCL msg1 dt 0x0D,0x0A,"G4JNT Four Frequency controller for AD9851 DDS " , 0 msg2 dt 0x0D,0x0A,"[R]ead EE data / [G]o to DDS / Any other key to change EE. " , 0 msg3 dt 0x0D,0x0A,"Enter Address 0 to 3 " , 0 msg4 dt 0x0D,0x0A,"Enter 4 bytes of Hex Data + [cr] " , 0 msg5 dt 0x0D,0x0A,"[W]rite / [A]bort " , 0 msg6 dt 0x0D,0x0A,"DDS Operating",0x0D,0x0A,0 ADDR dt 0x0D,0x0A,"ADDR. ",0 MsgTableEnd if ((DispMsg & 0xFF) >= (MsgTableEnd & 0xFF)) ERROR "Table code crosses page boundary" ERROR "ADJUST START OF TABLE" endif ;............................... dit call KeyDown ; call wait1u call KeyUp call wait1u return dah call KeyDown call wait1u ;dash is 3 elements long call wait1u Call wait1u call KeyUp call wait1u return space2 call wait1u call wait1u return wait1u movlw EEelle ; call GetEE movwf deltemp goto wait1 wait movlw Pause ;long wait between ident call GetEE movwf deltemp wait1 call delay20mS decfsz deltemp goto wait1 return delay20mS movlw d'20' movwf len delay1mS call delay500uS call delay500uS decfsz len goto delay1mS return ;********************* _a call dit ;send A call dah goto space2 _b call dah ;send B call dit call dit call dit goto space2 _c call dah ;send C call dit call dah call dit goto space2 _d call dah ;send D call dit call dit goto space2 _e call dit ;send E goto space2 _f call dit ;send F call dit call dah call dit goto space2 _g call dah ;send G call dah call dit goto space2 _h call dit ;send H call dit call dit call dit goto space2 _i call dit ;send I call dit goto space2 _j call dit call dah ;send J call dah call dah goto space2 _k call dah ;send K call dit call dah goto space2 _l call dit ;send L call dah call dit call dit goto space2 _m call dah call dah goto space2 _n call dah ;send N call dit goto space2 _o call dah ;send O call dah call dah goto space2 _p call dit ;send P call dah call dah call dit goto space2 _q call dah ;send Q call dah call dit call dah goto space2 _r call dit ;send R call dah call dit goto space2 _s call dit ;send S call dit call dit goto space2 _t call dah ;send T goto space2 _u call dit ;send U call dit call dah goto space2 _v call dit ;send V call dit call dit call dah goto space2 _w call dit ;send W call dah call dah goto space2 _x call dah ;send X call dit call dit call dah goto space2 _y call dah ;send Y call dit call dah call dah call space2 _z call dah ;send Z call dah call dit call dit goto space2 _1 call dit ;send 1 call dah call dah call dah call dah goto space2 _2 call dit ;send 2 call dit call dah call dah call dah goto space2 _3 call dit ;send 3 call dit call dit call dah call dah goto space2 _4 call dit ;send 4 call dit call dit call dit call dah goto space2 _5 call dit ;send 5 call dit call dit call dit call dit call space2 _6 call dah ;send 6 call dit call dit call dit call dit goto space2 _7 call dah ;send 7 call dah call dit call dit call dit goto space2 _8 call dah ;send 8 call dah call dah call dit call dit goto space2 _9 call dah ;send 9 call dah call dah call dah call dit goto space2 _0 call dah ;send 0 call dah call dah call dah call dah goto space2 slash call dah ;send / call dit call dit call dah call dit goto space2 return ;------------------------------- cblock 0x20 BitCount DelCount DelCount2 Temp D0 D1 D2 D3 D4 Counter FreqCode ;Added to EEprom address for freq value RxChar SD Flags AddrHold ;Used in message display MsgCount ; ditto len len1 ellen deltemp Endel ;enable delay keymode ;0 = F1A 1= A1A endc end