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 0x0200, 0x1700, // Don't forget to clear R7 0x0000, // 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 -------------------------------------------------------------------------------------
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.