Tuesday, 24 July 2012

Buzzer added, Code base released

A close up of the final board for the NRI 832.

I have added a piezo buzzer on the left. It provides a beep on start up and a beep whenever a key is pressed which does help with using the board.

Also, the final code archive should now be in the links on the right.

This is an archive of the entire project. If anyone wants to rebuild this, note that the Arduino code is included rather than linked - I couldn't figure out how to link 'C' code not part of the Arduino project in (I'm not even sure if it is possible) so this will require some tweaking.

Monday, 23 July 2012

From Prototype to Final

The last one was of course a prototype. I have now built a final permanent version on an Arduino Prototyping Shield with a detachable keyboard which is much easier to use than the old one hanging off the Arduino :)

Other than that it is much the same except the order of the LEDs is reversed. That's because this one is upside down to the prototype (the Arduino programming socket is now on the right).

The design is the same - 8 LEDs, 8 1k Resistors, 3 x 4 7 pin keypad, Arduino Duemanona - that thing, Uno, Leonardo, just about any Arduino is up to this.

I might add a beeper to this, for the following reasons.
  • I've got one in my box of electronic bits.
  • I've got some unused Arduino pins
  • I can use it to give audio feedback on key presses
  • I can (maybe) add some Audio instructions to the NRI832.

With the policy of plausible-in-1972-hardware (like the RAM* and Subroutine system)) though this means that hardware improvements have to be reasonably plausible.

I can't just plug an AY-3-8912 (award yourself 1 retropoint if you know what that is without looking). It would have to be something like a latch feeding a programmable down counter with bit 0 driving a speaker.

One thing that could be plausibly uprated is the speed. As far as I can see the clock speed is completely arbitrary. It could be driven a lot faster - it's stock 74 series TTL which has a propagation speed in nano seconds. It could probably run 50 times faster without breaking sweat. I suppose there wouldn't be much point though.

Thursday, 19 July 2012

Dracula has risen from the Grave.

It lives :)

The video above shows the new improved NRI832. It's running a simple program (see below) at what I think is the speed, about 16Hz (there's a 250Hz clock and 8 fetch and 8 execute cycles).

What happens in the video ... okay, it's not that exciting but it's still better than Gigli.

  1. I press the reset button
  2. The LEDs all blink to show it's alive
  3. The LEDs show the first program byte 00000011 (e.g. LDA 03)
  4. I press 9 (the run button)
  5. It displays the accumulator as it is running, hence the counting effect.
  • 00 LDA 03
  • 01 ADD 04
  • 02 JMP 01
  • 03 0
  • 04 1
I will upload some more demonstration stuff when I can stabilise my camera. This was shot with the hand you can't see holding my Android phone :)

Prototype Hardware

The rats nest to the right is the prototype for the NRI832 hardware. Nor running actual code yet, just a testing program that takes a key from the keypad and displays its ASCII value on the LEDs (00110010 == $32, or character '2').

Despite the mess it is relatively simple. It is an Arduino Duemanolive (sic ?) - i.e. a Mega328 based Arduino. Ontop of that is a prototyping shield with a breadboard.

The LEDs are connected to ground via 8 1k Resistors and are connected to pins 10,9,A5,A4,A3,A2,A1,A0 respectively (left to right).

The keypad is a standard 3x4 keypad (almost everywhere sells them) and it is connected to 8,7,6,5,4,3,2 (left to right).

Pins 1 and 0 are NC because I used Serial Debugging at one point.

Unfortunately it is upside down. On all these trainer-type constructs the display is always above the keyboard. I used a pin strip (6 pins) and a wire to fit the keyboard (the wire because of the gap between pins 7 and 8 on an Arduino).

Most of the code is written now - the 'C' code simulates the Arduinos operation, providing functions to isolate the actual physical I/O, so I just need to glue it to this code and hopefully it should work. The C code link on the right has been updated with this new code. Not that it's very interesting :)

Tuesday, 17 July 2012

C version of CPU Core

To get the system into an Arduino, I need a C version. This also can be used for simulating, running programs in a command line and for testing.

The first version of this is now available. It has three modes of use controlled by a single parameter.

nri832 run - runs the simulator for the Arduino system which isn't implemented yet.

