/** * Although this is undocumented, the ST7920 allows the character * data buffer (DDRAM) to be used in conjunction with the graphics * bitmap buffer (CGRAM). The contents of the graphics buffer is * XORed with the data from the character generator. This allows * us to make the progess bar out of graphical data (the bar) and * text data (the percentage). */ void ST7920_Lite_Status_Screen::draw_progress_bar(const uint8_t value) { #if HOTENDS == 1 // If we have only one extruder, draw a long progress bar on the third line constexpr uint8_t top = 1, // Top in pixels bottom = 13, // Bottom in pixels left = 12, // Left edge, in 16-bit words width = 4; // Width of progress bar, in 16-bit words #else constexpr uint8_t top = 16 + 1, bottom = 16 + 13, left = 5, width = 3; #endif const uint8_t char_pcnt = 100 / width; // How many percent does each 16-bit word represent? // Draw the progress bar as a bitmap in CGRAM for (uint8_t y = top; y <= bottom; y++) { set_gdram_address(left, y); begin_data(); for (uint8_t x = 0; x < width; x++) { uint16_t gfx_word = 0x0000; if ((x + 1) * char_pcnt <= value) gfx_word = 0xFFFF; // Draw completely filled bytes else if ((x * char_pcnt) < value) gfx_word = int(0x8000) >> (value % char_pcnt) * 16 / char_pcnt; // Draw partially filled bytes // Draw the frame around the progress bar if (y == top || y == bottom) gfx_word = 0xFFFF; // Draw top/bottom border else if (x == width - 1) gfx_word |= 0x0001; // Draw right border else if (x == 0) gfx_word |= 0x8000; // Draw left border write_word(gfx_word); } } // Draw the percentage as text in DDRAM #if HOTENDS == 1 set_ddram_address(DDRAM_LINE_3 + 4); begin_data(); write_byte(' '); #else set_ddram_address(DDRAM_LINE_2 + left); begin_data(); #endif // Draw centered if (value > 9) { write_number(value, 4); write_str_P(PSTR("% ")); } else { write_number(value, 3); write_str_P(PSTR("% ")); } }
void ST7920_Lite_Status_Screen::draw_print_time(const duration_t &elapsed) { #if HOTENDS == 1 set_ddram_address(DDRAM_LINE_3); #else set_ddram_address(DDRAM_LINE_3 + 5); #endif char str[7]; str[elapsed.toDigital(str)] = ' '; begin_data(); write_str(str, 6); }
void ST7920_Lite_Status_Screen::draw_status_message() { const char *str = ui.status_message; set_ddram_address(DDRAM_LINE_4); begin_data(); #if ENABLED(STATUS_MESSAGE_SCROLLING) uint8_t slen = utf8_strlen(str); if (slen <= LCD_WIDTH) { // String fits the LCD, so just print it write_str(str); for (; slen < LCD_WIDTH; ++slen) write_byte(' '); } else { // String is larger than the available space in screen. // Get a pointer to the next valid UTF8 character const char *stat = str + ui.status_scroll_offset; // Get the string remaining length const uint8_t rlen = utf8_strlen(stat); // If we have enough characters to display if (rlen >= LCD_WIDTH) { // The remaining string fills the screen - Print it write_str(stat, LCD_WIDTH); } else { // The remaining string does not completely fill the screen write_str(stat); // The string leaves space uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters write_byte('.'); // Always at 1+ spaces left, draw a dot if (--chars) { // Draw a second dot if there's space write_byte('.'); if (--chars) write_str(str, chars); // Print a second copy of the message } } // Adjust by complete UTF8 characters if (ui.status_scroll_offset < slen) { ui.status_scroll_offset++; while (!START_OF_UTF8_CHAR(str[ui.status_scroll_offset])) ui.status_scroll_offset++; } else ui.status_scroll_offset = 0; } #else uint8_t slen = utf8_strlen(str); write_str(str, LCD_WIDTH); for (; slen < LCD_WIDTH; ++slen) write_byte(' '); #endif }
void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint16_t percentage) { // We only have enough room for the feedrate when // we have one extruder #if HOTENDS == 1 set_ddram_address(DDRAM_LINE_2 + 6); begin_data(); write_number(percentage, 3); write_byte('%'); #endif }
void ST7920_Lite_Status_Screen::draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange) { switch (line) { case 0: set_ddram_address(DDRAM_LINE_1 + 1); break; case 1: set_ddram_address(DDRAM_LINE_2 + 1); break; case 2: set_ddram_address(DDRAM_LINE_3 + 1); break; case 3: set_ddram_address(DDRAM_LINE_3 + 1); break; } begin_data(); write_number(temp); if (showTarget) { write_byte('\x1A'); write_number(target); }; if (targetStateChange) { if (!showTarget) write_str_P(PSTR(" ")); draw_degree_symbol(5, line, !showTarget); draw_degree_symbol(9, line, showTarget); } }
void ST7920_Lite_Status_Screen::draw_heat_icon(const bool whichIcon, const bool heating) { set_ddram_address( #if HOTENDS == 1 DDRAM_LINE_2 #else DDRAM_LINE_3 #endif ); begin_data(); if (heating) write_word(whichIcon ? CGRAM_ICON_1_WORD : CGRAM_ICON_2_WORD); else { write_byte(' '); write_byte(' '); } }
void ST7920_Lite_Status_Screen::draw_position(const float x, const float y, const float z, bool position_known) { char str[7]; set_ddram_address(DDRAM_LINE_4); begin_data(); // If position is unknown, flash the labels. const unsigned char alt_label = position_known ? 0 : (ui.get_blink() ? ' ' : 0); dtostrf(x, -4, 0, str); write_byte(alt_label ? alt_label : 'X'); write_str(str, 4); dtostrf(y, -4, 0, str); write_byte(alt_label ? alt_label : 'Y'); write_str(str, 4); dtostrf(z, -5, 1, str); write_byte(alt_label ? alt_label : 'Z'); write_str(str, 5); }
void char_write(char mychar) { chars_written++; if ((chars_written==17)||(mychar=='\n')) { if (line_num==1) { set_ddram_address(0x40); line_num = 2; chars_written = 0; } else if (line_num==2) { lcd_init(); } } if (mychar!='\n') data_write((uint8_t)mychar); }
void ST7920_Lite_Status_Screen::draw_fan_speed(const uint8_t value) { set_ddram_address(DDRAM_LINE_1 + 6); begin_data(); write_number(value, 3); write_byte('%'); }
void ST7920_Lite_Status_Screen::draw_fan_icon(const bool whichIcon) { set_ddram_address(DDRAM_LINE_1 + 5); begin_data(); write_word(whichIcon ? CGRAM_ICON_3_WORD : CGRAM_ICON_4_WORD); }
/* This fills the entire text buffer with spaces */ void ST7920_Lite_Status_Screen::clear_ddram() { set_ddram_address(DDRAM_LINE_1); begin_data(); for (uint8_t i = 64; i--;) write_byte(' '); }
int main(int argc, char **argv) { int check_busy = 0; if (argc < 3) usage(); //init spi oled init_spi_oled(argv[1]); argc-=2; argv+=2; while (argc >= 1) { const char *cmd = argv[0]; int args = 0; if (strcmp(cmd, "-B") == 0) { check_busy = 0; args = 1; check_busy_flag3(atoi(argv[1])); } if (strcmp(cmd, "-b") == 0) check_busy = 1; if (check_busy) check_busy_flag(); if (strcmp(cmd, "-f") == 0) { select_font(atoi(argv[1])); args = 1; } if (strcmp(cmd, "-e") == 0) { entry_mode_set(atoi(argv[1]), atoi(argv[2])); args = 2; } if (strcmp(cmd, "-m") == 0) { display_mode(atoi(argv[1]), atoi(argv[2]), atoi(argv[3])); args = 3; } if (strcmp(cmd, "-c") == 0) clear_display(); if (strcmp(cmd, "-g") == 0) { set_ddram_address(atoi(argv[1]) * 0x40 + atoi(argv[2])); args = 2; } if (strcmp(cmd, "-a") == 0) { set_ddram_address(strtoul(argv[1], NULL, 0)); args = 1; } if (strcmp(cmd, "-A") == 0) { set_cgram_address(strtoul(argv[1], NULL, 0)); args = 1; } if (strcmp(cmd, "-w") == 0) { write_data(strtoul(argv[1], NULL, 0)); args = 1; } if (strcmp(cmd, "-h") == 0) return_home(); if (strcmp(cmd, "-C") == 0) { shift_cursor(*argv[1] == 'r'); args = 1; } if (strcmp(cmd, "-S") == 0) { shift_display(*argv[1] == 'r'); args = 1; } if (strcmp(cmd, "-t") == 0) { write_str(argv[1]); args = 1; } if (*cmd != '-') write_str(cmd); check_busy = 1; argc -= 1 + args; argv += 1 + args; } }