[A83] Re: greyscale


[Prev][Next][Index][Thread]

[A83] Re: greyscale




> > Nice grayscale on the Ti82/83(+) is also possible. The thing that
> > can be improved upon former approaches is that you don't write the
> > entire buffer to the screen at once. Do a some bit-masking between
> > the buffers and you get nice 4-level grayscale. 8-level is also
> > possible that way, but then you already see the bitmasking...
> >
> > Basicaly you add interlace to the picture. On CRT monitors this is
> > good for bad headaches. But since the pixels of an LCD are much slower
> > than one on your CRT, the pixels get a gray'ish look. It's much like the
> > grayscale used in Marspatrol on the Ti83.
> >
> > A drawback is that for a fast routine you need to use the graph-buffers
> > 'the other way around' (byte order is different). Which means you need
> > to write new sprite routines.

> Interresting... do you have any source code examples of this? (too
> lazy to find marspatrol =D)

If you have 8 pixels in a row which have to be displayed as grey, then you
can use the classic way of displaying repeatedly 11111111b and 00000000b,
but you can also switch between 10101010b and 01010101b. On LCDs that have
a relatively high refresh rate (all calcs above 83 series), the first way
is the best, because it's the fastest and the easiest to code (if you
consider a full screen grey scale routine, not just one byte). With slower
LCDs however, that isn't really an option because it causes to much
flicker as you switch between "all lights out" and "all lights on". The
second way works different and always shows half of the pixels that have
to be displayed as grey. Instead of turning all lights on/off at once you
split them up in groups and turn each group on/off in turns, giving a much
smoother effect.

That's for 3 level grey scale, having white, grey and black. For 4 level
greyscale, you can consider the same approach. Either you display
11110000b 2/3 of the time and 1/3 of the time 00001111b, which will give
you four pixels of dark grey and four pixels of light grey, OR you display
11010100b, 10111001b and 01100010b in turns. Those 3 values are built up
like this.

11010100b = (11110000b AND 11011011b) OR (00001111b AND 00100100b)
10111001b = (11110000b AND 10110110b) OR (00001111b AND 01001001b)
01100010b = (11110000b AND 01101101b) OR (00001111b AND 10010010b)

Applying the first rule on every byte pair in a screen buffer before
outputting it to the screen and next time the second and then the third
will give you very nice grey scale at a very decent speed. There are
numerous ways to improve the quality of the grey, but all in exchange for
speed. You could for instance, instead of applying one rule on an entire
screen, apply the first rule on the first byte pair, the second on the
second byte pair, etc. That already improves things a lot especially on
calcs with low batteries, where the first approach is slightly noticeable.
You can also use 5 mask rules instead of 3, which divides the colors a bit
better.

(screenBuf1 AND 10101101b) OR (screenBuf2 AND 01010010b)
(screenBuf1 AND 01011010b) OR (screenBuf2 AND 10100101b)
(screenBuf1 AND 10110101b) OR (screenBuf2 AND 01001010b)
(screenBuf1 AND 01101011b) OR (screenBuf2 AND 10010100b)
(screenBuf1 AND 11010110b) OR (screenBuf2 AND 00101001b)

That's the theory. Practically this means you need to adapt Joe's FastCopy
routine to do the necessary bit masking before outputting a byte to the
screen and put that in an interrupt routine. The main problem here is that
running through that code each interrupt tends to be slow. One way to
speed things up quite a bit, is to change the screenBuf structure. Where
you usually use row by row, it would be better to have collumn by collomn.
Two successive bytes in memory would then be displayed above/under each
other instead of next to each other. Additionally, you could put each byte
pair together forming one big screen buffer of 1536 bytes instead of two
different 768 byte areas, but then you need to allocate that amount of
bytes in user memory. All this requires other sprite and tilemap routines.
Non-aligned routines will be a little bit slower than usual, but not much
to worry about. Aligned sprite and tilemap routines become just an LDIR.

The fast routine, using 3 masks is available in the 83- archive of my
website http://tijl.studentenweb.org/ and everybody is free to use and
modify it to his own needs. I'd appreciate a place in the 'Thanks to' list
though :-) Do know that I've only tested them on regular TI83s. It should
work on a TI83+ too (after a few address changes), but not on an SE as
that calc's LCD seems a lot slower, so you have to build in more delays.

About VTI. It displays the fast 3 mask technique as perfect greyscale.
When using the slower 5 mask technique however, you see lighter and darker
lines running over the screen.

I've also done 8 level grey scale using this technique. It looks good with
brand new batteries (contrast level 1 or 2) However, the effect is highly
noticeable on calculators with lower batteries not only because you have
to cycle through 7 mask rules, but also because you have to apply them on
3 screen buffers. So the whole thing is unusable, even if you unrole the
inner loop in the FastCopy routine. I'm still looking for improvements
though, so maybe some time 8 level will be possible too, but that is
highly doubtful.

Tijl Coosemans