;* --------------------------------------------------------------------------------------
;*  Copyright (C) 2004 Dallas Semiconductor Corporation, All Rights Reserved.
;* 
;*  Permission is hereby granted, free of charge, to any person obtaining a
;*  copy of this software and associated documentation files (the "Software"),
;*  to deal in the Software without restriction, including without limitation
;*  the rights to use, copy, modify, merge, publish, distribute, sublicense,
;*  and/or sell copies of the Software, and to permit persons to whom the
;*  Software is furnished to do so, subject to the following conditions:
;* 
;*  The above copyright notice and this permission notice shall be included
;*  in all copies or substantial portions of the Software.
;* 
;*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
;*  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;*  MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
;*  IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
;*  OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
;*  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;*  OTHER DEALINGS IN THE SOFTWARE.
;* 
;*  Except as contained in this notice, the name of Dallas Semiconductor
;*  shall not be used except as stated in the Dallas Semiconductor
;*  Branding Policy.
;*
;* --------------------------------------------------------------------------------------
;* 
;* This demonstration program shows the use of the timers with the
;* MAXQ2000 Evaluation Kit.  All three timers are used to show different
;* functionality.  A scope is required to see the output of timers 0 and 1.
;*
;* Timer 0 is configured to be a single shot output.  The timer 0 output 
;* pins default high.  Upon pressing the button SW4, the single shot bit 
;* is written and a long, low pulse is output on the timer 0 output pins.
;* This pulse is long enough that it could probably be measured with a
;* multimeter.
;*
;* Timer 1 is configured to produce a 1/3 duty cycle waveform at 100 Hz.
;* The button SW5 will invert the polarity of the signal (toggles between
;* 1/3 high, 2/3 low and 1/3 low, 2/3 high).
;*
;* Timer 2 is configured to give simple, periodic interrupts, when we
;* rotate the value showing on the LED bank.  The LED bank should show 
;* one un-lit bit moving to the left every 1/2 second, rotating around
;* when it comes to the end (note that the last 2 LEDs on the right
;* are not included--these are tied to power and ground).
;*
;*  Turn ON the following switches for this demonstration:
;*
;*       SW6.2, SW6.5: Enable the push buttons
;*       SW6.8 : Enable the LED panel
;*
;* --------------------------------------------------------------------------------------
#include "..\api\maxQ2000.inc"
  .code
  .keep
    ;
    ; Some basic initialization.  Set Accumulator Controls to normal.
    ; Set interrupt vector.  Set data pointer controls.  
    ;
    move  APC, #0                      ; no accumulator-modulo behavior
    move  AP, #0                       ; select accumulator 0
    move  DPC, #0                      ; select DP[0], byte mode
    move  IV, #w:interrupt_handler       ; set interrupt vector

    call  init_push_buttons            ; setup push button configuration
    move  IC, #1                       ; initialize global interrupts

;*****************************************************************************
;
; Main application loop.  Toggle the top two bits twice per loop.  Toggle the
; bottom bit once per loop.  Interrupt handler will take care of everything 
; else.
;
;*****************************************************************************
main_top:
    move  PD0, #0FFh                   ; enable all outputs to the LED bank
    move  PO0, #07Fh                   ; leave just one bit off
    ; 
    ; Set up timer number 0 for single-shot low, long pulse.
    ; This waveform will appear on pin P6.5 and P6.4--on the EV Kit, these
    ; are pins 44 and 46 on header J2.
    ;
    move  T2V0, #0001h                 ;
    move  T2R0, #0001h                 ;
    move  T2C0, #0002h                 ;
  
    move  T2CFG0, #070h                ; use clock source div 128
    move  T2CNB0, #060h                ; 
    move  T2CNA0, #0E0h                ;
    ;
    ; now pushbutton SW4's interrupt will set the single shot bit
    ;

    ; 
    ; Set up timer number 1 to output a 1/3 duty cycle waveform at 100 Hz.
    ; This waveform will appear on pin P6.1 and P6.0--on the EV Kit, these
    ; are pins 52 and 54 on header J2.
    ; 
    move  T2V1, #07C2Ah                ;
    move  T2R1, #07C2Ah                ;
    move  T2C1, #0D40Eh                ;
  
    move  T2CFG1, #020h                ; use clock divided by 4
    move  T2CNB1, #040h                ;
    move  T2CNA1, #048h                ;
  
    ;
    ; Set up timer number 2 to give us periodic interrupts, when we will 
    ; toggle the LED bank.  I will change every 500 ms.  
    ;
    move  T2V2, #03202h                ;
    move  T2R2, #03202h                ;
    move  T2C2, #00002h                ; no compare, don't want that interrupt firing
  
    move  T2CFG2, #070h                ; use clock divided by 128
    move  T2CNB2, #000h                ;
    move  T2CNA2, #088h                ; start the timer, and enable interrupts
  
    move  ACC, IMR                     ; need to mask in module 4, 3 interrupts
    or    #18h                         ; 
    move  IMR, ACC                     ; store new interrupt mask

    ;
    ; Interrupts handle the rest of the application
    ;
    sjump $

