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