$BASE 10T
;**************************************************************************
;                            "TEMPLATE"
;
;                   Version 1.0  Revised 3/2/2003
;
;                        George Heron, N2APB
;                        2419 Feather Mae Ct.
;                        Forest Hill, MD  21050
;                        email: n2apb@amsat.org
;
; This program serves as a standard "starting point", or template, for developing
; other programs.  It's useful because it contains all the basic elements of a
; regular user application program.
;
; This code is intended to run on a Motorola 68HC908AB32 microcontroller and is
; best assembled within the Integrated Development Environment editor, provided free
; by Motorola as part of their HC908 development tool suite.
;
; Revision History:
; ----------------
; 1     3/2/2003      Initial version
;
;**************************************************************************
; Copyright 2003 by G. Heron, N2APB.  All rights reserved. For personal, non-profit use only.
;**************************************************************************

        include "../AB_REGS.INC"            ;MC68HC908GP32 register defimitions
        include "../macros.inc"             ;Macro instruction definition
        include "../local.inc"              ;Local variables

RAMStart     equ  $0053         ;User App RAM is from 53 to 3FF. (HCmon RAM from 400-44F)
EEPROM       equ  $800          ;EEPROM mem is 800-9FF (512 bytes)
RomStart     equ  $8000         ;Flash mem is 8000 to FFFF (32 MB)

                                ;Port A pin usage
LCD_e        equ  3               ;LCD enable = bit 3 of porta
LCD_rw       equ  2               ;LCD read/write. 0=write, 1=read
LCD_rs       equ  1               ;LCD register select. 0=instruction, 1=data

                                ;Port B pin usage
Reflect-FWD  equ  2               ;Reflectometer Forward Voltage
Reflect-REF  equ  1               ;Reflectometer Reflected Voltage
Reflect-Z    equ  0               ;Reflectometer Impedance Voltage

                                ;Port C Usage
Dah          equ  5               ;Dah paddle input
Dit          equ  2               ;Dit paddle input
Keyline      equ  1               ;Keyline control to transmitter
FreqCntr     equ  0               ;Frequency counter input

                                ;Port D pin usage
Tones        equ  2               ;Tones signal to audio amp

                                ;Port E Usage
Piezo        equ  2               ;Piezo sounder
RxData       equ  1               ;serial port receive
TxData       equ  0               ;serial port transmit

                                ;PortF pin usage
Mon_Jumper   equ  7               ;Monitor jumper
HeartbeatLED equ  6               ;Heartbeat LED
ENC_A        equ  5               ;Encoder-A pin
ENC_B        equ  4               ;Encoder-B pin
ENC_pb       equ  3               ;Encoder-Pushbutton pin
DDS_load     equ  2               ;DDS load pin
DDS_clk      equ  1               ;DDS clock pin
DDS_data     equ  0               ;DDS data pin

    org RamStart

_hbufpos     rmb  2               ;buffer position temp storage

Timeout1     ds   1               ;Allows three timeout routines to be called each of which
Timeout2     ds   1               ;can run for up to ~ 1/2 second.
Timeout3     ds   1

Piezo_temp   ds   1               ;piezo temp variable

Enc_tens     ds   1               ;encoder display digit (tens)
Enc_units    ds   1               ;encoder display digit (ones)

LCD_timer    ds   1               ;counter for timeout check in LCD busy_check
LCD_read     ds   1               ;temp store for status read in LCD busy_check
LCD_char     ds   1               ;temp for LCD data written (cmnd2LCD & data2LCD)
temp1        ds   1               ;temp store used in write_LCD
temp2        ds   1

temp         ds   1               ;temp used in EEPROM driver

enc_new      ds   1               ;new reading of encoder
enc_old      ds   1               ;last reading of encoder
enc_temp     ds   1               ;temp location for encoder bits
A_flag       ds   1               ;enc line A hi/lo status
B_flag       ds   1               ;enc line B hi/lo status

a2d_last     ds   1               ;previous A/D reading
a2d_lasta    ds   1               ;previous A/D reading + 1
a2d_lastb    ds   1               ;previous A/D reading - 1

bit_count    ds   1               ;DDS bit counter
byte_count   ds   1               ;DDS byte counter
byte2send    ds   1               ;DDS byte to send
DDS_w4       ds   1               ;DDS programming register W4 (freq-b7  ...  freq-b0)
DDS_w3       ds   1               ;DDS programming register W3 (freq-b15 ...  freq-b8)
DDS_w2       ds   1               ;DDS programming register W2 (freq-b23 ...  freq-b16)
DDS_w1       ds   1               ;DDS programming register W1 (freq-b31 ...  freq-b24)
DDS_w0       ds   1               ;DDS programming register W0 (phase-b4 ...  control-0)

