Указатели в функции

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Понадобилась помощь.

Есть дисплей Nokia 1616. цветной 132х162 точки

Интерфейс 9бит SPI

Так как стандартный SPI 8 бит, первый бит бит передается ногодрыганьем, а остально по SPI

Все работает, но медленно

На данный момент скорость зарисовки всего дисплея одним цветом удалось поднять с 0,74 кадра/сек до 3,37 кадра/сек. больше улучшить не получается

я бы успокоился, но нашел библиотеку которая делает почти 18 кадров/сек

и там везде используются указатели

так как я с ними не умею работать, и чтение различной литературы особо ясности не добавило, прощу объяснить как сделать максимальное быстродействие

в основном коде происходит вызов функции, которая например рисует пиксель

в функцию передаем цвет 16бит и сколько раз рисовать

но когда просто передаем мы из одной ячейки оперативной памяти копируем в другую и обрабатываем

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

//==============================================================================================
//                             Вывод на дисплей 8 бит данных или комманд
//==============================================================================================

void lcd_write(byte mode, byte c){
  //dWrite(CS, 0);
  (mode)? dWrite(DAT, 1) : dWrite(DAT, 0);
  dWrite(CLK, 1); 
  dWrite(CLK, 0);
  
  SPI_HW_ON;
  SPDR = c;
  SPI_HW_WAIT;
  SPI_HW_OFF;
}

//==============================================================================================
//                                 Вывод на дисплей 16 бит данных
//==============================================================================================

void lcd_write16(unsigned int dat){
  lcd_write(DATA,dat>>8);
  lcd_write(DATA,dat);
} 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
void fill_screen(unsigned int color){   
  lcd_write(CMD,0x2A); //x-координата
  lcd_write16(2);
  lcd_write(CMD,0x2B); //Y-координата
  lcd_write16(1);
  lcd_write(CMD,0x2C);
  
  for (byte i=0; i<DISP_H; i++){
    for(byte j=0;j<DISP_W;j++){
      lcd_write16(color);
    }
  } 
}

ну и в основной вызываем

fill_screen(0x001F);

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Если нужно передать только одно число, то указатель не поможет. Указатель нужен, когда нужно передать множество чисел, расположенных в непрерывной области памяти. Можно исходить ихз следующей логики:
1. Передаем как число. Это значит это число и будет считано в регистр и использовано.
2. Передаем как указатель. Это значит, что указатель будет помещен в регистры, затем будет считано это число из памяти.

Либо я не понял Вашего вопроса.

Geronimo
Offline
Зарегистрирован: 06.05.2013

Можно попробовать выделить в куче область видеопамяти где разные функции будут оперировать с общтми данными без копирования

toly
Offline
Зарегистрирован: 17.05.2014

Попробуйте для начала работаь только с глобальными переменными, вместо того, чтобы гонять их из функции в функцию. Если будет реальное улучшение быстродействия, то можно заменить все это на указатели в качестве параметров. У меня по крайней мере есть большие сомнения, что проблема решится именно указателями, тут наверняка еще и сам алгоритм в "быстрой" библиотеке просто очень хорошо оптимизирован.

__Alexander
Offline
Зарегистрирован: 24.10.2012

всё упирается в SPI, где один бит ногодрыгание... это и есть ограничение... никаких 18 кадров/с быть не может. И кстати, у 1616 160 на 128 точек, а не та херня что вы написали.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

__Alexander не знаешь лучше молчи. тебе код дать где это работает?

toly я уже честно сказать и не знаю, выложе исходный код где все быстро и сами увидите

там короче создается массив при заливке экране размеров в одну строку и из него через указатели выводят. наверно в этом дело

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

CPP

#include "LCD.h"
#include "Arduino.h"	
#include <avr/pgmspace.h>

void SpiCmd(u8 c);
void SpiData(u8 c);

#define DELAY_MS 0x200

#ifndef abs
#define abs(_x) ((_x) < 0 ? -(_x) : (_x))
#endif
#ifndef max
#define max(_a,_b) (((_a) > (_b)) ? (_a) : (_b))
#define min(_a,_b) (((_a) < (_b)) ? (_a) : (_b))
#endif


LCDInfo _lcd;	// LCD info for detected screen



void Cmd1616(u8 cmd, int a, int b){
	SpiCmd(cmd);
	SpiData(a>>8);
	SpiData(a);
	SpiData(b>>8);
	SpiData(b);
}

//=================================================================================

#if 0

void FillGeneric(int color, u32 count){
	u8 a = (color >> 8);
	u8 b = color;
	if (count <= 0)
		return;
	while (count--)
	{
		SpiData(a);
		SpiData(b);
	}
}


void BlitGeneric(const u8* data, u32 count)
{
	if (count <= 0)
		return;
	while (count--)
	{
		SpiData(*data++);
		SpiData(*data++);
	}
}

void BlitIndexedGeneric(const u8* data, const u8* palette, u32 count)
{
	if (count <= 0)
		return;
	while (count--)
	{
		int i = *data++;
		i += i;
		SpiData(palette[i]);
		SpiData(palette[i+1]);
	}
}

#else

#define SPI_HW_OFF   SPCR = 0;
#define SPI_HW_ON    SPCR = _BV(MSTR) | _BV(SPE);
#define SPI_HW_WAIT  while (!(SPSR & _BV(SPIF)));


#define MOSI 11
#define SCK 13
#define SSEL 10


#define MOSI0 dWrite(MOSI,0)
#define MOSI1 dWrite(MOSI,1)

#define SCK0 dWrite(SCK,0)
#define SCK1 dWrite(SCK,1)

#define SSEL0 dWrite(SSEL,0)
#define SSEL1 dWrite(SSEL,1)




void dWrite(u8 pin, u8  val){
  u8  bit = digitalPinToBitMask(pin);
  volatile u8  *out;
  out = portOutputRegister(digitalPinToPort(pin));

  if (val == LOW) *out &= ~bit;
  else *out |= bit;
}

void LCDInitHW(){
	SSEL1;
	MOSI1;
	SCK0;

	pinMode(MOSI, OUTPUT);
	pinMode(SCK, OUTPUT);
	pinMode(SSEL, OUTPUT);
}

void SpiCmd(u8 d){
	MOSI0;
	SCK1;
	SCK0;
	SPI_HW_ON;
	SPDR = d;
	SPI_HW_WAIT;
	SPI_HW_OFF;
}

