PDA

View Full Version : Repeater ID and controller



Macgman2000
- 27th March 2012, 03:41
Hello,

I am done building a UHF repeater out of 2 Motorola Maxtrac radios. I have the controller working. I want to add another function, auto morse code ID'er. I can inject the audio into the audio circuit (radio mic uses preamp, 100 ~ 200mv output). Besides using scaling resistors and capacitive coupling to get to 50mv (low volume ID). What is the best way to generate the dits and das? Use the PWM output to generate a base frequency of 1 ~ 2 Khz and interrupt it?

Nick

mister_e
- 27th March 2012, 05:33
PWM with pause
SOUND with pause
HPWM with Pause
Toggle loop and pauses
Substitute pause by Timer or not

all personal choices. No real need for interrupt

Mike, K8LH
- 27th March 2012, 13:08
If you're considering using PWM anyway, why not generate sine wave AF output? Seriously, why not setup the PWM period for 32 times the output frequency and generate a 32 step sine wave at 1 kHz? Let's see... With a 32 MHz clock 1000 Hz * 32 = 32 kHz or a period of 32.25 us. That's 250 instruction cycles so you would setup TMR2 with 1:1 prescaler and setup PR2 = 250-1. You could build a simple timer in the ISR to count off 1 ms intervals (32 pwm periods) for dit and dah timing.

Anyway, just spit-balling. Good luck...

Regards, Mike - K8LH

Dave
- 27th March 2012, 14:50
Macgmam2000, Attached is a piece of code I wrote for a 6 pin PIC 10F222. It was designed to be placed inside of an 1/8 inch phone plug and used with a hand held radio for fox hunting. you can use it but please mention the writer...



' STATION_ID3.BAS
' WRITTEN FOR PIC10F222
' WRITTEN BY DAVID PUROLA, N8NTA
' PROGRAM TO SEND STATION ID DATA AT A PREDITERMINED TIME INTERVAL or TRIGGERED
' BY PRESSING BUTTON FOR APPROX 2.3 SECONDS. CAN BE USED FOR REPEATER ID or FOR
' TRANSMITTER FOX HUNTING. TXENAB IS KEYED 250 Ms. BEFORE CW TRANSMISSION FOR
' KEYING OF THE RADIO PTT CIRCUIT.(07/18/2006)
'
asm
__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_ON & _IOFSCS_8MHZ
movwf OSCCAL ; load factory osccal value at start-up
bcf OSCCAL,0 ; Set GP2 as I/O pin
ENDASM

DEFINE OSC 8
'
' ************************************************** ******************
' Define Port Variables
' ************************************************** ******************
DATA_OUT VAR GPIO.0 '0-MODULATED DATA TO RADIO AUDIO CIRCUIT (THRU RESISTIVE DIVIDER AND CAP)
TXENAB VAR GPIO.1 '0-TRANSMIT ENABLE OUTPUT (THRU FET TO DIODE AND RESISTOR TO GROUND FOR PTT)
SPARE2 VAR GPIO.2 '0-NOT USED
TRIGGER VAR GPIO.3 '1-EXTERNAL ID TRIGGER (PUSH BUTTON TO GROUND W/100K PULLUP)

' ************************************************** ******************
' Declare Constants
' ************************************************** ******************
FREQ CON 110 'CHANGE THIS CONSTANT TO VARY THE TONE FREQUENCY (APPROX 565 Hz.)
DIT CON 4 'CHANGE THIS CONSTANT TO VARY THE WPM RATE (DOT)
TIMEOUT CON 60 'ID TIMEOUT IN APPROX. .1 MINUTE INCREMENTS
PTTDELAY CON 250 'PTT PRE CW DELAY TIMING FOR RF GENERATION

'------------- DON'T CHANGE THESE VARIABLES AS THEY ARE DYNAMIC --------------
DAH CON DIT * 3 'DASH TIMING IS EQUAL TO 3 DOT'S
INTERDITDAH CON DIT * 12 'INTER DOT/DASH TIMING IS EQUAL TO 1 DOT
CHARTIME CON DIT * 3 * 12 'INTER CHARACTER TIME IS EQUAL TO 3 DOT'S
WRDTIME CON DIT * 7 * 12 'INTER WORD TIMING IS EQUAL TO 7 DOT'S

