Grayscale Graphics

Grayscale graphics on the TI92 is accomplished (as many of you propably know) by switching between several pictures at a quick rate. Since LCD-displays are so slow, this gives a pretty good "simulation" of real grayscale colors.

The grayscale functions of Fargo consists of two simple functions in the file GRAYLIB.92P; One to turn on the grayscale display and return a pointer to the second bitplane, and one to turn it off again. The on-function just installs an interrupt routine on the 400hz counter that switches the bitplane every fourth time it is executed, which is exactly the same rate that is used for the LCD-refresh, 100hz. The planes is switched in such a way as to simulate three colors plus background instead of one plus background, using a cycle that is repeated every third time, like this:

Frame 1: Show Bitplane 0
Frame 2: Show Bitplane 0
Frame 3: Show Bitplane 1
So the normal bitplane at adress $4440 is shown for 20ms and then the second bitplane is shown for 10ms. The whole cycle is then repeated every 30ms. So if we assume that the color intensity is directly proportional to the part of the 30ms cycle in which it is visible (wich seems reasonable) we will get the following intensities:

Color 0:  0.0  (Background, never shown)
Color 1:  0.33
Color 2:  0.66
Color 3:  1.00
This should give as an evenly spaced set of colors. This is not, however, the case. Color 1 is much closer to color 0 than color 2 and color 2 is very close to color 3. It's almost as if we needed a fifth color at intensity 0.5. I really don't know what's causing this effect, so please mail any ideas you might have about this.

More Colors

We could produce more colors (say, eight) by using a third plane and constructing a switch cycle something like this:

Frame 1: Bitplane 0
Frame 2: Bitplane 1
Frame 3: Bitplane 0
Frame 4: Bitplane 2
Frame 5: Bitplane 0
Frame 6: Bitplane 1
Frame 7: Bitplane 0
Which will give us an evened spaced intensity range like the one above. The problem here is that this cycle is much longer (17.5ms) and the flickering is getting pretty bad, especially if the sourrounding light is flickering at 50hz. Maybe we will have to stand 4 colors for now...

Grayscale example

Here is the Grayscale example I posted on the Fargo mailinglist a while ago. Hope it will help someone...

	@program	prog_code,prog_name

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;% Grayscale Example for Newbies - by Jonas Minnberg (Sasq) %
;%                                                          %
;% Since so many people on the FargoList asks about this, I %
;% put together a small example that you may use freely.    %
;% It simply uses a pixelplot routine do draw horisontal    %
;% lines in different colors.                               %
;%                  /Jonas Minnberg (md94-jmi@nada.kth.se)  %
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

;************** Start of Fargo program ***************

POS:    dc.l    0       ;Holds X & Y position for next pixel to plot

prog_code:
        jsr     graylib[on]             ;Turn on Grayscale display
        move.l  a6,plane2               ;Save pointer to second bitplane

        move.w   #959,d7                ;Clear second bitplane
\cloop0:
        clr.l   (a6)+                   ;Slow clearing but who cares :)
        dbf     d7,\cloop0

        move.w   #959,d7                ;Clear first bitplane
        lea     $4440,a6
\cloop1:
        clr.l   (a6)+
        dbf     d7,\cloop1

        moveq   #0,d3                   ;D3 Holds color number
        lea     POS(pc),a2              ;A2 Holds offset to coordinates
        clr.l   (a2)                    ;Start at (0,0)
        moveq   #127,d6                 ;Loop index 1, 128 lines
\loop:
        move.w   #239,d7                ;Loop index 2, 240 rows
\loop2:
        movem.w  (a2),d0/d1             ;Put (X,Y) in DO & D1
        bsr     put_grayscale_pixel     ;Call our pixelplot routine
        add.w   #1,(a2)                 ;Increase X coordinate
        dbf     d7,\loop2               ;Do the (Inner) Loop

        clr.w   (a2)                    ;Clear X coordinate and...
        add.w   #1,2(a2)                ;increase Y coordinate
        addq    #1,d3                   ;Also increase colorvalue
        and.b   #$03,d3                 ;and make sure it's always 0-3
        dbf     d6,\loop                ;Do the (Outer) Loop

        jsr     flib[idle_loop]         ;Wait for a keypress
        jsr     graylib[off]            ;And turn off grayscale display
	rts

;D0.W = X position, D1.W = Y position, D3.B = Color (0-3)
put_grayscale_pixel:
        move.w  d0,d4
        move.w  d1,d5
        lea     $4440,a0                ;First bitplane
        btst    #1,d3                   ;Test bit 1 in colorvalue to see if
        beq.s   \cpix0                  ;we should set or clear this pixel
        bsr     set_pixel
        bra.s   \done0
\cpix0:
        bsr     clr_pixel
\done0:
        move.w  d4,d0
        move.w  d5,d1
        move.l  plane2(pc),a0           ;Second bitplane
        btst    #0,d3                   ;Test bit 0 in colorvalue to see if
        beq.s   \cpix1                  ;we should set or clear this pixel
        bsr     set_pixel
        bra.s   \done1
\cpix1:
        bsr     clr_pixel
\done1:
        rts

;Clear Pixel
;A0.L = bitplane, D0.W = X position, D1.W = Y position
;Destroys D0-D2
clr_pixel:
        bsr     calc_offset
        bclr.b  d2,0(a0,d1)
        rts

;Set Pixel
;A0.L = bitplane, D0.W = X position, D1.W = Y position
;Destroys D0-D2
set_pixel:
        bsr     calc_offset
        bset.b  d2,0(a0,d1)
        rts

calc_offset:
        add.w   d1,d1           ;Multiply Y coordinate by 30
        move.w  d1,d2           ;without MUL instruction
        lsl.w   #4,d1           ;(32*Y-2*Y)
        sub.w   d2,d1           ;Only shifts and adds

        move.b  d0,d2
        eor.b   #$7,d2
        lsr.b   #3,d0
        add.w   d0,d1           ;D1 Now holds offset to byte
        rts

plane2:
        dc.l    0

prog_name:
        dc.b    "Grayscale example for Newbies",0

;*************** End of Fargo program ****************

	reloc_open
        add_library     flib
	add_library	graylib
	reloc_close
	end

Written by Jonas Minnberg (Sasq / O2), md94-jmi@nada.kth.se

Back to Main