VGA 640x480, 800x600, 1024x768 full color ANSI text driver

ersmithersmith Posts: 3,490
edited 2019-10-02 - 21:42:47 in Propeller 2
(2019-10-02: Version 0.6: 8bpp color support, new silicon support, and converted C driver for Catalina and riscvp2)

(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).


screen.jpg
3264 x 2448 - 3M

Comments

  • Cool :) This looks nice...800x600 demo worked out of the box. I only had to reduce the pixel clock in the 640x480 demo - without it my cheapo little 4" monitor wouldn't accept the signal. Scoping it showed 76Hz vsync and I think 38 or 39kHz hsync. 30MHz pixclk was about the max that worked, but looked pretty jittery...25.175MHz looks solid, and yields a normal 59.94 vsync
    --
    WIP Spin/PASM drivers for various devices: LSM9DS1 (P1, P2) | US2066 | MLX90621 | SHT3x (P1, P2) | SSD1306 (P1, P2) | TCS3x7x | MAX31856 | BMP280 | TMC2130 | nRF24L01+ (P1, P2) | MLX90614 (P1, P2) | MAX9744 | DS28CM00 | TSL2591 | CC1101 | SX1231 | LM75 | DS18B20 | Si7021 | INA219 | SX1276/LoRa (P1, P2) | W25Qxxx (P2)
    Use with spin-standard-library (fork)
  • I've updated the .zip file in the first image with a newer version of the code. There's not much different in the driver itself, but the vga640x480 demo now includes a terminal driver that understands ANSI escape sequences (I forgot to update the 800x600 demo, but you can easily see how to copy the routines over from the 640x480 one -- the text processing functions are all in separate .spinh files).
  • the 640x480 works for me, but is very jittery...
    XDIV needs to be a low value (like 1 or 2) for the current silicon.

    800x600 doesn't work for me.
    Prop Info and Apps: http://www.rayslogic.com/
  • I've modified the 640x480 example to work with my monitor.
    Also, changed basepin...
    Prop Info and Apps: http://www.rayslogic.com/
  • RaymanRayman Posts: 9,739
    edited 2019-02-18 - 19:34:25
    I just tried adding a bitmap driver to this so can switch between text and bitmap.

    Adding the bitmap file into the DAT section seems to crash Fastspin…

    Doesn't seem to like a giant file being dropped in... Works if change to a small file...
    DAT
    '
    '
    ' Bitmap  'bitmap buffer starts at $1000
    '
    orgh    '$1000 - $436    'justify pixels at $1000, pallete at $1000-$400
    bitmap  
            file    "bitmap2.bmp"'combined1.bmp" 
            'bitmap2.bmp   '640 x 480, 8pbb-lut
    
    buffer  'tile buffer
        long 0[COLS*ROWS*2]
    '
    ' font buffer
    '
        long
    fontdata
        file "unscii-16.bin"
    '   file "unscii-8-fantasy.bin"
    
    '=================================================================================================================
    ' BELOW HERE IS THE DEMO CODE
    '=================================================================================================================
    democolors
        long $FF000000, $FFFF0000, $00FF0000, $00FFFF00
        long $0000FF00, $FF00FF00, $FFFFFF00, $00000000
        long $7F000000, $007F7F00, $007F0000
    
    Prop Info and Apps: http://www.rayslogic.com/
  • jmgjmg Posts: 13,993
    Rayman wrote: »
    the 640x480 works for me, but is very jittery...
    XDIV needs to be a low value (like 1 or 2) for the current silicon.

    800x600 doesn't work for me.

    Can you post images of the jitter vs PFD MHz for your P2/Monitor combination ?
    Does it suddenly get worse, or just gradually ?
    ie is /3 usable (6.66'MHz), or is 10MHz PFD needed ?

    Trying to get a feel for the 'minimum MHz' that P2 PFD can run at, for various VGA pairings.

    How tolerant is your monitor to Line Scan and Pixel clocks ?

    eg 26MHz, which is a cheap GPS TCXO value, can yield
    PFD = 26M/3 = 8.666'MHz
    Err = 1-29*(26M/3)/(25.175M*10) = 0.165%


  • Thanks for everyone's suggestions. My monitor seems to be pretty tolerant, but I'll try to keep the XDIV value low. I've updated the first post with some revised code. The frequency calculations in the 800x600 code is now properly parameterized, and I've tweaked the 640x480 code again to something that I hope will work for more monitors. For some reason @Rayman 's settings do not work on my monitor, even though it looks like they exactly follow the spec :(. Which is weird because as I mentioned my monitor is usually pretty tolerant, but maybe that's the problem -- it's picking the signal up as 720x400 instead of 640x480.

    I've optimized the pixel loop and can now display 1024x768. To do that I'm overclocking the P2 Eval board to 200 MHz, but my board at least doesn't feel too warm when I do this -- but your mileage may vary, so you may or may not want to actually try it yourself. (It sounds like many people have gone above 200 MHz so it's probably not too crazy.)

    I think that's the limit for full color foreground and background, changing on every character (hah! someone will prove me wrong :)) but for monochrome or with colors changing less often getting to 1600x1200 or 1920x1060 should be pretty easy
  • jmgjmg Posts: 13,993
    ersmith wrote: »
    ... To do that I'm overclocking the P2 Eval board to 200 MHz, but my board at least doesn't feel too warm when I do this -- but your mileage may vary, so you may or may not want to actually try it yourself. (It sounds like many people have gone above 200 MHz so it's probably not too crazy.)
    ..
    Measurements are being reported at 350MHz, so 200MHz looks more mainstream.
    IIRC Chip was hoping to target 250MHz as a more formal spec (HDMI min) , in the P2+ at OnSemi now - maybe with lower Max Tj, and tighter supply specs.
    Of course, that depends on just how the P&R goes at OnSemi, and there is more logic in 2+... time will tell.

  • Just FYI, most current LCD monitors appear to want ~60 Hz vertical..

    Although I think some gaming ones do 120 Hz...
    Prop Info and Apps: http://www.rayslogic.com/
  • Aha! I think I found why my monitor won't sync properly at 640x480 -- it's looking for negative polarity on hsync, whereas if I'm reading the code correctly we're providing positive. I've changed the driver to make the polarity a parameter. I *think* this should work OK, but I'm a software guy, not hardware, so it's entirely possible that I've messed something up with the signals. Please don't plug this in to an analog monitor until it's been thoroughly vetted, and in general be careful with it.

    The new version of the 640x480 demo runs at 60Hz (like the 800x600 and 1024x768 ones) and syncs fine on my monitor.
  • A lot of older LCD monitors are 59.97 (or there abouts) Hz, rather than exactly 60Hz.
    Gaming monitors come in 120Hz and 144Hz flavors.

    Also, I doubt you would damage an analog monitor with bad signal data (like pos vs neg hsync, or off timings), unless it was a really crappy monitor in the first place.
  • The newer modes all worked for me without changes. The HSync polarity does indeed change (monitor accepts it without any fuss), but altering the VSync polarity doesn't seem to have an effect - it always looks positive on the scope.
    --
    WIP Spin/PASM drivers for various devices: LSM9DS1 (P1, P2) | US2066 | MLX90621 | SHT3x (P1, P2) | SSD1306 (P1, P2) | TCS3x7x | MAX31856 | BMP280 | TMC2130 | nRF24L01+ (P1, P2) | MLX90614 (P1, P2) | MAX9744 | DS28CM00 | TSL2591 | CC1101 | SX1231 | LM75 | DS18B20 | Si7021 | INA219 | SX1276/LoRa (P1, P2) | W25Qxxx (P2)
    Use with spin-standard-library (fork)
  • ersmithersmith Posts: 3,490
    edited 2019-02-20 - 00:20:27
    @avsa242: Oh boy, there was a nasty typo on line 87 of vga_tile_driver.spin2; it should read
      drvc #vsync
    
    (I forget the "#", so it's driving some random pin :(). I'm posting an update now.

    Thanks for checking this on the scope! I wouldn't have noticed that the polarity was wrong, my monitor was only looking at horizontal polarity.
  • I'll repost this in here since it is using Eric's tile driver:

    Given HDMI needs 10x the data rate of the pixel rate, 640x480's 250MHz data rate would normally be considered the only viable resolution for the Prop2. In an attempt to go higher I've been playing with display timing of the vgatile driver. My LCD TV seems extremely forgiving of timings for any particular known resolution ... but it doesn't accept an unknown resolution. I suspect modern 16:9 monitors/TVs will generally have similar "reduced blanking" capabilities. After all, they have no need of retrace times.

    What I've been able to do is start from the spec'd 34MHz pixel rate of 848x480@60Hz mode and chop down the timings until I've even got 848x480 at 25MHz working.

    Question is, does this work for anyone else at all?
    https://forums.parallax.com/discussion/download/125779/vga848x480.spin2
    "We suspect that ALMA will allow us to observe this rare form of CO in many other discs.
    By doing that, we can more accurately measure their mass, and determine whether
    scientists have systematically been underestimating how much matter they contain."
  • Works for me - 26.26kHz, 54.25Hz
    One thing I'm not sure others are seeing though...I've seen it with all of these - is that the left and/or right is chopped off...haven't tried it with this mode yet, but have been able to adjust the timings set in the driver to get it to fit onscreen. This is a cheapo little 4-something inch LCD though. I suspect it's mostly to blame, as I remember running into the same with a lot of the P1-based drivers, as well...got to get my hands on a better VGA monitor, heh.
    --
    WIP Spin/PASM drivers for various devices: LSM9DS1 (P1, P2) | US2066 | MLX90621 | SHT3x (P1, P2) | SSD1306 (P1, P2) | TCS3x7x | MAX31856 | BMP280 | TMC2130 | nRF24L01+ (P1, P2) | MLX90614 (P1, P2) | MAX9744 | DS28CM00 | TSL2591 | CC1101 | SX1231 | LM75 | DS18B20 | Si7021 | INA219 | SX1276/LoRa (P1, P2) | W25Qxxx (P2)
    Use with spin-standard-library (fork)
  • jmgjmg Posts: 13,993
    Many larger monitors auto-fit, and in doing that, they expect an image border to work to.
    That means the image offered needs to have a definite edge - black backgrounds do not work as well, & any errant pixels outside display window can confuse it.
    Not sure how that squeezed flyback will interact with the auto-fit ?
  • ersmith wrote: »
    @avsa242: Oh boy, there was a nasty typo on line 87 of vga_tile_driver.spin2; it should read
      drvc #vsync
    
    (I forget the "#", so it's driving some random pin :(). I'm posting an update now.

    Thanks for checking this on the scope! I wouldn't have noticed that the polarity was wrong, my monitor was only looking at horizontal polarity.

    Yup! Neg and Pos both now reflect correctly here

    --
    WIP Spin/PASM drivers for various devices: LSM9DS1 (P1, P2) | US2066 | MLX90621 | SHT3x (P1, P2) | SSD1306 (P1, P2) | TCS3x7x | MAX31856 | BMP280 | TMC2130 | nRF24L01+ (P1, P2) | MLX90614 (P1, P2) | MAX9744 | DS28CM00 | TSL2591 | CC1101 | SX1231 | LM75 | DS18B20 | Si7021 | INA219 | SX1276/LoRa (P1, P2) | W25Qxxx (P2)
    Use with spin-standard-library (fork)
  • evanhevanh Posts: 8,033
    edited 2019-02-22 - 15:11:04
    Oh, I forgot about the 26kHz horizontal. That's really low for PC monitors. And I suspect is what is wrong when I try to plug an older LCD monitor in. I've had to up the requirements somewhat to 28 MHz to get this Dell monitor to take.

    This one should be more universal but will run hotter when targetting HDMI.
    EDIT: Updated comments in source
    EDIT2: Revised for 60 Hz vsync because it fit
    "We suspect that ALMA will allow us to observe this rare form of CO in many other discs.
    By doing that, we can more accurately measure their mass, and determine whether
    scientists have systematically been underestimating how much matter they contain."
  • avsa242 wrote: »
    ... is that the left and/or right is chopped off...haven't tried it with this mode yet, but have been able to adjust the timings set in the driver to get it to fit onscreen. This is a cheapo little 4-something inch LCD though...
    Yep, seen plenty of that on my TV too. VGA inputs on TV's seem to be somewhat different to monitors.
    "We suspect that ALMA will allow us to observe this rare form of CO in many other discs.
    By doing that, we can more accurately measure their mass, and determine whether
    scientists have systematically been underestimating how much matter they contain."
  • evanhevanh Posts: 8,033
    edited 2019-02-22 - 14:38:28
    Just done the same treatment to 800x600 and got the TV down to 30 MHz, and 28 MHz on the monitor. So 800x600 looks viable over HDMI. Albeit probably at 300MHz! :D

    Will be interesting to see how closely HDMI timings track these VGA timings and also if monitors and TVs differ from each other on HDMI.

    EDIT: +1 to vsync
    EDIT2: Added lots of experiments as options to the timings
    "We suspect that ALMA will allow us to observe this rare form of CO in many other discs.
    By doing that, we can more accurately measure their mass, and determine whether
    scientists have systematically been underestimating how much matter they contain."
  • evanh wrote: »
    Will be interesting to see how closely HDMI timings track these VGA timings and also if monitors and TVs differ from each other on HDMI.

    Yes it will be. I know my 24 inch Dell LCD (over DVI) took all sorts of weird timing and resolutions I threw at it using an HDMI signal from my custom FPGA implementation. I suspect HDTV's may be somewhat less forgiving but it would probably vary and is worth playing around with.
  • I think most monitors will be forgiving as long as refresh is 60 Hz +/- 10% or so.
    Prop Info and Apps: http://www.rayslogic.com/
  • evanhevanh Posts: 8,033
    edited 2019-02-21 - 01:58:28
    49 Hz seems to be the bottom limit for vsync. And 29 kHz for hsync. Although the TV clearly went lower on the horizontal.

    Keeping above those two figures, the biggest problem mostly was that the TV or monitor would detect wrong resolution and make an ugly picture.

    PS: I'm hoping HDMI devices have higher chance of making use of the integral clock and be much better with resolution detection.
    "We suspect that ALMA will allow us to observe this rare form of CO in many other discs.
    By doing that, we can more accurately measure their mass, and determine whether
    scientists have systematically been underestimating how much matter they contain."
  • I've updated the driver so that the VGA pin is now a parameter to the start() method rather than a constant. This should allow for multiple monitors to be easily connected; you'll need one Spin object (and COG) per monitor. The terminal driver code is now more cleanly separated from the tile driver and demo code.

    I've also added some very simple examples of how to use this from C (fastspin only for now, sorry) and BASIC.
  • Wow, I see I haven't updated this for a while, so here's a new version. For those coming to this for the first time: this is a VGA driver for P2 supporting text displayed at 640x480, 800x600, or 1024x768. Most ANSI escape codes are correctly interpreted (enough at least for the pye micropython editor to work correctly) including things like blinking and underlined text.

    There are a bunch of improvements over the last version:

    (1) The new silicon is supported. The hardware is checked at run time so both old and new silicon are supported by the same binary (only the streamer parameters have to change).

    (2) Memory used is more configurable: you can have either 8 bytes per character (allowing for full 24bpp on each of the foreground and background colors for each character) or 4 bytes per character (allowing 8bpp ANSI palette for foreground and background colors). Other than the color we also have 2 bytes per character for the character itself and for special effects.

    (3) A C version of the driver is provided. This is converted automatically from the Spin driver via spin2cpp. I've tested it with riscvp2 and Catalina. p2gcc doesn't have the propeller2.h support that's needed, but perhaps eventually the new PropGCC will. FlexC (aka fastspin) doesn't work with this converted C driver yet, but it can use the Spin code directly so that's not a big problem.

    The documentation is still a little sparse, but I hope the demos (demo.spin2, basdemo.bas, and ccode/cdemo.c) will show basic usage at least. For C only the 800x600 driver is provided, but you can change ccode/Makefile to use one of the other sizes if you'd like. For BASIC or Spin (or FlexC), pick a driver and instantiate it like:
    obj
       vga: "vgatext_640x480.spin2"
    ...
    vga.start(BASEPIN)
    vga.str(string("Hello, world!"))
    
    The parameter to the start function is the base pin of the VGA hardware. For the P2-Eval board this is usually a multiple of 8; I've defaulted to 48, but use whatever pin group your hardware is plugged in to. After initialization, you can write characters to the object using the usual methods .tx, .str, .dec, and so on. ANSI escape sequences may be used to change colors or provide special effects for the text.

    Source code is on my github at:

    https://github.com/totalspectrum/p2_vga_text
  • The pixels should be pretty solid with the new hardware. With the original P2 silicon it'd be wise to make the system clock speed some multiple of the VGA pixel clock, otherwise there will be jitter. For 800x600 I found 160MHz and 200Mhz (multiples of 40MHz) worked well.
  • On top of Eric's advise I'll add that in the revA silicon, of the first 16 divide values of XDIV, only /5 and /7 produce a lot of jitter. Above /16 though, things do get rougher.

    I should try HDMI out again myself ...
    "We suspect that ALMA will allow us to observe this rare form of CO in many other discs.
    By doing that, we can more accurately measure their mass, and determine whether
    scientists have systematically been underestimating how much matter they contain."
Sign In or Register to comment.