Hello Visitor

I started making some notes to myself for various projects and my revisit to the Amiga after 10+ years.  Some of them are probably quite useful so I've started publishing my research, findings and source code here.

I hope you find it useful.


I'm Back. It has been a while. Much has changed in the years since 2010. Watch this space.

Amiga 2000 Disaster June 2010

Doing some spring cleaning I decided to pull out my old Amiga 2000 from under the stairs where it has been since I packed it up in 1998.  Found everything with it: 2GB SCSI Hard Disk, SCSI 2X CD-ROM, PicassoIV graphics card, Ariadne Network card and the Blizzard 2060 50Mhz accelerator.  There is no doubt about it, this machine was my pride and joy.  My entire career was built on what this then-mighty machine had taught me: C, Pascal, 68000 assembler and lots about electronics.  And much more.

What a blow to find a black monitor screen when I turned the power on.  Found an A520 TV modulator and plugged it into the TV.  Ho hum, still just a black screen.  When I finally got off the phone from the Samaritans I decided to pull the machine to pieces to see what  the matter might be.

Oh no.  Hell no.  It turned out that despite believing otherwise I did not remove the 3.6V Ni-Cd battery (for the real-time clock & calender).  Samaritans no bloody use so I hung up on them this time.  With a level head it was time to assess the damage.  Lots of green/blue corrosion around the battery and PCB.  Some of the CPU pins looked rather messy too.  Removed the CPU only to find one of the pins was wobbly & completely corroded.  The 68pin DIL socket was in even worse condition.  When the CPU was removed some of the contacts just fell to pieces.  There was only one thing for it: eBay.

Managed to get a number of "new" 68000 CPUs in great condition and also a couple of turned pin DIL sockets.  First steps was to remove the battery that had caused all this mess.  Only to find Commodore had simply placed one of the pins right in the middle of a plane of copper.  The trusty 18W iron did not stand a chance at melting the solder.  No choice but to snip this leg and leave the remainder in the motherboard.  Note to self: buy a higher wattage soldering iron.

With the battery removed it was time to clean up the mess.  By far the easiest option was to put the motherboard into the kitchen sink, run some warn water over it and scrub with a toothbrush and washing-up liquid.  Yep, that did the trick.  Left the board to drip and then took a hair dryer to it to remove all trace of water.

Now for the 68pin DIL socket.  After trying 3 or 4 pins with the solder sucker I could see it was a waste of time.  No way on earth could I lift the whole socket out without taking some thru-plating with it.  I've removed many ICs and sockets up to around 20 pins and even then sometimes caused slight damage.

What it needed was desoldering and removing one pin at a time.  So out came the Dremmel.  Very carefully it was possible to cut into the plastic between each pin.  Once the pin was dislocated from the socket it was easy to desolder and remote it from the board.  This painful process took some 2 hours but not one tiny ounce of damage to the motherboard.  Excellent.

-this section not finished yet-

Amiga 2000 PSU Repairs July 2010

With the first Amiga 2000 fixed it's time to turn my attention to the second machine.  Fortunately I did remove the battery from this machine before it went into storage.  Infact it was because I noticed it had started to leak sometime back in the late 90s.  Even now you can still see some traces of green/blue on the motherboard.

The machine when powered up simply put the power LED from half brightness to full brightness and kept on rebooting. Finally found something to investigate. The PSU TICK line was a constant 5V.  This line should produce a square wave at 50Hz.  Opened the PSU only to find a cap had leaked when the machine was in storage.  A number of resistors looked rotten.  They were bad enough that you could no longer identity their colour codes.  So...opened my other A2000 and luckily enough it was exactly the same PSU and fortunately no damage to been seen.

I put the multimeter across each rotten looking resistor and compared it against the working PSU.  R51 was the only reading way off.

In the end I replaced the following components (the most rotten ones), including the cap I suspected of leaking:

Component Value Type DMM Value in circuit Farnell Ordering code  
R37 3K9 Carbon film 125mW 1118 Ohm 1700244  
R38 3K9 Carbon film 125mW 3800 Ohm 1700244  
R39 3K9 Carbon film 125mW 3870 Ohm 1700244  
R45 6K8 Carbon film 125mW 5320 Ohm 1700247  
R46 0R   Looks like 0 Ohm link.  Not ordered/swapped yet but ordering code looks correct 1700196  
R47 0R      1700196  
R52 10K Carbon film 125mW 1220 Ohm 1700251  
R56 100K Carbon film 125mW 1550 Ohm 1700264  
C24 1uF Electolytic 50V   (had this in stock already)  

Some years ago I blew the fuse and wound a bit of fuse wire around it.  I found a 6A replacement fuse on Farnell (1437153) and replaced it too.

Cleaned the board with Isopropanol (106970) which does a great job of removing all the flux residue.  The PSU now outputs a solid 50Hz square wave (0V to 5V) and the machine starts perfectly.

Note to self:  I need to change a few more rotten resistors.  I'll update this list again....may list all the component values so others may find it useful.

11 August 2010

Amiga 2000 #2 finally has a CD-ROM drive thanks again to eBay.  Plugged it into the SCSI controller of the GVP 68EC030 40Mhz card.  Here is the manual for it.

12 August 2010

On my Google travels I stumbled across the website of Ralph Babel.  From there you can download the final version of the gvpscsi.device ROMs.  I have a couple of GVP boards so I'm going to try to upgrade them.  Got my hands on a couple of 27C256 EPROMs from eBay along with an el-cheapo Willem style EPROM programmer all the way from China.

