Corrections ()

20x4 map integration.    Also some minor changes to the UBL Menu layout.     Both 20x4 LCD's and Graphical LCD panels should have similar functionality now.
This commit is contained in:
Tannoo 2017-07-07 10:05:08 -06:00 committed by Roxy-3D
parent 7fc31a7940
commit aaacef9441
6 changed files with 484 additions and 95 deletions

View File

@ -273,12 +273,6 @@
#define LCD_FEEDRATE_CHAR 0x06
#define LCD_CLOCK_CHAR 0x07
#define LCD_STR_ARROW_RIGHT ">" /* from the default character set */
#if ENABLED(AUTO_BED_LEVELING_UBL)
#define LCD_UBL_BOXTOP_CHAR 0x01
#define LCD_UBL_BOXBOT_CHAR 0x02
#endif
#endif
/**

View File

@ -208,6 +208,9 @@
#ifndef MSG_UBL_CUSTOM_HOTEND_TEMP
#define MSG_UBL_CUSTOM_HOTEND_TEMP MSG_UBL_SET_HOTEND_TEMP
#endif
#ifndef MSG_UBL_MESH_EDIT
#define MSG_UBL_MESH_EDIT _UxGT("Mesh Edit")
#endif
#ifndef MSG_UBL_EDIT_CUSTOM_MESH
#define MSG_UBL_EDIT_CUSTOM_MESH _UxGT("Edit Custom Mesh")
#endif

View File

@ -62,6 +62,10 @@ Stepper stepper; // Singleton
// public:
#if ENABLED(AUTO_BED_LEVELING_UBL)
extern bool ubl_lcd_map_control;
#endif
block_t* Stepper::current_block = NULL; // A pointer to the block currently being traced
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
@ -1281,7 +1285,12 @@ void Stepper::finish_and_disable() {
}
void Stepper::quick_stop() {
cleaning_buffer_counter = 5000;
#if ENABLED(AUTO_BED_LEVELING_UBL)
if (!ubl_lcd_map_control)
cleaning_buffer_counter = 5000;
#else
cleaning_buffer_counter = 5000;
#endif
DISABLE_STEPPER_DRIVER_INTERRUPT();
while (planner.blocks_queued()) planner.discard_current_block();
current_block = NULL;

View File

@ -1533,7 +1533,6 @@
while (ubl_lcd_clicked()) { // debounce and watch for abort
idle();
if (ELAPSED(millis(), nxt)) {
ubl_lcd_map_control = false;
lcd_return_to_status();
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
LCD_MESSAGEPGM(MSG_EDITING_STOPPED);

View File

@ -467,6 +467,9 @@ uint16_t max_display_update_time = 0;
encoderPosition = encoder;
if (screen == lcd_status_screen) {
defer_return_to_status = false;
#if ENABLED(AUTO_BED_LEVELING_UBL)
ubl_lcd_map_control = false;
#endif
screen_history_depth = 0;
}
lcd_implementation_clear();
@ -2149,14 +2152,11 @@ void kill_screen(const char* lcd_msg) {
void _lcd_ubl_map_homing() {
defer_return_to_status = true;
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL);
ubl_lcd_map_control = true; // Return to the map screen
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]) {
#if DISABLED(DOGLCD)
lcd_set_ubl_map_plot_chars();
#endif
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
lcd_goto_screen(_lcd_ubl_output_map_lcd);
}
}
/**
@ -2232,9 +2232,12 @@ void kill_screen(const char* lcd_msg) {
ubl_map_move_to_xy(); // Move to current location
if (planner.movesplanned() > 1) { // if the nozzle is moving, cancel the move. There is a new location
quickstop_stepper();
if (planner.movesplanned() > 1) { // if the nozzle is moving, cancel the move. There is a new location
stepper.quick_stop();
set_current_from_steppers_for_axis(ALL_AXES);
sync_plan_position();
ubl_map_move_to_xy(); // Move to new location
refresh_cmd_timeout();
}
}
}
@ -2243,9 +2246,10 @@ void kill_screen(const char* lcd_msg) {
* UBL Homing before LCD map
*/
void _lcd_ubl_output_map_lcd_cmd() {
ubl_lcd_map_control = true; // Return to the map screen (and don't restore the character set)
if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]))
if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) {
axis_homed[X_AXIS] = axis_homed[Y_AXIS] = axis_homed[Z_AXIS] = false;
enqueue_and_echo_commands_P(PSTR("G28"));
}
lcd_goto_screen(_lcd_ubl_map_homing);
}
@ -2281,6 +2285,7 @@ void kill_screen(const char* lcd_msg) {
START_MENU();
MENU_BACK(MSG_UBL_LEVEL_BED);
MENU_ITEM(submenu, MSG_UBL_BUILD_MESH_MENU, _lcd_ubl_build_mesh);
MENU_ITEM(gcode, MSG_UBL_MANUAL_MESH, PSTR("G29 I999\nG29 P2 B T0"));
MENU_ITEM(submenu, MSG_UBL_VALIDATE_MESH_MENU, _lcd_ubl_validate_mesh);
MENU_ITEM(submenu, MSG_UBL_EDIT_MESH_MENU, _lcd_ubl_edit_mesh);
MENU_ITEM(submenu, MSG_UBL_MESH_LEVELING, _lcd_ubl_mesh_leveling);
@ -2329,10 +2334,10 @@ void kill_screen(const char* lcd_msg) {
void _lcd_ubl_level_bed() {
START_MENU();
MENU_BACK(MSG_PREPARE);
MENU_ITEM(gcode, MSG_UBL_MANUAL_MESH, PSTR("G29 I999\nG29 P2 B T0"));
MENU_ITEM(gcode, MSG_UBL_ACTIVATE_MESH, PSTR("G29 A"));
MENU_ITEM(gcode, MSG_UBL_DEACTIVATE_MESH, PSTR("G29 D"));
MENU_ITEM(submenu, MSG_UBL_STEP_BY_STEP_MENU, _lcd_ubl_step_by_step);
MENU_ITEM(function, MSG_UBL_MESH_EDIT, _lcd_ubl_output_map_lcd_cmd);
MENU_ITEM(submenu, MSG_UBL_STORAGE_MESH_MENU, _lcd_ubl_storage_mesh);
MENU_ITEM(submenu, MSG_UBL_OUTPUT_MAP, _lcd_ubl_output_map);
MENU_ITEM(submenu, MSG_UBL_TOOLS, _lcd_ubl_tools_menu);

View File

@ -33,6 +33,20 @@
#if ENABLED(AUTO_BED_LEVELING_UBL)
#include "ubl.h"
#if ENABLED(ULTIPANEL)
#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 N_USER_CHARS 8
#define TOP_LEFT 0x01
#define TOP_RIGHT 0x02
#define LOWER_LEFT 0x04
#define LOWER_RIGHT 0x08
#endif
#endif
extern volatile uint8_t buttons; //an extended version of the last checked buttons in a bit array.
@ -1078,68 +1092,68 @@ static void lcd_implementation_status_screen() {
lcd.setBacklight(leds);
ledsprev = leds;
}
}
#endif // LCD_HAS_STATUS_INDICATORS
#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:
/**
Possible map screens:
16x2 |X000.00 Y000.00|
|(00,00) Z00.000|
16x2 |X000.00 Y000.00|
|(00,00) Z00.000|
20x2 | X:000.00 Y:000.00 |
| (00,00) Z:00.000 |
20x2 | X:000.00 Y:000.00 |
| (00,00) Z:00.000 |
16x4 |+-------+(00,00)|
|| |X000.00|
|| |Y000.00|
|+-------+Z00.000|
16x4 |+-------+(00,00)|
|| |X000.00|
|| |Y000.00|
|+-------+Z00.000|
20x4 | +-------+ (00,00) |
| | | X:000.00|
| | | Y:000.00|
| +-------+ Z:00.000|
*/
20x4 | +-------+ (00,00) |
| | | X:000.00|
| | | Y:000.00|
| +-------+ Z:00.000|
struct custom_char {
uint8_t custom_char_bits[ULTRA_Y_PIXELS_PER_CHAR];
};
struct coordinate pixel_location(uint8_t x, uint8_t y);
struct coordinate {
uint8_t column;
uint8_t row;
uint8_t y_pixel_offset;
uint8_t x_pixel_offset;
uint8_t x_pixel_mask;
};
void add_edges_to_custom_char(struct custom_char *custom, struct coordinate *ul, struct coordinate *lr, struct coordinate *brc, uint8_t cell_location);
extern custom_char user_defined_chars[N_USER_CHARS];
inline static void CLEAR_CUSTOM_CHAR(struct custom_char *cc) { uint8_t j; for (j = 0; j < ULTRA_Y_PIXELS_PER_CHAR; j++) cc->custom_char_bits[j] = 0; }
/*
void dump_custom_char(char *title, struct custom_char *c) { // This debug routine should be deleted by anybody that sees it. It doesn't belong here
int i, j; // But I'm leaving it for now until we know the 20x4 Radar Map is working right.
SERIAL_PROTOCOLLN(title); // We will need it again if any funny lines show up on the mesh points.
for(j=0; j<8; j++) {
for(i=7; i>=0; i--) {
if (c->custom_char_bits[j] & (0x01 << i))
SERIAL_PROTOCOL("1");
else
SERIAL_PROTOCOL("0");
}
SERIAL_PROTOCOL("\n");
}
SERIAL_PROTOCOL("\n");
}
*/
void lcd_set_ubl_map_plot_chars() {
#if LCD_HEIGHT > 3
//#include "_ubl_lcd_map_characters.h"
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) {
void lcd_implementation_ubl_plot(uint8_t x, uint8_t inverted_y) {
#if LCD_WIDTH >= 20
#define _LCD_W_POS 12
@ -1165,38 +1179,233 @@ static void lcd_implementation_status_screen() {
* 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]))));
lcd.print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x]))));
_YLABEL(_LCD_W_POS, 0);
lcd.print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));
lcd.print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[inverted_y]))));
lcd.setCursor(_PLOT_X, 0);
#else // 16x4 or 20x4 display
#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
struct coordinate upper_left, lower_right, bottom_right_corner;
struct custom_char new_char;
uint8_t i, j, k, l, m, n, n_rows, n_cols, y;
uint8_t bottom_line, right_edge;
uint8_t x_map_pixels, y_map_pixels;
uint8_t pixels_per_X_mesh_pnt, pixels_per_Y_mesh_pnt;
uint8_t 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;
lcd_implementation_clear();
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.
}
lcd.setCursor(_LCD_W_POS, 0);
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((char) 0x00); // top line of the box
lcd.setCursor(i, n_rows-1);
lcd.write(0x01); // bottom line of the box
}
for (j = 0; j < n_rows; j++) {
lcd.setCursor(0, j);
lcd.write(0x02); // Left edge of the box
lcd.setCursor(n_cols-1, j);
lcd.write(0x03); // right edge of the box
}
//
/* 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.write(' ');
lcd.setCursor(n_cols-1, n_rows-1); // right edge of the box
lcd.write(' ');
}
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
lcd.createChar(0, (uint8_t *) &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
lcd.createChar(1, (uint8_t *) &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
lcd.createChar(2, (uint8_t *) &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
lcd.createChar(3, (uint8_t *) &new_char);
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);
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);
bottom_right_corner = pixel_location(x_map_pixels, y_map_pixels);
/*
* 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.
*/
//dump_custom_char("at entry:", &new_char);
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;
}
}
//dump_custom_char("after loops:", &new_char);
add_edges_to_custom_char(&new_char, &upper_left, &lower_right, &bottom_right_corner, TOP_LEFT);
//dump_custom_char("after add edges", &new_char);
lcd.createChar(4, (uint8_t *) &new_char);
lcd.setCursor(upper_left.column, upper_left.row);
lcd.write(0x04);
//dump_custom_char("after lcd update:", &new_char);
/*
* 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);
lcd.createChar(5, (uint8_t *) &new_char);
lcd.setCursor(lower_right.column, upper_left.row);
lcd.write(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);
lcd.createChar(6, (uint8_t *) &new_char);
lcd.setCursor(upper_left.column, lower_right.row);
lcd.write(0x06);
}
/*
* Next, check for 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) {
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);
lcd.createChar(7, (uint8_t *) &new_char);
lcd.setCursor(lower_right.column, lower_right.row);
lcd.write(0x07);
}
#endif
/**
* Print plot position
*/
lcd.write('(');
lcd.print(x_plot);
lcd.write(',');
lcd.print(y_plot);
lcd.write(')');
/**
* Print plot position
*/
lcd.setCursor(_LCD_W_POS, 0);
lcd.write('(');
lcd.print(x);
lcd.write(',');
lcd.print(inverted_y);
lcd.write(')');
#if LCD_HEIGHT <= 3 // 16x2 or 20x2 display
@ -1204,8 +1413,8 @@ static void lcd_implementation_status_screen() {
* 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]));
if (!isnan(ubl.z_values[x][inverted_y]))
lcd.print(ftostr43sign(ubl.z_values[x][inverted_y]));
else
lcd_printPGM(PSTR(" -----"));
@ -1215,20 +1424,190 @@ static void lcd_implementation_status_screen() {
* 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]))));
lcd.print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x]))));
_YLABEL(_LCD_W_POS, 2);
lcd.print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));
lcd.print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[inverted_y]))));
/**
* 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]));
if (!isnan(ubl.z_values[x][inverted_y]))
lcd.print(ftostr43sign(ubl.z_values[x][inverted_y]));
else
lcd_printPGM(PSTR(" -----"));
#endif // LCD_HEIGHT > 3
return;
}
void add_edges_to_custom_char(struct custom_char *custom, struct coordinate *ul, struct coordinate *lr, struct coordinate *brc, unsigned char cell_location) {
unsigned char i, k;
int n_rows, n_cols;
n_rows = lr->row - ul->row + 1;
n_cols = lr->column - ul->column + 1;
/*
* 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 (n_cols == 1) {
if (ul->column != brc->column)
custom->custom_char_bits[0] = 0xff; // single column in middle
else {
for (i = brc->x_pixel_offset; i<ULTRA_X_PIXELS_PER_CHAR; i++) // single column on right side
custom->custom_char_bits[0] |= 0x01 << i;
}
}
else {
if (cell_location & TOP_LEFT)
custom->custom_char_bits[0] = 0xff; // multiple column in the middle
else
if (lr->column != brc->column)
custom->custom_char_bits[0] = 0xff; // multiple column with right cell 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 ((cell_location & TOP_LEFT) || (cell_location & LOWER_LEFT)) {
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
*/
// Single row of mesh plot cells
if ((n_rows==1) /* && ((cell_location == TOP_LEFT) || (cell_location==TOP_RIGHT)) */) {
if (ul->row == brc->row) {
if (n_cols == 1) { // single row, single column case
if (ul->column != brc->column)
k = 0x01;
else
k = brc->x_pixel_mask;
} else {
if (cell_location & TOP_RIGHT) { // single row, multiple column case
if(lr->column != brc->column)
k = 0x01;
else
k = brc->x_pixel_mask;
} else // single row, left of multiple columns
k = 0x01;
}
while (k < (0x01 << ULTRA_X_PIXELS_PER_CHAR)) {
custom->custom_char_bits[brc->y_pixel_offset] |= k;
k = k << 1;
}
}
}
// Double row of characters on LCD Display
// And this is a bottom custom character
if ((n_rows==2) && ((cell_location == LOWER_LEFT) || (cell_location==LOWER_RIGHT))) {
if (lr->row == brc->row) {
if (n_cols == 1) { // double row, single column case
if (ul->column != brc->column)
k = 0x01;
else
k = brc->x_pixel_mask;
} else {
if (cell_location & LOWER_RIGHT) { // double row, multiple column case
if(lr->column != brc->column)
k = 0x01;
else
k = brc->x_pixel_mask;
} else // double row, left of multiple columns
k = 0x01;
}
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;
return ret_val;
}
struct coordinate pixel_location(uint8_t x, uint8_t y) {
struct coordinate ret_val;
uint8_t 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;
return ret_val;
}
#endif // AUTO_BED_LEVELING_UBL