Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LCD Interactive Mesh #5

Closed
Tannoo opened this issue Jun 13, 2017 · 209 comments
Closed

LCD Interactive Mesh #5

Tannoo opened this issue Jun 13, 2017 · 209 comments

Comments

@Tannoo
Copy link
Owner

Tannoo commented Jun 13, 2017

I have another branch now out for "cleanup" of this:
https://github.com/Tannoo/Marlin/tree/LCD_Interactive_Mesh_Edit_Refinements

I just moved the whole function of _lcd_ubl_plot_drawing_prep to the DOGM.h file, but renamed it to _lcd_ubl_plot_drawing.

You should be able to add whatever you want to throw into this branch.

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 13, 2017

Essentially, everything that was in the #ifdef DOGLCD was moved.

@Roxy-3D
Copy link

Roxy-3D commented Jun 13, 2017

There is a big problem with moving function blocks to .h files. Any code that #includes the header file will also generate an instance of the function code that is embedded in the .h file. We don't want to do that.

I know it is confusing because you see inline definition of functions in the .h files. But those don't actually generate code. In those cases, they just define what to substitute into the code block when a .cpp file makes a 'call' to that function.

It maybe that we should have a separate .cpp file for functions that are only used with DOGM. But that function does not belong in the .h file. If we did make a separate file for DOGM functions, we probably will make a separate file for the 20x4 specific functions too.

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 13, 2017

Okay. Maybe a ultralcd_impl_DOGM.cpp?

@Roxy-3D
Copy link

Roxy-3D commented Jun 13, 2017

Yeah... That implies it is the implementation code for ultralcd that is DOGM specific. And I would prefer the 20x4 equivalent code was ultralcd_impl_20x4.cpp but everybody is going to complain that should be named ultralcd_impl_HD44780.cpp

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 13, 2017

Yes. Because that would also give room for more display specific code like this map.

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 13, 2017

You can change it up, or I'll do it this afternoon.

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 13, 2017

Time to get a nap in. Lol

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

Okay, there is something I'm just not getting.

.h files:
defines
function declarations

.cpp
functions

When I try to set it up that way, compile errors out the yin-yang.
Maybe I was getting ahead of myself... I did find that there were declarations inside of functions
and I just declared the function and left the defines in the cpp function. That didn't seem to work.
Plus, temperature.h and cardreader have to be included now? When the relevant functions were in .h, those did not need to be included. I'm lost.

Here's where I stopped for now:
ultralcd_impl_DOGM.h.txt
ultralcd_impl_DOGM.cpp.txt

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

I'm going to start over again trying just the map function again.
I did that once and it didn't work. But, I think I know where I messed up.

@Roxy-3D
Copy link

Roxy-3D commented Jun 15, 2017

Those two files you attached in the last post look reasonable. That is what a typical C programmer would expect to see. What errors are you getting with the files like that?

If you have those files in a branch ready to compile like that... I'll see if I can work through the errors. And assuming I can work through the errors... When you see what was done to fix the problems you will say "That makes sense!"

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

I will create a branch with this setup.
Here is the full list of errors:
current_errors.txt

@Roxy-3D
Copy link

Roxy-3D commented Jun 15, 2017

Please give me write access to the branch also...

With a little luck... I can beat the compiler into submission... (there are a lot of errors... So who knows??? But nothing looked too crazy in that error list.)

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

https://github.com/Tannoo/Marlin/tree/ultralcd_impl_DOGM.cpp

I believe you still have collaborator status to my repo... I don't think it's branch specific.

@Roxy-3D
Copy link

Roxy-3D commented Jun 15, 2017

I believe you still have collaborator status to my repo... I don't think it's branch specific.

Oh! OK! Git and I don't get along very well.... I'll clone it now and see if I can get it to compile clean.

@Roxy-3D
Copy link

Roxy-3D commented Jun 15, 2017

I turned on:

//
// RepRapDiscount FULL GRAPHIC Smart Controller
// http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
//
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER

and that got rid of 80% of the errors. That probably means you have stuff being used or pulled into the compilation that shouldn't be without the LCD Controller active. Very possibly, you are not checking to see if the ultralcd_impl_DOGM.cpp should be compiled or not with #ifdef's around it.... I don't know... But stuff is getting pulled in when it shouldn't be.

I'll keep looking at the remaining errors.

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

Ok, but that has been defined in my configuration.h file for 2 years now. I have not changed that. I have not changed displays in that time.

@Roxy-3D
Copy link

Roxy-3D commented Jun 15, 2017

Don't worry.... I'm getting close... And I'll be able to fix that problem too...

The problem is you started with a branch that did not have the Graphic's Controller LCD turned on... The Configuration.h file in the branch you gave me a link to was for the basic machines... (But still... That should compile clean... That is what I'm trying to communicate.)

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

Well, it didn't have the config files that I run.
Configuration.txt
Configuration_adv.txt

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 15, 2017

