El RTOS ejemplo "Alarma serie"
; The code segment lines 1-87 are explained in this paragraph.
; Line 4 tells the MPASM assembler which PICmicro you
; are using.
        list    p=16C54,t=ON,c=132
        include "P16C5X.INC"
; The include file PICREG.H follows with the
; equates and assignments to make the code more
; readable and changeable. You should use equates that
; relate symbols to each other.
;
; The Constants  lines 10-12 are the values to change
;   for different Baud rates.
; Constants
INDIR          equ     0           ;Indirect Register
OUT_BIT_TIME   equ     33h         ;9600 Baud, 104uS Bit Rate
IN_BIT_TIME    equ     64h         ;4800 Baud, 208uS Bit Rate
FUDGE_TIME     equ     23h         ;Current Time within a Fudge Factor
; They represent the Bit Times for the Baud rates divided
;  by 2 minus some latency factor. You might have to
;  adjust the “Fudge Factor” and other values to fine tune
;  the performance. The value used for the “Fudge
;  Factor” is related to the longest path of code.
;
; Lines 21-24 are an experiment that allows a simple
;  name to be associated to a single bit.
;  This allows for easily changeable assignments.
; PORTB Register Definitions
#define Level_Reset    PORTB,0     ;Low will cause Past Level to reset
                                   ;RB.7 - RB.1 == Input from Sensors
RB_TRIS        equ     B'11111111' ;RB TRIS at INIT State == all input
RB_MASK        equ     B'00000000' ;What is High/Low for RB at INIT State
; A Register Definitions - Programmable Inputs
#define Serial_IN_1    PORTA,0     ;Serial Input #1 - 8 bits
#define LED            PORTA,1     ;LED Output - Level/State Indicator
#define Serial_Out     PORTA,2     ;Serial Output - 8 bits + passwords
#define Serial_IN_2    PORTA,3     ;Serial Input #2 - 8 bits
RA_TRIS        equ     B'11111001' ;RA TRIS at INIT State  RA1,2 Output
RA_MASK        equ     B'00000000' ;What is High/Low for RA at INIT State
;
; Lines 30-54 are the variable assignments.
;   Variables (lines 35-39) are used as time counters.
;   They count the number of units of time, and are compared
;   to literals to see if an Event has just happened.
;
; Register Files RAM
temp           equ     07h          ;Tempary holding register - PIC16C54/56
Timer_Bits     equ     08h          ;Indicates which Timer(s) are Active = 1
Flags          equ     09h          ;Error Flags
LED_Mode       equ     0Ah          ;(0-2)=Mode, 3=LED_B, (4-6)=Seq #, 7=NEW
OState         equ     0Bh          ;Serial Out State
T_5_M_LO       equ     0Ch          ;5 Min Timer Counter - Low
T_5_M_HI       equ     0Dh          ;5 Min Timer Counter - High
T_5_S_CO       equ     0Eh          ;5 Second Timer - lack of Serial Input
T_20_mS_CO     equ     0Fh          ;20 mS Timer - used for debouncing
LED_C          equ     10h          ;LED Counter
Last_TMR0      equ     11h          ;Last value of the TMR0
First_TMR0_O   equ     12h          ;Starting time for next Output event
xmt_byte       equ     13h          ;Serial xmit byte - destroyed in use
Curnt_Cnt      equ     14h          ;256 * TMR0 time μs
RCV_Storage    equ     15h          ;Long term storage of rcv_byte #1 & 2
Old_RB         equ     16h          ;Oldest/Master copy of RB
Last_RB        equ     17h          ;Last copy of RB
IState1        equ     18h          ;Serial In #1 State
First_TMR0_I1  equ     19h          ;Starting time for next #1 Input event
nbti1          equ     1Ah          ;Next Bit #1 In Time - variable time 
rcv_byte_1     equ     1Bh          ;Receive Serial #1 In byte
IState2        equ     1Ch          ;Serial In #2 State
First_TMR0_I2  equ     1Dh          ;Starting time for next #2 Input event
nbti2          equ     1Eh          ;Next Bit #2 In Time - variable time
rcv_byte_2     equ     1Fh          ;Receive Serial #2 In byte
; The bits defined in lines 57-64 are used as Binary Semaphores.
;   They keep Critical Sections of data protected.
;   We will see them in action later in the code.
; Indicates which Timer(s) are Active = 1 & Flags
#define OState_B      Timer_Bits,0  ;Serial Out Active Bit
#define IState1_B     Timer_Bits,1  ;Serial IN #1 Active Bit
#define IState2_B     Timer_Bits,2  ;Serial IN #2 Active Bit
#define T_5_S_B       Timer_Bits,3  ;5 Second Timer Active Bit
#define T_5_M_B       Timer_Bits,4  ;5 Min Timer Active Bit
#define RCV_Got_One_B Timer_Bits,5  ;Got a NEW Received byte to send out
#define RB_NEW_B      Timer_Bits,6  ;Indicates a change in RB input
#define S_5_S_B       Timer_Bits,7  ;Serial In 5 secs of inactivity
; The bits defined in lines 67-73 are error flags.
;   They define the current or last error states of the Serial
;   routines, and whether data was lost coming in or out.
; Error Flags
#define FS_Flag_1      Flags,0       ;Serial #1 IN had a False Start Error
#define FE_Flag_1      Flags,1       ;Last Serial #1 IN had a Frame Error
#define FS_Flag_2      Flags,2       ;Serial #2 IN had a False Start Error
#define FE_Flag_2      Flags,3       ;Last Serial #2 IN had a Frame Error
#define RCV_Overflow   Flags,4       ;Lost Serial Input Byte - too Slow
#define RB_Overflow    Flags,5       ;Lost RB Input Byte - too Slow
#define S_5_S_Overflow Flags,6       ;Lost '5S Inactivity' msg - too Slow
;
; The section of equates in lines 76-85 are used to define
; the different LED activity. They are used by Task #7 to
; keep the LED blinking.
;
;Equates for LED Task #7
#define LED_B          LED_Mode,3    ;LED is active
#define LED_NEW_B      LED_Mode,7    ;LED has just changed Modes = 1
LED_OFF_MODE    equ    B'00001000'   ;LED OFF
LED_SEQ1_MODE   equ    B'10001001'   ;LED Sequence 1: .2s On, 1s Off
LED_SEQ2_MODE   equ    B'10001010'   ;LED Sequence 2: 3x(.2s), 1s Off
LED_SEQ3_MODE   equ    B'10001011'   ;LED Sequence 3: 5x(.2s), 1s Off
LED_SLOW_MODE   equ    B'10011100'   ;LED Slow Pulsing - .3 Hz
LED_MEDIUM_MODE equ    B'10011101'   ;LED Medium Pulsing - 1 Hz
LED_FAST_MODE   equ    B'10011110'   ;LED Fast Pulsing - 3 Hz
LED_ON_MODE     equ    B'10001111'   ;LED ON Continuously
; In lines 89-94, we try to save the all important first 256
;  bytes of any page.
; Clear Registers 7-1Fh 
Clear_Regs   
        GOTO    Do_Clear_Regs        ;Save space in first 256 bytes
