;;*****************************************************************************
;;  FILENAME: USBUART.asm
;;    Version: 1.0, Updated on 2008/04/07 at 12:05:03
;;  Generated by PSoC Designer ???
;;
;;  DESCRIPTION: USBUART User Module Descriptors
;;
;;  NOTE: User Module APIs conform to the fastcall convention for marshalling
;;        arguments and observe the associated "Registers are volatile" policy.
;;        This means it is the caller's responsibility to preserve any values
;;        in the X and A registers that are still needed after the API
;;        function returns. Even though these registers may be preserved now,
;;        there is no guarantee they will be preserved in future releases.
;;-----------------------------------------------------------------------------
;;  Copyright (c) Cypress Semiconductor, 2006. All Rights Reserved.
;;*****************************************************************************
;;*****************************************************************************
include "m8c.inc"
include "m8ssc.inc"
include "memory.inc"
include "USBUART_macros.inc"
include "USBUART.inc"

;-----------------------------------------------
;  Global Symbols
;-----------------------------------------------
EXPORT USBUART_Start
EXPORT _USBUART_Start
EXPORT USBUART_Stop
EXPORT _USBUART_Stop
EXPORT USBUART_Init
EXPORT _USBUART_Init

EXPORT USBUART_Write
EXPORT _USBUART_Write
EXPORT _USBUART_CWrite
EXPORT USBUART_CWrite
EXPORT USBUART_PutString
EXPORT _USBUART_PutString
EXPORT USBUART_CPutString
EXPORT _USBUART_CPutString
EXPORT USBUART_PutChar
EXPORT _USBUART_PutChar
EXPORT USBUART_PutCRLF
EXPORT _USBUART_PutCRLF
EXPORT USBUART_PutSHexByte
EXPORT _USBUART_PutSHexByte
EXPORT USBUART_PutSHexInt
EXPORT _USBUART_PutSHexInt

EXPORT USBUART_bGetRxCount
EXPORT _USBUART_bGetRxCount
EXPORT USBUART_bTxIsReady
EXPORT _USBUART_bTxIsReady

EXPORT USBUART_Read
EXPORT _USBUART_Read
EXPORT USBUART_ReadAll
EXPORT _USBUART_ReadAll
EXPORT USBUART_ReadChar
EXPORT _USBUART_ReadChar

EXPORT USBUART_dwGetDTERate
EXPORT _USBUART_dwGetDTERate
EXPORT USBUART_bGetCharFormat
EXPORT _USBUART_bGetCharFormat
EXPORT USBUART_bGetParityType
EXPORT _USBUART_bGetParityType
EXPORT USBUART_bGetDataBits
EXPORT _USBUART_bGetDataBits
EXPORT USBUART_bGetDataBits
EXPORT _USBUART_bGetDataBits
EXPORT USBUART_bGetLineControlBitmap
EXPORT _USBUART_bGetLineControlBitmap
EXPORT USBUART_SendStateNotify
EXPORT _USBUART_SendStateNotify

EXPORT USBUART_bCheckUSBActivity
EXPORT _USBUART_bCheckUSBActivity
EXPORT USBUART_SetPowerStatus
EXPORT _USBUART_SetPowerStatus


AREA InterruptRAM (RAM,REL,CON)
;-----------------------------------------------
;  Variable Allocation
;-----------------------------------------------
EXPORT USBUART_APITemp
 USBUART_APITemp:                       BLK   2 ; Two bytes of temporary  storage shared by the API  functions


AREA UserModules (ROM, REL)
export USBUART_USB_EP_BIT_LOOKUP

.LITERAL
USBUART_HEX_STR:
     DS    "0123456789ABCDEF"
USBUART_USB_EP_BIT_LOOKUP:  ;
    DB     01H                       ; EP0
    DB     02H                       ; EP1
    DB     04H                       ; EP2
    DB     08H                       ; EP3
    DB     010H                      ; EP4
.ENDLITERAL

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_Start
;
;  DESCRIPTION:    Starts the USB User Module
;                    Sets the device selection
;                    Set the configuration to unconfigured
;                    Enables the SIE for Address 0
;                    Enables the USB pullup ( D+ for full speed)
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:    A  is the operation voltage
;
;  RETURNS:		 Nothing
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_Start:
_USBUART_Start:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3

IF (USBUART_bSerialNumberType & USBUART_SERIAL_AUTO)   ;if serial number automatic
    push    A   ;save incoming parameter
;Generate the serial number
    RAM_SETPAGE_CUR 0
    RAM_SETPAGE_MVW 0
    RAM_SETPAGE_MVR 0
    mov     [bSSC_TABLE_TableId],0x00
    SSC_Action(0x06)
    ; the USBUART_SerialString is located in the InterruptROM area so it located on page 0.
    mov     [bSSC_KEY1], <USBUART_SerialString ; prepare for mvi
    mov     A, 26
    mvi     [bSSC_KEY1], A ; string descriptor length 26 bytes
    mov     A, 3
    mvi     [bSSC_KEY1], A ; descriptor type 3 = string
    mov     [bSSC_KEY1+1], bSSC_TABLE_TableId
    mov     X, 6 ;loop for all 6 byes with S/N