void SpiData(u8 d){
	MOSI1;
	SCK1;
	SCK0;
	SPI_HW_ON;
	SPDR = d;
	SPI_HW_WAIT;
	SPI_HW_OFF;
}


#define nop()  __asm__ __volatile__("nop")

//	Fill a 16 bit color
//	Blit 16 bit pixels
//	Blit 8 bit indexed pixels from palette
//	400,000 pixels/sec on a 16Mhz AVR for Solid fills and 16bpp blits
//	380,000 pixels/sec for indexed blits


void FillBlit(u32 color, u32 count, const u8* data = 0, const u8* palette = 0)
{
	PORTB |= (1<<3);			// MOSI = 1 = Data
	u8 sck0 = PORTB & ~(1<<5);	// SCK
	u8 sck1 = PORTB | (1<<5);	// out is 1 clock vs sbi at 2
	SPSR |= 1;	// 2x clock

	u8 a,b;
	
	//	Handle 16 bit blits and index mode
	signed char x = 0;
	u8 y;
	const u8* p = 0;
	if (data){
		a = *data++;
		x = 1;
		if (palette){
			p = palette + ((*data++) << 1);
			a = p[0];
			b = p[1];
			x = -1;
			y = 0;
		}
	}
	else{
		a = color >> 8;
		b = color;
	}

	count <<= 1;
	int loop = count >> 8;
	u8 c = count;
	if (c)
		loop++;
	while (loop){
		for (;;){
			SPCR = 0;						// Turn off SPI HW
			PORTB = sck1;
			PORTB = sck0;					// Clock MOSI 1 bit to signify data on 9 bit spi
			SPCR = _BV(MSTR) | _BV(SPE);	// SPI Master
			SPDR = a;						// Now we have 16 clocks to kill

			//	16 clocks to do fill, blit or indexed blit

			//	Indexed blit - 380k
			if (x < 0){
				if ((y^=1)){
					a = b;
					p = palette + ((*data++) << 1);
					if (--c)
						continue;	// Early out
				} else {
					a = p[0];
					b = p[1];
					if (--c)
						continue;	// Early out
				}
				break;
			}


			if (x){
			//	Blit
				a = *data++;
				nop();
				nop();		// 400k
			}
			else{
				// Solid Fill
				u8 t = a;	// swap pixel halves
				a = b;
				b = t;
				nop();
				nop();		// 400k
			}
			if (!--c)
				break;	// 5 
		};				// loop takes 3 clocks
		c = 0;
		loop--;
		while (!(SPSR & _BV(SPIF)));	// wait for last pixel
	}
	SPCR = 0;
}

void FillGeneric(u32 color, u32 count){
	FillBlit(color,count);
}



void BlitGeneric(const u8* data, u32 count)
{
	FillBlit(0,count,data);
}

void BlitIndexedGeneric(const u8* data, const u8* palette, u32 count)
{
	FillBlit(0,count,data,palette);
}

#endif

void RectangleGeneric(int x, int y, int width, int height, int color)
{
	int right = x + width;
	if (x < 0)
		x = 0;
	if (right > _lcd.width)
		right = _lcd.width;
	width = right - x;
	if (width <= 0)
		return;

	int bottom = y + height;
	if (y < 0)
		y = 0;
	if (bottom > _lcd.height)
		bottom = _lcd.height;
	height = bottom - y;
	if (height <= 0)
		return;

	_lcd.SetBounds(x,y,width,height);
	_lcd.Fill(color,width*((long)height));
}

void InitGeneric(const short* data, int count){
	while (count--){
		int b = pgm_read_word(data++);
		if (b == DELAY_MS){
			b = pgm_read_word(data++);
			delay(b);
			count--;
		}
		else{
			if (b > 0xFF)
				SpiData(b);
			else
				SpiCmd(b);
		}
	}
}


//=================================================================================
//=================================================================================
//	SPFD54124B Orise
//	132x162 TFT RDID is 0x38 0x84 0x4F
//	Nokia 6060 6101 6125 5200 6070 0.5mm connector
//	Nokia 2630 2760 Side 0.4mm connector
//	Nokia 3500 top

static const short _initSPFD54124B[] PROGMEM ={
	0xBA, 0x107, 0x115,	// Data Order
	0x25, 0x13F,		       // Contrast
	0x11,				       // Sleep Out
	0x13,				       // Display Normal mode

	0x37,0x100,			// VSCROLL ADDR
	0x3A,0x105,			// COLMOD pixel format 4=12,5=16,6=18
	0x29,				    // DISPON
	0x20,				    // INVOFF
	0x13,				    // NORON
};

void InitSPFD54124B(){
	InitGeneric(_initSPFD54124B,sizeof(_initSPFD54124B)/2);

	SpiCmd(0x2D);
	int i;
	for (i = 0; i < 32; i++)
		SpiData(i<<1);
	for (i = 0; i < 64; i++)
		SpiData(i);
	for (i = 0; i < 32; i++)
		SpiData(i<<1);
}

void SetBoundsSPFD54124B(int x, int y, int width, int height){
	Cmd1616(0x2A,x,x+width-1);	// column start/end
	Cmd1616(0x2B,y,y+height-1);	// page start/end
	SpiCmd(0x2C);				// RAMWR
}


#if 1
u8 _gray = 0;
u8 _prnd = 0;

//	65k period
u16 xor16(void)
{
	static u16 y16 = 0xC0ED;
    y16 ^= (y16 << 1);
    y16 ^= (y16 >> 1);
    return y16 ^= (y16 << 14);
}

//	128 bit period. Nice
u32 xor128(void)
{
  static u32 x = 123456789;
  static u32 y = 362436069;
  static u32 z = 521288629;
  static u32 w = 88675123;
  u32 t;

  t = x ^ (x << 11);
  x = y; y = z; z = w;
  return w = w ^ (w >> 19) ^ t ^ (t >> 8);
}

#endif

#define RNDOM xor128

#define SWAP(_a,_b) { _a = _a ^ _b; _b = _a ^ _b; _a = _a ^ _b; }


//=================================================================================
//=================================================================================


void LCDBegin(){	// Select LCD{
	SSEL0;
}
/*
void LCDEnd(){		// Release LCD
	if (_lcd.format == 1){
		BlitMono();
		memset(_mono,0,sizeof(_mono));
	}
	SSEL1;
}

*/