Turns out to be very simple indeed.  The programming software looks ancient but is able to run from the CD without any bother at all.  The programmer requires an LPT port and is powered from a USB cable.  The software is pretty intuitive and clrealy shows what jumpers need to be set.

The ROM is 16K but since I was using a 32K chip I had to burn it both into the top and bottom parts.  This was quite simple to achive:  Load the HEX file into the software, export it as a binary ROM.  Then simply copy /b rom+rom rom2... and then load it back into the software.

Bought an Oktagon 2008 SCSI controller (Zorro) for the Amiga a few weeks ago and have also been able to upgrade this ROM successfully.  I found this at http://amiga.resource.cx/install/Oktagon_ROM-612.zip.

It seems strangely satisfying (but sad at the same time) that these boards now have not only the latest version but the last version.

12 August 2010...continued

Since getting my first Amiga 500 in the late 80s I was always interested in Amiga copy protection and disk reading/recording in general.  Around 1990 I got myself a copy of "The Principles of Computer Hardware" by Alan Clements (ISBN 0-19-853703-4).  A pretty geeky book for a 15 year old kid.  This is where I learnt about FM/MFM encoding techniques.  Just checked Amazon  there and noticed that it's now in its third edition....£5.33 for a second hand copy delievered to my door...add to basket!

Having seen some great devices on the net such as this Floppy Disk Emulator I wanted to do some tinkering myself (having said that this product is on my wish list for sure).  So this week I bought myself a logic analyser from Saleae.  What a fantastic little gadget.  Cost something like £110 delivered by 24/48 hour courier.  My oscilloscope was useless since the data on the read line is not consistent and it's not a storage scope.

Within minutes of unpacking the device I was capturing data.  Brilliant.

Bread board, floppy and logic analyser

In this picture you can see the logic analyser in the bottom right-hand corner.  The drive is a Sony MFP920-Z/131.  The IC on the breadboard is a Microchip PIC18F2525 which I am using to control the drive (such as select, motor control, head seeking, read/write control. etc).  In the top right is the excellent Real Ice in-circuit emulator.

Logic sample

And here is a screen grab of the capture.  It clearly showed me 4us, 6us and 8us periods (give or take a few nanoseconds).  The 2 million samples at 8Mhz allowed me to capture just over 250 milliseconds of data, starting from INDEX being asserted.  The disk rotates at 300RPM so the track can be read in 200ms.

The program at this point is pretty useless to me so I did a binary export (2,100,000 bytes).  One byte per 125ns sample window.

I knocked up a quick piece of C# code to analyse the data.  To cut a long story short the code looks for the 4, 6 and 8us pulses.  There is a 64bit int which I'm using as a shift register.  If a 4us pulse is found then 10 is written to the register.  If a 6us pulse is found then 100 is written to the register.  If an 8us pulse if found then 1000 is written.  The windows do vary so the code is tolerant to about 5% at the moment - this seems to work OK for the disk under test.  The timing is reset with every flux transition detected so this avoids any accumulative errors.

With every bit placed into the shift register it is checked for the special MFM sync word (0x4489) and my breakpoint is hit.