.SNCopyLoop:
    mvi     A, [bSSC_KEY1+1] ;get S/N byte
    push    A
    asr     A ; select lower nibble
    asr     A
    asr     A
    asr     A
    and     A, 0x0F ; clear high bits
    index   USBUART_HEX_STR ; get ASCII
    mvi     [bSSC_KEY1], A ; save character
    mov     A, 0
    mvi     [bSSC_KEY1], A ; save 0x00 for Unicode high byte
    pop     A
    and     A, 0x0F ;clear high bits
    index   USBUART_HEX_STR ; get ASCII
    mvi     [bSSC_KEY1], A ; save character
    mov     A, 0
    mvi     [bSSC_KEY1], A ; save 0x00 for Unicode high byte
    dec     X
    jnz     .SNCopyLoop
    pop     A   ;restore incoming parameter
ENDIF
    RAM_SETPAGE_IDX >USBUART_bCurrentDevice ; Set the IDX_PP to the right page
	RAM_SETPAGE_CUR >USBUART_bCurrentDevice ; Set the CUR_PP to the right page

;Start User Module
    mov     [USBUART_bCurrentDevice], 0; The app selects the desired device

    mov     [USBUART_TransferType], USB_TRANS_STATE_IDLE ; Transaction Idle State
    mov     [USBUART_Configuration], 0 ; Unconfigured
    mov     [USBUART_DeviceStatus], 0  ; Clears device status

    mov     [USBUART_EPDataToggle], 0    ; Clear all EP data toggles
    mov     reg[TMP_DR0], 0	           ; EP1 start address in PMA space
	mov     reg[TMP_DR1], 64              ; EP2 start address in PMA space
	mov     reg[TMP_DR2], 128             ; EP3 start address in PMA space
	mov     reg[TMP_DR3], 192             ; EP4 start address in PMA space

;    mov     X, USB_MAX_EP_NUMBER      ; Set up loop to clear all of the endpoint data items
; Flow or jump here to clear the data for the next endpoint
;.loop:
;    mov     [X + USBUART_EPDataToggle], 0    ; Or in the toggle
;    dec     X                         ; Are we done?
;    jnz     .loop                     ; Jump to do another endpoint
; Flow here to enable the SIE

    mov     reg[USBUART_ADDR], USB_ADDR_ENABLE ; Enable Address 0
	mov     reg[USBUART_USBIO_CR0], USB_AUTO_DPDM

    M8C_SetBank1
	mov     reg[USBUART_USB_CR1], A
	M8C_SetBank0
    mov     reg[USBUART_EP0MODE], USB_MODE_STALL_IN_OUT ; ACK Setup/Stall IN/OUT
    M8C_EnableIntMask USBUART_INT_REG, (USBUART_INT_RESET_MASK | USBUART_INT_EP0_MASK)

;   Enable the pullup so we can start to rock and roll
    mov     reg[USBUART_USBIO_CR1], USB_PULLUP_ENABLE ; Pullup D+

    RAM_EPILOGUE RAM_USE_CLASS_3
	RAM_EPILOGUE RAM_USE_CLASS_4
    RET
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_Stop
;
;  DESCRIPTION: Performs all necessary shutdown tasks required for the USBUART
;               User Module.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS: None
;
;  RETURNS:   Nothing
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_Stop:
_USBUART_Stop:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >USBUART_bCurrentDevice ; Set the CUR_PP to the right page

    mov     [USBUART_bCurrentDevice], 0; The app selects the desired device

    mov     [USBUART_TransferType], USB_TRANS_STATE_IDLE ; Transaction Idle State
    mov     [USBUART_Configuration], 0 ; Unconfigured
    mov     [USBUART_DeviceStatus], 0  ; Clears device status
    mov     reg[USBUART_ADDR], 0       ; Clear the address and Address 0
	and     reg[USBUART_USBIO_CR1], ~USB_PULLUP_ENABLE ; Release D+
    mov     reg[USBUART_INT_REG], 0x00 ; Enable the interrupt

	RAM_EPILOGUE RAM_USE_CLASS_4
    RET
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bCheckUSBActivity
;
;  DESCRIPTION: Checks for USB Bus Activity.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS: Nothing
;
;  RETURNS:   A is a flag that indicates bus activity
;
;  SIDE EFFECTS: ;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_bCheckUSBActivity:
_USBUART_bCheckUSBActivity:
    RAM_PROLOGUE RAM_USE_CLASS_1
    M8C_SetBank1
    mov    A, reg[USBUART_USB_CR1]     ; USB Activity bit indicates activity
    and    A, USB_BUS_ACTIVITY         ; Activity?
    jz     .no_activity                ; Jump on no activity?
