:TITLE[JasmineHalftone4]; *Last edited by Fiala 20 Nov 80, by Maleson 3 April 80 *Floyd-Steinberg error distribution halftoning, 4 bits/point * "REPLACE" mode, * doesn't work for all modes (save space) *Available RM Temps: 44-53 56-57, 66-73; available Unused: 0 **These assignments require that the Mesa stack must not be allowed longer **than 6 words when this code is run. RV4[errorVec,errorVecHi,screenWord,screenWordHi,44]; RV4[bitCount,bitmapWidth,pixelArray,pixelArrayHi,50]; RV4[nInputPixels,blackVal,pixelVal,nOutputDots,10]; RV2[AddrTemp,AddrTempHi,14]; RV[CascadeRight,56]; RV[CascadeDiag,57]; RV[bitVal,66]; RV[jctr,67]; RV[x,70]; RV[val,71]; RV[errorTemp,72]; RV[returnLoc,73], Set[HalftonePage,15]; *Presumably the software that uses this microcode *must be revised if this page assignment changes *(i.e., if the starting location changes). PSet[PrintLine,HalftonePage,0]; *Starting location SetTask[0]; OnPage[HalftonePage]; *halftone stuff AddrTempHi ← 0C, At[PrintLine]; Stack&-1; T ← Stack; AddrTemp ← T, UseCTask; T ← APCTask&APC; returnLoc ← T; PFetch4[AddrTemp,errorVec,4]; Stack&+1; PFetch4[AddrTemp,bitCount,10]; T ← LSh[errorVecHi,10], Task; errorVecHi ← (errorVecHi) + T + 1; T ← LSh[screenWordHi,10]; screenWordHi ← (screenWordHi) + T + 1; PFetch4[AddrTemp,nInputPixels,0], Task; T ← LSh[pixelArrayHi,10]; Dispatch[bitCount,16,2]; pixelArrayHi ← (pixelArrayHi) + T + 1, Disp[.+1]; *bit selection dispatch table bitVal ← 170000C, Goto[b20], DispTable[4]; bitVal ← 7400C, Goto[b20]; bitVal ← 360C, Goto[b20]; bitVal ← 17C, Goto[b20]; b20: T ← bitCount; PFetch1[errorVec,CascadeRight]; bitCount ← LSh[bitCount,2]; T ← Stack; AddrTemp ← T; T ← nOutputDots; jctr ← (Zero) - T; CascadeDiag ← Zero; CascadeRight ← (LSh[CascadeRight,2]) - 1; T ← nInputPixels; Stack4 ← T; T ← LdF[bitmapWidth,4,1]; nInputPixels ← (nInputPixels) + T; x ← T, Goto[forX0]; *subroutines: pieces used by all four modes GetPixel: T ← RSh[x,1], Goto[xDone,ALU<0]; PFetch1[pixelArray,pixelVal]; LU ← x, Goto[xOdd,R Odd]; xEven: pixelVal ← RSh[pixelVal,10], Return; xOdd: pixelVal ← RHMask[pixelVal], Return; OrVal: PFetch1[screenWord,Stack6]; T ← bitVal; Dispatch[bitCount,14,2]; Stack6 ← (Stack6) and not T, Disp[.+1]; T ← LSh[val,14], Goto[or4], DispTable[4]; T ← LSh[val,10], Goto[or4]; T ← LSh[val,4], Goto[or4]; T ← val; or4: Stack6 ← (Stack6) or T, Return; StoreVal: PStore1[screenWord,Stack6], Return; GetError: CascadeRight ← (RSh[CascadeRight,1]) or T, Goto[a1,R Odd]; a0: T ← (RSh[CascadeRight,1]) or T, Goto[a00,R Even]; a01: CascadeRight ← (CascadeRight) + 1; a00: errorTemp ← T, Goto[haveError]; a1: T ← (RSh[CascadeRight,1]) or T, Goto[a10,R Even]; a11: errorTemp ← T ← (Zero) + T + 1, Goto[haveError]; a10: CascadeRight ← (CascadeRight) + 1, Goto[a00]; haveError: CascadeDiag ← (CascadeDiag) + T; T ← RSh[bitCount,2]; PStore1[errorVec,CascadeDiag], Return; GetNext: PFetch1[errorVec,Stack6]; T ← errorTemp; CascadeDiag ← T; T ← Stack6; CascadeRight ← (CascadeRight) + T; T ← Stack4, Return; xDone: APCTask&APC ← returnLoc; Stack&-1, Return; forX0: LU ← (nInputPixels) - T - 1, Call[GetPixel]; *5 mi T ← jctr, Goto[jDone0,R>=0]; whileJ0: T ← pixelVal; CascadeRight ← T ← (CascadeRight) + T; LU ← RSh[CascadeRight,10], Skip[ALU>=0]; val ← 0C, Goto[HaveVal]; *Neg. value PFetch1[AddrTemp,val], Goto[OverVal,ALU#0]; *Pos. value T ← val; T ← (LSh[val,4]) + T; CascadeRight ← (CascadeRight) - T, Goto[HaveVal]; OverVal: val ← 17C; CascadeRight ← (CascadeRight) - (377C); HaveVal: T ← LdF[bitCount,0,14], Call[OrVal]; T ← LdF[bitCount,0,14], Call[StoreVal]; EndDot0: T ← (CascadeRight) AND (100000C), Call[GetError]; bitCount ← (bitCount) + (4C); T ← RSh[bitCount,2], Call[GetNext]; jctr ← (jctr) + T; bitVal ← RCy[bitVal,4], Goto[whileJ0,ALU<0]; jDone0: T ← nOutputDots; jctr ← (jctr) - T; x ← T ← (x) + 1, Goto[forX0]; *could save 7 mi if jctr still negative