debug messages + slee
[my-code/atmel.git] / beginners / season_junior.asm
index 9c02191..9171e7c 100644 (file)
@@ -6,44 +6,97 @@
 
 ; at90s2313
 ; setup:
-; vcc card --- vcc cam
-; rst card --- rst cam --- atmel t0 (pd4)
-; clk card --- clk cam --- atmel t1 (pd5)
+;
+; vcc card --- atmel vcc
+; vcc cam  --- 
+; rst cam  --- atmel int0 (pd2)
+; rst card --- atmel (pd4)
+; clk card -\ 
+;            -  atmel t1 (pd5)
+; clk cam  -/
 ; gnd card --- gnd cam --- atmel gnd
-; i/o card --- atmel int0 (pd2)
+; i/o card --- atmel icp (pd6)
 ; i/o cam  --- atmel int1 (pd3)
 
 .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
+.equ etu = 625
+.equ etu_h = 312
+.equ baudrate = 8 ; UBRR value for 57600 bits/s (8mhz clock)
+
+; sizes
+.equ uart_data_len = 4
+
+; names for registers
+.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
+.equ LOW = (1<<0)
+.equ LOW_F = 1
+.equ HIGH = (1<<1)
+.equ HIGH_F = 2
+; mode
+.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 %)
+
+
+; #############
+; programm code
+; #############
+
+; ------------------
 ; interrupt vectors:
-;
+; ------------------
 
 ; reset
 rjmp INIT
 
 ; int0
-rjmp REC_CARD
+rjmp RST_CAM
 
 ; int1
 rjmp REC_CAM
 
 ; timer/counter capt 1
-reti
+rjmp REC_CARD
 
 ; timer/counter compare
 reti
@@ -58,7 +111,7 @@ reti
 reti
 
 ; uart data register empty
-reti
+rjmp UART_OUT
 
 ; uart tx complete
 reti
@@ -66,138 +119,421 @@ reti
 ; analog comparator
 reti
 
-;
+; ------------
 ; init routine
-;
+; ------------
 
 INIT:
 
+; output low on rst to card while init
+sbi DDRD,DDD4
+cbi PORTD,PD4
+
 ; set stackpointer
-ldi r16,low(RAMEND)
-out SPL,r16
+ldi tmp,low(RAMEND)
+out SPL,tmp
 
-; enable interrupts int0,int1
-ldi r16,((1<<INT0)|(1<<INT1))
-out GIMSK,r16
+; enable interrupts int0,int1,sleep
+ldi tmp,((1<<INT0)|(1<<INT1))
+out GIMSK,tmp
 ; int0/1 setup
-ldi r16,((1<<ISC01)|(1<<ISC00)|(1<<ISC10)|(1<<ISC11))
-out MCUCR,r16
-in r16,MCUCR
-sbic PORTD,PD2
-cbr r16,ISC00
-out MCUCR,r16
-sbic PORTD,PD3
-cbr r16,ISC10
-out MCUCR,r16
-
-; enable t/c overflow interrupt
-ldi r16,(1<<TOIE1)
-out TIMSK,r16
-; setup t/c
-ldi r16,((1<<CS12)|(1<<CS11)|(1<<CS10))
-out TCCR1B,r16
-
-; init bitcounter and overflow counter
-ldi r20,0 ; bitcounter
-ldi r21,0 ; register for constructing the byte
-ldi r22,0 ; overflow counter
-
-; constant 1 in r1
-ldi r16,1
-mov r1,r16
+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<<TICIE))
+out TIMSK,tmp
+; setup t/c and icp
+ldi tmp,((1<<CS12)|(1<<CS11)|(1<<CS10)|(1<<ICNC1)|(0<<ICES1))
+out TCCR1B,tmp
+
+; configure uart - interrupt enabled when i/o
+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 bitcount,0 
+ldi byte,0
+ldi overflow_counter,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 ZH,0
+ldi tmp,1
+mov one,tmp
+ldi tmp,0
+mov zero,tmp
 
 ; enable interrupts (global)
 sei
 
-;
-; rec_card routines
-;
+; output high on rst to card
+sbi PORTD,PD4
+
+; jump to mainloop
+rjmp MAIN
+
+; ------------
+; main routine
+; ------------
+
+MAIN:
+
+; debug
+.ifdef DEBUG
+ldi tmp,0x4d
+out UDR,tmp
+.endif
+
+; sleep/wait for next interrupt
+sleep
+
+; go to sleep again
+rjmp MAIN
+
+; ----------------
+; rec_card routine
+; ----------------
 
 REC_CARD:
 
-; int0 -> input, int1 -> output
-ldi r16,(1<<DDD3)
-out DDRD,r16
+.ifdef DEBUG
+ldi tmp,0x52
+out UDR,tmp
+.endif
 
