;/*----------------------------------------------------------------------------+
;|                                                                             |
;|              Copyright (C),  Philips Semiconductors SLH                     |                                                                             *
;|                                                                             |
;|  All rights are reserved. Reproduction in whole or in part is prohibited    |
;|           without the written consent of the copyright owner.               |
;|                                                                             |
;|  Philips reserves the right to make changes without notice at any time.     |
;| Philips makes no warranty, expressed, implied or statutory, including but   |
;| not limited to any implied warranty of merchantibility or fitness for any   |
;|   particular purpose, or that the use will not infringe any third party     |
;| patent, copyright or trademark. Philips must not be liable for any loss or  |
;|                      damage arising from its use.                           |
;|                                                                             |
;+-----------------------------------------------------------------------------+
;| Project: 336 355/105 - Control SW Library for HTRC110/HTRC120/HITAG2        |
;|                                                                             |
;| File: HT2_A.A51                                                             |
;|                                                                             |
;| Author: St.de Zeeuw                                                         |
;+--------------+-------+---------------------------------------------+--------+
;|     DATE     |VERSION| HISTORY/CHANGES                             |   BY   |
;|  (MM/DD/JJ)  | VX.Y  |                                             |        |
;+--------------+-------+---------------------------------------------+--------+
;|   10/12/97   |  1.0  | First version                               |   Ze   |
;|   27/04/98   |  2.0  |                                             |   Ze   |
;|              |       |                                             |        |
;+--------------+-------+---------------------------------------------+--------+
;$Modtime: 27.04.98 15:17 $  $Revision: 7 $
;
;+----------------------------------------------------------------------------*/

$include(hitag2.inc)

NAME  HT2_A

CODE_C_HITAG2   SEGMENT CODE
BIT_C_HITAG2    SEGMENT BIT OVERLAYABLE
DATA_C_HITAG2   SEGMENT DATA OVERLAYABLE


;+------------------------------------------------------------------------+
;|                      Imports                                           |
;+------------------------------------------------------------------------+

        EXTRN   DATA( NBit, Byte_Addr )
        EXTRN   DATA( Protocol_State )
        EXTRN   DATA( Protocol_Callback )
        EXTRN   CODE( next_HT_state )


;+------------------------------------------------------------------------+
;|                      Exported Variables                                |
;+------------------------------------------------------------------------+
                                                        
        PUBLIC  IntVec, Decoder_State, Bit_Count
        PUBLIC  Polarity
        PUBLIC  MSB_TABLE


        RSEG    DATA_C_HITAG2
Bit_Count:      DS      1
Decoder_State:  DS      1
IntVec:         DS      2


        RSEG    BIT_C_HITAG2
t_int:          DBIT    1
Polarity:       DBIT    1


;+------------------------------------------------------------------------+
;|                      Exported Functions                                |
;+------------------------------------------------------------------------+

        PUBLIC   Wait_End_INT, Send_HT_Bits_INT, Exec_Protocol_Callback
        PUBLIC   Receive_HT_Bits_INT, _HTRC110_Wait



        CSEG    at      0003H           ; Ext-Int 0 vector
        ljmp    ex0_int

        CSEG    at      000BH           ; Timer 0 vector
        ljmp    t0_int






   RSEG  CODE_C_HITAG2
   USING 0


                                        ; this is an external triggered interrupt
ex0_int:
        push    PSW           
        push    ACC
        push    B
        push    AR0

                                        ; reset timer with (-timeout)
        clr     TR0           
        mov     A,TL0
        mov     B,TH0
        mov     TL0,#low  (-(NO_T_TIMEOUT-INTERRUPT_DELAY))
        mov     TH0,#high (-(NO_T_TIMEOUT-INTERRUPT_DELAY))
        setb    TR0



                                        ; calculate number of elapsed T0
        add     A,#low  (NO_T_TIMEOUT-INTERRUPT_DELAY)
        anl     A,#0F0h
        swap    A
        xch     A,B
        addc    A,#high (NO_T_TIMEOUT-INTERRUPT_DELAY)
        swap    A
        anl     A,#0F0h
        orl     A,B
        add     A,#NO_05T0
        mov     B,#NO_T0
        div     AB
                                        ; t_int = 0        
        clr     t_int

                                        ; call interrupt routine
        push    IntVec+1       
        push    IntVec+0
        ret


                                        ; this is a timer overflow interrupt
t0_int:
        push    PSW
        push    ACC
        push    B
        push    AR0

                                        ; t_int = 0
        setb    t_int


                                        ; call interrupt routine
        push    IntVec+1
        push    IntVec+0
        ret





; Following the pseudo-C code for Send_HT_Bits_INT is listed
;
;       send pulse;
;       if (Bit_Count == NBit)
;       {
;          initialize timer with t_wait_1;
;          Byte_Addr ++;
;          next_HT_state();
;       }
;       else
;       {
;          if (Bit_Count > 0  && Bit_Count%8 == 0) Byte_Addr++;
;          if (*Byte_Addr & MSB_table[Bit_Count&7]) temp = t_log,1;
;          else                                     temp = t_log,0;
;          initialize timer with temp;
;          Bit_Count++;
;       }




Send_HT_Bits_INT:

        setb    DIN                     ; send pulse
        nop
        clr     DIN

        mov     A,Bit_Count             ; Bit_Count == NBit ?
        xrl     A,NBit
        jz      send_stop               ; last bit has been sent?

        mov     A,Bit_Count             ; special case: Bit_Count == 0
        jz      take_data_byte
        anl     A, #7                   ; Bit_Count % 8
        jnz     take_data_byte   
        inc     Byte_Addr               ;send next byte of data
        
take_data_byte:
        mov     R0, Byte_Addr
        mov     A,@R0

determine_bit:                          ;decide whether '1' od '0' has to be sent...
        mov     B,A
        mov     A,Bit_Count
        anl     A,#7                    ; build mask to store bit..
        add     A,#(MSB_TABLE - pc_label1)  
        movc    A,@A+PC
pc_label1:
        anl     A,B                     ; long or short pulse length?        
        jz      send_next_0


send_next_1:                            ; and now set timer duration ....
        mov     A,#low  (-(NO_T_1))  ;       .. to t_1
        mov     B,#high (-(NO_T_1))
        sjmp    send_settimer

send_next_0:
        mov     A,#low  (-(NO_T_0))  ;       .. to t_1
        mov     B,#high (-(NO_T_0))

send_settimer:                          ; initailize timer
        lcall   set_timeout

        inc     Bit_Count               ; and now Bit_Count++  .....
        sjmp    keep_on_sending


send_stop:
        inc     Byte_Addr               

set_stop_timer:                         ; reset timer for t_wait_1
        mov     A,#low  (-(NO_T_WAIT_1))
        mov     B,#high (-(NO_T_WAIT_1))
        lcall   set_timeout

        ljmp    call_next_ht_state      ; finally going back to the main program



keep_on_sending:

        pop     AR0
        pop     B
        pop     ACC
        pop     PSW
        reti




; Following the pseudo-C code for the bit storing routine bit_store()
;
;       if( Bit_Count<0 ) return; 
;       bit_no=Bit_Count & (UBYTE)7;
;
;       if(bit_no==0)
;       {
;            if(Bit_Count) Byte_Addr++;
;            *Byte_Addr=0;      /* Clear byte before storing bits */
;       }
;                               /*invert, if polarity was inverted*/
;       if (Polarity==INVERTED) data_bit = ~data_bit; 
;                               /* set data bit: MSB first */
;       if(data_bit) *Byte_Addr|=MSB_TABLE[bit_no]; 
;
;       Bit_Count++;
;       if (Bit_Count == NBit)
;       {
;            Byte_Addr++;
;            reset timer with t_wait_2
;            next_HT_state();
;            SP = SP - 2;  /* remove return value from stack */
;       }
;       return;

bit_store:
; Input: F0 = bit to store
; execution time: max 36 machine cycles (except for last bit)

                                        ; decide whether '1' or '0' has to be stored
        mov     R0,Byte_addr       
        mov     A,Bit_Count
        jb      ACC.7, zero_bit
        anl     A,#7
        jnz     write_bit               ; store bit at once....

        mov     B,A     
        mov     A,Bit_Count
        jz      first_bit               ;first of Byte to be written
        inc     R0
        clr     A
first_bit:
        mov     @R0,A
        mov     A,B

write_bit:                              ; polarity normal or inverted?
        jnb     Polarity,normal_polarity
        cpl     F0
normal_polarity:
        jnb     F0,zero_bit
                                        ; build mask to store bit..
        add     A,#MSB_TABLE - pc_label2
        movc    A,@A+PC
pc_label2:
        orl     A,@R0
        mov     @R0,A