; Flow here on bus activity
    mov    A, 1                        ; Return true
    jmp    .done
; Jump here on no activity
.no_activity:
    mov    A, 0                        ; Return false
; Jump or flow here to clear the activity bit, then return
.done:
    and    reg[USBUART_USB_CR1], ~USB_BUS_ACTIVITY  ; Clear the activity flag
    M8C_SetBank0
	RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bGetRxCount
;
;  DESCRIPTION: This function returns the number of bytes that were received
;               from the PC and are waiting in the RX buffer.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;	none
;
;  RETURNS:
;	If RX associated endpoint has EVENT_PENDING status return ()in A register) the values stored in the
;  	Count registers of the Endpoint; otherwise return zero.
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_bGetRxCount:
_USBUART_bGetRxCount:
    RAM_PROLOGUE RAM_USE_CLASS_3
	RAM_SETPAGE_CUR >USBUART_EndpointAPIStatus ; Set the IDX_PP to the right page
	mov     A, [USBUART_EndpointAPIStatus+3]	; Get the state
	cmp 	A, EVENT_PENDING
	jz		.ev_pending
	mov		A, 0
	jmp		.exit
.ev_pending:
    mov     A, reg[USBUART_EP3CNT0]    ; Here is the count
	sub		A, 2
; Jump or flow here for a common exit
.exit:
    RAM_EPILOGUE RAM_USE_CLASS_3
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_Write,  USBUART_CWrite
;
;  DESCRIPTION:    Send specified numbers of data
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     [SP-6] Count to send
;     [SP-5] MSB of data array address
;     [SP-4] LSB of data array address
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
;    Currently only the page pointer registers listed below are modified:
;          CUR_PP
;          IDX_PP
;
MEM_TYPE:	equ -1
; -2 and -3 is the return address to caller
DATA_LSB:   equ -4           ; LSB pointer of data
DATA_MSB:   equ -5           ; MSB pointer of data
CNTLEN: equ -6			 ; Length of data to send

 USBUART_CWrite:
_USBUART_CWrite:
	mov		A, 1 ;Set MEM_TYPE
	push	A
	jmp		USBUART_Write_Start
 USBUART_Write:
_USBUART_Write:
	mov		A, 0 ;Set MEM_TYPE
	push	A
USBUART_Write_Start:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
	RAM_SETPAGE_CUR >USBUART_bCurrentDevice ; Set the CUR_PP to the right page
    RAM_SETPAGE_IDX2STK
    ;Should we toggle the data bit??
    ;SET THE COUNT AND TOGGLE
	mov     X, SP
	mov     A, [X+CNTLEN]                 ; Get the Count
	mov     [USBUART_APITemp], A          ; Save the count
	mov     [USBUART_APITemp+1], 0        ; initialize this to avoid messing up message length with bit 0.

    mov     A, 04h                     ; EP2
	xor     [USBUART_EPDataToggle], A
    and     A, [USBUART_EPDataToggle]
    jz      .toggle0

    or      [USBUART_APITemp+1], USB_CNT_TOGGLE ; Set the data toggle
    jmp     .toggle_done
.toggle0:
    and     [USBUART_APITemp+1], ~USB_CNT_TOGGLE

.toggle_done:
	mov     A, [X+CNTLEN]                  ;Get count
    mov     reg[USBUART_EP2CNT0], A     ; Write it into the register
    mov     A, [USBUART_APITemp+1]      ; Retrieve the saved toggle
	mov     reg[USBUART_EP2CNT1], A        ; Write it into the register

; It's Time to move the data
; First we need to determine where, within the PMA, the EP Start Address is
	mov     A, reg[TMP_DR1]                ; Get the address of ep from tmp register
    M8C_SetBank1
    M8C_DisableGInt
    mov     reg[PMA0_WA], A             ; Set the Write pointer of our pma to ep space
    M8C_EnableGInt
    M8C_SetBank0

; Now we are y to start moving data
	mov     A, [X+CNTLEN]                  ; Check the count
	jz      .done                          ; If it is 0 then we have a 0 length packet

	or	 	[X+MEM_TYPE], 0
	jnz		.start_send_rom

	mov     A, [X+DATA_LSB]
	push    A
IF SYSTEM_LARGE_MEMORY_MODEL
	mov     A, [X+DATA_MSB]
	mov     reg[IDX_PP], A
ENDIF
	pop     X

.loop_ram:
	mov		A, [X]
	mov     reg[PMA0_DR], A
	inc     X
	dec     [USBUART_APITemp]
	jnz     .loop_ram
	jmp 	.done

