title 'Time module for the Modular CP/M 3 BIOS' public ?time, gs_rtc public prt0ini public gtimer,gstimer extrn @date,@hour,@min,@sec extrn f_cpu extrn ioiniml,div32_16 extrn msg.sm,msg.recv extrn _b0hlcall maclib z180reg.inc maclib config.inc ;---------------------------------------------------------------------- ; c == 00h: get time ; c == ffh: set time cseg ; time must be done from resident memory ?time: inc c ;zero if ff ld c,3 jr z,time_set ld a,(time_to) or a ret nz dec c time_set: b0hlcall gs_rtc ld a,0ffh ld (time_to),a ret ;---------------------------------------------------------------------- ; c = 2: get time ; c = 3: set time dseg gs_rtc: push hl push de ld hl,(@date) ld a,(@hour) ld d,a ld a,(@min) ld e,a ld a,(@sec) ld b,a ;b = sec, c = subcommand push hl ;2 push de ;4 push bc ;6 ld hl,3 * 256 + 0 ;h = command, l = 0 push hl ;8 ld h,l ;hl = 0 add hl,sp push hl inc hl ;7 ld b,7 call msg.sm pop hl ;8 ld b,8 ; max receive message len call msg.recv pop hl ;len/command (discard) pop bc ;subc/sec pop de pop hl ld a,b ld (@sec),a ld a,e ld (@min),a ld a,d ld (@hour),a ld (@date),hl pop de pop hl ret ;---------------------------------------------------------------------- ;uint32_t get_timer(uint32_t base) ;{ ; uint32_t ret; ; ATOMIC_BLOCK(ATOMIC_FORCEON) ; { ; ret = timestamp; ; } ; return ret - base; ;} dseg ; called from banked only gstimer: push de ex de,hl ld hl,(uptime) or a sbc hl,de pop de ret ;---------------------------------------------------------------------- gtimer: push bc ld b,h ld c,l or a di ld hl,(uptime) sbc hl,bc push hl ei ld hl,(uptime+2) sbc hl,de ex de,hl pop hl pop bc ret ;---------------------------------------------------------------------- ; intit timer interrupt dseg prt0ini: in0 a,(tcr) push af and ~(M_TIE0+M_TDE0) ;stop timer 0 out0 (tcr),a ld a,i ld h,a in0 a,(il) and 0E0h or IV$PRT0 ld l,a ld de,isvprt0 ld (hl),e inc hl ld (hl),d ld hl,(f_cpu) ld de,(f_cpu+2) ld bc,PRT_PRE * 800 ;1/800 s == 1,25 ms interrupt rate call div32_16 out0 (tmdr0l),l out0 (tmdr0h),h out0 (rldr0l),l out0 (rldr0h),h pop af or (M_TIE0+M_TDE0) out0 (tcr),a ret ;---------------------------------------------------------------------- ; timer interrupt ; ; 1,25 ms clock tick extrn i$stack cseg ;common! isvprt0: ; ld (i$stack),sp ; + 19 ld sp,i$stack ; + 9 push af ; 11 in0 a,(tcr) ;reset TIF0 flag 12 in0 a,(tmdr0l) ; 12 in0 a,(tmdr0h) ; 12 ; push hl ; 11 ld hl,time_to ; 9 ld a,(hl) ; 6 sub a,1 ; 6 79 jr c,iprt_0 ; 6/8 ld (hl),a ; 7 iprt_0: ; 87 92 inc hl ; 4 inc (hl) ; 10 101 jr nz,iprt_1 ; 6/8 109 -2 inc hl ; 4 inc (hl) ; 10 14 jr nz,iprt_1 ; 6/8 inc hl ; 4 inc (hl) ; 10 jr nz,iprt_1 ; 6/8 inc hl ; 4 inc (hl) ; 10 iprt_1: ; 109 138 pop hl ; 9 pop af ; 9 ld sp,(i$stack) ; + 18 ei ; 3 ret ; 9 139 199 ; +intack 18 157 217 time_to: db 0 uptime: dw 0,0 end