That is what my machine runs... RGB strip, DHT sensor, UBL, Full Graphic, and lots of other things enabled.
I don't think your machine would run that...and I didn't update the entire file set to support all of them on that branch.
If you want all the other supporting code for those additional functions that my printer runs, then switch to the Current_Running branch and drop those DOGM files and the ultralcd.cpp file into it.

@Roxy-3D
Copy link

Roxy-3D commented Jun 15, 2017

My comments were based on the assumption that was a clean copy of bugfix-v1.1.x with just the changes to put declarations in .h files and code in the .cpp files. If that is not true... My comments have less value.

I'm getting close to having something to send you....

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 16, 2017

clean copy of bugfix-v1.1.x with just the changes to put declarations in .h files and code in the .cpp files.

That is exactly what that branch is.

@Roxy-3D
Copy link

Roxy-3D commented Jun 16, 2017

OK... Well... I'm not doing anything too fantastic.... You will be saying "Of course..." to each change....

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 16, 2017

And one change to ultralcd.cpp to support the move of the _lcd_ubl_plot_DOGLCD function to the ultralcd_impl_DOGM.cpp file.

(I deleted _lcd_ubl_plot_DOGLCD from ultralcd.cpp)

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 16, 2017

I'm not doing anything too fantastic.... You will be saying "Of course..." to each change....

I hope so.. lol

@Roxy-3D
Copy link

Roxy-3D commented Jun 16, 2017

I did bust ultralcd_st7920_u8glib_rrd.h up into both a .h file and a .cpp file....

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 16, 2017

There are a lot of functions I created in the menu system and not once did I have to put anything into the ultralcd.h file. So, I assume that the .h file declarations are needed only if the functions in a given .cpp file are being called from a file OTHER than the .cpp file itself.
Even going on that theory, I have failed to get Marlin to cooperate with this new .cpp file addition.

If I can get the understanding of what you did, maybe I can get the ultralcd_impl_HD44780.cpp to work.
Although, I'm not getting my hopes up too high, yet.

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 16, 2017

I read that too fast... lol

@Tannoo
Copy link
Owner Author

Tannoo commented Jun 16, 2017

The ultralcd_st7920_u8glib_rrd.h needed to be done also? I didn't consider that.

@Roxy-3D
Copy link

Roxy-3D commented Jun 16, 2017

I know why you were having such a hard time! The .h files were not set up to be included by different .cpp files. The .h files (including utf_mapper.h) are generating code. And including them more than once is causing a lot of issues... I'm getting there. But I probably won't be done tonight before I have to quit.

@Roxy-3D
Copy link

Roxy-3D commented Jun 16, 2017

If you want... I can commit and sync when I quit tonight. But if I do that, it will leave the branch in a broken state. It will be much closer to 'right'. But it won't be right when I quit.

With that said... You can start looking at what I did and see what you think....

@Roxy-3D
Copy link

Roxy-3D commented Jul 3, 2017

Hah!!! I have it doing everything except the 4 character mesh point plot... Maybe I'll do that tomorrow. It does 1x1, 2x1 and 1x2 mesh point plots right now. Tomorrow... the 2x2 gets dropped into it...
Check this out:

tmp.txt

Wow, that is some file.

Yeah... it is kind of verbose. But I needed that to debug how the LCD Panel is going to plot pixels. You can see the custom characters that get generated and how they are positioned on the display. The good news is the routine to generate the special characters and plot the mesh point is relatively small.

When I get the 4 character mesh point types to plot... I'll work on compressing the code. And then tell it to generate a pixel map for every possible mesh dimension and for every pixel location on that mesh so I can verify everything looks nice and works as expected. THAT will be a large file.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 3, 2017

Ok... I'll wipe my hdd to get ready for it. ;)

@Roxy-3D
Copy link

Roxy-3D commented Jul 4, 2017

I've got the code squished down to almost the bare minimum. I have it calling createChar(7, &new_char); to add the customized characters with the bare minimum of stack space.

The function's name is

void draw_mesh_map_and_plot_point(int x, int y) 

It just needs to be called with the (x,y) point to plot on the mesh map. Do you have a branch I can add it to? And a place I can hook it into? I still have a couple little bugs outstanding. Some times it doesn't redraw the box on the mesh map points under very extreme GRID_MAX_POINTS_X; and GRID_MAX_POINTS_Y conditions. (And then... Only on the right side. I'll get that working tomorrow.)

I had to delete most of the file... But you should be able to see what it does...

tmp.txt

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 4, 2017

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 4, 2017

Are you ok with renaming the function to:

void lcd_implementation_ubl_plot(uint8_t x, uint8_t y)

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 4, 2017

Should this function be in it's own file due to the size of it? It doesn't look to be shrunk down yet, or in compliable format. lol

@Roxy-3D
Copy link

Roxy-3D commented Jul 4, 2017