.start_send_rom:
	mov     A, [X+DATA_MSB]
	mov		[USBUART_APITemp+1], A
	mov     X, [X+DATA_LSB]

.loop_rom:
	romx
	mov     reg[PMA0_DR], A

	inc     X	;go next address
	adc		[USBUART_APITemp+1], 0 ; don't forget carry
	mov 	A, [USBUART_APITemp+1] ; prepare MSB of address

	dec     [USBUART_APITemp]
	jnz     .loop_rom

.done:
    mov     [USBUART_EndpointAPIStatus+2], NO_EVENT_PENDING ; Set the state
	M8C_SetBank1
	mov     A, reg[TMP_DR1]               ; Get the value of the PMA start Address
    M8C_DisableGInt
	mov     reg[PMA0_RA+2], A             ; Load it into EP PMA so pre-fetch occurs
    M8C_EnableGInt
    mov     reg[USBUART_EP2MODE], USB_MODE_ACK_IN ; Enable the endpoint
	M8C_SetBank0

	pop 	A ; Clean up MEM_TYPE
    RAM_EPILOGUE RAM_USE_CLASS_3
	RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_PutString
;
;  DESCRIPTION:    Send NULL terminated string
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A contains MSB of the string pointer
;     X contains LSB of the string pointer
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
;    Currently only the page pointer registers listed below are modified:
;          CUR_PP
;          IDX_PP
;

 USBUART_PutString:
_USBUART_PutString:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
	RAM_SETPAGE_CUR >USBUART_APITemp      ; Set the CUR_PP to the right page
	push	A
	push	A	;put MSB of dataPtr  - prepare to Write call
	push	X	;put LSB of dataPtr - prepare to Write call
IF SYSTEM_LARGE_MEMORY_MODEL
	mov     reg[IDX_PP], A
ENDIF
	mov		[USBUART_APITemp], 0; init the length counter
.loop:
	mov		A, [X]
	jz		.done
	inc		X
	inc		[USBUART_APITemp]
	jmp		.loop
.done:
    RAM_SETPAGE_IDX2STK
	mov		A, [USBUART_APITemp]
	mov		X, SP
	mov 	[X-3], A
	lcall 	USBUART_Write
	add		SP, 253
    RAM_EPILOGUE RAM_USE_CLASS_3
	RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_CPutString
;
;  DESCRIPTION:    Send NULL terminated string ROM located string
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A contains MSB of the string pointer
;     X contains LSB of the string pointer
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
;    Currently only the page pointer registers listed below are modified:
;          CUR_PP
;          IDX_PP
;

 USBUART_CPutString:
_USBUART_CPutString:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
	RAM_SETPAGE_CUR >USBUART_APITemp      ; Set the CUR_PP to the right page
	RAM_SETPAGE_IDX2STK
	push	A	;reserve placeholder for count - prepare to Write call
	push	A	;put MSB of dataPtr  - prepare to Write call
	push	X	;put LSB of dataPtr - prepare to Write call
	mov		[USBUART_APITemp], 0	; init the length counter
	mov		[USBUART_APITemp+1], A	; store the pointer MSB
.loop:
	romx
	jz		.done
	inc		X	;increment pointer LSB
	adc 	[USBUART_APITemp+1],0 ;don't forget carry
	inc		[USBUART_APITemp]	;increment counter
	mov 	A, [USBUART_APITemp+1]	;load MSB into A - prepare address for romx
	jmp		.loop
.done:
	mov		A, [USBUART_APITemp]
	mov		X, SP
	mov 	[X-3], A
	mov 	[USBUART_APITemp+1], 0	;used later for toggle data
	lcall 	USBUART_CWrite
	add		SP, 253
    RAM_EPILOGUE RAM_USE_CLASS_3
	RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_PutChar
;
;  DESCRIPTION:    Send one character
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A contains character to send
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;

 USBUART_PutChar:
_USBUART_PutChar:
    RAM_PROLOGUE RAM_USE_CLASS_1
	push 	A	;save character in stack
	mov 	A, 1;	set 1 byte to transfer
	push	A
IF ( SYSTEM_LARGE_MEMORY_MODEL )
    mov   	A, reg[STK_PP]
ELSE
	mov 	A, 0
ENDIF
	push	A	;put MSB of dataPtr  - prepare to Write call
	mov 	X, SP
	mov		A, X
	sub 	A, 3
	push	A	;put LSB of dataPtr - prepare to Write call
	lcall 	USBUART_Write
	add		SP, 252
	RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_PutCRLF
;
;  DESCRIPTION:    Send one character
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     none
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;

 USBUART_PutCRLF:
_USBUART_PutCRLF:
    RAM_PROLOGUE RAM_USE_CLASS_1
	mov 	A, 0Dh
	push 	A	;save character in stack
	mov 	A, 0Ah
	push 	A	;save character in stack
	mov 	A, 2;	set 2 byte to transfer
	push	A
