Jump to content

    
Salamander

Как скопировать символы из обычного буфера в массив строк?

Recommended Posts

Зачем вообще что-то копировать и перемещать? Скролинг делается "скролингом" индекса. Я не знаю как у вас меняется индекс (кол-во) принятых строк 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 всегда будет указывать на последнюю принятую строку. не нужно ни каких адски сдвигов массивов с текстом, не будет ни какой нагрузки на МК.

Edited by razrab83

Share this post


Link to post
Share on other sites
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 раза быстрее.... помните про выравнивание

Share this post


Link to post
Share on other sites
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 строку, она запишется в третий элемент массива. А  чтобы вывести список строк, нам нужно читать с четвёртого по сотый, а дельше нулевой, первый и второй. И так далее. Я правильно понял? 

Share this post


Link to post
Share on other sites
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)

Edited by razrab83

Share this post


Link to post
Share on other sites
18 minutes ago, razrab83 said:

int j = i + str_buffer_write_position%100;

А зачем тут то остаток получать? Str_buffer_write_position  на данном этапе гарантированно будет обнуляться после ста, за счёт предшествующего кода. 

Share this post


Link to post
Share on other sites

я ни где в коде не увидел (не писал)

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 не нужно. 

Edited by razrab83

Share this post


Link to post
Share on other sites
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 - заботится и о выравнивании и о скорости

Share this post


Link to post
Share on other sites
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. И тогда работает. Но  после заполнения экрана скроллинга нет по понятным причинам.

Я конечно могу сделать проверку, поставить некий флажок после заполнения экрана, по срабатыванию которого меняется алгоритм, но мне это кажется "костылем". Хочется сделать изящно.... И не дает покоя мысль, что где-то ошибка, которую можно без костыля решить.

ЧТо думаете?

    
    

Share this post


Link to post
Share on other sites
9 часов назад, Salamander сказал:

уже неактуально. решил.

Нехорошо так заканчивать тему. С Вами тут две страницы обсуждали проблему, с которой Вы пришли. Потрудились бы хоть в общих чертах сообщить, в чём же именно она состояла и как удалось решить.

Share this post


Link to post
Share on other sites
35 minutes ago, Herz said:

Потрудились бы хоть в общих чертах сообщить, в чём же именно она состояла и как удалось решить.

Решил костылем. Просто понял, что проблема действительно не имеет чисто математического решения. Заполнял экран, сверху вниз, а опосля включал скроллинг.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.