I meant the code was shrunk down... I'm still debugging it... It might be best to be in its own file. Just so it can be turned off.

Yes, we can rename it to that name.

@Roxy-3D
Copy link

Roxy-3D commented Jul 4, 2017

Aaaaarrrrgggghhhhh! I have a function that adds edge pixels to the custom character cells. It tries to keep the box edges intact if a mesh point is in the same character cell that a box line was drawn.

I have to start over. Right now... things are close, but with the 4 character mesh point plots, there is a logic error. The function doesn't have enough information to always do the right thing.

Fortunately... It won't be that bad to re-write that function. But this code is more difficult than it should be.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 4, 2017

Would you like to take a look at the library I found to do graphic stuff on a character display?

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 4, 2017

Maybe it will give some insight?

@Roxy-3D
Copy link

Roxy-3D commented Jul 4, 2017

Na.... I'm really close. Trying to understand somebody else's work will be more effort than to fix what I have. And also... What I have is fairly efficient. The big problem with general purpose libraries is they have to handle anything. So... There is always a lot of code bloat in them.

And you can see from those text files it is working and doing the right thing. It is just in some super specific cases, it doesn't have enough information and it tries to add the box lines into the custom character cell when it shouldn't.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 4, 2017

Well, I couldn't see that. I will have to take your word for that. :)

@Roxy-3D
Copy link

Roxy-3D commented Jul 4, 2017

Here is a little text file to look at. On the four character mesh plot, it is getting confused and trying to add the bottom box line when it shouldn't. This hardly ever happens. But it did happen here. This is the whole reason I wanted to plot every mesh dimension and every mesh point.

tmp.txt

@Roxy-3D
Copy link

Roxy-3D commented Jul 4, 2017

Also... I'm converting stuff so it is almost just a Cut & Paste to move it to Marlin.

  k = pixels_per_Y_mesh_pnt * GRID_MAX_POINTS_Y + 2;
  l = ULTRA_Y_PIXELS_PER_CHAR * n_rows;
  if ( (k != l) && ((l-k)>=ULTRA_Y_PIXELS_PER_CHAR/2) ) {
    lcd_setCursor(0, n_rows-1);            // left edge of the box
    lcd_print(' ');                           
    lcd_setCursor(n_cols-1, n_rows-1);     // right edge of the box
    lcd_print(' ');      
  }

  CLEAR_CUSTOM_CHAR( &new_char );
  new_char.custom_char_bits[0] = (unsigned char) 0B11111;                // char #0 is used for the top line of the box
  createChar( 0, &new_char );

the lcd_print() lines need to be turned into lcd.print()
and lcd_setCursor() to lcd.setCursor() But you get the idea....

@Roxy-3D
Copy link

Roxy-3D commented Jul 5, 2017

Code is re-written... And almost correct and working. I see a couple of small errors in how it adds box lines to the mesh points... But very soon... I'm going to be ready to put it into your branch. Soon... the 20x4 displays will have an LCD Radar Map for interactive mesh editing!!!! :)

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

Sweet!! I'm trying to get the current code to work the way Thinky wants it.

@Roxy-3D
Copy link

Roxy-3D commented Jul 5, 2017

Yeah... The truth is, he is right... That code he is talking about I just cut and pasted from another part of Marlin where it was doing something close to what we needed. I just wanted something that worked. But that code can be collapsed and compressed significantly....

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

#6 is where I was asking for help on that. <-- I was mistaken on this.... I was asking for help on a different issue.

@Roxy-3D
Copy link

Roxy-3D commented Jul 5, 2017

Oh! I'm sorry! I never saw that thread. I get emails if you add anything to this thread, but because I never 'contributed' to that thread, I don't get any notifications about it.

And maybe I jumped to a bad conclusion. I was just assuming that the stepper motor quick stop was for the Postage Stamp Radar routine... I might have been wrong on that....

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

No, you are not wrong. I was asking for help with another issue.
Thinky just finds something else to change every time he looks at some code.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

I got his changes done. Now, I still have the issue described in #6.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

I got it working. I hope it's not hacked too bad.

@Roxy-3D
Copy link

Roxy-3D commented Jul 5, 2017

Is: https://github.com/Tannoo/Marlin/tree/20x4_lcd_update rebased and ready to code added to it?

I think I have the 20x4 Mesh Point plotter 'correct'. This is the .h file and some obvious stuff gets deleted out of it:

#pragma once

//#define GRID_MAX_POINTS_X         15
//#define GRID_MAX_POINTS_Y         15
extern int GRID_MAX_POINTS_X;		// These go away when moved Marlin.  We need these as int variables so we can scan the
extern int GRID_MAX_POINTS_Y;		// entire range and make sure things work for every combination.


#define ULTRA_X_PIXELS_PER_CHAR    5
#define ULTRA_Y_PIXELS_PER_CHAR    8
#define ULTRA_COLUMNS_FOR_MESH_MAP 7
#define ULTRA_ROWS_FOR_MESH_MAP    4

#define DISPLAY_COLUMNS 20
#define DISPLAY_ROWS    4

#define N_USER_CHARS    8

extern char display[DISPLAY_COLUMNS][DISPLAY_ROWS];

#define LEFT_EDGE     0x01
#define TOP_EDGE      0x02
#define RIGHT_EDGE    0x04
#define BOTTOM_EDGE   0x08 

#define TOP_LEFT      0x01
#define TOP_RIGHT     0x02
#define LOWER_LEFT    0x04
#define LOWER_RIGHT   0x08 

struct coordinate {
        int column;
        int row;
        int y_pixel_offset;
        int x_pixel_offset;
        unsigned int x_pixel_mask;
};

struct custom_char {
	unsigned char custom_char_bits[ULTRA_Y_PIXELS_PER_CHAR];
};
extern custom_char user_defined_chars[N_USER_CHARS];

inline static void CLEAR_CUSTOM_CHAR(struct custom_char *cc) { int j; for (j = 0; j < ULTRA_Y_PIXELS_PER_CHAR; j++) cc->custom_char_bits[j] = 0; }
void createChar(char c, struct custom_char *ptr);

void lcd_implementation_ubl_plot(int x, int y);
struct coordinate pixel_location(int x, int y);
void add_edges_to_custom_char(struct custom_char *custom, struct coordinate *ul, struct coordinate *lr, struct coordinate *brc, int flags);

char *to_binary_str(int x);   // These all go away when moving to Marlin
void show_20x4_LCD();
void lcd_setCursor(int x, int y);
void lcd_print(char c);

and the .cpp file:

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "20x4.h"
#define _CRT_SECURE_NO_WARNINGS

