TFT на базе ST7735

ptr
Offline
Зарегистрирован: 28.05.2016

А никто не пробовал читать из фреймбуфера дисплея на базе ST7735 при помощи AVR-овского MSPIM? Именно хардверным SPI, не программным.

 

ptr
Offline
Зарегистрирован: 28.05.2016

Неужели никому не надо было спрайты по экрану гонять? Народ! Красиво же! А без чтения фреймбуфера никакой оперативки не хватит.

 

diger67
Offline
Зарегистрирован: 25.07.2015

Э, наскольео я помню у большинства TFT буффером является регисры ввода/вывода, тоесть 16 бит и/или 8 бит, зависит от IM0 - 3. Судя по построению библиотек для TFT под AVR все делает м/к. Редкие TFT имеют две страници памяти и можно перед сменой экрана записывать невидимую страницу, а потом давать команду на ее отображение. Самый распрастраненный вариант это обновление определенной области. Если надо гонять по экрану спрайт,  то затирают нужным спрайтом старую и выводят в новую. Если вы ведете речь о работе с TFT без использования встоенной памяти матрицы, то в этом случае все определяется объемом внешней памяти и алгоритмом програмы. Только с чего вы взяли что 7735 может работать с внешней памятью в даташите про это ни слово.

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

Только с чего вы взяли что 7735 может работать с внешней памятью в даташите про это ни слово.

При чем тут внешняя память? На борту у ST7735 есть фреймбуфер размером в 384 килобита. Именно в нем хранится отображаемое изображение в формате 18 бит на пиксель. То есть, в каком бы формате (12/16/18 бит на пиксель) мы не писали, там будет все равно пересчитанное в 18 бит на пиксель. Для чтения фреймбуфера есть команда RAMRD, позволяющая считать и передать в МК содержимое любого прямоугольника, любого размера в любом месте фреймбуфера.

Если мы работаем со спрайтом, то у нас два варианта:

1. Хранить копию фреймбуфера в памяти МК, восстанавливая на экране пиксели, ранее затертые спрайтом, используя эту копию. Это не наш путь, так как даже в случае 12 битного цвета для этого нужны будет десятки килобайт оперативки, которых у нас нет.

2. Перед рисованием спрайта, считывать из фрейбуфера только затираемые точки и хранить только их. При адекватном размере спрайта, например 16*16 это потребует 384 байта оперативки, что уже приемлемо. Вот только читать что-либо из ST7735 у меня пока получается только программным SPI.

Если коротко, суть задачи, двигать спрайт незначительного размера по экрану на фоне картинки, например, загруженной с SD карты. Проблема в том, что SPI то один, и если переключаться на SD карту для чтения части картинки при каждом передвижении спрайта, спрайт будет двигаться очень медленно. Ну и считывать с SD нужно будет намного больше, чем с фреймбуфера. Для экрана 128*160 с 16-ти битным цветом и спрайта 16*16 с SD нужно будет считать либо 4Кб одним запросом, либо по 32 байта 16-тью запросами. Тогда как из фреймбуфера в самом худшем случае, мы считываем только 768 байт, при перемещении спрайта на 1 пиксель по вертикали или горизонтали всего 48 байт и по диагонали двумя запросами 48 и 45 байт. Выгода очевидна.

 

diger67
Offline
Зарегистрирован: 25.07.2015

Да все перкрасно понятно о чем вы говорите, эти грабри разложены для всех желающих любителей 8-ми битных контроллеров. Тут даже 16 бит параллельный интерфейс не спасет все будет тормозить. По этой причине и перешел на 32 разрядный камень, только и это не панацея, сижу оптимизирую библиотеку. Вобщем тут нужен другой алгоритм, считываем с полями запаса на передвижение спрайта из CD область фона и  делаем наложение спрайта, выводим в указанную область экрана. В большинстве TFT можно сделать активной любую область, тогда можно не заморачиваясь выводить байт за байтомуказав только (x, y). Помойму самый оптимальный алгоритм. Вот что пока получилось на частоте такта 72МГц .   http://178.130.34.198/tft_002.mp4

 

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

Вобщем тут нужен другой алгоритм, считываем с полями запаса на передвижение спрайта из CD область фона и  делаем наложение спрайта, выводим в указанную область экрана. В большинстве TFT можно сделать активной любую область, тогда можно не заморачиваясь выводить байт за байтомуказав только (x, y). Помойму самый оптимальный алгоритм. Вот что пока получилось на частоте такта 72МГц . 

Про это все я в курсе. В свое время делал аналогичное на Z80. Указывается не только точка начала, но и точка конца (диагональной вершины прямоугольника), что я и писал выше.. На самом деле даже на этом тормозе, при частоте SPI в 500КГц я успевал выводить спрайт размером 16х16 по tearing. То есть с частотой 60 кадров в секунду. А так как AVR поддерживает частоту SPI до 8МГц, есть шансы увеличить размер спрайта до 64х64, что более чем достаточно. А спрайт 16х16 при этом можно успеть вывести вообще только за время Vsync. Другое дело, что стандартные библиотеки ардуино настолько тормозные, что с их помощью и 16x16 на 4МГц SPI не успеваю вывести. А tearing вывода на моем TFT вообще нет, то есть его можно контролировать только считывая регистр из ST7735, что стандартные библиотеки вообще не позволяют и мы снова возвращаемся к возможности считывания из ST7735.

Ну а SPI бибилиотеку при любом раскладе переписывать для симлексного обмена, чтобы все же использовать буферизацию SPI в AVR, и в функции передачи байта ждать только, пока не освободится буфер трансмиттера, а не пока байт будет передан.

Кстати, судя по видео, tearing Вы не контролируете. А для динамических объектов это необходимо.

 

ptr
Offline
Зарегистрирован: 28.05.2016

На всякий случай уточню, что на Z80 я выводил на обычный телевизор с кинескопом, накладывая рекламу на выводимое изображение в формате NTSC - 60 полукадров в секунду.

diger67
Offline
Зарегистрирован: 25.07.2015

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

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

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

А я не с видопамятью на Z80 работал, а с тупой платой без МК по последовательной шине. На плате было 4 РУ6 фреймбуфера. В него и писал. И на Z80 стандартных библиотек не было у меня вообще. Ноль. Все что было - сам же и написал.

 

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

А я не с видопамятью на Z80 работал, а с тупой платой без МК по последовательной шине. На плате было 4 РУ6 фреймбуфера. В него и писал. И на Z80 стандартных библиотек не было у меня вообще. Ноль. Все что было - сам же и написал.

Да ну, а что по вашему эти 4 РУ6. Это и есть видеопамять, а передней на мультиплексорах собран модуль реализующий алгоритм чтение - модификация - запись.

ptr
Offline
Зарегистрирован: 28.05.2016

Читать фреймбуфер удалось, но плохо. На частоте в 1МГц читает стабильно. Но мне надо на 8МГц и через USART, чтобы была буферизация передачи. А уже на 4 МГц периодически, прет 0 вместо 1 от ST7735. Ну не тянет, бедолага, еще и USB2COM конвертер через 1К резистор (

Буду ждать Pro Mini из Китая. Продолжу эксперименты уже на ней.

 

 

ptr
Offline
Зарегистрирован: 28.05.2016

Удалось таки )
https://goo.gl/photos/xTjyYRWKER5nRCcg7

sslobodyan
Offline
Зарегистрирован: 28.09.2016

Интересно какой модуль экрана использован и как подключен. Ну и глянуть бы на скетч, если не комтайна. Сам сейчас играюсь с похожим экранчиком по SPI, только управляющий STM32. Нужно будет реализовать сдвиг части экрана влево-право на пару пикселей. У используемой библиотеки такой функционал отсутствует, так что пока храню фреймбуфер в контроллере. 

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

Удалось таки )
https://goo.gl/photos/xTjyYRWKER5nRCcg7

Неплохая работа, но больно уж мала матрица. Такое уже на 340х320 будет тормозить.

ptr
Offline
Зарегистрирован: 28.05.2016

sslobodyan пишет:

Интересно какой модуль экрана использован и как подключен. Ну и глянуть бы на скетч, если не комтайна.

Модуль ST7735. Я же с ним и экспериментирую. Скетч тут мало важен. Потому как библиотеку работы с TFT сам пишу. Но библиотеку нужно еще допилить перед выкладываением, а скетч вообще тут демонстрационный и тоже недописанный. Но если нужно:

001#include "st7735_spi.h"
002 
003typedef struct sprite_st {
004  uint8_t *sprite;
005  uint8_t width;
006  uint8_t height;
007  uint8_t x;
008  uint8_t y;
009  uint8_t *filled;
010} sprite_t;
011 
012sprite_t my_sprite;
013 
014void draw_sprite(sprite_t *sprite)
015{
016  st7735_spi_tft_read_rect_short(sprite->x, sprite->width, sprite->y, sprite->height, sprite->filled);
017  st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y, sprite->height, sprite->sprite);
018}
019 
020// vector Up=1, UpRight=3, Right=2, DownRight=6, Down=4, DownLeft=12, Left=8, UpLeft=9
021 
022uint8_t move_sprite(sprite_t *sprite, uint8_t vector)
023{
024  uint8_t row[sprite->width*2], col[sprite->height*2], tmp[sprite->height*2];
025  uint8_t i;
026 
027  switch ( vector )
028  {
029    case 1:
030      if ( !sprite->y ) return(4);
031      st7735_spi_tft_read_rect_short(sprite->x, sprite->width, sprite->y-1, 1, row);
032      sprite->y--;
033      st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y+sprite->height, 1, sprite->filled+sprite->width*(sprite->height-1)*2);
034      memmove(sprite->filled+sprite->width*2, sprite->filled, sprite->width*(sprite->height-1)*2);
035      st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y, sprite->height, sprite->sprite);
036      memcpy(sprite->filled, row, sprite->width*2);
037      break;
038    case 2:
039      if ( sprite->x+sprite->width>=ST7735_SCREEN_WIDTH ) return(8);
040      st7735_spi_tft_read_rect_short(sprite->x+sprite->width, 1, sprite->y, sprite->height, col);
041      for (i=0;i<sprite->height;i++)
042      {
043        tmp[i*2]=*(sprite->filled+sprite->width*2*i);
044        tmp[i*2+1]=*(sprite->filled+sprite->width*2*i+1);
045      }
046      st7735_spi_tft_write_rect_short(sprite->x, 1, sprite->y, sprite->height, tmp);
047      sprite->x++;
048      memmove(sprite->filled, sprite->filled+2, sprite->width*sprite->height*2-2);
049      st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y, sprite->height, sprite->sprite);
050      for (i=0;i<sprite->height;i++)
051      {
052        *(sprite->filled+(sprite->width-1)*2+sprite->width*2*i)=col[2*i];
053        *(sprite->filled+(sprite->width-1)*2+sprite->width*2*i+1)=col[2*i+1];
054      }
055      break;
056    case 4:
057      if ( sprite->y+sprite->height>=ST7735_SCREEN_HEIGHT ) return(1);
058      st7735_spi_tft_read_rect_short(sprite->x, sprite->width, sprite->y+sprite->height, 1, row);
059      st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y, 1, sprite->filled);
060      sprite->y++;
061      memmove(sprite->filled, sprite->filled+sprite->width*2, sprite->width*(sprite->height-1)*2);
062      st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y, sprite->height, sprite->sprite);
063      memcpy(sprite->filled+sprite->width*(sprite->height-1)*2, row, sprite->width*2);
064      break;
065    case 8:
066      if ( !sprite->x ) return(2);
067      st7735_spi_tft_read_rect_short(sprite->x-1, 1, sprite->y, sprite->height, col);
068      for (i=0;i<sprite->height;i++)
069      {
070        tmp[i*2]=*(sprite->filled+(sprite->width-1)*2+sprite->width*2*i);
071        tmp[i*2+1]=*(sprite->filled+(sprite->width-1)*2+sprite->width*2*i+1);
072      }
073      sprite->x--;
074      st7735_spi_tft_write_rect_short(sprite->x+sprite->width, 1, sprite->y, sprite->height, tmp);
075      memmove(sprite->filled+2, sprite->filled, sprite->width*sprite->height*2-2);
076      st7735_spi_tft_write_rect_short(sprite->x, sprite->width, sprite->y, sprite->height, sprite->sprite);
077      for (i=0;i<sprite->height;i++)
078      {
079        *(sprite->filled+sprite->width*2*i)=col[2*i];
080        *(sprite->filled+sprite->width*2*i+1)=col[2*i+1];
081      }
082      break;
083  }
084  return(0);
085}
086 
087void setup()
088{
089  static const uint8_t buf[] = "\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x00\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F\x80\x1F";
090  uint8_t i;
091 
092  st7735_spi_tft_init();
093  st7735_spi_tft_fill_rectangle(0, 128, 0, 160, ST7735_RED);
094 
095 
096  for ( i=3;i<128;i+=8)
097  {
098    st7735_spi_tft_fill_rectangle(i, 1, 0, 160, ST7735_GREEN);
099  }
100  for ( i=3;i<160;i+=8)
101  {
102    st7735_spi_tft_fill_rectangle(0, 128, i, 1, ST7735_GREEN);
103  }
104 
105  my_sprite.sprite=buf;
106  my_sprite.x=50;
107  my_sprite.y=60;
108  my_sprite.width=8;
109  my_sprite.height=8;
110  my_sprite.filled=malloc(my_sprite.width*my_sprite.height*2);
111  draw_sprite(&my_sprite);
112  return;
113}
114 
115void loop ()
116{
117  static uint8_t dirx=2, diry=1;
118  uint8_t rc;
119 
120  rc=move_sprite(&my_sprite, dirx);
121  if ( rc ) dirx=rc;
122  rc=move_sprite(&my_sprite, diry);
123  if ( rc ) diry=rc;
124  delay(2);
125  return;
126}

 

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

