Here's a nice new little feature I added yesterday: 4-level grayscale!
OK, so I added it really quick and dirty, and there's still some code that writes directly to the LCD and not to the gray planes, but I updated the primary glyph set (font) so it's now anti-aliased! The glyph set is still usable in monochrome mode (in fact it looks exactly the same as it did before).
(I'm not 100% satisfied with my anti-aliasing job, but it'll do for now.)
It took me only a couple hours to get grayscale working and then a couple more to make the terminal code work with it. I modeled the code after TIGCC's grayscale code, but I wrote mine in C instead of assembly (except for the fast copy routine).
I'm also planning to add grayscale and monochrome with double-buffering. To control all these LCD modes from userspace, I'm going to add a few ioctl() calls. An application only has to open /dev/lcd and use ioctl() to control it. Once the last file descriptor for /dev/lcd is closed, the LCD will revert to the default monochrome mode (so if a grayscale program is killed or crashes, the screen mode will automatically become monochrome before you return to the shell). I'm debating whether to make grayscale the default mode instead; graphical programs would have to explicitly set the mode if they want monochrome graphics. On HW2 (which is my main target), grayscale adds about 4% CPU overhead, which is not too bad to keep it active all the time. On HW1 (if I got it working) it would add even less than that. What's more, audio still works great with grayscale enabled! My biggest concern with grayscale was its interaction with audio, but it turns out to work well after all.
The Punix grayscale API will actually be much simpler than TIGCC's grayscale API (so it'll be more difficult to use it wrong, at least in theory
). Some of the TIGC calls mine won't have are the Gray*Set*AMSPlane routines (for obvious reasons), Gray(Set|Get)Int1Handler (that's privileged kernel functionality), and GrayDBufGet(Active|Hidden)Idx (not needed; use the "get planes" call). All in all, I'll add only 5 calls: get-mode, set-mode, get-planes, flip, and flip-and-sync. (Of course, a userspace library could emulate parts of the TIGCC grayscale API using combinations of those 5 calls, which might make it easier to port TI-AMS grayscale programs to Punix.) I'll also add ioctl calls to get/set/increment/decrement the contrast, but those are orthogonal to the grayscale calls.
EDIT 2012-03-06: scaled screenshot to 100%