; Determine the Highest Error Level & Start Task #7 outputing the new Level
D_H_E_L   
        GOTO    Do_D_H_E_L           ;Save space in first 256 bytes
;
; Task #1 outputs a byte Asynchronously over the Serial
; Output pin. Task #1 is started at line 98.
;  The time units used for Tasks #1-4 are 2μS.
;  Task #1 - Asynchronous 9600 Baud Serial Output (LOW=0)
;
; When Tasks #1-4 are then allowed to run, they check the
; difference between the first sample and the current time.
;  If the delta is greater than or equal to the delay,
;    then that Event has just happened.
;  We first check if the state of the Serial Output is zero.
;  We then jump to OStateS to start the outputting of the
;   “Start Bit”. Because any Serial Output timings must be
;   rock solid, we use a trick in lines 101-116 that helps greatly.
; We check if we are within a certain amount of time BEFORE
;   the deadline and then wait for the time to output another bit.
; This trick allows us to be within a certain ± amount of time
; within the expected time to output that bit. With this code,
; we are about <±8% accurate for the Serial Output.
; You can only use this trick on the most critical tasks,
;  and only on one. In this section of code, we are constantly checking
;  the delta of time from the “FIRST_TMR0_O” reading
;  and the current reading of TMR0.
; When we are very close to the output time, we jump to line 117 (_0005).
;
Do_OState
        MOVF    OState, F           ;if OState == 0   
        BTFSC   STATUS, Z           ;        
        GOTO    OStateS             ;   then goto Output-Start-Bit
		;  We first sample the TMR0 and store the count.
        MOVF    TMR0, W             ;Get current time  
        MOVWF   temp                ;    & store in temporary variable
        MOVF    First_TMR0_O, W     ;Get elapsed time; Time Unit = 2 uS 
        SUBWF   temp, F             ;Delta of Current Time & Orginal Time
        MOVLW   FUDGE_TIME          ;Take in account processing time to do it
        SUBWF   temp,W              ;Time within fudge factor ? 
        BTFSS   STATUS, C
        GOTO    _0005               ;Not time yet to change States so return
;   Check if we are within a certain amount of time BEFORE
;   the deadline and then wait for the time to output another bit.
_0003   MOVLW   OUT_BIT_TIME        ;Past time for next out-bit ? 
        SUBWF   temp,W          
        BTFSC   STATUS, C           ;Do some delaying until it is time
        GOTO    _0004               ;It is now time to out put a bit
        MOVLW   H'04'               ;Account for loop delay 
        ADDWF   temp, F
        NOP                         ;   make loop delay even
        GOTO    _0003               ;Wait for exact time to output bit
;****** 
; If we are not even close to the proper time, we exit back to the
; main loop, so we can check the other timers and tasks.
;
; Now look at Figure 4 for a description of the Output Pulses,
; the “Bit units of Time”, and the associated state numbers.
; Note that the activities are spread out over time.
; The timer Events help to define the different states and
;  their associated output activities. Each Event is
;  handled in a very short, well-defined set of code as Task #1.
; Lines 117-131, are a quick state jump table.
		; State machine  --- OState = state table Entry
_0004   MOVF    OState, W          ;Get (0-A) mode #
        ANDLW   H'0F'              ;Get only mode #  
        ADDWF   PCL, F             ;jump to subroutine
        GOTO    OStateS            ;Serial Start Bit
        GOTO    OState0_7          ;Bit 0 
        GOTO    OState0_7          ;Bit 1 
        GOTO    OState0_7          ;Bit 2 
        GOTO    OState0_7          ;Bit 3 
        GOTO    OState0_7          ;Bit 4 
        GOTO    OState0_7          ;Bit 5 
        GOTO    OState0_7          ;Bit 6 
        GOTO    OState0_7          ;Bit 7 
        GOTO    OStateE            ;Serial Stop Bit
        GOTO    OStateL            ;Last State 
