;******************************************************************************************************
;   Radio Transmit-Receive Sequencer, By Bertrand Zauhar, VE2ZAZ
;   For more details, visit VE2ZAZ's website at:   
;        http://www3.sympatico.ca/b.zauhar                                                                      
;******************************************************************************************************
;    Filename:      TR_Seq.asm                                            
;    Date:          28/02/2007                                                   
;    Software Version:  2                                                   
;
;    Designed to run on PICmicro PIC18F2220.
;                                                                     
;    Author: Bertrand Zauhar                                                          
;******************************************************************************************************
;    Files required:         P18F2220.INC                                     
;    Assembles using Microchip's MPASM assembler software
;******************************************************************************************************

    LIST P=18F2220        ;directive to define processor
    #include <P18F2220.INC>    ;processor specific variable definitions

;******************************************************************************************************
;Configuration bits
; The __CONFIG directive defines configuration data within the .ASM file.
; The labels following the directive are defined in the P18F2220.INC file.
; The PIC18F2220/2320/4220/4320 Data Sheet explains the functions of the
; configuration bits.

; NOTE: LOW VOLTAGE PROGRAMMING IS DISABLED BECAUSE THE PGM PIN IS USED FOR PORT B, BIT 5 AS AN I/O PIN.

    __CONFIG  _CONFIG1H, _INTIO2_OSC_1H & _FSCM_OFF_1H & _IESO_OFF_1H
    __CONFIG  _CONFIG2L, _PWRT_OFF_2L & _BORV_42_2L & _BOR_ON_2L
    __CONFIG  _CONFIG2H, _WDTPS_1_2H & _WDT_OFF_2H
    __CONFIG  _CONFIG3H, _MCLRE_ON_3H & _PBAD_DIG_3H & _CCP2MX_C1_3H
    __CONFIG  _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_OFF_4L
    __CONFIG  _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L 
    __CONFIG  _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
    __CONFIG  _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L 
    __CONFIG  _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
    __CONFIG  _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L 
    __CONFIG  _CONFIG7H, _EBTRB_OFF_7H

;******************************************************************************************************
;Bank 1 has 256 locations available
;Bank 0 is skipped to simplify variable access.

    CBLOCK    0x100         ;All of these variables are located in the RAM Bank 1.

    WREG_TEMP               ;0_variable used for context saving when interrupt occurs
    STATUS_TEMP             ;1_variable used for context saving when interrupt occurs
    BSR_TEMP                ;2_variable used for context saving when interrupt occurs

    ARM_PTT_STAT1           ;3_This is the PTT and ARMING status flag register    
                            ; 7-Sequencing process requested
                            ; 6-Disarming process requested flag. requested (1), not requested (0)
                            ; 5-Arming process requested flag. requested (1), not requested (0)
                            ; 4-Arming button debouncing happening flag. Happening (1), not happening (0)
                            ; 3-Arm button already treated flag. Already treated (1), not treated (0)
                            ; 2-Old PTT pin state: High (1), Low (0). Used for debouncing.
                            ; 1-Debounced PTT state. PTT enabled (1), PTT disabled (0)
                            ; 0-System armed (1), disarmed (0)

    ARM_PTT_STAT2           ;4_This is the PTT and ARMING status flag register    
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-(not used)
                            ; 4-(not used)
                            ; 3-(not used)
                            ; 2-PTT already treated flag. Already treated (1), not treated (0)
                            ; 1-Disarming process running. (1) running
                            ; 0-Arming process running. (1) running

    TX_SEQUENCING_STAT1     ;5_Tx sequencing status byte 1
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-(not used)
                            ; 4-(not used)
                            ; 3-(not used)
                            ; 2-Tx output delay timer started. Started (1), not started (0)
                            ; 1-Tx output feedback timer started. Started (1), not started (0)
                            ; 0-Tx sequencing over flag. Over (1), in progress (0)

    RX_SEQUENCING_STAT1     ;6_Rx sequencing status byte 1
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-(not used)
                            ; 4-(not used)
                            ; 3-Rx Pre-Switch feedback alarm detected (1), not detected (0)
                            ; 2-Rx output delay timer started. Started (1), not started (0)
                            ; 1-Rx output feedback timer started. Started (1), not started (0)
                            ; 0-Rx sequencing over flag. Over (1), in progress (0)

    TX_RX_OUTPUT_STAT       ;7_Tx/Rx output status byte
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 in Tx or Rx state. Tx (1)
                            ; 4-Output 5 in Tx or Rx state. Tx (1)
                            ; 3-Output 4 in Tx or Rx state. Tx (1)
                            ; 2-Output 3 in Tx or Rx state. Tx (1)
                            ; 1-Output 2 in Tx or Rx state. Tx (1)
                            ; 0-Output 1 in Tx or Rx state. Tx (1)

    TX_RX_SEQ_DONE          ;8_Tx/Rx sequence done for outputs status byte
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Tx or Rx sequence has Output 6 completed. Completed (1)
                            ; 4-Tx or Rx sequence has Output 5 completed. Completed (1)
                            ; 3-Tx or Rx sequence has Output 4 completed. Completed (1)
                            ; 2-Tx or Rx sequence has Output 3 completed. Completed (1)
                            ; 1-Tx or Rx sequence has Output 2 completed. Completed (1)
                            ; 0-Tx or Rx sequence has Output 1 completed. Completed (1)

    TX_RX_SW_REQ_STAT       ;9_Tx/Rx output switching requested status byte 
                            ; 7-DO NOT USE
                            ; 6-DO NOT USE
                            ; 5-Output 6 Tx/Rx switch requested. Requested (1)
                            ; 4-Output 5 Tx/Rx switch requested. Requested (1)
                            ; 3-Output 4 Tx/Rx switch requested. Requested (1)
                            ; 2-Output 3 Tx/Rx switch requested. Requested (1)
                            ; 1-Output 2 Tx/Rx switch requested. Requested (1)
                            ; 0-Output 1 Tx/Rx switch requested. Requested (1)

    TX_FB_ALM_STAT          ;10_Tx switching feedback failure status byte
                            ; 7-DO NOT USE
                            ; 6-DO NOT USE
                            ; 5-Output 6 Tx feedback fail alarm. Alarmed (1)
                            ; 4-Output 5 Tx feedback fail alarm. Alarmed (1)
                            ; 3-Output 4 Tx feedback fail alarm. Alarmed (1)
                            ; 2-Output 3 Tx feedback fail alarm. Alarmed (1)
                            ; 1-Output 2 Tx feedback fail alarm. Alarmed (1)
                            ; 0-Output 1 Tx feedback fail alarm. Alarmed (1)

    RX_FB_ALM_STAT          ;11_Rx switching feedback failure status byte
                            ; 7-DO NOT USE
                            ; 6-DO NOT USE
                            ; 5-Output 6 Rx feedback fail alarm. Alarmed (1)
                            ; 4-Output 5 Rx feedback fail alarm. Alarmed (1)
                            ; 3-Output 4 Rx feedback fail alarm. Alarmed (1)
                            ; 2-Output 3 Rx feedback fail alarm. Alarmed (1)
                            ; 1-Output 2 Rx feedback fail alarm. Alarmed (1)
                            ; 0-Output 1 Rx feedback fail alarm. Alarmed (1)

    TX_FB_PRESENT_STAT      ;12_Tx switching feedback present status byte
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 Tx feedback present. Present (1)
                            ; 4-Output 5 Tx feedback present. Present (1)
                            ; 3-Output 4 Tx feedback present. Present (1)
                            ; 2-Output 3 Tx feedback present. Present (1)
                            ; 1-Output 2 Tx feedback present. Present (1)
                            ; 0-Output 1 Tx feedback present. Present (1)

    RX_FB_PRESENT_STAT      ;13_Rx switching feedback present status byte
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 Rx feedback present. Present (1)
                            ; 4-Output 5 Rx feedback present. Present (1)
                            ; 3-Output 4 Rx feedback present. Present (1)
                            ; 2-Output 3 Rx feedback present. Present (1)
                            ; 1-Output 2 Rx feedback present. Present (1)
                            ; 0-Output 1 Rx feedback present. Present (1)

    TX_RX_FB_REQ_STAT       ;14_This register is used to flag that Feedback detection is requested on a specific output
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 feedback detection requested. Requested (1)
                            ; 4-Output 5 feedback detection requested. Requested (1)
                            ; 3-Output 4 feedback detection requested. Requested (1)
                            ; 2-Output 3 feedback detection requested. Requested (1)
                            ; 1-Output 2 feedback detection requested. Requested (1)
                            ; 0-Output 1 feedback detection requested. Requested (1)

    TX_Ox_POS_PTR           ;15_Bit pointer used in the Tx Sequencing loop

    RX_Ox_POS_PTR           ;16_Bit pointer used in the Rx Sequencing loop
  
    ARM_PTT_LED_STAT        ;17_LED status and control register
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-(not used)
                            ; 4-ARM/PTT LED to be set to Flashing
                            ; 3-ARM/PTT LED to be set to Red
                            ; 2-ARM/PTT LED to be set to Amber
                            ; 1-ARM/PTT LED to be set to Green
                            ; 0-ARM/PTT LED to be set to OFF

    LED_DIM_CTR             ;18_Counter to allow to detect when to turn off a LED and create a dimmed effect

    SERIAL_STAT             ;19_This is the USART status flag register    
                            ; 7-unused
                            ; 6-unused
                            ; 5-Request to Transmit Remote Monitoring Info
                            ; 4-Setup mode enabled (comms with PC active)
                            ; 3-tx cycle being performed.
                            ; 2-Request to transmit parameters information
                            ; 1-LF character received (end of user command entry)
                            ; 0-New character transmission cycle required

    GENERAL1_STAT           ;20_This is a general purpose status flag register    
                            ; 7-(not used)
                            ; 6-Flag when a Tx (too long) Auto-Disarm delay is counting
                            ; 5-Flag when a feedback alarm Auto-Disarm delay is counting
                            ; 4-Flag when a sequence tone is currnetly sounding
                            ; 3-Flag when a timeout tone is currently sounding
                            ; 2-Flag when the timeout cycle is running
                            ; 1-Flag when a timeout tone cycle start is requested
                            ; 0-Flag when a parameter EEPROM Write cycle is required

    TEMP1_HI                ;21_Temporary 16-bit variable available throughout code execution.
    TEMP1_LO                ;22_ "

    TEMP2_HI                ;23_Temporary 16-bit variable available throughout code execution.
    TEMP2_LO                ;24_ "

    TEMP3_HI                ;25_Temporary 16-bit variable available throughout code execution. Do not use during serial port transactions.
    TEMP3_LO                ;26_ "  Do not use during serial port transactions.

    WRT_EEPROM_POS          ;27_EEPROM Writing Counter. Indicates what parameter to write in EEPROM

    PWM_CYCLE_CTR           ;28_This is the number of cycles that a normal tone will have

    PWM_CYCLE_ALM_CTR       ;29_Counter used When an alarm tone (long) is sent

    MAX_NUM_PWM_CYCLE       ;30_The maximum number of periodes (cycles) to reach before stopping the tone

    TONE_REQ_STAT           ;31_This is the Output Tone requested status register    
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Flags when a tone is requested for output 6. Requested (1)
                            ; 4-Flags when a tone is requested for output 5. Requested (1)                            
                            ; 3-Flags when a tone is requested for output 4. Requested (1)
                            ; 2-Flags when a tone is requested for output 3. Requested (1)
                            ; 1-Flags when a tone is requested for output 2. Requested (1)
                            ; 0-Flags when a tone is requested for output 1. Requested (1)

    ARM_DEBOUNCE_CTR        ;32_Register used to debounce the ARM button
    
    TMOUT_TMR0_CTR          ;33_Register used to count the number of 5 second cycles for the timeout tone

    TONES_STAT              ;34_This is a general purpose status flag register    
                            ; 7-Flag when a sequence completed tone is sent (used by remote monitoring tool)
                            ; 6-Flag when a sequence started tone is sent (used by remote monitoring tool)
                            ; 5-(not used)
                            ; 4-Flag when a feedback alarm tone is requested
                            ; 3-Flag when a sequence tone is currently sounding
                            ; 2-Flag when a timeout tone is currently sounding
                            ; 1-Flag when the timeout cycle is running
                            ; 0-Flag when a timeout tone cycle start is requested

    Ox_HIGH_LOW             ;35_High/Low output status byte
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 is in High (1) state or Low (0) state
                            ; 4-Output 5 is in High (1) state or Low (0) state
                            ; 3-Output 4 is in High (1) state or Low (0) state
                            ; 2-Output 3 is in High (1) state or Low (0) state
                            ; 1-Output 2 is in High (1) state or Low (0) state
                            ; 0-Output 1 is in High (1) state or Low (0) state

    ARM_DISARM_Ox_POS       ;36_Indicates what output is being armed or disarmed

	PTT_DEBOUNCE_CTR_H      ;37_Registers used to debounce the ARM button
	PTT_DEBOUNCE_CTR_L		;38_ "

    TX_RX_PRESW_FB_REQ_STAT ;39_This register is used to flag that Pre-switch Feedback detection is requested on a specific output
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 Pre-switch feedback detection requested. Requested (1)
                            ; 4-Output 5 Pre-switch feedback detection requested. Requested (1)
                            ; 3-Output 4 Pre-switch feedback detection requested. Requested (1)
                            ; 2-Output 3 Pre-switch feedback detection requested. Requested (1)
                            ; 1-Output 2 Pre-switch feedback detection requested. Requested (1)
                            ; 0-Output 1 Pre-switch feedback detection requested. Requested (1)

    TX_RX_PRESW_FB_PRES_STAT;40_This register is used to flag that Pre-switch Feedback detection is requested on a specific output
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 Pre-switch feedback detection requested. Requested (1)
                            ; 4-Output 5 Pre-switch feedback detection requested. Requested (1)
                            ; 3-Output 4 Pre-switch feedback detection requested. Requested (1)
                            ; 2-Output 3 Pre-switch feedback detection requested. Requested (1)
                            ; 1-Output 2 Pre-switch feedback detection requested. Requested (1)
                            ; 0-Output 1 Pre-switch feedback detection requested. Requested (1)

    TX_RX_PRESW_FB_ALM_STAT	;41_This register is used to flag that Pre-switch Feedback alarm is identified on a specific output
                            ; 7-(not used)
                            ; 6-(not used)
                            ; 5-Output 6 Pre-switch feedback alarm latched. Latched (1)
                            ; 4-Output 5 Pre-switch feedback alarm latched. Latched (1)
                            ; 3-Output 4 Pre-switch feedback alarm latched. Latched (1)
                            ; 2-Output 3 Pre-switch feedback alarm latched. Latched (1)
                            ; 1-Output 2 Pre-switch feedback alarm latched. Latched (1)
                            ; 0-Output 1 Pre-switch feedback alarm latched. Latched (1)

	AUTO_DISARM_TMR0_CTR	;42_Register used to count the number of 5 second cycles for the auto-disarm process

    SERIAL_TX_INT_FSR0L_SAVE;43_Register that allow to save FSR0L value after a TX interrupt was treated

    SERIAL_RX_INT_FSR0L_SAVE;44_Register that allow to save FSR0L value after a RX interrupt was treated

    CHKSUM                  ;45_Register used to calculate the checksum during RS-232 RX and Tx exchange

    ENDC

    CBLOCK    0x15A
    O1_LED_STAT             ;OUTPUT LEDs status and control register
    O2_LED_STAT             ; 7-(not used)
    O3_LED_STAT             ; 6-(not used)
    O4_LED_STAT             ; 5-(not used)
    O5_LED_STAT             ; 4-Output 1-6 LED to be set to Flashing
    O6_LED_STAT             ; 3-Output 1-6 LED to be set to Red
                            ; 2-Output 1-6 LED to be set to Amber
                            ; 1-Output 1-6 LED to be set to Green
                            ; 0-Output 1-6 LED to be set to OFF              
    ENDC

;USER VARIABLES AND SYSTEM VARIABLES THAT ARE UPDATED BY THE WINDOWS CONFIG. SOFTWARE

    CBLOCK    0x140
    Ox_LOGIC                ;variable used to store the 6 output logics. 0 means Ox has active low Tx logic. 1 means active high.                        
    O1_O2_DEL   ; 0x141     ;variable used to store the O1-to-O2 switching delay
    O2_O3_DEL               ;variable used to store the O2-to-O3 switching delay
    O3_O4_DEL               ;variable used to store the O3-to-O4 switching delay
    O4_O5_DEL               ;variable used to store the O4-to-O5 switching delay
    O5_O6_DEL               ;variable used to store the O5-to-O6 switching delay
    O6_O5_DEL   ; 0x146     ;variable used to store the O6-to-O5 switching delay    
    O5_O4_DEL               ;variable used to store the O5-to-O4 switching delay
    O4_O3_DEL               ;variable used to store the O4-to-O3 switching delay
    O3_O2_DEL               ;variable used to store the O3-to-O2 switching delay
    O2_O1_DEL               ;variable used to store the O2-to-O1 switching delay               
    LAST_ENABLED_Ox         ;variable used to indicate the last output that is enabled (ex. 00100000 means O6 is the last output enabled)
    PTT_USER_LOGIC          ;PTT logic: active low (0) active high (1)
    Ox_FB_ENABLED           ;variable used to indicate if feedback detection is enabled for the 6 outputs(ex. 00000110 means O2 and O3 have feedback enabled)
    TONES_ENABLED           ;Tone enabled register. Enabled (1), disabled (0)
                            ; 2-Feedback alarm tone
                            ; 1-Timeout tone
                            ; 0-Sequencing tones    
    TMOUT_TONE_DURATION     ;This is the Tx timeout duration (in minutes) used to compare to Timer0 for rollover

    ENDC                    ;########### Maximum 192 variables in the blocks above!############.


    CBLOCK    0x160
    SERIAL_RX_BUFF          ;Serial USART Receive Buffer memory. 48 positions reserved.
    ENDC

    CBLOCK    0x190
    SERIAL_TX_BUFF          ;Serial USART Transmit Buffer memory. 48 positions reserved.
    ENDC

;******************************************************************************************************
;Constant definitions

    ;Bit or Pin Positions
