[Oberon] FPGA - Bitmap Paint Horizontal Line

Tomas Kral thomas.kral at email.cz
Wed May 10 11:33:19 CEST 2017


Hi,

I have coded this improved version. It generally works and seems to
handle both x, and w on bitwise level.

The main loop goes initially fast over words, and the rest by bytes.

This line `w0 := (w MOD 32) DIV 8 + 1' computes remaining bytes on
line over MOD 32, and this clips the outstretching bits wd*{0..w0*8+w}.

But the above calculation seems complicated, is there an easier
invariant I could code instead? 

`w0' can then be passed as a parameter as its value is known before
calling to `PaintHLine'.


PROCEDURE PaintHLine(x, src, dst, w: INTEGER);
  VAR bt: BYTE; w0, w1, wd: INTEGER; pix: SET;   
BEGIN
 
  (* (pix * {maskleft*8..31} * {0..maskright*8-1}) *)

  w0 := (w MOD 32) DIV 8 + 1;
  
  WHILE w > 0 DO

    IF w > 31 THEN SYSTEM.GET(src, wd); INC(src, 4); DEC(w, 32);
    ELSE 
      wd := 0; WHILE w > 0 DO SYSTEM.GET(src, bt); wd := LSL(wd, 8)+bt;
    INC(src); DEC(w, 8) END END;

    IF w < 0 THEN wd := SYSTEM.VAL(INTEGER, SYSTEM.VAL(SET,
    wd)*{0..w0*8+w}) END;

    SYSTEM.GET(dst, pix);
    SYSTEM.PUT(dst, SYSTEM.VAL(SET, LSL(wd, x MOD 32)) + pix);
      
    INC(dst, 4);
    IF x MOD 32 > 0 THEN
      SYSTEM.GET(dst, pix); wd := ASR(wd, -(x MOD 32));
      SYSTEM.PUT(dst, SYSTEM.VAL(SET, wd)*{0..x MOD 32-1}+ pix)
    END
 
  END
END PaintHLine;


-- 
Tomas Kral <thomas.kral at email.cz>


On Thu, 4 May 2017 16:42:57 +0200
Jörg <joerg.straube at iaeth.ch> wrote:

> If you write "x * 100H", the compiler will detect that "100H" is a
> power of two and will convert the multiplication into a shift
> operation.
> 
> Jörg
> 
> -----Original Message-----
> From: Oberon [mailto:oberon-bounces at lists.inf.ethz.ch] On Behalf Of
> Tomas Kral Sent: Donnerstag, 4. Mai 2017 11:25
> To: oberon at lists.inf.ethz.ch
> Subject: Re: [Oberon] FPGA - Bitmap Paint Horizontal Line
> 
> Hi,
> 
> I arrived at coding this, it may not be correct, but does things on
> $AAAAA$ patterns. 
> 
> PROCEDURE PaintHLine(x, src, dst, w: INTEGER);
>   VAR bt: BYTE; wd: INTEGER; pix: SET;   
> BEGIN
>  
>   (* (pix * {maskleft*8..31} * {0..maskright*8-1}) *)
> 
>   WHILE w > 0 DO
> 
>     (* this part modified from Display.Mod:CopyPattern *)
> 
>     SYSTEM.GET(src, bt); wd := bt; INC(src); DEC(w, 8);
>     IF w > 0 THEN SYSTEM.GET(src, bt); wd := wd + bt*100H; INC(src);
>     DEC(w, 8); IF w > 0 THEN SYSTEM.GET(src, bt); wd := wd +
> bt*10000H; INC(src); DEC(w, 8); IF w > 0 THEN SYSTEM.GET(src, bt);
> wd := wd + bt*1000000H; INC(src); DEC(w, 8) END END
>     END;
> 
>     SYSTEM.GET(dst, pix);
>     SYSTEM.PUT(dst, SYSTEM.VAL(SET, LSL(wd, x MOD 32)) + pix);
>     SYSTEM.GET(dst+4, pix); wd := ROR(wd, x MOD 32);
>     SYSTEM.PUT(dst+4, SYSTEM.VAL(SET, wd)*{0..x MOD 32} + pix);
> 
>     INC(dst, 4)
>   END
> 
> END PaintHLine;
> 
> Comments:
> 
> [a] it now reflects x coordinate, but works only with w*8, need to
> deal with a remaining bits w MOD 8, as the last step
> 
> [b] bits shifted left in memory, appears shifted right on display,
> interestingly also vice versa, as if on reflection in the mirror 
> 
> [c] need to somehow unroll the loop into three parts for speed
> improvement as suggested, as is, it needs four byte reads from source,
> two word read/writes per iteration INC(dst,4), but how?
> 
> [d] bt*100H is defacto shift 8 operation, why normal ASR/LSL
> were not used instead, how many RISC cycles they got?
>  
> Tomas
> 
> On Sun, 30 Apr 2017 17:45:08 +0200
> Jörg <joerg.straube at iaeth.ch> wrote:
> 
> > Hi Tomas
> > 
> > One possibilty is to split your algorithm in three parts
> > 1) handle the left border (max 31 bit) until you reach a multiple of
> > 32 bit 2) then copy n words (32 bit)
> > 3) handle the right border = remaining bits up to the width "w"
> > 
> > Jörg
> > 
> > > Am 30.04.2017 um 16:33 schrieb Tomas Kral <thomas.kral at email.cz>:
> > > 
> > > Chris, Joerg,
> > > 
> > > Learning, not doing much useful bitmap examples.
> > > 
> > > I was surprised to realise, Bitmaps are easy to be
> > > copied/displayed, by lines, after each line destination address
> > > is incremented by 128 bytes per display line, source address by
> > > bitmap width DIV 8, lines h decremented by 1.
> > > 
> > > This works nicely on any bitmap of widths multiple of
> > > 32 bits accross. 32xN, 64xN, etc, and must be aligned horizontally
> > > also on 32 bit as well, for x=0,32,64,.. coordinate (x,y = top
> > > left). Bitmaps are drawn upwards. 
> > > 
> > > (* paints horizontal bitmap line, for x,w=32,64,... *)
> > > PROCEDURE PaintHLine(src, dst, w: INTEGER);
> > >  VAR s,t: SET;
> > > BEGIN
> > >  w := (w+7) DIV 8; (* bytes per bitmap line *)
> > >  WHILE w > 0 DO
> > >    SYSTEM.GET(src, t);  SYSTEM.GET(dst, s);
> > >    SYSTEM.PUT(dst, s + t);
> > >    INC(dst, 4);  INC(src, 4);  DEC(w, 4)
> > >  END
> > > END PaintHLine;
> > > 
> > > I am looking into a solution where x can spill over byte boundary,
> > > also width of finer bitwise granularity.  
> > > 
> > > I did a similar exercise in assembly many, many years ago on 8-bit
> > > computers.
> > > 
> > > Tomas
> > > 
> > > 
> > > On Sun, 30 Apr 2017 21:26:09 +0930
> > > Chris Burrows <chris at cfbsoftware.com> wrote:
> > > 
> > >>> -----Original Message-----
> > >>> From: Oberon [mailto:oberon-bounces at lists.inf.ethz.ch] On Behalf
> > >>> Of Tomas Kral
> > >>> Sent: Sunday, 30 April 2017 8:05 PM
> > >>> To: oberon at lists.inf.ethz.ch
> > >>> Subject: Re: [Oberon] FPGA - SET initialisation
> > >>> 
> > >>> Ah yes, sily me.
> > >>> 
> > >>> But how to best initialise a SET variable with an arbitrary
> > >>> byte / integer?
> > >>> 
> > >>> TYPE ii = POINTER TO iidsc;
> > >>> iidsc = STRUCT i: INTEGER END;
> > >>> 
> > >>> i := b; SYSTEM.PUT(ii,i); SYSTEM.GET(ii,s); (* initialise a set
> > >>> with a byte *) SYSTEM.PUT(ii,i); SYSTEM.GET(ii,s); (* initialise
> > >>> a set with an integer
> > >>> *)
> > >>> 
> > >> 
> > >> Do you mean how do you typecast an INTEGER / BYTE variable to a
> > >> SET variable?
> > >> 
> > >> If so then:
> > >> 
> > >>  VAR
> > >>    s: SET;
> > >>    i: INTEGER;
> > >>    b: BYTE;
> > >> 
> > >>  BEGIN
> > >>    s := SYSTEM.VAL(SET, i); 
> > >>    s := SYSTEM.VAL(SET, ORD(b))
> > >> 
> > >> I'm curious. What is it that you are trying to do that makes you
> > >> ask this question?
> > >> 
> > >> Regards,
> > >> Chris Burrows
> > >> CFB Software
> > >> http://www.astrobe.com/RISC5
> > >> 
> > >> --
> > >> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related
> > >> systems https://lists.inf.ethz.ch/mailman/listinfo/oberon
> > > 
> > > --
> > > Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related
> > > systems https://lists.inf.ethz.ch/mailman/listinfo/oberon
> > --
> > Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related
> > systems https://lists.inf.ethz.ch/mailman/listinfo/oberon
> 
> 
> 





More information about the Oberon mailing list