int LCDInit(){
	LCDInitHW();
	delay(120);						// Too long?

	SSEL0;
	SpiCmd(0x11);					// SLEEPOUT
	delay(120);						// Too long?
	SSEL1;

	delay(100);	// too short?

	LCDInfo* info = &_lcd;
	info->Fill = FillGeneric;
	info->Blit = BlitGeneric;
	info->BlitIndexed = BlitIndexedGeneric;
	info->Rectangle = RectangleGeneric;
	info->width = 132;
	info->height = 162;
	info->format = 16;

	SCK0;
	SSEL0;
	
	InitSPFD54124B();
	info->SetBounds = SetBoundsSPFD54124B;

	SSEL1;
	SSEL0;
}

H файл 



/* Copyright (c) 2010, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/

#ifndef u8
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
#endif

#define DELAY_MS 0x200

typedef void (*LCDRectangleProc)(int x, int y, int width, int height, int color);
typedef void (*LCDSetBoundsProc)(int x, int y, int width, int height);
typedef void (*LCDFillProc)(u32 color, u32 count);
typedef void (*LCDBlitProc)(const u8* data, u32 count);
typedef void (*LCDBlitIndexedProc)(const u8* data, const u8* palette, u32 count);
typedef void (*LCDScrollProc)(int y);

typedef struct
{
	u32	id;
	int	width;
	int	height;
	int	format;
	int	feature;

	LCDRectangleProc	Rectangle;
	LCDSetBoundsProc	SetBounds;
	LCDFillProc			Fill;
	LCDBlitProc			Blit;
	LCDBlitIndexedProc	BlitIndexed;
	LCDScrollProc		Scroll;
} LCDInfo;

u32 LCDReadID();
int LCDInit();

void LCDBegin();	// Select LCD
void LCDEnd();		// Release LCD
u32 LCDChanged();

void LCDLine(int x0, int y0, int x1, int y1, int color);

#define LCDWidth() 		_lcd.width
#define LCDHeight() 	_lcd.height
#define LCDFormat() 	_lcd.format
#define LCDRectangle 	_lcd.Rectangle
#define LCDSetBounds 	_lcd.SetBounds
#define LCDFill 		_lcd.Fill
#define LCDBlit 		_lcd.Blit
#define LCDBlitIndexed	_lcd.BlitIndexed
#define LCDScroll 		_lcd.Scroll
#define LCDID() 		_lcd.id

extern LCDInfo _lcd;

и код для иде

#include <LCD.h>
unsigned long time;
unsigned long time2;
void setup(){
  LCDInit();
  Serial.begin(9600);
}
u16 xor16(void);

void Draw8(int cx, int cy, int x, int y, int color)
{
  LCDRectangle(cx-y,cy-x,y<<1,1,color);
  LCDRectangle(cx-x,cy-y,x<<1,1,color);
  LCDRectangle(cx-x,cy+y,x<<1,1,color);
  LCDRectangle(cx-y,cy+x,y<<1,1,color);
}

//	Octant circle drawing
void Circle(int cx, int cy, int radius, int color){
  int error = -radius;
  int x = radius;
  int y = 0;

//	draws in 4 strips from top down and middle up + reflection about y
  while (x >= y){
    Draw8(cx, cy, x, y,color);
    error += y;
    ++y;
    error += y;
    if (error >= 0){
      --x;
      error -= x<<1;
    }
  }
}

void TestBlit(){
  int buf[132];
  int w = LCDWidth();
  int h = LCDHeight();
  for (int i = 0; i < w; i++)
    buf[i] = 0xF800;
  LCDSetBounds(0,0,w,h);
  for (int y = 0; y < h; y++)
    LCDBlit((const u8*)buf,w);
}
void TestBlit2(){
  int buf[132];
  int w = LCDWidth();
  int h = LCDHeight();
  for (int i = 0; i < w; i++)
    buf[i] = 0x001F;
  LCDSetBounds(0,0,w,h);
  for (int y = 0; y < h; y++)
    LCDBlit((const u8*)buf,w);
}

void TestIndexedBlit(){
  int palette[132];
  u8 indx[132];
  int w = LCDWidth();
  int h = LCDHeight();
  for (int i = 0; i < w; i++){
    palette[i] = 0xF800 + (i >> 2);
    indx[i] = i;
  }
  LCDSetBounds(0,0,w,h);
  for (int y = 0; y < h; y++)
    LCDBlitIndexed(( u8*)indx,(u8*)palette,w);
}

void TestFill(){
  int cx = xor16() % LCDWidth();
  int cy = xor16() % LCDHeight();
  int radius = xor16() % LCDWidth();
  Circle(cx,cy,radius>>2,xor16());
}

void loop(){
  LCDBegin();
  
  time = millis();
  for (int y = 0; y < 50; y++){
     TestBlit();
     TestBlit2();
}
 
  time2= millis()-time;
  Serial.print(time2);
  Serial.print("   ");
  Serial.print((10000000/time2)/100);
  Serial.print(",");
  Serial.println((10000000/time2)%100);
 
}

 

toly
Offline
Зарегистрирован: 17.05.2014

Посмотрел немного...есть указатели, но по другому передать массив в функцию в С и нельзя. Например строка 145 в срр, тут два указателя на начало массивов байт, и отдельно их размер. Код в функции просто передвигает указатель чтобы читать данные, понятно, что это работает быстро, потому что действительно никакие данные в другой массив не копируются, работа идет с исходным массивом.

...для примера, выражение *data++ это данные из ячейки с адресом data, после чтения адрес сдвигается на одну ячейку (в нашем случае байт, т.к data объявлен как указатель на u8)

Geronimo
Offline
Зарегистрирован: 06.05.2013

так массив в си и есть указатель. 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Что я говорил, то в исходниках и есть. Непрерывная область передается указателем, одно число (8-16 бит) передается по значению.
 

gregoryl
Offline
Зарегистрирован: 09.09.2013

jeka_tm пишет:

я бы успокоился, но нашел библиотеку которая делает почти 18 кадров/сек

....

так как я с ними не умею работать, и чтение различной литературы особо ясности не добавило, прощу объяснить как сделать максимальное быстродействие

Я тут тоже игрался с SPI но совсем с другой стороны... SPI далеко не медленная штука :-)

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

Короче говоря если чистое время посылки Х а время на вызров функции Y, то общее время ( X + Y ) * N.

Если же передавать массив то формула почти не измениться ( X + Z ) * N, где Z это время на цикл прохода по массиву. Причем в зависимости от платформы и компилятора Z минимум в 3-4 а то и в 10-20 раз меньше чем Y. Улавливаете разнцицу ? но что еще более интересно что моя чуйка мне говорит, что X и Z это значения одного порядка, если у вас hardware SPI.....

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

gregoryl не понял что вы хотите сказать

кстати пока без использования указателей поднял частоту с 3,37 кадра/сек до 9,64 кадра/сек

дальше хочу ногодрыгать через прямое управление портов

не 

#define CS_On           PORTB |= 1<<2        // CS    PB2

а 

PORTB = 0b00000100;  //cs 1 data 0 clock 0

что будет быстрее. но писать тяжело если честно. пока не заработало

__Alexander
Offline
Зарегистрирован: 24.10.2012

jeka_tm пишет:

__Alexander не знаешь лучше молчи. тебе код дать где это работает?

Спешл во ю. Вот я подключил к хмеге, где spi 16Мгц. Давай, затыкай мне рот.

Или с математикой плохо? Давай считать, по SPI на 16Мгц ардине (это 8 реальных) ты один байт + одно ногодрыгание передашь за 3 мксек. Итого 128*160*2(байта на цвет)*3мксек = 123 мсек. т.е за секунду можно выплюнуть 8 кадров. хоть с указателями, хоть с папой римским. это тупо максимум. 

http://youtu.be/yJ9z7VrpfPQ

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

интересно. у меня сейчас без указателей частота обновления экрана 9,64кадра/сек. что я делаю неправильно?))) ведь это больше чем максимальные 8 кадров в сек

__Alexander
Offline
Зарегистрирован: 24.10.2012

я же примерно прикинул. давайте точнее посчитаем.

скорость зависит от этого куска, правильно?

void SpiData(u8 d){
MOSI1;
SCK1;
SCK0;
SPI_HW_ON;
SPDR = d;
SPI_HW_WAIT;
SPI_HW_OFF;
}

чтобы быть более точным, то прогнал в симуляторе. итого 2.5 мксек вместе в вызовом и возвратом. чтобы вывести 40960 быйт надо 102 400 мксек, что составляет 9.8 кадра. Но никак не 18, согласитесь.

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

 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да но ведь разговор идет о просто заливке. если это ускорить то ускорится весь вывод

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

vba0
Offline
Зарегистрирован: 05.07.2014

Уважаемый "jeka_tm" взял ваш пример с бибилеотеками, подключил экранчик nokia 1616 (MOSI 11, SCK 13, CS 10, reset 8) но нечего не происходит (только горит подсветка), подскажите что сделал не так.

P.S. подключал к ардуино мини про

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

вот рабочий вариант на хардварном SPI

http://yadi.sk/d/CXjuENmaEEwun

файл называется Nokia_1616_HARD

распакуйте в папку с вашими скетчами

reset подключить к 3.3В

 

vba0
Offline
Зарегистрирован: 05.07.2014

Огромное спасибо "jeka_tm".

Теперь встал вопрос: как вывести графику- картинку и чем конвертировить, желательно примерчик, я только пятаюсь всё понять (я новичок в этом деле).

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

с sd карточки я не пробовал еще, а из флеша без проблемм

вот только памяти сжирает очень много

2байта на цвет*128ширина*160высота= 40960 байт. картинку для всего экрана даже в обычную ардуину не засунешь

нужно цеплять sd карточку. я планирую сделать, как только разберусь с форматом bmp или научусь пользовать функциями библиотеки sd, там уже вроде все реализовано

я конвертирую lcd-image-converter

 

vba0
Offline
Зарегистрирован: 05.07.2014

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

Картинка 16bit (R5G6B5)  16x16:

0xffff, 0xffff, 0xffdf, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xffdf, 0xffff, 0xffff, 
0xffff, 0xc65b, 0x63b4, 0x63b4, 0x6bb4, 0x6bd4, 0x6bd4, 0x6bb4, 0x6bb4, 0x6bd4, 0x6bd4, 0x6bb4, 0x63b4, 0x63b4, 0xc65b, 0xffff, 
0xffdf, 0x63b4, 0x953a, 0xb63e, 0xb63d, 0xbe3d, 0xb63d, 0xbe5e, 0xbe5e, 0xb63d, 0xbe3d, 0xb63d, 0xbe3e, 0x953a, 0x63b4, 0xffdf, 
0xf79e, 0x63b4, 0xb61d, 0xbe5e, 0xbe7e, 0xc69f, 0xe73f, 0xf7bf, 0xf7bf, 0xe73f, 0xc69f, 0xbe7f, 0xbe5e, 0xb61d, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0xaddc, 0xb63e, 0xbe3d, 0xe75f, 0xffff, 0xffdf, 0xffdf, 0xffff, 0xe75f, 0xbe3d, 0xbe3e, 0xaddc, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0xadbc, 0xb61d, 0xc67e, 0xffff, 0xf7bf, 0xbe5d, 0xbe5d, 0xf7bf, 0xffff, 0xbe5d, 0xb61d, 0xadbc, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0xa59b, 0xaddc, 0xb61d, 0xe75e, 0xce9d, 0xaddd, 0xbe5d, 0xffdf, 0xf7bf, 0xb5fc, 0xaddc, 0xa59b, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0x9d7b, 0xa5bb, 0xa5bc, 0xadbc, 0xadbc, 0xbe3c, 0xf7bf, 0xffff, 0xbe5d, 0xa5bb, 0xa5bb, 0x9d7b, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0x953a, 0x9d7b, 0x9d7b, 0xa59b, 0xa59b, 0xef7f, 0xffff, 0xb61c, 0x9d7b, 0x9d7b, 0x9d7b, 0x953a, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0x8cf9, 0x953a, 0x953a, 0x953a, 0x9d7a, 0xffdf, 0xd6dd, 0x951a, 0x955a, 0x953a, 0x953a, 0x8cf9, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0x84b8, 0x8cd8, 0x8cf9, 0x8cf9, 0x8cf9, 0xb5fb, 0xa57a, 0x8cf9, 0x8cf9, 0x8cf9, 0x8cd8, 0x84b8, 0x63b4, 0xf79e, 
0xf79e, 0x63b4, 0x7c97, 0x8497, 0x8498, 0x8498, 0x94f8, 0xffff, 0xdf1d, 0x8498, 0x84b8, 0x84b8, 0x8497, 0x7c97, 0x63b4, 0xf79e, 
0xf79e, 0x6394, 0x7c57, 0x7456, 0x7c76, 0x7c76, 0x7c97, 0xc67b, 0xadda, 0x7456, 0x7c77, 0x7c76, 0x7456, 0x7c77, 0x6394, 0xf79e, 
0xffdf, 0x63b4, 0x6bd5, 0x7436, 0x7436, 0x7456, 0x7456, 0x6c16, 0x7436, 0x7456, 0x7456, 0x7436, 0x7436, 0x6bd5, 0x63b4, 0xffdf, 
0xffff, 0xc65b, 0x63b4, 0x6394, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x6394, 0x63b4, 0xc65b, 0xffff, 
0xffff, 0xffff, 0xffdf, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xffdf, 0xffff, 0xffff

Вот к примеру что содержится в каждом блоке "0xffff", цвет ? Как эту информицию обработать.

Заранее спасибо.

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

в инициализации дисплея включен режим 16 бит. вот ваши каждые 2 байта это 1 пиксель

в коде есть функция создания области вывода LCD_Window

создаете область вывода с вашими размерами рисунка

а потом просто цикл и считываете поочередно все байты из массива и рисуете пиксель

только пиксель рисуете не командой LCD_Pixel, а просто передаете данные командой 

lcd_write16(color); где color цвет пикселя. чтение из массива слева направо сверху вниз

с командой lcd_write16 будет быстрее немного

можно и  LCD_Pixel использовать, но тогда каждой точке надо задавать координаты

а если точки идут подряд можно просто передавать цвет

ffff это цвет. в данном случае белый

vba0
Offline
Зарегистрирован: 05.07.2014

т.е. как я понимаю в даном случае это двухмерный масив цветов 16х16 ?

е ещё вопрос как обьявить этот масив как int или byte, просто как я понимаю в тип byte не влезить цвет за раз а в int влезит.

и как правельно передавать значение функции допустем так ?:

int myimg[] PROGMEM = {0xffff, 0xffff, 0xffdf, 0xf79e, 0xf79e, 0xf79e, .......... , 0xf79e, 0xf79e, 0xffdf, 0xffff, 0xffff}

void LCD_drawImage (byte x, byte y, byte w, byte h, const int *bitmap)
{
  for (byte _y=0; _y < h-1; _y++)
  {
     LCD_Window(x, y+_y, w, y+_y);
     for (byte _x=0; _x < w-1; _x++)
     {
        lcd_write16(bitmap[(_y*h)+_x]);
     }
}

void loop()
{
  LCD_drawImage(25,25,16,16, myimg);
  delay(10000);
}

Кстати а как изменить контрастность ?

И ещё вопрос посмотрел откоректированную вами библеотеку "Adafruit_ST7735" она очень похожа на тот код что вы дали (фрагментами), возможно ли её легко-быстро переделать под дисплей 1616 или есть подводные камни ?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

unsigned int

что то вроде

контрастность особо не удалось изменить, а вам зачем? вроде хорошо работает дисплей

хотя можете даташит покурить на контроллер дисплея

конечно они похожи. ведь и там и там дисплей с 16 битным режимом цвета, размер дисплея, и почти одинаковый интерфейс

зачем переделывать? вообще можно, но я не хочу, в чем смысл если получится почти тоже самое что я дал вам

vba0
Offline
Зарегистрирован: 05.07.2014

jeka_tm пишет:

контрастность особо не удалось изменить, а вам зачем? вроде хорошо работает дисплей

у меня получается если смотреть на него от шлейфа в верх то нехрена не видно, а наоборот сильно перенасыщенно.

jeka_tm пишет:

конечно они похожи. ведь и там и там дисплей с 16 битным режимом цвета, размер дисплея, и почти одинаковый интерфейс

зачем переделывать? вообще можно, но я не хочу, в чем смысл если получится почти тоже самое что я дал вам

просто там всё структурировано плюс уже готовые примеры есть и их не надо переделовать )))

 

P.S. нашёл ошибку (или я чегото не правельно делаю) но если перевернуть экран (90 градусов) то получаем по недействующему пикселю по X и Y. вышей из ситуации так:
сделал переменую: byte lcd_mode =0;

и изменил "LCD_Window":

void LCD_Window(byte x, byte y, byte w, byte h)
{
  lcd_write_cmd(0x2A); //x-координата
  if ((lcd_mode == 0) or (lcd_mode == 2)) {lcd_write16(x+2); lcd_write16(x+w+1);} else
  if ((lcd_mode == 1) or (lcd_mode == 3)) {lcd_write16(x+1); lcd_write16(x+w);} 
  lcd_write_cmd(0x2B);//Y-координата
  if ((lcd_mode == 0) or (lcd_mode == 2)) {lcd_write16(y+1); lcd_write16(y+h+1);} else
  if ((lcd_mode == 1) or (lcd_mode == 3)) {lcd_write16(y+2); lcd_write16(y+h+2);} 
  lcd_write_cmd(0x2C);
}

интересно ваше мнение, я ошибаюсь или всё верно ?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

насчет контрастности я такого не замечал, смотрел на дисплей первендикулярно в основном

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

так переделайте либу и радуйтесь. если не можете тут я вам не помогу. рабочую уже дал

структурируйте эту если что то не устраивает

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

а насчет изменений тестируйте. только or не оставляйте

 

 

vba0
Offline
Зарегистрирован: 05.07.2014

jeka_tm пишет:

а насчет изменений тестируйте. только or не оставляйте

Очень интересует почему нельза OR ? и вместо него поставить ||  ?

Спасибо большое за помощь вы очень сильно помогли, теперь буду подключать sd и работать с bmp (я как понял в нём изображение с заду на перед читать надо).

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да пожалуйста

||

насчет bmp я пока не разобрался. если разберетесь киньте код

__Alexander
Offline
Зарегистрирован: 24.10.2012




for x:= (strtoint(Edit6.Text)) - 1 downto 0 do
for y:= 0 to (strtoint(Edit7.Text)) - 1  do begin
    color:=image1.Canvas.Pixels[x,y];

 r:=GetRValue(color);
 g:=GetGValue(color);
 b:=GetBValue(color);

 lowbyte := ((b and $F8) or (g shr 5));
 highbyte := (((g shl 3) and $E0)or (r shr 3));


 Memo1.SelText := '0x' + inttohex(lowbyte, 2)+ ', 0x' +inttohex(highbyte, 2) + ',';
 Memo1.SelText := #13+#10;

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

я делал вот так. на делфи.

 

vba0
Offline
Зарегистрирован: 05.07.2014

Думаю в наш век проблем с размером sd карты не возникнет, а bmp читать то легко, это просто таблица пиксель-RGB, мне просто удобно видеть наглядно когда я подготовливаю флешку на пк.
http://en.wikipedia.org/wiki/BMP_file_format

У меня вот проблема возникла с подключением LCD и SD одновременно, если есть какие нибудь примерчики или разьяснения (желательно подробней) буду очень рад.

__Alexander
Offline
Зарегистрирован: 24.10.2012

читать bmp то легко, только преобразование в 5-6-5 будет забирать время. т.е. следовательно - падение fps.

vba0
Offline
Зарегистрирован: 05.07.2014

но я впринцепе фильмы гонять не буду поэтому мне хватит заглаза.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

есть программка Easy Graphic Converter

конвертирует в 16 битный формат. на форуме находил инфу что в 5-6-5. но не уверен

попробовал конвертировать. работает. но что там получается хз

vba0
Offline
Зарегистрирован: 05.07.2014

Помогите запустить LCD и SD одновремено, всё кроме CS подключено паралельно. По отдельности всё работает.

#include <avr/pgmspace.h>
#include <SD.h>
#include "Arduino.h"
#include "fonts.h"
#include "images.h"

// ====================================================================================================================================================================
#define PIN_LCD         10
#define PIN_SD        4

#define CS         10
#define DAT        11
#define CLK        13

#define SPI_OFF   SPCR = 0;
#define SPI_ON    SPCR = _BV(MSTR) | _BV(SPE);
#define SPI_WAIT  while (!(SPSR & _BV(SPIF)));

// определение основных цветов 16bit
#define BLACK   0x0000
#define WHITE   0xffff
#define RED     0xF800
#define GREEN   0x07E0
#define BLUE    0x001F
#define YELLOW  0xFFE0 //Желтый
#define CYAN    0x07FF //Голубой
#define MAGENTA 0xDEE0 //Фиолетовый

//#define DISP_W 128
//#define DISP_H 160
byte DISP_W = 128;
byte DISP_H = 160;

byte lcd_mode =0;

#define CHAR_W 8
#define CHAR_H 15

#define CS_On           PORTB = 1<<2        // CS    PB2
#define CS_Off          PORTB = 0<<2
#define DAT_On          PORTB = 1<<3        // Data  PB3
#define DAT_Off         PORTB = 0<<3
#define CLK_On          PORTB = 1<<5        // Clock PB5
#define CLK_Off         PORTB = 0<<5

unsigned int bgcolor = BLACK;



//=============================Вывод на дисплей 8 бит комманд===================================

void lcd_write_cmd(byte c){
  SPI_WAIT;
  SPI_OFF;
  
  DAT_Off;
  CLK_On;
  CLK_Off;
 
  SPI_ON;
  SPDR = c;
}

//=============================Вывод на дисплей 8 бит данных====================================

void lcd_write_dat(byte c){
  SPI_WAIT;
  SPI_OFF;
  
  DAT_On;
  CLK_On;
  CLK_Off;
  
  SPI_ON;
  SPDR = c;
}

//============================Вывод на дисплей 16 бит данных====================================

void lcd_write16(unsigned int dat){
  lcd_write_dat(dat>>8);
  lcd_write_dat(dat);
} 

//================================Инициализация дисплея=========================================

void lcd_init_rgb(byte mode = 0){ 
  
  pinMode(CS, OUTPUT);
  pinMode(DAT, OUTPUT);
  pinMode(CLK, OUTPUT);
  
  SPSR |= 8;	// 2x clock

  SPI_ON;
  SPDR = 0x00;
  
  CS_Off;
  delay(10);
  CS_On;
  lcd_write_cmd(0x01); 
  delay(50);       //reset  
  CS_Off;

  lcd_write_cmd(0xBA); // Порядок отсылки данных
  lcd_write_dat(0x07);
  lcd_write_dat(0x15);
  lcd_write_cmd(0x25); // Контраст
  lcd_write_dat(0x3F);
  lcd_write_cmd(0x11); // Выход из режима sleep, (0x10) sleep
  lcd_write_cmd(0x14);
  
  lcd_write_cmd(0x37); // Дополнительные настройки
  lcd_write_dat(0x00);
  lcd_write_cmd(0x3A);
  lcd_write_dat(0x05);
  lcd_write_cmd(0x29); // Включить дисплей, (0x28) выключить
  lcd_write_cmd(0x20); // Нормальный режим, (0x21) инвертированный
  
  lcd_write_cmd(0x36); // Ориентация дисплея
  lcd_mode = mode;
  if (mode == 0){
    lcd_write_dat(0xC0); //   0 градусов
    DISP_W = 128;
    DISP_H = 160;
  }
  if (mode == 1){
    lcd_write_dat(0xA0); //   90 градусов
    DISP_W = 160;
    DISP_H = 128;
  }
  if (mode == 2){
    lcd_write_dat(0x00); //   180 градусов
    DISP_W = 128;
    DISP_H = 160;
  }
  if (mode == 3){
    lcd_write_dat(0x60); //   270 градусов
    DISP_W = 160;
    DISP_H = 128;
  }
  
  lcd_write_cmd(0x13);
  
  CS_Off;
}

//===================================Заливка дисплея============================================

void LCD_Fill_all(unsigned int color){   
  LCD_Window(0, 0, DISP_W, DISP_H);
  byte i=DISP_H;
  byte j;
  while(i--){
    j=DISP_W;
    while(j--){
      lcd_write16((color));
    }
  }
 
}

//================================Переход в координаты XY=======================================

void LCD_XY(byte x, byte y){
  lcd_write_cmd(0x2A); //x-координата
  lcd_write16(x+2);
  lcd_write_cmd(0x2B);//Y-координата
  lcd_write16(y+1);
}

//============================Создание области для рисования====================================

void LCD_Window(byte x, byte y, byte w, byte h){
  lcd_write_cmd(0x2A); //x-координата
  //lcd_write16(x+2);
  if ((lcd_mode == 0) or (lcd_mode == 2)) {lcd_write16(x+2); lcd_write16(x+w+1);} else
  if ((lcd_mode == 1) or (lcd_mode == 3)) {lcd_write16(x+1); lcd_write16(x+w);} 
  //lcd_write16(x+w+1);
  lcd_write_cmd(0x2B);//Y-координата
  //lcd_write16(y+1);
  if ((lcd_mode == 0) or (lcd_mode == 2)) {lcd_write16(y+1); lcd_write16(y+h+1);} else
  if ((lcd_mode == 1) or (lcd_mode == 3)) {lcd_write16(y+2); lcd_write16(y+h+2);} 
  //lcd_write16(y+h+1);
  lcd_write_cmd(0x2C);
}

//====================================Рисуем пиксель============================================

void LCD_Pixel(byte x, byte y, int color){
  LCD_XY(x,y);
  lcd_write_cmd(0x2C);// WR_MEM
  lcd_write16(color);
}   

//===========================Вывод символа в XY заданного цвета=================================

void LCD_Char(byte x, byte y, unsigned char c, unsigned int color){
  byte ch;  
  byte mask = 0x80;  
  
  LCD_Window(x, y, CHAR_W, CHAR_H);

  for (byte h=0; h<CHAR_H; h++){ // every column of the character
    ch=pgm_read_byte(&(FONT8x15[c-32][h]));
    mask = 0x80;
    for (byte p=0; p<CHAR_W; p++){  // write the pixels
      (ch & mask)? lcd_write16(color) : lcd_write16(bgcolor);
       mask >>= 1;
    }
  }
}

//===========================Вывод текста в XY заданного цвета==================================

void put_string(byte x, byte y, char *str, unsigned int color){
  unsigned char j;
  j=0;
  while (j<strlen(str)){
    LCD_Char((x+j*CHAR_W),y,str[j], color);
    j++;
  }
}



//===================================Линия=======================================

void LCD_Line(byte x0, byte y0, byte x1, byte y1, unsigned int color){ 
  int dy = y1 - y0; 
  int dx = x1 - x0; 
  int stepx, stepy; 
  if (dy < 0){ 
    dy = -dy;  
    stepy = -1; 
  } 
  else stepy = 1; 
  if (dx < 0){ 
    dx = -dx;  
    stepx = -1; 
  } 
  else stepx = 1; 

  dy <<= 1;                              // dy is now 2*dy 
  dx <<= 1;                              // dx is now 2*dx 

  LCD_Pixel(x0, y0, color); 

  if (dx > dy) { 
    int fraction = dy - (dx >> 1);     // same as 2*dy - dx 
    while (x0 != x1){ 
      if (fraction >= 0) { 
        y0 += stepy; 
        fraction -= dx;            // same as fraction -= 2*dx 
      } 
      x0 += stepx; 
      fraction += dy;                // same as fraction -= 2*dy 
      LCD_Pixel(x0, y0, color); 
    } 
  } 
  else{ 
    int fraction = dx - (dy >> 1); 
    while (y0 != y1){ 
      if (fraction >= 0){ 
        x0 += stepx; 
        fraction -= dy; 
      } 
      y0 += stepy; 
      fraction += dx; 
      LCD_Pixel(x0, y0, color); 
    } 
  } 
} 





//==========================================Круг===============================================

void LCD_Circle(byte x0, byte y0, byte r, unsigned int color) {
  int16_t f = 1 - r;
  int16_t ddF_x = 1;
  int16_t ddF_y = -2 * r;
  int16_t x = 0;
  int16_t y = r;

  LCD_Pixel(x0  , y0+r, color);
  LCD_Pixel(x0  , y0-r, color);
  LCD_Pixel(x0+r, y0  , color);
  LCD_Pixel(x0-r, y0  , color);

  while (x<y) {
    if (f >= 0) {
      y--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;

    LCD_Pixel(x0 + x, y0 + y, color);
    LCD_Pixel(x0 - x, y0 + y, color);
    LCD_Pixel(x0 + x, y0 - y, color);
    LCD_Pixel(x0 - x, y0 - y, color);
    LCD_Pixel(x0 + y, y0 + x, color);
    LCD_Pixel(x0 - y, y0 + x, color);
    LCD_Pixel(x0 + y, y0 - x, color);
    LCD_Pixel(x0 - y, y0 - x, color);
  }
}  


void LCD_VLine(byte x, byte y, byte h, unsigned int color) {
  LCD_Line(x, y, x, y+h-1, color);
}

void LCD_HLine(byte x, byte y, byte w, unsigned int color) {
  LCD_Line(x, y, x+w-1, y, color);
}

void LCD_Rect(byte x, byte y, byte w, byte h, unsigned int color) {
  LCD_HLine(x, y, w, color);
  LCD_HLine(x, y+h-1, w, color);
  LCD_VLine(x, y, h, color);
  LCD_VLine(x+w-1, y, h, color);
}

void LCD_drawBitmap(byte x, byte y, const byte *bitmap, byte w, byte h, unsigned int color){

  byte i, j, byteWidth = (w + 7) / 8;

  for(j=0; j<h; j++) {
    for(i=0; i<w; i++ ) {
      if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
        LCD_Pixel(x+i, y+j, color);
      }
    }
  }
}



void LCD_drawImage (byte x, byte y, byte w, byte h, const int *bitmap)
{

 for (byte _y=0; _y < h-1; _y++)
 {
   LCD_Window(x, y+_y, w, y+_y);
   for (byte _x=0; _x < w-1; _x++)
   {
      lcd_write16(bitmap[(_y*h)+_x]);
   }
  }
}

uint16_t ConvertColorRGB(uint8_t r, uint8_t g, uint8_t b) {  //565
  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

/*void LCD_Off (){
  digitalWrite(CS, LOW);
  pinMode(CS, INPUT);
  delay(80);
  pinMode(CS, INPUT);
}

void LCD_On ()
{
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  digitalWrite(CS, LOW);
}*/