Wow.  It worked first time - I did not expect that for a second!  (ok, first signs are good; don't get too excited just yet).

        private static void PushBit(ref UInt64 sync, int p)
            sync <<= 1;

            if (p == 1) sync |= 1;

            if ((sync & 0xFFFFFFFF) == 0x44894489)
                Console.WriteLine("Sync Marker found");
This breakpoint was hit 14 times, which by my calculations is about right.  We expect 11 sectors per track, so with 250ms read that's about 1.25 tracks.  11 x 1.25 = 13.75...

A point worth noting is that when the full 64bits are inspected I am getting 2 different values:

0x2aaaaaaa44894489 and

I think this is correct since the first part of bits depend on previous bits.

Next steps... convert the MFM data into real bits and see if the block checksum computes.

13 August 2010

Further analysis of the MFM data.  I have modified the PushBit code to pull out data bits and ignore clock bits once the sync marker has been found. The first 32 actual bits on mt first break point looks like this: 0xF012F010

According to RKRM: Devices page 572 after the sync words we should get:

one byte of format byte (Amiga 1.0 format = $FF)
one byte of track number
one byte of sector number
one byte of sectors until end of write (NOTE 1)
[above 4 bytes treated as one longword for purposes of MFM encoding]

So my data from above looks wrong.   But reading further on page 573 is states that encoding is done in blocks.  Odd bits are encoded first and then even bits.

Taking that into account 0xF012F010 converts to FF 00 03 08.  This looks much more like it.  FF = yes.  00 = yes we were on track 0.  And lastly 3 + 8 = 11 sectors.  It's looking good... so let's check the next breakpoint.

0xf001f023 is the next value which converts to FF 00 04 07. Excellent, sector number went up and number of tracks to write went down. We're cooking on gas alright.

Taking all this odd/even encoding into account I suppose I'd better write a piece of code to decode it before I go any further.  All this manual decoding is not good for the brain.

A strange thing occurred to me.  Using my little PIC and some intelligent firmware it should be theoretically possible to read an entire Amiga disk and convert it to ADF just using the PC and the logic analyser.  Hm.  Must think about this.  Must look at the SDK features of the Saleae device.


14 August 2010

Last night I changed the PushBit() routine.  After a Sync marker is found it now builds an array of bytes filled with MFM data, up to a maximum of 1080 bytes.  This is 4 bytes of the data above, 16 bytes sector label, 4 bytes header checksum, 4 bytes data checksum and 512 bytes sector data.  540 bytes in total times 2 since we're storing clock data too.

Once filled I'm just writing the 540 bytes out to disk for inspection with a hex editor.

Look what we have here:

00000000  FF 00 00 0B  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000010  00 00 00 00  00 00 00 04  54 15 11 00  44 4F 53 00  ........T...DOS.
00000020  E3 3D 0E 73  00 00 03 70  43 FA 00 3E  70 25 4E AE  .=.s...pC..>p%N.
00000030  FD D8 4A 80  67 0C 22 40  08 E9 00 06  00 22 4E AE  ..J.g."@....."N.
00000040  FE 62 43 FA  00 18 4E AE  FF A0 4A 80  67 0A 20 40  .bC...N...J.g. @
00000050  20 68 00 16  70 00 4E 75  70 FF 4E 75  64 6F 73 2E   h..p.Nup.Nudos.
00000060  6C 69 62 72  61 72 79 00  65 78 70 61  6E 73 69 6F  library.expansio
00000070  6E 2E 6C 69  62 72 61 72  79 00 00 00  00 00 00 00  n.library.......
00000080  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000090  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000000A0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000000B0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000000C0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000000D0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000000E0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000000F0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000100  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000110  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000120  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000130  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000140  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000150  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000160  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000170  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000180  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000190  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000001A0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000001B0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000001C0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000001D0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000001E0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
000001F0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000200  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
00000210  00 00 00 00  00 00 00 00  00 00 00 00               ............

It's the first block of a boot block!  Excellent - working a treat.

The next thing is - tidy the code to make it more modular.  Then calculate the checksum.  Once I've done all this I'm going to see about changing the PIC code to read the whole disk so I can analyse more data.

I got in contact with a guy called Keith.  He's doing some Amiga floppy stuff on his blog at techtravels.org.  Very helpful and has lots of experience doing this stuff.  It's uncanny how close our thought patterns are.  Be sure to check out his site.

Another excellent resource is this site here http://lclevy.free.fr/adflib/adf_info.html.  The checksum logic does not appear to be explained at all in the RKRM and Laurent's site was quite useful.  The source from ADFRead also confirmed what was going on: http://www.winuae.net/files/stuff/adfread-1.1.zip


14 August 2010 19:30

Well not a whole heap done today as we had a rare glimpse of the sun.  The checksum checking is done & I've created a C# struct that represents all the non-Sync parts of a sector:

        [StructLayout(LayoutKind.Sequential, Size = 540, Pack = 1)]
        private struct AmigaSector
            public byte DiskFormat, TrackNumber, SectorNumber, SectorsToWrite;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public byte[] SectorLabel;

            public uint HeaderChecksum
                    return (uint)(HeaderChecksum4 << 24 | HeaderChecksum3 << 16 | HeaderChecksum2 << 8 | HeaderChecksum1);

            public byte HeaderChecksum4;
            public byte HeaderChecksum3;
            public byte HeaderChecksum2;
            public byte HeaderChecksum1;

            public uint DataChecksum
                    return (uint)(DataChecksum4 << 24 | DataChecksum3 << 16 | DataChecksum2 << 8 | DataChecksum1);

            public byte DataChecksum4;
            public byte DataChecksum3;
            public byte DataChecksum2;
            public byte DataChecksum1;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] SectorData;

The properties were needed because Amiga longs are stored as Big Endian and they do the conversion for me.

I still need to tidy the code a little but I've run the checksum check over the first 14 sectors I am sniffing.  The results look perfect so far:

Sync Marker found
FMT: 255  TRK: 0  SEC: 3  REM: 8
Stored header csum: 0x00000004
Calculated header csum: 0x00000004
Stored data csum: 0x15441114
Calculated data csum: 0x15441114

Sync Marker found
FMT: 255  TRK: 0  SEC: 4  REM: 7
Stored header csum: 0x00000404
Calculated header csum: 0x00000404
Stored data csum: 0x04051114
Calculated data csum: 0x04051114

Sync Marker found
FMT: 255  TRK: 0  SEC: 5  REM: 6
Stored header csum: 0x00000505
Calculated header csum: 0x00000505
Stored data csum: 0x11001410
Calculated data csum: 0x11001410

Sync Marker found
FMT: 255  TRK: 0  SEC: 6  REM: 5
Stored header csum: 0x00000505
Calculated header csum: 0x00000505
Stored data csum: 0x51514551
Calculated data csum: 0x51514551

Sync Marker found
FMT: 255  TRK: 0  SEC: 7  REM: 4
Stored header csum: 0x00000404
Calculated header csum: 0x00000404
Stored data csum: 0x05045155
Calculated data csum: 0x05045155

Sync Marker found
FMT: 255  TRK: 0  SEC: 8  REM: 3
Stored header csum: 0x00000400
Calculated header csum: 0x00000400
Stored data csum: 0x51444054
Calculated data csum: 0x51444054

Sync Marker found
FMT: 255  TRK: 0  SEC: 9  REM: 2
Stored header csum: 0x00000501
Calculated header csum: 0x00000501
Stored data csum: 0x44555051
Calculated data csum: 0x44555051

Sync Marker found
FMT: 255  TRK: 0  SEC: 10  REM: 1
Stored header csum: 0x00000501
Calculated header csum: 0x00000501
Stored data csum: 0x10504040
Calculated data csum: 0x10504040

