        IF      IODRIVERRAM
        PAGE    *** CLOCK: DRIVER ***
CLOCKDCB        FCB     1       CLOCK'S ALWAYS DONE
        FDB     0       LASTER
        FDB     CLOCKSTR
        FDB     NEXTDEVICEDCB
        FDB     CLOCKDRIVER
DIV60DIVIDEND   EQU     *
CLOCKBUFFER     FCB     0,0,0
DAY     FCB     0
MONTH   FCB     0
YEAR    FCB     0
CLOCKFRACTION   FCB     -1
CLOCKSTR        FCC     'CLOCK:'
        FCB     0
*
NEXTDEVICEDCB   SET     CLOCKDCB
*
        FIN     IODRIVERRAM
        IF      IODRIVERBODY
CLOCKDRIVER     FDB     CLOCKOPEN
        FDB     CLOCKCLOSE
        FDB     CLOCKREADA
        FDB     ILLDEVICEOP     WRITEA IS A NO-NO
        FDB     CLOCKREADB
        FDB     CLOCKWRITEB
        FDB     ILLDEVICEOP     YOU UPDATE THE CLOCK, NOT REBUILD IT (CREATE)
        FDB     ILLDEVICEOP     RENAME IT TO WHAT? CLOCK-RADIO: ???
        FDB     ILLDEVICEOP     YOU CAN'T GET RID OF THE CLOCK, NEITHER
        FDB     ILLDEVICEOP     NO CONTROL FUNCTIONS
        FDB     CLOCKSTATUS     SAY "I'M A CLOCK, TICK-TOCK"
        FDB     CLOCKRESET      
        FDB     CLOCKPFRESTART  WHO UNPLUGGED ME???
*
CLOCKCLOSE      EQU     *       WHAT AM I SUPPOSED TO DO, PUT THE CLOCK AWAY??
CLOCKOPEN       EQU     *       HOW ABOUT LOOKING AT YOUR $9 TI CHEAPIE, MAC!
CLOCKPFRESTART  EQU     *       AM I SUPPOSED TO KEEP TIME WITH NO POWER???
        OKRTS           TOUGH!

*
CLOCKSPRUNG     JMP     ILLDEVICEOP

CLOCKSTATUS     CMPA    #SC:GETTYPE
        BNE     CLOCKSPRUNG
        LDX     SDOS+SDOS:IOBLOCKPTR
        JSR     SDOS+SDOS:CHECKRDLEN    HAS HE GOT A BYTE SPACE
        FDB     1
        LDX     SCBLK:RDBUF,X   GET THE BUFFER POINTER
        LDAA    #DVTYP.CLOCK    I'M ALIVE AND TICKING (HOPEFULLY!)
        STAA    DVTYP:TYPE,X
        OKRTS

CLOCKWRITEB     JSR     SDOS+SDOS:CHECKWRLEN    HAS HE GOT 6 BYTES?
        FDB     6
        LDX     SCBLK:WRBUF,X   WRITE BUFFER POINTER
        LDAB    #6
CLOCKWB1        LDAA    0,X
        INX
        PSHA
        DECB
        BNE     CLOCKWB1
        JSR     INTDISABLE      DON'T WANT TO UPDATE THE CLOCK WHILE SETTING IT
        LDX     #SDOS
        LDAB    #6
CLOCKWB2        PULA
        STAA    SDOS:CLOCK+5,X
        DEX
        DECB
        BNE     CLOCKWB2
        JSR     INTENABLE
        OKRTS           AND WE'S DONE!
*
*
*
CLOCKREADB      JSR     SDOS+SDOS:CHECKRDLEN
        FDB     6       HE BETTER HAVE 6 BYTES AT LEAST
        JSR     INTDISABLE      DON'T WANT CLOCK UPDATED WHILE READING IT
        LDX     #SDOS
        LDAB    #6
CLOCKRB1        LDAA    SDOS:CLOCK,X
        INX
        PSHA
        DECB
        BNE     CLOCKRB1
        JSR     INTENABLE
        LDX     SDOS+SDOS:IOBLOCKPTR
        LDX     SCBLK:RDBUF,X
        LDAB    #6
CLOCKRB2        PULA
        STAA    5,X
        DEX
        DECB
        BNE     CLOCKRB2
        OKRTS
