;======== pic beacon 2 980702 petek ============ ; (c) 1997 1998 by Peter Kerckhoff ; permission granted to copy for non-commercial use only ; all other rights reserved ; ; 981004 changed sleep mode to lower current draw ; ; lines with a *** denote changes to the code to make ; the program work with a 16c84 or 16f84 PIC ; ; header information, specify device type, hex numbers list p=12c508 ; list p=16f84 ; *** change for 16f84 radix hex ; configuration word for programming (msb -> lsb) ; MCLRE = 0 (internal reset) ; CP = 1 (code protection off) ; WDTE = 0 (watch dog timer disabled) ; FOSC1, FOSC0 = 10 (internal 4MHz oscillator) __config b'01010' ; *** comment out for 16f84 ; register equates w equ 0x00 f equ 0x01 pc equ 0x02 status equ 0x03 zerof equ 0x02 caryf equ 0x00 port equ 0x06 regbase equ 0x07 ; *** comment out for 16f84 ;regbase equ 0x0c send equ regbase ; the morse data to send msgreg equ regbase+1 ; msg string pointer didah equ regbase+2 ; on time for di's and dah's delay1 equ regbase+3 ; delay rtn counters delay2 equ regbase+4 ; d100 equ regbase+5 ; d250 equ regbase+6 ; d5 equ regbase+7 ; tonep equ regbase+8 ; tone period (set by jumpers) pert equ regbase+9 ; tone duration math equ regbase+0x0a ; for literal add, subtract sw0 equ 0x00 ; tone select inputs sw1 equ 0x01 ; pwr equ 0x02 ; transmitter power onoff equ 0x03 ; on/off input line ook equ 0x04 ; OOK output line tone equ 0x05 ; tone output ;-------------------------------------------------- ; the 12c508 uses an automatic reset vector of 0x00 ; location 0x1ff is used for the internal 4MHz calibration ; value and should not be used or changed ; when using a 16f84 for testing, the org can remain at ; 0x00 as the interrupt ability of the 16f84 isn't used ; so the interrupt vector is not needed org 0x00 ;-------------------------------------------------- ; OPTION register settings (msb -> lsb) ; enable wake-up on pin change (GPUWU = 0) ; disenable weak pullups (GPPU = 1) ; timer0 clock source internal (TOCS = 0) ; timer0 edge select l->h (TOSE = 0) ; prescaler assigned to timer0 (PSA = 0) ; prescaler select of 1:2 (PS2-PS0 = 000) ; gp0 - (in ) select line 0 (lsb) ; gp1 - (in ) select line 1 (msb) ; gp2 - (out) output power to transmitter, 1= on ; gp3 - (in ) on/off, 1= on, 0= off (sleep) ; gp4 - (out) OOK output, 0= off ; gp5 - (out) tone output, 0=off start movlw b'01000000' ; option settings option movlw b'11001011' ; port configure tris port ; upon power up, play the ID message, then enter ; the locating beep loop. During the locating beep ; loop the program checks for the on/off input bit set ; to off, if so, the processor goes to sleep, minimizing ; current draw long bsf port,pwr ; turn the transmitter on call w100mS ; wait 1/2 second call w100mS ; for the transmitter to call w100mS ; stabilize call w100mS call w100mS call logmsg ; play ID message bcf port,pwr ; turn transmitter off ; play the locating beep while keeping time and checking ; for the on/off command, the frequency of the locating ; beep toon is determined by the jumper (switch) settings ; the following code segment sets the half-period time ; for the tone rtn-- ; sw1 sw0 period half frequency ; 0 0 1350 uS 675 uS 740 Hz ; 0 1 1000 uS 500 uS 1 kHz ; 1 0 750 uS 375 uS 1.3 kHz ; 1 1 250 uS 500 uS 2 kHz ; ; note that 0=jumper installed, 1= NO jumper movlw d'41' ; setup literal add movwf math movlw d'82' ; preset for 2kHz btfss port,sw1 ; test msb movlw d'164' ; lower frequency btfss port,sw0 ; test lsb addwf math,w ; lsb=0 movwf tonep ; save period count ; now do a similar thing but for the 100mS delay constant movlw d'198' ; delay const for 2kHz btfss port,sw1 movlw d'99' movwf math ; save partial result clrw ; set w to zero btfss port,sw0 movlw d'50' ; set for subtraction subwf math,w ; math-w => w movwf pert ; save 100mS constant ; main loop, produce a locating tone for 1 second out of every ; three, then at 5 minute intervals play the ID message main5 movlw d'100' ; 100 loops of 3 seconds each movwf d5 ; = 300/60 = 5 minutes fivel bsf port,pwr ; turn on the transmitter call w100mS ; wait 200mS for call w100mS ; transmitter to sabilize ; produce a tone for 1 second, 10 loops of 100mS bsf port,ook ; turn on the OOK output movlw d'10' ; setup for 10x100mS movwf delay1 tnlop movf pert,w ; get 100mS constant movwf d100 ; based upon tone frequency wtone bsf port,tone ; high cycle of tone movf tonep,w ; get period constant movwf d250 whight decfsz d250,f ; delay high period goto whight bcf port,tone ; low cycle of tone movf tonep,w ; get period constant movwf d250 wlowt decfsz d250,f ; delay low period goto wlowt btfss port,onoff ; test for on/off goto gnite ; leave if off decfsz d100,f ; done w/100mS? goto wtone ; nope, loop decfsz delay1,f ; done with 1 second? goto tnlop ; nope, loop bcf port,ook ; turn off OOK output bcf port,pwr ; turn off transmitter ; delay 1.8 seconds (18 x 100mS) movlw d'18' movwf d250 d15 call w100mS btfss port,onoff ; test on/off bit goto gnite ; leave if off decfsz d250,f ; done 1.8 seconds? goto d15 ; nope, loop back decfsz d5,f ; done 5 minutes? goto fivel ; nope, loop back goto long ; else play ID message gnite bcf port,ook ; set outputs low bcf port,pwr bcf port,tone movlw b'11111111' ; port configure tris port ; to all input bits movf port,w ; read all port bits sleep ; go to sleep ; this routine sends the message stored at msg in morse logmsg clrf msgreg ; clear the message counter playl movf msgreg,w ; get the message counter call msg ; used to point to msg character ; returned is morse equivalent play movwf send ; save the morse character movlw mEND ; is it the end flag? subwf send,w btfss status,zerof goto morout ; no, so play it return ; yes, end, leave ;---------------------------------------------------- ; morout ; enter with the morse character to be transmitted ; in the send register, this routine will toggle ; an output line, simulating a morse code transmission ; ; check for a control word delay flag first, then do ; either the delay or start sending the cw ; morout movlw mSpace ; is it a space (between words) subwf send,w btfss status,zerof goto morlop ; not a space, go send didah call w100mS ; space, wait 700mS call w100mS ; for 12wpm cw call w100mS ; 400mS here and another call w100mS ; 300mS at mordn goto mordn ; send the cw from the information stored in the send register ; Shift the eight bit register to the left, if the carry bit ; is 0 then send a di, if the carry bit is a 1 send a dah. ; When the send register = 1000 0000 then all bits have been ; sent. morlop movlw 0x01 ; setup for di bcf status,caryf ; make sure carry bit is clear rlf send,f ; shift to get bit to send btfsc status,caryf ; skip next instruction for di's iorlw 0x02 ; 3x di = dah movwf didah ; save didah time morwat movlw d'198' ; loop for 100mS (12 wpm) movwf d100 bsf port,ook ; turn on OOK output wmors bsf port,tone ; turn on tone bit (high period) movlw d'82' ; delay for 250 uS (2kHz) movwf d250 whigh decfsz d250,f ; high period delay goto whigh bcf port,tone ; low period for tone bit movlw d'82' movwf d250 wlow decfsz d250,f ; low period delay goto wlow decfsz d100,f ; loop for 100mS goto wmors decfsz didah,f ; fall thru for di's goto morwat ; or do again twice for dah's bcf port,ook ; turn off OOK output call w100mS ; delay between di-dahs movlw b'10000000' ; check for end of data subwf send,w btfss status,zerof ; not equal, not end goto morlop ; so continue with this character mordn call w100mS ; delay between characters call w100mS ; 300mS for 12wpm call w100mS incf msgreg,f ; move to next character (pointer) goto playl ; loop for rest of message ;----------------------------------------------------- ; 100 mS delay rtn ;w100mS return ; for testing in MPLAB ; comment the next w100mS ; and uncomment this one ; -- speeds things up :) w100mS movlw d'100' ; 1 cycle movwf delay2 ; 1 cycle ; gets kinda funky here ; as there is a 1mS rtn ; built into the 100mS ; rtn (saving a sub call ; and stack space!) d100ms movlw d'197' ; 1 cycle ---+ movwf delay1 ; 1 cycle | d1ms2 goto $+1 ; 2 cycles (x 197) | decfsz delay1,f ; 1 cycle (x 197) | goto d1ms2 ; 2 cycles (x 197) | ; 3 + 197 x 5 = 988 | goto $+1 ; = 990 | goto $+1 ; = 992 ---+ decfsz delay2,f ; 1 cycle goto d100ms ; 2 cycles, = 995 ; setup cycles 2 + 1 for fall thru = 3 ; interior cycles = 100 x 995 = 99500 ; = 99503 uS (99.503 mS) ; the calling rtn eats up 2 more and the return eats ; two cycles, = 99507uS, need to eat up 493 uS to ; give a precise 100mS delay ; also gives us an approximate 500uS delay w500uS movlw d'122' ; 1 cycle movwf delay1 ; 1 cycle d101ms nop ; 1 cycle x 122 decfsz delay1,f ; 1 cycle x 122 goto d101ms ; 2 cycles x 122 ; 2 + 1 + 4 x 122 = 491 uS goto $+1 ; waste 2 more cycles ; for 493 uS, add in ; the call (2uS) and ; return (2uS) for return ; a grand total of 100mS ;=========================================================== ; message area ; ; call the rtns with the message character number in ; w, returned is the morse coded in w ; ; the four messages are msg01, msg02, msg03, and msg04 ; use the following examples for coding up the message ; patterns. Fundamentally the code starts with a ; addwf to move to the correct retlw command. The ; return commands pass back the coded morse. To use ; a letter, preceed the letter with a 'm'. ; ; for example, to transmit CQ as message 1... ; ; msg01 addwf pc,f ; retlw mC ; retlw mQ ; retlw mSpace (optional space) ; retlw mEND (required end) ; ; the morse is transmitted in 12wpm (100mS for a dit) ; dashes are 3 times as long as a dit. Between dits ; and dahs is silence a dit in length. A silence 3 ; dits in length is automatically inserted between ; letters. A silence of 7 dits in length can be added ; between words by using the mSpace character ; ; messages programmed ; KB0YRQ telemetry beacon msg addwf pc,f ; KB0YRQ telemetry beacon retlw mK retlw mB retlw m0 retlw mY retlw mR retlw mQ retlw mSpace retlw mT retlw mE retlw mL retlw mE retlw mM retlw mE retlw mT retlw mY retlw mSpace retlw mB retlw mE retlw mA retlw mC retlw mO retlw mN retlw mEND ; equates for morse characters ; specify the coded characters by using 'm' followed ; by the letter you want to send the coded form of ; morse is based in... 0 = dit, 1 = dash, roll out ; the bits, when 0x80 remains the code is done ; this Morse Code storage rtn was published in _BYTE_ ; October 1976, pg. 36 in an article by L. Krakauer mA equ 0x60 mB equ 0x88 mC equ 0xa8 mD equ 0x90 mE equ 0x40 mF equ 0x28 mG equ 0xd0 mH equ 0x08 mI equ 0x20 mJ equ 0x78 mK equ 0xb0 mL equ 0x48 mM equ 0xe0 mN equ 0xa0 mO equ 0xf0 mP equ 0x68 mQ equ 0xd8 mR equ 0x50 mS equ 0x10 mT equ 0xc0 mU equ 0x30 mV equ 0x18 mW equ 0x70 mX equ 0x98 mY equ 0xb8 mZ equ 0xc8 m0 equ 0xfc m1 equ 0x7c m2 equ 0x3c m3 equ 0x1c m4 equ 0x0c m5 equ 0x04 m6 equ 0x84 m7 equ 0xc4 m8 equ 0xe4 m9 equ 0xf4 mPeriod equ 0x56 mComma equ 0xce mQuest equ 0x32 mEqual equ 0x8c mColon equ 0xe2 mSemi equ 0xaa mSlash equ 0x94 mDash equ 0x86 mSpace equ 0x01 ; space between words mEND equ 0x00 ; end of the info end