count_lo     ds   1
count_hi     ds   1
to_addr      ds   2               ;index pointer storage locs
from_addr    ds   2

EEbyte_count ds   1               ;EEPROM byte counter
EEline_count ds   1               ;EEPROM line counter

    org $040A                     ;common "_inbuf" buffer with HCmon
_inbuf       rmb  RXBLEN          ;Input Buffer

    org RomStart

;**************************************************************************
;   Vector Jump Table (located at start of User Area = 8000)
;**************************************************************************

_user_adc         jmp    Dummy_ISR      ; Insert jump to ADC vector code
_user_keyboard    jmp    Dummy_ISR      ; Insert jump to Keyboard vector code
_user_scitx       jmp    Dummy_ISR      ; Insert jump to SCI transmit vector code
_user_scirx       jmp    Dummy_ISR      ; Insert jump to SCI receive vector code
_user_scierr      jmp    Dummy_ISR      ; Insert jump to SCI error vector code
_user_timbch3     jmp    Dummy_ISR      ; Insert jump to TIMB Channel 3 Vector code
_user_timbch2     jmp    Dummy_ISR      ; Insert jump to TIMB Channel 2 Vector code
_user_spitx       jmp    Dummy_ISR      ; Insert jump to SPI transmit vector code
_user_spirx       jmp    Dummy_ISR      ; Insert jump to SPI receive vector code
_user_timb_of     jmp    Dummy_ISR      ; Insert jump to TIMB Overflow Vector code
_user_timb_ch1    jmp    Dummy_ISR      ; Insert jump to TIMB Channel 1 Vector code
_user_timb_ch0    jmp    Dummy_ISR      ; Insert jump to TIMB Channel 0 Vector code
_user_tima_of     jmp    Dummy_ISR      ; Insert jump to TIMA Overflow Vector code
_user_tima_ch3    jmp    Dummy_ISR      ; Insert jump to TIMA Channel 3 Vector code
_user_tima_ch2    jmp    Dummy_ISR      ; Insert jump to TIMA Channel 2 Vector code
_user_tima_ch1    jmp    T_ISR          ; Insert jump to TIMA Channel 1 Vector code
_user_tima_ch0    jmp    Dummy_ISR      ; Insert jump to TIMA Channel 0 Vector code
_user_tim_of      jmp    Dummy_ISR      ; Insert jump to TIM Overflow Vector code
_user_pll         jmp    Dummy_ISR      ; Insert jump to PLL Vector code
_user_irq         jmp    Dummy_ISR      ; Insert jump to ~IRQ1 Vector code

_HCmon_LCD_disp   jmp    HCmon_LCD_disp ; vector (at $803C) for HCmon
                                        ; to display message to LCD

;**************************************************************************
;**********************      USER APP ENTRY POINT     *********************
;**************************************************************************
;        This is the point ($8040) where User Code starts executing       *
;        after coming from the Monitor "X" command (eXecute User App)     *
;        or after board gets a RESET (when Monitor jumper is off)         *
;**************************************************************************

        org     $8040

Start:
        sei                            ;disable all interrupts
        ldhx    #$01FF                 ;initialize
        txs                            ;  the stack pointer (why not 3FF?)
        mov     #$FF,ddra              ;set porta as outputs
        mov     #$02,ddre              ;set port E2 as output

        lda     portf                  ;get initial encoder position
        and     #$30                   ;isolate the encoder bits
        sta     enc_old                ;initialize encoder old value

        jsr     Init_Timer
        clr     timeout1               ;init timeouts (0=off)
        clr     timeout2
        clr     timeout3
        cli                            ;allow interrupts to happen

;**************************************************************************
;*****************      USER APPPLICATION MAINLINE      *******************
;**************************************************************************

User_Main:
        mov     #3,timeout1            ;Start an A/D conversion in 3*2ms=6ms
        ldhx    #TemplateBanner_msg
        jsr     _puts                  ;print Exerciser Banner message

Main_Loop:
        sta     copctl                 ;clear the COP counter
        bra     Main_Loop

TemplateBanner_msg:  fcb    'Template Program',CR,LF,0




;**************************************************************************
;***************      HCmon_LCD_disp        *******************************
;*     Routine called from HCmon to display message to LCD                *
;**************************************************************************

