I tried it on my C3 card, and it looks good. The only problem I see is that the left edge of the image is chopped off a bit on my monitor. There are blank pixels on the right side of the image, so I might be able to adjust the horizontal position to center the image correctly.
The dithered image is a bit grainy, but it's recognizable.
Dave, if yours is like mine, you might have to push the "auto adjust" button to get it right...
Phil, does your driver use the standard horizontal and vertical timings for VGA? Just wondering if the need for auto adjust is because something is slightly off...
My monitor recognizes it is as 640x480@59.9 Hz..
As was mine, your monitor's horizontal position is probably adjusted for the incorrect horizontal timing that persists across some of the Prop VGA drivers. I have one monitor that's very finicky about timing issues, and it simply chopped off the right-hand side of my original images with no options for adjustment. Once I checked the horizontal timing against the VGA specs, I realized that the relative sizes of the front porch and back porch were off, so I corrected them. That produced the correct image on my finicky monitor, and caused me to have to adjust the horizontal positions on my other monitors to compensate.
First off, I was wrong in my previous post about the sync timing. I was relying on erroneous info from the web -- imagine that! -- and since it worked with my finicky monitor, I assumed it was correct. It wasn't. Driving that monitor with 640x480 VGA from a laptop demonstrated that the monitor simply chops off a bit of the image on the right-hand side. So back to the original sync timing.
I've changed the program so that the color-swap buffer overlays the PASM code in hub RAM, which saves about 700 bytes.
I've also added a primitive inter-slide transition function. During a slide presentation, while a new slide is loading from the SD card, the buffer will contain bogus data. So it's important not to be showing anything during this time. In order to make smooth transitions between slides, fades or wipes are often employed. Neither is possible here, given the 6-bit color palette and the slide's data structure; but moving it on and off the screen vertically is quite simple. The attached program demonstrates the effect.
I tried making a video, but my camera's autoexposure was too slow to accommodate the rapid brightness changes. The archive attached above does not require a Prop BOE or an SD card to run: any Prop board with a VGA output will work. This may be the last demo I write that does not require a Prop BOE, though, since the next step is the SD stuff.
Wow, the gamut reduction is REALLY pronounced in that demo. Makes that image look terrible!
Yeah, I know. That's what prompted my strident plea here. But you can fix it on your PPUSB. Just solder in some 100-ohm resistors, as shown in this Demo Board photo:
Here's a link to a post that shows the workaround I used on the Prop BOE:
Once I've finalized the format, I will post an online file converter and also provide the Perl source code. Right now it's a rather tedious process, involving a color mask in the two-color file and a separate file for the photo inset. My objective is to automate the entire process so that a single image can be input to produce the .dat file. I'm planning to change .dat to .pps (Parallax Propeller Slide) and add a four-byte header with "PPS", followed by a version number.
Before I do that, though, I need to make sure I can read the file from SD. In order to save RAM, I'm including Andy Schenck's minimized FSRW in the main program so that the SPI PASM code can overlay the color-swap buffer along with the driver PASM code.
Source code would be great. I think I can port this over for use on our 3.5" and 4.3" touchscreen products...
(Should be great on PTP2 with 256 color palette).
Before I do that, though, I need to make sure I can read the file from SD. In order to save RAM, I'm including Andy Schenck's minimized FSRW in the main program so that the SPI PASM code can overlay the color-swap buffer along with the driver PASM code.
-Phil
Phil, the attached 2nd version of the fsrw_mini_rd may help you with that. It reuses the PASM image in hub for the two sector buffers. The PASM code reserves some longs to reach 1024 kByte. You can use that free ram for the color-swap buffers. Perhaps you need to move the SDSPI code to the main object for that, and pass the start-address to fsrw, which starts then the pasm cog. The fsrw_mini_rd2 has all the buffer accesses done with two pointers instead of the sector byte arrays.
This safes another 760 bytes compared to the first mini version. You can perhaps safe also the 59 reserved longs (=236 bytes).
How compressed is the 4-color image area with your method?
Just thinking about full screen fat pixel mode at 320x240...
The regular way uses 19kB with a fixed 4-color palette. Does your way use less or more memory?
I think it must be more. But, still less than the 75kB you need for 1 byte per pixel.
320 x 240 would be 160 x 240 fat pixels at 2 bits per pixel = 76800 bits, or 9600 bytes. To that, add one to four bytes for every 16 pixels for the color-swap data, so another 2400 to 9600 bytes. The total image size would thus be anywhere between 12000 and 19200 bytes. The high number would be rare, since that would entail a complete palette change every 16 pixels. If the image fills the screen, it would probably not be necessary to have a separate cog unpacking the color-swap data, since there would be time enough in the rendering routine to do it in the foreground.
Bear in mind that his format works for static images only. The Propeller would not be able to create them internally with any kind of drawing commands.
Ok, that's interesting. Right now, I can do 160x120 with 1 byte per pixel in 19200 bytes. But, you can do 160x240 in the same size.
Maybe 320x120 would be better, but I guess that would need 38,400 bytes... But maybe for simple things it could be smaller, right?
The space savings in my four-color algorithm come only from the color swaps. There are two sets of data: the pixels, which are two bits apiece, and the color-swap data. Both sets of data start at the upper-lefthand corner of the image. The pixel data are just a straight-up mapping -- nothing special there. Each byte of color-swap data consists of a 6-bit color and a 2-bit relative index where the sync bits would normally go. The program has a pointer that indicates one of four positions in the current palette. The index in each successive color-swap byte moves that pointer by from one to four positions, then XORs the color at the indexed position with its own payload. When it indexes out of the current palette, that palette is ready for the next block of 16 pixels. Because two bits of indexing information are not enough to skip a palette, every palette must receive at least one color swap -- even it the color is replaced by the same color -- just to get to the next palette.
Doing a pure 2-bit color image in this manner is pretty straightforward. The slides, however, mix 1-bit and 2-bit image data on the same line, which entails a bit more complexity. The hardest part is analyzing an image to determine which parts get 1-bit treatment and which parts have to be rendered with 2-bit color. I haven't figured that out yet, except by doing it manually.
Thanks for the expanation Phil.
Perhaps GUI control screens is a very nice application for this...
At run time, maybe you don't need to change the screen graphics too much, just the colors (like make a circle turn from red to green).
At run time, maybe you don't need to change the screen graphics too much, just the colors (like make a circle turn from red to green).
That would be extremely difficult, unfortunately. The reason is that the circle's red color may occur in byte 0 of the palette in one place, byte 1 in another, and bytes 2 or 3 somewhere else. It all depends on how the intervening colors are assigned. Then, to find where in the color-swap list to make the appropriate changes would be very messy.
The only way I can think of to make an image dynamic like that would be for each dynamic object to have an index into the color-swap list for all the color-swap bytes that affect its color. But even that would be tricky, since some palettes that require a swap for red would not have a swap byte in the list for green, since green already existed in a previous tile. So the compression program would have to create dummy swaps in order to reserve places in the list.
I'm having trouble with your fsrw object. Doing some tracing, I see that the call in fsrw's mount_explicit to sdspi.start_explicit(DO, CLK, DI, CS) is returning a value of 29708 ($740c), but the subsequent call to sdspi.readblock(0, @buf) is not returning at all.
Okay, I formatted my 2GB SD as FAT16, and I'm getting past the filesystem mount, but it's clobbering my video RAM. (I'm not reading any data yet.) Here's a program that illustrates the problem:
It prints Star to the PST screen before clobbering stuff and crapping out.
I've been successful running the demo program here with the same SD card, so I know the SD card and PropBOE are working okay.
-Phil
Addendum: BTW, I noticed that you had the _1024 padding ahead of the res labels, which would put them out of bounds, so I moved it to after the res labels. But it didn't help.
I'm having trouble with your fsrw object. Doing some tracing, I see that the call in fsrw's mount_explicit to sdspi.start_explicit(DO, CLK, DI, CS) is returning a value of 29708 ($740c), but the subsequent call to sdspi.readblock(0, @buf) is not returning at all.
Any ideas?
Thanks,
-Phil
Hello Phil
All the @buf references must be changed to just buf, because buf is now a pointer to the begin of the sector puffer and not the buffer array itself. Seems I missed this methode call in the mount methode. So please try it with removing the @.
The mount_explicit methode returns the startaddress of the first sector buffer on success (a positive value), or a negative value on errors, so $740C looks good.
Andy
Edit: Attached is a corrected fsrw spin file. I also found that I have commented out a bit too much in the popen methode - this one now returns -1, if the file was not found.
This works for me with a 4GB FAT32 and with a 2GB FAT16 card.
Ken, I've got your DVI Graphics board working on a PropBOE. Thought about several different options, but I think this one is best. The data pins just plug in with extra long male header pins on P4..P15. This leaves P0..P3 exposed for XBee control. Plus, the board is upside down, which you might like so you won't have to explain the "Rayslogic.com" logo on it:
But, you have to run jumper wires for power. I've hid them under the board:
But, this is DVI and you want VGA, so I have to figure out the best way to put in that card...
What I think will work best is to mount that board without the VGA connector, so it only adds a few mm on top.
Then, you'll need to use a DVI-VGA adapter. I've got them lying around everywhere, so I'll put one on for you.
BTW: I thought my driver could be easily changed to work on any pins. But, it didn't exactly work right and I had to update the driver.
So, this was a good exercise because I never actually tried it on different pins until now...
Attached is an archive that will run a slide show on a Prop BOE with an SD card holding the slide data. Add the slide***.pps files to the SD card's root directory. A small SD card ~ 2GB formatted FAT16 has worked best for me.
This will give you an idea which kinds of images work best. I switched to the Verdana typeface for the later slides and like it way better at this resolution than Arial. It's much cleaner on a low-res screen.
Many thanks to Andy Schenk and Tomas Rokicki for their work on the SD card reader objects! It would've taken me a blue moon to figure that stuff out.
I had to make one timing adjustment to the video generator. I noticed that, in two slides, the screen would go black briefly at random intervals. I discovered that those slides were generating infrequent, very narrow Vsync pulses during the visible portion of the image. It turns out that the interaction between rdlong hub accesses and waitvid was producing occasional instances when the program missed its waitvid appointment. Moving one statement that was before the waitvid to follow it fixed the problem.
Comments
The dithered image is a bit grainy, but it's recognizable.
Phil, does your driver use the standard horizontal and vertical timings for VGA? Just wondering if the need for auto adjust is because something is slightly off...
My monitor recognizes it is as 640x480@59.9 Hz..
As was mine, your monitor's horizontal position is probably adjusted for the incorrect horizontal timing that persists across some of the Prop VGA drivers. I have one monitor that's very finicky about timing issues, and it simply chopped off the right-hand side of my original images with no options for adjustment. Once I checked the horizontal timing against the VGA specs, I realized that the relative sizes of the front porch and back porch were off, so I corrected them. That produced the correct image on my finicky monitor, and caused me to have to adjust the horizontal positions on my other monitors to compensate.
-Phil
I've changed the program so that the color-swap buffer overlays the PASM code in hub RAM, which saves about 700 bytes.
I've also added a primitive inter-slide transition function. During a slide presentation, while a new slide is loading from the SD card, the buffer will contain bogus data. So it's important not to be showing anything during this time. In order to make smooth transitions between slides, fades or wipes are often employed. Neither is possible here, given the 6-bit color palette and the slide's data structure; but moving it on and off the screen vertically is quite simple. The attached program demonstrates the effect.
-Phil
I tried making a video, but my camera's autoexposure was too slow to accommodate the rapid brightness changes. The archive attached above does not require a Prop BOE or an SD card to run: any Prop board with a VGA output will work. This may be the last demo I write that does not require a Prop BOE, though, since the next step is the SD stuff.
-Phil
FWIW, all you have to do to display it on a PPUSB is tell the program it's a demo board.
Here's a link to a post that shows the workaround I used on the Prop BOE:
-Phil
(If you're done with it...)
Once I've finalized the format, I will post an online file converter and also provide the Perl source code. Right now it's a rather tedious process, involving a color mask in the two-color file and a separate file for the photo inset. My objective is to automate the entire process so that a single image can be input to produce the .dat file. I'm planning to change .dat to .pps (Parallax Propeller Slide) and add a four-byte header with "PPS", followed by a version number.
Before I do that, though, I need to make sure I can read the file from SD. In order to save RAM, I'm including Andy Schenck's minimized FSRW in the main program so that the SPI PASM code can overlay the color-swap buffer along with the driver PASM code.
-Phil
(Should be great on PTP2 with 256 color palette).
Phil, the attached 2nd version of the fsrw_mini_rd may help you with that. It reuses the PASM image in hub for the two sector buffers. The PASM code reserves some longs to reach 1024 kByte. You can use that free ram for the color-swap buffers. Perhaps you need to move the SDSPI code to the main object for that, and pass the start-address to fsrw, which starts then the pasm cog. The fsrw_mini_rd2 has all the buffer accesses done with two pointers instead of the sector byte arrays.
This safes another 760 bytes compared to the first mini version. You can perhaps safe also the 59 reserved longs (=236 bytes).
Andy
-Phil
How compressed is the 4-color image area with your method?
Just thinking about full screen fat pixel mode at 320x240...
The regular way uses 19kB with a fixed 4-color palette. Does your way use less or more memory?
I think it must be more. But, still less than the 75kB you need for 1 byte per pixel.
320 x 240 would be 160 x 240 fat pixels at 2 bits per pixel = 76800 bits, or 9600 bytes. To that, add one to four bytes for every 16 pixels for the color-swap data, so another 2400 to 9600 bytes. The total image size would thus be anywhere between 12000 and 19200 bytes. The high number would be rare, since that would entail a complete palette change every 16 pixels. If the image fills the screen, it would probably not be necessary to have a separate cog unpacking the color-swap data, since there would be time enough in the rendering routine to do it in the foreground.
Bear in mind that his format works for static images only. The Propeller would not be able to create them internally with any kind of drawing commands.
-Phil
Maybe 320x120 would be better, but I guess that would need 38,400 bytes... But maybe for simple things it could be smaller, right?
Doing a pure 2-bit color image in this manner is pretty straightforward. The slides, however, mix 1-bit and 2-bit image data on the same line, which entails a bit more complexity. The hardest part is analyzing an image to determine which parts get 1-bit treatment and which parts have to be rendered with 2-bit color. I haven't figured that out yet, except by doing it manually.
-Phil
Perhaps GUI control screens is a very nice application for this...
At run time, maybe you don't need to change the screen graphics too much, just the colors (like make a circle turn from red to green).
-Phil
The only way I can think of to make an image dynamic like that would be for each dynamic object to have an index into the color-swap list for all the color-swap bytes that affect its color. But even that would be tricky, since some palettes that require a swap for red would not have a swap byte in the list for green, since green already existed in a previous tile. So the compression program would have to create dummy swaps in order to reserve places in the list.
-Phil
I'm having trouble with your fsrw object. Doing some tracing, I see that the call in fsrw's mount_explicit to sdspi.start_explicit(DO, CLK, DI, CS) is returning a value of 29708 ($740c), but the subsequent call to sdspi.readblock(0, @buf) is not returning at all.
Any ideas?
Thanks,
-Phil
Okay, I formatted my 2GB SD as FAT16, and I'm getting past the filesystem mount, but it's clobbering my video RAM. (I'm not reading any data yet.) Here's a program that illustrates the problem:
It prints Star to the PST screen before clobbering stuff and crapping out.
I've been successful running the demo program here with the same SD card, so I know the SD card and PropBOE are working okay.
-Phil
Addendum: BTW, I noticed that you had the _1024 padding ahead of the res labels, which would put them out of bounds, so I moved it to after the res labels. But it didn't help.
Hello Phil
All the @buf references must be changed to just buf, because buf is now a pointer to the begin of the sector puffer and not the buffer array itself. Seems I missed this methode call in the mount methode. So please try it with removing the @.
The mount_explicit methode returns the startaddress of the first sector buffer on success (a positive value), or a negative value on errors, so $740C looks good.
Andy
Edit: Attached is a corrected fsrw spin file. I also found that I have commented out a bit too much in the popen methode - this one now returns -1, if the file was not found.
This works for me with a 4GB FAT32 and with a 2GB FAT16 card.
-Phil
But, you have to run jumper wires for power. I've hid them under the board:
But, this is DVI and you want VGA, so I have to figure out the best way to put in that card...
What I think will work best is to mount that board without the VGA connector, so it only adds a few mm on top.
Then, you'll need to use a DVI-VGA adapter. I've got them lying around everywhere, so I'll put one on for you.
BTW: I thought my driver could be easily changed to work on any pins. But, it didn't exactly work right and I had to update the driver.
So, this was a good exercise because I never actually tried it on different pins until now...
This will give you an idea which kinds of images work best. I switched to the Verdana typeface for the later slides and like it way better at this resolution than Arial. It's much cleaner on a low-res screen.
Many thanks to Andy Schenk and Tomas Rokicki for their work on the SD card reader objects! It would've taken me a blue moon to figure that stuff out.
I had to make one timing adjustment to the video generator. I noticed that, in two slides, the screen would go black briefly at random intervals. I discovered that those slides were generating infrequent, very narrow Vsync pulses during the visible portion of the image. It turns out that the interaction between rdlong hub accesses and waitvid was producing occasional instances when the program missed its waitvid appointment. Moving one statement that was before the waitvid to follow it fixed the problem.
-Phil