// ====================================================================================================================================================================

void setup(){
  Serial.begin(9600);
  
  
  lcd_init_rgb(1);
  
  
/*  if (!SD.begin(PIN_SD)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");*/
  
  
  
  
  //pinMode(PIN_SD, OUTPUT);
  //pinMode(PIN_SD, OUTPUT);
  
  /*pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);*/
  
  
  LCD_Fill_all(bgcolor);
  //LCD_Fill_all(ConvertColorRGB(255,255,255));
  //put_string(20, 20, "privet", RED);

  
  //LCDInit();
  
  
}
//u16 xor16(void);


void loop(){
  //LCDBegin();
//LCD_On;
 
  //for (int y = 0; y < 50; y++){
    
    LCD_Fill_all(BLACK);
    put_string(20, 20, "privet", RED);
    delay(3000);
    LCD_Fill_all(GREEN);
    delay(1000);
    LCD_Fill_all(BLUE);
    delay(1000);
    
  
   File dataFile = SD.open("ico.txt");

  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  } 
  

  
    
    LCD_Fill_all(RED);
    delay(1000);
    LCD_Fill_all(ConvertColorRGB(255,255,255));
    delay(5000);
    
    /*LCD_drawImage(0,0,16,16, myimgq2);
    LCD_drawImage(0,112,16,16, myimgq2);
    
    LCD_drawImage(25,25,16,16, myimgq2);
    LCD_drawImage(50,25,16,16, myimgq2);
    LCD_drawImage(25,50,16,16, myimgq2);
    LCD_drawImage(25,75,16,16, myimgq2);
    LCD_drawImage(50,75,16,16, myimgq2);*/
    //LCD_drawBitmap(1,1, myimg,96,68, GREEN);
    //byte zz;
    //for (zz = 1; zz < 256; zz++){
    //   LCD_Fill_all(myimgq[zz]);  
    //   Serial.print("Num: ");
    //  Serial.print(zz);
    //  Serial.print("   Data: ");
    //  Serial.println(myimgq[zz]);
    //  delay(1500);
    //}
    
     //TestBlit();
     //delay(3000);
     //TestBlit2();
    // delay(3000);
    // TestIndexedBlit();
   //  delay(3000);
   //  TestFill();
    // delay(3000);

 // }
 
 
}

 

