Hexadecimal Entry

A project log for Suite-16

Suite-16 is a 16-bit cpu built entirely from TTL. It is a personal exploration of how hardware and software interact.

monsonitemonsonite 11/02/2019 at 20:290 Comments

It's been a bit of a slow week, and I must admit that I lost focus in the middle of the week with my hexadecimal number entry routine.

In my opinion, hexadecimal entry is more complex than decimal entry, because the characters 0-9, and A-F are discontinuous in the ASCII table.

Characters 0-9 need to have 0x30 subtracted, whilst characters A-F need to have 0x37 subtracted. Anything else is not a valid hex digit and can be ignored until a newline character is seen.

With each incoming character you have to check if it is a legitimate hexadecimal digit, and modify it, either by subtracting 0x30 or 0x37 to get it's true numerical value.

This test and modify is best done using a short subroutine - at the end of the listing

Once you have the numerical value allocated to the character the rest of the routine is similar to the decimal entry routine, except that you are multiplying by 16 rather than 10.

There's a further twist in the tail when you detect the end of the valid digits and have to add in the last digit - modifying it accordingly.

This first draft allows hexadecimal mumbers up to 0xFFFF to be entered and prints them back in decimal format. 

You can find the latest listing for the Arduino in my Github Suite-16 repository

EDIT:  I found some redundant code in the main GETHEX routine and have managed to shorten it from 52 to 34 words.  

Further optimisation became possible with the test and modify subroutine approach.  

As the instruction set currently lacks a shift left instruction,  and it's not yet proven that ADD R0, R0 will be implemented in hardware, the routine to multiply the accumulator by 16 is a little cumbersome using eight instructions rather than a possible four.

EDIT: After proving the ADD R0, R0 instruction and fixing a minor bug the routine is now down to 31 words in length.

// 0x003C -----------------------------GETHEX----------------------------

        // Accepts a hexadecimal number up to FFFF from terminal input buffer
        // converts it to an integer and puts it into register R0
        // It can then be printed out as a decimal using PRINTNUM - for checking integrity
        // R1 is the pointer in the text buffer - which starts at 0x0200
        // R4 is used as a temporary store for the character in the accumulator R0
        // R5 is used in the "Times 16" routine
        // R7 is used to accumulate the powers of 16 when forming the integer in R0
        0x1100,     // SET R1, 0x0200    text buffer start
        0x1700,     // Don't forget to clear R7 

     // 0x0040--------------------------------------------------------------------------------------  
        0x4100,     // LD AC, @R1  get first character from buffer  :Getchar
        0x3400,     // Store R0 in R4
        0xE100,     // INC R1
        0x4100,     // LD AC, @R1  get next character - and test to see if it's a number or hex digit or space newline etc
        0x0B30,     // Subtract 0x30 Is it bigger than 0x30?
        0x0250,     // BLT 0x50 Quit  No - so must be a space or newline etc
        0x0B17,     // SBI 0x17  is it bigger than 0x47 ascii for "F" ?
        0x0350,     // BGT 0x50 Quit Not a hexadecimal digit
        0x0853,     // CALL 0x0053 Restore, Test and Modify R0
        0xA700,     // Add in the accumulating total from R7 - ready to multiply
        0xA000,     // ADD R0, R0  Double R0  2X
        0xA000,     // ADD R0, R0  Double R0  4X
        0xA000,     // ADD R0, R0  Double R0  8X
        0xA000,     // ADD R0, R0  Double R0  16X
        0x3700,     // Store R0 in R7   R7 is the accumulating total of all the digits multiplied by powers of 16
        0x0040,     // BRA 0x0040       Get the next digit

     // 0x0050-------------------------------------------------------------------------------------- 
        0x0853,     // CALL 0x0053      Restore, Test and modify R0
        0xA700,     // Add the accumulated sum from R7 - integer decimal number is now in R0   
        0x0010,     // BRA 0x0010  Print it in decimal     
     // 0x0053---------------------------------TEST R0 & MODIFY--------------------------------------

        // If R0 = 0-9 subtract 0x30 to form a number 0-9
        // If R0 = A-F subtract 0x37 to form a number 10-15

        0x2400,     // Get R0 back from R4   - we now have a hex character in the range 0-F and need to convert it to a value 0-15
        0x0B40,     // Subtract 0x40 Is it bigger than 0x40? Then subtract 0x37 else subtract 0x30
        0x0258,     // BLT Not A-F so subtract 30 and return
        0x0A09,     // ADI 0x09 (restores and corrects R0 to correct numerical value)
        0x005A,     // BRA  Return
        0x2400,     // LD  R0, R4   Get the character back in R0 - we know it's 0-9
        0x0B30,     // Subtract 0x30
        0x0900,     // RET
        0x0F00,     // NOP

        0x0F00,     // NOP
        0x0F00,     // NOP
        0x0F00,     // NOP
        0x0F00,     // NOP

       // 0x0060 -------------------------------------------------------------------------------------