diff --git a/Lib/delay.c b/Lib/delay.c index 1f1d5aff5..a4c1bff2d 100644 --- a/Lib/delay.c +++ b/Lib/delay.c @@ -74,4 +74,3 @@ void delay(uint32_t ms) yield(); } } - diff --git a/Lib/delay.h b/Lib/delay.h index 19f042588..db738f4a6 100644 --- a/Lib/delay.h +++ b/Lib/delay.h @@ -34,6 +34,7 @@ // ----- System Includes ----- #include +#include "mk20dx.h" @@ -56,6 +57,11 @@ static inline uint32_t millis(void) return systick_millis_count; // single aligned 32 bit is atomic; } +static inline uint32_t microsToTicks(uint32_t) __attribute__((always_inline, unused)); +static inline uint32_t microsToTicks(uint32_t usec) +{ + return usec * (F_CPU / 1000000); +} static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); static inline void delayMicroseconds(uint32_t usec) @@ -84,3 +90,32 @@ uint32_t micros(void); void delay(uint32_t ms); +static inline uint8_t isTicksPassed(uint32_t, uint32_t, uint32_t) __attribute__((always_inline, unused)); +static inline uint8_t isTicksPassed(uint32_t startmillis, uint32_t startticks, uint32_t ticks) +{ + // the milliseconds must be gotten before the ticks. + uint32_t currentmillis = systick_millis_count; + uint32_t currentticks = SYST_CVR; + if (currentmillis > startmillis + 1) { + return 1; + } + if (currentmillis == startmillis + 1) { + currentticks += (F_CPU / 1000); + } + else if (currentticks < startmillis) { + // the microseconds is reset after getting the ticks. + currentticks += (F_CPU / 1000); + } + if (startticks + ticks < currentticks) { + return 1; + } + else{ + return 0; + } +} + +static inline uint32_t ticks(void) __attribute__((always_inline, unused)); +static inline uint32_t ticks(void) +{ + return SYST_CVR; +} diff --git a/Scan/STLcd/4x6FontLicense b/Scan/STLcd/4x6FontLicense new file mode 100644 index 000000000..c6cbef1a2 --- /dev/null +++ b/Scan/STLcd/4x6FontLicense @@ -0,0 +1,27 @@ +** Copyright 1999 Brian J. Swetland +** Copyright 1999 Vassilii Khachaturov +** Portions (of vt100.c/vt100.h) copyright Dan Marks +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions, and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions, and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the authors may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Scan/STLcd/4x6font.bmp b/Scan/STLcd/4x6font.bmp new file mode 100755 index 000000000..39cebb6e9 Binary files /dev/null and b/Scan/STLcd/4x6font.bmp differ diff --git a/Scan/STLcd/bitmapfont2Struct.py b/Scan/STLcd/bitmapfont2Struct.py new file mode 100755 index 000000000..089bbd5eb --- /dev/null +++ b/Scan/STLcd/bitmapfont2Struct.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2015 by Jacob Alexander +# Copyright (C) 2016 by Cui Yuting +# +# This file is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this file. If not, see . + +# Imports +import sys + +from array import * +from PIL import Image # Use pillow instead of PIL, it works with Python 3 + +class Bitmap_Size: + def __init__( self, height=0, width=0, size=0, x_ppem=0, y_ppem=0): + self.height = height + self.width = width + self.size = size + self.x_ppem = x_ppem + self.y_ppem = y_ppem + +# Convenience class to deal with converting images to a C array +class STLcdFont: + # Some constants for the LCD Driver + array('B') + + def __init__( self, glyph_width, glyph_height, num_glyphs ): + self.glyph_height = glyph_height + self.glyph_width = glyph_width + self.glyph_size = (glyph_height + 7) // 8 * glyph_width + self.num_fixed_sizes = 1 + self.availible_sizes = [ Bitmap_Size( self.glyph_height, self.glyph_width ) ] + self.num_glyphs = num_glyphs + self.glyph_data = [] + for index in range( 0, self.num_glyphs ): + self.glyph_data.append( array( 'B', [0] * self.glyph_size ) ) + + def setpixel( self, index, x, y ): + newy = self.glyph_height - y - 1 + # Calculate which byte + byte = newy // 8 * glyph_width + x + + # Calculate which bit + bit = newy % 8 + + # Set pixel bit + self.glyph_data[ index ][ byte ] |= (1 << bit) + + def renderglyph( self, index, flags=0 ): + return self.glyph_data[ index ] + + def getarray( self ): + struct = "{\n" + + for glyph in self.glyph_data: + for elem in glyph: + struct += "0x{0:02x}, ".format( elem ) + struct += "\n}" + + return struct + +filename = sys.argv[1] +glyph_width = int( sys.argv[2] ) +glyph_height = int( sys.argv[3] ) +bitmap_spacing = 0 +bitmap_linespacing = 0 +if ( len( sys.argv ) >= 6 ): + bitmap_spacing = int( sys.argv[4] ) + bitmap_linespacing = int( sys.argv[5] ) +num_glyphs = 128 # ASCII +if filename is None: + print( "You must specify a bitmap filename. Try './bitmapfont2Struct.py font.bmp 4 6 0 0'" ) + sys.exit( 1 ) +output_image = STLcdFont( glyph_width, glyph_height, num_glyphs ) + + + +# Load the input filename and convert to black & white +try: + input_image = Image.open( filename ).convert('1') +except: + print( "Unable to load image '{0}'".format( filename ) ) + +input_width, input_height = input_image.size +columns = ( input_width - glyph_width ) // ( glyph_width + bitmap_spacing ) + 1 +rows = ( input_width - glyph_height ) // ( glyph_height + bitmap_linespacing ) + 1 + +# Iterate over all of the pixels +# Also prepare the debug view of the image (disp_test) +disp_test = "+" + "-" * input_width + "+\n" +glyph_index = 0 +for y in range( 0, input_height ): + row = y // ( glyph_height + bitmap_linespacing ) + if row >= rows: + break + if y % ( glyph_height + bitmap_linespacing ) >= glyph_height: + # empty + continue + disp_test += "|" + for x in range( 0, input_width ): + column = x // ( glyph_width + bitmap_spacing ) + if x % ( glyph_width + bitmap_spacing ) >= glyph_width: + continue + glyph_index = row * columns + column + if column >= columns or glyph_index >= num_glyphs: + disp_test += " " + else: + # Use image value to determine pixel + try: + if input_image.getpixel( (x, y) ) == 0: + disp_test += "*" + output_image.setpixel( glyph_index, + x % ( glyph_width + bitmap_spacing ), + y % ( glyph_height + bitmap_linespacing ) ) + else: + disp_test += " " + except IndexError: + print( (x, y) ) + pass + + disp_test += "|\n" + +disp_test += "+" +for pixel in range( 0, input_width ): + disp_test += "-" +disp_test += "+\n" + +# BMP Conversion preview +print( disp_test ) +#print () +print( "uint8_t array[] = {0};".format( output_image.getarray() ) ) +print( "uint8_t font_glyphs_width = {0};".format( output_image.glyph_width ) ) +print( "uint8_t font_glyphs_height = {0};".format( output_image.glyph_height ) ) +print( "uint8_t font_glyphs_size = {0};".format( output_image.glyph_size ) ) +print( "uint8_t font_num_glyphs = {0};".format( output_image.num_glyphs ) ) diff --git a/Scan/STLcd/capabilities.kll b/Scan/STLcd/capabilities.kll index d5daaead2..460f44f53 100644 --- a/Scan/STLcd/capabilities.kll +++ b/Scan/STLcd/capabilities.kll @@ -63,6 +63,19 @@ STLcdDefaultImage = " 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, "; +STLcdDefaultFont => STLcdDefaultFont_define; +STLcdDefaultFontWidth => STLcdDefaultFontWidth_define; +STLcdDefaultFontHeight => STLcdDefaultFontHeight_define; +STLcdDefaultFontSize => STLcdDefaultFontSize_define; +STLcdDefaultFontLength => STLcdDefaultFontLength_define; + +STLcdDefaultFont = "0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x22, 0x3e, 0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x30, 0x3e, 0x14, 0x3e, 0x14, 0x3e, 0x28, 0x24, 0x08, 0x12, 0x3c, 0x3a, 0x0e, 0x00, 0x30, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x1c, 0x00, 0x28, 0x10, 0x28, 0x08, 0x1c, 0x08, 0x02, 0x04, 0x00, 0x08, 0x08, 0x08, 0x00, 0x02, 0x00, 0x06, 0x08, 0x30, 0x1e, 0x22, 0x3c, 0x10, 0x3e, 0x00, 0x2e, 0x2a, 0x3a, 0x22, 0x2a, 0x3e, 0x38, 0x08, 0x3e, 0x3a, 0x2a, 0x2e, 0x3e, 0x2a, 0x2e, 0x26, 0x28, 0x30, 0x3e, 0x2a, 0x3e, 0x3a, 0x2a, 0x3e, 0x00, 0x14, 0x00, 0x02, 0x14, 0x00, 0x08, 0x14, 0x22, 0x14, 0x14, 0x14, 0x22, 0x14, 0x08, 0x20, 0x2a, 0x30, 0x1c, 0x2a, 0x1a, 0x1e, 0x28, 0x1e, 0x3e, 0x2a, 0x14, 0x1c, 0x22, 0x22, 0x3e, 0x22, 0x1c, 0x3e, 0x2a, 0x2a, 0x3e, 0x28, 0x28, 0x1c, 0x2a, 0x2e, 0x3e, 0x08, 0x3e, 0x22, 0x3e, 0x22, 0x04, 0x02, 0x3c, 0x3e, 0x08, 0x36, 0x3e, 0x02, 0x02, 0x3e, 0x18, 0x3e, 0x3e, 0x20, 0x3e, 0x1c, 0x22, 0x1c, 0x3e, 0x28, 0x10, 0x1c, 0x26, 0x1e, 0x3e, 0x2c, 0x1a, 0x12, 0x2a, 0x24, 0x20, 0x3e, 0x20, 0x3c, 0x02, 0x3e, 0x38, 0x06, 0x38, 0x3e, 0x0c, 0x3e, 0x36, 0x08, 0x36, 0x30, 0x0e, 0x30, 0x26, 0x2a, 0x32, 0x3e, 0x22, 0x22, 0x10, 0x08, 0x04, 0x22, 0x22, 0x3e, 0x10, 0x20, 0x10, 0x02, 0x02, 0x02, 0x20, 0x10, 0x00, 0x16, 0x1a, 0x0e, 0x3e, 0x12, 0x0c, 0x0c, 0x12, 0x12, 0x0c, 0x12, 0x3e, 0x0c, 0x16, 0x1a, 0x08, 0x1e, 0x28, 0x0c, 0x15, 0x1e, 0x3e, 0x10, 0x0e, 0x00, 0x2e, 0x00, 0x02, 0x01, 0x2e, 0x3e, 0x0c, 0x12, 0x22, 0x3e, 0x02, 0x1e, 0x1c, 0x1e, 0x1e, 0x10, 0x0e, 0x0c, 0x12, 0x0c, 0x1f, 0x12, 0x0c, 0x0c, 0x12, 0x1f, 0x0e, 0x10, 0x10, 0x0a, 0x1e, 0x14, 0x10, 0x3e, 0x12, 0x1c, 0x02, 0x1e, 0x1c, 0x06, 0x1c, 0x1e, 0x0e, 0x1e, 0x12, 0x0c, 0x12, 0x18, 0x05, 0x1e, 0x16, 0x1e, 0x1a, 0x08, 0x36, 0x22, 0x00, 0x36, 0x00, 0x22, 0x36, 0x08, 0x10, 0x30, 0x20, 0x3e, 0x3e, 0x3e,"; +STLcdDefaultFontWidth = 3; +STLcdDefaultFontHeight = 6; +STLcdDefaultFontSize = 3; +STLcdDefaultFontLength = 128; + +# TTYOutputChar => TTY_outputChar_capability(charactor : 1); # Layer Status Display diff --git a/Scan/STLcd/lcd_scan.c b/Scan/STLcd/lcd_scan.c index 1dd912682..c9685dab8 100644 --- a/Scan/STLcd/lcd_scan.c +++ b/Scan/STLcd/lcd_scan.c @@ -33,14 +33,13 @@ // Local Includes #include "lcd_scan.h" - - // ----- Defines ----- #define LCD_TOTAL_VISIBLE_PAGES 4 #define LCD_TOTAL_PAGES 9 #define LCD_PAGE_LEN 128 - +#define LCD_WIDTH 128 +#define LCD_HEIGHT 32 // ----- Macros ----- @@ -55,11 +54,15 @@ // ----- Function Declarations ----- // CLI Functions -void cliFunc_lcdCmd ( char* args ); -void cliFunc_lcdColor( char* args ); -void cliFunc_lcdDisp ( char* args ); -void cliFunc_lcdInit ( char* args ); -void cliFunc_lcdTest ( char* args ); +void cliFunc_lcdCmd ( char* args ); +void cliFunc_lcdColor ( char* args ); +void cliFunc_lcdDisp ( char* args ); +void cliFunc_lcdInit ( char* args ); +void cliFunc_lcdTest ( char* args ); +void cliFunc_lcdTextOut ( char* args ); +void cliFunc_ttyPrint ( char* args ); +void cliFunc_ttyScrollUp ( char* args ); + @@ -68,6 +71,14 @@ void cliFunc_lcdTest ( char* args ); // Default Image - Displays on startup const uint8_t STLcdDefaultImage[] = { STLcdDefaultImage_define }; +const uint8_t STLcdDefaultFont[] = { STLcdDefaultFont_define }; +const uint8_t STLcdDefaultFontWidth = STLcdDefaultFontWidth_define; +const uint8_t STLcdDefaultFontHeight = STLcdDefaultFontHeight_define; +const uint8_t STLcdDefaultFontSize = STLcdDefaultFontSize_define; +const uint8_t STLcdDefaultFontLength = STLcdDefaultFontLength_define; + + + // Full Toggle State uint8_t cliFullToggleState = 0; @@ -80,6 +91,9 @@ CLIDict_Entry( lcdColor, "Set backlight color. 3 16-bit numbers: R G B. i.e. CLIDict_Entry( lcdDisp, "Write byte(s) to given page starting at given address. i.e. 0x1 0x5 0xFF 0x00" ); CLIDict_Entry( lcdInit, "Re-initialize the LCD display." ); CLIDict_Entry( lcdTest, "Test out the LCD display." ); +CLIDict_Entry( lcdTextOut, "Output text to the LCD at the given x-y coordinate."); +CLIDict_Entry( ttyPrint, "Output text to the LCD." ); +CLIDict_Entry( ttyScrollUp, "Scroll up given lines on the LCD." ); CLIDict_Def( lcdCLIDict, "ST LCD Module Commands" ) = { CLIDict_Item( lcdCmd ), @@ -87,6 +101,9 @@ CLIDict_Def( lcdCLIDict, "ST LCD Module Commands" ) = { CLIDict_Item( lcdDisp ), CLIDict_Item( lcdInit ), CLIDict_Item( lcdTest ), + CLIDict_Item( lcdTextOut), + CLIDict_Item( ttyPrint ), + CLIDict_Item( ttyScrollUp ), { 0, 0, 0 } // Null entry for dictionary end }; @@ -168,7 +185,7 @@ void LCD_writeControlReg( uint8_t byte ) // Write to display register // Pages 0-7 normal display -// Page 8 icon buffer +// Page 8 icon buffer void LCD_writeDisplayReg( uint8_t page, uint8_t *buffer, uint8_t len ) { // Set the register page @@ -311,14 +328,14 @@ inline void LCD_setup() // @ 0xFFFF period, 72 MHz / (0xFFFF * 2) = Actual period // Higher pre-scalar will use the most power (also look the best) // Pre-scalar calculations - // 0 - 72 MHz -> 549 Hz - // 1 - 36 MHz -> 275 Hz - // 2 - 18 MHz -> 137 Hz - // 3 - 9 MHz -> 69 Hz (Slightly visible flicker) - // 4 - 4 500 kHz -> 34 Hz (Visible flickering) - // 5 - 2 250 kHz -> 17 Hz - // 6 - 1 125 kHz -> 9 Hz - // 7 - 562 500 Hz -> 4 Hz + // 0 - 72 MHz -> 549 Hz + // 1 - 36 MHz -> 275 Hz + // 2 - 18 MHz -> 137 Hz + // 3 - 9 MHz -> 69 Hz (Slightly visible flicker) + // 4 - 4 500 kHz -> 34 Hz (Visible flickering) + // 5 - 2 250 kHz -> 17 Hz + // 6 - 1 125 kHz -> 9 Hz + // 7 - 562 500 Hz -> 4 Hz // Using a higher pre-scalar without flicker is possible but FTM0_MOD will need to be reduced // Which will reduce the brightness range @@ -338,10 +355,248 @@ inline void LCD_setup() PORTC_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(4); } +static uint32_t STLcdSyncStartMillis; +static uint32_t STLcdSyncStartTicks; + +// Display buffer +uint8_t STLcdBuffer [ LCD_PAGE_LEN * LCD_TOTAL_VISIBLE_PAGES ]; +uint8_t STLcdSyncBuffer [ LCD_PAGE_LEN * LCD_TOTAL_VISIBLE_PAGES ]; + + +// Bounding box. +static uint8_t STLcdUpdateXMin = LCD_WIDTH, STLcdUpdateXMax = 0, STLcdUpdateYMin = LCD_HEIGHT, STLcdUpdateYMax = 0; +static uint8_t STLcdSync = 0; +static uint8_t STLcdSyncPageMin, STLcdSyncPageMax, STLcdSyncColumnMin, STLcdSyncColumnMax; + +static void STLcd_updateBoundingBox( uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax ) { + if ( xmin < STLcdUpdateXMin ) STLcdUpdateXMin = xmin; + if ( xmax > STLcdUpdateXMax ) STLcdUpdateXMax = xmax; + if ( ymin < STLcdUpdateYMin ) STLcdUpdateYMin = ymin; + if ( ymax > STLcdUpdateYMax ) STLcdUpdateYMax = ymax; +} + +void STLcd_clear( void ) { + memset( STLcdBuffer, 0, LCD_PAGE_LEN * LCD_TOTAL_VISIBLE_PAGES ); + STLcd_updateBoundingBox( 0, 0, LCD_WIDTH, LCD_HEIGHT ); +} + +static uint8_t STLcdSyncPageCurrent; +static uint8_t *STLcdSyncBufferColumnCurrent; +static uint8_t *STLcdSyncBufferColumnMin, *STLcdSyncBufferColumnMax; +static uint32_t STLcdSyncStage; + +#define STAGE_WRITE_START 15 + +void STLcd_blockingSync(void) { + for ( ; STLcdSyncPageCurrent < STLcdSyncPageMax; + STLcdSyncPageCurrent++, STLcdSyncBufferColumnMin += LCD_PAGE_LEN ) + { + LCD_writeControlReg( 0xB0 | STLcdSyncPageCurrent ); + LCD_writeControlReg( 0x10 | STLcdSyncColumnMin >> 4 ); + LCD_writeControlReg( 0x10 | ( STLcdSyncColumnMin & 0x0f ) ); + SPI_write( STLcdSyncBufferColumnMin, STLcdSyncColumnMax - STLcdSyncColumnMin ); + } +} + +// a non-blocking sync function +void STLcd_sync() { + for ( ;; ) + { + switch(STLcdSyncStage) + { + // Verify SPI0 TxFIFO is not full, then enable LCD configuration registers (A0 to Low) + case 0: + if ( SPI0_TxFIFO_CNT != 0 ) // while ( SPI0_TxFIFO_CNT != 0 ); + return; + GPIOC_PCOR |= (1<<7); + STLcdSyncStage++; + + // Verify SPI0 TxFIFO has 4 or fewer entries, then write page number to TxFIFO (CS0, CTAR0) + case 1: // Begin SPI_write( &byte, 1); + if ( !( SPI0_SR & SPI_SR_TFFF ) ) + return; + SPI0_PUSHR = ( 0xB0 | STLcdSyncPageCurrent ) | SPI_PUSHR_PCS(1); + STLcdSyncStage++; + + // TODO: Verify the transfer has completed? + case 2: + if ( !( SPI0_SR & SPI_SR_TCF ) ) + return; + SPI0_SR |= SPI_SR_TCF; + STLcdSyncStage++; // End SPI_write + + // Verify SPIO TxFIFO is empty, then save the current time. + case 3: + if ( SPI0_TxFIFO_CNT != 0 ) // while ( SPI0_TxFIFO_CNT != 0 ); + return; + STLcdSyncStage++; + STLcdSyncStartTicks = ticks(); + STLcdSyncStartMillis = millis(); + + // Verify that 10 microseconds have passed, then enable LCD display registors (A0 to high) + case 4: + // delayMicroseconds(10); + if ( !isTicksPassed( STLcdSyncStartMillis, STLcdSyncStartTicks, F_CPU / 1000000 * 10 ) ) + return; + GPIOC_PSOR |= (1<<7); + STLcdSyncStage++; // End LCD_writeControlReg( 0xB0 | page); + + // TODO: maybe these lines is not need? Because the last command also writes to the control register. + case 5: // Begin LCD_writeControlReg( 0x10 | STLcdSyncColumnMin >> 4); + if ( SPI0_TxFIFO_CNT != 0 ) // while ( SPI0_TxFIFO_CNT != 0 ); + return; + GPIOC_PCOR |= (1<<7); + STLcdSyncStage++; + + // Verify SPI0 TxFIFO has 4 or fewer entries, + // then write the high half of column number to TxFIFO (CS0, CTAR0) + case 6: // Begin SPI_write( &byte, 1); + if ( !( SPI0_SR & SPI_SR_TFFF) ) + return; + SPI0_PUSHR = ( 0x10 | STLcdSyncColumnMin >> 4 ) | SPI_PUSHR_PCS(1); + STLcdSyncStage++; + + // TODO: Verify the transfer has completed? + case 7: + if ( !( SPI0_SR & SPI_SR_TCF ) ) + return; + SPI0_SR |= SPI_SR_TCF; + STLcdSyncStage++; // End SPI_write + + // Verify SPIO TxFIFO is empty, then save the current time. + case 8: + if ( SPI0_TxFIFO_CNT != 0 ) // while ( SPI0_TxFIFO_CNT != 0 ); + return; + STLcdSyncStage++; + STLcdSyncStartTicks = ticks(); + STLcdSyncStartMillis = millis(); + + // Verify that 10 microseconds have passed, then enable LCD display registors (A0 to high) + case 9: + // delayMicroseconds(10); + if ( !isTicksPassed( STLcdSyncStartMillis, STLcdSyncStartTicks, F_CPU / 1000000 * 10 ) ) + return; + GPIOC_PSOR |= (1<<7); + STLcdSyncStage++; // End LCD_writeControlReg( 0x10 | STLcdSyncColumnCurrent >> 4); + + // TODO: maybe these lines is not need? Because the last command also writes to the control register. + case 10: // Begin LCD_writeControlReg( 0x00 | STLcdSyncColumnCurrent & 0x0f); + if ( SPI0_TxFIFO_CNT != 0 ) // while ( SPI0_TxFIFO_CNT != 0 ); + return; + GPIOC_PCOR |= (1<<7); + STLcdSyncStage++; + + // Verify SPI0 TxFIFO has 4 or fewer entries, + // then write the lower half of column number to TxFIFO (CS0, CTAR0) + case 11: // Begin SPI_write( &byte, 1); + if ( !( SPI0_SR & SPI_SR_TFFF) ) + return; + SPI0_PUSHR = ( 0x00 | ( STLcdSyncColumnMin & 0x0f ) ) | SPI_PUSHR_PCS(1); + STLcdSyncStage++; + + // TODO: Verify the transfer has completed? + case 12: + if ( !( SPI0_SR & SPI_SR_TCF ) ) + return; + SPI0_SR |= SPI_SR_TCF; + STLcdSyncStage++; // End SPI_write + + // Verify SPIO TxFIFO is empty, then save the current time. + case 13: + if ( SPI0_TxFIFO_CNT != 0 ) // while ( SPI0_TxFIFO_CNT != 0 ); + return; + STLcdSyncStage++; + STLcdSyncStartTicks = ticks(); + STLcdSyncStartMillis = millis(); + + // Verify that 10 microseconds have passed, then enable LCD display registors (A0 to high), + // then begin to write the buffer to SPI. + case 14: + // delayMicroseconds(10); + if ( !isTicksPassed( STLcdSyncStartMillis, STLcdSyncStartTicks, F_CPU / 1000000 * 10 ) ) + return; + GPIOC_PSOR |= (1<<7); + STLcdSyncStage++; // End LCD_writeControlReg( 0x00 | (STLcdSyncColumnCurrent & 0x0f)); + STLcdSyncBufferColumnCurrent = STLcdSyncBufferColumnMin; + // Begin SPI_write( STLcdSyncBufferColumnMin, + // STLcdSyncColumnMax - STLcdSyncColumnMin); + + // If the current page has been outputed, + // then change to next page or finish the sync( if it's the last page). + case STAGE_WRITE_START: + if ( STLcdSyncBufferColumnCurrent >= STLcdSyncBufferColumnMax ) + { // next page + STLcdSyncStage = 0; + STLcdSyncPageCurrent++; + if ( STLcdSyncPageCurrent >= STLcdSyncPageMax ) + { // has finished + STLcdSync = 0; + return; + } + else{ + STLcdSyncBufferColumnMin += LCD_PAGE_LEN; + STLcdSyncBufferColumnMax += LCD_PAGE_LEN; + break; + } + } + STLcdSyncStage++; + + // Verify SPI0 TxFIFO has 4 or fewer entries, + // then write the byte of current column to TxFIFO (CS0, CTAR0) + case 16: + if( !( SPI0_SR & SPI_SR_TFFF) ) + return; + SPI0_PUSHR = ( *STLcdSyncBufferColumnCurrent ) | SPI_PUSHR_PCS(1); + STLcdSyncStage++; + + // TODO: Verify the transfer has completed? + // then changed to the next column of current page and go back to the start of this loop. + case 17: + if( !( SPI0_SR & SPI_SR_TCF ) ) + return; + SPI0_SR |= SPI_SR_TCF; + STLcdSyncBufferColumnCurrent++; + STLcdSyncStage=STAGE_WRITE_START; // Loop back to STAGE_WRITE_START + break; + } + } +} + // LCD State processing loop inline uint8_t LCD_scan() { + if ( STLcdSync ) + { + STLcd_sync(); + } + else + { + if ( STLcdUpdateYMin >= STLcdUpdateYMax ) + return 0; + STLcdSyncPageMin = STLcdUpdateYMin >> 3; + STLcdSyncPageMax = ( STLcdUpdateYMax + 7 ) >> 3; + STLcdSyncPageCurrent = STLcdSyncPageMin; + + STLcdSyncColumnMin = STLcdUpdateXMin; + STLcdSyncColumnMax = STLcdUpdateXMax; + + STLcdSyncBufferColumnMin = STLcdSyncBuffer + STLcdSyncPageCurrent * LCD_PAGE_LEN + STLcdSyncColumnMin; + STLcdSyncBufferColumnMax = STLcdSyncBuffer + STLcdSyncPageCurrent * LCD_PAGE_LEN + STLcdSyncColumnMax; + + memcpy( STLcdSyncBuffer + STLcdSyncPageMin * LCD_PAGE_LEN, STLcdBuffer + STLcdSyncPageMin * LCD_PAGE_LEN, + ( STLcdSyncPageMax - STLcdSyncPageMin ) * LCD_PAGE_LEN ); + + STLcdSync = 1; + STLcdSyncStage = 0; + //STLcd_syncBlocking(); + STLcd_sync(); + + STLcdUpdateXMin = LCD_WIDTH - 1; + STLcdUpdateXMax = 0; + STLcdUpdateYMin = LCD_HEIGHT - 1; + STLcdUpdateYMax = 0; + } return 0; } @@ -417,16 +672,11 @@ void LCD_layerStackExact_capability( uint8_t state, uint8_t stateType, uint8_t * // Iterate through each of the pages // XXX Many of the values here are hard-coded - // Eventually a proper font rendering engine should take care of things like this... -HaaTa + // Eventually a proper font rendering engine should take care of things like this... -HaaTa + STLcd_clear(); for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ ) { - // Set the register page - LCD_writeControlReg( 0xB0 | ( 0x0F & page ) ); - - // Set starting address - LCD_writeControlReg( 0x10 ); - LCD_writeControlReg( 0x00 ); - + uint8_t offset = 0; // Write data for ( uint16_t layer = 0; layer < stack_args->numArgs; layer++ ) { @@ -437,19 +687,10 @@ void LCD_layerStackExact_capability( uint8_t state, uint8_t stateType, uint8_t * { layerIndex = 0; } - - // Write page of number to display - SPI_write( (uint8_t*)&numbers[ layerIndex ][ page * 32 ], 32 ); - } - - // Blank out rest of display - uint8_t data = 0; - for ( uint8_t c = 0; c < 4 - stack_args->numArgs; c++ ) - { - for ( uint8_t byte = 0; byte < 32; byte++ ) - { - SPI_write( &data, 1 ); - } + memcpy(STLcdBuffer + page * LCD_PAGE_LEN + offset, + &numbers[layerIndex][page * 32], + 32); + offset += 32; } } } @@ -461,15 +702,15 @@ void LCD_layerStackExact_capability( uint8_t state, uint8_t stateType, uint8_t * FTM0_C2V = STLcdBacklightBlue_define; // Write default image - for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ ) - LCD_writeDisplayReg( page, (uint8_t *)&STLcdDefaultImage[page * LCD_PAGE_LEN], LCD_PAGE_LEN ); + memcpy(STLcdBuffer, STLcdDefaultImage, LCD_PAGE_LEN * LCD_TOTAL_VISIBLE_PAGES); + STLcd_updateBoundingBox(0, 0, LCD_WIDTH, LCD_HEIGHT); } } // Determines the current layer stack, and sets the LCD output accordingly // Will only work on a master node when using the interconnect (use LCD_layerStackExact_capability instead) uint16_t LCD_layerStack_prevSize = 0; -uint16_t LCD_layerStack_prevTop = 0; +uint16_t LCD_layerStack_prevTop = 0; void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args ) { // Display capability name @@ -485,12 +726,13 @@ void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args // Ignore if the stack size hasn't changed and the top of the stack is the same if ( macroLayerIndexStackSize == LCD_layerStack_prevSize - && macroLayerIndexStack[macroLayerIndexStackSize - 1] == LCD_layerStack_prevTop ) + && (macroLayerIndexStackSize == 0 || + macroLayerIndexStack[macroLayerIndexStackSize - 1] == LCD_layerStack_prevTop )) { return; } LCD_layerStack_prevSize = macroLayerIndexStackSize; - LCD_layerStack_prevTop = macroLayerIndexStack[macroLayerIndexStackSize - 1]; + LCD_layerStack_prevTop = macroLayerIndexStack[macroLayerIndexStackSize - 1]; LCD_layerStackExact_args stack_args; memset( stack_args.layers, 0, sizeof( stack_args.layers ) ); @@ -525,6 +767,254 @@ void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args LCD_layerStackExact_capability( state, stateType, (uint8_t*)&stack_args ); } +static uint8_t STLcdDrawMasks[8][8] = +{ + { 0x00, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 }, + { 0x01, 0xfd, 0xf9, 0xf1, 0xe1, 0xc1, 0x81, 0x01 }, + { 0x03, 0xfb, 0xf3, 0xe3, 0xc3, 0x83, 0x03, 0x03 }, + { 0x07, 0xf7, 0xe7, 0xc7, 0x87, 0x07, 0x07, 0x07 }, + { 0x0f, 0xef, 0xcf, 0x8f, 0x0f, 0x0f, 0x0f, 0x0f }, + { 0x1f, 0xdf, 0x9f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, + { 0x3f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f }, + { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f } +}; + +void STLcd_drawBitmap( const uint8_t *bitmap, uint8_t x, uint8_t y, uint8_t width, uint8_t height ) +{ + uint8_t *buffer = STLcdBuffer + (y>>3) * LCD_PAGE_LEN + x; + uint8_t maxcolumn = ( x + width <= LCD_WIDTH ) ? width : ( LCD_WIDTH - x ); + uint8_t remainheight = + ( y + height <= LCD_HEIGHT ) + ? height : ( LCD_HEIGHT - y ); + uint8_t srcpages = ( remainheight + 7 ) / 8; + uint8_t page = 0; + if ( y & 0x07 ) + { + uint8_t highbits = y & 0x07; + + uint8_t mask = STLcdDrawMasks[ highbits ][ ( remainheight > 7 ) ? 0 : remainheight ]; + for ( uint8_t column = 0; column < maxcolumn; column++ ) + { + buffer[ column ] = ( buffer[ column ] & mask ) | ( bitmap[ column ] << highbits ); + } + remainheight -= 8 - highbits; + page++; + for ( ; remainheight > 7; page++, remainheight -= 8 ) + { + for ( uint8_t column = 0; column < maxcolumn; column++ ) + { + buffer[ page * LCD_PAGE_LEN + column ] = + ( bitmap[ ( page - 1 ) * width + column ] >> ( 8 - highbits ) ) + | ( bitmap[ page * width + column ] << highbits ); + } + } + if ( remainheight > 0 ) + { + mask = ~STLcdDrawMasks[ remainheight ][ 0 ]; + if ( page == srcpages ) + { + for ( uint8_t column = 0; column < maxcolumn; column++ ) + { + buffer[ page * LCD_PAGE_LEN + column ] = + ( bitmap[ ( page - 1 ) * width + column ] >> ( 8 - highbits ) ) + | ( buffer[ page * LCD_PAGE_LEN + column ] & mask ); + } + } + else + { + for ( uint8_t column = 0; column < maxcolumn; column++ ) + { + buffer[ page * LCD_PAGE_LEN + column ] = + ( bitmap[ page * width + column ] << highbits ) + | ( bitmap[ ( page - 1 ) * width + column ] >> ( 8 - highbits ) ) + | ( buffer[ page * LCD_PAGE_LEN + column ] & mask ); + } + } + } + } + else + { + uint8_t page = 0; + for ( page = 0; remainheight > 7; page++, remainheight -= 8 ) + { + memcpy( buffer + page * LCD_PAGE_LEN, + bitmap + page * width, + maxcolumn ); + } + if ( remainheight > 0 ) + { + uint8_t mask = ~STLcdDrawMasks[ remainheight ][ 0 ]; + for ( uint8_t column = 0; column < maxcolumn; column++ ) + { + uint16_t destindex = page * LCD_PAGE_LEN + column; + buffer[ destindex ] = ( buffer[ destindex ] & mask ) + | ( bitmap[ page * width + column ] ); + } + } + } +} + +static uint8_t TTYInitialized = 0; +static const uint8_t * TTYFont = 0; +static uint8_t TTYFontHeight = 0; +static uint8_t TTYFontWidth = 0; +static uint8_t TTYFontSize = 0; +static uint8_t TTYSpacing = 0; +static uint8_t TTYLineHeight = 0; +static uint8_t TTYFontLength = 0; +static uint8_t TTYLines = 0; +static uint8_t TTYColumns = 0; +static uint8_t TTYCurrentLine = 0; +static uint8_t TTYCurrentColumn = 0; + +void TTY_initialize( const uint8_t *font, uint8_t fontSize, uint8_t fontLength, + uint8_t fontWidth, uint8_t fontHeight, + uint8_t spacing, uint8_t lineHeight ) +{ + STLcd_clear(); + TTYInitialized = 1; + TTYFont = font; + TTYFontSize = fontSize; + TTYFontWidth = fontWidth; + TTYFontHeight = fontHeight; + TTYFontLength = fontLength; + TTYSpacing = spacing; + TTYLineHeight = lineHeight; + TTYLines = ( LCD_HEIGHT - fontHeight) / lineHeight + 1; + TTYColumns = ( LCD_WIDTH - fontWidth ) / ( fontWidth + spacing ) + 1; + TTYCurrentLine = TTYLines - 1; + TTYCurrentColumn = 0; +} + +void TTY_exit() +{ + STLcd_clear(); + TTYInitialized = 0; +} + +void TTY_drawGlyph( uint8_t index ) +{ + if ( index < TTYFontLength ) + return; + STLcd_drawBitmap( TTYFont + index * TTYFontSize, + TTYCurrentColumn * ( TTYFontWidth + TTYSpacing ), + TTYCurrentLine * TTYLineHeight, + TTYFontWidth, + TTYFontHeight ); + STLcd_updateBoundingBox( TTYCurrentColumn * ( TTYFontWidth + TTYSpacing ), + TTYCurrentLine * TTYLineHeight, + TTYCurrentColumn * ( TTYFontWidth + TTYSpacing ) + TTYFontWidth, + TTYCurrentLine * TTYLineHeight + TTYFontHeight ); +} + +void TTY_scrollUp( uint8_t lines ) +{ + uint8_t scrollpixels = lines * TTYLineHeight; + uint8_t scrollshiftbits = scrollpixels & 0x07; + uint8_t scrollpages = scrollpixels >> 3; + if ( scrollshiftbits == 0 ) + { + if ( scrollpages == 0 ) + { + return; + } + memcpy( STLcdBuffer, + STLcdBuffer + scrollpages * LCD_PAGE_LEN, + LCD_PAGE_LEN * ( LCD_TOTAL_VISIBLE_PAGES - scrollpages ) ); + memset( STLcdBuffer + LCD_PAGE_LEN * ( LCD_TOTAL_VISIBLE_PAGES - scrollpages ), + 0, + scrollpages * LCD_PAGE_LEN ); + } + else + { + if ( scrollpages < LCD_TOTAL_VISIBLE_PAGES - 1 ) + { + for ( uint8_t destpage = LCD_TOTAL_VISIBLE_PAGES - 1, + srcpage = LCD_TOTAL_VISIBLE_PAGES - scrollpages - 1; + srcpage > 0; + destpage--, srcpage-- ) + { + for ( uint8_t column = 0; column < LCD_PAGE_LEN; column++ ) + { + STLcdBuffer[ destpage * LCD_PAGE_LEN + column ] = + ( STLcdBuffer[ srcpage * LCD_PAGE_LEN + column ] << scrollshiftbits ) | + ( STLcdBuffer[ ( srcpage - 1 ) * LCD_PAGE_LEN + column ] >> ( 8 - scrollshiftbits ) ); + } + } + } + if ( scrollpages < LCD_TOTAL_VISIBLE_PAGES ) + { + for ( uint8_t column = 0; column < LCD_PAGE_LEN; column++ ) + { // last non-empty page + STLcdBuffer[ scrollpages * LCD_PAGE_LEN + column ] = STLcdBuffer[ column ] << scrollshiftbits; + } + } + if ( scrollpages > 0 ) // have empty pages + { + memset( STLcdBuffer, + 0, + scrollpages * LCD_PAGE_LEN ); + } + } + STLcd_updateBoundingBox(0, 0, LCD_WIDTH, LCD_HEIGHT); +} + +void TTY_newLine( void ) +{ + if ( TTYCurrentLine > 0 ) + { + TTYCurrentLine--; + TTYCurrentColumn = 0; + } + else + { + TTY_scrollUp( 1 ); + TTYCurrentColumn = 0; + } +} + +void TTY_outputChar( uint8_t c ) +{ + if ( !TTYInitialized ){ + TTY_initialize ( STLcdDefaultFont, STLcdDefaultFontSize, STLcdDefaultFontLength, + STLcdDefaultFontWidth, STLcdDefaultFontHeight, + 1, 0 ); + } + switch ( c ) + { + case 0x8: // \b + if ( TTYCurrentColumn ) + { + TTYCurrentColumn--; + TTY_drawGlyph( 0x20 ); + } + break; + case 0x9: // \t + TTYCurrentColumn = ( TTYCurrentColumn & 0xfc ) + 4; + if ( TTYCurrentColumn >= TTYColumns ) + { + TTY_newLine(); + } + break; + case 0x0a: // \n + TTY_newLine(); + break; + case 0x0c: // \f + STLcd_clear(); + TTYCurrentColumn = 0; + TTYCurrentLine = TTYLines - 1; + break; + default: + TTY_drawGlyph( c ); + TTYCurrentColumn++; + if ( TTYCurrentColumn >= TTYColumns ) + { + TTY_newLine(); + } + break; + } +} + // ----- CLI Command Functions ----- @@ -537,8 +1027,8 @@ void cliFunc_lcdInit( char* args ) void cliFunc_lcdTest( char* args ) { // Write default image - for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ ) - LCD_writeDisplayReg( page, (uint8_t *)&STLcdDefaultImage[page * LCD_PAGE_LEN], LCD_PAGE_LEN ); + memcpy( STLcdBuffer, STLcdDefaultImage, LCD_PAGE_LEN * LCD_TOTAL_VISIBLE_PAGES ); + STLcd_updateBoundingBox( 0, 0, LCD_WIDTH, LCD_HEIGHT ); } void cliFunc_lcdCmd( char* args ) @@ -625,13 +1115,74 @@ void cliFunc_lcdDisp( char* args ) if ( *arg1Ptr == '\0' ) return; uint8_t address = numToInt( arg1Ptr ); + uint8_t start = address; - // Set the register page - LCD_writeControlReg( 0xB0 | ( 0x0F & page ) ); + // Process all args + for ( ;; ) + { + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + break; + + uint8_t value = numToInt( arg1Ptr ); + STLcdBuffer[ page * LCD_PAGE_LEN + address ] = value; + address++; + } + STLcd_updateBoundingBox( start, page * 8, address, (page + 1) * 8 ); +} - // Set starting address - LCD_writeControlReg( 0x10 | ( ( 0xF0 & address ) >> 4 ) ); - LCD_writeControlReg( 0x00 | ( 0x0F & address )); +void cliFunc_lcdTextOut( char* args ) +{ + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + + // First process page and starting address + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + return; + uint8_t x = numToInt( arg1Ptr ); + + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + return; + uint8_t y = numToInt( arg1Ptr ); + + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + return; + uint8_t value = numToInt( arg1Ptr ); + if ( value >= STLcdDefaultFontLength ) + { + print( "The charactor: " ); + printHex( value ); + print( " is out of the boundary of the font(length "); + printHex( STLcdDefaultFontLength ); + print( ")" ); + print( NL ); + } + STLcd_drawBitmap( STLcdDefaultFont + value * STLcdDefaultFontSize, x, y, + STLcdDefaultFontWidth, STLcdDefaultFontHeight ); + STLcd_updateBoundingBox( x, y, x + STLcdDefaultFontWidth, y + STLcdDefaultFontHeight ); +} + +void cliFunc_ttyPrint( char* args ) +{ + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; // Process all args for ( ;; ) @@ -644,9 +1195,23 @@ void cliFunc_lcdDisp( char* args ) break; uint8_t value = numToInt( arg1Ptr ); - - // Write buffer to SPI - SPI_write( &value, 1 ); + TTY_outputChar( value ); } } +void cliFunc_ttyScrollUp( char* args ) +{ + char* curArgs; + char* arg1Ptr; + char* arg2Ptr = args; + + curArgs = arg2Ptr; + CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); + + // Stop processing args if no more are found + if ( *arg1Ptr == '\0' ) + return; + + uint8_t value = numToInt( arg1Ptr ); + TTY_scrollUp( value ); +}