vba0
Offline
Зарегистрирован: 05.07.2014

Ну что никто не знает как переключатся между LCD и SD ?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

этот код я делал чтобы выжать макс скорость отрисовки экрана, и для работы с sd и дисплеем не особо подходит. точнее подходит, но нужно один кусок поправить. точнее функцию lcd_write_cmd и lcd_write_dat

изменения одинаковые

а переключаться просто (наверно, я только теоретически догадываюсь). есть пинь SS вроде называется (обычно), короче выбор нужного устройства на SPI выбирая этот пин. и перидически переключаться между дисплеем и карточкой.

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

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

интересует как работать с файлом картинки сохраненной на SD. допустим один файл одна картинка. формат bmp. возможно уже сконвертированный в формат R5G6B5 (если программа конвертирует как надо)

интересует следующее. так как всю картинку считать оперативки не хватит, нужно по кускам. как это делает? скорее всего считывается например 500 байт а потом выводятся на дисплей и так далее пока не считается вся картинка

вопрос как считывать картинку с SD и как считывать по кускам файл

leshak
Offline
Зарегистрирован: 29.09.2011

>вопрос как считывать картинку с SD

Вы одновременно работы SD и экрана уже добились?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

нет. я к sd даже не приступал. точнее только считывал только инфу что карточке, и свобоное место

