Wednesday, February 26, 2014

68k project: step IV - Switching to fast clock

[original article - http://xepb.org/dtz/68kavr.html ]
20140129
We will add fast clock. Just will, because out current CPU clock is slow. And for future 68681 UART which I am planning.

On my opinion, our AVR clock is about 60 times slower then external clock. (I run ATmega8A from 12Mhz crystal).

So lets' add an external quarts. (around 12 in my case; it will be devided by 2, read more). We will use
the Searle Grant's scheme on 74HCT04 and get FASTCLK signal pins 3,4,5,6.
And a trigger - 7474 (should be ALS or HCT, but I've tried old 7474 and it worked too.)
The trigger (1-7 pin) will behave the following manner: on reset, it will be at 1 (CLKFROMAVR high), and
by accessing E0000 address it will go low, that will be switching to fast clock. Also, by accessing C0000
from CPU you can switch it back to AVR clock. So we will mix /C0000 and /CPURESET signals on 7400, so
it will go high when any of /CPURESET and /C0000 will be active, and invert it on 74HCT00 pins 0 and 1
Then, we'll take the trigger output (CLOCKFROMAVR and /CLOCKFROMAVR) and mix it with CPUCLK on one segment
of 7400 and with FASTCLK. We'll get AVRCE (AVR Clock Enabled) and FCE (Fast Clock Enabled) signals.
When any of them disabled, it will go high, the other should tick. And let's mix them on one extra 7400
to get MIXEDCLK2

Is MIXEDCLK2 is good for clocking CPU? Maybe, I'm not sure.

Imagine you switch from AVR clock by accessing E0000, and fast clock front comes right after that?
That may be not good (because that will lead to a very fast clock tick) (or may not, because when you
switch the trigger you are at the end of cycle)

So let's use the other side of the moon 7474 trigger it to revert on any even clock change.
(And this devides clock by two.) I do not remember why I've decided that, but I really thought we'll have
one guaranteed tick in the worst case; it looks I'm wrong.
Anyway, this works ;-) (it really was an argument of doing it, but I forgot)

And unsolder CPUCLK clock from CPU and connect it to the output of that trigger (called CPUCLK')

20140213 Well, here it the worst case this trigger prevents: imagine we switch the clock
from slow to fast, and the MIXEDCLK2 is high. And saying when switched to fast clock it's low and
just before rising edge. So, the MIXEDCLK2 will go from high (from AVR) to low and back to high
too fast.
This is the case this trigger prevents.
Oh shit! Xepb.org is down again
We've never discussed M68K assembler code; some code in examples, but now it's time to speak about it
Currently I use A68K assembler (not pila) to get binary output of program; it has $1D bytes prefix (is it
for HP calc?), so I cut it and translate the rest of binary to C code via bin2c.tcl script.
While what you see in the 68K code is very experimetal (this is my first attempt to write 68K code),
at least here you can see an example (in byteio_fast.asm) file how to read and write bytes via AVR UART emulation


uartstat equ $A0002
uartdata equ $A0000
slowclock equ $C0000
fastclock equ $E0000

;------------------ RX char
rx_char:
bsr rx_notempt ; while rx is not empty, ie, no char
beq rx_char ; loop
move.b d0,(slowclock) ; switching clock slow
move.b (uartdata),d0 ; read from uart
move.b d0,(fastclock) ; switching clock fast
cmpi.b #CTRLC,d0 ; CTRL-C?
beq warm ; warm reset
rts

;------------------ Test input for a char (NOT ZERO if IS)
rx_notempt:
move.b d0,(slowclock) ; switching clock slow
move.b (uartstat),d0
move.b d0,(fastclock) ; switching clock fast
andi.b #$02,d0 ; bit 1 is 1? (I've told you that it is my first attempt to write 68k code!)
rts

;------------------ Wait for clear to send -------
tx_rdy_w:
move.l d0,-(sp)
tx_rdy_w1:
bsr tx_rdy
bne tx_rdy_w1
move.l (sp)+,d0
rts

;------------------ TX char
tx_char:
bsr tx_rdy_w
move.b d0,(slowclock) ; switching clock slow
move.b d0,(uartdata)
move.b d0,(fastclock) ; switching clock fast
rts
;----------------- Returns TX ready (Z)
tx_rdy:
move.b d0,(slowclock) ; switching clock slow
move.b (uartstat),d0
move.b d0,(fastclock) ; switching clock fast
andi.b #$01,d0
rts


The most interesting in this code is that it is working. I do not know what to tell you about this code,
may be the only thing: do not forget to switch the clock fast in your's main program

Avr/GCC/A86k source code