HCmon_LCD_disp:
        jsr     LCD_init
        jsr     LCD_clear
        ldhx    #mon_msg1
        jsr     disp_msg
        lda     #$C0
        jsr     cmnd2lcd
        ldhx    #mon_msg2
        jsr     disp_msg
        rts

mon_msg1:
        fcb     'HCmonitor v1.0',0

mon_msg2:
        fcb     'G.Heron N2APB',0


$page
;**************************************************************************
;*****************       DELAY ROUTINES     *******************************
;**************************************************************************

;--------------------------------------------------------------------------
;   Delay -- This subroutine performs a simple software delay loop based upon
;            the value passed in ACC. The following timing calculation applies:
;               delay = ((ACC * 74) + 12) (tcyc)

delay:
        psha                           ;[2] save delay parameter temporarily
delay1:
        lda #22T                       ;[2] initialize 5us loop counter
                                       ;     (repeat for timing)
delay2:
        dbnza delay2                   ;[3] decrement inner delay loop counter
        dbnz 1,sp,delay1               ;[6] decrement outer delay loop counter
        pula                           ;[2] deallocate local variable
        rts                            ;[4] return

;--------------------------------------------------------------------------
; Wait500ms -- Waits here for (10 x 50 x 1ms) = 500ms

wait500ms:
        lda     #10
        sta     count_hi
w500m1: lda     #$50
        sta     count_lo
w500m2: jsr     wait1ms
        dbnz    count_lo,w500m2
        dbnz    count_hi,w500m1
        rts

;--------------------------------------------------------------------------
; Wait100ms-- Waits here for 100ms

wait100ms:
        lda     #100
w100a:  psha
        bsr     wait1ms
        pula
        dbnza   w100a
        rts

;--------------------------------------------------------------------------
; Wait64ms-- Waits here for 64ms

wait64ms:
        lda     #64
w64a:   psha
        bsr     wait1ms
        pula
        dbnza   w64a
        rts

;--------------------------------------------------------------------------
; Wait50ms-- Waits here for 50ms

wait50ms:
        mov     #16,timeout1
w50a:   tst     timeout1
        bne     w50a
        rts

;--------------------------------------------------------------------------
; Wait32ms-- Waits here for 32ms

wait32ms:
        lda     #32
w32a:   psha
        bsr     wait1ms
        pula
        dbnza   w32a
        rts

;--------------------------------------------------------------------------
; Wait64ms-- Waits here for 16ms

wait16ms:
        lda     #16
w16a:   psha
        bsr     wait1ms
        pula
        dbnza   w16a
        rts

;--------------------------------------------------------------------------
; Wait10ms-- Waits here for 10ms

Wait10ms:
        lda     #10
w10a:   psha
        bsr     wait1ms
        pula
        dbnza   w10a
        rts

;--------------------------------------------------------------------------
; Wait1ms-- Waits here for 1ms

wait1ms:
        lda     #10
w1msa:  psha
        bsr     wait100us
        pula
        dbnza   w1msa
        rts

;--------------------------------------------------------------------------
; Wait100us -- Waits here for 100us
;              1 cycle = .11454545 US
;              (137 x (5 x .11454545)) + (6 x .11454545)
;              (174 x .5727) + .687 = 100 us

wait100us:
        lda     #174       ; [2]
w100u:  deca               ; [1]
        nop                ; [1]
        bne     w100u      ; [3]
        rts                ; [4]

;--------------------------------------------------------------------------
; Wait1us -- Waits here for 1us

wait1us:
        lda     us1
        dbnza   *
        rts


;*************************************************************
;*****************     TIMER MODULE    ***********************
;*************************************************************

;-------------------------------------------------------------
; Init_Timer - Turns on timer A channel 1 for an Output
;              Compare in approximately 2ms. Creates an interrupt
;              vector to the Timer ISR (T_ISR), where Timeout1,
;              Timeout2 and Timeout3 are decremeted. If a timer
;              reaches 0, then a user-specified operation is
;              done.  Thus, the user can either set a timer in his
;              code and sit there waiting on it to become 0, or
;              he may place the timeout action routine right here
;              in the Timer Handlers.  We use the latter technique
;              for the "heartbeat" LED blink. We set Timeout1 to
;              FF in the Timer1 Handler below, and when 256 ticks
;              of the 2ms timer interrupt occur, we toggle the state
;              of the heartbeat LED and reset Timeout1 to occur again
;              in another 256 ticks.


