source: avrstuff/CPC stuff/cpc_serial_2313/code/main.asm@ 7d5e268

main
Last change on this file since 7d5e268 was 7d5e268, checked in by Adrien Destugues <pulkomandy@…>, 14 years ago

Add some init code.

git-svn-id: svn://pulkomandy.tk/avrstuff@29 c6672c3c-f6b6-47f9-9001-1fd6b12fecbe

  • Property mode set to 100644
File size: 3.9 KB
Line 
1; ---------------------------------------------------------------
2; Copyright 2010, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
3; Distributed under the terms of the MIT Licence
4.INCLUDE "2313def.inc"
5
6; Firmware for µSerial expansion board
7
8.EQU ALL_OUT = 255
9.EQU ALL_IN = 0
10
11.EQU DATADIR = DDRB
12.EQU DATAOUT = PORTB
13.EQU DATAIN = PINB
14
15.EQU CTRLIN = PIND
16.EQU CTRLOUT = PORTD
17.EQU CTRLDIR = DDRD
18
19.EQU A0 = PIND5
20.EQU _READ = PIND3
21.EQU _WRITE = PIND2
22.EQU DEL = PIND6
23.EQU INT = PIND4
24
25.EQU curregbak = SRAM_START
26
27; REGISTERS ALLOCATION
28; R0 = 255 used in interrupt handler for fast switching of DATADIR
29; X (R27 & R26) used in interrupt for fast addressing of regs
30
31.CSEG
32; Vectors
33; reset
34 RJMP init
35; int0
36 RJMP cpc_write
37; int1
38 RJMP cpc_read
39; ...
40
41; Interrupt vectors for external INT pins (read and write).
42; we have to react very quick.
43; A read operation for the CPC lasts 3 clock cycles at 4MHz, that's 15
44; AVR cycles. But the interrupt latency is as follow :
45; Lowlevel detection ; 2 cycles
46; End of running instruction ; up to 2 cycles
47; Save PC ; 4 cycles
48;Vector RJMP ; 2 cycles
49 ; TOTAL => 10 cycles
50
51; --- READ INTERRUPT ---
52cpc_read:
53; That means we only have 5 cycles left to output the value on the BUS!
54; We have no time to do anything, so we assume that X is already pointing at
55; the right place and we just OUT it to the data port. We have no time for
56; PUSHing and loading it, anyway.
57
58; Note you can read from either port and get the same result. Two reasons to
59; that : you can already access all the registers and part of the SRAM,
60; and there's no time to do something more clever.
61
62; There is no time to push/pop regs, so we just use X as is. R27 is part of X.
63
64; We assume X (R26:R27) points to the current reg
65; So we can load it and react fast enough to the interrupt
66 OUT DATADIR,R16 ; 1
67 LD R27,X ; 2 cycles ; peut être économisé si un reg. contient
68 ; déjà la valeur à envoyer
69 ; (mais qui l'update ?)
70 OUT DATAOUT, R27 ; 1 cycle
71
72; Here data is sent, the CPC read operation is handled.
73; We now wait for the end of the read cycle.
74; This is not the end of the time-constrained nightmare, however :
75; In the worst case, the CPC can do another OUT or IN right after,
76; so we don't have an infinite number of cycles to handle the interrupt.
77; it is much more relaxed, as we have 12 CPC cycles = 60 AVR cycles free.
78
79; Restore R27
80 LDS R27,curregbak
81
82; release the bus
83 SER R16
84 OUT DATADIR, R16
85 CLR R16
86
87; Restore R27 to selected reg. (we erased it to do the OUT)
88 RETI
89
90
91; --- WRITE INTERRUPT ---
92cpc_write:
93; The timing is a bit less constraining here.
94 PUSH R0 ; 2 cycles
95 IN R0,DATAIN ; 1
96; we also need to know A0 state...
97 SBIS CTRLIN,A0 ; 1
98 ; This was actually a reg select operation!
99 ; Jump to the proper code
100 RJMP regSel
101; We have read the CPC data. End of the heavy-constraint area
102
103; Register write
104 ST X,R0 ; Normal register write
105 RJMP intEnd
106
107regSel:
108 STS curregbak,R0
109 MOV R27,R0
110
111intEnd:
112 POP R0
113 RETI
114
115
116; --- RESET VECTOR ---
117; Here we perform the hardware initialization.
118; At a bare minimum :
119; * Set up the INT0 and INT1 so the CPC can do the rest of the setup itself
120init:
121 CLI
122 ; setup ctrl port : RW and A0 as inputs, INT and DEL as output
123 LDI R16,0x28
124 OUT CTRLDIR,R16
125
126 ; setup dataport as input
127 CLR R0
128 OUT DATADIR,R0
129
130 ; led on (will be turned off by software at init)
131 SBI CTRLOUT,DEL
132
133 ; init serial port speed and io
134 LDI R16,10
135 OUT UBRR,R16
136
137 ; check for bootloader jumper and jump to bootload code if needed
138 ; TODO
139
140 ; setup interrupts (enable INT0 and INT1 on falling edge)
141 LDI R16,0x0A
142 OUT MCUCR,R16
143
144 LDI R16,0xC0
145 OUT GIMSK,R16
146
147 ; we can now enable interrupts
148 SEI
149
150mainloop:
151 ; maybe we will have to handle a buffer for the serial port
152 ; and 'fake' registers in SRAM
153
154 SLEEP
155 RJMP mainloop
Note: See TracBrowser for help on using the repository browser.