lf_eoc_received             EQU .1                  ;position of the new cycle of character reception is required
send_parameters             EQU .2                  ;position of the bit to request sending parameters information
tx_cycle_on                 EQU .3                  ;position of the tx cycle being performed flag
write_cycle_req             EQU .0                  ;bit position for flagging when a FLL parameter Write in EEPROM is req'd
setup_mode                  EQU .4                  ;bit position of SERIAL_STAT to flag when the setup mode using a PC is enabled
old_ptt_pin_state           EQU .2                  ;bit position in ARM_PTT_STAT1 to flag that PTT is in transition to enabled state.
ptt_in_pin                  EQU .6                  ;pin position for PTT input line on PORT B 
sys_armed                   EQU .0                  ;bit position in ARM_PTT_STAT1 for system arming state 
ptt_debounced_state         EQU .1                  ;bit position in ARM_PTT_STAT1 for debounced PTT state
arm_button_pin              EQU .7                  ;pin position for ARM button input line on PORT B
arm_butt_treated            EQU .3                  ;bit position in ARM_PTT_STAT1 to flag that the button has already been treated
ptt_treated                 EQU .2                  ;bit position in ARM_PTT_STAT2 to flag that the PTT has already been debounced.
arming_process_req          EQU .5                  ;bit position in ARM_PTT_STAT1 to flag that the arming process is requested.
disarming_process_req       EQU .6                  ;bit position in ARM_PTT_STAT1 to flag that the disarming process is requested.
sequencing_process_req      EQU .7                  ;bit position in ARM_PTT_STAT1 to flag that a sequencing process is requested      
arming_process_run          EQU .0                  ;bit position in ARM_PTT_STAT2 to flag that the arming process is happening.      
disarming_process_run       EQU .1                  ;bit position in ARM_PTT_STAT2 to flag that the disarming process is happening.      
seq_over                    EQU .0                  ;bit position in TX/RX_SEQUENCING_STAT1 to flag that the Tx sequencing is over 
fb_tmr_started              EQU .1                  ;bit position in TX/RX_SEQUENCING_STAT1 to flag that the feedback delay timer is started.
del_tmr_started             EQU .2                  ;bit position in TX/RX_SEQUENCING_STAT1 to flag that the waiting delay is started.
o1_done                     EQU .0                  ;bit position in TX_RX_OUTPUT_STAT to flag that output 1 Tx sequencing is done.
o2_done                     EQU .1                  ;bit position in TX_RX_OUTPUT_STAT to flag that output 1 Tx sequencing is done.
o3_done                     EQU .2                  ;bit position in TX_RX_OUTPUT_STAT to flag that output 1 Tx sequencing is done.
o4_done                     EQU .3                  ;bit position in TX_RX_OUTPUT_STAT to flag that output 1 Tx sequencing is done.
o5_done                     EQU .4                  ;bit position in TX_RX_OUTPUT_STAT to flag that output 1 Tx sequencing is done.
o6_done                     EQU .5                  ;bit position in TX_RX_OUTPUT_STAT to flag that output 1 Tx sequencing is done.
o1_switch_req               EQU .0                  ;bit position in TX_RX_SW_REQ_STAT to flag that output 1 Tx switch is requested.
o2_switch_req               EQU .1                  ;bit position in TX_RX_SW_REQ_STAT to flag that output 2 Tx switch is requested.
o3_switch_req               EQU .2                  ;bit position in TX_RX_SW_REQ_STAT to flag that output 3 Tx switch is requested.
o4_switch_req               EQU .3                  ;bit position in TX_RX_SW_REQ_STAT to flag that output 4 Tx switch is requested.
o5_switch_req               EQU .4                  ;bit position in TX_RX_SW_REQ_STAT to flag that output 5 Tx switch is requested.
o6_switch_req               EQU .5                  ;bit position in TX_RX_SW_REQ_STAT to flag that output 6 Tx switch is requested.
o1_tx_fb_fail_alm           EQU .0                  ;bit position in TX_FB_ALM_STAT to flag that output 1 failed to switch to Tx.
o2_tx_fb_fail_alm           EQU .1                  ;bit position in TX_FB_ALM_STAT to flag that output 2 failed to switch to Tx.
o3_tx_fb_fail_alm           EQU .2                  ;bit position in TX_FB_ALM_STAT to flag that output 3 failed to switch to Tx.
o4_tx_fb_fail_alm           EQU .3                  ;bit position in TX_FB_ALM_STAT to flag that output 4 failed to switch to Tx.
o5_tx_fb_fail_alm           EQU .4                  ;bit position in TX_FB_ALM_STAT to flag that output 5 failed to switch to Tx.
o6_tx_fb_fail_alm           EQU .5                  ;bit position in TX_FB_ALM_STAT to flag that output 6 failed to switch to Tx.
o1_rx_fb_fail_alm           EQU .0                  ;bit position in RX_FB_ALM_STAT to flag that output 1 failed to switch to Rx.
o2_rx_fb_fail_alm           EQU .1                  ;bit position in RX_FB_ALM_STAT to flag that output 2 failed to switch to Rx.
o3_rx_fb_fail_alm           EQU .2                  ;bit position in RX_FB_ALM_STAT to flag that output 3 failed to switch to Rx.
o4_rx_fb_fail_alm           EQU .3                  ;bit position in RX_FB_ALM_STAT to flag that output 4 failed to switch to Rx.
o5_rx_fb_fail_alm           EQU .4                  ;bit position in RX_FB_ALM_STAT to flag that output 5 failed to switch to Rx.
o6_rx_fb_fail_alm           EQU .5                  ;bit position in RX_FB_ALM_STAT to flag that output 6 failed to switch to Rx.
o1_fb_present               EQU .0                  ;bit position in TX_FB_PRESENT_STAT to flag that output 1 Ts switch feedback is detected.              
o2_fb_present               EQU .1                  ;bit position in TX_FB_PRESENT_STAT to flag that output 2 Ts switch feedback is detected.              
o3_fb_present               EQU .2                  ;bit position in TX_FB_PRESENT_STAT to flag that output 3 Ts switch feedback is detected.              
o4_fb_present               EQU .3                  ;bit position in TX_FB_PRESENT_STAT to flag that output 4 Ts switch feedback is detected.              
o5_fb_present               EQU .4                  ;bit position in TX_FB_PRESENT_STAT to flag that output 5 Ts switch feedback is detected.              
o6_fb_present               EQU .5                  ;bit position in TX_FB_PRESENT_STAT to flag that output 6 Ts switch feedback is detected.              
led_off                     EQU .0                  ;bit position in O1_LED_STAT and ARM_PTT_LED_STAT to signal to turn off the LED
led_green                   EQU .1                  ;bit position in O1_LED_STAT and ARM_PTT_LED_STAT to signal to make the LED green
led_amber                   EQU .2                  ;bit position in O1_LED_STAT and ARM_PTT_LED_STAT to signal to make the LED amber
led_red                     EQU .3                  ;bit position in O1_LED_STAT and ARM_PTT_LED_STAT to signal to make the LED red
led_flashing                EQU .4                  ;bit position in O1_LED_STAT and ARM_PTT_LED_STAT to signal to make the LED flash
arm_ptt_led_pin             EQU .7                  ;bit position in Port A for the Arm/PTT LED.
tmout_tone_cycl_req         EQU .0                  ;bit position in GENERAL_STAT1 to flag that a timeout tone cycle is required
tmout_tone_cycl_run         EQU .1                  ;bit position in GENERAL_STAT1 to flag that a timeout tone cycle is runing
tmout_tone_sounding         EQU .2                  ;bit position in GENERAL_STAT1 to flag that a timeout tone is currently sounding
seq_tone_sounding           EQU .3                  ;bit position in GENERAL_STAT1 to flag when a sequence tone is currnetly sounding
seq_tone_enabled            EQU .0                  ;bit position in TONES_ENABLED to flag when the sequence tones are enabled 
tmout_tone_enabled          EQU .1                  ;bit position in TONES_ENABLED to flag when the timeout tone is enabled 
fb_alm_tone_req             EQU .4                  ;bit position in TONES_ENABLED to flag when the fb alarm tone is required
fb_alm_tone_sounding        EQU .5                  ;bit position in TONES_ENABLED to flag when the fb alarm tone is sounding
fb_tone_enabled				EQU .2                  ;bit position in TONES_ENABLED to flag when the feedback tone is enabled 
ccp2_pin                    EQU .1                  ;pin position on PortC for the CCP2 (Tone output)
auto_disarm_alm_del_cnting	EQU .5					;bit position in GENERAL1_STAT to indicate that an alarm auto-disarm delay is counting
auto_disarm_tx_del_cnting	EQU .6					;bit position in GENERAL1_STAT to indicate that a TX auto-disarm delay is counting
remote_mon_req              EQU .5                  ;bit position in SERIAL_STAT to request a transmission of the Remote Monitoring Information
seq_end_tone_sounding       EQU .7                  ;bit position in TONES_STAT to signal to the remote monitoring tool that an end of sequence tone is sounding
seq_start_tone_sounding     EQU .6                  ;bit position in TONES_STAT to signal to the remote monitoring tool that an start of sequence tone is sounding

   ;Bit Masks
new_tx_cycle                EQU b'00000001'         ;mask to test if new cycle of character transmission is required

    ;Initialization Values
;W                          EQU .0                  ;Is the working Register flag in various commands (defined in .INC file)
F                           EQU .1                  ;File register flag in various commands
number_param_to_stor        EQU .16                 ;This is the number of parameters that are saved/restored in Data EEPROM, incl. addr. 0.                                                    
eecon1_data_eeprom_access   EQU b'00000000'         ;will initialize EECON1 register for a Data EEPROM access.
eecon1_prog_ee_access       EQU b'10000000'         ;will initialize EECON1 register for a Data EEPROM access.
firmware_version            EQU .2
max_arm_debounce_ctr        EQU .255
max_ptt_debounce_ctr_h      EQU .1					;This corresponds to a PTT debounce of ~160ms
max_ptt_debounce_ctr_l      EQU .170
fb_alm_auto_disarm_del      EQU .36                 ;number of 5 second slices (3 minutes) before auto-disarming after a feedback alarm.
tx_auto_disarm_del          EQU .132                ;number of 5 second slices (11 minutes) before auto-disarming when a transmission is too long.


;******************************************************************************
;Reset vector
; This code will start executing when a reset occurs.

        ORG    0x0000
        GOTO MAIN                                  ;go to start of main code

;******************************************************************************************************
;High priority interrupt vector
; This code will start executing when a high priority interrupt occurs or
; when any interrupt occurs if interrupt priorities are not enabled.

        ORG    0x0008
        BRA    HIGHINT                              ;go to high priority interrupt routine

;******************************************************************************************************
;LOWINT
;Low priority interrupt vector and routine
; This code will start executing when a low priority interrupt occurs.

        ORG    0x0018
LOWINT
        MOVFF STATUS,STATUS_TEMP                    ;save STATUS register
        MOVFF WREG,WREG_TEMP                        ;save working register
        MOVFF BSR,BSR_TEMP                          ;save BSR register
        CLRWDT                                      ;Repeatedly clears the WatchDog timer.
SERIAL_INT_CHECK
        BTFSS PIE1,TXIE                             ;Is TX interrupt enabled?
        BRA SERIAL_RX_CHECK                         ;No, go to test RX
        BTFSC PIR1,TXIF                             ;Yes, Did USART TX cause interrupt?
        BRA USART_TX_INT                            ;Yes, service it.
SERIAL_RX_CHECK
        BTFSS PIE1,RCIE                             ;Is RX interrupt enabled?
        BRA NO_VALID_INT                            ;No, go to other test
        BTFSC PIR1,RCIF                             ;Yes, Did USART RX cause interrupt?
        BRA USART_RX_INT                            ;Yes, service it.
NO_VALID_INT
        BRA LOWINT_EXIT                             ;no, branch to leave interrupt routine
USART_TX_INT
        BTFSS SERIAL_STAT,new_tx_cycle              ;verify if new character tx cycle initiated
        BRA NO_NU_CYCLE                             ;no, go to next validation
        LFSR FSR0,0x190                             ;load Serial Tx buffer's base address in FSR register
        BCF SERIAL_STAT,new_tx_cycle                ;yes, clear new Tx cycle flag
        BRA NU_TX_CYCLE								;branch to process a new Tx cycle
NO_NU_CYCLE
        MOVFF SERIAL_TX_INT_FSR0L_SAVE,FSR0L        ;Save TX FSR0L indirect addressing register value
NU_TX_CYCLE
        TSTFSZ INDF0                                ;is there a character in the buffer?
        BRA CHAR_PRESENT                            ;yes, go load it in tx buffer
        BCF SERIAL_STAT,tx_cycle_on					;nom clear the tx_cycle_on flag
        BCF PIE1,TXIE                               ;disable future TX interrupts 
        BCF PIR1,TXIF                               ;Clear interrupt request Flag.
        BRA LOWINT_EXIT_TX                          ;go to end of ISR, restore context, return        
CHAR_PRESENT
        MOVFF INDF0,TXREG                           ;transfer (indirect addressing) character to Tx register 
        CLRF POSTINC0                               ;clear character and increase indirect pointer
        BCF PIR1,TXIF                               ;Clear interrupt request Flag.
        BRA LOWINT_EXIT_TX                          ;go to end of ISR, restore context, return
USART_RX_INT    
        BCF PIR1,RCIF                               ;clear Rx char. available interrupt flag
        MOVLW 06h                                   ;Mask out unwanted bits
        ANDWF RCSTA,W                               ;Check for errors
        BTFSS STATUS,Z                              ;Was either error status bit set?
        BRA RXERROR                                 ;Found error, flag it
        TSTFSZ SERIAL_RX_BUFF                       ;is there a character in the first rx buffer cell?
        BRA NO_NU_RX_CYCLE                          ;yes, go read next character
        LFSR FSR0,0x160                             ;no, load Serial rx buffer's base address in FSR register
        BRA NU_RX_CYCLE								;Branch to process a new Rx cycle
NO_NU_RX_CYCLE
        MOVFF SERIAL_RX_INT_FSR0L_SAVE,FSR0L        ;Save RX FSR0L indirect addressing register value
NU_RX_CYCLE
        MOVFF RCREG,POSTINC0                        ;Get rx character from USART and increment indirect addr. pointer
        MOVLW h'8F'                                 ;Has end of Rx buffer been reached (address 0x17F)?
        CPFSLT FSR0L                                ;"
        BRA END_RX_CYCLE                            ;Yes, go end Rx cycle
        MOVLW .10                                   ;No, Load LF char in Wreg
        CPFSEQ RCREG                                ;Is character received LF
        BRA LOWINT_EXIT_RX                          ;No, go to end of ISR, restore context, return
END_RX_CYCLE
        BSF SERIAL_STAT,lf_eoc_received             ;Yes, lift the end of user command flag
        BRA LOWINT_EXIT                             ; go to end of ISR, restore context, return
RXERROR
		MOVF RCREG,W								;Discard received errored byte
        BCF RCSTA,CREN                              ;Clear receiver status
        BSF RCSTA,CREN                              ; "
LOWINT_EXIT_RX
        MOVFF FSR0L,SERIAL_RX_INT_FSR0L_SAVE        ;Recover previous RX FSR0L indirect addressing register value
        BRA LOWINT_EXIT                             ;Leave interrupt Routine
LOWINT_EXIT_TX
        MOVFF FSR0L,SERIAL_TX_INT_FSR0L_SAVE        ;Recover previous TX FSR0L indirect addressing register value
LOWINT_EXIT
        MOVFF BSR_TEMP,BSR                          ;Restore BSR register
        MOVFF WREG_TEMP,WREG                        ;Restore working register
        MOVFF STATUS_TEMP,STATUS                    ;Restore STATUS register
        RETFIE 0                                    ;This exits and re-enable low priority interrupts

;******************************************************************************************************
;HIGHINT 
;High priority interrupt routine
; no need to save status registers for a high priority interrupt routine

HIGHINT    
        INCF PWM_CYCLE_CTR,F                        ;Increment the dither counter.
        BCF PIR1,TMR2IF                             ;Clear TIMER2 interrupt request flag        
        RETFIE FAST                                 ;This restores the 3 status registers and exits interrupt routine.


;******************************************************************************************************
;MAIN
;Start of main program
;Initialization Area. This stuff is executed only once and at Reset time.

MAIN    
        MOVLB .1                                    ;Select RAM bank 1 for all variable accesses 
        CLRF INTCON                                 ;disable interrupts
        MOVLW b'10000000'                           ;enable interrupt priorities (high/low)
        MOVWF RCON                                  ; "
        MOVLW b'01110010'                           ;select internal oscillator and set it to 8MHz
        MOVWF OSCCON                                ; "
        MOVLW b'10000111'                           ;Set Timer0 to operate on internal clock with a prescaler value of 256.
        MOVWF T0CON
        MOVLW b'00110010'                           ;enable Timer2=PR2 interrupt, Rx interrupt, Tx Interrupt
        MOVWF PIE1                                  ; " 
        MOVLW b'00000001'                           ;enable CCP2 interrupt
        MOVWF PIE2                                  ; " 
        MOVLW b'00000010'                           ;assign low priority to CCP1 interrupt, Timer1 ovfl, USART Tx 
        MOVWF IPR1                                  ;  and high priority to CCP2=PR2 (PWM)
        MOVLW b'10111111'                            ;PORTC set as follows: All set as inputs (except bit 7) to turn off LEDs
        MOVWF TRISC                                 ; 7-Serial input
                                                    ; 6-Serial output
                                                    ; 5-Output LED 5
                                                    ; 4-Output LED 4                                 
                                                    ; 3-Output LED 3
                                                    ; 2-Output LED 2
                                                    ; 1-CCP2 PWM output. Reserved for Piezzo buzzer.
                                                    ; 0-Output LED 1
        BCF INTCON2,NOT_RBPU                        ;Enables pullup resistors on Port B.
        MOVLW 0x0F                                  ;Set RB<7:0> as
        MOVWF ADCON1                                ; digital I/O pins
        MOVLW b'11111111'                           ;PORTB set as follows:
        MOVWF TRISB                                 ; 7-Arm button input. Has internal pull-up.
                                                    ; 6-PTT input. Has internal pull-up.
                                                    ; 5-Feedback input for output 6. Has internal pull-up.                               
                                                    ; 4-Feedback input for output 5. Has internal pull-up.
                                                    ; 3-Feedback input for output 4. Has internal pull-up.
                                                    ; 2-Feedback input for output 3. Has internal pull-up.
                                                    ; 1-Feedback input for output 2. Has internal pull-up.
                                                    ; 0-Feedback input for output 1. Has internal pull-up.
        SETF PORTA                                  ;Put all ones on Port A outputs.
        BCF ADCON0,.0                               ;Disable ADC conversion
        MOVLW b'01111111'                           ;PORTA set as follows:    
        MOVWF TRISA                                 ; 7-ARM/PTT LED 
                                                    ; 6-Output LED 6
                                                    ; 5-Sequencing output 6 
                                                    ; 4-Sequencing output 5 (this one has an open drain output)                                  
                                                    ; 3-Sequencing output 4
                                                    ; 2-Sequencing output 3
                                                    ; 1-Sequencing output 2
                                                    ; 0-Sequencing output 1
STARTUP_DELAY                                       ;This 1 sec delay is added to let the supply voltage stabilize.
        MOVLW h'E1'                                 ;Load 1 second equivalent (500ns * 256 * (0x10000 - 0xE17B)) into timer0 value
        MOVWF TMR0H                                 ; "
        MOVLW h'7B'                                 ; "
        MOVWF TMR0L                                 ; "
        BCF INTCON,TMR0IF                           ;Clear the timer0 overflow interrupt flag
