; *************************************************** ; 6801 slot control ;13 Oct. 1982 12:02 pm PDT (Wednesday) ;--Turned off offset toggling for people who have Ravens with no offsetter ;GW & DP ;May 14, 1982 12:24 PM ;**************************************************** ;ram equates ;**************************************************** .getnolist "m6801predefs.sr" .getnolist "lsepdefs.bca" datadir1 = 00000 ; 6801 data direction register 1 datadir2 = 00001 ; 6801 data direction register 2 ipoprt1 = 00002 ; 6801 ipo port 1 ipoprt2 = 00003 ; 6801 ipo port 2 datadir3 = 00004 ; 6801 data direction register 4 datadir4 = 00005 ; 6801 data direction register 5 ipoprt3 = 00006 ; 6801 ipo port 3 ipoprt4 = 00007 ; 6801 ipo port 4 tcsr = 00008 ; timer control status register cntrhi = 00009 ; counter high byte cntrlo = 0000a ; counter low byte outcmphi = 0000b ; output compare high byte outcmplo = 0000c ; output compare low byte inpcaphi = 0000d ; input capture high byte inpcaplo = 0000e ; input capture low byte ipoprt3cs= 0000f ; ipo port 3 control,status register serate = 00010 ; serial rate and mode register (say what?) sercon = 00011 ; serial control and status register serrx = 00012 ; serial receiver data register sertx = 00013 ; serial transmit data register ramcon = 00014 ; rampeprom control register ;************************************************** ;15 to 1f hex reserved (don't ask) ;************************************************** altoi = 00080 ; input byte from alto altoo = 00081 ; output byte to alto ;N.B., All bits but one of this port are output direction UartOUT = 00082 ; output byte to uart. uarti = 00083 ; input byte from uart inbyte = 00084 ; input byte from slot card OutToSlot = 00085; output byte to slot card stcntr = 00086 ; system state counter ;********************************************* ;some ram assignments ;********************************************* uartflgs = 00087; flag byte for uart communications MultiPage = 00088; flag for multi-feed sequences PageTimer = 0089; two-byte quantity for doing page sync timing PageTimer1 = 0090; PageSyncHigh = 0091; WhichTray = 0092; OffSetToggle = 0093; ; input byte equates prntreq = 01 ; print request bit from slot ; output byte equates pgsync = 080 ; page sync bit to slot online = 040 ; online bit to slot I.E. the printer is ready onlineCpl = 0BF; compliment of online addpaper = 20 ; add paper bit to slot [active low] addpaperCpl = 0DF; compliment of addpaper clrpprpth = 10 ; clear paper path bit to slot [active low] clrpprpthCpl = 0EF; compliment of clrpprpth allOK = 070 ;status word that tells slot that all is ok. prombase = 0F800 ; base of the 2716 prt1msk = 0fe wait = 2400 ;2400 = ~8mSec terminalWait = 0F000; uartOutResetWait = 000FF pageDuration = 024B; i.e., 024 * 2400 = ~ 4.62 seconds ;125(decimal) in the high multiplier =~1 second So for 4.62 seconds, need 587(decimal) ;587 decimal = 024B (hex) ;**************************************************** ; Uart equates combit = 01 recfull = 80 ;this is the "uart receiver full" bit ;**************************************************** ; interupt vector equates ;**************************************************** restrtms = 0fffe restrtls = 0ffff ; restart vector nmims = 0fffc nmils = 0fffd ; nonmaskable interupt swims = 0fffa swils = 0fffb ; software interupt irq1ms = 0fff8 irq1ls = 0fff9 ; irq1 interupt tcapms = 0fff6 tcapls = 0fff7 ; timer input capture or irq 2 interupt tcompms = 0fff4 tcompls = 0fff5 ; timer output compare or irq 2 interupt tovms = 0fff2 tovls = 0fff3 ; timer overflow or irq 2 interupt serinms = 0fff0 serinls = 0fff1 ; serial ipo interupt ;**************************************************** ; INIT the machine ;**************************************************** .loc 0f800 start: ldsi 000FF; stack grows down from here clra staae altoi staae altoo staae uarti staae UartOUT ; clear all the working registers staae inbyte staae OutToSlot staae stcntr staae uartflgs staae MultiPage staae PageTimer staae PageTimer1 ;zero out low order byte too staae PageSyncHigh ldaai prt1msk staae datadir1 ; set up the port for ipo ldaai prntreq andae ipoprt1 ; init the input byte staae inbyte ldaai 009 ; staae serate ; set rate to 9600 baud CC1 1 CC0 0 S1 0 S0 1 ldaai 00a ; staae sercon ; set tx and rx enable ldaai allOK; for now, say all's ok staae ipoprt1; send to SLOT ldaae OffSetToggle; we want to change the offset at beginning of each coma; document -- which is right after reset staae OffSetToggle; lddi uartOutResetWait; don't send anything out the uart for awhile jsr TimerWait; ldaai readStatus staae UartOut ;ask the Raven for its status ldaai combit ;don't bother to OR into this reg for now staae uartflgs; ; ldxi RunningStr; ; jsr OutString jsr SetTimer ;set interrupts ;*************************************************** ; start outer loop: ; ; read and update inputs from the slot card & set status for Raven ;*************************************************** ReadSlot: ldaai prntreq ; mask the raw input from port 1 andae ipoprt1 ; tab; ;save a copy eorae inbyte ; has it changed since last time? beq NoInput ; no change so don't change anything tba; beq NoInput ; is this a 1 to 0 transition? If so then skip. ;here when we get print request. We then decide which tray to feed from: ; it's always the opposite from the previous printed page. ; Afterward, we decide whether to offset the output, based on OffSetToggle. ; That variable is toggled at the beginning of each job. ldaae WhichTray; andai 001; beq DoBottom; ldaai feedTop jmp SendIt; DoBottom: ldaai feedBottom SendIt: ; pshb; ;commented this out for those who have Ravens ; ldabe OffSetToggle; ; that don't recognize offsetting ; andbi 001; ; aba; ; pulb; staae UartOUT ldaai combit ; set the flag that will cause output reg to be sent oraae uartflgs ;to the raven staae uartflgs NoInput: ;update outputs to the slot card stabe inbyte; ldaae OutToSlot ;remember to not destroy bits already there staae ipoprt1 jmp ReadSlot ;end of outer loop ;*************************************************** ; Interrupt Level!!! Timer interupt and uart communications. ;*************************************************** readuart: ldaai recfull andae sercon ; mask and test the receiver full bit beq NothingWaiting ;skip read if it isn't set ldaae serrx andai 7F; ;mask the parity bit off staae uarti ;*** For debugging, type received char from terminal back on terminal ; ldxi ShowCharString ; jsr OutString ; ldabe uarti ; jsr OutByteVal ; ldxi StrCRT; ; jsr OutString ;call status parsing routine here to take appropriate action, given input. ldabe uarti jsr StatusDispatch; ;for now, sets up OutToSlot NothingWaiting: ;If pagesync is high, decrement timer and drop signal if timer=0 ldaae PageSyncHigh; beq NoPageSync; ldde PageTimer; subdi 01; stde PageTimer bne NoPageSync; clre PageSyncHigh; here if page timer just expired ldaae OutToSlot; eorai pgsync; drop page sync signal staae OutToSlot; NoPageSync: ;write UART if have something to send ldaai combit; mask and test the communications flag andae uartflgs beq NothingToSend; don't send any thing if it's not set ldaae UartOUT ldabe sercon staae sertx ldaai combit; clear the flag cause we just send the character coma andae uartflgs staae uartflgs NothingToSend: jsr SetTimer rti ;*************************************************** ; status parsing routine: expects the command to be in acc B and ; returns a dispatch address in the IX register. This stuff processes only the ; status from the printer at the moment. ;*************************************************** StatusDispatch: subbi PSkey0; subtract the lowest command value from the command in ACb bcs CmdErrorRtn; the command passed in is less than the lowest command cmpbi PSillegalTop; now see if the command is greater than any we have. bcc CmdErrorRtn; ldxi PSTable; put the base address into the index register aslb; multiply the B register by two by shifting. abx; and add in the contents of AC b ldxx 00; load the memory location pointed to by IX reg. jsrx 00; call the procedure pointed to by the index register rts; done CmdErrorRtn: ldxi 000; rts; done ;the procs that are dispatched to: PSkey0Proc: rts; PSkey1Proc: rts; PSkey2Proc: rts; PSkey3Proc: rts; PSkey4Proc: rts; PSkey5Proc: rts; PSkey6Proc: rts; PSkey7Proc: rts; PSkey8Proc: rts; PSkey9Proc: rts; PSclearKeyProc: rts; PStestKeyProc: rts; PSonLineKeyProc: ldaae OutToSlot ;turn on "OnLine" signal to SLOT oraai online staae OutToSlot rts; PSoffLineKeyProc: ldaae OutToSlot ;turn off "OnLine" signal to SLOT andai onlineCpl staae OutToSlot rts; noopProc: rts; PSwaitProc: ldaae OutToSlot ;make "clrpprpth" signal to SLOT TRUE andai clrpprpthCpl ;(remember it's active low) staae OutToSlot rts; PSstandbyProc: ldaae OutToSlot; oraai allOK; [clearPaperPath=F, addPaper=F, OnLine=T, PageSync unaffected] staae OutToSlot; rts; PSfeederFaultProc: ldaae OutToSlot ;make "addpaper" signal to SLOT TRUE andai addpaperCpl ;(remember it's active low) staae OutToSlot rts; PShardStop1Proc: jmp PSwaitProc rts; PShardStop2Proc: jmp PSwaitProc rts; PShardStop3Proc: jmp PSwaitProc rts; PSsorterJamProc: jmp PSwaitProc rts; PSinterlockOpenProc: jmp PSwaitProc rts; PSfuserUnderTempProc: jmp PSwaitProc rts; PSrunFeedingProc: rts; PSrunReadyProc: rts; PSstatusDisplayedProc: rts; PScmdRejParityProc: ldaai combit; resend the last command and hope it's the right one oraae uartflgs ;to the raven staae uartflgs rts; PScmdRejUnrecogProc: rts; PScmdRejIllSeqProc: rts; PScmdRejSorterDownProc: rts; PSnoFeedTrayProc: jmp PSwaitProc rts; PSpageSyncProc: ldaae OutToSlot; oraai pgsync; ;will cause slot to relay this to uCode staae OutToSlot; on next cycle through main loop ;SET A TIMER FOR DROPPING PAGE SYNC HERE!!! lddi pageDuration; stde PageTimer; ince PageSyncHigh; set this boolean true for checking by the timer routine ldaae WhichTray; toggle the tray selection for next page coma; staae WhichTray; ;The idea here will be to eventually handle the case of multiple feeding ; If this is the result of a previous feed and there is another print request ; coming from the SLOT, feed another sheet here. ; tst MultiPage; ; beq PgSync1; not multi page if zero ; ldaai feedBottomNoOffset ; staae UartOUT; cause another feed if we're multi feeding ; ldaai combit; set the flag that will cause output reg to be sent ; oraae uartflgs ;to the raven ; staae uartflgs ; Think about decrementing the MultiPage word here OR at the beginning of the ; proc so as not to do one too many feeds PgSync1: rts; PSpageDeliveredProc: ; ldaae OutToSlot; this is now done at the expiration of the page timer ; eorai pgsync; ; staae OutToSlot; rts; PSpageDelveredSorterProc: jmp PSpageDeliveredProc; rts; PScycleOffLIneProc: jmp PSoffLineKeyProc rts; PSoffLineProc: jmp PSoffLineKeyProc rts; PSonLineProc: jmp PSonLineKeyProc rts; PSoutTrayFullProc: jmp PSwaitProc rts; PSstackerFullProc: jmp PSwaitProc rts; PSTable: .ADR PSkey0Proc; --"30" .ADR PSkey1Proc; .ADR PSkey2Proc; .ADR PSkey3Proc; .ADR PSkey4Proc; .ADR PSkey5Proc; .ADR PSkey6Proc; ; .ADR PSkey7Proc; "37" .ADR PSonLineKeyProc; "37" also! ; .ADR PSkey8Proc; "38" .ADR PSoffLineKeyProc; "38" also! .ADR PSkey9Proc; "39" .ADR PSclearKeyProc; "3A" .ADR PStestKeyProc; "3B" .ADR noopProc; .ADR noopProc; .ADR noopProc; .ADR noopProc; "3F" .ADR PSwaitProc; "40" .ADR PSstandbyProc; .ADR PSfeederFaultProc; .ADR noopProc; "43" .ADR PShardStop1Proc; "44" .ADR PShardStop2Proc; .ADR PShardStop3Proc; .ADR PSsorterJamProc; "47" .ADR PSinterlockOpenProc; .ADR PSfuserUnderTempProc; .ADR PSrunFeedingProc; "4A" .ADR PSrunReadyProc; .ADR PSstatusDisplayedProc; .ADR PScmdRejParityProc; "4D" .ADR PScmdRejUnrecogProc; .ADR PScmdRejIllSeqProc; "4F" .ADR PScmdRejSorterDownProc; .ADR PSnoFeedTrayProc; .ADR PSpageSyncProc; "52" .ADR PSpageDeliveredProc;"53" .ADR PSpageDelveredSorterProc; .ADR PScycleOffLIneProc; .ADR PSoffLineProc; "56" .ADR PSonLineProc; .ADR PSoutTrayFullProc; .ADR PSstackerFullProc; --"59" SetTimer: ;this routine sets timer interrupt lddi wait ; load D with wait count addde cntrhi ; add D to counter clre tcsr ; clear timer control status reg stde outcmphi ; set output compare ldaai 008 ; staae tcsr cli; ;clear interrupt disable! rts; ;NB, if this routine is called from code that can be interrupted, it's a good ; idea to change this routine to turn off interrupts then reenable them ; when done. OR, to disable the interrupts before calling. TimerWait: ;this routine doesn't set timer interrupt ;this routine now expects d to be loaded before call ;; lddi terminalWait ; load D with wait count addde cntrhi ; add counter to D clre tcsr ; clear timer control status reg stde outcmphi ; set output compare ldaai 040 ; TimerWait1: bitae tcsr ; now wait for output compare flag beq TimerWait1 ; not yet rts; ;call OutString by putting the address of the string into IX OutString: ldabx 00; pick up the length into b AnotherChar: inx; increment IX to point to first char of string ldaax 00; pick up char using index reg as addressor pshb; save b jsr OutPutChar pulb; decb; bgt AnotherChar; branch if gt zero, i.e., more characters there rts; OutPutChar: ;doesn't destroy a psha; lddi terminalWait jsr TimerWait; pula; ldabe sercon; read serial controller reg into b staae sertx; send arg rts; OutByteVal: ;takes argument in B, prints it as two hex chars pshb; lsrb; lsrb; lsrb; lsrb; ldxi ByteValTab; abx; ldaax 00; ;get the ascii rep for left byte jsr OutPutChar; pulb; andbi 00F; ldxi ByteValTab; abx; ldaax 00; ;get the ascii rep for right byte jsr OutPutChar; rts; ByteValTab: $0; $1; $2; $3; $4; $5; $6; $7; $8; $9; $A; $B; $C; $D; $E; $F; ;Literals here ShowCharString: .TXT "Here's the char: "; StrCRT: .TXT "*n*l"; RunningStr: .TXT "We're Running!*n*l"; AtInterruptStr: .TXT "At Interrupt Level*n*l"; MainLoopStr: .TXT "Main Loop*n*l"; .loc 0fff0 0f8 00 .loc 0fff4 .ADR readuart .loc 0fffe 0f8 00