(3/01/2019: Version 0.5: Re-arranged to make using multiple monitors possible. Added simple C and BASIC demos.)
(2/19/2019: Version 0.4. Fixed a nasty bug in the vsync polarity. Please update!)
(2/19/2019: Updated again with a newer driver that supports 1024x768 and has better sync at 640x480)
(2/18/2019: Updated with a screenshot and newer driver.)
This is still a work in progress, but it seems to sync OK on my monitor. It uses a 1bpp bitmap with 256 characters. The font provided is 8x16, so we get 80x30 characters at 640x480 and 100x40 characters at 800x600 (we only use 15 rows of the font in the latter case). Each character can have arbitrary background and foreground colors, so each character takes up 8 bytes of memory; thus the 800x600 case uses 100*40*8 = 32000 bytes of memory for the screen. The way it works generates 8 pixels at a time, so practically speaking the font has to be 8 pixels wide, but can be any height.
Internally it loads one row of the font into COG RAM during horizontal blanking, and uses getbyte to look up the pixel data for each character from that font row, while placing the fg and bg colors into the LUT for display. Doing this for higher resolutions is probably going to be difficult, although I'm sure there are ways to shave some cycles off the inner loop.
The demo only works properly in the most recent fastspin (3.9.20) because it uses setpiv to blend pixel colors, and earlier fastspins had a bug in that instruction. The actual driver should be OK with older fastspin and should easily port to PNut (there's just the usual Start/Stop Spin methods, most of the driver code is in PASM).