STARTUP_DELAY_LOOP  
        BTFSS INTCON,TMR0IF                         ;Is flag raised (timer0 overflow)?
        BRA STARTUP_DELAY_LOOP                      ;No, loop to test again
CONT_AFTER_DELAY                                    ;Yes, continue with initialization
        MOVLW b'00000011'                           ;set timer2 to prescaler div. by 16 
        MOVWF T2CON                                 ; but don't enable it yet
        MOVLW b'00001100'                           ;enables ccp2 in PWM mode
        MOVWF CCP2CON                               ; "
CLEAR_VARIABLES                                     ;Clear all variables, except the RS232 buffers and the EEPROM variables
        LFSR FSR1,0x100                             ;Load indirect addressing register with base address of the variables to clear
CLR_VARS_LOOP
        CLRF POSTINC1                               ;Clear variable and increase indirect addressing pointer
        MOVLW 0x40                                  ;Have it reached end of buffer addresses
        CPFSEQ FSR1L                                ; "
        BRA CLR_VARS_LOOP                           ;No, loop again. 
READ_EEPROM_PARAMS                                  ;Parameters are transfered from Data EEPROM to RAM variables
        LFSR FSR1,0x140                             ;Load indirect addressing register with base address of the parameter variables
        CLRF TEMP1_HI                               ;Clear temporary variable used as EEPROM address offset
READ_EEPROM_LOOP
        INCF TEMP1_HI,F                             ;Increment EEPROM address offset
        MOVF TEMP1_HI,W                             ;Load it in Wreg
        CALL READ_EEPROM_DATA                       ;Read data from EEPROM address 
        MOVWF POSTINC1                              ;Transfer EEPROM value to the parameter variable                          
        MOVLW number_param_to_stor                  ;Is this the last address (parameter) to read?
        CPFSLT TEMP1_HI                             ; "
        BRA CONT_INITIALIZE                         ;Yes leave EEPROM reading loop
        BRA READ_EEPROM_LOOP                        ;No, loop to read next EEPROM value
CONT_INITIALIZE
        MOVLW b'00100100'                           ;Enable USART TX, 8 bits, Async, High Speed
        MOVWF TXSTA                                 ; "
        MOVLW .207                                  ;Set baud rate to 2400 bps @ 8MHz CPU frequency
        MOVWF SPBRG                                 ; "
        MOVLW b'10010000'                           ;Enable Serial port, enable Rx, 8 bits on Rx, Async
        MOVWF RCSTA                                 ; "
        LFSR FSR1,0x160                             ;Load indirect addressing register with base address of the USART Receive buffer
CLR_RX_BUFFER_LOOP
        CLRF POSTINC1                               ;Clear Rx buffer cell and increase indirect addressing pointer
        MOVLW 0x90                                  ;Have it reached end of buffer addresses
        CPFSEQ FSR1L                                ; "
        BRA CLR_RX_BUFFER_LOOP                      ;No, loop again. 
CONFIG_VARIABLES        
        MOVLW b'00111111'							;Initialize the Sequence done Register
    	MOVWF TX_RX_SEQ_DONE                        ; "
       	BSF RX_SEQUENCING_STAT1,.0                  ;Sets the Rx sequencing over flag
        BCF SERIAL_STAT,setup_mode                  ;Disable the setup mode
INIT_OUTPUT_LOGIC_RX
        CLRF Ox_HIGH_LOW                            ;Clear the output high/low register
        MOVLW b'00000001'                           ;Initialize TEMP1_HI as bit position mask
        MOVWF TEMP1_HI                              ; "
INIT_LOGIC_LOOP
        MOVF TEMP1_HI,W                             ;Transfer bit position mask to Wreg
        ANDWF Ox_LOGIC,W                            ;Mask Ox logic high/low bit
        BZ SET_LOGIC_Ox_Tx_LOW                      ;Is Ox logic high/low bit 0? Yes, go set low logic on Tx for that output
SET_LOGIC_Ox_Tx_HIGH
        COMF TEMP1_HI,W                             ;Complement Ox logic high/low bit mask and transfer it into Wreg
        ANDWF Ox_HIGH_LOW,F                         ;Clear the corresponding Ox bit in the output high/low register
        BRA PREP_LOGIC_LOOP                         ;Go prepare the looping for another Output                        
SET_LOGIC_Ox_Tx_LOW
        MOVF TEMP1_HI,W                             ;Move Ox logic high/low bit mask into Wreg
        IORWF Ox_HIGH_LOW,F                         ;Set the corresponding Ox bit in the output high/low register
PREP_LOGIC_LOOP
        MOVLW b'00100000'                           ;Load the last output bit mask into Wreg
        CPFSLT TEMP1_HI                             ;Is the last output treated?
        BRA INIT_LOGIC_COMPLETE                     ;Yes, leave logic initialization loop
        RLNCF TEMP1_HI,F                            ;No, shift the bit position mask to the next Ox 
        BRA INIT_LOGIC_LOOP                         ;Loop to treat next Ox
INIT_LOGIC_COMPLETE
        BSF WDTCON,0                                ;Enable WatchDog Timer
        MOVLW 0x46                                  ;load initial (50%) eight duty cycle MSb's in CCP2 register        
        MOVWF CCPR2L                                ; "
        BCF CCP2CON,4                               ;clear two duty cycle LSb's in CCP register
        BCF CCP2CON,5                               ; "
        CLRF PIR1                                   ;Clear all interrupt request flags
        CLRF PIR2                                   ; "
        BCF PIR1,RCIF                               ;Clear RCIF Interrupt Flag
        BSF INTCON,GIEH                             ;enable high priority interrupts
        BSF INTCON,GIEL                             ;enable low priority interrupts

;******************************************************************************************************
;TR_SEQ_MAIN 
;This is the main loop that repeats indefinitely

TR_SEQ_MAIN
        CLRWDT                                      ;Clear the WatchDog timer.
        CALL READ_ARM_BUTTON                        ;Read, debounce and interpret the Arm/Disarm button
        CALL CTRL_ARMING                            ;Control the Output Arming process
        CALL CTRL_DISARMING                         ;Control the Output Disarming process
        CALL READ_PTT                               ;Read and debounce PTT line
        CALL CTRL_TX_SEQUENCING                     ;Control the Output Sequencing in Transmit mode
        CALL CTRL_RX_SEQUENCING                     ;Control the Output Sequencing in Receive mode
        CLRWDT                                      ;Clear the WatchDog timer.
        CALL CTRL_OUTPUTS                           ;Control the Output pins
        CALL READ_PRESW_FEEDBACK                    ;Read Pre-switch output feedback
        CALL READ_FEEDBACK                          ;Read the Output feedback
		CALL CTRL_TMR0								;Updates Timer0 and increases various counters
        CALL CTRL_TIMEOUT_TONE                      ;Control the Timeout Tone process
        CALL CTRL_FB_ALM_TONE                       ;Control the feedback alarm tone
        CALL CTRL_SEQ_TONES                         ;Control the Sequencing Tones process
		CALL CTRL_FB_ALARM_AUTO_DISARM				;Control a delayed disarming when a feedback alarm is present
        CLRWDT                                      ;Clear the WatchDog timer.
		CALL CTRL_TX_AUTO_DISARM					;Controls the auto-disarm when a transmission lasts too long
        CALL CTRL_ARM_PTT_LED                       ;Control the ARM/PTT LED
        CALL CTRL_OUTPUT_LEDS                       ;Control the 6 Output LEDs
        CALL CTRL_PARAM_INFO_TX                     ;Control contents of the parameter line sent over serial port
        CALL CTRL_PARAM_INFO_RX                     ;Receives commands and parameters sent over serial port
        CALL CTRL_PARAM_UPD_EEPROM                  ;Control Writing in Flash EEPROM of parameters       
        GOTO TR_SEQ_MAIN                            ;Loop back to beginning

;******************************************************************************************************
;READ_ARM_BUTTON
;This routine detects the arm button action and requests an arming or disarming process

READ_ARM_BUTTON
        BTFSC SERIAL_STAT,setup_mode                ;Is the setup mode enabled?
        BRA CLEAR_BUTTON_FLAGS                      ;Yes, cancel ARM button reading and leave routine
        BTFSC PORTB,arm_button_pin                  ;No, Is Arm button pushed (pin low)?                    
        BRA CLEAR_BUTTON_FLAGS                      ;No, go clear button flags and leave routine
        BTFSC ARM_PTT_STAT1,arm_butt_treated        ;Yes, Is the arm button already treated flag raised?
        BRA READ_ARM_RET                            ;Yes, leave routine
TEST_ARM_DEBOUNCING
        MOVLW max_arm_debounce_ctr                  ;No, load the maximum value of debounce counter into Wreg
        CPFSLT ARM_DEBOUNCE_CTR                     ;Is the debounce counter less than the maximum
        BRA TEST_ARM_BUT_AGAIN                      ;No, Go validate the arm button again
        INCF ARM_DEBOUNCE_CTR,F                     ;Yes, increment the debounce counter
        BRA READ_ARM_RET                            ;Leave routine
TEST_ARM_BUT_AGAIN
        BTFSS PORTB,arm_button_pin                  ;Is Arm button still pushed (pin low)?                    
        BRA ARM_BUTT_VALIDATED                      ;Yes, go update Arm button debounced state
        BRA CLEAR_BUTTON_FLAGS                      ;No, go clear button flags and leave routine
ARM_BUTT_VALIDATED
        CLRF ARM_DEBOUNCE_CTR                       ;Clear the debounce counter
        BSF ARM_PTT_STAT1,arm_butt_treated          ;Raise the arm button already treated flag
        BTFSC ARM_PTT_STAT1,sys_armed               ;Check if system is armed?
        BRA DO_DISARMING                            ;Yes, go disarm system 
DO_ARMING
        BTFSC ARM_PTT_STAT1,ptt_debounced_state     ;No, is the PTT active?
        BRA READ_ARM_RET                            ;Yes, leave routine
        BTFSS RX_SEQUENCING_STAT1,seq_over          ;No, is the Rx sequencing process over
        BRA READ_ARM_RET                            ;No, leave routine
        BSF ARM_PTT_STAT1,arming_process_req        ;Raise the arming process requested flag 
        BRA READ_ARM_RET                            ;Leave routine
DO_DISARMING
        BCF ARM_PTT_STAT1,sys_armed                 ;Change system armed flag to disarmed 
        BSF ARM_PTT_STAT1,disarming_process_req     ;Raise the disarming process requested flag 
        BRA READ_ARM_RET                            ;Leave routine
CLEAR_BUTTON_FLAGS
        BCF ARM_PTT_STAT1,arm_butt_treated          ;Clear the Arm button already treated flag
READ_ARM_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_ARMING
;This routine controls the arming process when requested by the arm button. It enables outputs starting at
;the last enabled outputs and ending at output #1. It inserts proper sequence delays between outputs activation.


CTRL_ARMING
        BTFSC SERIAL_STAT,setup_mode                ;Is the setup mode enabled?
        BRA CTRL_ARM_RET                            ;Yes, leave routine
        BTFSC ARM_PTT_STAT2,arming_process_run      ;Is the arming process currently running?
        BRA CONTINUE_ARMING                         ;Yes, continue to treat it
        BTFSS ARM_PTT_STAT1,arming_process_req      ;No, is the arming process requested flag raised?
        BRA CTRL_ARM_RET                            ;No, leave routine
ARMING_START
        MOVFF LAST_ENABLED_Ox,ARM_DISARM_Ox_POS     ;Yes, transfer the last enabled output bit into the arming output position pointer
        BCF ARM_PTT_STAT1,arming_process_req        ;Clear the arming process required flag
        BSF ARM_PTT_STAT2,arming_process_run        ;Set the arming process running flag
    	MOVF PORTA,W								;Put all outputs to '0' in preparation for the output arm process
		ANDLW b'11000000'							; "	
		MOVWF PORTA									; "
        LFSR FSR1,0x146                             ;Load the Rx sequence delays base address into the indirect addressing register
        MOVLW b'00100000'							;Initialize TEMP1_HI to output-6 position
        MOVWF TEMP1_HI								; "
ARM_PREP_LOOP
        CPFSLT LAST_ENABLED_Ox                      ;Is the last enabled Ox register less than the temporary pointer
        BRA ARM_Ox                                  ;No, Go arm the first output
        RRNCF TEMP1_HI,F                            ;Yes, roll right the temporary pointer
        MOVF TEMP1_HI,W                             ;Move this temporary pointer to Wreg 
        INCF FSR1L,F                                ;Increment the indirect pointer by one location
        BRA ARM_PREP_LOOP                           ;Loop to next iteration
CONTINUE_ARMING
   	    BTFSS INTCON,TMR0IF                         ;Is the Timer 0 count rollover flag set?              
        BRA CTRL_ARM_RET                            ;No, leave routine
ARM_Ox
        MOVFF Ox_LOGIC,TEMP1_LO                     ;Yes, transfer the output logic variable into TEMP1_LO
        MOVF ARM_DISARM_Ox_POS,W                    ;Transfer the currently treated Ox into Wreg 
        ANDWF TEMP1_LO,F                            ;Mask the current Ox logic bit
        COMF TEMP1_LO,W                             ;Complement the current Ox logic bit register and load into Wreg
        ANDWF PORTA,F                               ;Toggle PortA pin corresponding to current Ox accordingly  
        ANDWF Ox_HIGH_LOW,F                         ;Also Toggle the current Ox output pin state into the high/low register
        COMF ARM_DISARM_Ox_POS,W                    ;Complement the currently treated Ox and transfer result into Wreg       
		ANDLW b'01111111'							;But first prepare bits 7 and 8 of port A mode so that they are not changed when AND'ing
        ANDWF TRISA,F                               ;Set the current output Port A pin in output mode
        MOVLW b'00000001'                           ;Is last output treated?
        CPFSGT ARM_DISARM_Ox_POS                    ; "
        BRA END_ARMING                              ;Yes, go end the arming process
        RRNCF ARM_DISARM_Ox_POS,F                   ;No, shift the currently treated Ox bit right to treat the next Ox on the next pass
        CALL READ_DELAY_TABLE                       ;Read the corresponding output sequence delay
    	INCF FSR1L,F                                ;Increment the indirect pointer by one location
        MOVFF TEMP2_HI,TMR0H                        ;Transfer these values into Timer0 high latch      
        MOVFF TEMP2_LO,TMR0L                        ;Transfer these values into Timer0 low latch    
   	    BCF INTCON,TMR0IF                           ;Clear the Timer 0 count rollover flag               
        BRA CTRL_ARM_RET                            ;Leave routine
END_ARMING
        CLRF TX_RX_OUTPUT_STAT                      ;Clear the Tx/Rx status register
        BSF ARM_PTT_STAT1,sys_armed                 ;Yes, change system armed flag to armed 
        BCF ARM_PTT_STAT2,arming_process_run        ;Clear the arming process running flag
        CLRF TX_FB_ALM_STAT                         ;Clear the Tx feedback alarm status register
        CLRF RX_FB_ALM_STAT                         ;Clear the Rx feedback alarm status register
        CLRF TX_RX_PRESW_FB_ALM_STAT                ;Clear the Rx pre-switch feedback alarm status register
CTRL_ARM_RET                                        
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_DISARMING
;This routine controls the disarming process when requested by the arm button. It enables outputs starting at
;output #1 and ending with output #6. It inserts proper sequence delays between outputs de-activation.

CTRL_DISARMING
        BTFSC SERIAL_STAT,setup_mode                ;Is the setup mode enabled?
        BRA CTRL_DISARM_RET                         ;Yes, leave routine
        BTFSC ARM_PTT_STAT2,disarming_process_run   ;Is the disarming process running?
        BRA CONTINUE_DISARMING                      ;Yes, continue to treat disarming
        BTFSS ARM_PTT_STAT1,disarming_process_req   ;Is the disarming process requested flag set?
        BRA CTRL_DISARM_RET                         ;No, leave routine
DISARMING_START
        MOVLW b'00000001'                           ;Yes, Initialize the disarming output position pointer witht the first output position to treat
        MOVWF ARM_DISARM_Ox_POS                     ; "
        BCF ARM_PTT_STAT1,disarming_process_req     ;Clear the disarming process required flag
        BSF ARM_PTT_STAT2,disarming_process_run     ;Set the disarming process running flag
        LFSR FSR1,0x141                             ;Load the Tx sequence delays base address into the indirect addressing register
        BRA DISARM_Ox                               ;Go disarm the first output
CONTINUE_DISARMING
   	    BTFSS INTCON,TMR0IF                         ;Is the Timer 0 count rollover flag set?
        BRA CTRL_DISARM_RET                         ;No, leave routine
DISARM_Ox
        MOVF ARM_DISARM_Ox_POS,W                    ;Yes, Transfer the output position bit into Wreg
        IORWF TRISA,F                               ;Set the corresponding Port A output pin as an input
        MOVF LAST_ENABLED_Ox,W                      ;Is the last output treated?
        CPFSLT ARM_DISARM_Ox_POS                    ; "
        BRA END_DISARMING                           ;Yes, go end the disarming process
        RLNCF ARM_DISARM_Ox_POS,F                   ;No, roll left the output position bit to treat the next output on the next pass
        CALL READ_DELAY_TABLE                       ;Read the corresponding output sequence delay
        INCF FSR1L,F                                ;Increment the indirect pointer by one location
        MOVFF TEMP2_HI,TMR0H                        ;Transfer these values into Timer0 high latch      
        MOVFF TEMP2_LO,TMR0L                        ;Transfer these values into Timer0 low latch    
   	    BCF INTCON,TMR0IF                           ;Clear the Timer 0 count rollover flag               
        BRA CTRL_DISARM_RET                         ;Leave routine
END_DISARMING										;Portion of code that makes sure that the output LEDs show the right status after disarming regardless of when disarm button is pressed.
    	MOVF Ox_LOGIC,W                             ;Load Output logic register into Wreg
		BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Is the PTT active?
    	BRA DISARM_PTT_LOW							;No, Disarm while PTT is inactive
DISARM_PTT_HIGH
    	ANDLW b'00111111'							;Yes, isolate the 6 output logic bits
    	MOVWF Ox_HIGH_LOW							;Transfet these into the output high/low status byte								
    	BSF TX_SEQUENCING_STAT1,seq_over			;Mark the Tx sequence as over
    	MOVLW b'00111111'							;Load Tx/Rx output states into Wreg
    	BRA DISARM_PTT_CONT							;Go continue to disarm
DISARM_PTT_LOW
    	COMF Ox_LOGIC,W								;Complement the output logic register
    	ANDLW b'00111111'							;Isolate the complemented output logic bits
    	MOVWF Ox_HIGH_LOW							;Transfet these into the output high/low status byte
    	BSF RX_SEQUENCING_STAT1,seq_over			;Mark the Rx sequence as over
    	MOVLW b'00000000'							;Load Tx/Rx output states into Wreg