void lcd_implementation_ubl_plot(int x, int inverted_y) {
  struct coordinate upper_left, lower_right, bottom_right_corner;
  custom_char new_char;
  int i, j, k, l, m, n, n_rows, n_cols, y;
  int bottom_line, right_edge;
  int x_map_pixels, y_map_pixels;
  int pixels_per_X_mesh_pnt, pixels_per_Y_mesh_pnt;
  int suppress_x_offset=0, suppress_y_offset=0;

//  ********************************************************
//  ************ Clear and setup everything        *********
//  ********************************************************

  y = GRID_MAX_POINTS_Y - inverted_y - 1;

  upper_left.column  = 0;
  upper_left.row     = 0;
  lower_right.column = 0;
  lower_right.row    = 0;

  for (i = 0; i < DISPLAY_COLUMNS; i++)
    for (j = 0; j < DISPLAY_ROWS; j++) {
      lcd_setCursor(i, j);
      lcd_print(' ');
    }

  x_map_pixels = ULTRA_X_PIXELS_PER_CHAR * ULTRA_COLUMNS_FOR_MESH_MAP - 2;  // minus 2 because we are drawing a box around the map 
  y_map_pixels = ULTRA_Y_PIXELS_PER_CHAR * ULTRA_ROWS_FOR_MESH_MAP - 2;

  pixels_per_X_mesh_pnt = x_map_pixels / GRID_MAX_POINTS_X;
  pixels_per_Y_mesh_pnt = y_map_pixels / GRID_MAX_POINTS_Y;

  if (pixels_per_X_mesh_pnt >= ULTRA_X_PIXELS_PER_CHAR)  {                  // There are only 2 custom characters available, so the X
    pixels_per_X_mesh_pnt = ULTRA_X_PIXELS_PER_CHAR;                        // size of the mesh point needs to fit within them independent
    suppress_x_offset = 1;                                                  // of where the starting pixel is located.
  }

  if (pixels_per_Y_mesh_pnt >= ULTRA_Y_PIXELS_PER_CHAR) {                   // There are only 2 custom characters available, so the Y
    pixels_per_Y_mesh_pnt = ULTRA_Y_PIXELS_PER_CHAR;                        // size of the mesh point needs to fit within them independent
    suppress_y_offset = 1;                                                  // of where the starting pixel is located.
  }


  x_map_pixels = pixels_per_X_mesh_pnt * GRID_MAX_POINTS_X;                 // now we have the right number of pixels to make both
  y_map_pixels = pixels_per_Y_mesh_pnt * GRID_MAX_POINTS_Y;                 // directions fit nicely

  right_edge = pixels_per_X_mesh_pnt * GRID_MAX_POINTS_X + 1;               // find location of right edge within the character cell
  bottom_line= pixels_per_Y_mesh_pnt * GRID_MAX_POINTS_Y + 1;               // find location of bottome line within the character cell

  n_rows = (bottom_line / ULTRA_Y_PIXELS_PER_CHAR) + 1;
  n_cols = (right_edge / ULTRA_X_PIXELS_PER_CHAR) + 1;

  for (i = 0; i < n_cols; i++) {
    lcd_setCursor(i, 0);
    lcd_print(0x00);                           // top line of the box
    lcd_setCursor(i, n_rows-1);
    lcd_print(0x01);                           // bottom line of the box
  }

  for (j = 0; j < n_rows; j++) {
    lcd_setCursor(0, j);
    lcd_print(0x02);                           // Left edge of the box
    lcd_setCursor(n_cols-1, j);
    lcd_print(0x03);                           // right edge of the box
  }
	  
  if (n_cols != ULTRA_COLUMNS_FOR_MESH_MAP) {
	  printf("n_cols mismatch with ULTRA_COLUMNS_FOR_MESH_MAP for (%d x %d) --> %d cols instead of %d\n", GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, n_cols, ULTRA_COLUMNS_FOR_MESH_MAP);
  }

  if (n_rows != ULTRA_ROWS_FOR_MESH_MAP) {
	  printf("Not able to use all rows of display for (%d x %d) --> %d rows instead of %d\n", GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, n_rows, ULTRA_ROWS_FOR_MESH_MAP);
  }

  //
  /* if the entire 4th row is not in use, do not put vertical bars all the way down to the bottom of the display */
  //

  k = pixels_per_Y_mesh_pnt * GRID_MAX_POINTS_Y + 2;
  l = ULTRA_Y_PIXELS_PER_CHAR * n_rows;
  if ( (k != l) && ((l-k)>=ULTRA_Y_PIXELS_PER_CHAR/2) ) {
    lcd_setCursor(0, n_rows-1);            // left edge of the box
    lcd_print(' ');                           
    lcd_setCursor(n_cols-1, n_rows-1);     // right edge of the box
    lcd_print(' ');      
  }

  CLEAR_CUSTOM_CHAR( &new_char );
  new_char.custom_char_bits[0] = (unsigned char) 0B11111;                // char #0 is used for the top line of the box
  createChar( 0, &new_char );

  CLEAR_CUSTOM_CHAR( &new_char );
  k = GRID_MAX_POINTS_Y * pixels_per_Y_mesh_pnt + 1;                     // row of pixels for the bottom box line
  l = k % ULTRA_Y_PIXELS_PER_CHAR;                                       // row within relivant character cell
  new_char.custom_char_bits[l] = (unsigned char) 0B11111;                // char #1 is used for the bottom line of the box
  createChar( 1, &new_char );

  CLEAR_CUSTOM_CHAR( &new_char );
  for (j = 0; j < ULTRA_Y_PIXELS_PER_CHAR; j++) 
    new_char.custom_char_bits[j] = (unsigned char) 0B10000;              // char #2 is used for the left edge of the box
  createChar(2, &new_char);

  CLEAR_CUSTOM_CHAR( &new_char );
  m = GRID_MAX_POINTS_X * pixels_per_X_mesh_pnt + 1;                     // column of pixels for the right box line
  n = m % ULTRA_X_PIXELS_PER_CHAR;                                       // column within relivant character cell
  i = ULTRA_X_PIXELS_PER_CHAR - 1 - n;                                   // column within relivant character cell (0 on the right)
  for (j = 0; j < ULTRA_Y_PIXELS_PER_CHAR; j++) 
    new_char.custom_char_bits[j] = (unsigned char) 0B00001 << i;         // char #3 is used for the right edge of the box
  createChar( 3, &new_char );

  printf("\n");
  printf("GRID_MAX_POINTS_X      :  %-4d  GRID_MAX_POINTS_Y      :  %-4d   ", GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y);
  printf("      Mesh_Point(%d,%d) \n", x, inverted_y);
  printf("ULTRA_X_PIXELS_PER_CHAR:  %-4d  ULTRA_Y_PIXELS_PER_CHAR:  %-4d \n", ULTRA_X_PIXELS_PER_CHAR, ULTRA_Y_PIXELS_PER_CHAR);
  printf("pixels_per_X_mesh_pnt:    %-4d  pixels_per_Y_mesh_pnt:    %-4d \n", pixels_per_X_mesh_pnt, pixels_per_Y_mesh_pnt);
  printf("    suppress_x_offset:    %-4d      suppress_y_offset:    %-4d \n", suppress_x_offset, suppress_y_offset);  
  printf("x_map_pixels:             %-4d  y_map_pixels:             %-4d \n", x_map_pixels, y_map_pixels);
  printf("\n");

  printf("Upper Left   : ");
  i = x*pixels_per_X_mesh_pnt - suppress_x_offset; 
  j = y*pixels_per_Y_mesh_pnt - suppress_y_offset;
  upper_left = pixel_location(i, j);

  printf("Lower Right  : ");
  k = (x+1)*pixels_per_X_mesh_pnt-1-suppress_x_offset;
  l = (y+1)*pixels_per_Y_mesh_pnt-1-suppress_y_offset;
  lower_right = pixel_location(k, l);

  printf("Bottom Corner: ");
  bottom_right_corner = pixel_location( x_map_pixels, y_map_pixels);
  printf("\n");


  if (GRID_MAX_POINTS_X == 7 && GRID_MAX_POINTS_Y == 5 && x == 2 && y == 1)   // break point on any mesh plot that doesn't look correct
	  printf("Break!\n");

  /* 
   * First, handle the simple case where everything is within a single character cell.
   * If part of the Mesh Plot is outside of this character cell, we will follow up
   * and deal with that next.
   */

  CLEAR_CUSTOM_CHAR( &new_char );
  for(j=upper_left.y_pixel_offset; j<upper_left.y_pixel_offset+pixels_per_Y_mesh_pnt; j++) {
	  if (j >= ULTRA_Y_PIXELS_PER_CHAR)
		  break;
    i=upper_left.x_pixel_mask;
    for(k=0; k<pixels_per_X_mesh_pnt; k++)  {
      new_char.custom_char_bits[j] |= i;
      i = i >> 1;
    }
  }

  add_edges_to_custom_char(&new_char, &upper_left, &lower_right, &bottom_right_corner, TOP_LEFT );
  createChar( 4, &new_char );

  lcd_setCursor(upper_left.column, upper_left.row);
  lcd_print(0x04);

  /* 
   * Next, check for two side by side character cells being used to display the Mesh Point
   * If found...  do the right hand character cell next.
   */
    if (upper_left.column+1 == lower_right.column ) {
      l = upper_left.x_pixel_offset;
      CLEAR_CUSTOM_CHAR( &new_char );
	  for (j = upper_left.y_pixel_offset; j < upper_left.y_pixel_offset + pixels_per_Y_mesh_pnt; j++) {
		if (j >= ULTRA_Y_PIXELS_PER_CHAR)
          break;
        i=0x01 << (ULTRA_X_PIXELS_PER_CHAR-1);                  // fill in the left side of the right character cell
        for(k=0; k<pixels_per_X_mesh_pnt-1-l; k++)  {
          new_char.custom_char_bits[j] |= i;
          i = i >> 1;
        }
      }
      add_edges_to_custom_char(&new_char, &upper_left, &lower_right, &bottom_right_corner, TOP_RIGHT );

      createChar( 5, &new_char );

      lcd_setCursor( lower_right.column, upper_left.row);
      lcd_print(0x05);
    }

  /* 
   * Next, check for two character cells stacked on top of each other being used to display the Mesh Point
   */
  if ( upper_left.row+1 == lower_right.row ) {    
      l = ULTRA_Y_PIXELS_PER_CHAR - upper_left.y_pixel_offset;        // number of pixel rows in top character cell
      k = pixels_per_Y_mesh_pnt - l;                                  // number of pixel rows in bottom character cell
      CLEAR_CUSTOM_CHAR(&new_char);
      for(j=0; j<k; j++) {
        i=upper_left.x_pixel_mask;
        for(m=0; m<pixels_per_X_mesh_pnt; m++)  {                     // fill in the top side of the bottom character cell
          new_char.custom_char_bits[j] |= i;
          i = i >> 1;
          if ( !i )
            break;
        }
      }
      add_edges_to_custom_char(&new_char, &upper_left, &lower_right, &bottom_right_corner, LOWER_LEFT );
      createChar(6, &new_char);

      lcd_setCursor( upper_left.column, lower_right.row);
      lcd_print(0x06);
    } 

  /* 
   * Next, check for a four character cells being used to display the Mesh Point.  If that is
   * what is here, we work to fill in the character cell that is down one and to the right one
   * from the upper_left character cell.
   */

  if (upper_left.column+1 == lower_right.column && upper_left.row+1 == lower_right.row ) {    
    printf("4-Cell Plot\n");
    l = ULTRA_Y_PIXELS_PER_CHAR - upper_left.y_pixel_offset;        // number of pixel rows in top character cell     
    k = pixels_per_Y_mesh_pnt - l;                                  // number of pixel rows in bottom character cell
    CLEAR_CUSTOM_CHAR(&new_char);
    for (j = 0; j<k; j++) {
      l = upper_left.x_pixel_offset;
      i = 0x01 << (ULTRA_X_PIXELS_PER_CHAR - 1);                    // fill in the left side of the right character cell               
      for (m = 0; m<pixels_per_X_mesh_pnt - 1 - l; m++) {           // fill in the top side of the bottom character cell
        new_char.custom_char_bits[j] |= i;
        i = i >> 1;
      }
    }
    add_edges_to_custom_char(&new_char, &upper_left, &lower_right, &bottom_right_corner, LOWER_RIGHT );
    createChar(7, &new_char);

    lcd_setCursor( lower_right.column, lower_right.row);
    lcd_print(0x07);
  }
  show_20x4_LCD();

  printf(" \n");
 return;
}