_0005   RETLW   H'00'
; You need to break all Real-Time code into very short
;  segments  in and then out.
;  Each segment is just a few lines long.
; You do your activity, save status, and increment to
;  the next state.
; Notice that OState0_7 code is used several times to
;   output all 8 bits.
; The state variable (OState) is used also to count the number
;   of bits already outputted.
; The time to the next outputting of a bit is calculated
;   and is adjusted to take out the accumulation of
;   errors in lines 151-152.
OS_End  MOVLW   OUT_BIT_TIME       ;Adjust out the cumulation of error   
        ADDWF   First_TMR0_O, F
        INCF    OState, F          ;increment to next state 
        RETLW   H'00'
; We make sure of a full “Stop Bit” length in the OStateE code.
; In the OStateL code,
OStateL   
        CLRF    OState             ;Ready to send next byte out  
        BCF     OState_B           ;Serial Out not active  
        RETLW   H'00'
;   we reset the OState variable to zero, and tell the world
;   that we are not outputting now in line 157.
; This is important because we use that bit (OState_B)
;   to Signal that we need to protect the variable xmt_byte
;   that changes over several states.
; We also use it to Signal that we are ready for another byte
;   to output.
; Look at Task #4. See how it uses this Semaphore to full advantage.
; We have just explained a Critical Segment variable as
;   outlined in the theory sections of this article.
;
; Task #2 starts at line 302.
; Task #2’s subroutines continue at line 363 and continue until line 423.
; This task reads the Serial Input #1 for Asynchronous data.
; Task #2 can be described as a State Machine for outputting
;  a byte Serially.
; Task #2 reads the Serial Input line 1, running at 4800 Baud.
;******         ;Task #2 - Asynchronous 4800 Baud Serial Input (LOW=0)
Do_I1State   
        MOVF    IState1, F          ;if IState1 == 0  
        BTFSC   STATUS, Z           ;      then Do Start Bit 
        GOTO    I1StateS
        MOVF    TMR0, W             ;Get current time
        MOVWF   temp
        MOVF    First_TMR0_I1, W    ;Get elapsed time; Time Unit = 2 uS 
        SUBWF   temp, F
        MOVF    nbti1, W            ;Past time for next input bit ? 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    _0033
	; State machine - IState1 = State table entry
        MOVF    IState1, W          ;Get (0-B) mode #
        ANDLW   H'0F'               ;Get only mode #  
        ADDWF   PCL, F              ;jump to subroutine
        GOTO    I1StateS            ;State - Serial Start Bit 
        GOTO    I1State2            ;State - 1/2 of Start Bit - see if False Start
        GOTO    I1State0_7          ;State - Bit 0  
        GOTO    I1State0_7          ;State - Bit 1  
        GOTO    I1State0_7          ;State - Bit 2  
        GOTO    I1State0_7          ;State - Bit 3  
        GOTO    I1State0_7          ;State - Bit 4  
        GOTO    I1State0_7          ;State - Bit 5  
        GOTO    I1State0_7          ;State - Bit 6  
        GOTO    I1State0_7          ;State - Bit 7  
        GOTO    I1StateE            ;State - Serial Stop Bit 
        GOTO    I1StateL            ;Last State - End of Stop Bit
_0033   
        RETLW   H'00'
;***            ;Subroutines for Task #2
I1StateS                           ;Start Bit - Setup timing variables
        BSF     IState1_B          ;Serial Input Active 
        MOVF    TMR0,W             ;Store starting time
        MOVWF   First_TMR0_I1
        MOVLW   H'0D'              ;Fudge again 
        SUBWF   First_TMR0_I1, F
        MOVLW   H'32'              ;Time delay = 1/2 bit time 
        MOVWF   nbti1
        INCF    IState1, F         ;Increment to next state  
        RETLW   H'00'
I1State2                           ;Check if still a Start Bit
        BTFSS   Serial_IN_1        ;False Start Error ? 
        GOTO    FS_Error_1
        BCF     FS_Flag_1          ;Start Bit OK  
        MOVF    nbti1, W           ;Adjust out the error
        ADDWF   First_TMR0_I1, F
        MOVLW   IN_BIT_TIME        ;Time Delay = full bit time
        MOVWF   nbti1
        INCF    IState1, F         ;increment to next state
        RETLW   H'00'
I1State0_7                         ;Bit 0 - 7 
        BTFSS   Serial_IN_1        ;Move Input bit into C    
        BCF     STATUS,C
        BTFSC   Serial_IN_1
        BSF     STATUS,C
        RRF     rcv_byte_1, F      ;Move C into left most bit 
        MOVF    nbti1,W
        ADDWF   First_TMR0_I1, F   ;Adjust out the error
        INCF    IState1, F         ;increment to next state 
        RETLW   H'00'
I1StateE                           ;Check if we have a proper Stop Bit
        BTFSC   Serial_IN_1        ;Frame Error
        GOTO    F_Error_1
        BCF     FE_Flag_1          ;Stop Bit OK
        CLRF    T_5_S_CO           ;Reset 5 Sec Timer - got a good byte 
        ;Process the msg Here !
        MOVF    rcv_byte_1, W      ;Make a copy of just received byte  
        MOVWF   RCV_Storage
        BTFSS   RCV_Got_One_B      ;Report Lost data 
        BCF     RCV_Overflow
        BTFSC   RCV_Got_One_B
        BSF     RCV_Overflow
        BSF     RCV_Got_One_B      ;We Now have a RB Value to go out 
I1StateL   
        CLRF    IState1            ;Ready to receive next byte
        BCF     IState1_B          ;Serial In not currently active
        RETLW   H'00'
FS_Error_1                         ;False Start - Shut Down Checking
        BCF     IState1_B          ;Serial Input NOT Active
        BSF     FS_Flag_1          ;False Start Error 
        GOTO    I1StateL           ;Start All Over 
