; timer routines ; this implementation is for Atari and C64. ; it uses parts of the C runtime library ; ; the timer should be a 16-bit counter that's incremented by about ; 1000 units per second. it doesn't have to be particularly accurate. .include "../inc/common.inc" .export timer_init .export timer_read .export timer_seconds .import __clocks_per_sec, _clock .import tosumodeax, tosudiveax .import pusheax, incsp4 .importzp sp, sreg .bss timer_freq: .res 1 ; VBLANK frequency: 50 - PAL, 60 - NTSC (Atari); always 60 (C64) mult_temp: .res 2 ; temp var for multiplication routines mult_temp_x:.res 1 ; another temp var for multiplication routines .data mult: .byte $4C ; JMP opcode .res 2 ; address .code ; get timer frequency and patch multiplication routine pointer ; inputs: none ; outputs: none timer_init: jsr __clocks_per_sec sta timer_freq cmp #50 beq @timer50 lda #mult17 bne @timerset ; jmp always @timer50: lda #mult20 @timerset: sta mult+1 stx mult+2 rts ; read the current timer value ; inputs: none ; outputs: AX = current timer value in milliseconds timer_read = mult ; get current seconds clock hand ; inputs: none ; outputs: A = seconds hand (in BCD, range $00..$59) timer_seconds: jsr _clock ; return current tick count in sreg:AX (high:low 16bits) jsr pusheax ; push tick count onto stack ldx #0 stx sreg stx sreg+1 lda timer_freq jsr tosudiveax ; dividend on stack, divisor in sreg:AX jsr pusheax ldx #0 stx sreg stx sreg+1 lda #60 jsr tosumodeax ; result modulo 60 ; convert to BCD, a poor man's conversion here.... cmp #50 bcs @rs_50 cmp #40 bcs @rs_40 cmp #30 bcs @rs_30 cmp #20 bcs @rs_20 cmp #10 bcs @rs_10 rts @rs_10: sbc #10 ora #$10 rts @rs_20: sbc #20 ora #$20 rts @rs_30: sbc #30 ora #$30 rts @rs_40: sbc #40 ora #$40 rts @rs_50: sbc #50 ora #$50 rts ; get the current tick count, multiply it by 20, and return the lower 16 bits ; x*20 = x*16 + x*4 ; inputs: none ; outputs: AX - tick count times 20 ('milliseconds') mult20: jsr _clock ; return current tick count in sreg:AX (high:low 16bits) stx mult_temp_x ; remember high byte of lower 16bits asl a rol mult_temp_x asl a rol mult_temp_x sta mult_temp ldx mult_temp_x stx mult_temp+1 ; mult_temp = ticks * 4 asl a rol mult_temp_x asl a rol mult_temp_x ; mult_temp_x:A = 'ticks * 16' clc ; AX - tick count * 16, mult_temp - tick count * 4 adc mult_temp sta mult_temp lda mult_temp+1 adc mult_temp_x tax lda mult_temp rts ; get the current tick count, multiply it by 17, and return the lower 16 bits ; x*17 = x*16 + x ; inputs: none ; outputs: AX - tick count times 17 ('milliseconds') mult17: jsr _clock ; return current tick count in sreg:AX (high:low 16bits) sta mult_temp stx mult_temp+1 stx mult_temp_x .repeat 4 asl a rol mult_temp_x .endrepeat ; mult_temp_x:A = 'ticks * 16' clc adc mult_temp sta mult_temp lda mult_temp+1 adc mult_temp_x tax lda mult_temp rts ;-- LICENSE FOR clk_timer.s -- ; The contents of this file are subject to the Mozilla Public License ; Version 1.1 (the "License"); you may not use this file except in ; compliance with the License. You may obtain a copy of the License at ; http://www.mozilla.org/MPL/ ; ; Software distributed under the License is distributed on an "AS IS" ; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the ; License for the specific language governing rights and limitations ; under the License. ; -- LICENSE END --