Ruud's Commodore Site: PC-Flop Home Email

PC-Flop




What is it?

Remark in advance: this project is the ancestor of 1541LPT, No more floppies anymore!, so some text and ideas will look familiar.

PC-Flop is a project where I am going to use a PC as a hard disk drive for the C64, C128 and VIC-20 and other IEC-computers using a 1541 as an interface. As a small bonus you can use the CD-ROM, 1.44 MB-drive and network-drives of the PC as well!
Products: software, a cable and a modified 1541-board.


The story

Marko Mäkelä, Frank Kontros, Andre Fachat and I exchange a lot of ideas and one day I suggested to build a small 6502-machine as an interface between the PC and the C64 to let GEOS think it is dealing with an real 1541 or other drive. Marko (or Andre ?) replied that I should use an old 1541-board instead, it would save me a lot of soldering.


Theory

To understand how the 1541 transfers data to/from the floppy disk, you can read this document . The 1541 uses a 6522 (UC2) to transfer data from/to the head of the drive and to steer the stepping motor. This 6522 is as far as a programmer can go. The idea is to remove the mechanical part and the connected electronics and to connect the I/O-lines of the 6522 with the printer port of a PC instead. The PC now must emulate the parts we removed: it must read the data send by the 6522 and store it, and it must send stored data to the 6522 as if it was coming from a real floppy.

This can only be done when the PC handles/emulates the "handshake" signals in the right way. I use the word "handshake" by lack of a better word.
The first thing a drive does when a command is given is to read the track where the head is above. The PC can detect this because PB2, motor on/off, becomes active (H). As you know, the original 1540 and 1541 have no "track 0"-detector. It detects the track where the head is above by reading the first header off a sector it "sees" because the header contains this information. If it doesn't read anything, then the "famous" head-bumping occurs because the floppy thinks the mis-reading could be caused by a wrong alignment of the head. My idea is anyway to let a drive think that, after powering up or "changing" the floppy, the head is above track 18.
If the drive wants to change the track, it does this by changing the outputs PB0 and PB1 like 00, 01, 10, 11, 00 etc. when increasing the tracknumber and changing the values in the opposite way when decreasing the tracknumber. The head is above a track when PB0 = 0. This means that the drive needs two steps to change the track. We will come back to this matter when discussing "Copy protections". The PC only has to detect the changes of both PB0 and PB1 and act on it as needed.

The PC must start reading and storing data the moment it detects CB2 is (L). If the byte has been stored it must signal this to the drive by negating the "Byte ready"-line towards CA1 and the SO-input of the processor. Normally the drive needs 26 to 32 usec to write the info away. The needed time depends on the track where it is on. After receiving the "Byte ready"-signal the processor outputs a new byte to port A of the 6522. I do not know how much time this will take but with the help of the following disassembly it can be calculated:
B_F5BF  LDA     (BUFPNT),Y              6
  
B_F5C1  BVC     B_F5C1                  3
  
        CLV                             2
        STA     PortA2                  4
        INY                             2
        BNE     B_F5BF                  3
                                      ----+
                                       20
The above is a part of the procedure to write a complete datablock to the floppy disk. The numbers behind the text is the number of cycles this instruction needs to be executed. As you can see the total is 20. We have to wait at least this amount of time plus some reserve. We also can see that it takes up to 11 cycles before the new data is outputted to the port.

When reading data the opposite happens:
B_F4D4  BVC     B_F4D4
  
        CLV     
        LDA     PortA2         STA     (BUFPNT),Y
        INY     
        BNE     B_F4D4
Again the 6502 needs at least 20 cycles to read a byte.
Notice that the 6502 immediately resets the overflow flag after detecting it has been set. This is possible because the SO-input is edge sensitive. For the same reason the PC can set the signal immediately after it had been negated.
Remark: From now on the handling of the "Byte ready"-signal is included when I mention reading or writing a byte from/to port A. As we have no handshake from the drive to signal that it is ready to write/read the next byte, we must respect the timing mentioned above.

