leitor rfid
Post on 19-Dec-2015
244 Views
Preview:
DESCRIPTION
TRANSCRIPT
Leitor RFID
Leitor RFID
Cartes RFID so normalmente usados para controle de acesso e tickets de nibus e metrs. Eles so convenientes porque no precisam de contato direto para transferir informaes de/para o carto. Como estes cartes so alimentados pelos prprios leitores, dispensam o uso de baterias que precisariam ser recarregadas.
Para os meus experimentos estou usando catres da HID ISProx. Estes cartes so os mais simples de toda a linha de cartes RFID, que somente armazenam um nmero de srie e no usam criptografia. A frequncia da portadora de 125kHz.O primeiro passo descobrir como desenvolver um leitor simples. Ns sabemos que o cartes RFID alimentado pelo campo magntico emitido pelo leitos. Astags RFID transferem informao de volta ao leitor consumindo este campo magntico, que detectado pelo leitor como uma variao no campo.
So chamados de tags RFID todos os elementos que armazenam informaes e so mveis, como o carto, neste caso especfico.
O projeto mais comum de um leitor RFID faz uso de um circuito ressonante srie. Ele consiste de um indutorsimples e um capacitor, excitados por uma fonte de tenso de baixa impedncia. Se o Q do circuito for alto o suficiente, a tenso no ponto de amostragem (Vsample) vai exceder a tenso de alimentao. Quando o RFID alimentado por este campo magntico o Q do circuito cai. O resultado uma pequena alterao na tenso de amostragem (Vsample no circuito mostrado).
Eu criei um leitor simples com componentes encontrados em minha sucata. Usando um gerador de funo como fonte de sinal e um osciloscpio no ponto de amostragem, eu pude sintonizar a frequncia at encontrar o ponto ressonante do circuito. Eu continuei substituindo os capacitores neste circuito at encontrar a frequncia que eu estava procurando. O clculo da frequncia este:
Por alguma razo eu me confundi e iniciei o projeto tendo em mente a frequncia de 150kHz ao invs de 125kHz. AstagsRFID respondem bem a uma frequncia mais alta, ento eu mantive assim para evitar voltar a trs e redesenhar todo o circuito. Com um ajuste simples eu verifiquei quais alteraes aconteciam quando a tag RFID era submetida a 4 ou 5 ciclos de frequncia da portadora. Uma vez que o sinal precisa ser AC e no DC, eu assumi que a frequncia de transmisso seria 150kH/8 = 18.75kHz ou 150kHz/10 = 15kHz. Este detalhe eu encontrei em um site que foi realmente til por conter boas informaes sobre RFID:http://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2006/cjr37/Website/index.htm.
Atagaparentemente codifica o dado usando FSK. As duas frequncias representam o 0 e 1 lgicos.
Com esta informaes em mos, eu avancei e iniciei o projeto do meu prprio indutor-antena. Uma vez que eu mantive a idia de usar 150kHz como frequncia da portadora, eu fiz o clculo e fiquei com uma indutncia de 160uH e um capacitor de 10nF. Eu utilizei a seguinte equao para estimar o nmero de voltas que precisaria em minha bobina:
Onde x, y so o comprimento e a largura da bobina, h a altura e b a espessura da parte condutora. Eu utilizer x=y=6cm, h=1cm e b=0.3cm. O nmero encontrado foi 34. Eu enrolei a bobina em uma caixa de papel que encontrei, de onde eu extrai o x e y. Depois de enrolada, a bobina foi extrada e presa com fita adesiva.
Para um ajuste fino da frequncia ressonante do sistema todo eu decidi brincar com o valor da capacitncia. Usando o gerador de funo para variar a frequncia e visualizando o pico da sada com um osciloscpio, eu variei os valores dos capacitores at que o pico da resposta ressonante fosse a 150kHz. O capacitor final foi de 0.056uF. Uma vez que o meu capacitor precisa ser um valor de mercado, a bobina que eu constru precisa ter uma indutncia maior que 160uH.
O prximo estgio era projetar o circuito analgico. Eu usei o confivel AMPOP TL062 (eu j possuia vrios desses em casa). As frequncias envolvidas neste circuito so relativamente baixas, ento a baixa peformace em frequncia deste AMPOP no problema. Eu havia decidido evitar um circuito complexo, ento elegi o circuito mais simples que poderia ser usado.
Ento, a idia usar um simples diodo detector. Este detector de tenso passar por um primeiro AMPOP configurado como amplificador inversor com uma resposta em frequncia passa baixa. Isso remover uma boa parte do volume da portadora. O prximo estgio do circuito analgico extrair o sinal FSK. O circuito mais simples que me veio a mente foi um filtro ressonante passa banda com frequncia central em torno de 17kHz. Isso s me custaria um AMPOP. Este circuito foi desenhado no SPICE e o grfico da frequncia de resposta mostrado no final desta pgina.
A sada do passa banda um sinal que pode ser diretamente conectado um microcontrolador PIC. Eu escolhi para este projeto o bom e velho microcontrolador PIC16F628A. Com o comparador interno eu posso receber o sinal diretamente do AMPOP e extrair o sinal digital.
A decodificao do sinal FSK feita por software, o que realmente interessante para no aumentar a nossa lista de componentes.Para decodificar o sinal FSK eu implementei trs subrotinas que usam o TMR0 para marcar o tempo passado entre as mudanas detectadas na sada do comparador. Nenhuma interrupo usada. Ao invs disso, as rotinas foram colocadas em loop at que um estado de mudana detectado. O loop que faz a deteco leva em torno de trs ciclos de CPU para rodar; assim, dependendo de quando a mudana ocorre, o erro mximo de 3 ciclos.
Algum que conhece como o hardware do PIC funciona poderia me perguntar porque eu no usei o mdulo CCP (Compare and Capture). Infelismente eu utilizei o mdulo PWM para gerar a portadora de 150kHz. Como o CCP compartilha recursos com o mdulo PWM, apenas um deles pode ser ativado por vez.
Para ter uma idia geral de como o sinal FSK aparece depois de digitalizado, eu adicionei um modo debug onde ele ir capturar um nmero de ciclos de CPU ocorridos entre cada mudana no sinal de entrada.
Devido s limitaes da memria on-chip, somente 80+64 pontos de dados foram capturados. Isso no grande o sufuciente para decodificar o dado, mas suficiente para ns desenharmos uma viso geral de como o sinal se parece.
Sada do modo Debug, logo aps o final do contador de ciclos
Neste grfico, os nmeros no eixo Y representam o tempo (em ciclos de CPU) entre cada mudana de estado no sinal de entrada. Eu decidi que 85 era um nmero bom para saber se o sinal de entrada era zero ou um. No futuro eu acabei decidindo alterar a rotina de decodificao para contar o tempo gasto entre cada borda de subida do sinal (uma vez que o sinal no possui componente DC, isto economizaria memria j que eu s guardaria um bit ao invs de dois). Assim, a constante utilizada no firmware do PIC cresceu e eu estou usando 170 (2x 85).
A sequncia decodificada dos dados se parece com:
0000000000000000000000001111111111111111000001111110000001111100000011111000000111111 ... ...
111111000001111110000001111100000011111111110000000000001111111111100000011111000000000000 ...
0000001111110000001111111111000000111111000000000000000000000000111111111111111100000
Voc pode ver que o dado inicia com vrios zeros, seguidos de alguns nmeros 1 que so o dado atual. A sequncia inteira continua a se repetir.Eu conheo o sinal codificado em Manchester, ento, a partir do sinal, eu posso chegar seguinte concluso:1. A sinal inicia com uma sequencia de zeros, superior a vinte zeros.2. A segunda sequncia tambm sempre uma sequncia de 1 com pelo menos 15 bits.3. Para cada bit existem entre 10 e 12 nmeros zero ou um.4. O bit zero se no existe nenhuma mudana no sinal durante o tempo de um bit.
Um grfico rpido pode ser desenhado:
111111000001111110000001111100000011111111110000000000001111111111100000011111000000000000
-----------|-----------|----------|_________|___________|__________|----------|___________
1 1 1 0 0 0 1 0
Com essas regras em mente, eu adicionei a funo para decodificar o dado. Como um resumo de todo o sistema eu adicionei os seguintes diagramas:
Diagrama de blocos
Esquemticos:
Analgico
Microcontrolador
Simulao Passa-Faixa:
Concluso
Atualmente eu ajustei o Vcc para 10V. A tenso se +5V extrada a partir de um regulador de tenso 78L05. O Vref setado pata a metade da tenso de alimentao, 2,5V. Isso feito utilizando um simples divisor resistivo de 4,7k ohm.
O cdigo fonte pode ser baixado logo abaixo. Existem duas verses:
Reviso 1: 1 de Maio de 2007 Lanamento inicial
Reviso 2: 5 de Maio de 2007 Reviso 2
Recursos adicionados:Auto start, iniciado quando o pino PB7 colocado em nvel alto;Suporte a um buzzer, sada no pino 4Deteco automtica do carto
Desenvolvido porRick Huang.Adaptado para o portugus por Eletronica.org, com autorizao do autor.
Anexos
Firmware Leitor RFID Reviso 2 Firmware Leitor RFID Reviso 1;*******************************************************************************
;**
;**RFID reader section, generate 150KHz carrier frequency
;** and decode the basic data stream
;**
;**Written by Rick Huang, Copyright (C) 2007
;**Revision YYYY/MM/DD
;**Rev 1. 2007/04/29 - Initial release
;** Rev 2.
2007/05/05 - Add automatic card detect
;**
;**Command Functions
;**'1'
Basic decode, binary data output
;**'2'
Debug capture, 8bit data output
;**'3'
Full capture and decode
;** '4'
Hex test - echo any hex input
;**'6'
Auto card detect mode
;**'7'
;**
;**
;** This program is free software; you can redistribute it and/or modify
;** it under the terms of the GNU General Public License as published by
;** the Free Software Foundation; either version 2 of the License, or
;** (at your option) any later version.
;**
;** This program is distributed in the hope that it will be useful,
;** but WITHOUT ANY WARRANTY; without even the implied warranty of
;** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;** GNU General Public License for more details.
;**
;** You should have received a copy of the GNU General Public License
;** along with this program; if not, write to the Free Software
;** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;*******************************************************************************
;****************************************************************************
;** NOTE: Disable the WDT when debugging the code, however, make sure
;**
the WDT is enabled when putting the system into lift time test
;**
The timeout for WDT is about 2 seconds with 128:1 prescaler
;****************************************************************************
include
__config_HS_OSC& _WDT_ON & _LVP_OFF & _BODEN_ON & _MCLRE_ON & _PWRTE_ON
;*****************************************************************
;**Variables
TempW
EQU
70h
;
BitLocationEQU
71h
CounterBEQU
72h
NextFSR
EQU
73h
;
CounterWEQU
74h
BitCountEQU
75h
LastBitValEQU
76h
Data0
EQU
77h
; Final data output
Data1
EQU
78h
Data2
EQU
79h
Data3
EQU
7ah
Data4
EQU
62h
Zero
EQU
7bh
; Zero is 0x00
SerData
EQU
7ch
Temp
EQU
7dh
Output
EQU
7eh
Counter
EQU
7fh
TMRsampleEQU
60h
BinCnt
EQU
61h
Toggle
EQU
63h
ThreeTryEQU
64h
FCData0
EQU
65h
; First data captured
FCData1
EQU
66h
FCData2
EQU
67h
FCData3
EQU
68h
FCData4
EQU
69h
WrittenBitEQU
6ah
#define
_POASPORTB, 7
; Power ON Auto Start
#define
_DOUTPORTB, 6
;
#define
_KEYPORTB, 5
; Key good output
#define
_BEEPPORTB, 4
; Beeper output
#define
_PWM_OPORTB, 3
; PWM - 150kHz
#define
_TXDPORTB, 2
; UART
#define
_RXDPORTB, 1
; UART
#define
_UNU1PORTB, 0
; Unused
#define
DecisionVal
d'170' ;Hard decision, 0 = 159 cycle, 1 = 198 cycle
;*****************************************************************
;** Program code here
gotoStart
ORG4
;waiting for
;interrupt vector
;gotoInterrupt
ORG5
;*****************************DATA
StringStart:
PWelcomeMsg:
addwfPCL, F
DT"Welcome!"
DTH'0d', H'0a', H'00'
PCommandMsg:
DT"Command Error?"
DTH'0d', H'0a', H'00'
PParameterMsg:
DT"Parameter Error?"
DTH'0d', H'0a', H'00'
PNoAckMsg:
DT"Missing Ack"
DTH'0d', H'0a', H'00'
StringEnd:
WelcomeMsg
EQU0
CommandMsg
EQUPCommandMsg - 1 - 5
; 5 is the offset where the
ParameterMsgEQUPParameterMsg - 1 - 5
; Strings start
NoAckMsg
EQUPNoAckMsg - 1 - 5
HexTable:
addwfPCL, F
DT"0123456789ABCDEF"
;*****************************************************************
;********************Program Starts here
Start:
;*********************Setup WDT
;********************** Setting up TMR0, used to decode FSK
bcf
_BEEP
clrwdt
bsf
STATUS, RP0
movlwb'00001111'
;Prescaler to WDT, 1:128
movwfOPTION_REG
clrwdt
;*********************Setting up environment
movlwb'10000010'
;Serial port in too
movwfTRISB
;Set port B I/O
movlwb'00000111'
movwfTRISA
;Set port A I/O
bcf
STATUS, RP0
clrfPORTA
;********************** Disable 16f628 specific features
movlw b'00000110'
;Setup comparator
movwfCMCON
;********************** Setting up PWM module for 150KHz signal
movlwb'00001100'
;Enable PWM module, duty = 2
movwfCCP1CON
movlwb'00000010'
;Using source frequency = 12MHz
movwfCCPR1L
movlwb'00000101'
;Setting up TMR2, Prescale = 1:4
movwfT2CON
bsf
STATUS, RP0
movlwb'00000100'
movwfPR2
;Setting the period = 4
bcf
STATUS, RP0
;********************** Setup UART
bsf
STATUS, RP0
movlwd'12'
;57600 for 12MHz Clock, High speed
movwfSPBRG
;The only rate with low mismatch
movlwb'10100111'
;Async 8-bit @ High speed
movwfTXSTA
bcf
STATUS, RP0
movlwb'10110000'
;Enable serial port
movwfRCSTA
clrfZero
movlwWelcomeMsg
;Display welcome string on startup
callSendString
;----------------------- Debug insert
gotoSkipDebug
movlw0a0h
movwfFSR
movlwb'00000011'
movwfINDF
incfFSR, F
movlwb'11111111'
movwfINDF
incfFSR, F
movlwb'11111100'
movwfINDF
incfFSR, F
movlwb'00011111'
movwfINDF
incfFSR, F
movlwb'10000001'
movwfINDF
incfFSR, F
movlwb'11110000'
movwfINDF
incfFSR, F
movlwb'00111110'
movwfINDF
incfFSR, F
movlwb'00000111'
movwfINDF
incfFSR, F
goto FD_DecodeEntry
SkipDebug:
;----------------------- Wait for command
WaitMore:
btfsc_POAS
gotoAutoDecode
clrwdt
btfscRCSTA, OERR
gotoClearError
btfssPIR1, RCIF
gotoWaitMore
movfwRCREG
movwfSerData
movwfTXREG
;Send it back out
callSSpace
movlw'1'
;Decode command
xorwfSerData, W
btfscSTATUS, Z
gotoAttemptSample;Start a RFID sample
movlw'2'
xorwfSerData, W
btfscSTATUS, Z
gotoDebugSample
;Debug run, output sampled data
movlw'3'
xorwfSerData, W
btfscSTATUS, Z
gotoFullDecode
;Fully capture and decode data
movlw'4'
xorwfSerData, W
btfscSTATUS, Z
gotoHexTest
;Testing HEX routine
movlw'5'
xorwfSerData, W
btfscSTATUS, Z
gotoBinTest
;Testing Bin dump routine
movlw'6'
xorwfSerData, W
btfscSTATUS, Z
gotoAutoDecode
;No Debug message, auto card detection
movlw'7'
xorwfSerData, W
btfscSTATUS, Z
gotoTestBeep
movlw'8'
xorwfSerData, W
btfscSTATUS, Z
gotoDummyNow
DummyNow:
;For all command not in use
movlwCommandMsg
callSendString
;Send error command message
gotoWaitMore
;*********************Clear receving overrun error
ClearError:
movfwRCREG
movfwRCREG
bcf
RCSTA, CREN
bsf
RCSTA, CREN
gotoWaitMore
;----------------------Commands execution
;********************** Command 1:
AttemptSample:
;Command 1: Sample RFID data, do 1024 bits
callCompCheck
;Dummy read once to setup condition
movlw0a0h
movwfFSR
;Use FSR to store data
movlwd'80'
;Do this for 80 bytes
movwfCounter
SampleLoop1:
callCaptureByte
incfFSR, F
;A byte is full, move to the next one
decfszCounter, F
gotoSampleLoop1
;---------------------- Switch memory bank
movlw020h
movwfFSR
;Use FSR to store data
movlwd'64'
;Do this for 64 bytes
movwfCounter
SampleLoop2:
callCaptureByte
incfFSR, F
;A byte is full, move to the next one
decfszCounter, F
gotoSampleLoop2
;----------------------Data is full, now dump the data out
movlwd'80'
;Do this for 80 bytes
movwfCounter
movlw0a0h
movwfFSR
;Use FSR to access data
SampleLoop10:
movfwINDF
callSendBin
incfFSR, F
decfszCounter, F
gotoSampleLoop10
;----------------------Switch bank
movlwd'64'
;Do this for 64 bytes
movwfCounter
movlw020h
movwfFSR
;Use FSR to access data
SampleLoop11:
movfwINDF
callSendBin
incfFSR, F
decfszCounter, F
gotoSampleLoop11
callNewLine
gotoWaitMore
;*********************** Command 2 Debug mode
DebugSample:
;Command 2: Sample RFID data, debug mode
callCompCheck
;Dummy read once to setup condition
movlw0a0h
movwfFSR
;Use FSR to store data
movlwd'80'
;Do this for 80 bytes
movwfCounter
DebugSLoop1:
callCompCheck
movfwTMRsample
movwfINDF
incfFSR, F
;A byte is full, move to the next one
decfszCounter, F
gotoDebugSLoop1
;---------------------- Switch memory bank
movlw020h
movwfFSR
;Use FSR to store data
movlwd'64'
;Do this for 64 bytes
movwfCounter
DebugSLoop2:
callCompCheck
movfwTMRsample
movwfINDF
incfFSR, F
;A byte is full, move to the next one
decfszCounter, F
gotoDebugSLoop2
;----------------------Data is full, now dump the data out
movlwd'80'
;Do this for 80 bytes
movwfCounter
movlw0a0h
movwfFSR
;Use FSR to access data
DebugSLoop10:
movfwINDF
callSendHex
callNewLine
incfFSR, F
decfszCounter, F
gotoDebugSLoop10
;----------------------Switch bank
movlwd'64'
;Do this for 64 bytes
movwfCounter
movlw020h
movwfFSR
;Use FSR to access data
DebugSLoop11:
movfwINDF
callSendHex
callNewLine
incfFSR, F
decfszCounter, F
gotoDebugSLoop11
callNewLine
gotoWaitMore
;*********************** Command 3 Full capture and decode
FullDecode:
;Wait for start sequence, than start capture
callCompCheck
;Dummy read once to setup condition
callWaitTillStart;Wait for start
movlw0a0h
movwfFSR
;Use FSR to store data
movlwd'80'
;Do this for 80 bytes
movwfCounter
FDLoop1:
callCaptureByte
incfFSR, F
;A byte is full, move to the next one
decfszCounter, F
gotoFDLoop1
;----------------------Data is full, now dump the data out
movlwd'80'
;Do this for 80 bytes
movwfCounter
movlw0a0h
movwfFSR
;Use FSR to access data
FDLoop10:
movfwINDF
callSendBin
incfFSR, F
decfszCounter, F
gotoFDLoop10
callNewLine
FD_DecodeEntry:
;---------------------- Collaspe data bits
movlwd'8'
;Set up for bit read
movwfBitLocation
movlw0a0h
movwfNextFSR
;---------------------- Start extraction
clrfData0
;Clear data holder
clrfData1
clrfData2
clrfData3
clrfData4
clrfToggle
FD_BitLoopZ:
callGetBitCount
movfwBitCount
movlwd'20'
subwfBitCount, W
btfscSTATUS, C
gotoFD_DoneDecode; Bitcount - 15 = Positive, Looped already, STOP
movlwd'7'
subwfBitCount, W
btfssSTATUS, C
gotoFD_Send2bit
;Negative, 1 bits
movlw'*'
;Positive, 2 bit
callSendChar
callSendChar
bsf
STATUS, C
callLongShift
callLongShift
gotoFD_NextBit
FD_Send2bit:
movlw'_'
callSendChar
bcf
STATUS, C
callLongShift
FD_NextBit:
movlw0efh
subwfNextFSR, W
;NextFSR - W
btfssSTATUS, C
gotoFD_BitLoopZ
;Negative, keep looping
callNewLine
;Positive, NextFSR > 0xef
;----------------------- Final data output
FD_DoneDecode:
callNewLine
movfwData4
callSendHex
movfwData3
callSendHex
movfwData2
callSendHex
movfwData1
callSendHex
movfwData0
callSendHex
callNewLine
gotoWaitMore
;*********************** Command 6: Auto detection of card
AutoDecode:
clrwdt
movlw03h
;Three trys
movwfThreeTry
AD_CaptureAgain:
clrfWrittenBit
clrwdt
callCompCheck
;Dummy read once to setup condition
callWaitTillStart;Wait for start condition
movlw0a0h
movwfFSR
;Use FSR to store data
movlwd'80'
;Do this for 80 bytes
movwfCounter
ADLoop1:
callCaptureByte
incfFSR, F
;A byte is full, move to the next one
decfszCounter, F
gotoADLoop1
AD_DecodeEntry:
;---------------------- Collaspe data bits
movlwd'8'
;Set up for bit read
movwfBitLocation
movlw0a0h
movwfNextFSR
;---------------------- Start extraction
clrfData0
;Clear data holder
clrfData1
clrfData2
clrfData3
clrfData4
clrfToggle
AD_BitLoopZ:
callGetBitCount
movlwd'20'
subwfBitCount, W
btfscSTATUS, C
gotoAD_DoneDecode; Bitcount - 15 = Positive, Start condition again, STOP
movlwd'7'
subwfBitCount, W
btfssSTATUS, C
gotoAD_Send2bit
;Negative, 1 bits
bsf
STATUS, C
;Positive, 2 bit
callLongShift
callLongShift
gotoAD_NextBit
AD_Send2bit:
bcf
STATUS, C
callLongShift
AD_NextBit:
incfWrittenBit, F
movlw0efh
subwfNextFSR, W
;NextFSR - W
btfssSTATUS, C
gotoAD_BitLoopZ
;Negative, keep looping
;Positive, NextFSR > 0xef, error
gotoAutoDecode
;Restart...
;----------------------- Check data is the same for three times
AD_DoneDecode:
movlwd'30'
;Error check, if too many zero bits, restart
subwfBitCount, W
btfscSTATUS, C
gotoAutoDecode
;Too many bits
movlwh'46'
;Check number of bit written, too little, restart
subwfWrittenBit, W
btfssSTATUS, C
gotoAutoDecode
movlwh'55'
;Check number of bit written, too many, restart
subwfWrittenBit, W
btfscSTATUS, C
gotoAutoDecode
movlwd'3'
xorwfThreeTry, W
btfssSTATUS, Z
;First try indicator
gotoAD_NotFirstTry
movfwData0
movwfFCData0
movfwData1
movwfFCData1
movfwData2
movwfFCData2
movfwData3
movwfFCData3
movfwData4
movwfFCData4
decfThreeTry, F
gotoAD_CaptureAgain
AD_NotFirstTry:
movfwData0
xorwfFCData0, W
btfssSTATUS, Z
gotoAutoDecode
;Not matched, restart
movfwData1
xorwfFCData1, W
btfssSTATUS, Z
gotoAutoDecode
;Not matched, restart
movfwData2
xorwfFCData2, W
btfssSTATUS, Z
gotoAutoDecode
;Not matched, restart
movfwData3
xorwfFCData3, W
btfssSTATUS, Z
gotoAutoDecode
;Not matched, restart
movfwData4
xorwfFCData4, W
btfssSTATUS, Z
gotoAutoDecode
;Not matched, restart
decfszThreeTry, F
gotoAD_CaptureAgain
;----------------------- Final data output
callNewLine
movfwData4
callSendHex
movfwData3
callSendHex
movfwData2
callSendHex
movfwData1
callSendHex
movfwData0
callSendHex
callNewLine
callBeep
gotoWaitMore
;*********************** Command 4,5 Serial debug
HexTest:
callRcvHex
;Command 4: Hex test
movfwOutput
callSendHex
callNewLine
gotoWaitMore
BinTest:
callRcvHex
;Command 5: Bin test
movfwOutput
callSendBin
callNewLine
gotoWaitMore
TestBeep:
callBeep
;Command 7: Test beep
callNewLine
gotoWaitMore
;*****************************SUBROUTINE
;-----------------------------------------------------------------
; LongShift, Shift 1 bit of the data into Data[0:4] register
; Shift only 1 bit per two calls
; Input: C
LongShift:
btfssToggle, 0
gotoToggleNotSet
rlf
Data0, F
rlf
Data1, F
rlf
Data2, F
rlf
Data3, F
rlf
Data4, F
bcf
Toggle, 0
return
ToggleNotSet:
bsf
Toggle, 0
return
;-----------------------------------------------------------------
; CaptureByte, Capture a single byte of data
; Output: INDF
CaptureByte:
callCompCheck
movlwDecisionVal
;Hard decision, 0 = 159 cycle, 1 = 198 cycle
subwfTMRsample, W
rlf
INDF, F
;Store the data into pointed address
callCompCheck
;Do this for 8 times to fill up a byte
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
callCompCheck
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
callCompCheck
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
callCompCheck
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
callCompCheck
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
callCompCheck
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
callCompCheck
movlwDecisionVal
subwfTMRsample, W
rlf
INDF, F
return
;-----------------------------------------------------------------
; WaitTillStart, Wait until the start sequence is detected
; This is marked by 20 or more zeros
WaitTillStart:
movlwd'20'
movwfCounterW
WTS_next:
clrwdt
callCompCheck
movlwDecisionVal
subwfTMRsample, W
btfscSTATUS, C
;Check for a 0 value
gotoWaitTillStart;If 1, restart
decfszCounterW, F
gotoWTS_next
;Loop until done
return
;-----------------------------------------------------------------
; CompCheck, Check the comparator output and store the informtion in
; Output: TMRsample
CompCheck:
;Process: Loop until a transition, clear TMR0,
;wait till next 0-1 transition
SCSampleL3:
btfscCMCON, C1OUT
gotoSCSampleL3
SCSampleL2:
;Was a low, wait for a high
btfssCMCON, C1OUT
gotoSCSampleL2
movfwTMR0
movwfTMRsample
;Store the result in TMRsample
clrfTMR0
;Clear TMR0 for the next bit
return
;-----------------------------------------------------------------
; GetBitCount, Count number of bits until the next change
; Output: BitCount
; Address: BitLocation, NextFSR
; Use: LastBitVal, BitCount, NextFSR, BitLocation, TempW
GetBitCount:
clrfBitCount
btfssLastBitVal, 0
gotoGBC_lastbit0
;gotoGBC_lastbit1;Last bit is a 1
GBC_loop1:
callGetNextBit
btfssSTATUS, Z
gotoGBC_done1
incfBitCount, F
;Continue if value is a zero
gotoGBC_loop1
GBC_done1:
;Done if bit change to one
bcf
LastBitVal, 0
return
GBC_lastbit0:
;Last bit is a 0
GBC_loop0:
callGetNextBit
btfscSTATUS, Z
gotoGBC_done0
incfBitCount, F
;Continue if value is a one
gotoGBC_loop0
GBC_done0:
;Done if bit change to one
bsf
LastBitVal, 0
return
;-----------------------------------------------------------------
; GetNextBit, Get a bit from the buffer
; Output: Z
; Address: BitLocation, NextFSR, BitLocation = 1 for LSB
GetNextBit:
movfwNextFSR
movwfFSR
movfwBitLocation
movwfCounterB
decfszBitLocation, F;Go to the next bit
gotoGNB_nextStep
movlwd'8'
movwfBitLocation
incfNextFSR, F
;Rollover for the next read
GNB_nextStep:
clrfTempW
bsf
STATUS, C
GNB_loop:
rlf
TempW, F
;TempW contain bit mask
decfszCounterB, F
gotoGNB_loop
movfwTempW
andwfINDF, W
;Result in Z
return
;*****************************SUBROUTINE
;-----------------------------------------------------------------
; SendHex, Send a single byte out of serial port, hex format
; Input: data stored in W
SendHex:
movwfTemp
swapfTemp, W
andlw00fh
callHexTable
HexWaitLoop1:
btfssPIR1, TXIF;Wait till buffer is empty
gotoHexWaitLoop1
movwfTXREG
movfTemp, W
andlw00fh
callHexTable
HexWaitLoop2:
btfssPIR1, TXIF;Wait till buffer is empty
gotoHexWaitLoop2
movwfTXREG
return
;-----------------------------------------------------------------
; SendBin, Send a single byte out of serial port, binary format
; Input: data stored in W
SendBin:
movwfTemp
movlw8h
movwfBinCnt
BinWaitLoop1:
btfssPIR1, TXIF;Wait till buffer is empty
gotoBinWaitLoop1
movlw'0'
btfscTemp, 7
movlw'1'
movwfTXREG
rlf
Temp, F
decfszBinCnt, F
gotoBinWaitLoop1
return
;-----------------------------------------------------------------
; RcvHex, Receive a single byte from serial port in hex format
; Output: data stored in Output
RcvHex:
btfssPIR1, RCIF
gotoRcvHex
movfwRCREG
movwfSerData
movwfTXREG
; Send it back out
movlw30h
subwfSerData, F
movlw10h
subwfSerData, W; F - W
btfscSTATUS, C; Positive means letter input
gotoLetter1
RtnLetter1:
swapfSerData, W
movwfOutput
RcvHexLoop:
btfssPIR1, RCIF
gotoRcvHexLoop
movfwRCREG
movwfSerData
movwfTXREG
; Send it back out
movlw30h
subwfSerData, F
movlw10h
subwfSerData, W; F - W
btfscSTATUS, C; Positive means letter input
gotoLetter2
RtnLetter2:
movfwSerData
iorwfOutput, F
callSSpace
return
Letter1:
movlw07h
subwfSerData, F
movlw10h
subwfSerData, W
btfscSTATUS, C; Positive means bad input
gotoLetter1E
gotoRtnLetter1
Letter1E:
movlwd'32'
subwfSerData, F
gotoRtnLetter1
Letter2:
movlw07h
subwfSerData, F
movlw10h
subwfSerData, W
btfscSTATUS, C; Positive means bad input
gotoLetter2E
gotoRtnLetter2
Letter2E:
movlwd'32'
subwfSerData, F
gotoRtnLetter2
;-----------------------------------------------------------------
; LongDelay, 15 cycles, 3ins/cycle 22.5uS for 8Mhz clock
long_delay:
movlwd'15'
movwfCounter
long_delay_L:
decfszCounter, F
gotolong_delay_L
return
;-----------------------------------------------------------------
; SendString, send the string out to serial port
; Input: String location in W
SendString:
movwfCounter
SendLoop:
btfssPIR1, TXIF;Wait till buffer is empty
gotoSendLoop
callStringStart
iorwfZero, W
btfscSTATUS, Z;Zero is the end of string
return
movwfTXREG
incfCounter, F
movfwCounter
gotoSendLoop
;-----------------------------------------------------------------
; NewLine, send s newline character into serial port
; Input: None
NewLine:
btfssPIR1, TXIF;Wait till buffer is empty
gotoNewLine
movlw0dh
movwfTXREG
movlw0ah
NewLineLoop:
btfssPIR1, TXIF;Wait till buffer is empty
gotoNewLineLoop
movwfTXREG
return
;-----------------------------------------------------------------
; Space, send a space character into serial port
; Input: None
SSpace:
btfssPIR1, TXIF;Wait till buffer is empty
gotoSSpace
movlw' '
movwfTXREG
return
;-----------------------------------------------------------------
; SendChar, send a character into serial port
; Input: W
SendChar:
btfssPIR1, TXIF;Wait till buffer is empty
gotoSendChar
movwfTXREG
return
;-----------------------------------------------------------------
; Beep, genertate a 0.5 sec beeper signal, 2KHz
; Using: Data0, 1, 2, 3
Beep:
clrfToggle
movlwd'200'
movwfData0
movlwd'100'
movwfData2
movlwd'10'
movwfData3
BeepLoop:
decfszData0, F
gotoBeepLoop
movlwd'200'
movwfData0
movlwb'00010000'
xorwfPORTB, F
clrwdt
decfszData2, F
gotoBeepLoop
movlwd'100'
movwfData2
decfszData3, F
gotoBeepLoop
bcf
_BEEP
return
;-----------------------------------------------------------------
; End of program
end
top related