-; decide what to do
-sbic PORTD,PD2
-rjmp REC_CARD_HIGH
-rjmp REC_CARD_LOW
+; input & pullup
+cbi DDRD,DDD6
+sbi PORTD,PD6
 
-REC_CARD_HIGH:
+; activate led
+sbi PORTB,LED_CAM
+cbi PORTB,LED_CARD
 
-; output high on port to cam
-ldi r16,(1<<PD3)
-out PORTD,r16
+; toggle state
+eor state,state_m
 
-; toggle int0 sense
-in r16,MCUCR
-cbr r16,ISC00
-out MCUCR,r16
+; toggle icp sense
+rcall TOGGLE_ICP_SENSE
 
+; fwd to cam if in stupid mode
+sbrc mode,STUPID_F
+rcall FWD_TO_CAM
+
+; calculate delta clocks if in cool mode
+sbrc mode,COOL_F
+rcall CALC_DELTA_CLOCK
+
+; send time and state via uart
+sbrc mode,COOL_F
+rcall PREPARE_UART
+
+; return
 reti
 
-REC_CARD_LOW:
+; ------------------------
+; calc_delta_clock routine
+; ------------------------
 
-; output low on port to cam
-ldi r16,0
-out PORTD,r16
+CALC_DELTA_CLOCK:
 
-; toggle int0 sense
-in r16,MCUCR
-cbr r16,ISC00
-out MCUCR,r16
+.ifdef DEBUG
+ldi tmp,0x63
+out UDR,tmp
+.endif
 
-reti
+; store counters
+mov counter_l_tmp,counter_l
+mov counter_h_tmp,counter_h
 
-;
-; rec_cam routines
-;
+; 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
+cbr tmp,ICES1
+sbrs state,HIGH ; maybe toggle according to TCCR1B?
+sbr tmp,ICES1
+out TCCR1B,tmp
+
+; return 
+ret
+
+; ------------------
+; fwd_to_cam routine
+; ------------------
+
+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 GIMSK,tmp
+
+; output state on port to cam
+in tmp1,PORTD
+sbr tmp1,PD3
+sbrs state,HIGH_F
+cbr tmp1,PD3
+
+; configure as output and push-pull low/high
+sbi DDRD,DDD3
+out PORTD,tmp1;
+
+; reenable external interrupt 1
+sbr tmp,INT1
+out GIMSK,tmp
+
+; return
+ret
+
+; --------------------
+; prepare_uart routine
+; --------------------
+
+PREPARE_UART:
+
+.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
+
+; return
+ret
+
+
+; ---------------
+; rec_cam routine
+; ---------------
 
 REC_CAM:
 
-; int1 -> input, int0 -> output
-ldi r16,(1<<DDD2)
-out DDRD,r16
+.ifdef DEBUG
+ldi tmp,0x72
+out UDR,tmp
+.endif
+
+; first thing - pullup on
+cbi DDRD,DDD3
+sbi DDRD,PD3
+
+; activate led
+sbi PORTB,LED_CARD
+cbi PORTB,LED_CAM
 
-; decide what to do
-sbic PORTD,PD3
-rjmp REC_CAM_HIGH
-rjmp REC_CAM_LOW
+; toggle state
+eor state,state_m
 
-REC_CAM_HIGH:
+; toggle int sense
+rcall TOGGLE_INT_SENSE
 
-; output high on port to card
-ldi r16,(1<<PD2)
-out PORTD,r16
+; fwd to card if in stupid mode
+sbrc mode,STUPID_F
+rcall FWD_TO_CARD
 
-; toggle int1 sense
-in r16,MCUCR
-cbr r16,ISC10
-out MCUCR,r16
+; calculate delta clocks if in cool mode
+sbrc mode,COOL_F
+rcall CALC_DELTA_CLOCK
 
+; return
 reti
 
-REC_CAM_LOW:
+; ------------------------
+; toggle_int_sense routine
+; ------------------------
 
-; output low on port to card
-ldi r16,0
-out PORTD,r16
+TOGGLE_INT_SENSE:
 
-; toggle int 1 sense
-in r16,MCUCR
-cbr r16,ISC10
-out MCUCR,r16
+.ifdef DEBUG
+ldi tmp,0x73
+out UDR,tmp
+.endif
 
-reti
+in tmp,MCUCR
+cbr tmp,ISC10
+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:
 
-add r22,r1 ; inc counter overflow register
+.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 routine
+; ---------------
+
+RST_CAM:
+
+.ifdef DEBUG
+ldi tmp,0x69
+out UDR,tmp
+.endif
+
+; by now just jump to init
+rjmp INIT
+
+; ----------------
+; uart_out routine
+; ----------------
+
+UART_OUT:
+
+; disable uart data register empty interrupt
+cbi UCR,UDRIE
+
+; init counter(s)
+mov tmp,zero
+
+; send the data
+rcall UART_SEND
+
+; return
+reti
+
+; -----------------
+; 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