We'll now discuss all actions the drive can perform on a disk:
  • Positioning the head
    The drive moves the head by changing the values of bit 0 and 1 of port B of the 6522. Counting up moves the head inwards to a higher track, counting down to a lower track. The only thing the PC has to do is react accordingly to the behaviour of these two bits.

    Formatting a disk is another matter. The drive seeks the first track using the "famous" bump-action. The reason for this is that, with exception of the 1541C, the drive does have no means to detect if the head is above the first track. The bumping is caused by the fact that the drive performs 90 steps (= 45 tracks) outwards. So on whatever track the head was positioned before, it always ends up at track 1.
    The only way the PC can find out that a BUMP is going on is that at a certain moment during this action its internal trackpointer will count down to zero and we all know that track 0 does not exist. The only thing the PC can do now is keeping the pointer pointing to track 1 and to wait for the 1541 to stop counting down.
  • Formatting the disk
    A disk is formatted by formatting the tracks one by one. The first thing the drive does with a track is writing 10240 times a SYNC-char (= $FF) to it. Can a track contain 10240 bytes? No.
    Spinning at 300 RPM it means one track is 200.000 uSec long. For track 1 this means 200.000 / 26 = 7693 bytes. For track 35 this means 200.000 / 32 = 6250 bytes.
    With writing 10240 bytes the drive can be very sure that the complete track has been overwritten. (Or you must have a drive that turns at 225 RPM or slower) The next step is writing another 4000 SYNC-chars and then 4000 times $55. This last action surely overwrites some of the SYNC-chars. (Unless your drive is slower then 289 RPM) The drive now starts to count the bytes of both actions. If the result is too low (drive is too slow) an error will occur. It then starts to calculate the gap between two blocks of data (incl. the header). I studied the source but until now it is not clear to me how the gap is calculated and how big it will be for every track. I only know that the size depends on the found result mentioned above. And this number depends on the speed of the drive !!!
    The only thing the PC has to do is to create an array of 7692 bytes. It simply starts writing the data into the array from the point the bytevector is pointing to (actual point is not important now). The moment the vector reaches the maximum number of bytes the track can contain (7693, 7143 6667 or 6250), it starts with byte zero again. Once the 1541 has calculated the gap, it starts writing the sectors. But where should the PC start writing the new sectors? At that point the bytevector is pointing to !!! You simply don't know what and why the drive is writing data to the floppy. The result can be that the start of sector 0 is somewhere in the middle of the array. When the drive changes track, the PC only has to change the array, NOT the bytevector!

    Where should the bytevector point to after changing a track? IMHO that doesn't matter. The 1541 hasn't a "sector 0"-detector as PC-floppies do. So during the formatting process, the creations of the sector on a track starts at that point where the head is at that moment. This moment depends on how much time was needed to write the previous track, which depends on the total size of that track, which depends on the size of the gap between two sectors, which depends on the speed of the drive. And as a drive is a mechanical thing, you can bet on it that the speed differs for all drives. This simply means that the alignment of two sectors of different tracks may be the same for two floppies formatted on the same drive but probably will differ for floppies formatted on different drives.
    Remark: When changing track to the inside, the bytevector can have a value greater then the maximum value for that track.
  • Writing data
    The only thing the PC has to do is to feed the content of the array to port A at an interval of 26 uSec. But where should it start reading? If the drive is looking for a specific sector, it simply starts reading all the headers of the sectors until the sector is found. The header of a sector also contains info about the track where it is on. So if the drive finds out that it is on the wrong track, it has to go to the right track first. Starting the drivemotor, moving the head, all these actions cost time. So there is no logic in what sector the drive will find first. So IMHO the PC can start feeding the drive with data starting from the first byte of the array. Remember: the beginning of the array is not necessarily the beginning of the track.
  • Reading data
    The only thing the PC has to do is to read the bytes from port A and to write them into the array at an interval of 26 uSec. Period.

Copy protections

At this moment I only can think of six types of copy protection that can be used on a disk:
  • Writing own data to the disk
    Using ML you can send your own data to port A to be written on the disk. In this way you can write patterns to a track in such a way that the Kernal won't recognize them as sectors or whatever. In this case the drive will return read error to the host. IMHO this is no problem for PC-Flop. As I already stated above: "Store what port A is giving. Don't think about it, just do it!". So whatever data is received, it will be returned in the same way.
    Still one funny problem can occur. Sending data to port A you have to take care of one thing: don't use more then three zeros in a row !!! Four zeros, 0000, will be read as 0001. That is, if you're were dealing with a real 1541. With no precautions, PC-Flop will return 0000. The only way you can avoid this is scanning the data and adjusting the data after everything has been stored. The funny thing about this phenomena can only be used as a copy protection against PC-Flop as it has no use at all on whatever 1541.
  • Using half-tracks
    The half-tracks are the tracks between the normal tracks. Or technical spoken, the tracks where the head is above the moment bit 0 of port B is 1. Why doesn't the drive use these tracks as well because it could double the capacity of the drive? The reason is that when using half-tracks as well, the tracks would overlap each other. Reading such a track is a guarantee for faulty data. But on the other hand, there is nothing against formatting track 1, 2.5, 3.5 and 5, and putting valid sectors and data on it. The only thing is that the unprepared 1541 most likely will produce read errors for the tracks 2, 3 and 4.
    What does this mean for PC-Flop? Once you know half-tracks are used, you have to reserve an array for every step of the stepping motor. At the moment I'm thinking about a scheme which automatically takes care of half-tracks if needed.
  • Shifting tracks
    This means that the drive first reads a track to find a certain pattern and, once found, switches to another track to write a pattern there. When the software is used, it first looks for the first pattern. Once found, it switches to the other track. The pattern the software will read now should be the second pattern.
    The protection lays in the fact that if you want to copy the disk, you need a copyprogram that is capable of copying a track bit for bit but also is capable of aligning the tracks in the same way as the original disk. The bit copying is needed because you don't know at what place the second pattern has been written to. If it was, for example, written over the header of a sector, a normal copy program won't be able anymore of finding this sector ie. copying it.

    At this moment the only means of aligning tracks that the PC has is not changing the bytevector during the moment the drive changes track. IMHO this should be enough to handle this type of protection. Comment on this statement is welcome !!!