DISARM_PTT_CONT
    	MOVWF TX_RX_OUTPUT_STAT						;Transfer these into the Tx/Rx output status register
        BCF ARM_PTT_STAT2,disarming_process_run     ;Clear the disarming process running flag
        BCF T2CON,TMR2ON                            ;Disable Timer2 (Turns off any tone)               
        BSF TRISC,ccp2_pin                          ;Put the CCP2 pin in input mode (disables)
        BCF TONES_STAT,tmout_tone_cycl_run          ;Clear the timeout tone cycle running flag
        BCF TONES_STAT,tmout_tone_cycl_req          ;Clear the timeout tone cycle required flag
        BCF TONES_STAT,tmout_tone_sounding          ;Clear the timeout tone sounding flag
        BCF TONES_STAT,fb_alm_tone_req              ;Clear the feedback alarm tone requested flag
        BCF TONES_STAT,fb_alm_tone_sounding         ;Clear the feedback alarm tone sounding flag
        BCF TONES_STAT,seq_tone_sounding            ;Clear the sequencing tone sounding flag
      	MOVLW b'00111111'							;Mark the Sequence as completed
      	MOVWF TX_RX_SEQ_DONE						; "
        CLRF TX_FB_ALM_STAT                         ;Clear the Tx feedback alarm status register
        CLRF RX_FB_ALM_STAT                         ;Clear the Rx feedback alarm status register
      	CLRF TX_RX_PRESW_FB_ALM_STAT				;Clear the pre-switch feedback alarm status register
		BCF GENERAL1_STAT,auto_disarm_alm_del_cnting;Clear the alarm auto disarm delay counting flag
		BCF GENERAL1_STAT,auto_disarm_tx_del_cnting ;Clear the Tx auto disarm delay counting flag
		CLRF AUTO_DISARM_TMR0_CTR					;Clear the timer0 Counter
CTRL_DISARM_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
; READ_PTT
;This routine reads and debounces the sequencer PTT line.

READ_PTT
        MOVFF PORTB,TEMP1_HI                        ;Take a snapshot of the PTT pin by copying PORTB into TEMP1_HI
        BTFSS ARM_PTT_STAT1,old_ptt_pin_state       ;Is previous PTT pin state high?
        BRA TEST_PTT_OLD_LOW                        ;No, it is low. Go test when previous PTT state is low
TEST_PTT_OLD_HIGH
        BTFSS TEMP1_HI,ptt_in_pin                   ;Yes, is the current PTT pin state in high?
        BRA PTT_IN_TRANSITION                       ;No, go flag a PTT pin transition
        BTFSS ARM_PTT_STAT2,ptt_treated             ;Yes, is the PTT already treated flag set?
        BRA OLD_NEW_PTT_SAME                        ;No, go validate debounced PTT state
        BRA READ_PTT_RET                            ;Yes, leave routine
TEST_PTT_OLD_LOW
        BTFSC TEMP1_HI,ptt_in_pin                   ;Is the current PTT pin state in low?                 
        BRA PTT_IN_TRANSITION                       ;No, go validate PTT in transition state
        BTFSS ARM_PTT_STAT2,ptt_treated             ;Yes, is the PTT already treated flag set?
        BRA OLD_NEW_PTT_SAME                        ;No, go validate debounced PTT state
        BRA READ_PTT_RET                            ;Yes, leave routine
OLD_NEW_PTT_SAME
        INFSNZ PTT_DEBOUNCE_CTR_L                   ;Increment the PTT debouncing counter
        INCF PTT_DEBOUNCE_CTR_H                     ; "
TEST_DEBNC_CNTR
        MOVLW max_ptt_debounce_ctr_h                ;Load the maximum value high of debounce counter into Wreg
        CPFSGT PTT_DEBOUNCE_CTR_H                   ;Is the debounce counter high less than the maximum
        BRA READ_PTT_RET                            ;Yes, leave routine
        MOVLW max_ptt_debounce_ctr_l                ;Load the maximum value low of debounce counter into Wreg
        CPFSGT PTT_DEBOUNCE_CTR_L                   ;Is the debounce counter low less than the maximum
        BRA READ_PTT_RET                            ;Yes, leave routine
        BSF ARM_PTT_STAT2,ptt_treated               ;No, set the PTT treated flag
        TSTFSZ PTT_USER_LOGIC                       ;Is PTT logic set to active low?
        BRA PTT_LOGIC_HI                            ;No, Go treat active high PTT logic
        BRA PTT_LOGIC_LO                            ;Yes, Go treat active low PTT logic
PTT_LOGIC_LO
        BTFSS TEMP1_HI,ptt_in_pin                   ;Active low PTT logic. Is PTT pin  high (inverse of real PTT line)?                    
        BRA PTT_DISABLED                            ;No, Go set the PTT state to disabled
        BRA PTT_ENABLED                             ;Yes, go enable PTT
PTT_LOGIC_HI
        BTFSC TEMP1_HI,ptt_in_pin                   ;Active high PTT logic. Is PTT pin low (inverse of real PTT line)?                    
        BRA PTT_DISABLED                            ;No, Go set the PTT state to disabled
PTT_ENABLED
        BTFSC ARM_PTT_STAT1,ptt_debounced_state     ;Yes, Is the debounced PTT already active
        BRA READ_PTT_RET                            ;Yes, leave routine
        BSF ARM_PTT_STAT1,ptt_debounced_state       ;No, Set the debounced PTT state flag to enabled
        BSF ARM_PTT_STAT1,sequencing_process_req    ;Set the new sequencing process requested flag
        BCF TX_SEQUENCING_STAT1,seq_over            ;Clear the Tx Sequencing over flag
        BRA READ_PTT_RET                            ;leave routine
PTT_DISABLED
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Yes, Is the debounced PTT already inactive
        BRA READ_PTT_RET                            ;Yes, leave routine
        BCF ARM_PTT_STAT1,ptt_debounced_state       ;No, Clear the debounced PTT state flag to disabled
        BSF ARM_PTT_STAT1,sequencing_process_req    ;Set the new sequencing process requested flag
        BCF RX_SEQUENCING_STAT1,seq_over            ;Clear the rx Sequencing over flag
        BRA READ_PTT_RET                            ;leave routine
PTT_IN_TRANSITION
        CLRF PTT_DEBOUNCE_CTR_H                     ;Clear the PTT debouncing counter
		CLRF PTT_DEBOUNCE_CTR_L                     ; "
        BTFSS TEMP1_HI,ptt_in_pin                   ;Is the current PTT pin state in high?                 
        BCF ARM_PTT_STAT1,old_ptt_pin_state         ;No, set the previous PTT state flag to low
        BTFSC TEMP1_HI,ptt_in_pin                   ;Yes, Is the current PTT pin state in low?                 
        BSF ARM_PTT_STAT1,old_ptt_pin_state         ;No, set the previous PTT state flag to high                 
        BCF ARM_PTT_STAT2,ptt_treated               ;Clear the PTT already treated flag
READ_PTT_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_TX_SEQUENCING
;This procedure controls the transfer from Rx to Tx by switching outputs one at a time while checking
;feedback for switching confirmation and inserting a user-defined delay between outputs. 

CTRL_TX_SEQUENCING
        BTFSC SERIAL_STAT,setup_mode                ;Is the setup mode enabled?
        BRA CTRL_TX_SEQ_RET                         ;Yes, leave routine
        BTFSC ARM_PTT_STAT2,arming_process_run      ;No, is the arming process running flag set?
        BRA CTRL_TX_SEQ_RET                         ;Yes, leave routine
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;No, Is the debounced PTT state flag raised
        BRA CTRL_TX_SEQ_RET                         ;No, leave routine
        BTFSC TX_SEQUENCING_STAT1,seq_over          ;Yes, is the Tx sequencing over?
        BRA CTRL_TX_SEQ_RET                         ;Yes, leave routine                  
        TSTFSZ TX_FB_ALM_STAT                       ;No, Did any of the feedback points failed?
        BRA CTRL_TX_SEQ_RET                         ;Yes, leave routine
    	TSTFSZ RX_FB_ALM_STAT                       ;No, Did any of the feedback points failed?
    	BRA CTRL_TX_SEQ_RET                         ;Yes, leave routine
    	TSTFSZ TX_RX_PRESW_FB_ALM_STAT              ;No, Did any of the pre-switchfeedback points failed?
    	BRA CTRL_TX_SEQ_RET                         ;Yes, leave routine
        BTFSS ARM_PTT_STAT1,sequencing_process_req  ;Is this a new sequencing process requested flag?
        BRA CHECK_Ox_TX_DONE                        ;No, go check the outputs
    	MOVFF TX_RX_OUTPUT_STAT,TX_RX_SEQ_DONE      ;Transfer the Tx/Rx Status byte into the sequence done register
        BCF ARM_PTT_STAT1,sequencing_process_req    ;Clear the new sequencing process requested flag
        CLRF TX_FB_PRESENT_STAT                     ;Clear the Tx feedback present register
		BCF TX_SEQUENCING_STAT1,fb_tmr_started		;Clear the Tx feedback timer started flag
        BCF RX_SEQUENCING_STAT1,fb_tmr_started		;Clear the Rx feedback timer started flag
        BCF TX_SEQUENCING_STAT1,del_tmr_started  	;clear the Tx delay timer started flag
    	CLRF TX_RX_PRESW_FB_PRES_STAT				;Clear the TX/RX Pre-switch Feedback Present Status register
    	CLRF TX_RX_PRESW_FB_REQ_STAT				;Clear the TX/RX Pre-switch Feedback request Status register
    	CLRF RX_FB_ALM_STAT                       	;Clear the Rx feedback alarm points
        MOVLW b'00000001'                           ;Initialize the Tx output position pointer to output 1
        MOVWF TX_Ox_POS_PTR                         ; "
        LFSR FSR1,0x141                             ;load Tx Delay registers base address into indirect addressing pointer        
CHECK_Ox_TX_DONE
        MOVF TX_RX_SEQ_DONE,W                       ;Move the sequencing done register into Wreg
        ANDWF TX_Ox_POS_PTR,W                       ;Mask the current output's sequencing done bit. Is current output switch completed?
        BNZ PREP_TX_LOOP                            ;Yes, go test next output
CONT_Ox_CHECK_DONE
        BTFSC TX_SEQUENCING_STAT1,del_tmr_started   ;No, delay timer started? 
        BRA CHECK_Ox_Oy_TX_DELAY                    ;Yes, go test timer for delay expiry
        BTFSC TX_SEQUENCING_STAT1,fb_tmr_started    ;No, feedback timer started? 
        BRA CHECK_Ox_TX_FB_DELAY                    ;Yes, go test timer for feedback or feedback delay expiry
    	BTFSS ARM_PTT_STAT1,sys_armed               ;No, check if system is armed
    	BRA NO_TX_PRESWITCH_CHECK                   ;No, don't validate Pre-switch feedback
    	MOVF TX_RX_PRESW_FB_REQ_STAT,W				;Yes, is a Pre-switch feedback test requested for currently treated output?
    	ANDWF TX_Ox_POS_PTR,W                       ; "  
    	BZ TX_PRESW_REQ_FB_CHECK					;No, go request for a feedback check
    	MOVF TX_RX_PRESW_FB_PRES_STAT,W				;Yes, is the feedback checked and present for the currently treated output?
    	ANDWF TX_Ox_POS_PTR,W                       ; "
    	BZ TX_FB_SET_ALM							;No, go set the alarm for that output
    	CLRF TX_RX_PRESW_FB_PRES_STAT				;Yes, clear the TX/RX Pre-switch Feedback Present Status register
    	CLRF TX_RX_PRESW_FB_REQ_STAT				;Clear the TX/RX Pre-switch Feedback request Status register
NO_TX_PRESWITCH_CHECK
        MOVFF TX_Ox_POS_PTR,TX_RX_SW_REQ_STAT   	;Request to switch o1 to Tx
        CALL START_FB_TIMER                         ;Start the feedback timer
        BSF TX_SEQUENCING_STAT1,fb_tmr_started      ;Set the feedback timer started flag
        BRA CTRL_TX_SEQ_RET                         ;Leave routine                          
TX_PRESW_REQ_FB_CHECK
    	MOVFF TX_Ox_POS_PTR,TX_RX_PRESW_FB_REQ_STAT ;Request to check pre-switch feedback on current output
    	BRA CTRL_TX_SEQ_RET 						;Leave routine
CHECK_Ox_Oy_TX_DELAY 
     	BTFSS INTCON,TMR0IF                         ;Is the Timer 0 count rollover flag set?
        BRA CTRL_TX_SEQ_RET                         ;No, Leave routine 
        BCF TX_SEQUENCING_STAT1,del_tmr_started     ;Yes, clear the delay timer started flag
        BRA CTRL_TX_SEQ_RET                         ;Leave routine      
CHECK_Ox_TX_FB_DELAY
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA Ox_TX_SWITCH_DONE                       ;No, don't validate feedback
        MOVF TX_Ox_POS_PTR,W                        ;Yes, Is feedback sensing enabled for this output?
        ANDWF Ox_FB_ENABLED,W                       ; "
        BZ Ox_TX_SWITCH_DONE                        ;No, don't validate feedback
        MOVF TX_FB_PRESENT_STAT,W                   ;Yes, mask feedback present bit for current output    
        ANDWF TX_Ox_POS_PTR,W                       ;Is feed back detected for current output?
        BNZ Ox_TX_SWITCH_DONE                       ;Yes, go mark switching of output 1 as done
        BTFSS INTCON,TMR0IF                         ;No, Is the Timer 0 count rollover flag set?
        BRA CTRL_TX_SEQ_RET                         ;No, leave routine
TX_FB_SET_ALM
        MOVF TX_Ox_POS_PTR,W                        ;Yes, Transfer Tx output position pointer into Wreg
        IORWF TX_FB_ALM_STAT,F                      ;Set the feedback alarm for the current output
        BSF TONES_STAT,fb_alm_tone_req              ;set the feedback alarm tone requested flag
        TSTFSZ TX_RX_PRESW_FB_REQ_STAT				;Are there any pre-switch feedback requests active?
        MOVFF TX_RX_PRESW_FB_REQ_STAT,TX_RX_PRESW_FB_ALM_STAT ;Yes, Transfer the request bit into an alarm bit
        CLRF TX_RX_PRESW_FB_PRES_STAT				;Clear the TX/RX Pre-switch Feedback Present Status register
        CLRF TX_RX_PRESW_FB_REQ_STAT				;Clear the TX/RX Pre-switch Feedback request Status register
        BRA CTRL_TX_SEQ_RET                         ;leave routine      
Ox_TX_SWITCH_DONE
        MOVF TX_Ox_POS_PTR,W                        ;Transfer Tx output position pointer into Wreg                        
        IORWF TX_RX_SEQ_DONE,F                      ;Set flag for current output Tx switch completed
        MOVF LAST_ENABLED_Ox,W                      ;Is last output treated
        CPFSLT TX_Ox_POS_PTR                        ; "
        BRA TX_SEQ_OVER                             ;Yes, go end the Tx sequence
        BCF TX_SEQUENCING_STAT1,fb_tmr_started      ;No, Clear the feedback timer started flag
        CALL READ_DELAY_TABLE                       ;Go read the corresponding output delay from the table
        MOVFF TEMP2_HI,TMR0H                        ;Transfer these values into Timer0 high latch      
        MOVFF TEMP2_LO,TMR0L                        ;Transfer these values into Timer0 low latch    
   	    BCF INTCON,TMR0IF                           ;Clear the Timer 0 count rollover flag               
        BSF TX_SEQUENCING_STAT1,del_tmr_started     ;Set the delay timer flag
        BRA PREP_TX_LOOP                            ;Go prepare next pass and leave routine      
TX_SEQ_OVER
        CLRF TX_RX_FB_REQ_STAT                      ;Clear the feedback request register
        CLRF TX_FB_ALM_STAT                         ;Clear the Tx output feedback alarm status register
        CLRF TX_FB_PRESENT_STAT                     ;Clear the feedback present register
        BSF TX_SEQUENCING_STAT1,seq_over            ;Set the Tx Sequencing over flag
        BCF TX_SEQUENCING_STAT1,fb_tmr_started      ;Clear the feedback timer started flag  
        BSF TONES_STAT,tmout_tone_cycl_req          ;Request a start of the the timeout timer
        BRA CTRL_TX_SEQ_RET                         ;Leave routine      
PREP_TX_LOOP
        RLNCF TX_Ox_POS_PTR,F                       ;shift left the output position pointer bit for next pass.
    	INCF FSR1L,F                                ;Increment the indirect pointer by one location
CTRL_TX_SEQ_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_RX_SEQUENCING
;This procedure controls the transfer from Tx to Rx by switching outputs one at a time while checking
;feedback for switching confirmation and inserting a user-defined delay between outputs. 

CTRL_RX_SEQUENCING
        BTFSC SERIAL_STAT,setup_mode                ;Is the setup mode enabled?
        BRA CTRL_RX_SEQ_RET                         ;Yes, leave routine
        BTFSC ARM_PTT_STAT1,ptt_debounced_state     ;Is the debounced PTT state flag cleared
        BRA CTRL_RX_SEQ_RET                         ;No, leave routine
        BTFSC RX_SEQUENCING_STAT1,seq_over          ;Yes, is the Rx sequencing over?
        BRA CTRL_RX_SEQ_RET                         ;Yes, leave routine                  
        TSTFSZ RX_FB_ALM_STAT                       ;No, Did any of the feedback points failed?
        BRA CTRL_RX_SEQ_RET                         ;Yes, leave routine
      	TSTFSZ TX_FB_ALM_STAT                       ;No, Did any of the feedback points failed?
      	BRA CTRL_RX_SEQ_RET                         ;Yes, leave routine
        BTFSS ARM_PTT_STAT1,sequencing_process_req  ;Is this a new sequencing process requested flag?
        BRA CHECK_Ox_RX_DONE                        ;No, go check the outputs
        COMF TX_RX_OUTPUT_STAT,W                    ;Yes, read the invert of the the Rx output state register
        ANDLW b'00111111'                           ;isolate the 6 output bits
        MOVWF TX_RX_SEQ_DONE                        ;Transfer the inversion into the sequence done register
        BCF ARM_PTT_STAT1,sequencing_process_req    ;Clear the new sequencing process requested flag
        BCF RX_SEQUENCING_STAT1,seq_over         	;Clear the rx Sequencing over flag
        CLRF RX_FB_PRESENT_STAT                     ;Clear the rx feedback present register
		BCF RX_SEQUENCING_STAT1,fb_tmr_started		;Clear the feedback timer started flag
        BCF RX_SEQUENCING_STAT1,del_tmr_started  	;clear the delay timer started flag
	    BCF TX_SEQUENCING_STAT1,fb_tmr_started		;Clear the feedback timer started flag
        CLRF TX_RX_PRESW_FB_PRES_STAT				;Clear the TX/RX Pre-switch Feedback Present Status register
        CLRF TX_RX_PRESW_FB_REQ_STAT				;Clear the TX/RX Pre-switch Feedback request Status register
        MOVFF LAST_ENABLED_Ox,RX_Ox_POS_PTR         ;Initialize the Tx output position pointer to the last enabled output
        LFSR FSR1,0x146                             ;load Rx Delay registers base address into indirect addressing pointer        
        MOVLW b'00100000'                           ;Initialize TEMP1_HI as the Tx output position pointer to output 6
        MOVWF TEMP1_HI                              ; " 
RX_SEQ_PREP_LOOP
        CPFSLT RX_Ox_POS_PTR                        ;Is the current output pointer less than the temporary pointer
        BRA CHECK_Ox_RX_DONE                        ;No, go check Ox output
        RRNCF TEMP1_HI,F                            ;Yes, roll right the temporary pointer
        MOVF TEMP1_HI,W                             ;Move this temporary pointer to Wreg 
        INCF FSR1L,F                                ;Increment the indirect pointer by one location
        BRA RX_SEQ_PREP_LOOP                        ;Loop to next iteration
CHECK_Ox_RX_DONE
        MOVF TX_RX_SEQ_DONE,W                       ;Move the sequencing done register into Wreg
        ANDWF RX_Ox_POS_PTR,W                       ;Mask the current output's sequencing done bit. Is current output switch completed?
        BNZ PREP_RX_LOOP                            ;Yes, go test next output
        BTFSC RX_SEQUENCING_STAT1,del_tmr_started   ;No, delay timer started? 
        BRA CHECK_Ox_Oy_RX_DELAY                    ;Yes, go test timer for delay expiry
        BTFSC RX_SEQUENCING_STAT1,fb_tmr_started    ;No, feedback timer started? 
        BRA CHECK_Ox_RX_FB_DELAY                    ;Yes, go test timer for feedback or feedback delay expiry
    	BTFSS ARM_PTT_STAT1,sys_armed               ;No, Check if system is armed
    	BRA NO_RX_PRESWITCH_CHECK                   ;No, don't validate Pre-switch feedback
    	MOVF TX_RX_PRESW_FB_REQ_STAT,W				;Yes, Is a Pre-switch feedback test requested for currently treated output?
    	ANDWF RX_Ox_POS_PTR,W                       ; "  
    	BZ RX_PRESW_REQ_FB_CHECK					;No, go request for a feedback check
    	MOVF TX_RX_PRESW_FB_PRES_STAT,W				;Yes, is the feedback checked and present for the currently treated output?
    	ANDWF RX_Ox_POS_PTR,W                       ; "
    	BZ RX_PRESW_FB_SET_ALM						;No, go set the alarm for that output
    	CLRF TX_RX_PRESW_FB_PRES_STAT				;Yes, clear the TX/RX Pre-switch Feedback Present Status register
    	CLRF TX_RX_PRESW_FB_REQ_STAT				;Clear the TX/RX Pre-switch Feedback request Status register
NO_RX_PRESWITCH_CHECK
        MOVFF RX_Ox_POS_PTR,TX_RX_SW_REQ_STAT   	;Request to switch o1 to Rx
        CALL START_FB_TIMER                         ;Start the feedback timer
        BSF RX_SEQUENCING_STAT1,fb_tmr_started      ;Set the feedback timer started flag
        BRA CTRL_RX_SEQ_RET                         ;Leave routine                          
RX_PRESW_REQ_FB_CHECK
    	MOVFF RX_Ox_POS_PTR,TX_RX_PRESW_FB_REQ_STAT ;Request to check pre-switch feedback for the current output
    	BRA CTRL_RX_SEQ_RET 						;Leave routine
CHECK_Ox_Oy_RX_DELAY 
     	BTFSS INTCON,TMR0IF                         ;Is the Timer 0 count rollover flag set?
        BRA CTRL_RX_SEQ_RET                         ;No, Leave routine 
        BCF RX_SEQUENCING_STAT1,del_tmr_started     ;Yes, clear the delay timer started flag
        BRA CTRL_RX_SEQ_RET                         ;Leave routine      
CHECK_Ox_RX_FB_DELAY
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA Ox_RX_SWITCH_DONE                       ;No, don't validate feedback
        MOVF RX_Ox_POS_PTR,W                        ;Yes, is feedback sensing enabled for this output?
        ANDWF Ox_FB_ENABLED,W                       ; "
        BZ Ox_RX_SWITCH_DONE                   		;No, don't validate feedback
        MOVF RX_FB_PRESENT_STAT,W                   ;Yes, validate feedback    
        ANDWF RX_Ox_POS_PTR,W                       ;Is feed back detected for output 1?
        BNZ Ox_RX_SWITCH_DONE                       ;Yes, go mark switching of output 1 as done
        BTFSS INTCON,TMR0IF                         ;No, Is the Timer 0 count rollover flag set?
        BRA CTRL_RX_SEQ_RET                         ;No, leave routine
		BRA RX_FB_SET_ALM							;Yes, go set feedback alarm
RX_PRESW_FB_SET_ALM
    	CLRF TX_RX_PRESW_FB_PRES_STAT				;Clear the TX/RX Pre-switch Feedback Present Status register
    	CLRF TX_RX_PRESW_FB_REQ_STAT				;Clear the TX/RX Pre-switch Feedback request Status register
RX_FB_SET_ALM
        MOVF RX_Ox_POS_PTR,W                        ;Yes, Raise the feedback alarm flag for that output.
        IORWF RX_FB_ALM_STAT,F                      ; "
        BSF TONES_STAT,fb_alm_tone_req              ;Set the feedback alarm tone requested flag
        BRA CTRL_RX_SEQ_RET                         ;Leave routine      
Ox_RX_SWITCH_DONE                        
        MOVF RX_Ox_POS_PTR,W                        ;Set flag for current output Rx switch completed
        IORWF TX_RX_SEQ_DONE,F                      ; "
        MOVLW b'00000001'                           ;Is the last output treated
        CPFSGT RX_Ox_POS_PTR                        ; "
        BRA RX_SEQ_OVER                             ;Yes, go terminate the Rx sequence
        BCF RX_SEQUENCING_STAT1,fb_tmr_started      ;No, clear the feedback timer started flag
        CALL READ_DELAY_TABLE                       ;Load the Rx output delay form the lookup table
        MOVFF TEMP2_HI,TMR0H                        ;Transfer these values into Timer0 high latch 
        MOVFF TEMP2_LO,TMR0L                        ;Transfer these values into Timer0 low latch
   	    BCF INTCON,TMR0IF                           ;Clear the Timer 0 count rollover flag               
        BSF RX_SEQUENCING_STAT1,del_tmr_started     ;Set the delay timer flag
        BRA PREP_RX_LOOP                            ;Go prepare next pass and leave routine 
RX_SEQ_OVER
        CLRF TX_RX_FB_REQ_STAT                      ;Clear the feedback request register
        CLRF RX_FB_ALM_STAT                         ;Clear the Rx output feedback status register
        CLRF RX_FB_PRESENT_STAT                     ;Clear the feedback present register
        BSF RX_SEQUENCING_STAT1,seq_over            ;Set the rx Sequencing over flag
        BCF RX_SEQUENCING_STAT1,fb_tmr_started      ;Clear the feedback timer started flag  
        BRA CTRL_RX_SEQ_RET                         ;Leave routine      
PREP_RX_LOOP
        RRNCF RX_Ox_POS_PTR,F                       ;shift right the output position pointer bit for next pass.
        INCF FSR1L,F                                ;Increment the indirect pointer by one location
CTRL_RX_SEQ_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;START_FB_TIMER
;This sub-routine is called by the Tx and Rx sequencing codes to initialize a waiting period for feedback  
;detection. Timer 0 is used.

START_FB_TIMER
    	MOVLW h'F8'                                 ;Load Timer0 H register with the proper value for a 200 milli-second count 
    	MOVWF TMR0H                                 ; "
     	MOVLW h'5F'                                 ;Load Timer0 L register with the proper value for a 200 milli-second count
     	MOVWF TMR0L                                 ; "
     	BCF INTCON,TMR0IF                           ;Clear the Timer 0 count rollover flag               
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_OUTPUTS
;This piece of code control the switching of the 6 outputs and initiates a switching feedback request.

CTRL_OUTPUTS
        BTFSC ARM_PTT_STAT2,arming_process_run      ;Is the arming process currently running?
        BRA CTRL_OUTPUTS_RET                        ;Yes, leave routine
        MOVF TX_RX_SW_REQ_STAT,W                    ;No, load the switching request register into Wreg
        BZ CTRL_OUTPUTS_RET                         ;Any switching request? No, go leave routine
SWITCH_TX_RX_OUTS
        XORWF PORTA,F                               ;Yes, update the Port A outputs
        XORWF TX_RX_OUTPUT_STAT,F                   ;Update the Tx/Rx status register
        XORWF Ox_HIGH_LOW,F                         ;Update the Output high/low state register              
        MOVFF TX_RX_SW_REQ_STAT,TX_RX_FB_REQ_STAT   ;Request for feedback check by setting the proper bit in the feedback request register
CTRL_OUTPUTS_RET
        CLRF TX_RX_SW_REQ_STAT                      ;Clear the switching request register
        RETURN                                      ;Leave routine

;******************************************************************************************************
;READ_FEEDBACK
;This portion of code manages the post-switching feedback detection and issue a switching tone request.

READ_FEEDBACK
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed?
        BRA READ_FB_RET                             ;No, leave routine
     	TSTFSZ RX_FB_ALM_STAT                       ;No, Did any of the Rx feedback points failed?
     	BRA READ_FB_RET                         	;Yes, leave routine
     	TSTFSZ TX_FB_ALM_STAT                       ;No, Did any of the Tx feedback points failed?
     	BRA READ_FB_RET                         	;Yes, leave routine
        TSTFSZ TX_RX_FB_REQ_STAT                    ;Yes, is any Output feedback detection requested?      
        BRA CHECK_FB_ENABLED                        ;Yes, go test feedback condition
        BRA READ_FB_RET                             ;No, leave routine
CHECK_FB_ENABLED
        MOVF TX_RX_FB_REQ_STAT,W                    ;Yes, Is feedback sensing enabled for this output?
        ANDWF Ox_FB_ENABLED,W                       ; "
        BZ END_FB_PRESENT                           ;No, don't validate feedback        
CHECK_FB_Ox            
        MOVF TX_RX_FB_REQ_STAT,W                    ;Find what output logic the current output is set to.
        ANDWF Ox_LOGIC,W                            ; "
        BNZ FB_Ox_POS_LOGIC                         ;Is output logic positive (active high)? Yes, go test for positive logic
FB_Ox_NEG_LOGIC
        BTFSS TX_SEQUENCING_STAT1,fb_tmr_started    ;No, is the Tx feedback timer started?
        BRA FB_Ox_NEG_RX                            ;No, Go test Rx, negative logic.
FB_Ox_NEG_TX
        MOVF TX_RX_FB_REQ_STAT,W                    ;Yes, test for Tx, negative logic.
        ANDWF PORTB,W                               ; "
        BTFSC STATUS,Z                              ;Detect if feedback is present on input pin of the treated output. is Port B, bit 0 low?
        BRA READ_FB_RET                             ;No, leave routine
        MOVF TX_RX_FB_REQ_STAT,W                    ;Yes, set the Output 1 Tx feedback present bit. 
        IORWF TX_FB_PRESENT_STAT,F                  ; " 
        COMF TX_RX_FB_REQ_STAT,W                    ;Clear the feedback alarm flag for that output.
        ANDWF TX_FB_ALM_STAT,F                      ; "
        BRA END_FB_PRESENT                          ;Go request for a sequence tone and leave routine
FB_Ox_NEG_RX                                        
        MOVF TX_RX_FB_REQ_STAT,W                    ;Test for Rx, negative logic.
        ANDWF PORTB,W                               ; " 
        BTFSS STATUS,Z                              ;Detect if feedback is present on input pin of the treated output. Is Port B, bit 0 high?
        BRA READ_FB_RET                             ;No, leave routine
        MOVF TX_RX_FB_REQ_STAT,W                    ;Yes, set the Output 1 Rx feedback present bit. 
        IORWF RX_FB_PRESENT_STAT,F                  ; "
        COMF TX_RX_FB_REQ_STAT,W                    ;Clear the feedback alarm flag for that output.
        ANDWF RX_FB_ALM_STAT,F                      ; "
        BRA END_FB_PRESENT                          ;Go request for a sequence tone and leave routine
FB_Ox_POS_LOGIC
        BTFSS TX_SEQUENCING_STAT1,fb_tmr_started    ;Is the Tx feedback timer started?
        BRA FB_Ox_POS_RX                            ;No, Rx feedback timer started. Go test Rx, positive logic.
FB_Ox_POS_TX
        MOVF TX_RX_FB_REQ_STAT,W                    ;Test for Tx, positive logic.
        ANDWF PORTB,W                               ; "                              
        BTFSS STATUS,Z                              ;Detect if feedback is present on input pin of the treated output. Is Port B, bit 0 low?
        BRA READ_FB_RET                             ;No, leave routine
        MOVF TX_RX_FB_REQ_STAT,W                    ;Yes, set the Output 1 Tx feedback present bit. 
        IORWF TX_FB_PRESENT_STAT,F                  ; "
        COMF TX_RX_FB_REQ_STAT,W                    ;Clear the feedback alarm flag for that output.
        ANDWF TX_FB_ALM_STAT,F                      ; "
        BRA END_FB_PRESENT                          ;Go request for a sequence tone and leave routine
FB_Ox_POS_RX
        MOVF TX_RX_FB_REQ_STAT,W                    ;Test for Rx, positive logic.
        ANDWF PORTB,W                               ; "
        BTFSC STATUS,Z                              ;Detect if feedback is present on input pin of the treated output.  Is Port B, bit 0 high?
        BRA READ_FB_RET                             ;No, leave routine
        MOVF TX_RX_FB_REQ_STAT,W                    ;Yes, set the Output 1 Rx feedback present bit. 
        IORWF RX_FB_PRESENT_STAT,F                  ; "
        COMF TX_RX_FB_REQ_STAT,W                    ;Clear the feedback alarm flag for that output.                   
        ANDWF RX_FB_ALM_STAT,F                      ; "
END_FB_PRESENT
        MOVFF TX_RX_FB_REQ_STAT,TONE_REQ_STAT       ;Feedback present. Set the sequence tone requested flag for that output.
        CLRF TX_RX_FB_REQ_STAT                      ;Clear the feedback requested flag register.
READ_FB_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;READ_PRESW_FEEDBACK
;This portion of code manages the pre-switching feedback detection.

READ_PRESW_FEEDBACK
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed?
        BRA READ_PRESW_FB_RET                       ;No, leave routine
     	TSTFSZ RX_FB_ALM_STAT                       ;No, Did any of the Rx feedback points failed?
     	BRA READ_PRESW_FB_RET                       ;Yes, leave routine
     	TSTFSZ TX_FB_ALM_STAT                       ;No, Did any of the Tx feedback points failed?
     	BRA READ_PRESW_FB_RET                       ;Yes, leave routine
        TSTFSZ TX_RX_PRESW_FB_REQ_STAT              ;Yes, is any Output pre-switch feedback detection requested?      
        BRA CHECK_PRESW_FB_ENABLED                  ;Yes, go test feedback condition
        BRA READ_PRESW_FB_RET                       ;No, leave routine
CHECK_PRESW_FB_ENABLED
        MOVF TX_RX_PRESW_FB_REQ_STAT,W              ;Yes, Is feedback sensing enabled for this output?
        ANDWF Ox_FB_ENABLED,W                       ; "
        BZ SW_FB_PRESENT                    		;No, don't validate feedback        
CHECK_PRESW_FB_Ox            
        MOVF TX_RX_PRESW_FB_REQ_STAT,W              ;Find what output logic the current output is set to.
        ANDWF Ox_LOGIC,W                            ; "
        BNZ PRESW_FB_Ox_POS_LOGIC                   ;Is output logic positive (active high)? Yes, go test for positive logic
PRESW_FB_Ox_NEG_LOGIC
        MOVF TX_RX_PRESW_FB_REQ_STAT,W              ;Yes, test for Tx, negative logic.
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Is the debounced PTT already active
        BRA PRESW_FB_Ox_NEG_RX                      ;No, Go test Rx, negative logic.
PRESW_FB_Ox_NEG_TX
        ANDWF PORTB,W                               ;Detect if feedback is present on input pin of the treated output. is Port B, bit 0 low?
        BTFSS STATUS,Z                              ; "
        BRA READ_PRESW_FB_RET                       ;No, leave routine
		BRA SW_FB_PRESENT							;Yes, go treat with FB present
PRESW_FB_Ox_NEG_RX                                        
        ANDWF PORTB,W                               ;Detect if feedback is present on input pin of the treated output. Is Port B, bit 0 high? 
        BTFSC STATUS,Z								; "                              
        BRA READ_PRESW_FB_RET                       ;No, leave routine
		BRA SW_FB_PRESENT							;Yes, go treat with FB present
PRESW_FB_Ox_POS_LOGIC
        MOVF TX_RX_PRESW_FB_REQ_STAT,W              ;Test for Tx, negative logic.
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Is the debounced PTT already active
        BRA PRESW_FB_Ox_POS_RX                      ;No, Rx feedback timer started. Go test Rx, positive logic.
PRESW_FB_Ox_POS_TX
        ANDWF PORTB,W                               ;Detect if feedback is present on input pin of the treated output. Is Port B, bit 0 low?                              
        BTFSC STATUS,Z                              ; "
        BRA READ_PRESW_FB_RET                       ;No, leave routine
		BRA SW_FB_PRESENT							;Yes, go treat with FB present
PRESW_FB_Ox_POS_RX
        ANDWF PORTB,W                               ;Detect if feedback is present on input pin of the treated output.  Is Port B, bit 0 high?
        BTFSS STATUS,Z                              ; "
        BRA READ_PRESW_FB_RET                       ;No, leave routine
SW_FB_PRESENT
        MOVFF TX_RX_PRESW_FB_REQ_STAT,TX_RX_PRESW_FB_PRES_STAT;Feedback present. Set the pre-switch feedback present for that output.
        COMF TX_RX_PRESW_FB_REQ_STAT,W              ;Clear the feedback alarm flag for that output.                   
        ANDWF RX_FB_ALM_STAT,F                      ; "
READ_PRESW_FB_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_TMR0
;Timer 0 is shared by several functions. This piece of code treats Timer 0 for the Transmit (11 minutes of transmission)
;auto-disarm function and for the feedback alarm (3 minutes after a feedback alarm).