Sync Marker found
FMT: 255  TRK: 0  SEC: 0  REM: 11
Stored header csum: 0x00000004
Calculated header csum: 0x00000004
Stored data csum: 0x54151100
Calculated data csum: 0x54151100

Sync Marker found
FMT: 255  TRK: 0  SEC: 1  REM: 10
Stored header csum: 0x00000105
Calculated header csum: 0x00000105
Stored data csum: 0x00000000
Calculated data csum: 0x00000000

Sync Marker found
FMT: 255  TRK: 0  SEC: 2  REM: 9
Stored header csum: 0x00000105
Calculated header csum: 0x00000105
Stored data csum: 0x15410001
Calculated data csum: 0x15410001

Sync Marker found
FMT: 255  TRK: 0  SEC: 3  REM: 8
Stored header csum: 0x00000004
Calculated header csum: 0x00000004
Stored data csum: 0x15441114
Calculated data csum: 0x15441114

Sync Marker found
FMT: 255  TRK: 0  SEC: 4  REM: 7
Stored header csum: 0x00000404
Calculated header csum: 0x00000404
Stored data csum: 0x04051114
Calculated data csum: 0x04051114

Sync Marker found
FMT: 255  TRK: 0  SEC: 5  REM: 6
Stored header csum: 0x00000505
Calculated header csum: 0x00000505
Stored data csum: 0x11001410
Calculated data csum: 0x11001410


15 August 2010 10:30

I had links on the PC, links on the laptop so here they are all merged into one tidy place.  All kinds of things here.  It's a nice day again today but I'll try and get some more time in on the floppy reader.

http://amigadev.elowar.com/ Amiga Developer Docs
http://techtravels.org/amiga/amigablog/ Amiga Floppy Blog
http://afr.back2roots.org/ Amiga Floppy Reader Project
http://amiga.resource.cx/ Amiga Hardware Database
http://www.devili.iki.fi/mirrors/4x4.hopto.org/ Amiga Schematics and Manuals
http://www.amiga.org/ Amiga.org
http://www.amiga-stuff.com/ Amiga Stuff
http://aminet.net/ Aminet
http://whdloadrules.tripod.com/rob_northen_interview.html Interview with Rob Northern
http://www.back2roots.org/ Back to the Roots - Amiga Culture Directory Project
http://wandel.ca/homepage/execdis/index.html Markus Wandel
http://babel.de/amiga.html Ralph Babel's Amiga archive
http://en.wikipedia.org/wiki/Rob_Northen_copylock Rob Northen copylock
http://www.softpres.org/ Software Preservation Society
http://lclevy.free.fr/adflib/adf_info.html The .ADF (Amiga Disk File) format FAQ
http://bboah.amiga-resistance.info/index_e.html The Big Book of Amiga Hardware
http://www.vesalia.de/ Vesalia Online - The Amiga & Retro Computing Store (Est. 1987)
http://www.viksoe.dk/code/adfview.htm ADF View shell extension
http://whdload.de/ WHDLoad Support Page
http://www.winuae.net/ WinUAE
http://www.amigaforever.com/ Amiga Forever
http://amiga.nvg.org/ Amiga@NVG
http://www.amigakit.co.uk/ Leaman Computing
http://eab.abime.net/ English Amiga Board
http://www.abime.net/ Amiga Addicts Sanctuary
http://www.lemonamiga.com/ Lemon Amiga
http://hxc2001.free.fr/floppy_drive_emulator/ Floppy Drive Emulator




Dave Haynie files

15 August 2010 11:30

Managed to get half an hour in here.  Making the code a bit more analytical.  It now tells me if a SYNC word was found mid-sector and also reports how many non-sector bytes were discarded before a sync work was found.  It's looking exactly as I expected:

 Sync Marker found
** 4889 junk bits found inbetween sectors
FMT: 255  TRK: 0  SEC: 3  REM: 8
Stored header csum: 0x00000004
Calculated header csum: 0x00000004
Stored data csum: 0x15441114
Calculated data csum: 0x15441114


Sync Marker found
** 5400 junk bits found inbetween sectors
FMT: 255  TRK: 0  SEC: 0  REM: 11
Stored header csum: 0x00000004
Calculated header csum: 0x00000004
Stored data csum: 0x54151100
Calculated data csum: 0x54151100


As you can see we have junk in 2 places.  Firstly at the very start of the capture which is not surprising since we started reading in a completely random place.  Then secondly the is junk right before sector 0, which is the gap.  This code is going to get more interesting once I start stepping the heads - we will start to see more of this junk (but correctly so).

Still need to tidy the code so I must tackle that next before I get side-tracked.


15 August 2010 21:00

Not much done today, but got and hour and a half in this evening.  PIC code has now been modified to scan the whole disk, pretty much as follows:

  • Select Drive
  • Motor On
  • Seek to Track Zero
  • Select Side 0
  • Wait 250ms
  • Select Side 1
  • Wait 250ms
  • Step head

...and do the above for 80 cylinders.

I had modified the Saleae binary parsing code to something like this to do some validation:

         if (sectorStruct.SectorNumber >= 0 && sectorStruct.SectorNumber <= 10)
             if (sectorStruct.TrackNumber >= 0 && sectorStruct.TrackNumber <= 159)
                 if (sectorStruct.DataChecksum == dataChecksum)
                     if (sectorStruct.HeaderChecksum == headerChecksum)
                         blocksFound[sectorStruct.TrackNumber * 11 + sectorStruct.SectorNumber] = true;

