[Oberon] FPGA - Bitmap Paint Horizontal Line

Jörg joerg.straube at iaeth.ch
Thu May 4 16:42:57 CEST 2017


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



-- 
Tomas Kral <thomas.kral at email.cz>
--
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