CTRL_TMR0
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA CTRL_TMR0_RET                           ;No, leave routine	
        BTFSC GENERAL1_STAT,auto_disarm_alm_del_cnting;No, is the feedback alarm auto-disarm delay counting?
        BRA TREAT_ALM_OR_TX                         ;Yes, go treat timer0
        BTFSC GENERAL1_STAT,auto_disarm_tx_del_cnting;No, is the auto disarm delay counting?
        BRA TREAT_ALM_OR_TX                         ;Yes, go treat timer0
        BRA CTRL_TMR0_RET                           ;No, leave routine	
TREAT_ALM_OR_TX
        BTFSS INTCON,TMR0IF                         ;Is the timer 0 rollover flag set?
        BRA CTRL_TMR0_RET                           ;No, leave routine	
        INCF TMOUT_TMR0_CTR,F                       ;Yes, increment the Timeout counter
        INCF AUTO_DISARM_TMR0_CTR,F                 ;Yes, increment the auto-disarm counter
        MOVLW 0x67                                  ;Yes, initialize timer 0 for a 5 second rollover delay
        MOVWF TMR0H                                 ; "
        MOVLW 0x69                                  ; "
        MOVWF TMR0L                                 ; "
   	    BCF INTCON,TMR0IF                           ;Clear the Timer 0 count rollover flag               
CTRL_TMR0_RET
		RETURN                                      ;Leave Routine

;******************************************************************************************************
;CTRL_TIMEOUT_TONE
;This code controls the Timeout Timer tone function. The delay before the sounding of the alarm is set by 
;the user via the Windows program.

CTRL_TIMEOUT_TONE
        BTFSS TONES_ENABLED,tmout_tone_enabled      ;Is the timeout tone feature enabled?
        BRA CTRL_TIMEOUT_TONE_RET                   ;No, leave routine   
        BTFSS ARM_PTT_STAT1,sys_armed               ;Yes, check if system is armed
        BRA CTRL_TIMEOUT_TONE_RET                   ;No, leave routine
        MOVF TX_FB_ALM_STAT,W                       ;Yes, test to see if there is any feedback alarm
        IORWF RX_FB_ALM_STAT,W                      ; "
        BNZ CTRL_TIMEOUT_TONE_RET                   ;Yes, leave routine
        BTFSC TONES_STAT,tmout_tone_cycl_req        ;No, is a timeout tone cycle requested?
        BRA START_TIMOUT_CYCLE                      ;Yes, go start a timeout tone cycle
        BTFSS TONES_STAT,tmout_tone_cycl_run        ;No, Is a timeout tone cycle currently running?
        BRA CTRL_TIMEOUT_TONE_RET                   ;No, leave routine
        BTFSC ARM_PTT_STAT1,ptt_debounced_state     ;Yes, is the system PTT in Tx mode?
        BRA TST_TMOUT_EXPIRED                       ;Yes, go test if timeout is expired
CLEAR_TIMOUT_PROC
        BTFSC TONES_STAT,tmout_tone_sounding        ;No, is the timeout tone currently sounding?
        BCF T2CON,TMR2ON                            ;Yes, Disable Timer2                
        BSF TRISC,ccp2_pin                          ;Put the CCP2 pin in input mode (disables)
        BCF TONES_STAT,tmout_tone_cycl_run          ;Clear the timeout tone cycle running flag
        BCF TONES_STAT,tmout_tone_sounding          ;Clear the timeout tone sounding flag
        BRA CTRL_TIMEOUT_TONE_RET                   ;Leave routine
START_TIMOUT_CYCLE                                  
        BSF TONES_STAT,tmout_tone_cycl_run          ;Set the timeout tone cycle running flag
        BCF TONES_STAT,tmout_tone_cycl_req          ;Clear the timeout tone cycle requested flag
        CLRF TMOUT_TMR0_CTR                         ;Clear the timeout timer 0 rollover counter register
        MOVLW 0x67                                  ;Initialize timer 0 for a 5 second rollover delay
        MOVWF TMR0H                                 ; "
        MOVLW 0x69                                  ; "
        MOVWF TMR0L                                 ; "
        BRA CTRL_TIMEOUT_TONE_RET                   ;Leave routine
TST_TMOUT_EXPIRED
        BTFSC TONES_STAT,tmout_tone_sounding        ;Is the timeout tone sounding?
        BRA CTRL_TIMEOUT_TONE_RET                   ;Yes, leave routine
        INCF TMOUT_TONE_DURATION,W                  ;Increment the timeout tone duration register and it into Wreg
        MULLW .6                                    ;Multiply it by 6 to get 30 secs slices since each timer 0 rollover is 5 secs.
        MOVF PRODL,W                                ;Load multiplication result into Wreg
        CPFSLT TMOUT_TMR0_CTR                       ;Is the rollover counter less than the timeout delay
        BRA START_TMOUT_TONE                        ;No, go sound timeout tone
        BRA CTRL_TIMEOUT_TONE_RET                   ;Leave routine
START_TMOUT_TONE
        MOVLW 0x33                                  ;Load timer 2 with the proper timeout tone pitch on the PWM
        MOVWF PR2                                   ; "
        MOVLW 0x1A                                  ;Load timer 2 for a 50% duty cycle on the PWM
        MOVWF CCPR2L                                ; "
        BCF PIR1,TMR2IF                             ;Clear Timer2 interrupt flag
        CLRF TMR2                                   ;Clear the timer 2 counter
        BSF T2CON,TMR2ON                            ;Enable Timer2                
        BCF TRISC,ccp2_pin                          ;Put the CCP2 pin in output mode (enables)
        BSF TONES_STAT,tmout_tone_sounding          ;Set the timeout tone sounding flag
CTRL_TIMEOUT_TONE_RET
        RETURN                                      ;Leave routine


;******************************************************************************************************
;CTRL_FB_ALM_TONE
;This routine controls the emission of the feedback alarm tone. The feature can be disabled within the Windows
;tool.

CTRL_FB_ALM_TONE
        BTFSS TONES_ENABLED,fb_tone_enabled         ;Is the feedback tone feature enabled?
        BRA CTL_FB_TONE_RET		                    ;No, leave routine   
        BTFSC TONES_STAT,fb_alm_tone_sounding       ;Is the feedback alarm tone sounding?
        BRA CONTINUE_ALM_TONE                       ;Yes, go treat sounding alarm
        BTFSC TONES_STAT,fb_alm_tone_req            ;No, is a feedback tone requested?
        BRA START_ALM_TONE                          ;Yes, go start a feedback tone
        BRA CTL_FB_TONE_RET                         ;No, leave routine
START_ALM_TONE
        CLRF PWM_CYCLE_CTR                          ;Clear the PWM cycle counter
        CLRF PWM_CYCLE_ALM_CTR                      ;Clear the alarm tone cycle counter
        MOVLW 0x33                                  ;Load the alarm tone pitch and duty cycle into CCP2 period register
        MOVWF PR2                                   ; "
        MOVLW 0x1A                                  ;Load the alarm tone duty cycle into CCP2 duty cycle register
        MOVWF CCPR2L                                ; "
        BCF TONES_STAT,fb_alm_tone_req              ;Clear the feedback alarm tone requested flag
        MOVLW .16                                   ;Load the maximun number of cycles for the alarm tone
        MOVWF MAX_NUM_PWM_CYCLE                     ; "
        BCF PIR1,TMR2IF                             ;Clear Timer2 interrupt flag
        CLRF TMR2                                   ;Clear the Timer2 counter
        BSF T2CON,TMR2ON                            ;Enable Timer2                
        BCF TRISC,ccp2_pin                          ;Put the CCP2 pin in output mode (enables)
        BSF TONES_STAT,fb_alm_tone_sounding         ;Set the alarm tone sounding flag
        BRA CTL_FB_TONE_RET                         ;Leave routine
CONTINUE_ALM_TONE
        MOVF RX_FB_ALM_STAT,W                       ;Load the Rx feedback alarm status register into Wreg
        IORWF TX_FB_ALM_STAT,W                      ;Or it with the Tx feedback alarm status register and load result into Wreg
        BZ END_ALM_TONE                             ;Any feedback alarm? No, go end alarm tone
        MOVF MAX_NUM_PWM_CYCLE,W                    ;Yes, transfer maximum number of cycles into Wreg
        CPFSEQ PWM_CYCLE_CTR                        ;Is the PWM cycle counter at the maximum number of cycles?
        BRA CTL_FB_TONE_RET                         ;No, leave routine
        MOVLW .200                                  ;Yes, has the alarm tone cycle counter reached the limit?
        CPFSLT PWM_CYCLE_ALM_CTR                    ; "
        BRA END_ALM_TONE                            ;Yes, go end the alarm tone
        INCF PWM_CYCLE_ALM_CTR,F                    ;No, increment the alarm tone cycle counter
        CLRF PWM_CYCLE_CTR                          ;Clear the pwm cycle counter
        BRA CTL_FB_TONE_RET                         ;Leave routine
END_ALM_TONE
        BCF PIR1,TMR2IF                             ;Clear Timer2 interrupt flag
        BCF T2CON,TMR2ON                            ;Enable Timer2                
        BSF TRISC,ccp2_pin                          ;Put the CCP2 pin in input mode (disables)
        BCF TONES_STAT,fb_alm_tone_sounding         ;Clear the feedback alarm tone sounding flag
CTL_FB_TONE_RET
        RETURN

;******************************************************************************************************
;CTRL_SEQ_TONES
;This routine controls the emission of the switching tones. The last tone lasts longer than the other switching
;tones to indicate to the user that the sequence is over. The feature can be disabled within the Windows
;tool.

CTRL_SEQ_TONES
        BTFSS TONES_ENABLED,seq_tone_enabled        ;Is the sequence tone feature enabled?
        BRA CTRL_TONES_RET                          ;No, leave routine   
        BTFSC ARM_PTT_STAT1,sys_armed               ;Yes, check if system is armed
        BRA TONES_SYS_IS_ARMED                      ;Yes, go treat the sequence tone
        CLRF TONE_REQ_STAT                          ;Clear the Tone requested flags
        BRA CTRL_TONES_RET                          ;Leave routine
TONES_SYS_IS_ARMED
        BTFSC TONES_STAT,fb_alm_tone_sounding       ;Is the feedback alarm tone sounding?
        BRA CTRL_TONES_RET                          ;Yes, leave routine
        BTFSC TONES_STAT,seq_tone_sounding          ;Is the sequence tone sounding?
        BRA CONTINUE_TONE                           ;Yes, go treat the tone
        TSTFSZ TONE_REQ_STAT                        ;No, is there a request for a tone seuqence?
        BRA START_TONE                              ;Yes, go start tone
        BRA CTRL_TONES_RET                          ;No, leave routine
CONTINUE_TONE
        MOVF MAX_NUM_PWM_CYCLE,W                    ;Is the maximum number of PWM cycles reached?
        CPFSEQ PWM_CYCLE_CTR                        ; "
        BRA CTRL_TONES_RET                          ;No, leave routine
END_TONE
        CLRF TONE_REQ_STAT                          ;Yes, Clear the requested tone flags
        BCF PIR1,TMR2IF                             ;Clear Timer2 interrupt flag
        BCF T2CON,TMR2ON                            ;Disable Timer2                
        BSF TRISC,ccp2_pin                          ;Put the CCP2 pin in input mode (disables)
        BCF TONES_STAT,seq_tone_sounding            ;Clear the sequence tone warning flag
        BRA CTRL_TONES_RET                          ;Leave routine
START_TONE
        CLRF PWM_CYCLE_CTR                          ;Clear the PWM cycle counter
        CLRF PWM_CYCLE_ALM_CTR                      ;Clear the PWM alarm counter
        MOVLW high Ox_TONE_PERIOD_LOCN              ;Load the tone period table lookup table high address location in the table pointer H
        MOVWF TBLPTRH                               ; "
        MOVLW low Ox_TONE_PERIOD_LOCN               ;Load the tone period table low address location in the table pointer L
        MOVWF TBLPTRL                               ; "
        CLRF TBLPTRU                                ;Clear the upper table pointer address
        CLRF TEMP1_LO                               ;Clear TEMP1_LO temporary variable
        MOVLW b'00000001'                           ;Load TEMP1_HI with the first output bit position
        MOVWF TEMP1_HI                              ; "
START_TONE_LOOP1
        CPFSGT TONE_REQ_STAT                        ;Are we treating the last tone request in the sequence
        BRA END_START_TONE_LOOP1                    ;Yes, exit the current start loop
        RLNCF TEMP1_HI,F                            ;No, shift-left the temporary output position pointer 
        MOVF TEMP1_HI,W                             ;Transfer the current output position pointer into Wreg
        INCF TBLPTRL,F                              ;Increment the table pointer position
        BRA START_TONE_LOOP1                        ;Jump back to loop beginning
END_START_TONE_LOOP1
        MOVLW eecon1_prog_ee_access                 ;Initialize EEPROM data configuration registrer
        MOVWF EECON1                                ; "
        TBLRD*                                      ;Read into TABLAT and increment TBLPTR
        MOVFF TABLAT,TEMP1_LO                       ;copy period into TEMP1_LO
        INCF TEMP1_LO,F                             ;50% duty cycle = (PR2 + 1) / 2. Add 1 to period and 
        RRNCF TEMP1_LO,F                            ;Divide result by 2 to get duty cycle = 50%
        BCF TEMP1_LO,.7                             ; "
        MOVFF TEMP1_LO,CCPR2L                       ;Transfer duty cycle into CCPR2L
        MOVFF TABLAT,PR2                            ;Transfer period value into the period register PR2
        MOVLW .8                                    ;Load default tone duration for the first (lowest pitch) tone
        MOVWF TEMP1_LO                              ; "
        MOVLW b'00000001'                           ;Load temp variable TEMP1_HI with initial output position pointer
        MOVWF TEMP1_HI                              ; "
START_TONE_LOOP2
        MOVF TONE_REQ_STAT,W                        ;Are we positioned on the requested tone output?
        CPFSLT TEMP1_HI                             ; "
        BRA END_START_TONE_LOOP2                    ;Yes, leave loop
        RLNCF TEMP1_HI,F                            ;No, shift-left output position pointer
        INCF TEMP1_LO,F                             ;Increment the number of tone cycles to send
        BRA START_TONE_LOOP2                        ;Jump to beginning of loop
END_START_TONE_LOOP2
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Is the debounced PTT already active
        BRA SET_TONE_RX                             ;No, go set a Rx tone to be sent
        MOVF LAST_ENABLED_Ox,W                      ;Yes, are we treating the last enabled output position?
        CPFSEQ TEMP1_HI                             ; "
        BRA SET_TONE                                ;No, go set normal tone 
        BRA MULT_TONE_LENGTH                        ;Yes, go set a long tone
SET_TONE_RX
        MOVLW b'00000001'                           ;This is a Rx cycle. Are we treating the last output tone?
        CPFSEQ TEMP1_HI                             ; "
        BRA SET_TONE                                ;No, go send a normal tone duration
MULT_TONE_LENGTH                                    
        SWAPF TEMP1_LO,F                            ;Yes, lengthen the tone by a factor of 16
        BSF TONES_STAT,seq_end_tone_sounding        ;indicate to the remote monitoring tool to send a tone
SET_TONE
        MOVFF TEMP1_LO,MAX_NUM_PWM_CYCLE            ;Load the number of periods (cycle to send)
        BCF PIR1,TMR2IF                             ;Clear Timer2 interrupt flag
        CLRF TMR2                                   ;Clear the Timer2 counter
        BSF T2CON,TMR2ON                            ;Enable Timer2                
        BCF TRISC,ccp2_pin                          ;Put the CCP2 pin in output mode (enables)
        BSF TONES_STAT,seq_tone_sounding            ;Set the tone sounding flag
CTRL_TONES_RET       
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_FB_ALARM_AUTO_DISARM
;This piece of code controls the automatic disarming when a feedback alarm has happened and the user does
;not disarm the sequencer manually. The delay is hard-set at 3 minutes.

CTRL_FB_ALARM_AUTO_DISARM
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA CTRL_AUTO_DISARM_RET                    ;No , leave routine
        MOVF TX_FB_ALM_STAT,W                       ;Yes, test to see if there is any feedback alarm
        IORWF RX_FB_ALM_STAT,W                      ; "
        BZ CTRL_AUTO_DISARM_RET                     ;No, leave routine
        BTFSS GENERAL1_STAT,auto_disarm_alm_del_cnting;Yes, is the auto disarm delay counting?
        BRA START_TIMER0_AUTODSRM_DEL               ;No, go start a delay counting
TST_AUTODSRM_DEL_EXPIRED
		MOVLW fb_alm_auto_disarm_del                ;Yes, the auto disarm delay is 36 x 5 = 180 secondes
        CPFSLT AUTO_DISARM_TMR0_CTR                 ;Is the rollover counter less than the auto-disarm delay
        BRA INITIATE_AUTO_DISARM                    ;No, go initiate an auto-disarm
        BRA CTRL_AUTO_DISARM_RET                    ;Yes, Leave routine
START_TIMER0_AUTODSRM_DEL
		CLRF AUTO_DISARM_TMR0_CTR					;Clear the auto-disarm Counter
		BSF GENERAL1_STAT,auto_disarm_alm_del_cnting;Set the feedback alarm auto disarm delay counting flag
        BRA CTRL_AUTO_DISARM_RET                    ;Leave routine
INITIATE_AUTO_DISARM
        BCF ARM_PTT_STAT1,sys_armed                 ;Change system armed flag to disarmed 
        BSF ARM_PTT_STAT1,disarming_process_req     ;Raise the disarming process requested flag 	
		BCF GENERAL1_STAT,auto_disarm_alm_del_cnting;Clear the auto disarm delay counting flag
CTRL_AUTO_DISARM_RET
		RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_TX_AUTO_DISARM
;This piece of code controls the automatic disarming when a transmission reaches an 11 minute duration. 
;The delay is hard-set at 11 minutes.

CTRL_TX_AUTO_DISARM
        BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA CTRL_TX_AUTO_DISARM_RET                 ;No, leave routine
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Yes, is the debounced PTT state flag raised
        BRA RESET_TX_DISARM_STATUS                  ;No, go reset the Tx auto-disarm counting flag and leave routine
        BTFSS TX_SEQUENCING_STAT1,seq_over          ;Yes, is the the Tx Sequencing over flag set
		BRA RESET_TX_DISARM_STATUS                  ;No, leave routine
        BTFSS GENERAL1_STAT,auto_disarm_tx_del_cnting;Yes, is the auto disarm delay counting?
        BRA START_TMR0_AUTODSRM_DEL                 ;No, go start a delay counting
