#### Equip your Genius

Welcome to the Parallax Discussion Forums, sign-up to participate.

# C: Processing Windows Bitmaps Or DIBs With The Propeller?

## Comments

• Posts: 1,930
edited 2017-04-10 (10:53 PM)
Pretty much that - If you ever decided to bump it to 15 bits instead of 14, or change the command value to include another value, or ... ? It's future-proofing.

If you put your Windows calculator into programmer mode you can enter numbers in hex, decimal, or binary, and it supports left shift, right shift, OR, NOT, etc.

As for the ability to read it, it's like anything else - practice makes perfect. Do it a bunch and you get the hang of it. There's no magic there. You can build them semi-manually too, like this:
``````// Number of possible values in N bits:
// 16  = 4 bits    (0 - 15, or 0 - 0xF)
// 32  = 5 bits    (0 - 31, or 0 - 0x1F)
// 64  = 6 bits    (0 - 63, or 0 - 0x3F)
// 128 = 7 bits    (0 - 127, or 0 - 0x7F)
// 256 = 8 bits    (0 - 255, or 0 - 0xFF)
// 512 = 9 bits    (0 - 511, or 0 - 0x1FF)
// 1024 = 10 bits  (0 - 1023, or 0 - 0x3FF)
// 2048 = 11 bits  (0 - 2047, or 0 - 0x7FF)
// 4096 = 12 bits  (0 - 4095, or 0 - 0xFFF)
// 8192 = 13 bits  (0 - 8191, or 0 - 0x1FFF)
// 16384 = 14 bits (0 - 16383, or 0 - 0x3FFF)

const int Head_Config_Mask  = 3 << 28;   // == 0x30000000   (also 3 << 28)
const int Head_Width_Mask  = ((1<<14)-1) << 14;  // == 0x0FFFC000  (also 0x3FFF << 14)
const int Head_Height_Mask = (1<<14) - 1;  // == 0x00003FFF

typedef struct
{
unsigned long value;

void SetConfig(int config)
{
// using (value & Mask) zeros the previous bits in the positions we're interested in
// following that we | (or) a new value into that space, shifting it up into the right place first.
value = (value & Head_Config_Mask) | (config << 28);
}

void SetWidth(int width)
{
value = (value & Head_Width_Mask) | (width << 14);
}

void SetHeight(int height)
{
value = (value & Head_Height_Mask) | (height << 0);
}

} HDRLONG, *LPHDRLONG;
``````
• Posts: 6,168
edited 2017-04-11 (1:53 AM)
Jason

I was looking around the house at various computer books and I came across one that had several pages with lots of pictures and a wealth of information pertaining to the binary, hexidecimal, and decimal numbering system. Since it looks like it should be very informative, I believe it is definitely worth the time to read it. Additionally, you have certainly provided quite a bit of learning material within this thread. I think I might also take a trip to the library to see what kind of books I can find on the subject bit manipulation. However, as with anything else you learn, if you don't use it you lose it. It took me several hours just to get reacquainted with MFC and get back in the groove. Besides the bit manipulation part of this program, I think I did pretty darn good, for not programming with C, since the last time we worked together on the 3D printer application. Which I have also been thinking about opening back up again, but I don't know, there are easier routes.

I believe I have read that you mess around with lasers also. If that is the case, how hard is it to get the type of focus or spot that you want?

As for additional questions:

How many steps per inch can you achieve with your router and plotter? Or variations? I am just wondering if you might have any use for this type of software. I suppose the only real limiting factor for any x,y, z machine at utilizing this software would be laser dot size, pen size, or bit size, because the dpi could be set in an editor when creating an image to match a machines steps per inch. If you want a copy when it's done, I will be more than happy to provide it to you.

I also see that you reworked the struct for me and it compiles just fine. Thank you for that. I only have one other thing that I want to do with the program. I think I am going to modify the operation of the open file dialog box. Basically I created, as I see it, a major flaw in the program, but it is not difficult to fix, but it would be difficult to fix appropriately. There are two buttons, which are select file and create file. The select files main objective is to get the bitmap file path, and the main processing begins, when the user clicks create file. The problem is that I do not test image resolution until after the user clicks the create button, at which point, if it is above 1 bit or two colors, the program notifies the user that only monochrome bitmaps are allowed. To clear all the check boxes and the edit box after the user clicks create, well let's just say there would be a lot of redundant code. The simple fix would be to just open the bitmap twice, once during file selection to check for resolution and the other for the actual processing. It is either that or redo the program one more time, just to weed that problem out. I don't like it, but it is what it is.

