GOSTARIA DE TER OPÇÃO DA FAMILIA PIC PARA SEU RECEPTOR DE CONTROLE REMOTO? ENTÃO ESTA RESOLVIDO !!! SEGUINDO O MESMO ESTILO DO ARTIGO “RECEPTOR DE CONTROLE REMOTO GENERICO PARA HCS200..301 COM AT89C2051” VOCE VERÁ AGORA MAIS 2 APLICAÇÕES GENÉRICAS BASEADAS NAS “ NOTE APLICATTIONS” DA MICROCHIP PUBLICADAS NA INTERNET.
PRIMEIRAMENTE, VAMOS VER UM RECEPTOR COM PIC16F628A COM 4 SAIDAS (LIGADAS A LEDS) QUE COMANDARÃO A SUA FUTURA APLICAÇÃO.
TUDO NO MESMO ESQUEMA. TEM QUE ESCOLHER A KEY (OU USAR A QUE FOI COMPILADA NO ARQUIVO HEX = ‘0123456789ABCDEF’) COMUM NO RECEPTOR E TRANSMISSOR. TEM QUE USAR DISC=SERIAL NUMBER . CONFORME O HCS USADO NO CHAVEIRINHO , TEM QUE PROGRAMAR A WORD ‘CONFIG’. VEJA SEMPRE OS DATASHETS DO COMPONENTE QUE SERÁ USADO.
NOVAMENTE, NÃO ESQUECER QUE A FREQUENCIA DO RECEPTOR TEM QUE SER IGUAL AO DO CONTROLE REMOTO (CHAVEIRINHO). LEIA OS ARTIGOS SOBRE ISTO NESTE BLOG. TUDO O ACIMA SE APLICA AOS DOIS CIRCUITOS.
A SEGUNDA APLICAÇÃO, MAIS SIMPLES, USA UM PEQUENO PIC12F629 PARA CONTROLAR 2 SAIDAS APENAS(LED1 E LED 2). MAS , GERALMENTE, É SUFICIENTE PARA A MAIORIA DAS APLICAÇÕES COMO ALARMES E CONTROLES REMOTOS DE PORTÃO. AMBOS OS ESQUEMA PERMITEM, POR DEFINIÇÃO DE PROGRAMA, MEMÓRIZAR ATÉ 15 CONTROLES (CHAVEIRINHOS).
EM RESUMO:
1) VOCE ADQUIRE UM PAR DE CONTROLE REMOTO (ESCOLHA 2 IGUAIS COM O MESMO CHIP HCS (PODE SER 200 , 201, 300 OU 301), DE QUALQUER FABRICANTE.
2) VOCE PROGRAMA UMA NOVA KEY (A SUA KEY OU A CITADA ACIMA SE FOR USAR O ARQUIVO COMPILADO) ,DEIXA AS OUTRAS WORDS TUDO ‘0000’
EXCETUANDO A WORD “CONFIG” QUE DEVE SER ‘ 0030’ PARA 200,300,301 E ‘0000’ PARA 201 . PODERÁ USAR O HCS_PROG OU HCS_PROG_TINY. NÃO PRECISA TIRAR O CHIP (GERALMENTE SMD) DA PLACA. APENAS, SOLDE PEQUENOS FIOZINHOS ( DO TIPO DE TELEFONE) E CONECTE NO PROGRAMADOR. AO FAZER ISTO , TIRE A BATERIA DE 12 VOLTS FORA DO CONTROLE. NÃO ESQUECA DE ATERRAR OS PINOS DA SAIDA S0 E S1.(VEJA DATASHEET DO HCS EM USO, NA SEÇÃO ‘PROGRAMAÇÃO’).
3) MONTE O CIRCUITO DO RECEPTOR (PROTOBOARD OU PLACA UNIVERSAL, DAQUELAS QUE VAI LIGANDO COM FIOZINHOS). PROGRAME AGORA O MICROCONTROLADOR COM O ARQUIVO HEX APROPRIADO. USE O WINPIC, IC_PROG OU QUALQUER OUTRO PROGRAMADOR COM UM HARDWARE COMO O JDM OU SIMILARES.
4) FAÇA O APRENDIZADO DE CADA CONTROLE , APERTANDO PRIMEIRO A TECLA ‘LEARN’ E DEPOIS ACIONANDO O CONTROLE REMOTO. FAÇA ISTO COM CADA CONTROLE. APÓS ISTO, EM USO, A CADA BOTÃO APERTADO NO CONTROLE REMOTO DEVERÁ ACENDER UM LED CORRESPONDENTE NO RECEPTOR.
5) AGORA , USE-O EM SEU NOVO PROJETO!!!
CHEGA DE BLÁ BLÁ BLÁ !!!
VEJA O ESQUEMA DA APLICAÇÃO 1 COM PIC 16F628A:
SEGUE ABAIXO ARQUIVO ASM PARA VERSÃO PIC16F628A:
SEGUE ABAIXO ARQUIVO HEX PARA VERSÃO PIC16F628A:
SEGUE ABAIXO, SUGESTÃO DE PLACA VERSÃO 16F628A :
SEGUE ABAIXO, SUGESTÃO DE PLACA VERSÃO 16F628A COM COMPONENTES VISTO PELO LADO COBREADO E LISTA DE MATERIAIS:
VEJA O ESQUEMA DA APLICAÇÃO 2COM PIC 12F629:
SEGUE ABAIXO ARQUIVO ASM PARA VERSÃO PIC12F629:
SEGUE ABAIXO ARQUIVO HEX PARA VERSÃO PIC12F629:
SEGUE ABAIXO A PLACA PARA A VERSÃO 12F629:
SEGUE ABAIXO A PLACA PARA A VERSÃO 12F629 COM COMPONENTES MONTADOS VISTO PELO LADO COBREADO E LISTA DE MATERIAIS:
ATÉ O PRÓXIMO ARTIGO !!!
Curiosidades:
Cuidado! Você está sendo vigiado!
O preço de se levar uma vida muito ‘corrida’
Sua cama e seu sono
Outros artigos:
Ensine valores morais aos seus filhos
Casais – Como administrar bem o dinheiro
Tenha um conceito correto sobre desastres naturais
Como sobreviver ao primeiro ano de casamento
Caro Claudio, bom dia.
Fico muito grato por sua atenção e retorno.
Acredito que não haverá problemas em relação a quantidade de pinos do PIC12F629 (6 portas), pois tenho esse mesmo programa em .ASM para o PIC12C509. Imprimi sua resposta e vou tentar proceder as alterações e compilações. Para testar estou usando o simulador do Proteus 7. Apresenta um bom resultado. Segue abaixo o .ASM – Atenciosamente, Pretti
;**********************************************************************
; Pinout and notes on 16F628A K8 implementation imw/EWP
;
; 16F628A, 20 (or 4) MHz P-DIP part
; ==================================
; pin name connection
; ————————
; 1 RA2 N/C
; 2 RA3 N/C
; 3 RA4 N/C
; 4 MCLR 10k pullup resistor to +5v
; 5 VSS 0v (ground)
; 6 RB0 KEY(4.7 K res to base of oc trans keys tx)
; 7 RB1 N/C
; 8 RB2 ST (sidetone, to piezo spkr)
; 9 RB3 STK (beacon sw, optional, see manual)
; 10 RB4 DIT (paddle dit contact)
; 11 RB5 DAH (paddle dah contact)
; 12 RB6 N/C
; 13 RB7 PB (push button memory, hold 2 s for command)
; 14 VDD +5v (can be 3.5 to 5.5 v)
; 15 RA6 N/C
; 16 RA7 N/C
; 17 RA0 N/C
; 18 RA1 N/C
;
; A 0.01uF decoupling capacitor connects between pins 14 and 5.
;
; The unit can be powered from 3, 1.5v cells in series. You may want to
; add an on/off switch (this is also the only way to reset the unit).
;
;**********************************************************************
;
TITLE “K8 Morse Keyer”
LIST P=16F628A, R=D
#include
;
;**********************************************************************
;***************** K8 Customization Header ****************************
;
; The following defines setup the basic configuration of the K8
; take a look at how they are used in the code to get an understanding
; of how they work. If you leave them as they are here you will get
; a working K8 without beacon mode, code protect off.
;
; If you don’t know what you are doing, only modify the
; CALL, SPEED_DEFAULT, message selection, and AR_ON
;
; DON’T CHANGE MODE_DEFAULT, PERIOD, or SPD_CONST
; unless you are thoroughly familiar
; with the code.
;——————————————————————-
;
; Define STANDARD, QRP, CQTEST, or CONTEST default operation
#define STANDARD ; can be: STANDARD, QRP, CQTEST, or CONTEST
;
; If debug is defined, the code protect if OFF
#define DEBUG ; default is defined
;
; If BEACON is defined, beacon mode enabled. See manual
; #define BEACON ; default is not defined
;
; Number of seconds for beacon repeat
#define BEACON_TIME 4
;
; Defining NO_DE modifies default messages (EWP?)
; #define NO_DE
;
; Defining SETFARNS enables the Farnsworth option
; #define SETFARNS
;
; AR or or off in message, change as required
#define AR_ON ; comment this out if you don’t want AR sent
;
; MODE_DEFAULT is a bitfield that sets the default mode
;
; Bit 0 = STEN, Sidetone enable, 1 is on
; Bit 1 = STRQ, Sidetone request, always 1 (EWP?)
; Bit 2 = always 0
; Bit 3 = SWAP paddles, 0 for normal
; Bit 4 = I_MODE, 1 for full IAMBIC mode, 0 DE mode (see manual)
; Bit 5 = IAM_A, Iambic Mode A flag (A=1, B=0)
; Bit 6 = SKM, Straight Key Mode enable when 1
; Bit 7 = ASP, Autospace enable bit, on when 1
;
MODE_DEFAULT EQU 013H ; IAM_B mode + ASP off (original)
; MODE_DEFAULT EQU 0B3H ; IAM_A mode + ASP on (alternate)
;
;——————————————————-
; Morse Equates Table
; These need to be defined first but
; should NOT be changed
;
M_END EQU 0x00 ; Ending delimiter
M_SKIP EQU 0x01 ; Skip this entry
M_SP EQU 0x02 ; Word space
M_USER EQU 0x03 ; Toggle to USER RAM
M_CALL EQU 0x05 ; Toggle to USER Callsign
M_TO EQU 0x80 ; Timeout return from GETCW
M_0 EQU 0xFC ; 0 1111 1100 = DAH-DAH-DAH-DAH-DAH
M_1 EQU 0x7C ; 1 0111 1100 = DI-DAH-DAH-DAH-DAH
M_2 EQU 0x3C ; 2 0011 1100 = DI-DI-DAH-DAH-DAH
M_3 EQU 0x1C ; 3 0001 1100 = DI-DI-DI-DAH-DAH
M_4 EQU 0x0C ; 4 0000 1100 = DI-DI-DI-DI-DAH
M_5 EQU 0x04 ; 5 0000 0100 = DI-DI-DI-DI-DIT
M_6 EQU 0x84 ; 6 1000 0100 = DAH-DI-DI-DI-DIT
M_7 EQU 0xC4 ; 7 1100 0100 = DAH-DAH-DI-DI-DIT
M_8 EQU 0xE4 ; 8 1110 0100 = DAH-DAH-DAH-DI-DIT
M_9 EQU 0xF4 ; 9 1111 0100 = DAH-DAH-DAH-DAH-DIT
M_AR EQU 0x54 ; 0101 0100 = DI-DAH-DI-DAH-DIT
M_SK EQU 0x16 ; 0001 0110 = DI-DI-DI-DAH-DI-DAH
M_PER EQU 0x56 ; 0101 0110 = DI-DAH-DI-DAH-DI-DAH
M_COM EQU 0xCE ; 1100 1110 = DAH-DAH-DI-DI-DAH-DAH
M_BT EQU 0x8C ; 1000 1100 = DAH-DI-DI-DI-DAH
M_QUE EQU 0x32 ; ? 0011 0010 = DI-DI-DAH-DAH-DI-DIT
M_DN EQU 0x94 ; 1001 0100 = DAH-DI-DI-DAH-DIT
M_A EQU 0x60 ; A 0110 0000 = DI-DAH
M_B EQU 0x88 ; B 1000 1000 = DAH-DI-DI-DIT
M_C EQU 0xA8 ; C 1010 1000 = DAH-DI-DAH-DIT
M_D EQU 0x90 ; D 1001 0000 = DAH-DI-DIT
M_E EQU 0x40 ; E 0100 0000 = DIT
M_F EQU 0x28 ; F 0010 1000 = DI-DI-DAH-DIT
M_G EQU 0xD0 ; G 1101 0000 = DAH-DAH-DIT
M_H EQU 0x08 ; H 0000 1000 = DI-DI-DI-DIT
M_I EQU 0x20 ; I 0010 0000 = DI-DIT
M_J EQU 0x78 ; J 0111 1000 = DI-DAH-DAH-DAH
M_K EQU 0xB0 ; K 1011 0000 = DAH-DI-DAH
M_L EQU 0x48 ; L 0100 1000 = DI-DAH-DI-DIT
M_M EQU 0xE0 ; M 1110 0000 = DAH-DAH
M_N EQU 0xA0 ; N 1010 0000 = DAH-DIT
M_O EQU 0xF0 ; O 1111 0000 = DAH-DAH-DAH
M_P EQU 0x68 ; P 0110 1000 = DI-DAH-DAH-DIT
M_Q EQU 0xD8 ; Q 1101 1000 = DAH-DAH-DI-DAH
M_R EQU 0x50 ; R 0101 0000 = DI-DAH-DIT
M_S EQU 0x10 ; S 0001 0000 = DI-DI-DIT
M_T EQU 0xC0 ; T 1100 0000 = DAH
M_U EQU 0x30 ; U 0011 0000 = DI-DI-DAH
M_V EQU 0x18 ; V 0001 1000 = DI-DI-DI-DAH
M_W EQU 0x70 ; W 0111 0000 = DI-DAH-DAH
M_X EQU 0x98 ; X 1001 1000 = DAH-DI-DI-DAH
M_Y EQU 0xB8 ; Y 1101 1000 = DAH-DAH-DI-DAH
M_Z EQU 0xC8 ; Z 1100 1000 = DAH-DAH-DI-DIT
;
;——————————————-
; Code Speed Index Defines
; Each index points to a delay value in the
; code speed index table. Use the call IDX2SPD
; to convert index to speed delay.
; These need to be defined first but should
; NOT be changed
;
WPM_5 EQU 00D
WPM_6 EQU 01D
WPM_7 EQU 02D
WPM_8 EQU 03D
WPM_9 EQU 04D
WPM_10 EQU 05D
WPM_11 EQU 06D
WPM_12 EQU 07D
WPM_13 EQU 08D
WPM_14 EQU 09D
WPM_15 EQU 10D
WPM_16 EQU 11D
WPM_17 EQU 12D
WPM_18 EQU 13D
WPM_19 EQU 14D
WPM_20 EQU 15D
WPM_21 EQU 16D
WPM_22 EQU 17D
WPM_23 EQU 18D
WPM_24 EQU 19D
WPM_25 EQU 20D
WPM_26 EQU 21D
WPM_27 EQU 22D
WPM_28 EQU 23D
WPM_29 EQU 24D
WPM_30 EQU 25D
WPM_31 EQU 26D
WPM_32 EQU 27D
WPM_33 EQU 28D
WPM_34 EQU 29D
WPM_35 EQU 30D
WPM_36 EQU 31D
WPM_37 EQU 32D
WPM_38 EQU 33D
WPM_39 EQU 34D
WPM_40 EQU 35D
WPM_41 EQU 36D
WPM_42 EQU 37D
WPM_43 EQU 38D
WPM_44 EQU 39D
WPM_45 EQU 40D
WPM_46 EQU 41D
WPM_47 EQU 42D
WPM_48 EQU 43D
WPM_49 EQU 44D
;
MAXSPDIDX EQU WPM_49
;
; ————Callsign default, change as required ————-
;
CALL_0 EQU M_V ; Put your call here, letter by letter
CALL_1 EQU M_A ; No more than 7 characters
CALL_2 EQU M_3
CALL_3 EQU M_E
CALL_4 EQU M_P
CALL_5 EQU M_END
CALL_6 EQU M_END
CALL_7 EQU M_END
;
; – Speed default, change as required to any defined WPM_** symbol —
;
SPEED_DEFAULT EQU WPM_15 ; can be WPM_5 to WPM_49
;
;**************** End of Customization Header ***********************
;**********************************************************************
; Modify below this point only if you REALLY understand the code
;**********************************************************************
;**********************************************************************
; Configuration word selection, based on configuration parameters
;
ifdef BEACON
ifdef DEBUG
;development mode, code protect off, watchdog on
; __CONFIG _CP_OFF & _WDT_ON & _XT_OSC ; original EWP
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _CP_OFF & _LVP_OFF & _BODEN_OFF
else
;manufacture mode, code protect on, watchdog on
; __CONFIG _CP_ON & _WDT_ON & _XT_OSC ; original EWP
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _CP_ON & _LVP_OFF & _BODEN_OFF
endif
else
ifdef DEBUG
; manufacture mode, code protect off, watchdog off
; _lvp_off & _boden_off are required for strict ’84 compatibility EWP
; __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC; Original EWP
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _CP_OFF & _LVP_OFF & _BODEN_OFF
else
;manufacture mode, code protect on, watchdog off
; __CONFIG _CP_ON & _WDT_OFF & _XT_OSC; Original EWP
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _CP_ON & _LVP_OFF & _BODEN_OFF
endif
endif
;
PERIOD EQU 120D
SPD_CONST EQU 212D
;
;——————————————-
; PIC Specific Equates
;——————————————-
;
; standard register defines are taken from the include file
;
PC9 EQU Z ; makes BSF STATUS, PC9 (etc) no-ops
PC EQU PCL ; for 8-bit PC adds, etc
;
;——————————————-
; File Register Assignments
;——————————————-
;
GPIO EQU PORTB ; I/O Port – see below for changed pin assignments
CBLOCK 0x20 ; Registers, changed from ’84 X0C EWP
PROCLAT ; Process Latch
DELAYHI ; High delay counter register
DELAYLO ; Low delay counter register
TIMEBASE ; Morse Time Base
CURMSG ; Currently Selected Message
MODEREG ; Mode Bits
WTEMP ; for loading PCLATH
SPEEDIDX ; Current speed table index
FARNS ; Letterspacing
BX ;
AL ; General Purpose Registers
AH ;
CL ;
CH ;
DL ;
DH ;
USRCALL: 8 ; User Callsign
USERRAM: 16 ; User Message
ENDC
;
;——————————————-
; MPU Bit Assignments
; ** 16F84A uses port B **
;——————————————-
; These bits also used in PROCLAT, differ from port assignments
DITPDL EQU 00H ; IN DIT Paddle
DAHPDL EQU 01H ; IN DAH Paddle
PB EQU 03H ; IN Message/Config Push Button
;
XDITPDL EQU 04H ; RB4, IN DIT Paddle
XDAHPDL EQU 05H ; RB5, IN DAH Paddle
KEY EQU 00H ; RB0, OUT Keyed Output
XPB EQU 07H ; RB7, IN Message/Config Push Button
TONE EQU 02H ; RB2, OUT Sidetone Output
ifdef BEACON
BCON EQU 03H ; RB3, OUT Beacon Request Output
else
STK EQU 03H ; RB3, OUT Keyed Sidetone Output
endif
;
;——————————————-
; Mode Bit Assignments
;
; Note: The STEN bit *must* be enabled in
; MODE_DEFAULT so the signon character will
; be audible, it gets setup properly at the
; beginning of SERVICE.
;——————————————-
STEN EQU 00H ; Sidetone enable
STRQ EQU 01H ; Sidetone request
;
SWAP EQU 03H ; Swap paddles enable bit
I_MODE EQU 04H ; Full iambic mode enable (no auto DE message)
IAM_A EQU 05H ; Iambic Mode A flag (A=1, B=0)
SKM EQU 06H ; Straight Key Mode enable bit
ASP EQU 07H ; Autospace enable bit
;
STRQBIT EQU 02H ; Use this to XORF STRQ
SWAPBIT EQU 08H ; Use this to XORF SWAP
IAMBIT EQU 10H ; Use this to XORF I_MODE
IABBIT EQU 20H ; Use this to XORF IAM_A
SKMBIT EQU 40H ; Use this to XORF SKM
ASPBIT EQU 80H ; Use this to XORF ASP
;
;——————————————-
; PROCLAT Equates
;——————————————-
;
PDLMASK EQU 03H ; Mask: Paddle input bits
PROCMASK EQU 0FCH ; Mask: Process bits
INLAST EQU 02H ; Last input flag, 1 means Dit was just entered
USERON EQU 03H ; Use USERRAM as message source when set
CONVERSE EQU 04H ; Conversational mode flag (for DE message)
OUTLAST EQU 05H ; Last output flasg, 1 means Dit was sent last
BOTH_ON EQU 06H ; Both paddles were pressed, used in iambic mode B
TXSQ EQU 07H ; Transmit Key Squelch bit in PROCLAT
;
;——————————————-
; Miscellaneous Equates
;——————————————-
;
SELDELAY_H EQU 120D ; Delay constants for
SELDELAY_L EQU 240D ; SELDELAY routine
GC_TO_L EQU 220D ; GETCW timeout inside loop
GC_TO_M EQU 170D ; GETCW timeout middle loop
GC_TO_H EQU 3D ; GETCW timeout outside loop
SPEEDCNT EQU 4D ; Number of characters sent in SPEED loop
;
;*******************************************
; RESET ENTRY
;*******************************************
;
ORG 0
GOTO INIT
;
ORG 4
INTVEC GOTO INTVEC
;
;===========================================
; Subroutines
;
; Must reside in first
; 256 bytes of codespace
; (probably not necessary on the ‘628 EWP)
;===========================================
;===========================================
; Sample and Latch Input State
;===========================================
;
SAMPLE
CALL NSAMPLE
RETLW 0
;
NSAMPLE
ifdef BEACON
CLRWDT ; Reset watchdog timer
endif
BTFSC GPIO, XDITPDL
GOTO RIGHT_TEST
BTFSC MODEREG, SWAP
GOTO NS_DAH1
LEFT_TEST
BSF PROCLAT, DITPDL
BSF PROCLAT, INLAST ; Set on DIT
GOTO RIGHT_TEST
NS_DAH1
BSF PROCLAT, DAHPDL
BCF PROCLAT, INLAST ; Clear on DAH
RIGHT_TEST
BTFSC GPIO, XDAHPDL
GOTO NS_DONE
BTFSS MODEREG, SWAP
GOTO NS_DAH2
BSF PROCLAT, DITPDL
BSF PROCLAT, INLAST ; Clear on DAH
GOTO NS_DONE
NS_DAH2
BSF PROCLAT, DAHPDL
BCF PROCLAT, INLAST ; Set on DAH
NS_DONE
RETURN
;===========================================
; Send DIT
;===========================================
DITOUT
ifndef BEACON
BTFSC MODEREG, STEN ; Sidetone enabled ?
BSF GPIO, STK ; Key Sidetone
endif
BTFSS PROCLAT, TXSQ ; Transmit Key Squelch ?
BSF GPIO, KEY
CALL NDITDELAY
ifndef BEACON
BCF GPIO, STK ; Unkey Sidetone
endif
BCF GPIO, KEY
CALL NDITDLY_NT
BCF PROCLAT, DITPDL ; Clear DIT bit in paddle register
BSF PROCLAT, OUTLAST ; Mark that Dit was sent
RETLW 0
;===========================================
; Send DAH
;===========================================
DAHOUT
ifndef BEACON
BTFSC MODEREG, STEN ; Sidetone enabled ?
BSF GPIO, STK ; Key Sidetone
endif
BTFSS PROCLAT, TXSQ ; Transmit Key Squelch ?
BSF GPIO, KEY
MOVLW 3
MOVWF BX
NDLP
CALL NDITDELAY
DECFSZ BX, F
GOTO NDLP
ifndef BEACON
BCF GPIO, STK ; Unkey Sidetone
endif
BCF GPIO, KEY
CALL NDITDLY_NT
; if (I_MODE is off &&
; we are in conversational mode &&
; both paddles are pressed)
; then GOTO TRAILER
BCF PROCLAT, DAHPDL ; Clear DAH bit in paddle register
BCF PROCLAT, OUTLAST ; Mark that Dah was sent
BTFSS MODEREG, I_MODE ; Is DE mode allowed ?
BTFSC PROCLAT, CONVERSE ; Not in converse or iambic modes
RETLW 0 ; No, return
BTFSS GPIO, XDAHPDL
BTFSC GPIO, XDITPDL ; if both paddles pressed goto TRAILER
RETLW 0 ; else return
;===========================================
; Send Trailer Message
;===========================================
TRAILER
; BCF PROCLAT, CONVERSE ; End conversational mode
ifdef NO_DE
CALL DITOUT ; Send rest of ‘K’
CALL DAHOUT
else
CALL DITOUT ; Send rest of ‘D’
CALL DITOUT
endif
CALL LETTERSPACE
TRAIL0
BTFSC GPIO, XDITPDL ; Wait till both paddles
BTFSS GPIO, XDAHPDL ; are released
GOTO TRAIL0
MOVLW MSG7-MSGBASE ; Point to ‘DE’+1 message
GOTO L_SENDMSG ; We will return to caller from there
;===========================================
; Wait sidetone delay with transmitter
; keyed. Used by TUNE & KEYDIRECT
; TUNE and KEYDIRECT call NDITDELAY thru
; STCLK, which sets an outside loop count
; of 1 and a reduced sidetone “low” time.
; This gives us a better match between
; KEYER and TUNE/KEYDIRECT sidetone.
;===========================================
STCLK
MOVLW 10D ; Ten passes
GOTO DITDEL
;===========================================
; Dit Delay
;
; Set delay period to be 1.15mSec to give a
; sidetone frequency of 800Hz.
;===========================================
NDITDELAY
MOVF TIMEBASE, W ; Get interval
DITDEL
MOVWF DELAYHI
MOVLW PERIOD-4 ; Compensate for NSAMPLE
GOTO DITDEL15
DITDEL0
MOVLW PERIOD ; 1/2 Period High, 575 us
DITDEL15
MOVWF DELAYLO
DITDEL1
GOTO DTL0
DTL0
DECFSZ DELAYLO, F ; Inner Loop 1 Test
GOTO DITDEL1
BTFSC MODEREG, STEN ; Sidetone enabled ?
BSF GPIO, TONE ; Key Sidetone
MOVLW PERIOD ; 1/2 Period Low, 575 us
MOVWF DELAYLO
DITDEL2
GOTO DTL1
DTL1
DECFSZ DELAYLO,F ; Inner Loop 2 Test
GOTO DITDEL2
BCF GPIO, TONE ; Unkey Tone
DECFSZ DELAYHI,F ; Outer Loop Test
GOTO DITDEL0
GOTO NSAMPLE ; Latch early input
; RETURN from there
;
;===========================================
; Dit Delay without Sidetone
;===========================================
NDITDLY_NT
MOVF TIMEBASE, W ; Get interval
MOVWF DELAYHI
DD_NT0
MOVLW PERIOD ; 1/2 Period
MOVWF DELAYLO
DD_NT1
GOTO DNT0
DNT0
GOTO DNT1
DNT1
GOTO DNT2
DNT2
NOP
DECFSZ DELAYLO, F ; Inner Loop Test
GOTO DD_NT1
DECFSZ DELAYHI,F ; Outer Loop Test
GOTO DD_NT0
GOTO NSAMPLE ; Latch early input
; RETURN from there
;
;===========================================
; Autospace Handler
;
; The idea is to keep the morse “pipe” full,
; that means that there should always be
; something in PROCLAT to send after the
; current dit or dah is sent. If not it is
; interpreted as an intercharacter space
; and a pause is inserted to fill out the
; remainder of a letterspace period.
; Any paddle events will be recorded in
; PROCLAT and issued in the order received
; thanks to the INLAST bit.
;===========================================
AUTOSP
CALL SAMPLE ; Refresh PROCLAT
BTFSS MODEREG, ASP ; Leave if autospace disabled
GOTO SERVLOOP
BTFSS PROCLAT, DITPDL ; Check if any in latch
BTFSC PROCLAT, DAHPDL
GOTO SERVLOOP ; Yes: go send
CALL LETTERSPACE ; No: wait full letterspace
GOTO SERVLOOP ; before allowing more sending
;
;===========================================
; Word and Letter Spacing
;
; Remember that all characters have one
; dit delay tacked on automatically so
; only two are needed to provide a three
; bit letterspace. Six are needed for a
; seven bit word space. Extra letterspace
; is added via the value FARNS.
;===========================================
WORDSPACE
MOVLW 6
GOTO WLSPAC0
LETTERSPACE
MOVLW 2
WLSPAC0
BTFSS PROCLAT, CONVERSE ; no extra space in converse mode
ADDWF FARNS, W
MOVWF BX
WLSPAC1
CALL NDITDLY_NT
DECFSZ BX, F
GOTO WLSPAC1
RETLW 0
;===========================================
; Output Single Morse Character
; Uses AL
;===========================================
OSCHAR
MOVWF AL ; Copy character
OSLOOP
MOVF AL, W ; Get coded morse
ADDWF AL, F ; AL*2, if (Z==0) DONE else C=DIT/DAH
BTFSS STATUS, Z ; Skip if zero
GOTO OSCONT
CALL LETTERSPACE ; Inter-letter space
RETLW 0 ; All done, return
OSCONT
BTFSC STATUS, C ; (C==1) then DAH else DIT
GOTO OSDAH
CALL DITOUT
GOTO OSLOOP
OSDAH
CALL DAHOUT
GOTO OSLOOP
;===========================================
; Decimal to Morse Conversion Table
;===========================================
DEC2CW
MOVWF WTEMP
MOVLW HIGH($)
MOVWF PCLATH
MOVF WTEMP,W
ADDWF PC, F ; Jump through table
DECTBL
RETLW M_0
RETLW M_1
RETLW M_2
RETLW M_3
RETLW M_4
RETLW M_5
RETLW M_6
RETLW M_7
RETLW M_8
RETLW M_9
;===========================================
; Cross Page Jumps
;
; Note 1: Routines in high page assume they
; called from low page and clear PC9 before
; they return. It is not possible to call
; a high page routine from the high page.
;
; Note 2: Subroutines above the 256 byte
; boundary are called through this interface.
; A call is converted to a jump, the called
; subroutine in high page ends with a return
; which pops the full 10 bit return address
; of the low page caller.
;
; (This is probably not necessary for the ‘628
; but appears to work EWP)
;===========================================
L_SENDMSG
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO SENDMSG
L_CW2IDX
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO CW2IDX
L_IDX2SPD
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO IDX2SPD
L_GETCW
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO GETCW
L_CONV_HI
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO CONV_HI
L_CONV_LO
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO CONV_LO
;===========================================
; Long delay for user prompts
; Uses: CL
; Returns:
; CL MSB=1 if paddle pressed, 0 if not
;===========================================
SELDELAY
MOVLW SELDELAY_H ; Set high select delay
MOVWF DELAYHI
SELD0
MOVLW SELDELAY_L ; Set low select delay
MOVWF DELAYLO
SELD1
CALL SAMPLE ; Latch paddle press
GOTO SLD0
SLD0
DECFSZ DELAYLO, F ; Inner Loop 1 Test
GOTO SELD1
DECFSZ DELAYHI, F ; Inner Loop 1 Test
GOTO SELD0
BTFSS PROCLAT, DAHPDL ; DAH closed ?
BTFSC PROCLAT, DITPDL ; DIT closed ?
GOTO SDYES
SDNO
BCF CL, 0 ; Timed out w/no paddle pressed
GOTO SDRET
SDYES
BSF CL, 0 ; A paddle was pressed
SDRET
RETLW 0
;===========================================
; Push Button Switch Handler
; Converse mode is defined as the phase
; where the user is actually entering some
; morse letters. We want letterspace off
; to improve response, and we want DE mode
; off to prevent undesired output.
;===========================================
CONFIG
; ——- Disable Letterspace Here ———–
BSF PROCLAT, CONVERSE ; Start converse mode
BSF PROCLAT, TXSQ ; Disable Key
BSF MODEREG, STEN ; Force sidetone
MOVLW M_R ; Signal user to enter code
CALL OSCHAR
CONFWT
CLRWDT
BTFSS GPIO, XPB ; Still closed ?
GOTO CONFWT ; wait till released
CALL L_GETCW ; Get user response
CALL L_CW2IDX ; Translate CW to table index
BCF STATUS, PC9 ; Clear page bit
MOVWF WTEMP
MOVLW HIGH($)
MOVWF PCLATH
MOVF WTEMP,W
ADDWF PC, F ; Jump through table
GOTO SIDETONE ; A=Sidetone enable
GOTO LOADCALL ; C=Load new callsign
GOTO FARNSWORTH ; F=Farnsworth Adjust
GOTO IAMBIC ; I=Iambic mode toggle
GOTO KEYMODE ; K=Keyer mode
GOTO LOADUSER ; L=Load user RAM
GOTO SPEED ; S=Speed
GOTO TUNE ; T=Tune
GOTO ASP_TOGGLE ; U=Autospace Toggle
GOTO SWAP_TOGGLE ; X=Swap Paddles Toggle
GOTO DE_TOGGLE ; Z=DE Mode Toggle
; ——- Allow Letterspace for below ———
GOTO DUMPUSER ; D=Play user RAM
GOTO MSGSELECT ; M=Message select
GOTO PRACTICE ; P=Practice mode
GOTO OUTWPM ; W=Report Morse speed
GOTO QUERET ; Unknown entry !?!?
; Use common return
;*******************************************
; Wake Up Handler
; BX is used as a beacon timer, it is
; initialized at the end of QVRET.
; The OPTION register is setup so that WDT
; will cause a reset every 2 seconds. From
; INIT we will get vectored here. Where
; BX will be checked to see if it is zero.
; If so pin 2 will be configured as an output
; and asserted low true. If BX is not zero
; it is is decremented. Note that a pin
; change will be handled in the same manner
; as a WDT timeout but this is moot since
; the beacon enable switch will be off in
; non-beacon mode. BX will normally rest at
; a value of zero courtesy of the DAHOUT and
; LETTERSPACE routines.
;*******************************************
ifdef BEACON
WAKEUP
MOVF BX, W ; Test beacon timer
BTFSC STATUS, Z ; If zero: Beacon ON
GOTO BEAC_ON
DECF BX, F ; Else: Decrement beacon timer
GOTO SERVICE ; Continue in case it was
; a pin change wakeup
BEAC_ON
BCF GPIO, BCON ; Insure that GP5 reg is zero
MOVLW B’11110000′ ; Make RB3 an output
BSF STATUS, RP0
MOVWF TRISB ^ 0x80 ; to assert beacon request
BCF STATUS, RP0
endif
;*******************************************
;* MAIN GPIO Service Routine *
;*******************************************
SERVICE
BCF MODEREG, STEN ; Restore user’s
BTFSC MODEREG, STRQ ; sidetone
BSF MODEREG, STEN ; preference.
CLRF PROCLAT ; Clear TXSQ and any latched inputs
SERVLOOP
CALL SAMPLE
BTFSS MODEREG, SKM ; Straight key mode ?
GOTO KEYER ; No: Go keyer
BTFSC PROCLAT, DAHPDL ; DAH paddle pressed ?
GOTO KEYDIRECT ; Yes: Go straight key
GOTO PBTEST ; No: Test pushbutton
;
; Iambic operation: If iambic mode is enabled the following state
; machine outputs alternating dits and dahs when both paddles are
; pressed at the same time. DIT_PADDLE = GPIO, DIT_PADDLE_L = PROC_LAT
;
; if ((DIT PADDLE && DAH PADDLE) && (I_MODE == TRUE)
; {
; set BOTH_ON “ref. Mode B”
; if (DIT LAST) {
; send DAH
; clear DIT LAST
; }
; else {
; (this also handles odd case where both paddles
; hit simultaneously)
; send DIT
; set DIT LAST
; }
; }
; else if (BOTH_ON == TRUE) { “ref: Mode B, BOTH_ON is
; clear BOTH_ON never set in MODE A”
; if (DIT LAST)
; send DAH
; else
; send DIT
; }
; else {
; if (L_DIT_PADDLE && L_DAH_PADDLE) {
; if (INLAST) {
; send DAH
; clear DIT LAST
; }
; else {
; send DIT
; set DIT LAST
; }
; }
; if (DIT PADDLE) {
; send DIT
; set DIT LAST
; }
; else if (DAH PADDLE) {
; send DAH
; clear DIT LAST
; }
; else {
; (if neither paddle is set, do nothing)
; }
; }
; }
KEYER
BTFSS MODEREG, I_MODE ; DE mode ?
GOTO CHK_SINGLE ; Yes: Skip
;
; Iambic mode A and B operation depend on PROCLAT, BOTH_ON and current
; state of the paddles. In mode B PROCLAT is used to check if the
; both paddles were pressed at the end of toggle mode to see if an
; extra dit or dah are sent.
; In mode A the PROCLAT is cleared when leaving toggle mode to
; prevent any additional dits or dahs from being sent.
;
; We check GPIO here since we need to monitor real time paddle
; status, the case where both are set in PROCLAT must be
; handled specially since order must be observed.
BTFSS GPIO, XDITPDL ; DIT paddle *and*
BTFSC GPIO, XDAHPDL ; DAH paddle pressed ?
GOTO CHK_BOTH_ON ; No: Go check if both is pending
; Both Paddles are pressed
BSF PROCLAT, BOTH_ON ; Set both paddles on flag
TOGGLE
BTFSC PROCLAT, OUTLAST ; If LAT==1 (dit was last) then DAH
GOTO LPDAH ;
GOTO LPDIT ; else, always DIT. This addresses
; the case where both paddles hit at
; the same time.
; Both paddles aren’t pressed, check if they just were
; and if in MODE B, issue alternate. Otherwise just
; check for single dit or dah request.
CHK_BOTH_ON
BTFSS PROCLAT, BOTH_ON
GOTO CHK_SINGLE
BCF PROCLAT, BOTH_ON
BTFSS MODEREG, IAM_A
GOTO TOGGLE ; Mode B, send one more
CLRF PROCLAT ; Mode A, kill any in latch
GOTO AUTOSP
; First check to see if both bits are set, if they are we
; need to figure out which one to send first. INLAST tells
; the last paddle input received, so the opposite is sent.
CHK_SINGLE
BTFSC PROCLAT, DITPDL
BTFSS PROCLAT, DAHPDL
GOTO CHK_S1
BTFSC PROCLAT, INLAST ; INLAST = 1 if DIT was last
GOTO LPDAH
; Fall thru, and a DIT gets sent
CHK_S1
BTFSC PROCLAT, DITPDL ; DIT Paddle closed when = 1
GOTO LPDIT
BTFSS PROCLAT, DAHPDL ; DAH Paddle closed when = 1
GOTO PBTEST
LPDAH
CALL DAHOUT
GOTO AUTOSP
LPDIT
CALL DITOUT
GOTO AUTOSP
PBTEST
BTFSS GPIO, XPB ; Push Button closed when = 0
GOTO PBHANDLE ; changed logic of skip (imw)
;
;===========================================
; Go into sleep mode until one
; of the switches are hit or
; Watchdog timer times out.
;===========================================
;
SLEEP ; RB change will wake us up. Since GIE not enabled, arrive
NOP ; here.
BCF INTCON, 0 ; clear RBIF
GOTO SERVICE ; resume
PBHANDLE ; jump logic changed for jump around sleep, etc
ifdef BEACON
MOVLW B’11111000’ ; Restore Pin 2 as an input
BSF STATUS, RP0 ; to cancel beacon request
MOVWF TRISB ^ 0x80
BCF STATUS, RP0
endif
CALL SELDELAY
BTFSC GPIO, XPB ; Is Push Button closed ? (==0)
GOTO PBMSG ; No: output message
CALL SELDELAY ; Yes: wait again
BTFSS GPIO, XPB ; Is Push Button closed ? (==0)
GOTO CONFIG ; Yes: do config routine
PBMSG ; No: output message
MOVF CURMSG, W ; Point to ‘current’ message
GOTO QVRET
;===========================================
; Key transmitter for tuning
;===========================================
TUNE
BTFSS MODEREG, STRQ ; Restore sidetone
BCF MODEREG, STEN ; preference.
ifndef BEACON
BTFSC MODEREG, STEN ; Sidetone enabled ?
BSF GPIO, STK ; Key Sidetone
endif
BSF GPIO, KEY ; Key transmitter
TUNELP
CALL STCLK ; Key XMTR and delay w/sidetone
BTFSC PROCLAT, DAHPDL ; DAH paddle ends tune
GOTO WAIT4OFF
BTFSS PROCLAT, DITPDL ; DIT paddle ends tune
GOTO TUNELP
; Fall through
;===========================================
; Wait for paddle release
;===========================================
WAIT4OFF
MOVLW 25D ; debounce count
MOVWF AL
WAIT4LP
ifdef BEACON
CLRWDT ; Reset watchdog timer
endif
BTFSC GPIO, XDITPDL ; Make sure paddles
BTFSS GPIO, XDAHPDL ; remain unpressed
GOTO WAIT4OFF
DECFSZ AL, F
GOTO WAIT4LP
ifndef BEACON
BCF GPIO, STK ; Unkey Sidetone
endif
BCF GPIO, KEY ; Unkey transmitter
GOTO SERVICE
;===========================================
; Key XMTR for straight key mode
;
; We only look at one paddle for straight
; keying but the user can select which one
; with the swap command.
;===========================================
KEYDIRECT
BTFSS MODEREG, STRQ ; Restore sidetone
BCF MODEREG, STEN ; preference.
ifndef BEACON
BTFSC MODEREG, STEN ; Sidetone enabled ?
BSF GPIO, STK ; Key Sidetone
endif
BSF GPIO, KEY ; Key transmitter
KEYDLP
BCF PROCLAT, DAHPDL ; Clear latched DAH
CALL STCLK ; Key XMTR and delay w/sidetone
BTFSC PROCLAT, DAHPDL ; DAH paddle still pressed ?
GOTO KEYDLP ; Yes: Loop
GOTO WAIT4OFF ; No: Leave via debounce
;===========================================
; Set Extra Letterspace
; Uses: AH, CL
;===========================================
FARNSWORTH
MOVLW M_E ; Ask for Number
CALL OSCHAR
CALL L_GETCW ; Get user response in AH
MOVLW M_TO ; Did user just sit there ?
SUBWF AH, W
BTFSC STATUS, Z
GOTO QUERET ; Yes, end it
MOVLW 80H ; Validity check value
MOVWF CL ; save it for later
CALL L_CONV_LO ; Convert AH to 1’s
BCF STATUS, PC9 ; Clear page bit
ADDWF CL, W ; Check value
BTFSS STATUS, C ; Valid if Carry = 1
GOTO QUERET
MOVWF FARNS ; Set new Farnsworth adj.
GOTO COMRET_R
;===========================================
; Set New CW Sending Speed
; Uses: AH, CL, CH
;===========================================
SPEED
CLRF CH ; Init pass count
SPLOOP
MOVLW M_E ; Ask for Number
CALL OSCHAR
CALL L_GETCW ; Get user response in AH
MOVLW M_TO ; Did user just sit there ?
SUBWF AH, W
BTFSC STATUS, Z
GOTO QUERET ; Yes, end it
BTFSC CH, 0 ; Skip on 1st pass
GOTO SPSUM
CALL L_CONV_HI ; Convert AH to 10’s
BCF STATUS, PC9 ; Clear page bit
MOVWF CL ; Save MSN
BSF CH, 0 ; Set pass flag
GOTO SPLOOP
SPSUM
CALL L_CONV_LO ; Convert AH to 1’s
BCF STATUS, PC9 ; Clear page bit
ADDWF CL, F ; Add in MSN
BTFSS STATUS, C ; If both are valid both MSBs = 1
GOTO QUERET ; So if Carry=1 we have good values
MOVLW -5D ; Adjust for indexing
ADDWF CL, W ; And verify low limit
BTFSS STATUS, C ; C==1 if >= 5, error if not
GOTO QUERET
MOVWF SPEEDIDX
CALL L_IDX2SPD ; Convert index to delay constant
BCF STATUS, PC9 ; Clear page bit
MOVWF TIMEBASE ; Store it away
GOTO COMRET_R
QUERET
MOVLW M_QUE ; Send ? for error
GOTO COMRET
;===========================================
; Message Selection
;===========================================
MSGSELECT
CALL SELDELAY
MSGLOOP
MOVLW MSG2-MSGBASE ; Select message 2: Short CQ
MOVWF CURMSG
MOVLW M_C ; C
CALL OSCHAR
MOVLW M_Q ; Q
CALL OSCHAR
CALL SELDELAY
BTFSC CL, 0 ; Paddle closure ?
GOTO MSGDONE ; Yes, all done
MOVLW MSG1-MSGBASE ; Select message 1: Variable
MOVWF CURMSG
ifdef CQTEST
MOVLW M_C ; C
CALL OSCHAR
MOVLW M_Q ; Q
CALL OSCHAR
MOVLW M_T ; T
CALL OSCHAR
endif
ifdef CONTEST
MOVLW M_T ; T
CALL OSCHAR
MOVLW M_S ; S
CALL OSCHAR
MOVLW M_T ; T
CALL OSCHAR
endif
ifdef QRP
MOVLW M_Q ; Q
CALL OSCHAR
MOVLW M_R ; R
CALL OSCHAR
MOVLW M_P ; P
CALL OSCHAR
endif
ifdef STANDARD
MOVLW M_C ; C
CALL OSCHAR
MOVLW M_Q ; Q
CALL OSCHAR
MOVLW M_L ; L
CALL OSCHAR
endif
CALL SELDELAY
BTFSC CL, 0 ; Paddle closure ?
GOTO MSGDONE ; Yes, all done
MOVLW MSG3-MSGBASE ; No, select message 3
MOVWF CURMSG
MOVLW M_D ; D
CALL OSCHAR
MOVLW M_X ; X
CALL OSCHAR
CALL SELDELAY
BTFSC CL, 0 ; Paddle closure ?
GOTO MSGDONE ; Yes, all done
MOVLW MSG4-MSGBASE ; No, select message 4
MOVWF CURMSG
MOVLW M_C ; C
CALL OSCHAR
MOVLW M_Q ; Q
CALL OSCHAR
MOVLW M_C ; C
CALL OSCHAR
CALL SELDELAY
BTFSC CL, 0 ; Paddle closure ?
GOTO MSGDONE ; Yes, all done
MOVLW MSG5-MSGBASE ; No, select message 5
MOVWF CURMSG
MOVLW M_M ; M
CALL OSCHAR
MOVLW M_S ; S
CALL OSCHAR
MOVLW M_G ; G
CALL OSCHAR
CALL SELDELAY
BTFSS CL, 0 ; Paddle closure ?
GOTO MSGLOOP ; No: loop till user picks one
MSGDONE
MOVLW M_R ; Yes: Send an ‘R’ for acknowledgement
CALL OSCHAR
GOTO WAIT4OFF ; Common “wait then return”
;===========================================
; Paddle Swap Toggle
;===========================================
SWAP_TOGGLE
MOVLW SWAPBIT
GOTO COMXOR ; Shared XOR
;===========================================
; Sidetone Toggle
;===========================================
SIDETONE
MOVLW STRQBIT
GOTO COMXOR ; Shared XOR
;===========================================
; Toggle Keyer Mode
; Default is keyer mode, everytime this
; is called the mode will toggle between
; keyer and straight key mode.
;===========================================
KEYMODE
MOVLW SKMBIT
COMXOR
XORWF MODEREG, F ; Shared XOR
GOTO MSGDONE ; Common return, R for ack
;
;===========================================
; Toggle Iambic Mode
; Toggle the iambic mode between Mode A
; which is not self completing and Mode B
; which is. Self completing means an extra
; alternate element is sent after both
; paddles are released.
;===========================================
IAMBIC
MOVLW IABBIT
XORWF MODEREG, F
MOVLW M_A ; Assume Iambic mode A
BTFSS MODEREG, IAM_A ; A=1, B=0
MOVLW M_B ; Assumed wrong, it’s B
GOTO COMRET
;===========================================
; Autospace Toggle
;===========================================
ASP_TOGGLE
MOVLW ASPBIT
XORWF MODEREG, F
MOVLW M_A ; Assume Autospace mode
BTFSS MODEREG, ASP ; Autospace=1, Normal=0
MOVLW M_N
GOTO COMRET
;===========================================
; Toggle DE Mode
; Toggle the user defined iambic enable
; In iambic mode, when both paddles are
; pressed alternating dits/dahs are sent.
; I_MODE off will allow the use of the
; automatic ‘DE’ message.
;===========================================
DE_TOGGLE
MOVLW IAMBIT
XORWF MODEREG, F
MOVLW M_D ; Assume DE mode
BTFSC MODEREG, I_MODE
MOVLW M_I ; Assumed wrong, it’s iambic mode
GOTO COMRET ; Use shared return
;===========================================
; Code Practice
; Send a stream of random CW characters
;===========================================
PRACTICE
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO PRAC_RUN
;===========================================
; Load RAM Routine
; Two entry points, one for loading callsign
; and a second for loading user message.
;
; Uses AH, CL
;===========================================
LOADCALL
MOVLW USRCALL ; Point to start of callsign string
MOVWF FSR
MOVLW 08H ; Max callsign length (8 decimal)
GOTO LU00
LOADUSER
MOVLW USERRAM ; Point to start of user string
MOVLW 0FH ; Max string length (15 decimal)
LU00
MOVWF CL ; Length in reg CL
; CLRF INDF ; In case nothing is entered
LULOOP
MOVLW M_E ; Signal user to enter code
CALL OSCHAR
CALL L_GETCW ; Get a letter in AH
MOVLW M_PER ; Did user explicitly end ?
SUBWF AH, W
BTFSC STATUS, Z
GOTO LUDONE ; Yep, leave
MOVLW M_TO ; Did user just sit there ?
SUBWF AH, W
BTFSS STATUS, Z
GOTO LU0 ; No, we have a valid character
MOVLW M_SP ; Yes, they want a space
GOTO LU1
LU0
MOVF AH, W ; Get char
LU1
MOVWF INDF ; Store in RAM
INCF FSR, F ; Bump counter
MOVLW M_END ; Append an EOS token
MOVWF INDF ; Store in RAM
DECFSZ CL, F ; Decrement length count
GOTO LULOOP
LUDONE
; Fall thru to common return
;===========================================
; Common Return
;===========================================
COMRET_R
MOVLW M_R ; Send a “roger”
COMRET
CALL OSCHAR
GOTO SERVICE
;
;===========================================
; Dump User String
;===========================================
DUMPUSER
MOVLW MSG5-MSGBASE ; Point to USER message
QVRET
CALL L_SENDMSG ; We will return to caller from there
MOVLW BEACON_TIME
MOVWF BX
GOTO SERVICE
;===========================================
; Report Morse speed
;===========================================
OUTWPM
MOVLW 5D ; Slowest speed
ADDWF SPEEDIDX, W ; Add index
OUTDEC
CLRF CH ; Clear tens register
MOVWF CL ; Copy decimal number
MOVLW 10D ; Base 10
ODLOOP
SUBWF CL, F ; Extract 10’s
BTFSS STATUS, C ; C==0 : Underflow
GOTO ODNEG
INCF CH, F ; Incr 10’s
GOTO ODLOOP
ODNEG
ADDWF CL, F ; Restore ones to positive
MOVF CH, W ; Output 10’s first
BTFSC STATUS, Z ; Suppress leading zero
GOTO ODONES
CALL DEC2CW
BCF STATUS, PC9 ; Clear page bit
CALL OSCHAR
ODONES
MOVF CL, W ; Output 1’s
CALL DEC2CW
BCF STATUS, PC9 ; Clear page bit
CALL OSCHAR
MOVLW MSG8-MSGBASE ; Send WPM string
GOTO QVRET ; Use shared return
;*******************************************
;* Initialization Routine *
;*******************************************
INIT BCF STATUS, RP0 ;on ‘628 for ’84 compat on Bank0
MOVLW H’07’ ;Init CMCON for digital IO
MOVWF CMCON ;on PORTA
;
ifdef BEACON
MOVLW B’11111000′ ; IN:RB7,6,5,4,3 OUT:RB2,1,0
else
MOVLW B’11110000′ ; IN:RB7,6,5,4 OUT:RB3,2,1,0
endif
BSF STATUS, RP0
MOVWF TRISB ^ 0x80
MOVLW 0
MOVWF TRISA ^ 0x80 ; A = all outputs
MOVLW B’00001110′ ; Enable PUs, Pscl->WDT
MOVWF OPTION_REG ^ 0x80 ; Timer Clk=Internal, Prescale=1:64
BCF STATUS, RP0
CLRF GPIO ; Note: Beacon Request is asserted
; but not active since RB3 is an input
MOVLW B’00001000′ ; Enable RB port change interrupt (but NOT GIE)
MOVWF INTCON
ifdef BEACON
BTFSS STATUS, PD ; Is this is a power up or dead man WDT ?
; Finish reset if so
GOTO WAKEUP ; else: Go do wakeup stuff
else
; TODO – implement wake-on-interrupt
endif
ifdef SETFARNS
MOVLW 1 ; CAN ONLY USE THIS IN NON_BEACON MODE !!!
MOVWF FARNS
else
CLRF FARNS ; Initialize Farnsworth adj.
endif
MOVLW SPEED_DEFAULT ; Initialize Morse Timebase
MOVWF SPEEDIDX
CALL L_IDX2SPD ; Convert index to delay constant
BCF STATUS, PC9 ; Clear page bit
MOVWF TIMEBASE ; Store it away
MOVLW MODE_DEFAULT ; Load MODEREG default
MOVWF MODEREG
MOVLW USERRAM
MOVWF FSR ; Use indirect addressing
CLRF INDF ; To init user message empty
MOVLW USRCALL ; Load callsign into RAM
MOVWF FSR ; Use indirect addressing
BSF STATUS, PC9 ; Set PAGE bit for long GOTO
GOTO XFRSTUB
XFRRET
MOVLW MSG2-MSGBASE ; Select message 2: Short CQ
MOVWF CURMSG ; as default
BSF PROCLAT, TXSQ ; Don’t transmit, just run sidetone
; SERVICE will reset TXSQ
MOVLW M_R ; Send R for hello
BTFSS GPIO, XDAHPDL ; Hook to get version
MOVLW M_G ; Send Version ID
GOTO COMRET ; Use common return entry
;===========================================
; Page Boundary
;===========================================
ORG 0300h ; change from 200 to make
; room for extra 628 code EWP
;===========================================
; Move W to (FSR++)
;===========================================
XFRIDX
MOVWF INDF
INCF FSR, F
RETLW 0
;===========================================
; Message Table
;===========================================
; Call with message pointer in DH reg
; Table entry *DH++ is returned in W.
; We start at a new page to allow us to have
; a long message table which we can be sure
; will never cross a page boundary.
; Note: CALLs and computed jumps will always
; clear the PC[8] bit. PC[9] is sourced from
; STATUS reg bit 5.
GETMSG
MOVF DH, W
INCF DH, F
MOVWF WTEMP
MOVLW HIGH($)
MOVWF PCLATH
MOVF WTEMP,W
ADDWF PC, F ; Jump through table
;—————————————————–
MSGBASE
MSG1
ifdef CONTEST
RETLW M_T ; Contest Message
RETLW M_E
RETLW M_S
RETLW M_T
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_T ; Contest Message
RETLW M_E
RETLW M_S
RETLW M_T
RETLW M_SP
RETLW M_END
endif
ifdef CQTEST
RETLW M_C ; CQ TEST
RETLW M_Q
RETLW M_SP
RETLW M_T
RETLW M_E
RETLW M_S
RETLW M_T
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_T
RETLW M_E
RETLW M_S
RETLW M_T
RETLW M_SP
RETLW M_D
RETLW M_E
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_K
RETLW M_END
endif
ifdef QRP
RETLW M_C ; QRP
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_D
RETLW M_E
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
; RETLW M_SP
RETLW M_DN
RETLW M_Q
RETLW M_R
RETLW M_P
RETLW M_SP
ifdef AR_ON
RETLW M_AR
RETLW M_SP
endif
RETLW M_K
RETLW M_END
endif
ifdef STANDARD
RETLW M_C ; Long CQ Message
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_D
RETLW M_E
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
RETLW M_SP
endif
;
MSG2
RETLW M_C ; CQ Message
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_D
RETLW M_E
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
RETLW M_SP
; RETLW M_CALL ;extra
; RETLW M_SP ;extra
ifdef AR_ON
RETLW M_AR
RETLW M_SP
endif
RETLW M_K
RETLW M_END
;
MSG3
RETLW M_C ; CQ DX Message
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_C
RETLW M_Q
RETLW M_SP
RETLW M_D
RETLW M_X
RETLW M_SP
RETLW M_D
RETLW M_E
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_D
RETLW M_X
RETLW M_SP
ifdef AR_ON
RETLW M_AR
RETLW M_SP
endif
RETLW M_K
RETLW M_END
;
MSG4
RETLW M_USER ; Custom Contest Message
RETLW M_SP
RETLW M_D
RETLW M_E
RETLW M_SP
RETLW M_CALL
RETLW M_SP
RETLW M_CALL
RETLW M_SP
ifdef AR_ON
RETLW M_AR
RETLW M_SP
endif
RETLW M_K
RETLW M_END
;
MSG5
RETLW M_USER ; User Message
RETLW M_SP
RETLW M_END
;
MSG7
ifdef NO_DE
RETLW CALL_1
RETLW CALL_2
RETLW CALL_3
else
RETLW M_E
RETLW M_SP
RETLW M_CALL
endif
RETLW M_SP
RETLW M_END
;
MSG8
RETLW M_SP ; WPM suffix
RETLW M_W
RETLW M_P
RETLW M_M
RETLW M_END
;===========================================
; Randomized Code Practice Table
;===========================================
GETPRAC
MOVWF WTEMP
MOVLW HIGH($)
MOVWF PCLATH
MOVF WTEMP,W
ADDWF PC, F ; Jump through table
CWTBL
RETLW 0xE4 ; 8 8 1110 0100 = DAH-DAH-DAH-DI-DIT
RETLW 0x20 ;25 I 0010 0000 = DI-DIT
RETLW 0x70 ;39 W 0111 0000 = DI-DAH-DAH
RETLW 0x50 ;34 R 0101 0000 = DI-DAH-DIT
RETLW 0xA8 ;19 C 1010 1000 = DAH-DI-DAH-DIT
RETLW 0xD8 ;33 Q 1101 1000 = DAH-DAH-DI-DAH
RETLW 0x32 ;15 ? 0011 0010 = DI-DI-DAH-DAH-DI-DIT
RETLW 0x3C ; 2 2 0011 1100 = DI-DI-DAH-DAH-DAH
RETLW 0x94 ;16 / 1001 0100 = DAH-DI-DI-DAH-DIT
RETLW 0x60 ;17 A 0110 0000 = DI-DAH
RETLW 0x68 ;32 P 0110 1000 = DI-DAH-DAH-DIT
RETLW 0xFC ; 0 0 1111 1100 = DAH-DAH-DAH-DAH-DAH
RETLW 0x78 ;26 J 0111 1000 = DI-DAH-DAH-DAH
RETLW 0xCE ;13 , 1100 1110 = DAH-DAH-DI-DI-DAH-DAH
RETLW 0x0C ; 4 4 0000 1100 = DI-DI-DI-DI-DAH
RETLW 0x10 ;35 S 0001 0000 = DI-DI-DIT
RETLW 0x8C ;14 BT 1000 1100 = DAH-DI-DI-DI-DAH
RETLW 0x54 ;10 AR 0101 0100 = DI-DAH-DI-DAH-DIT
RETLW 0x28 ;22 F 0010 1000 = DI-DI-DAH-DIT
RETLW 0xD0 ;23 G 1101 0000 = DAH-DAH-DIT
RETLW 0x90 ;20 D 1001 0000 = DAH-DI-DIT
RETLW 0x04 ; 5 5 0000 0100 = DI-DI-DI-DI-DIT
RETLW 0x88 ;18 B 1000 1000 = DAH-DI-DI-DIT
RETLW 0x18 ;38 V 0001 1000 = DI-DI-DI-DAH
RETLW 0xF4 ; 9 9 1111 0100 = DAH-DAH-DAH-DAH-DIT
RETLW 0x56 ;12 . 0101 0110 = DAH-DAH-DI-DI-DAH
RETLW 0xC0 ;36 T 1100 0000 = DAH
RETLW 0x30 ;37 U 0011 0000 = DI-DI-DAH
RETLW 0xB8 ;41 Y 1101 1000 = DAH-DAH-DI-DAH
RETLW 0xE0 ;29 M 1110 0000 = DAH-DAH
RETLW 0xC4 ; 7 7 1100 0100 = DAH-DAH-DI-DI-DIT
RETLW 0x84 ; 6 6 1000 0100 = DAH-DI-DI-DI-DIT
RETLW 0x16 ;11 SK 0001 0110 = DI-DI-DI-DAH-DI-DAH
RETLW 0x1C ; 3 3 0001 1100 = DI-DI-DI-DAH-DAH
RETLW 0x08 ;24 H 0000 1000 = DI-DI-DI-DIT
RETLW 0x98 ;40 X 1001 1000 = DAH-DI-DI-DAH
RETLW 0xC8 ;42 Z 1100 1000 = DAH-DAH-DI-DIT
RETLW 0x48 ;28 L 0100 1000 = DI-DAH-DI-DIT
RETLW 0x7C ; 1 1 0111 1100 = DI-DAH-DAH-DAH-DAH
RETLW 0xB0 ;27 K 1011 0000 = DAH-DI-DAH
RETLW 0xA0 ;30 N 1010 0000 = DAH-DIT
RETLW 0x40 ;21 E 0100 0000 = DIT
RETLW 0xF0 ;31 O 1111 0000 = DAH-DAH-DAH
;===========================================
; Code Speed Table
;===========================================
;——————————————-
; TIMEBASE Defaults
;
; Using ARRL Handbook as a reference, a 5 WPM dit
; is 240 msec, a dah is 720 ms.
; Formula:
;
; Count= (((5/WPM) * 240) / SIDETONE_PERIOD)
;
; For Sidetone Freq of 870 Hz (1.15 ms):
;
; Count = ((5/WPM) * (240/1.15))
;
SVAL EQU (5D * SPD_CONST) ; Fudged By oscilloscope verification
;
;——————————————-
IDX2SPD
MOVWF WTEMP
MOVLW HIGH($)
MOVWF PCLATH
MOVF WTEMP,W
; endif
ADDWF PC, F ; Jump through table
SPEEDTBL
RETLW SVAL/5D ; WPM_5
RETLW SVAL/6D ; WPM_6
RETLW SVAL/7D ; WPM_7
RETLW SVAL/8D ; WPM_8
RETLW SVAL/9D ; WPM_9
RETLW SVAL/10D ; WPM_10
RETLW SVAL/11D ; WPM_11
RETLW SVAL/12D ; WPM_12
RETLW SVAL/13D ; WPM_13
RETLW SVAL/14D ; WPM_14
RETLW SVAL/15D ; WPM_15
RETLW SVAL/16D ; WPM_16
RETLW SVAL/17D ; WPM_17
RETLW SVAL/18D ; WPM_18
RETLW SVAL/19D ; WPM_19
RETLW SVAL/20D ; WPM_20
RETLW SVAL/21D ; WPM_21
RETLW SVAL/22D ; WPM_22
RETLW SVAL/23D ; WPM_23
RETLW SVAL/24D ; WPM_24
RETLW SVAL/25D ; WPM_25
RETLW SVAL/26D ; WPM_26
RETLW SVAL/27D ; WPM_27
RETLW SVAL/28D ; WPM_28
RETLW SVAL/29D ; WPM_29
RETLW SVAL/30D ; WPM_30
RETLW SVAL/31D ; WPM_31
RETLW SVAL/32D ; WPM_32
RETLW SVAL/33D ; WPM_33
RETLW SVAL/34D ; WPM_34
RETLW SVAL/35D ; WPM_35
RETLW SVAL/36D ; WPM_36
RETLW SVAL/37D ; WPM_37
RETLW SVAL/38D ; WPM_38
RETLW SVAL/39D ; WPM_39
RETLW SVAL/40D ; WPM_40
RETLW SVAL/41D ; WPM_41
RETLW SVAL/42D ; WPM_42
RETLW SVAL/43D ; WPM_43
RETLW SVAL/44D ; WPM_44
RETLW SVAL/45D ; WPM_45
RETLW SVAL/46D ; WPM_46
RETLW SVAL/47D ; WPM_47
RETLW SVAL/48D ; WPM_48
RETLW SVAL/49D ; WPM_49
;===========================================
; SENDMSG:
; Sends message pointed to by W
; Be careful of case where message table
; grows so large that it pushes this code
; above 0xff or a CALL instruction will
; not be able to reach it.
; Uses AL, DH (DH = MSGIDX)
;===========================================
SENDMSG
MOVWF DH ; Store index
S0LOOP
BTFSC PROCLAT, USERON ; Determine data source
GOTO S0USER
CALL GETMSG ; Get *DH++ in W
GOTO S0CONT
S0USER
MOVF INDF, W ; Get *USERRAM++
INCF FSR, F
S0CONT
MOVWF AL
MOVLW M_END ; End delimiter ?
SUBWF AL, W
BTFSS STATUS, Z ; Skip if no compare
GOTO S1CONT
BTFSS PROCLAT, USERON ; End of user or end of message ?
GOTO S1DONE
BCF PROCLAT, USERON
GOTO S0LOOP
S1DONE
BCF STATUS, PC9 ; Clear PAGE bit, we are done here
BCF PROCLAT, USERON ; Clear User mode (case: user msg aborted)
RETLW 0 ; All done, return
S1CONT
MOVLW M_USER ; Toggle to User Mode ?
SUBWF AL, W
BTFSC STATUS, Z ; Skip if no compare
GOTO S1USER
MOVLW M_CALL ; Toggle to Callsign Mode ?
SUBWF AL, W
BTFSC STATUS, Z ; Skip if no compare
GOTO S1CALL
MOVLW M_SKIP ; Skip entry ?
SUBWF AL, W
BTFSC STATUS, Z ; Skip if no compare
GOTO S0LOOP
MOVLW M_SP ; Word space ?
SUBWF AL, W
BTFSS STATUS, Z ; Skip if compare
GOTO S2LOOP
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL WORDSPACE ; Word Space = 7 time bits
BSF STATUS, PC9 ; Set PAGE bit on return
GOTO S0LOOP
S1CALL
MOVLW USRCALL ; Point to start of callsign string
GOTO S100
S1USER
MOVLW USERRAM ; Point to start of user string
S100
MOVWF FSR
BSF PROCLAT, USERON
GOTO S0LOOP
S2LOOP
BTFSS GPIO, XDAHPDL
GOTO ABORT1
BTFSC GPIO, XDITPDL
GOTO NOABORT
ABORT1
ifdef BEACON
CLRWDT ; Reset watchdog timer
endif
CLRF PROCLAT
BTFSC GPIO, XDAHPDL ; Wait till hands off paddle
BTFSS GPIO, XDITPDL
GOTO ABORT1
GOTO S1DONE
NOABORT
MOVF AL, W ; Get coded morse
ADDWF AL, F ; AL*2, if (Z==0) DONE else C=DIT/DAH
BTFSS STATUS, Z ; Skip if zero
GOTO S2CONT
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL LETTERSPACE ; Inter-letter space
BSF STATUS, PC9 ; Set PAGE bit on return
GOTO S0LOOP
S2CONT
BTFSC STATUS, C ; (C==1) then DAH else DIT
GOTO S2DAH
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL DITOUT
BSF STATUS, PC9 ; Set PAGE bit on return
GOTO S2LOOP
S2DAH
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL DAHOUT
BSF STATUS, PC9 ; Set PAGE bit on return
GOTO S2LOOP
;===========================================
; Get a Morse Character from User
; Value returned in AH
; Uses AL, DH
;===========================================
GETCW
CLRF AH ; Start with empty frame
MOVLW 08H ; Init bit count
MOVWF AL
MOVLW GC_TO_L ; Init timeouts
MOVWF DELAYLO
MOVLW GC_TO_M ; Init timeouts
MOVWF DELAYHI
MOVLW GC_TO_H ; Init timeouts
MOVWF DH
GCLOOP
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL SAMPLE
BSF STATUS, PC9 ; Set PAGE bit back for high access
BTFSS PROCLAT, DITPDL ; Both Dit
GOTO GCSINGLE
BTFSC PROCLAT, DAHPDL ; and Dah ?
GOTO GCTOGGLE
GCSINGLE
BTFSC PROCLAT, DITPDL ; DIT Paddle closed when = 1
GOTO GCDIT
BTFSC PROCLAT, DAHPDL ; DAH Paddle closed when = 1
GOTO GCDAH
DECFSZ DELAYLO, F ; Inner loop test
GOTO GCLOOP
MOVLW GC_TO_L ; Reset inner loop
MOVWF DELAYLO
DECFSZ DELAYHI, F ; Middle loop Test
GOTO GCLOOP
MOVLW GC_TO_M ; Reset middle loop
MOVWF DELAYHI
DECFSZ DH, F ; Outer loop Test
GOTO GCLOOP
GOTO GCJUST ; Timed out, we are done, now justify
GCTOGGLE
BTFSS MODEREG, IAM_A
GOTO GCTOGL1
MOVLW PROCMASK ; Mode A, kill any in latch
ANDWF PROCLAT, F
GCTOGL1
BTFSC PROCLAT, OUTLAST ; If Dit was last send a DAH
GOTO GCDAH
GCDIT
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL DITOUT
BSF STATUS, PC9 ; Set PAGE bit on return
BCF STATUS, C ; DIT is 0
GOTO GCLOAD
GCDAH
BCF STATUS, PC9 ; Clear PAGE bit for low page call
CALL DAHOUT
BSF STATUS, PC9 ; Set PAGE bit on return
BSF STATUS, C ; DAH is 1
GCLOAD
RLF AH, F ; Shift left 1, CARRY->LSB
DECFSZ AL, F ; Decrement bit count
GOTO GCLD1
GOTO GCERR ; Overflow, treat as null
GCLD1
MOVLW GC_TO_L ; Restart timeouts
MOVWF DELAYLO
MOVLW GC_TO_M ;
MOVWF DELAYHI
MOVLW 1 ; set a shorter 2nd timeout
MOVWF DH
GOTO GCLOOP
GCJUST
BSF STATUS, C ; Add tag bit
GOTO GCJ2
GCJ1
BCF STATUS, C ; Fill in bottom
GCJ2
RLF AH, F ; with zeroes
DECFSZ AL, F ; Keep going till left justified
GOTO GCJ1
GCDONE
BCF STATUS, PC9 ; Clear PAGE bit for low page return
RETLW 0
GCERR
MOVLW M_TO ; Overflow error treated as a timeout
MOVWF AH
GOTO GCDONE
;===========================================
; This was moved here from the low page to
; free up some code space. It’s function is
; to load fixed callsign into RAM.
;===========================================
XFRSTUB
MOVLW CALL_0
CALL XFRIDX
MOVLW CALL_1
CALL XFRIDX
MOVLW CALL_2
CALL XFRIDX
MOVLW CALL_3
CALL XFRIDX
MOVLW CALL_4
CALL XFRIDX
MOVLW CALL_5
CALL XFRIDX
MOVLW CALL_6
CALL XFRIDX
MOVLW CALL_7
CALL XFRIDX
BCF STATUS, PC9 ; Clear PAGE bit for low page goto
GOTO XFRRET
;===========================================
; Code Practice
; Send a stream of random CW characters
;===========================================
;
; Generates pseudo random numbers by hopping
; though a morse character table with a constantly
; incrementing index. The index is incremented on
; every pass by an odd valued skip factor. A new
; skip factor is used periodically. The interval
; of the period is “randomly” read from the timer.
; Note that by virtue of the fact that the skip
; can cause a table bounds wrap, both positive
; and negative moves occur.
; DH = Skip, DL = Running index, AH = Loop count
PRAC_RUN
CLRF DL ; Clear index
PRCLP0
MOVF TMR0, W ; Get an initial skip factor
MOVWF AH ; save loop count
IORLW 01H ; make it odd
ANDLW 01FH ; 1 -> 31
MOVWF DH
PRCLP1
MOVF DH, W ; Get skip value in W
ADDWF DL, F ; Add to index
MOVLW -43D ; If > 42 wrap around
ADDWF DL, W ; Carry will be set on wrap
BTFSS STATUS, C ; Value wrapped, use wrapped value
MOVF DL, W ; Value was within limits, use it as is
MOVWF DL ; Update index in case we wrapped
CALL GETPRAC
BCF STATUS, PC9 ; Clear page bit for low page call
CALL OSCHAR
BSF STATUS, PC9 ; Set PAGE bit on return
BTFSC GPIO, XDITPDL ; loop till paddle hit
BTFSS GPIO, XDAHPDL ; loop till paddle hit
GOTO PRCDONE ; paddle hit: leave
DECFSZ AH, F ; decrement loop count
GOTO PRCLP1 ; NZ: Continue
GOTO PRCLP0 ; Z: Get new skip factor & loop count
PRCDONE
BCF STATUS, PC9 ; Clear page bit
GOTO WAIT4OFF ; Common “wait then return”
;===========================================
; Convert CW Character Into Table Index
; Input: CW in AH
; Return: Index in AH
; Uses: AL, AH
; Note: A timeout code (M_TO) will be handled
; the same as an illegal code, .ie it won’t
; be found in the table.
;===========================================
CW2IDX
MOVF AH, W ; Transfer AH to AL
MOVWF AL
MOVLW M_A ; A ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 0
MOVLW M_C ; C ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 01D
MOVLW M_F ; F ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 02D
MOVLW M_I ; I ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 03D
MOVLW M_K ; K ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 04D
MOVLW M_L ; L ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 05D
MOVLW M_S ; S ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 06D
MOVLW M_T ; T ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 07D
MOVLW M_U ; U ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 08D
MOVLW M_X ; X ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 09D
MOVLW M_Z ; Z ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 10D
BCF PROCLAT, CONVERSE ; End converse mode
MOVLW M_D ; D ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 11D
MOVLW M_M ; M ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 12D
MOVLW M_P ; P ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 13D
MOVLW M_W ; W ?
SUBWF AL, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 14D
RETLW 15D ; Unknown command
;===========================================
; Convert to ONES
; Valid numbers are returned with MSB set,
; Input: AH Output:W
;===========================================
;
CONV_LO
MOVLW M_1 ; 1 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 01D+80H
MOVLW M_2 ; 2 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 02D+80H
MOVLW M_3 ; 3 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 03D+80H
MOVLW M_4 ; 4 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 04D+80H
MOVLW M_5 ; 5 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 05D+80H
MOVLW M_6 ; 6 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 06D+80H
MOVLW M_7 ; 7 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
RETLW 07D+80H
MOVLW M_8 ; 8 ?
SUBWF AH, W ; Compare
BTFSC STATUS, Z ; Skip if no compare
Olá de novo João!
Estudando o seu arquivo asm enviado, notei que você já começou a modificar algumas linhas. Tem como enviar sem modificações (original) ou indicar o link que você pegou? Tem esquema para entender o que realmente vai ser usado? Você disse que viu este arquivo na versão 12c509. Porque não compilar este asm com o cabeçalho do 12f629? Fica muito mais fácil!!!! Este arquivo, eu deduzo que se trata de um equipamento que envia mensagens em código morse, com opção de uso do manipulador manual. É isto mesmo? No que você pretende usar esta ‘raridade’? Você gosta de radioamadorismo ou pretende bolar alguma coisa diferente com isto?
Claudio
Caro Claudo, bom dia.
O programa em Assembly a que me referi no comentário anterior é para emissão de sinais morse. Trata-se de um oscilador iâmbico que usamos no radioamadorismo na faixa de CW. A minha intensão é tão somente gravar o .HEX no novo microcontrolador, no caso o PIC12F629. Só que não entendo de programação em Assembly. Se puder me ajudar fico grato. Atenciosamente, João.
Bom dia. Tenho um programa escrito em Assembly para o PIC16F628A e gostaria de modificar sua estrutura para, após compilação, gravar o .HEX no PIC12F629. Voce poderia me ajudar nessa tarefa? Possso mandar o .ASM para análise. Grato.
Olá João! Gostaria de saber se a quantidade de pinos que será usado é compativel, pois o PIC 12f629 só tem 6 portas ,sendo uma que pode ser usado somente como entrada e 5 como io’s. Agora , se tiver de usar cristal externo, só ficará 3 io’s e uma entrada. Seria suficiente? Se for, não é dificil alterar para este modelo. Basta alterar os arquivos iniciais do pic e alterar as configurações de trisa/trisb por trisio. Todas as menções de ‘porta’ e ‘ portb’ tem que ser alterada para ‘gpio’. Para isto, abra o seu arquivo no editor do MPLAB e faça as alterações. Escolha que pinos irá ligar determinada carga ou será entrada. Acerte o ‘trisio’ para isto também. Depois, recompile, se der falha, corrija os eventuais erros e de novo. Quando conseguir compilar, monte o circuito no protoboard e carregue o arquivo hex. Teste. Se não funciona a contento, faça novas alterações e recompile. Depois de umas 500 carga de hex (brincadeira) vai funcionar.
Se desejar, pode enviar via este comentario, seu arquivo asm que eu dou uma olhada.
Claudio
Boa noite Claudio,desculpe-me então infelizmente estou no projeto errado.Estou querendo analisar o projeto do RECEPTOR que decodifica o CHAVEIRINHO da ht com 16f628.
Olá Genilson! Não se preocupe. Eu também confundo, pois são muito parecidos. Tem o projeto do receptor generico que usa o 12f629 com o ht6p20b. Basta trocar o tipo de microcontrolador no código asm e trocar a gpio/ trisio por porta /trisa e portb/trisb no pinos que desejar usar para saidas. Há,….não se esqueça de colocar o ‘movlw.7 /movwf cmcon’ para desligar os comparadores do 16f628. Depois é só recompilar para o 16f628 no Mplab-ide e usar o código Hex.
Cláudio
OLA CLAUDIO realmente quando pego teu codigo asm e compilo pelo MPLAB e está dando varios erros tentei corrigi alguns mais que é erros de digitação,porém eu não sei nada de assembler.Vc poderia dá uma olhada nesse erros por favor.Muito obrigado
Olá Genilson! Qual a versão que está dando erro? Para PIC 16f628a ou 12f629? Voce sabe que este receptor precisa ter um HC200 .. 301 programado por voce para funcionar, não sabe? E que não ira funcionar com chaveirinhos comerciais a menos que voce reporograme seus Hc..?
Claudio