F_Error_1                          ;Frame Error - Wait for End of Stop Bit 
        MOVF    nbti1,W            ;Adjust out the error
        ADDWF   First_TMR0_I1, F
        MOVLW   H'32'              ;Time Delay = 1/2 bit time
        MOVWF   nbti1
        BSF     FE_Flag_1          ;Frame Error for this Byte ?
        INCF    IState1, F         ;Increment to next state
        RETLW   H'00'
; The code structure is very similar to that of Task #1 (Figure 3).
; Notice that there are more states than the Serial Output Task #1.
;  Once the “Start Bit” is detected, we half step into the
;  “Start Bit” to see if it was a “False Start” or not.
; We then sample and store theincoming bits to form an 8-bit byte
;  just like Task #1.
;  We sample the “Stop Bit” to see if it is a “Frame Error”.
;  We delay another 1/2 bit to get to the end of the “Stop Bit”
;   if there was an “Frame Error” before resetting Task #1’s
;   state to 0. Otherwise, we reset Task #1’s state to 0, and
;   Signal that we are ready for another “Start Bit”.
; The just received byte is stored in variable “RCV_Storage”.
; A check is made to see if we already sent out the last
;  received byte before clobbering the old byte with the new byte.
;
; Task #3 reads the Serial Input line 2, running at 4800 Baud.
; The code structure is the same as Task #2
; Task #3 interrupts the code of Task #2 at line 333 and continues
;   until line 362.
; Task #3’s subroutines continue at line 424 and continue until line 484
;   is reached.
; The received byte is also put into the same
; storage variable as Task #2 - “RCV_Storage”.
; When either Task #2 or Task #3 receives a valid byte,
;   Task #8’s counter is reset.
;   You can up the Baud rate of Task #2 and 3 if you lower the output
;   Baud rate of Task #1.
; Note that for reading the Serial Input Lines, you can be
; off by ±15% for each sampling, but not accumulatively
;******    ;Task #3 - Asynchronous 4800 Baud Serial Input (LOW=0)
Do_I2State   
        MOVF    IState2, F          ;if IState1 == 0
        BTFSC   STATUS, Z           ;   then Do Start Bit 
        GOTO    I2StateS
        MOVF    TMR0, W             ;Get current time
        MOVWF   temp
        MOVF    First_TMR0_I2, W    ;Get elapsed time; Time Unit = 2 uS
        SUBWF   temp, F
        MOVF    nbti2, W            ;Past time for next input bit ? 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    _0035
	; State machine - IState2 = State table entry
        MOVF    IState2,W           ;Get (0-B) mode #
        ANDLW   H'0F'               ;Get only mode #  
        ADDWF   PCL, F              ;jump to subroutine 
        GOTO    I2StateS            ;State - Serial Start Bit 
        GOTO    I2StateS2           ;State - 1/2 of Start Bit - see if False 
Start  
        GOTO    I2State0_7          ;State - Bit 0
        GOTO    I2State0_7          ;State - Bit 1
        GOTO    I2State0_7          ;State - Bit 2
        GOTO    I2State0_7          ;State - Bit 3
        GOTO    I2State0_7          ;State - Bit 4
        GOTO    I2State0_7          ;State - Bit 5
        GOTO    I2State0_7          ;State - Bit 6
        GOTO    I2State0_7          ;State - Bit 7
        GOTO    I2StateE            ;State - Serial Stop Bit 
        GOTO    I2StateL            ;Last State - End of Stop Bit 
_0035   RETLW   H'00'
;
;***    ;Subroutines for Task #3
I2StateS                           ;Start Bit - Setup timing variables
        BSF     IState2_B          ;Serial Input Active  
        MOVF    TMR0, W            ;Store starting time 
        MOVWF   First_TMR0_I2
        MOVLW   H'0D'              ;Fudge again   
        SUBWF   First_TMR0_I2, F
        MOVLW   H'32'              ;Time delay = 1/2 bit time
        MOVWF   nbti2
        INCF    IState2, F         ;Increment to next state
        RETLW   H'00'
I2StateS2                          ;Check if still a Start Bit
        BTFSS   Serial_IN_2        ;False Start Error ?  
        GOTO    FS_Error_2
        BCF     FS_Flag_2          ;Start Bit OK 
        MOVF    nbti2,W            ;Adjust out the error 
        ADDWF   First_TMR0_I2, F
        MOVLW   IN_BIT_TIME        ;Time Delay = full bit time 
        MOVWF   nbti2
        INCF    IState2, F         ;increment to next state
        RETLW   H'00'
I2State0_7                         ;Bit 0 - 7 
        BTFSS   Serial_IN_2        ;Move Input bit into C
        BCF     STATUS, C
        BTFSC   Serial_IN_2
        BSF     STATUS, C
        RRF     rcv_byte_2, F      ;Move C into left most bit 
        MOVF    nbti2, W
        ADDWF   First_TMR0_I2, F   ;Adjust out the error    
        INCF    IState2, F         ;increment to next state 
        RETLW   H'00'
I2StateE                           ;Check if we have a proper Stop Bit
        BTFSC   Serial_IN_2        ;Frame Error
        GOTO    F_Error_2
        BCF     FE_Flag_2          ;Stop Bit OK 
        CLRF    T_5_S_CO           ;Reset 5 Sec Timer - got a good byte
        ;Process the msg Here !
        MOVF    rcv_byte_2, W      ;Make a copy of just received byte 
        MOVWF   RCV_Storage
        BTFSS   RCV_Got_One_B      ;Report Lost data 
        BCF     RCV_Overflow
        BTFSC   RCV_Got_One_B
        BSF     RCV_Overflow
        BSF     RCV_Got_One_B      ;We Now have a RB Value to go out   
