;________________________ GLOBAL LABELS _______________________________________ _P1DDR EQU $0000 ;Port 1 data direction register. _P1DR EQU $0002 ;Port 1 data register. _TCSR EQU $0008 ;Timer: control & status register. _FRC EQU $0009 ;Timer: 16 bit free running counter. _OCR EQU $000B ;Timer: 16 bit output compare register. _ICR EQU $000D ;Timer: 16 bit input capture register. _RMCR EQU $0010 ;SCI: rate & mode control register. _TRCSR EQU $0011 ;SCI: transmit/receive control & status register. _RDR EQU $0012 ;SCI: receive data register. _TDR EQU $0013 ;SCI: transmit data register. _IRAM EQU $0080 ;Internal RAM $0080..$00FF (128byte). _XRAM EQU $2000 ;External RAM $2000..$3FFF (8192byte). _DDRA EQU $6000 ;PIA: Data direction / Periferial register A. _CRA EQU $6001 ;PIA: Control register A. _DPRB EQU $6002 ;PIA: Data direction / Periferial register B. _CRB EQU $6003 ;PIA: Control register B. _WAD12 EQU $6010 ;A/D converter: trigger 12bit conversion. _RMS EQU $6010 ;A/D converter: read MSB bit7..bit0 _WAD8 EQU $6011 ;A/D converter: trigger 8bit conversion. _RLS EQU $6011 ;A/D converter: read LSB bit7..bit4 _RSF EQU $6012 ;A/D converter: read status flag. _MUX EQU $6012 ;Multiplexer: write select channel. _LSA EQU $6020 ;D/A converter A: input register LSB bit7..bit0. _MSA EQU $6021 ;D/A converter A: input register MSB bit3..bit0. _LSB EQU $6022 ;D/A converter B: input register LSB bit7..bit0. _MSB EQU $6023 ;D/A converter B: input register MSB bit3..bit0. _WDA12 EQU $6030 ;D/A converter: trigger 12bit conversion. _KBDD EQU $8000 ;Keyboard data (Read only). _LEDD EQU $A000 ;LED display (Write only). _SYROM EQU $C000 ;System EPROM $C000..$DFFF (8192byte). _EPROM EQU $E000 ;User EPROM $E000..$FFFF (8192byte). ;======================== EPROM $E000..$FFFF ================================== ORG _EPROM ;________________________ TASK SCHEDULE _______________________________________ SCHTAB FDB ST_IMP FDB SCI FDB SCI FDB SCI FDB ST_IMP FDB SCI FDB SCI FDB SCI FDB ST_IMP FDB SCI FDB SCI FDB SCI FDB ST_IMP FDB SCI FDB SCI FDB SCI SCHRTS rts ;________________________ THE SCHEDULER INTERRUPT RUTINE (~=86) _______________ ;12 cycles between interrupt and _OCF! _OCF ldaa SCHTST ; 4 Get test byte. beq SCHOK ; 3 Branch if previous interrupt completed, SCHERR bra SCHERR ; Fatal error, can't continue! SCHOK inc SCHTST ; 6 Set test byte to indicate running interrupt. ldaa _TCSR ; 3 Clear TOF by reading TCSR. ldd _OCR ; 4 Load output compare register, addd #1200 ; 4 increment it by time slice std _OCR ; 4 and restore it to OCR. ldx SCHPTR ; 5 Get pointer to current 1/64s period task. ldx 0,X ; 5 Get the task's entry address. cli ; 2 Allow interrupts. jsr 0,X ; 6 EXECUTE THE TASK. ldaa SCHPTR+1 ; 4 Get high byte of SCHPTR, adda #2 ; 2 increment it, anda #%00011110 ; 2 overlay 0's staa SCHPTR+1 ; 4 and restore it to SCHPTR. clr SCHTST ; 6 Reset test byte to indicate end of interrupt. rti ;10 Return from OCF interrupt ;________________________ ENABLE THE SCHEDULER ________________________________ SCHON clr SCHTST ;6 Reset time slice exceeding test ldx #SCHTAB ;3 Initialize pointer stx SCHPTR ;5 to first 1/64s period tasks. ldaa #%00001000 ;2 Set EOCI flag bit staa _TCSR ;3 to enable output compare interrupt. ldd _FRC ;4 Load free running counter addd #1200 ;4 increment it by time slice std _OCR ;4 and restore it to output compare register. cli ;2 Clear interrupt mask. rts ;5 Return(Scheduler running). ;________________________ TIMER TASK (~<=77) __________________________________ ; This is a real-time clock driver. TIM should be placed into the task ; schedule at a 1/256 second duty cycle. TIM updates four global variables ; TIMH (Hours 0..23), TIMM (minutes 0..59), TIMS (seconds 0..59) and ; TIMF (second fractions 0..255). ;------------------------------------------------------------------------------ TIM inc TIMF ;6 Increment fraction counter, bne TIMRTS ;3 Branch down if no overflow inc TIMS ;6 Increment second counter, ldaa TIMS ;4 load it to A cmpa #60 ;2 and compare with 60. bcs TIMRTS ;3 Branch down if no overflow clr TIMS ;6 and reset second counter otherwise. inc TIMM ;6 Increment minute counter, ldaa TIMM ;4 load it to A cmpa #60 ;2 and compare with 60. bcs TIMRTS ;3 Branch down if no overflow clr TIMM ;6 and reset minute counter otherwise. inc TIMH ;6 Increment hour counter, ldaa TIMH ;4 load it to A cmpa #24 ;2 and compare with 24. bcs TIMRTS ;3 Branch down if no overflow clr TIMH ;6 and reset hour counter otherwise. TIMRTS rts ;5 Return(). ;________________________ SYNCHRONIZE WITH SCHEDULER __________________________ ; Call this subroutine from any non-realtime routine to request D<1100 ; uninterrupted subsequent maschine cycles. Upon return, you have the ; requested number of uninterrupted cycles, plus D extra cycles. Use D=0 to ; find out the number of cycles left until next scheduler interrupt. ;------------------------------------------------------------------------------ SCHSYN pshx ;4 Push X. addd #$0020 ;4 Add the system overhead of 32 machine cycles. pshb ;3 Push number of machine cycles psha ;3 from D to stack tsx ;3 and make X point to it. SCHWAI ldd _OCR ;4 Load output compare register, subd _FRC ;5 subtract free running counter subd 0,X ;6 and number of cycles. bmi SCHWAI ;3 Loop back if not enough cycles until interrupt. pulx ;5 Dummy pull X to clear D from stack. pulx ;5 Restore X. rts ;5 Return(D=extra cycles left). ;________________________ TRANSMIT CHARACTER (~<=51) __________________________ ; Place binary in A to the SCI transmitting buffer TRAB-TRAE. In case of a ; full buffer, the procedure returns Z=1, otherwise Z=0. The contents of all ; registers are preserved. This procedure must never be interrupted by another ; call to TRACHR! ;------------------------------------------------------------------------------ TRACHR pshx ldx TRAE staa 0,X inx cpx #TRAE bne TRA1 ldx #TRAB+2 TRA1 cpx TRAB beq TRAERR stx TRAE TRAERR pulx rts ;________________________ SERIAL COMMUNICATION TASK (~<=106) __________________ ; This is a real-time serial communication driver. SCI should be placed into ; the task schedule. In each cycle, SCI checks the serial communication ; hardware to see if a new byte has been received. If so, the byte is ; transferred into the receiveing buffer RECB-RECE. The transmission register ; is also checked. If it is empty and the transmission buffer TRAB-TRAE is not ; empty, then the first byte from the fifo buffer is transferred to the ; transmission hardware. ;------------------------------------------------------------------------------ SCI pshx ldaa _TRCSR anda #%11000000 beq SCI_TR pulx rts SCI_TR ldaa _TRCSR anda #%00100000 beq SKONEC ldx TRAB cpx TRAE beq SKONEC ldaa 0,X staa _TDR inx cpx #TRAE bne SKON ldx #TRAB+2 SKON stx TRAB SKONEC pulx rts ;________________________ RECEIVE CHARACTER (~<=51) ___________________________ ; Read one character from the SCI receiveing buffer RECB-RECE to A. In case ; of an empty buffer, the procedure returns Z=1. A successful read is ; indicated by Z=0. The contents of all registers are preserved. This ; procedure must never be interrupted by another call to RECCHR!! ;------------------------------------------------------------------------------ RECCHR rts ;________________________ DIVIDE D BY X (~<=981) ______________________________ ; This is a 16bit multi-purpose division routine. The unsigned integer in D ; is divided by the unsigned integer in X. The unsigned integer portion of ; the quotient is returned in D, the modulus is passed in X respectively ; (in pascal syntax this would be D:=D div X; X:=D mod X;). WARNING, it is ; the caller's responsibility to guarantee a non-zero divisor in X! ;------------------------------------------------------------------------------ DIV pshb ;3 Push dividend from D psha ;3 to quotient. clra ;2 Clear modulus psha ;3 and push it psha ;3 on top of quotient. pshx ;4 Push divisor from X on top of modulus. ldaa #16 ;2 Initialize psha ;3 and push shift counter. tsx ;3 Make X point to top of stack. DIV1 asl 6,X ;6 Arithmetic shift rol 5,X ;6 left quotient rol 4,X ;6 into the rol 3,X ;6 modulus. ldd 3,X ;5 Load current 16-bit modulus subd 1,X ;6 and try to subtract the divisor. bcs DIV2 ;3 Jump down if divisor higher, std 3,X ;5 restore new modulus otherwise. inc 6,X ;6 Set LSbit of quotient. DIV2 dec 0,X ;6 Decrement shift counter bne DIV1 ;3 and loop back if not zero. pula ;4 Dummy pull pulx ;5 3 bytes from stack. pulx ;5 Get modulus from stack to X. pula ;4 Get quotient from pulb ;4 stack to D. rts ;5 Return(D:=D div X, X:=D mod X). V_ASCII clr ASC_STEV ASC_Z1 subd #1000 bmi ASC_K1 inc ASC_STEV bra ASC_Z1 ASC_K1 addd #1000 psha ldaa ASC_STEV adda #$30 staa 0,X pula clr ASC_STEV ASC_Z2 subd #100 bmi ASC_K2 inc ASC_STEV bra ASC_Z2 ASC_K2 addd #100 ldaa ASC_STEV adda #$30 staa 1,X clra ASC_Z3 subb #10 bmi ASC_K3 inca bra ASC_Z3 ASC_K3 addb #10 addb #$30 stab 3,X adda #$30 staa 2,X rts ;________________________ TRANSMIT STRING (~<=32+x*73) ________________________ ; Transmit string staring with the character at X. TRASTR copies characters ; from string to the transmision buffer TRAB-TRAE until the null-character ; is encountered or until the tranmision buffer is full. In the later case ; the transmision is interrupted and Z=1 is returned. Z=0 on the other hand ; indicates a successfull transmission. ;------------------------------------------------------------------------------ TRASTR ldaa 0,X beq TKONC jsr TRACHR inx bra TRASTR TKONC rts ;________________________ RECEIVE STRING FROM SCI _____________________________ ; Get a CR-terminated string from the SCI receiveing buffer using RECCHR. ; As they are read, the characters are echoed back via TRACHR. Backspace ; characters ($08) cause the deletion of the leftmost character. The resulting ; null-terminated string is stored in memory at X. The string length will not ; exceed A characters excluding the termination byte. The final string length ; is returned in B. ;------------------------------------------------------------------------------ RECSTR rts ;-----------------------RMP--------------------------------------------------- ;INICIALIZACIJA PIE INITPIA pshx ldaa _CRA anda #%11111011 staa _CRA ldaa #%00000010 staa _DDRA ldaa #%00000100 oraa _CRA staa _CRA ldaa #%00000010 staa _DDRA clr IZR_ZAST ldx #2560 stx STETJE clr STEJ clr STEJ+1 ldx #SPOROCH1 jsr TRASTR ldx #SPOROCH2 jsr TRASTR clr SK_OBR clr SK_OBR+1 pulx rts SPOROCH2 FCB $0C,$0D FCC 'Hitrost [km/h]: ' FCB $00 SPOROCH1 FCB $0C,$0D FCC 'CITALEC HITROSTI IN POTI (VERZIJA no.1) ' FCB $00 ;STETJE IMPULZOV ST_IMP psha pshb jsr VRTENJE ldd STETJE subd #1 std STETJE beq ST_NOVO ST_IMP_K pulb pula rts ST_NOVO ldd #2560 std STETJE inc IZR_ZAST ldd STEJ std IZR_STEJ clr STEJ clr STEJ+1 bra ST_IMP_K VRTENJE tst PREJPOZ beq VRT_N ldaa _DDRA VRT_K anda #%00000001 staa PREJPOZ rts VRT_N ldaa _DDRA anda #%00000001 beq VRT_K psha ldd STEJ addd #1 std STEJ pula bra VRT_K IZRACUN ldd IZR_STEJ asld ldx #HITROST jsr V_ASCII ldx #BRISI ; Brisi prejsnjo hitrost in pot jsr TRASTR ldx #HITROST jsr PRIKAZI ; ldd IZR_STEJ lsrd addd SK_OBR std SK_OBR ldx #84 jsr DIV ldx #POT jsr V_ASCII ldx #SPR_POT jsr TRASTR ldx #POT jsr PRIKAZI clr IZR_ZAST rts PRIKAZI ldaa 0,X jsr TRACHR ldaa 1,X jsr TRACHR ldaa 2,X jsr TRACHR ldaa #'.' jsr TRACHR ldaa 3,X jsr TRACHR rts SPR_POT FCC ' ; Pot [km]: ' FCB $00 BRISI FCB $08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08 FCB $08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$00 AUX ;======================== EXTERNAL RAM $2000..$3FFF =========================== ORG _XRAM ;________________________ KERNEL VARIABLES (7 bytes) __________________________ SCHPTR RMB 2 ;16 bit pointer to current task in SCHTAH. SCHTST RMB 1 ;Test task on exceeding time slice. TIMH RMB 1 ;Hours (0..23), TIMM RMB 1 ;minutes (0..59), TIMS RMB 1 ;seconds (0..59), TIMF RMB 1 ;and fractions (0..255). ;________________________ DRIVER VARIABLES (101 bytes) ________________________ KBDB RMB 3+8 ;KBD buffer KBDE RMB 2 ;with a capacity of 8 characters. KBDKEY RMB 1 ;KBD status variable: keypressed? MOTCUR RMB 2 ;Currrent rotor position, written by MOT. MOTEND RMB 2 ;Final rotor position, read by MOT. BEEDUR RMB 1 ;The beeping duration in 1/64s. TRAB RMB 3+100 ;SCI transmitting buffer TRAE RMB 2 ;with a capacity of 64 characters. RECB RMB 3+8 ;SCI receiveing buffer RECE RMB 2 ;with a capacity of 8 characters. ;________________________ USER VARIABLES ______________________________________ ; ; Place global application variables here! TEMP RMB 1 KBDPOINT RMB 1 KBDRCNT RMB 1 KBDVAL RMB 1 KBDBUF RMB 1 STETJE RMB 2 POT RMB 4 STEJ RMB 2 PREJPOZ RMB 1 IZR_ZAST RMB 1 IZR_STEJ RMB 2 HITROST RMB 4 ASC_STEV RMB 1 SK_OBR RMB 2 ;________________________ VARIABLE HEAP _______________________________________ HEAP RMB 1 ;First byte of variable heap. ORG AUX ;________________________ INITIALIZE RAM VARIABLES ____________________________ INIT ldx #$0000 ;Clear stx TIMH ;hours, minutes, stx TIMS ;seconds and fractions. stx MOTCUR ;Reset current stx MOTEND ;and final motor position. ldaa #%00001100 ;Set the motors initial staa _P1DR ;stepping sequence. ldx #KBDB+2 ;Clear the stx KBDB ;keyboard stx KBDE ;buffer. clr BEEDUR ;Shut up the beeper. clr _LEDD ;Clear the LED display. ldx #TRAB+2 ;Clear the stx TRAB ;SCI transmitting stx TRAE ;buffer. ldx #RECB+2 ;Clear the stx RECB ;SCI receiveing stx RECE ;buffer. ldaa #$05 staa _RMCR ldaa #$0A staa _TRCSR rts ;Return(). ;________________________ RESET _______________________________________________ _RES lds #$3FFF ;Define stack segment. jsr INIT ;Initialize RAM variables. jsr SCHON ;Start schedule jsr INITPIA jsr MAIN ;Call MAIN -- there should be no return. HALT bra HALT ;Dead loop! ;________________________ MAIN PROGRAM ________________________________________ MAIN ;Application user code ; ... ; including user subroutines. tst IZR_ZAST beq MAIN_K jsr IZRACUN MAIN_K jmp MAIN rts ;________________________ INTERRUPT VECTOR TABLE ______________________________ ORG $FFF0 FDB HALT ;Serial communication interrupt vector. FDB HALT ;Timer overflow flag interrupt vector. FDB _OCF ;Output compare flag interrupt vector. FDB HALT ;Input capture flag interrupt vector. FDB HALT ;Interrupt request vector. FDB HALT ;Software interrupt vector. FDB HALT ;Non-maskable interrupt vector. FDB _RES ;Processor reset vector. END