nri832 test - runs the unit test of the CPU core, running 1,000,000 simulated instructions which takes about 7 seconds on my PC.

nri832 ???? - runs the binary file and dumps the processor status to the console as it goes along.

The code is for Code::Blocks and the provided binary is for 64 bit Linux, though it should compile on any version of gcc or more or less any other 'C' compiler.

The picture shows the result of a run of the 'divide' code.  It is dividing $86 (134) by $0C (12) giving a result of $0D (13) remainder $02 (2).

These values are store in the data memory except for the result which is in the Accumulator.

This version also supports the subroutine extensions and 512 bytes of memory.

Monday, 16 July 2012

NRI832 Assembler now available.

Now you can write NRI832 code using an assembler. The assembler takes source files and creates a binary output file, and a source/object listing.

The assembler is written in Python and requires version 2.7. The archive includes the multiplication and division routines, and a version of the divide code using the paging system.

To use it, you need to run it as a Python script from the command line (okay, Visual Studio 2012 it is not .....) and pass source file name(s) as a parameter.

As well as producing hexadecimal listing, it also produces a 737 octal listing (i.e. an octal number representing bits 5,6,7, bits 3,4, and bits 0,1,2. The reason for this is that the hardware version won't use toggle switches but a 3x4 keypad (see piccy), and the operation codes are better suited to 737 format than 377 format.

I am using a 3x4 keypad because .... that's what I've got in my box of electronic bits and bobs. Actually a 4x4 keypad allowing Hexadecimal opcodes wouldn't be as clear and the octal keypad gives four keys for controlling the machine. Using a 737 format gives you the opcode as the first digit and the operand as the last two. However it is a bit of a daft thing for constants. So it'll be one of these, 8 LEDs, 8 resistors and an Arduino Uno.

I wasn't ever actually going to reproduce the physical controls of the NRI832. I do not have 128 toggle switches for one thing. If I did I wouldn't want to spend hours wiring the things up along with the multiplexer circuits. It would be a nightmare to program anyway. The toggle switches aren't too bad, but memory locations 16-31 (the TTL Ram) you have to write a little program to load the code into there and you can't really check it.

It also outputs a URL which for Linux (yo !) and iMac (rich or what ?) users means you can write click on it and open the object code in the javascript version, in the same way the multiply example works. Windows users will have to cut and paste it into the browser bar.

However, the assembler does support the subroutine calls mechanism described earlier and the javascript emulator does not.

Friday, 13 July 2012

Javascript NRI832 now running

I now have a working 'classic' NRI832 emulator (see picture right). It looks the same as the earlier one, but this one actually works.

This is the display after running the multiplication example in the reference manuals.

You can try it out by visiting NRI832 Emulator - Multiplication - the code is loaded in via the query string.  It is calculating 5 x 7 which is 00100011 (35) as can be seen on the accumulator display.

To run it, press the 'Start' button. To change the run speed use the High / Low switch. To single step run it, set the Clock to 'Manual' and press the Step button.

To perform a different calculation put the two numbers you want to multiply into memory locations 11 and 12 using the toggle switches (blue), reset the computer, and press 'start' again

It is a peculiarity of the system that the Start / Step buttons only work when the Clock switch is on Auto / Manual respectively.

It works very similarly to the original (as far as I can tell from the manual). The main differences are that there are 32 'switches' to set program memory rather than 16 as on the original - and there is no disassembly column, obviously :)

The source code can also be downloaded (see the links on the right)

Note that this application now uses cookies - the current state of the memory / switches is stored in a cookie so that if  you refresh the page the current program is not lost.  Please see usual blather about cookies and privacy - the cookie in this application just stores a 64 character string representing the 'program memory'. 

Oh, and it also keeps all your bank account details and the location of all the valuables in your house, and the cookie will sneak out of the computer in the night and strangle you.

Subroutines - an addendum

Having pondered this for a little time today, I think using STA $00 as the effective return from subroutine is a bad idea.

The reason is because you can't do a subroutine call to the root page, zero. This introduces as unnecessary limit because you may want to write code to the 16 bytes of RAM to do things like indexing and indirection.

