-
Stick a Fork in it
07/24/2023 at 03:04 • 0 commentsIt's done! As in the software is at version 1.0 and ready to ship.
_ /o) _/\/\/\_// _/NOVASAUR/ /_/{_}~~{_} Novasaur 64k CP/M vers 2.2 Copyright 1979 (c) by Digital Research a>b:uptime System uptime: 0 days, 03:18:38 CPU Load Average (last 4 mins) 0 0.5 1.0 1.5 2.0 2.5 +-------+-------+-------+-------+-------+ 0.05 | . 0.05 | . 0.05 | . 0.06 |= . 0.67 |===========. 1.02 |==========.===== 1.03 |==========.===== 0.30 |==== . 0.07 |= . 0.24 |=== . 0.15 |== . 0.29 |==== . 0.05 | . 0.05 | . 0.05 | . +-------+-------+-------+-------+-------+ 0% 5% 10% 15% 20% 25% CPU Idle Cycle % (dotted line)
The last pieces of the puzzle have been added to the B: drive highlighted below.
B: ASM COM : BASIC COM : CPM SYS : DDT COM B: DUMP COM : ED COM : FORMAT COM : LOAD COM B: PIP COM : STAT COM : SUBMIT COM : UPTIME COM B: XFER COM : XSUB COM
These are three small (1k) utility programs as follows:
FORMAT
Used to format any CP/M drive installed on the Novasaur. Currently this would only apply to drive A:
FORMAT drive: [/Y] [/B] /Y Confirm without further prompt. /B Bleach the file system (set all bytes to ctrl-Z).
UPTIME
As shown above. This returns the time elapsed since the last cold boot and a chart showing the load average and CPU idle percentage over the last four minutes.
XFER
Used to send and receive binary files over the serial connection. This was originally going to be XMODEM, but this was changed to a basic file transfer utility. The USB FTDI connection is reliable and the transfer can be completed with a simple send or capture command from the host.
XFER <drive:filename.ext> {/R or /S} /R Receive file over serial. /S Send file over serial.
The XFER program detects if it running on the TTY and will respond appropriately. File capture from CRT will ask for a keyboard confirmation to start the file transfer. From TTY an extended timeout is used to allow time to control file capture without confirmation.
-
Year 5
02/27/2023 at 01:37 • 0 commentsThe project is entering its fifth year and plenty has been going on. Here's an update on completed and in-progress tasks for the 1.0 software release, plus some future plans for the platform.
Load Averages
To finish debugging the kernel, some additional insight was needed on how the kernel was handling messages. It's possible to measure the load average of the machine by counting the number of virtual machine cycles used by the CPUs vs. the kernel. Each CPU can run for up to 100 blocks before a context switch and sequence; kernel, CP/M, CP/M, disk, means up to 300 blocks could pass between kernel calls.
This average block count is sampled every two seconds and added to a record containing 128 values. This can be averaged again to give various load averages, e.g last 15 seconds, 1 minute, 4 minutes. The load average is just the average block count divided by 100 and since the disk block count is typically below 20 it will fit in the available range 0.00 to 2.55 for one byte per sample.
In addition to the load average the kernel also tracks CPU efficiency. The IDLE instruction is called every time the virtual CPU doesn't have enough cycles in the video line to execute an instruction. The additional idle time is used to increment a 16-bit counter and keep track of the number of idle cycles. This count is now reset and sampled by the same code used to sample the load average. The result is a byte representing the percentage of idle cycles and can range from 0 to 25.5%.
The data is stored in the kernel memory at location 0xE800-0xE87F for the idle data and 0xE880-0xE8FF for the load average. The plan is to add a way to view this data in future.
Buffered Serial
A serial console has been in place since the early days of the 8080 machine code monitor, but this was designed for handling one byte of text data as a time. What is needed for file transfer is a buffered binary mode. Work started on this back in April last year and was only recently completed.
Data sent to the PUNCH BIOS call is buffered by CP/M until a threshold is reached. Once reached the buffer is copied to the CPU's shared memory as a record and a SEND command sent to the kernel. The kernel will then add the record data to the serial transmit buffer. This buffer may be full, or only some of the data can be sent. These various corner cases are handled by the CP/M BIOS and kernel code to keep the transfer state in sync.
Data read from the READER BIOS call sends a RECV command to the kernel and the kernel returns the serial receive buffer as a record back to CP/M. The subsequent calls to READER will return bytes from this record until empty, then a new call is made to the kernel. Both kernel calls for sending and receiving data result in a delayed return from the kernel. The delay is two ticks, or the amount of time it takes to transmit or receive 128 bytes of data at 9600 baud.
This delayed kernel response keeps the CP/M calls in sync with a 128 byte transmit or receive transfer buffer size. In this way the serial connection can be utilized at its most efficient with CP/M sleeping until the next chunk of data is available.
Basic Load and Save
The plan was to have basic "on board" when the machine ships. There is not a lot of room in the ROM, so the more advanced MS BASIC was out of the question. Instead a more classical 8k BASIC is included. These early BASIC interpreters would typically load and save programs via tape... not 1980's home computer cassette tape, but punched paper tape!
IMSAI 8k BASIC is shipping in the ROM and the tape load and save code has been updated in the to use the new buffered serial mode. The SAVE command switches the BASIC output to the READER and then the LIST command is called along with a terminating KEY command. The output can now be copied from the serial console and saved in a file.
The LOAD command will switch the BASIC input to READER and then start processing commands until a KEY command is reached. This way the original saved output can be replayed via the serial console to re-enter the program. The console output is silenced to keep the transfer as fast as possible.
The 8k BASIC is now complete with the ability to load and save BASIC programs.
Util
That covers all the completed features, now comes the last piece of the puzzle. The original plan was to include an XMODEM program to transfer files over the buffered serial connection. It turns out to be a very obsolete tool and not well supported on modern computers. It also turns out to be fairly unnecessary since the FTDI chip does a great job of handling error-free communications between a host USB and the RS232 port.
The original XMODEM program is being refactored to be just a simple file transfer tool that can read/write CP/M files and send them over the buffered serial connection. The plan is to add a few more features, like a "format" command to format the A: drive and possibly an uptime command to show the uptime and load averages discussed earlier. As such, the 2k byte XMODEM command has now become a more generic UTIL command.
The UTIL command will be the final feature and complete 1.0 software release.
Disintegrated
So what comes next? The 3+ years of software development has created a pretty impressive TTL computer platform with a lot of potential and it would be great to get it out to a wider audience.
The idea of offering an assembled version has been floating around for some time. It makes most sense to use surface mount components for automated assembly, and an SMD version of the current design is definitely possible. However, this might be a great opportunity to go a bit further and create something more along the lines of the Monster 6502.
Going down to the transistor level would be impractical though, but a single gate/function-per-chip design is possible. The plan would be to use a limited selection of chips, each of which would come in an SOT-23 size package. After evaluating the options, the following four devices were chosen:
These consist of:
- 1G374 - D-type Flip Flop with tristate output (est. 170 total)
- 1G19 - 1:2 demultiplexer, or OR-gate, or inverter (est. 100 total)
- 1G11 - 3-input AND-gate (est. 50 total)
- 1G86 - 2-input XOR-gate (used to convert D-flip flops to T-flip flops, est. 20 total)
There would also be a few analog switches for the video selector, op-amps for the audio filter, and transistors for the RS232 drivers, PS/2 port. These would also be SOT-23 packages. The only non-SOT-23s would be the RAM (TSOP II) and ROM (socketed PLCC).
There would be at least 500 SMD components on the board, of which 350-370 would be SOT-23. The rest would be passives. The board would be the same size with the same connector layout and fit in the same box as the original Novasaur. There may be some more LEDs on the board for that added blinken light look.
The first step is to see if the logic can meet the propagation and setup times to run at the current speed. The critical areas are the execution state machine (PAL) and program counter. The schematics below show what this logic looks like in the disintegrated form.
The good news is the LVC 5V logic can not only meet but exceeds the timing requirements. The execution state machine comes in just below 25ns and the subsequent program counter propagation is just under 40ns total. This could allow the machine to run with a 40MHz dot clock using 45ns RAM.
It's a long road ahead though. This project can not be done in one step. The first stage will be to evaluate this approach by building out the two circuits above and validating them in the current design. Once debugged the rest of the system is fairly easy to convert. It will likely take the rest of this year to get to a working design and this is a current year 5 goal.
-
Race Conditions
01/22/2023 at 21:21 • 0 commentsThere was a six month pause in software development, which wasn't such a good idea. It's taken a while to get back up to speed and get to grips with the remaining "minor" bugs/features. These are all hard problems like race conditions and the binary-mode serial interface. This log explains one such race condition.
The following eye charts show the context switch sequence and message flow for requesting a RAM-disk record (discussed in the Kernel section of this log). The sequence is basically kernel-cpm-kernel-disk and originally all the disk quadrants were sequenced together (show below). The advantage of this is the ability to complete a full disk operation with only 8 context switches.
[ 1 = Kernel, 2+3 = CP/M, 4+5+6+7 = Disk Quadrant ]
One disadvantage is that all kernel operations require an 8-cycle turn around. This means just printing a single character to the console will take 8 context switches... such is the life of a micro kernel. One way to improve this is to scan only one disk quadrant per sequence. This increases the maximum disk operation (cpm-kernel-disk-kernel-cpm) to 16 cycles, but reduces the console turn around (cpm-kernel-cpm) to just 4 cycles.
There is one issue with the approach and that's the possibility of dispatching multiple requests to the same disk quadrant before that quadrant is reached. This turns out to be quite likely when the machine is booting up. Both the TTY and CRT instances of CP/M boot up in lockstep. They both dispatch a request for the same disk quadrant around the same time and the second request gets dropped.
Apparently this was a know issue with the classic "TODO" comment in the code...
@@ -161,7 +163,7 @@ HANDHL: ADI BASEPG ;A=BASEPG+CPU# ; SNDRET: DW IPCSND ;SEND MSG, EXPECT RETURN ORA A ;A==0? - JZ WAIT ;TODO: HANDLE ERR + JZ IPCERR ;HANDLE ERR SETRET: CALL HANDHL ;HL=HANDLER MOV M,C ;CMD=C LDA SRCCPU @@ -172,6 +174,12 @@ SETRET: CALL HANDHL ;HL=HANDLER INX H MOV M,D JMP WAIT + +IPCERR: LDA SRCCPU + MVI B,0 + DW IPCSND + JP WAIT +
The IPCSND instruction returns zero in the accumulator if the destination CPU is not expecting a message**, e.g. if it just received one from another process. The error is now handled by clearing the sequence number in the originating command and returning a message in the same thread. The CP/M BIOS will retry the disk operation if this occurs.
** Update: "not expecting a message" was the CPU not in the wait state, but it has now been updated to include both not sleeping OR sending a command. This was causing another race condition that showed up after the previous one was fixed.
-
Machined
12/15/2022 at 23:58 • 0 commentsFiguring out the CNC machine and designing the panel cutting and engraving patterns was yet another subproject of immense proportions! Thankfully this is now complete...
A simple method was found to machine the panels. This is done by using a slot made by a facing bit to hold the panel level with the face of the spoil board. A small gap is left at the top to allow two countersunk screws to hold the panel in place and stop it from breaking loose while milling.
The back panels for the Novatron (top) and Novasaur (bottom) are show below.
A V-cut bit is used on the front panel to engrave the name and cut two holes, one for the LED and one for the power switch. The image below shows the development of the engraving:
And the final designs...
A few kits have made it out in to the wild for beta testing. Work is starting on the assembly instructions to complete the kit.
-
Solid State Machines
10/06/2022 at 21:07 • 0 commentsThings are still progressing with a lot of behind the scenes work. This included setting up a business to officially launch the products - there will be two initial products with plans for more produced by Solid State Machines!
The website has some basic info, a forum, wiki, and store. The plan is to fill out the wiki by pulling a lot of details from these logs and adding more detailed info on the software and how to develop the platform.
Both the Novasaur and Novatron made it to VCF Midwest last month. The Novasaur was showing off not one, but two instances of CP/M running on the same machine.
The image above shows the VGA output displaying a mandelbrot set generated by MS Basic (it took a long time!) and a game of Super Star Trek being played via the serial terminal. Both these programs were loaded over the serial terminal using PIP as Intel hex files and then converted to binaries using Load.
This is going to be the initial release configuration of the Novasaur with the machine booting to CP/M on both the VGA console and serial terminal (the machine-code monitor is still accessible by hitting ctrl-alt-home).
VCF Midwest also hosts a lot of retro-tech YouTuners resulting in some brief coverage by the 8-Bit Guy and Ben Heck, plus a full one-on-one interview with Dr Dave.
Components are on hand for two dozen kits including packaging materials to ship the final product. The images below show the kit components.
There are a couple of things still missing: The assembly guide and the machining of the case. This requires something to machine the ABS panels... so there's a new side project to set up a CNC machine.
After the CNC setup and assembly guide there's still a couple of minor bugs to clean up in the Novasaur software to get to a 1.0 release. The plan is to release both the Novasaur and Novatron together in the new year. Sorry for all the teasing this year... it's getting there!
-
A Slight Detour
07/08/2022 at 21:28 • 3 commentsIt's been a couple of months since the last update and the plan earlier this year was to have some kits available by now. Things in the post-COVID world were a bit more challenging than expected, but component inventory is starting to roll in!
The user manual still remains the long pole in the tent for the final kit configuration, so an initial kit will launch with a slimed down construction guide. The target for this is the Vintage Computer Fest Midwest in early September. A website is also under construction to provide more details and online ordering.
But there's more... There was a slight detour to take a break from the endless software development and to remind me that debugging hardware is just a painful as software... Introducing the Novatron!
The Novatron is a binary compatible version of the Gigatron TTL microcomputer in the form factor of the Novasaur. The benefit here is the existing software ecosystem proving a much shorter runway to a finished product (3 months vs. 3 years).
Shown above is the Rev.2 board with the Pluggy Reloaded add-on, and below is the machine in action housed in a groovy faux-wood finished case and matching 80's portable TV.
The final version will drop the Pluggy Reloaded and include features from the Gigatron IO and RAM Expander/Expansion project. This adds support for 128k RAM and two SPI ports with the first connected to an SD Card holder mounted directly to the board. The second SPI is available via header for an internal expansion board or a second external SD Card breakout board.
Other modifications over the original Gigatron include 6-bit audio (reducing the blinken lights to a single bi-color LED) and a hi-res output. The hi-res output is based on the Novasaur design and is selectable using a switch mounted in the same position as the Novasaur volume control. The rest of the connectors and switches match the Novasaur and are mounted in the same positions so they can use the same machined case.
A Novatron kit should be available around the same time as the Novasaur kit, or shortly thereafter.
-
File Transfer
04/16/2022 at 04:17 • 0 commentsThe final piece of the puzzle is file transfer and the plan is to use the era-appropriate Xmodem. A modern version has been developed for 8080 CP/M by Martin Eberhard (founder of Tesla). Only basic functionality is needed, so the early version 1.01 is being added to the ROM at a cost of only 2k bytes.
It's going to take a few more weeks though. The plan is to buffer the data on the CP/M BIOS side and hand it off in chunks to the kernel. The CP/M process will yield on a kernel timer to allow time for the chuck to transfer (10 blocks per byte). This will allow the full duplex serial connection to perform concurrent transfers: One instance of CP/M can be downloading a file while another is uploading.
In the meantime there is a way to transfer files to CP/M via the monitor: The monitor has some kernel functions available to get and put records to the RAM disk. These take the following form:
KG[track][sector] [address] > KG0000 0000 KP[track][sector] [address] > KP0000 0000
There are a total of 63 tracks (00-3E) with 32 sectors each (00-1F). Each sector contains a 128-byte record that can be read (kernel get) with KG or written (kernel put) with KP. The records are read from, or written to, a 16-bit address in the monitor memory.
The CP/M A: drive directory is 2k and occupies the first 16 sectors (track 00, sector 00-0F). The kernel format command KF will create an empty directory record and copy it to these sectors. The following monitor commands can be used to copy the first 4 sectors of the directory and display then in memory location 0-1FF:
> KG 0 > KG1 80 > KG2 100 > KG3 180 > D 1FF
A file can be created in CP/M by quitting the monitor (enter Q) and using the save command:
a> save 4 test.txt
This will save the first 4 pages of the TPA in a 1k file called test.txt. The directory entry will show a single block number of 02 which corresponds to track 00, sectors 10-1F. A file can be transferred over the monitor serial connection as a sequence of hex digits (one per line) using the monitor load command. The following would load data (e.g. 1k) to address 100 to 4FF and then transfer it to track 00, sectors 10-1F.
> L100 0100: FF ... copy hex, end with Q > KP10 100 > KP11 180 > KP12 200 > KP13 280 > KP14 300 > KP15 380 > KP16 400 > KP17 480
The data transfer will overwrite the contents of the 1k test.txt file on the CP/M A: drive. This isn't very user friendly, but it was a useful technique for testing and debugging the CP/M BIOS and kernel code.
-
Time
03/31/2022 at 00:19 • 0 commentsThe realtime clock (RTC) was introduced in this log. There was mention of instructions to get the time in a more convenient format. That code was written about a year ago, but has only just been integrated as various loose ends are being tied up.
The RTC counters are reset on power up or cold boot. The clock then keeps track of time with an accuracy of around 14ppm. The first application was to add an UPTIME command to the monitor. This displays the time since power up (cold boot) in the format DDD HH:MM:SS
Clock Division
The hardware abstraction layer (HAL) divides down the 8.25MHz CPU clock by a total of 182,474,244,096,000. This is done via the following steps:
- Osc: 33.000MHz (+/- 100ppm)
- CPU (÷4) 8.25MHz
- HAL (÷43) 191.86kHz
- Line (÷5 or ÷4) 38.372kHz or 47.965kHz (depending on video mode)
- Block (÷4 or ÷5) 9.593kHz
- Frame (÷128 or ÷160) 74.9455Hz or 59.9564Hz (depending on video mode)
- Tick (÷5 or ÷4) 14.9891Hz
- TIME0 (÷90*) count to 6.00436 secs (*adjust TIME0 by -1 every 15th TIME1 count)
- TIME1 (÷120) count to 719.990 secs or 11.9998 mins
- TIME2 (÷120) count to 1439.98 mins, 23.9997 hrs, or 0.999986 days
- TIME3 (÷256) count to 256 days, 36.57 weeks, 8.4 months, or 0.7 years
Real-Time Clock
The realtime clock consists of the four bytes: TIME0-TIME3. As shown above, these don't count typical increments like seconds, minutes, hours etc. They are optimized for 7-bit arithmetic and the ability to update everything within one additional virtual-machine cycle. These counters are updated at the following rates:
- TIME0 - 15 ticks per second
- TIME1 - 10 ticks per minute
- TIME2 - 5 ticks per hour
- TIME3 - 1 tick per day
One other thing to note. The counts for TIME0-TIME2 are negative and count up to zero. This is done to simplify the overflow condition and just test the sign bit. The final count TIME3 is the only positive count and represents the number of complete days the machine has been on.
Calculating Time
A general formula can be used to calculate the actual time unit:
- UNIT[n] = (TIME[n+1] % 10) * max + TIME[n] / ticks
Where max is the highest value of that unit held by the counter and ticks are the ticks per unit. This leads to the following formulas for the standard time units:
- SECONDS = (TIME1 % 10) * 6 + TIME0 / 15
- MINUTES = (TIME2 % 10) * 12 + TIME1 / 10
- HOURS = TIME2 / 5
- DAYS = TIME3
However, these formulas assume the counts are positive numbers. In this case they are not and this type of math will not work.
Modular Arithmetic
There are two approaches to dealing with the negative counts: convert the numbers to their positive versions, or use the negative versions and then convert the result. An important observation here is the fact the results will be sexagesimal. This allows the use of modular or clock arithmetic and favors the latter method.
The counts are considered to be positive 8-bit integers and adjusted with a final offset to wrap to the correct sexagesimal number using a MOD60 operation:
- SECONDS = MOD60 (13 + (|TIME1| % 10) * 6 + |TIME0 - 1| / 15)
- MINUTES = MOD60 (35 + (|TIME2| % 10) * 12 + |TIME1 - 6| / 10)
- HOURS = MOD60 (|TIME2 + 120| / 5)
- DAYS = TIME3
This may look more complex, but it can be efficiently coded to fit in a single 2-cycle extended instruction (utilizing a jump page in the 0xED range of instructions). The MOD60 unary function is also used to convert the result to binary-coded decimal (BCD), or more specifically, binary-coded sexagesimal.
Sexagesimal Adjust Accumulator
The reason for converting the result to BCD is the typical use case where the time displayed as a timestamp. The realtime clock is reset to zero on cold boot and the current time can be calculated by adding the time the machine started to the current uptime tracked by the realtime clock.
This requires the addition of two BCD numbers and is possible with the use of the Decimal Adjust Accumulator (DAA) instruction. This will adjust the result back to BCD after the addition, along with setting the carry from the 100's column.
The same technique can be used to add times with a Sexagesimal Adjust Accumulator (SAA) instruction. This is similar to DAA except the carry is generated when the most significant digit is greater than 5 rather than 9. The result is mod-60 rather than mod-100.
Kernel Timers
One additional use of the realtime clock is to addition of timers to the kernel. These can be programmed to trigger at some point in the future based on a number of ticks. The concept is fairly simple: Each time the kernel main loop runs it will check to see if TIME0 has changed. If it has then the kernel will check the timers.
Each timer consists of a count and an address to call. Each time the kernel detects a tick it will decrement the counters and check to see if any have reached zero. When a timer reaches zero the kernel will delete the timer and execute the code specified by the address. The timer code can add the timer back again for a repetitive event.
Timers are added to a heap and the kernel will scan the entire heap to find expired timers. The timer is deleted by replacing the expired timer with the timer removed from the top of the heap. When the expired timer is at the top of the heap then there are no more timers.
-
State of Play
03/25/2022 at 01:07 • 0 commentsThe following log is going to be a bit of a brain dump on the current state of the firmware/software development. This snapshot is captured in the R0.3 ROM uploaded to the files section today (also tagged in the Git repo).
First a quick overview of how the current software is structured:
The R0.3 ROM was the final phase of the Kernel/CPM testing and debug (Test/Debug Configuration). Here the CP/M instance is running in the Kernel space of CPU1. It can access the input and output ports directly to simplify the console access. It is also possible to exit CP/M and return to the system monitor to examine the RAM. The Kernel is only used to talk to the RAM disk (CPU4-CPU7 contexts).
The next stage of development is switching to the final Multi-user Configuration. Here there are two CP/M instances running on the CPU2 and CPU3 contexts. These cannot access the console directly and will interface via the Kernel to access the console. This additional layer of abstraction provides the ability to create pseudo-TTY terminals and allow the user to switch between the two CP/M instances (similar to Unix).
Test/Debug Configuration
The rest of this log describes the functions/features of the R0.3 ROM in the Test/Debug Configuration. On a cold boot (power on or hardware reset) the machine will boot to the 8080 system monitor. There are a couple of issues to clean up with the keyboard initialization, so there may be an extra character shown after boot.
The monitor accepts input via the console (PS/2 keyboard and VGA display) and the RS232 serial port. This is the default start up, so the keyboard and display are not required. The board can be connected to just a serial terminal.
Serial Port
The RS232 serial port has a fixed speed of 9600 baud, one start bit, 8 data bits, no parity (9600-8-N-1). The serial port uses RTS/CTS hardware flow control. The LED is connected to the RTS line and will light when RTS is asserted. If the LED is off then the board is not ready for serial data.
The serial status can be toggled using the 'T' command in the monitor. Typing 'T' will turn the serial thread off/on and the RTS LED will toggle to show the serial status. An additional state is tracked by the serial interface to manage flow control. If a command is sent via the serial port then the monitor will enforce flow control and prevent the input and output buffers from overflowing. This will cause the RTS LED to go out during heavy serial load, like doing a dump command.
Note: some serial terminals and interface programs do not support RTS/CTS flow control correctly. This can result in some glitchy behavior.
Console
There are four native video modes supported by the board, with additional timings and fonts available. This provides the following 8 text modes:
- VGA @ 60Hz - 8x8 glyphs - 104x60 text
- VGA @ 75Hz - 8x8 glyphs - 80x60 text
- VGA @ 75Hz - 8x10 glyphs - 80x48 text
- VGA @ 75Hz - 8x16 glyphs - 80x30 text <-- cold boot starts here
- SVGA @ 60Hz - 8x8 glyphs - 80x75 text
- SVGA @ 60Hz - 8x10 glyphs - 80x60 text
- SVGA @ 60Hz - 8x16 glyphs - 80x37 text
- XGA @ 60Hz - 8x16 glyphs - 64x48 text
The video mode can be changed from the keyboard using a CTRL-ALT escape sequence as follows:
- CTRL-ALT-DEL - reboot machine to current mode
- CTRL-ALT-PAGE_UP - reboot machine to next mode
- CTRL-ALT-PAGE_DOWN - reboot machine to previous mode
The cold-boot console color scheme is set to the classic green text on a black background. The font, background, and foreground color can be changed by sending a byte to output port 2F ($CONF). The following command would update this to 78:
O2F 78
A control sequence from above will restart the video and fill the console memory with this value. The least-significant 3 bits from the first nibble sets the foreground color (RGB) and the least-significant 3 bits from the second nibble sets the background color. The most significant bits from the two nibbles set the one of the four fonts. The example shown sets the foreground text color to 7 (white) and the background color to 0 (black). The selected font is the 0b01 (thin serif). The available fonts are shown below.
Fonts with 8x8 and 8x10 glyph timings:
- 0 - thick serif - IBM PC BIOS. ca. 1981
- 1 - thin serif - COMPAQ MS-DOS 3.31 (Rev. G). ca. 1990
- 2 - thick san-serif (8x8) - Phoenix Enhanced Video BIOS PLUS (Chips 82C435) ca. 1985
- 3 - thick san-serif (8x10) - ditto with underline
Fonts with 8x16 glyph timings:
- 0 - thick serif - IBM PS/2 VGA/MCGA. ca. 1987
- 1 - thin serif - COMPAQ MS-DOS 3.31 (Rev. G). ca. 1990
- 2 - thick san-serif - Phoenix Enhanced Video BIOS PLUS (Chips 82C435) ca. 1985
- 3 - thick san-serif - ditto with underline
Note: dark fonts on a light background will show some smudging of the video signal. This is due to the parasitic capacitance of the analog switch FETs. The CD4053 is the one of the original CMOS chips released by RCA 50 years ago. It has huge features!
Graphics
The machine supports a range of graphics modes, both 256 color and a hybrid 8-color version using a combination of the text mode with graphics-mode timing. So far only static image demos have been shown on the machine. The focus was on bringing up the operating system and text mode, so still a lot of work to do here.
Audio
The audio thread is off by default and the sound is muted. To use audio the thread can be turned on by sending a byte to output port A as follows:
OA 1
From 1 to 3 melodic voices can be enabled by sending the relevant value. A value of 0 will disable the audio thread and mute the audio. The audio instructions are part of the extended set that follow 0xDD: 0x10-0x13 configure the voice, 0x18-0x1B set the note (MIDI number), 0x1C-0x1F gate on, 0x14-0x17 gate off.
The following program sets up voice one and will gate on:
MVI A, 2 ; wave:0=sine,1=saw,2=sqr,15=noise LXI B, 00905H ; attack,decay LXI D, 00C02H ; sustain, release DW 011DDH ; config voice 1 MVI A, 33H ; MIDI note number DW 019DDH ; set note 1 ;GATE ON DW 01DDDH ; gate note on RET ;GATE OFF DW 015DDH ; gate note off RET
This can be loaded at location 0x100 via the monitor command L100 followed by this code:
3E 02 01 05 09 11 02 0C DD 11 3E 33 DD 19 DD 1D C9 DD 15 C9
Use the monitor command C100 to call the config and gate on code to hear the note. Use monitor command C111 to gate off. To play the same note again, just call gate on with C10E.
Note: Don't forget to start the audio thread first with at least the one voice using: OA 1
System Monitor
More details can be found in this log. The following is a quick summary of the commands that came with the original monitor code:
- AD<start> <end> Dump memory in ASCII from <start> to <end>.
- AL<address> Load ASCII data to <address>. End with Control-X.
- AS<start> <end> <chars> Search for ASCII data consisting of one or two characters, from <start> through <end> address.
- C<address> Call routine at <address> (should end in RET instruction).
- D<start> <end> Dump memory in hex and ASCII from <start> to <end>.
- F<start> <end> <data> Fill memory from <start> to <end> with byte <data> (hex or ASCII preceded by "'".
- G<address> Go to routine at <address>.
- H<address1> <address2> Hex math: report sum and difference of two hex addresses.
- I<port> Input (read) and display data from i/o port <port>.
- L<address> Load or edit memory from <address>. Enter new data in hex, ASCII preceded by "'", or <Return> to advance. <Control>-X will return to prompt.
- M<start> <end> <new> Move (copy) memory from <start> through <end> address to <new> start address.
- O<port> <data> Output (send) data to i/o port <port>.
- R<start> <end> <from> <to> Replace every occurrence of hex byte <from> to <to>, in range of addresses <start> through <end>.
- S<start> <end> <byte> <byte> Search for byte or word size data from start through end address.
- V<start> <end> <to> Compare (verify) data between <start> and <end> address with data starting at <to> address.
- Z<start> <end> Write zeroes to memory from addresses <start> through <end>.
The following additional commands were added to support the Novasaur:
- KF Kernel command - Format RAM disk drive - confirm with (capital) 'Y'.
- KG<track><sector> <to> Kernel command - Get RAM disk record <track><sector> and copy to <to> address.
- KP<track><sector> <from> Kernel command - Put RAM disk record <track><sector> copied from <from> address.
- P Measure 8080 processor speed and display in KIPs.
- T Toggle serial mode (default on, toggle off).
- Q Quit monitor program and run CP/M.
CP/M
In the final configuration the machine will boot to CP/M 2.2. There are two ways to get to CP/M from the monitor: use the quit command Q or call the BDOS directly with CDA00
Before using CP/M the A: drive needs to be formatted. Use the monitor command KF to do this followed by capital 'Y' to confirm. This initializes the A: drive directory of the RAM disk. This is only needed once if the battery is installed to backup the RAM.
The ROM contains a bank of memory with the basic CP/M utilities installed. This is represented as the read-only B: drive. Commands can be run by switching to the B: drive or by referencing the drive at the start of the command. The disk information can be shown using the following:
b:stat dsk:
There are a couple of additional programs on the B: drive: basic.com and xmodem.com These are still work in progress, but basic is mostly functional. There are a couple of issues to be aware of: This version of basic is expecting upper case. There isn't a caps-lock, so hold the shift key down to enter programs (sorry!). The test/debug console code has a race condition that causes an infinite loop when a program is interrupted via ctrl-C.
To be continued...
-
8k BASIC
03/21/2022 at 03:49 • 0 commentsThe hope was to ship the Novasaur with some form of BASIC on board. There is just enough space on the B: drive to fit a 1970's era 8k BASIC. The more capable MBASIC 5.21 can be loaded to the A: drive, but at over 24k it won't ship in the ROM.
The initial effort was bringing up the original Microsoft Altair BASIC (circa 1978). There is a source code available, but this proved to be defective. The alternative was the IMSAI 8K Floating-point BASIC (circa 1977). This source code was more successful!
The image above shows the following BASIC program running at actual speed:
10 FOR X=0 TO 2*PI STEP PI/15 20 PRINT SPACE(INT(SIN(X)*36+36));"*" 30 NEXT X
There are still some optimizations to be made in terms of console integration and the software restarts. The performance isn't too bad though considering the CPU is running at 1/5th the speed of the original hardware.