Copying an already existing floppy is a different matter. There are two solutions:
  • A software solution: we need a program that copies the tracks bit by bit and determines the alignment. But I foresee problems programming the whole thing because one part has to run in the drive and one part in the host computer.
  • a hardware solution: we connect a cable to the 6522 and read the tracks parallel to the 6522 using bigger arrays capable of storing at least a track twice. During changing the track we store the pointer as well. Once the whole floppy is read, the PC can do the analyzing. The only program needed for the 1541 is one that moves the head from track 1 to 35 (or more) while waiting a second above every track. Nothing else, even any reading!.
  • Changing the clockfrequency
    As already stated in this document about the 1541 , the drive places the data with an higher frequency on the outside surface of the disk then on the inside surface. Writing the data with an altered frequency causes errors when reading it with the normal frequency. Writing 101... at slow speed will be read as 11... at high speed; the 0 is not detected.
    Because we don't use/need this mechanism at all, it won't trouble us.
  • Using more tracks
    The 1541 only uses 35 tracks but an external PRG can address up to 40 (maybe more ???). The reason why Commodore choose not to use 40 tracks is unknown to me. Anyway, there are programs that can use these extra tracks. For most of them it is not meant as a copy protection but this part of the document seemed to be the most suitable to discuss it.
    The only consequence for the PC is that it has to store more data/arrays. That's all.
  • Intentionally physical damage
    This is a very interesting way of copy protection. The program writes data to the place that is damaged. When reading from this place, it expects anything but the written data back. But the surface of the copy disk is most likely NOT damaged at this particular spot and so the program will read the data it just has written!
    But this kind of protection is very rarely used. I myself only heard of one case. The reason for this is probably that there is a lot of work involved in the preparation of the disk.
    This kind of protection can be emulated by telling the program what part of the disk to treat as read-only.

Realization

The only thing we have to do is to place two extra sockets between the 6522 and its original socket. All pins are connected to each other by means of soldering with the exception of:
  • PA0..7 (pin 2..9, bidir.): used to transfer data
  • CB1 (pin 18, in): not used by the drive, connect to +5V through 10K resistor for future use.
  • CB2 (pin 19, out): direction of the data (H: read, L: write)
  • PB0..1 (pin 10..11, out): lines to steer the stepping motor
  • PB2 (pin 12, out): motor on/off
  • PB4 (pin 14, in): write-protection detector
  • PB5..6 (pin 15..16, out): lines to select density
  • PB7 (pin 17, in): synchronisation-byte detected
  • CA1 (pin 40, in): byte ready
  • CA2 (pin 39, out): disable SO-input of 6502

As you can see there are 8 bi-directional lines, 7 outputs and 3 inputs. PB5 and PB6 influence the density of data on the floppy and, IMHO, can be neglected for our purposes. This means we have 5 outputs to deal with. A bi-directional printer port of a PC has 8 bi-directional lines, 5 inputs and 4 outputs. As you can see this makes a nice match.
The second step is to connect a male 25 pins D-connector to the free pins of the upper socket. This connector is used to make the connection with the LPT-port of the PC and is wired like this:
                6522                                    LPT
        Name    Meaning pin                     name            pin
        ----    ------- ---                     ----------      ---
        PA0              2                      D0               2
         .                                       .
         .                                       .
        PA7              9                      D7               9
  
        CA1     BRDY    40                      Strobe           1  (O) 
        PB7     SYNC    17                      Auto feed       14  (O) 
        PB4     WPE     14                      Initialize      16  (O)   
        PB0     Stp1    10                      Select          13  (I) 
        PB1     Stp0    11                      Paper out       12  (I) 
        PB2     Mtr     12                      Acknowl.        10  (I) 
        CB2     Mode    19                      Busy            11  (I) 
        CA2     SOE     19                      Error           15  (I)   
        CB1             18                      Select out      17  (O)   
  
