RECEPTOR DE CONTROLE REMOTO GENERICO PARA HCS200…301 COM PIC 12F629 E 16F628A

0

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:

DECPIC628A_ASM

SEGUE ABAIXO ARQUIVO HEX PARA VERSÃO PIC16F628A:

DECPIC628A_HEX

SEGUE ABAIXO, SUGESTÃO DE PLACA VERSÃO 16F628A :

placa_gen_628pdf

SEGUE ABAIXO, SUGESTÃO DE PLACA VERSÃO 16F628A COM COMPONENTES VISTO PELO LADO COBREADO E LISTA DE MATERIAIS:

placa_gen_628_montagem_pdf

VEJA O ESQUEMA DA APLICAÇÃO 2COM PIC 12F629:

SEGUE ABAIXO ARQUIVO ASM PARA VERSÃO PIC12F629:

DECPIC629_ASM

SEGUE ABAIXO ARQUIVO HEX PARA VERSÃO PIC12F629:

DECPIC629_HEX

SEGUE ABAIXO A PLACA PARA A VERSÃO 12F629:

placa_gen_629pdf

SEGUE ABAIXO A PLACA PARA A VERSÃO 12F629 COM COMPONENTES MONTADOS VISTO PELO LADO COBREADO E LISTA DE MATERIAIS:

placa_gen_629_montagem_pdf

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

0