void add_edges_to_custom_char(struct custom_char *custom, struct coordinate *ul, struct coordinate *lr, struct coordinate *brc, int cell_location ) {
  int i, k;

     /*
     * Check if Top line of box needs to be filled in
     */
      if ( (ul->row == 0) && ((cell_location&TOP_LEFT) || (cell_location&TOP_RIGHT)))  {   // Only fill in the top line for the top character cells
          if (ul->column != brc->column )
            custom->custom_char_bits[0] = 0xff;     // do the full width of character cell if in middle
          else {
            for (i=brc->x_pixel_offset; i<ULTRA_X_PIXELS_PER_CHAR; i++) 
              custom->custom_char_bits[0] |= 0x01 << i;
          }
      }

    /*
     * Check if left line of box needs to be filled in 
     */
              if (ul->column == 0) {                          // Left column of characters on LCD Display
                if ( ul->row != brc->row )
                  k = ULTRA_Y_PIXELS_PER_CHAR;      // if it isn't the last row... do the full character cell
                else
                  k = brc->y_pixel_offset;
                for (i = 0; i < k; i++) 
                  custom->custom_char_bits[i] |= 0x01 << (ULTRA_X_PIXELS_PER_CHAR - 1);
              }

        /*
        * Check if bottom line of box needs to be filled in
        */
        if ( (ul->row==brc->row) || ((lr->row==brc->row) && ((cell_location&LOWER_LEFT) || (cell_location&LOWER_RIGHT))) ) {     // Bottom row of characters on LCD Display
                if ( lr->column != brc->column )
                  k = 0x01;                                  // if it isn't the last column... do the full character cell
                else
                  k = brc->y_pixel_offset;

                while (k < (0x01 << ULTRA_X_PIXELS_PER_CHAR) ) {
                  custom->custom_char_bits[brc->y_pixel_offset] |= k;
                  k = k << 1;
                }
        }

        /*
        * Check if right line of box needs to be filled in
        */

        if (lr->column == brc->column)  {     // nothing to do if the lower right part of the mesh pnt isn't in the same column as the box line
          if (  (ul->column == brc->column) ||
               ((lr->column == brc->column) && (cell_location&TOP_RIGHT)) ||
               ((lr->column == brc->column) && (cell_location&LOWER_RIGHT)) ) {   // This mesh point is in the same character cell as the right box line

            if (ul->row != brc->row)
              k = ULTRA_Y_PIXELS_PER_CHAR;      // if it isn't the last row... do the full character cell
            else
              k = brc->y_pixel_offset;
            for (i = 0; i < k; i++)
              custom->custom_char_bits[i] |= brc->x_pixel_mask;
          }
        }
}