' ************************************************** ******************
' Declare Variables
' ************************************************** ******************
IDCHAR VAR BYTE
SCRATCH VAR BYTE
POINTER VAR BYTE

' ************************************************** ******************
' Define MORSE CHARACTERS
' ************************************************** ******************
' A B C D E F G H I J K L M N 0 P Q R S T U V W X Y Z
'$42,$84,$A4,$83,$01,$24,$C3,$04,$02,$74,$A3,$44,$ C2,$82,$E3,$64,$D4,$43,$03,$81,$23,$14,$63,$94,$B4 ,$C4
' 0 1 2 3 4 5 6 7 8 9 /
'$FD,$7D,$3D,$1D,$0D,$05,$85,$C5,$E5,$F5,$95

'************************************************* ********************
STATIONID: 'SEND STATION ID TO TRANSMITTER
'************************************************* ********************

' ************************************************** ******************
' DO NOT CHANGE THESE LINES
' ************************************************** *****************
TRISIO = %11111000 'SET PORT DIRECTION REGISTER *
OPTION_REG = %11001000 'DISABLE PULL-UPS,PSA to WDT *
ADCON0 = %00000000 'Channel 0,A/D Off *
'************************************************* *******************

TXENAB = 1 'ENABLE TRANSMITTER
PAUSE PTTDELAY 'ALLOW TIME FOR RF TO BEGIN
IDCHAR = $FF 'DEFAULT FOR FIRST PASS
POINTER = 0
WHILE IDCHAR <> 0 'CYCLE THRU ALL CHARACTERS IN MESAGE UNTIL $00 IS REACHED (255 TOTAL CHARACTERS MAXIMUM)
' N 8 N T A _ T H I S _ I S _ T H E _ F O X
LOOKUP POINTER,[$82,$E5,$82,$81,$42,$FF,$81,$04,$02,$03,$FF,$02,$0 3,$FF,$81,$04,$01,$FF,$24,$E3,$94,$00],IDCHAR
IF IDCHAR <> $FF THEN 'IF NOT INTER CHARACTER SPACE THEN
SCRATCH = IDCHAR & 7 'HOW MANY DITS & DAHS
WHILE SCRATCH > 0 'LOOP FOR NUMBER OF DIT'S AND DAH'S
IF IDCHAR.7 = 1 THEN 'IF IT'S A DAH THEN
SOUND DATA_OUT,[FREQ,DAH] '~565 Hz
ELSE 'IF IT'S A DIT THEN
SOUND DATA_OUT,[FREQ,DIT] '~565 Hz
ENDIF
DATA_OUT = 0 'MAKE SURE OUTPUT IS AT 0
PAUSE INTERDITDAH 'PAUSE INTER DIT/DAH TIME
IDCHAR = IDCHAR << 1 'SHIFT FOR NEXT DIT or DAH
SCRATCH = SCRATCH - 1 'INCREMENT DIT/DAH POINTER
WEND
PAUSE CHARTIME 'PAUSE BETWEEN CHARACTERS
ELSE
PAUSE WRDTIME 'PAUSE BETWEEN WORDS
ENDIF
POINTER = POINTER + 1 'INCREMENT TO NEXT CHARACTER
WEND
GPIO = %00001000 'DISABLE TRANSMITTER & AUDIO OUTPUT
TRISIO = %11111001 'SET PORT DIRECTION REGISTER
IDCHAR = TIMEOUT 'SET FOR (TIMEOUT/10) MINUTES BEFORE NEXT TIMED ID
WHILE IDCHAR > 0 'MINUTES COUNTER
POINTER = 3 'SET FOR 6 SECONDS
WHILE POINTER > 0 '.05 SECOND COUNTER
SLEEP 1 'LOW POWER MODE FOR APPROX. 2.3 SECONDS
IF TRIGGER = 0 THEN STATIONID 'CHECK FOR EARLY ID
POINTER = POINTER - 1
WEND
IDCHAR = IDCHAR - 1
WEND
GOTO STATIONID 'SEND STATION ID TO TRANSMITTER
STOP

Macgman2000
- 27th March 2012, 19:29
Thanks all for your suggestions.