So, STA $0F is now the 'return from subroutine' (actually , switch paging register and PC back to original without long branch). This makes code difficult to access in page $F - you can't call that page - but not impossible (you can get there by running code past page $1DF.

This is, of course, completely insane given the hardware :)

Thursday, 12 July 2012

Souping up an NRI 832 - Subroutines

The other obvious thing missing is a subroutine system.

My first thoughts along this line were rather borrrring. Basically implementing a latch and copying the information to from the stack on call and return.

However, in keeping with the easily extensibility and TTL Feasability idea, I decided to pinch an idea from the RCA 1802 Microprocessor.

Rather than have a stack, I may go for multiple Program Counters (and Page Registers). Well, two.

This makes it very simply plug in. Duplicating the program counter and paging hardware is fairly simple - you can copy most of the inputs directly and just gate the clock and preset lines, and multiplex the output lines (the 5 or 9 bit program counter) - this way you have 2 9 bit Program Counter/Page register pairs, with a JK Flip Flop to toggle between the two of them.

This models - sort of - the 1802 subroutine system which has 16 index registers and you pick one to be a program counter. Subroutines are done by loading the another index register with the routine address and making that the program counter. To return, set the original one to the program counter.

The simplest way of doing this switch is to make it part of the STA 0x instruction (which now becomes an extended jump remembering the return).

If there are two sets of program counter/page register then an STA 0x instruction would switch to the other set before doing the page jump (in T1), so that the new page and resetting of the PC would be done in the other set of program counter, page register - the original one would have the return address.

The remaining issue is that of the return, which would reset the flip flop selecting the program counter/page register. This could be done using the STA 00 instruction, easily detected using a NOR gate.

Normally you would not do a long jump to page 0 because that would be effectively rerunning the program.

So you could disable the long jump for STA 00 and have it only do the actual page write / program counter clear for STA 01-STA 0F. STA 00 would still toggle the pair selector flip flop back again, but wouldn't change the page register or the program counter, thus resuming code from where the routine called the subroutine.

This is obviously only a single level of subroutine call. But it's only 512 bytes anyway.

And we still have perfect backwards compatibility.

Wednesday, 11 July 2012

Souping up a NRI 832 - More Memory

The NRI 832 is quite limited. This isn't actually anything to do with the core design.  It is mostly to do with the shortage of program space, which is related to the cost of TTL memory - this is why the original design can operate with no memory at all, something of a record low for a home computer.

I want to upgrade the design, while retaining backward compatibility. However, in the spirit of RetroChallenge, this must be something that is feasible - sensibly - with TTL Logic Chips and without too much complexity.

There is a currently 5 bit program counter.  The plan is to add a 4 bit page register to the design, giving a whopping 512 bytes of program memory.

This would involve having a presettable 4 bit counter which can be written to using an used instruction. The obvious choice is STA for values from 0-F which currently does absolutely nothing as you cannot write to the 'ROM' space. This is better than the alternative (appropriating OPR instructions) because it does not require any changes to the OPR decoding.

So the output from the STA/EXEC/E2 line - which triggers the physical write, would be ANDed with the Not(A4) line to produce a signal which would latch the counter with the lower 4 bits of the instruction register.

The clock pin would be connected to bit 4 of the program counter, so when a carry out from that line occurred it would clock the page register, so that [Page1] [0x1F] would go to [Page2] [0x00] when incremented.

Additionally, this latching signal could reset the Program Counter, thus effectively making STA n 0-F a long jump to address n * 32

Memory reads for program and data would operate using this paged register, so each little 32 byte block would operate independently. This would be program code/constant data ; there would be no write access to this extended memory.

The exception to this would be memory access from 10-1F. The locations that access this memory would ignore the page register and read and write from the TTL as usual - allowing read/write access to 16 bytes of data memory.

This would mean that constants would tend to be placed in the first 16 bytes of a 32 byte page, because they could not otherwise be accessed (because loading and storing would be directed to page zero for addresses 10-1F.

This has the advantage of making it compatible with the standard 16 byte version of the NRI 832, which would ignore the page instructions.

Or I could just do the obvious and use a 6502. But that wouldn't be as much fun ......

Tuesday, 10 July 2012

Javascript Console now Working

This is a screenshot of the Console control for the Javascript version of the NRI832.

It is only partly working - you can toggle all the switches, push all the buttons, but it's a view only - none of them actually work.

It's written in CoffeeScript so the Javascript Code is a bit unreadable. I will release the source code when it's actually closer to finished.

It should work on almost any browser (only actually tested on Chrome,Firefox, IE6, IE8, iPad), except IE8 or earlier versions will be all square buttons rather than round ones as rounded DIVs are not supported. It is all drawn with empty DIVs (all the buttons and lamps) and HTML Text Elements.

On the subject of the Overflow flag

The reference is somewhat unhelpful with this. It says it 'monitors' the output signal from the adder, and clocks the JK Flip Flop that is the overflow bit on T7 (e.g. last bit shifted) when there is an arithmetic instruction (DCA, ADD, SUB).

It is 'initially reset' apparently which could mean either (i) it resets on reset or (ii) it resets in the fetch/execute cycle. Either is feasible as a sensible design, though (ii) is better because otherwise you can't clear the carry.

On the circuit the J line is set to the Adder Carry Out, the Reset to 'Clr' and the K line to OVFC. The FlipFlop is clocked by the system clock.  The circuit would suggest that the overflow flip flop is cleared by the system reset button.

J is the Carry out from the adder. The adder appears to operate whether you are adding or not. However, the ASD line forces the carry in to be zero outside ASD commands, and the input is gated off, so there cannot be a carry out on the 7th bit (because Carry In is zero and one of the inputs is zero).

However, this line must oscillate between 0 and 1 as the carry comes from the adder, otherwise the adder circuit doesn't work. So when CLK occurs the inputs to J must be 0 or 1, and K is OVFC.  The problem is I can't see where OVFC comes from - it calls it the "Overflow Control". It doesn't appear to be on any of the schematics.

The reference however states that during T7 J and K are both '1' if there is a carry out and this causes the overflow flag to change.  This would suggest OVFC = ASD.T7 e.g. set on the final calculation for an ASD instruction.

The thing that puzzles me is if J is toggling between 1 and 0 on carry out from sub bits in the serial addition and K is 0 then the JK Flip Flop will set itself to '1' when J=1 K=0 and CLK occurs.  If J=K=1 and CLK occurs then this does toggle the flip flop to its opposite state.

So if this is right, the the overflow is cleared at reset and set whenever there is a carry out from any bit position in the adder, and toggled when the 7th bit is non-zero.

This doesn't sound correct. You want it clocked on T7.ASD really, so that the value is stored on the 7th cycle of an add/subtract/decrement instruction.

I'm wondering if the given circuit diagram is actually correct.

This all sounds deeply silly. Mind you you could argue the same about the RetroChallenge :)

And as you can't access the overflow (without wiring in the SKC line) it makes absolutely no difference :)

Unless I have a magic moment, I'm going to assume it is cleared on reset and set on T7.ASD.CarryOut

The NRI832 Instruction Set

The NRI832 instruction set is described fairly well in the reference book, but it is slightly incomplete in places. So here is my interpretation of it, with a commentary for things that are unknown or derived from the schematic.

Main Instruction Set

000aaaaa LDA <addr>

Loads the A register with the contents of memory location aaaaa

001aaaaa STA <addr>

Stores the A register into memory location aaaaa. The memory location must be in the TTL Memory from 10000 to 11111 (16..31). If the unit is unexpanded, then this is written to the E register instead.

010aaaaa ADD <addr>

Adds the contents of the memory location aaaaa to the A register. The Overflow flag is set from the carry out of the 8th bit of this addition.

011aaaaa SUB <addr>

Subtract the contents of memory location aaaaa from the A register. This is done in twos complement arithetic - it is equivalent to adding the ones complement of the memory location aaaaa plus one.

The documentation does not say what happens to the overflow flag. As it uses the same hardware as ADD this will be a 'not borrow' result like the 6502 CPU - e.g set if A + ~Mem[aaaaa] + 1 has a carry out.

100aaaaa JMP <addr>

Set the Program Counter to aaaaa

101aaaaa JOM <addr>

Set the Program Counter to aaaaa if the A register is negative (e.g. bit 7 is non zero). There is no flag for this (as for the Z80 say), it simply tests the bit value as is.

110aaaaa JOZ <addr>

Set the Program Counter to aaaaa if the A register is zero. There is no flag for this (as for the Z80 say), it simply tests the accumulator value

111dxccc OPR <instruction>

These are extended instructions rather like on a PDP-8. There are currently eight, defined by the ccc bits. The d bit indicates the direction of the shift (0 = right,1 = left)

Technically the dx bits can have any value (apart from the shift) without affecting the operation. I am standardising the 'x' bit as zero in this project so I can extend the instruction set if I wish to do so. All extensions will be "plausible" (e.g. could be implemented in TTL at the time the machine was designed).

So x should by convention be zero for the 'standard' OPR instructions, and d should be zero for anything other than SHL.

OPR Instructions

111xx000 RAB

This rotates the A and B registers. This means, in NRI832 terms, swap them round. The "rotate" probably comes from the serial nature of the original CPU.

1110x001 SHR 

This shifts the A register 1 bit to the right, setting the most significant bit to zero. The least significant bit is lost.

This is a variant of the SHA instruction which does not specify direction (it is specified by bit 4) which I have given the SHR mnemonic to in case I write an Assembler.

111xx010 AND

Logical AND the B register to the A register

111xx011 DCA

Decrement the A register by 1.

This operation uses the serial adder (the ADD and SUB use) but jams the inputs to 1, so it is adding '11111111' binary to the Accumulator. Logically, therefore this should set the Overflow flag accordingly (e.g. it will be set to '1' unless the Accumulator was originally zero, an inverse borrow).

111xx100 CMA

Ones complement the accumulator

111xx101 SKC

SKC skips the next instruction to be executed, if the CDX connection is logical '1'.

This is actually unspecified. The documentation says "can be wired to sense practically any logical condition in the computer" and the CDX input (on page 4 of the schematic) actually isn't wired to anything at all on the rest of the schematics. 

It is a reasonable guess that the CDX connection is wired differently for different activities (I do not know what the courseware was) so it could be used to count pulses or something similar. 

Logically the most likely connection is to the overflow line as there is no other way of checking if a carry-out has occurred and there is nothing else to connect it to that makes any kind of sense. The reference document does suggest this. 

However at present it will be a no-operation effectively (e.g. assume CDX is logical zero)
111xx110 RAE

Rotates (e.g. exchanges) the A and E registers

111xx111 HLT

Stops the processor from running (if it is free running)

1111x001 SHL

This shifts the A register 1 bit to the left, setting the least significant bit to zero. The most significant bit is lost.

This is a variant of the SHA instruction which does not specify direction (it is specified by bit 4) which I have given the SHL mnemonic to in case I write an Assembler. 

About the Project

This entry for the retrocomputing challenge is to recreate the NRI832 computer, first in software, then in hardware.  

The big question - what is an NRI 832 ?

It's pictured on the right.

It's one of the first - possibly the first - home computers you could buy or build, along with things like the Mark-8, Educ-8 and Kenbak-1.

It was sold as a DIY kit, for $503, as a teaching computer. Unlike many of the courses available at the time though, it is actually a computer.

It is entirely built out of standard TTL Logic gates, about 75 of them, so you could actually build the real thing. I won't do it that way, I will reproduce it using more modern hardware - probably an Arduino. The main reason is I do not fancy wiring up the 128 switches - I'll use one of those cheap keypads instead.

It comes in two variations ; one has no RAM and 16 byte of ROM, the other has 16 bytes of RAM added.  You can still 'store' on the original, it just stores to the internal register instead.

The ROM is the array of switches you see on the picture - you 'program' it by setting each switch to the binary pattern.

The CPU (which is a serial processor) has 3 8 bit registers A,B and E, and an instruction set with 16 instructions - 7 of which have a single operand, and 9 of which have no operand.

It operates at 250Hz (fast mode) or 2Hz (slow mode)

Next thing to do is to read the available documentation. There were three manuals, but only two are available - the schematic and the construction manual. There was also an "11k Reference Manual" which I would guess was the training guide, but I've not been able to find it. All contributions accepted :)


The Circuit Diagram
The 10k Reference Manual

Picture (courtesy of OldComputerMuseum.com which also has some historical information)