; === ROCAFOX == REV. 1.1 == 5 May 2002 ==================== ; ; File Description: ; Modifications to FOXBOX2 to make the transmitter controller ; more suitable for radio orienteering in a compact area. ; ; History: ; ; Version 1.1 - May 5, 2002 ; - Fixed 1-second turn-off when only one transmit slot ; - Returned dit pattern to MOE, MOI, etc. ; - All settings are now stored in EEPROM, instead of ; being set by DIP switches at power on. ; - PORTA, 4 is now used to control power applied to the ; transmitter, to save additional power (requires ; modification to hardware). ; ; Version 1.0 - January 31, 2000 ; Changes to FOXBOX2 Rev 1.0 ; - Changed tx message to the easily recognized ; "shave-and-a-haircut" pattern of dits only. ; - Added a one-character delay to sending of tx messages ; to prevent slow transmitter turn on (e.g., DJ-S11) ; from cutting off the first element. ; - Replaced prehunt delay operation of the DIP switches 1-3 ; with transmit period adjustment function (see explanation ; at bottom of assembly code). ; ; ; === FOXBOX2 == REV. 1.0 == 31 May 1999 ========================= ; ; File Description: ; Modifications and French-to-English Translation ; by Charles Scharlau NZ0I & Karen Scharlau N7SRO ; ; History: ; ; Version 1.0 - June 7, 1999 ; Changes to VE2JX/VE2EMM Rev 3.1a ; - Changed ID code speed from 25 WPM to 20 WPM ; - Disabled turn-off; the controller now runs forever ; without shutting down. ; - Added software revision number; it gets sent in CW just ; before "de " is sent when setting call sign. ; ; ; === FOXBOX == REV. 3.1a == Feb 10, 98 ========================= ; ; Use Microchip MPASM assembler ; ; Written by Francois Tremblay VE2JX and Jacques Brodeur VE2EMM, ; Nov. 1997. ; ; Used for Montreal Fox Controller, "Homing In" for April 1998 ; This software can be reproduced freely only to be used by ; Amateur Radio Operators and Amateur Radio Clubs. Any other ; use is prohibited. ; ;**************************************************************** ; ; Use a 4.194304 MHz XTAL ; list P=16F84 radix HEX __CONFIG _WDT_OFF&_XT_OSC&_CP_OFF&_PWRTE_ON ; ;**************************************************************** ; ; List of memory addresses ; CBLOCK 0X0C ; variables used for sending CW NU_MESSAGE CHAR_INDEX ; index into message CW_CHAR ; NBR_SPACE ; length of Morse space being sent NBR_DIT ; length of Morse element being sent CTR_NBR CTR_DIT TONE ; sets audio tone frequency PORTX ; dummy port CW_SPEED ; CW code speed TX_INTERVAL ; holds period of time transmitter stays on air ; ----------------------------------- TMPW ; holds W for restoring W after interrupt TMPS ; holds STATUS for restoring STATUS... ; ...after interrupt DIVIDE16 ;* countdown register with the value of 16 SECONDS ;* seconds count SIXSECONDS ;* six-second count TMP_1 ; temporary storage CW_SPEED_TMP ; temporary storage for CW_SPEED CYCLE_SLOT ;* number of current slot in TX cycle XMSNS_IN_CYCLE ; holds total xmit slots per cycle TX_ID_MESSAGE ; sets the ID message that gets sent FLAG ; Flags TX_NUMBER ; sequence number in the transmit order SEC_TOGGLE ;* increments once per second ENDC ;* Variables changed by the timer overflow interrupt. ; ; ----------------------------------- ; Assign labels to PIC registers ; TMR0 EQU 0X01 ; timer 0 PCL EQU 0X02 ; program count STATUS EQU 0X03 ; status register FSR EQU 0X04 ; file select register PORTA EQU 0X05 ; port A PORTB EQU 0X06 ; port B EEDATA EQU 0X08 ; EEPROM data register EEADR EQU 0X09 ; EEPROM address register PCLATH EQU 0X0A ; upper 5 bits of program counter INTCON EQU 0X0B ; interrupt control register TRISA EQU 0X85 ; port A data direction register TRISB EQU 0X86 ; port B data direction register EECON1 EQU 0X88 ; EEPROM control register 1 EECON2 EQU 0X89 ; EEPROM control register 2 ; ; ---------- List of symbolic values ; RP0 EQU 0X05 ; bank bit in STATUS register W EQU 0X00 ; file register designator = W F EQU 0X01 ; file register designator = F Z EQU 0X02 ; zero flag in STATUS C EQU 0X00 ; carry flag in STATUS WREN EQU 0X02 ; EECON1 write enable bit WR EQU 0X01 ; EECON1 write bit RD EQU 0X00 ; EECON1 read bit _CP_OFF EQU 0X3FFF ; code protection off _PWRTE_ON EQU 0X3FF7 ; power up timer enable ; 16C84 = 0X3FFF; 16F84 = 3FF7 _WDT_OFF EQU 0X3FFB ; watch dog timer off _XT_OSC EQU 0X3FFD ; crystal oscillator TX_ID EQU 0X09 ; EEPROM address for identifier (dit, dit-dit, etc.) TX_TOTAL EQU 0X0A ; EEPROM address for number of transmitters (time slots) = n TX_SLOT EQU 0X0B ; EEPROM address for transmit slot = 1,2,...n TX_DUR EQU 0X0C ; EEPROM address for transmit duration 10s, 12s, 15s, etc. ; ; ============================================================ ; vector table ; ORG 0X000 GOTO START ; vector to start of program ORG 0X004 GOTO TIMER0_INTERRUPT ; timer overflow interrupt vector ;**************************************************************** ; MORSE MESSAGES ;**************************************************************** ORG 0X006 ; set start address to end of vectors MESSAGE0 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X00 ; word space RETLW 0XFF ; end of message MESSAGE1 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE2 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE3 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE4 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE5 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE6 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE7 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0X02 ; "E" RETLW 0XFF ; end of message MESSAGE8 ; EEDATA code, "Sender's CALL" MOVF CHAR_INDEX, W ; load W w/ index to next char... ; ...to send MOVWF EEADR ; load it BSF STATUS, RP0 ; bank 1 BSF EECON1, RD ; command a read BCF STATUS, RP0 ; back to bank 0 MOVF EEDATA, W ; load the read value in W RETURN MESSAGE9 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; go to it RETLW 0X09 ; "D" RETLW 0X02 ; "E" RETLW 0X00 ; word space RETLW 0XFF ; end of message MESSAGE10 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; send the shave-and-haircut prefix RETLW 0X00 ; word space ; RETLW 0X02 ; "E" ; RETLW 0X08 ; "S" ; RETLW 0X02 ; "E" RETLW 0x07 ; "M" RETLW 0x0F ; "O" RETLW 0X00 ; word space RETLW 0XFF ; end of message MESSAGE11 MOVF CHAR_INDEX, W ; load W w/ index to next char to send ADDWF PCL, F ; go to it RETLW 0X00 ; word space RETLW 0x18 ; "V" RETLW 0X02 ; "E" RETLW 0x0A ; "R" RETLW 0x3E ; "1" RETLW 0x0A ; "R" RETLW 0x3F ; "1" RETLW 0x31 ; "BT pause" RETLW 0X00 ; word space RETLW 0XFF ; end of message ;**************************************************************** ; Program the controller ;**************************************************************** ;Read the dip switches to determine which parameter to program PROGRAM1 CALL BEEP_ONCE MOVF PORTB, W ; ANDLW B'00000111' ; mask off switches 3-2-1 ADDWF PCL, F ; jump table indexed by W GOTO SET_CALLSIGN ;000 set call sign GOTO SET_ID ;001 set identifier GOTO SET_NUM_XMTRS ;010 set number of time slots GOTO SET_SLOT ;011 set time slot GOTO SET_DURATION ;100 set tx duration GOTO SEND_VERSION ;101 send version number GOTO SEND_VERSION ;110 send version number GOTO SEND_VERSION ;111 send version number ;**************************************************************** ;Program the Call Sign identification ;**************************************************************** SET_CALLSIGN MOVLW D'9' ; Send "DE " CALL SEND_MSG ; MOVLW 0X00 ; EEDATA starting address 0X00 MOVWF CHAR_INDEX ; memory location NEXT_LETTER BTFSC PORTA, 3 ; read enter button GOTO NEXT_LETTER ; wait for enter MOVF CHAR_INDEX, W ; load starting address MOVWF EEADR ; MOVF PORTB, W ; get CW character from switches MOVWF EEDATA ; MOVWF CW_CHAR ; save the character BSF STATUS, RP0 ; go to bank 1 BSF EECON1, WREN ; write enable MOVLW 0X55 MOVWF EECON2 MOVLW 0XAA MOVWF EECON2 BSF EECON1, WR ; write command BCF EECON1, WREN ; disable the write enable BCF STATUS, RP0 ; back to bank 1 LOOP BTFSS PORTA, 3 ; wait for switch 2 closure GOTO LOOP ; MOVF PORTB, W XORLW 0XFF ; test for EOM character SKPNZ GOTO CALL_COMPL CALL SEND_ONE_CHAR ; send CW confirmation to user INCF CHAR_INDEX, F GOTO NEXT_LETTER ; CALL_COMPL MOVLW 0X03 ; send long beep MOVWF CW_CHAR MOVWF NBR_DIT MOVLW D'255' ; 1/4 second MOVWF CW_SPEED CALL SEND_ONE_CHAR ; BSF FLAG, 7 ; set FLAG.7 ALL_DONE CALL BEEP_ONCE FOREVER GOTO FOREVER ; finish: wait for a RESET/SYNC ;**************************************************************** ; set transmit identification ;**************************************************************** SET_ID BTFSC PORTA, 3 ; read enter button GOTO SET_ID ; wait for enter MOVLW TX_ID ; EEDATA tx id address MOVWF EEADR ; set EEPROM address CALL PERM_SWITCHES GOTO ALL_DONE ;**************************************************************** ; set number of transmitters ;**************************************************************** SET_NUM_XMTRS BTFSC PORTA, 3 ; read enter button GOTO SET_NUM_XMTRS ; wait for enter MOVLW TX_TOTAL ; EEDATA tx total address MOVWF EEADR ; set EEPROM address CALL PERM_SWITCHES GOTO ALL_DONE ;**************************************************************** ; set slot ;**************************************************************** SET_SLOT BTFSC PORTA, 3 ; read enter button GOTO SET_SLOT ; wait for enter MOVLW TX_SLOT ; EEDATA tx slot address MOVWF EEADR ; set EEPROM address CALL PERM_SWITCHES GOTO ALL_DONE ;**************************************************************** ; set transmit duration ;**************************************************************** SET_DURATION BTFSC PORTA, 3 ; read enter button GOTO SET_DURATION ; wait for enter MOVLW TX_DUR ; EEDATA tx duration address MOVWF EEADR ; set EEPROM address CALL PERM_SWITCHES GOTO ALL_DONE PERM_SWITCHES ;read switches for number of transmitters MOVF PORTB, W ; ANDLW B'00000111' ; mask off switches 3-2-1 MOVWF EEDATA ; put value into EEDATA BSF STATUS, RP0 ; go to bank 1 BSF EECON1, WREN ; write enable MOVLW 0X55 MOVWF EECON2 MOVLW 0XAA MOVWF EECON2 BSF EECON1, WR ; write command BCF EECON1, WREN ; disable the write enable BCF STATUS, RP0 ; back to bank 1 RETURN ;**************************************************************** ; send the software version number in Morse code ;**************************************************************** SEND_VERSION MOVLW D'145' ; CW speed 8 WPM MOVWF CW_SPEED MOVLW D'11' ; send the software version number CALL SEND_MSG ; GOTO SEND_VERSION ;**************************************************************** ; send a short beep ;**************************************************************** BEEP_ONCE MOVLW 0X01 ; 1 dit MOVWF NBR_DIT BSF PORTA,1 ; 80 Meters CW, Key ON CALL SEND_TONE BCF PORTA,1 ; 80 Meters CW, Key OFF RETURN ;**************************************************************** ; SEND_MSG ;**************************************************************** ; Generates 80m CW and MCW output. ; RA0 = MCW ; RA1 = Keyed CW/80 meters ; ;To send a message, enter the "SEND_MSG" routine with: ; - The # of the message to be transmitted in W ; - The speed of the CW in memory "CW_SPEED" ; 5 WPM = 240, 20 WPM = 60 ; ;To send a letter, enter the "SEND_ONE_CHAR" routine with: ; - the letter to be transmitted in memory "CW_CHAR" ; - The speed of the CW in memory "CW_SPEED" ; 5 WPM = 240, 20 WPM = 60 ; ;To generate a beep, enter the "SEND_TONE" routine with: ; - 250 in "CW_SPEED" = 1/4 second beep ; - # of 1/4 sec. in "NBR_DIT" ;============================================================= SEND_MSG MOVWF NU_MESSAGE ; save message # in NU_MESSAGE CLRF CHAR_INDEX ; initialize character index GET_MSG CLRC ; get next character to send RLF NU_MESSAGE, W ; multiply message # by 2 to... ; ...get jump value ADDWF PCL, F ; jump to the selected message CALL MESSAGE0 ; get message 0: MO GOTO SEND_CW CALL MESSAGE1 ; get message 1: "e.g., E" GOTO SEND_CW CALL MESSAGE2 ; get message 2: "e.g., I" GOTO SEND_CW CALL MESSAGE3 ; get message 3: "e.g., S" GOTO SEND_CW CALL MESSAGE4 ; get message 4: "e.g., H" GOTO SEND_CW CALL MESSAGE5 ; get message 5: "e.g., 5" GOTO SEND_CW CALL MESSAGE6 ; get message 6: "e.g., N" GOTO SEND_CW CALL MESSAGE7 ; get message 7: "e.g., D" GOTO SEND_CW CALL MESSAGE8 ; get message 8: call sign in EEPROM GOTO SEND_CW CALL MESSAGE9 ; get message 9: "DE" GOTO SEND_CW CALL MESSAGE10 GOTO SEND_CW CALL MESSAGE11 ; get message 10: software version # SEND_CW MOVWF CW_CHAR ; load CW_CHAR with character to be sent MOVF CW_CHAR, F ; set zero flag in STATUS register SKPNZ ; test for a word space GOTO DO_WORD_SPACE ; send a word space MOVLW 0XFF ; FF = end of message XORWF CW_CHAR, W SKPNZ ; test for the end of message RETURN ; end of message CALL SEND_ONE_CHAR ; send a character NEXT_CHAR INCF CHAR_INDEX, F ; next letter MOVLW 0X02 ; add 2 dit periods MOVWF NBR_SPACE ; total 3 dit periods CALL SEND_SPACE ; GOTO GET_MSG ; get another letter DO_WORD_SPACE MOVLW 0X04 ; add 4 dit periods MOVWF NBR_SPACE ; total 7 dit periods CALL SEND_SPACE ; GOTO NEXT_CHAR ; get another letter ; ;================================================================ ;**************************************************************** ; SEND_ONE_CHAR ;**************************************************************** ; Sends a CW character. Activates MCW tone (port A.0) and 80m CW ; output (port A.1) ; CW character to be sent must be held in CW_CHAR ; ; dit = 1 period ; dah = 3 periods ; Space between characters = 1 period ; Space between letters = 3 periods ; Space between words = 7 periods ;================================================================ SEND_ONE_CHAR CLRC ; clear carry RRF CW_CHAR, F ; rotate a code element (dit... ; ...or dah) into the carry flag MOVF CW_CHAR, F SKPNZ RETURN ; zero means character is done SKPC ; jump if dah GOTO SEND_A_DIT ; bit at 0 SEND_A_DAH MOVLW 0X03 ; 1 dah = 3 dits MOVWF NBR_DIT MOVLW 0X01 ; MOVWF NBR_SPACE ; 1 space after the dah BSF PORTA,1 ; 80 Meters CW, Key ON CALL SEND_TONE BCF PORTA,1 ; 80 Meters CW, Key OFF CALL SEND_SPACE GOTO SEND_ONE_CHAR SEND_A_DIT MOVLW 0X01 ; 1 dit MOVWF NBR_DIT MOVWF NBR_SPACE ; 1 space after the dit BSF PORTA,1 ; 80 Meters CW, Key ON CALL SEND_TONE BCF PORTA,1 ; 80 Meters CW, Key OFF CALL SEND_SPACE GOTO SEND_ONE_CHAR ; ;================================================================ ;**************************************************************** ; SEND_TONE ;**************************************************************** ; ; SEND_TONE generates the audible tone on port A.0 in multiples ; of a dit length. The length of the tone to be sent must be ; held in NBR_DIT when this routine is called. ; ; SPEED OF A CYCLE, example: generate 1000 Hz with a ; XTAL of 4.194304 MHz. One instruction cycle = ; .95 usec. (4 clocks per instruction cycle) ; Time of 1 audio cycle : 1/1000 = 0.001 second ; Time of 1/2 audio cycle : 0.001/2 = 0.0005 second ; The time required for each decrement of TONE is 3 ; instruction cycles or 2.86 useconds. ; ; The number passed to do a half audio cycle at 1000 Hz is ; 0.0005/0.00000286 = 178 ; ; The length of a DIT for a MCW of 20 WPM is 0.060 seconds ; The numbers of cycles to is 0.060/0.001 = 60 for a dit. ; "CW_SPEED" = ; MCW @ 20 WPM = 60 ; MCW @ 15 WPM = 90 ; MCW @ 10 WPM = 120 ; MCW @ 08 WPM = 150 ; MCW @ 05 WPM = 240 ; ;================================================================ SEND_TONE MOVF NBR_DIT, W ; place # of space-dits in W MOVWF CTR_NBR DIT_LENGTH MOVF CW_SPEED, W ; dit period is set by CW_SPEED MOVWF CTR_DIT ; START_CYCLE BSF PORTA,0 ; set A.0=1 for first half cycle MOVLW D'178' ; # of times thru 1st half cycle MOVWF TONE ; set the tone frequency HIGH_HALF DECFSZ TONE, F ; count down to 0 GOTO HIGH_HALF BCF PORTA,0 ; set A.0=0 for second half cycle MOVLW D'178' ; MOVWF TONE LOW_HALF DECFSZ TONE, F ; wait until 0 to finish GOTO LOW_HALF DECFSZ CTR_DIT, F ; GOTO START_CYCLE DECFSZ CTR_NBR, F GOTO DIT_LENGTH ; do next cycle RETURN ; done ; ;================================================================ ;**************************************************************** ; SEND_SPACE ;**************************************************************** ; ; SEND_SPACE sends a space (i.e., silence/port A.0 not ; activated) in multiples of a dit length. The length of the ; space to be sent must be held in NBR_DIT when this routine ; is called. ; ; This routine is similar to SEND_TONE routine, but without sound ; It activates a "virtual speaker": PORTX. The timing is kept the ; same as for SEND_TONE. ;================================================================= SEND_SPACE MOVF NBR_SPACE, W ; place # of spaces into W MOVWF CTR_NBR DIT_LENGTH_SP MOVF CW_SPEED, W ; length of a dit period MOVWF CTR_DIT START_CYCLE_SP BSF PORTX,0 ; set X.0=0 for first half cycle MOVLW D'178' ; # of times thru this half cycle MOVWF TONE ; HIGH_HALF_SP DECFSZ TONE, F ; count down to 0 GOTO HIGH_HALF_SP BCF PORTX,0 ; set X.0=0 for second half cycle MOVLW D'178' ; MOVWF TONE LOW_HALF_SP DECFSZ TONE, F ; wait until 0 to finish GOTO LOW_HALF_SP DECFSZ CTR_DIT, F ; GOTO START_CYCLE_SP DECFSZ CTR_NBR, F GOTO DIT_LENGTH_SP ; do one more cycle RETURN ; done ; ;================================================================ ;**************************************************************** ; TIMER 0 Interrupt service routine ;**************************************************************** ; This interrupt occurs every time timer 0 overflows from ; 11111111 to 00000000. Since the timer zero prescaler is ; in effect, and set to divide the timer 0 input clock by ; 256, a timer overflow occurs every 256 * 256 = 65536 ; instruction cycles. One instruction cycle is 4 crystal ; oscillator clock cycles. So this interrupt occurs every ; 65535 * 4 = 262144 crystal oscillator cycles. ; ; With a 4.194304 MHz crystal the timer 0 interrupt period ; is 262144 / 4194304 = 0.0625 seconds, or 16 times a ; second. TIMER0_INTERRUPT MOVWF TMPW ; save contents of W SWAPF STATUS, W ; move STATUS into W MOVWF TMPS ; save STATUS in TMPS ;----------------------------------- DECFSZ DIVIDE16, F ; 16 interrupts = second GOTO POP ; not yet 1 second jump to POP MOVLW D'16' ; set W to 16 MOVWF DIVIDE16 ; re-initialize counter ;----------------------------------- INCF SEC_TOGGLE, F ; increments once per second DECFSZ SIXSECONDS, F ; decrement 6-second count GOTO DO_SECS ; reset 6-sec count MOVLW D'6' MOVWF SIXSECONDS ;----------------------------------- DO_SECS DECFSZ SECONDS, F ; decrement seconds counter GOTO POP ; not yet tx interval, jump to POP BSF FLAG, 0 ; set interval done flag ;reset seconds countdown MOVF TX_INTERVAL, W ; put TX_INTERVAL into W MOVWF SECONDS ; reset transmit period ;------------------------------------ INCF CYCLE_SLOT, F ; slot of the transmit cycle... ; ...from 1 to XMSNS_IN_CYCLE MOVF CYCLE_SLOT, W ; SUBWF XMSNS_IN_CYCLE, W ; compare current slot with... SKPZ ; ...number of slots in a cycle GOTO POP MOVLW D'1' MOVWF CYCLE_SLOT ; reset current slot count to 1 POP BCF INTCON, 2 ; reset TMR0 interrupt flag SWAPF TMPS, W ; restore W, STATUS, and F to... ; ...their pre-interrupt values MOVWF STATUS ; SWAPF TMPW, F ; SWAPF TMPW, W ; RETFIE ; return from interrupt ; ;================================================================ ;**************************************************************** ; Start of main program ;**************************************************************** ; ; ; assembly instructions for controlling fox transmitter ; ; ORG 0X10A ; why was this address being set? START MOVLW B'00000111' OPTION ; load option register: ; bit 0 = 1 prescale by 256 ; bit 1 = 1 " ; bit 2 = 1 " ; bit 3 = 0 TMR0 use internal clk ; bit 4 n/a ; bit 5 = 0 timer mode ; bit 6 n/a ; bit 7 = 0 enable port B pullups CLRF PORTA ; clear port A CLRF PORTB ; clear port B MOVLW B'00001000' ; 1=input pin, 0=output pin TRIS PORTA ; initialize port A MOVLW B'11111111' ; port B is all inputs TRIS PORTB ; initialize port B ; ; check for the presence of jumper JP1 ; BTFSC PORTA, 3 ; see if the jumper is present GOTO PROGRAM1 ; no jumper=program controller MOVLW D'1' MOVWF PCLATH GOTO FOX_CONTROL ; jumper is there=run fox hunt FOX_CONTROL CLRF TMR0 ; CLRWDT ; disable watchdog CLRF INTCON ; BSF INTCON,7 ; enable interrupts BSF INTCON,5 ; enable TMR0 ovrflw interrupts MOVLW D'16' ; MOVWF DIVIDE16 ; generate seconds CLRF FLAG ;--------------------------------------------------------------- ;read transmit identification from EEPROM MOVLW TX_ID ; load W w/ EEPROM address MOVWF EEADR ; load it BSF STATUS, RP0 ; bank 1 BSF EECON1, RD ; command a read BCF STATUS, RP0 ; back to bank 0 MOVF EEDATA, W ; load the read value in W ; CALL TX_MESSAGE ; translate setting into message MOVWF TX_ID_MESSAGE ; save transmit message in TX_ID_MESSAGE ;read transmit slot from EEPROM MOVLW TX_SLOT ; load W w/ EEPROM address MOVWF EEADR ; load it BSF STATUS, RP0 ; bank 1 BSF EECON1, RD ; command a read BCF STATUS, RP0 ; back to bank 0 MOVF EEDATA, W ; load the read value in W ; CALL TIME_CYCLE ; translate setting into cycle number SKPNZ ADDLW D'1' MOVWF TX_NUMBER ; save position of transmitter... ; ...in transmission cycle ;read total # of transmitters from EEPROM MOVLW TX_TOTAL ; load W w/ EEPROM address MOVWF EEADR ; load it BSF STATUS, RP0 ; bank 1 BSF EECON1, RD ; command a read BCF STATUS, RP0 ; back to bank 0 MOVF EEDATA, W ; load the read value in W ; CALL TIME_CYCLE SKPNZ ADDLW D'1' ADDLW D'1' MOVWF XMSNS_IN_CYCLE ; transmissions in a full cycle MOVF XMSNS_IN_CYCLE, W ; is slot > slots in cycle? SUBWF TX_NUMBER, W BTFSC STATUS,C CALL ALARM ; if yes, signal trouble (more... ; ...foxes than time slots!) ;read tx duration from EEPROM and place in TX_INTERVAL & SECONDS MOVLW TX_DUR ; load W w/ EEPROM address MOVWF EEADR ; load it BSF STATUS, RP0 ; bank 1 BSF EECON1, RD ; command a read BCF STATUS, RP0 ; back to bank 0 MOVF EEDATA, W ; load the read value in W CALL SET_TX_INTERVAL ; translate setting into seconds MOVWF TX_INTERVAL ; transmit interval in seconds MOVWF SECONDS ; generate transmit intervals CALL DO_TXCYCLE ; start hunt transmit cycles BCF INTCON,7 ; disable all interrupts SLEEP ; sleep (low-power wait state) NOP ; ;================================================================ ;**************************************************************** ; Subroutines ;**************************************************************** ;**************************************************************** ; set transmit duration ;**************************************************************** SET_TX_INTERVAL ADDWF PCL, F ; jump table indexed by W RETLW D'10' ; 10-second tx period if all switches read 0 RETLW D'12' ; 12-second tx period if switches = 1 RETLW D'15' ; 15-second tx period if switches = 2 RETLW D'20' ; 20-second tx period if switches = 3 RETLW D'30' ; 30-second tx period if switches = 4 RETLW D'36' ; 36-second tx period if switches = 5 RETLW D'48' ; 48-second tx period if switches = 6 RETLW D'60' ; 60-second tx period if switches = 7 ;================================================================ ;**************************************************************** ; transmit message ;**************************************************************** ;TX_MESSAGE ADDWF PCL, F ; jump table indexed by W ; RETLW D'0' ; ID#1 (e.g., MO) ; RETLW D'1' ; ID#2 (e.g., MOE) ; RETLW D'2' ; ID#3 (e.g., MOI) ; RETLW D'3' ; ID#4 (e.g., MOS) ; RETLW D'4' ; ID#5 (e.g., MOH) ; RETLW D'5' ; ID#6 (e.g., MO5) ; RETLW D'6' ; ID#7 (e.g., MON) ; RETLW D'7' ; ID#8 (e.g., MOD) ;================================================================ ;**************************************************************** ; transmitter # and time to wait before repeating transmission ;**************************************************************** ;TIME_CYCLE ADDWF PCL, F ; jump table indexed by W ; RETLW D'1' ; 1 tx interval in cycle / transmitter 0 ; RETLW D'1' ; 1 tx interval in cycle / transmitter 1 ; RETLW D'2' ; 2 tx intervals in cycle / transmitter 2 ; RETLW D'3' ; 3 tx intervals in cycle / transmitter 3 ; RETLW D'4' ; 4 tx intervals in cycle / transmitter 4 ; RETLW D'5' ; 5 tx intervals in cycle / transmitter 5 ; RETLW D'6' ; 6 tx intervals in cycle / transmitter 6 ; RETLW D'7' ; 7 tx intervals in cycle / transmitter 7 ;================================================================ ;**************************************************************** ; alarm routine ;**************************************************************** ALARM MOVF DIVIDE16, W ; flash the LED ANDLW B'00000010' SKPZ BSF PORTA,1 SKPNZ BCF PORTA,1 GOTO ALARM ; ;================================================================ ;**************************************************************** ; delay prior to hunt ;**************************************************************** ;DELAYED_TIME BCF FLAG,0 ;REDO_WAIT MOVF DIVIDE16, W ; ANDLW B'0001111' ; SKPNZ ; BSF PORTA,1 ; blink LED to show the timer is running ; SKPZ ; BCF PORTA,1 ; BTFSS FLAG,0 ; check whether time has expired ; GOTO REDO_WAIT ; ; BCF PORTA,1 ; finish with the LED extinguished ; RETURN ; ;================================================================ ;**************************************************************** ; send transmitter message for one transmit interval ;**************************************************************** DO_TXCYCLE MOVLW D'1' ; init CYCLE_SLOT to slot #1 MOVWF CYCLE_SLOT ;**************************************************************** ; wait for the right transmit slot ;**************************************************************** WAIT_UR_TURN MOVF CYCLE_SLOT, W ; put current slot in W XORWF TX_NUMBER, W ; compare W with transmit slot SKPZ GOTO WAIT_UR_TURN CLRF SEC_TOGGLE ; reset SEC_TOGGLE to zero ;**************************************************************** ; Power up transmitter, and chill for 1 second ;**************************************************************** ;apply power to transmitter and wait 1 second BSF PORTA, 4 ; turn on power to transmitter WAIT_PWR_ON BTFSS SEC_TOGGLE, 0 ; wait for power to settle GOTO WAIT_PWR_ON ;**************************************************************** ; Key the transmitter and start sending ID ;**************************************************************** BSF PORTA, 2 ; turn on PTT MOVLW D'6' ; synchronize 6-sec counter MOVWF SIXSECONDS BCF FLAG, 0 ; clear transmission done flag ; MOVLW D'145' ; 8 WPM MOVLW D'90' ; 15 WPM MOVWF CW_SPEED MOVLW 0X00 MOVWF PCLATH ; page 0 MOVF TX_ID_MESSAGE, W ; send message at the start of the cycle GOTO DOSEND ; jump to transmission ;see if SECONDS is less than 12 CHECK11 MOVF SECONDS, W SUBLW D'11' ; 11 - SECONDS BTFSC STATUS,C ; skip if result negative GOTO WAITCALL ; SECONDS <= 11 SEC6X MOVF SIXSECONDS, W ; send message at 6 sec. intervals SUBLW D'6' ; 6 - SIXSECONDS SKPZ ; skip if result zero GOTO SEC6X ; SIXSECONDS <> 6 DOSEND MOVLW D'10' ; send prefix pattern CALL SEND_MSG ; MOVF TX_ID_MESSAGE, W ; CALL SEND_MSG GOTO CHECK11 WAITCALL MOVF SIXSECONDS, W ; send message at 6 sec. intervals SUBLW D'6' ; 6 - SIXSECONDS SKPZ ; skip if result zero GOTO WAITCALL ; SIXSECONDS <> 6 MOVLW D'60' ; send the call sign at 20 WPM MOVWF CW_SPEED MOVLW D'9' ; send "DE " CALL SEND_MSG MOVLW D'8' ; send call sign CALL SEND_MSG MOVLW D'1' ; back to page number 1 MOVWF PCLATH ; WAIT_TX_DONE BTFSS FLAG, 0 ; wait for end of xmission GOTO WAIT_TX_DONE CLRF SEC_TOGGLE ; reset SEC_TOGGLE to zero WAIT_FINISH BTFSS SEC_TOGGLE, 0 ; wait before PTT off GOTO WAIT_FINISH ; if only one transmit slot, don't turn transmitter off. ;read total # of transmitters from EEPROM MOVLW TX_TOTAL ; load W w/ EEPROM address MOVWF EEADR ; load it BSF STATUS, RP0 ; bank 1 BSF EECON1, RD ; command a read BCF STATUS, RP0 ; back to bank 0 MOVF EEDATA, W ; load the read value in W XORLW 0X01 ; test for one transmit slot SKPNZ GOTO WAIT_UR_TURN BCF PORTA, 2 ; clear PTT WAIT_PWR_OFF BTFSC SEC_TOGGLE, 0 ; wait before pwr off GOTO WAIT_PWR_OFF BCF PORTA, 4 ; turn off power to transmitter GOTO WAIT_UR_TURN ; ;**************************************************************** ; ;**************************************************************** ; ORG 0X0200 ; why was this address being set? ; ;FLASH BSF PORTA,1 ; CALL LOOP_BEGIN ; BCF PORTA,1 ; CALL LOOP_BEGIN ; GOTO FLASH ; ;LOOP_BEGIN MOVLW 0XFF ; MOVWF TMPF1 ; MOVWF TMPF2 ; ;LOOP_WAIT DECFSZ TMPF1, F ; GOTO LOOP_WAIT ; MOVLW 0XFF ; MOVWF TMPW ; DECFSZ TMPF2, F ; GOTO LOOP_WAIT ; RETURN ; ; ;--- EEDATA ----------------------------------------------------- ; ; Default setting of EEDATA memory ; ORG 0X2100 ; start address of the EEDATA DE 0x0A ; "R" call sign, EEDATA ADR. 0X00 DE 0x0F ; "O" DE 0x15 ; "C" DE 0x06 ; "A" DE 0XFF ; end of message DE 0XFF ; blank DE 0XFF ; blank DE 0XFF ; blank DE 0XFF ; blank ; ORG 0X2109 ; start address of settings DE 0X01 ; = identifier (e.g., tx1 = MOE) DE 0X05 ; = number of transmitters (time slots) DE 0X01 ; = transmit slot DE 0X07 ; = transmit duration (e.g., 0 = 10 seconds) ; END ; ; THE END ; ;================================================================= ; ; MORSE ENCODING ; ; One Morse character per BYTE, bitwise, LSB to MSB. ; ; 0 = dit, 1 = dah. The byte is shifted to the right bit ; by bit, until the last 1 is left, this 1 is an end of ; character indicator. A maximum of 7 Morse code elements ; can be encoded. Thus the error symbol (8 dits) is not ; supported. ; ; SEND_MSG MSB LSB assembly to copy ; ----------- --- --- --------------------------------- ; KN -.--. 00101101 RETLW 0x2D ; "KN go only" ; SK ...-.- 01101000 RETLW 0x58 ; "SK clear" ; AR .-.-. 00101010 RETLW 0x2A ; "AR over" ; BT -...- 00110001 RETLW 0x31 ; "BT pause" ; AS .-... 00100010 RETLW 0x22 ; "AS stand by" ; ? ..--.. 01001100 RETLW 0x49 ; "?" ; / -..-. 00101001 RETLW 0x29 ; "/" ; 0 ----- 00111111 RETLW 0x3F ; "0" ; 1 .---- 00111110 RETLW 0x3E ; "1" ; 2 ..--- 00111100 RETLW 0x3C ; "2" ; 3 ...-- 00111000 RETLW 0x38 ; "3" ; 4 ....- 00110000 RETLW 0x30 ; "4" ; 5 ..... 00100000 RETLW 0x20 ; "5" ; 6 -.... 00100001 RETLW 0x21 ; "6" ; 7 --... 00100011 RETLW 0x23 ; "7" ; 8 ---.. 00100111 RETLW 0x27 ; "8" ; 9 ----. 00101111 RETLW 0x2F ; "9" ; A .- 00000110 RETLW 0x06 ; "A" ; B -... 00010001 RETLW 0x11 ; "B" ; C -.-. 00010101 RETLW 0x15 ; "C" ; D -.. 00001001 RETLW 0x09 ; "D" ; E . 00000010 RETLW 0x02 ; "E" ; F ..-. 00010100 RETLW 0x14 ; "F" ; G --. 00001011 RETLW 0x0B ; "G" ; H .... 00010000 RETLW 0x10 ; "H" ; I .. 00000100 RETLW 0x04 ; "I" ; J .--- 00011110 RETLW 0x1E ; "J" ; K -.- 00001101 RETLW 0x0D ; "K" ; L .-.. 00010010 RETLW 0x12 ; "L" ; M -- 00000111 RETLW 0x07 ; "M" ; N -. 00000101 RETLW 0x05 ; "N" ; O --- 00001111 RETLW 0x0F ; "O" ; P .--. 00010110 RETLW 0x16 ; "P" ; Q --.- 00011011 RETLW 0x1B ; "Q" ; R .-. 00001010 RETLW 0x0A ; "R" ; S ... 00001000 RETLW 0x08 ; "S" ; T - 00000011 RETLW 0x03 ; "T" ; U ..- 00001100 RETLW 0x0C ; "U" ; V ...- 00011000 RETLW 0x18 ; "V" ; W .-- 00001110 RETLW 0x0E ; "W" ; X -..- 00011001 RETLW 0x19 ; "X" ; Y -.-- 00011101 RETLW 0x1D ; "Y" ; Z --.. 00010011 RETLW 0x13 ; "Z" ; ...... 01000000 RETLW 0x40 ; "six dits" ; ....... 10000000 RETLW 0x80 ; "seven dits" ; SPACE 00000000 RETLW 0x00 ; "word space" ; EOM 11111111 RETLW 0xFF ; "end of message" ; ; ;======================================================= ; ; DIP SWITCH TIMING CONTROL SETTINGS ; ; Remove programming jumper. Set the first three dip ; switches 3-2-1 to select the function: ; ; 0 0 0 set call sign ; 0 0 1 set identifier ; 0 1 0 set number of time slots ; 0 1 1 set transmit time slot ; 1 0 0 set tx duration ; 1 0 1 send version number ; 1 1 0 send version number ; 1 1 1 send version number ; ; Press reset. After the short beep, set the first three ; dip switches for the desired value... ; ; Set the DIP switches as follows: ; ; Number of transmitters: ; switches 3-2-1: (Number of transmitters) ; ; 0 0 0 send continuously (i.e., 1 transmitter) ; 0 0 1 send continuously (i.e., 1 transmitter) ; 0 1 0 2-minute cycle (i.e., 2 transmitters) ; 0 1 1 3-minute cycle (i.e., 3 transmitters) ; 1 0 0 4-minute cycle (i.e., 4 transmitters) ; 1 0 1 5-minute cycle (i.e., 5 transmitters) ; 1 1 0 6-minute cycle (i.e., 6 transmitters) ; 1 1 1 7-minute cycle (i.e., 7 transmitters) ; ; Transmit time slot: ; switches 3-2-1 ; ; 0 0 0 send continuously ; 0 0 1 send in 1st time slot ; 0 1 0 send in 2nd time slot ; 0 1 1 send in 3nd time slot ; 1 0 0 send in 4nd time slot ; 1 0 1 send in 5nd time slot ; 1 1 0 send in 6nd time slot ; 1 1 1 send in 7nd time slot ; ; Transmit identifier: ; switches 3-2-1 ; ; 0 0 0 send "MO" ; 0 0 1 send "MOE" ; 0 1 0 send "MOI" ; 0 1 1 send "MOS" ; 1 0 0 send "MOH" ; 1 0 1 send "MO5" ; 1 1 0 send "MOEEEEEE" ; 1 1 1 send "MOEEEEEEE" ; ; Transmit duration (on-air time) ; switches 3-2-1 ; ; 0 0 0 10-second tx period if all switches read 0 ; 0 0 1 12-second tx period if switches = 1 ; 0 1 0 15-second tx period if switches = 2 ; 0 1 1 20-second tx period if switches = 3 ; 1 0 0 30-second tx period if switches = 4 ; 1 0 1 36-second tx period if switches = 5 ; 1 1 0 48-second tx period if switches = 6 ; 1 1 1 60-second tx period if switches = 7 ; ; ...then press reset again.