I decided to use subroutines for dit and dah audio frequency and tone length (dit/dah). In main I will just run through my callsign characters calling on subroutines, once it is done ID'ing then run a timer for 10 ~ 15 min between ID's. I guess I was looking at this too closely... I will need to integrate this into my controller code. The repeater TX control passes through the processor and is delayed for 7 seconds after the receive signal COR drops. This eliminates the ker-chunk that you hear from the carrer dropping at the end of a transmission between two parties talking.


Nick

Macgman2000
- 27th March 2012, 22:53
Hello Dave,

trying to follow what is going on in the pointer call. $82 = N....not following, can you clarify?


Nick

Dave
- 28th March 2012, 11:40
Well it's quite simple, The 3 least significant bits are how many DIT's or DAH'S make up the character. The most significant 5 bits make up the message of DIT'S or DAH'S. The 1's are DAH'S and the 0's are DIT'S from left to right. The program mearly loops the number of dit's or dah's and depending on the state of the most significant bit, generates the appropriate dit or dah. The character is then left shifted for the next dit or dah. Understand? I had to make the code compact as the 10F222 only has 512 bytes of flash memory and 23 bytes of ram.....

Mike, K8LH
- 28th March 2012, 13:19
That's a very nice method, Dave. It won't accommodate a comma, question mark, or any character with more than five elements, but you probably don't need those characters in that application.

One method I've used involves inserting a single '1' bit terminator after the last element. This allows for characters or pro-signs up to seven elements in length and eliminates the need for an element counter. A space character is empty except for the terminator bit ('10000000'). Processing the dits and dahs is similar to the method in Dave's example.


id
retlw b'10010000' ; 'd', dah-di-dit
retlw b'01000000' ; 'e', dit
retlw b'10000000' ; ' ', space
retlw b'10110000' ; 'k', dah-di-dah
retlw b'11100100' ; '8', dah-dah-dah-di-dit
retlw b'01001000' ; 'l', di-dah-di-dit
retlw b'00001000' ; 'h', di-di-di-dit
retlw b'10010100' ; '/', dah-di-di-dah-dit
retlw b'01010000' ; 'r', di-dah-dit
retlw 0 ; end-of-table

Macgman2000
- 28th March 2012, 15:57
Mike, Dave,

Great job, very nicely done! I will use this method when optimising my code. I have it working via sub calls and it is working nicely. I have to add program mode (to alter the parameters of my repeater including call sign), add a serial display for remote mounting along with a keypad. All of which I have written in modular form for other projects. I need to message it all together...LOL....yeah like that ever goes smoothly. I will post the code when I am done, since this is not propietary or for a client.

Nick

Mike, K8LH
- 28th March 2012, 18:39
Hi Nick,

Glad to hear you've got it up-n'-runnin'.

If you were to try that other character format you'd need to change the algorithm. I don't have PBP but I think it would use one less variable (below). Other than that, the algorithms are so close I'm not sure there would be any advantage using one format over the other.

I'd love to see your code when you're finished (is there such a thing as "finished"?)...

Cheerful regards, Mike, K8LH

<note> that outer loop doesn't look quite right, does it?

while idchar <> 0 '
lookup pointer,[$90,$40,$80,$B0,$E4,$48,$08,$94,$50,$00],idchar
' " d e k 8 l h / r "
if idchar = 128 then ' if <space> char
pause wordtime ' do word space
else ' otherwise
while idchar <> 128 ' while unprocessed bits
if idchar.7 = 1 then '
sound data_out,[freq,dah] ' do 'dah'
else '
sound data_out,[freq,dit] ' do 'dit'
endif '
data_out = 0 ' force output to 0
pause interditdah ' 1 dit space
idchar = idchar << 1 ' prep for next bit
wend '
pause chartime ' pause between chars
endif '
pointer = pointer + 1 ' bump table pointer
wend '

Mike, K8LH
- 29th March 2012, 00:37
Dave,

I'm running an assembly language version of your program on a 10F200 (100 words of memory) and it works great.

Dave
- 29th March 2012, 11:33
Mike, <note> that outer loop doesn't look quite right, does it? The outer loop allows the lookup table statement to be dynamic in nature. If one decides to, there can be multiple lookup statements for messages with out having to place a separate variable for the length of each of the messages. It was designed to to have the spare input bit possibly select another message if triggered by a branch statement.

Mike, K8LH
- 29th March 2012, 23:06
Hey Dave... I meant it didn't look right with my code which won't process a 0x00 character. It looks great with your code Sir...