About CW Identifier Circuits

Using A PIC for an IDER

In the course of building HAM repeaters I have built controllers and identifiers. The first CW identifier I built was a discrete diode array. The identifier’s printed circuit board (PCB) was double-sided. The top side of the PCB contained columns and the bottom had rows. As the array was scanned it would send a pulse each time it hit a diode. The diode array’s capacity was about 120 elements. Since a zero has 19 elements, the board couldn’t hold much more than a call sign.
Eprom technologies increased storage capacity and simplified programming, which far surpassed the old diode arrays. Next generation of CW identifiers used an Eprom to hold the message. The Eprom Ider in my circuit box, was originally tested using a manual programmer. The manual programmer consisted of two sets of dip switches and a 555 timer. The first bank of switches loaded the Eprom’s memory address and the second set of switches loaded the data. Once set the chip’s memory was programmed by triggering a 555 timer which applied a write pulse. After testing the Eprom design using the manual programmer, I quickly purchased an Eprom programmer to ease the process of message programming. All these designs were problematic, in that, the message could easily be improperly coded.
With a advent of the microcontroller the next generation of Ider’s fixed the CW characters by using a byte of data (8 bits) and storing them in the program . Once properly encoded he numeric value of a character could be repeated without concern of a missing dit.
Working in Assembly Language lots of data manipulation was done using the computer’s registers.  A byte has  more than enough space to hold CW characters. By shifting the data around using a register makes encoding Morse Code characters straight forward. Using a 0 to equal a dit and a one to equal dah. A character could be encoded and placed in a register. By shifting the character one bit at a time and decoding either a dit for zero or dah for a one until finally is only a single 1 left in the register. A single one in the register signaled the End of Character. There were two special characters added: 0xFF all ones and the second 0x00 all zeros. 0xFF is End of Message (EOM) and 0x00 is  Word Space (WS).
The Assembly code (retlw 0x06 ;a). Is an “A” CW character using the HEX base number. The computer speaks several number systems HEX, BINARY and BASE10, the numbering system we like to use. A HEX number 0x6  is equal to BINAY number 110. If we use the Binary number 110 the first bit the computer encounters is a 0 = dit , next is a 1 = dah and then its left with the stop bit 1. The computer has  decoded  dit dah  which is CW for the letter “A” and then stopped.

Soon there were C compilers available for the PIC microprocessor chips and life became easier for the PIC programmers. But the Character encoding that was done in Assembly programs still works today as we shift bits in C++.

The code below is the PIC Chip assembly language program for the PIC 16F84. The program was finished in 1997 and was published in a QST article Jan. 1998.

(updated 09-18-2008)

;***********************************************************************
;**** Built  Thu Oct 28 11:29:05 2004 *****
;**** VERSION  CWT-2222,  2-23-97 *****
;**** VERSION  CWT-2223, 10-15-2004 ****
;**** MSG Comments added, 09-18-2008 ****
;****   CW IDER  BY B. ANDING ********* 
; * This program is free software. Licensed for private use only 
; * Permission is granted to use, copy, or redistribute this program 
; * so long as it is not sold for profit.
; * THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND,
; * EITHER EXPRESSED OR IMPLIED. This notice must follow program listing.
; ***********************************************************************   
        LIST    P=16F84
	radix   hex
;=======================================
w       equ     0
f       equ     1
;=======================================
tmr0    equ     0x01
pc      equ     0x02
status  equ     0x03
porta   equ     0x05             
portb   equ     0x06
shift   equ     0x0c
tcount  equ     0x0d
count   equ     0x0e
;=======================================
START   org     0x00
	movlw   0x00  
	tris    portb  ;set portb write
	movlw   0xff  
	tris    porta  ;set porta read
	clrf    portb              
;-------------------------------------
WAIT    clrf    count
	bcf     portb,2 ;clear PTT pin
	btfss   porta,1 ;check sw 1 for 1
	goto    TIMER
	goto    WAIT
;-------------------------------------
LTRSPC  movlw	0xae	;letter space = 174
	movwf   tcount  ;set count
	goto	SPC
	return
WDSPC	movlw	0xcb	;word space = 203
	movwf   tcount  ;set count
	call    SPC
	movlw	0xcb	;word space = 203
	movwf   tcount  ;set count
	call    SPC
	goto    GETLTR