ptr пишет:

Удалось таки )
https://goo.gl/photos/xTjyYRWKER5nRCcg7

Неплохая работа, но больно уж мала матрица. Такое уже на 340х320 будет тормозить.

А в чем разница? Хоть 1920x1080. Обновляю я ведь, в любом случае, только спрайт и то, что затирал спрайт. Тут скорость от размера спрайта зависит, а не от размера матрицы. На текущей Delay(2) пришлось ставить, чтобы спрайт хоть увидеть можно было )

 

ptr
Offline
Зарегистрирован: 28.05.2016

sslobodyan пишет:

Нужно будет реализовать сдвиг части экрана влево-право на пару пикселей. У используемой библиотеки такой функционал отсутствует, так что пока храню фреймбуфер в контроллере. 

Из известных мне контроллеров TFT я не знаю ни один, умеющий смещать экран аппаратно. А программная реализация требует или хранения всего фреймбуфера в МК, что, порой, вообще не реально, либо того, что делаю в этой теме я: читаю по аппаратному SPI из фреймбуфера контроллера TFT по той же шине, что и передаю ему команды и данные. Больше всего возни именно с чтением фреймбуфера получилось.

 

sslobodyan
Offline
Зарегистрирован: 28.09.2016

А покажите функцию чтения пикселя. Я еще сам не пробовал, только читал у забугорных товарищей, что там еще и резистор дополнительный впаивают что бы читать данные. 

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

diger67 пишет:

ptr пишет:

Удалось таки )
https://goo.gl/photos/xTjyYRWKER5nRCcg7

Неплохая работа, но больно уж мала матрица. Такое уже на 340х320 будет тормозить.

А в чем разница? Хоть 1920x1080. Обновляю я ведь, в любом случае, только спрайт и то, что затирал спрайт. Тут скорость от размера спрайта зависит, а не от размера матрицы. На текущей Delay(2) пришлось ставить, чтобы спрайт хоть увидеть можно было )

 

В том то и дело что для отображения спрайта того же размера понадобится буфер немного большего размера.

diger67
Offline
Зарегистрирован: 25.07.2015

sslobodyan пишет:

А покажите функцию чтения пикселя. Я еще сам не пробовал, только читал у забугорных товарищей, что там еще и резистор дополнительный впаивают что бы читать данные. 

Да нет ни чего проще, задаем область спрайта (регистры 2Ah, 2Bh), регистр чтения пикселя(регистр 2Eh) и считываем данные, в этом случае два байта на пиксель если шина SPI или 8 бит и один байт если 16бит, умноженные на Hsprite * Vsprite.

sslobodyan
Offline
Зарегистрирован: 28.09.2016

ЗдОрово, если все так просто. А я вот смотрел на форуме AdaFruits (разработчики модулей и библиотеки к ним), та вот что сами разрабы сказали:

Re: 1.8" - ST7735 - reading a pixel from RAM

by adafruit on Sun Dec 11, 2011 5:29 pm

it appears you cant, we could never get it to work :(
Так что вам надо к объяснить им как все таки можно читать видеобуфер :) А лучше запулить к ним в библиотеку свою функцию :)
ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

Да нет ни чего проще, задаем область спрайта (регистры 2Ah, 2Bh), регистр чтения пикселя(регистр 2Eh) и считываем данные, в этом случае два байта на пиксель если шина SPI или 8 бит и один байт если 16бит, умноженные на Hsprite * Vsprite.

Вы очень сильно не правы. Все существенно сложнее. Чуть позже напишу подробней.

sslobodyan
Offline
Зарегистрирован: 28.09.2016

О, жду с нетерпением ;)

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

diger67 пишет:

Да нет ни чего проще, задаем область спрайта (регистры 2Ah, 2Bh), регистр чтения пикселя(регистр 2Eh) и считываем данные, в этом случае два байта на пиксель если шина SPI или 8 бит и один байт если 16бит, умноженные на Hsprite * Vsprite.

Вы очень сильно не правы. Все существенно сложнее. Чуть позже напишу подробней.

Может обработка считанного дампа и сложнее, а вот считать определенную область нет проще чем предложено. Иначе вы даташит читать не умеете. Такой метод особенно эффективен в случае если в м/к есть DMA. Почитайте на досуге даташит повнимательней. Читать по пиксельно, если вы о таком режиме, это добавлять лишние циклы, попробуйте вариант обработки спрайтов с использованием массивов. Понятно что надо иметь спрайт фона выделенной области и сам накладывамый спрайт. И не подлежит сомнению что перемещение спрайта происходит путем записи логически сложенного куска фона и самого спрайта. Помойму нет более быстрого вывода. И есть некое замечание, вы выделили память под буфер, а вот по окончании работы надо предусмотреть освобождение резервирования памяти, чтобы в последствии память можно было испоользовать для любых дручих целей.

ptr
Offline
Зарегистрирован: 28.05.2016

sslobodyan пишет:

А покажите функцию чтения пикселя. Я еще сам не пробовал, только читал у забугорных товарищей, что там еще и резистор дополнительный впаивают что бы читать данные. 

Одним резистром там не обойдешься. Но чтобы понять, почему так, необходимо описать пройденный мной путь.

Для начала я повертел готовые библиотеки и убедился, что они жутко медленные. Естественно, захотелось понять, почему. Ну да, код не слишком оптимален, но вроде бы не настолько. При ближайшем рассмотрении, обнаружилось, что проблема то в реализации аппаратного SPI на ATMega328 и иже с ней. Дело в том, что SPI там реализован вообще без буферизации передатчика. И инициировать передачу следующего байта можно только по окончании передачи текущего. Из-за этого, попытка переключиться с 4МГц тактовой SPI на 8МГц не давала никакого видимого эффекта.

Однако, в AVR есть так же Master SPI mode у USART. Причем USART по жизни имеет буфера и для передатчика, и для приемника. А значит, позволяет передавать по SPI без пауз между байтами. Но, на имеющихся у меня Arduino UNO и Arduino Nano выход RX соединен через 1К резистор с выходом TX ATMega8U2. То есть, хоть в лоб, хоть по лбу, имеет устойчивые 5 вольт с током до 5ма (при нуле) на входе RX ATMega128.

Поэтому, кроме китайского модуля согласования уровней 3.3 и 5 вольт, пришлось городить целую схему:

Один из выводов управляет, в каком направлении работает SPI шина. Когда на нем высокий уровень и на выходе TX низкий уровень, транзистор Q2 открыт и имеем низкий уровень на входе ST7735 (через преобразователь уровней). Когда на R/W высокий уровень, то имеем низкий уровень на входе ST7735, за счет 10К подтягивающего резистра на 3.3 вольта в преобразователе уровней.

Транзистор Q1 понадобился только из-за наличия резистора 1К к ATMega8U2, о чем писалось выше. Предполагаю, что на Arduino Pro Mini без этого транзистора вполне можно обойтись.

Теперь про чтение. Проблема в том, что в не зависимости от того, в каком формате мы отправляем цвет в ST7735, в его фреймбуфере он всегда хранится в 18-ти битном виде. И читать оттуда позволяется тоже исключительнов 18-ти битном виде. Так как 18-ти битный цвет занимает три байта на пиксель, теряя 6 бит в никуда, то и чтение его без преобразования потребовало бы буфера в полтора раза больше. Кроме того, его все равно пришлось бы потом перекодировать в 16-ти битный цвет. В связи с этим, я и реализовал при чтении перекодирование обратно в 16-ти битный цвет на лету.

Функцию я прилагаю, но толку с нее, без остального кода мало. А приведу весь код в порядок я не раньше следующих выходных. Во тогда и выложу на гитхаб. А сюда пихать около тысячи строк кода, на мой взгляд, как-то неправильно.

Вот функция:
 

001void st7735_spi_read_frame_memory(uint8_t *data, uint8_t status, uint8_t buffer_length)
002{
003  uint8_t firstb, readb, lastb;
004 
005  asm volatile ( ";                             \n\t \
006  cpi   %[status], 0                  ;1        \n\t \
007  breq  FLUSH_RECEIVER%=              ;1/2      \n\t \
008  clr   %[status]                     ;1        \n   \
009; Rx = data, RxBuf = empty, RxEDR = data        \n   \
010WAIT_UDREn_FOR_DATA%=:                          \n\t \
011  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
012  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
013  rjmp  WAIT_UDREn_FOR_DATA%=         ;2        \n   \
014  sts   %[UDRn_addr], %[filler]       ;2   (8)  \n   \
015; Rx = data, RxBuf = data, RxEDR = data         \n\t \
016WAIT_RXCn_FOR_DATA%=:                           \n\t \
017  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
018  sbrs  __tmp_reg__, %[RXCn_bit]      ;1/2      \n\t \
019  rjmp  WAIT_RXCn_FOR_DATA%=          ;2        \n\t \
020  lds   %[readb], %[UDRn_addr]        ;2        \n   \
021; Rx = data, RxBuf = empty, RxEDR = data        \n\t \
022  cpi   %[status], 0                  ;1   (9)  \n\t \
023  brlt  COLOR_LAST_BYTE%=             ;1/2      \n\t \
024  breq  COLOR_FIRST_BYTE%=            ;1/2      \n\t \
025  lsl   %[readb]                      ;1        \n\t \
026  swap  %[readb]                      ;1        \n\t \
027  mov   %[lastb], %[readb]            ;1        \n\t \
028  andi  %[readb], 0b00000111          ;1        \n\t \
029  or    %[readb], %[firstb]           ;1        \n\t \
030  ldi   %[status], 0xFF               ;1        \n\t \
031  RJMP  CONTINUE_LOOP%=               ;2   (20) \n   \
032COLOR_FIRST_BYTE%=:                             \n\t \
033  lsl   %[readb]                      ;1        \n\t \
034  lsl   %[readb]                      ;1        \n\t \
035  andi  %[readb], 0b11111000          ;1        \n\t \
036  mov   %[firstb], %[readb]           ;1        \n\t \
037  inc   %[status]                     ;1        \n\t \
038  RJMP  WAIT_UDREn_FOR_DATA%=         ;2   (17) \n   \
039COLOR_LAST_BYTE%=:                              \n\t \
040  lsr   %[readb]                      ;1        \n\t \
041  andi  %[lastb], 0b11100000          ;1        \n\t \
042  or    %[readb], %[lastb]            ;1        \n\t \
043  clr   %[status]                     ;1        \n   \
044CONTINUE_LOOP%=:                                \n\t \
045  com   %[readb]                      ;1        \n\t \
046  st    %a[data]+, %[readb]           ;2        \n\t \
047  dec   %[buffer_length]              ;1        \n\t \
048  brne  WAIT_UDREn_FOR_DATA%=         ;1/2      \n\t \
049  rjmp  EXIT_ASM%=                    ;2        \n   \
050FLUSH_RECEIVER%=:                               \n\t \
051  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
052  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
053  rjmp  FLUSH_RECEIVER%=              ;2        \n\t \
054  sts   %[UCSRnA_addr], __zero_reg__  ;2        \n\t \
055  ldi   %[readb], %[rdmemcmd]         ;1        \n\t \
056  cli                                 ;1        \n\t \
057  sts   %[UDRn_addr], %[readb]        ;2        \n   \
058; Tx = any, TxBuf = rdmemcmd                    \n   \
059; Rx disabled                                   \n   \
060WAIT_UDREn_FOR_COMMAND%=:                       \n\t \
061  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
062  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
063  rjmp  WAIT_UDREn_FOR_COMMAND%=      ;2        \n\t \
064  cbi   %[dc_port], %[dc_pin]         ;2        \n\t \
065  ldi   %[lastb], %[TXCn_clear]       ;1        \n   \
066WAIT_UDREn_BEFORE_DUMMY%=:                      \n\t \
067  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
068  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
069  rjmp  WAIT_UDREn_BEFORE_DUMMY%=     ;2        \n\t \
070  sts   %[UDRn_addr], %[filler]       ;2        \n\t \
071  sts   %[UCSRnA_addr], %[lastb]      ;2        \n   \
072; Tx = rdmemcmd, TxBuf = dummy                  \n   \
073; Rx disabled                                   \n   \
074WAIT_UDREn_FOR_DUMMY%=:                         \n\t \
075  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
076  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
077  rjmp  WAIT_UDREn_FOR_DUMMY%=        ;2        \n   \
078; Tx = dummy, TxBuf = empty                     \n   \
079; Rx disabled                                   \n   \
080  sbi   %[dc_port],%[dc_pin]          ;2        \n\t \
081  cbi   %[rw_port],%[rw_pin]          ;2        \n\t \
082  sei                                 ;1        \n\t \
083  ldi   %[status], %[RX_Enable]       ;1        \n\t \
084WAIT_TXCn_FOR_DUMMY%=:                          \n\t \
085  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
086  sbrs  __tmp_reg__, %[TXCn_bit]      ;1/2      \n\t \
087  rjmp  WAIT_TXCn_FOR_DUMMY%=         ;2        \n\t \
088  sts   %[UCSRnA_addr], %[lastb]      ;2        \n\t \
089; Tx = dummy, TxBuf = dummy                     \n   \
090; Rx disabled                                   \n\t \
091  sts   %[UCSRnB_addr], %[status]     ;2        \n\t \
092  clr   %[status]                     ;1        \n   \
093  rjmp  WAIT_UDREn_FOR_DATA%=         ;2        \n   \
094EXIT_ASM%=:                                     \n   \
095  "
096  : [data] "+b" (data), [status] "+d" (status), [buffer_length] "+r" (buffer_length),
097    [firstb] "=r" (firstb), [readb] "=d" (readb), [lastb] "=d" (lastb)
098  : [filler] "r" (0xFF), [rdmemcmd] "I" (_ST7735_SPI_COMMAND_RAMRD_CODE_),
099    [UCSRnA_addr] "M" (_ST7735_SPI_UCSRnA_ADDRESS_),
100    [UDREn_bit] "I" (UDRE0),
101    [UCSRnB_addr] "M" (_ST7735_SPI_UCSRnB_ADDRESS_),
102    [RX_Enable] "M" ((0<<RXCIE0)|(0<<TXCIE0)|(0<<UDRIE0)|(1<<RXEN0)|(1<<TXEN0)),
103    [RX_Disable] "M" ((0<<RXCIE0)|(0<<TXCIE0)|(0<<UDRIE0)|(0<<RXEN0)|(1<<TXEN0)),
104    [TXCn_bit] "I" (TXC0),
105    [RXCn_bit] "I" (RXC0),
106    [TXCn_clear] "M" (1<<TXC0),
107    [UDRn_addr] "M" (_ST7735_SPI_UDRn_ADDRESS_),
108    [dc_port] "I" (PIN_TO_PORTn_OFFSET(ST7735_SPI_DC_PIN_NO)),
109    [dc_pin] "I" (PIN_TO_PINn_BIT(ST7735_SPI_DC_PIN_NO)),
110    [rw_port] "I" (PIN_TO_PORTn_OFFSET(ST7735_SPI_RW_PIN_NO)),
111    [rw_pin] "I" (PIN_TO_PINn_BIT(ST7735_SPI_RW_PIN_NO))
112  : "cc" );
113  return(status);
114}

 

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

ptr пишет:

diger67 пишет:

Да нет ни чего проще, задаем область спрайта (регистры 2Ah, 2Bh), регистр чтения пикселя(регистр 2Eh) и считываем данные, в этом случае два байта на пиксель если шина SPI или 8 бит и один байт если 16бит, умноженные на Hsprite * Vsprite.

Вы очень сильно не правы. Все существенно сложнее. Чуть позже напишу подробней.

вы даташит читать не умеете.

Из даташит:

10.1.22 RAMRD (2Eh): Memory Read

The data color coding is fixed to 18-bit in reading function.

И кто из нас не умеет читать? )))

И это не считая того, что:
1. Первый принимаемый байт пустой

2. Между приемом команды и началом передачи ST7735 пропускает один такт синхронизации и данные принимаются со смещением в 1 бит.

3. Для коректного завершения передачи необходимо не менее, чем на 350 нс передернуть CS

4. Все это удовольствие еще сопровождается выставлением D/C так, что бы до передачи последнего бита команды на нем был низкий уровень, а до передачи или приема последнего бита данных - высокий.

Вы бы сначала сами написали весь код, а потом бы уже учили тех, кто этот код не только написал, но и отладил.

ptr
Offline
Зарегистрирован: 28.05.2016

Забыл добавить, что в данной схеме принимаемый по SPI код получается инвертированным, что следует учитывать в программе (45-ая строка функции). Все тестировалось на частоте SPI 8МГц. То есть, между приемом или передачей одного байта у меня было только 16 тактов процессора. Потому и свалился на ассемблер.

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

diger67 пишет:

ptr пишет:

diger67 пишет:

Да нет ни чего проще, задаем область спрайта (регистры 2Ah, 2Bh), регистр чтения пикселя(регистр 2Eh) и считываем данные, в этом случае два байта на пиксель если шина SPI или 8 бит и один байт если 16бит, умноженные на Hsprite * Vsprite.

Вы очень сильно не правы. Все существенно сложнее. Чуть позже напишу подробней.

вы даташит читать не умеете.

Из даташит:

10.1.22 RAMRD (2Eh): Memory Read

The data color coding is fixed to 18-bit in reading function.

И кто из нас не умеет читать? )))

И это не считая того, что:
1. Первый принимаемый байт пустой

