Home-made computer from the AON board

Recently, several articles about home-made computers created from various non-standard components have appeared on Habré. I also decided to talk about my computer, created back in 1993. In the wake of the general enthusiasm for sinclair, I wanted to have a completely original 8-bit computer based on z80 and, in addition, create software for it, starting from the operating system and ending with toys. What came of it, read under the cut.

The first question that arose when creating your computer was the question of architecture. I decided that it would be compact enough, based on the z80 processor, without displaying an image on a TV, but with an LCD text screen, a fairly large keyboard, sound output in the form of a single-tone tweeter (standard at that time for most computers) and an RS232 port for connecting to other computers for programming and debugging purposes.

However, there was a problem where to get a printed circuit board for a completely original circuit, because in 1993 the Chinese had not yet produced boards for the whole world, and ordering development and production at the factory was very expensive. And then I turned my attention to the boards from which the caller IDs were made - automatic caller IDs. They were on sale at the Mitinsky market, had the opportunity to install the components I needed, but needed to be improved. On sale there were several varieties of such printed circuit boards of which, if my memory serves me, I chose a board called "Rus."

Let me remind you for young readers what AON was. It was a telephone with button dialing (by the way, at that time it was pretty cool, since most of the phones had a spinning disk), consisting of 12 buttons and a luminous 9-bit, 7-segment indicator, on which the telephone number was displayed, if it was possible to determine and some other information. The AON board contained a z80 processor, a parallel port 58055, a decoder circuit, a timer 58053, a 32-kilobyte ROM (with ultraviolet erasure), an 8-kilobyte static RAM, the analog part connected to the telephone line and, possibly, something else, what I forgot about over the past years.

The 12-button keyboard and the indicator available on the Caller ID did not categorically suit me, since they normally could not enter information or display it (in particular letters). Therefore, it was decided to use a 40-button homemade keyboard and a text 24-character, 2-line LCD screen, which then appeared on sale. To connect the keyboard and LCD screen, it was necessary to modify the AON scheme. The first thing I did was throw away the entire analog part associated with the telephone line, or rather, I simply did not seal it. At the same time, the output legs on the decoder, which selected the indicator discharge and legs on the parallel port 58055, were freed. The LCD screen required 4 lines for transmitting information, but for the keyboard it was necessary to use a decoder.Since 40 buttons on the keyboard were arranged in a matrix of 5 rows of 8 pieces, it was decided to connect these 8 buttons to the decoder so that they could be scanned by supplying different combinations of three lines to the decoder input and reading 5 values ​​from the rows of buttons using the KR580VB55. Thus, a scan code of the pressed button on the keyboard was one byte in size, where the first three bits determined the column in which the button was pressed, and the remaining 5 bits indicated in which row this button (or several buttons at once) was pressed . In addition, I considered that 8 kilobytes of RAM would not be enough and replaced it with 32 kilobytes. At the same time, I had to re-solder a couple of tracks on the printed circuit board, fortunately, the 8- and 32-kilobyte RAM cases were almost identical in pinout. In this way,I got 32 kilobytes of ROM and 32 kilobytes of RAM (I recall that the z80 can address a maximum of 64 kilobytes, so that I used the address space to the maximum). In addition, two more lines of 58055 went to the RS232 serial port, which is necessary for connecting to another computer. I put all this economy in the case from the tester. The result is this design:

image

After the hardware was done, it was time to create software. Here it should be noted that the process of its creation did not look at all what it looks like today. Firstly, most of it was written in assembler z80 (although at that time almost all programs for such systems were written in assembler, well, except for BASIC). For compilation from assembler at the first stage, my friend helped me, who had a Profi computer - a sinclair clone, but with TR-DOS on board. Then I began to use my IBM PC, which was OS / 2, which ran MS-DOS in a separate window, in which, in turn, the TR-DOS emulator was launched, in which the compilation took place. I must say that when the software grew noticeably, the compilation and assembly process took ten minutes. The second problem wasthat no debugging tools existed and, therefore, it was necessary to download everything every time on my homemade computer and check how it works (the first thing that had to be done was a program for working RS232 at 9600 bits per second for downloading). And finally, it should be said that after debugging the ROM image, it was necessary to write it to this ROM itself, having previously erased what was already written there. Erasing was carried out using an ultraviolet lamp for tanning through a special window in the microcircuit housing, which was then covered with a special black adhesive paper, which serves to seal the hole on the side of a 5-inch diskette to protect it from writing. In addition, since I didn’t have a programmer, to write a new version of the software to ROM, each time I had to go to my friend to the other end of Moscow,who had this programmer. Here it is necessary to clarify the question, how was it possible to debug the image of the ROM without loading it into this ROM? There was a base address for this, which all my software used, shifting addresses by 32 kilobytes. That is, a new ROM image was loaded into RAM and debugged there, and after debugging, the base address was set to zero, everything was compiled again, and I went to a friend to write a new version in ROM.everything was compiled again and I went to a friend to write a new version in ROM.everything was compiled again and I went to a friend to write a new version in ROM.