zero_bit:                               ; store '0', that means no physical storing
                                        ; at this moment, * Byte_Addr was initialized           
                                        ; already
        mov     Byte_addr,R0
        inc     Bit_Count
        mov     A,Bit_Count             ; Bit_Count == NBit??
        xrl     A,NBit
        jnz     not_finished

        inc     Byte_addr               ; Byte_Addr ++

                                        ; Bit_Count == NBit:reset timer 
                                        ; with t_wait_2
        clr     EX0                      
        mov     A,#low  (-(NO_T_WAIT_2))
        mov     B,#high (-(NO_T_WAIT_2))
        lcall   set_timeout

        mov     A,SP
        add     A,#-4                   ; immediate exit from Receive_HT_Bits_INT_1 and Receive_HT_Bits_INT now
        mov     SP,A                    ; (remove return addresses from stack)

        mov     Decoder_State,#D_STOP
        ljmp    call_next_HT_state

not_finished:
        ret


MSB_TABLE:                               ; this is a table of masks to ease storing the bits
	DB	080H
	DB	040H
	DB	020H
	DB	010H
	DB	008H
	DB	004H
	DB	002H
	DB	001H








; poll_last_bit is a routine which resets the timer to (-NO_T_POLL = - 24 T0),
; that is the third quarter of a coded bit frame. This routine is only called
; at the end when no unambiguous coding is given 

poll_last_bit:

        clr  	EX0          
                                        ; reset timer with 24 T0
        mov     A,#low  (NO_T_TIMEOUT-(NO_T_POLL-INTERRUPT_DELAY))
        mov     B,#high (NO_T_TIMEOUT-(NO_T_POLL-INTERRUPT_DELAY))
        lcall   set_timeout

        jnb     TF0,$

        mov     C,DOUT                  ; DOUT is polled, inverted and stored
        cpl     C
        mov     F0,C
        clr     TF0

        ret