struct coordinate pixel_location(int x, int y) {
  struct coordinate ret_val;
  int xp, yp, r, c;

  x++;  // +1 because there is a line on the left 
  y++;  // and a line at the top to make the box

  c = x / ULTRA_X_PIXELS_PER_CHAR;
  r = y / ULTRA_Y_PIXELS_PER_CHAR;

  ret_val.column = c;
  ret_val.row    = r;

  xp = x - c * ULTRA_X_PIXELS_PER_CHAR;   // get the pixel offsets into the character cell
  xp = ULTRA_X_PIXELS_PER_CHAR - 1 - xp;  // column within relivant character cell (0 on the right)
  yp = y - r * ULTRA_Y_PIXELS_PER_CHAR;

  ret_val.x_pixel_mask   = 0x01 << xp;
  ret_val.x_pixel_offset = xp;
  ret_val.y_pixel_offset = yp;

  printf("Pixel mapping:  (%02d,%02d) --->  Col:%02d  Row:%02d   x_pixel_mask=%s  y_pixel_offset=%d\n", x, y, c, r, to_binary_str(ret_val.x_pixel_mask), ret_val.y_pixel_offset);

  return ret_val;
}

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

Yup. In fact, this is the entire current character display code at the end of the file:

#if ENABLED(AUTO_BED_LEVELING_UBL)

  /**
   * These are just basic data for the 20x4 LCD work that
   * is coming up very soon.
   * Soon this will morph into a map code.
   */

  /**
  Possible map screens:

  16x2   |X000.00  Y000.00|
         |(00,00)  Z00.000|

  20x2   | X:000.00  Y:000.00 |
         | (00,00)   Z:00.000 |

  16x4   |+-------+(00,00)|
         ||       |X000.00|
         ||       |Y000.00|
         |+-------+Z00.000|

  20x4   | +-------+  (00,00) |
         | |       |  X:000.00|
         | |       |  Y:000.00|
         | +-------+  Z:00.000|
  */

  void lcd_set_ubl_map_plot_chars() {
    #if LCD_HEIGHT > 3
      const static byte _lcd_box_top[8] PROGMEM = {
        B11111,
        B00000,
        B00000,
        B00000,
        B00000,
        B00000,
        B00000,
        B00000
      };
      const static byte _lcd_box_bottom[8] PROGMEM = {
        B00000,
        B00000,
        B00000,
        B00000,
        B00000,
        B00000,
        B00000,
        B11111
      };
      createChar_P(LCD_UBL_BOXTOP_CHAR, _lcd_box_top);
      createChar_P(LCD_UBL_BOXBOT_CHAR, _lcd_box_bottom);
    #endif
  }

  void lcd_implementation_ubl_plot(const uint8_t x_plot, const uint8_t y_plot) {

    #if LCD_WIDTH >= 20
      #define _LCD_W_POS 12
      #define _PLOT_X 1
      #define _MAP_X 3
      #define _LABEL(C,X,Y) lcd.setCursor(X, Y); lcd.print(C)
      #define _XLABEL(X,Y) _LABEL("X:",X,Y)
      #define _YLABEL(X,Y) _LABEL("Y:",X,Y)
      #define _ZLABEL(X,Y) _LABEL("Z:",X,Y)
    #else
      #define _LCD_W_POS 8
      #define _PLOT_X 0
      #define _MAP_X 1
      #define _LABEL(X,Y,C) lcd.setCursor(X, Y); lcd.write(C)
      #define _XLABEL(X,Y) _LABEL('X',X,Y)
      #define _YLABEL(X,Y) _LABEL('Y',X,Y)
      #define _ZLABEL(X,Y) _LABEL('Z',X,Y)
    #endif

    #if LCD_HEIGHT <= 3   // 16x2 or 20x2 display

      /**
       * Show X and Y positions
       */
      _XLABEL(_PLOT_X, 0);
      lcd.print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]))));

      _YLABEL(_LCD_W_POS, 0);
      lcd.print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));

      lcd.setCursor(_PLOT_X, 0);

    #else                 // 16x4 or 20x4 display

      /**
       * Draw the Mesh Map Box
       */
      uint8_t m;
      lcd.setCursor(_MAP_X, 0); for (m = 0; m < 5; m++) lcd.write(LCD_UBL_BOXTOP_CHAR); // Top
      lcd.setCursor(_MAP_X, 3); for (m = 0; m < 5; m++) lcd.write(LCD_UBL_BOXBOT_CHAR); // Bottom
      for (m = 0; m <= 3; m++) {
        lcd.setCursor(2, m); lcd.write('|'); // Left
        lcd.setCursor(8, m); lcd.write('|'); // Right
      }

      lcd.setCursor(_LCD_W_POS, 0);

    #endif

    /**
     * Print plot position
     */
    lcd.write('(');
    lcd.print(x_plot);
    lcd.write(',');
    lcd.print(y_plot);
    lcd.write(')');

    #if LCD_HEIGHT <= 3   // 16x2 or 20x2 display

      /**
       * Print Z values
       */
      _ZLABEL(_LCD_W_POS, 1);
      if (!isnan(ubl.z_values[x_plot][y_plot]))
        lcd.print(ftostr43sign(ubl.z_values[x_plot][y_plot]));
      else
        lcd_printPGM(PSTR(" -----"));

    #else                 // 16x4 or 20x4 display

      /**
       * Show all values at right of screen
       */
      _XLABEL(_LCD_W_POS, 1);
      lcd.print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]))));
      _YLABEL(_LCD_W_POS, 2);
      lcd.print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));

      /**
       * Show the location value
       */
      _ZLABEL(_LCD_W_POS, 3);
      if (!isnan(ubl.z_values[x_plot][y_plot]))
        lcd.print(ftostr43sign(ubl.z_values[x_plot][y_plot]));
      else
        lcd_printPGM(PSTR(" -----"));

    #endif // LCD_HEIGHT > 3
  }

