From aabbb214d0f7b6f640d1e6e963760d5ed95a0f67 Mon Sep 17 00:00:00 2001 From: Eric Teunis de Boone Date: Sat, 4 Jan 2020 19:38:05 +0100 Subject: [PATCH] Wrap Up: Scrolling text not yet working --- serial_text_scroller/display.ino | 177 ++++++++++++++++++ serial_text_scroller/serial.ino | 66 +++++++ serial_text_scroller/serial_text_scroller.ino | 107 +++++++++++ 3 files changed, 350 insertions(+) create mode 100644 serial_text_scroller/display.ino create mode 100644 serial_text_scroller/serial.ino create mode 100644 serial_text_scroller/serial_text_scroller.ino diff --git a/serial_text_scroller/display.ino b/serial_text_scroller/display.ino new file mode 100644 index 0000000..4e5eec8 --- /dev/null +++ b/serial_text_scroller/display.ino @@ -0,0 +1,177 @@ +/* + ============================================== + Functions needed for manipulating the displays + ============================================== +*/ + + +void initDisplay(); +void updateDisplay(); +char* scrolltext(const char* text, unsigned int tick, int chars); +char* scrolltext(const char* text, unsigned int tick); + +#define LCD 1 // Use the LCD instead of OLED + +#if LCD == 1 +// Use LCD + // include the library code: + #include + + const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; + LiquidCrystal display(rs, en, d4, d5, d6, d7); + + #define DISPLAY_COLS 16 + #define DISPLAY_ROWS 2 + +#else +// OLED display + #include + #include + #include + #include + + //Functionality + const int rs = 4; + Adafruit_SSD1306 display(rs); + + #define NUMFLAKES 10 + #define XPOS 0 + #define YPOS 1 + #define DELTAY 2 + + #define DISPLAY_COLS 21 + #define DISPLAY_ROWS 4 + + + #define LOGO16_GLCD_HEIGHT 16 + #define LOGO16_GLCD_WIDTH 16 + static const unsigned char PROGMEM logo16_glcd_bmp[] = + { B00000000, B11000000, + B00000001, B11000000, + B00000001, B11000000, + B00000011, B11100000, + B11110011, B11100000, + B11111110, B11111000, + B01111110, B11111111, + B00110011, B10011111, + B00011111, B11111100, + B00001101, B01110000, + B00011011, B10100000, + B00111111, B11100000, + B00111111, B11110000, + B01111100, B11110000, + B01110000, B01110000, + B00000000, B00110000 }; + + #if (SSD1306_LCDHEIGHT != 32) + #error("Height incorrect, please fix Adafruit_SSD1306.h!"); + #endif +#endif + + +void initDisplay() { + // Initialise the Display + display.begin(DISPLAY_COLS, DISPLAY_ROWS); + display.noAutoscroll(); + display.clear(); +} +void updateDisplay( const unsigned int tick ) { + + // Update the Display + display.clear(); + display.setCursor(5, 0); + display.print("|"); + + display.setCursor(0, 0); + display_scrolltext(line_buffer[line_buffer_read], tick , 5); + + + display.setCursor(0, DISPLAY_ROWS); + display.print("LPS:"); + display.print( lps ); + + display.setCursor(10, DISPLAY_ROWS); + display.print("T:"); + display.print( tick ); +} + +void display_scrolltext(const char* text, const unsigned int tick) { + return display_scrolltext(text, tick, DISPLAY_COLS); +} +void display_scrolltext(const char* text, const unsigned int tick, const int nchars) { + int len = strlen(text); + + char new_text[nchars]; + + // text fits in nchars characters + if ( len <= nchars ) + { + for( int i = 0; i < len; i++){ + new_text[i] = text[i]; + } + for (int i = len; i < nchars; i++ ) { + new_text[i] = ' '; + } + display.print(new_text); + return; + } + + + const char separator[] = "-"; + const unsigned int scroll_speed = 1; + const int sep_len = strlen(separator); + + int i = 0; + int offset = (scroll_speed * tick) % (len + sep_len); + + // copy string from offset until the end, or until nchars have been reached + for ( i = 0; i < nchars && i < len - offset; i++ ) { + new_text[i] = text[offset+i]; + } + Serial.println(i); + + // pad with separator; + for (int j = 0 ; i < nchars && j < sep_len ; j++ ) { + + new_text[i++] = separator[j]; + } + Serial.println(i); + + + // copy from beginning until nchars reached + for ( ; i < nchars; i++ ) { + new_text[i] = text[i - sep_len - (len - offset) ]; + } + Serial.println(i); + // Somewhere this null byte is rewritten + new_text[nchars] = '\0'; + display.print(new_text); + Serial.println(new_text); +} + +/* +ABCDE +-+ +- + +chars = 4; // length of output +len = 6 // length of string +offset = 3 // offset of output + +==> 'DE - AB' + int newlen = len + strlen(separator); + char newtext[newlen]; + + for ( int i = 0; i < len; i++ ) { + newtext[i] = text[i]; + } + for ( int i = 0; i < strlen(separator); i++ ) { + newtext[len + i] = separator[i]; + } + + // text does not fit in chars characters + // TODO: this works ugly, I want a separator in between start and end + for ( int i = 0; i < chars; i ++ ) { + display.print(newtext[(offset + i) % (newlen)]); + } +} +*/ diff --git a/serial_text_scroller/serial.ino b/serial_text_scroller/serial.ino new file mode 100644 index 0000000..c09b917 --- /dev/null +++ b/serial_text_scroller/serial.ino @@ -0,0 +1,66 @@ +/* + ======================================================= + Serial Input Capability using the Serial Event Function + ======================================================= +*/ +#define SERIAL_INPUT_MAX_LENGTH 30 + +void handleInputBuffer( const char* input_buffer ); +void serialEvent(); + +char serial_input_buffer[SERIAL_INPUT_MAX_LENGTH+1]; // holds incoming data +int serial_input_buffer_index = 0; + +/* + SerialEvent occurs whenever a new data comes in the + hardware serial RX. This routine is run between each + time loop() runs, so using delay inside loop can delay + response. Multiple bytes of data may be available. + */ +void serialEvent() { + bool serial_input_buffer_complete = false; + + while (Serial.available()) { + // get the new byte and add it to the buffer + serial_input_buffer[serial_input_buffer_index] = (char) Serial.read(); + + // if the incoming character is a newline, set a flag + // so we can + if ( serial_input_buffer[serial_input_buffer_index] == '\n' + || serial_input_buffer[serial_input_buffer_index] == '\0' + || serial_input_buffer_index == SERIAL_INPUT_MAX_LENGTH + ) { + serial_input_buffer_complete = true; + serial_input_buffer[serial_input_buffer_index] = '\0'; + break; + } + + // Increase the index + serial_input_buffer_index++; + } + + if ( serial_input_buffer_complete ) { + handleInputBuffer( serial_input_buffer ); + + // Reset flag and buffer + serial_input_buffer_complete = false; + serial_input_buffer_index = 0; + } +} + +/* + * Handle a command, make sure this is short as serialEvent() uses this function + */ +void handleInputBuffer( const char* input_buffer ){ + // Handle Incoming Line + for ( int i = 0; i < STR_MAX_LENGTH ; i++ ) { + // Stop copying when null character found. + if ( input_buffer[i] == '\0' || input_buffer[i] == '\n') { + break; + } + + line_buffer[line_buffer_write][i] = input_buffer[i]; + } + + line_buffer_write = ((line_buffer_write + 1 ) % LINE_BUFFER_SIZE ); +} diff --git a/serial_text_scroller/serial_text_scroller.ino b/serial_text_scroller/serial_text_scroller.ino new file mode 100644 index 0000000..450b0e0 --- /dev/null +++ b/serial_text_scroller/serial_text_scroller.ino @@ -0,0 +1,107 @@ +/* + Have a Serial connection send lines to be displayed on a screen / display. + If the display is too small, scroll the text along the display. +*/ + +#define BAUD_RATE 9600 +#define STR_MAX_LENGTH 20 +#define LINE_BUFFER_SIZE 4 + + +void initDisplay(); +void updateDisplay( const unsigned int tick ); +void serialEvent(); + + +char line_buffer[LINE_BUFFER_SIZE][STR_MAX_LENGTH + 1] = {// Small Ringbuffer to collect lines + "Liquid Crystal Boob", + "Captain", + "Pilot", + "Snippy" +}; +int line_buffer_read = 0; // Index of Ringbuffer +int line_buffer_write = 0; // Index of Ringbuffer + +const unsigned int timer_lps = 1000; +const unsigned int timer_display = 1000; +const unsigned int timer_print_line_buffers = 10000; +const unsigned int timer_switch_line_buffer = timer_print_line_buffers; + +long lastMillis_lps = 0; +long lastMillis_display = 0; +long lastMillis_switch_line_buffer = 0; +long lastMillis_print_line_buffers = 0; + +long loops = 0; +long lps = 0; + +void setup() { + Serial.begin(BAUD_RATE); + initDisplay(); +} + +void loop() { + long currentMillis = millis(); + loops++; + + // Estimate Loops per Seconds + if ( currentMillis - lastMillis_lps > timer_lps ) { + lastMillis_lps = currentMillis; + + lps = loops; + loops = 0; + } + + // Update Screen once per 1s + if ( currentMillis - lastMillis_display > timer_display ) { + lastMillis_display = currentMillis; + + updateDisplay( (currentMillis / 1000) ); + } + + // Display next line in line_buffer + if ( currentMillis - lastMillis_switch_line_buffer > timer_switch_line_buffer ) { + lastMillis_switch_line_buffer = currentMillis; + + line_buffer_read = (line_buffer_read + 1 ) % LINE_BUFFER_SIZE; + } + + // Print all Line Buffers once every 10 seconds + if ( currentMillis - lastMillis_print_line_buffers > timer_print_line_buffers ) { + lastMillis_print_line_buffers = currentMillis; + + Serial.println(F("=========================")); + Serial.println(F("Printing all Line buffers")); + Serial.println(F("=========================")); + + for (int i = 0; i < LINE_BUFFER_SIZE ; i++) { + if ( line_buffer_read == i ) + { + Serial.print('r'); + } + else + { + Serial.print(' '); + } + + if ( line_buffer_write == i ) + { + Serial.print('w'); + } + else + { + Serial.print(' '); + } + + Serial.print(" Line "); + Serial.print( i ); + Serial.print(": '"); + Serial.print( line_buffer[i] ); + Serial.print("' "); + + Serial.println(); + } + Serial.println(F("=========================")); + } + +}