IF ( SYSTEM_LARGE_MEMORY_MODEL )
    mov   	A, reg[STK_PP]
ELSE
	mov 	A, 0
ENDIF
	push	A	;put MSB of dataPtr  - prepare to Write call
	mov 	X, SP
	mov		A, X
	sub 	A, 4
	push	A	;put LSB of dataPtr - prepare to Write call
	lcall 	USBUART_Write
	add		SP, 251
	RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_PutSHexByte
;
;  DESCRIPTION:    Print a byte in Hex (two byte) representation to the USBUART
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A contains byte to send
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_PutSHexByte:
_USBUART_PutSHexByte:
    RAM_PROLOGUE RAM_USE_CLASS_1
	mov 	X, A	; Save lower nibble
	asr		A   ; Shift high nibble to right
	asr		A
	asr		A
	asr		A
	and		A,0Fh	; Mask off nibble
	index USBUART_HEX_STR;  Get Hex value
	push 	A
	mov		A, X
	and   	A,0Fh	; Mask off lower nibble
	index USBUART_HEX_STR	; Get Hex value
	push	A
	mov		A, 2	; 2 bytes to transfer
	push	A
IF ( SYSTEM_LARGE_MEMORY_MODEL )
    mov   	A, reg[STK_PP]
ELSE
	mov 	A, 0
ENDIF
	push	A	;put MSB of dataPtr  - prepare to Write call
	mov 	X, SP
	mov		A, X
	sub 	A, 4
	push	A	;put LSB of dataPtr - prepare to Write call
	lcall 	USBUART_Write
	add		SP, 251
	RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_PutSHexInt
;
;  DESCRIPTION:    Print a byte in Hex (two byte) representation to the USBUART
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A  => LSB of Int
;     X  => MSB of Int
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_PutSHexInt:
_USBUART_PutSHexInt:
    RAM_PROLOGUE RAM_USE_CLASS_3
	RAM_SETPAGE_IDX2STK
	push	A	;save LSB
	mov 	A, X
	asr		A   ; Shift high nibble to right
	asr		A
	asr		A
	asr		A
	and		A,0Fh	; Mask off nibble
	index USBUART_HEX_STR;  Get Hex value
	push	A
	mov		A, X	;retrieve lower nibble
	and   	A,0Fh	; Mask off lower nibble
	index USBUART_HEX_STR	; Get Hex value
	push	A
	mov 	X, SP
	mov		A, [X-3]	;retrieve LSB
	mov 	X, A	; Save lower nibble
	asr		A   ; Shift high nibble to right
	asr		A
	asr		A
	asr		A
	and		A,0Fh	; Mask off nibble
	index USBUART_HEX_STR;  Get Hex value
	push	A
	mov		A, X
	and   	A,0Fh	; Mask off lower nibble
	index USBUART_HEX_STR	; Get Hex value
	push	A

	mov		A, 4	; 4 bytes to transfer
	push	A
IF ( SYSTEM_LARGE_MEMORY_MODEL )
    mov   	A, reg[STK_PP]
ELSE
	mov 	A, 0
ENDIF
	push	A	;put MSB of dataPtr  - prepare to Write call
	mov 	X, SP
	mov		A, X
	sub 	A, 6
	push	A	;put LSB of dataPtr - prepare to Write call
	lcall 	USBUART_Write
	add		SP, 248
	RAM_EPILOGUE RAM_USE_CLASS_3
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_Read
;
;  DESCRIPTION:    This function reads from the specified endpoint buffer
;                  with the count number of bytes.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     [SP-5] Count to read
;     [SP-4] MSB of data array address to put data in
;     [SP-3] LSB of data array address to put data in
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
;    Currently only the page pointer registers listed below are modified:
;          CUR_PP
;          IDX_PP
;
DATA_LSBR:   equ -3           ; MSB pointer of data
DATA_MSBR:   equ -4           ; LSB pointer of data
RDCNTLEN:		 equ -5           ; Length of data to send

 USBUART_Read:
_USBUART_Read:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
	RAM_SETPAGE_CUR >USBUART_bCurrentDevice ; Set the CUR_PP to the right page
    RAM_SETPAGE_IDX2STK

    ;Get the count value passed
	mov		X, SP
	mov     A, [X+RDCNTLEN]               ; Get the Count
	mov     [USBUART_APITemp], A          ; Save the count

    ;Determine which is smaller the requested data or the available data
	mov     A, reg[USBUART_EP3CNT0]        ; Get the Real count
	mov 	[USBUART_APITemp+1], A ; set the reminder
	sub 	A, 2
	cmp     A, [USBUART_APITemp]           ; Are they equal
	jz      .CountCorrect                  ; If they are check if they are 1
	jnc      .CountCorrect                 ;If the requested count is smaller use it
	mov 	A, 80h	; Set error condition and exit
	jmp 	.exit
