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 _b0call include config.inc include z180reg.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: b0call 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 cseg ;common! isvprt0: push af in0 a,(tcr) ;reset TIF0 flag in0 a,(tmdr0l) in0 a,(tmdr0h) push hl ;11 ld hl,uptime ; 9 inc (hl) ;10 jr nz,iprt_1 ;6/8 38 inc hl ; 4 inc (hl) ;10 jr nz,iprt_1 ;6/8 58 inc hl ; 4 inc (hl) ;10 jr nz,iprt_1 ;6/8 inc hl ; 4 inc (hl) ;10 iprt_1: pop hl ; 9 ld a,(time_to) sub a,1 jr c,iprt_0 ld (time_to),a iprt_0: pop af ei ret uptime: dw 0,0 time_to: db 0 end