вот думаю как подступится

библиотека конечно есть, но что делать хз. код то готовый был

leshak
Offline
Зарегистрирован: 29.09.2011

jeka_tm пишет:

нет. я к sd даже не приступал. точнее только считывал только инфу что карточке, и свобоное место

Так вот это "считывал инфу на карточке" одноврменно с экраном или нет?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

нет. вывод был через w5100 насколько помню

экран я отдельно запускал

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

нет. вывод был через w5100 насколько помню

экран я отдельно запускал

leshak
Offline
Зарегистрирован: 29.09.2011

jeka_tm пишет:

нет. вывод был через w5100 насколько помню

Ну в теории тут должно быть то же самое. Причем теорию вы сами озвучили выше :)  Каждому свой SS пин и перед тем как работать с кем-то из них - включать его, а после - выключать.

Вначале добейтесь тупого:
1. Проинициализировать экран, и вывести на него, скажем цифру один.
2. Отклчить его SS
3. Проинициализировать SD (включив ее SS), что-нибудь с нее прочитать (ту же инфу) и отправить в Serial 
4. Выключить SS sd-шки.
5. Включить SS экрана, вывести на него цифру два.

Ну вообщем если эти пункты удайтся пройти то можно сказать "они работают одновременно". Потом можно будет разбиратся как "читать по кускам" и т.п.

