Skip to content

Instantly share code, notes, and snippets.

@BobBurns
Created July 19, 2015 12:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BobBurns/beda039a5c6531fd19cd to your computer and use it in GitHub Desktop.
Save BobBurns/beda039a5c6531fd19cd to your computer and use it in GitHub Desktop.
avr code to control pn532 to read and decrement MiFare card value
;this program attempts to read a MiFare card initialized with a name at address 0x04
; and a value block at 0x05
;
;compile with gavrasm read_dec.asm ;flash with avrdude -c avrisp -p m168 -P /dev/tty.usbmodem1411 -b 19200 -U flash:w:read_dec.hex
;
; I/O pins:
; ** use PORTB except RDYN on PORTD **
; ** SCK on pin 5 configured as output **
; ** MISO on pin 4 configured as input with pullup **
; ** MOSI on pin 3 configured as output **
; ** NSS on pin 2 configured as output **
; ** NSS on pin 2 not selected (high)
; ** IRQ on PB1 configured as input with pullup **
;---- defines ----
.device atmega168
.equ HAL_PORT = 0x05 ;PORTB
.equ HAL_DDR = 0x04 ;DDRB
.equ HAL_PIN = 0x03 ;PINB
.equ HAL_SCK = 5
.equ HAL_MISO = 4
.equ HAL_MOSI = 3
.equ HAL_NSS = 2
; not using IRQ
;
.equ MSG_FLG = 0
.equ RD_FLG = 1
;
;UBBR value for USART from f_cpu 1000000
.equ UBBRvalue = 12
;*** some opcodes for PN532 ***
.equ C_TEST = 0x00
;*** delay constant
.equ dlp_init = 50000
;---- registers
.def temp = r16
.def count = r17
.def temp2 = r18
.def r_dcs = r19
.def delayL = r24
.def delayH = r25
.def xL = r26
.def xH = r27
.def yL = r28
.def yH = r29
.def zL = r30
.def zH = r31
.cseg
;---- Interrupt Vector ---
.org 0
rjmp reset
rjmp RDYN_L ;INT0 vector
RDYN_L:
; I'm not going to use this yet
reti
reset:
;Initialize Stack
ldi temp,low(RAMEND)
out SPL,temp
ldi temp,high(RAMEND)
out SPH,temp
;Init SPI
;** don't have to set phase or polarity. PN532 uses mode 0
in temp,SPCR
sbr temp,(1 << SPR0) ;divide f_cpu by 16, better for breadboards
sbr temp,(1 << MSTR) ;set AVR to SPI Master mode
sbr temp,(1 << DORD) ;use LSB bit order
sbr temp,(1 << SPE) ;enable SPI
out SPCR,temp
;
;*** set ddr and output on pin lines
;
sbi HAL_DDR,HAL_NSS ;output on NSS
cbi HAL_PORT,HAL_NSS ;lower NSS to wake up pn532
sbi HAL_DDR,HAL_SCK ;output on SCK
sbi HAL_PORT,HAL_MISO ;set pullup on MISO // confg as input
sbi HAL_DDR,HAL_MOSI ;output on MOSI
; wait to set pullup on IRQ line sbi HAL_PORT,HAL_IRQ ;set pullup on IRQ line
;
;initialize USART
ldi temp,high(UBBRvalue) ;baud rate param
sts UBRR0H,temp
ldi temp,low(UBBRvalue)
sts UBRR0L,temp
lds temp,UCSR0A
ori temp,(1 << U2X0) ;set use 2x because %error actual baud > .5
sts UCSR0A,temp
;--- USART register values
ldi temp,(1 << TXEN0) | (1 << RXEN0) ;enable transmit and receive
sts UCSR0B,temp
ldi temp,(1 << UCSZ01) | (1 << UCSZ00) ;8 data bits, 1 stop bit
sts UCSR0C,temp
;********* Main Program **********
;
; wake up pn532
ldi count,5 ;one second
rcall delay ;delay after startup
start:
ldi zH,high(gfv << 1) ;call get firmware version to sync?
ldi zL,low(gfv << 1)
rcall snd_cmd
sbi HAL_PORT,HAL_NSS ;snd_cmd doesn't raise NSS when finished
ldi xL,low(in_buf) ;set up pointer to storage buffer
ldi xH,high(in_buf)
rcall ack_resp
ldi zH,high(samc << 1) ;next configure SAM normal 14 01
ldi zL,low(samc << 1)
rcall snd_cmd
sbi HAL_PORT,HAL_NSS
ldi xL,low(in_buf) ;set up pointer to storage buffer
ldi xH,high(in_buf)
rcall ack_resp
poll:
ldi zH,high(ilpt << 1)
ldi zL,low(ilpt << 1)
rcall snd_cmd ;send inListPassiveTarget command
sbi HAL_PORT,HAL_NSS
ldi xL,low(in_buf) ;set up pointer to storage buffer
ldi xH,high(in_buf)
rcall ack_resp ;get response
ldi xL,low(in_buf)
ldi xH,high(in_buf)
adiw xH:xL,9
ld temp,X+
cpi temp,4 ;make sure NFCID is MiFare1
breq cont_2
rjmp error
cont_2: ldi zH,high(ide_a << 1)
ldi zL,low(ide_a << 1)
rcall snd_cmd ;send first part of command
ldi count,4
ldi r_dcs,0x76 ;dcs before NFCID
auth_end:
ld temp,X+
add r_dcs,temp
rcall SPI_tradeByte
dec count
brne auth_end
mov byte_tx,r_dcs
; rcall transmit
neg r_dcs
mov byte_tx,r_dcs
; rcall transmit
mov temp,r_dcs
rcall SPI_tradeByte
ldi temp,0x00
rcall SPI_tradeByte
sbi HAL_PORT,HAL_NSS
ldi xL,low(in_buf) ;set up pointer to storage buffer
ldi xH,high(in_buf)
rcall ack_resp
ldi xL,low(in_buf)
ldi xH,high(in_buf)
adiw xH:xL,4 ;check response status
ld temp,X
cpi temp,0x00
breq cont_1
rjmp error
;********* send read and dec commands ************
cont_1:
ldi zH,high(cmd_head << 1)
ldi zL,low(cmd_head << 1)
rcall snd_cmd
ldi zH,high(read_name << 1) ;read name on card
ldi zL,low(read_name << 1)
rcall snd_dcs
sbi HAL_PORT,HAL_NSS
ldi xL,low(name_buf) ;set up pointer to name buffer
ldi xH,high(name_buf)
rcall ack_resp
ldi zH,high(cmd_head << 1)
ldi zL,low(cmd_head << 1)
rcall snd_cmd
ldi zH,high(dec_vb << 1) ;decrement value-block 05
ldi zL,low(dec_vb << 1)
rcall snd_dcs
sbi HAL_PORT,HAL_NSS
ldi xL,low(in_buf)
ldi xH,high(in_buf)
rcall ack_resp
ldi zH,high(cmd_head << 1)
ldi zL,low(cmd_head << 1)
rcall snd_cmd
ldi zH,high(tra_vb << 1) ;transfer value to block
ldi zL,low(tra_vb << 1)
rcall snd_dcs
sbi HAL_PORT,HAL_NSS
rcall ack_resp
ldi zH,high(cmd_head << 1)
ldi zL,low(cmd_head << 1)
rcall snd_cmd
ldi zH,high(read_vb << 1) ;read updated value block 05
ldi zL,low(read_vb << 1)
rcall snd_dcs
sbi HAL_PORT,HAL_NSS
ldi xL,low(value_buf) ;set up pointer to name buffer
ldi xH,high(value_buf)
rcall ack_resp
;done
; ldi zH,high(succ_str << 1)
; ldi zL,low(succ_str << 1)
; rcall print_s ;print success
;****** serial tx *********
;* first send STX(0x02) then full name block(16 bytes)
;*
ldi byte_tx,0x02
rcall transmit
ldi xL,low(name_buf)
ldi xH,high(name_buf)
adiw xH:xL,5 ;should point to beginning of string
ldi count,0x10
nm_lp:
ld byte_tx,X+
rcall transmit
dec count
brne nm_lp
;* then ETX(0x03), STX(0x02), 4 byte value
;*
ldi byte_tx,0x03
rcall transmit
ldi byte_tx,0x02
rcall transmit
ldi xL,low(value_buf)
ldi xH,high(value_buf)
adiw xH:xL,5 ;should point to beginning of value
ldi count,4
vl_lp: ld r24,X+
rcall t_htoa ;send ascii representation of value
dec count
brne vl_lp
;* finally send ETX(0x03) and EOT(0x04)
ldi byte_tx,0x03
rcall transmit
ldi byte_tx,0x04
rcall transmit
ldi count,25
rcall delay ;5 sec delay
rjmp poll
error: ldi byte_tx,0xEE
rcall transmit
rcall transmit ;EE EE on error
exit_lp:
nop
rjmp exit_lp
;****** Subroutines ******
;print out message
prt_m:
push count
ldi xL,low(in_buf)
ldi xH,high(in_buf) ;load x reg with pointer to message
ld count,X+
mov byte_tx,count
rcall transmit
p_lp: ld byte_tx,X+
rcall transmit
dec count
brne p_lp
pop count
ret
.def byte_tx = r19
;---- function to transmit byte ----
;transmit byte from r19 over usart
transmit:
lds temp,UCSR0A
sbrs temp,UDRE0
rjmp transmit
sts UDR0,byte_tx
ret
;print string function
;takes Z loaded with pointer to string with first byte being length
;uses r16,r17,r19
print_s:
lpm count,Z+
for1: lpm byte_tx,Z+
wait: lds temp,UCSR0A
sbrs temp,UDRE0 ;wait for Tx buffer to be empty
rjmp wait ;not ready
sts UDR0,byte_tx;
dec count
brne for1
ret
;
;-------- delay subroutines ------------
;takes count in reg r17 * 200 milliseconds
delay:
ldi delayH,high(dlp_init)
ldi delayL,low(dlp_init)
dlp: sbiw delayH:delayL,1
nop ;makes 4 clock cycles
brne dlp
dec count
brne delay
ret
;millisecond delay *** takes count (r17) as msecond value
m_delay:
ldi temp,0xfa
md_lp: nop
nop
dec temp
brne md_lp ;4 clock cycles times 250 = 1000us (1000000 f_cpu)
dec count
brne m_delay
ret
;----- SPI routines -----
;uses temp r16 as tx byte and returns with rx byte in temp
SPI_tradeByte:
out SPDR,temp
lp1: in temp2,SPSR
sbrs temp2,SPIF
rjmp lp1
in temp,SPDR
ret
;send ascii representation of one byte over serial
;byte to convert in r24
;uses r24 as low nibble to send and r25 for high nibble
t_htoa:
lds temp,UCSR0A
sbrs temp,UDRE0
rjmp t_htoa
ldi temp,0x30 ;ascii offset
mov r25,r24
lsr r25
lsr r25
lsr r25
lsr r25
cpi r25,0x0A
brlt no_e
ldi temp,0x37 ;extended hex
no_e: add r25,temp
sts UDR0,r25
t_2: lds temp,UCSR0A
sbrs temp,UDRE0
rjmp t_2
ldi temp,0x30 ;ascii offset
andi r24,0x0f ;low nibble
cpi r24,0x0a
brlt no_e2
ldi temp,0x37
no_e2: add r24,temp ;add 0x30 to get ascii representation
sts UDR0,r24
ret
;print message from inbuf
p_mess:
ldi xL,low(in_buf)
ldi xH,high(in_buf)
ld count,X+
mess_lp:
ld byte_tx,X+ ;reprint data
rcall transmit
dec count
brne mess_lp
ret
;send command routine
;Z reg points to command string with first byte being length
snd_cmd:
cbi HAL_PORT,HAL_NSS
lpm count,Z+
snd_for:
lpm temp,Z+
rcall SPI_tradeByte
dec count
brne snd_for
ret
; send routine with data checksum
snd_dcs:
lpm count,Z+
mov temp,count
rcall SPI_tradeByte
mov temp,count ;count is same as length byte
neg temp
rcall SPI_tradeByte ;send length byte and length checksum
lpm temp,Z+
mov r_dcs,temp ;first byte to add to (TFI)
rcall SPI_tradeByte
dec count
sdcs_for:
lpm temp,Z+
add r_dcs,temp
rcall SPI_tradeByte
dec count
brne sdcs_for
mov temp,r_dcs
neg temp
rcall SPI_tradeByte
ldi temp,0x00
rcall SPI_tradeByte
ret
;ack routine
;
ack_resp:
cbi HAL_PORT,HAL_NSS
sr_lp: ldi temp,0x02 ;status reading SR
rcall SPI_tradeByte
ldi temp,0x00
rcall SPI_tradeByte
mov byte_tx,temp
; rcall transmit
sbrs byte_tx,0 ;ready bit
rjmp sr_lp
sbi HAL_PORT,HAL_NSS
;get ack and print for now
ldi count,0x06 ;6 bytes
cbi HAL_PORT,HAL_NSS
ldi temp,0x03 ;data reading
rcall SPI_tradeByte
ack_p: ldi temp,0x00
rcall SPI_tradeByte
mov byte_tx,temp
; rcall transmit
dec count
brne ack_p
sbi HAL_PORT,HAL_NSS
ldi byte_tx,0xAC
; rcall transmit
cbi HAL_PORT,HAL_NSS
rec: ldi temp,0x02 ;status reading
rcall SPI_tradeByte
ldi temp,0x00
rcall SPI_tradeByte
sbrs temp,0
rjmp rec
sbi HAL_PORT,HAL_NSS
ldi count,0x03 ;first three bytes preamble + start code
cbi HAL_PORT,HAL_NSS
ldi temp,0x03
rcall SPI_tradeByte ;data reading
out_p: ldi temp,0x00
rcall SPI_tradeByte
mov byte_tx,temp
; rcall transmit ;print
dec count
brne out_p
ldi temp,0x00
rcall SPI_tradeByte
mov byte_tx,temp
; rcall transmit
cpi byte_tx,0x01 ;length byte 1 on error
breq app_err
mov count,byte_tx
inc count
inc count
inc count
st X+,count ;store length first
rec_end:
ldi temp,0x00
rcall SPI_tradeByte
st X+,temp ;store rec mess
mov byte_tx,temp
; rcall transmit
dec count
brne rec_end
sbi HAL_PORT,HAL_NSS
ret
app_err:
ldi count,0x04
err_lp: ldi temp,0x00
rcall SPI_tradeByte
mov byte_tx,temp
rcall transmit
dec count
brne err_lp
sbi HAL_PORT,HAL_NSS
end: nop ;dont return
rjmp end
;****** strings ******
succ_str: .db 20,0x0d,0x0a,"*** Success! ***",0x0d,0x0a,0x00
;********************************************************************
;some commands to send
gfv: .db 0x0A,0x01,0x00,0x00,0xFF,0x02,0xFE,0xD4,0x02,0x2A,0x00,0x00
samc: .db 0x0D,0x01,0x00,0x00,0xFF,0x05,0xFB,0xD4,0x14,0x01,0x00,0x01,0x16,0x00
ilpt: .db 0x0C,0x01,0x00,0x00,0xFF,0x04,0xFC,0xD4,0x4A,0x01,0x00,0xE1,0x00,0x00
ide_a: .db 0x11,0x01,0x00,0x00,0xFF,0x0F,0xF1,0xD4,0x40,0x01,0x60,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
cmd_head: .db 0x04,0x01,0x00,0x00,0xFF,0x00
wr_name: .db 0x15,0xD4,0x40,0x01,0xA0,0x04,0x44,0x61,0x72,0x62,0x79,0x20,0x43,0x72,0x61,0x73,0x68,0x00,0x00,0x00,0x00,0x00
credit_blk: .db 0x15,0xD4,0x40,0x01,0xA0,0x05,0x9B,0x02,0x00,0x00,0x64,0xFD,0xFF,0xFF,0x9B,0x02,0x00,0x00,0x05,0xFA,0x05,0xFA
read_st7: .db 0x05,0xD4,0x40,0x01,0x30,0x07
read_name: .db 0x05,0xD4,0x40,0x01,0x30,0x04
dec_vb: .db 0x09,0xD4,0x40,0x01,0xC0,0x05,0x01,0x00,0x00,0x00
tra_vb: .db 0x05,0xD4,0x40,0x01,0xB0,0x05
read_vb: .db 0x05,0xD4,0x40,0x01,0x30,0x05
.dseg
;**** in_buf starts with a length byte
in_buf: .byte 0x40
name_buf: .byte 0x32
value_buf: .byte 0x32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment