01/06/2018 - Work on the Arduino port of the TMS0805 Simulator continues

A project log for Sinclair Scientific Calculator Emulator

A register level TMS0805 CPU emulator on an Arduino Nano runs the original 320 instruction calculator program. A custom PCB houses it all.

Arduino EnigmaArduino Enigma 03/22/2018 at 20:070 Comments

We start the process of porting to an Arduino sketch by looking under the hood.

Right click on an empty place on the page and select View page source. This is a very friendly page that is meant to be read and understood by others. We have to start finding out what happens in each of the following modules. 

The file cpu.js is important to us, so are masks_sinclair.js, model.js, sourceCode_Sinclair.js

Here is the beginning of the CPU step function, found in CPU.js

We have to start looking for important functions and their dependencies. The function step() seems important, it fetches an instruction, decodes and executes it. it depends on variable called model and it uses extensively a function called add. 

Javascript programs look like C, but it is not a strong typed language. Porting this code involves determining what the proper C type will be to replace the var declaration in Javascript. One has to find out if the value is 16 bits, 8 bits, positive values only or can it go negative. 

Below is the ported code. Since the instructions are numbers greater than 255, but less than 65535, and they are always positive, the type unsigned int (we could also use uint16_t). The variables classBits and opcode are bit shifts of the variable instruction. Looking at the amount of shifts or the mask applied with a bitwise AND (&) operator, one can see that these hold 8 bit values and can be expressed as byte or uint8_t. 

Looking at the add function we see that it depends on getMask and maskVec, time to find those functions and port them. 

As a quick example of the effort involved, here is the C version of this function. The amount of information that has to be added is visible. Since src1 is an array of 8 bit values that can go negative, signed char src1[] is used. The for loop logic counts down from 10 to 0, exiting when it goes negative, a signed char has to be used here as well.

The mask function is also found in cpu.js. We need to identify its dependencies and the data types of the variables used.

Here are the masks, expressed as an array of strings. Since this do not change, when porting these, the keyword PROGMEM will be used to keep them in ROM space in the Arduino and not load them into the very limited 2K RAM space. The pgm_read_byte_near() function is needed to get their values from ROM.

Here is an important data structure. It holds all the CPU registers, flags, program counter,

Finally, the actual original Sinclair program can be found in the objectCode variable. Above it is a commented disassembly of the program.

To put things in perspective, here is the whole program for the Sinclair Scientific Calculator. The rest of the Javascript files decode, execute, and interface these 320 instructions to the real world.

This was bothering me for a while. I could not find the definition of the keys[] array in any of the Javascript files. It turns out it was in the main webpage.

The following file is the beginning of the porting efforts. It contains the ALU (Arithmetic Logic Unic) functions such as ADD, SUB, COMPARE and their mask related dependencies. The setup function tests those functions and displays the results.

Here is the final Arduino Sketch (SinclairScientific1.ino). It has all the data structures needed by the CPU emulator. Everything is put together here, the keyboard is read, the display updated and the CPU stepped.

The code for the CPU emulator is here. These links open in a new window so you can see the Javascript code above and find the equivalent C functions and see how they were translated.

The following file is called by the step() function with a sequential instruction ID number assigned to each original cpu instruction. It was useful at the beginning to see that the instructions being executed matched the disassembly on the web page.

Time for a couple of Tweets: