: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