When the process of "coding" - "debugging" - "firmware" was debugged, the question arose of writing an operating system. The operating system had to support keyboard input, display information on an LCD screen, support for outputting different sounds and do all this in parallel, if possible, that is, be multi-tasking. For all this, the following architecture was chosen - in the OS there were three types of tasks: several real-time tasks with the highest priority, one user task that interacted with the person itself and background tasks that worked when the processor was idle. I hung up tasks with the highest priority on the interrupt, which was generated by the KR580VI53 timer 10 times per second. It should be said that in Caller ID, interrupts were generated 400 times per second, because it was necessary to update the indicator very often in order toso that a person does not notice flicker. In addition to updating the indicator in interrupts, the keyboard was polled for the search for the pressed key. Such a frequent interruption in AON led to the fact that most of the processor time was spent actually on interrupts, and I wanted my computer to do something else useful. Since I installed an LCD screen as an information display device, which had its own memory and did not need dynamic updating, the need for such an interrupt frequency was no longer needed. It was experimentally established that 10 interruptions per second is enough to poll the keyboard.that most of the processor time was actually spent on interrupts, and I wanted my computer to do something else useful. Since I installed an LCD screen as an information display device, which had its own memory and did not need dynamic updating, the need for such an interrupt frequency was no longer needed. It was experimentally established that 10 interruptions per second is enough to poll the keyboard.that most of the processor time was actually spent on interrupts, and I wanted my computer to do something else useful. Since I installed an LCD screen as an information display device, which had its own memory and did not need dynamic updating, the need for such an interrupt frequency was no longer needed. It was experimentally established that 10 interruptions per second is enough to poll the keyboard.

Thus, real-time tasks were launched at each interrupt and placed new information in a special event queue. Events were of several types and contained information corresponding to the type of event, for example, the “pressed button” event contained a scan code. Actually, one of the priority tasks that started at each interrupt was the task of polling the keyboard and programmatically removing contact bounce. In addition to this task, there were also priority tasks - timers that the user task could set, and which, after a specified time, queued the corresponding event, there were alarms that worked at a certain time, clock and calendar, and there was also a task that played music using programming KR580VI53, and the input to it was fed data in the form of notes. In this way,the user's task could simply start playing music and do other things.

Useful work on my computer was done by a user task that was event driven. A typical view of such a task looked like:

while(true) {
  Event e;

  GetEvent(e);

  /* process event */
}


Here the GetEvent (e) function waited for the event to appear in the queue and, when it appeared, populated the Event structure. It is clear that according to a certain event, the program could exit an infinite loop and transfer control back to the system monitor, which launched user tasks. Since events in the user task were usually processed quickly, the program waited for a new event to appear in the GetEvent (e) procedure. In order to somehow utilize this expectation, background tasks were introduced that the user program could run and which worked independently. That is, when an interrupt from the timer occurs, the real-time tasks were first fulfilled by placing events in the queue, then after the interruption the user task processed all the events from the queue, and the remaining time until the next interruption was given to background tasks.Today, such a scheme looks natural, but in 1993 it was very progressive.

There was another problem related to the fact that the LCD screen was not able to display Russian letters. This was due to the fact that such indicators have just appeared on our market and no one has specifically Russified them. Naturally, there were no libraries for working with them, but there was only a specification and description of the commands. Therefore, all the work on initialization and working with it had to be written from scratch. I solved the problem with Russification as follows: a special procedure was written, the input of which was a string with Russian text that needed to be displayed. This procedure replaced all Russian letters that were similar to Latin with corresponding Latin letters, and those that were impossible to replace were created on the fly using custom images that could be downloaded to the LCD screen. It should be notedthat there were eight such user images in it and, accordingly, in the Russian text there could be no more than eight letters, analogues of which were not in the Latin alphabet. But usually it was enough. Another fun opportunity that I used was that if you change user images for one character, you get a funny animation. I used this opportunity in the sapper game, which I will discuss below, where the flag above the mine has flown in the wind and the bomb explodes.I used this opportunity in the sapper game, which I will discuss below, where the flag above the mine has flown in the wind and the bomb explodes.I used this opportunity in the sapper game, which I will discuss below, where the flag above the mine has flown in the wind and the bomb explodes.