.CountCorrect:
; First we need to determine where, within the PMA, the EP Start Address is
	mov     A, reg[TMP_DR2]                ; Get the address of ep from tmp register
	M8C_SetBank1
    M8C_DisableGInt
	mov     reg[PMA0_RA], A                ; Set the Read pointer of our pma to ep space
    M8C_EnableGInt
	M8C_SetBank0

; Now we are ready to start moving data
	mov     A, [USBUART_APITemp]           ; Check the Count register
	jz      .done                          ; If it is 0 then we have a 0 length packet

.start_send:
	mov     A, [X+DATA_LSBR]               ; Get the LSB of the pointer
	push    A                              ; save on stack
IF SYSTEM_LARGE_MEMORY_MODEL
	mov     A, [X+DATA_MSBR]               ; Get the MSB of the pointer
	mov     reg[IDX_PP], A                 ; Use as value for IDX_PP
ENDIF
	pop     X                              ; Get the LSB again

.loop:
	mov     A, reg[PMA0_DR]                ; Get the data from the PMA space
	mov		[X], A                            ; save it in data array
	inc     X                              ; increment the pointer
	dec		[USBUART_APITemp+1]               ; decrement the reminder
	dec     [USBUART_APITemp]              ; decrement the counter
	jnz     .loop                          ; wait for count to zero out

.done:
    RAM_SETPAGE_IDX2STK
	mov		X, SP
    mov     A, reg[TMP_DR2]
    add     A, [X+RDCNTLEN]
    mov     reg[TMP_DR2], A
	cmp 	[USBUART_APITemp+1], 2 	; If only 2 bytes of checksum left in EP
	jz		.BufferEmpty
	mov		A, [USBUART_APITemp+1]		; Prepare count reminder for return
	mov		reg[USBUART_EP3CNT0], A
	jmp .exit

.BufferEmpty:
    mov     [USBUART_EndpointAPIStatus+3], NO_EVENT_PENDING ; For the API
	mov     reg[USBUART_EP3CNT0], 64
	M8C_SetBank1
	mov		reg[TMP_DR2], 128
    mov     A, reg[TMP_DR2]
	mov     reg[PMA3_WA], A
    mov     A, reg[USBUART_EP3MODE]    ; Unlock the mode register
    mov     reg[USBUART_EP3MODE], USB_MODE_ACK_OUT ; Enable the endpoint
	mov 	A, 0;	; No error and no bytes left in EP
    M8C_SetBank0

.exit:
    RAM_EPILOGUE RAM_USE_CLASS_3
	RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_ReadAll
;
;  DESCRIPTION:    This function reads all from the Rx associated endpoint buffer
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A - MSB of data array address to put data in
;     X - LSB of data array address to put data in
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;

 USBUART_ReadAll:
_USBUART_ReadAll:
    RAM_PROLOGUE RAM_USE_CLASS_2
	add		SP, 1	; Prepare space for number of bytes
	push	A	;put MSB of dataPtr  - prepare to Write call
	push	X	;put LSB of dataPtr - prepare to Write call
   	mov     A, reg[USBUART_EP3CNT0]    ; Here is the count
	sub		A, 2
	mov		X, SP
	mov 	[X-3], A ; put the number of bytes
	RAM_EPILOGUE RAM_USE_CLASS_2
	lcall 	USBUART_Read
	RAM_PROLOGUE RAM_USE_CLASS_2
	add		SP, 253
   	RAM_EPILOGUE RAM_USE_CLASS_2
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_ReadChar
;
;  DESCRIPTION:    This function reads all from the Rx associated endpoint buffer
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     none
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;

 USBUART_ReadChar:
_USBUART_ReadChar:
    RAM_PROLOGUE RAM_USE_CLASS_1
	add		SP, 1	; Prepare placeholder in stack
	mov		A, 1
	push	A		; Read one byte
IF ( SYSTEM_LARGE_MEMORY_MODEL )
    mov   	A, reg[STK_PP]
ELSE
	mov 	A, 0
ENDIF
	push	A	;put MSB of dataPtr  - prepare to Write call
	mov 	X, SP
	mov		A, X
	sub 	A, 3
	push	A	;put LSB of dataPtr - prepare to Write call
	lcall 	USBUART_Read
	add		SP, 253
	mov		X, A	;copy status to MSB
	pop		A	; Get the character from the stack;
    RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bTxIsReady
;
;  DESCRIPTION:   Returns whether the ACK bit of EP has been set for
;                 an endpoint
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;	none
;
;  RETURNS:       A is 0 if Tx is not ready and non-zero if it is
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_bTxIsReady:
_USBUART_bTxIsReady:
    RAM_PROLOGUE RAM_USE_CLASS_1
	M8C_SetBank1
    mov    A, reg[USBUART_EP2MODE]
	M8C_SetBank0
    and    A, 0x10
    ret                                ; Exit
    RAM_EPILOGUE RAM_USE_CLASS_1