Looks promising so far.  The capture is around 350MB and all 1760 blocks appear to have been found!  The main thing I did notice is that towards cylinder 80 the bit timing is much less precise than on the outer tracks and had to modify the tolerances.  Tomorrow I will store the decoded sectors into the array and write out a binary (i.e. and ADF file) and see what ADFView and/or WinUAE makes of it.  I am quietly confident.

Some other interesting things I've started to notice - some sectors have 2-3 bits of junk between them.  Must investigate this further at some point.

16 August 2010 20:00

Added a piece of code to PushBit() to check if all 1760 blocks have been found.  If so then it writes them out to disk in the ADF format.  Take a look below; this screenshot was taken from WinUAE booting as an A1200 with a Workbench3.1 disk.  The disk scanned is the one called 'TandemCDInstall' which I've opened so you can see its contents...  Nifty, eh?

ADF screenshot

and here's another screenshot.  This time of the same disk opened under Windows7 using ADFView:

ADF View

I've tried 2 more disks without problems, but again I had to adjust the bit cell windows even more tonight.  I've added more validation before deciding if a sector is good or not:  Format must be 0xFF and SectorsToWrite must be >=1 and <= 11.

Let's state it for the record:  The Saleae logic analyser is a superb little tool!

18 August 2010 20:00

Last night I scanned about 6 disks in and tinkered with the MFM decoding logic.  Most of my time was spent with genuine faulty disks, for half of the night I got that dreaded click-click-click-click sound as the head passed over a tiny piece of dirt.  Out came the cotton buds with a small helping of Isoproponal cleaner and believe it or not I was able to restore a couple of disks to their former glory.

There is no doubt though; my decoder is struggling with a couple of disks.  Interestingly (or worryingly) the code is reading a disk with 2 bad sectors - these refuse to read on the Amiga but my MFM code says the checksums are OK.  I know the sector to be corrupt as the LHA archive sitting there shows a CRC failed file when I tried to extract the archive.  This is telling me that the checksum routines Commodore were using are not that strong.

Secondly I am also reading one or two sectors that show total garbage yet the checksums add up; again this all points to weak checksum routines made by Commodore.  What I have done tonight is save an ADF on the Amiga using my TDRead code I wrote in 1994 (which I will post when I get a moment) and write it back to a blank disk.  The newly written disk can be read perfectly by my MFM code.  So...  first thoughts; bit cells becoming dodgy because of the age of the disk, or, as I suspect disks were originally badly mastered.  The disks with the problems are 5 disks I bought from Commodore; they are the 3.1 Includes and Examples, etc.  A number of disks have trouble on exactly the same tracks - the whole track.  Even when I first bought the disks disk 2 would not read; I eventually got it backed up by trying and trying (might have even tried different drives but don't remember).  On a positive note though; I actually archived about 100 of my most important floppies back in 1995 so hopefully all is not lost.

I have tested 6 or so ADF dumps against a newly written copy of the disk on the Amiga and they all matched.  This is good I suppose in that old and new copies seem to match - however - one major thing I need to do is actually check byte for byte.  The ADF dump on the Amiga must match the ADF dump on the PC.  A rig needs to be setup to do this; probably get my A600 or A1200 and stick a compact flash in it or something (my Ariadne is not configured yet in the A2000).

I'm also aware that I've tinkered with the code to get something working; this is bad as I have not re-tested previous dumps.  The sensible thing to do is keep the 300MB dump for every disk on my HD as ripping is pretty time consuming.  Everytime I change the code I need to re-scan ALL the Logic analyser dumps to ensure the resulting ADF is the same as before!

18 August 2010 22:00

Track 159 is the one of the problem tracks.  Very crude analysis in Excel shows wildly varying bit cells.  Very hard to say at this point if it's the problem as I have not compared them against the rest of the disk.  The problem is related to an earlier post where I mentioned "garbage" between some sectors; it's clear I am detecting too many flux changes.

It's like looking for a needle in a haystack.  Looks like I picked the wrong week to quit sniffing glue.

My plan therefore is simple: write the dodgy track back to a disk in a effort to get a good sector from it.  Then convert the sector into MFM and compare my framing with the correct waveform.  It should then be very simple to find the detection error.

One thing is that if I slow down and generally mess with the disk RPM (but sticking my thumb against the flywheel) I can get what seems to be a good read - human readable text in the sectors, so that's a good sign.

And here is the TDRead code and executable I wrote back in 1994, zipped up.  If I get a moment I'll update my contact details and release it as V1.2 to Aminet.

By the way - these 350MB captures actually compress very well as you'd expect; tried one a short time ago and got it down to around 12MB.

21 August 2010 11:00

Spent the last few days analysing the data from a particular sector I am having trouble reading.  To setup the analysis I changed the PIC code to seek to track 159 (my problem track) and then captured a couple of rotations using Logic.  Then I made a copy of the disc on the Amiga (which is able to read the track without problems) and then captured the MFM data in the same way.

Luckily the MFM decoder is able to find most sector heads on the problem disc so I had a fighting chance to put the two captures side by side.  Since there is still a lot of data here I am concentrating on comparing just one sector.

Using Excel I put the data in side by side and put a formula in to look for mismatches.  Very quickly I could see that on 4 occasions my decoder was misjuding the bit window widths.  The good news at least was the number of flux transitions in both captures were the same.

A 'textbook' disc should have flux transitions at 4, 6 or 8us intervals so it was time to do some further analysis.  The MFM decoder has been modified to show 1)  what width the code is assuming and 2) the actual time elapsed since the last flux transition.  Then using Excel we can analyse the drift.  The first table shows the drift timing and the number of times it occured for the freshly copied disc:

Drift (uS) Count
-0.250 65
-0.125 491
0.000 987
0.125 1063
0.250 643
0.375 44

From this we can see the timing is actually pretty consistent; there are a couple of times we are 375ns out but generally speaking we are no more than 250ns out.  Bear in mind also that the capture is running at 8Mhz so 125ns is the resolution.

Now compare this with the sector I am having trouble reading:

Drift (uS) Count
-0.875 1
-0.750 18
-0.625 100
-0.500 217
-0.375 340
-0.250 235
-0.125 453
0.000 412
0.125 511
0.250 455
0.375 294
0.500 187
0.625 66
1.125 4

Yikes!  Big difference.  Straight away we can see there is a much larger range of drifts and the drifts are bigger.  Most importantly we can see some are miles out, 4 over 1us out.  Why?  I don't know - badly duplicated, age-related, perhaps a deliberate attempt by the manufacturer to put a signature on the disk for authenicity validation...?

Speculation aside my code is failing at the 4 points where the window is 1.125us out.  The MFM decoder needs to be re-thought a little to tolerate this.  I was surprised the original code works as well as it does because it's working strictly on the edges of the flux changes rather than using a "sample window".

22 August 2010

TDRead has been renamed and released to Aminet as TDTool.  You can download it from Aminet here.

Or you can download directly from this server: TDTool.lha and TDTool.readme.  These links will always point to the latest version.

I spent some time on it before release, mainly adding a new DEVICE command line parameter that allows you to specify a different block device, such as gvpscsi.device for example.

25 August 2010

Nothing to report on the floppy side of things.  Still need to sit down for a few hours to study the sector with the wildly varying bit cells.

On another note I have just bought a DIP42 adapter for the EPROM programmer.  This allows me to program 27C400 chips which appear to be pin compatible with the Amiga Kickstart.  An idea I had some time ago was to develop a diagnostics ROM to dump information out the the serial port.  You'd use this in "dead" Amigas, say for example a chip ram IC was duff; this util would pump out the memory test results to the serial port.  (Basically stick it in a machine that won't boot and hopefully find out what is wrong...)

Anyway, the first thing is to check to make sure all is OK and to do that I simply attempted to make a backup of my Kickstart.

Sourced some 27C400-105DC chips (thanks again eBay).  I inserted the Kickstart chip into the programmer an did a read operation.  Data looked great.  Stuck in the 27C400 and hit program.  It took a couple of minutes but the result was perfect, the thing verified OK.  Inserted in the A2000 and away it went...

Small point worth noting is that if you're programming from a ROM from, say, WinUAE you need to change the endianness by swapping around the bytes of each 16 bit word before programming (infact this feature was a part of the programming software so happy days).

30 August 2010 12:30

TDTool V1.3 has been released.  I have now added a WRITE function, bit of a hack but it makes the program a whole lot more useful.  You can download it from Aminet here.

Or you can download directly from this server: TDTool.lha and TDTool.readme.  These links will always point to the latest version.

30 August 2010 12:45

Qwk2Pkt, another program from 1994 has been dusted off and released to Aminet with its source code.  It will never likely be released again; I doubt if anyone will use it, but the source code may come in handy.  I'll add the links once they become available, come back to this post in a day or two.

You can download directly from this server: Qwk2Pkt and Qwk2Pkt.readme

31 August 2010 18:00

Here's another project I have been working on for some time.  An RS232 PBX Call Logger/Data Logger.  Some of its main features:

  • Firmware can be remotey upgraded in less than 3 minutes
  • Unlimited capacity in practice - uses one industry standard SD card, up to 4GB
  • Communications protected by CRC16 checksums
  • Keenly priced; could be sold for around £99 + VAT by my estimation
  • Seven PBX baud rates supported: 300, 600, 1200, 2400, 4800, 9600 and 19200
  • Extremely fast transfer rate: 115,200 baud with V42/V42bis
  • Nett weight of just 170 grams!
  • Transmission can be resumed from any point
  • Exponential back-off retry algorithm
  • Low power: less than 0.5 Watts in standby and around 1W during transmission

And if that's not enough:

  • Complete multi-tasking firmware; unit stores PBX data whilst communicating with the central server
  • Supports No Parity, Odd Parity, Even Parity.  Errors are counted and sent to the central server
  • Supports 7 bit data, or 8 bit data
  • Optionally mask off top bit
  • Framing errors counted and sent to the central server
  • False start errors counted and sent to the central server
  • Automatic baud rate detection (optionally stored to EEPROM)
  • No jumpers to cut or solder
  • Supports back-to-back bytes (no inter-byte delay required)
  • Just one unit for all markets UK, IRL, USA - configuration is 'menu driven'
  • Firmware is production line friendly, for example SD testing commands
  • Firmware can also run remote memory tests, and report results
  • Support an estimated 50,000 units using just 2U (yes, really) of rack space
  • Configurable timestamp markers
  • Timer resolution of 100 milliseconds

It's true to say this is the only major electronics project I've ever 'completed'.  Ok, to finish this product it would need to be looked at by an electronics professional, go through EMC testing, CE approvals etc.

Here's a picture of what the final version looks like:

PBX Call Logger / Data Logger

The main thing missing here is the top label which would have 4 clear areas so the status LEDs can shine through.  This unit pictured has gone through 6+ months in a commercial environment and results have been nothing less than perfect.  Just 6 minor firmware releases to add a couple of new features and fix some silly bugs.

And this is what it looks like under the lid:

Call Logger PCB


31 August 2010 20:00

I've been looking for an escape from technology for some time and at last I've found it here.

5 September 2010 12:00

Not much done with the floppy stuff over the last few weeks.  To say I've had a tough time at work recently would be the understatement of the century.

Managed to sit down last night with a clear head to sort out this problem sector.  Firstly it's obvious the post from 21 August is slightly erroneous.  The 4 bit cells that are the "massive" 1.125uS out are not out by that much at all!  The table was (wrongly) calculated based on what cell size I had assumed it to be.  Let me explain that:  The 4 bit cells were 6.875uS, and based on my assumption the cell should have been 8uS, the difference is 1.125uS.  Considering the actual cell size should be 6uS the difference is only 0.875uS.  That's more more workable.

I discovered this problem quite quickly once I started analysing the actual window sizes, rather than the drift.  The following graph shows the problem sector from the original disk:

Graph of problem sector from the original disk

It's clear that considering a 6.875us cell as an 8us cell is not so smart, it's too close.  I have changed my MFM code to consider from 7uS as being an 8uS window.  After re-running the code I can now decode this sector with a valid checksum, etc.

For completeness here are the other graphs I produced:

Graph of problem sector from the copied disk

This graph clearly shows much more consisent cell sizes (as confirmed from my earlier post), and as a result far less of a "grey area".  And just to finish off here's the combined graph:

Graph showing problem sector from both disks

In addition to this I have now started to build my library of 300MB Logic captures, as mentioned before, these will be invaluable later on.  Should I change any code in the MFM decoder I need to re-test everything to date and this is by far the easiest way of achieving that.  There are now 10 discs in the library from my efforts this morning.  All appear to scan OK (i.e. all 1760 blocks checksum OK).  I've checked a number of disks that contained LhA archives and they passed their CRC checks OK, another good sign.

However, I've seen the disk checksum issues in the past so I think the next sensible step would be to rip them on the Amiga also.  The easiest thing to do would be to create an MD5 or SHA-1 hash of the entire ADF file making comparison very easy.  This is probably a good starting point http://aminet.net/package/dev/c/md5.

So that's it.  At the moment my code "works".  I just have to keep capturing and comparing and see what turns up next.  Watch this space.

5 September 2010 12:30

Thanks to all you crazy people, TDTool now has 238 downloads on Aminet, and a couple from this server too.  Thanks!

6 September 2010 21:00

Tool building is the order of the evening.  The MFM decoder now can scan all of my Logic captures and save ADF files of the same name, along with the MD5 hash.  See the example output:

093d5091d5ce7e3fd430d49c75b4e553 *AutoDocsDisk1of5.adf
9d00a6f3960292d759d5323b66d6231a *AutoDocsDisk2of5.adf
G:\AutoDocsDisk2of5Copy.bin - missing block(s): 655 825
3e6d092cc04f10af29fe328e42fbd891 *AutoDocsDisk2of5CopyOfCopy.adf
2ec2fbf190c22ef88d90ffdeb4b728a7 *AutoDocsDisk3of5.adf
838cc5dbbbc9b60bc2fdccb67a3dde5e *AutoDocsDisk4of5.adf
a48289feea65b15b014e272b231bc8cd *AutoDocsDisk5of5.adf
1a14f7737e21357542781c28fbd74f74 *XDCC1.adf
bb4b789bd96f560f324f5036b72c1f6c *XDCC2.adf
37c16da9ca389d88b58605255cddad31 *XDCC3.adf
203a6f1518a315a82f414ee6547fba25 *XDCC4.adf

Also see the extra logging, it now shows what blocks could not be recovered from the capture.

The most useful MD5 hashing tool for the Amiga in the end turned out the be this one http://aminet.net/package/util/crypt/MD5SUM.  There was an md5sum2 program that supported Amiga wildcards etc, but this turned out to lock up the machine.  No source code supplied so I could not fix it.

Here is a summary of what everything looks like:

 match			093d5091d5ce7e3fd430d49c75b4e553 *AutoDocsDisk1of5.adf
no read on amiga	9d00a6f3960292d759d5323b66d6231a *AutoDocsDisk2of5.adf
no read on PC		3e6d092cc04f10af29fe328e42fbd891 *AutoDocsDisk2of5Copy.adf
match			3e6d092cc04f10af29fe328e42fbd891 *AutoDocsDisk2of5CopyOfCopy.adf
match			2ec2fbf190c22ef88d90ffdeb4b728a7 *AutoDocsDisk3of5.adf
match			838cc5dbbbc9b60bc2fdccb67a3dde5e *AutoDocsDisk4of5.adf
match			a48289feea65b15b014e272b231bc8cd *AutoDocsDisk5of5.adf
match			1a14f7737e21357542781c28fbd74f74 *XDCC1.adf
match			bb4b789bd96f560f324f5036b72c1f6c *XDCC2.adf
match			37c16da9ca389d88b58605255cddad31 *XDCC3.adf
match			203a6f1518a315a82f414ee6547fba25 *XDCC4.adf

So, you can see we actually do have a problem disk:  AutoDocsDisk2of5Copy.  When I bought these disks from Commodore disk 2 proved to be a problem disk and I eventually was able to copy the files from it, which is why there is a copy in my collection.  I decided to make a fresh copy like I did before earlier in my floppy studies.  This was a bit of a problem since AmigaDOS changes the sector/sectors remaing number (i.e. the copied disc may not be a 100% match to the original).  In the end I solved this problem by using XCopyPro in nibble mode.  As before the newly written disk is readable on the PC.

The next session then is to study blocks 655 and 825 on the PC to see what the problem might be.  At least now if I change the code in any way I can easily run the new logic over the 11 captures to make sure I don't break something in the process...

7 September 2010 20:00

The table below shows a snippet of block 655 on the "Copy" disk and the "CopyOfCopy" disk (on the right).  It's the dreaded 5 and 7 microseconds.  Slap bang in the middle between valid bit cell windows.  I did the obvious thing and adjusted my code to accept these values and re-run it.  Bingo!  I was able to read the sector & the whole disk hash matched.

##8 7.625 ##8 8 TRUE
##6 5 ##4 3.875 FALSE  
##6 7 ##8 8 FALSE  
##4 4.75 ##4 3.875 TRUE
##6 5.625 ##6 6 TRUE
##4 4.125 ##4 3.875 TRUE
##4 4.125 ##4 4 TRUE
##4 3.875 ##4 3.875 TRUE
##4 4.25 ##4 4.125 TRUE
##6 6 ##6 5.875 TRUE
##8 7.625 ##8 8 TRUE
##8 7.25 ##8 7.875 TRUE
##6 5 ##4 3.875 FALSE  
##4 3.875 ##4 4 TRUE

The success was short-lived however.  When running the new logic against the other captures it showed that two disks failed to read.  By adjusting my code I'm robbing Peter to pay Paul.  In the example above the preceding cell is a fair chunk out, which is causing the following cell's window to be much larger.  Maybe the code should consider this.

7 September 2010 21:00

The MFM decoder logic has now been adjusted to take into account the last bitcell width.  If it's too short it will knock 125uS off the current bitcell.  If the last bitcell was too long it will add 125uS to the current bitcell.

Success!  All 10 disks have 100% block recovery rate.  I am not getting too excited this time since this whole thing still feels a little "fragile" and changing the 125uS correction to 250uS causes 2 sectors on AutoDocsDisk3of5 not to read.

There is one core difference between me and the Amiga.  The Amiga is checking the sectors as the track is read and I suspect if a sector cannot be read it probably tries a couple of times - my capture is strictly one revolution (and a bit) per track.  Perhaps this is another thing to test - run disk 3 of 5 and get 2 track captures and see it if fails again with 250uS correction?

Next steps: capture more disks.

8 September 2010 21:20

15 disks scanned and hashed on the Amiga.  The same 15 disks scanned and hashed from the Logic captures.  100% match.

Total: 26 of 26 disks appear to decode OK.  Next steps: capture more disks!

12 September 2010 20:00

A total of 50 disks have now been captured.  One disk would not read on the Amiga but a bit of isopropolene and a cotton bud soon sorted that problem.  I appear to be having trouble with 2 of them, very old disks (Workbench 1.3.2 and The Very First).

I also initially had trouble with a "Fonts 2.04" disk but a re-scan sorted that problem.  Which made me wonder again.  I still reckon AmigaDOS has some kind of retry algorithm, as I have found the next track read might be OK.  I have started looking at XCopyPro once again as it does everything in raw MFM mode and sure enough it was interesting to watch.  (By the way all 3 of these disks has the nasty clicking sound of dirt on the surface...).

The CHECKDISK function on these 3 (2 now) problem disks I have shows a red number on a track but after another spin it turns to a green zero.    So this shows even the miggy has trouble reading some sectors.  The 2 troublesome sectors though seem to read first time on the Amiga, although in general these 2 disks have a number of sectors XCopy needs to scan more than once.

I think the next steps are to look closely at these 2 problem sectors as I have done with al the others.  Total 48/50 have matching MD5 hash.

13 September 2010 20:45

Hm.  These two disks are now 100%.  I have just re-captured both of them and they went through first time.  The sector on the original capture was miles out, 2us for example.  I was having some trouble with the Logic device, complaining about not being able to capture at a certain rate.

So a couple of things; maybe Logic was messing me about, or a couple more spins have shifted the dirt from the disk surface (they were both very dirty indeed).

It's probably a good idea to get myself a drive head cleaning disk and maybe clean the drive every 20 or so disks that go in it?  Anyway we're up at 50/50 so maybe tomorrow I'll scan some more.

14 September 2010 21:00

Scanned 11 more disks.  The Amiga even had trouble reading a couple; tried in DF1: rather than DF0: and that did the trick.  Also had to clean 2 of the disks with Isopropanol again.  11 disks scanned OK and matched; one disk needed a couple of extra rotations to read, but the Amiga also had trouble reading this disc.  Total 61/61.

16 September 2010 21:00

Not much to report; 3 more disks scanned and everything OK.  Total 64/64.

One handy thing about doing this is that at least I now know with a pretty high degree of certainty what Workbench disks are original.  I have got a number from eBay and indeed from my own original collection but could not be sure if I had written to them at all.  So when I find, say, 3 disks with the same hash I can be pretty sure they are as original as the day they were first mastered!

19 September 2010 19:00

Been away from home over the last 2 weekends so not much to report.  Scanned two more disks tonight to get the rig back up and running; one had a dirty great finger print on it so another bit of cleaning needed; the other needed a couple of extra spins on track 159.  Total 66 out of 66 disks now read OK.