#endif // AUTO_BED_LEVELING_UBL

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

I know you will be replacing that. That's okay.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

if lcd_set_ubl_map_plot_chars() is not needed, then it can be removed from ultralcd.cpp here:

    void _lcd_ubl_map_homing() {
      defer_return_to_status = true;
      ubl_lcd_map_control = true; // Return to the map screen
      #if DISABLED(DOGLCD)
        lcd_set_ubl_map_plot_chars();
      #endif
      if (lcdDrawUpdate) lcd_implementation_drawmenu_static(LCD_HEIGHT < 3 ? 0 : (LCD_HEIGHT > 4 ? 2 : 1), PSTR(MSG_LEVEL_BED_HOMING));
      lcdDrawUpdate = LCDVIEW_CALL_NO_REDRAW;
      if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
        lcd_goto_screen(_lcd_ubl_output_map_lcd);
    }

@Roxy-3D
Copy link

Roxy-3D commented Jul 5, 2017

Do you want to try hooking it in? It is going to be a day or two before I can get to it... I'll be able to answer any questions if you run into trouble. The code isn't too hard to understand.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

I can.

@Tannoo
Copy link
Owner Author

Tannoo commented Jul 5, 2017

email it to me.

@Tannoo Tannoo closed this as completed Jul 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants