razrab83 21 9 апреля, 2021 Опубликовано 9 апреля, 2021 (изменено) · Жалоба Зачем вообще что-то копировать и перемещать? Скролинг делается "скролингом" индекса. Я не знаю как у вас меняется индекс (кол-во) принятых строк str_buffer_write_position. Допустим изменятеся от 0 до 10000000000000000000000000000000000. тогда #define RX_BUFFER_SIZE 256 uint8_t rx_buffer[RX_BUFFER_SIZE]; char TERMINAL_TEXT[100][256]; for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[str_buffer_write_position%100][i]=rx_buffer[i]; и ни чего, при появлении 101-ой строки ни куда не нужно перекопировать. последняя строка всегда str_buffer_write_position%100 можно, для читаемости кода так #define RX_BUFFER_SIZE 256 uint8_t rx_buffer[RX_BUFFER_SIZE]; char TERMINAL_TEXT[100][256]; static int index = 0; index = str_buffer_write_position%100; for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[index][i]=rx_buffer[i]; for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[str_buffer_write_position][i]=rx_buffer[i]; У вас же не каконить ПК с говновиндой, у вас МК со всеми потрахами. Зачем какие-то memmove и т.п.? Используйте DMA. ps сделайте буфер размером степень 2, т.е. 128 или 64. Тогда #define RX_BUFFER_SIZE 256 uint8_t rx_buffer[RX_BUFFER_SIZE]; char TERMINAL_TEXT[128][256]; static int index = 0x7f; //при получении новой строки инкремент индекса ++index &= 0x7f; //или (128-1), или (64-1) //for(uint8_t i=0;i<255;i++) // TERMINAL_TEXT[index][i]=rx_buffer[i]; memcpy(&TERMINAL_TEXT[index][0], rx_buffer, 255); у вас index всегда будет указывать на последнюю принятую строку. не нужно ни каких адски сдвигов массивов с текстом, не будет ни какой нагрузки на МК. Изменено 9 апреля, 2021 пользователем razrab83 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 9 апреля, 2021 Опубликовано 9 апреля, 2021 · Жалоба char TERMINAL_TEXT[128][256]; ++index &= 0x7f; //или (128-1), или (64-1) uint32_t *pOut = (uint32_t *)&TERMINAL_TEXT[index][0]; uint32_t *pInt = (uint32_t *)rx_buffer; for(uint8_t i=0;i<64;i++) //копируем 256 байт pOut[i] = pInt[i]; ps в 4 раза быстрее.... помните про выравнивание Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 9 апреля, 2021 Опубликовано 9 апреля, 2021 · Жалоба 1 hour ago, razrab83 said: for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[str_buffer_write_position%100][i]=rx_buffer[i]; Я понял в чем ваша идея. Я, по глупости, переписывался содержимое всего массива. Нулевой элемент затирал первыпэм, первый затирал вторым... последний - новым. И так 100 раз. Вы же предлагаете затирать новым элементом самый старый элемент. А чтобы не переписывать все остальные, просто сдвигать фокус чтения и нумероватт элементы от этого самого фокуса. То есть, скажем, получили мы 103 строку, она запишется в третий элемент массива. А чтобы вывести список строк, нам нужно читать с четвёртого по сотый, а дельше нулевой, первый и второй. И так далее. Я правильно понял? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 9 апреля, 2021 Опубликовано 9 апреля, 2021 (изменено) · Жалоба 12 минут назад, Salamander сказал: Я понял в чем ваша идея. Я, по глупости, переписывался содержимое всего массива. Нулевой элемент затирал первыпэм, первый затирал вторым... последний - новым. И так 100 раз. Вы же предлагаете затирать новым элементом самый старый элемент. А чтобы не переписывать все остальные, просто сдвигать фокус чтения и нумероватт элементы от этого самого фокуса. То есть, скажем, получили мы 103 строку, она запишется в третий элемент массива. А чтобы вывести список строк, нам нужно читать с четвёртого по сотый, а дельше нулевой, первый и второй. И так далее. Я правильно понял? Да! При этом, скорость "скролинга" не будет зависить от размера строкового буфера. Хоть буфер на 5 строк, хоть на 100 строк, хоть на 65000 строк. Вывод начиная с самой старой строки for(int i = 0; i<100; i++) { int j = i + str_buffer_write_position%100; if( j > 99) j -= 100; printf(&TERMINAL_TEXT[j][0]); } как-то так (только "100" заменть на define) Изменено 9 апреля, 2021 пользователем razrab83 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 9 апреля, 2021 Опубликовано 9 апреля, 2021 · Жалоба 18 minutes ago, razrab83 said: int j = i + str_buffer_write_position%100; А зачем тут то остаток получать? Str_buffer_write_position на данном этапе гарантированно будет обнуляться после ста, за счёт предшествующего кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 9 апреля, 2021 Опубликовано 9 апреля, 2021 (изменено) · Жалоба я ни где в коде не увидел (не писал) str_buffer_write_position = .... Переменная str_buffer_write_position измениться только после оператора "=". for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[str_buffer_write_position%100][i]=rx_buffer[i]; Тут str_buffer_write_position делится на 100, остаток от деления используется в качестве индекса массива, но сама переменная str_buffer_write_position не меняется. Если у вас где-то в коде str_buffer_write_position обнуляется, то тогда дополнительно в выводе %100 не нужно. Изменено 9 апреля, 2021 пользователем razrab83 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 9 апреля, 2021 Опубликовано 9 апреля, 2021 · Жалоба 1 час назад, juvf сказал: char TERMINAL_TEXT[128][256]; ++index &= 0x7f; //или (128-1), или (64-1) uint32_t *pOut = (uint32_t *)&TERMINAL_TEXT[index][0]; uint32_t *pInt = (uint32_t *)rx_buffer; for(uint8_t i=0;i<64;i++) //копируем 256 байт pOut[i] = pInt[i]; ps в 4 раза быстрее.... помните про выравнивание memcpy - заботится и о выравнивании и о скорости Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 10 апреля, 2021 Опубликовано 10 апреля, 2021 · Жалоба On 4/9/2021 at 3:39 PM, razrab83 said: Если у вас где-то в коде str_buffer_write_position обнуляется, то тогда дополнительно в выводе %100 не нужно. Действительно, обнуляется. Ваш код (я уменьшил число строк до 15 для удобства) for(int i = 0; i<100; i++) { int j = i + str_buffer_write_position; if( j > 14) j -= 15; printf(&TERMINAL_TEXT[j][0]); } работает отлично. Если понаблюдать отладчиком то имеем полноценный кольцевой буфер. Но.... блин, вроде задача простая, а я что-то мозг весь сломал. Проблемы начинаются при чтении этого буфера. Хочу чтобы выглядело так - получили первую строку - она вывелась первой, получили вторую строку - на экране ниже первой появилась вторая, ну как при печати. А когда экран заполнен (15 строк) начинается скроллинг. По факту имеем следующее - получаем нулевую строку - она появляется в последней строке экрана, получаем следующую строку - нулевая перескакивает выше, внизу появляется новая. Если непонятно - я хочу, чтобы выглядело как при печати текста, а выглядит как финальные титры фильма. Почему так получается? Смотрите, получена первая строка, str_buffer_write_position=1. Начинаем выводить, заполняем первую строку дисплея. i=0, тогда j = i + str_buffer_write_position дает нам "1". И программа читает строку не из нулевого элемента массива, а из первого, а там пусто. И так дальше. И лишь когда мы выводим последнюю строку, у нас срабатывает if( j > 14) j -= 15; и мы получаем "указатель" на нулевой элемент массива. Логичная попытка сделать j = i + str_buffer_write_position -1 (уменьшили на единицу) - это работает только на первой строке. Как только появляется следующая строка, str_buffer_write_position увеличивается до 2 и тогда уже нужно отнимать 2. По сути - до того как экран заполнится полностью, j = i + str_buffer_write_position нужно заменить на j=i. И тогда работает. Но после заполнения экрана скроллинга нет по понятным причинам. Я конечно могу сделать проверку, поставить некий флажок после заполнения экрана, по срабатыванию которого меняется алгоритм, но мне это кажется "костылем". Хочется сделать изящно.... И не дает покоя мысль, что где-то ошибка, которую можно без костыля решить. ЧТо думаете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 10 апреля, 2021 Опубликовано 10 апреля, 2021 · Жалоба уже неактуально. решил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 11 апреля, 2021 Опубликовано 11 апреля, 2021 · Жалоба 9 часов назад, Salamander сказал: уже неактуально. решил. Нехорошо так заканчивать тему. С Вами тут две страницы обсуждали проблему, с которой Вы пришли. Потрудились бы хоть в общих чертах сообщить, в чём же именно она состояла и как удалось решить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 11 апреля, 2021 Опубликовано 11 апреля, 2021 · Жалоба 35 minutes ago, Herz said: Потрудились бы хоть в общих чертах сообщить, в чём же именно она состояла и как удалось решить. Решил костылем. Просто понял, что проблема действительно не имеет чисто математического решения. Заполнял экран, сверху вниз, а опосля включал скроллинг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 15 апреля, 2021 Опубликовано 15 апреля, 2021 · Жалоба Друзья еще вопрос. Нашел готовую функцию разбиения строки на подстроки по разделителю #include "stdio.h" #include "stdlib.h" #include "string.h" #include <assert.h> char** str_split(char* a_str, const char a_delim) { char** result = 0; size_t count = 0; char* tmp = a_str; char* last_comma = 0; char delim[2]; delim[0] = a_delim; delim[1] = 0; /* Count how many elements will be extracted. */ while (*tmp) { if (a_delim == *tmp) { count++; last_comma = tmp; } tmp++; } /* Add space for trailing token. */ count += last_comma < (a_str + strlen(a_str) - 1); /* Add space for terminating null string so caller knows where the list of returned strings ends. */ count++; result = malloc(sizeof(char*) * count); if (result) { size_t idx = 0; char* token = strtok(a_str, delim); while (token) { assert(idx < count); *(result + idx++) = strdup(token); token = strtok(0, delim); } assert(idx == count - 1); *(result + idx) = 0; } return result; } Проект с этой функцией компилируется, то есть никаких неизвестных функций в коде нет. Но вот при линковке получаю "Error: L6218E: Undefined symbol strdup (referred from main.o)." Блин... почему так? Стандартные же библиотеки, include прописаны, чего еще не хватает? у меня KEIL, если что. в string.h прототип strdup не описан. Я понимаю, что код писался под навороченные компиляторы и библиотеки к ним, а в KEIL они урезанные что ли.... но чем заменить эту функцию тогда? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aleksandr Baranov 1 15 апреля, 2021 Опубликовано 15 апреля, 2021 · Жалоба А функция strtok Вам не пригодится? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Salamander 2 15 апреля, 2021 Опубликовано 15 апреля, 2021 · Жалоба 12 minutes ago, Aleksandr Baranov said: А функция strtok Вам не пригодится? Хм.. Вы указали на функцию, которая вызывается в той функции, что я привёл. Что скажете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aleksandr Baranov 1 15 апреля, 2021 Опубликовано 15 апреля, 2021 (изменено) · Жалоба Ах. прошу прощения. Просмотрел по диагонали и не заметил. У меня в IAR есть strdup, но, в принципе, его можно заменить на strcpy, слегка изменив программу. Изменено 15 апреля, 2021 пользователем Aleksandr Baranov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться