;NEWHFBCN.ASM G4JNT May 2006 ; LIST P=16F628 INCLUDE "P16F628.INC" __config 0x3F63 ;LV Programming off , OSC EC Mode #define MR PORTA, 0 #define SCLK PORTA, 1 #define IOUD PORTA, 2 #define SDIO PORTA, 3 #define IORST PORTA, 4 #define PPS PORTB, 0 #define SERIN PORTB, 1 #define SEROUT PORTB, 2 #define LCKEN PORTB, 3 #define LEDGrn PORTB, 4 #define LEDRed PORTB, 5 #define TXENABLE PORTB, 6 #define TESTLINK PORTB, 7 #define FigFlag Flags, 0 #define TestModeFlag Flags, 1 #define GPSOk Flags, 2 #define UseEnv Flags, 3 #define CurrData Flags, 4 #define Idle31 Flags, 5 NMEAPol = 0 ;RS232 levels CONTROLPLL = 0x04 ;Part of Control reg for PLL CWSPEED = d'50' ;CW Dot length, ms RPTTime = d'15' ;Repeat Interval SeqOffset = 1 ;Minutes after reference time errorlevel 1, -207 ;Suppress msgs. and warnings about labels after col 1. org 0 nop movlw b'00000000' ;No interupts until passed thro here once movwf INTCON ; goto startup ;jump to main code ;------------------ Interrupt routine, get here 4 cycles after TMR overflow -- movwf Wreg ;Save W swapf STATUS , W ; nb. movwf does not affect any STATUS bits movwf SaveSts ;Stave STATUS, without affecting it btfss INTCON, T0IF goto OtherInt ;Get to here 9 cycles after timer overflow ;Update the DDS with previous amplitude bcf INTCON , T0IF ;Timing based on 2.5MHz/16, timer counts bsf IOUD ; 237 to 256 for count of 19 nop ;Pad out to total of 16 clocks, for an nop ; extra divider's worth of counting bcf IOUD ; for a total of 20 counts movlw d'237' movwf TMR0 ;Timer restarts counting 2 cycles after here ;------ Below here is not time critical but must be less than 300 cycles ;Here every 7812.5Hz (for 10MHz xtal) incf IntCounter movlw d'249' subwf IntCounter , W btfss STATUS, Z goto NotBoundary clrf IntCounter ; ~~~~~~~~~~~~~~~~~ Data boundary ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; First toggle the phase if UseEnv flag is set, as we're now at ; the zero amplitude point of the last bit bsf LEDRed ;Flash red led at symbol rate btfsc UseEnv ;UseEnv was set during previous bit and call TogglePhase ; has by now reduced the amplitude to zero ; Now get the NEXT data bit into CurrData flag movf VCodeLen ;Test to see if a new character is needed btfss STATUS, Z goto ContVariCode ;Test for startup run-in btfss CharCount , 7 goto NotRunIn movlw 8 ;Idle with multiples of 8 symbols movwf VCodeLen clrf VCHi ;All zeros gives the idling condition clrf VCLo incf CharCount ;Have to do this separately here as we goto ContVariCode ; miss the increment below ;............... ; Load new character NotRunIn movlw LOW(MsgData) ;Lookup next character in message addwf CharCount, W call GetEE iorlw 0 btfss STATUS, Z ;Test for End of message (null terminator) goto ContMsg bcf INTCON, T0IE ;Disable the interrupt to complete message ContMsg call Varicode ;Update VCHi/Lo & VCodeLen incf CharCount ContVariCode rlf VCLo rlf VCHi bcf CurrData btfsc STATUS, C bsf CurrData ;Save data bit decf VCodeLen goto OutInterrupt ;..................... NotBoundary ;Set amplitude value movlw d'125' ;Test for mid point, and set UseEnv flag subwf IntCounter , W ; depending on latest data in CurrData btfss STATUS, Z goto NotMidPoint bcf UseEnv ;UseEnv set if data is 0, ie phase changes btfss CurrData ;Phase will change at next boundary if bsf UseEnv ; CurrData = 0, so start ampl change now. bcf LEDRed ;Flashes at symbol rate with 50% duty cycle NotMidPoint movf IntCounter, W btfss UseEnv movlw d'125' call SetPSKAmpl ;If UseEnv =0, amplitude forced to max by ; calling with dummy mid point value goto OutInterrupt ;............... OtherInt OutInterrupt swapf SaveSts , W ;Restore STATUS movwf STATUS swapf Wreg ;Restore W swapf Wreg , W ;Can't use movf as it affects Z bit retfie ;===================================== startup clrf PORTA ;Special setup to disable comparator on 'F628 movlw 7 movwf CMCON bsf STATUS,RP0 ;ram page 1 movlw b'00000011' ;Internal input, Prescalar /16 pull-ups movwf OPTION_REG movlw b'00000000' ; movwf PORTA ; movlw b'10000011' ;B0 PPS, B1 SerIn, B2 SerOut B3 Lock enable movwf PORTB ;B6 ext key output, B7 test mode input bcf STATUS,RP0 ;ram page 0 clrf PORTB clrf PORTA clrf TMR0 clrf IntCounter clrf VCodeLen ;Ensures first character is looked up at start clrf Flags bsf LEDRed call SetUpDDS bcf LEDRed movlw b'10000000' ;Enable global int, not timer overflow int yet movwf INTCON MainLoop btfss TESTLINK goto TestMode call GetGPSData ;Sets Minutes, Seconds and RxStatus movlw RPTTime - 1 ;need to test for the minute BEFORE wanted one subwf Minutes, W btfss STATUS, Z goto MainLoop movlw d'59' ;Second immediately before start time subwf Seconds, W btfss STATUS, Z goto MainLoop ;Now in the second immediately preceeding the wanted interval movlw 0 ;Activate the Tx control, to allow slow call OnOff ; turn on PAs, but put RF to zero bsf TXENABLE ; bcf LEDGrn bsf LEDRed call WaitPPS ;Start CW mesage immediately the movlw LOW(CWMsgData) ; correct interval starts movwf CWMsgCnt call SendCWMsg movlw 1 call OnOff ;Continue with carrier up to the 7 second mark WaitSteps call GetGPSData ;Test for the second BEFORE ; the wanted interval, followed by PPS movlw d'6' ;No need to wait for PPS now subwf Seconds, W ;If <7 seconds, continue looking btfss STATUS, C ;W = Seconds - 6, if -ve, C=0, stay looping goto WaitSteps ; Getting the Seconds value from GPS data can be messey during step sequence ; so we maintain the count manually until end of power steps StepLoop call WaitPPS incf Seconds ;Now keeping the Seconds count manually, and ; incrementing it POST PPS, so use proper value movlw d'7' ; for testing step reference times subwf Seconds, W ;T = 7s, First set of power steps btfsc STATUS, Z goto RefreshPowerSteps movlw d'16' ;T = 16s, Second set of power steps subwf Seconds, W btfsc STATUS, Z goto RefreshPowerSteps movlw d'25' ;T = 25s, period of full carrier subwf Seconds, W btfsc STATUS, C ;W = T - 25, if -ve, C=0, carry on steps goto OutSteps goto NextStep ;Default for T>6 and T <> 15 and T<24 ;...................... RefreshPowerSteps movlw 0x0F movwf StepAmplHi movlw 0xFF movwf StepAmplLo NextStep clrf D0 clrf D1 movlw 8 movwf DDSAddr call DataTo9852 bsf IOUD nop nop bcf IOUD bcf LEDGrn bcf LEDRed movlw d'100' ;100ms break before each power step movwf DelCount2 StepDelLoop call Delay1ms decfsz DelCount2 goto StepDelLoop bsf LEDRed movf StepAmplHi, W movwf D1 movf StepAmplLo, W movwf D0 movlw 8 movwf DDSAddr call DataTo9852 bsf IOUD nop nop bcf IOUD bcf STATUS, C ;6dB amplitude drop ready for next step rrf StepAmplHi rrf StepAmplLo goto StepLoop ;....................... OutSteps movlw 1 call OnOff ;Red led stays on WaitFor30Loop ;Resume using GPS data to derive Seconds count call GetGPSData movlw d'29' ;Wait for the 30 second interval subwf Seconds, W ; btfss STATUS, Z ; goto WaitFor30Loop call WaitPPS bcf LEDGrn clrf TMR0 ;Prepare PSK31 registers clrf IntCounter clrf VCodeLen ;Ensures first character is looked up at start movlw d'256'-d'4' ;Prime with a negative value to give some movwf CharCount ; run-in idling at start of transmission bsf INTCON, T0IE ;Start the PSK31 sequence going WaitForPSKEnd btfsc INTCON, T0IE ;This is reset from inside the interrupt goto WaitForPSKEnd ; routine when message completes movlw 1 ;Period of carrier to complete the minute call OnOff ; bsf LEDRed ;Flashes in antiphase during GetGPSData WaitForCompletion call GetGPSData movlw d'59' ;Wait for the end of the minute subwf Seconds, W ; btfss STATUS, Z ; goto WaitForCompletion call WaitPPS bcf TXENABLE ;Leave running at full amplitude, but turn off Tx bcf LEDRed goto MainLoop ;............................. TestMode ;TESTLINK Input grounded movlw 1 call OnOff bsf LEDRed bcf LEDGrn bsf TXENABLE TestModeLoop btfss TESTLINK goto TestModeLoop bcf LEDRed bcf TXENABLE goto MainLoop ;=========================================== WaitPPS ;In case PPS is still high btfsc PPS ; look for a low to high transition goto WaitPPS WaitRefPPS ;Now wait for the rising edge itself btfss PPS goto WaitRefPPS return ;---------------------- GetEE ;different from ;F84 EE registers all in bank 1 now bsf STATUS,RP0 ;ram page 1 movwf EEADR bsf EECON1 , RD movf EEDATA , W bcf STATUS , RP0 ;ram page 0 return ;----------------------- SetUpDDS bsf MR movlw d'10' movwf DelCount2 call LongDelay bcf MR call LongDelay ;Allow things to settle movlw 7 ;Control register movwf DDSAddr movlw 0x10 movwf D3 movlw CONTROLPLL ;PLL factor & range bit held in ...E2.INC movwf D2 movlw 0x00 ;LSB of this is external update movwf D1 movlw 0x60 ;OSK Enabled, bypass InV Sinc. movwf D0 call DataTo9852 movlw 2 movwf DDSAddr movlw LOW(FreqData) + 5 ;Set CW carrier frequency call GetEE movwf D0 movlw LOW(FreqData) + 4 call GetEE movwf D1 movlw LOW(FreqData) + 3 call GetEE movwf D2 movlw LOW(FreqData) + 2 call GetEE movwf D3 movlw LOW(FreqData) + 1 call GetEE movwf D4 movlw LOW(FreqData) call GetEE movwf D5 call DataTo9852 bsf IOUD nop nop bcf IOUD movlw 8 ;Turn amplitude full on immediately movwf DDSAddr movlw 0xFF movwf D0 movlw 0x0F movwf D1 call DataTo9852 bsf IOUD nop nop bcf IOUD return ;-------------------------- OnOff iorlw 0 ;W = 0 output off, W = 1, Output level = max btfsc STATUS, Z ;Each amplitude update takes approx 320 clocks goto RampOff ; == 130us. So 8 of these = 1ms movlw 0xFF movwf D0 movlw 0 movwf Amplitude movlw d'16' movwf SoftCount ;Initialise with 0x1FF SoftOnLoop movf Amplitude, W movwf D1 ;Eight passes though here ramp the values: movlw 8 ;0x0FF, 0x1FF, 0x2FF...0xFFF movwf DDSAddr call DataTo9852 bsf IOUD nop nop bcf IOUD movlw 1 addwf Amplitude ;Increment ready for next pass through decfsz SoftCount goto SoftOnLoop return ;............ RampOff movlw 0 movwf D0 ;Initialise with 0xF00 movlw 0x0F movwf Amplitude ;Ramp value 0xF00, 0xE00, 0xD00...0x000 movlw d'16' movwf SoftCount SoftOffLoop movf Amplitude, W movwf D1 movlw 8 movwf DDSAddr call DataTo9852 bsf IOUD nop nop bcf IOUD movlw 1 subwf Amplitude ; ready for next pass through decfsz SoftCount goto SoftOffLoop return ;-------------------------- TogglePhase clrf DDSAddr ;Phase is address 0 call Send9852Byte movlw b'00100000' xorwf Phase ;Toggle MSB movf Phase, W call Send9852Byte movlw 0 call Send9852Byte ;IOUD updated next interrupt return ;-------------------------- Send9852Byte ;86 clocks incl call and return movwf Temp movlw 8 movwf Counter DDSSendLoop rlf Temp btfsc STATUS, C bsf SDIO btfss STATUS, C bcf SDIO bsf SCLK bcf SCLK decfsz Counter goto DDSSendLoop return ;------------------------- LongDelay ;Approx 1 second delay movlw d'250' movwf DelCount2 LongDelLoop call Delay1ms call Delay1ms call Delay1ms call Delay1ms decfsz DelCount2 goto LongDelLoop return ;------------------------- Delay1ms ;5N+5 = 1250 clocks, * 2 = 2500 clocks = 1ms movlw d'249' movwf DelCount Del1msLoop nop nop decfsz DelCount goto Del1msLoop movlw d'249' movwf DelCount Del1ms2Loop nop nop decfsz DelCount goto Del1ms2Loop nop nop nop nop return ;------------------------- GetGPSData ;Monitors SERIN line for @@Ea incf SerCounter bsf LEDGrn ;Flash Green LED Until header is received btfss GPSOk bcf LEDGrn ;Flash in antiphase if GPS is not locked up call PushStack call GetByte movwf Stack0 ;String starts @@Eamdyyhms ;Stack position - A9876543210 movf StackA , W sublw "@" btfss STATUS , Z goto GetGPSData movf Stack9 , W sublw "@" btfss STATUS , Z goto GetGPSData movf Stack8 , W sublw "E" btfss STATUS , Z goto GetGPSData movf Stack7 , W sublw "a" btfss STATUS , Z goto GetGPSData ;Having reached here means correct data message ; has started and HMS data is stored in stack call DoTime ;Extract time from stack and update counters bcf LEDGrn ;Green off means time data has been decoded btfss GPSOk bsf LEDGrn ;Flash in antiphase if GPS is not locked up GetGPSStatus ;Now read in rest of stack data until [cr][lf] incf SerCounter ; at the end. BUT, these may occur as part of call PushStack ; binary data, so only test after 74 chars call GetByte ; have been received (should be 76, but...) movwf Stack0 movlw d'74' subwf SerCounter, W btfss STATUS, C ;W = SerCounter - W, if +Ve (C=1) count is ready goto GetGPSStatus ; to test for [cr][lf] movf Stack0, W sublw 0x0A ;Stack ends with ...msdsC[cr][lf] btfss STATUS , Z ; 65432 1 0 goto GetGPSStatus ;At some future point, could validate movf Stack1, W ; with a checksum calculation. sublw 0x0D btfss STATUS , Z goto GetGPSStatus ;Reached here means terminating [cr][lf] is in movf Stack3, W ; the right place, so extract status info movwf RxStatus bcf GPSOk movlw b'00001011' ;Mask the GPS status data to give just the andwf RxStatus, W ; bits that show no proper fix then, only btfsc STATUS, Z ; if these are all zero, set GPSOk Flag bsf GPSOk ; WAS b'01001011', now ignores poor geometry flag clrf SerCounter ;Ready for next time return ;-------------------------------------- DoTime ;Extract MMSS from ser data, generate interval value movf Stack1, W ; movwf Minutes movlw SeqOffset ; 0 - RptTime-1, starting at sequence ref point. subwf Minutes, W ;W = Minutes - SeqOffset btfss STATUS, C ;If result -ve (C=0), add 60 to normalise addlw d'60' movwf Minutes ;MinCount = (Minutes - SeqOffset) MOD 60 MinModLoop ;Repeatedly subtract RPTTime until result is -ve movlw RPTTime ; subwf Minutes, W ;W = Minutes - RPTime, if -ve(C=0), MOD is done btfss STATUS, C goto ModDone1 movwf Minutes ; otherwise save back and continue goto MinModLoop ;.................. ModDone1 movf Stack0, W movwf Seconds DoneTime ;Seconds contains 0 - 59 ;Minutes contains 0 - [RPTTime -1] return ;-------------------------------------- GetByte if NMEAPol == 1 ; 1 = RS232 levels (0/-ve = Idle btfss SERIN ; 0 = Logic levels (1 = Idle) else btfsc SERIN endif goto GetByte ;Loop waiting for start bit call HalfBitDelay ;Centre of start bit if NMEAPol == 1 btfss SERIN else btfsc SERIN ;Check it's still low endif goto GetByte movlw 8 movwf Counter clrf Temp ;probably not needed, but good practice InitByteLoop call HalfBitDelay call HalfBitDelay ; nop bcf STATUS , C ;start in known state if NMEAPol == 1 btfss SERIN else btfsc SERIN endif bsf STATUS , C ;Data into Carry rrf Temp ;and then into Temp, LSB first decfsz Counter goto InitByteLoop ;loop is 8 + 2 * HalfBitDelay long call HalfBitDelay ;#### Don't really need to wait for stop bit! #### ; Now have approx 50us of stop bit left movf Temp , W ;to use this data return ;Exit with received byte in W and Temp ;----------------------------------------- SendByte movwf Temp if NMEAPol == 1 bsf SEROUT else bcf SEROUT ;start bit endif call HalfBitDelay ; call HalfBitDelay movlw 8 movwf Counter SendDatLoop rrf Temp ;bit into C if NMEAPol == 1 btfsc STATUS , C bcf SEROUT btfss STATUS , C bsf SEROUT ;could have 2us jitter depending on 1/0 else btfsc STATUS , C bsf SEROUT btfss STATUS , C bcf SEROUT ;could have 2us jitter depending on 1/0 endif call HalfBitDelay call HalfBitDelay decfsz Counter goto SendDatLoop ;loop 8 + BitDelay long if NMEAPol == 1 bcf SEROUT else bsf SEROUT endif call HalfBitDelay call HalfBitDelay ;Two stop bits call HalfBitDelay call HalfBitDelay return ;----------------------------------------- HalfBitDelay ;9600 baud needs 104us, so delay 126 clocks here movlw d'24' ; for a total of 126 * 2 + 8 = 260 clocks = 104us movwf DelCount BaudDelLoop nop nop decfsz DelCount goto BaudDelLoop nop return ;------------------------------- PushStack movf StackE , W movwf StackF movf StackD , W movwf StackE movf StackC , W movwf StackD movf StackB , W movwf StackC movf StackA , W movwf StackB movf Stack9 , W movwf StackA movf Stack8 , W movwf Stack9 movf Stack7 , W movwf Stack8 movf Stack6 , W movwf Stack7 movf Stack5 , W movwf Stack6 movf Stack4 , W movwf Stack5 movf Stack3 , W movwf Stack4 movf Stack2 , W movwf Stack3 movf Stack1 , W movwf Stack2 movf Stack0 , W movwf Stack1 return ;------------------------------- ;---------------------- SendCWMsg ;Enter with EE address programmed into CWMsgCnt movf CWMsgCnt, W call GetEE ;Test for terminator at start = no CW message addlw 0 btfsc STATUS, Z return movlw 0 ;Lead in gap makes initial CW clearer call OnOff call CWDelay call CWDelay call CWDelay call CWDelay CWLoop movf CWMsgCnt, W call GetEE addlw 0 btfsc STATUS, Z goto DoneCWMsg call SendCWChar incf CWMsgCnt goto CWLoop DoneCWMsg call CWDelay call CWDelay call CWDelay call CWDelay return ;-------------------------- SendCWChar ;Sends a single CW character addlw 0xE0 ;Subtract 32 (add 256 - 32) to point to table call CWTable movwf CWChar ;Doesn't affect STATUS so... movf CWChar ; check for invalid returned code here btfsc STATUS , Z goto NoChar movlw 0x07 andwf CWChar , W ;Extract element count into W movwf CWCharCnt movlw 6 subwf CWCharCnt , W ;W = Elcount - 6. If +ve/0 then C=1, > 5 els btfss STATUS , C goto Send5 rrf CWCharCnt ;Puts LSB into C as 110 = . 111 = - call SendEle ;First . or - for 6 element characters movlw 5 movwf CWCharCnt ;Force count to 5 for rest of the elements Send5 rlf CWChar ;Element to be sent into C. call SendEle ; count already in Counter decfsz CWCharCnt goto Send5 NoChar ;Inter word gap, and invalid codes. bcf LEDRed call CWDelay call CWDelay return ;------------------- SendEle ;Data in STATUS , C; 0 = dit 1 = dah rrf Stack0 ;Save C bit temporarily on stack movlw 1 call OnOff bsf LEDRed rlf Stack0 ;Recovery C bit again, to get dot/dash btfss STATUS , C ;test for dot or dash goto SendDot call CWDelay call CWDelay SendDot call CWDelay movlw 0 call OnOff bcf LEDRed call CWDelay ;Inter element gap return ;------------------- CWDelay movlw CWSPEED movwf DelCount2 CWDelLoop call Delay1ms decfsz DelCount2 goto CWDelLoop return ;-------------------------- SetPSKAmpl ;Sets output amplitude according to value in W call GetPSKAmpl movwf D1 ;Not using D registers for DDS, so use D1 ; as temporary holding register movlw 8 ;Address 8 is amplitude call Send9852Byte ;Load data, updated next interrupt swapf D1, W ;12 bits of amplitude in 9825 andlw 0x0F ;MS Nibble into LS Nibble of High ampl reg. call Send9852Byte swapf D1, W ;LS Nibble into MS Nibble of Low ampl reg. andlw 0xF0 call Send9852Byte return ;------------------------------- Varicode ;Enter with ASCII Char, exit with bits in VCodeHi/Lo movwf VCLo ;VCLo used as temporary storage bcf STATUS, C rlf VCLo, W ;Multiply by 2 to point at high data byte call VCodeTable ;Extract bit pattern movwf VCHi bcf STATUS, C rlf VCLo, W ;Recover Ascii, * 2 + 1 to point at low data byte addlw 1 call VCodeTable movwf VCLo ;LS Nibble contain code length andlw 0x0F movwf VCodeLen incf VCodeLen ;Final two code positions are zero for terminator incf VCodeLen movlw 0xF0 ;VCHi/Lo contains left justified varicode bit andwf VCLo ; pattern, with its length in VCodeLen return ;--------------------- org 0x5FB ;Positioned to place table at 0x600 exactly VCodeTable movwf Temp movlw HIGH(VCodeData) movwf PCLATH ;Enter with ASCII * 2 for High bits movf Temp, W ; and ASCII * 2 + 1 for Low bits + length addwf PCL VCodeData dt 0xAA,0xCA,0xB6,0xCA,0xBB,0x4A,0xDD,0xCA ; 0 - 3 dt 0xBA,0xCA,0xD7,0xCA,0xBB,0xCA,0xBF,0x4A ; 4 - 7 dt 0xBF,0xCA,0xEF,0x08,0xE8,0x05,0xDB,0xCA ; 8 - 11 dt 0xB7,0x4A,0xF8,0x05,0xDD,0x4A,0xEA,0xCA ; 12 - 15 dt 0xBD,0xCA,0xBD,0x4A,0xEB,0x4A,0xEB,0xCA ; 16 - 19 dt 0xD6,0xCA,0xDA,0xCA,0xDB,0x4A,0xD5,0xCA ; 20 - 23 dt 0xDE,0xCA,0xDF,0x4A,0xED,0xCA,0xD5,0x4A ; 24 - 27 dt 0xD7,0x4A,0xEE,0xCA,0xBE,0xCA,0xDF,0xCA ; 28 - 31 dt 0x80,0x01,0xFF,0x89,0xAF,0x89,0xFA,0x89 ; 32 - 35[sp]- # dt 0xED,0x89,0xB5,0x4A,0xAE,0xCA,0xBF,0x89 ; 36 - 39 $ - ' dt 0xFB,0x08,0xF7,0x08,0xB7,0x89,0xEF,0x89 ; 40 - 43 ( - + dt 0xEA,0x07,0xD4,0x06,0xAE,0x07,0xD7,0x89 ; 44 - 47 , - / dt 0xB7,0x08,0xBD,0x08,0xED,0x08,0xFF,0x08 ; 48 - 51 0 - 3 dt 0xBB,0x89,0xAD,0x89,0xB5,0x89,0xD6,0x89 ; 52 - 55 4 - 7 dt 0xD5,0x89,0xDB,0x89,0xF5,0x08,0xDE,0x89 ; 56 - 59 8 - ; dt 0xF6,0x89,0xAA,0x07,0xEB,0x89,0xAB,0xCA ; 60 - 63 < - ? dt 0xAF,0x4A,0xFA,0x07,0xEB,0x08,0xAD,0x08 ; 64 - 67 @ - C dt 0xB5,0x08,0xEE,0x07,0xDB,0x08,0xFD,0x08 ; 68 - 71 D - G dt 0xAA,0x89,0xFE,0x07,0xFE,0x89,0xBE,0x89 ; 72 - 75 H - K dt 0xD7,0x08,0xBB,0x08,0xDD,0x08,0xAB,0x08 ; 76 - 79 L - O dt 0xD5,0x08,0xEE,0x89,0xAF,0x08,0xDE,0x07 ; 80 - 83 P - S dt 0xDA,0x07,0xAB,0x89,0xDA,0x89,0xAE,0x89 ; 84 - 87 T - W dt 0xBA,0x89,0xBD,0x89,0xAB,0x4A,0xFB,0x89 ; 88 - 91 X - [ dt 0xF7,0x89,0xFD,0x89,0xAF,0xCA,0xB6,0x89 ; 92 - 95 \ - _ dt 0xB7,0xCA,0xB0,0x04,0xBE,0x07,0xBC,0x06 ; 96 - 99 ` - c dt 0xB4,0x06,0xC0,0x02,0xF4,0x06,0xB6,0x07 ; 100 - 103 d - g dt 0xAC,0x06,0xD0,0x04,0xF5,0x89,0xBF,0x08 ; 104 - 107 h - k dt 0xD8,0x05,0xEC,0x06,0xF0,0x04,0xE0,0x03 ; 108 - 111 l - o dt 0xFC,0x06,0xDF,0x89,0xA8,0x05,0xB8,0x05 ; 112 - 115 p - s dt 0xA0,0x03,0xDC,0x06,0xF6,0x07,0xD6,0x07 ; 116 - 119 t - w dt 0xDF,0x08,0xBA,0x07,0xEA,0x89,0xAD,0xCA ; 120 - 123 x - { dt 0xDD,0x89,0xAD,0x4A,0xB5,0xCA,0xED,0x4A ; 124 - 127 | -  ;--------------------------- org 0x700 ;Put all routines with tables into last pages ;------------------------- ;--------------------------------------- GetRegLen ;gets number of bytes needed for value in DDSAddr movlw HIGH($) movwf PCLATH movf DDSAddr, W addwf PCL dt 2,2,6,6,6,4,3,4,2,2,1,2 ;Number of bytes in each register ;------------------------- GetPSKAmpl movwf Temp sublw d'125' ;W = 125 - W btfsc STATUS, C ;If W<= 125, +ve, C=1 goto LowCycle ;Count in the range 0 - 125, look up directly movf Temp, W ;Else W = 250 - W, to map back onto 125 - 1 sublw d'250' movwf Temp LowCycle movlw HIGH($) movwf PCLATH movf Temp , W addwf PCL ; 125 Point First quadrant Sine Table dt 0x00,0x03,0x06,0x0A,0x0D,0x10,0x13,0x16,0x1A,0x1D,0x20,0x23 ;0 - 11 dt 0x26,0x29,0x2D,0x30,0x33,0x36,0x39,0x3C,0x3F,0x43,0x46,0x49 ;12 - 23 dt 0x4C,0x4F,0x52,0x55,0x58,0x5B,0x5E,0x61,0x64,0x67,0x6A,0x6D dt 0x6F,0x72,0x75,0x78,0x7B,0x7E,0x80,0x83,0x86,0x89,0x8B,0x8E ; dt 0x91,0x93,0x96,0x98,0x9B,0x9E,0xA0,0xA3,0xA5,0xA7,0xAA,0xAC ;48 - 59 dt 0xAF,0xB1,0xB3,0xB5,0xB8,0xBA,0xBC,0xBE,0xC0,0xC2,0xC4,0xC7 dt 0xC9,0xCA,0xCC,0xCE,0xD0,0xD2,0xD4,0xD6,0xD7,0xD9,0xDB,0xDC dt 0xDE,0xDF,0xE1,0xE2,0xE4,0xE5,0xE7,0xE8,0xE9,0xEB,0xEC,0xED ;84 dt 0xEE,0xEF,0xF0,0xF2,0xF3,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9 dt 0xF9,0xFA,0xFA,0xFB,0xFC,0xFC,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE ;108 - 119 dt 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF ;120 - 125 ;----------------- DataTo9852 ;Send contents of Dn...D0 to 9852 movf DDSAddr, W call Send9852Byte ;Send the address data call GetRegLen ;Returns with number of bytes to be sent movwf Temp bcf STATUS, C rlf Temp, W sublw d'12' ;W = 12 - 2 * (No of bytes to be sent) addwf PCL ;Jump into byte sending at the right place movf D5, W call Send9852Byte movf D4, W call Send9852Byte movf D3, W call Send9852Byte movf D2, W call Send9852Byte movf D1, W call Send9852Byte movf D0, W call Send9852Byte bcf SDIO ;Rest in low state for min. current consumption return ;------------------------- CWTable ;CW Characters in compressed form. movwf Temp movlw HIGH($) movwf PCLATH movf Temp , W addwf PCL retlw b'00000000' ; [sp] 00 retlw b'00000000' ; ! 00 retlw b'10010110' ; " 96 retlw b'00010101' ; # 15 retlw b'00000000' ; $ 00 retlw b'00000000' ; % 00 retlw b'00000000' ; & 00 retlw b'11110110' ; ' F6 retlw b'10110101' ; ( B5 retlw b'01101111' ; ) 6F retlw b'01000101' ; * 45 retlw b'00000000' ; + 00 retlw b'10011111' ; , 9F Coding for CW characters of up to retlw b'00001111' ; - 0F 6 elements. Stored as : retlw b'10101110' ; . AE Bits 7 to 3 make first five CW elements retlw b'10010101' ; / 95 Reading Left to Right retlw b'11111101' ; 0 FD Coded as 0 = dit 1 = dah retlw b'01111101' ; 1 7D Bts 2-0 are number of elements except for retlw b'00111101' ; 2 3D 110 > 1st element is a dit retlw b'00011101' ; 3 1D 111 > 1st element is a dah retlw b'00001101' ; 4 0D retlw b'00000101' ; 5 05 retlw b'10000101' ; 6 85 retlw b'11000101' ; 7 C5 retlw b'11100101' ; 8 E5 retlw b'11110101' ; 9 F5 retlw b'00000000' ; : 00 retlw b'00000000' ; ; 00 retlw b'00000000' ; < 00 retlw b'10001101' ; = 8D retlw b'00000000' ; > 00 retlw b'01100110' ; ? 66 retlw b'11010110' ; @ D6 retlw b'01000010' ; A 42 retlw b'10000100' ; B 84 retlw b'10100100' ; C A4 retlw b'10000011' ; D 83 retlw b'00000001' ; E 01 retlw b'00100100' ; F 24 retlw b'11000011' ; G C3 retlw b'00000100' ; H 04 retlw b'00000010' ; I 02 retlw b'01110100' ; J 74 retlw b'10100011' ; K A3 retlw b'01000100' ; L 44 retlw b'11000010' ; M C2 retlw b'10000010' ; N 82 retlw b'11100011' ; O E3 retlw b'01100100' ; P 64 retlw b'11010100' ; Q D4 retlw b'01000011' ; R 43 retlw b'00000011' ; S 03 retlw b'10000001' ; T 81 retlw b'00100011' ; U 23 retlw b'00010100' ; V 14 retlw b'01100011' ; W 63 retlw b'10010100' ; X 94 retlw b'10110100' ; Y B4 retlw b'11000100' ; Z C4 ;================================ org 0x2100 FreqData de 0x09,0xA6,0x33,0xFC,0x9D,0x67 MsgData de 0x0D,0x0A,"G4JNT G4JNT, Loc. IO90IV " de "Direct DDS generated PSK31 test beacon 1960kHz.",0 CWMsgData de "G4JNT/BCN",0 ;-------------------------------- cblock 0x20 Temp DelCount DelCount2 IntCountLo IntCountHi Counter IntCounter ;counts 0 to 249 at 7812.5Hz rate CharCount SoftCount ;Used in amplitude ramping Amplitude StepAmplHi ;Used in power steps StepAmplLo DDSAddr Flags Wreg SaveSts Seconds Minutes ICount CommaCount CWChar CWMsgCnt CWCharCnt TonePtr SerCounter ;Count of characters on GPS serial data RxStatus ;GPS Receiver status Phase ;Holds instantaneous phase value for AD9852 VCHi ;Varicode symbols VCLo VCodeLen D0 ;D data sent to DDS registers D1 D2 D3 D4 D5 A0 ;Ax and Bx inputs to maths routines A1 A2 A3 A4 A5 B0 B1 B2 B3 B4 B5 ;Accx output from maths routines Acc0 Acc1 Acc2 Acc3 Stack0 Stack1 Stack2 Stack3 Stack4 Stack5 Stack6 Stack7 Stack8 Stack9 StackA StackB StackC StackD StackE StackF endc ;========================================== end