I2StateL   
        CLRF    IState2            ;Ready to receive next byte 
        BCF     IState2_B          ;Serial In not currently active 
        RETLW   H'00'
FS_Error_2   
        BCF     IState2_B          ;False Start - Shut Down Checking
        BSF     FS_Flag_2          ;False Start Error 
        GOTO    I2StateL           ;Start All Over
F_Error_2                          ;Frame Error - Wait for End of Stop Bit
        MOVF    nbti2,W            ;Adjust out the error 
        ADDWF   First_TMR0_I2, F
        MOVLW   H'32'              ;Time Delay = 1/2 bit time 
        MOVWF   nbti2
        BSF     FE_Flag_2          ;Frame Error for this Byte ? 
        INCF    IState2, F         ;Increment to next state 
        RETLW   H'00'
;
; Task #4 starts at line 538 and finishes at line 561.
; Task #4 controls the feeding of Task #1 from several other tasks
; that want data to be outputted. It uses several Semaphores
; to make sure that Task #1 is not bothered until
; it is ready for another byte.
;
Task_4 ;Task #4 - Finds next Buffered Byte to Send Out through Task 1
        BTFSC   OState_B           ;if outputing now then skip call
        GOTO    _0059
        BTFSS   RCV_Got_One_B      ;Got a NEW Received byte to send
        GOTO    _0057
        MOVF    RCV_Storage, W     ;Send just received byte 
        MOVWF   xmt_byte
        BCF     RCV_Got_One_B      ;Clear need to send old byte 
        BSF     OState_B           ;Start Task #1 & Lock Out Others 
        GOTO    _0059
_0057   BTFSS   RB_NEW_B           ;Indicates a change in RB input 
        GOTO    _0058
        MOVF    Old_RB, W          ;Send New RB value  
        MOVWF   xmt_byte
        BCF     RB_NEW_B           ;Clear need to send out newest value 
        BSF     OState_B           ;Start Task #1 & Lock Out Others
        GOTO    _0059
_0058   BTFSS   S_5_S_B            ;Serial In 5 secs of inactivity
        GOTO    _0059
        MOVLW   H'FF'              ;Tell of inactivity of Serial In 
        MOVWF   xmt_byte
        BCF     S_5_S_B            ;Clear need to send msg  
        BSF     OState_B           ;Start Task #1 & Lock Out Others
                
       ;Heart Beat - Time unit = 512 uS for Tasks #5 & #6
_0059   MOVF    TMR0,W             ;Step-up time units * 512  
        MOVWF   temp
        MOVF    Last_TMR0, W       ;Test to see if it overflowed 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    Inc_Time
        MOVF    temp, W            ;unit error = < |+-512 uS| 
        MOVWF   Last_TMR0
        GOTO    Task_1             ;Serial Output
Inc_Time
        MOVF    temp, W            ;Save current TMR0 into Last_TMR0
        MOVWF   Last_TMR0
; Task #4 finds the next buffered byte to send out through Task #1.
; Task #4 also controls the order of which byte
; goes first over another less important byte of data.
; It can be said that Task #1 Blocks Task #4 from running.
; You can think of the Serial Output Line as a Shared Resource.
; The use of Semaphores here allow the Synchronization of data
;  and actions.
;
; Task#5 runs through lines 576-581, and is very short.
Task_5  ; - Monitor Level Reset Input Line - Always Running ! 
        BTFSC   Level_Reset
        GOTO    Task_6             ; Debounces sensors input lines
        MOVLW   LED_OFF_MODE       ;Lowest Level Indicator output
        MOVWF   LED_Mode
; Task #5 monitors the Level Reset Input Line and will
; reset the LED state variable if the line ever goes low.
; This task is always in the Ready State. This task is said
; to simply “pole the input line” when ever it can.
;
; Task #6 debounces the seven sensor input lines,
; running every 20 ms. Lines 582-611 represent Task #6.
; The variable “T_20_mS_CO” is incremented every 512 μs (Clock Tick)
; and is compared to the count needed to equal 20 ms. If it is time,
; the subroutine QCheck_T123 is called to see if Tasks
; #1-3 are in the Ready State.
Task_6  ;Task #6 - Debounce 8 bit Input Sensors - Runs every 20 mS 
        INCF    T_20_mS_CO, F      ;Inc Counter - Time Unit = 512 uS
        MOVLW   H'27'              ;Used to debounce the input 
        SUBWF   T_20_mS_CO, W
        BTFSS   STATUS, Z
        GOTO    _0065
        CLRF    T_20_mS_CO         ;Reset T_20_mS_CO to start over again
        CALL    QCheck_T123        ;Quick Check of Tasks #1, #2 and #3 
        MOVF    PORTB,W            ;Last copy of RB same as Current ? 
        SUBWF   Last_RB,W
        BTFSC   STATUS, Z        
        GOTO    _0062
        MOVF    PORTB, W           ;  Store Current RB - diff from Last
        MOVWF   Last_RB
        GOTO    _0063
_0062   MOVF    Last_RB, W         ;New Old RB <- same value over 20 mS 
        MOVWF   Old_RB
_0063   MOVF    Old_RB, F          ;See if RB is now 0 
        BTFSC   STATUS,Z           ;RB == 0 ? then keep timer running 
        GOTO    _0064
        CLRF    T_5_M_LO           ;Reset 5 Min Timer 
        CLRF    T_5_M_HI           ;  still not zero yet 
_0064   CALL    D_H_E_L            ;Determine the Highest Error Level
        BTFSS   RB_NEW_B           ;Check for Lost Data Error 
        BCF     RB_Overflow
        BTFSC   RB_NEW_B
        BSF     RB_Overflow
        BSF     RB_NEW_B           ;Every 20 mS send Old_RB out
                
        ;Heart Beat - Time unit = 131072 uS for Tasks #7, #8 & #9
