;************************************************************** ; mousetmr.ASM ; Revision 1.01 (Last Revised Nov. 28,1999) ; ;(Copyright 1999, David J. Gacke, All Rights Reserved) ; This source code may be used and modified freely as long as credit is given ; to the original author in the source code as well as the documentation of ; any products derived from it. ; ;*************************** DISCLAIMER - LEGAL STUFF... ********************************************* ; PLEASE READ: USE THIS CODE AT YOUR OWN RISK. The author assumes NO responsibility for the use, or misuse of this ; product/source code. The author also assumes NO responsibility for computer equipment damage that may result ; by the use, misuse, or improper construction of this product. It is released on an AS IS BASIS, all liabilities ; are the END USER'S. ; ;****************************************************************************************************** ; ; ; DEVELOPER NOTES: This is the assembly code for 1/2 of a 2 PIC set. ; This program allows the PIC to generate all the timing signals necessary ; to emulate the Tandy Hi-Res Adapter (TM) Tandy... ; ; In addition, it receives absolute mouse position updates from ; The other PIC via a serial data stream that is clocked to it. ; ;**************************************************************** LIST p=16c505 #include "c:\progra~1\mplab\p16c505.inc" __config _WDT_OFF & _XT_OSC & _MCLRE_OFF & _CP_OFF radix dec ;set default radix to decimal ; ********* DEFINED KEYWORDS ******************************* ; ********* FILE REGISTER ASSIGNMENTS ********************* MOUSEXPOSLSB equ 0x08 ; current mouse x position MOUSEXPOSMSB equ 0x09 ; MOUSEYPOSLSB equ 0x0A ; current mouse y position MOUSEYPOSMSB equ 0x0B ; this timer is a 16bit accumulator for TMR0 BIGTIMERLSB equ 0x0C ; 16 bit timer BIGTIMERMSB equ 0x0D ; NEWMOUSEXPOSLSB equ 0x0E ; new mouse x position NEWMOUSEXPOSMSB equ 0x0F ; NEWMOUSEYPOSLSB equ 0x10 ; current mouse y position NEWMOUSEYPOSMSB equ 0x11 BITCOUNTER equ 0x12 ; counter for the bits clocked in. NEWMOUSEXPOSPLUS4 equ 0x13 ; this keeps the value of the file register position which is NEWMOUSEXPOSLSB+4 = 0x12 ;********************** DEFINED CONSTANTS **************************** ACKOUT equ 0x00 ; bit number of the ack line in port c DATAIN equ 0x01 ; bit number of the data in line on port c DATAVALIDIN equ 0x02 ; bit number of the data valid in line on port c TRISTATEALL equ 0x04 ; bit nomber of the tristate line on port c JOYX equ 0x00 ; bit number of joystick pot in port b JOYY equ 0x01 ; bit number of joystick pot in port b RESETIN equ 0x02 ; bit number of the reset line, this resets the BITCOUNTER variable CASSLINE equ 0x03 ; bit number of CoCo "cassette data" input line on port 5 ; ********* END OF ASSIGNMENTS **************************** STARTUP CODE H'000' startup: ; Main power up initialization takes place here movwf OSCCAL ;calibrating the internal oscillator movlw B'10001000' ; option clrf PORTB clrf PORTC clrf FSR movlw 0 movwf STATUS ; must use movlw 0 on status reg to clear, CANNOT USE CLRF movlw B'00111100' ;trisate all lines except joy outs tris PORTB movlw B'00111110' ;trisate all lines except ACKLINE tris PORTC clrf MOUSEXPOSLSB ;reset mouse x position clrf MOUSEXPOSMSB ; clrf MOUSEYPOSLSB ;reset mouse y position clrf MOUSEYPOSMSB ; clrf NEWMOUSEXPOSLSB ;reset mouse x position clrf NEWMOUSEXPOSMSB ; clrf NEWMOUSEYPOSLSB ;reset mouse y position clrf NEWMOUSEYPOSMSB ; clrf BIGTIMERLSB ;reset 16 bit timer clrf BIGTIMERMSB ; movlw NEWMOUSEXPOSLSB ; move newmousexposlsb into w register movwf FSR ; move w value into FSR clrf BITCOUNTER movlw 0x12 ; load this value into NEWMOUSXPOSPLUS4 movwf NEWMOUSEXPOSPLUS4 clrf TMR0 ; reset the timer ; This is the main loop of the program. In a nutshell, it does this: ; 1. (updatetimer) Updates the software emulated 16 bit timer (see notes below) ; 2. (comparetimertox) Compares that timer value to the current xposition of the mouse, ; and drives JOYX line high if necessary. ; 3. (comparetimertoy) Does same as number 2 except its for the other axis ; 4. Test CASSLINE for high, if so, reset the timer ; 5. Check to see if there are more bits to be clocked in of the 32 bit position update serial stream ; 6. Goto step 1 mainloop: call updatetimer ;update timer call comparetimertox ;check to see if timer value is greater than mouse values, if so drive lines high call comparetimertoy ;check to see if timer value is greater than mouse values, if so drive lines high btfsc PORTB,CASSLINE ; test cassline for high, if high make call call resettimer ; reset bigtimer if cass line is high call checkfornewmousecoords btfss PORTC,TRISTATEALL call tristateports goto mainloop resettimer: ; this "function" resets the timer value of the 16 bit software timer register ; as well as the 8 bit hardware TMR0 register. movlw 0 movwf PORTB ; drive all pins low on port B, this will only affect the 2 joy lines right now, but be careful in future clrf BIGTIMERLSB ;reset 16 bit timer clrf BIGTIMERMSB ; holdresetcondition: btfsc PORTB,CASSLINE ; test cassline for high, if high make call goto holdresetcondition movlw 0x04 ; write 0x04 into TMR0, this is how long it takes to reset the timer movwf TMR0 retlw 0 ;return after timer reset updatetimer: ; this function basically creates a 16 bit timer from the 8 bit one ;it adds the 8 bit timer value to the BIGTIMERLSB and increments ;BIGTIMERMSB if necessary movf BIGTIMERLSB,0 ; move lsb of bittimer into w addwf TMR0,0 ; add timer 0 to lsb btfsc STATUS,C ;check status to see if carry bit is set, if so incr bigtimermsb incf BIGTIMERMSB,1 movwf BIGTIMERLSB ; move result from previous add back out to bigtimerlsb bcf STATUS,C ;clear carry flag, just in case it was set clrf TMR0 movlw 6 ; add an addition 6 to make up for missed clocks on timer reset addwf BIGTIMERLSB,1 ; stor back in lsb btfsc STATUS,C ;check status to see if carry bit is set, if so incr bigtimermsb incf BIGTIMERMSB,1 retlw 0 comparetimertox: ; this function compares the value of the x position to the 16 bit timer value ; if the timer value is larger than the x position value, it drives the JOYX line high btfsc PORTB,JOYX ; first, check to see if the joyx line is already high retlw 0 ; if so, return movf BIGTIMERMSB,0 ; move the MSB of timer into w register subwf MOUSEXPOSMSB,0 ; subtract MSB of timer from mouse MSB, keep result in w reg. btfss STATUS,C ; if timer is greater than msb goto joyxhigh goto joyxhigh btfss STATUS,Z ; if timer is less than msb just return, if equal check low order byte as well retlw 0 movf BIGTIMERLSB,0 ;move the LSB of mouse x position into w register subwf MOUSEXPOSLSB,0 ;subtract LSB of timer btfss STATUS,C ; if timer is greater than lsb goto joyxhigh bsf PORTB,JOYX ;set joy x line high retlw 0 comparetimertoy: ; this function compares the value of the y position to the 16 bit timer value ; if the timer value is larger than the y position value, it drives the JOYY line high btfsc PORTB,JOYY ; first, check to see if the joyy line is already high retlw 0 ; if so, return movf BIGTIMERMSB,0 ; move the MSB of timer into w register subwf MOUSEYPOSMSB,0 ; subtract MSB of timer from mouse MSB, keep result in w reg. btfss STATUS,C ; if timer is greater than msb goto joyyhigh goto joyyhigh btfss STATUS,Z ; if timer is less than msb just return, if equal check low order byte as well retlw 0 movf BIGTIMERLSB,0 ;move the LSB of mouse y position into w register subwf MOUSEYPOSLSB,0 ;subtract LSB of timer btfss STATUS,C ; if timer is greater than lsb goto joyyhigh bsf PORTB,JOYY ; set joy y line high retlw 0 joyxhigh: ; set joy y line high bsf PORTB,JOYX retlw 0 joyxlow: ; set joy x line low bcf PORTB,JOYX retlw 0 joyyhigh: ; set joy y line high bsf PORTB,JOYY retlw 0 joyylow: ;set joy y line low bcf PORTB,JOYY retlw 0 tristateports: movlw B'00111111' ;trisate all lines on both ports tris PORTB tris PORTC holdtristatecondition: btfss PORTC,TRISTATEALL ; if this line is pulled low, hold the tristate condition goto holdtristatecondition ; once line goes high, return teh ports to normal operating state movlw B'00111100' ;trisate all lines except joy outs tris PORTB movlw B'00111110' ;trisate all lines except ACKLINE tris PORTC retlw 0 checkfornewmousecoords: ; this function checks the DATAVALIDIN line to see if its high. ; if so, that means there is a bit ready to be clocked in. ; once we have read teh bit, drive our ACKOUT line high, until the other pic drops ; the DATAVALIDIN signal. then repeat. ; Also, if the RESETIN line is high when DATAVALIDIN goes high, that means to ; reset the bitstream. that is how the data stays framed properly. btfss PORTC,DATAVALIDIN ; if line is low,return goto ackoutlow btfsc PORTC, ACKOUT ; if my ackout was high still, then just return. it goes low when other mcu drops data valid retlw 0 btfsc PORTB,RESETIN ; check to see if reset line is set, if so goto reset routine goto resetmousedata btfss PORTC,DATAIN goto databitlow goto databithigh retlw 0 ackoutlow: bcf PORTC,ACKOUT retlw 0 databitlow: rrf INDF,1 ; rotate bit right 1 bcf INDF,7 ;clear bit 7 of the register pointed to by indf incf BITCOUNTER,1 movlw 8 ; check to see if that was 8th bit subwf BITCOUNTER,0 btfsc STATUS,Z goto fullbyte BSF PORTC, ACKOUT ; ack the bit retlw 0 databithigh: rrf INDF,1 ; rotate bit right 1 bsf INDF,7 ;set bit 0 of the register pointed to by indf incf BITCOUNTER,1 movlw 8 ; check to see if that was 8th bit subwf BITCOUNTER,0 btfsc STATUS,Z goto fullbyte BSF PORTC, ACKOUT ; ack the bit retlw 0 fullbyte: BSF PORTC, ACKOUT ; ack the bit incf FSR,1 ; fill byte, increment FSR register to start next byte movlw 0 movwf BITCOUNTER ; reset bitcounter to 0 movf FSR,0 ;load fsr into w andlw 0x1f ; mask off upper 3 bits, those are 2 bank select bits, and 1 other subwf NEWMOUSEXPOSPLUS4,0; check to see if fsr=mousexposlsb+4 btfss STATUS,Z retlw 0 ; != to 4 just return here ; The following bit shifts are here due to the fact that the mouse was ; not sensitive enough originally; Meaning, it took too much physical ; movement of the mouse to make the pointer move on the screen. bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEXPOSLSB,1 rlf NEWMOUSEXPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEXPOSLSB,1 rlf NEWMOUSEXPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEXPOSLSB,1 rlf NEWMOUSEXPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEXPOSLSB,1 rlf NEWMOUSEXPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEYPOSLSB,1 rlf NEWMOUSEYPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEYPOSLSB,1 rlf NEWMOUSEYPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEYPOSLSB,1 rlf NEWMOUSEYPOSMSB,1 bcf STATUS,C ; clear carry before the rotate rlf NEWMOUSEYPOSLSB,1 rlf NEWMOUSEYPOSMSB,1 ; copy the newly received coordinate set over the top of the old coordinates movf NEWMOUSEXPOSLSB, 0 ;load the lsb into the w register movwf MOUSEXPOSLSB ; write int the mousexposlsb movf NEWMOUSEXPOSMSB, 0 ;load the msb into the w register movwf MOUSEXPOSMSB ; write int the mousexposmsb movf NEWMOUSEYPOSLSB, 0 ;load the lsb into the w register movwf MOUSEYPOSLSB ; write int the mouseyposlsb movf NEWMOUSEYPOSMSB, 0 ;load the msb into the w register movwf MOUSEYPOSMSB ; write int the mouseyposlsb movlw NEWMOUSEXPOSLSB ; reset FSR bat to start of mouse pos registers movwf FSR retlw 0 resetmousedata: movlw 0 movwf BITCOUNTER ; if line is NOT high, reset BITCOUNTER, and make it HIGH movlw NEWMOUSEXPOSLSB ; move the memory address of the lsb of new x into w movwf FSR ; write that value in the fsr reg bsf PORTC,ACKOUT ; set high retlw 0 ; return here END