Friday, July 26, 2013

Marking Time

It is time once again for another exciting update on my Micro-C for CoCo project.  It has been a busy week for me here in North Cackalacky!  Unfortunately for me, it has mostly been a "work" kind of busy...  Nevertheless, I have been able to make a little progress on my project.

Pak It In

Like many machines of it's era (e.g. the Atari 2600), the CoCo had the option of using software distributed on ROM cartridges.  The clever marketing folks at Tandy marketed this as "Program Pak" software...  In any case, there are advantages to this software format.  So, it might be nice to distribute compiled C programs the same way.

Relocating the compiled code to the ROM cartridge address space is the obvious first step.  An added twist is the question of where to put the variables.  Obviously, storing "variables" in ROM is of limited value.  Luckily, the Dunfield library already provides for allocating variables in a different address range from where the code resides.  Yet another variation of the startup code allows for selecting this configuration.

Many programs require the use of interrupts for proper operation.  But, handling interrupts requires machine-specific accommodations that aren't part of the standard C language.  Many compilers provide mechanisms for implementing interrupt handlers in C, and Micro-C is no exception.  Unfortunately, the default mechanism provided with the Micro-C package generates code to hook the 6809's interrupt vectors in a ROM image.  That is fine for use in an embedded system, but it won't work with the CoCo.

The CoCo ROMs redirect the interrupt vectors through a secondary set of vectors in RAM.  Using the stock Micro-C interrupt implementation as a guide for interfacing with the compiled code, I implemented a CoCo-compatible version.  My implementation uses a macro to output some inline assembly code in order to establish some code labels and to provide a 'trampoline' function.  The trampoline function calls the C interrupt handler and then uses an RTI instruction to resume normal operation of the CPU.  I also added some macros to make it easier to point the secondary interrupt vectors at the appropriate handlers in the C code.

Time Flies

One of the few timing sources on the CoCo is the ~60 Hz Vertical Sync (a.k.a. "Vsync") interrupt.  With the code described above I was able to build a simple clock program that keeps time by counting Vsync interrupts.  I also used an inline assembly macro to provide access to the SYNC instruction.  This allowed me to properly time a colorful border animation for the clock -- the border is timed to complete a loop in approximately 1 second.  Just for fun, I compiled the clock to run in the emulator as a ROM image.  Since I didn't bother to burn a physical ROM, I also re-compiled the clock as a BIN file to load through the cassette interface on a real CoCo.

If you experiment with running my clock demo, you will find that the CoCo isn't really a very good time keeper.  Keeping time by dead reckoning with an almost-but-not-quite 60 Hz timing source doesn't compete with the accuracy of a Swiss watch!  I toyed with a few drift compensation strategies, but so far all I've done is prove that programming the CoCo in C is every bit as much fun as it is to program one in BASIC or assembly... :-)

Anyway, I guess that is enough for now.  Only a few more days remain for the Summer 2013 Retrochallenge event.  I hope to make the most of them, but I suspect that in any case I will be working on this project well past the end of the competition.  Either way, I hope you will stay tuned!

1 comment:

  1. Not so much these days, but in the earlier days of PCs, PCs had notoriously bad clocks built in. I once came across an MS DOS program that addressed the bad clock issues, and the solution was actually pretty cool. Basically, you'd install the program, and for the first week or two, you would adjust the clock once a day or so while the program was in "learn" mode. After a week of you manually adjusting the clock each day the program would have a good idea of how much drift (and what direction, fast or slow... usually slow), and would then "take over" adjusting the clock. At that point, say it needed to make up 5 minutes per day (which was about how bad our clocks were). The program would then proceed to adjust the clock spreading out the adjustment over the day. For example, 5 minutes is 300 seconds, 300 seconds / 24 hours = 12.5 seconds per hour, or about .2 seconds per minute. So it would probably adjust 1 second every 5 minutes or so. This worked really well and the clocks would stay accurate for weeks or months rather than a couple of days. I wrote a clock program not that long ago for the CoCo using BASIC and the timer function, and you're right, it was horrendously poor at keeping time, to the tune of about 10 minutes per hour. I bet a similar drift compensation program for the CoCo could yield similar results. The system I worked on was a POS system for a pizza shop, and it had a server with 5 other computers networked to the server. A make line station to display incoming orders, 3 order taking stations, and a dispatch station for drivers. These stations communicated with the server where the customer database was kept, and I think the constant communication between stations and the server were the cause because those old school network cards would halt the PC CPU while communicating with the servers.

    John Laury