.ENDSECTION


.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_Init
;
;  DESCRIPTION:    Try to initialize USBUART device if it already enumerated
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:  None
;
;  RETURNS:	1 if successfully initialized, otherwise 0
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
 USBUART_Init:
_USBUART_Init:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
; check that USB is configured
	RAM_SETPAGE_CUR >USBUART_Configuration
    mov     A,[USBUART_Configuration]
	jz		.done
; load zero length dummy packet to EP2
	RAM_SETPAGE_CUR >USBUART_bCurrentDevice ; Set the CUR_PP to the right page

    ;SET THE COUNT AND TOGGLE
    mov     A, 04h                     ; EP2
    and     A, [USBUART_EPDataToggle]
    jz      .toggle0

    or      [USBUART_APITemp+1], USB_CNT_TOGGLE ; Set the data toggle
    jmp     .toggle_done
.toggle0:
    and     [USBUART_APITemp+1], ~USB_CNT_TOGGLE

.toggle_done:
    mov     reg[USBUART_EP2CNT0], 0     ; Write it into the register
	mov     A, [USBUART_APITemp+1]         ; Get The Data toggle for EP
	mov     reg[USBUART_EP2CNT1], A        ; Write it into the register

    ; It's Time to move the data
    ; First we need to determine where, within the PMA, the EP Start Address is
    RAM_SETPAGE_IDX2STK
	mov     A, reg[TMP_DR1]                ; Get the address of ep from tmp register
	M8C_SetBank1
    M8C_DisableGInt
	mov     reg[PMA0_WA], A                ; Set the Write pointer of our pma to ep space
    M8C_EnableGInt
	M8C_SetBank0

    ; Now we are ready to start moving data
    mov     [USBUART_EndpointAPIStatus+2], NO_EVENT_PENDING ; Set the state
	M8C_SetBank1
	mov     A, reg[TMP_DR1]               ; Get the value of the PMA start Address
	mov     reg[PMA2_RA], A               ; Load it into EP PMA so pre-fetch occurs
	mov     reg[USBUART_EP2MODE], USB_MODE_ACK_IN ; Enable the endpoint
	M8C_SetBank0

; Enable EP 3
    RAM_SETPAGE_IDX >USBUART_EndpointAPIStatus
    mov     [USBUART_EndpointAPIStatus+3], NO_EVENT_PENDING ; For the API
	mov     reg[USBUART_EP3CNT0], 64
	M8C_SetBank1
    mov     A, reg[TMP_DR2]
	mov     reg[PMA3_WA], A
    mov     A, reg[USBUART_EP3MODE]    ; Unlock the mode register
    mov     reg[USBUART_EP3MODE], USB_MODE_ACK_OUT ; Enable the endpoint
    M8C_SetBank0

; prepare return
	mov		A, 1

.done:
    RAM_EPILOGUE RAM_USE_CLASS_3
	RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_dwGetDTERate
;
;  DESCRIPTION:    Return DTE Rate
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:  None
;
;  RETURNS:	DWORD containing DTE rate in bits per second
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
USBUART_dwGetDTERate:
_USBUART_dwGetDTERate:
	RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_PROLOGUE RAM_USE_CLASS_3
	; Disable interrupt here
	M8C_DisableIntMask USBUART_INT_REG, USBUART_INT_EP0_MASK
	RAM_SETPAGE_CUR >USBUART_LineCoding
	RAM_SETPAGE_IDX A
	push  A
	mov   A,[USBUART_LineCoding + 3]
	mov   [X + 0],A
	mov   A,[USBUART_LineCoding + 2]
	mov   [X + 1],A
	mov   A,[USBUART_LineCoding + 1]
	mov   [X + 2],A
	mov   A,[USBUART_LineCoding]
	mov   [X + 3],A
	pop   A

	M8C_EnableIntMask USBUART_INT_REG, USBUART_INT_EP0_MASK
	RAM_EPILOGUE RAM_USE_CLASS_4
	RAM_EPILOGUE RAM_USE_CLASS_3
	ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bGetCharFormat
;
;  DESCRIPTION:    Returns number of stop bits
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:  None
;
;  RETURNS:	BYTE containing character format (data bits)
;				 (0 = 1 stop bit, 1 = 1.5 stop bit, 2 = 2 stop bit)
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
USBUART_bGetCharFormat:
_USBUART_bGetCharFormat:
	RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >USBUART_LineCoding
	mov A, [USBUART_LineCoding+4];
	RAM_EPILOGUE RAM_USE_CLASS_4
	ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bGetParityType
