; at90s2313
; setup:
+;
; vcc card --- atmel vcc
; vcc cam ---
; rst cam --- atmel int0 (pd2)
.include "../include/2313def.inc"
-; functions by now:
-;
-; stupid mode only by now. just see what cam/card do and redirect
-; this to card/cam.
-;
-; next implementation:
-;
-; try to read one byte of card/cam communication and output via uart.
-; output time information in some way.
-;
-; future:
-;
-; buffer/parse whole strings and decide whether to send to card or not.
; #######
; defines
; baudrate = clock freq / etu
; std smartcard etu: 372
; other smartcards: 625
-.define clock 8000000
-.define clk_h 4000000
-.define etu 625
-.define etu_h 312
-.define baudrate 5 ; UBRR value for 76800 bits/s (8mhz clock)
+.equ etu = 625
+.equ etu_h = 312
+.equ baudrate = 8 ; UBRR value for 57600 bits/s (8mhz clock)
; sizes
-.define uart_data_len 4
-.define uart_data_len_f 3
+.equ uart_data_len = 4
; names for registers
-.define tmp r16
-.define bitcount r17
-.define tmp1 r18
-.define tmp2 r19
-.define byte r20
-.define overflow_counter r21
-.define counter_l r22
-.define counter_h r23
-.define state r24
-.define state_m r25
-.define mode r26
-.define counter_l_tmp r27
-.define counter_h_tmp r28
-.define address_h r31
-.define address_l r30
-.define one r1
-.define zero r0
+.def tmp = r16
+.def bitcount = r17
+.def tmp1 = r18
+.def tmp2 = r19
+.def byte = r20
+.def overflow_counter = r21
+.def counter_l = r22
+.def counter_h = r23
+.def state = r24
+.def state_m = r25
+.def mode = r26
+.def counter_l_tmp = r27
+.def counter_h_tmp = r28
+.def one = r1
+.def zero = r0
; state
-.define LOW (1<<0)
-.define LOW_F 1
-.define HIGH (1<<1)
-.define HIGH_F 2
+.equ LOW = (1<<0)
+.equ LOW_F = 1
+.equ HIGH = (1<<1)
+.equ HIGH_F = 2
; mode
-.define STUPID (1<<0) ; forward cam <-> card communication
-.define STUPID_F 1
-.define COOL (1<<1) ; send time (clocks) & state via uart
-.define COOL_F 2
-.define ELITE (1<<2) ; create bytes, maybe even whole command arrays
-.define ELITE_F 3
-.define GODLIKE (1<<3) ; filter and mask for commands to card - send rejected via uart only
-.define GODLIKE_F 4
-.define INCREDIBLE_HACK (1<<4) ; destroy all your hardware
-.define INCREDIBLE_HACK_F 5
+.equ STUPID = (1<<0) ; forward cam <-> card communication
+.equ STUPID_F = 1
+.equ COOL = (1<<1) ; send time (clocks) & state via uart
+.equ COOL_F = 2
+.equ ELITE = (1<<2) ; create bytes, maybe even whole command arrays
+.equ ELITE_F = 3
+.equ GODLIKE = (1<<3) ; filter and mask for commands to card - send rejected via uart only
+.equ GODLIKE_F = 4
+.equ INCREDIBLE_HACK = (1<<4) ; destroy all your hardware
+.equ INCREDIBLE_HACK_F = 5
+; leds
+.equ LED_CARD = PB0
+.equ LED_CAM = PB1
+.equ LED_FWD_TO_CAM = PB2
+.equ LED_FWD_TO_CARD = PB3
+.equ LED_OVERFLOW = PB4
; but there is only stupid and cool mode right now %)
reti
; timer/counter overflow 1
-rjmp CLK_OVERFLOW
+rjmp T1_OVERFLOW
; timer/counter overflow 0
reti
INIT:
+; output low on rst to card while init
+sbi DDRD,DDD4
+cbi PORTD,PD4
+
; set stackpointer
ldi tmp,low(RAMEND)
out SPL,tmp
-; enable interrupts int0,int1
+; enable interrupts int0,int1,sleep
ldi tmp,((1<<INT0)|(1<<INT1))
out GIMSK,tmp
; int0/1 setup
-ldi tmp,((1<<ISC01)|(0<<ISC00)|(1<<ISC11)|(0<<ISC10))
+ldi tmp,((1<<ISC01)|(0<<ISC00)|(1<<ISC11)|(0<<ISC10)|(1<<SE))
out MCUCR,tmp
; enable t/c overflow interrupt and icp
-ldi tmp,((1<<TOIE1)|(1<<TICIE1))
+ldi tmp,((1<<TOIE1)|(1<<TICIE))
out TIMSK,tmp
; setup t/c and icp
ldi tmp,((1<<CS12)|(1<<CS11)|(1<<CS10)|(1<<ICNC1)|(0<<ICES1))
ldi tmp,baudrate
out UBRR,tmp
sbi UCR,TXEN
+; debug
+.ifdef DEBUG
+ldi tmp,0x49
+out UDR,tmp
+.endif
+
+; enable pullups on int0, int1, clk, icp io ports
+ldi tmp,((1<<PD2)|(1<<PD3)|(1<<PD5)|(1<<PD6))
+
+; pb 0-4 output high
+ldi tmp,((1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4))
+out DDRB,tmp
+out PORTB,tmp
; init registers
-ldi bitcounter,0
+ldi bitcount,0
ldi byte,0
ldi overflow_counter,0
-ldi tmp1,0
-ldi tmp2,0
ldi counter_l,0
ldi counter_h,0
ldi state,HIGH ; .. as waiting for falling edge of start bit
ldi state_m,0x03
ldi mode,(STUPID|COOL)
-ldi counter_l_tmp,0
-ldi counter_h_tmp,0
-ldi address_h,SRAM_START_H
+ldi ZH,0
ldi tmp,1
mov one,tmp
ldi tmp,0
; enable interrupts (global)
sei
+; output high on rst to card
+sbi PORTD,PD4
+
; jump to mainloop
rjmp MAIN
MAIN:
-; loop and wait for interrupts
+; debug
+.ifdef DEBUG
+ldi tmp,0x4d
+out UDR,tmp
+.endif
+
+; sleep/wait for next interrupt
+sleep
+
+; go to sleep again
rjmp MAIN
; ----------------
REC_CARD:
-; save counter
-In counter_l,ICR1L
-in counter_h,ICR1H
+.ifdef DEBUG
+ldi tmp,0x52
+out UDR,tmp
+.endif
+
+; input & pullup
+cbi DDRD,DDD6
+sbi PORTD,PD6
+
+; activate led
+sbi PORTB,LED_CAM
+cbi PORTB,LED_CARD
; toggle state
eor state,state_m
sbrc mode,STUPID_F
rcall FWD_TO_CAM
-; calculate delta clocks if in stupid mode
+; calculate delta clocks if in cool mode
sbrc mode,COOL_F
-rcall CALC_DELTA_CLOCK ; -> calc delta, store to counter_l_tmp, counter_h_tmp
+rcall CALC_DELTA_CLOCK
; send time and state via uart
sbrc mode,COOL_F
; return
reti
+; ------------------------
+; calc_delta_clock routine
+; ------------------------
+
+CALC_DELTA_CLOCK:
+
+.ifdef DEBUG
+ldi tmp,0x63
+out UDR,tmp
+.endif
+
+; store counters
+mov counter_l_tmp,counter_l
+mov counter_h_tmp,counter_h
+
+; get new ones
+in counter_l,ICR1L
+in counter_h,ICR1H
+
+; delta calc on host software by now
+
+; return
+ret
+
; ------------------------
; toggle_icp_sense routine
; ------------------------
TOGGLE_ICP_SENSE:
+.ifdef DEBUG
+ldi tmp,0x54
+out UDR,tmp
+.endif
+
; toggle according to state
in tmp,TCCR1B
-cbi tmp,ICES1
+cbr tmp,ICES1
sbrs state,HIGH ; maybe toggle according to TCCR1B?
-sbi tmp,ICES1
+sbr tmp,ICES1
out TCCR1B,tmp
; return
FWD_TO_CAM:
+.ifdef DEBUG
+ldi tmp,0x66
+out UDR,tmp
+.endif
+
+; activate led
+sbi PORTB,LED_FWD_TO_CARD
+cbi PORTB,LED_FWD_TO_CAM
+
; disable external interrupt 1 while toggling edge
in tmp,GIMSK
cbr tmp,INT1
out PORTD,tmp1;
; reenable external interrupt 1
-cbr tmp,INT1
+sbr tmp,INT1
out GIMSK,tmp
; return
PREPARE_UART:
-; by now just send state and counter, so there is no data to prepare
+.ifdef DEBUG
+ldi tmp,0x50
+out UDR,tmp
+.endif
+
+; write transfer data to sram
+ldi ZL,0x60
+st Z+,counter_l
+st Z+,counter_h
+st Z+,overflow_counter
+st Z+,state
; enable uart data register empty interrupt
sbi UCR,UDRIE
REC_CAM:
+.ifdef DEBUG
+ldi tmp,0x72
+out UDR,tmp
+.endif
+
; first thing - pullup on
cbi DDRD,DDD3
sbi DDRD,PD3
-; save counter
-in counter_l,ICR1L
-in counter_h,ICR1H
+; activate led
+sbi PORTB,LED_CARD
+cbi PORTB,LED_CAM
; toggle state
eor state,state_m
; toggle int sense
rcall TOGGLE_INT_SENSE
-HIER FEHLT NOCH VIEL ...
+; fwd to card if in stupid mode
+sbrc mode,STUPID_F
+rcall FWD_TO_CARD
+
+; calculate delta clocks if in cool mode
+sbrc mode,COOL_F
+rcall CALC_DELTA_CLOCK
; return
reti
; ------------------------
-: toggle_int_sense routine
+; toggle_int_sense routine
; ------------------------
TOGGLE_INT_SENSE:
+.ifdef DEBUG
+ldi tmp,0x73
+out UDR,tmp
+.endif
+
in tmp,MCUCR
cbr tmp,ISC10
-sbis state,HIGH_F
+sbrs state,HIGH_F
sbr tmp,ISC10
out MCUCR,tmp
; return
ret
+; -------------------
+; fwd_to_card routine
+; -------------------
+
+FWD_TO_CARD:
+
+.ifdef DEBUG
+ldi tmp,0x46
+out UDR,tmp
+.endif
+
+; activate led
+sbi PORTB,LED_FWD_TO_CAM
+cbi PORTB,LED_FWD_TO_CARD
+
+; disable icp interrupt while toggling edge
+in tmp,TIMSK
+cbr tmp,TICIE
+out TIMSK,tmp
+
+; output state on port to card
+in tmp1,PORTD
+sbr tmp1,PD6
+sbrs state,HIGH_F
+cbr tmp1,PD6
+
+; configure as output and push-pull low/high
+sbi DDRD,DDD6
+out PORTD,tmp1;
+
+; reenable icp interrupt
+sbr tmp,TICIE
+out TIMSK,tmp
+
+; return
+ret
+
; -------------------
; t1_overflow routine
; -------------------
T1_OVERFLOW:
+.ifdef DEBUG
+ldi tmp,0x74
+out UDR,tmp
+.endif
+
; increment counter overflow
add overflow_counter,one
+; toggle led status
+mov tmp,overflow_counter
+and tmp,one
+sbi PORTB,LED_OVERFLOW
+sbrs tmp,1
+cbi PORTB,LED_OVERFLOW
+
; return
reti
RST_CAM:
-; pull down rst from card
-sbi DDRD,DDD4
-cbi PORTD,PD4
+.ifdef DEBUG
+ldi tmp,0x69
+out UDR,tmp
+.endif
-; jump to init
+; by now just jump to init
rjmp INIT
; ----------------
; disable uart data register empty interrupt
cbi UCR,UDRIE
-; init counter
-mov address_l,zero
+; init counter(s)
+mov tmp,zero
; send the data
rcall UART_SEND
; return
reti
-.... wahhh ! zzZz
+; -----------------
+; uart_send routine
+; -----------------
+
+UART_SEND:
+
+; read next byte from memmory and transfer via uart
+sbic USR,UDRE
+rcall UART_GS
+
+; return if everything was sent
+cpi tmp,uart_data_len
+brne UART_SEND
+ret
+
+; ---------------
+; uart_gs routine
+; ---------------
+
+UART_GS:
+
+;
+; wie macht man load mit autoinc richtig?
+;
+
+; read byte from memory and write via uart
+ld tmp1,Z+
+out UDR,tmp1
+
+; increment counter (maybe needed later)
+add tmp,one
+
+; return
+ret