                ORG     $0
                DC.L    $8000           stack pointer value after a reset
                DC.L    START           program counter value after a reset

START:          JSR     INIT_IO         initialize the DUART
                BREAK
                MOVE.L  #$1fa79ad9,-(SP)
                JSR     PUT_HEX         call PUT_HEX
                BREAK


********************************************************************************
********************************************************************************
*
* INPUT / OUTPUT stuff
*

DUART           EQU     $effc01
MR1A            EQU     0
MR2A            EQU     0
SRA             EQU     2
CSRA            EQU     2
CRA             EQU     4
TBA             EQU     6

BUFFER_F        DS.B    $ff             buffer containing $100 bytes with start
BUFFER_L        DS.B    1               ... and end address
                * caution: should be a multiple of word in order to avoid
                * alignment problems in subsequent statements!!!


********************************************************************************
*
* function: void INIT_IO( )
*
* description:
*   Initializes the Dual UART Device
*
* registers affected: none
*

INIT_IO:        MOVEM.L A0,-(SP)                save registers on stack
                LEA     DUART,A0
                MOVE.B  #%00010000,CRA(A0)      reset MRxA pointer
                MOVE.B  #%00000011,MR1A(A0)     8 data bits
                MOVE.B  #%00000000,MR2A(A0)     normal mode
                MOVE.B  #%10111011,CSRA(A0)     set clock to 9600
                MOVE.B  #%00000100,CRA(A0)      enable Tx
                MOVEM.L (SP)+,A0                restore registers
                RTS


********************************************************************************
*
* function: void PUT_CHAR( (SP))
*
* description:
*   Prints the character that is passed via the stack (lowest byte of the long)
*
* registers affected: none
*


PUT_CHAR:       LINK    A6,#0           store pointer to argument frame in A6
                MOVEM.L D0,-(SP)        save registers on stack
                MOVE.L  8(A6),D0        fetch character

PC_LOOP:        BTST    #2,SRA+DUART    check whether port is ready
                BEQ.S   PC_LOOP
                MOVE.B  D0,TBA+DUART    write data to output

                MOVEM.L (SP)+,D0        restore registers
                UNLK    A6              restore A6
                MOVE.L  (SP),4(SP)      kill argument frame: move return address
                ADDQ.L  #4,SP                                adjust SP
                RTS


********************************************************************************
*
* function: void PUT_STR( (SP))
*
* description:
*   Prints the string (sequence of bytes) whose starting address is passed via
*   the stack (long)
*
* registers affected: none
*


PUT_STR:        LINK    A6,#0           store pointer to argument frame in A6
                MOVEM.L A0/D0,-(SP)     save registers on stack
                MOVE.L  8(A6),A0        fetch address of string

PS_LOOP:        MOVE.B  (A0)+,D0        fetch first character of string
                CMPI.B  #0,D0           is this the terminating 0?
                BEQ     PS_DONE
                MOVE.L  D0,-(SP)
                JSR     PUT_CHAR
                BRA     PS_LOOP

PS_DONE:        MOVEM.L (SP)+,A0/D0     restore registers
                UNLK    A6              restore A6
                MOVE.L  (SP),4(SP)      kill argument frame: move return address
                ADDQ.L  #4,SP                                adjust SP
                RTS


********************************************************************************
*
* function: void PUT_HEX( (SP))
*
* description:
*   Prints the hex number that is passed via the stack (long)
*
* registers affected: none
*

PUT_HEX:        LINK    A6,#0           store pointer to argument frame in A6
                MOVEM.L D0,-(SP)        save registers on stack
                MOVE.L  8(A6),D0        fetch hex number

                MOVE.L  #BUFFER_F,-(SP) push pointer to start of buffer
                MOVE.L  #BUFFER_L,-(SP) push pointer to end of buffer
                MOVE.L  D0,-(SP)        push hex number
                JSR     HTOA            create ascii-rep in buffer and 
                                        * return ptr to result on stack
                JSR     PUT_STR         print buffer starting at returned ptr

                MOVEM.L (SP)+,D0        restore registers
                UNLK    A6              restore A6
                MOVE.L  (SP),4(SP)      kill argument frame: move return address
                ADDQ.L  #4,SP                                adjust SP
                RTS


********************************************************************************
*
* function: (SP1) HTOA( (SP1), (SP2), (SP3))
*
* description:
*   Converts the unsigned hex number (SP3) into an ascii string which is put
*   into the buffer whose begin and end is pointed at by (SP1) and (SP2)
*   respectively. The starting address within the buffer is returned via the
*   stack (SP1).
*
* registers affected: none
*
                                                                                
HTOA:           LINK    A6,#0           store pointer to argument frame in A6
                MOVEM.L D0-D2/A0-A1,-(SP)
                MOVE.L  8(A6),D0        fetch hex number
                MOVE.L  12(A6),A1       fetch pointer to end of buffer
                MOVE.L  16(A6),A0       fetch pointer to start of buffer

                MOVE.B  #$00,(A1)       write terminating 0 into buffer
                MOVE.L  #8,D2           convert 8 digits

HTOA_LOOP:      MOVE.L  D0,D1
                ANDI.L  #$F,D1          separate last digit
                ADDI.B  #$30,D1         add '0' in order to get a char '0', ...
                CMPI.L  #$39,D1         is char > '9' ?
                BLE     HTOA2
                ADD.B   #$7,D1          add ('A' - ('9' + 1))
HTOA2:          CMPA.L  A1,A0           end of buffer reached?
                BEQ     HTOA_OOB
                MOVE.B  D1,-(A1)        write char into buffer
                LSR.L   #4,D0           shift addr 4 Bit right
                SUBI.L  #1,D2
                BNE     HTOA_LOOP

                CMPA.L  A1,A0           end of buffer reached?
                BEQ     HTOA_OOB
                MOVE.B  #$24,-(A1)      write '$' into buffer
                MOVE.L  A1,16(A6)       write result over buffer arg!
                JMP     HTOA_DONE

HTOA_OOB:       MOVE.L  12(A6),16(A6)   out of bounds: return empty string

HTOA_DONE:      MOVEM.L (SP)+,D0-D2/A0-A1
                UNLK    A6              restore A6
                MOVE.L  (SP),8(SP)      kill last two entries of arg.frame:
                ADDQ.L  #8,SP             move return address, adjust SP
                RTS


END
