Wednesday, January 6, 2010

Adventures in LPT - Part II

In the last post, I mentioned the XE1541 cable and the fact that it can be used to connect the C64 to a PC, where an emulator runs on the PC and through the LPT acts like a C64 disk drive. This is a pretty cool idea...but to do so, I'd either need to download someone else's emulator, or write my own.

Most of the emulators around now have a couple major flaws that I just can't live with: the free ones are DOS (I'll get into why later), and most of them only have the most basic implementations of the 1541's DOS. Pretty much all they allow are use of the C64's kernal LOAD and SAVE commands, and sometimes they can load a .d64's table of contents to the C64's BASIC memory (thus allowing one to display them on the machine with a LIST command). That's just not enough. If I really want to utilize the C64's hardware, I'm gonna need something that at least supports a basic IRQ loader.

For those of you who don't know, an IRQ loader is a C64 routine that allows data to be loaded into RAM from a disk drive while other things are happening on screen. This is extremely valuable for demos, since one effect can be playing from one chunk of memory while another effect or picture is loaded into a different part of memory, almost simultaneously. EXTREMELY cool :) . 

The fact is, I want a freely-available, Windows-compatible, cycle-exact 1541 emulator. So, I'm making my own :) . Which means I need to figure out how all this works...the connections, how each piece of hardware is supposed to act and when, pinouts, the LPT, and more. This should be fun :) .

Well....I have a confession to make. That last paragraph said I have to figure it all out, as if I hadn't done so...now, that's not entirely true ;) . I HAVE actually done quite a bit of research into the topic (but that was probably obvious in the last post, hehe).

To start, let's talk about the LPT.

This is a DB25 parallel port. It has 8 data lines (input/output), 4 control lines (output), and 5 status lines (input). Though I'll admit the pinout isn't completely logical, it's still a pretty simple port to use and understand. Here's a pretty simple picture of the port and its pins:




Note that the unlabeled green pins are all ground lines, and I'll get to what "D", "S", and "C" stand for in a moment. As you can see, though some of the pins seem out of order, this is an incredibly easy port to design hardware for. "High" voltage always runs at (with negligible error of course) +5v, so an average LED is safe with just a 100kΩ resistor, and most MCU's are safe at this voltage even without any resistors at all. 

So, this port is simple to wire...but what about programming? The "D" from earlier stands for "Data". These lines make up an 8-bit input/output port. the "S" stands for "Status"; a 5-bit input port. Finally, the "C" stands for "Control"; a 4-bit output port. But why these names?

Remember, the port is called "LPT" - Line Print Terminal. This is a printer port. The PC sends the printer a command over the control lines, then the printer sends its status back in the status lines, and they transfer data to each other in the data lines. OK, that's pretty simple...but still doesn't explain how to code the dang thing.

Well, it's remarkably simple. Each LPT in a machine (on normal PC's, usually 1 is present, and sometimes 2) has a base address which can be read from the system's BIOS from address 0000:0408. This points directly to the data register. The byte after that? The status register. And the one after? Yup, you guessed it - control register. 

Fun fact: the serial COM ports' addresses reside at 0000:0400. 

Now, we could always be safe and read these whenever we want to use the port, but c'mon. Unsafe is always more fun :D !! See, in almost every currently-used computer LPT1 resides at 0000:0378, and LPT2 at 0000:0278. This means that in pretty much every case we'll encounter, our data register for our port (we'll assume we're gonna use LPT1) is at 0000:0378, status at 0000:0379, and control at 0000:037a. Awesome :) We'll use those.

Only one problem - since the release of Windows NT, direct access to these ports has been banhammerred for security reasons.

Ouch.

This is why most emulators are written for DOS (told you I'd mention it later). But I want WINDOWS. WINDOWS!!!

So, we need a kernal mode driver. Once again - I either find a free one online, or a write my own. Luckily though, in this case, the guys at http://logix4u.net have developed the perfect .dll to get around this issue: Inpout32.dll. This .dll has a pretty simple architecture: on load, it checks if we're running under Win9x. If so, no driver is necessary. Otherwise, it automagically installs a very lightweight driver itself and directs all port processes through that. The only change then to the code is to use this .dll instead of direct writing to the ports. This sent a red flag in my head: SLOW BLOATWARE ALERT. But nope!! These guys did quite well. The source code to both the driver and the .dll are included in the .dll package. A quick glance at the [very clean] C code reassurred me that this is a great .dll :) . Awesome work, guys.

So now I have a simple way to code for the port and I have the pinouts. What's next? I'll tell you: my first real soldering project!!

I decided I'd make a little board to test the port :) Nothing too fancy...just need to display the control register with 4 LED's and wire 4 switches for the status register tests. Awesome :) .

Now, you may have noticed that I didn't include the data register or the 3rd status bit...this is because the XE1541 doesn't use these...not only that, but it made the project more lightweight and easier to build. The concepts are the same so I figured no extra work was really necessary. Besides, until my actual cable arrives from Europe (I ordered it on Dec. 27th, my birthday hehe), this should be more than enough to hold me off.

I took a trip to Radio Shack and bought myself a wonderful little soldering iron, solder, a male DB25 connector, a basic printed circuit board, and some helping hands. The rest of the stuff I had around since I like to play with a breadboard :) . I then did a YouTube search to find out how to solder, and sure enough, found this wonderful video, which was all I needed:




Wonderful :) Anyways, I'm rambling quite a bit, so I'll just post some pictures of the project. Sorry for the crappy quality, too...took them with my cell phone:



 
 
 
 
 

So, yeah :) . Not too complicated, in fact ridiculously simple...but I had tons of fun making this :) . Now, I must admit, I'm pretty tired, so I should head to bed...next time I'll talk about programming and testing this little bugger :) .

Goodnight!

0 comments:

Post a Comment