_0065   MOVLW   H'F9'              ;RA TRIS - refresh RA=1001
        TRIS    5
        MOVLW   H 'FF'             ;RB TRIS - refresh 
        TRIS    6
        DECFSZ  Curnt_Cnt, F	   ;Step-up time units * 256 
        GOTO    Task_1             ;Serial Output
;
; If any of the Tasks #1-3 are ready, they are ran and we then
;  continue with Task #6.
; We compare the current value of the input Port_B to
; see if it stayed the same from the last reading 20 ms back.
; If the two readings are the same, then Port_B is
;  considered to be stable and the possibly new value is
;  placed in the variable “Old_RB” to be outputted by Task#1.
;
; The subroutine D_H_E_L is called to determine the new LED state.
; We then check if Task #1 was too busy to output the last sensor
; status byte, if so then that error is recorded.
;
; Do_D_H_E_L determines the LED’s next state based
;   on the 7 sensor input status.
; This subroutine checks each bit to see if it is active and then
;   checks if a change in the LED’s current state needs changing.
;****
Do_D_H_E_L      
; Determine the Highest Error Level & Start Task #7
; - Output Highest Level Indication on LED
        MOVLW   H'07'              ;Check top 7 bits 
        MOVWF   temp
        MOVF    Old_RB, W          ;Get copy of 7 debounced Sensor Input
        MOVWF   Last_RB
_0070   RLF     Last_RB, F         ;Put top bit into C bit
        BTFSC   STATUS, C          ;Check if C bit is set 
        GOTO    _0072
        DECFSZ  temp, F            ;Continue to check lesser bits
        GOTO    _0070
_0071   MOVF    PORTB, W           ;Restore current value of RB 
        MOVWF   Last_RB
        RETLW   H'00'
_0072  ; Implimentation off  missing instruccion SUBLF  L, RAM-Reg
        MOVF    LED_Mode, W        ;Get current Level Indicator 
        ANDLW   H'07'              ;Get only      "       "  
        MOVWF   Last_RB            ;Store into a tempary register 
        MOVF    temp, W            ;Check if already at this Level
        SUBWF   Last_RB, W
		                   ; end implementation
        BTFSC   STATUS, C
        GOTO    _0071
        MOVLW   H'88'              ;Start to build LED_Mode 
        IORWF   temp, W            ;Put new Level Indicator into reg 
        MOVWF   LED_Mode           ;Store new LED Mode 
        GOTO    _0071
; Task #7 outputs the Highest Severity Level Indicationon the LED.
; Task #7’s main code is lines 621-628.
;
; Do_LED starts at line 161, and continues to 276.
; This task is also broken into small time units of code.
; It is constantly checking to see if it is time to switch the
;  on/off condition of the LED.
;  The time units for Task #7 are regulated by the code in lines 613-619.
;  131072 μS = time unit for Tasks #7-9.
; Task #7 has many state jump tables so it is included in the
;  first 256 bytes of the first page.
;  Lines 168-175 explain the on and off sequences and offs that
;  represent levels of severity of the input status lines.
;  The variable “LED_Mode” has both Task #7’s current state number
;   and the sub-state-number for that state’s output sequence.
;
;  Task #8 is a 5 second lack of input from either of the two
;  Serial input timers. Tasks #2 and #3 will reset the time
;   counter for Task #8, when either receives a full byte.
;  If the time counter “T_5_S_CO” equals 5 secs, then the
;   LED’s state is bumped to the highest, and a special
;   byte is sent down the line to the next “Remote Alarm” unit.
;   The counter variable is reset, and count starts all over.
; We then check if Task #1 was too busy to output
;   the last special status byte, if so then that error is recorded.
;
; Task #9 measures 5 minutes of calm on the 7 sensor
;   lines and then resets the LED’s state.
; Lines 646-663 compose Task #9.
Task_9  ; - 5 Min. Lack of Severe Error from Sensors Reset Timer 
        BTFSS   T_5_M_B            ;5 Min Timer Active ? 
        GOTO    Task_A
        ; 16-bit increment
        INCF    T_5_M_LO, F        ;Inc LO Counter; Time Unit = 131072 uS
        BTFSC   STATUS,Z           ;  See if carry needs to be passed on ?
        INCF    T_5_M_HI, F        ;Inc HI Counter; Time Unit = 131072 uS
		                   ; end of 16-bit increment
        MOVLW   H'08'              ;#2288<  Check T_5_M_HI if time  
        SUBWF   T_5_M_HI, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        MOVLW   H'F0'              ;#2288>  Check T_5_M_LO if time 
        SUBWF   T_5_M_LO, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        CLRF    T_5_M_LO           ;Reset T_5_M_LO 
        CLRF    T_5_M_HI           ;Reset T_5_M_HI 
        MOVLW   LED_OFF_MODE       ;Lowest Level Indicator output 
        MOVWF   LED_Mode
Task_A   
        GOTO    Task_1             ; Loop Forever
; Task #9 needs 16 bits of counter power to record 5 minutes of time.
; The counter variables are reset after being triggered.
; Subrutie Do_Clear_Regs clears registers 7-1Fh.
; It leaves the FSR register zeroed out.
; This is very important for the PIC16C57 chip.
Do_Clear_Regs   ; Limpia Registros RAM  07h-1Fh
        MOVLW   H'1F'             ;Write the base (First regs to clear)
        MOVWF   FSR               ; into FSR 
Loop_C  CLRF    INDIR             ; Limpia el registro apuntado 
        DECF    FSR, F            ;   y apunta al siguiente registro