Well I can see I am just rambling.... But I want to ensure you that I am very thankful for all the help you have given me. However be forewarned, I may ask for your assistance when it comes to the Propeller side and I am having trouble getting my data out of the file

Thank you Jason

Bruce
• Posts: 1,930
>> How many steps per inch can you achieve with your router and plotter?

Steppers typically have an error tolerance of 5%, so anything more than 10x micro-stepping is basically wasted, because now the stepper motor itself is less precise than your control system. My big CNC machine is set to about 1908 steps per inch, but my actual physical repeatability on it is probably in the neighborhood of 5 thousandths of an inch. Plenty good for woodworking.

For the little plotter, I think it's 178 steps per mm with 1/4 stepping (4500ish steps per inch).

Most of the stuff I use runs either GCode (router and plotter) or custom files produced by vendor-specific software (the laser). I'm actually in the process of writing my own version of the laser cutter software because their UI is terrible. For image engraving they encode a scheme similar to what you've done.
• Posts: 6,168
Jason
I'm actually in the process of writing my own version of the laser cutter software because their UI is terrible.

Hopefully it is not too difficult. However I am sure you can handle it.
For image engraving they encode a scheme similar to what you've done.

Cool, then at least I know the software isn't that hairbrained of an idea
• Posts: 6,168
Jason

I have been thinking about this a little more and now I think I should perhaps make the machine capable of acquiring data from both an SD card and a PC. Approximately how much faster could I acquire data over a PC USB connection operating at 115,200, as compared to acquiring the data from an SD card?
• Posts: 8,673
edited 2017-04-16 (2:11 PM)
Theoretical maximum data rate for asynch data would be (115,200/10) x 8 = 92,160 bits/sec. That assumes 1 start bit, 8 data bits, 1 stop bit, and no delays caused by the PC or USB connection.

A class 10 SD card can transfer data at 10MBytes/s or 80MBits/sec. Even the slower class 2 SD cards can transfer data at 2MBytes/s or 16MBits/sec. IOW, SD cards are 2 to 3 orders of magnitude faster assuming your hardware and software can keep up.
• Posts: 6,168
kwinn
IOW, SD cards are 2 to 3 orders of magnitude faster assuming your hardware and software can keep up

WOW.... I thought USB was faster. That is quite a significant difference.

Thanks kwinn
• Posts: 1,930
USB 3.0 is faster, but the Prop uses a serial-to-USB connection, and 115,200 is 115,200 bits per second, or 11,520 bytes per second. You can run a Prop up to about 1MBit/sec over serial, but that's pushing it.

An SD card with very simple code will pull 250kb/sec. I think the FSRW routines will do about 922kb/sec, so well faster than serial, and pretty reliably. Again, the libraries on the Prop are the limiting factor here - FSRW (and most other Prop libs) assume the SD card is connected in "serial" or SPI mode. SD cards can also read data a nybble at a time using 4 data lines, which obviously goes a lot faster, but requires more pins and different code.
• Posts: 8,673
idbruce wrote: »
kwinn
IOW, SD cards are 2 to 3 orders of magnitude faster assuming your hardware and software can keep up

WOW.... I thought USB was faster. That is quite a significant difference.

Thanks kwinn

As Jason posted USB 3.0 is faster, but the serial connection to the Prop limits the speed. To paraphrase an old saying "your speed is only as fast as the slowest link in the communication chain".
• Posts: 6,168
Jason and kwinn

Thanks for the clarification. That is good information to know.

Actually when I stop to think about it, especially when Jason said....
or 11,520 bytes per second

That is actually pretty darn fast. If the machine works well off of SD, then I could always add the option for connection to a PC.
• Posts: 6,168
Jason

I found this the other day and it got me to thinking that perhaps I should make a better interface for creating the file data. On this page, about 1/2 way down, they show a GUI for an engraving setup. Overall it looks pretty good, especially when using a computer to send the data instead of an SD. I could even add a couple of other things for pixel editing.

buildlog.net/cnc_laser/xmos_controller.html
• Posts: 9,935
I haven't read this thread properly so you may already have worked this out but what I have done in the (distant) past was to check and decode these bitmaps once only at startup and save in a format that permits directly writing to the display. So if you have flag.bmp with a newer timestamp than the your flag.bin then you would decode and write to the flag.bin while updating flag.bin's timestamp. That way whenever you want to display a "bmp" all you are actually doing is reading your binary file that is optimized for your display.
• Posts: 6,168
Peter

