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
RevLine 
[1dc9759]1; ---------------------------------------------------------------
2; Copyright 2010, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
3; Distributed under the terms of the MIT Licence
[53d1ddc]4.INCLUDE "2313def.inc"
[1dc9759]5
6; Firmware for µSerial expansion board
7
[53d1ddc]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
[7d5e268]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
[53d1ddc]24
25.EQU curregbak = SRAM_START
26
[741c0b9]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
[53d1ddc]31.CSEG
[1dc9759]32; Vectors
33; reset
[53d1ddc]34 RJMP init
[1dc9759]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 ---
[53d1ddc]52cpc_read:
[1dc9759]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
[741c0b9]66 OUT DATADIR,R16 ; 1
[53d1ddc]67 LD R27,X ; 2 cycles ; peut être économisé si un reg. contient
[1dc9759]68 ; déjà la valeur à envoyer
69 ; (mais qui l'update ?)
[741c0b9]70 OUT DATAOUT, R27 ; 1 cycle
[1dc9759]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
[741c0b9]80 LDS R27,curregbak
[1dc9759]81
82; release the bus
[7d5e268]83 SER R16
[53d1ddc]84 OUT DATADIR, R16
[7d5e268]85 CLR R16
[1dc9759]86
87; Restore R27 to selected reg. (we erased it to do the OUT)
88 RETI
89
[53d1ddc]90
[1dc9759]91; --- WRITE INTERRUPT ---
[53d1ddc]92cpc_write:
[1dc9759]93; The timing is a bit less constraining here.
[741c0b9]94 PUSH R0 ; 2 cycles
95 IN R0,DATAIN ; 1
[1dc9759]96; we also need to know A0 state...
[741c0b9]97 SBIS CTRLIN,A0 ; 1
[1dc9759]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
[53d1ddc]107regSel:
[741c0b9]108 STS curregbak,R0
[1dc9759]109 MOV R27,R0
110
[53d1ddc]111intEnd:
[1dc9759]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
[53d1ddc]120init:
[7d5e268]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
[741c0b9]130 ; led on (will be turned off by software at init)
[7d5e268]131 SBI CTRLOUT,DEL
132
[741c0b9]133 ; init serial port speed and io
[7d5e268]134 LDI R16,10
135 OUT UBRR,R16
136
[741c0b9]137 ; check for bootloader jumper and jump to bootload code if needed
[7d5e268]138 ; TODO
139
140 ; setup interrupts (enable INT0 and INT1 on falling edge)
141 LDI R16,0x0A
142 OUT MCUCR,R16
[741c0b9]143
[7d5e268]144 LDI R16,0xC0
145 OUT GIMSK,R16
146
147 ; we can now enable interrupts
[741c0b9]148 SEI
[7d5e268]149
[741c0b9]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.