A, B, or C? (GLCD Plot Algorithms)

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
I have been playing with different ways to plot a temperature chart. X-axis is always one step. Plotting single data points is easy, but I don't like how it looks when the temperature change is more than 2° (1 pixel per degree). Here are three exaggerated examples of up and down results. In practice, the chart will be mostly up or no change and cooling will be mostly down or no change. Screen will be approximately 64 x 64 pixels. Y-axis is 8, 8-pixel high pages.

Which do you prefer? (Open circles are the actual data points. Trend line is in green. Red line is the demarcation between two hypothetical pages.)

1607194553629.png

From the standpoint of coding, B is probably a tiny bit easier than A (i.e., previous datapoint does not need to be OR'ed) and is closer to the Bresenham line. Either A or B is easier than C. Clipping only one pixel off the 5th datapoint in B would be at least as difficult as C alone.
 

ericgibbs

Joined Jan 29, 2010
18,766
hi John,
I would use a regular histogram plot from a common base line.
Also do you plan to say left shift the plots as the plots reach the right side end of the display.?
So that the latest plot will always be at the last Column
E
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Right now, I do not want a histogram. Easy to do, but for now I am a line graph person. May change as time goes on. They do look nice. This project was functionally done 18 months ago (big Spring, Summer, and early Fall break). Right now, I am just having fun with coding to see if I can make it do what I want it to do.

As for graph range and scrolling, yes, those are set up. If either Y-max or Y-min is met while adding a new point, the whole graph is scrolled. Right now, I scroll 5 pixels so I don't have to change the Y-axis tick marks. That's adds a bit more complication because rows are 8-pixels high and each point has to be re-calculated. So far, that scroll is not very noticeable. X-axis (time) scroll is also 5 pixels, and that is not much of a problem. My byte calculation routines are fast enough that I only store raw data (i.e., temperature) and recalculate the entire screen on every scroll. The main difference is that once a new datapoint causes a scroll up or down or X-axis, range testing on earlier data is limited to finding whether the data point on axis, which creates a skip, or in range. If I didn't do that, I could envision the screen going crazy if the temperature range during an hour (X-axis max) exceeded Y-max/Y-min. ;)
 

nsaspook

Joined Aug 27, 2009
13,084
You must be close to finishing this project.;)

After a rescale.
1607194553629.png
A: Just looks bad.
B or C: I would pick B because while the displayed trend is not pixel accurate the visual of change is more apparent.
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Yes, it is all about looks. For example, for a rise of, say 3°, I go diagonal rather than horizontal, which looks "clunky" to me. Plus, it is kind of fun butchering bits..
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Quick update:
1) I decided on A, as i like the highest pixel in a column to represent the actual value. Lots of other issues came up to limit my time, but I am almost there. The problem is recovering history from a GLCD that cannot be read. Not all that hard to do, but it does use up registers.
2) @ericgibbs
I decided to take a break from that effort this morning and try a histogram. Very easy to do, requires no memory of prior states/values and doesn't look bad at all. In fact, it looks pretty good. I wanted to get some timings, but apparently MPLab 8.92 with an ICD3 in hardware simulation doesn't support that for the 16F1783. It works fine with the 16F1829. It is very short code but des have a loof to write 0xFF from the value pixel to the X-axis. Just wanted to show a picture:
GLCD histogram.jpg

The curves are drawn from a calculated table (sigmoid + exponential).
 

ericgibbs

Joined Jan 29, 2010
18,766
hi John,
I would say that presentation is excellent, simple and easy to read.

Do you plan to add a grid as a background scale,?

E
 

MrChips

Joined Oct 2, 2009
30,712
I wrote assembler code for vector graphics many moons ago before the debut of the IBM PC.

There is an art and craft in writing DDA code (digital differential analyzer). You have to do proper rounding. Also because I was doing selective erase it was important that the pixels hit were the same regardless of the direction in which the vector was drawn.

If you need help with this I can try to dig up my notes.
 

MrChips

Joined Oct 2, 2009
30,712
From a programmatic algorithm perspective there is another scheme shown as D.
Since x-inc is always +1, just move over to x+1 and draw the next column either starting at the same y or y±1.

