ASCIIToHex

Purpose: Convert two (2) ASCII BYTEs into their hexadecimal equivalent value.
Assumes:   The byte order is R25:R24, but they are two (2) ASCII BYTEs, not a WORD.
Passed: R25   BYTE bHigh ASCII digit representing the MSByte (e.g., '1', 'a')
R24 BYTE bLow ASCII digit representing the LSByte (e.g., 'F', '9')
Returns: R24   BYTE   bASCII   Hexadecimal value corresponding to the 2 ASCII digits
T FLAG   BIT_T   CLEAR (0 or FALSE) if no error, SET (1 or TRUE) on error
An error is any digit NOT '0' to '9', 'A' to 'F', or 'a' to 'f'
Alters: Only R24, R25, and the FLAGs (SREG)
Notes: "Error" above means any unconvertable ASCII BYTE pair, i.e., not in the "00" to "FF" range.
An ASCIIz terminating NULL is a good example of using 'T' to signal the end of convertable data.

HexToASCII

Purpose: Convert the Low-Order NYBBLE of R24 to its UPPERCASE ASCII character.
Assumes:   Uppercase "A" through "F" are used rather than lowercase AND
The caller has saved the High-Order NYBBLE.
Passed: R24 BYTE bDigit the Low Nybble to be converted, i.e., to '0' to '9', 'A' to 'F' (none invalid)
Returns: R24   BYTE   bASCII   the ASCII character representing the LSNybble digit, 0x30 to 0x39, 0x41 to 0x46
Alters: Only R24 and the FLAGs (SREG)
Notes: Only the LOW 4 bits of R24 are used so the caller must save R24, swap, and call again to get both digits.
The bits in the MSNybble (Most Significant Nybble) of R24 are lost.

UpperCase

Purpose: Convert a lowercase ASCII character to its UPPERCASE equivalent.
Assumes:   Any BYTE value may be passed; only 'a' through 'z' are modified.
Passed: R24 BYTE bChar the ASCII BYTE to be examined and converted, if lowercase
Returns: R24   BYTE   bCHAR   the ASCII character, unchanged unless 'a' (0x61) through 'z' (0x7A)
Alters: Only R24 and the FLAGs (SREG)

Example   
 Part 1:
   .ORG  0x1000
AResultBuffer = 0x0700

ASCIItoHex_Demo:
   ADIW    R26, 0                   ; If 'X' is zero, the command line tail is
   BRNE    AASCIItoHex_Begin        ;  empty, so just exit
   RET

ASCIItoHex_Begin:
   ADIW    R26, 1                   ; Move 'X' past the initial space character
   LDI     R31, AResultBuffer >> 8  ; Point 'Z' at an aribitrary buffer in SRAM
   LDI     R30, AResultBuffer & 0xFF

ASCIItoHex_Loop:
   LD      R25, X+                  ; R25 is the MSNybble, R24 is the LSNybble,
   LD      R24, X+                  ;  so this is reading the 2 ASCII digits
   CALL    AASCIIToHex              ; Call the System Function to convert it
   BRTC    AASCIItoHex_Store        ; Any unrecognized digit terminates the
   LDI     R24, 0                   ;  string; replace it with an ASCIIz NULL

ASCIItoHex_Store:
   ST      Z+, R24                  ; Store the new BYTE, either converted or
   BRTC    AASCIItoHex_Loop         ;  or NULL terminator, and loop if former
                                    ; Fall through into UpperCase_Init
Example   
 Part 2:
UpperCase_Init:
   ADIW    R30, 16                  ; Align 'Z' so the last digit is 0 (e.g., 
   ANDI    R30, B11110000           ;  0x0720, called a "sentence" boundary)
   MOVW    R20, R30                 ; Save it for the HexToASCII step below
   LDI     R27, AResultBuffer >> 8  ; Point to the BYTEs saved above
   LDI     R26, AResultBuffer & 0xFF

UpperCase_Loop:
   LD      R24, X+                  ; Retrieve the next BYTE and convert it
   CALL    AUpperCase               ;  to its UPPERCASE equivalent
   ST      Z+, R24                  ; Store it then see if it was the NULL
   OR      R24, R24                 ;  ASCIIs string terminator (assumes that
   BRNE    AUpperCase_Loop          ;  it was text); loop back if not a NULL
                                    ; Fall through into HexToASCII_Init