;Following the routine Receive_HT_bits_INTis given in pseudo-C code. 
;The User Manual also explains this routine in detail. 
; 
; 
;   if (t_int) 	/* timeout has been generated, examine the situation*/
;   {
;     switch(Decoder_State)
;     {
;       case D_START:
;         Bit_Count     = (-2);
;         Polarity      = NORMAL;
;         reset timer with (-64 T0 =  - NO_T_TIMEOUT_SHORT);
;         Decoder_State = D_WAIT_1_EDGE;
;         return;
;
;       case D_CDP_SYNC:
;         if ( Bit_Count == NBit-2 )
;         {
;           bit_store(1);
;           bit_store(1);
;           return;
;         }
;         goto timeout_error;
;
;       case D_CDP_ASYNC:
;       case D_MANCH_SYNC:
;       case D_MANCH_ASYNC:
;         if ( Bit_Count == NBit-1 )
;         {
;           bit_store(1);
;           return;
;         }
;         goto timeout_error;
;     }
;     goto timeout_error;
;
;   }   /* end if(t-int)....*/
;   else                /* negative edge has been detected */
;   {
;     switch (Decoder_State)
;     {
;       case D_WAIT_1_EDGE: /* no real data, we are in the middle of the header*/
;         switch (T0_delta)
;         {
;           case 1:
;             Decoder_State = D_WAIT_2_EDGE;
;             return;
;           case 2:
;             Bit_Count++;
;             Polarity      = INVERTED;
;             Decoder_State = D_MANCH_ASYNC;
;             return;
;           case 3:
;             Bit_Count++;
;             Decoder_State = D_CDP_SYNC;
;             return;
;         }
;         goto delta_error;
;
;
;       case D_WAIT_2_EDGE: /* no real data, we are still in the middle of the header*/
;         switch (T0_delta)
;         {
;           case 2:
;             Bit_Count++;
;             Decoder_State = D_MANCH_SYNC;
;             return;
;           case 4:
;             Bit_Count+=2;
;             Decoder_State = D_CDP_SYNC;
;             return;
;         }
;         goto  delta_error;
;
;       case D_CDP_SYNC:    /* data detection, CDP coded */
;         switch (T0_delta)
;         {
;           case 2:
;             bit_store(0);
;             Decoder_State = D_CDP_SYNC;
;             break;
;           case 3:
;             bit_store(1);
;             bit_store(0);
;             Decoder_State = D_CDP_ASYNC;
;             return;
;           case 4:
;             bit_store(1);
;             bit_store(1);
;             Decoder_State = D_CDP_SYNC;
;             break;
;           default:
;             goto  delta_error;
;         }
;         if ((Bit_Count == NBit-1)  /* last bit has to be polled */
;         {
;           reset timer with (-64 T0);
;           poll last bit;
;         }
;         return;
;
;       case D_CDP_ASYNC:    /* data detection, CDP coded */
;         switch (T0_delta)
;         {
;           case 2:
;             Decoder_State = D_CDP_ASYNC;
;             bit_store(0);
;             return;
;           case 3:
;             Decoder_State = D_CDP_SYNC;
;             bit_store(1);
;             if ((Bit_Count == NBit-1)
;             {
;               reset timer with (-64 T0);
;               poll last bit;
;             }
;             return;
;         }
;         goto  delta_error;
;
;       case D_MANCH_SYNC:   	/* data detection, Manchester coded */
;         switch (T0_delta)
;         {
;           case 2:
;             Decoder_State = D_MANCH_SYNC;
;             bit_store(1);
;             return;
;           case 3:
;             Decoder_State = D_MANCH_ASYNC;
;             bit_store(1);
;             bit_store(0);
;             return;
;         }
;         goto  delta_error;
;
;       case D_MANCH_ASYNC:   /* data detection, Manchester coded */
;         switch (T0_delta)
;         {
;           case 2:
;             Decoder_State = D_MANCH_ASYNC;
;             bit_store(0);
;             return;
;           case 3:
;             Decoder_State = D_MANCH_SYNC;
;             bit_store(1);
;             return;
;           case 4:
;             Decoder_State = D_MANCH_ASYNC;
;             bit_store(1);
;             bit_store(0);
;             return;
;         }
;         goto  delta_error;
;
;     } /* end switch*/
;   } /* end else (t_int)...*/
;
;
;/****** false T0_delta has been detected: execute error call back ********/
;delta_error:
;Decoder_State  = D_DELTA_ERROR;
;Protocol_State  = P_STOP;
;next_HT_state();
;return;
;
;
;/****** timeout has been detected: execute error call back ********/
;timeout_error:
;Decoder_State  = D_TIMEOUT;
;Protocol_State  = P_STOP;
;next_HT_state();
;return;



Receive_HT_Bits_INT:
; Input: ACC = T0_Delta

        lcall   Receive_HT_Bits_INT_1
        pop     AR0
        pop     B
        pop     ACC
        pop     PSW
        reti

Receive_HT_Bits_INT_1:
        mov     B,A
        mov     A,Decoder_State

        jb   	t_int,timeout_triggered
        ljmp    edge_triggered


;**********************************************************************
;**********************************************************************
timeout_triggered:

;**********************************************************************
t_START:
        cjne    A,#D_START,t_CDP_SYNC

        mov  	Decoder_State,#D_WAIT_1_EDGE   ; this is the decoder start
        mov  	Bit_Count,#-2
        clr  	Polarity     ; (= NORMAL)

        setb 	EX0                             

        mov     A,#low  (-(NO_T_TIMEOUT_VERY_SHORT))
        mov     B,#high (-(NO_T_TIMEOUT_VERY_SHORT))
        lcall   set_timeout

        jnb     TF0,$                   ;wait until the middle of the header is reached  

        clr     TF0
        clr     IE0


$IF CALIBRATE                       ; the conditional parts define the calibration pulse
        setb    CAL_PORT
$ENDIF
                                        ; reset timer for a short timeout (-64 T0)
        mov     A,#low  (-(NO_T_TIMEOUT_SHORT))
        mov     B,#high (-(NO_T_TIMEOUT_SHORT))


$IF CALIBRATE
        clr     CAL_PORT
$ENDIF

        ljmp    set_timeout



;**********************************************************************
t_CDP_SYNC:
        cjne    A,#D_CDP_SYNC,t_CDP_ASYNC

        mov     A,NBit                  ; the end of CDP coded data: store 2x '1'
        add     A,#-2
        xrl  	A,Bit_Count
        jnz     timeout_error

        setb 	F0
        lcall	bit_store
        setb 	F0
        lcall	bit_store
        ret



;**********************************************************************
t_CDP_ASYNC:                            ; the end of CDP coded data, store one '1'
        cjne    A,#D_CDP_ASYNC,t_MANCH_SYNC   
        sjmp    t_2



;**********************************************************************
t_MANCH_SYNC:                           ; the end of Manchester coded data, store one '1'
        cjne    A,#D_MANCH_SYNC,t_MANCH_ASYNC
        sjmp    t_2



;**********************************************************************
t_MANCH_ASYNC:
        cjne    A,#D_MANCH_ASYNC,timeout_error

t_2:    mov  	A,NBit
        dec  	A
        xrl  	A,Bit_Count
        jnz   	timeout_error
        setb 	F0
        lcall	bit_store
        ret


;**********************************************************************
timeout_error:
        mov  	Decoder_State,#D_TIMEOUT
        mov  	Protocol_State,#P_STOP
        dec     SP                      ; immediate exit from Receive_HT_Bits_INT now
        dec     SP                      ; (remove return address from stack)
        ljmp    call_next_HT_state





;**********************************************************************
;**********************************************************************
edge_triggered:
; abbreviation e_....

;**********************************************************************
e_WAIT_1_EDGE:
        cjne    A,#D_WAIT_1_EDGE,e_WAIT_2_EDGE

        mov     A,B
        dec     A
        jz      e_1ED_1
        dec     A
        jz      e_1ED_2
        dec     A
        jz      e_1ED_3
        ljmp 	delta_error

e_1ED_1:                                ; elapsed time: 8 T0
        mov  	Decoder_State,#D_WAIT_2_EDGE
        ret

e_1ED_2:                                ; elapsed time: 24 T0
        inc  	Bit_Count
        setb 	Polarity                ; (= INVERTED)
        mov  	Decoder_State,#D_MANCH_ASYNC
        ret

e_1ED_3:                                ; elapsed time: 40 T0
        inc  	Bit_Count
        mov  	Decoder_State,#D_CDP_SYNC
        ret



;**********************************************************************
e_WAIT_2_EDGE:
        cjne    A,#D_WAIT_2_EDGE,e_CDP_SYNC

        mov     A,B
        add     A,#-2
        jz      e_2ED_2
        add     A,#-2
        jz      e_2ED_4
        ljmp 	delta_error

e_2ED_2:         ; elapsed time: 32 T0
        inc  	Bit_Count
        mov  	Decoder_State,#D_MANCH_SYNC
        ret

e_2ED_4:         ; elapsed time: 64 T0
        inc  	Bit_Count
        inc  	Bit_Count
        mov  	Decoder_State,#D_CDP_SYNC
        ret


; names of labels (further explanations see User Manual):
; e_                       : edge-triggered
;   CDP                    : CDP-coded
;   MAN                    : Manchester-coded
;      S                   : synchonous
;      A                   : asynchronous
;       _x                 : elapsed time = x*16 T0
;**********************************************************************
e_CDP_SYNC:
        cjne    A,#D_CDP_SYNC,e_CDP_ASYNC

        mov     A,B
        add     A,#-2
        jz      e_CDPS_2
        dec     A
        jz      e_CDPS_3
        dec     A
        jz      e_CDPS_4
        ljmp 	delta_error

e_CDPS_2:
        mov     A,NBit
        add     A,#-2                   ; TWO more bits to store?
        xrl  	A,Bit_Count
        jz   	e_1                     ; if yes, poll last bit

        clr  	F0
        lcall	bit_store
        ret

; Last-Bit polling, case 1:
e_1:    lcall   poll_last_bit
        push    PSW                     ; save polled bit on stack
        clr  	F0
        lcall	bit_store
        pop     PSW
        lcall   bit_store               ; store polled bit
        ret

e_CDPS_3:
        mov  	Decoder_State,#D_CDP_ASYNC
        setb 	F0
        lcall	bit_store
        clr  	F0
        lcall	bit_store
        ret

e_CDPS_4:
        mov     A,NBit
        add     A,#-3                   ; THREE more bits to store?
        xrl  	A,Bit_Count
        jz   	e_2                     ; if yes, poll last bit

        setb 	F0
        lcall	bit_store
        setb 	F0
        lcall	bit_store
        ret

; Last-Bit polling, case 2:
e_2:    lcall   poll_last_bit
        push    PSW                     ; save polled bit on stack
        setb 	F0
        lcall	bit_store
        setb 	F0
        lcall	bit_store
        pop     PSW
        lcall   bit_store               ; store polled bit
        ret


;**********************************************************************
e_CDP_ASYNC:
        cjne    A,#D_CDP_ASYNC,e_MANCH_SYNC

        mov     A,B
        add     A,#-2
        jz      e_CDPA_2
        dec     A
        jz      e_CDPA_3
        ljmp 	delta_error

e_CDPA_2:
        clr  	F0
        lcall	bit_store
        ret

e_CDPA_3:
        mov     A,NBit
        add     A,#-2                   ; TWO more bits to store?
        xrl  	A,Bit_Count
        jz   	e_3                     ; if yes, poll last bit

        mov  	Decoder_State,#D_CDP_SYNC
        setb 	F0
        lcall	bit_store
        ret

; Last-Bit polling, case 3:
e_3:    lcall   poll_last_bit
        push    PSW                     ; save polled bit on stack
        setb 	F0
        lcall	bit_store
        pop     PSW
        lcall   bit_store               ; store polled bit
        ret

;**********************************************************************
e_MANCH_SYNC:
        cjne    A,#D_MANCH_SYNC,e_MANCH_ASYNC


        mov     A,B
        add     A,#-2
        jz      e_MANS_2
        dec     A
        jz      e_MANS_3
        ljmp 	delta_error

e_MANS_2:
        setb 	F0
        lcall	bit_store
        ret

e_MANS_3:
        mov  	Decoder_State,#D_MANCH_ASYNC
        setb 	F0
        lcall	bit_store
        clr  	F0
        lcall	bit_store
        ret



;**********************************************************************
e_MANCH_ASYNC:
        cjne    A,#D_MANCH_ASYNC,delta_error

        mov     A,B
        add     A,#-2
        jz      e_MANA_2
        dec     A
        jz      e_MANA_3
        dec     A
        jz      e_MANA_4
        ljmp 	delta_error

e_MANA_2:
        clr  	F0
        lcall	bit_store
        ret

e_MANA_3:
        mov  	Decoder_State,#D_MANCH_SYNC
        setb 	F0
        lcall	bit_store
        ret

e_MANA_4:
        setb 	F0
        lcall	bit_store
        clr  	F0
        lcall	bit_store
        ret



;**********************************************************************
delta_error:
        mov  	Decoder_State,#D_DELTA_ERROR
        mov  	Protocol_State,#P_STOP
        dec     SP                      ; immediate exit from Receive_HT_Bits_INT now
        dec     SP                      ; (remove return address from stack)
        ljmp    call_next_HT_state








;set_timeout resets the timer with values stored in A,B and considers the
;currently elapsed time
set_timeout:       
        clr     TR0
        add     A,TL0
        mov     TL0,A
        mov     A,B
        addc    A,TH0
        mov     TH0,A
        clr     TF0
        setb    TR0
        ret




; Routine to save the main program values and to call next_HT_state
Wait_End_INT:       
call_next_ht_state:
        push    AR1
        push    AR2
        push    AR3
        push    AR4
        push    AR5
        push    AR6
        push    AR7
        push    DPL
        push    DPH

        lcall   next_HT_state

        pop     DPH
        pop     DPL
        pop     AR7
        pop     AR6
        pop     AR5
        pop     AR4
        pop     AR3
        pop     AR2
        pop     AR1

        pop     AR0
        pop     B
        pop     ACC
        pop     PSW
        reti





;the HTRC110_wait routine is called from Receive_HT_Bits and uses
;the polling method to wait.

_HTRC110_wait:
        setb    TR0                     ; stop timer
        mov     A,TH0                   ; save current timer value
        mov     B,TL0
        cjne    A,TH0,wait_reload_lo1   ; has TH0 been incremented since saving?
        sjmp    wait_no_reload_lo1
wait_reload_lo1:
        mov     A,TH0                   ;TH0 has been incremented, save again, now 
        mov     B,TL0                   ;incremention is impossible
wait_no_reload_lo1:
        xch     A,B           
                                        ; 16 bit addition
        add     A,R7
        mov     R7,A
        mov     A,B
        addc    A,R6
        mov     R6,A

wait_loop:

        mov     A,TH0                   ; save current timer value again...
        mov     B,TL0
        cjne    A,TH0,wait_reload_lo2
        sjmp    wait_no_reload_lo2
wait_reload_lo2:
        mov     A,TH0                   ; TH0 has been incremented since saving
        mov     B,TL0
wait_no_reload_lo2:
        xch     A,B

        clr     C                       ; 16 bit subtraktion
        subb    A,R7
        mov     A,B
        subb    A,R6

        jc      wait_loop               ; timer value != (R6, R7)

        ret





; routine to execute the protocol callback
Exec_Protocol_Callback:
        mov     A,Protocol_Callback+0
        orl     A,Protocol_Callback+1
        jz      no_callback

        push    Protocol_Callback+1
        push    Protocol_Callback+0

no_callback:
        ret


 END