3BC,378,278 = Printer data
3BD,379,279 = Printer status
bit 0 = not used
bit 1 = not used
bit 2 = not used
bit 3 = error (15)
bit 4 = select (13)
bit 5 = paper end (12)
bit 6 = acknowledge (10)
bit 7 = busy (11)
  
3BE,37A,27A = Printer control
bit 0 = strobe (1)
bit 1 = autofeed (14)
bit 2 = Initialize (16)
bit 3 = select out (17)
bit 4 = enable IRQ7
bit 5 = data port direction
bit 6 = not used
bit 7 = not used
  
Control after reset:  $CC
Between the 74LS174 (= Printer control port) and the Strobe-pin (1) at the connector you'll find a 74LS05 open-collector inverter. This is the same for Autofeed (14) and "Select out" (17). For Initialize you'll find two 05-inverters. Combining this info with the fact that the byte $EC is written to the controlport results in the fact that the inputs CA1, PB4 and PB7 all read a 1. CB1 will read a 0.


The software

Unless we expand, the rest is only a matter of software on the PC.

Under
Giving the appropriate commands to the PC can 'change' the floppy. In this case a change of the Kernal or a major change of the hardware of the 1541 is not needed. But my idea is to use a stand-alone PC at the end so the next step is to add some commands to the Kernal.


Testing everything

At this moment everything is purely theoretically. To make sure that my theory is according the reality, I have to see first how a live drive uses the above mentioned signals. For this I need three extra inputs ie. a second printer port.
                6522                                            LPT
        Name    Meaning        pin                     name            pin 
        ----    -------        ---                     ----------      ---
        CA1     BRDY            40                     Acknowl.         10  (I)
        PB7     SYNC            17                     Busy             11  (I) 
        PB4     WPE             14                     Paper out        12  (I) 
What now has to be done is writing some software that scans the bus continuously.

In case we want to expand the Kernal with extra commands, we need to expand the onboard (EP)ROM and RAM. This is described below in separate parts.


We need more ROM

If we want to use a stand-alone PC, we must be able to command it in one or another way. This means we must use the 6522 in a way that is not provided by the standard Kernal of the 1541.
This could be archived by executing a small program in one of the buffers. The disadvantage of this procedure is we first have to load this program from disk. This does mean that this program has to be available on every "floppy" on the PC otherwise we are not able to change "floppies" anymore.
The more logical step is to change the Kernal. IMHO the only thing we need to change is the command-interpreter. And I'm very sure this can be done with maintaining 100% compatibility.
Adding more commands means we need more ROM. There are 256 bytes free in the range $C000/$C0FF but I don't think that this will be enough. My idea is to replace both onboard ROMs with one 32 KB EPROM like the 27256. This gives us an extra 16 KB of EPROM to be filled with our own programs.


We need more RAM

At this moment I don't know if I need more RAM. But expanding the 1541 with 2KB of extra RAM is simple and the 1541 will still be 100% compatible.
The only thing we have to do is to add one AND-gate and a 6116, 2016 or equivalent 2K*8 RAM. The last one can be piggybacked on the original one: all pins are soldered with the exception of pin 18, the chip select-input. For the AND-gate we need a 74LS08 that can be piggybacked upon another TTL-IC with pin 14 and 7. The output of the AND-gate is connected to the previously mentioned CS-input. The inputs of the AND gate are connected to pin 13 and 12 of the onboard 74LS138. In this way the new RAM is mapped from $0800 to $0FFF.


Emulating more drives

Another idea is to have the possibility to assign more then one devicenumber to the 1541. But every device needs its own 2KB RAM starting at address $0000. So we must save the contents of this RAM every time another device needs this range. To archive this we could add more RAM to the board but this would mean a major rebuild and that is a little bit out of the scope of this project. Another idea is to save the contents of the RAM on the PC. This will cost some performance but will need fewer modifications of the 1541-board. To perform the needed save- and restore-operations, we will need some extra RAM but that is already covered by the part above.
One remark: A multi-device drive cannot be two devices at the same time. So I foresee troubles with copy-programs that transfer data directly from one drive to the other.


Software

The SW can be split up in two parts:
  • the software for the 1541 board
  • the software for the PC
To be able to alter the original kernal, you first must have the source code of it. As I haven't found one complete with comments etc. yet, I'm working on one myself. When this is done, I can start studying where and how to alter it.
The software for the PC is less trouble as I can use the core of CBM-HD for this purpose. Theoretically I only have to change the I/O- and command-interpreter-part (I hope).


Schematics

Not even started yet.





Having questions or comment? You want more Info?
You can email me here.