*
*
*
CLOCKREADA      JSR     SDOS+SDOS:CHECKRDLEN
        FDB     17      ENOUGH FOR HH:MM:SS MM/DD/YY
        BSR     CLOCKGETTD      GET TIME, DATE FROM SDOS
        BSR     CLOCKDATE       FORMAT DATE
        JSR     CLOCKTIME       FORMAT TIME
        LDX     SDOS+SDOS:IOBLOCKPTR
        LDAA    #17
        STAA    SCBLK:RPLEN+1,X
        LDX     SCBLK:RDBUF,X
        STX     TEMPX
        LDX     #TIME$
CLOCKRA1        LDAB    0,X
        INX
        STX     TEMPX+2
        LDX     TEMPX
        STAB    0,X
        INX
        STX     TEMPX
        LDX     TEMPX+2
        DECA
        BNE     CLOCKRA1
        OKRTS
*
*
*
CLOCKGETTD      JSR     INTDISABLE
        LDX     #SDOS
        LDAB    #6
CLOCKGETTD1     LDAA    SDOS:CLOCK,X
        INX
        PSHA
        DECB
        BNE     CLOCKGETTD1
        JSR     INTENABLE
        LDX     #CLOCKBUFFER
        LDAB    #6
CLOCKGETTD2     PULA
        STAA    5,X
        DEX
        DECB
        BNE     CLOCKGETTD2
        RTS
*
*
*
DATE    BSR     CLOCKGETTD
CLOCKDATE       LDAA    MONTH
        BSR     BCDTOASC
        STAA    DATE$:MONTH
        STAB    DATE$:MONTH+1
        LDAA    DAY
        BSR     BCDTOASC
        STAA    DATE$:DAY
        STAB    DATE$:DAY+1
        LDAA    YEAR
        BSR     BCDTOASC
        STAA    DATE$:YEAR
        STAB    DATE$:YEAR+1
        LDX     #DATE$
        LDAA    #8
        RTS
*
BCDTOASC        TAB
        ANDB    #$F
        ADDB    #'0
        LSRA
        LSRA
        LSRA
        LSRA
        ADDA    #'0
        RTS
*
*
TIME    BSR     CLOCKGETTD
CLOCKTIME       JSR     DIVIDEBY60      NOW DIVIDEND HAS SECONDS
        LDX     #TIME$:SECONDS
        BSR     CLOCKMAKEXX
        LDX     #TIME$:MINUTES
        BSR     CLOCKMAKEXX
        LDX     #TIME$:HOURS
        BSR     CLOCKMAKEXX
        LDX     #TIME$
        LDAA    #8
        RTS
*
CLOCKMAKEXX     JSR     DIVIDEBY60
        ADDA    #'0
        ADDB    #'0
        STAB    0,X
        STAA    1,X
        RTS
*
TIME$   EQU     *
TIME$:HOURS     FCC     '00:'
TIME$:MINUTES   FCC     '00:'
TIME$:SECONDS   FCC     '00 '
DATE$   EQU     *
DATE$:MONTH     FCC     '00/'
DATE$:DAY       FCC     '00/'
DATE$:YEAR      FCC     '00'
*
*
*
*
*       DIVIDE BY 60 -- DIVIDE 3 BYTE "DIV60DIVIDEND" BY 60
*               DIVIDEND:=DIVIDEND/60
*               (A):=REMAINDER MOD 10
*               (B):=INT(REMAINDER/10)
DIVIDEBY60      EQU     *
        LDAB    #3*8+1  NUMBER OF BITS
        CLRA
DIVIDE60L       EQU     *
        ROLA
        CMPA    #60
        BCS     DIVIDE60L2
        SUBA    #60
        SEC
        BRA     DIVIDE60L2.1    SKIP THE NEXT INSTRUCTION
DIVIDE60L2
        CLC
DIVIDE60L2.1
        ROL     DIV60DIVIDEND+2
        ROL     DIV60DIVIDEND+1
        ROL     DIV60DIVIDEND+0
        DECB
        BNE     DIVIDE60L
        LDAB    #-1
DIVIDE60L3      INCB
        SUBA    #10
        BCC     DIVIDE60L3
        ADDA    #10
        RTS
        FIN     IODRIVERBODY
        IF      IODRIVERPOLL
        IF      &USECONSOLEACIAASCLOCK
POLL1
        IF      USEACIAASCLOCK
        LDAA    CLOCKACIA
        BPL     POLL2A
        STAA    CLOCKACIA+1     * RESET TDRE TO TRANSMIT ( FOR 1/60TH SEC. )
        ELSE
        LDAA    MSCTL   CLOCK ?
        BPL     POLL2A
        LDAA    MSDAT   YES, CLEAR THE INTERRUPT
        DEC     TIMER   USED TO HANDLE 50/60HZ OPTION
        BNE     POLL4   SEE "COMPUTECLKCONSTANT" IN INIT CODE
TIMEDELAY       EQU     *+1
        LDAA    #1      GET NEW VALUE TO INITZ TIMER WITH
        STAA    TIMER
TIMEPASSED      EQU     *+1
        FIN     ELSE USEACIAASCLOCK
        LDAA    #1      1/60TH SECOND WENT BY...
        IF      MT
        JMP     MT:CLOCKTICKED
        ELSE
        JMP     SDOS+SDOS:CLOCKTICKED   HOW EASY TO HANDLE!
        FIN
POLL4   JMP     SDOS+SDOS:RTI
TIMER   FCB     1
POLL2A  EQU     *
        FIN     &USECONSOLEACIAASCLOCK
        FIN     IODRIVERPOLL
        IF      IODRIVERINIT

        IF      USECONSOLEACIAASCLOCK
CLOCKRESET      EQU     *
        OKRTS
        ELSE
        IF      USEACIAASCLOCK
CLOCKRESET        LDX     #CLOCKACIA
        LDAA    #3
        STAA    0,X     * MASTER RESET
        LDAA    #%00110101      TRANS. INT., 8DATA, 1STOP  /16
        STAA    0,X
        LDX     #CLOCKDCB
        STX     DCBPOINTER
        OKRTS
        ELSE
MSCTL   EQU     $FAF7   MISCELLANEOUS CONTROL PIA
MSDAT   EQU     $FAF6

CLOCKRESET      EQU     *
        LDAA    #%00000101      USE CB1 INTERRUPT ON KEYBOARD PIA...
        STAA    MSCTL   TO PROVIDE "60HZ" INTERRUPT
*
*       NOW DECIDE WHETHER WE'RE RUNNING 50 OR 60 HZ
*       AND BUILD NEW CLOCK CONSTANTS AS APPROPRIATE
*
        LDAA    MSDAT   ACK VERT SYNC
        LDX     #0
WAITVSYNC1      LDAA    MSCTL   WAIT FOR VERT SYNC
        BPL     WAITVSYNC1
        LDAA    MSDAT   ACK VERT SYNC
WAITVSYNC2      INX             COUNT # TIMES THAT WE LOOP AROUND...
        LDAA    MSCTL   WAITING FOR NEXT VERT SYNC
        BPL     WAITVSYNC2
        LDAA    MSDAT   ACK VERT SYNC, JUST TO BE NICE
        STX     TEMPX   = CLOCK SPEED
        LDAA    TEMPX   NOW 55HZ @ 1.2569 US./ CYCLE
        LDAB    TEMPX+1 = 14465 CYCLES ( $3C7 = 60 HZ; $487 = 50 HZ)
        SUBB    #(($3C7+$487)/2)&$FF    REMEMBER THAT THERE ARE 12 CYCLES...
        SBCA    #(($3C7+$487)/2)/256    PER LOOP ITERATION ABOVE
        LDAA    #1      ASSUME 60 HZ
        LDAB    #1      "EVERY 1 TICKS, TELL SDOS 1/60 SEC PASSED"
        BCS     COMPUTECLKSPEED1        B/ WAS 60 HZ
        LDAA    #5      OOPS, IS 50 HZ, GET PROPER CONSTANTS
        LDAB    #6      "EVERY 5 TICKS, TELL SDOS 1/10 SEC PASSED"
COMPUTECLKSPEED1        EQU     *
        STAA    TIMEDELAY       # TICKS TO COUNT
        STAB    TIMEPASSED      # 60THS SEC PASSED
        CLR     $FAE0   RESET "POWER-FAIL" LO-LITE
        OKRTS
        FIN     ELSE USEACIAASCLOCK
        FIN     ELSE USECONSOLEACIAASCLOCK
        FIN     IODRIVERINIT