;-------------------------------------
;This is the "ID" message code which will send the CW message 
;As its written it sends the alphabet
;To send my call remove the alphabet code and insert AA5OY 
;Then add a EOM to stop message
;see the following example
;ID     addwf   pc,f	;ID = memory location
;	retlw	0x06	;a = sends  A
;	retlw	0x06	;a = sends  A
;	retlw	0x20	;5 = sends  5
;	retlw	0x0f	;o = sends  O
;	retlw	0x1d	;y = sends  Y
;	retlw   0xff   	;EOM = ends message 
;---------------------------------------
ID      addwf   pc,f
	retlw	0x06	;a
	retlw	0x11	;b
	retlw	0x15	;c
	retlw	0x09	;d
	retlw	0x02	;e
	retlw	0x14	;f
	retlw	0x0b	;g
	retlw	0x10	;h
	retlw	0x04	;i
	retlw	0x1e	;j
	retlw	0x0d	;k
	retlw	0x12	;l
	retlw	0x07	;m
	retlw	0x05	;n
	retlw	0x0f	;o
	retlw	0x16	;p
	retlw	0x1b	;q
	retlw	0x0a	;r
	retlw	0x08	;s
	retlw	0x03	;t
	retlw	0x0c	;u
	retlw	0x18	;v
	retlw	0x0e	;w
	retlw	0x19	;x
	retlw	0x1d	;y
	retlw	0x13	;z
	retlw	0x3e	;1
	retlw	0x3c	;2
	retlw	0x38	;3
	retlw	0x30	;4
	retlw	0x20	;5
	retlw	0x21	;6
	retlw	0x23	;7
	retlw	0x27	;8
	retlw	0x2f	;9
	retlw	0x3f	;0
	retlw	0x00	;Word Space
	retlw	0x29	;/
	retlw	0x68	;SK
	retlw	0x2a	;AR
	retlw	0x31	;BT
	retlw	0x4c	;?
	retlw   0xff   ;EOM
;-------------------------------------
DELAY   clrf    tmr0    ;set timer
	clrwdt          ; clear watch dog timer
	movlw   b'11010011'	;893hz.
	option          ; load reg
AGAIN   btfss   tmr0,5  ; delay 
	goto    AGAIN
	return
;-------------------------------------    
GETLTR  nop
	movf    count,w
	call    ID      ;get next letter
	incf    count,f ;move count to next letter
	movwf   shift   ;move letter to shift reg
	movlw   0x00    ;Word Space = 00
	subwf   shift,w
	btfsc   status,2
	goto    WDSPC
	movlw   0xff    ;EOM = 256
	subwf   shift,w
	btfsc   status,2
	goto    WAIT
;--------------------------------------
LOOP    movf    shift,w ;get bit pattern
	btfsc   shift,0
	movlw	0xae	;get DAH  length = 174
	btfss	shift,0
	movlw	0x3a	;get DIT  length = 58
	movwf   tcount
	call    PULSE
	rrf     shift,f ;ROTATE BIT to LSB
	bcf     shift,7 ;clear MSB
	movlw   0x01    ;Check for end bit
	subwf   shift,w 
	btfss   status,2        ;if end break loop
	goto    LOOP
	call    LTRSPC  ; letter spacing        
	goto    GETLTR  ;get next letter
;----------------------------------
PULSE   bsf     portb,1 ;set port b
	call    DELAY   ; delay  
	bcf     portb,1 ; clear port b
	call    DELAY   ; delay 
	decfsz  tcount,f
	goto    PULSE
	movlw	0x3a	;element space
	movwf   tcount  ;set count
SPC	nop
	call    DELAY   ; delay  
	nop             ; silent
	call    DELAY   ; delay 
	decfsz  tcount,f
	goto    SPC
	return
;-------------------------------------------
TIMER   movlw   0x8b	;16C84 =(.8) * 16F84
	movwf   count   ;set count to 139
	clrwdt
	movlw   b'11011111'     ; set 256 
	option          ; load prescaler in reg.
REPT    bsf     portb,7 ;signal active timer
	sleep           ; delay 2.3 sec.
	bcf     portb,7 ;signal active timer
	sleep           ; delay 2.3 sec.
	decfsz  count,f
	goto    REPT
	clrwdt
	clrf    count
	bsf     portb,2 ;set PTT pin
	goto    GETLTR  ;start IDer
;----------------------------
	end

idckt

1 thought on “About CW Identifier Circuits

Leave a comment