Mercurial > hg > Members > kono > nitros9-code
view level1/modules/clock.asm @ 3246:be3446f758ca
Updated dwread.asm and dwwrite.asm so that the 6551 routines could have specially defined
flags so that some of the addresses could be overridden by the make files if needed.
author | David Ladd <drencor-xeen@users.sourceforge.net> |
---|---|
date | Sun, 11 Mar 2018 01:30:30 -0600 |
parents | 185c31229f22 |
children |
line wrap: on
line source
******************************************************************** * Clock - NitrOS-9 System Clock * * $Id$ * * Edt/Rev YYYY/MM/DD Modified by * Comment * ------------------------------------------------------------------ * ????/??/?? * NitrOS-9 2.00 distribution. * * 9r4 2003/01/01 Boisy G. Pitre * Back-ported to OS-9 Level Two. * * 9r5 2003/08/18 Boisy G. Pitre * Separated clock into Clock and Clock2 for modularity. * * 9r6 2003/09/04 Boisy G. Pitre * Combined Level One and Level Two sources * * 9r7 2004/11/27 Phill Harvey-Smith * Fixed bug in init routine that was causing DP and CC to * be pulled off the stack and stored in D.Proc under Level 1 * * 9r7 2005/01/17 Boisy G. Pitre * Fixed incorrect value for PIA initialization. Robert indicated * that it should be $3434, not $3435. * * 9r7 2005/04/08 Phill Harvey-Smith * Made the above level dependent as having PIAs inited with $3434 * will disable the IRQ from them, this is ok for Level 2/CoCo 3 as the * IRQ is later enabled from the GIME, however the CoCo 1,2 and Dragon * do not posses a GIME so anything dependent on the clock tick will * hang. So changed to conditionaly compile based on level :- * * 9r8 2005/12/04 Boisy G. Pitre * Minor code optimizations, fixed issue in Level 1 where clock ran slow * due to improper initialization of certain system globals. nam Clock ttl NitrOS-9 System Clock ifp1 use defsfile endc tylg set Systm+Objct atrv set ReEnt+rev rev set 8 edition set 9 IFNE atari USENMI EQU 0 ENDC *------------------------------------------------------------ * * Start of module * mod len,name,tylg,atrv,init,0 name fcs "Clock" fcb edition TkPerTS equ TkPerSec/10 ticks per time slice * * Table to set up Service Calls * NewSvc fcb F$Time fdb FTime-*-2 fcb F$VIRQ fdb FVIRQ-*-2 fcb F$STime fdb FSTime-*-2 fcb $80 end of service call installation table *------------------------------------------------------------ * * Handle F$STime system call * * First, copy time packet from user address space to system time * variables, then fall through to code to update RTC. * FSTime equ * ldx R$X,u ldd ,x std <D.Year ldd 2,x std <D.Day ldd 4,x std <D.Min lda #TkPerSec reset to start of second sta <D.Tick ldx <D.Clock2 get entry point to Clock2 clra clear carry jmp $06,x and call SetTime entry point *-------------------------------------------------- * * Clock Initialization * * This vector is called by the kernel to service the first F$STime * call. F$STime is usually called by SysGo (with a dummy argument) * in order to initialize the clock. F$STime is re-vectored to the * service code above to handle future F$STime calls. * * Clock2 fcs "Clock2" init pshs dp,cc save DP and CC clra tfr a,dp set DP to zero leax <Clock2,pcr lda #Sbrtn+Objct os9 F$Link bcc LinkOk jmp >$FFFE level 1: jump to reset vector LinkOk puls cc,dp ; Restore saved dp and cc sty <D.Clock2 save entry point InitCont * Do not need to explicitly read RTC during initialization ldd #59*256+$01 last second and last tick std <D.Sec will prompt RTC read at next time slice ldb #TkPerSec stb <D.TSec set ticks per second ldb #TkPerTS get ticks per time slice stb <D.TSlice set ticks per time slice stb <D.Slice set first time slice IFNE atari leax SvcIRQ,pcr set IRQ handler IFNE USENMI stx <D.NMI ELSE stx <D.IRQ ENDC ELSE leax SvcIRQ,pcr set IRQ handler stx <D.IRQ ENDC leay NewSvc,pcr insert syscalls os9 F$SSvc * Call Clock2 init routine ldy <D.Clock2 get entry point to Clock2 jsr ,y call init entry point of Clock2 * Initialize clock hardware IFNE corsham * Corsham SS-50 6809 board -- uses the Arduino as a clock source * Timer values: * 0 = disable timer interrupts * 1 = 10 ms * 2 = 20 ms * 3 = 30 ms * 4 = 40 ms * 5 = 50 ms * 6 = 100 ms * 7 = 250 ms * 8 = 500 ms * 9 = 1000 ms pshs d,cc * Check if subroutine module has already been linked IFGT LEVEL-1 ldu <D.DWSubAddr ELSE ldu >D.DWSubAddr ENDC * The following code is commented because the pio subroutine module has already * been linked and its entry point stored prior to us getting here. * bne SetTimer * Link to subroutine module * clra * leax iosub,pcr * os9 F$Link * bcs ClkEx * tfr y,u * IFGT LEVEL-1 * stu <D.DWSubAddr * ELSE * stu >D.DWSubAddr * ENDC * Initialize the low level device * jsr ,u SetTimer orcc #IntMasks ldd #CSETIMR*256+$02 std 1,s * Tell Arduino to generate timer interrupts leax 1,s ldy #2 jsr 6,u ldy #1 jsr 3,u lda ,x cmpa #RACK beq SETIM1 ldy #1 jsr 3,u read error code bra ClkEx SETIM1 * Tell PIA to enable interrupts ldx #PIA0Base lda 3,x ora #$01 *enable interrupts sta 3,x lda 2,x *clear pending ints ClkEx puls cc,d,pc *iosub fcs /pio/ ELSE IFNE atari IFNE USENMI lda #$40 sta NMIEN enable VBlank NMI rts ELSE lda #IRQST.TIMER1 pshs cc orcc #IntMasks ora <D.IRQENShdw sta <D.IRQENShdw sta IRQEN lda #%00101001 sta AUDCTL clr AUDC1 lda #$FF sta AUDF1 sta STIMER puls cc,pc ENDC ELSE ldx #PIA0Base point to PIA0 clra no error for return... pshs cc save IRQ enable status (and Carry clear) orcc #IntMasks stop interrupts sta 1,x enable DDRA sta ,x set port A all inputs sta 3,x enable DDRB coma sta 2,x set port B all outputs ; ldd #$343C [A]=PIA0 CRA contents, [B]=PIA0 CRB contents ldd #$3435 IRQ needs to be left enabled for Level1, as no GIME generated IRQ sta 1,x CA2 (MUX0) out low, port A, disable HBORD high-to-low IRQs stb 3,x CB2 (MUX1) out low, port B, disable VBORD low-to-high IRQs lda 2,x clear possible pending PIA0 VBORD IRQ puls cc,pc recover IRQ enable status and return ENDC ENDC * * Clock IRQ Entry Point * * For CoCo 1/2, called once every 16.667 milliseconds SvcIRQ clra tfr a,dp set direct page to zero IFNE corsham tst PIA0Base+3 bmi ClearInt it's a clock interrupt -- clear it jmp [>D.SvcIRQ] else service other possible IRQ ClearInt tst PIA0Base+2 clear clock interrupt by reading register ELSE IFNE atari IFNE USENMI sta NMIRES clear NMI interrupt ELSE lda IRQST get hw byte bita #IRQST.TIMER1 beq L0032 branch if interrupt occurred jmp [>D.SvcIRQ] else service other possible IRQ L0032 lda #$FF sta AUDF1 lda <D.IRQENShdw tfr a,b A = clear interrupt, B = set interrupt anda #^IRQST.TIMER1 orb #IRQST.TIMER1 sta IRQEN stb IRQEN stb <D.IRQENShdw sta STIMER ENDC ELSE tst PIA0Base+3 get hw byte bmi L0032 branch if sync flag on jmp [>D.SvcIRQ] else service other possible IRQ L0032 tst PIA0Base+2 clear interrupt ENDC ENDC dec <D.Tick decrement tick counter bne L007F go around if not zero ldb <D.Sec get minutes/seconds * Seconds increment incb increment seconds cmpb #60 full minute? bcs L0079 nope... * * Call GetTime entry point in Clock2 * ldx <D.Clock2 get entry point to Clock2 jsr $03,x call GetTime entry point fcb $8C skip next 2 bytes L0079 stb <D.Sec update sec L007B lda <D.TSec get ticks per second value sta <D.Tick and repopulate tick decrement counter L007F clra clear A pshs a and save it on the stack ldy <D.CLTb get pointer to VIRQ Polling Entries bra L009E go to the processing portion of the loop L0087 ldd Vi.Cnt,x get count down counter subd #$0001 subtract tick count bne L009C branch if not at terminal count ($0000) lda #$01 sta ,s set flag on stack to 1 lda Vi.Stat,x get status byte beq DelEntry branch if zero (one shot, so delete) L0096 ora #Vi.IFlag set interrupted flag sta Vi.Stat,x save in packet ldd Vi.Rst,x get reset count L009C std Vi.Cnt,x save tick count back L009E ldx ,y++ get two bytes at Y bne L0087 if not zero, branch lda ,s+ else get byte off stack beq GoAltIRQ branch if zero ldx <D.Proc else get pointer to current process descriptor beq L00AE branch if none tst P$State,x test process state bpl UsrPoll branch if system state not set L00AE jsr [>D.Poll] poll ISRs bcc L00AE keep polling until carry set GoAltIRQ jmp [>D.AltIRQ] jump into an alternate IRQ if available DelEntry bsr DelVIRQ delete the VIRQ entry bra L0096 UsrPoll leay >up@,pcr point to routine to execute jmp [>D.URtoSs] User to System up@ jsr [>D.Poll] call polling routine bcc up@ keep polling until carry set ldx <D.Proc get current process descriptor ldb P$State,x and its state andb #^SysState turn off sysstate bit stb P$State,x save new state ldd <P$SWI2,x std <D.SWI2 ldd <D.UsrIRQ std <D.SvcIRQ bra GoAltIRQ DelVIRQ pshs y,x save off Y,X dl@ ldx ,y++ get next entry stx -$04,y move up bne dl@ continue until all are moved puls y,x restore leay -2,y move back 2 from Y (points to last entry) rts return * Install or Remove VIRQ Entry FVIRQ pshs cc orcc #IntMasks mask all interrupts ldy <D.CLTb get pointer to VIRQ polling table ldx <D.Init get pointer to init module ldb PollCnt,x get poll count ldx R$X,u get pointer to caller's X beq L0118 branch if removing tst ,y entry available? beq L010C subb #$02 lslb leay b,y tst ,y bne PTblFul polling table full L0106 tst ,--y beq L0106 leay $02,y L010C ldx R$Y,u stx ,y ldy R$D,u sty ,x bra L0124 L0118 leax R$Y,u X = caller's Y L011A tst ,y end of VIRQ table beq L0124 branch if so cmpx ,y++ else compare to current VIRQ entry and inc Y bne L011A continue searching if not matched bsr DelVIRQ else delete entry L0124 puls cc clrb rts PTblFul puls cc comb ldb #E$Poll rts * F$Time system call code FTime ldx R$X,u ldd <D.Year std ,x ldd <D.Day std 2,x ldd <D.Min std 4,x clrb rts emod len equ * end