$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