;
;  DESCRIPTION:    Return Parity type
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:  None
;
;  RETURNS:	Parity type
;				 (0 = none, 1 = odd, 2 = even, 3 = mark, 4 = space)
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
USBUART_bGetParityType:
_USBUART_bGetParityType:
	RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >USBUART_LineCoding
	mov A, [USBUART_LineCoding+5];
	RAM_EPILOGUE RAM_USE_CLASS_4
	ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bGetDataBits
;
;  DESCRIPTION:    Returns data bits (5,6,7,8 or 16)
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:  None
;
;  RETURNS:	Data bits
;				 (5,6,7,8 or 16)
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
USBUART_bGetDataBits:
_USBUART_bGetDataBits:
	RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >USBUART_LineCoding
	mov A, [USBUART_LineCoding+6];
	RAM_EPILOGUE RAM_USE_CLASS_4
	ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_bGetLineControl
;
;  DESCRIPTION:    Return Line Control Bitmap
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:  None
;
;  RETURNS:	Line control bitmap
;				D7..D2 - reserved
;				D1 - RTS (0 = deactivate carrier, 1 = activate carrier)
;				D0 - DTR (0 = not present, 1 = present);
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
USBUART_bGetLineControlBitmap:
_USBUART_bGetLineControlBitmap:
	RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >USBUART_LineControlBitmap
	mov A, [USBUART_LineControlBitmap+1];
	RAM_EPILOGUE RAM_USE_CLASS_4
	ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_SendStateNotify
;
;  DESCRIPTION:    Send notification about UART state
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     	A - State bitmap
;
;  RETURNS:
;     none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to preserve their values across calls to fastcall16
;    functions.
;
;    Currently only the page pointer registers listed below are modified:
;          CUR_PP
;          IDX_PP
;
; -2 and -3 is the return address to caller
 USBUART_SendStateNotify:
_USBUART_SendStateNotify:
    RAM_PROLOGUE RAM_USE_CLASS_1
    ;Should we toggle the data bit??
    ;SET THE COUNT AND TOGGLE
	push 	A
	mov     [USBUART_APITemp], 10         ; Save the count

    mov     A, 02h                     ; EP1
    xor     [USBUART_EPDataToggle], A
    and     A, [USBUART_EPDataToggle]
    jz      .toggle0

    or      [USBUART_APITemp+1], USB_CNT_TOGGLE ; Set the data toggle
    jmp     .toggle_done
.toggle0:
    and     [USBUART_APITemp+1], ~USB_CNT_TOGGLE

.toggle_done:
    mov     reg[USBUART_EP1CNT0], 10    ; Write it into the register
	mov     A, [USBUART_APITemp+1]         ; Retrieve the saved toggle (MSB)
	mov     reg[USBUART_EP1CNT1], A        ; Write it into the register

; It's Time to move the data
; First we need to determine where, within the PMA, the EP Start Address is
	mov     A, reg[TMP_DR0]                ; Get the address of ep from tmp register
	M8C_SetBank1
    M8C_DisableGInt
	mov     reg[PMA0_WA], A                ; Set the Write pointer of our pma to ep space
    M8C_EnableGInt
	M8C_SetBank0

; Now we are y to start moving data
	mov		reg[PMA0_DR], A1h	; bmRequestType
	mov		reg[PMA0_DR], 20h	; Serial State
	mov		reg[PMA0_DR], 0		; wValue MSB
	mov		reg[PMA0_DR], 0		; wValue LSB
	mov		reg[PMA0_DR], 0		; wIndex MSB
	mov		reg[PMA0_DR], 0		; wIndex (Interface)
	mov		reg[PMA0_DR], 0		;wLen
	mov		reg[PMA0_DR], 2		;wLen
	mov		reg[PMA0_DR], 0		;wLen
	pop		A
	mov		reg[PMA0_DR], A		;State bitmap

    mov     [USBUART_EndpointAPIStatus+1], NO_EVENT_PENDING ; Set the state
	M8C_SetBank1
	mov     A, reg[TMP_DR0]               ; Get the value of the PMA start Address
    M8C_DisableGInt
	mov     reg[PMA0_RA+1], A             ; Load it into EP PMA so pre-fetch occurs
    M8C_EnableGInt
    mov     reg[USBUART_EP1MODE], USB_MODE_ACK_IN ; Enable the endpoint
	M8C_SetBank0
    RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: USBUART_SetPowerStatus
;
;  DESCRIPTION:    Set The Current Power status.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:      A contains the power status
;
;  RETURNS:        None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16
;    functions.
;
 USBUART_SetPowerStatus:
_USBUART_SetPowerStatus:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >USBUART_DeviceStatus
    cmp     A, 0
    jz      .bus_powered
    or      [USBUART_DeviceStatus], USB_DEVICE_STATUS_SELF_POWERED
    jmp     .done
.bus_powered:
    and     [USBUART_DeviceStatus], ~USB_DEVICE_STATUS_SELF_POWERED
.done:
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret                                ; All done
.ENDSECTION
