1: TOYCSR = 177526 2: 3: / April 6, 2000 - sms@moe.2bsd.com 4: / Remove the cpu type (93 or 94) restriction and probe for the TOY register. 5: / Some systems have clock boards added _and_ P11 (Begemot Computer Associates' 6: / PDP-11 emulator) have support for the TOY clock. 7: / 8: / April 10, 1997 - sms@moe.2bsd.com 9: / The day of week calculation was incorrect and would return -1 for Saturday 10: / rather than 6. Alan Sieving spotted this one too (toyset.s must be favorite 11: / reading material ;-)) 12: / 13: / February 6, 1997 - sms@moe.2bsd.com 14: / Forgot that May has 31 days. Thanks to Alan Sieving (ars@quickware.com) for 15: / spotting this. 16: / 17: / August 21, 1993 - Steven M. Schultz (sms@wlv.iipo.gtegsc.com) 18: / This is a standalone program which is used to set the TOY (Time Of Year) 19: / clock on a PDP-11/93 or 11/94. If this program is run on other than a 20: / 93 or 94 an error is printed and the program 'exits' back to the boot 21: / runtime. 22: / 23: / The current date is printed (in the same format used to enter the new date) 24: / and the prompt "Toyset> " is displayed. At that time a string of the form: 25: / YYMMDDHHMM[.SS]\n is entered. The seconds "SS" are optional, if not entered 26: / the seconds will be set to 0. Any invalid input string simply loops back 27: / to the top of the program. 28: / 29: / To not change the date and time simply hit a return and the program will 30: / exit, returning control to 'boot'. 31: 32: .globl _main, csv, cret, _printf, _gets, _exit, _module 33: .globl nofault 34: 35: _main: 36: main: 37: jsr r5,csv / srt0.o sets up a C frame... 38: 39: jsr pc,init / probe for clock, display current TOY 40: 41: clrb line / init buffer 42: mov $line,-(sp) 43: jsr pc,_gets / get input from user 44: tst r0 45: bgt 1f 46: leave: 47: jsr pc,_exit / exit on error 48: 1: 49: tstb line / did we get anything? 50: beq leave / nope - go exit 51: 52: clr r3 / clear '.' seen flag 53: mov $line,r4 / point to input data 54: 2: 55: movb (r4)+,r0 56: beq 1f / end of string - go validate it 57: cmpb r0,$'. / are there seconds present? 58: bne 2b / not yet - go try another byte 59: clrb -1(r4) / zap '.' - separating two parts of date 60: mov r4,r3 / set seconds present flag 61: tstb (r3)+ / must have two... 62: beq main / and only two... 63: tstb (r3)+ / characters after... 64: beq main / the '.'... 65: tstb (r3) / followed by a ... 66: bne main / null character. 67: 1: 68: clrb seconds / assume no seconds (start of minute) 69: tst r3 / do we have seconds? 70: beq nosec / no - br 71: cmpb -(r3),-(r3) / back up to beginning of seconds string 72: mov r3,-(sp) 73: jsr pc,atoi2 / convert two digits to binary 74: tst (sp)+ 75: cmp r0,$59. / range check 76: bhi main / error - go back to top 77: movb r0,seconds / save for later 78: nosec: 79: sub $line+1,r4 / number of characters in date string 80: cmp r4,$10. / _must_ have *exactly* "YYMMDDhhmm" 81: bne main / back to the top on error 82: mov $line,r4 / point to start of date string 83: mov r4,-(sp) 84: jsr pc,atoi2 / convert 2 digits to binary (year) 85: tst (sp)+ 86: cmp r4,$-1 / error? 87: beq main / yes - go back to top 88: cmp r0,$69. / before [19]69? 89: bgt 1f / no - it's a 1970-1999 year - br 90: add $100.,r0 / 21st century and 11s are still around! 91: 1: 92: movb r0,year / save year for later 93: cmpb (r4)+,(r4)+ / skip two digits, move to month 94: mov r4,-(sp) 95: jsr pc,atoi2 / convert month to binary 96: tst (sp)+ 97: cmp r0,$12. / range check 98: bhi main / back to top on too high 99: cmpb (r4)+,(r4)+ / move on to day of month 100: movb r0,month / save month for later 101: beq main / can't have a month 0 102: mov r4,-(sp) 103: jsr pc,atoi2 / convert day of month to binary 104: tst (sp)+ 105: movb month,r1 106: cmpb r0,Mtab-1(r1) / crude check (no leap year case) 107: bhi main / on day of month 108: movb r0,day / save the day for later 109: cmpb (r4)+,(r4)+ / move along to hours of day 110: mov r4,-(sp) 111: jsr pc,atoi2 / convert hours of day to binary 112: tst (sp)+ 113: cmp r0,$23. / can't have more than 23 hours 114: bhi main / but 00 is ok (midnight) 115: movb r0,hours / save hours for later 116: cmpb (r4)+,(r4)+ / move over to minutes 117: mov r4,-(sp) 118: jsr pc,atoi2 / convert minutes to binary 119: tst (sp)+ 120: cmp r0,$59. / can't have more than 59 minutes 121: bhi main / back to top on out of range error 122: movb r0,minutes / save for later 123: 124: / need to compute the "day of week". why the TOY clock couldn't figure 125: / this out (or do without) itself i don't know. 126: 127: jsr pc,t2dow / find out "day of week" 128: movb r0,dow / save for later 129: 130: / now we have to convert the binary data to BCD. We needed (or preferred) 131: / the binary form for ease of range checking but the TOY wants BCD. Besides 132: / i like to improve my typing skills ;-) 133: 134: movb seconds,r1 135: jsr pc,tobcd 136: movb r0,bcd+1 / seconds 137: 138: movb minutes,r1 139: jsr pc,tobcd 140: movb r0,bcd+2 / minutes 141: 142: movb hours,r1 143: jsr pc,tobcd 144: movb r0,bcd+3 / hours 145: 146: movb dow,r1 147: jsr pc,tobcd 148: movb r0,bcd+4 / day of week 149: 150: movb day,r1 151: jsr pc,tobcd 152: movb r0,bcd+5 / day of month 153: 154: movb month,r1 155: jsr pc,tobcd 156: movb r0,bcd+6 / month of year 157: 158: movb year,r1 159: jsr pc,tobcd 160: movb r0,bcd+7 161: 162: / Now initialize the TOY by sending the 'recognition' sequence. We have 163: / to inline this because immediately after the recognition sequence must 164: / come the 'write' of data - a 'read' to save the contents of the CSR 165: / would tell the TOY we're reading data. *sigh* 166: 167: tst *$TOYCSR / strobe the clock register 168: clr -(sp) / save previous high byte of register 169: movb *$TOYCSR+1,(sp) / only bit 8 belongs to TOY! 170: bic $1,(sp) / make sure bit 8 (TOY bit) is clear 171: mov $2,r2 / number of double words to send clock 172: 1: 173: mov $35305,r0 / first word of recognition code 174: jsr pc,toyload / send it to clock 175: mov $56243,r0 / second word 176: jsr pc,toyload / send it 177: sob r2,1b / do the whole thing twice 178: 179: / Now write the data to the TOY without an intervening 'tst' or 'movb' 180: / to the CSR. 181: 182: mov bcd,r0 / first two bytes 183: jsr pc,toyload 184: mov bcd+2,r0 / bytes 3 and 4 185: jsr pc,toyload 186: mov bcd+4,r0 187: jsr pc,toyload / bytes 5 and 6 188: mov bcd+6,r0 189: jsr pc,toyload / bytes 7 and 8 190: 191: tst (sp)+ / clean stack now, we're done 192: clr r0 / "exit" status. ha! ;-) 193: jsr pc,_exit 194: 195: / Probe for the TOY register. If present initialize the TOY and read the 196: / current date otherwise print an error message and exit. Convert the date 197: / into printable form and print it out along with the prompt. 198: 199: init: 200: mov $1f, nofault / catch fault if no TOY clock 201: tst *$TOYCSR 202: br 2f / we have a clock 203: 1: 204: mov $errmsg1,-(sp) 205: jsr pc,_printf 206: mov $1,r0 207: jsr pc,_exit 208: 2: 209: clr nofault / faults are serious again 210: jsr pc,initoy / init the TOY clock 211: mov $bcd,-(sp) / buffer for the date 212: jsr pc,_gettoy / read the TOY 213: tst (sp)+ 214: mov $timbuf,r3 / where to put printable form of date 215: clr r1 216: bisb bcd+7,r1 / year in bcd 217: jsr pc,bcd2msg 218: movb bcd+6,r1 / month in bcd 219: jsr pc,bcd2msg 220: movb bcd+5,r1 / day of month in bcd 221: jsr pc,bcd2msg 222: movb bcd+3,r1 / hour of day in bcd 223: jsr pc,bcd2msg 224: movb bcd+2,r1 / minute of hour in bcd 225: jsr pc,bcd2msg 226: movb $'.,(r3)+ 227: movb bcd+1,r1 / seconds of minute in bcd 228: jsr pc,bcd2msg 229: mov $timmsg,-(sp) 230: jsr pc,_printf 231: tst (sp)+ 232: rts pc 233: 234: / convert two bytes of ascii pointed to by 2(sp) into a binary number. 235: / the return value is in r0. 236: 237: atoi2: 238: movb *2(sp),r1 239: inc 2(sp) 240: movb *2(sp),r0 241: sub $'0,r1 242: sub $'0,r0 243: mul $10.,r1 244: add r1,r0 245: rts pc 246: 247: / convert a byte of BCD (in r1) two to ascii digits and place those 248: / at (r3)+ and (r3)+ respectively. 249: 250: bcd2msg: 251: clr r0 252: div $16.,r0 253: add $'0,r0 254: add $'0,r1 255: movb r0,(r3)+ 256: movb r1,(r3)+ 257: rts pc 258: 259: / convert a binary number (in r1) to a byte containing two bcd digits. 260: / return result in r0. 261: 262: tobcd: 263: clr r0 264: div $100.,r0 / truncate to max of 99 265: clr r0 266: div $10.,r0 267: ash $4,r0 268: bis r1,r0 269: rts pc 270: 271: / To calculate the day of the week (Sunday = 1) an algorithm found in 272: / "The Ready Reference (r) Weekly Planner 1986 ((c) 1986 Ready Reference)" 273: / is used. 274: 275: t2dow: 276: jsr r5,csv / save registers 277: movb year,r4 / low two digits (93) of year 278: mov r4,r0 279: asr r0 / divide by 4 280: asr r0 / ignoring any remainder 281: add r0,r4 / add to year 282: movb day,r0 283: add r0,r4 / add day of month 284: movb month,r0 285: movb m_magic-1(r0),r3 286: cmp r0,$2 / February Or January? 287: bgt 1f / no - br 288: movb year,r0 289: add $1900.,r0 290: mov r0,-(sp) 291: jsr pc,isleap / are we in a leap year? 292: mov r0,(sp)+ 293: beq 1f / no - br 294: dec r3 / adjust number from magic month table 295: 1: 296: add r3,r4 / add magic number to total 297: cmpb year,$69. / before 1969? 298: bgt 2f / no - br, we're in the 20th century 299: add $6,r4 / adjustment for 21st century 300: 2: 301: mov r4,r1 302: clr r0 303: div $7,r0 / divide total by 7 304: dec r1 / Saturday or Sunday? 305: bgt 3f / no - br 306: add $7,r1 / yes - set Saturday to 6, Sunday to 7 307: 3: 308: mov r1,r0 / put return value in right place 309: jmp cret / 1 = Monday ... 7 = Sunday 310: 311: / (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) 312: 313: isleap: 314: clr r0 315: mov 2(sp),r1 / get year 316: bit $3,r1 / easy check for "mod 4" 317: bne 1f / can't be a leap - br 318: div $100.,r0 / % 100 319: tst r1 / check remainder 320: bne 2f 321: bit $3,r0 / % 400 322: beq 2f 323: 1: 324: clr r0 325: rts pc 326: 2: 327: mov $1,r0 328: rts pc 329: 330: initoy: 331: tst *$TOYCSR / strobe the clock register 332: clr -(sp) / save previous high byte of register 333: movb *$TOYCSR+1,(sp) / only bit 8 belongs to TOY! 334: bic $1,(sp) / make sure bit 8 (TOY bit) is clear 335: mov $2,r2 / number of double words to send clock 336: 1: 337: mov $35305,r0 / first word of recognition code 338: jsr pc,toyload / send it to clock 339: mov $56243,r0 / second word 340: jsr pc,toyload / send it 341: sob r2,1b / do the whole thing twice 342: tst (sp)+ / clean stack 343: rts pc 344: 345: / send contents of r0 to the TOY. 2(sp) has the old bits 9-15, bit 8 346: / has been cleared. 347: 348: toyload: 349: mov $16.,r1 / number of bits to send 350: 1: 351: mov r0,r3 / scratch copy 352: bic $177776,r3 / clear all but bit being sent 353: bis 2(sp),r3 / merge in old_csr_bits 354: movb r3,*$TOYCSR+1 / send bit to clock 355: asr r0 / shift pattern down 356: sob r1,1b / do all 16 bits in the word 357: rts pc 358: 359: .globl _gettoy 360: _gettoy: / (void)gettoy(&char[8]); 361: jsr r5,csv / C callable 362: mov 4(r5),r2 / buffer address 363: mov $4,r3 / number of words in buffer 364: 1: 365: mov $16.,r4 / number of bits in word 366: 2: 367: movb *$TOYCSR+1,r0 / low bit of top byte is a clock bit 368: asr r0 / put it in carry 369: ror r1 / ripple in at top end of r1 370: sob r4,2b / do all 16 bits 371: mov r1,(r2)+ / store the word in the buffer 372: sob r3,1b / do all 4 words 373: jmp cret / and return 374: 375: .data 376: Mtab: 377: .byte 31.,29.,31.,30.,31.,30. 378: .byte 31.,31.,30.,31.,30.,31. 379: m_magic: 380: .byte 1,4,4,0,2,5,0,3,6,1,4,6 381: errmsg1: 382: <No TOY clock present\n\0> 383: timmsg: 384: <Current TOY: > 385: timbuf: 386: .=.+13. / room for YYMMDDhhmm.ss 387: <\n> 388: <Toyset\> \0> 389: _module: 390: <Toyset\0> 391: .even 392: .bss 393: seconds: 394: .=.+1 395: minutes: 396: .=.+1 397: hours: 398: .=.+1 399: day: 400: .=.+1 401: month: 402: .=.+1 403: year: 404: .=.+1 405: dow: 406: .=.+1 407: .even 408: bcd: 409: .=.+8. 410: line: 411: .=.+64.