Poll
Question:
Does CPC use the R-efresh Z80A register for refresh Internal RAM?
Option 1: Yes.
Option 2: No.
org #4000
di
ld bc,&bc06
out (c),c
ld bc,&bd00
out (c),c
ld bc,&bc01
out (c),c
ld bc,&bd00
out (c),c
ld ix,0
ld bc,&1
ld a,0
ld de,0
ld hl,10
.loop
add ix,bc
ld r,a
nop
nop
nop
jr nc,loop
ld r,a
sbc hl,de
ld r,a
jr nc,loop
ld bc,&bc06
out (c),c
ld bc,&bd00+25
out (c),c
ld bc,&bc01
out (c),c
ld bc,&bd00+40
out (c),c
halt
Two options allowed in the poll?
I don't think it does:
See https://www.cpcwiki.eu/forum/amstrad-cpc-hardware/crtc-settings-which-cause-ram-refresh-to-stop/
Quote from: Gryzor on 20:46, 11 March 24Two options allowed in the poll?
Yes. ;D so that someone can change their mind.
I'll just leave this here...
It's a paragraph taken from the great book "Understanding And Expanding Your AMSTRAD CPC 464 664 6128" by Alan Trevennor and published by Sigma Press (well worth reading). https://www.cpcwiki.eu/index.php/Understanding_and_Expanding_your_Amstrad_CPC464-664/6128
The entire book can be found in text and PDF format here:
https://archive.org/stream/understanding-and-expanding-your-amstrad-cpc-464-664-6128-alan-trevennoracme/Understanding_and_expanding_your_AMSTRAD_CPC464-664-6128%28Alan_TREVENNOR%29%28acme%29_djvu.txt
"The RAM chips
The RAM consists of 8 chips. These are all 64K by 1 bit dynamic RAM chips,
type HM4864. Whilst they offer far higher capacity per chip than a static RAM
(for example the 6116 RAM which is a 2K by 8 bit, which you may have
seen used in magazine projects a lot), dynamic RAM chips need to be
continuously reminded of what they are remembering! This is because the
memory elements are actually tiny capacitors, which if they are not topped up
will lose their charge. This top up function is called refreshing them. (No
Lager jokes please!). The trick is to perform the RAM refresh when the
memory is not being accessed. In fact the Z80A has the facility to
automatically perform refresh, but in the CPC the gate array has been chosen
to do it. This is because the memory is also accessed by the VDU controller,
and the gate array has to ensure that the memory is not required by either
processor or VDU controller before refresh can occur. The memory refresh
process consists of pulsing two input lines to all the RAM chips. These are
called CAS (Column Address strobe) and RAS (Row address strobe). These
are pulsed whilst the row and column addresses are passed into the RAM
sequentially. The 4864 chips used have a cycle time of 200 nanoseconds."
Bryce.
Quote from: McArti0 on 21:43, 11 March 24Quote from: Gryzor on 20:46, 11 March 24Two options allowed in the poll?
Yes. ;D so that someone can change their mind.
That's another option ("allow users to change their vote" or something), the option you enabled allows users to vote both yes and no at the same time :D
But now they won't deny that they pressed NO. ;D At least I think so
Why would they want to deny something that I just confirmed above?
Bryce.
Because the code I showed shows that if you turn off the CRTC counter and turn off R, refreshing does not occur.
But if we do not turn off R, refreshing works great, for all memory. Why?
Because the memory is refreshed based on R from Z80 and the RAS signal in RAS-only memory mode.
And this happens for 60% of the time CPC is running in standard resolution.
Ps. Additionally, it is a surprise that in LowROM there are LD R,A and LD A,R commands, and more than once. :P
Quote from: McArti0 on 15:34, 12 March 24But if we do not turn off R, refreshing works great, for all memory. Why?
Did you check "CRTC off, but R active" where your test code disables all interrupts, disables the CRTC and then enters an endless loop?
Quote from: eto on 16:00, 12 March 24where your test code disables all interrupts, disables the CRTC and then enters an endless loop?
On my CPC :D. I will prepare such a comparison on DSK.
The code shown is spectacular because it shows the contents of unrefreshed memory.
The CRTC is creating the addresses for the refresh, so any changes to the CRTC could effect the refreshing.
Bryce.
R6=0 R1=0 and CRTC nothing creating. When always set R=0 CPC crashing. When R is working CPC without CRTC working too.
I might be wrong but when I made my internal RAM expansion I this became my understanding of the refresh, which was the foundation to actually replace the internal RAM with bigger ICs:
The 4164 ICs are organized as a matrix of 128 rows and 512 columns of cells(bits). These cells need to be refreshed every 2ms at least. Each 512 cells in a row are refreshed, when the respective row is accessed (RAS signal + address lines). So what a computer needs to ensure is that within 2ms all 128 RAM rows are accessed at least once. It's not necessary to really read from RAM, it's just important that the RAS signal is there and 128 different ROW addresses have been accessed within those 2ms. How the computer is doing that is is done is not relevant. You can use the RFSH signal to build a respective circuit that does that - or you can do it differently. Any access to the RAM will refresh cells and as long as you make sure all rows are accessed your RAM will be refreshed.
The Amstrad engineers now did quite a genius trick which ensures RAM refresh as a side effect of the GateArray accessing the RAM, which it will always do (unless someone explicitly disables it):
The lower address lines A0-A7 of the memory are usually mapped to the CAS sequence of RAM access, but in the CPC they are mapped to the RAS sequence. (Note: The higher lines A8-A15 are then mapped to the CAS sequence. For the physical storage in the RAM ICs this doesn't matter how exactly the bytes are stored as long as reads and writes to the same address also access the same byte in RAM.)
This unusual physical addressing has a nice side effect for RAM refresh: As long as RAM is accessed byte per byte for at least 128 bytes continuously all RAM rows will be refreshed properly - without the need for any special refresh logic.
And exactly this is, what the GateArray does as it accesses the screen RAM byte by byte for usually 16KB in a row. And as long as the GateArray reads the screen the RAM will be refreshed.
If you now turn off the GateArray access it doesn't necessarily mean that the RAM will no longer be refreshed as also CPU access to the RAM will also refresh the RAM. Again as long as the CPU reads from 128 continuous addresses (within the refresh period of 2ms) all RAM rows will be accessed - and refreshed. If I am not mistaken this does even work if the CPU reads from ROM as the address will be put on the RAM IC address pins during the RAS sequence - just the CAS is not executed - but that doesn't matter as only RAS is required to do the RAM refresh.
So as long as the computer is accessing "enough" bytes within the 2ms refresh window the RAM rows will be refreshed.
Quote from: McArti0 on 16:07, 12 March 24On my CPC :D. I will prepare such a comparison on DSK.
Sorry, I did not mean "where" you did that. But you need to compare both situations similarly:
When you set the R-register to the same value you are doing that in an endless loop. When you do the same check without setting the R register you need to use the exact same code that disables the CRTC and goes into an endless loop (just not set the R register).
YES! :D eto win. Long 7ms between last screen line no. 200 to first line no. 0, memory is refreshing by z80 and his R register.
I try to answer it in a different way.
No the CPC in any normal operation never needs or considers the refresh register. Also the Gatearray is very closely managing the access to the ram.
How does the refresh work on a 4864 ?
If you put an address (8bit) to the RAM chip, and then strobe RAS signal, it will read the whole row into a buffer and writes it back into the cell. That is actually the refresh.
So if you do read every row through the required time, then the CPU putting addresses to the bus, would not be required.
However obviously with normal code, you cannot guarantee, that the CPU just by chance is reading all rows.
So that is (we are now forgetting about the CPC for a second here), why the CPU supports to output addresses to the addressbus, when it actually does not need it and then run the refresh with that. This would be required in other systems, as nothing else would read the RAM.
However in CPC, the CRTC is connected to the RAM in a way, that it output each of the 256 row addresse for every frame. So the refresh will be done every 20µs.
Also the Gatearray is handling the access of the Addressbus to the RAM. At CPU T-Cycles 3 and 4 (3 and 4 are normally the normal refresh cycle) the gatearray exclusively reserves the RAM access to the CRTC and Gatearray. CRTC is actually not reading it, but outputting the correct memory address.
Gatearray will read actually data in that timeframe.
So even if you would want to believe that the CPU refresh is doing anything, it is actually not able to ever output the address to the physical ram as it is blocked via the Multiplexer by command of the GateArray.
The GateArray is actually the Commander in the CPC - not the CPU. The CPU needs to obey to the ruling of the GateArray.
Some more background, from Z80 User Manual:
QuoteMemory Refresh (R) Register. The Z80 CPU contains a memory refresh counter, enabling dynamic memories to be used with the same ease as static memories. Seven bits of this 8-bit register are automatically incremented after each instruction fetch. The eighth bit remains as programmed, resulting from an LD R, A instruction. The data in the refresh counter is sent out on the lower portion of the address bus along with a refresh control signal while the CPU is decoding and executing the fetched instruction. This mode of refresh is transparent to the programmer and does not slow the CPU operation. The programmer can load the R register for testing purposes, but this register is normally not used by the programmer. During refresh, the contents of the I Register are placed on the upper eight bits of the address bus.
Here is the corresponding timing diagram:
OpCodeFetch.jpg
So you can see, refresh is working in T-Cycles 3 and for of an M1 cycle (opcode fetch).
Two other things to notice:
1. The RFSH line is not connected to any component in the CPC, only to the external bus. That would be needed, as if you do not strobe the RAS signal, you will not get the RAM to read anything into the buffer and therefore not being able to refresh it. Some extra logic is required to use that feature.
2. See the Gatearray timing, that exclusively openes a Window for the addresses of the CPU getting to the RAM.
Pls see the attached diagram. I shamelessly copied it from here https://bread80.com/2021/06/03/understanding-the-amstrad-cpc-video-ram-and-gate-array-subsystem/:
Blue is, the gatearry is using the RAM, red is, when the Gatearray is actually alowing the CPU to read from ram. But control (RAMRD and CPU line) is handled by the GateArray.
CPUvsGateArray.jpg
All incorrect. T4 is for CPU. and CPU refresh work.
You are saying Zylog is incorrect about their timing?
Read it yourself if you do not trust me copying it from the original manual.
https://www.zilog.com/docs/z80/um0080.pdf
I know you know better than anyone before you. We are all wrong.
ETO win this competition. Do not get excited. Write next post tomorrow ok?
Winner text:
Quote from: eto on 12.03.2024, 16:39:51
If you now turn off the GateArray access it doesn't necessarily mean that the RAM will no longer be refreshed as also CPU access to the RAM will also refresh the RAM. Again as long as the CPU reads from 128 continuous addresses (within the refresh period of 2ms) all RAM rows will be accessed - and refreshed. If I am not mistaken this does even work if the CPU reads from ROM as the address will be put on the RAM IC address pins during the RAS sequence - just the CAS is not executed - but that doesn't matter as only RAS is required to do the RAM refresh.
Quote from: McArti0 on 17:26, 12 March 24memory is refreshing by z80 and his R register.
no, it's not... that's what I tried to explain in my very long post (and what SerErris also explained in a different way): The r register does not have anything to do with the RAM refresh in the CPC.
You can also check the schematics to see that the RFSH line of the CPU is not used anywhere in the CPC (except for the expansion bus).
Quote from: McArti0 on 18:31, 12 March 24ETO win this competition. Do not get excited. Write next post tomorrow ok?
Winner text:
Quote from: eto on 12.03.2024, 16:39:51
If you now turn off the GateArray access it doesn't necessarily mean that the RAM will no longer be refreshed as also CPU access to the RAM will also refresh the RAM. Again as long as the CPU reads from 128 continuous addresses (within the refresh period of 2ms) all RAM rows will be accessed - and refreshed. If I am not mistaken this does even work if the CPU reads from ROM as the address will be put on the RAM IC address pins during the RAS sequence - just the CAS is not executed - but that doesn't matter as only RAS is required to do the RAM refresh.
but it's not the refresh feature of the CPU. This will only happen if the CPU "coincidentally" accesses the right addresses. And this coincidence is pretty high in the CPC as A0-A7 are connected to the RAM rows.
It is actually the loop you are running to test it.
Every read of the memory (so actually the loop) will read that row (the whole row). And this row will get refreshed. Your loop will have some bytes, which translates into memory rows (as ETO explained).
So if you are running aloop over a few bytes (lets say 10) you will already hit 10 rows in the CPC. If your loop is running over 127 bytes - you probably hit all rows.
So the loop itself will never recognize that anything is wrong as the loop itself does refresh the cells needed for the loop (and others).
Quote from: SerErris on 18:51, 12 March 24is running over 127 bytes - you probably hit all rows.
if it runs over 128 bytes it will definitely hit all rows.
Quote from: McArti0 on 17:26, 12 March 24memory is refreshing by z80 and his R register.
Maybe another test you can do: Remove the Z80 from its socket. Bend up the RFSH pin and put the CPU back into its socket. Then try again.
Quote from: eto on 18:42, 12 March 24You can also check the schematics to see that the RFSH line of the CPU is not used anywhere in the CPC (except for the expansion bus).
Our memory not need RFSH line because they are "RAS-only" refresh. They only need ROW ADDRESS and RAS edge. thats all.
Quote from: SerErris on 18:51, 12 March 24So if you are running aloop over a few bytes (lets say 10) you will already hit 10 rows in the CPC. If your loop is running over 127 bytes - you probably hit all rows.
I took care of that. the loop is tight. Moreover, it is not 127 bytes but 256+126 because CPC has addresses connected to ROW A0-A6 in the order A2, A1, A4, A3, A6, A5, A8. Without A0 and A7, there is A8.
Refreshing works for me at R6=0. So what's wrong?
Quote from: McArti0 on 18:31, 12 March 24ETO win this competition. Do not get excited. Write next post tomorrow ok?
Winner text:
Quote from: eto on 12.03.2024, 16:39:51
If you now turn off the GateArray access it doesn't necessarily mean that the RAM will no longer be refreshed as also CPU access to the RAM will also refresh the RAM. Again as long as the CPU reads from 128 continuous addresses (within the refresh period of 2ms) all RAM rows will be accessed - and refreshed. If I am not mistaken this does even work if the CPU reads from ROM as the address will be put on the RAM IC address pins during the RAS sequence - just the CAS is not executed - but that doesn't matter as only RAS is required to do the RAM refresh.
So what you are actually saying is that your aim, right from the start, was to ignore all the evidence presented before you by multiple people and documented in books until you found someone who vaguely confirmed your incorrect initial assumptions? You have a great future in politics ahead of you!
So now explain to us all what R157 and R158 are there for?
Bryce.
One thing I've often wondered but not entirely understood is this comment in the Arnold V documentation about the screen spli:
QuoteNote that care should be taken with programming this facility such that the screen split does not alter the function of address bits A1-A8 and the dynamic memory refresh is not upset.
Has anyone got an example of what you could do that would cause this issue? Or maybe
@McArti0 can explain why it doesn't matter if the Z80 refresh mechanism is used.
I have code that returns even though CRTC is disabled and does not produce artifacts.
I showed code that produces artifacts when avoiding R increment.
I don't know what r157,158 are for, CPC also works without them.
I hope I (at least vaguely) disproved the initial assumption...
That this was seen as proof/confirmation is quite surprising to me.
Ah no, the 0 byte does not count :D
And yet it doesn't work. I thought I had an ace up my sleeve and I didn't. :-\
When i set R6=0, screen has one scan line and refresh something.
Quote from: McArti0 on 20:47, 12 March 24Quote from: eto on 18:42, 12 March 24You can also check the schematics to see that the RFSH line of the CPU is not used anywhere in the CPC (except for the expansion bus).
Our memory not need RFSH line because they are "RAS-only" refresh. They only need ROW ADDRESS and RAS edge. thats all.
Yes, but the CPU cannot strobe RAS. The GateArray does. And the GA does it based on /RD and /MREQ or on its own reads. /RFSH has no impact - is not connected to the GateArray and to anything else inside the CPC.
/RD is disabled during /RFSH.
you can see it in the timing diagram of the CPU but as well as the real operation of the gatearray:
CPUvsGateArray.jpg
The blue part is where the gatearray is accessing the RAM, and where it is actually reading the screen data.
You can see the following: GA sets RAS (one time) and then two times CAS. The reason for that is, that the CRTC has generated two addresses and only the lowest bit, so the next byte in RAM from the same column is retrieved. That is one of the features of the RAM, that it can burst read. So you only need to have a single RAS and can then read up to 512 bytes (256 bytes depending on the memory). This is unused in CPC other for the aspect of the Gatearray reading screen data.
You can also see NRD high (not active) at the same time - that is the CPU signal to read stuff which active low. So in this particular section it is not active or disabled.
What you also can see is that during the blue time, the NMREQ is going down (active). That is the actual time when the CPU wants to refresh. NRFSH is not captured unfortunately, but would be active at the same time, as you can see in the CPU documentation.
So the logic is actually RD and MREQ active = RAS/CAS. But only if that is coming in in a specific time window (Sequencer).
But here, we actually do not have RD and MREQ active, but only MREQ, so it is getting ignrored by the GateArray.
So all in all, there is no technical way for the CPC to use the RFSH Line of the CPU and even the normal RD and MREQ lines are not directly connected to the RAM, but instead to the GateArray. And it will not use it to create the RAS signal here.
Your conclusion out of what you overserve, is just not correct and you need to alter the conclusion.
Here there is no M1 cycle, then the nCPU comes first and then refresh at the same time as the screen reading. Classic NOP. but of course the Z80 refresh is a competitor to reading RAM for the screen
NCPU_ADDR is high - means it is not active (active low signal). Which means during the blue part, the CPU cannot access the ram, however during the red part it can access the RAM.
More technically it means, during NCPU_ADDR active (low) the address lines of the CPU are multiplexed to the RAM (ram) and all other times the CRTC address lines are connected to RAM.
The CPU can only read or write during the short period of time when the gate array puts NCPU_ADDR low. Which starts at second half of the image and ends 3/4 to the right of the image.
The Gatearray actually need to force the CPU to be in that slot, so that it does not write to the RAM (e.g. wants to write), but the address lines are currently connected to the CRTC and also NMWE is disabled (so nothing the CPU will do will get ever written into CPU). It does it with wait states, so that it always falls into the 4 clock cycle boundry and the CPU will ever read or write from Memory at this particular fixed window.
That is actually T2 of the CPU M cycle and after that the address lines are disconnected - so the address output of the refresh address genereated by the R register between T3 and T4 cannot reach the RAM.
In CPC the CPU can not compete with screen reading and can not use its refresh technology for any task.
One more thing to chew on: The R register is only a seven bit counter (bit 7 never updates). The 4164 DRAM requires 16-bit addresses. To quote from the datasheet (https://www.farnell.com/datasheets/1905614.pdf):
"Refresh A refresh operation must be performed at least every four milliseconds to retain data. Since the output buffer is in the high−impedance state unless CAS is applied, the RAS only refresh sequence avoids any output during refresh. Strobing each of the 256 row addresses (A0 through A7) with RAS causes all bits in each row to be refreshed. CAS can remain high (inactive) for this refresh sequence to conserve power."
The memory chips require an 8-bit refresh counter. The Z80 only provides a 7-bit refresh counter. Therefore the Z80 can't be the one driving the refresh.
(And to recap what's already been said: The CRTC and GA already provide a 14 bit counter, and this is already driving RAS of the RAMs. Why would the designers of the Amstrad ignore this and add extra circuitry to get the refresh from the Z80 (and they'd need to find extra time in the video cycle to do so?).)
Quote from: Bread80 on 18:42, 13 March 24each of the 256 row addresses
quite many (most?) 4164 chips use only 7 bits for the rows, e.g. the Samsung KM4164B.
Quote from: eto on 16:39, 12 March 24The 4164 ICs are organized as a matrix of 128 rows and 512 columns of cells(bits). These cells need to be refreshed every 2ms at least. Each 512 cells in a row are refreshed, when the respective row is accessed (RAS signal + address lines). So what a computer needs to ensure is that within 2ms all 128 RAM
Just out of interest, I looked the datasheet of the 4164 up, and was wondering about this as well.
According to this datasheet https://www.silicon-ark.co.uk/datasheets/TMS4164-datasheet-texas-instruments.pdf
it is actually a 256 rows by 256 columns chip.
So the chips build into the 464s (at least) would need full 8 bit for refresh.
However the Hitachi 4864 actually have a 128x512 organisation and can be refreshed in 128 cycles (actually can get refreshed by the R register of the Z80.
I think they just jammed everything in the CPCs, and that was possible because of Refresh is being done by GA/CRTC and they do not care if it needs 256 reads or 128 reads.
In reality 256 reads are about 3,2 screen lines, which will take about 128 µs only.
And the 4164 already have a refresh time of 4ms ... which is plenty of time. So that is actually never a problem.
Also the refresh of the CRTC is absolutely stable, vs. the CPU is refreshing only at M1 cycles and that would be very inconsistent depending on the code you actually execute. It would be in average every 3-4µs and so that would mean 256 rows (256 commands) would be about 1ms. Still a lot of air in there.
I suspect the real reason for using the GA is that the original design was based on the 6502, which needed external RAM refresh. So they'd probably already figured that out before switching the CPU over to the Z80 and why change something that already worked?
But CRTC does not refresh at all for 7ms per frame.
Have any of you checked if the RAS for CRTC exists under every high nCAS state even when it is border?
I think if Roland Perry and William Poel got in a time machine and read this forum, their minds would explode. They would definitely kidnap some of you and take them back to their own time to exploit your talents and intelligence.
Quote from: SerErris on 20:15, 13 March 24However the Hitachi 4864 actually have a 128x512 organisation and can be refreshed in 128 cycles (actually can get refreshed by the R register of the Z80.
I've read that the 7-bit refresh of the Z80 caused 'challenges' for computer designers when 64kbit DRAMs started to arrive. I'd guess Hitachi found a clever solution - refresh two lines off a single RAS.
BTW, one more thing I'm thinking about: A0 is driven by the GA. It's used to read the two video bytes during a cycle. It updates between the two video CAS cycles. There is no second RAS. If A0 where being used for CAS only bytes at even addresses would get refreshed!
I'm willing to bet that the A0 is sent to the RAMs during a CAS cycle. A RAS cycle is (probably) running off A1 to A8 (although could be other address lines). This would depend on the wiring of the multiplexers. If anyone wants to take a look at the schematics they're welcome.
Quote from: McArti0 on 20:58, 13 March 24But CRTC does not refresh at all for 7ms per frame.
Have any of you checked if the RAS for CRTC exists under every high nCAS state even when it is border?
See attached a screenshot from the 6845 datasheet: The CRTC address lines continue to run. This actually makes sense as the CRTC was (also) used in graphics cards where no CPU could do the RAM refreshes so the CRTC had to make sure all graphics RAM is always refreshed.
Quote from: Bread80 on 00:11, 14 March 24I'm willing to bet that the A0 is sent to the RAMs during a CAS cycle. A RAS cycle is (probably) running off A1 to A8 (although could be other address lines). This would depend on the wiring of the multiplexers. If anyone wants to take a look at the schematics they're welcome.
that's exactly what's happening
Quote from: McArti0 on 20:58, 13 March 24But CRTC does not refresh at all for 7ms per frame.
Have any of you checked if the RAS for CRTC exists under every high nCAS state even when it is border?
The GA is still generates all the video related signals during HSYNC, VSYNC and border periods as if nothing has changed.
I'm not an expert on the 6845 but the datasheet appears to show that the addresses (MA0-MA13) continue to count during those periods.
https://www.cpcwiki.eu/imgs/d/da/Mc6845.motorola.pdf
(Up until now I'd assumed the designers had missed a trick my not running the CPU at full speed during those periods. But if the video cycles are still required for memory refresh then they were simply being clever...)
Quote from: McArti0 on 20:58, 13 March 24But CRTC does not refresh at all for 7ms per frame.
Have any of you checked if the RAS for CRTC exists under every high nCAS state even when it is border?
You are now mixing up blank cycles of a frame and CRTC counting. Even during the blank cycle the CRTC keeps counting, because how would it know otherwise if the blank phase needs to end?`
Beneath the counting and the addresses the CRTC is generating three signals.
VSYNC, HSYNC and DISPEN. All three are going into the GA and it is used there to create the correct timing of the video signal.
But the CRTC never stops counting.
Regarding the RAS signal.
Yes it is important that not only the CRTC is counting, but that the GA is continue to create a RAS signal.
And yes it does.
Internally the GA creates a sequence byte, that is pretty much independent of any other value in the CPC (there is one exception regarding interrupts).
The Sequence looks like this:
Bits 7654 3210 S7-S0
---------------
FF: 1111 1111
FE: 1111 1110
FC: 1111 1100
FB: 1111 1000
F0: 1111 0000
E0: 1110 0000
C0: 1100 0000
80: 1000 0000
00: 0000 0000
01: 0000 0001
03: 0000 0011
07: 0000 0111
0F: 0000 1111
1F: 0001 1111
3F: 0011 1111
7F: 0111 1111
FF:
.
.
.
The clock is running at 16Mhz. So it runs from one value to the next ever 1/16 µs. That is 4 times faster then the CPU signal.
This sequence is then used to create most of the other signals. That includes the CPU clock, the CRTC clock (and sound chip) the RAS signal and some others.
The RAS signal only depends on this sequence and the clock. The clock is used to trigger a flip-flop to stabilize the RAS output.
The function is S0 AND (NOT S2 OR S6)
So this is true for the following Values:
FF, 01,03, 7F. ... in other order 01-03 (2 clocks) and 7F-FF (2 clocks) the RAS high will be generated (not active) and from 07-3F (4 clocks) and FE-00 (8 clocks) it will RAS low (active).
So yes. the GateArray is creating the RAS signal whatever happens to the other parts of the systems. It is not even dependent on the HSYNC/VSYNC signals.
CAS however is only created if it GA needs to read something or if there is a MREQ from the CPU. However the MREQ is also conditionally that it is NOT a Refresh (e.g. not during an M1 cycle after it has finished its opcode read). There is a particular piece of logic in the GA that actually filters this specific condition, to not get confused when a CAS signal is needed.
If you want to read the logic of the CAS signal, which is pretty much more complicated than the RAS signal, I can only recommend Gerald's schematics of the GateArray. Most is explained there, and I just described it in more words.
Addition:
CPU signal (which is used to switch from CRTC Address to CPU address is the following logic:
S1 NAND NOT S7
So when S1 = 1 and S7 = 0 CPUN gets low (active)
This is exactly the case during 03-7F, so for exactly 6 GA cycles, or for 6/16 or 0,375 µs each µs. That is the time window (and the only time window) when the CPU address bus is connected to the RAM. All other times, it is disconnected and the CRTC address bus is connected.
Also this logic is not depending on anything else than the internal Sequencer of the GateArray.
Double post
BTW: The Toshiba TMM4164AP also has a 7*9 bit matrix. It is just internally taking one bit of the RAS and combining it with the 8 bit of CAS to achieve that.
https://www.datasheetarchive.com/datasheet?id=dccad5d93e48b7d136da4dc4f6d7cf660e1972&type=M&term=tmm4164
They have a very good datasheet showing how they do this internally:
TMM4164AP_Block.jpg
Quote from: SerErris on 10:14, 14 March 24Gerald's schematics of the GateArray.
oh... were can we find that?
You can find them in the Gate Array Decapped thread: https://www.cpcwiki.eu/forum/index.php?msg=170713
Or in codedchip's repository: https://github.com/codedchip/AMSGateArray
all this makes sense but one thing i don't understand - the video ram is being read full-time, 2 bytes each microsecond
the cpu is allocated its slot for the last part of that
how is a ram refresh squeezed into this time if the v-ram part is constant?
i thought i read somewhere it only refreshes if the z80 isn't accessing the ram I guess RD and WR being checked...
so it could be doing it selectively when cpu doesn't need memory access, if so i'm not sure how it handles it when external ram is paged in, maybe it switches that off too as part of it
so although it's under gate array control maybe it happens during the time the cpu usually has access to the ram?
Quote from: martin464 on 14:32, 14 March 24how is a ram refresh squeezed into this time if the v-ram part is constant?
vram and all internal RAM is read at all time by GA based on the address from CRTC . This is enough for refresh all.
Reading a row of RAM is sufficient to refresh that row, when the GA doesn't need to read the row (because we're in the border area) it just refreshes it instead. Thus the RAM is always refreshed and the Z80 mechanism doesn't need to be involved.
If you set the GA up in such a way that it won't refresh the RAM itself, then it pretty much down to whether the Z80 ends up reading sufficient rows often enough to keep them all refreshed, because it's own mechanism isn't connected to the RAM.
I think we turning in circles now. All that has been extensively explained in the posts before.
The RAM is organized (depending on the ram) in 127 or 256 rows and 512 or 256 columns.
The refresh of the ram works if you put one of the row addresses to the adress bus and then strobe the RAS signal.
The RAM in CPC is connected in a way, that the lowest 8 bit actually form the row address.
So in worst case it takes 256 µs for the gate array to read all row addresses. (2/µs).
about 2/3 of a µs (10/16µs) is used by the GA to read two bytes and the other 6/10s are available to the CPU to work with memory.
There is no additional refresh as the read from the gate array and the way how refresh works for RAM is enough to refresh everything 16times of the required time. So that includes the full 64/128kb of RAM.
Interestingly - the gate array does not read all the ram, it only reads the 4k addressed by the CRTC. The rest is never read, and esp the second bank of the 6128 is actually never read. It just gets the same RAS signals and therefore is getting refreshed the same way, but it never gets CAS signals from GateArray. Some expections - bank switching.
Quote from: SerErris on 22:15, 14 March 24I think we turning in circles now.
Ok. Lets go far. So how does CPC use the R-efresh register?
https://github.com/Bread80/CPC6128-Firmware-Source/blob/main/6128ROM.disasm
It's like timer?
;; sample edge and check for escape
;; L = bit-sequence which is shifted after each edge detected
;; starts of as &55 (%01010101)
;; check for escape
2b3d 06f4 ld b,&f4 ;; PPI port A
2b3f ed78 in a,(c) ;; read keyboard data through PPI port A (connected to PSG port A)
2b41 e604 and &04 ;; escape key pressed?
;; bit 2 is 0 if escape key pressed
2b43 c8 ret z
;; precompensation?
2b44 ed5f ld a,r ;;<<<<<<<<<<<<<<<<<<<<<<< A,R <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;; round up to divisible by 4
;; i.e.
;; 0->0,
;; 1->4,
;; 2->4,
;; 3->4,
;; 4->8,
;; 5->8
;; etc
2b46 c603 add a,&03
2b48 0f rrca ;; /2
2b49 0f rrca ;; /4
2b4a e61f and &1f ;;
2b4c 4f ld c,a
2b4d 06f5 ld b,&f5 ; PPI port B input (includes cassette data input)
;; -----------------------------------------------------
;; loop to count time between edges
;; C = time in 17us units (68T states)
;; carry set = edge arrived within time
;; carry clear = edge arrived too late
2b4f 79 ld a,c ; [1] update edge timer
2b50 c602 add a,&02 ; [2]
2b52 4f ld c,a ; [1]
2b53 380e jr c,&2b63 ; [3] overflow?
2b55 ed78 in a,(c) ; [4] read cassette input data
2b57 ad xor l ; [1]
2b58 e680 and &80 ; [2] isolate cassette input in bit 7
2b5a 20f3 jr nz,&2b4f ; [3] has bit 7 (cassette data input) changed state?
;; pulse successfully read
2b5c af xor a
2b5d ed4f ld r,a ;;<<<<<<<<<<<<<<<<<<<<<<< R,A <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2b5f cb0d rrc l ; toggles between 0 and 1
2b61 37 scf
2b62 c9 ret
;; time-out
2b63 af xor a
2b64 ed4f ld r,a ;;<<<<<<<<<<<<<<<<<<<<<<< R,A <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2b66 3c inc a ; "read error a"
2b67 c9 ret
;;========================================================================================
;; write data byte to cassette
;; A = data byte
2b68 d5 push de
2b69 1e08 ld e,&08 ;; number of bits
2b6b 57 ld d,a
2b6c cb02 rlc d ;; shift bit state into carry
2b6e cd782b call &2b78 ;; write bit to cassette
2b71 3003 jr nc,&2b76
2b73 1d dec e
2b74 20f6 jr nz,&2b6c ;; loop for next bit
2b76 d1 pop de
2b77 c9 ret
;;========================================================================================
;; write bit to cassette
;;
;; carry flag = state of bit
;; carry set = 1 data bit
;; carry clear = 0 data bit
2b78 ed4be8b1 ld bc,(&b1e8)
2b7c 2aeab1 ld hl,(&b1ea)
2b7f 9f sbc a,a
2b80 67 ld h,a
2b81 2807 jr z,&2b8a ; (+&07)
2b83 7d ld a,l
2b84 87 add a,a
2b85 80 add a,b
2b86 6f ld l,a
2b87 79 ld a,c
2b88 90 sub b
2b89 4f ld c,a
2b8a 7d ld a,l
2b8b 32e8b1 ld (&b1e8),a
;; write a low level
2b8e 2e0a ld l,&0a ; %00001010 = clear bit 5 (cassette write data)
2b90 cda72b call &2ba7
2b93 3806 jr c,&2b9b ; (+&06)
2b95 91 sub c
2b96 300c jr nc,&2ba4 ; (+&0c)
2b98 2f cpl
2b99 3c inc a
2b9a 4f ld c,a
2b9b 7c ld a,h
2b9c cd002b call &2b00 ; update crc
;; write a high level
2b9f 2e0b ld l,&0b ; %00001011 = set bit 5 (cassette write data)
2ba1 cda72b call &2ba7
2ba4 3e01 ld a,&01
2ba6 c9 ret
;;=====================================================================
;; write level to cassette
;; uses PPI control bit set/clear function
;; L = PPI Control byte
;; bit 7 = 0
;; bit 3,2,1 = bit index
;; bit 0: 1=bit set, 0=bit clear
2ba7 ed5f ld a,r ;;<<<<<<<<<<<<<<<<<<<<<<< A,R <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2ba9 cb3f srl a
2bab 91 sub c
2bac 3003 jr nc,&2bb1 ;
;; delay in 4us (16T-state) units
;; total delay = ((A-1)*4) + 3
2bae 3c inc a ; [1]
2baf 20fd jr nz,&2bae ; [3]
;; set low/high level
2bb1 06f7 ld b,&f7 ; PPI control
2bb3 ed69 out (c),l ; set control
2bb5 f5 push af
2bb6 af xor a
2bb7 ed4f ld r,a ;;<<<<<<<<<<<<<<<<<<<<<<< R,A <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2bb9 f1 pop af
2bba c9 ret
need to delete to rework
;********************************** Read Byte
; OUT: A: Byte
; CY=0 for error
; A: Error number
29B0 D5 PUSH DE
29B1 1E 08 LD E,08 ; Counter for 8 bits
29B3 2A CE B8 LD HL,(B8CE) ; Time limit/edge flag
29B6 CD D4 29 CALL 29D4 ; Wait for 1st edge of the bit
29B9 DC DD 29 CALL C,29DD ; Is it okay? Wait for 2nd edge
29BC 30 0D JR NC,29CB ; Error?
29BE 7C LD A,H ; Time counter limit
29BF 91 SUB C ; Subtract current time counter to get bit
29C0 9F SBC A ; A=$FF for 1-bit
29C1 CB 12 RL D ; Rotate bit into byte
29C3 CD 90 29 CALL 2990 ; Set check-w. according to bit
29C6 1D DEC E ; Bit counter
29C7 20 EA JR NZ,29B3 ; More bits?
29C9 7A LD A,D ; Read byte
29CA 37 SCF ; CY=1 for no error
29CB D1 POP DE
29CC C9 RET
;********************************** Wait for next edge, ESC t.
; IN/OUT: L: Edge flag
; L=$55 for negative edge
; L=$AA for positive edge
; (OUT for the other edge)
; OUT: C: Time counter
; CY=0, Z=1, A=0 for abort
; CY=0, Z=0 for error then: A: Error number
29CD 06 F4 LD B,F4 ; PIO, Port B
29CF ED 78 IN A,(C) ; Keyboard feedback of the 8th row
29D1 E6 04 AND 04 ; Isolate ESC bit
29D3 C8 RET Z ; ESC pressed?
;********************************** Wait for next edge
; IN/OUT: L: Edge flag
; L=$55 for negative edge
; L=$AA for positive edge
; (OUT for the other edge)
; OUT: C: Time counter
; CY=0, Z=0 for error then: A: Error number
29D4 ED 5F LD A,R ; Time since last edge
29D6 C6 03 ADD 03
29D8 0F RRCA ; Generate corresponding time counter value
29D9 0F RRCA
29DA E6 1F AND 1F
29DC 4F LD C,A ; Put it as time counter into C
;********************************** Wait for 2nd edge in the bit
; IN/OUT: L: Edge flag
; L=$55 for negative edge
; L=$AA for positive edge
; (OUT for the other edge)
; C: Time counter
; OUT: CY=0, Z=0 for error then: A: Error number
29DD 06 F5 LD B,F5 ; PIO, Port B
29DF 79 LD A,C ; Time counter
29E0 C6 02 ADD 02 ; Increment
29E2 4F LD C,A ; Set again
29E3 38 0E JR C,29F3 ; Carry? Then time is too long -+
29E5 ED 78 IN A,(C) ; Load input bit from cassette |
29E7 AD XOR L ; Invert depending on edge flag |
29E8 E6 80 AND 80 ; Isolate input bit |
29EA 20 F3 JR NZ,29DF ; Not the expected level? ----+
29EC AF XOR A ; Reset time counter |
29ED ED 4F LD R,A ; Reset register |
29EF CB 0D RRC L ; Edge flag for next edge |
29F1 37 SCF A ; CY=1 for no error |
29F2 C9 RET |
;Error Handling |
29F3 AF XOR ; Reset time counter <---+
29F4 ED 4F LD R,A ; Reset register
29F6 3C INC A ; Error number = 1, CY=0
29F7 C9 RET
;********************************** Output byte
; IN : A: Byte
; OUT: CY=0 for error; A: Error number
29F8 D5 PUSH DE
29F9 1E 08 LD E,08 ; Counter for 8 Bits
29FB 57 LD D,A ; Byte
29FC CB 02 RLC D ; Next bit
29FE CD 08 2A CALL 2A08 ; Write to tape
2A01 30 03 JR NC,2A06 ; Error?
2A03 1D DEC E ; Bit counter
2A04 20 F6 JR NZ,29FC ; More bits?
2A06 D1 POP DE
2A07 C9 RET
;********************************** Write bit to tape
; IN : CY: Bit
; OUT: CY=0 for error; A: Error number.
2A08 ED 4B D0 B8 LD BC,(B8D0) ; Previous time value/correction value
2A0C 2A D2 B8 LD HL,(B8D2) ; Main time value to L
2A0F 9F SBC A ; A=$FF if 1-bit
2A10 67 LD H,A ; Save for check-word
2A11 28 07 JR Z,2A1A ; Bit=0?
2A13 7D LD A,L ; Otherwise, main time value
2A14 87 ADD A ; *2 as 1-bit is twice as long
2A15 80 ADD B ; Add correction value
2A16 6F LD L,A ; As time value
2A17 79 LD A,C ; Time value of the previous bit
2A18 90 SUB B ; Subtract correction value
2A19 4F LD C,A ; Reset
2A1A 7D LD A,L ; New time value
2A1B 32 D0 B8 LD (B8D0),A ; Save for the next bit
2A1E 2E 0A LD L,0A ; Port C b5 (WR DATA) cleared
2A20 CD 37 2A CALL 2A37 ; Delay and output
2A23 38 06 JR C,2A2B ; No error?
2A25 91 SUB C ; Error time-original time value
2A26 30 0C JR NC,2A34 ; Error time too large?
2A28 2F CPL ; Original time value-error time
2A29 3C INC A ; (Magnitude of the difference)
2A2A 4F LD C,A ; Set as new time value
2A2B 7C LD A,H ; Flag for 0/1-bit
2A2C CD 90 29 CALL 2990 ; Set check-word according to bit
2A2F 2E 0B LD L,0B ; Port C b5 (WR DATA) set
2A31 CD 37 2A CALL 2A37 ; Delay and output
2A34 3E 01 LD A,01 ; Error number for "Write error a"
2A36 C9 RET
;********************************** Output next half wave
; IN : L=$0A for negative edge
; L=$0B for positive edge
; C: Time value
2A37 ED 5F LD A,R ; Divide refresh counter by 2
2A39 CB 3F SRL A ; Subtract desired time value since the last half-wave
2A3B 91 SUB C ; Has the time already elapsed?
2A3C 30 03 JR NC,2A41 ; If not, remaining time
2A3E 3C INC A ; Otherwise, remaining time
2A3F 20 FD JR NZ,2A3E ; Delay
2A41 06 F7 LD B,F7 ; PIO, Control register
2A43 ED 69 OUT (C),L ; Set/clear Port C/b5
2A45 F5 PUSH AF ; Error flag
2A46 AF XOR A ; Reset time counter
2A47 ED 4F LD R,A ; Reset register
2A49 F1 POP AF ; Error flags
2A4A C9 RET
Okay, I checked a very good german fully commented ROM listing for the CPCs. The addresses are different (because they do the full comment on the 464 and only comment on differences for the other two models), but that is the exact same function.
So this is the tape read and write routines and R is used as a counter for correct timing.
This is only possible because the CPC never uses anything the R register contains, so they can use it as a counter.
So they set it to 0 (reset operation as in 29ED) and then use it as a counter.
The only thing they need to achieve is, that both edges are the same time. So they use R to have a counter. As they are running the same code, it will have the same time IF the signal from tape is correct.
How does it work:
The start to wait for an edge (which is a change of signal).
Then they reset the timer
Then they wait for the next edge and store the time (LD A,R)
Then they reset the time
Then they wait for the next edge.
This is one bit. And the edge timer is pretty much constant during that operation, however each bit sets the timings new. So the duration of a high and low flank is recorded.
That is important, as a high bit only takes half the time of a low bit. (the Pulse frequency is exactly 2x for high to low).
It would appear they are using the R register as a timing control. This makes sense as it is normally unaffected by anything external to the Z80, also the 1/300th interrupt is seen as insufficient for timing to be used for speedy bit transfers.
Think about that as at 1/300th interrupt only allows for 300 bits/sec where as using the R register could get a far high bit rate.
except that R doesn't tick tok evenly.
Quote from: McArti0 on 00:50, 16 March 24except that R doesn't tick tok evenly.
No, but it does tick predictably, especially if interrupts are disabled (as I assume they would be while tape loading). If you know what instructions are executing, R is a viable timing mechanism for something like this.
Quote from: McArti0 on 00:50, 16 March 24except that R doesn't tick tok evenly.
That is true, but does not matter in this particular example, as a tick is running the code segment and a tock is running the same code segment again. So this is both the exact same commands in exact same order, so the time of both code segments will be the same.
But R is not good as a universal timer. You either need to count cycles and then ensure that both are the same with the same number of M1 cycles, or as in here, have the exact same code run again.
The more I read the ROM comment, the more I am impressed on what those guys have achieved.
Is it actually known how has written the ROM?
This article on The Register gives a lot of detail about all aspects of development.
https://www.theregister.com/2014/02/12/archaeologic_amstrad_cpc_464/
Quote from: Bread80 on 12:51, 17 March 24This article on The Register gives a lot of detail about all aspects of development.
https://www.theregister.com/2014/02/12/archaeologic_amstrad_cpc_464/
Thank you for this interesting article. It slipped on my by now.
I am thinking of archiving it to archive.org. Reaching out to the register