GLCD pixel graphics.jpg
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Increasing temperature is no problem. That was done a long time ago:
1611599924841.png
It handles page crossing very well and is not terribly complex. The problem is decreasing temperature. My current approach is to calculate a mask for decreasing temperature, IOR that with the previous mask, and rather than printing it in the current column, it is printed in the previous column , which is what I intended example A to show.

The code worked for everything I threw at it, except for a specific glitch. I can make it fail by going up and down quickly (5 to 7 degrees) and crossing page boundaries. I can get an extra bit added to the top of the penultimate mask. I put 3 or 4 days into that and decided to let it rest a day or two. I think it is a code problem,* not algorithm, which is why I took a rest today and did the histogram. I was so happy with the histogram's appearance that I will probably use it.

However, I still want to solve the original problem. Unfortunately, I didn't take any pictures of the specific problem.

John

* My algorithm was written in light of a particular project -- a roast thermometer that predicts the done time. In order to make the math a little simpler and save registers, I set as one of the conditions that the temperature in one minute cannot increase or decrease more than one page. Since my GLCD page is set to one pixel per degree, a change of more than 8°F as a worst case would cause a range error. Of course, if the 0th pixel in one byte is set, the temperature could decrease 15° (e.g., 95° to 80°, before crossing a second page boundary.

Given a value, I calculate its modulo 8 (lower 3 bits) and row number (upper 5 bits). A bit is set in a register corresponding to the modulus ("newbyte"). My rows go from 0 (highest value) to 31 (lowest value); pages are limited to the 7 or 8 usable pages on the 64x132 GLCD. A simple offset converts from one to the other and allows scrolling.

Masks are constructed by subtracting the previous and current bytes representing the modulus and complementing , if necessary. Obviously, the page for oldbyte and newbyte are not always the same. So, I align oldbyte data to a register that matches to newbyte's page. If you picture newbyte at say page 4, then the modulus data in oldbyte could be page 3,4, or 5. I avoid calling them upper, high, and low, because the upper byte is the lowest value on the GLCD. I call them left (upper), oldbyte or middle, and right (lower), respectively.
Here's my code for that:
Code:
     movlw     oldbyte      
     movwf     FSR0           ;center FSRn on oldbyte regs   
     movf      newpage,w
     subwf     oldpage,w      ;oldpage-newpage expected range +1(incr)/-1(decr)
     addwf     FSR0,f         ;FSRn now aligns oldbyte regs with newbyte page
     movf      oldbyte,w
     clrf      oldbyte
     movwf     INDF0          ;data in oldbyte may go to oldbyteR, oldbyte, oldbyteL
I simply subtract newbyte from the oldbyte registers -- only one of which is greater than 0 -- to get a mask. The enhanced mid-range instruction set helps a little.
 
Last edited:

MrChips

Joined Oct 2, 2009
30,712
I must be missing something. Off-hand I don't see what is different about decreasing temperature from increasing temperature.
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Off-hand I don't see what is different about decreasing temperature from increasing temperature.
It depends on how they are plotted. In A, one uniquely needs to plot to a previously plotted mask, hence my IOR'ing. With rising values, that is never a problem. B and C require knowing the end of the previous data mask. XOR'ing should do that, but that still requires saving a previous mask. D would not require much change in my code at all.

My original question perhaps arose because of the decades I spent reading strip charts:

1611607974249.png

If you are trying to read the values of the plotted points, you read the inflection points (dots), In a histogram, you read the top of each bar. When that is reduced to a single pixels, as in this example with the same data:

1611609313084.png
My initial impression was that one should still read the tops, even though it looks really bad. Versions B, C, and D would be easier to implement than A, and in order of ease, D>B>C (D is easiest).

I have not faced this issue before, as GLCD's are relatively new to me. My original post was basically asking whether there is a correct/accepted way to do it.
I am beginning to think D or B might be the correct way. C avoids the double width lines that tend to look bad.

On reflection, let's say the choice is between B or D. What do others think?
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
UPDATE:

Option D works easily and looks pretty good. Here's a test pattern designed to accentuate the overlap versus option B or C.
1611752494985.png

Here is what the histogram pattern looks like with the line draw:

Option D.jpg

Really not too bad in a more realistic setting.

John
 
Top