TST_TX_AUTODSRM_DEL_EXPIRED
		MOVLW tx_auto_disarm_del                    ;Yes, the auto disarm delay is 132 x 5 = 660 secondes (11 minutes)
        CPFSLT AUTO_DISARM_TMR0_CTR                 ;Is the rollover counter less than the auto-disarm delay
        BRA INITIATE_TX_AUTO_DISARM                 ;No, go initiate an auto-disarm
        BRA CTRL_TX_AUTO_DISARM_RET                 ;Yes, leave routine
START_TMR0_AUTODSRM_DEL
		CLRF AUTO_DISARM_TMR0_CTR					;Clear the auto-disarm Counter
		BSF GENERAL1_STAT,auto_disarm_tx_del_cnting ;Set the Tx auto disarm delay counting flag
        BRA CTRL_TX_AUTO_DISARM_RET                 ;Leave routine
INITIATE_TX_AUTO_DISARM
        BCF ARM_PTT_STAT1,sys_armed                 ;Change system armed flag to disarmed 
        BSF ARM_PTT_STAT1,disarming_process_req     ;Raise the disarming process requested flag 	
RESET_TX_DISARM_STATUS
		BCF GENERAL1_STAT,auto_disarm_tx_del_cnting ;Clear the Tx auto disarm delay counting flag
CTRL_TX_AUTO_DISARM_RET
		RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_ARM_PTT_LED
;This LED control routine determines the PTT/Status LED color based on the sequencer state at that moment. 
;This firmware will work when a bi-color LEDs are used. Three colors are supported Red, Green and Amber.
                                                    
CTRL_ARM_PTT_LED
        CLRF ARM_PTT_LED_STAT                       ;Clear the ARM_PTT_LED_STAT register. It will get updated after
        BTFSC ARM_PTT_STAT1,sys_armed               ;Check if system is armed?
        BRA SET_ARM_LED_COLOR                       ;Yes, go treat the armed mode
        BTFSC ARM_PTT_STAT2,arming_process_run      ;No, Is the arming process currently running?
        BRA SET_ARM_LED_COLOR                       ;Yes, go treat the LED in armed mode
SET_ARM_LED_DISARMED 
        MOVLW b'00000111'                           ;No, disarmed state. Test if the last 3 bits of the dimming counter are set
        ANDWF LED_DIM_CTR,W                         ; This effectively divides the "high" time by 8 and causes a dim
        SUBLW b'00000111'                           ; "
        BZ SET_ARM_LED_COLOR                        ;If no dim is required, go treat LED color
        MOVLW b'00000111'                           ;No, disarmed state. Test if the last 3 bits of the dimming counter are cleared
        ANDWF LED_DIM_CTR,W                         ; This effectively divides the "low" time by 8 and causes a dim
        SUBLW b'00000000'                           ; "
        BZ SET_ARM_LED_COLOR                        ;If no dim is required, go treat LED color
        BSF ARM_PTT_LED_STAT,led_off                ;Dim required. Turn off the LED this pass to create a dim effect
        BRA SW_ARM_LED_OUT                          ;Yes, Go switch the LED pin
SET_ARM_LED_COLOR
        BTFSS ARM_PTT_STAT1,ptt_debounced_state     ;Yes, is the debounced PTT active?
        BSF ARM_PTT_LED_STAT,led_green              ;No, set the green flag on
        BTFSC ARM_PTT_STAT1,ptt_debounced_state     ;Yes, Is the debounced PTT inactive?
        BSF ARM_PTT_LED_STAT,led_amber              ;No, set the amber flag on
SW_ARM_LED_OUT
        BTFSC ARM_PTT_LED_STAT,led_off              ;Is the off flag cleared?
        BSF TRISA,arm_ptt_led_pin                   ;No, set the LED output pin in input mode     
        BTFSC ARM_PTT_LED_STAT,led_green            ;Yes, Is the green flag raised?       
        BCF PORTA,arm_ptt_led_pin                   ;Yes, set the LED output pin low
        BTFSC ARM_PTT_LED_STAT,led_red              ;No, Is the red flag raised? 
        BSF PORTA,arm_ptt_led_pin                   ;Yes, set the LED output pin high
        BTFSC ARM_PTT_LED_STAT,led_amber            ;No, Is the amber flag raised?
        BTG PORTA,arm_ptt_led_pin                   ;Yes, toggle the LED output pin
        BTFSS ARM_PTT_LED_STAT,led_off              ;No,Is the off flag raised?
        BCF TRISA,arm_ptt_led_pin                   ;No, set the LED output pin in output mode
CTRL_ARM_LED_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_OUTPUT_LEDS
;This routine controls the behavior of the six Output LEDs. The amber color is generated by toggling rapidly
;between green and red. LED 6 is a separate case since it is not phisically located on the same physical port as the other 5 ones.

CTRL_OUTPUT_LEDS
        BTFSC SERIAL_STAT,setup_mode                ;Is the setup mode enabled?
        BRA CTRL_OUT_LEDS_RET                       ;Yes, leave routine
        LFSR FSR2,0x15A                             ;Load Indirect pointer with base address of output LEDs status register
        MOVLW b'00000001'                           ;Initialize temporary variable to output 1 LED position
        MOVWF TEMP1_HI                              ; "
        MOVWF O3_LED_STAT                           ;Initialize LED 3-6 status registers by setting the off flags
        MOVWF O4_LED_STAT                           ; "
        MOVWF O5_LED_STAT                           ; "
        MOVWF O6_LED_STAT                           ; "
LOOP_OUT_LED
        CLRF INDF2                                  ;Clear the pointed output LED status register
    	BTFSS ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA TEST_LED_NO_ALM                         ;Yes, go to set LED when armed
TEST_LED_ALM
        MOVF TX_FB_ALM_STAT,W                       ;Yes, test to see if there is any feedback alarm
        IORWF RX_FB_ALM_STAT,W                      ; "
        ANDWF TEMP1_HI,W                            ;Isolate the currently treated output feedback alarm
        BZ TEST_LED_NO_ALM                          ;No, go set the LED for no-alarm condition
        BSF INDF2,led_red                           ;Yes, set the red LED flag into the pointed output LED status register
        BRA PREP_OUT_LED_LOOP                       ;Go prepare for next output LED pass (loop)
TEST_LED_NO_ALM
        MOVF TEMP1_HI,W                             ;Transfer the pointed output LED status register into Wreg
        ANDWF Ox_HIGH_LOW,W                         ;Is the output pin low (output active)?
        BZ SET_LED_AMBER                            ;Yes, go set the current output LED amber flag 
        BSF INDF2,led_green                         ;No, set the green LED flag the pointed output LED status register
        BRA PREP_OUT_LED_LOOP                       ;Go prepare for next output LED pass
SET_LED_AMBER
        BSF INDF2,led_amber                         ;Set the amber LED into the pointed output LED status register
        BRA PREP_OUT_LED_LOOP                       ;Go prepare for next output LED pass
PREP_OUT_LED_LOOP
        MOVF LAST_ENABLED_Ox,W                      ;Is the currently treated output LED the last one?
        CPFSLT TEMP1_HI                             ; "
        BRA SW_OUT_LEDS                             ;Yes, go switch the output LED pins
        RLNCF TEMP1_HI                              ;No, roll left the current LED treated pointer
        INCF FSR2L,F                                ;Increment the pointer to the current output LED status register
        BRA LOOP_OUT_LED                            ;loop to treat the next output LED
SW_OUT_LEDS
        INCF LED_DIM_CTR                            ;Icrement the dimming counter
        LFSR FSR2,0x15A                             ;Load Indirect pointer with base address of output LEDS status register
        MOVLW b'00000001'                           ;Initialize temporary variable to output 1 LED position
        MOVWF TEMP1_HI                              ; "
SW_OUT_LEDS_LOOP
        BTFSC TEMP1_HI,6                            ;Are we treating the 6th output LED (special case due to pin position)?
        BRA SW_O6_LED                               ;Yes, go set the output LED 6
        BTFSS INDF2,led_off                         ;No, is the treated LED status flag set to off?
        BRA TEST_Ox_LED_GREEN                       ;No, go test for green flag
        MOVF TEMP1_HI,W                             ;Yes, set the output pin to input mode
        IORWF TRISC,F                               ; "
        BRA PREP_SW_OUT_LEDS_LOOP                   ;Go prepare for next output LED setting
TEST_Ox_LED_GREEN
        COMF TEMP1_HI,W                             ;Complement the current LED treated indicator and store into Wreg
        ANDWF TRISC,F                               ;Set the current LED pin as an output to turn on LED
        BTFSS INDF2,led_green                       ;Is the treated LED status flag set to green?
        BRA TEST_Ox_LED_RED                         ;No, go test for red flag
        COMF TEMP1_HI,W                             ;Complement the current LED treated indicator and store into Wreg
        ANDWF PORTC,F                               ;Set the current LED pin as output low (green)
        BRA PREP_SW_OUT_LEDS_LOOP                   ;Go prepare for next output LED setting
TEST_Ox_LED_RED
        BTFSS INDF2,led_red                         ;Is the treated LED status flag set to red?       
        BRA TEST_Ox_LED_AMBER                       ;No, go test for amber flag
        MOVF TEMP1_HI,W                             ;Yes, Store the current LED treated indicator into Wreg
        IORWF PORTC,F                               ;Set the current LED output pin as output high (red)
        BRA PREP_SW_OUT_LEDS_LOOP                   ;Go prepare for next output LED setting
TEST_Ox_LED_AMBER
        BTFSS INDF2,led_amber                       ;Is current LED amber flag set?
        BRA PREP_SW_OUT_LEDS_LOOP                   ;No, Go prepare for next output LED setting
        MOVF TEMP1_HI,W                             ;Yes, Store the current LED treated indicator into Wreg
        XORWF PORTC,F                               ;Toggle the current LED pin (fast red-green toggle gives amber color)
PREP_SW_OUT_LEDS_LOOP
        BTFSC ARM_PTT_STAT1,sys_armed               ;Check if system is armed
        BRA ARMED_NO_DIM                            ;Yes, go set current LED in full brightness
     	BTFSC ARM_PTT_STAT2,disarming_process_run   ;Is the disarming process running ? 
     	BRA ARMED_NO_DIM                            ;Yes, go set current LED in full brightness     
        MOVLW b'00001111'                           ;No, test if the last 4 bits of the dimming counter are set
        ANDWF LED_DIM_CTR,W                         ; This effectively divides the "hi" time by 16 and causes a dim
        SUBLW b'00001111'                           ; "            
        BZ ARMED_NO_DIM                             ;If, no dim is required in this pass, go prepare for next LED
        MOVLW b'00001111'                           ;No, test if the last 4 bits of the dimming counter are cleared
        ANDWF LED_DIM_CTR,W                         ; This effectively divides the "low" time by 16 and causes a dim
        SUBLW b'00000000'                           ; "            
        BZ ARMED_NO_DIM                             ;If, no dim is required in this pass, go prepare for next LED
        MOVF TEMP1_HI,W                             ;Dim required. Turn off the LED this pass to create a dim effect
        IORWF TRISC,F                               ; "
ARMED_NO_DIM
        INCF FSR2L,F                                ;Increnment indirect pointer to currently treated LED status register
        RLNCF TEMP1_HI,F                            ;Roll left the current LED treated indicator
        BTFSC TEMP1_HI,.1                           ;Are we preparing for output 2 LED?
        RLNCF TEMP1_HI,F                            ;Yes, roll left another time (due to port C output pin assignment skipping)
        BRA SW_OUT_LEDS_LOOP                        ;Loop for next output LED treatment
SW_O6_LED
        BTFSS O6_LED_STAT,led_off                   ;Treating output 6 LED. Is the off flag set?
        BRA TEST_O6_LED_GREEN                       ;No, go test for greed color
        BSF TRISA,.6                                ;Yes, set output 6 LED to input (turn off)
        BRA TEST_O6_LED_DIM                         ;GO test Output 6 LED for dimming
TEST_O6_LED_GREEN
        BCF TRISA,.6                                ;Set output 6 LED pin to output (turn on)
        BTFSS O6_LED_STAT,led_green                 ;Is green flag set?
        BRA TEST_O6_LED_RED                         ;No, go treat red color
        BCF PORTA,.6                                ;Yes, set output 6 LED pin to low (green)
        BRA TEST_O6_LED_DIM                         ;GO test Output 6 LED for dimming
TEST_O6_LED_RED
        BTFSS O6_LED_STAT,led_red                   ;Is the red flag set?       
        BRA TEST_O6_LED_AMBER                       ;No, go test for amber color
        BSF PORTA,.6                                ;Yes, set output LED 6 pin to high (red)
        BRA TEST_O6_LED_DIM                         ;GO test Output 6 LED for dimming
TEST_O6_LED_AMBER
        BTFSS O6_LED_STAT,led_amber                 ;Is the amber flag set?
        BRA CTRL_OUT_LEDS_RET                       ;No, leave routine
        BTG PORTA,.6                                ;Yes, toggle output 6 LED pin (fast red-green toggle gives amber color)
TEST_O6_LED_DIM                     
        BTFSC ARM_PTT_STAT1,sys_armed               ;Is system armed?
        BRA CTRL_OUT_LEDS_RET                       ;Yes, leave routine
     	BTFSC ARM_PTT_STAT2,disarming_process_run   ;Is the disarming process running ? 
     	BRA CTRL_OUT_LEDS_RET                       ;Yes, go set current LED in full brightness     
        MOVLW b'00001111'                           ;No, test if the last 4 bits of the dimming counter is set
        ANDWF LED_DIM_CTR,W                         ; This effectively divides the "on" time by 16 and causes a dim
        SUBLW b'00001111'                           ; "
        BZ CTRL_OUT_LEDS_RET                        ;If no dim is required, leave routine
        MOVLW b'00001111'                           ;No, test if the last 4 bits of the dimming counter is set
        ANDWF LED_DIM_CTR,W                         ; This effectively divides the "on" time by 16 and causes a dim
        SUBLW b'00000000'                           ; "
        BZ CTRL_OUT_LEDS_RET                        ;If no dim is required, leave routine
        BSF TRISA,.6                                ;Dim required. Turn off the LED this pass to create a dim effect
CTRL_OUT_LEDS_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_PARAM_INFO_TX
;This piece of code processes the transmission of the Sequencer parameters string to the serial port. It transfers the 
;parameters and formats the ASCII string.

CTRL_PARAM_INFO_TX
        BTFSC SERIAL_STAT,tx_cycle_on               ;Is the transmit cycle already happening?     
        BRA USART_INFO_RET                          ;Yes, exit routine   
        BTFSC SERIAL_STAT,remote_mon_req            ;Is it requested to send Remote Monitoring Info string?
        BRA TREAT_REMOTE_MON_TX                     ;Yes, go treat the Remote monitoring string   
        BTFSC SERIAL_STAT,send_parameters           ;No, Is it requested to send parameter string?
        BRA TREAT_PARAM_TX                          ;Yes, go prepare the parameter string   
        BRA USART_INFO_RET                          ;No, leave routine
TREAT_REMOTE_MON_TX                                 ;Here, Indirect addressing cannot be used since we are not in Setup mode and FSR regs are used everywhere.
        MOVLW "M"                                   ;Load character M into Wreg
        MOVWF SERIAL_TX_BUFF                        ;Load this character into the first Rx Buffer memory cell
        MOVFF ARM_PTT_STAT1,TEMP1_HI                ;Transfer the hex value of ARM_PTT_STAT1 into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.1            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF O1_LED_STAT,TEMP1_HI                  ;Transfer the hex value of O1_LED_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.2            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF O2_LED_STAT,TEMP1_HI                  ;Transfer the hex value of O2_LED_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.3            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF O3_LED_STAT,TEMP1_HI                  ;Transfer the hex value of O3_LED_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.4            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF O4_LED_STAT,TEMP1_HI                  ;Transfer the hex value of O4_LED_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.5            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF O5_LED_STAT,TEMP1_HI                  ;Transfer the hex value of O5_LED_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.6            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF O6_LED_STAT,TEMP1_HI                  ;Transfer the hex value of O6_LED_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_LO,SERIAL_TX_BUFF+.7            ;Transfer the lower nibble ASCII equivalent into the Tx buffer
        MOVFF TONES_STAT,TEMP1_HI                   ;Transfer the hex value of TONES_STAT into TEMP1_HI
        CALL HEX_2_ASCII                            ;Convert to ASCII value.
        MOVFF TEMP1_HI,SERIAL_TX_BUFF+.8            ;Transfer the higher nibble ASCII equivalent into the Tx buffer
        MOVLW "\r"                                  ;Load CR
        MOVWF SERIAL_TX_BUFF+.9                     ; into Tx buffer
        MOVLW "\n"                                  ;Load LF
        MOVWF SERIAL_TX_BUFF+.10                    ; into Tx buffer
        MOVLW 00h                                   ;Load Null
        MOVWF SERIAL_TX_BUFF+.11                    ; into Tx buffer
        BCF TONES_STAT,seq_end_tone_sounding        ;Clear the flag that indicates to the remote monitoring tool to send a tone
        BRA END_TX_COMMAND                          ;Go end the Tx string
TREAT_PARAM_TX
        CLRF TEMP2_HI                               ;Clear TEMP2_HI. Will be used as a counter
        LFSR FSR1,0x140                             ;Load the Parameters' base address in FSR1 register
        LFSR FSR2,0x190                             ;Load Serial Tx buffer's base address in FSR2 register
        MOVLW "P"                                   ;Load "P" character
        MOVWF POSTINC2                              ; into Tx buffer
        MOVLW firmware_version                      ;Load the firmware version value in TEMP1_HI 
        MOVWF TEMP1_HI                              ; "
        CALL HEX_2_ASCII                            ;Convert to two ASCII characters
        MOVFF TEMP1_HI,POSTINC2                     ;Conversion routine returns TEMP1_HI/TEMP1_HI. Load first Hex char into Tx buffer.
        MOVFF TEMP1_LO,POSTINC2                     ; and second hex char into Tx buffer.
PARAM_TX_XFER_LOOP
        INCF TEMP2_HI,F                             ;Increment parameter counter
        MOVFF POSTINC1,TEMP1_HI                     ;Load the current parameter register in TEMP1_HI                
        CALL HEX_2_ASCII                            ;Convert to two ASCII characters
        MOVFF TEMP1_HI,POSTINC2                     ;Conversion routine returns TEMP1_HI/TEMP1_HI. Load first Hex char into Tx buffer.
        MOVFF TEMP1_LO,POSTINC2                     ; and second hex char into Tx buffer.
        MOVLW number_param_to_stor                  ;Has the maximum number of parameters to store been reached
        CPFSEQ TEMP2_HI                             ; "
        BRA PARAM_TX_XFER_LOOP                      ;No, loop to treat the next parameter
SEND_CR_LF
        MOVLW "\r"                                  ;Yes, Load CR
        MOVWF POSTINC2                              ; into Tx buffer
        MOVLW "\n"                                  ;Load LF
        MOVWF POSTINC2                              ; into Tx buffer
        MOVLW 00h                                   ;Load Null
        MOVWF POSTINC2                              ; into Tx buffer