В качестве примера можно как раз про w5100 смотреть, там тоже "по очереди" с ними работают.

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

1. я уже сделал. библиотеку писал же, помогли конечно. но основное я. я туда и FFT выводил уже

2. это могу

3-5 попробую завтра

leshak
Offline
Зарегистрирован: 29.09.2011

Так, шо-бы було... когда дойдете до bmp-шки читать, вот такая ссылочка нагуглилась: https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino/blob/master/examples/bmp/bmp.pde там можно попытатся спионерить чтение, парсинг bmp-шки.
Только уже вывод самой точки на экран, на вызов вашей библиотеки подменить.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

о спасибо. завтра будут пробывать. че то я железе зарылся в последнее время

ирония судьбы)))

leshak
Offline
Зарегистрирован: 29.09.2011

jeka_tm пишет:

о спасибо. завтра будут пробывать. че то я железе зарылся в последнее время

Не, не.... до этого еще далеко. У нас еще куча всего проверить будет... маленькими шагами. Только так. 
Сделать 5 копипастов из 5-ти мест получить портянку на 15 пейждаунов, а потом пытаться разобраться "что же тут не так" - это не наш метод (ну по крайней мере такое - без меня).

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а вам значит можно, а мне нельзя. так нечестно

leshak
Offline
Зарегистрирован: 29.09.2011

jeka_tm пишет:

а вам значит можно, а мне нельзя. так нечестно

Кто сказал что "мне можно"? Я ссылочку оставил что-бы "не потерялась" :)

А сам я тоже, только вначале по частям все проверить, потом начать добавлять по ОДНОЙ фишке.
Только малыми шагами, только так, только одно что-то за раз меняя.

Я вот сам бы ровно по тем же шагам что вам перечислил делал бы. Я вот с новым железом (с програмно части) тоже разбираюсь именно так.

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да я так, не спорю. сам бы так сделал. все собирался занятся этим вопросом. все откладывал

но с вашей поддержкой будет проще. не хватает знаний