99 comentários sobre “RECEPTOR DE CONTROLE REMOTO GENERICO PARA HCS200…301 COM PIC 12F629 E 16F628A

  1. 0

    Olá!

    Primeiramente meus parabém por compartilhar o conhecimento e de forma gratuita, está cada vez mais difícil de sencontrar pessoas como você!

    Eu tenho um sisteminha RX/TX que usa os HT12 E/D e joga para um ci ATMEGA8-16PU (programado como um controlador de joystick USB, link http://www.raphnet.net/electronique/usb_game12/index_en.php). Estava pensando em usar o seu método para aproveitar os controles com a tecnologia KEELOQ e gostaria de saber se seria possível integrar tudo no PIC16F628a, ou seja aprender o controle e enviar via USB um comando como se fosse um botão de joystick. Quais as leituras que poderia me indicar? Desde já muito grato.

    1. 0

      Olá Karllo!
      Muito obrigado por seu comentário apreciativo por este site. Infelizmente, o microcontrolador pic 16f628a não tem velocidade suficiente para trabalhar com usb. Um Atmega8_16pu rodando a 16mhz tem apenas 62,5 nanosegundos por instrução, enquanto o pic 16f628a, mesmo usando cristal de 20 MHZ não passa dos 200 nanosegundos. Ou você usa microcontroladores mais rápidos para integrar tudo ou usa um ci para a recepção e outro para enviar via usb. Mas não teria, no momento, nenhum circuito ou sugestão para te dar.
      Cláudio

  2. 0

    Olá amigo, e muito legal todo este seu trabalho sem fins lucrativos, meus parabéns.

    sou um humilde hobista rs que vem aprendendo muito com os projetos postados aqui em seu blog, meu maior projeto ate hoje (e sem fins lucrativos rs) foi grassas as leituras que fiz aqui. Obrigado!
    Pretendo levar para a pratica mais um de seus projetos, se possível gostaria de sua ajuda.
    Será esta montagem ´´ RECEPTOR DE CONTROLE REMOTO GENERICO PARA HCS200… 301 COM PIC 16F628A´´, sei que terei de usar também este projeto ´´ HCS_PROG_V628 – MAIS UMA OPÇÃO PARA PROGRAMAR HCS200… 301 COM PIC 16F628A.
    Sei que especificou entre os hcs200 a 301.

    então, você poderia me enviar uns links que mostrassem alguns controles, com 4 teclas, que possua um desses hcs. Tive uma certa dificuldade de montar meus próprios controles(chaveiros) pois as caixas que consegui não tinham uma estética muito boa. entao vi aqui essa brilhante ideia de utilizar os controles ja prontos.

    Encontrei um perfeito para meu projeto ´´ http://issportoes.mercadoshops.com.br/controle-linear-hcs-teclas-oferta_20xJM ´´ porem não sei se ele serviria.
    Meu amigo, desde já, obrigado.

    1. 0

      Olá Edson! Fico feliz que o blog esteja sendo de ajuda! Quanto a indicar algum chaveirinho transmissor, já não poderei, pois todos os controles que tenho são reaproveitado de outros equipamentos e não diretamente adquirido em lojas. Portanto, não saberia indicar um link. Tenho um, de portão residencial, da _gate, que usa o hcs201. Pergunte ao vendedor qual é o ci interno ( no caso da internet), ou abra um e veja na hora, se tiver com dúvida. Atente também para a frequência de trabalho que deverá ser igual ao do seu receptor.
      Cláudio

        1. 0

          Olá Edilson Franco! Que bom que você teve sucesso! Obrigado por retornar o resultado de seu empreendimento.
          Cláudio

  3. 0

    Ola, construi o circuito com pic 12f629 e parece estar funcionando, mas os led nao ficam acessos, assim que paro de pressionar o controle o led apaga isso e normal?

    1. 0

      Olá Mavomax! Completando a resposta do comentário de 29/01/13 as 14:02, Se você estiver usando a versão para hcs201…301 (roller code) é normal depois de parar de pressionar apagar os leds. è uma versão didática, que você poderá alterar o código para sua aplicação. Tem a opção da ‘placa para portão‘ que dará uma idéia de uso.
      Cláudio

  4. 0

    Caro Claúdio, boa tarde.
    Aproveitando este espaço para lhe desejar um Feliz Natal com votos de saúde e paz, extensivo aos seus familiares, e muitas realizações em 2013.
    Os osciladores “CW” com os PIC´s 12F629 e 16F628, depois das mudanças incrementadas por voce estão funcionando que é uma beleza. Valeu de verdade.
    Grande abraço.
    João.

    1. 0

      Olá Dercy! Peguei do site o arquivo asm, compilei e carreguei no pic. Não tive problemas. Gravei 15 controles sem apagar nenhum. Você fez alguma modificação no Asm? Tente recarregar o arquivo e testar de novo.
      Claudio

  5. 0

    Ola Cláudio, estou usando em forma de pulso.
    Não sei se voce me entendeu o projeto aceita só
    dois controles.

    1. 0

      Olá Dercy! Acho que estou confundindo. Voce está usando com controles que usam Hcs200 a 301, certo! Você programou os controles com a ‘Key’ e funcionou ok com 2 controles remotos. Mas , você tenta programar um terceiro e ai apaga toda a memória ou não grava apenas este terceiro?
      Fico no aguardo….
      Claudio

  6. 0

    Ola Cláudio,Montei o Receptor de controle Remoto Generico p/ HCS200…301 com pic16f628a e funcionou p/ 2 controles. quando tento colocar o 3º ele apaga
    o 2º.
    Vc poderia dar uma dica .Muito obrigado

    1. 0

      Olá Dercy! Neste arquivo asm não foi previsto o uso do 3º led. Assim que tiver um tempinho , vou montar o circuito no protoboard e acertar isto. Voce está usando em forma de pulso ou retenção?
      Claudio

      1. 0

        OLA CLAUDIO, AINDA NÃO CONSEGUI FAZER FUNCIONAR, A ALTERAÇÃO FICO ASSIM CONFORME A BAIXO!!
        *******************************************

        ;**************************************************************************
        ; RX_GEN_HT6P20B_V4.ASM ( ALTERAÇAO )
        ;
        ;
        ; RECEPTOR RF PARA CONTROLE REMOTOS (CHAVEIRINHOS) COM CI HT6P20B
        ;
        ; PARA DECODIFICAR UTILIZA UM PIC 12F629 (OPCIONALMENTE UM 12F675, DES-
        ; COMENTANDO/COMENTANDO AS LINHAS CITADAS NO TEXTO).
        ;
        ; CLAUDIO INICIO: 27-07-2012 TERMINO:28-06-2012
        ; REVISADO : 05-8-2012 (ELIMINADO ‘BUG’ QUE TRAVAVA SOB INTERFERENCIA
        ; FORTE NA ENTRADA ‘RFIN’)
        ; VERSÃO4: MANTÉM LEDS ACESOS ENQUANTO BOTÃO FICAR PRESSIONADO (NÃO PISCA)
        ;**************************************************************************
        ;
        ; GRAVAR CONTROLE: APERTE UM BOTÃO DO CONTROLE E MANTENHA APERTADO.
        ; APERTE TAMBÉM O BOTÃO ‘LEARN’ NA PLACA (PINO 4 DO PIC 12F629 A MASSA)E
        ; SOLTE-O EM MENOS DE 1 SEGUNDOS. O LED ‘LEARN'(PINO 2) PISCARÁ 1
        ; VEZ, PARA INDICAR ‘CODE APRENDIDO’. REPITA ISTO COM O OUTRO BOTÃO DO CONTROLE
        ; E COM TODOS OS CONTROLES REMOTOS QUE FOR UTILIZAR, UM POR VEZ.
        ; APAGAR TODOS OS CONTROLES DA MEMÓRIA: APERTAR BOTÃO ‘LEARN’ NA PLACA E
        ; MANTENHA PRESSIONADO POR MAIS DE 10 SEGUNDOS. O LED ‘LEARN’ (PINO 2) PISCARÁ
        ; 3 VEZES , INDICANDO O PLENO APAGAMENTO DE TODOS OS SENSORES DA MEMÓRIA.
        ; APÓS ISTO, CADA CONTROLE DEVERÁ SER ‘REAPRENDIDO’ NOVAMENTE PARA OPERAR.
        ;***************************************************************************
        ; DESCOMENTAR/COMENTAR CONFORME MODELO ESCOLHIDO
        ; LIST P=12f675 , R=DEC
        LIST P=12f629 , R=DEC
        ; INCLUDE “P12F675.INC”
        INCLUDE “P12F629.INC”
        ;————————–
        ERRORLEVEL -302
        __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_ON & _MCLRE_OFF

        #DEFINE BANK0 BCF STATUS,RP0 ;SETA BANK0 DE MEMORIA
        #DEFINE BANK1 BSF STATUS,RP0 ;SETA BANK1
        #DEFINE FLAG FLAGS,0 ;FLAG DE SITUAÇÃO
        #DEFINE FLAG1 FLAGS,1 ;FLAG DE NOVA LEITURA
        #DEFINE FLAGGR FLAGS,2 ;FLAG DE ‘LEARN’ APRENDER
        #DEFINE SIN GPIO,0 ;PINO 7 IN RF
        #DEFINE LRN GPIO,3 ;PINO 4 IN LEARN BOTTON
        #DEFINE LED GPIO,5 ;PINO 2 SAIDA LED ‘LEARN’
        #DEFINE LED2 GPIO,2 ;PINO 5- SAIDA DO LED2
        #DEFINE LED1 GPIO,1 ;PINO 6- SAIDA DO LED1
        #DEFINE FLAG_TRAVA_LED3 FLAGS,3 ;FLAG TRAVA

        CBLOCK 0X20
        RES3,RES2,RES1,RES0,AUX,C3,C2,C1,C0,WS,TEMP,BITCOUNTER,FLAGS,TL0,TL1,TL2,Z2,Z1,Y1,Y2
        LcdDelayCounter,LcdDelayCounter1,tmpLcdRegister,tmpLcdRegister1,SITUAÇÃO
        temp,SDATA,AUX2 ,LC,HC ,CONT,RES3A,RES2A,RES1A,RES0A,X,R0,R1,R2,TMP1,TMP2,TMP3,ADDRESS,TMP
        ENDC

        WRCFG EQU B’00000000′ ; PORTB: EEPROM WRITE TRI-STATE VALUE
        YTRISA EQU B’001001′ ; PORTA: TRI-STATE VALUE
        TMAX EQU .50 ;TEMPO MAXIMO DO SINAL LOW
        QBYTE EQU .28 ;QUANTIDADE DE BYTES A SER RECEBIDO (22 ADRESS+ 2 DADO+ 4 ANTICODE)
        TGR EQU .255 ;TEMPO DE BOTÃO APERTADO PARA APAGAR GRAVAÇAO

        T_DESL_LED EQU .20 ;TEMPO MÁXIMO QUE LEDS FICAM ACESOS APÓS CESSAR TRANSMISSÃO

        ORG 0X00
        GOTO START
        ORG 0X04
        RETFIE

        START:
        MOVLW 0X07
        MOVWF CMCON ;DESLIGA COMPARADORES
        CLRF GPIO ; RESET PORT
        MOVLW YTRISA ; SETUP PORTA
        TRIS GPIO

        ;DESCOMENTAR ABAIXO PARA 12F675
        ; BANK1
        ; MOVLW .0
        ; MOVWF ANSEL ;LIBERA PORTAS DO AD (somente 12f675)
        ; BANK0
        CLRF FLAGS ;APAGA REGISTRADOR DE FLAGS
        MOVLW TGR
        MOVWF Z2
        CLRF Z1 ;LIMPA REGISTRADORES
        INICIO:

        CLRF RES3
        CLRF RES2
        CLRF RES1
        CLRF RES0
        MOVLW QBYTE ;PREPARA PARA A RECEPÇÃO COM NUMERO DE BITS A RECEBER
        MOVWF BITCOUNTER

        L0
        BCF FLAG ;LIMPA FLAG E REGISTRADORES DE RECEPÇÃO
        CLRF HC
        CLRF LC
        L1
        ;———————————

        BTFSS LRN ;TESTA BOTÃO ‘LEARN’ APERTADO
        GOTO TAPAGAMENTO ;APERTADO, COMEÇA A CONTAR TEMPO MAX. DE APAGAMENTO
        MOVLW TGR
        MOVWF Z2 ;RECARGA DO TEMPO DE APAGAMENTO
        CLRF Z1 ;LIMPA REGISTRADORES
        L1H
        GOTO SS5

        TAPAGAMENTO ;APAGAR TODOS OS CONTROLES DA MEMÓRIA
        DECFSZ Z1,F
        GOTO L1H
        DECFSZ Z2,F
        GOTO L1H
        CALL APAGAEEPROM ;ATINGIU TEMPO MAXIMO: APAGAR MEMÓRIA

        BSF LED ;ACENDE LED (UMA PISCADA)
        MOVLW .10
        CALL DELAYM
        BCF LED ;APAGA LED
        MOVLW .10
        CALL DELAYM
        BSF LED ;ACENDE LED (UMA PISCADA)
        MOVLW .10
        CALL DELAYM
        BCF LED ;APAGA LED
        MOVLW .10
        CALL DELAYM
        BSF LED ;ACENDE LED (UMA PISCADA)
        MOVLW .10
        CALL DELAYM
        BCF LED ;APAGA LED
        MOVLW .10
        CALL DELAYM

        BTFSS LRN ;AGUARDA SOLTAR BOTÃO ‘LEARN’
        GOTO $-1
        GOTO INICIO

        ;===================ROTINA DE RECEPÇÃO==========================
        SS5:
        ;A

        BTFSS FLAG ;TESTA FLAG DE HUM/ZERO RECEBIDO
        GOTO L2 ;FLAG=0
        ;——————————–
        ;B
        BTFSS SIN ;SIN ? TESTA SINAL DE ENTRADA DO RECEPTOR DE RF
        GOTO M0 ; SIN=0
        ;———————————-
        L2
        ;C
        BTFSS SIN ;SIN ?
        GOTO LA1 ;SIN=0
        ;————————————-
        ;E
        BSF FLAG ;SIN=1
        INCF HC,F
        BTFSC STATUS,Z
        DECF HC,F
        GOTO LA2 ;VAI CONTAR TEMPO DE 50 MICRO SEGUNDOS
        ;———————————————————
        LA1
        ;D
        INCF LC,F ;INCREMENTA REGISTRADOR DE LOW SIGNAL NA ENTRADA RF
        BTFSC STATUS,Z
        DECF LC,F
        LA2

        DECFSZ Y1,F ;CONTADOR DE TEMPO DE DESLIGAMENTO DE SAIDAS
        GOTO J0
        DECFSZ Y2,F ;CONTADOR DE TEMPO DE DESLIGAMENTO DE SAIDAS
        GOTO J0
        BCF LED1 ;APAGA LEDS
        BCF LED2
        BCF FLAG_TRAVA_LED3 ;ESTE FLAG CONTROLARÁ O ON/OFF DO LED 3 ;mudança aqui!!!!!!!!!!!!!
        INCF Y1,F
        INCF Y2,F

        MOVLW .11 ;.11 = 80 MICROSEG (ACERTA TEMPO ENTRE LEITURAS DA ENTRADA DE RF)
        MOVWF CONT
        DECFSZ CONT,F
        GOTO $-1
        GOTO L1

        M0
        ;———————————-
        ;F
        MOVFW LC ;TESTA SE NÃO PASSOU DO LIMITE MAXIMO DE TEMPO EM LOW NA ENTRADA DE RF
        SUBLW TMAX
        BTFSS STATUS,C
        GOTO INICIO ;C=0 (-) – LC>TMAX (REJEITAR DADO – PAUSA INICIAL)
        ;F’

        ;———————————–

        ;G
        MOVFW HC ;OBTEM O VALOR DE ‘CARRY'(HUM OU ZERO)
        SUBWF LC,W

        RRF RES3,F ;DESLOCA O BIT NOS REGISTRADORES DE RESULTADO
        RRF RES2,F
        RRF RES1,F
        RRF RES0,F
        ;————————————-
        ;H

        DECFSZ BITCOUNTER,F ;DECREMENTA O CONTADOR DE BITS A SER RECEBIDO
        GOTO L0 ;LE PROXIMO BIT

        MOVLW .4 ;DESPREZA OS BITS DE ‘ANTICODE’ 1010
        MOVWF BITCOUNTER
        ACERTA
        BCF STATUS,C
        RRF RES3,F
        RRF RES2,F
        RRF RES1,F
        RRF RES0,F ;RESULTADO FICA SOMENTE EM RES2 A RES0,DESPREZA RES3
        DECFSZ BITCOUNTER,F
        GOTO ACERTA

        BTFSC FLAG1 ;TESTA SE É A PRIMEIRA OU A SEGUNDA RECEPÇÃO
        GOTO PULA1
        MOVFW RES2 ;SALVA A PRIMEIRA LEITURA PARA COMPARAÇÃO COM UMA SEGUNDA
        MOVWF RES2A
        MOVFW RES1
        MOVWF RES1A
        MOVFW RES0
        MOVWF RES0A
        BSF FLAG1 ;SETA FLAG DE PRIMEIRA RECEPÇÃO

        GOTO INICIO
        PULA1
        BCF FLAG1 ;SEGUNDA RECEPÇÃO, COMPARA COM A PRIMEIRA
        MOVFW RES2
        XORWF RES2A,W
        BTFSS STATUS,Z
        GOTO RESETAC
        MOVFW RES1
        XORWF RES1A,W
        BTFSS STATUS,Z
        GOTO RESETAC
        MOVFW RES0
        XORWF RES0A,W
        BTFSS STATUS,Z
        GOTO RESETAC ;ERRO DE RECEPÇÁO
        GOTO AÇÃO ;OK – BOA RECEPÇÃO

        RESETAC
        CLRF RES3A ; APAGA RESULTADOS DE COMPARAÇÃO
        CLRF RES2A
        CLRF RES1A
        CLRF RES0A
        GOTO INICIO

        ;————————————-
        AÇÃO
        ;I
        BTFSS LRN ;BOTÃO ESTÁ APERTADO?
        BSF FLAGGR
        CALL PPT
        SUBLW .0
        BTFSC STATUS,Z ; É ‘0’?
        GOTO APRENDER ;NENHUM CONTROLE FOI GRAVADO
        MADDRESS
        MOVFW TMP
        MOVWF ADDRESS
        CALL EEREAD
        XORWF RES2,W ;COMPARA COM RES2
        BTFSS STATUS,Z
        GOTO PROXIMO
        DECF ADDRESS,F
        MOVFW ADDRESS
        CALL EEREAD
        XORWF RES1,W ;COMPARA COM RES1
        BTFSS STATUS,Z
        GOTO PROXIMO
        DECF ADDRESS,F
        MOVFW ADDRESS
        CALL EEREAD
        XORWF RES0,W ;COMPARA COM RES0
        BTFSC STATUS,Z
        GOTO ACIONAR ;ENCONTRADO CONTROLE NA MEMÓRIA
        PROXIMO ;VAI PARA O PROXIMO ENDEREÇO DE MEMÓRIA PROCURAR….

        MOVFW ADDRESS
        MOVWF TMP
        MOVLW .3
        SUBWF TMP,F ;ACERTA DE 3 EM 3 A POSIÇÃO DE BUSCA NA MEMÓRIA

        BTFSS STATUS,C
        GOTO APRENDER

        BTFSS STATUS,Z
        GOTO MADDRESS ;VOLTA A BUSCA

        APRENDER
        BTFSS FLAGGR ;TESTA SE BOTÃO ‘LEARN’ ESTÁ PRESSIONADO
        GOTO INICIO ;NÃO ESTÁ.
        CALL PPT ;ESTÁ, PEGA PONTEIRO
        MOVWF ADDRESS ;PEGA O ENDEREÇO APONTADO
        SUBLW 0X7E ;LIMITE MAXIMO DA EEPROM (128-1 /3= 42 BOTÕES OU 24 CONTROLES)
        BTFSS STATUS,C
        CLRF ADDRESS ;INICIA SOBREGRAVAÇÃO
        INCF ADDRESS,F ;SOMA 1
        MOVFW RES0
        MOVWF TMP ;COLOCA EM ‘TMP’
        MOVFW ADDRESS ;DA O POSIÇÃO DE MEMORIA A SER GRAVADO
        CALL EEWRITE ;ROTINA DE ESCRITA NA EEPROM
        INCF ADDRESS,F ;PROXIMA POSIÇÃO DE ESCRITA NA EEPROM
        MOVFW RES1
        MOVWF TMP
        MOVFW ADDRESS
        CALL EEWRITE
        INCF ADDRESS,F
        MOVFW RES2
        MOVWF TMP
        MOVFW ADDRESS
        CALL EEWRITE
        MOVFW ADDRESS
        MOVWF TMP
        MOVLW .0
        CALL EEWRITE ;GRAVA NOVO ENDEREÇO DE PONTEIRO
        BCF FLAGGR
        BTFSS LRN
        GOTO $-1
        MOVLW .10 ;TEMPO DE ATRASO
        CALL DELAYM

        BSF LED ;LIGA LED
        MOVLW .10 ;TEMPO DE ATRASO
        CALL DELAYM
        BCF LED ;DESLIGA

        ACIONAR

        BTFSS RES2,7 ;TESTA SE OS 2 BOTÕES JUNTOS FORAM ACIONADOS
        GOTO SEG888 ;UM NÃO FOI
        BTFSS RES2,6
        GOTO SEG888 ;OUTRO NÃO FOI
        BTFSC FLAG_TRAVA_LED3 ;TESTA A TRAVA:SE ESTIVER EM 1 NÃO FAZ NADA
        GOTO SEG999
        BSF FLAG_TRAVA_LED3 ;LIGA A TRAVA
        BTFSS LED3 ;TESTA O ESTADO ANTERIOR DO LED3
        GOTO LIGA_LED3 ;ESTAVA DESLIGADO, VAI LIGAR ENTÃO…
        BCF LED3 ;ESTAVA LIGADO, VAI DESLIGAR ENTÃO…
        GOTO SEG999 ;SAI RECARREGANDO O TEMPO
        LIGA_LED3
        BSF LED3 ;LIGA LED 3
        GOTO SEG999 ;SAI RECARREGANDO O TEMPO
        ;ROTINA DE TESTE INDIVIDUAL
        SEGUE888
        BTFSC RES2,7 ;TESTA QUAIS BOTÕES FORAM ACIONADOS NA TRANSMISSÃO
        BSF LED1 ;ATIVA LED1
        BTFSS RES2,7
        BCF LED1 ;APAGA LED1
        BTFSC RES2,6
        BSF LED2 ;ATIVA LED2
        BTFSS RES2,6
        BCF LED2 ;APAGA LED2
        SEG999
        MOVLW T_DESL_LED ;RECARGA DO TEMPORIZADOR DE DESLIGAMENTO
        MOVWF Y2
        MOVLW .255
        MOVWF Y1
        GOTO INICIO

        ;————————————————————–
        DELAYM
        MOVWF R0
        XC
        CALL AGUARDE
        DECFSZ R0,F
        GOTO XC
        RETURN

        ;****************************************************
        ;PEGA PONTEIRO NA EEPROM – ULTIMO ENDEREÇO
        PPT
        MOVLW .0
        CALL EEREAD ;LE PONTEIRO DA EEPROM
        RETURN

        AGUARDE ;ROTINA DE ATRASO ENTRE OPERAÇÕES DE EEPROM

        MOVLW .64
        MOVWF R1
        CG2
        CLRWDT
        MOVLW .255
        MOVWF R2

        DECFSZ R2,F
        GOTO $-1
        DECFSZ R1,F
        GOTO CG2
        RETURN

        EEWRITE

        ; ******* EEPROM WRITE ENABLE ******************
        ;endereço esta em ADDRESS
        ;DADOS A ESCREVER ESTA EM TMP(MSB)

        BANK1
        movwf EEADR
        BANK0
        MOVFW TMP ;PEGA PRIMEIRO DADO
        BANK1
        movwf EEDATA
        bcf EECON1, EEIF
        bsf EECON1, WREN ; enable Write\par
        movlw 0x55
        movwf EECON2
        movlw 0xAA
        movwf EECON2
        bsf EECON1, WR
        WRITE_SN_A clrwdt
        btfsc EECON1, WR ; Write complete ?\par
        goto WRITE_SN_A
        bcf EECON1, WREN ; disable Write\par
        BANK0

        clrwdt

        ESPERA1 ;DELAY ENTRE APAGAMENTOS
        CALL AGUARDE
        RETURN

        EEREAD
        ;endereço esta em ADDRESS
        ;DADOS LIDOS SERÃO ESCRITOS EM TMP0

        clrwdt
        ; MOVFW ADDRESS

        BANK1
        movwf EEADR
        bsf EECON1, RD ; do a read\par
        clrwdt
        btfsc EECON1, RD ; Read done ?\par
        goto $-1
        movf EEDATA,W
        BANK0
        MOVWF TMP ;RECUPERA PRIMEIRO NUMERO DA EEPROM
        clrwdt

        RETURN
        ;——————————————————————————
        APAGAEEPROM ;OK TESTADA E APROVADA
        ; ROTINA PARA APAGAR TODAS AS POSIÇOES DA EEPROM DO 16F628

        MOVLW 0X80 ;TOTAL DE 128 + 1 BYTES DE EEPROM
        MOVWF AUX
        RET6
        CLRWDT
        MOVFW AUX
        MOVLW .1 ;ACERTA ENDEREÇO TIRANDO 1
        SUBWF AUX,W
        BANK1
        movwf EEADR
        MOVLW 0XFF
        movwf EEDATA
        bcf EECON1, EEIF
        bsf EECON1, WREN ; enable Write\par
        movlw 0x55
        movwf EECON2
        movlw 0xAA
        movwf EECON2
        bsf EECON1, WR
        WRITE_SN_C clrwdt
        btfsc EECON1, WR ; Write complete ?\par
        goto WRITE_SN_C
        bcf EECON1, WREN ; disable Write\par
        BANK0
        DECFSZ AUX,F
        GOTO ESPERA
        clrwdt
        RETLW 0H
        ESPERA ;DELAY ENTRE APAGAMENTOS
        MOVLW .8
        MOVWF R1
        CG1
        MOVLW .255
        MOVWF R2

        DECFSZ R2,F
        GOTO $-1
        DECFSZ R1,F
        GOTO CG1
        GOTO RET6

        ORG H’2100′
        DE .0

        end

    1. 0

      Olá Fabinhos! A frequência para este esquema é 433mhz. Mas você poderá trocar o microreceptor para a frequencia de 315mhz e usar chaveirinhos de 315 mhz. Note que a versão acima tem que usar chaveirinhos com o HCS200 a 301 dentro (roller code). Para operar corretamente, você terá que obrigatóriamente reprogramar os chaveirinhos que adquirir para uma code ‘key’ que será a mesma a ser usado no receptor (troque no código ASM). Isto exigirá fazer um dos ‘gravadores de HCS‘ postados neste blog ou um comercial. Adianto que para iniciantes é um verdadeiro desafio. Caso queira começar, indico o ‘ receptor genérico‘ com ht6p20b, que não precisa programar os ci interno do chaveirinhos (o ht6p20b já vem programado).
      Cláudio

  7. 0

    TENHO UM PROJETO DE RECEPTOR 3 SAÍDAS. HT6P20B
    COM O PIC 16F628A. TENHO QUE FAZER ALGUMAS ALTERAÇÕES MAS NÃO TENHO EXPERIENCIA.
    SE POSSÍVEL GOSTARIA DE NEGOCIAMOS. A POSSIBILIDADE DE UMA AJUDA, TENHO O ASM FUNCIONADO BLZ. MANTENDO O BOTÃO PRESSIONADO PULSA SAÍDAS.

    CASO ENTERESSE;
    GEORGELIMA2012@GMAIL.COM

    1. 0

      Olá José! Se desejar compartilhar (ou se puder) seu arquivo ASM com este blog, talvez possa ajudar. Se não puder compartilhar (segredos de ‘estado’), não executo serviços por remuneração, apenas por hobby ( não sou programador profissional, mas autodidata). O que voce deseja fazer?
      Claudio

      1. 0

        ola Claudio, boa tarde! vou ter o maior prazer em compartilha um pouco do meu conhecimento aqui com vc´s só me diz como faço para posta os arquivos. e duvidas.
        gostaria de hoje mesmo posta.

        1. 0

          Olá Ney! Agradeço a sua disposição em compartilhar também seus conhecimentos. Peço que voce me envie o material que desejar para o email claudio@larios.tecnologia.ws . Se possivel, envie o esquema e um bloco de notas com a explicação dos componentes e funcionamento, e se tiver alguma regulagem, bem como modo de usar. Não use projetos de terceiros sem a devida autorização para postagem em modo ‘free’. Estou pensando em fazer uma seção de ‘ projetos dos leitores. Quem sabe dá certo.
          Claudio

          1. 0

            ola Cláudio, estou com um desafio aqui, usa o RX GEN HT6P V4 utilizando um controle de 2 botão. E mantida as 3 saídas
            Quando mantém o botão 1 apertado, o led 1. se mantém aceso, sem piscar
            Quando mantém o botão 2 apertado, o led 2. se mantém aceso, sem piscar
            Quando apertado botão 1 e 2 , o led. 3 se mantém ligado on / quando apertado botão 1 e 2 novamente desliga off. será possível ? to tentado ainda não consegui, só iniciante em programação.

          2. 0

            Olá Ney!
            Realmente, este asm não foi previsto o uso do led 3. Mas ache as seguintes porções do código Asm e faça as substituições:

            ;=============================================================================================================================
            ;antiga
            ACIONAR

            BTFSC RES2,7 ;TESTA QUAIS BOTÕES FORAM ACIONADOS NA TRANSMISSÃO
            BSF LED1 ;ATIVA LED1
            BTFSS RES2,7
            BCF LED1 ;APAGA LED1

            BTFSC RES2,6
            BSF LED2 ;ATIVA LED2
            BTFSS RES2,6
            BCF LED2 ;APAGA LED2

            MOVLW T_DESL_LED ;RECARGA DO TEMPORIZADOR DE DESLIGAMENTO
            MOVWF Y2
            MOVLW .255
            MOVWF Y1

            GOTO INICIO
            ;============================================================================================================================

            troque este pedaço de código pelo o abaixo:

            ;============================================================================================================================

            ;nova
            ACIONAR

            ;obs. muitas mudanças!!!!

            BTFSS RES2,7 ;TESTA SE OS 2 BOTÕES JUNTOS FORAM ACIONADOS
            GOTO SEG888 ;UM NÃO FOI
            BTFSS RES2,6
            GOTO SEG888 ;OUTRO NÃO FOI
            BTFSC FLAG_TRAVA_LED3 ;TESTA A TRAVA:SE ESTIVER EM 1 NÃO FAZ NADA
            GOTO SEG999
            BSF FLAG_TRAVA_LED3 ;LIGA A TRAVA
            BTFSS LED3 ;TESTA O ESTADO ANTERIOR DO LED3
            GOTO LIGA_LED3 ;ESTAVA DESLIGADO, VAI LIGAR ENTÃO…
            BCF LED3 ;ESTAVA LIGADO, VAI DESLIGAR ENTÃO…
            GOTO SEG999 ;SAI RECARREGANDO O TEMPO
            LIGA_LED3
            BSF LED3 ;LIGA LED 3
            GOTO SEG999 ;SAI RECARREGANDO O TEMPO

            ;ROTINA DE TESTE INDIVIDUAL

            SEGUE888
            BTFSC RES2,7 ;TESTA QUAIS BOTÕES FORAM ACIONADOS NA TRANSMISSÃO
            BSF LED1 ;ATIVA LED1
            BTFSS RES2,7
            BCF LED1 ;APAGA LED1

            BTFSC RES2,6
            BSF LED2 ;ATIVA LED2
            BTFSS RES2,6
            BCF LED2 ;APAGA LED2
            SEG999

            MOVLW T_DESL_LED ;RECARGA DO TEMPORIZADOR DE DESLIGAMENTO
            MOVWF Y2
            MOVLW .255
            MOVWF Y1

            GOTO INICIO
            ;========================================================================================================================

            AGORA, IDENTIFIQUE ESTA SEÇÃO TAMBÉM:
            ;======================================================================================================================
            LA2

            DECFSZ Y1,F ;CONTADOR DE TEMPO DE DESLIGAMENTO DE SAIDAS
            GOTO J0
            DECFSZ Y2,F ;CONTADOR DE TEMPO DE DESLIGAMENTO DE SAIDAS
            GOTO J0
            BCF LED1 ;APAGA LEDS
            BCF LED2
            INCF Y1,F
            INCF Y2,F
            J0
            ;=======================================================================================================================

            TROQUE POR ESTA:
            ;=======================================================================================================================
            LA2

            DECFSZ Y1,F ;CONTADOR DE TEMPO DE DESLIGAMENTO DE SAIDAS
            GOTO J0
            DECFSZ Y2,F ;CONTADOR DE TEMPO DE DESLIGAMENTO DE SAIDAS
            GOTO J0
            BCF LED1 ;APAGA LEDS
            BCF LED2
            BCF FLAG_TRAVA_LED3 ;ESTE FLAG CONTROLARÁ O ON/OFF DO LED 3 ;mudança aqui!!!!!!!!!!!!!
            INCF Y1,F
            INCF Y2,F
            ;========================================================================================================================

            tAMBÉM, ACRESCENTE ESTA DEFINIÇÃO NO COMEÇO DO ARQUIVO ASM:

            ;======================================================================================================================
            ERRORLEVEL -302
            __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_ON & _MCLRE_OFF

            #DEFINE BANK0 BCF STATUS,RP0 ;SETA BANK0 DE MEMORIA
            #DEFINE BANK1 BSF STATUS,RP0 ;SETA BANK1
            #DEFINE FLAG FLAGS,0 ;FLAG DE SITUAÇÃO
            #DEFINE FLAG1 FLAGS,1 ;FLAG DE NOVA LEITURA
            #DEFINE FLAGGR FLAGS,2 ;FLAG DE ‘LEARN’ APRENDER
            #DEFINE SIN GPIO,0 ;PINO 7 IN RF
            #DEFINE LRN GPIO,3 ;PINO 4 IN LEARN BOTTON
            #DEFINE LED GPIO,5 ;PINO 2 SAIDA LED ‘LEARN’
            #DEFINE LED2 GPIO,2 ;PINO 5- SAIDA DO LED2
            #DEFINE LED1 GPIO,1 ;PINO 6- SAIDA DO LED1
            ;====================================================================================================================

            E TROQUE POR ESTA:

            ;===============================================================================================================

            ERRORLEVEL -302
            __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_ON & _MCLRE_OFF

            #DEFINE BANK0 BCF STATUS,RP0 ;SETA BANK0 DE MEMORIA
            #DEFINE BANK1 BSF STATUS,RP0 ;SETA BANK1
            #DEFINE FLAG FLAGS,0 ;FLAG DE SITUAÇÃO
            #DEFINE FLAG1 FLAGS,1 ;FLAG DE NOVA LEITURA
            #DEFINE FLAGGR FLAGS,2 ;FLAG DE ‘LEARN’ APRENDER
            #DEFINE SIN GPIO,0 ;PINO 7 IN RF
            #DEFINE LRN GPIO,3 ;PINO 4 IN LEARN BOTTON
            #DEFINE LED GPIO,5 ;PINO 2 SAIDA LED ‘LEARN’
            #DEFINE LED2 GPIO,2 ;PINO 5- SAIDA DO LED2
            #DEFINE LED1 GPIO,1 ;PINO 6- SAIDA DO LED1
            #DEFINE FLAG_TRAVA_LED3 FLAGS,3 ;FLAG TRAVA ;MUDANÇA AQUI!!!!

            ;==================================================================================================================

            Eu não tive tempo de testar na prática. Pode ser até que não funcione (lei de Murphy). Mas pediria o favor de voce me testar e

            retornar, por favor.
            Claudio

  8. 0

    Caro Claudio, bom dia.
    Ao usar a expressão “abriu de lona”, quiz dizer que o autor do projeto não acrescentou nada à consulta que fiz; não demonstrou o mínimo interesse pelo assunto enfocado. Esta expressão é um dito popular, rs rs rs. Mas vamos em frente, pois o mundo é assim mesmo.
    Estava pensando aqui na rotina para salvar as informações na EEprom do PIC. Não seria, talvez, somente um acréscimo ao que já existe no programa? Ou talvez, mudar o caminho, ao invéz das informaçoes serem salvas na RAM seriam salvas na EEprom. Se fosse possível isso na versão 16F628A, mesmo sem voce conhecer o “CW”…seria uma “mão na roda” (outro dito popular), ou seja um grande avanço. Mas enquanto não acertamos esse detalhe estou com uma alternativa que, acredito, irá resolver o problema.
    Outro dito popular…”quem não tem cão caça com gato, hi hi hi.
    Ao alimentar o PIC externamente via regulador 7805, passando por um diodo 1n4007, farei uma derivação através de um resistor de 10R em série com outro diodo 1n4007 para o positivo de uma bateria CR2032 (aquelas de computador); O positivo da CR2032 através de outro 1n4007, vai ao pino 1 do PIC (no caso dos 12C509 e 12F629) O 12F629 ainda tem aquele resistor pull up. Conclusão: Enquanto estiver usando alimentação externa para operar o oscilador a CR2032 estará recebendo carga via resistor de 10R. Ao desligar o oscilador e a fonte externa (aí vem o pulo do gato), a memória RAM do PIC vai continuar alimentada pela CR2032, desta forma, preservando as informações. Dois diodos evitam que a bateria se descarregue pela fonte, quando esta estiver desligada e o outro diodo evita que a fonte, quando ligada, alimente a bateria com 5 volts direto, sem passar pelo resistor de 10R.
    Vou continuar nos testes e volto a fazer contato. Fique na Paz de Deus e vamos em frente. Um bom feriado prolongado, saúde e paz junto aos familiares.
    Atenciosamente,
    João

    1. 0

      Olá João! Excelente idéia! As vezes caçamos até com ‘rato’, para entrar na onda dos ditados. Obrigado pela explicação dos ‘termos poucos conhecidos’.
      Bons ‘cw’ para você e os seus.
      Claudio

    2. 0

      Olá João! Peço a sua atenção no seguinte: Na ocasião que você montou a versão com pic 12f629 do manipulador ‘k8’ (blog ‘larios.tecnologia.ws’), você fez uso do ‘beacon’? Se fez, em que pinos foi colocado? Eu não lembro se ficou ativo esta função ou foi desativada na ocasião. Se for possível, me retorna.
      Cláudio

  9. 0

    Caro Claudio, boa noite.
    Entendo sua dificuldade, apesar da boa vontade, pelo fato de não conhecer o “CW”. Mas já foi um grande avanço conseguir a versão 12F629 e estou muito satisfeito pelo seu serviço gratuíto em prol do Radioamadorismo. Por ser leigo no assunto “Assembly”, estava pensando que esta rotina fosse uma coisa simples, mas não é. Vamos deixar como está que prá mim já está atendendo muito bem; os detalhes vamos driblando.
    Com relação ao autor, já fiz contato, ele abriu de lona. A versão disponibilizada na internet por ser gratuíta tem estas pendengas, é assim mesmo que a coisa funciona.
    Valeu sua ajuda e muito obrigado.
    Deus te abençoe e ilumine sempre.
    Atenciosamente,
    João.

    1. 0

      Olá João! O que significa a expressão ‘abrir de lona’????? Vou ler algumas materias, por curiosidade, sobre CW. Quem sabe eu ache um jeito de ‘entender’ os ‘di-dah-dah’ e possa prosseguir com o aperfeiçoamento! Mas, também agradeço por suas ‘aulas’ interessantes de CW. Espero que outros colegas seus possam fazer uso da nova versão com 12f629.
      Cláudio

  10. 0

    Caro Claudio, boa noite.
    Se não for possível criar a rotina na versão 12F629, por falta de espaço, teria jeito de criar na versão 16F628a?
    Atenciosamente,
    João.

  11. 0

    Caro Claudio, boa noite.
    Esses termos eu observei no programa e estou, tirando conclusões, tavez absurdas; vamos esquecer essa parte, rs rs rs. Voce disse a coisa certa; as mudanças que faço em operação são perdidas, pois ficam na memória RAM e a minha intensão seria criar uma rotina que possa salvá-las na EEprom interna do 12F629. Será que se tirar as linhas relativas ao beacon não caberia? Se não tiver jeito, paciência.
    Essa rotina é muito complicada de fazer?
    O restante ficou tudo muito bom.
    Atenciosamente.
    Pretti

    1. 0

      Olá João! Mesmo tirando as rotinas do ‘beacon’ não teriamos suficiente espaço para linhas de código necessárias. Teria que fazer um estudo complicado, que mudasse o fluxo inteiro da rotina, visando reduzir espaço e aproveitar ao máximo as caracteristicas do microcontrolador. Creio que sobrou umas míseras 10 linhas de código livre e a rotina que precisamos precisa de umas 80 a 100 linhas de código. Para piorar, a falta de conhecimento de ‘CW’ iria atrapalhar em muito o desenvolvimento. Quanto ao 16F628a, este sim teria espaço para estas rotinas. Mas o problema é que coisas precisariam ser salvas? Será que não exigiria grandes mudanças na linha de código? Até que ponto esta alteração vai afetar os tempos envolvidos? Talvez, pela falta de conhecimento em ‘CW’, eu não esteja ‘bem apto’ para modificações tão profundas. Por exemplo: Vou testar se esta salvando uma configuração. Aperto o botão ‘PB’ e inicia uma sequencia de sons em código morse… aí, eu boio, escorrego na maionesi, dá até raiva….Será que era o esperado? Percebe o meu problema, caro João? Talvez você poderia entrar em contato com o autor original para sugerir as mudanças que você acha que seria interessante fazer, para melhorar o projeto, em base de sugestão. Tente entrar em contato com o sr. Steven T. Elliott K1EL.
      http://k1el.tripod.com/freeware.html
      email: steve@k1el.com or k1el@aol.com
      conforme consta no arquivo asm original.
      Claudio

  12. 0

    Caro Claudio, boa noite.
    Sim, eu entendi. Já fiz a mudança no ASM e compilei. Agora sempre que desligar e religar será wpm_36, ok. Caso mude para wpm_40, quando desligar e religar voltará para wpm_36. Gostaria que permanecesse wpm_40.
    Estou observando uma rotina interessante na linha 167 do “ASM modificado”:
    ;Defining NO_DE modifies default messages (EWP?)
    ; #Define NO_DE
    Estou entendendo que esta rotina quando desabilitada, como está, impossibilita que eu modifique a mensagem original inserida no ASM. Posso até mudar com o oscilador ligado, mas assim que desligar e religar a mensagem default volta, entendeu. Caso eu habilite esta rotina, aí poderei alterar a msg original. Então para a wpm deve existir uma chave.
    Por favor, dê uma olhadinha nessa linha. Se não tiver nada que ajude, então vamos encerrar essa questâo, rs rs rs.
    Desculpe estar te apurrinhando ainda.
    Atenciosamente,
    João.

    1. 0

      Olá João! Tenho dificuldade de entender os termos usados por vocês ‘cedablistas’ (se me permite usar o termo). O que é EWP?????? O que voce quer dizer com ‘existir uma chave para wpm’? O que seria este ‘DE’? Gostaria de lembra-lhe que todas as mudanças feitas durante a operação de funcionamento serão TODAS perdidas, pois ficam na Ram e não temos mais linhas no programa suficientes para fazer uma rotina que possa salva-las na EEprom do Pic12f629. È uma pena, já que o chip dispõem de EEprom interna.
      Claudio

  13. 0

    Caro Claudio, boa noite.
    Ok, vou ter que fazer isso.
    Eu te perguntei porque tenho um oscilador com o PIC12F629 que adquiri muito tempo atrás em que mudo a WPM e ao desligar e religar a nova WPM é mantida. Tentei abrir o PIC, mas está protegido.
    Vamos em frente, vou continuar os testes.
    Grato mais uma vez.
    Atenciosamente,
    João.

    1. 0

      Olá João!
      Voce poderá mudar a linha escrita : SPEED_DEFAULT EQU WPM_15 para SPEED_DEFAULT EQU WPM_36

      Você localizará no programa quando se parecer com o abaixo:

      ; ————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 (ESTE AQUI VOCE DEVE MUDAR E DEPOIS RECOMPILAR NO MPLAB)

      O restante está tudo operacional????
      ;

      Claudio

  14. 0

    Caro Claudio, boa tarde.
    Estou verificando o funcionamento do PIC no circuito e já esbarrei num detalhe interessante. A velocidade default no “ASM modificado” está em WPM_15 (linha 295). Então quando ligo e checo a velocidade, pelo comando “w” está em 15. No circuito e usando o botão de programar alterei a velocidade para WPM_36 e funcionou normalmente. Porém ao desligar o circuito e depois voltar a ligar ele retorna para WPM_15, entendeu. Resumo: Toda vez que ligo o circuito a velocidade é WPM_15. É normal isso ou pode-se fazer algum ajuste no ASM para manter a nova velocidade programada, WPM_36?
    Atenciosamente,
    João.

    1. 0

      Olá João! Creio que é normal, uma vez que o valor é salvo na memória RAM e uma vez que você desliga, será perdido a informação. Você pode alterar o valor padrão do Asm para ser o que você deseja (wpm_36).
      Claudio

  15. 0

    Caro Claudio, boa tarde.
    Aproveitando o tempo chuvoso estou aki desde cedo procurando acertar as arestas e tirar todas as dúvidas. Valeu de verdade mais esta ajuda. Agora vou me organizar e fazer os testes com o novo ASM.
    Com relação ao primeiro ASM, objetivando mudar alguns pinos, fiz as mudanças primeiramente alí nos GPIO,2…etc, logo no início do ASM. Mas notei que mais adiante tinha algo ainda a ser modificado em “initialization routine”, nas linhas MOVLW B’00101011′ e MOVLW B’00001011′. Fui para o datasheet para achar alguma coisa sobre esses números e voei geral.
    Só por curiosidade, como voce chegou à esses números? Se é que eles tem algo em relação à mudança de pinagem.
    Ok quanto ao errorlevel -302.
    No mais tudo tudo certinho graças a Deus.
    Mais uma vez obrigado por sua atenção e disponibilidade, um bom fim de semana e que Deus te abençoe sempre.
    Todos os resultados dos testes vou te repassar com certeza.
    Atenciosamente.
    João.

  16. 0

    Caro Claudio, bom dia.
    Estou desde cedo tentando descobrir os mistérios das mensagens que surgem na compilação, até agora nada.
    Te incomodando mais um pouco.
    Se quiser colocar o sidetone no pino 2, a saída para o rádio no pino 3 e o botão de programação no pino 5, onde preciso alterar? atualmente está:
    sidetone…3
    programação…4
    saída/rádio….5
    Atenciosamente.
    João.

    1. 0

      Olá João! As mensagens do compilador são normais, mas para elimina-la basta digitar ‘ERRORLEVEL -302 ‘ no programa asm. Mudar os pinos nesta versão é muito chato, pois têm que mudar em várias partes do programa, a carga do registrador ‘trisio’. Por isso, estou fornecendo abaixo, uma versão com um ‘facilitador’ para mudanças de pinos. Basta ir na parte do programa asm onde você lerá ‘OPÇÃO PARA ESCOLHA DE PINOS DO MICROCONTROLADOR’ e alterar os pinos que te convier (para facilidade de placa de circuito impresso, por exemplo). Esta ‘facilidade’ altera automaticamente o registrador ‘trisio’ quando voce alterar a função na gpio. Corrigi também a questão da mensagens do compilador nesta versão. Por favor, teste-a e depois de um retorno.

      Você verá esta parte no programa asm:
      ;***********************************************************************************

      ;ALTERE AQUI OS PINOS A GOSTO, SOMENTE LEMBRANDO QUE GP3 (PINO 4) SOMENTE PODERÁ
      ; SER USADO COMO UMA ‘ENTRADA’ (E QUE TAMBÉM DEVERÁ USAR UM PULL-UP EXTERNO )
      ; (OS VALORES DE TRISIO IRÃO ACOMPANHAR AUTOMATICAMENTE ESTAS MODIFICAÇÕES)

      ;SENDO AS PINAGENS:
      ;GPIO,0= PINO 7
      ;GPIO,1= PINO 6
      ;GPIO,2= PINO 5
      ;GPIO,3= PINO 4
      ;GPIO,4= PINO 3
      ;GPIO,5= PINO 2
      ; +VCC = PINO 1
      ; GND = PINO 8

      XDITPDL EQU 00H ; IN DIT Paddle PINO 7
      XDAHPDL EQU 01H ; IN DAH Paddle PINO 6
      KEY EQU 02H ; OUT Keyed Output PINO 5
      XPB EQU 03H ; IN Message/Config Push Button PINO 4
      TONE EQU 04H ; OUT Sidetone Output PINO 3
      BCON EQU 05H ; IN/OUT Beacon Request PINO 2

      ; EX. SE COLOCAR ‘KEY EQU 00H’ ENTÃO GPIO,0 PINO 7 SERÁ A SAIDA ‘KEY’
      ; OU AINDA, SE COLOCAR ‘XPB EQU 01H’ ENTÃO GPIO,1 PINO 6 SERÁ ENTRADA ‘XPB’
      ; AUTOMATICAMENTE JÁ ACERTADO O REGISTRADOR TRISIO DE IO’S.
      ; CONFIRA PARA NÃO COLOCAR DOIS ‘IGUAIS’ OU ESQUECER DE ALGUM.
      ;==============================================================================

      Pegue o arquivo asm modificado -> aqui

      Cláudio

  17. 0

    Caro Claudio, boa noite.
    Na linha 85 do ASM consta: Escolha o micro…aqui.
    Na linha 86…1º)Optei pelo 12F629 e compilei.
    Deram 5 mensagens: Linhas 1433, 1449, 1451, 1453, 1455. Não sei o que significam estas mensagens.
    Obs: Nenhum erro registrado.
    No simulador/Proteus 7: Funcionou zero bala (sinal verde) sem erros.
    Quanto ao circuito: Alimentei o pino 4 através de um resistor de 10K, mantendo a chave phus-pull diretamente no pino do PIC.
    Obs: Sem essa alimentação, realmente não funciona.
    Resultado: Ao iniciar a simulação o oscilador emite um “R”. As chaves de ponto e traço estão OK. Pressionando momentaneamente a chave do pino 4 inicia a chamada geral default, por duas vezes, e para. Mantendo pressionada esta chave, o oscilador emite um “R” indicando que está em modo de programação. Então está tudo muito bom, parabéns.
    Com relação ao 12F675, na linha 86 mudei conforme instrução e compilei.
    Deram seis mensagens: Linhas 1433, 1447, 1449, 1451, 1453, 1455. Não sei o que significam.
    Nenhum erro registrado.
    No simulador/Proteus, também tudo cem por cento. Sinal verde, sem erros.
    Acredito que não haja nada mais a ser feito. Quanto às msg geradas na compilação, também, quero acreditar que não venham a influenciar no pleno funcionamento do oscilador quando montado na placa/fibra. Pelo ao menos no simulador Proteus está tudo ótimo.
    Voce teria alguma noção do que poderia estar gerando essas mensagens? É normal isto ocorrer, mesmo sem a ocorrência de erros?
    No mais, estou muito satisfeito e agradecido. Amanhã vou analizar tudo com calma e procurar entender um pouco as modificações que voce efetuou no ASM do 16F628A.
    Fico-lhe muito grato e que Deus te abençoe e ilumine sempre. O Radioamadorismo, também, agradece por sua gentileza gratuíta.
    Em tempo: Vou montar um K-8/PIC12F629, versão CL, no Proto-board e fazer todos os testes. Depois te informo o resultado.
    Boa noite e um bom fim de semana.
    Atenciosamente,
    João.

  18. 0

    Caro Claudio, boa dia.
    Se ao pressionar a chave de programação momentaneamente ele emite a mensagem defaut (gravada no programa), é possível que as chaves de ponto e traço também estejam ok. E se ao pressionar a chave de programação por uns 2 ou 3 segundos ele emitir um sinal “R”, então, esta função também deve estar ok.
    Se vc não suprimiu nenhuma linha do programa a estrutura funcional dele está intacta, indicando que voce está conseguindo desenvolver a versão com o 12F629. Sucesso e boa sorte na caçada…
    Obs: Com o 16F628, não tem a função “beacon”.
    Atenciosamente.
    João.

    1. 0

      Olá João! Tomei uma canseira com 2 pic’s 12f629 com defeito. Horas perdidas…. Gostaria que você testasse a versão do K8 para pic 12f629 ou opcionalmente, para 12f675. Voce deverá compilar no Mplab (está em assembler).

      Pegue o arquivo ASM do manipulador K8 clicando -> aqui.
      (K8 Shareware Keyer Microchip PIC Source Code)
      Use este esquema sem a chave ‘beacon’. Também, voce deverá adicionar um resistor de pull up (4K7 ao +Vcc) no pino 4 (já que ele não tem este recurso internamente).
      Por favor, me de um retorno.

      Cláudio

  19. 0

    Caro Claudio, boa noite.
    Eu olho os datasheets dos PIC’s mas não consigo entender nada. Se Vc conseguiu uma compilação sem erros, já é um bom sinal. Caso vc esteja usando o simulador do Proteus, ao iniciar a simulação ele dará um sinal. Apertando a chave de programação momentaneamente ele emite uma mensagem por duas vezes e para. Esta msg é do próprio programa. É uma chamada geral. Se aterrar o pino 6 ele emite uma sequência de pontos e se aterrar o 7 ele emite uma sequência de traços. Vc não consegue entrar no modo programação pelo simulador porque as chaves não são sincronizadas e sim duas chaves independentes. Aí vc não consegue fazer as combinações para gerar os caracteres de forma correta. Mas se voce manter o pino de programação aterrado por uns 3 segundos o PIC vai emitir um “R”, ou seja um ponto, um traço e um ponto (.-.); isto significa “R” em morse, rs rs rs. Quer dizer que o PIC está pronto para receber os comandos pela chave iâmbica. Estou aki torcendo para dar certo.
    Com as mudanças e após a compilação ele zerou em tudo ou deu alguns avisos? Não tenho a mínima idéia do que vc fez, em termos de modificações.
    Outra coisa; vc está trabalhando com o F628 para 629 ou C509 para 629?
    Atenciosamente.
    Pretti

    1. 0

      Olá João!
      Já consegui fazer o envio da ‘chamada geral’ ao ligar e dar um toque na chave de configuração. Estou usando o f628 para 629. Já não dá mensagem de erros, mas os problemas tem que ver com a diferença entre bits dos registradores. Vou ‘caçar’ as diferenças. Mas, pode demorar algum tempo.
      Claudio

  20. 0

    Caro Claudio, bom dia.
    Eu tenho aqui a versão para o 12C509 e 16F628-A.
    Gostaria de ter a versão com o 12F629, porque tenho uns 12 por aki e quero aproveitá-los e também pelo tamanho.
    Já mudei o cabeçalho do 16F628-A para 12F629, deu bastante erro.
    Só uma curiosidade: qual a diferença real do 16F628 para o 16F628-A?
    Por aki é difícil encontrar esses PIC’s. Quando alguma loja de eletrônica tem, o preço é sempre muito alto e não vale a pena adquirir nada por aki. Sai mais em conta comprar em São Paulo, mesmo com o frete embutido.
    Deus ajude que o 16F628 seja mais parecido com o 12F629.
    Atenciosamente.
    João.

    1. 0

      Olá João! As diferenças você ve comparando os data sheets dos dois modelos. Os erros se deve ao fato do 629 usar o termo gpio ao invés de porta ou portb. Sempre , ao fazer mudanças de um pic para outro, tem que olhar os datasheets para não ter surpresas. Já consegui compilar com 629 mas, ainda to tentando entender o que o circuito tem que fazer. Não estou conseguindo entrar em modo de configuração, mas já está enviando algum sinal (só voce que entende morse).
      Cláudio

  21. 0

    Caro Claudio, boa noite.
    No Site de PY2MG, por favor dê uma olhada no projeto nº 5, K8 versão PIC16F628.
    De repente pode ser mais parecido com o 12F629.
    Atenciosamente.
    Pretti

  22. 0

    Caro Claudio, boa noite.
    Pela sua explanação referente às diferenças entre os microprocessadores a coisa me parece mais complicada que pensei. A minha preferência pelo 12F629 é que tenho dele aki o 12F683 não.
    Com relação às funções, vou tentar explicar:
    Pino 2: Beacon – Quanto ligado uma mensagem em morse, definida pelo operador e gravada no PIC, é enviada para o rádio de 20 em 20 segundos, por exemplo.
    Pino 3: Sidetone – É o monitor de áudio. Tudo que o operador transmite ele ouve. É a sua referência.
    Pino 4: Chave tipo push button. Apertando momentaneamente, o PIC emite uma mensagem em morse defaut, tipo uma chamada geral (cq cq cq de xx1fg xx1fg AR k). Se pressionar esse botão por alguns segundos entra no modo programação. Aí o PIC emite um sinal (R) informando que está preparado para receber os comandos. Então, existem vários comandos, de A a Z. Cada letra tem uma finalidade. Por exemplo: A letra “A” ativa e desativa o monitor de áudio. A letra “M” ativa a seleção de mensagem. A letra “S” ajusta a velociade de manipulação, e assim por diante. Todos os comandos são via chave que está nos pinos 6,7 e 8.
    Pino 5: Saída para o rádio. Quando a chave beacon está ligada ou o operador estiver transmitidindo pela chave iâmbica (pinos 6,7 e 8) a base do transistor é alimentada, colocando o coletor em massa. Isto faz o rádio entrar em transmissão, emitindo para a antena os sinais morse.
    Pino 6 e 7: A chave iâmbica está ligada nestes pinos e ao 8. Esta chave fica sobre a mesa na posição horizontal. O operador trablha nela com os dedos polegar e indicador. Quando se curto-circuita o pino 6 com o pino 8, geram vários sinais longos (são os traços). Quando se curto-circuita os pinos 7 e 8, geram os sinais breves (são os pontos). Da combinação dos traços e pontos
    formam-se as palavras, textos, números, pontuação, etc…O operador pode transmitir numa velocidade muito grande, 20, 30, 40, 50, palavras por minuto, dependendo de sua destreza. A velocidade de transmissão é definida pelo botão que está no pino 4.
    No geral é isto que o oscilador eletrônico para CW faz. Coisa, realmente, de maluco.
    Gostaria de ajudar, mas infelizmente não entendo nada de assembly. Se voce achar que não vale a pena, sua boa vontade em me atender e ajudar já foi uma grande vitória.
    Atenciiosamente.
    João

    1. 0

      Olá João! Obrigado pela aula de radiamadorismo (lição 1). Já deu para clarear as idéias. Vou ver o esquema com o 16f628 e estuda-lo. Aguarde…
      Claudio

    2. 0

      Olá João!
      Esqueci de perguntar, se na sua região tem o pic 16f628 ou 16f628a? A sua escolha pelo Pic 12f629 é pelo tamanho ou porque não existe os outros modelos na sua região? Voce já tentou compilar esta versão com 628?
      Claudio

  23. 0

    Caro Claudio, bom dia.
    No Google digite PY2MG, procure “manipuladores eletronicos para CW” , projeto nº3 K8-K1EL.
    Voce vai encontrar a versão PIC12C509, esquema, manual e o ASM.
    Pelo e-mail que me mandou não consegui. Uma msg diz que o destinatário não foi encontrado.
    Espero que pelo caminho acima dê certo.
    Atenciosamente.
    João.

    1. 0

      Olá João! Realmente, mudar somente o cabeçalho na adianta. Estudando o datasheet de ambos microcontroladores, nota-se muitas diferenças: o 509 só tem 2 nivéis de stack, e 8 para o 629, o endereço inicial da ram do 509 é 07h e do outro 20h, a palavra de status de um é diferente da outra, a palavra de configuração tem mais variações no 629, o registrador gpio fica no endereço 6 no 509 e 5 no 629, o registrador option_reg tem diferença, o 509 não tem comparadores e no 629 tem que desliga-los. Resumindo: vai ser um verdadeiro desafio fazer funcionar, pois terá que ser alterado muitas rotinas. O espaço do programa já é justo. Com as mudanças irá aumentar o tamanho do programa não cabendo no 629 se não for alterado substancialmente a rotina original. Para piorar, eu não sei exatamente para que serve certas funções (não entendo de radiamadorismo). Existe a função ‘beacon’, eu pergunto para voce para que serve? Voce poderia fazer uma detalhada descrição, olhando para o esquema, de como voce usa este aparelho? Ex. apertando a chave dit acontece…. apertando a chave dat….apertando funções escolherei fazer….. a saida tx eu ligo no …. o monitor eu uso para ….,etc. Existe a opção do pic 12f683 que tem 2k de memória. Tem ele na sua região?
      Claudio

  24. 0

    Caro Claudio, boa noite.
    Tentei passar duas vezes o email (pela manhã e agora a noite). Acredito que não foram, pois recebi uma mensagem alertando que não foi possível encontrar o destinatário.
    Atenciosamente.
    Pretti.

  25. 0

    Caro Claudio, boa noite.
    Me oriente como enviar os arquivos ASM e circuitos por aqui. Coloquei meu email na última msg mas sumiu. Os arquivos ASM são mto grandes e os circuitos estão em pdf e jpg.
    73.
    joão.

  26. 0

    Caro Claudio, boa noite.
    Tenho o .ASM na na versão do PIC12C509. Já fiz a compilação com o cabeçalho do 12C629. Deu dois avisos apesar de não apresentar erros, só que ao testar no simulador do Proteus não funcionou. Tenho aki também a versão para o PIC16F84A e 12C509. Por aki não sei direito como enviar os arquivos e esquema. O circuito funciona como um oscilador eletronico para envio de sinais morse por chave iâmbica, possuindo também mensagens gravadas. É muito operado por Radioamadores pelo mundo afora.
    Atenciosamente.
    João.

    1. 0

      Olá João! percebo que você gosta de radioamadorismo. Aguardo o envio dos esquemas e dos códigos asm que você tem. Defina bem o que voce deseja fazer ou seja, suas opções de circuitos que melhor lhe atende.
      Claudio

  27. 0

    Caro Claudio, bom dia.
    Já fiz mais de 500 compilações e não cheguei há lugar nenhum. Estou desde cedo tentando e nada.
    Onde tinha escrito PORTA e PORTB, modifiquei para GPIO. Agota alterar essas configurações de TRISA/TRISB por TRISIO, me deu um nó. Onde eu encontro isto. Acertar o TRISIO? me embananou todo. Te mandei o .ASM mas acho que ficou faltando um pedaço no final. Dê uma olhada com carinho prá ver se eu acerto esse projeto. No datasheet do PIC12F629, quanto mais eu observo pior fica, não entendo nada. Já procurei por TRISA/TRISB – TRISIO e nada. É tudo muito difícil e complicado. No mais, tudo certinho. Bom domingo e desculpe estar te apurrinhando com minhas idéias.
    Atenciosamente,
    João.

  28. 0

    Caro Claudio, bom dia.
    Na cópia que mandei acho que o final do arquivo não foi….Caso precise mando novamente.
    Posso mandar por e-mail? Posso citar meu e-mail aqui?
    Atenciosamente.
    João.

  29. 0

    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

    1. 0

      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

  30. 0

    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.

  31. 0

    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.

    1. 0

      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

  32. 0

    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.

    1. 0

      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

  33. 0

    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

    1. 0

      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

  34. 0

    Ola Claudio eu não estou conseguindo pegar o hex e gravar no pic estou usando o ICPROG copiei o HEX disponibilizado por vc e não está gravando e aí tentei compilar pelo MPLAB e naõ está compilando ta dando varios erros.Qual o compilador que vc usa?

  35. 0

    ola claudio

    para gravar neste ci e so copiar o arquivo que vc passou,ou tem outro macete?
    abraços Vagner

    1. 0

      Olá Vagner! De posse de um gravador de sua preferência, basta escolher a versão do arquivo hex (12f629 ou 16f628a) desejado e enviar para o ci a gravar.
      Claudio

  36. 0

    ola claudio
    gostaria de saber como faço pra gravar este programa no beeprog,pois tenho ele no trabalho.sei usar o beeprog,mas nao sei como gravar.da uma dica ai,estou fazendo um trabalho para feira da puc bh e essa seria uma otima base para meu projeto,necessito de receptor para o HT6P20B que tenha 3 saidas de nivel logico 1

    no aguardo de sua resposta abraços vagner
    segue meu email ribeir.vagner@oi.com.br

    1. 0

      Olá Vagner! Eu tenho usado um hardware programador caseiro conhecido como ‘ simples programador’ e o software programador WinPic800. Não conheço o BeeProg, mas poderá obter informações no site da elnec com seus manuais de operação. Verifique com colegas de sua secção, se eles não podem dar uma dica ‘pratica’ de como usar o aparelho, pois está envolvido a parte fisica do hardware e o programa que tem de rodar no PC.
      Claudio

  37. 0

    Ok Claudio, quanto a assinar os projetos nao teria problema ja que sou engenheiro e me responsabilizaria por eles, entendo o objetivo do blog e estou totalmente de acordo com voce que em internet o objetivo principal é ajudar aos nossos amigos internautas (tambem comparto muitos arquivos com a galera )..Mas sem problema fico aguardando que voce tenha um tempinho , esperei muito tempo pra encontrar esse tipo de projeto (posso esperar um pouco mais ,rsrsrsrs)..Enquanto isso desde ja agradeço seus projetos ja em ajudaram muito como base pra desenvolver outras idéias aqui tambem ..qualquer novidade sobre o que conversamos me avise por favor, um abraço….

  38. 0

    Claudio muito obrigado pela sua atençao , teria como voce desenhar um projeto com essa quantidade de controles que voce falou (máximo 40 ), com isso ja possso fazer alguma coisa aqui (imagino que isso tem algum custo ,mas sem problema ) por isso que gostaria de entrar em contato com voce pra ver a possibilidade de trabalhar nesse projeto e desenvolvelo .. eu sou do interior de sao paulo e a 10 anos moro e trabalho em caracas venezuela fabricando e instalando sistemas de segurança eletronica e de perimetro tenho um blog http://www.brazitech.blogspot.com , gostaria muito de contar com sua ajuda …..

    1. 0

      Prezado Claudinei

      Sinto me honrado pelo seu pedido, mas percebo que suas intenções são comerciais. E sou apenas um simples hobista, não tenho qualificações profissionais (como tecnico ou engenheiro) para assinar projetos e responsabilizar por eles. Ademais, o objetivo deste blog é apenas divulgar conhecimento padrão que possa ser adaptado as necessidades individuais, não visando fins comerciais. Mas, se voce desejar, posso disponibilizar o blog para algum programador que esteja lendo este artigo e queira ganhar uns trocos, possa entrar em contato com voce. Do contrário, quando tiver um tempinho, e for bem sucedido, postarei alguma coisa.
      Obrigado

  39. 0

    Ah esqueci de falar o projeto seria para um condominio com mais ou menos 50 pessoas e um só motor para o portao para entrada e saida , por isso é que precisa ter um controle de cada usuario e em caso de perda do controle remoto por segurança se lo eliminaria da memória….

    1. 0

      Olá de novo Claudinei
      A memória EEprom dos pic’s menores tem em média 128 bytes, o que dá aproximadamente 40 controles. Pode-se usar memória 24c0x externa ou pic com mais capacidade de memória. A vantagem da memória externa, é , se der pau na placa, pode-se trocar a memória antiga na placa nova, pois estando já programada, não precisará reprogramar tudo de novo. Com respeito ao numero maximo, deve-se levar em conta que cada controle armazenado será comparado com o sinal recebido, e isto gasta ‘ n’ microsegundos. Quanto mais controles, e na ocasião que o ultimo da memória tenha que ser comparada, será n x numero do ultimo controle. A situação piora quando temos de usar memória externa i2c porque o clock delas é limitado a algumas centenas de khz. Assim, entre a recepção e ativação do portão não pode passar mais que 0,5 segundos, sob pena de alguém reclamar. Conclusão: projetos com centenas de controles são mais trabalhosos. Precisa de muitos testes para se ter um funcionamento adequado. Vou colocar na minha lista de futuros projetos essa sua necessidade.

      1. 0

        Diante do problema de performance, acredito que seja possível implementar o algorítimo de busca binária;

        A idéia é manter organizado sequencialmente na memória, os itens, toda vez que for realizada uma inserção ou acréscimo; Depois no momento da busca, faz-se a pesquisa sempre na metade, evitando a necessidade de percorrer todos os registros durante a consulta;

        Acredito que isto possa ajudar a minimizar o problema, mas na prática,
        no mundo dos PICS, não faço a menor idéia do resultado.

        http://pt.wikipedia.org/wiki/Pesquisa_bin%C3%A1ria
        http://www.indiastudychannel.com/projects/2748-Assembly-language-program-for-Binary-search.aspx

        http://www.dailyfreecode.com/code/sort-list-ascending-order-binary-search-2008.aspx

        http://en.wikipedia.org/wiki/Binary_search

  40. 0

    Outro detalhe, parace que aqui mesmo no seu blog tem um esquema de um leitor de codigo com lcd poderia utilizar como base esse circuito talvez ??

  41. 0

    É exatamente o que voce descreveu que preciso ,gostaria de ver a possibilidade de desenvolver um projeto desse tipo e se voce teria como ajudar com seus conhecimentos, conheço muito de eletronica desenho e produçao de circuitos impressos ,mas me complico um pouco ainda com projetos com os pics da vida… faz muito tempo que ando buscando esse tipo de projeto ..outro detalhe até quantos controles se poderia aprender ???..

  42. 0

    Bom dia Cláudio, me interessa muito esse projeto gostaria de saber se esse sistema é compativel com os controles que utilizam o hcs 201 , mas a ideia que tenho é a seguinte , precios de um sistema que alem, de ler o codigo dos controles, tenha a funçao de poder eliminar controles ou adicionar controles de forma individual..se possivel se voce tiver um telefone ou email para contato seria ótimo realmente estou muito interessado…

    1. 0

      Ola
      á Claudinei
      Sim é compativel com hc201. Quanto a eliminar controles individuais, exigiria um gerenciador de controles/sensores aprendido que alistasse um nome/numero a uma posição de memória. Desta forma, com o nome/numero poderiamos saber os lugares da memória a apagar. Com certeza, torna o projeto mais complicado, mais memória, um lcd para ver o nome/numero,etc. Qual é a sua idéia?

  43. 0

    😛 parabens pela iniciativa de divulgar um trabalho deste em, para mim estes controles e um mito, vou por a mão na massa aqui para testar, valeu mesmo ai ok, um abraço

Os comentários estão fechados.