e6a46067d459aaf6c6aa0bd249c0921370a2f84a
[my-code/atmel.git] / beginners / season_junior.asm
1 ; season - junior
2 ;
3 ; author: hackbard@hackdaworld.dyndns.org
4 ;
5
6
7 ; at90s2313
8 ; setup:
9 ;
10 ; vcc card --- atmel vcc
11 ; vcc cam  --- 
12 ; rst cam  --- atmel int0 (pd2)
13 ; rst card --- atmel (pd4)
14 ; clk card -\ 
15 ;            -  atmel t1 (pd5)
16 ; clk cam  -/
17 ; gnd card --- gnd cam --- atmel gnd
18 ; i/o card --- atmel icp (pd6)
19 ; i/o cam  --- atmel int1 (pd3)
20
21 .include "../include/2313def.inc"
22
23
24 ; #######
25 ; defines
26 ; #######
27
28 ; baudrate = clock freq / etu
29 ; std smartcard etu: 372
30 ; other smartcards: 625
31 .define clock 8000000
32 .define clk_h 4000000
33 .define etu 625
34 .define etu_h 312
35 .define baudrate 5 ; UBRR value for 76800 bits/s (8mhz clock)
36
37 ; sizes
38 .define uart_data_len 4
39
40 ; names for registers
41 .def tmp = r16
42 .def bitcount = r17
43 .def tmp1 = r18
44 .def tmp2 = r19
45 .def byte = r20
46 .def overflow_counter = r21
47 .def counter_l = r22
48 .def counter_h = r23
49 .def state = r24
50 .def state_m = r25
51 .def mode = r26
52 .def counter_l_tmp = r27
53 .def counter_h_tmp = r28
54 .def address_h = r31
55 .def address_l = r30
56 .def one = r1
57 .def zero = r0
58
59 ; state
60 .define LOW (1<<0)
61 .define LOW_F 1
62 .define HIGH (1<<1)
63 .define HIGH_F 2
64 ; mode
65 .define STUPID (1<<0) ; forward cam <-> card communication
66 .define STUPID_F 1
67 .define COOL (1<<1) ; send time (clocks) & state via uart
68 .define COOL_F 2
69 .define ELITE (1<<2) ; create bytes, maybe even whole command arrays
70 .define ELITE_F 3
71 .define GODLIKE (1<<3) ; filter and mask for commands to card - send rejected via uart only
72 .define GODLIKE_F 4
73 .define INCREDIBLE_HACK (1<<4) ; destroy all your hardware
74 .define INCREDIBLE_HACK_F 5 
75
76 ; but there is only stupid and cool mode right now %)
77
78
79 ; #############
80 ; programm code
81 ; #############
82
83 ; ------------------
84 ; interrupt vectors:
85 ; ------------------
86
87 ; reset
88 rjmp INIT
89
90 ; int0
91 rjmp RST_CAM
92
93 ; int1
94 rjmp REC_CAM
95
96 ; timer/counter capt 1
97 rjmp REC_CARD
98
99 ; timer/counter compare
100 reti
101
102 ; timer/counter overflow 1
103 rjmp T1_OVERFLOW
104
105 ; timer/counter overflow 0
106 reti
107
108 ; uart rx complete
109 reti
110
111 ; uart data register empty
112 rjmp UART_OUT
113
114 ; uart tx complete
115 reti
116
117 ; analog comparator
118 reti
119
120 ; ------------
121 ; init routine
122 ; ------------
123
124 INIT:
125
126 ; output low on rst to card while init
127 sbi DDRD,DDD4
128 cbi PORTD,PD4
129
130 ; set stackpointer
131 ldi tmp,low(RAMEND)
132 out SPL,tmp
133
134 ; enable interrupts int0,int1
135 ldi tmp,((1<<INT0)|(1<<INT1))
136 out GIMSK,tmp
137 ; int0/1 setup
138 ldi tmp,((1<<ISC01)|(0<<ISC00)|(1<<ISC11)|(0<<ISC10))
139 out MCUCR,tmp
140
141 ; enable t/c overflow interrupt and icp
142 ldi tmp,((1<<TOIE1)|(1<<TICIE))
143 out TIMSK,tmp
144 ; setup t/c and icp
145 ldi tmp,((1<<CS12)|(1<<CS11)|(1<<CS10)|(1<<ICNC1)|(0<<ICES1))
146 out TCCR1B,tmp
147
148 ; configure uart - interrupt enabled when i/o
149 ldi tmp,baudrate
150 out UBRR,tmp
151 sbi UCR,TXEN
152
153 ; enable pullups on int0, int1, clk, icp io ports
154 ldi tmp,((1<<PD2)|(1<<PD3)|(1<<PD5)|(1<<PD6))
155
156 ; init registers
157 ldi bitcount,0 
158 ldi byte,0
159 ldi overflow_counter,0
160 ldi counter_l,0
161 ldi counter_h,0
162 ldi state,HIGH ; .. as waiting for falling edge of start bit
163 ldi state_m,0x03
164 ldi mode,(STUPID|COOL)
165 ldi address_h,0
166 ldi tmp,1
167 mov one,tmp
168 ldi tmp,0
169 mov zero,tmp
170
171 ; enable interrupts (global)
172 sei
173
174 ; output high on rst to card
175 sbi PORTD,PD4
176
177 ; jump to mainloop
178 rjmp MAIN
179
180 ; ------------
181 ; main routine
182 ; ------------
183
184 MAIN:
185
186 ; loop and wait for interrupts
187 rjmp MAIN
188
189 ; ----------------
190 ; rec_card routine
191 ; ----------------
192
193 REC_CARD:
194
195 ; input & pullup
196 cbi DDRD,DDD6
197 sbi PORTD,PD6
198
199 ; toggle state
200 eor state,state_m
201
202 ; toggle icp sense
203 rcall TOGGLE_ICP_SENSE
204
205 ; fwd to cam if in stupid mode
206 sbrc mode,STUPID_F
207 rcall FWD_TO_CAM
208
209 ; calculate delta clocks if in cool mode
210 sbrc mode,COOL_F
211 rcall CALC_DELTA_CLOCK
212
213 ; send time and state via uart
214 sbrc mode,COOL_F
215 rcall PREPARE_UART
216
217 ; return
218 reti
219
220 ; ------------------------
221 ; calc_delta_clock routine
222 ; ------------------------
223
224 CALC_DELTA_CLOCK:
225
226 ; store counters
227 mov counter_l_tmp,counter_l
228 mov counter_h_tmp,counter_h
229
230 ; get new ones
231 in counter_l,ICR1L
232 in counter_h,ICR1H
233
234 ; delta calc on host software by now
235
236 ; return
237 ret
238
239 ; ------------------------
240 ; toggle_icp_sense routine
241 ; ------------------------
242
243 TOGGLE_ICP_SENSE:
244
245 ; toggle according to state
246 in tmp,TCCR1B
247 cbr tmp,ICES1
248 sbrs state,HIGH ; maybe toggle according to TCCR1B?
249 sbr tmp,ICES1
250 out TCCR1B,tmp
251
252 ; return 
253 ret
254
255 ; ------------------
256 ; fwd_to_cam routine
257 ; ------------------
258
259 FWD_TO_CAM:
260
261 ; disable external interrupt 1 while toggling edge
262 in tmp,GIMSK
263 cbr tmp,INT1
264 out GIMSK,tmp
265
266 ; output state on port to cam
267 in tmp1,PORTD
268 sbr tmp1,PD3
269 sbrs state,HIGH_F
270 cbr tmp1,PD3
271
272 ; configure as output and push-pull low/high
273 sbi DDRD,DDD3
274 out PORTD,tmp1;
275
276 ; reenable external interrupt 1
277 sbr tmp,INT1
278 out GIMSK,tmp
279
280 ; return
281 ret
282
283 ; --------------------
284 ; prepare_uart routine
285 ; --------------------
286
287 PREPARE_UART:
288
289 ; write transfer data to sram
290 ldi address_l,0x60
291 st address_l+,counter_l
292 st address_l+,counter_h
293 st address_l+,overflow_counter
294 st address_l+,state
295
296 ; enable uart data register empty interrupt
297 sbi UCR,UDRIE
298
299 ; return
300 ret
301
302
303 ; ---------------
304 ; rec_cam routine
305 ; ---------------
306
307 REC_CAM:
308
309 ; first thing - pullup on
310 cbi DDRD,DDD3
311 sbi DDRD,PD3
312
313 ; toggle state
314 eor state,state_m
315
316 ; toggle int sense
317 rcall TOGGLE_INT_SENSE
318
319 ; fwd to card if in stupid mode
320 sbrc mode,STUPID_F
321 rcall FWD_TO_CARD
322
323 ; calculate delta clocks if in cool mode
324 sbrc mode,COOL_F
325 rcall CALC_DELTA_CLOCK
326
327 ; return
328 reti
329
330 ; ------------------------
331 ; toggle_int_sense routine
332 ; ------------------------
333
334 TOGGLE_INT_SENSE:
335
336 in tmp,MCUCR
337 cbr tmp,ISC10
338 sbrs state,HIGH_F
339 sbr tmp,ISC10
340 out MCUCR,tmp
341
342 ; return
343 ret
344
345 ; -------------------
346 ; fwd_to_card routine
347 ; -------------------
348
349 FWD_TO_CARD:
350
351 ; disable icp interrupt while toggling edge
352 in tmp,TIMSK
353 cbr tmp,TICIE
354 out TIMSK,tmp
355
356 ; output state on port to card
357 in tmp1,PORTD
358 sbr tmp1,PD6
359 sbrs state,HIGH_F
360 cbr tmp1,PD6
361
362 ; configure as output and push-pull low/high
363 sbi DDRD,DDD6
364 out PORTD,tmp1;
365
366 ; reenable icp interrupt
367 sbr tmp,TICIE
368 out TIMSK,tmp
369
370 ; return
371 ret
372
373 ; -------------------
374 ; t1_overflow routine
375 ; -------------------
376
377 T1_OVERFLOW:
378
379 ; increment counter overflow
380 add overflow_counter,one
381
382 ; return
383 reti
384
385 ; ---------------
386 ; rst_cam routine
387 ; ---------------
388
389 RST_CAM:
390
391 ; by now just jump to init
392 rjmp INIT
393
394 ; ----------------
395 ; uart_out routine
396 ; ----------------
397
398 UART_OUT:
399
400 ; disable uart data register empty interrupt
401 cbi UCR,UDRIE
402
403 ; init counter(s)
404 mov address_l,zero
405 mov tmp,zero
406
407 ; send the data
408 rcall UART_SEND
409
410 ; return
411 reti
412
413 ; -----------------
414 ; uart_send routine
415 ; -----------------
416
417 UART_SEND:
418
419 ; read next byte from memmory and transfer via uart
420 sbic USR,UDRE
421 rcall UART_GS
422
423 ; return if everything was sent
424 cpi tmp,uart_data_len
425 brne UART_SEND
426 ret
427
428 ; ---------------
429 ; uart_gs routine
430 ; ---------------
431
432 UART_GS:
433
434
435 ; wie macht man load mit autoinc richtig?
436 ;
437
438 ; read byte from memory and write via uart
439 ld tmp1,address_l+
440 out UDR,tmp1
441
442 ; increment counter (maybe needed later)
443 add tmp,one
444
445 ; return
446 ret