Init_Timer:
       mov   #$36,TASC     ; Timer A - Cleared + Stopped.
                           ;    Clicks once every 64 BUS Cycles
                           ;    77t Clicks ~ 2ms

       mov   #$0,TACH1H    ; Set Output Compare to happen 77T clicks
       mov   #77T,TACH1L   ; after we start the timer. (~2ms). The
                           ; timer interrupt will set OC for another ~2ms.

       mov   #$54,TASC1    ; Timer A Channel 1
                           ; Set for Output Compare operation.

       mov   #$06,TASC     ; Start the timer
       rts


**************************************************************
* T_ISR - Timer Interrupt Service Routine.                   *
*             after a RESET.                                 *
**************************************************************
T_ISR:
       pshh
       pshx
       psha
       lda   tasc1
       and   #$7f
       sta   tasc1              ; Clear O.C. Flag
       ldhx  tach1h
       aix   #77T               ; Setup another interrupt in ~2ms
       sthx  tach1h

Check_t1:
       tst timeout1
       beq check_t2             ; Is Timeout 1 currently active?
       dec timeout1             ;   yes
       bne check_t2             ; Did it just finish counting down?
       jsr t1_handler           ;   Yes - Execute Timeout 1 handler

Check_t2:
       tst timeout2
       beq check_t3             ; Is Timeout 2 currently active?
       dec timeout2             ;   yes
       bne check_t3             ; Did it just finish counting down?
       jsr t2_handler           ;   Yes - Execute Timeout 2 handler

Check_t3:
       tst timeout3
       beq done_tisr            ; Is Timeout 3 currently active?
       dec timeout3             ;   yes
       bne done_tisr            ; Did it just finish counting down?
       jsr t3_handler           ;   Yes - Execute Timeout 3 handler

done_tisr:
       pula
       pulx
       pulh
       rti

****************************************************************
* Timeout Handlers - All the user has to do is set one of the  *
*                    timeout variables to any number n (1-255) *
*                    and the timeout handler will be executed  *
*                    in 2*n milliseconds. Setting the timeout  *
*                    variable from within the handler will     *
*                    cause a periodic timeout as shown in      *
*                    timeout 1.                                *
****************************************************************
t1_handler:
       lda     #$FF
       sta     timeout1
       brclr   6,portF,t1a      ;toggle heartbeat LED
       bclr    6,portF
       rts
t1a:   bset    6,portF
       rts

t2_handler:
       nop
       rts

t3_handler:
       nop
       rts

**************************************************************
* DUMMY_ISR - Dummy Interrupt Service Routine.               *
*             Just does a return from interrupt.             *
**************************************************************
dummy_isr:
       nop
       rti           ; return

**************************************************************
* UTILS - Utilities and routines shared from HCmon           *
**************************************************************

      include "../drivers.s"     ;drivers for Shaft Enc, LCD, EEPROM, DDS

**************************************************************
* UTILS - Utilities and routines shared from HCmon           *
*         Just link to routines in HCmon                     *
*         (But remember to adjust jump addresses if HCmon    *
*         ever changes!)                                     *
**************************************************************

;        include "../utils.s"    ;this is the alternative (but replicates code!)

_sp_gets:     jmp   $F4DB
_gets:        jmp   $F4EE
_ahex2b:      jmp   $F53F
_a2nibhex:    jmp   $F54D
_dblchar:     jmp   $F556
_nib_to_asc:  jmp   $F561
_comma_sp:    jmp   $F56C
_pr_letter_x: jmp   $F577
_pr_pound:    jmp   $F57C
_pr_comma:    jmp   $F581
_crlf:        jmp   $F586
_byte_sp:     jmp   $F58F
_space:       jmp   $F592
_pr_nibble:   jmp   $F599
_putch:       jmp   $F59C
_pwordx:      jmp   $F5A5
_pword:       jmp   $F5AD
_pbyte_sp:    jmp   $F5B9
_pbytex:      jmp   $F5BD
_pbyte:       jmp   $F5BE
_ischar:      jmp   $F5CD
_getchne:     jmp   $F5D7
_getch:       jmp   $F5E1
_do_again:    jmp   $F5F6
_puts_lp:     jmp   $F602
_puts:        jmp   $F60A
_gethexbyte:  jmp   $F60E
_get_atbl:    jmp   $F62E
_tohex:       jmp   $F641
_ishex:       jmp   $F64A
_clr_spaces:  jmp   $F660
_next_hex:    jmp   $F66C
_first_hex:   jmp   $F677
_gethex:      jmp   $F67E
_readhex:     jmp   $F686
_numck_lp:    jmp   $F689
_dis_asm:     jmp   $F6FA