END_TX_COMMAND
        BSF SERIAL_STAT,new_tx_cycle                ;Raise new TX cycle flag
        BCF SERIAL_STAT,send_parameters             ;Clear the parameter string request flag       
        BCF SERIAL_STAT,remote_mon_req              ;Clear the Remote Monitoring String request flag       
        BSF SERIAL_STAT,tx_cycle_on                 ;Raise the transmit cycle flag       
        BSF PIE1,TXIE                               ;Enable TX interrupts              
USART_INFO_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;CTRL_PARAM_INFO_RX
;This piece of code processes the reception of the Sequencer parameters string from the serial port. It transfers the 
;parameters and formats the ASCII string.

CTRL_PARAM_INFO_RX
        BTFSC SERIAL_STAT,tx_cycle_on               ;Is a Tx cycle being processed?
        BRA USART_RX_RET                            ;Yes, leave (Indirect addressing reg. FSR2 shared with CTRL_TX_STRING)
        BTFSS SERIAL_STAT,lf_eoc_received           ;No, has end of command flag (LF) been detected by interrupt routine
        BRA USART_RX_RET                            ;No, leave routine     
        BCF PIE1,RCIE                               ;Yes, disable RX interrupts                 
        MOVLW "M"                                   ;Load character M into Wreg
        CPFSEQ SERIAL_RX_BUFF                       ;Is it the Remote Monitor Request command command?
        BRA CONT_PARAM_TREAT                        ;No, go to next validation
        BSF SERIAL_STAT,remote_mon_req              ;Yes, clear the remote monitoring string requested flag
        BCF SERIAL_STAT,lf_eoc_received             ;Clear the end of command flag
        CLRF SERIAL_RX_BUFF                         ;Clear the Rx buffer
        CLRF SERIAL_RX_BUFF+.1                      ; "
        CLRF SERIAL_RX_BUFF+.2                      ; "
        BRA USART_RX_RET                            ;Leave routine
CONT_PARAM_TREAT                                    ;A pre-screening is required here to reject any non-supported command
        MOVLW "U"                                   ;Load character U into Wreg
        SUBWF SERIAL_RX_BUFF,W                      ;Is it the parameters update command?
        BZ VALID_RX_COMMAND                         ;Yes, go treat it 
        MOVLW "S"                                   ;Load character S into Wreg
        SUBWF SERIAL_RX_BUFF,W                      ;Is it the Send parameters command?
        BZ VALID_RX_COMMAND                         ;Yes, go treat it
        MOVLW "R"                                   ;Load character R into Wreg
        SUBWF SERIAL_RX_BUFF,W                      ;Is it Reset command?
        BNZ CLR_RX_BUFF                             ;No, go clear the Rx buffer                  
VALID_RX_COMMAND
        BTFSC ARM_PTT_STAT2,disarming_process_run   ;Yes, is the disarming process currently running?
        BRA USART_RX_NOINT_RET                      ;Yes, leave
        BTFSS ARM_PTT_STAT1,sys_armed               ;No, check if system is armed?
        BRA RX_OK_TREAT                             ;No, continue with RX process
        BCF ARM_PTT_STAT1,sys_armed                 ;Yes, Change system armed flag to disarmed 
        BSF ARM_PTT_STAT1,disarming_process_req     ;Invoke a disarming process by setting the right bit
        BRA USART_RX_NOINT_RET                      ;Leave routine
RX_OK_TREAT
        CLRF TEMP2_HI                               ;Yes, clear the TEMP2_HI variable. Will be used as a counter
        BSF SERIAL_STAT,setup_mode                  ;Enable the setup mode
        LFSR FSR1,0x140                             ;Load the Parameters' base address in FSR1 register
        LFSR FSR2,0x160                             ;Load Serial rx buffer's base address in FSR2 register
        MOVFF POSTINC2,TEMP1_LO                     ;Transfer first char into temp variable
TST_U_COMMAND
        MOVLW "U"                                   ;Load character U into Wreg
        CPFSEQ TEMP1_LO                             ;Is it the parameters update command?
        BRA TST_S_COMMAND                           ;No, go to next validation
RX_CHECKSUM_CHECK
        MOVLW .0                                    ;Clear the checksum
        CLRF CHKSUM                                 ; "
RX_CHKSUM_LOOP                
        MOVF POSTINC2,W                             ;Read the following character from the Rx buffer
        ADDWF CHKSUM,F                              ;Add its ASCII value to the checksum
        MOVLW 0x81                                  ;Checksum position in the Rx Buffer
        CPFSEQ FSR2L                                ;Have we reach the end of the string to compute the checksum from?
        BRA RX_CHKSUM_LOOP                          ;No, loop to calculate checksum for next character
        MOVFF POSTINC2,TEMP1_HI                     ;Yes, Transfer received checksum high character of hex into TEMP1_HI
        MOVFF POSTINC2,TEMP1_LO                     ;Transfer received checksum low character of hex into TEMP1_LO
        CALL ASCII_2_HEX                            ;Convert to hex value.
        MOVF TEMP1_HI,W                             ;Transfer hex value of the received checksum into Wreg
        CPFSEQ CHKSUM                               ;Does received checksum equals computed checksum?                                                              
        BRA CLR_RX_BUFF                             ;No, do not process command and go empty rx buffer
        LFSR FSR2,0x161                             ;Yes, Load Serial rx buffer's first parameter position in FSR2 register
        CLRF TEMP2_HI                               ;Clear the TEMP2_HI variable. Will be used as a counter
U_XFER_LOOP
        INCF TEMP2_HI,F                             ;Increment the TEMP2_HI counter
        MOVFF POSTINC2,TEMP1_HI                     ;Transfer high character of hex into TEMP1_HI
        MOVFF POSTINC2,TEMP1_LO                     ;Transfer low character of hex into TEMP1_LO
        CALL ASCII_2_HEX                            ;Convert to hex value. Zero Flag is valid here.
        MOVFF TEMP1_HI,POSTINC1                     ;Transfer hex value into the parameter variable
        MOVLW number_param_to_stor                  ;Has the maximum number of parameters to store been reached
        CPFSEQ TEMP2_HI                             ; "       
        BRA U_XFER_LOOP                             ;No, loop to continue to treat the U command transfer
        BSF GENERAL1_STAT,write_cycle_req           ;Yes, set the flag to write the EEPROM with the DAC value and all other parameters
        BRA CLR_RX_BUFF                             ;go empty rx buffer
TST_S_COMMAND       
        MOVLW "S"                                   ;Load character S into Wreg
        CPFSEQ TEMP1_LO                             ;Is it the Send parameters command?
        BRA TST_R_COMMAND                           ;No, go to next validation
        BSF SERIAL_STAT,send_parameters             ;Yes, set the send parameters information flag
        BRA CLR_RX_BUFF                             ;go empty rx buffer
TST_R_COMMAND
        MOVLW "R"                                   ;Load character R into Wreg
        CPFSEQ TEMP1_LO                             ;Is it Reset command?
        BRA CLR_RX_BUFF                             ;No, go empty rx buffer
        RESET                                       ;Execute device reset
CLR_RX_BUFF
        BCF SERIAL_STAT,lf_eoc_received             ;Clear the end of command flag
        LFSR FSR2,0x160                             ;load Serial rx buffer's base address in FSR register.
CLR_RX_BUFF_LOOP
        CLRF POSTINC2                               ;Clear Rx buffer cell and increase indirect addressing pointer
        MOVLW 0x80                                  ;Has the whole Rx buffer been erased?
        CPFSEQ FSR2L                                ; "
        BRA CLR_RX_BUFF_LOOP                        ;No, loop again.
USART_RX_RET                                        
        BSF PIE1,RCIE                               ;Yes, enable RX interrupts                    
USART_RX_NOINT_RET
        RETURN                                      ;exit routine

;******************************************************************************************************
;CTRL_PARAM_UPD_EEPROM
;This portion of code writes the Sequencer parameters to data EEPROM. This is a multi-pass process. Before the
;next byte write cycle can be processed, s/w must wait for the previous byte write cycle to complete.

CTRL_PARAM_UPD_EEPROM
        BTFSS GENERAL1_STAT,write_cycle_req         ;Is a Parameter Write cycle required or in progress?
        BRA UPDATE_PARAM_RET                        ;No, leave routine
        BTFSC SERIAL_STAT,tx_cycle_on               ;Is a Tx cycle being processed?
        BRA UPDATE_PARAM_RET                        ;Yes, leave (EEPROM access of Data and Program must not happen concurrently)
EXECUTE_WRITE                    
        LFSR FSR1,0x140                             ;Load indirect addressing pointer with first parameter address
NEXT_PARAM_WRITE_LOOP
        MOVLW .0                                    ;Is is time to load the valid Data Flag (00) parameter in the first location?
        CPFSEQ WRT_EEPROM_POS                       ; "
        BRA WRITE_PARAMS                            ;No, go write next parameter in EEPROM
        CLRF TEMP1_LO                               ;Yes, load 0 in TEMP1_LO
        BRA CALL_WRITE_DATA                         ;go call EEPROM writing routine
WRITE_PARAMS
        MOVF WRT_EEPROM_POS,W                       ;Load the current EEPROM address (position) into Wreg 
        MOVFF POSTINC1,TEMP1_LO                     ;Load current parameter into temporary variable
CALL_WRITE_DATA
        CALL WRITE_EEPROM_DATA                      ;Call EEPROM writing routine
WRITE_WAIT_LOOP
        CLRWDT                                      ;Repeatedly clears the WatchDog timer.        
        BTFSC EECON1,WR                             ;Yes, is Write cycle happening
        BRA WRITE_WAIT_LOOP                         ;Yes, loop until write cycle is over
        MOVLW number_param_to_stor                  ;Is this the last address (parameter) to write?
        CPFSLT WRT_EEPROM_POS                       ; "
        BRA END_WRITE_CYCLE                         ;Yes, go end the EEPROM writing process
        INCF WRT_EEPROM_POS,F                       ;No, Increment EEPROM Writing Position       
        BRA NEXT_PARAM_WRITE_LOOP                   ;Go treat the next parameter to Write
END_WRITE_CYCLE
        BCF GENERAL1_STAT,write_cycle_req           ;Clear the write cycle flag     
        CLRF WRT_EEPROM_POS                         ;Clear write position 
UPDATE_PARAM_RET
        RETURN                                      ;Leave routine

;******************************************************************************************************
;HEX_2_ASCII
;This code converts an hexadecimal byte to the equivalent two ASCII characters.

HEX_2_ASCII                                         ;The hex value is expected to be in TEMP1_HI when the routine is called
        MOVLW .58                                   ;Load ASCII equivalent of 10 into temporary var.
        MOVWF TEMP3_LO                              ; "
LO_NIBBLE
        MOVF TEMP1_HI,W                             ;Move hex value into Wreg
        ANDLW h'0F'                                 ;isolate lower nibble
        ADDLW .48                                   ;add ASCII ofset
        CPFSGT TEMP3_LO                             ;verify if ASCII char is higher than "9"
        ADDLW .7                                    ;yes, add additional ASCII offset
        MOVWF TEMP1_LO                              ;No, low ASCII characters is returned in TEMP1_LO
HI_NIBBLE
        SWAPF TEMP1_HI,W                            ;load nibble-swapped hex value into Wreg
        ANDLW h'0F'                                 ;isolate lower nibble
        ADDLW .48                                   ;add ASCII ofset
        CPFSGT TEMP3_LO                             ;verify if ASCII char is higher than "9"
        ADDLW .7                                    ;yes, add additional ASCII offset
        MOVWF TEMP1_HI                              ;No, high ASCII characters is returned in TEMP1_HI   
        RETURN                                      ;Leave routine. Result are in TEMP1_HI and TEMP1_LO

;******************************************************************************************************
;ASCII_2_HEX  
;This code converts two ASCII characters representing a hexadecimal byte to its numerical equivalent.

ASCII_2_HEX                                         ; The ASCII characters are expected to be in TEMP1_HI and TEMP1_LO when the routine is called
        MOVLW .10                                   ;load the offset required to test for gap between ASCII code for 9 and A
        MOVWF TEMP3_LO                              ; "           
HIGH_CHAR
        MOVLW .48                                   ;load ASCII offset equiv. into Wreg
        SUBWF TEMP1_HI,W                            ;substract 48 from ASCII character
        CPFSGT TEMP3_LO                             ;is ASCII character higher than "9" (like A,B,C,D,E,F)
        ADDLW .249                                  ;yes, substract an additional ASCII offset of 7 (adding 249 does the same)
        MOVWF TEMP1_HI                              ;no, load result into TEMP1_HI
        SWAPF TEMP1_HI,F                            ;swap nibbles to move to higher hex position   
LO_CHAR
        MOVLW .48                                   ;load ASCII offset equiv. into Wreg
        SUBWF TEMP1_LO,W                            ;substract 48 from ASCII character
        CPFSGT TEMP3_LO                             ;is ASCII character higher than "9" (like A,B,C,D,E,F)
        ADDLW .249                                  ;yes, substract an additional ASCII offset of 7 (adding 249 does the same)
        ADDWF TEMP1_HI,F                            ;add the result to the higher hex result 
        RETURN                                      ;Leave routine. Result is in TEMP1_HI

;******************************************************************************************************
;READ_EEPROM_DATA
;This sub-routine reads one byte of Data EEPROM

READ_EEPROM_DATA
        MOVWF EEADR                                 ;Address to read is in Wreg  
        BCF EECON1, CFGS                            ;Point to DATA memory
        BCF EECON1,EEPGD                            ;Point to DATA memory
        BSF EECON1,RD                               ;EEPROM Read
        MOVF EEDATA,W                               ;value read is moved to Wreg 
        RETURN                                      ;Leave sub-routine

;******************************************************************************************************
;WRITE_EEPROM_DATA
;This sub-routine writes one byte of Data EEPROM

WRITE_EEPROM_DATA
        MOVWF EEADR                                 ;Data Memory Address to write is in Wreg
        MOVFF TEMP1_LO,EEDATA                       ;Data memory value is in TEMP1_LO
        BCF EECON1, CFGS                            ;Point to DATA memory
        BCF EECON1, EEPGD                           ;Point to DATA memory
        BSF EECON1, WREN                            ;Enable writes
        BCF INTCON, GIE                             ;Disable Interrupts
        MOVLW h'55'                     
        MOVWF EECON2                                ;Write 55h
        MOVLW h'AA'
        MOVWF EECON2                                ;Write AAh
        BSF EECON1, WR                              ;Set WR bit to begin write
        BCF EECON1, WREN                            ;Disable writes
        BSF INTCON, GIE                             ;Enable Interrupts
        RETURN                                      ;Leave sub-routine

;******************************************************************************************************
;READ_DELAY_TABLE
;This sub-routine determines the values to load to the timer that generates the switching delays based
;on user input (data flash values) as sent by the Windows program.

READ_DELAY_TABLE
        MOVLW high Ox_DEL_TABLE_LOCN                ;Load Output Delay lookup table high address location in the table pointer H
        MOVWF TBLPTRH                               ; "
        MOVLW low Ox_DEL_TABLE_LOCN                 ;Load Output Delay lookup tabl low address location in the table pointer L
        MOVWF TBLPTRL                               ; "
        CLRF TBLPTRU                                ;Load TBLPTR with the base address of the word
        RLNCF INDF1,W                               ;Multiply the current output delay index by 2
        ANDLW b'11111110'                           ; "
        ADDWF TBLPTRL,F                             ;Add it to the lower table pointer
        MOVLW eecon1_prog_ee_access                 ;Initialize EEPROM data configuration registrer
        MOVWF EECON1                                ; "
        TBLRD*+                                     ;Read to TABLAT and increment TBLPTR
        MOVFF TABLAT,TEMP2_LO                       ;Transfer low delay value into TEMP2_LO
        TBLRD*                                      ;Read into TABLAT
        MOVFF TABLAT,TEMP2_HI                       ;Transfer high delay value into TEMP2_HI
        RETURN                                      ;Leave sub-routine

;******************************************************************************************************

;This is the Output Delay Lookup table and it is placed in Program Memory
; The values in this table are loaded into Timer0 to count the output delay specified by the user.
        ORG 0x0FC0
Ox_DEL_TABLE_LOCN                        
;           20ms , 30ms , 40ms , 50ms , 60ms , 70ms , 80ms , 90ms , 100ms, 150ms 
        DW 0xFF64,0xFF16,0xFEC8,0xFE79,0xFE2B,0xFDDD,0xFD8F,0xFD41,0xFCF3,0xFB6C
;           200ms, 250ms, 300ms, 400ms, 500ms, 600ms, 700ms, 800ms, 900ms,1000ms
        DW 0xF9E5,0xF85F,0xF6D8,0xF3CB,0xF0BE,0xEDB0,0xEAA3,0xE796,0xE489,0xE17B

;******************************************************************************************************

;This is the Output Tone period lookup table. The values saved are for the CCP2 PR2 register and will make 
;the PWM produce the frequencies listed below. This table is saved in Program Memory.
        ORG 0x0FE8
Ox_TONE_PERIOD_LOCN                        
;           O1:523Hz , O2:587Hz , O3:659Hz , O4:698Hz , O5:784Hz , O6:880Hz
        DB   0xEE    ,  0xD4   ,   0xBD   ,   0xB2   ,   0x9E   ,   0x8D

;******************************************************************************************************

;Default Sequencer parameter values added into Data EEPROM locations, starting at address 0x00
;Make sure the number_param_to_stor constant is updated when changing the number of parameters saved.
        ORG 0xF00000
PARAMETERS_LOCN
;          NULL , Ox_LOGIC , O1_O2_DEL , O2_O3_DEL , O3_O4_DEL , O4_O5_DEL ,  O5_O6_DEL , O6_O5_DEL , O5_O4_DEL , O4_O3_DEL 
        DE 0x00 ,   0x00   ,   0x08    ,   0x08   ,    0x08   ,   0x08    ,    0x08    ,    0x08   ,    0x08   ,    0x08
;          O3_O2_DEL , O2_O1_DEL , LAST_ENABLED_Ox , PTT_USER_LOGIC , Ox_FB_ENABLED , TONES_ENABLED , TMOUT_TONE_DURATION , NULL
        DE   0x08    ,   0x08    ,      0x20       ,     0x01       ,    0x00       ,     0x03      ,       0x07          , 0xFF
;Then we fill the remaining data EEPROM values (except the last two) with FF. This makes the PIC burner happy.
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        DE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF

;******************************************************************************************************

;The last Data EEPROM value stores the FW VERSION to allow to read the firmware version from PICMicro burner,  
;whitout running the firmware. It is not saved or retrieved by firmware. It is located in the last Data EEPROM Byte.
;             BLANK  ,   FW VERSION
        DE    0xFF   ,      .2

;******************************************************************************************************

;End of program
        END
