jac_goudsmit wrote:
Hi cbmeeks,
Can you elaborate on what exactly you want to do? It sounds like you're trying to make this unnecessarily complicated by using the address bus for signaling. It's probably much easier to just let the 65C02 run a program that e.g. reads a byte from a location that your MCU catches, and then writes that byte into memory. You could use the SOB pin and the BVS instruction on the 65C02 to let it know that it received the last input from the I/O device (the MCU).
Sure, I'd be glad to. I'm still toying with ideas for an expansion card for the L-Star. My first instincts are always audio/video. So I was thinking of having an external Propeller that drives them both using some video drivers I have. The external Propeller would act as a dedicated video buffer (sorta like the TMS9918) of 8-16K of video RAM. It would draw an image from its internal RAM. The host computer (L-Star) would send commands to the card for changing video RAM, drawing chars, etc. I realize this is usually slower than direct DMA. The TMS9918 suffered the same way. But there are things you can do to get around it. Plus, if the video generator had internal commands to do complex work (sprites, etc.) then it would be just a few commands from the host to do some complicated things. Like a display list for Atari or copper list for Amiga. So I didn't want the 65C02 sending a constant stream of data for anything. It needs to "set and forget". This applies to audio too. My idea was to implement an SD card on the expansion board. This card could contain a list of VGM files (video game music). The host sends a few simple commands to the expansion ("play castlevania.vgm") and the expansion Propeller would stream the music from SD while the host can do other things. Imagine playing around with Krusader while chiptunes are playing. All on a nice, color NTSC or VGA screen.
So the problem I was trying to solve was:
1) Efficiently communicate with expansion Propeller by sending commands (like the 65C22)
2) Re-route video through the expansion board.
3) No modifications to the L-Star other than using the built-in jumpers. Preferably no jumper wires either. I know the L-Star is a hobbyist computer. But the fun for me is treating it like it is an Apple I rolling off the assembly line and I'm building expansion cards for it.
I didn't mention that I would disable the L-Star video and take that pin to control RAMEN. Because video would be hosted by the expansion board. Once I can communicate with the expansion board Propeller, the sky's the limit.
jac_goudsmit wrote:
The 65C02 controls the address bus at all time, even when you hold the clock low, so you can't use the address pins for signaling (unless you use BE to take the 65C02 off the address line). However, during Phi1 (i.e. whenever the clock is low), the 65C02 doesn't use the data bus, so you can stop the 65C02 and use the data bus to communicate between two microcontrollers. You can make this wicked-fast by implementing a smart protocol that uses all 8 data bit lines at the same time (but half-duplex, so while one MCU writes, the other one reads). Depending on which MCU you use, you could probably transfer several megabytes per second this way, but it's probably difficult to implement. Alternatively, you could simply use a known protocol such as SPI or I2C or RS-232 to communicate data between the MCUs over the data bus while the 65C02 is "parked" with CLK0 low.
Ah, that's some good advice. I didn't realize that about the address bus. I knew the BE pin was the "proper" way to do it. But, I don't see that the BE pin is exposed easily with the L-Star.
Utilizing the data bus, I could probably come up with a protocol that allowed the host/expansion to send data back/forth that way.
jac_goudsmit wrote:
When the 65C02 is stopped in Phi1 (CLK0 low), it really doesn't care what happens on the data bus. But you can't manipulate the address bus for communication because it's always under control of the 65C02. You will damage the 65C02 if you try to override the address bus.
I am curious on how the Apple II did it, however. I know the video controller used the RAM during the PHI1 (LOW). But wouldn't it have to change the address bus to get the video data?
jac_goudsmit wrote:
If you want to have the data bus available to you, it makes most sense to stop the clock when it's in low state, yes.
The difficult part of stopping and restarting the clock is that you have to make sure that the last pulse (before stopping) and the first pulse (after restarting) are long enough.
Ah, good point.
But...assuming 1 MHz, that is 500ns per half-cycle. So if I were 20ns into the LOW half-cycle or 400ns into the HIGH half-cycle, could I not stop it indefinitely if I wanted to? I mean, how would the CPU even know? I've always thought of the clock as time and by stopping it, the CPU has no notion of time anymore.
Oh, wait...I think I see what you're saying....
So if I was 20ns into the LOW half-cycle, I would need to make sure when I started the clock back up, I would run another 480ns at LOW right?
Like:
Code:
LOW --> 20ns * STOP CLOCK...DO LOTS OF WORK * Finish LOW with 480ns HIGH....
___________ ____________________|----------
Is that what you mean?
jac_goudsmit wrote:
The current L-Star firmware doesn't bother to do this correctly, .....
I would more than likely re-write the clock code.
jac_goudsmit wrote:
The RAMEN pin is not on the expansion port. It wouldn't do you any good to monitor it anyway, because the code that controls it (which doesn't exist yet) will monitor the clock pin. During normal operation, the RAM chip will only be enabled during Phi2. So if you stop the clock, RAMEN will not become active and the RAM chip will stay off the data bus.
Here is how I thought I would handle that.
1) Disable L-Star video and connect the pin to RAMEN
2) Host (L-Star) starts up and disables external RAM.
3) Host "disables" 65C02 by either not starting the clock or holding the clock LOW.
4) Host enables RAM and sends ROM images from EEPROM to RAM. So ROM is now RAM (which I'm fine with).
5) Host enables 65C02...perhaps forces the fake reset or something to kick start it on the external RAM which now contains Krusader, Woz, etc.
Now, how will the expansion board Propeller know the host is sending commands to it? It it monitors P25 (which *is* on the expansion port) for a transition to HIGH, then it knows the host has disabled the external RAM. One drawback to this is during the boot-up when the host holds the RAM high for a bit. Not sure how I would handle that just yet. Perhaps a small delay on the expansion board Propeller of a few milliseconds.
jac_goudsmit wrote:
The RAM chip control code (which, again, I still have to write), will make it possible to do DMA (which I think is what you're trying to do) by making it possible to enable the RAM chip for certain addresses during Phi1, and feeding STA <absolute address> instructions to the 65C02. Then all your MCU would need to do is put the data on the data bus at the right time, and wait until the clock goes high. This is all a bit "up in the air" but it will work when it's done, and it'll be documented in the source code. The module will probably be called RAMcontrol.spin, so if you see it on Github, that's probably the module you want to read.
That is pretty much what I want to do. DMA. However, I'd like the idea of running the host faster. Perhaps 2-4 MHz which we're not going to be able to do with memory.spin. So certain I/O operations would have to slow down the CPU by doing things like stopping or slowing the clock down. IMHO, this was quite common back in the day. The TMS9918 was slower than many systems that used it. But, since it could run independently of the host, certain things really benefited from it. So if my expansion board can run independently of the host, only slowing the host down when it needs certain commands, I could then do a ton of cool things.