Nice to have you visit I hope all is well.

The thread mostly applies to the other couple of threads I started lately, pertaining to LDI for PCBs. However, as I mentioned, the concept could also be used for display purposes. The bitmaps that I will be using, are going to be pretty large, especially when factoring in various possible dpi's.

However and as always, it is very nice to have your input. Perhaps a user, which intends to display bmp's, may find your post useful.
I haven't read this thread properly so you may already have worked this out but what I have done in the (distant) past was to check and decode these bitmaps once only at startup and save in a format that permits directly writing to the display.

Were these Windows bmps that you were decoding on a Propeller?
• Posts: 9,935
edited 2017-04-20 (6:39 AM)
The good thing about SD memory is that is plentiful and cheap so there is no problem with creating an optimized data file from a bitmap with unoptimized code, whether that be for a display or any other purpose. I did this stuff a long time ago on 16-bit processors, Windows bmp formats, and SCSI hard-drives!

As for serial over USB I run reliably at 2M baud without any trouble and even 3M but SD cards are much faster and more convenient as I you can pretty much run close to 1MB/s when reading in multi-block mode. Even random sector reads in Tachyon are over 630kB/s. However I don't think the information for "4-bit mode" is available, is it? Unless maybe that is different from the "Secure Digital" 4-bit mode that pretty much requires \$\$\$\$\$ and NDAs to work with.
• Posts: 1,930
Bruce - I'm not sure how good your C chops are, but Qt and C# are both really good for doing GUI applications. I know VB is similar, but the newer ones built on the .NET platform have a LOT of helper stuff that's really useful. Some examples below.

These took some time of course, but as you learn the frameworks you get much faster at doing things with them, and there are plenty of examples online to show how stuff works. Qt has very good documentation and examples.

I'm actually more comfortable in C#, and the results are easier to distribute (and smaller), but Qt gets you cross-platform. if you do any amount of UI work it might be worth putting some time in on one of these to see if they could help you.

The laser editing software I'm writing (Qt):

GroundStation (Qt):