Now I’ll tell you about those user tasks that I created for my computer. When I began to create them, I quickly realized that writing them in assembler, as everyone did at that time for systems like sinclair, is pretty sad. Since I programmed C on an IBM PC, I thought about whether it is possible to program on C and on my computer. After some searching, I found a compiler from the C language for TR-DOS, moreover, in its classic K&R version. This compiler was rather primitive, for example, it did not check whether the number of parameters passed to the procedure corresponded to their actual number, not to mention checking their types. But if I could use this compiler for my computer, it would be a tremendous progress. The problem was how to adapt the code received by this compiler for my computer.Here I went the classic way, which we have already forgotten about, and in 1993 they still remembered. This way was to compile the source code not directly into the object file, but into assembler source code. Thus, it was only necessary to write macros that would allow calling the assembler procedures compiled from the code and vice versa, with the correct transfer of parameters, which was done. Using this compiler, besides the convenience of working with code, provided another great advantage - it became possible to work with integer multiplication / division (I recall that the z80 does not have integer multiplication and division commands), and also (lo and behold!), The ability to work with numbers floating point. However, for this I had to deal with the library attached to the compiler,since all the mathematical operations after compilation were performed as a call to this library. The problem was that this library used temporary variables that the compiler placed in the memory model specific to TR-DOS, which, of course, completely did not correspond to the memory model of my computer. I had to look for all such temporary variables and redo them for addresses that fit my RAM. But as a bonus, I got a lot of standard functions like sine and cosine, which I used in my tasks, which I will discuss below.I had to look for all such temporary variables and redo them for addresses that fit my RAM. But as a bonus, I got a lot of standard functions like sine and cosine, which I used in my tasks, which I will discuss below.I had to look for all such temporary variables and redo them for addresses that fit my RAM. But as a bonus, I got a lot of standard functions like sine and cosine, which I used in my tasks, which I will discuss below.

The first program that was created using the C compiler was a program for checking the correct operation of RAM. This program went through the whole RAM, wrote, and then read various patterns and compared the result. Moreover, the entire process was displayed on the LCD screen, which also confirmed the correct operation of the procedures associated with it. It is clear that this was just a test of the pen before writing more interesting programs. The next thing I did was create a hex editor to modify the contents of RAM. This editor already possessed quite wide possibilities, including not only viewing and editing memory cells, but also searching for interesting bytes in RAM. In particular, it became possible to write small programs directly in RAM in machine codes. To test the sound capabilities of your computer,I created a program such as a “music box” that played various melodies (I recall that melodies were recorded as notes). Further, a program was written for the game "bulls and cows", where a person was asked to guess a random four-digit number conceived by a computer (yes, I also made a random number generator). In this program, I had to create a scrolling list with a history of already entered numbers, since it was impossible to display a particularly long list on two lines. The next program created was a classic “sapper” on a 16x16 field. Since I had only two lines at my disposal, I did scrolling, adding musical accompaniment and animation of a flag flying in the wind and exploding bombs. Further, for meditation, I made a program that showed worms crawling in a random direction,using the ability to upload custom images to the screen. Well, and where without the classic tic-tac-toe? In them I tested the minimax algorithm, that is, the computer calculated (rather quickly) all the options and never lost. Since my operating system supported alarms, time, and a calendar, I made a user program that set the time, date, and several alarms that, when the set time was reached, played different melodies. And finally, the crown of creation in my computer is a program for calculating the trajectory of motion in the problem of two gravitating bodies. That is, for a given initial position and velocity of the body, as well as the mass of the attracting center,the problem of numerical integration of a system of two nonlinear ordinary differential equations of the second order with a given integration step was solved. For this, I added a procedure that numerically integrated these equations. All variables were double floating point format. Here I emphasize once again that in the z80 processor there is not only hardware support for working with floating point, but also the usual multiplication / division of integers, everything was done programmatically. This integration worked pretty slowly, about one step per second, but it worked!but also the usual multiplication / division of integers, everything was done programmatically. This integration worked pretty slowly, about one step per second, but it worked!but also the usual multiplication / division of integers, everything was done programmatically. This integration worked pretty slowly, about one step per second, but it worked!

What I still wanted to implement, but it didn’t work out - firstly, dynamic allocation / deallocation of memory, so that I could flexibly manage the resources of each task. Also, recording / reading on tape was not implemented, as was done in the Sinclair. But overall, I was pleased with what I managed to do. I emphasize that all of the above was in a 32 kilobyte ROM - the current size of one not-so-large email.

You can look at my computer in action here:




And download his software here

All Articles