; Con el PIC16F54, en el reg FSR, solo podemos cambiar los bits 4 -> 0
; cuando estan en 1 1111 e incrementamos FSR este pasa a 0 0000 sin afectar
;      los bits 5,6 & 7.
        MOVLW   H'E7'             ;Vemos si ya alcanzamos el limite bajo
        SUBWF   FSR, W            ;  de RAM el cual es 07h pero como los
                                  ;  bits 5, 6, y 7 de
                                  ; FSR estan ajustados a 1 ... debemos
                                  ; subtraer  E7h
        BTFSC   STATUS, C         ;
        GOTO    Loop_C            ;  No: Regresa hasta que se alcanze
        CLRF    FSR               ;  Si:  Limpia el reg FSR
        RETLW   H'00'             ;       y regresa
; The main or starting code is started at line 485.
; From that line to line 515, all variables are initialized, and all tasks
;  are initialized at this time also.
;******         ;Code Starting point
Main
	; Configura Puertos y TMR0
        MOVLW   H'00'             ;What is High/Low for RA at INIT State 
        MOVWF   PORTA
        MOVLW   H'00'             ;What is High/Low for RB at INIT State 
        MOVWF   PORTB
        MOVLW   H'F9'             ;RA TRIS at INIT State  
        TRIS    5
        MOVLW   H'FF'             ;RB TRIS at INIT State 
        TRIS    6
        MOVLW   H'00'             ; Set TMR0/2 
	; bit5-Clock source = Internal  bit4-Edge =low-to-high transition
	; bit3-Prescaler on TMR0        bit210- Prescaler = 1:2
        OPTION
        CALL    Clear_Regs        ;Clear Registers 7-1F - Same Memory Page
        CLRF    TMR0              ;Start timers
;Initialize Tasks
                                  ;Task #1 waits for byte to output
                                  ;Asynchronous 9600 Baud Serial Output
;
                                  ;Task #2 waits for Serial IN Start Bit
                                  ;1st Asynchronous 4800 Baud Serial Input
;
                                  ;Task #3 waits for Serial IN Start Bit
                                  ;2nd Asynchronous 4800 Baud Serial Output
;
                                  ;Task #4 runs when Task 1 is Not
                                  ;  Finds next Buffered Byte to Send Out
                                  ;  through Task 1
;
                                  ;Task #5 is always running
                                  ;   Monitor Level Reset Input Line
;
                                  ;Task #6  - Runs every 20 mS
                                  ;   Debounce 8 bit Input Sensors
        MOVF    PORTB, W        ;Task #6 is Initialized here 
        MOVWF   Old_RB
        MOVF    Old_RB, W         ;Make all the same initial value 
        MOVWF   Last_RB
        BSF     RB_NEW_B          ;Tell Task #4: RB byte ready to output
;								
                                  ;Task #7  - Runs every 20 mS
                                  ;   Output Highest Level Indication on LED
        MOVLW   LED_OFF_MODE
        MOVWF   LED_Mode          ;Task #7 is Started 
;
                                  ;Task #8 - Runs every 20 mS
                                  ;   5 Second Serial Input Lack of
                                  ;   Activity Timer
        BSF     T_5_S_B           ;Task #8 is Started here  
;
                                  ;Task #9 - 5 Min. Lack of Severe Error
                                  ;   from Sensors Reset Timer
        BSF     T_5_M_B           ;Task #9 is Started here  
; The Main Loop is started at line 516 and ends at line 665.
; This is where the real action is done.
; Each task checks the time to see if the conditions are correct for it to run.
; The tasks that are not Blocked, and have a job to do now are in a Ready State.
; In the Main Loop, we check the current state of
; each task in order of Priority (1-9). If ready, we do a
; very simple Task Switch and place that task in the
; Executing State/Running State. Several time unit
; changes take place in the Main Loop.
; Handle Task & Timer activities - Main Loop
Task_1  ;Task #1 - Asynchronous 9600 Baud Serial Output (LOW=0)
        BTFSS   OState_B          ;if not outputing now then skip call 
        GOTO    Task_2
        CALL    Do_OState         ;Go Do Task #1
Task_2  ;Task #2 - Asynchronous 4800 Baud Serial Input (LOW=0)
        BTFSC   IState1_B         ;if already started then call
        GOTO    _0053
        BTFSC   Serial_IN_1       ;if Start bit ? then call
        GOTO    _0053
        GOTO    Task_3
_0053   CALL    Do_I1State        ;Go Do Task #2
Task_3  ;Task #3 - Asynchronous 4800 Baud Serial Input (LOW=0)
        BTFSC   IState2_B         ;if already started then call 
        GOTO    _0055
        BTFSC   Serial_IN_2       ;if Start bit ? then call 
        GOTO    _0055
        GOTO    Task_4
_0055   CALL    Do_I2State        ;Go Do Task #3
Task_4  ;Task #4 - Finds next Buffered Byte to Send Out through Task 1
        BTFSC   OState_B          ;if outputing now then skip call
        GOTO    _0059
        BTFSS   RCV_Got_One_B     ;Got a NEW Received byte to send
        GOTO    _0057
        MOVF    RCV_Storage, W    ;Send just received byte 
        MOVWF   xmt_byte
        BCF     RCV_Got_One_B     ;Clear need to send old byte 
        BSF     OState_B          ;Start Task #1 & Lock Out Others 
        GOTO    _0059
_0057   BTFSS   RB_NEW_B          ;Indicates a change in RB input 
        GOTO    _0058
        MOVF    Old_RB, W         ;Send New RB value  
        MOVWF   xmt_byte
        BCF     RB_NEW_B          ;Clear need to send out newest value 
        BSF     OState_B          ;Start Task #1 & Lock Out Others
        GOTO    _0059