Halftoner (C#):
• Posts: 6,168
edited 2017-04-20 (7:17 AM)
Jason

My basic C++ is pretty darn good and much better than my C skills, which are not too bad either, however, my MFC skills are pretty well tuned, for serious output. When I finally get around to upgrading my computer and programming software, I will definitely go with Visual C++, mostly because of the support for MFC, and because I like the Visual Studio IDE.

Additionally, all of my major code and snippets are specific to the Visual C++ platform. It would take a lot of time and serious effort to port all the code that I would want to keep.

As for the pics, they all look very nice, and oh my, that Parallax Ground Station, I can only imagine how much time and effort you put into that software. For complex projects and GUIs, I also like to use Property Sheets and Pages, but I have not done anything complex in a very long time.

LOL... That property sheet has 8 tabs showing with a spin button to access more LOL How many property pages do you have in that program?
• Posts: 6,168
Peter
However I don't think the information for "4-bit mode" is available, is it?

You really don't expect me to know the answer to that question, do you? Heck I don't know
• Posts: 1,930
idbruce wrote: »
LOL... That property sheet has 8 tabs showing with a spin button to access more LOL How many property pages do you have in that program?

There's only one missing: GPS. It actually shows Google Maps hosted in the control. That was a pain in the butt to get working. Most of the panels have custom controls, like the radio sticks you see here, that actually function and move in real time. I like doing stuff like that, even though it's more effort, because it looks more polished.

For serial, I know if you use a uni-directional driver you can go quite a bit faster than the bi-directional ones, particularly if you disable hardware flow control and just use software. If you assume half duplex at all times you could do it in one cog.
• Posts: 1,930
Peter - looks like maybe it's been released into the wild?
https://yannik520.github.io/sdio.html

I'm headed to bed, but I'm going to save this link and look when I have more time.
• Posts: 6,168
Jason
There's only one missing: GPS. It actually shows Google Maps hosted in the control. That was a pain in the butt to get working.

Was it an ActiveX control which showed the actual position of a drone?
• Posts: 9,935
idbruce wrote: »
Peter
However I don't think the information for "4-bit mode" is available, is it?

You really don't expect me to know the answer to that question, do you? Heck I don't know

More rhetorical but loosely addressed to anyone who reads this since this is an open forum. I know some work was being done to try to reverse engineer this.

• Posts: 6,168
More rhetorical but loosely addressed to anyone who reads this since this is an open forum.

Whew!!! Good thing. That thinking cap of mine weighs a ton
• Posts: 1,930
edited 2017-04-20 (6:00 PM)
idbruce wrote: »
Was it an ActiveX control which showed the actual position of a drone?

I think so - it was running WebKit? (I think?) - Qt has a web browser component that can be hosted, and then it just runs a JavaScript applet and whatever magic happens to make the maps interface show up. Otherwise, yes, the connection was live and showed the location of the drone. It wasn't accurate / fast enough for meaningful flight control though. Needs a bunch of work.
• Posts: 6,168
then it just runs a JavaScript applet

We will chalk that up as a typo

Yea, sounds like ActiveX. I think perhaps it might be hard to speed that up, because you would be relying on Google servers to produce the info rapidly.
• Posts: 6,168
I don't know if this is what you are using, but in Google, it mentioned that you could speed up or slow down requests:

https://github.com/googlemaps/google-maps-services-java
• Posts: 6,168
• Posts: 1,930
I basically just run an embedded browser, and it hosts a simple HTML page with some embedded JavaScript (not applet) that starts an embedded Google Maps canvas. It works pretty well.

This is the page / script:
https://github.com/parallaxinc/Flight-Controller/blob/FloatStreamCompiler/GroundStation-Qt/google_maps.html

The code to interact with it is here (look for "gps"):
https://github.com/parallaxinc/Flight-Controller/blob/FloatStreamCompiler/GroundStation-Qt/mainwindow.cpp
• Posts: 6,168
Jason

At first, I thought perhaps you were using a third party applet, but as far as I can tell from your code source, it now appears that you are directly accessing the Google Maps API.

Anyhow, nice looking software. Thanks for sharing.
• Posts: 5,484
Hi Bruce, Sorry to chime in a bit late on your discussion but I dug up an old file that can read bitmap files off an SD card. We were then processing these to convert 24 bit down to 16 bit color in a little pasm routine and then displaying these on a touch screen. The code involved hacking into the bitmap format, getting the file size, then reading out the data. Bitmaps start at the end so you have to reverse the order and there are a few other things. The spin program below is rather large and has a lot of things you don't need but it does have the part to read a bitmap, move it into external ram and process it.
The really important bit is below, and it sends off the lines one at a time to a cog to be processed. You might find you run out of memory so you could do conversions to smaller formats (eg grayscale in n bits) on the fly in a cog with some different code.
``````PUB SDBMPtoRam(stringptr) | width,height,w,i,ramaddress       ' .bmp from sd to ram and convert to 2 byte ili format and reverse order along the way
' http://en.wikipedia.org/wiki/BMP_file_format scroll down about 1/3 of the way for the header formats
' get the width, height
' store these as 2 longs at the beginning of the ram file
' the bitmap format starts at the last row and works up so need to reverse the order
ramaddress := NextLocation                          ' get the next ram location
OpenFileRead(stringptr)
fat.readdata(@sdbuffer,\$36)                         ' get the header 0x36 hex bytes
width := sdbuffer[\$12] + sdbuffer[\$13] << 8         ' only read in two bytes as never will be >64k wide or high
height := sdbuffer[\$16] + sdbuffer[\$17] << 8
w := width * 3                                      ' this number of bytes per row, and round up to nearest 4 bytes et 327 goes to 328 The size of each row is rounded up to a multiple of 4 bytes (a 32-bit DWORD) by padding.
w +=3                                               ' add 3 and
w &= %11111111_11111111_11111111_11111100           ' round down
SpinHubToRam(@sdbuffer,ramaddress,\$36)         ' store header to ram
i := \$36 + ramaddress + ((height - 1) * width) ' start + header and on the last row and work back
repeat height
fat.readdata(@sdbuffer,w)                         ' read in the first row
CogCmd("F",@sdbuffer,@rambuffer,width)
HubToRam(i,width)                                 ' send to ram
i -= width                                        ' subtract the width, move up the picture
FileClose
Ramsize[Filenumber] := \$36 + (width * height)      ' size of bitmap file in words
result := FileNumber                                ' returns the current file number
FileNumber += 1                                     ' add 1 to filenumber
``````
• Posts: 6,168
Dr_Acula

Good to see ya. I hope you are doing well.

Thanks for the post and code, I am sure someone will find it useful. However, I have opted to process the bitmaps on the PC and then store them to SD, once they have been formatted to something I can use.

My files would be rather large to process on the Propeller, but after processing with the PC, the files on SD would contain the bit info.
Sign In or Register to comment.