$BASE 10T ;************************************************************************** ; "EXERCISER" ; DIGITAL QRP BREADBOARD ; ; Version 1.0 04/10/2003 ; ; George Heron, N2APB ; 2419 Feather Mae Ct. ; Forest Hill, MD 21050 ; email: n2apb@amsat.org ; ; This program is the initial application that comes pre-loaded on the HC908 Daughtercard. ; It sits in "User Application" area of memory ($8000-$EEFF) and co-resides ; with the HCmon debug monitor also on the Daughtercard (at $EF00-$FFDE). ; ; "Exerciser" is a simple application that is controlled via the RS-232 serial port ; and is used to demonstrate use of typical I/O peripherals one might use with the ; processor. Exerciser provides a set of library routines and drivers for the various ; hardware components comprising the Digital Breadboard project: LCD, keypad, ; DDS, A/D Converter, shaft encoder and EEPROM. These library routines ; are individually selectable from a menu presented sent to the serial ; port, allowing the user to invoke any of the functions for test purposes. ; Further, the user may conveniently modify the Exerciser program to serve as the starting ; point for custom program development. ; ; For complete documentation and design details, see the web pages devoted for this ; project at www.njqrp.org/hc908_resource_page ; ; 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. See the HC908 Resource Page ; for full details on obtaining this development software. ; ; Revision History: ; ---------------- ; 1.0 04/10/2003 Initial release ; ;************************************************************************** ; 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 system 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?) ;configure the output ports mov #$FC,ddre ;set port E7-E2 as outputs mov #$47,ddrf ;set port F6, F2-F0 as outputs mov #$FE,ddrb ;set port B7-B1 as outputs mov #$03,ddrh ;set port H1-H0 as outputs mov #$07,ddrg ;set port G2-G0 as outputs mov #$FF,ddrd ;set port D7-D0 as outputs mov #$34,ddrc ;set port C5, C4 and C2 as outputs ;initialize the output ports mov #$FF,portb mov #$FF,portC mov #$FF,portd mov #$FF,porte mov #$FF,portg mov #$FF,porth bset 2,portF bset 1,portf bset 0,portf lda portf ;get initial encoder position and #$30 ;isolate the encoder bits sta enc_old ;initialize encoder old value sta enc_new ;initialize encoder new value mov #$FF,A_flag mov #$FF,B_flag jsr Init_Timer jsr Init_EEPROM 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 jsr LCD_init sta copctl ;clear the COP counter lda #100 jsr delay ldhx #ExerciserBanner jsr _puts ;print Exerciser Banner message ldhx #ExerciserMsg jsr disp_msg um1: ldhx #Prompt jsr _puts ;print prompt ("Exerciser> ") jsr _gets ;get an input string bcs um1 ;not valid char (ctl+C or ESC), try again lda _inbuf ;get the character beq um1 ;nothing entered (just ENTER), try again and #$DF ;turn to capital letter ldhx #_cmdtab ;point to the command table jsr _get_atbl ;get the routine corresponding to the menu entry bcc um2 ;menu item not recognized, print error and try again jsr ,x ;call the selected menu routine bra um1 ;go get another command um2: ldhx #Err_Msg ;"What?" jsr _puts bra um1 ExerciserBanner: fcb CR,LF,CR,LF,'~~ Digital Breadboard Exerciser v1.0 G. Heron N2APB ~~',CR,LF,0 Prompt: fcb CR,LF,CR,LF,'Excerciser (D,S,L,V,Y,E,W,R,T,A,X,H) >',0 Err_Msg: fcb CR,LF,'What?',0 ExerciserMsg: fcb 'Exerciser v1.0',0 ;******************************************************************** ;**************** COMMAND LOOKUP TABLE ***************** ;******************************************************************** _cmdtab: fcb 'D' fdb DDS fcb 'S' fdb Shaft_Encoder fcb 'L' fdb LED_Port_Test fcb 'Y' fdb Display_Test fcb 'E' fdb Erase_EEPROM fcb 'W' fdb Write_EEPROM fcb 'R' fdb Read_EEPROM fcb 'T' fdb Timing_Test fcb 'A' fdb ADC_Test fcb 'H' fdb Help fcb 'X' fdb Monitor fcb NUL $page ;******************************************************************** ;***************** COMMAND PROCESSORS ***************** ;******************************************************************** ;------------------------ ; DDS -- Command 'D' ;------------------------ DDS: ldhx #Freq_Msg ;"DDS Freq set to 10 MHz" jsr _puts ;put string to serial terminal mov #$01,DDS_w4 ;test DDS programming data mov #$EE,DDS_w3 mov #$09,DDS_w2 mov #$00,DDS_w1 mov #$00,DDS_w0 jsr set_dds ;set the DDS rts Freq_Msg: fcb CR,LF,' DDS Freq set to 10 MHz',0 ;------------------------------ ; Shaft Encoder -- Command 'S' ;------------------------------ Shaft_Encoder: ldhx #Enc_Msg ;"Shaft Encoder (Special)" jsr _puts ;put string to serial terminal jsr LCD_Clear jsr Wait64ms jsr ClearLCDLine2 jsr Wait64ms lda #$C0 ;point to 2nd line on LCD jsr Cmnd2LCD ldhx #EncoderMsg jsr Disp_Msg mov #$30,enc_tens ;init the turns counter mov #$30,enc_units se1: jsr Do_Special_Encoder ;process the encoder turns bne se2 jsr decrease_digit_display ;CCW turn detected bra se1 se2: jsr increase_digit_display ;CW turn detected bra se1 rts Enc_Msg: fcb CR,LF,' Shaft Encoder (Special) - to exit',0 EncoderMsg: fcb 'Encoder = 00',0 ;----------------------- ;encoder turned down (ccw) Decrease_Digit_Display: dec enc_units ;decrement units digit lda #$2F ;units at min? cmp enc_units beq dwn1a ;yes, roll down bra dwn1b ;no,just continue dwn1a: mov #$39,enc_units ;roll down units to 9 dec enc_tens ;and decr tens lda #$2F cmp enc_tens ;tens at min? beq dwn1c ;yes, reset cntr to 00 bra dwn1b ;no, just continue dwn1c: lda #$39 sta enc_units ;reset tens to zero sta enc_tens ; and units to zero dwn1b: jsr update_digits ;update counter digits rts ;----------------------------------- ;encoder turned up (cw) Increase_Digit_Display: inc enc_units ;increment units digit lda #$3A ;units at max? cmp enc_units beq up1a ;yes, roll over bra up1b ;no, just continue up1a: mov #$30,enc_units ;roll over units to zero inc enc_tens ;and bump tens lda #$3A ;tens at max? cmp enc_tens beq up1c ;yes, reset cntr to 00 bra up1b ;no, just continue up1c: lda #$30 sta enc_units ;reset tens to zero sta enc_tens ; and units to zero up1b: jsr update_digits ;update counter digits rts ;------------- update_digits: lda #$CA ;point to tens digit on 2nd line jsr Cmnd2LCD lda enc_tens ;send the tens digit there jsr Data2LCD lda #$CB ;point to units digit on 2nd line jsr Cmnd2LCD lda enc_units ;send the units digit there jsr Data2LCD rts ;------------------------------ ; LED Port Test -- Command 'L' ;------------------------------ LED_Port_Test: ldhx #LED_Msg ;"LED Port Test" jsr _puts ;put string to serial terminal bclr 5,portc jsr Wait_LED bset 5,portc bclr 4,portc jsr Wait_LED bset 4,portc bclr 2,portc jsr Wait_LED bset 2,portc bclr 2,portf jsr Wait_LED bset 2,portf bclr 1,portf jsr Wait_LED bset 1,portf bclr 0,portf jsr Wait_LED bset 0,portf bclr 1,portg jsr Wait_LED bset 1,portg bclr 0,portg jsr Wait_LED bset 0,portg bclr 7,porte jsr Wait_LED bset 7,porte bclr 6,porte jsr Wait_LED bset 6,porte bclr 1,portd jsr Wait_LED bset 1,portd bclr 2,portg jsr Wait_LED bset 2,portg bclr 1,portb jsr Wait_LED bset 1,portb bclr 3,portb jsr Wait_LED bset 3,portb bclr 5,portb jsr Wait_LED bset 5,portb bclr 7,portb jsr Wait_LED bset 7,portb bclr 2,portb jsr Wait_LED bset 2,portb bclr 4,portb jsr Wait_LED bset 4,portb bclr 6,portb jsr Wait_LED bset 6,portb bclr 0,portd jsr Wait_LED bset 0,portd bclr 3,portd jsr Wait_LED bset 3,portd bclr 2,portd jsr Wait_LED bset 2,portd bclr 0,porth jsr Wait_LED bset 0,porth bclr 4,portd jsr Wait_LED bset 4,portd bclr 6,portd jsr Wait_LED bset 6,portd bclr 1,porth jsr Wait_LED bset 1,porth bclr 5,portd jsr Wait_LED bset 5,portd bclr 7,portd jsr Wait_LED bset 7,portd bclr 3,porte jsr Wait_LED bset 3,porte bclr 4,porte jsr Wait_LED bset 4,porte bclr 5,porte jsr Wait_LED bset 5,porte rts Wait_LED: jsr Wait64ms rts LED_Msg: fcb CR,LF,' LED Port Test',0 ;------------------------------ ; Timing Test -- Command 'T' ;------------------------------ Timing_Test: ldhx #Timing_Msg ;"Timing Test (reset to exit)" jsr _puts ;put string to serial terminal sei tt1: bset HeartbeatLED,portF ; jsr Wait100us ;change this Wait to reflect desired test bclr HeartbeatLED,portF ;else, without the waits, it's a cycle timing test ; jsr Wait100us ;change this Wait to reflect desired test bra tt1 cli rts Timing_Msg: fcb CR,LF,' Cycle Timing (reset to exit)',0 ;------------------------------ ; Read EEPROM -- Command 'R' ;------------------------------ Read_EEPROM: ldhx #Read_Msg ;"EEPROM = " jsr _puts ;put string to serial terminal ldhx #$800 ;EEPROM mem is 800-9FF mov #32,EEline_count ;32 lines of EEPROM to display ree1: mov #16,EEbyte_count ;display 16 bytes/line ree2: lda ,x ;get the EEPROM byte jsr _pbyte ;else print the char to the terminal jsr _space aix #1 dbnz EEbyte_count,ree2 ;not done with current line of 16 yet jsr _crlf dbnz EEline_count,ree1 ;not do with all 32 lines of EEPROM yet rts Read_Msg: fcb CR,LF,' EEPROM Memory (800-9FF):',CR,LF,0 ;------------------------------ ; Erase EEPROM -- Command 'E' ;------------------------------ Erase_EEPROM: jsr Erase_EEPROM_All ;clear all 512 locations ldhx #Erase_Msg ;"EEPROM addresses 800-9FF now erased!" jsr _puts ;put string to serial terminal rts Erase_Msg: fcb CR,LF,' EEPROM addresses 800-9FF now erased!',0 ;------------------------------ ; Write EEPROM -- Command 'W' ;------------------------------ Write_EEPROM: ldhx #Write_Msg ;"Enter EEPROM data to be written: " jsr _puts ;put string to serial terminal jsr _gets ;get an input string bcs we_exit ;if ctl+C or ESC, exit lda _inbuf ;get the character beq we_exit ;nothing entered (just ENTER), exit ;transfer from input buffer to EEPROM ldhx #$800 ;start of EEPROM = 800 sthx to_addr ldhx #_inbuf ;point to start of input buffer sthx from_addr we1: ldhx from_addr lda ,x ;get char from input buffer beq we_exit ;exit if EOT terminator found (0) incx sthx from_addr ldhx to_addr jsr Write_EEPROM_byte ;write reg A to loc (hx) in EEPROM area incx sthx to_addr bra we1 we_exit: rts Write_Msg: fcb CR,LF,' Enter EEPROM data to be written: ',0 ;------------------------------ ; Display Test -- Command 'Y' ;------------------------------ Display_Test: jsr ClearLCDline2 ldhx #DispTst_Msg ;"LCD Display Test" jsr _puts ;put string to serial terminal jsr LCD_clear ;clear the LCD jsr Wait64ms lda #$80 ;point to first char, line 1 jsr Cmnd2LCD ldhx #Line1Msg jsr Disp_Msg ;display line 1 test message lda #$C0 ;point to first char, line 2 jsr Cmnd2LCD ldhx #Line2Msg jsr Disp_Msg rts DispTst_Msg: fcb CR,LF,' Display Test',0 Line1Msg: fcb 'ABCDefghIJKLmnop',0 Line2Msg: fcb 'QRSTuv0123456789',0 ;-------------------------------------- ; Analog-to-Digital Test -- Command 'A' ;-------------------------------------- ADC_Test: ldhx #ADC_Msg ;"Analog-To-Digital (ADC) Test" jsr _puts ;put string to serial terminal ldhx #ADC_Msg_LCD lda #$C0 ;point to 1st char line 2 jsr Cmnd2LCD jsr Disp_Msg ;put string to LCD mov #$70,ADCLK ;select clock divide of 011 ; and set the ADICLK bit adc_start: mov #$00,ADSCR ;clear COCO, AIEN, ADCO ; and specify port 0, and start a conversion adc_wait: brclr 7,ADSCR,adc_wait ;wait for Conversion Complete (COCO) lda ADR ;read the A/D register psha sub a2d_last ;compare to last reading pula beq adc_start ;go back and read again if same sta a2d_last ;else save new value jsr _pbyte ;and output it jsr _crlf lda #$C6 ;point to digit position on 2nd line jsr Cmnd2LCD lda a2d_last ;get the A/D data value back again nsa ;swap upper/lower nibbles jsr _nib_to_asc ;convert the upper nibble to ascii jsr data2LCD ;and display it lda #$C7 ;point to digit position on 2nd line jsr Cmnd2LCD lda a2d_last ;get the A/D data value back again jsr _nib_to_asc ;convert the lower nibble to ascii jsr data2LCD ;and display it jsr Wait64ms bra adc_start ;go trigger another conversion ADC_Msg: fcb CR,LF,' Analog-To-Digital Converter',0 ADC_Msg_LCD: fcb 'A/D = ',0 ;------------------------------ ; Exit to Monitor -- Command 'X' ;------------------------------ Monitor: swi ; Software Interrupt enters HCmon rts ;------------------------------------------- ; Help -- Command 'H' ;------------------------------------------- Help: ldhx #Help_Msg ;"Help Menu" jsr _puts ;put string to serial terminal rts Help_Msg: fcb CR,LF fcb 'Help Menu ',CR,LF fcb '========= ',CR,LF fcb ' D = DDS Set ',CR,LF fcb ' S = Shaft Enc ',CR,LF fcb ' L = LED Ports ',CR,LF fcb ' Y = Display Test',CR,LF fcb ' E = Erase EEPROM',CR,LF fcb ' W = Write EEPROM',CR,LF fcb ' R = Read EEPROM ',CR,LF fcb ' T = Timing Test ',CR,LF fcb ' A = ADC Test ',CR,LF fcb ' X = Exit to HCmon',CR,LF fcb ' H = Help ',CR,LF fcb 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 255 ticks ; of the 2ms timer interrupt occur, we toggle the state ; of the heartbeat LED and reset Timeout1 to occur again ; in another 255 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 #255 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