_0058   BTFSS   S_5_S_B           ;Serial In 5 secs of inactivity
        GOTO    _0059
        MOVLW   H'FF'             ;Tell of inactivity of Serial In 
        MOVWF   xmt_byte
        BCF     S_5_S_B           ;Clear need to send msg  
        BSF     OState_B          ;Start Task #1 & Lock Out Others
                
        ;Heart Beat - Time unit = 512 uS for Tasks #5 & #6
_0059   MOVF    TMR0,W            ;Step-up time units * 512  
        MOVWF   temp
        MOVF    Last_TMR0, W      ;Test to see if it overflowed 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    Inc_Time
        MOVF    temp, W           ;unit error = < |+-512 uS| 
        MOVWF   Last_TMR0
        GOTO    Task_1
            ;Serial Output
Inc_Time   
        MOVF    temp, W           ;Save current TMR0 into Last_TMR0
        MOVWF   Last_TMR0
Task_5  ;Task #5 - Monitor Level Reset Input Line - Always Running ! 
        BTFSC   Level_Reset
        GOTO    Task_6
        MOVLW   LED_OFF_MODE      ;Lowest Level Indicator output
        MOVWF   LED_Mode
Task_6  ;Task #6 - Debounce 8 bit Input Sensors - Runs every 20 mS 
        INCF    T_20_mS_CO, F     ;Inc Counter - Time Unit = 512 uS
        MOVLW   H'27'             ;Used to debounce the input 
        SUBWF   T_20_mS_CO, W
        BTFSS   STATUS, Z
        GOTO    _0065
        CLRF    T_20_mS_CO        ;Reset T_20_mS_CO to start over again
        CALL    QCheck_T123       ;Quick Check of Tasks #1, #2 and #3 
        MOVF    PORTB,W           ;Last copy of RB same as Current ? 
        SUBWF   Last_RB,W
        BTFSC   STATUS, Z        
        GOTO    _0062
        MOVF    PORTB, W          ;  Store Current RB - diff from Last
        MOVWF   Last_RB
        GOTO    _0063
_0062   MOVF    Last_RB, W        ;New Old RB <- same value over 20 mS 
        MOVWF   Old_RB
_0063   MOVF    Old_RB, F         ;See if RB is now 0 
        BTFSC   STATUS,Z          ;RB == 0 ? then keep timer running 
        GOTO    _0064
        CLRF    T_5_M_LO          ;Reset 5 Min Timer 
        CLRF    T_5_M_HI          ;  still not zero yet 
_0064   CALL    D_H_E_L           ;Determine the Highest Error Level
        BTFSS   RB_NEW_B          ;Check for Lost Data Error 
        BCF     RB_Overflow
        BTFSC   RB_NEW_B
        BSF     RB_Overflow
        BSF     RB_NEW_B          ;Every 20 mS send Old_RB out
                
        ;Heart Beat - Time unit = 131072 uS for Tasks #7, #8 & #9
_0065   MOVLW   H'F9'             ;RA TRIS - refresh RA=1001
        TRIS    5
        MOVLW   H'FF'             ;RB TRIS - refresh 
        TRIS    6
        DECFSZ  Curnt_Cnt, F	  ;Step-up time units * 256 
        GOTO    Task_1            ;Serial Output
Task_7          ;Task 7 - Output Highest Level Indication on LED
        BTFSS   LED_B             ;Is LED active ? 
        GOTO    Task_8
        CALL    QCheck_T123       ;Quick Check of Tasks #1, #2 and #3 
        CALL    Do_LED            ;Handle LED timing
                                  
Task_8  ;Task #8 - 5 Second Serial Input Lack of Activity Timer
        BTFSS   T_5_S_B           ;5 Sec Timer Active ?  
        GOTO    Task_9
        INCF    T_5_S_CO, F       ;Inc Counter - Time Unit = 131072 uS 
        MOVLW   H'26'             ;Check T_5_S_CO if time  
        SUBWF   T_5_S_CO, W
        BTFSS   STATUS, Z
        GOTO    Task_9
        CLRF    T_5_S_CO          ;Reset T_5_S_CO 
        MOVLW   LED_ON_MODE       ;Highest Level Indicator output 
        MOVWF   LED_Mode
        BTFSS   S_5_S_B           ;Check if Lost Data Error 
        BCF     S_5_S_Overflow
        BTFSC   S_5_S_B
        BSF     S_5_S_Overflow
        BSF     S_5_S_B           ;Send notice of 5 seconds of inaction  
Task_9  ;Task #9 - 5 Min. Lack of Severe Error from Sensors Reset Timer 
        BTFSS   T_5_M_B           ;5 Min Timer Active ? 
        GOTO    Task_A
        ; 16-bit increment
        INCF    T_5_M_LO, F       ;Inc LO Counter; Time Unit = 131072 uS 
        BTFSC   STATUS,Z          ;  See if carry needs to be passed on ?
        INCF    T_5_M_HI, F       ;Inc HI Counter; Time Unit = 131072 uS
	; end of 16-bit increment
        
        MOVLW   H'08'             ;#2288 < Check T_5_M_HI if time  
        SUBWF   T_5_M_HI, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        MOVLW   H'F0'             ;#2288 > Check T_5_M_LO if time 
        SUBWF   T_5_M_LO, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        CLRF    T_5_M_LO          ;Reset T_5_M_LO 
        CLRF    T_5_M_HI          ;Reset T_5_M_HI 
        MOVLW   LED_OFF_MODE      ;Lowest Level Indicator output 
        MOVWF   LED_Mode
Task_A   
        GOTO    Task_1          ; Loop Forever