Example   
 Part 3:
HexToASCII_Init:
   ADIW    R30, 16                  ; Align 'Z' again to the next "sentence"
   ANDI    R30, B11110000
   MOVW    R26, R20                 ; Initialize 'X' to the prior 'Z' start

HexToASCII_Loop:
   LD      R24, X+                  ; Retrieve the next hex BYTE to convert
   CPI     R24, 0                   ; If is it a NULL terminator (set by the
   BREQ    AHexToASCII_Ret          ;  Uppercase code above), exit the loop
   MOV     R25, R24                 ; Save the BYTE just retrieved to R25
   SWAP    R24                      ; Swap the MSNybble to the LSNybble and
   CALL    AHexToASCII              ;  convert it (MSNybble) to its ASCII
   ST      Z+, R24                  ;  equivalent and store it, advancing 'Z'
   MOV     R24, R25                 ; Convert the Least Significant Nybble to
   CALL    AHexToASCII              ;  to its uppercase ASCII character and
   ST      Z+, R24                  ;  store it, again advancing 'Z' pointer
   RJMP    AHexToASCII_Loop         ; Always loop back; exit check done above

HexToASCII_Ret:
   ST      Z, R24                   ; Since R24 = 0 caused the loop to exit,
   RET                              ;  NULL terminate the string and return
Test all 3:
m>EFS 0x700 0x7E 112  ; Fill the buffer with nonzero BYTEs
m>DS+ 0x700 112       ; The initial destination buffer contents:
SRAM contents:
0700:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
0710:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
0720:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
0730:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
0740:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
0750:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
0760:  7E 7E 7E 7E 7E 7E 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ~~~~~~~~~~~~~~~~
m>@ 0x1000 44656d6f20737472696E67202D2031322c3334352e ; Note mixed case
m>DS+ 0x700 112       ; The results of all three (3) examples above:
SRAM contents:
0700:  44 65 6D 6F 20 73 74 72-69 6E 67 20 2D 20 31 32  Demo string - 12
0710:  2C 33 34 35 2E 00 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ,345..~~~~~~~~~~
0720:  44 45 4D 4F 20 53 54 52-49 4E 47 20 2D 20 31 32  DEMO STRING - 12
0730:  2C 33 34 35 2E 00 7E 7E-7E 7E 7E 7E 7E 7E 7E 7E  ,345..~~~~~~~~~~
0740:  34 34 34 35 34 44 34 46-32 30 35 33 35 34 35 32  44454D4F20535452
0750:  34 39 34 45 34 37 32 30-32 44 32 30 33 31 33 32  494E47202D203132
0760:  32 43 33 33 33 34 33 35-32 45 00 7E 7E 7E 7E 7E  2C3334352E.~~~~~
m>                                                                              
Notes: Example Parts 1 through 3 above were all assembled from one file, at one time, as a complete sequence, to generate the output shown above.
Dropin: 
(setup
code)
;   Setup for the ASCIIToHex() call:
; Passed:  R25 BYTE bHigh  ASCII digit representing the High Byte
;          R24 BYTE bLow   ASCII digit representing the Low Byte
; Returns: R24 BYTE bASCII Hexadecimal value for the R25:R24 ASCII digits
;          'T' FLAG BIT_T  CLEAR if accepted, FALSE if either digit not hex
; Alters:  R24, R25, and the FLAGs

;   Setup for the HexToASCII() call:
; Passed:  R24 BYTE bDigit Low Nybble to be converted to its ASCII equivalent
; Returns: R24 BYTE bASCII ASCII character representing LSNybble digit as hex
; Alters:  R24 and the FLAGs

;   Setup for the UpperCase() call:
; Passed:  R25 BYTE bChar ASCII CHARacter to be examined and converted
; Returns: R24 BYTE bCHAR ASCII CHARacter, changed if 'a' (0x61) to 'z' (0x7A)
; Alters:  R24 and the FLAGs
Also see:  -