Subscribe via RSS
13Sep/161

Amiga 1200: Installing OS 3.9 from USB

Not having had an Amiga when younger, I'm completely foreign to the basics. Due to this, I've managed to make a dog's breakfast of the main hard disk on my Amiga 1200. I had installed software from left, right and center and have started to have random issues. It got to the point where AmiDock couldn't find a correctly versioned library and AWeb just wouldn't load.

Due to all of the above, and my new understanding of the directory structure and basic OS layout, my weekend task was to completely rebuild the Amiga 1200's CF HD from scratch. I didn't want to cheat either... so I attempted to do it without using WinUAE to build the base image.

TL;DR: For those of you who just want to get something done... scroll down to the Amiga 911 Maker section. The first two sections are just me ranting and learning and breaking things. In the end, if I'd just used the Maker and built the disk I would've had the system up an running in an hour!

Bootdisk required - Amiga911

I needed USB to be available when my Amiga booted, the CD-ROM drive that I had was an external IDE boxed unit and I'd previously installed Poseidon with my Rapid Road USB card. After a little searching, I came across the Amiga911 Emergency Boot Disks. Unfortunately, the chicken-vs-egg scenario occurs straight away as I needed a bootable Amiga to be able to write a bootable floppy image! Fortunately, I did still have a bootable Amiga and managed to get to a shell to burn ADF images.