2. Между приемом команды и началом передачи ST7735 пропускает один такт синхронизации и данные принимаются со смещением в 1 бит.

3. Для коректного завершения передачи необходимо не менее, чем на 350 нс передернуть CS

4. Все это удовольствие еще сопровождается выставлением D/C так, что бы до передачи последнего бита команды на нем был низкий уровень, а до передачи или приема последнего бита данных - высокий.

Вы бы сначала сами написали весь код, а потом бы уже учили тех, кто этот код не только написал, но и отладил.

Ну я например спокойно заисываю двубайтные значения цветов без дурацкого вида преобразований RGB18 -> RGB16. Есть такой регистр как 3Ah он определяет формат ввода вывода пикселя, он дает возможность не заниматься ананизмом. 

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

ptr пишет:

Из даташит:

10.1.22 RAMRD (2Eh): Memory Read

The data color coding is fixed to 18-bit in reading function.

И кто из нас не умеет читать? )))

Ну я например спокойно заисываю двубайтные значения цветов без дурацкого вида преобразований RGB18 -> RGB16. Есть такой регистр как 3Ah он определяет формат ввода вывода пикселя, он дает возможность не заниматься ананизмом. 

Вы утверждаете, что в даташит ложь? )))

Писать в ST7735 легко можно и в 12-ти битном цвете и 16-ти битном. Но читать он позволяет только в 18-ти битном. Могу сделать вывод, что Вы никогда не читали из него фреймбуфер, раз утверждаете обратное.

P.S. Спорить в лом. Код и схему подключения в студию. Рабочий. Чтобы можно было проверить.

ptr
Offline
Зарегистрирован: 28.05.2016

Функцию записи в фреймбуфер я уже вроде бы публиковал, но не в этой теме. Повторю, не гордый:
 

01/*-----------------12.09.2016 13:17-----------------
02 * Buffer send function:
03 * - status not updated
04 * - status have bits according to st7735_spi_buffer_status_t
05 * - function don't check dc_bit_set bit in status
06 * - send command with data => status = 0
07 * - send only data => status=1 or is_data_only=1
08 * - buffer_length=0 allow to send 256 bytes in buffer
09 * - function don't check buffer pointer; be carefull!
10 * --------------------------------------------------*/
11 
12void st7735_spi_send_buffer(uint8_t *data, uint8_t status, uint8_t buffer_length)
13{
14  uint8_t readb;
15 
16  asm volatile ( ";                             \n\t \
17  ld    %[readb], %a[data]+           ;2        \n   \
18WAIT_UDREn_ON_START%=:                          \n\t \
19  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
20  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
21  rjmp  WAIT_UDREn_ON_START%=         ;2        \n\t \
22  cli                                 ;1        \n\t \
23  sts   %[UDRn_addr], %[readb]        ;2        \n\t \
24  ld    %[readb], %a[data]+           ;2        \n\t \
25  sbrc  %[status], 0                  ;1/2      \n\t \
26  rjmp  WAIT_UDREn_FOR_DATA%=         ;2        \n   \
27; Set DC for command                            \n   \
28WAIT_UDREn_FOR_COMMAND%=:                       \n\t \
29  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
30  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
31  rjmp  WAIT_UDREn_FOR_COMMAND%=      ;2        \n\t \
32  cbi   %[port],%[pin]                ;2        \n\t \
33  dec   %[buffer_length]              ;1        \n\t \
34  BREQ  EXIT_ASM%=                    ;1        \n\t \
35  ld    %[status], %a[data]+          ;2        \n\t \
36  sts   %[UDRn_addr], %[readb]        ;2   (16) \n\t \
37  mov   %[readb], %[status]           ;1        \n   \
38WAIT_UDREn_FOR_DATA%=:                          \n\t \
39  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
40  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
41  rjmp  WAIT_UDREn_FOR_DATA%=         ;2        \n\t \
42  sbi   %[port],%[pin]                ;2        \n\t \
43  sei                                 ;1   (8)  \n   \
44DATA_LOOP%=:                                    \n\t \
45  dec   %[buffer_length]              ;1        \n\t \
46  BREQ  EXIT_ASM%=                    ;1        \n   \
47WAIT_UDREn_IN_DATA_LOOP%=:                      \n\t \
48  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
49  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
50  rjmp  WAIT_UDREn_IN_DATA_LOOP%=     ;2   (5)  \n\t \
51  sts   %[UDRn_addr], %[readb]        ;2   (16) \n\t \
52  ld    %[readb], %a[data]+           ;2        \n\t \
53  rjmp  DATA_LOOP%=                   ;2   (12) \n   \
54EXIT_ASM%= :                                    \n\t \
55  sei                                 ;1        \n\t \
56  "
57  : [data] "+b" (data), [status] "+d" (status), [buffer_length] "+r" (buffer_length),
58    [readb] "=r" (readb)
59  : [UCSRnA_addr] "M" (_ST7735_SPI_UCSRnA_ADDRESS_),
60    [UDREn_bit] "I" (UDRE0), [UDRn_addr] "M" (_ST7735_SPI_UDRn_ADDRESS_),
61    [port] "I" (PIN_TO_PORTn_OFFSET(ST7735_SPI_DC_PIN_NO)),
62    [pin] "I" (PIN_TO_PINn_BIT(ST7735_SPI_DC_PIN_NO))
63  : "cc" );
64}

 

ssss
Offline
Зарегистрирован: 01.07.2016

ptr пишет:

Писать в ST7735 легко можно и в 12-ти битном цвете и 16-ти битном. Но читать он позволяет только в 18-ти битном.

А в чём вообще смысл таких извращений? Зачем все эти манипуляции с убогим ТФТ на убогом МК? Что это даёт? В чём тайный смысл, если отвратный результат заведомо известен?

sslobodyan
Offline
Зарегистрирован: 28.09.2016

ptr пишет:

Писать в ST7735 легко можно и в 12-ти битном цвете и 16-ти битном. Но читать он позволяет только в 18-ти битном

Кстати, да, вот кусочек из ДШ:

Note2: The Command 3Ah should be set at 55h when writing 16-bit/pixel data into frame memory, but 3Ah should be re-set to 66h when reading pixel data from frame memory

Типа нас заставляют перейти в 18бит при чтении. 

ptr
Offline
Зарегистрирован: 28.05.2016

ssss пишет:

А в чём вообще смысл таких извращений? Зачем все эти манипуляции с убогим ТФТ на убогом МК? Что это даёт? В чём тайный смысл, если отвратный результат заведомо известен?

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

 

ssss
Offline
Зарегистрирован: 01.07.2016

Вопрос нормальный и очевидный. Отсутствие профита видно ещё на простейших функциях работы с ТФТ. А ваши портянки на АСМе это ваще смертельный приговор какому либо результату. Если вопрос этих телодвижений чисто теоретический, то это одно, иначе это просто пустая трата времени. Поэтому и спросил, в чём тайный смысл?

ptr
Offline
Зарегистрирован: 28.05.2016

ssss пишет:

А ваши портянки на АСМе это ваще смертельный приговор какому либо результату.

Поэтому и спросил, в чём тайный смысл?

Только результат почему то есть на видео выше и меня вполне устраивает )

Сын хочет написать упрощенный аналог арканоида на ардуине. Стандартные библиотеки слишком медленные для такой игрушки. А моя вполне в состоянии обеспечить требуемую производительность. Я даже при полном выводе всего фреймбуфера добился почти 25 кадров в секунду. И спрайт на видео у меня летает с задержкой в 2 миллисекунды на цикл. Причем летает даже быстрее, чем нужно для этого арканоида, хотя и не оптимально. Для пробы реализовал только сдвиг или по горизонтали, или по вертикали. Если добавить диагональные смещения, то скорость увеличится еще в полтора раза. Значит запас на прочий просчет еще есть, и не маленький.

 

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

ssss пишет:

А в чём вообще смысл таких извращений? Зачем все эти манипуляции с убогим ТФТ на убогом МК? Что это даёт? В чём тайный смысл, если отвратный результат заведомо известен?

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

 

Ну может с чтением вы и правы, но вот то что вы делаете полный изврат. Писал уже, берем область фона перекрывающий уже записанный спрайт, накладываем спрайт с заданным смещением, записывам в память TFT. Точка!!! остальное АНАНИЗМ. Чем вы и занимаетесь с пристрастием. Сравните вашу хвостатую камету по вашему алгоритму, когда след тянется на пол экрана и то что получается по может и идиотскому но более оптимальному агоритму. И не маловажный вопрос, что еще может делать м/к в момент когда гоняет квадратик по экрану, ответ очевиден, ни чего. И нахрена козе баян.

slider
Offline
Зарегистрирован: 17.06.2014

ptr , интересеная у вас реализация, использовать видео ОЗУ контроллера дисплея для передвижения кусочка изображения, надобности у меня нехватило это реализовать. Снимите видос на ютуб что у вас получилось, по перемещению небольшой картинки. Для себя пока, для немного похожей задачи, перешёл на Мегу , там объем ОЗУ позволил создать приемлемый видеобуфер из переменных byte для запоминания нескольких графиков для их последующего смещения.

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

А вот если же двигать маленькую картинку на большой картинке-фоне , то либо весь фон надо загнать в ОЗУ , либо сохранять участок картинки-фона , куда будет перемещатся маленькая картинка, чтоб после её ухода, заново восстановить на этом месте фон. Тогда получиться нам нужна видеопамять по размеру чуть больше маленькой перемещаемой катринки.

с mcufriend kvb пока небыло времени разобраться, но похоже там scroll реализован , походу софтово, но как-то уж быстро

https://www.youtube.com/watch?v=FB_ZEFw86OU    (на 9сек диагональное смещение)

https://youtu.be/w1XNoqz0UNY?t=36  (сдвиг слов и картинки тоже)

diger67, согласен, но надо добить именно этот способ до конца. все способы уникальны и интересны в своем роде. Надо тогда уж отдельную тему создавать по реализованным спрайтам, где будет сравнение способов, но для начала их надо практически реализовать. У меня нет что показать реализацию передвижения спрайта на ардуине, и посему поддерживаю пытливого ума ptr , который вот вот покажет на сколько fps можно выйти его способом. 
хотелось бы узреть передвижение именно картинки , а не монотонного объекта когда достаточно дорисовывать фронт и затирать тыл для его визуального перемещения дабы не перерисовывать весь объект заново.

diger67
Offline
Зарегистрирован: 25.07.2015

slider,так предлогал ему такой вариант. Ведь все будет работать  гараздо быстрее, можно на меге еще 64к прицепить. Создать зеркало ОЗУ TFT, а заготовки разместить во внешней flash типа 25Qxxx. По сути один раз подготавливаем заплатку и гоняем ее так как на надо. Если графики много и она шыбко шустра, то лучше использовать ARM. Я подсел на STM, вот жду когда приедет F7, там уже вроде можно задействовать D2DMA не только с LTDC. Что сделает вывод на TFT еще эффективнее.

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

Ведь все будет работать  гараздо быстрее

можно на меге

Ну не позорьтесь. Даже на меге тратить больше 40 килобайт RAM - непозволительная роскошь. И на Ваших любимых STM32 столько не всегда найдется. Получить несколько процентов прироста скорости для сферического коня в вакууме (где код?) ценой увеличения потребления RAM программой на порядки - смешно )

 

ptr
Offline
Зарегистрирован: 28.05.2016

slider пишет:

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

Тем, что его там нет. Я вообще не встречал ни одиного контроллера tft такое умеющего.

Цитата:

А вот если же двигать маленькую картинку на большой картинке-фоне , то либо весь фон надо загнать в ОЗУ , либо сохранять участок картинки-фона , куда будет перемещатся маленькая картинка, чтоб после её ухода, заново восстановить на этом месте фон. Тогда получиться нам нужна видеопамять по размеру чуть больше маленькой перемещаемой катринки.

Так ведь именно так и сделано )

sslobodyan
Offline
Зарегистрирован: 28.09.2016

ptr пишет:

Так ведь именно так и сделано )

А я б не заморачивался с переводом 18 в 16 бит при считывании фона. Проще запомнить фон в 18 битах, а в момент восстановления фона (когда затираем старый спрайт) переключиться тоже на 18 бит и залить то, что ранее считали один к одному.

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

diger67 пишет:

Ведь все будет работать  гараздо быстрее

можно на меге

Ну не позорьтесь. Даже на меге тратить больше 40 килобайт RAM - непозволительная роскошь. И на Ваших любимых STM32 столько не всегда найдется. Получить несколько процентов прироста скорости для сферического коня в вакууме (где код?) ценой увеличения потребления RAM программой на порядки - смешно )

 

Даже в F103c8t6 который по распространенности в использовании можно сравнить с mega328 20к RAM. Но не это главное. Вы откуда записываете фон в TFT, правильно из заране подготовленного файла, я например не знаю более быстрого способа. Что такое спрайт, это опять же заранее подготовленный файл. Думаю здесь вы спорить не будите. И ответте себе на вопрос, откуда быстрее считать данные из Flash или из TFT.

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

 И ответте себе на вопрос, откуда быстрее считать данные из Flash или из TFT.

Из программной флеш памяти МК - быстрее. Но ее и так мало. Если речь же именно о файле, то есть о чтении с SD карты, то, очевидно, что из фреймбуфера считать существенно быстрее, чем с карточки.

Потому что:

1. Общение и с SD и с фреймбуфером осуществляется по одному и тому же SPI на одной и той же скорости.

2. При чтении из фреймбуфера у меня прямая адресация, при чтении же с SD все равно в ней читается целиком блок. Хорошо еще, если найдете старую карточку, этак на 32-128 мегабайт. На современных блок будет уже мегабайтного размера или более. Мне так ни разу еще не попадалась SD карточка, способная прочитать один байт быстрее, чем за одну миллисекунду.

3. Даже если файл не фрагментирован, он все равно или будет занимать больше одного кластера FAT, или будет лишние операции и расход памяти на FAT32.

3. Общение с SD картой требует дополнительных затрат памяти на открытые файлы и структуры FAT. Причем совсем не маленьких.

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

 

ptr
Offline
Зарегистрирован: 28.05.2016

sslobodyan пишет:

А я б не заморачивался с переводом 18 в 16 бит при считывании фона. Проще запомнить фон в 18 битах, а в момент восстановления фона (когда затираем старый спрайт) переключиться тоже на 18 бит и залить то, что ранее считали один к одному.

[/quote]

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

 

 

diger67
Offline
Зарегистрирован: 25.07.2015

ptr пишет:

Из программной флеш памяти МК - быстрее. Но ее и так мало. Если речь же именно о файле, то есть о чтении с SD карты, то, очевидно, что из фреймбуфера считать существенно быстрее, чем с карточки.

Есть Flahs память с интерфейсом 8 бит, читается она как обычная RAM. Не пробовали смотреть в эту сторону. Я к примеру сейчас разбираюсь с samsung flahs на 1Gb. У нее как раз 8 бит шина. Или 25Qxxx, она работает по SPI и считывать надо будет два а не три байта на пиксель. Надо посчитать, может будет выйгрышь.

ssss
Offline
Зарегистрирован: 01.07.2016

diger67 пишет:

ptr пишет:

Из программной флеш памяти МК - быстрее. Но ее и так мало. Если речь же именно о файле, то есть о чтении с SD карты, то, очевидно, что из фреймбуфера считать существенно быстрее, чем с карточки.

Есть Flahs память с интерфейсом 8 бит, читается она как обычная RAM. Не пробовали смотреть в эту сторону. Я к примеру сейчас разбираюсь с samsung flahs на 1Gb. У нее как раз 8 бит шина. Или 25Qxxx, она работает по SPI и считывать надо будет два а не три байта на пиксель.

Это у вас есть вероятность манёвра, при любых раскладах. У ptr всё сложно и плохо, ему там и дёргаться особо некуда, "Шаг вправо, шаг влево..."(с).

ssss
Offline
Зарегистрирован: 01.07.2016

ptr пишет:

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

Вы как вчера родились, но учились в прошлом веке. Нахрен никому не интересна ваша "экономия" памяти, когда она копейки стоит, если разговор идёт о повышении производительности. Или вопросы оптимизации вами никогда в жизни не рассматривались?

diger67
Offline
Зарегистрирован: 25.07.2015

ssss пишет:

diger67 пишет:

ptr пишет:

Из программной флеш памяти МК - быстрее. Но ее и так мало. Если речь же именно о файле, то есть о чтении с SD карты, то, очевидно, что из фреймбуфера считать существенно быстрее, чем с карточки.

Есть Flahs память с интерфейсом 8 бит, читается она как обычная RAM. Не пробовали смотреть в эту сторону. Я к примеру сейчас разбираюсь с samsung flahs на 1Gb. У нее как раз 8 бит шина. Или 25Qxxx, она работает по SPI и считывать надо будет два а не три байта на пиксель.

Это у вас есть вероятность манёвра, при любых раскладах. У ptr всё сложно и плохо, ему там и дёргаться особо некуда, "Шаг вправо, шаг влево..."(с).

Можно взять не 328 мегу а 2560,ну да тормозно конечно будет, но появляется хардварная шина на 8 бит. Что дает поле для подергивания в сторону. Я то при работе с TFT смотрю в сторону ARM по причине более высокоо быстодействия и наличия, непобоюсь это сказать, огромного выборв в периферии. У F7 уже появился кэшь ядра и 99% команд выполняются за один такт.

 

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

Есть Flahs память с интерфейсом 8 бит, читается она как обычная RAM. Не пробовали смотреть в эту сторону. Я к примеру сейчас разбираюсь с samsung flahs на 1Gb. У нее как раз 8 бит шина. Или 25Qxxx, она работает по SPI и считывать надо будет два а не три байта на пиксель. Надо посчитать, может будет выйгрышь.

Я сейчас на ATMega328. У меня ног уже не хватит для параллельного интерфейса.

Вот когда из Китая прийдет STM32, тогда можно будет поэкспериментировать.

ptr
Offline
Зарегистрирован: 28.05.2016

ssss пишет:

Вы как вчера родились, но учились в прошлом веке. Нахрен никому не интересна ваша "экономия" памяти, когда она копейки стоит, если разговор идёт о повышении производительности. Или вопросы оптимизации вами никогда в жизни не рассматривались?

Вы как с Луны свалились. За сколько копек вы расширите память в моей Ардуино UNO? Я готов целых 100 копеек Вам заплатить, если вы увеличите ее хотя бы на 16К! )))

 

ptr
Offline
Зарегистрирован: 28.05.2016

diger67 пишет:

Можно взять не 328 мегу а 2560

Смысла нет вообще. Ни 2560, ни, тем более, Due просто не рентабельны. В том смысле, что на ESP или STM32 решение будет дешевле не в ущерб функциональности