diff --git a/src/list b/src/list new file mode 160000 index 0000000..23faa20 --- /dev/null +++ b/src/list @@ -0,0 +1 @@ +Subproject commit 23faa20d03b67d752e1f882f0832c941a942c75b diff --git a/testline.c b/testline.c new file mode 100644 index 0000000..fed75c0 --- /dev/null +++ b/testline.c @@ -0,0 +1,213 @@ +#include +#include +#include "src/list/src/list.h" + +/* +typedef struct InfoState { + char* info; + int len; + int fullLines; + int Nlines; + int lastlinelen; + char *pos1, *pos2, *pos3; + list_t* wrap; +} InfoState; + +void initInfoState(InfoState* st, char* text) { + st->info = text; + st->len = strlen(text); + st->fullLines = st->len / 15; + st->Nlines = (st->len + 14) / 15; + st->lastlinelen = st->len % 15; + st->pos1 = text; + st->pos2 = text; + st->pos3 = text; + st->wrap = list_new(); + char* tmp = text; + //list_node_t *c = list_rpush(st->wrap, list_node_new("c")); +} + +void lcd_blank_line() { + for (int i = 0; i < 15; ++i) { + lcd.print(' '); + } +} + +void initInfoScreen(InfoState* st, char* text) { + initInfoState(st, text); + lcd.setCursor(0, 0); + if (*(st->pos1) == '\n' || *(st->pos1) == '\r') { + lcd_blank_line(); + ++st->pos1; + ++st->pos2; + } else { + st->pos2 += lcd_print_line(st->pos1); + } + lcd.setCursor(0, 1); + if ((*(st->pos2) == '\n' || *(st->pos2) == '\r') && *(st->pos2 - 1) == *(st->pos2)) { + lcd_blank_line(); + } else { + lcd_print_line(st->pos2); + } +#ifdef DEBUG + //Serial.println(String("pos1: ") + st->pos1); + //Serial.println(String("pos2: ") + st->pos2); + Serial.println("init"); + Serial.print(st->pos1-st->info); + Serial.println(String(" ")+(st->pos2-st->info)); +#endif +} +*/ + +list_t* aux_gen_wrap_list(list_t* wrap, char* text) { + if (wrap == NULL) { + wrap = list_new(); + } + char* curr = text; + int suf = 0; + list_node_t *node; + if (list_rpush(wrap, list_node_new(0)) == NULL) { + return NULL; + } + while (*curr != '\0') { + //printf("suf: %d\tpos: %d\n", suf, (unsigned int)(curr-text)); + if (suf < 15) { + if (*curr != '\n' && *curr != '\r') { + ++suf; + } else { + if (list_rpush(wrap, list_node_new((unsigned int)(curr-text))) == NULL) { + return NULL; + } + suf = 0; + } + } else { + if (list_rpush(wrap, list_node_new((unsigned int)(curr-text))) == NULL) { + return NULL; + } + suf = (*curr != '\n' && *curr != '\r') ? 1 : 0; + } + ++curr; + } + return wrap; +} + +/* + Separate a substring that can be printed on one line, and return the + original string position corresponding to the end of the substring. + */ +/* +char* aux_sub_line(char* str, char substr[16]) { + int suf = 0; + char* curr = str; + memset(substr, 0, 16); + + while (*curr != '\0' && suf < 15) { + if (*curr != '\n' && *curr != '\r') { + substr[suf++] = *(curr++); + //++curr; + } else + if (curr == str){ ++curr; } else + { + break; + } + } + +//#if !REFRESH + while (suf < 15) { + substr[suf++] = ' '; + } +//#endif + return curr; +} + +char* aux_sub_line_rev(char* str, char substr[16]) { + int suf = 0; + char* curr = str; + memset(substr, 0, 16); + + while (*curr != '\0' && suf < 15) { + if (*curr != '\n' && *curr != '\r') { + substr[suf++] = *(curr--); + } else + if (curr == str){ --curr; } else + { + break; + } + } + + { + int i = 0; + int j = suf - 1; + while (i < j) { + char temp = substr[i]; + substr[i] = substr[j]; + substr[j] = temp; + i++; + j--; + } + } + +//#if !REFRESH + while (suf < 15) { + substr[suf++] = ' '; + } +//#endif + return curr+1; +} +*/ + +int main() { + char* cinfo = "Far far away, a\n\nbehind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts."; + + list_t *wrap = list_new(); + wrap = aux_gen_wrap_list(wrap, cinfo); + + list_node_t *node; + list_iterator_t *it = list_iterator_new(wrap, LIST_HEAD); + + + while ((node = list_iterator_next(it))) { + printf("%d\n", (unsigned int)(node->val)); + } + + /* + if ((node = list_iterator_next(it))) { + char* p = cinfo; + list_node_t *test; + while (*p != '\0') { + //printf("node->val: %d\n", node->val); + if (p - cinfo != node->val) { + printf("%c", *p); + //printf("%d %d\n", (unsigned int)(p - cinfo), (unsigned int)(node->val)); + } else { + printf("|\n"); + if (*p != '\n' && *p != '\r') { + printf("%c", *p); + } + if ((test = list_iterator_next(it))) { + node = test; + } + } + ++p; + } + } else { + printf("%s", cinfo); + } + */ + /* + char line[16]; + char* pos = aux_sub_line(cinfo, line); + printf("%d\n%s\n", pos-cinfo, line); + for (int i = 0; i < 4; ++i) { + pos = aux_sub_line(pos, line); + printf("%d\n%s\n", pos-cinfo, line); + } + for (int i = 0; i < 4; ++i) { + pos = aux_sub_line_rev(pos-1, line); + printf("%d\n%s\n", pos-cinfo, line); + } + */ + list_iterator_destroy(it); + list_destroy(wrap); + return 0; +} \ No newline at end of file diff --git a/testline.ino b/testline.ino new file mode 100644 index 0000000..3984b6d --- /dev/null +++ b/testline.ino @@ -0,0 +1,341 @@ +#include +#include +#include "src/list/src/list.h" + +LiquidCrystal lcd(12, 11, 5, 4, 3, 2); + +//#define REFRESH 1 +#define DEBUG + +uint8_t up_arrow[8] = {0x04,0x0E,0x1F,0x1F,0x00,0x00,0x00,0x00}; +uint8_t down_arrow[8] = {0x00,0x00,0x00,0x1F,0x1F,0x0E,0x04,0x04}; + +typedef struct InfoState { + char* info; + int len; + int fullLines; + int Nlines; + int lastlinelen; + char *pos1, *pos2, *pos3; + list_t *wrap; + list_iterator_t *it; +} InfoState; + +void setup() { + Serial.begin(9600); + lcd.begin(16, 2); + lcd.createChar(0, up_arrow); + lcd.createChar(1, down_arrow); + lcd.setCursor(0, 0); + lcd.print("..............."); + lcd.setCursor(0, 1); + lcd.print("..............."); +} + +void loop() { + char* cinfo = "Far far away, a\n\nbehind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts."; + //String info = "hello,`world!wwwwwwwwwwwwwwww"; + InfoState st; + initInfoScreen(&st, cinfo); + +#ifdef DEBUG + Serial.println(String("len: ") + st.len); +#endif + +#ifdef DEBUG + Serial.println("down"); +#endif + for (int i = 0; i < 3; ++i) { + delay(1000); + scrollDown(&st); + } + +#ifdef DEBUG + Serial.println("up"); +#endif + for (int i = 0; i < 5; ++i) { + delay(1000); + scrollUp(&st); + } + +#ifdef DEBUG + Serial.println("down2"); +#endif + for (int i = 0; i < 3; ++i) { + delay(1000); + scrollDown(&st); + } + +#ifdef DEBUG + Serial.println("up2"); +#endif + for (int i = 0; i < 5; ++i) { + delay(1000); + scrollUp(&st); + } + + delay(3000); +} + +list_t* aux_gen_wrap_list(list_t* wrap, char* text) { + if (wrap == NULL) { + wrap = list_new(); + } + char* curr = text; + int suf = 0; + list_node_t *node; + if (list_rpush(wrap, list_node_new(0)) == NULL) { + return NULL; + } + while (*curr != '\0') { + //printf("suf: %d\tpos: %d\n", suf, (unsigned int)(curr-text)); + if (suf < 15) { + if (*curr != '\n' && *curr != '\r') { + ++suf; + } else { + if (list_rpush(wrap, list_node_new((unsigned int)(curr-text))) == NULL) { + return NULL; + } + suf = 0; + } + } else { + if (list_rpush(wrap, list_node_new((unsigned int)(curr-text))) == NULL) { + return NULL; + } + suf = (*curr != '\n' && *curr != '\r') ? 1 : 0; + } + ++curr; + } + if (list_rpush(wrap, list_node_new(strlen(text))) == NULL) { + return NULL; + } + return wrap; +} + +void initInfoState(InfoState* st, char* text) { + st->info = text; + st->len = strlen(text); + st->fullLines = st->len / 15; + st->Nlines = (st->len + 14) / 15; + st->lastlinelen = st->len % 15; + st->pos1 = text; + st->pos2 = text; + st->pos3 = text; + st->wrap = list_new(); + st->wrap = aux_gen_wrap_list(st->wrap, st->info); + st->it = list_iterator_new(st->wrap, LIST_HEAD); +} + +void initInfoScreen(InfoState* st, char* text) { + initInfoState(st, text); + lcd.setCursor(0, 0); + + /* + if (*(st->pos1) == '\n' || *(st->pos1) == '\r') { + lcd_blank_line(); + ++st->pos1; + ++st->pos2; + } else { + st->pos2 += lcd_print_line(st->pos1); + } + lcd.setCursor(0, 1); + if ((*(st->pos2) == '\n' || *(st->pos2) == '\r') && *(st->pos2 - 1) == *(st->pos2)) { + lcd_blank_line(); + } else { + lcd_print_line(st->pos2); + } +#ifdef DEBUG + //Serial.println(String("pos1: ") + st->pos1); + //Serial.println(String("pos2: ") + st->pos2); + Serial.println("init"); + Serial.print(st->pos1-st->info); + Serial.println(String(" ")+(st->pos2-st->info)); +#endif + */ +} + + +void scrollDown(InfoState* st) { + st->pos1 = st->pos2; + lcd.setCursor(0, 0); + if ((*(st->pos1) == '\n' || *(st->pos1) == '\r') && *(st->pos1 - 1) == *(st->pos1)) { + lcd_blank_line(); + ++st->pos1; + ++st->pos2; + } else { + st->pos2 += lcd_print_line(st->pos1); + } + lcd.setCursor(0, 1); + if ((*(st->pos2) == '\n' || *(st->pos2) == '\r') && *(st->pos2 - 1) == *(st->pos2)) { + lcd_blank_line(); + } else { + lcd_print_line(st->pos2); + } +#ifdef DEBUG + //Serial.println(String("pos1: ") + st->pos1); + //Serial.println(String("pos2: ") + st->pos2); + Serial.print(st->pos1-st->info); + Serial.println(String(" ")+(st->pos2-st->info)); +#endif +} + +void scrollUp(InfoState* st) { + if (st->pos1 > st->info) { + st->pos2 = st->pos1; + int i = 1; + int va = 1; + /* + int bound = min(st->pos1, 15); + Serial.println(String("bound: ")+bound); + while (i < bound) { + if (st->info[st->pos1-i] != '\n' && st->info[st->pos1-i] != '\r') { + ++i; + } else + if (i == 1){ ++i; ++bound; } else + { + break; + } + } + */ + + /* + while (i < st->pos1-st->info && va < 15) { + if (st->info[st->pos1-i] != '\n' && st->info[st->pos1-i] != '\r') { + ++i; + ++va; + } else + if (i == 1){ ++i; } else + { + break; + } + } + + st->pos1 -= i; + */ + bool is_blank = false; + while (st->pos1 > st->info && va <= 15) { + if (*(st->pos1) != '\n' && *(st->pos1) != '\r') { + ++i; + ++va; + } else if (*(st->pos1 - 1) == *(st->pos1)) { + is_blank = true; + --st->pos1; + break; + } + --st->pos1; + } + while (st->pos1 > st->info && (*(st->pos1) == '\n' || *(st->pos1) == '\r')) { + --st->pos1; + } + //st->pos1 -= i; + + lcd.setCursor(0, 0); + if (is_blank) { + lcd_blank_line(); + } else { + lcd_print_line(st->pos1); + } + lcd.setCursor(0, 1); + if ((*(st->pos2) == '\n' || *(st->pos2) == '\r') && *(st->pos2 - 1) == *(st->pos2)) { + lcd_blank_line(); + } else { + lcd_print_line(st->pos2); + } + } +#ifdef DEBUG + //Serial.println(String("pos1: ") + st->pos1); + //Serial.println(String("pos2: ") + st->pos2); + Serial.print(st->pos1-st->info); + Serial.println(String(" ")+(st->pos2-st->info)); +#endif +} + +int lcd_print_line(char* str) { + int i = 0; + int va = 0; + /* + int bound = min(strlen(str), 15); + while (i < bound) { + if (str[i] != '\n' && str[i] != '\r') { + lcd.print(str[i++]); + } else + if (i == 0){ ++i; ++bound;} else + { + break; + } + } + */ + int slen = strlen(str); + while (i < slen && va < 15) { + if (str[i] != '\n' && str[i] != '\r') { + lcd.print(str[i++]); + ++va; + } else + if (i == 0){ ++i; } else + { + break; + } + } + + if (va < 15) { +#if !REFRESH + for (int j = 15 - va; j > 0; --j) { + lcd.print(' '); + } +#endif + ++i; + } + return i; +} + +/* + Separate a substring that can be printed on one line, and return the + original string position corresponding to the end of the substring. + */ +/* +char* aux_sub_line(char* str, char substr[16]) { + int suf = 0; + char* curr = str; + memset(substr, 0, 16); + + while (*curr != '\0' && suf < 15) { + if (*curr != '\n' && *curr != '\r') { + substr[suf++] = *(curr++); + } else + if (curr == str){ ++curr; } else + { + break; + } + } + +#if !REFRESH + while (suf < 15) { + substr[suf++] = ' '; + } +#endif + return curr; +} + +char* aux_sub_line_rev(char* str, char substr[16]) { + int suf = 0; + char* curr = str; + memset(substr, 0, 16); + + while (*curr != '\0' && suf < 15) { + if (*curr != '\n' && *curr != '\r') { + substr[suf++] = *(curr--); + } else + if (curr == str){ --curr; } else + { + break; + } + } + + +} +*/ +void lcd_blank_line() { + for (int i = 0; i < 15; ++i) { + lcd.print(' '); + } +}