Glancing over the Amiga911 site, I chose the first basic disk image which included the Poseidon USB stack. Writing it to a spare DD floppy using adf2disk was easy enough. Unfortunately, upon boot I was presented with Software Failure; ramlib - Program failed (error #80000004). Wait for disk activity to finish.

DSC06013

I've dealt with this before: the reason for this error is that I have Kickstart 3.X ROMs from Cloanto and these need a specific library to be installed on the boot partition library folder. Instead of obtaining the library, I switched to a spare set of Kickstart 3.1 ROMs and managed to get further. Before I continue the saga, a quick note on ROMs: stock 3.1 ROMs are 1 pin shorter than the Cloanto versions. These need to be aligned to the RIGHT of the socket. ROM 2 is at the top, ROM 1 underneath. It is a fatal mistake to left-align them! i.e. make sure there is a spare pin on the left-hand side of the socket, as per below.

DSC06009

DSC06010

Where was I?... Oh yeah, I could now boot into the Amiga911 Emergency Disk! Progress was halted as I was quickly warned that I needed a real Workbench disk to proceed. I didn't have one in the flesh, so I had to revert back to my main partition to create one. Of course, the main partition would no longer boot as it seemed to expect the 3.X Kickstart ROM. I swapped them back in ... bending pins and putting them in the wrong order. Finally... after 3 failed boots (black screens) I was back at my crappy workbench. I wrote the Workbench disk to a spare DD floppy.

At this point I decided to actually copy the 3.X ROM libraries required to the Amiga911 Emergency Boot Disk so it would boot... that way I wouldn't have to swap the ROMs again. The library in question was workbench.library as mentioned on Cloanto's Site. Whilst trying to copy this over to the Amiga911 disk, I initially thought I was in trouble... the only file showing on the burnt floppy was an Activate Amiga911 executable. My brain then thought magic happened on boot and that everything was in compressed archives that got decompressed during startup. This actually is the case, but there are still base system files that need to be executed first. Of course, I wasn't showing all files and initially couldn't see them. After this I managed to find the Libs folder and copied the relevant workbench.library to it.

DSC06016 DSC06015 DSC06017

It then booted! A few presses of enter got me to a prompt asking for the workbench disk. I swapped to the disk I'd burnt earlier (note that this is the wbench image, not the install image) and ... upon 'press any key' it told me it wasn't a proper workbench disk. On second try, it worked. Seems I hadn't waited long enough the the disk poller to unmount the boot disk and mount the workbench disk.

DSC06018 DSC06019 DSC06020

Amiga911 then copied a whole bunch of files off the workbench disk and asked me to put the Amiga911 disk back in... making sure it was write enabled. I did as asked, this time with an obligatory 5 second pause between removal/insertion/keypress. The installation process then stripped hunks... I giggled. It seemed to be building a compressed system image on the floppy. The compression process then failed with a crappy write error (you could hear it coming by the repetitive noises the floppy drive was making)... I wonder if this was because I put a library on the disk that took up too much space? Funny thing was that the Amiga911 script considered the process a success... I don't think it correctly read the return code from the LZX utliity!

Either way, I let it finish and the rebooted the machine... it seemed to get quite a way but then bombed out with just a Workbench Screen title bar and no disk activity. So. Back to the start. I went through the process again with a newer DD floppy (yes, I managed to acquire a fresh box of floppies!) and it all worked. The disk was written. I then copied the workbench.library from my OS 3.9 partition to the floppy and restarted.

DSC06022 DSC06023 DSC06024

DSC06025 DSC06026 DSC06028

DSC06029

I was presented with an invalid library message and a hung screen.... no workbench! Yey. I attempted to use AmiKick to get the workbench.library from my 3.1 KickStart ROM, but this didn't help either. So... back to kickstart 3.1. The boot disk is built from Workbench 3.1, so using the 3.9 library was (in hindsight) an obvious mistake. It turns out that you can get the relevant 3.1 disks from Cloanto if you have a valid serial number and you register... I've since done this and might try this method again later just for shits and giggles!

Back to the main task, I chose to downgrade back to 3.1 to be able to continue. After another dangerous ROM swap, I had the Amiga911 disk booting. Turns out the base Amiga911 disk doesn't contain the drivers for my USB card though! I searched my OS3.9 disk and copied the rapidroadrcusb driver to the floppy. I also then removed the drivers that I didn't need. At this point, I was really starting to wonder if all of this effort was going to pay off! Upon reboot, I manually started the USB Stack (check the Tools menu in Workbench) and my USB Key appeared on the desktop. Ok... nearly there... I would also have to install AmiCDFS at this point.

And so I did that... I dropped the files from AmiCDFS (there's no installer) into the relevant locations on the floppy disk... watching it fill up... I think I had around 40kb free in the end. After another reboot, and a manual USB stack start, I had a frozen workbench. Oh joy.

This has to be the equivalent of DLL-hell in windows. I am sure all of these 40-something versions on libraries mean something... I mean... they could be decades apart and completely incompatible. At this point I'd realised I made a stupid executive decision when installing AmiCDFS: there was already a CD0 on the Amiga911 disk in Devs/DOSDrivers and I left it there... for some reason I thought it would be ok. I checked the files again and realised that the CD0 icon on the floppy was the old driver from the floppy, not the driver from the AmiCDFS archive. I re-copied this into Devs/DOSDrivers from the AmiCDFS archive and rebooted. After a reboot, I heard the CD spin up... but no icon on the workbench. I unplugged and re-plugged the CD Drive and ... SUCCESS!

DSC06033

So, at that point I had a USB stack running from this disk... from there I needed to actually install Amiga OS 3.9. Before doing so, I used SFSFormat and wiped the main OS partition that had supported me up to this point... no turning back now!

I had booted off the floppy, so the OS disk wasn't needed and the format went fine. Trying to then run the OS 3.9 Installer off the CD presented me with "Could not load required libraries." What the hell? All this way just to realise that the boot disk doesn't have the right files to allow the OS 3.9 Installer to function? I suppose that's why there is another disk available called the OS 3.9 Emergency Disk II? I seem to have gotten this far, on my own, but for no apparent point as there's another ready-to-roll disk that'll work better.

(Hindsight: That "Could not load required libraries." error was actually because of the Kickstart 3.X ROM!)

Using the Emergency Boot Disk II

Back to square one, I wrote the ADF for this disk to a new floppy. After a reboot it told me that the disk needed to be activated and that this had to be done from a standard boot and not whilst booting this emergency disk. So, back to the Amiga911 with USB floppy that I'd built above.

I swapped the new disk back in and then ran the activation program. It brought up the familiar console screen and told me to make sure that I had an Amiga OS 3.9 CD mounted. This was the case, so I whacked enter. I was then presented with errors...

Turns out that the keyfile for LZX is not on the Amiga911 boot disk. Fortunately, LZX has been freeware for a long time and you can get the licence file from here. Once back in Workbench, I copied it to the Ramdisk:System/System/L directory. Trying again... the disk built! Of course... it had the wrong USB drivers. I did the same steps as above and put the correct drivers in and AmiCDFS. On a reboot, the machine actually booted! Now, this was built off an OS3.9 boot image, so I swapped my Kickstart 3.X ROMs back in. Why not? OS3.9 is correctly supported!

After a reboot, I actually successfully installed Amiga OS 3.9 on my main CF card. It rebooted and all was OK! I then tried to install Boing Bag 1 and got all sorts of errors. Initially it was due to "failed execution 3" and then "Could not load workbench details". Both of these errors indicated a broken "installer". I replaced it with Installer-43_3 and then InstallerNG, but nothing worked... I couldn't complete the installation of Boing Bag 1.

After a little more searching, I realised that I'd put in all this effort for nothing. Amiga 911 actually comes with an Amiga911 Maker which will allow you to configure your boot disk parameters and then write a totally targeted boot disk for your machine!

Amiga 911 Maker

This application is very easy to use and provides a step-by-step GUI for building your boot disk. I had troubles using it with the Kickstart 3.X ROMs, but that could have been due to a broken base OS install. I do admit though, with the same install but with Kickstart 3.1 ROMs, the application worked flawlessly. I'm still trying to work out why that occurs!

a911-makera911-sys-1 a911-sys-2

a911-sys-3 a911-apps

Anyway, step through the application and configure your disk. The questions are all self-explanatory and the processes are numbered. You will need the Amiga OS 3.9 CD mounted to build a boot disk. At the end, slap in a blank or erasable DD floppy and write your disk.

After configuring, I rebooted my machine with the new disk and everything loaded flawlessly! A little painful after the effort spent above, but hey, we're getting somewhere. OS 3.9 installed perfectly and then all Boing Bag's (nearly) worked a treat! I haven't tried to switch back to the 3.X ROMs yet.

A quick note on Boing Bag 3&4

After finally getting 1 and 2 installed, I ran into an error with the combined 3&4 package. If I selected the A1200 as the model, I was presented with an error indicating that No help text specified in line 835. I extracted and re-extracted using both LHA and UNARC, but to no avail... the error kept appearing.

DSC06068

I dug into the files and realised that the Install file was nothing more than a script. The language was actually quite clean and tidy, based on indentation and parenthesis. I scrolled down to 835 and saw an askchoice which was meant to present a prompt on whether or not I wanted to update scsi.device. The askchoice above had an extra line in the definition providing the 'help' text whereas this one didn't. I therefore tried to add it via the ed command. Scrolling down to the line took a while, adding the line was easy, so was saving... but then I got weirder errors from the installer. It seems that ED truncates lines that are too long and does damage to the file! Instead I cheated and edited the file on Notepad++ on windows.

DSC06069 DSC06072 DSC06073

Fixing this line allowed me to install the Boing Bag!

Further software to install

I want to try ClassicWB. There's a specific distro for the A1200 running OS3.9. I assume this installs updated icons... if not, then maybe NewIcons or something similar.

1Sep/160

Amiga 1200: Rapid Road USB

After cross-grading from the ACA1220 to the ACA1221, I'd decided that USB would be an easier transfer mechanism over PCMCIA to CF cards. USB would also allow more peripheral options, as opposed to PCMCIA ethernet cards and CDROM drives.

DSC05097 DSC05913 DSC05914

Whilst purchasing the ACA1221, I also purchased the Rapid Road USB interface. This kit comes with all you need to add two USB ports to an Amiga 1200. It's all been sitting in a box for quite a while as I've been distracted by other tasks.

Hardware Installation

The Rapid Road slots on nicely to the ACA1221. As that the ACA1221 is a smaller size, there is ample room and, once on, the whole kit takes up the previous size of standard accelerators. I did find that the unit didn't seem to plug all the way on. It definitely makes contact though. It might be advisable to somehow provide a backing support beam to keep the Rapid Road in place.

DSC05915 DSC05916 DSC05917

You need to connect power from the Rapid Road to the ACA1221 and then the ground wire to the chassis. The floppy drive screw provides a good location for this. There is no need for any other cabling, apart from the USB plugs themselves!

DSC05918 DSC05919 DSC05920

Some might call it butchering... I call it creative-license. Yes, I didn't really measure or calculate a precise entry for my grinder, but in the end, the USB sockets are firmly installed. I used M4 screws that I had lying around and drilled them into the rubber of the plugs.

DSC05921

Everything fit back together nicely. The trapdoor cover is now an essential part of this Amiga 1200!

Software Installation

The USB stack used is known as Poseidon. You can find the links on the Icomp.de Rapid Road Wiki Page. Once downloaded, get the LHA to the Amiga. Of course, you can't do this via USB yet!

DSC05923 DSC05924 DSC05926

Installation was very next-next-finish. The default options put everything in the correct locations. Once the installer finishes, the USB stack is actually loaded! I had already put my USB key into the slot and the bloody thing showed up on the desktop. It also made a really funky space-ship sounding noise... turns out this happens upon device insertion.

DSC05927

At this point, I thought I was done. I rebooted the Amiga after playing with files on the USB key. Upon reboot, I got an error from the startup script: PsdStackDLoader not found. Turns out that this script is created once you've gone through the configuration. This is done via the Trident Prefs file which you'll find on the drive you installed Poseidon to.

DSC05928 DSC05929 DSC05930

Run through this, it's all pretty self-explanatory. As long as you chose the correct driver during install then it'll be selectable. It should come 'online' after configuration. Make sure you save all your changes at the end. I didn't configure any further classes or devices.

DSC05931

On the next reboot... my USB Mass Storage Device was mounted again.

USB CD-ROM Drive

I have an external drive and tried it... unfortunately it needs more power than the USB ports put out. I'll be finding a powered hub shortly and will test this again.

DSC05932 DSC05935 DSC05936

The hub in the middle didn't help... it just chewed more power as I didn't have an adapter for it! Turns out that buying a powered hub didn't help either... I needed a specific cable that provided two-ports-worth of amperes to power the CD unit.

DSC05937 DSC05939 DSC05941

Ok, we're now recognised... I can see the CD drive in the Trident prefs tool... but we don't have a CD mounted on the desktop? What gives?

DSC05943 DSC05944 DSC05945

Ahhh... big hint there. I needed to download and install AmiCDFS. After doing so, and rebooting, I had a CD mounted on the desktop! I got lazy whilst installing AmiCDFS and just dragged the C, L and LIBS folder to OS:. I expected this would merge the folders, and it did, but it also overwrote the icons! Must be stored in folder metadata somewhere.

DSC05946 DSC05949 DSC05950

A quick check of what was on the CD...

DSC05951 DSC05953DSC05954

DSC05957

...and then a great time was had by all destroying the landscape!

4Aug/1626

Commodore 64: Using an ancient BW TV

Using the Commodore 64 on the main TV produces a really great picture over the composite cables, but using it via a converter to VGA or via RF is a little dicey. I like the idea of 1:1 picture when using composite, there's no need to covert the signal. I also don't always get to use the main TV, so I went hunting for a suitable display for the Commodore 64.

DSC05296

DSC05302 DSC05303 DSC05297

Turns out that last weekend I was in luck. Whilst rummaging at the local Trash and Treasure I stumbled across a Samsung LCD TV (RF, VGA, Composite and Component in!) and then... the holy grail... a tiny, portable, black-and-white CRT Television! Check out that hideous battery pack.

It happily allows you to scan the VHF/UHF airwaves; unfortunately there aren't any signals broadcast in this spectrum anymore. Actually, at the low end of VHF I got a local radio station, but no picture. It has the option for an external antenna, but this used a mono 3.5" audio jack.

Hooking it up to the C64

The external antenna jack was easy to work with. Opening the TV (runs on DC voltage, but BE VERY CAREFUL WITH CAPACITORS NEAR THE TUBE), I inspected the circuitry and found that the in-built telescopic antenna was also wired into the jack. This makes sense: plugging in the external antenna disables the internal antenna. The jack functions as a nice routing switch, choosing between sources when the jack has a cable plugged in.

DSC05305 DSC05306 DSC05308

DSC05309 DSC05311 DSC05313

DSC05318 DSC05320 DSC05321

With this knowledge, I chopped up a 3.5" audio cable that I had spare and worked out which wire was ground. As expected, it turns out that the shielding was ground and the very tip (the white audio wire, red is unconnected) made contact with the RF input pin and disabled the internal antenna. With this, I then cut an RCA lead and joined the relevant cables. The C64 has a single RCA-style port for the RF output. Plugging the wire together, I then started scanning the airwaves.

I vaguely remember, from back in the day when tuning in a brand new Nintendo Entertainment System, that most consoles output a frequency somewhere near UHF channel 60. I happened to start at the 'top' of the UHF band, but after winding the dial to the other end I had a picture!

DSC05323 DSC05326 DSC05338

There was further tuning on the side. Contrast, brightness and V-Hold allowed me to get quite a clear display in black and white, of course.

The fun part now was taking a quality picture of the tube. Shutter speeds are usually way too quick to see the full image... the camera can easily beat the scanline. I therefore slowed the camera down. Using this theory, I also had fun and sped the camera up...

DSC05329 DSC05328 DSC05330

Hah... nice... very easy to see how the tube works. That Horizontal scanline illuminates a bunch of dots/pixels and does it fast enough to resemble a whole picture to the slow human brain.

Testing a game

My first cartridge was acquired from Game Over? in Amsterdam. This is 'Rat Radar Race', a game I'd never heard of. It was purchased because I didn't want to leave the shop empty-handed and, for quite a while, I've wanted to test out how cartridges work.

DSC05143 DSC05335 DSC05336

I plugged it in and turned on the machine. I was amazed to find that it booted straight into the game. Very seamless and very fast! With floppy disks and tapes you actually had to enter BASIC commands to boot. This method is much nicer!

The best part? Audio! The RF cable was dodgy, but functioning quite well. The picture and hideous audio was being output rather well. I tried the game for a bit: You're a mouse, there's three of you... you navigate a maze by holding down the arrow of the direction you wish to turn next. Scaling the maze, you pick up cheese. If you hit a cat or a fellow 'blind' mouse then you fail. The theme music is actually the 'three blind mice' 'melody'.

RF Modulation/Demodulation

Just like an old dial-up modem, the RF mechanism for getting your console to display on your TV is inefficient. RF was meant for radio waves; the goal was to be able to transmit images over long distances. The tuner in the TV is therefore capable of tuning in to differing frequencies, producing different channels on your display.

This is overkill if your console is sitting right next to the TV. There is no real need to convert to a lossy format, only to make the TV find the signal and convert it back to a displayable format. Hence, TVs later added extra inputs for 'direct' signals. After RF came composite, SCART, Component, VGA, DVI, HDMI, etc... The Commodore 64 can actually produce a composite signal (as I was using on my other TV), so I wonder how hard it would be to provide a direct composite input into this little TV?

Bypassing the RF input and providing Composite

Turns out that this is totally achievable. The job of the 'tuner' circuit in the TV is actually to produce a composite video signal to rest of the video circuitry. The main question is: Where do I inject the composite signal from the C64 without destroying the TV, the C64 or endangering myself?

Our first step is to inspect the circuitry and determine what ICs are used. Next we'll check out the datasheets and then try and work out a method for signal injection. The signals we are talking about are available 'naked' on the back/front of most audio/visual components, so shorting them out is possible in the real-world and therefore shouldn't damage our equipment if we happen to do so. The main issue is when you wire up the signal to a power rail or other high-voltage feed... such a process wont end well!

I would first recommend that you review a few BW TV Schematics to understand what basic components are used. Ralph K has a great article: TV and VCR tuner modules which has a schematic for a tuner that shows how the fundamental components are connected. The tuner IC actually seems to be a mirror of the one used in this TV... either way, it still helped with the circuit tracing.

DSC05386 DSC05388 DSC05389

A quick scan of the circuit board in this TV shows that it was built on a suite of Samsung chips. There's a KA2133 - 1-Chip Deflection System that provides the synchronisation for the tube. There's high voltages down in this area, so be very careful around the large capacitors!

Up under the tube is a KA2101 - Linear Integrated Circuit (TV Sound IF Amplifier). Not exactly what we're after, but we'll need this after we get the video fed in.

Top left of the board is the RF 'tuner'. Actually, the left-most box is a de-modulator. It does the opposite of what the RF modulator inside the C64 does. Unfortunately, it's not as simple as the modulator; it needs to be fed in variable parameters to determine the exact frequency to demodulate at. The C64 merely has a fixed set of parameters to modulate the signal.

You can see the wires running from the front panel into the space between the demodulator and, what I believe is, the tuner next to it on the right. This tuner is also shielded, but from the underside of the board I can see it has an IC in there. With a good torch and a little more disassembly of the chassis I was able to read the model of the IC. It is a KA2912 - Video IF Processor for BW TVs. Bingo. That datasheet also shows that Pin 3 is the video output.

The underside of the circuit board also has the pin numbers for the IC. How awesome for us? And for the assembly line lemmings who constructed it. Thanks to PIN DETAILS OF IC A-Z, BASIC ELECTRONICS AND ANTENNA : KA2912, we can see that it actually outputs a composite signal!

Injecting an external composite signal

From here, we're going to do damage to the circuit board. The first step is to bare the trace running to pin 3 by scratching the protective coating away. I've used my pocketknife to do this.

DSC05400

DSC05401 DSC05404 DSC05406

Next we need to actually cut the track. Use the sharpest tool you have and scratch the track at a perpendicular angle, slicing a gap into the board. Make it a little wider than 1mm. A flat-head screwdriver can be used once the initial cut is in place. Now that you've got pads to solder to, tin the areas that are bare. Make sure that you don't have any solder bridging the gap! At this point I then turned on the TV to test it. No picture? Perfect! The signal from the UHF/VHF tuner has been severed.

At this point, as a test, we're going to hook the composite RCA plug directly into this track. It's better to find out as early as possible if we've got the track or location wrong. If there is no picture when you do this, then you'll need to dig further into the datasheets and determine a better location to cut in the signal.

DSC05410 DSC05412 DSC05414

I hooked up the trusty C64 and ... it worked! Well.. nearly... the picture was scrolling and buzzing awfully. Turns out that there are two GROUNDs in on the circuit board. There's the 'signal ground' and 'supply ground'. If you, as I did with a paper-clip, ground the incoming signal to the supply ground then you'll get a shit signal. I then tried grounding to the other signal ground and got a much clearer picture. It was still rolling though.

BW TV Animation

What could be the problem? I quickly rotated the V-HOLD trimpot and had no luck... picture still rolling. At this point, I should have stopped ... breathed ... rolled the trimpot slowly... and tested it properly. But I didn't... instead I went and re-adjusted EVERY pot on the board. In fact, I didn't keep an initial record of what they were all set to and COMPLETELY de-configured the TV. I then spent another night re-configuring based on guesses from the photos I took for this blog. Painful... There were also fragile wires around the tuner circuit of which I managed to break free of the circuit board; these then required resoldering and reinforcing. Finally, I was nearly back to a functional TV again, the final issue being that a trimpot I replaced was grounding against the tuner RF shield! After fixing all these mistakes, I had a rather reliable picture.

DSC05454

Now that this was certain, I went about inserting a switch that selected between the antenna plug or the composite input. This was a DPST switch, as I wanted to switch the mono audio as well.

DSC05460 DSC05466

Now that I had a quick way to switch between both inputs, I plugged in both the RF signal and the Composite from the C64.

DSC05470 DSC05472

For the standard BASIC screen, shown above, the picture was very nice on composite (first picture) and quite blurry on RF (second picture). Either way, they both showed well.

DSC05467 DSC05469

Above is the display difference of a game cartridge. It actually seems that the cartridge is changing how the C64 outputs the picture! The first picture is composite and seems to be over-scanning? The second is RF and is happily rendered within the bounds of the picture tube. I wonder if that's PAL vs. NTSC or some other timing issue. Or maybe because I happened to alter all the trimpots and de-configured the TV. I'll keep digging.

Audio

The same trick was then applied to the sound channel output by the KA2101 - Audio amplifier. Documentation, other than the datasheet, on the KA2101 wasn't so easy to find, so I searched for similar devices. Turns out the MC1358 is a clone (let's not get into which one was created first) and there are quite a few circuits available online as examples of audio amplifiers.

If you look here at TradeOFIC, you'll see a stereo amplifier. We don't need 2 channels, but we do need to know where to inject our composite audio signal. On the mid-left of the diagram, you'll notice that they have an input select that cuts the line from Pin 8 of the MC1358 and splices in audio from an external plug. I love it when it's this simple! There is a capacitor on the other side, so we'll check our circuit and cut in after that if we have one too.

DSC05478

DSC05482 DSC05483 DSC05486

DSC05489 DSC05490 DSC05491

The circuit was cut and the wires were hacked on. I then fed via the external audio input via the same DPST switch that I used for the audio. I only need to switch one wire as ground is common (remember to use SIGNAL ground!) and the audio is mono, so there is only one audio and one video wire. Having a TPST switch would've allowed for 'future expandability', but I cannot see myself installing stereo speakers into this little beast.

The best part? It seems that feeding a proper audio signal in with the composite video stabilised the video signal! Look at that crisp picture!

Looking back...

This was not an easy task... this post was written around 4 nights after I started pulling apart the TV. Take your time with old electronics. The case was brittle and the circuit board had been repaired and re-soldered.

DSC05394 DSC05395 DSC05398

One thing I didn't mention above: I had to replace one shotty capacitor and I destroyed a trimpot. Don't forget that flexing wires around will break their solder joints... so expect to re-tin the majority of contacts under the board. Go nuts and replace/re-tin ANYTHING that looks suspicious!

Capacitors are a standard item to replace. Cell batteries are usually next in line for leaking. You're bound to find all sorts of issues with vintage items. Good luck!

Other References

28Jul/160

GAME OVER? Amsterdam – Retro Games Store

GAME OVER? has existed for over 14 years, tucked away in a side-street in central Amsterdam. I was very happy to hear this when asking the owner about the history of the shop.

DSC04719

game-over-map

This shop is bursting at the seams! Wall to wall of amazing retro goodness. You'll find everything here from VIC20/C64/Atari through to XBOX/Gameboy/PlayStation. The window is full of relics and will get anyone interested inside. Don't be fooled into thinking that what's on display is all there is to offer... If you know what you're after, then ask away and have the owner dig bits and pieces out for you.

DSC04720 DSC04721 DSC04722

I happened to want one of the controllers in the window; turns out they're all damaged and just for display. I was then lead to a draw, on the left as you walk in, and a motherload of C64/Atari items was presented. Pretty ... much ... heaven. The owners are really friendly and let me take pictures inside the store... so do chat with them; their wealth of knowledge was very helpful!

DSC05140 DSC05141 DSC05143

As you can see from above, I picked up two Atari controllers and my first ever C64 cartridge: Rat Radar Race. Am still to test it, but have been told it is in working order. I couldn't trek half-way across the globe and not purchase a few goodies when they were there in front of me. I actually tried a few of the 'markets' around Amsterdam but found zero retro gaming items.

Check this shop out if you're ever in Amsterdam!

26Jul/160

AmigaDOS to Windows CMD/DOS Reference

Recently acquiring an Amiga has lead me to realise that not all command prompts are equal. *NIX shells aside, I had expected *DOS prompts to act on a standard set of commands... turns out I was gravely mistaken!

One imporant point: When copying from Windows, long filenames will have a '~1' at the end. The 'tilde', to AmigaDOS, is actually a wildcard. So when you're deleting, etc... it'll match ALL THE BLOODY FILES and delete them all on you. Therefore, when copying to Amiga, make sure that all filenames are in the old-school 8.3 format. See more on pattern matching here.

Therefore, I present to you the following reference guide. I've provided the mapping, where possible, between standard Microsoft *DOS commands and their equivalent AmigaDOS commands. Find a full list of available commands here.

Microsoft DOS AmigaDOS Notes
cd .. cd / Slash is not the root folder!
cd dir_name dir_name You can actually just type the directory name. This makes perfect sense, as you cannot have a file the same name, so it just changes to that directory!
copy A.txt B.txt copy A.txt TO b.txt Note the TO
copy A.txt other_dir\B.txt copy A.txt TO otherdir/b.txt Slashes are reversed!
copy ..\A.txt . copy /A.txt TO A.txt Single-slash to get to parent directory
copy x:\zz.txt . copy x:zz.txt TO zz.txt Note that drives are rarely one character on Amiga
copy z:\docs\readme.txt . copy z:docs/readme.txt TO readme.txt No need for a '/' start after the drive colon
dir *.txt dir #?.txt Yes, the wildcard is #?
dir /p list Amiga dir doesn't format any other way. Use list.

Good luck.

25Jul/160

Amiga 1200: ATX Power Supply

Amiga 1200s are ancient now... if you're having phantom issues with hardware or software then a crappy power supply may be to blame! Adding extra hardware, overclocking and otherwise modding these old machines also puts undue strain on their ageing power supplies.

DSC05022 DSC05023 DSC05024

DSC05025 DSC05028 DSC05030

Due to this, it's best to prevent problems and provide a fresh and powerful source from which the A1200 can drain as many electrons as it wants.

Wiring up an ATX Power Supply

This is very straight-forward. All ATX supplies provide the required wires for the Amiga motherboards. Unfortunately, they also provide 100 other cables of which we don't need.

Ian Stedman's site has all the information you need to get the power supply hooked up. I followed the instructions and had no issues at all.

DSC05034 DSC05036 DSC05037

If you're installing this in a tower case, then you can easily hide the extra wiring. If you're still using the 'keyboard' case, then you may want to find a way to discard all the extra cables. One method might be to de-solder or cut them right back at the power supply main board. Just be careful if you're opening it.

The wiring for the cable goes as follows.

ATX Power Supply Red Yellow Blue Black not connected
Component +5v +12v -12v Ground Shield
Amiga 1200 Red Brown White Black Yellow

Note: Don't forget to connect green from the ATX supply to ground! This is the soft-power latch that needs to be grounded for the supply to turn on.

DSC05038 DSC05040 DSC05043

I entirely recommend you confirm the wiring from your Amiga power cable is wired as above! Also make sure that you test the cable prior to plugging it in to your Amiga!

After a quick test, I plugged it in and the A1200 purred away. Unfortunately my PCMCIA Ethernet issues still continued!

22Jul/162

Amiga 1200: ACA1220 + PCMCIA Network Cards

This has been a battle. I'd purchased the A1200 and was playing games... but realised I needed more RAM. So I found an Apollo 1220 online and purchased that. Little did I realise this was an actual Apollo.. I had initially (mis)thought that it was an ACA1220. Not wanting to admit defeat, I ran with it anyway. My machine now had 4mb of RAM, instead of 2mb, and I was able to do more things.

DSC03793 DSC03794 DSC03797

From there, it was time to connect to the local network to ease file transferring and also enter the world wide interwebs. This was to be easy; find an appropriate PCMCIA card and configure the software. And it worked fine, I purchased a compatible card and got the Amiga online. Unfortunately, with only 4mb of RAM, I found that I only had around 100kb free once connected... no good.

Hunting for an accelerator... I wrangled a swap of my Apollo 1220 + cash for an actual ACA1220. Hurrah! It arrived.. but then I had to head overseas for 3 weeks... so I've only just gotten back to it.

DSC05097 DSC05099 DSC05100

Installing it, I booted into my KS3.X + OS3.9 WB and attempted to connect to my access point. This was the same CF HD, same configuration, same everything that had got me online before. Unfortunately, this time, whilst running WirelessManager (the tool that comes with Prism2v2) my Amiga 1200 locked up (froze) as soon as it attempted to talk to the real world.

Diagnosis time. The only thing that had changed since I was previously online was the accelerator. The ACA1220 is very much targeted at people that don't want to configure things and comes stock with a very compatible configuration. It even boasts "PCMCIA Compatible." I've got a few more cards on the way also... just to determine if my setup works with non-wireless cards. There a forum post here where the author has successfully used PCMCIA-CF adapters, but not wireless cards.

Further into the internet and I came across this post describing how RESET is called during initialisation and that the author created a home-made reset switch for the PCMCIA socket and managed to baby the card into operation. The computer would still freeze at initialisation but, from what I can tell, he got it up and running. This makes me think that a proper hardware RESET fix is required. There's two mentioned below.

TL;DR: It doesn't work. Don't try and use a PCMCIA network card with an A1200 that has an ACA1220 in it! I have successfully used a PCMCIA-CF Card adapter and transferred files... but any network card I try locks up the system! (Update: The ACA1221 works fine!)

Here's a list of fixes I've applied to try and get this thing working:

Power Supply

I had a hunch that the Amiga was struggling since I'd added the PCMCIA, an Indivision AGA-MK2CR and the ACA1220. There was possibly not enough current available to handle them all. After purchasing and wiring up an new and way-overpowered ATX power supply, I still had the same issues. Either way, here's the article if you want to learn how to wire up a new power supply.

Motherboard Capacitors

Further to inconsistent power supplies, capacitors can cause phantom issues in electronic systems. I've just watched a great video series on the repairing of a Sony-Nintendo Super Nintendo CD Prototype. You'll find the videos here: Part 1 and Part 2. Ben Heck managed to get the CD Drive component working again by replacing faulty capacitors.

This is a known issue with the Amiga 1200 and AmigaKit has everything you'll need to replace them. If you don't want to replace them yourself, then they also provide a capacitor replacement service.

I've ordered the pack for the A1200 and I'll update again once I've done the swap.

Motherboard Timing issues

There's articles everywhere (including my own one here) on this... but the Commodore manufacturing employees seem to have gotten confused on the assembly line and installed some components where they shouldn't be. Ian Stedman has a great article on how to fix this. It doesn't directly mention the ACA1220, but I applied the 'ACA' fixes anyway... to no avail!

Kickstart ROMs

Thinking that my Cloanto 3.X ROMs could be the cause, I tried to swap them out for the original KS3.0. I couldn't boot my main HD, so I used the NetworkBootDisk here. No luck... event the SetPrism2Defaults app locked up the machine when trying to configure the card.

Amiga OS Version

I had OS3.9 on the CF Card and thought any number of supporting libraries might have been causing conflicts... Unfortunately they weren't. Cold boots with the boot disk mentioned above didn't help at all.

IDE to CF Card Adapter

There was a forum post here that mentioned the IDE to CF Card adapter and/or brand of CF card was the issue. I removed my altogether, but the machine still locked up.

CardPatch & CardReset

No combination of either of these, before or after SetPatch, did anything. There's also the resetpcmcia flag on acatune, but that didn't help either. Every now and then the PCMCIA card would stop the Amiga from booting, but this didn't worry me at all... you just need to pop it out and in again quickly to get it to continue.

Hardware PCMCIA Reset Fix

Just to quell a few advisors, I applied this fix as well... it did prevent the reset issue when the machine wouldn't boot... but had no effect on the card initialisation freeze. For those playing at home, connect a 10uf electrolytic capacitor from R715A to pin 5 on the Gayle chip. Further instructions are here.

DSC05088 DSC05089 DSC05091

'Gayle Reset Fix'

There's another reset fix for the IC that controls the PCMCIA Port, of which I soldered the capacitor to in the attempt directly before this. The IC is known as the Gayle chipset and Retro Kit came up with a nifty solution for the issue. Just like the Indivision aga-mk2cr, this fix involves a socket for the IC that slips on backwards. It inverts the reset signal so that PCMCIA cards will function correctly.

Here's the same fix from Amiga World in German. This time we get the component list. I'm going to purchase the components tomorrow and give this a go. If it works, then I'll buy the real thing from AmigaKit.

DSC05127 DSC05128 DSC05134

The parts cost less than AUD$1.00. The installation was very easy... the outcome was: waste of time. The freezing still occurs.

ACA1220 timig issue?

Is there a chance that the speed of the ACA1220 is impacting the function of the PCMCIA chipset? There's an option to overclock the card... a solderable SMD resistor. It's actually a 0hm jumper... so it just needs to be bridged rather than another resister put in its place. I could attempt to over/underclock the accelerator card. This would possibly limit the speed of my machine, but would still give me the RAM. Of course, it'd void my warranty.

DSC05093 DSC05094 DSC05096

I clocked the card from 25mhz to 30mhz and the freeze still occurs. I should probably try slowing it down...

Interrupts

IRQs are a part of every computer. You'll find that most hardware has a direct line to the CPU to indicate that it desperately needs to do something. These are known as Interrupt Requests. They do exactly that; interrupt the CPU and then run the specific code that the programmer has attached to handle the interrupt. If there's no code there, then there's a problem... as the interrupt will therefore lock the CPU. Currently... this seems like the most probable cause. The WIFI card or PCMCIA chipset is causing an interrupt of which is not handled.

Looks like I can redirect debug output... might help with diagnosis. Further information here. Seems to all be for OS4 though.

I'll keep digging and update this as I find out ways to catch these unhandled IRQs.

Give up and use a USB to Ethernet adapter

This is a valid answer... but you'll need to buy a USB card first. I've now purchased a Rapid Road interface to go along with the ACA1221 that I mention next. Once they arrive I'll experiment with USB to Ethernet devices. I just happened across one at Trash and Treasure this morning. Got a 2-button joystick and a Netgear FA120 for AUD$10!

Give up and try the ACA1221

The ACA1221 has half the RAM. It actually comes crippled, and you then purchase licences to unlock features... a very interesting model. I ended up purchasing this model accelerator and the wireless PCMCIA card works fine!

Other Sufferers

Amiga 1200 freezing/crashing issue
Trying to get my a1200 online using my NetGear MA401 WiFi card
WLAN Problem
Вот, купил себе Амигу... :(
PCMCIA nie działa (albo coś koło tego)
A1200 freezes when using PCMCIA Network card

19Jul/160

Amiga 1200: Timing Fixes

I've recently been trying to get a PCMCIA wireless card going in the Amiga 1200 and have had no luck. Every time I try to initialise the card, the entire machine locks up. You can't even move the mouse pointer.

Initially, I thought it was drawing too much current from the ageing power supply. To remedy this, I purchased an ATX power supply and wired it in (I'll post an article on this shortly.) Unfortunately, this wasn't the solution.

After a lot more googling, it seems that my A1200 might have the dreaded 'timing issues' that are mentioned across the web. It seems that, during construction of these machines many decades ago, some were fitted with capacitors and resistors that weren't meant to be in the final design. The motherboards actually have the spaces for all of these components, so I can imagine it would be easy for an employee on the construction line to accidentally insert components that were part of a draft design and not meant for the final.

Note that a system without acceleration will (most often) not realise any of these timing issues. The symptoms really only appear once you start pushing the hardware.

Timing Issue Symptoms

There's a really good forum post here that details a lot of motherboard/accelerator combinations and the successes/failures that people experienced. In the end, the result is a total crap-shoot! It seems total luck-of-the-draw as to whether your accelerator will work with your motherboard.

Timing Issue Solution

Fortuantely, you shouldn't despair just yet. There are known solutions for all revisions of the Amiga 1200 motherboards and I'll list (and attempt) two of them below.

Your solution will depend entirely on what accelerator you have and what motherboard revision it's plugged in to. There are two basic groups of accelerators (ACA and Apollo) and instructions for both methods involve removing/adding SMD components. These tiny little resistors and capacitors are an absolute nightmare to deal with and will require a good soldering iron and a VERY steady hand.

Searching around the web, it seems that everyone has their own theory as to what solution is best for what accelerator. It was actually quite hard to draw a concise picture as to what was required for my ACA1220.

For both Apollo and ACA, Ian Stedman has a great wealth of knowledge here which includes the required fixes for both.

ACA themselves also have instructions on timing issue fixes. They only seem to mention the removal of items though. Reading other forum posts, it seems that this is only 'half the job' for a proper timing fix.

There's also a summary of the ACA fix in this thread. I'll quote the information here to make sure it doesn't go missing:

FOL 16:54 01 January 2013
To help others, this is the full fix that should be applied.

E121R and E122R need to be changed to 60ohm Ferrite Beads.
E121C and E122C need to be added (22pf), if not already.

Only E125C should be removed (insome cases you need to leave it). E125R, E125C E123C and E123R should be present.

Some rare cases, you need to leave E125C on and remove E123C.

Note that the ferrite beads mentioned above are 100ohm? But the ones on Ian's page are 60ohm?
Also, note that on the second-last line, I've changed it to what I believe is the correct component reference. It initially indicated that 125C should be removed, but then says that it might be needed... then that it should be present. I believe that the final three items listed should be E125R, E123C and E123R. Not 125. (Actually, if you read the entire forum post, you'll see that FOL corrects the error as I have above.)

It's minor differences like this that can be REALLY confusing.

Following ACA's Recommendations

The rules are meant to be simple: remove four capacitors. Well, turns out these are tiny SMD components and the removal wasn't as trivial as I had hoped. Make sure you have the time and space to focus.

Removing SMD capacitors requires you to heat up the entire item and lift it in one go. Do not try to heat one side and then the other. I used a pair of tweezers, grabbed the capacitor in the middle and then placed the soldering iron through the tweezer grip. The goal was to make sure that the soldering iron would touch both sides that needed to be melted; adding a little bit of solder to the tip of the soldering iron helped as well. Once hot enough, you can then lift the entire lot and the capacitor should be freed.

I actually had the whole SMD component lift with the soldering iron and stick to the tip most times. This probably damages them entirely, but I had a new set of components to put in place, so there was no harm.

After removing all four capacitors... I tested the PCMCIA card and it still locked up! Boo hoo... What to do next? FOL's next advice is as follows:

FOL 15:27 01 July 2013

Originally Posted by marcel21674:
ok, opened up my 1200 this morning. Just to prepare, for some upgrades the next couple of days.
After removing the RF-shield, i thought of removing the E123C and E125C capacitors, but surprise surprise, the already have been removed....
So my rev.2B motherboard does have some timing fixes, but it didn't fix the issues with the aca1232...

Pretend it doesn't.

Add All four components, then do fixes as if your doing it for the first time.

Change E121R and E122R to 60ohm Ferrite Beads,
Add E121C and E122C 22pf caps.
Remove E125C, test A1200. If its all fine, leave it.
If E125C doesn't help, then readd E125C and remove E123C and test again.

I your still having trouble, then try removing both E123C and E125C, then test again.

The forum thread ends with the original poster indicating that they'll try the fixes. Of course... no resolution is mentioned... I might sign up and ask how it all panned out. I'll also try the fixes myself.

The best part about the fixes is that, despite a few minor capacitor values (22pf vs 27pf), the instructions map directly to Ian Stedman's directions.

Following Ian Stedman's Directions

Ian's page indicates that the following changes are required for all Amiga 1200 motherboard versions when using accelerators manufactured by ACA. I've added links to the relevant components at Element 14.

E123C E125C E123R E125R E121R E122R E121C E122C R118
Try fitting 22pF SMD Capacitor if it does not work Fit 22pF SMD Capacitor Fit 27ohm SMD Resistor Fit 27ohm SMD Resistor Change to 0.1ohm Ferrite Bead Change to 0.1ohm Ferrite Bead Add 27pF SMD Capacitor Add 27pF SMD Capacitor Leave alone

Once your care package has arrived, you can prepare your motherboard for surgery. Do be careful extracting the motherboard from the casing. Make sure you unplug every component and unfasten every screw. Excessive force is NOT required.

DSC05071 DSC05072 DSC05078

The components are absolutely tiny and come in ribbons. The plastic sheet can be peeled back, allowing the components to pop out.

DSC05062 DSC05065 DSC05066

Fitting all the components is a nightmare... but I managed to do it with my crappy soldering station.

DSC05075 DSC05076 DSC05081

That's the ferrite cores... installing them was just as hard. I found that soldering one side, then the other and finally returning to the initial side worked ok. The issue would be that it was easy to solder them in at a bad angle and then re-touching meant throwing the components completely out of alignment.

All changes were made... but the PCMCIA card still played up. Turns out the timing issues aren't my main concern.

24Jun/167

Commodore 64: Fixing RS-232 Serial Limitations

This is going to be a bit of a rant, so I apologise in advance. I have just spent a good 75 hours getting the C64 to talk to an Arduino via RS-232 and each step of the way has been painful. Initially, communications were sorted and data made it across to the Arduino. All wasn't as it should be as I realised that the character mappings (PETSCII vs ASCII) meant that the data had to be translated. Once that was sorted, it was a matter of sending data back. Again, character mappings were required. Past this, I then wanted to send 64-bits of raw data. Not characters, but 8-bits-to-a-byte raw data as I wanted up to 64 sensors and therefore only 8 bytes to transmit this. Turns out that the C64 is hard-coded to transmute the serial value zero to something else...

Diagnosing the issue

I'd already built up a large-ish application on the C64 for controlling the trains. There was also a large amount of code on the Arduino side. Due to this, any support libraries or includes or other interrupt-hacking routines could've been interjecting and mangling data. After a lot of to-ing and fro-ing, compiling on windows and switching to SD card... I got jack of the speed of which I was able to debug on real hardware.

Fortunately, VICE came to my rescue. Not only does it have a debugger, but it also emulates the RS-232 User Port Serial and shit... it even reproduced the error! Let me show you how to set that up...

Configuring VICE's User Port Serial

rs232-userport-settingsOpen VICE and choose Settings -> Catridge/IO Settings -> RS232 userport settings.... Enable the RS232 userport emulation, leave it as device 1 and set the baud rate to 2400. Hit OK.

rs232-settingsBack to Settings -> RS232 settings.... We want to edit RS232 device 1. Fill in the text box with the relevant IP and port of the machine you wish to communicate with. If you're going to use my TCP server below, then enter 127.0.0.1:25232.

Close VICE. Next time you open it, VICE will attempt to connect to a TCP Server listening on your localhost IP on port 25232. You can configure this to whatever you want, but we are going to use the default. VICE will then treat the connection as RS-232 and provide any data received to the internal C64 user port. It will also send out any data sent to the user port via this channel.

Now that we're done with the settings, we need to give it something to connect to.

TCP Server in C#

Download the code here. I've rigged up a very simple C# TCP server for VICE to connect to. The TCP server must always be loaded first, otherwise VICE will continue silently and never send out any data. The code is also overly-primitive and, upon closing VICE, the TCP server will need to be restarted prior to starting another instance of VICE.

simple-tcp-console

Once running, you can use the 1-8 keys to set the bits of the byte to be sent. Alternatively, pressing any keys of the alphabet will set the byte to that letter in ASCII.

Finally, hitting Enter will transmit the byte.

C64 RS-232 Serial Test Program

Grab the Serial Test Application here that I wrote to test the RS-232 serial port on the C64 using Johan's driver. There's a batch file in there that you can use to run the program. Just make sure it knows where VICE is.

Make sure the TCP Server is loaded first, then run the batch program. It's set to auto-start the binary. If this doesn't work, then you can open VICE and via Settings -> Peripheral Settings... configure the directory where the binary is. You can then LOAD it as per usual.

peripheral-settings

Once loaded, you'll be in the app. It's pretty straightforward and will just print out the data that has been received.

c64-serial-app

Make sure that the TCP Server has shown that the connection has been established. You can now press the keys as per the instructions above on the TCP Server and send data. At the bottom is a timer and a number of bytes received. As each byte comes in, it'll be displayed up the top. It'll also be numerically represented down below, next to in:, above the clock.

At this point, type random letters from the alphabet and send them to the C64. You'll note that lowercase get translated to uppercase thanks to the ASCII to PETSCII translation. Tinker with the 1-8 keys to set the relevant bits in the byte to send and then hit enter. Watch that 1 = 1, 2 = 2, etc... until you try to send a raw zero... bugger.

Debugging the problem

Ok, we've now worked out that, even in the land of emulation, sending a zero to the RS-232 serial port on the C64 produces an 0x0d. This rules out the 'client'... both the Arduino and my TCP Server send raw zeroes and both VICE and a real C64 render the wrong character once received. From here, it could be the custom driver, the cc65 support libraries or something much more evil.

Debugging on real hardware is something I'm scared of... I'm so used to multiple windows and multi-tasking that I'd like to do it in a more comfortable environment. Thankfully VICE has a monitor that can help us. Open this up via the File menu and prepare to delve into the land of assembler! Note that, when open, the C64 emulation is paused.

vice-monitor

Once the emulator and application are loaded, choose View -> Disassembly Window. You'll get a little window showing the entire memory of the emulated C64, disassembled. This means that VICE, with it's knowledge of C64 6502 CPU op-codes, has translated the raw memory into known commands. Fortunately, it also has information on the mapping of the memory and therefore does a very good job of this translation. Unfortunately, there is no search command... so we will need to scour over this to find what we are looking for.

What are we looking for?

The million-dollar question. The serial test app that we've compiled for the C64 (and executed in VICE) is based on the sample code by Johan. It also includes his 2400-baud serial driver. Looking at his source code, we can see the routines that are called when we call the ser_get function from our main loop. If you browse over to his source, you'll find the relevant lines in driver/c64-up2400.s.

GET:   
        ldx #2
        jsr CHKIN
        jsr rshavedata
        beq GET_NO_DATA
        jsr BASIN
        ldx #$00
        sta (ptr1,x)
        jsr CLRCH 
        lda #<SER_ERR_OK
        tax 
        rts

vice-disassemblyThe snippet above was copied on the 24th of June, 2016. This code has hopefully been updated by now, but what you see above is the function, as it was back at that time, which reads data in from the RS-232 Serial port. I can't fully explain each line, but what we can do is find this chunk of code in the disassembly window. Unfortunately, we'll be doing this by hand as I don't know a better method to search for it.

After a lot of scrolling... this code has been found in memory location $238A. ldx #2 is seen as LDX #$02. The further jumps are visible, but their happy names are gone. Instead we see the memory addresses of each of those functions. You can see that I've also clicked the row in question. This sets a breakpoint, represented as a red highlight on the row.

Triggering the debugger

From here, we can actually close the debugger. Make sure that the red row is set prior to closing the main Monitor window. If you just did this, then you'll find that the debugger window popped back up straight away and now our red breakpoint is a lovely shade of teal. Teal? What happened to Red? In the disassembly list, a blue line indicates the location of the next line to be executed. Ours is teal because it's a set breakpoint AND it's the next line to execute. If you're bored, click the line and it'll turn blue. Click it again and it should return to teal.

Ok, we've triggered it... but why? No data was sent down the channel! It turns out that, if you look at the source above, there's a hint on the line with GET_NO_DATA. The ser_get is called from our code on each program loop; it returns a SER_ERR_NO_DATA when there is no data... so this line we've broken on is too early in the driver code. We really want to set a breakpoint at the first line executed when there is data.

So step through the code. To do this, press the 8th button on the toolbar in the Monitor window. Press it a few more times and watch the execution. We're currently 'stepping over' functions; the two JSRs might well send the program counter off into other parts of memory and execute code, but we don't care. Once you're on the BEQ GET_NO_DATA line, press it again. Note that we now jump down to the location of GET_NO_DATA and exit out. We can assume that this jump is the significant point where, when data exists, the execution continues straight through and does not jump.

debugger-at-char-received

Now that we know where this junction is, we want to clear our previous breakpoint and set one on the line directly after BEQ. Set the breakpoint and close the Monitor. It should not pop back up this time.

Viewing the data coming in via Serial

Ok, we've set our breakpoint in the driver and it hasn't triggered yet; let's hope it does when data is received. To test this theory, we'll need to use the TCP Server from above. If it's not already running, close VICE first and then start the Server. You need to have the TCP Server running prior to VICE for the connection to be correctly established. Once everything is running, ensure that the server has reported that the connection is established. Confirm your breakpoint is still in place; VICE doesn't save these, so you'll need to go hunting again if you lost the position. Once everything is configured, make sure you close the Monitor window to allow the C64 emulation to proceed. When the Monitor window is open, the CPU emulation is halted!

Once ready, focus on the TCP Server window and press the a key. Make sure it reports back that the byte is set to 97, which is ASCII. Press the enter key and you should trigger the breakpoint in VICE.

Ok, we've got it, our breakpoint was hit and we presumably have data somewhere? Our breakpoint is actually on a JSR through to the address $FFCF. At this point in time, this address is unfamiliar. All our previous driver code has been around the $2300 mark. Due to this, we're going to step over it. The next call is an LDA which uses a pointer + offset to load a value into register A. Stepping over this, we see the following in the Monitor window:

(C:$2394) n
.C:2397  A2 00       LDX #$00       - A:61 X:03 Y:00 SP:f2 ..-.....    6728381

Interesting... A:61 hey? That's the ASCII HEX value for a lower-case a! So there it is, the value has come through and we can see it in memory. You can close the debugger now and play around with data on the TCP server to see how it arrives on the C64.

Note that as soon as you try to send a zero from the TCP Server, it'll appear as an 0x0d. At this point, we've honed in on the location where the char is read in, but we don't know what code is hosted up in the $FF00 range?

C64 Memory Mapping

Time to go deeper. Thank god we're working on a seriously old system that has been thoroughly documented. You'll find the memory map of the Commodore 64 here. If you scroll down the page, you'll find that the area in question contains the Kernal (Kernel?). At this point... we might as well retire.

Retire? Yes. The KERNAL is ROM, you know... READ-ONLY MEMORY. It's the raw system code burnt onto chips on the motherboard and it is a fixed entity. Those bytes can't be hacked... anything we try to do will require reproduction of kernal commands in the 'user' area. Should we try this? Sure... but first it'd be nice to know what's going on.

C64 Kernal Disassembly

Again, thanks to the age of this system, there's a full disassembly of the C64 Kernal here. We know that we're jumping in to location $FFCF, so browse down to that area.

FFCF   6C 24 03   JMP ($0324)   ; (F157) input char on current device

Oh look, it's just another JMP. Fortunately it's commented and we know to browse through to $F157. Now we are in murky waters... not many comments here. We get a heading of ; input a character, but then not much else. The assembly, to the naked eye, looks like a switch statement. It seems to be going through checking which device to read from. In our case, we can actually step through it in the debugger. If you step into the JSR #$FFCF then you'll be able to watch it jump as you send in characters from the TCP Server.

The basic trail jumps through: $FFCF -> $F157 -> $F166 -> $F173 -> $F1B8 (a.k.a. read a byte from RS-232 bus) via F177. At $F1BD, there's a comparison of the incoming byte to 0x00. If there's no match, then the code jumps out to $F1B3 and returns the value. If there is a zero, then the following occurs:

F1C1   AD 97 02   LDA $0297
F1C4   29 60      AND #$60
F1C6   D0 E9      BNE $F1B1

If the AND fails to compare, then the jump happens at $F1C6 to $F1B1. Looking at $F1B1 made me cry. The code implicitly inserts an 0x0d, overwriting the byte that was read into the buffer and then returns it.

I don't quite know what the LDA from $0297 is and why it is AND'd with #$60. I'm sure there's some RFC or some prehistoric rule back in the late 1980s that said if a modem or other serial device returned a zero, then it actually meant it to be a carriage return. Maybe it was a BBS thing? I'll continue digging and attempt to comment this area of code, but for now... we know that it's futile. The KERNAL ROM is fighting us and thinks it knows better!

A valid workaround

Righto... what do we do here? I initially thought it was a complete loss and gave up. Further Sapporo made me realise that this call was made from our custom driver. What if we specifically mention that our custom driver is built to handle 'zero' byte data and implement a work-around? If we copy out the code from the Kernal and re-produce it in the driver, then we can effectively resolve this (I wont say bug, I'm sure they had their reasons!) issue.

So, the trick here is to grab the portion of code from the full disassembly of the C64 Kernal and build it into a function in Johan's driver.

We know the entry point is $FFCF. This is a JMP to the switch statement which chooses the device. We know that this is the RS-232 driver, so we can skip that part and copy the code from $F1B8 to $F1C8. I've pasted this in below.

; read a byte from RS-232 bus

F1B8   20 4E F1   JSR $F14E
F1BB   B0 F7      BCS $F1B4
F1BD   C9 00      CMP #$00
F1BF   D0 F2      BNE $F1B3
F1C1   AD 97 02   LDA $0297
F1C4   29 60      AND #$60
F1C6   D0 E9      BNE $F1B1
F1C8   F0 EE      BEQ $F1B8

That CMP #$00 is the pain. Let's just jump to $F1B3 all the time. Actually... $F1B3 is just CLC and RTS. Let's just write that. We also can't directly BCS to $F1B4, so we'll need to JSR to a closer function and then call JMP. If we JMP directly then we'll lose our position in the stack.

F1B8   20 4E F1   JSR $F14E
F1BB   B0 F7      BCS $F1B4   ;re-write this to a BCS and JMP
...    ...        CLC
...    ...        RTS

With my patch above, I've removed (what seems to be) a re-try loop in the code. If it falls all the way through to $F1C8 then it returns to $F1B8 and tries to read a character again. I haven't seen this state occur in real life, but I'll keep an eye out and try and work out when this actually occurs. It seems that the AND #$60 must check for an error state which I'm yet to encounter.

I don't actually know the assembled opcodes off-hand. We will write this as standard assembly into the c64-up2400.S driver source file and then it'll write the opcodes on compilation. So, from line 139 we slap in:

;----------------------------------------------------------------------------
; OTHERFUNC: Shortcut to Kernal code
;

OTHERFUNC:
		jmp $F1B4
		
;----------------------------------------------------------------------------
; OURBASIN: This is a minimised call to get the character from the buffer.
; The Kernal code does not allow zero bytes (0x00)... this does.
;

OURBASIN:
		jsr $F14E
		bcs OTHERFUNC
		clc
		rts
		
;----------------------------------------------------------------------------
; GET: Will fetch a character from the receive buffer and store it into the
; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is
; return.
;

GET:   
        ldx #2
        jsr CHKIN
        jsr rshavedata
        beq GET_NO_DATA
        jsr OURBASIN
        ldx #$00
        sta (ptr1,x)
        jsr CLRCH 
        lda #<SER_ERR_OK
        tax 
        rts

I'll give the kernal function a real name soon. Right now the basic point is that we write our own BASIN function that is just a tiny subset of the greater procedure and then skip the part where it inserts that shitty little 0x0d.

it-worked

Either way... compiling this (see notes on that here) saw the bloody thing work! I'm going to get in touch with Johan now and determine what needs to be tidied up to get this trick included in the trunk.

That was fun!

22Jun/160

Serial Train Controller (C64+Arduino)

I'd previously attempted to use the parallel port for train control but have now switched to the Serial port for communications. I've also slapped an Arduino in between the layout and the controlling (Terminal) device. The Arduino will be programmed to understand data coming in from the Serial port, which can be fed from any device which is capable of outputting an RS-232 signal. For the example below, I'll be doing this from a Commodore 64. See this article to learn how to build a Serial Port for your C64.

Designing a communication language

Since we'll be using the RS-232 standard, we're able to define a language that any Terminal can speak to control the Arduino. This will be based on ASCII for command verbs and then raw byte data where targets and values are required. For instance, we could set throttle number 1 to 150 or point number 4 to left. Without being too tricky, 3 bytes is adequate to communicate these commands: C|T|V. If we wanted the data messages to be 'human readable' (so you can print them straight out to a file or other serial line), then we should send through 7 bytes C|TTT|VVV, where the target and value are padded out with zeroes. Fortunately, we only need these two to be 8-bit values, which is the definition of a byte. We'll simply have to convert them to ASCII if we ever want to print or display them.

Next, we'll need a command separator. I've chosen the exclamation mark '!'. Hence, when sending commands, our messages will be 4 bytes long. The recipients will need to wait data, ensure there is at least a full 4-byte message with a terminator and then start processing.

Important Note: As is described down below, I found out the hard way that not all text is equal. I've naively mentioned 'ASCII' two paragraphs above and jumped straight onto the C64, compiling strings and sending them down the wire. For some reason, although I full-well knew that I was coding in PETSCII, I neglected to think that it would actually send it down the line! Long-story-short, when the C64 sends a capital A, it actually sends a character that does not map to ASCII. Also, when it sends a lower-case A, it is actually seen in ASCII as an upper-case A!

Moral of the story? Make sure you understand what character set each device is transmitting and receiving!

Talking back to the Terminal

Although everything written above indicates that most of the communication will be one-directional; this won't always be the case! Some of the commands in the table below will actually be asking for data from the layout. This will be in the form of sensor blocks, where optical or occupation sensors will exist on the layout and be wired to binary input data. The Arduino will be hooked up to shift registers which, when daisy-chained, will be capable of 'watching' up to 64 inputs.

To get this data back to the terminal, we'll send through a message of 10 bytes. This will start with the letter S and be followed by 8 bytes of binary data indicating the state of all connected sensors. Finally a '\0' will be appended to indicate the end of the message. The Arduino wont expect a response to this; if the Terminal has failed to receive, then it can simply request the data again.

The Command Table

Now that we have our expectation of 3 data bytes and one terminator per message, we can start to define all of the commands expect to send.

Command Target Data
T

Set Throttle

1 or 2

The Arduino will have two separate PWM throttles.

0 to 255

The throttles will supply 12v DC PWM. The wave-cycle will be dependent on the value from 0-255. This maps to 0-12v. Hence 128 should be roughly ~6v.

D

Set Direction

1 or 2

Each throttle has it's own direction.

F or R

Forward or Reverse.

P

Toggle Point

1 to 8

8 separate points will be connected.

L or R

We'll use ASCII here to make life easier. Left or Right can be specified.

S

Read Sensors

0

We don't need to specify a block... we'll get the whole 8 bytes back regardless.

0

No value required here. We'll send a zero for padding.

Code for the Arduino

The Arduino will need to keep an eye on the serial port and act on commands when they appear on the channel. Data from the serial port will come in as singular bytes, so they'll need to be written into a buffer and processed once a whole message is found. In case the Arduino struggles, it'll need to be able to understand what a whole message is and discard anything that looks incomplete.

I'll skip the bits on PWM throttles, reading sensors and LED Matrices here... I'll describe all that in another article. Currently you can find individual articles on each of these topics on this site if you need the information straight away.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(8,9); // RX, TX

void setup() {
	// set the data rate for the SoftwareSerial port
	mySerial.begin(2400);
}

...

void processCommand() {
	int x = 0;
	switch (serial_buff[0])	{
		case 'T':
			setThrottle(serial_buff[1], serial_buff[2]);
			break;
		case 'D':
			changeDir(serial_buff[1], serial_buff[2]);
			break;
		case 'P':
			//adjust point
			break;	
		case 'S':
			//read sensors and return the data.
			break;
						
	}
	
	for (int x = 0; x < SERIAL_MAX; x++) serial_buff[x] = '\0';
	last_pos = 0;
}

...

void loop() {
	//if there's data and we've not read the end of the current message.
	if (mySerial.available() && (last_pos == 0 || last_char != '!')) {
		last_char = mySerial.read();
		serial_buff[last_pos] = last_char;
		last_pos++;
		if (last_pos > SERIAL_MAX) {
			//then we need to do something drastic
		}
		if (last_char == '!') processCommand();
	}
}

The snippet above checks if there's data and if we don't already have data. If the buffer is empty, then it'll read a character into it. If that character happens to be '\0' then it'll prevent further reading and process the message.

Controlling with a Commodore 64

cc65 has all the libraries we need to get the serial interface up and running; see more on that here. We'll use a text-based interface and control everything with the keyboard. At a later date I'll write a GEOS-based GUI.

I attempted to use the Tiny Graphics Interface libraries that cc65 provides. Unfortunately, that would've also meant writing a text renderer or graphical font library as the basic 'text out' for TGI isn't implemented on the C64. Staying with text-mode was to be easier and PETSCII has enough cool symbols to draw throttles and the like.

c64-trainctl2

The screen displays the throttle, just one for now, and the direction. It also provides a clock and a schedule. The user can add and edit items in the schedule and, when in run mode, these will be executed accordingly.

void sendCommand(unsigned char c, unsigned char t, unsigned char v) {
	ser_put(c);
	ser_put(t);
	ser_put(v);
	ser_put(33);
}

...

void main() {
	...
	sendCommand('d', 1, current_direction);
	sendCommand('t', 1, current_throttle);
	...
}

I've left out most of the guff ... I'll include the full source soon. For the meantime, you'll see that I've put individual characters to the serial channel for reading at the Ardunio end. Specifically they are lower-case! You'll also note that I write 33 instead of the literal character !. The reason is, of course, that the exclamation mark in PETSCII is not the same as ASCII.

What's Next?

This works. The train happily moves back and forth using the signals sent from the C64! It's overly boring though and based on the clock. I want sensors read back to be able to trigger events... so I'll hook up the multiplexing and post again shortly.