;*****************************************************************************
;
; Initialize the push buttons.  We will be using push buttons 10 and 15 in 
; this application.  Set for falling edge triggered interrupts.  Enables 
; interrupts from module 1 in the system interrupt mask.
;
; Input:     None
; Output:    None
; Destroyed: ACC, PSW
;
;*****************************************************************************
init_push_buttons:
    move  EIE1, #84h                   ; enable interrupts for EI 10 and 15
    move  EIES1, #84h                  ; select falling edge for EI 10 and 15
    move  ACC, IMR                     ; get the interrupt mask enable
    or    #2                           ; include interrupts for module 1
    move  IMR, ACC                     ; store new interrupt mask enable value
    ret



;*****************************************************************************
;
; Interrupt handler for the application.  Since our application is in 
; 'sjump $'-land, we don't need to worry about saving anything.
; 
;*****************************************************************************
interrupt_handler:
    move  ACC, EIF1                    ; get the interrupt flag
    and   #4                           ; check for interrupt 10
    jump  z, interrupt_not_10
    ;
    ; External interrupt 10 fired.  Set the single shot bit for timer 0.
    ;
    move  T2CNA0.1, #1                 ; bit 1 triggers single cycle of timer
    ;
    ; Fallthrough to check if other interrupt fired too
    ;
interrupt_not_10:
    move  ACC, EIF1                    ; get the interrupt flag
    and   #80h                         ; check for interrupt 15
    jump  z, interrupt_not_15
    ;
    ; External interrupt 15 fired.  Change polarity on timer 1.
    ;
    move  T2CNA1.6, #0                 ; disable primary output  
    move  T2CNB1.6, #0                 ; disable secondary output  
    move  ACC, T2CNA1                  ; get primary control
    xor   #20h                         ; toggle the polarity bit
    move  T2CNA1, ACC                  ; update the primary control
    move  ACC, T2CNB1                  ; get secondary control
    xor   #20h                         ; toggle the polarity bit
    move  T2CNB1, ACC                  ; update the secondary control
    move  T2CNA1.6, #1                 ; enable primary output  
    move  T2CNB1.6, #1                 ; enable secondary output  
    ;
    ; Fallthrough to check if other interrupts fired too
    ;
interrupt_not_15:
    move  EIF1, #0                     ; clear the interrupt conditions

    ;
    ; See if we got a timer2 firing...
    ;
    move  ACC, T2CNB2                  ; get the timer 2 control bits
    and   #08h                         ;  isolate interrupt flag
    jump  z, interrupt_nottimer2
    move  ACC, PO0                     ; get the output pin states
    rl                                 ; rotate left, NOT through the carry
    ;
    ; However, we want a rotate around 8 bits. We've just done a rotate
    ; around 16 bits...slightly more than we wanted.  Put it in GR and or 
    ; the upper half into the lower half
    ; 
    move  GR, ACC                      ; put it in our 'byte-accessible' register
    or    GRH                          ; upper byte has the bit we want to rotate in
    move  PO0, ACC                     ; we should have just rotated PO0 to the left
    move  T2CNB2.3, #0                 ; clear timer 2 interrupt flags

interrupt_nottimer2:
    ;
    ; See if we got a timer0 firing...
    ;
    move  ACC, T2CNB0                  ; get the timer 0 control bits
    and   #0Ah                         ;  isolate interrupt flags
    jump  z, interrupt_nottimer0
    move  T2CNB0.1, #0                 ; clear timer 0 interrupt flags
    move  T2CNB0.3, #0                 ; clear timer 0 interrupt flags

interrupt_nottimer0:
    ;
    ; Nothing else to check
    ;
    reti

end
