Retrocomputing

Clock module

This version maintains a time polling table. Device drivers may install themselves in the table via a F$Timer request. They are then called at every tick. This necessitates the Clock tick routine duplicating some of the User/System switching normally done in UserIRQ in OS9p1, to allow the routines to use system calls such as F$Send.

         nam Clock Module
         ttl Module Header
* opt -c

************************************************************
*                                                          *
*     Clock Module                                         *
*                                                          *
* Copyright 1982 by Microware Systems Corporation          *
* Reproduced Under License                                 *
*                                                          *
* This source code is the proprietary confidential prop-   *
* erty of Microware Systems Corporation, and is provided   *
* to the licensee solely for documentation and educational *
* purposes. Reproduction, publication, or distribution in  *
* any form to any party other than the licensee is         *
* is strictly prohibited !!!                               *
*                                                          *
************************************************************
 ifne TimePoll
************************************************************ * * This version maintains a time polling table. Device * drivers may install themselves in the table via a * F$Timer request. They are then called at every tick. * This necessitates the Clock tick routine duplicating * some of the User/System switching normally done in * UserIRQ in OS9p1, to allow the routines to use * system calls such as F$Send. * *************************************************************
endc * ifeq ClocType-MC6840
* Initialize 6840 Timer Chip For 50Ms Intervals
endc ifeq ClocType-VIA
endc ifeq ClocType-M58167
* Initialize M58167 Clock Chip For 100Ms Intervals
endc ifeq ClocType-MC146818
endc ifeq CPUType-DRG128
* Initialise PIA for VSYNC interrupts,
endc ifne TimePoll
* Set up Timer Polling Table, for device drivers needing to * run a timing routine every tick,
endc * and take control of IRQ vector * * Edition 3 - time polling table added. Vivaway Ltd 83/11/07 PSD * CPORT set A.Clock use defsfile ************************************************************* * * MODULE HEADER * Type set SYSTM+OBJCT Revs set REENT+1 mod ClkEnd,ClkNam,Type,Revs,ClkEnt,CPORT ClkNam fcs /Clock/ fcb 3 Edition number * * CLOCK DATA DEFINITIONS * TIMSVC fcb F$TIME fdb TIME-*-2 ifne TimePoll
fcb F$Timer+SysState fdb Install-*-2
endc fcb $80 CLKPRT equ M$Mem Memory has Clock port address ifeq (ClocType-MC6840)*(ClocType-VIA)
TCKCNT set 10000 #of mpu cycles/tick
endc ifne (ClocType-M58167)*(ClocType-MC146818)
* * DAYS IN MONTHS TABLE * MONTHS fcb 0 Uninitialized month fcb 31 January fcb 28 February fcb 31 March fcb 30 April fcb 31 May fcb 30 June fcb 31 July fcb 31 August fcb 30 September fcb 31 October fcb 30 November fcb 31 December
else
SecMilli equ 0 SecTenth equ 1 Second equ 2 Minute equ 3 Hour equ 4 DayWeek equ 5 DayMonth equ 6 Month equ 7 Status equ 16 Control equ 17 CountRst equ 18 LatchRst equ 19 RollOver equ 20 Go equ 21
endc page ifne ClocType
************************************************************* * * Non-Clock Interrupt Service * NOTCLK ldd D.Poll get polling routine ptr lbra TICK50 ************************************************************* * * Clock Interrupt Service routine * * NOTE: the stack pointer is invalid when this routine is * entered. It must not be used, but it must not be * lost. * CLKSRV ldx CLKPRT,PCR GET CLOCK ADDRESS ifeq ClocType-MC6840
lda 1,x anda #2 Is it clock? beq NOTCLK Branch if not
endc ifeq ClocType-VIA
endc ifeq (ClocType-M58167)*(ClocType-MC146818)
lda Status,X Get status/clear interrupt beq NOTCLK Branch if not clock
endc ifeq CPUType-DRG128
lda 1,x get CRA of 6821 ifne Cx2Int
bita #$40 test Cx2 interrupt flag beq NOTCLK not a clock interrupt
else
endc sta D.LtPen save reg for light pen flag lda ,x clear the interrupt
endc Tick equ * ifne (ClocType-M58167)*(ClocType-MC146818)
* * UPDATE CURRENT TIME * dec D.Tick COUNT TICK bne Tick40 BRANCH IF NOT END OF SECOND ldd D.MIN GET MINUTE & SECOND incb COUNT SECOND cmpb #60 END OF MINUTE? bcs TICK35 BRANCH IF NOT inca COUNT MINUTE cmpa #60 END OF HOUR? bcs TICK30 Branch if not ldd D.DAY Get day & hour incb COUNT Hour cmpb #24 End of day? bcs TICK25 Branch if not inca COUNT Day leax MONTHS,PCR Get days/month table ldb D.Month Get month cmpb #2 Is it february? bne TICK10 Branch if not ldb D.YEAR Get year beq TICK10 Branch if even hundred andb #3 Is it leap year? bne TICK10 Branch if not deca ADD Feb 29 TICK10 ldb D.Month Get month cmpa B,X End of month? bls TICK20 Branch if not ldd D.YEAR Get year & month incb COUNT Month cmpb #13 End of year? bcs TICK15 Branch if not inca COUNT Year ldb #1 New month TICK15 std D.YEAR Update year & month lda #1 New day TICK20 clrb NEW Hour TICK25 std D.DAY Update day & hour clra NEW Minute TICK30 clrb NEW Second TICK35 std D.MIN Update minute & second ifeq (ClocType-MC6840)*(ClocType-VIA)*(ClocType-VSYNC)
ifne (CPUType-Profitel)
lda #TickSec Get ticks presecond
else
endc
endc sta D.Tick
else
* M58167 code here. Probably: ldd D.Clock bra TICK50
endc ifne TimePoll
Tick40 leau ,s copy sp ldx D.SysIRQ in system mode? cmpx D.XIRQ beq Tick41 ..yes; no switch required lds D.SysStk get system stack ldd D.SysSvc set system service table std D.XSWI2 Tick41 pshs u save the sp as was ldx D.TimTbl get timer polling table pointer beq Tick47 ..there isn't one ldb #64 max entries pshs x,dp,b save regs Tick42 ldy ,x++ get routine address beq Tick45 ..no more ldu ,x++ get static stx 2,s save ptr jsr ,y call routine ldx 2,s retrieve ptr dec ,s all done? bne Tick42 ..no Tick45 puls x,dp,b restore regs Tick47 ldd D.Clock get clock routine ptr puls u retrieve saved sp leas ,u restore it
else
ldd D.Poll get polling routine ptr
endc TICK50 std D.SvcIRQ set IRQ service routine jmp [D.XIRQ] enter system
endc ***** * * CLOCK INITIALIZATION ENTRY * ClkEnt equ * ifne TimePoll
clrb clear carry ldx D.TimTbl table already exists? bne ClkEnt3 ..yes; skip initialisation
endc ifne ClocType
pshs CC save interrupt masks ifeq (ClocType-MC6840)*(ClocType-VIA)*(ClocType-VSYNC)
ifne (CPUType-Profitel)
lda #TickSec get ticks per second
else
endc
endc ifeq ClocType-M58167 M58167 CLOCK CHIP
lda #TickSec get ticks per second
endc ifeq ClocType-MC146818 MC146818 Clock chip
endc sta D.Tick lda #TickSec/10 set ticks/time slice sta D.TSlice sta D.Slice ifne TimePoll
ldd #256 allocate memory for timer polling table pshs u os9 F$SRqMem bcs ClkEnt2 ..none stu D.TimTbl save table address ldy #0 clear it out ldb #64*2 number of entries*2 (4 bytes/entry) ClkEnt1 sty ,u++ decb bne ClkEnt1 ClkEnt2 puls u
endc orcc #IntMasks set interrupt masks leax CLKSRV,pcr GET SERVICE ROUTINE stx D.IRQ SET INTERRUPT VECTOR ifeq ClocType-MC6840 M6840 TIMER CHIP
ldx CLKPRT,PCR get clock address ldd #TCKCNT-1 Get tick count ifeq M6840Typ-Missed
std 2,X store count in timer #1 ldd #1 std 4,X inz timer #2 ldb #$50 constant for control reg stb 1,X put it there ldd #90 max count of missed ticks std 6,X store it clr 0,X constant for C3 ldb #$51 constant for C2 stb 1,X store it ldb #$92 constant for C1 stb 0,X enable timer operation
else
std 4,X Store in timer #2 count ldb #$53 Constant for control reg. stb 1,X Put it there. clr 0,X Enable timer operation
endc
endc ifeq ClocType-VIA
endc ifeq ClocType-VSYNC
ldx CLKPRT,pcr get PIA address lda ,x clear any current interrupts lda 1,x get Control register ifne Cx2Int
ora #$18 positive edge interrupt on CA2 (CB2)
else
endc sta 1,x set control register
endc ifeq ClocType-M58167 M58167 CLOCK CHIP
leas -5,S get scratch ldx #D.Month Get month ptr bsr CNVBB Convert binary to bcd stb 0,S save month bsr CNVBB Convert stb 1,S save day bsr CNVBB Convert stb 2,S save hour bsr CNVBB Convert stb 3,S save minute bsr CNVBB Convert stb 4,S save second ldx CLKPRT,PCR get clock address ldd #$FF02 sta LatchRst,X Reset latches lda Status,X Clear any interrupt stb Control,X enable 100 millisec line lda 0,S retrieve month beq SkipSet sta Month,X set clock chip lda 1,S retrieve day beq SkipSet sta DayMonth,X lda 2,S retrieve hour sta Hour,X Set clock chip ldd 3,S retrieve minute & second sta Minute,X set clock chip clr Go,X reset seconds stb Second,X SkipSet leas 5,S return scratch
endc ifeq ClocType-MC146818 MC146818 Clock chip
endc puls CC retrieve masks
endc leay TIMSVC,PCR OS9 F$SSVC SET TIME SERVICE ROUTINE ClkEnt3 rts ifeq ClocType-M58167
CNVBB lda ,X+ Get binary byte ldb #$FA Init bcd byte CNVB10 addb #$10 Count ten suba #10 Is there a ten? bcc CNVB10 Branch if so CNVB20 decb Count Unit inca Is there a unit? bne CNVB20 Branch if so rts
endc ifne TimePoll
**************************************** * * Install caller in timer polling table * Install pshs cc orcc #IntMasks mask interrupts ldx D.TimTbl get table pointer ldb #64 max entries ldy R$X,u get routine address beq Remove skip for remove Install1 ldy ,x this one free? beq Install2 ..yes leax 4,x move to next decb table full? bne Install1 ..no InsErr puls cc retrieve masks comb error - ldb #E$Poll polling table full rts Install2 ldy R$X,u get routine address sty ,x++ set it ldy R$U,u get static storage Install3 sty ,x set it Install4 puls cc retrieve masks clrb no error rts Remove ldy R$U,u get user's static Remove1 cmpy 2,x found it? beq Remove2 ..yes leax 4,x move to next decb all searched? bne Remove1 ..no bra Install4 ..exit; can't find Remove2 decb number to copy over beq Remove4 ..none Remove3 ldy 4,x copy down next entry beq Remove4 skip if empty; end of entries sty ,x++ copy down ldy 4,x and static sty ,x++ decb ..all done? bne Remove3 Remove4 ldy #0 delete this entry sty ,x++ bra Install3 and exit
endc page ************************************************************* * * Subroutine Time * * Time of Day service routine * TIME equ * ifeq (ClocType-M58167)
ldx CLKPRT,PCR Get clock port address pshs CC Save masks orcc #IntMasks Set interrupt masks TIME10 lda Second,X get second sta D.SEC Set second lda Minute,X get minute sta D.MIN Set minute lda Hour,X Get hour sta D.HOUR Set hour lda DayMonth,X Get day sta D.DAY Set day lda Month,X get month sta D.Month Set month lda RollOver,X Check for rollover rora bcs TIME10 Branch if so puls CC Retrieve interrupt masks ldx #D.Month Get date ptr TIME20 lda 0,X Get bcd byte anda #$F0 Get msn tfr A,B Copy it eora 0,X Get lsn sta 0,X Save it lsrb ADJUST Msn lsrb lsrb lsrb lda #10 mul addb 0,X Add lsn stb ,X+ Save converted byte cmpx #D.SEC+1 bcs TIME20
endc lda D.SysTsk get system task number ldx D.Proc get process ptr ldb P$Task,x get process task number ldx #D.Time get source ptr ldy #6 get byte count ldu R$X,u get specified location os9 F$Move move time to user rts emod ClkEnd equ * opt c end