HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
LINK
BACK
 

2017/03/20

Raspberry Pi用 KeDei 3.5インチ TFT液晶を SPIで自前のプログラムで制御する方法 Raspberry Pi用 KeDei 3.5インチ TFT液晶を SPIで自前のプログラムで制御する方法

(遂に KeDei 3.5インチ液晶 V5.0を自前プログラムで制御できる様になった!)

Tags: [Raspberry Pi], [電子工作]





● Raspberry Pi 3 Model Bを遂に購入

 Raspberry Pi3 Model B RPI2 RPI3

 大人気の CPUボードの Raspberry Piに WiFiと Bluetoothが搭載されたモデルが新発売となりました。
 以前から Raspberry Pi 2を買おうかどうか迷っていましたが、Raspberry Pi 3 Model Bの発売を機に購入を決意してラズベリアンになる事にしました。

 ※ ラズパイの OS Raspbianはバージョンが上がる毎に過去の版と OSの内部の作りが変わり、過去に書かれた製作記事(例えば Raspbian Wheezyの時代の記事)がそのままではエラーが出たりして動かない事が有ります。
 ※ 当方のホームページのラズパイ記事は全て Raspberry Pi 3 Model Bと Raspbian Jessieの組み合わせで動作確認をしております。
(ただし、将来的に新しい Raspbian OSが出た場合に、当方の Raspbian Jessieを基にした内容がそのままでは動かない可能性が有ります。)
 ※ 2017/08/16から Raspbian OSは Raspbian Jessieから Raspbian Stretchに変わりました。
 ※ 2019/06/20から Raspbian OSは Raspbian Stretchから Raspbian Busterに変わりました。

Download Raspbian for Raspberry Pi

ちなみに、歴代のバージョンと名称は
Debianコードネーム年月備考(参考)Ubuntuでの該当名称
Debian 11Bullseye2021/08/14~2021/11からラズパイにリリースFocal Fossa 20.04 LTS ?
Debian 10Buster2019/06/20~2019/06からラズパイ4対応Bionic 18.04 LTS
Debian 9Stretch2017/08/16~2018/03からラズパイ3B+対応Xenial 16.04 LTS
Debian 8Jessie2015~2016/02からラズパイ3対応Trusty 14.04 LTS
Debian 7Wheezy2013~2016
Debian 6.0Squeeze2011~2014
Debian GNU/Linux 5.0Lenny2009~2012


● 3.5インチ SPI接続 液晶ディスプレイ(感圧式タッチパネル搭載 XPT2046 SPI接続)

 Kedei 3.5 TFT LCD for Raspberry Pi
KeDei公式ホームページ http://www.kedei.net

 3.5inch LCD V5.0 480x320 Pixel XPT2046 Touch Controller
 液晶表示制御(SPI接続, CE1=GPIO7)
 3552 3.5インチ 4線式抵抗膜タッチスクリーンデジタイザ
 XPT2046タッチパネルコントローラ(SPI接続, PENIRQ=GPIO25, CE0=GPIO8)

 ・液晶パネル TFT 320*(RGB)*480 Dots、86.0*56.2mm、6 White LED
 ・液晶パネルコントローラ ILI9488
 ・タッチパネルコントローラ XPT2046
 ・タッチパネル LXH-TPM207-3.5 Model

 KeDei製の液晶は汎用性に欠けるので購入をオススメしません。(ドライバをアップデートしないので将来的に使えなくなる。と言うか 2017年 3月の現時点で V5版は実質的に使えなくなりました。)

 が、下記の解析結果により FBTFTドライバへの移植が期待されます。

 2017/03/24 notro氏の提供する tinydrmを使用して KeDei 3.5インチ液晶 V5.0をフレームバッファ駆動する事に成功しました。
KeDei 3.5 inch 480x320 TFT lcd from ali
 by notro > Fri Mar 24, 2017 3:52 am

 ただし、物凄く遅いです。
[GitHub] FREEWING-JP/tinydrm - forked from notro/tinydrm
[GitHub] FREEWING-JP/tinydrm - forked from notro/tinydrm


● 3.5インチ タッチパネル付き TFT液晶 KeDei Ver5.0 2016/3/1版(GPIO接続)

KeDei LCD Interface Define:
ピン接続:
1   ----> NC
2   ----> 5v
3   ----> NC
4   ----> 5V
-- ----------
19 ----> MOSI
20 ----> GND
21 ----> MISO
22 ----> TP_IRQ  GPIO25
23 ----> SCLK
24 ----> TP_CS  GPIO8 CE0
25 ----> GND
26 ----> LCD_CS GPIO7 CE1

 KeDei TFT LCD Ver5.0 2016/3/1
・Kedei 3.5inch TFT LCD V5.0 module for Raspberry Pi
Kedei 3.5inch TFT LCD V5.0 module for Raspberry Pi




● ラズパイ3用 3.5インチ液晶 KeDei V5.0

 KeDei液晶と格闘している人達

 ※ KeDei液晶は GitHubの notro/fbtftは使えません。
GitHub notro/fbtft

KeDei 3.5 inch 480x320 TFT lcd from ali
by Conjur - Mon Aug 22, 2016 2:12 am - Final post on the KeDei v5.0 code.
 ESP8266モジュールで無改造の KeDei液晶 V5.0を制御している。

1N4148/Kedei - Samples for Kedei TFT captured with a FPGA based shift register decoder V6.0液晶
 YXT35MH357-A

KeDei 3.5 inch 480x320 TFT lcd from ali
 FBTFTで動く様に KeDei液晶の回路部分を改造している。
Just another weblog - Raspberry Pi TFT
KeDei液晶を解析した回路図等
 74HC595Dを 74VHC595に交換すれば SPIクロックを 30MHzから 100MHzにクロックアップで動く様にできるかも?(単純に 3倍速)

GitHub - Search kedei
・saper-2/rpi-spi-lcd35-kedei
 Driver for user software to controll KeDei 3.5" TFT LCD on SPI without custom kernel
・l0nley/kedei35
 Kedei 35 TFT LCD Libary. based on saper-2 library
・zefj/kedei2-patchfiles
 Patchfiles and driver to compile custom kernel that supports Kedei 3.5" TFT V2
・wdim0/esp8266_with_KeDei_lcd_module
 ESP8266 with 3.5" KeDei LCD module
 ESP8266とは WiFi付きの Arduino互換モジュール
 KeDei液晶の回路部分を改造して表示している。

2016/04/30
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板

  Espressif ESP8266 ESP-12-E NodeMCU V1 ESP12 CP2102


● 3.5インチ液晶 KeDei V5.0を素の状態の Raspbian OSで使用する方法

 3.5インチ液晶 KeDei V5.0を素の状態の Raspbian OSで使用する方法。
 目的としては KeDei公式のパッチを使用せずに notro/fbtft等で使用できる様にします。
 (公式パッチで普通に問題無く使用できますが、自前で自由に制御したい)

 まずは、タッチパネルの制御。
$ sudo nano /boot/config.txt
 に下記を追加する。
# KeDei 3.5inch SPI LCD with Touch Panel XPT2046(SPI, IRQ=GPIO25, CE0)
# タッチパネル用に SPIを有効にする
dtparam=spi=on
dtoverlay=ads7846,penirq=25,speed=10000,penirq_pull=2,xohms=150,cs=0

 タッチパネル校正アプリのインストール
$ sudo apt-get -y install evtest tslib libts-bin

 タッチパネルの動作確認、Device Treeが有効の時に動く
$ sudo evtest

No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: ADS7846 Touchscreen
Select the device event number [0-0]: 0
Input driver version is 1.0.1
Input device ID: bus 0x0 vendor 0x0 product 0x0 version 0x0
Input device name: "ADS7846 Touchscreen"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 330 (BTN_TOUCH)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 1762
Min 0
Max 4095
Event code 1 (ABS_Y)
Value 1605
Min 0
Max 4095
Event code 24 (ABS_PRESSURE)
Value 0
Min 0
Max 65535
Properties:
Testing ... (interrupt to exit)

 ~~~液晶画面をタッチすると下記の動作ログが出力される ~~~
Event: time 1463221567.720745, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1463221567.720745, type 3 (EV_ABS), code 0 (ABS_X), value 1878
Event: time 1463221567.720745, type 3 (EV_ABS), code 1 (ABS_Y), value 2176
Event: time 1463221567.720745, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 65289
Event: time 1463221567.720745, -------------- EV_SYN ------------
Event: time 1463221567.747000, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1463221567.747000, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 0
Event: time 1463221567.747000, -------------- EV_SYN ------------


● ESP8266モジュールで無改造の KeDei液晶 V5.0を制御しているのをラズパイに移植してみた。

 上記の KeDei液晶と格闘している人達の解析記事を参考にして動かす事に成功しました。

https://github.com/l0nley/kedei35 l0nley/kedei35
 と
KeDei 3.5 inch 480x320 TFT lcd from ali
by Conjur - Mon Aug 22, 2016 2:12 am - Final post on the KeDei v5.0 code.
 ESP8266モジュールで無改造の KeDei液晶 V5.0を制御している。

 を参考に、双方を合体させて、KeDei液晶 V5.0を自前のプログラムから動かす事に成功しました!!!
 これで FBTFT等の汎用ドライバへの移植が可能になります!!!

・キーとなる部分
 SPIの送信部分
 コマンド、データ、色データの 3個の関数が有る。
void lcd_rst(void) {
  GPOC = 1<<SPI_SS_L; SPI.write(0); GPOS = 1<<SPI_SS_L; delay(25);
  GPOC = 1<<SPI_SS_L; SPI.write(1); GPOS = 1<<SPI_SS_L; delay(25);
}
void lcd_cmd(uint8_t cmd) {
  GPOC = 1<<SPI_SS_L; SPI.write(cmd>>1); SPI.write(0x11+((cmd&1)<<5)); GPOS = 1<<SPI_SS_L;
  GPOC = 1<<SPI_SS_L; SPI.write(cmd>>1); SPI.write(0x1B+((cmd&1)<<5)); GPOS = 1<<SPI_SS_L;
}
void lcd_data(uint8_t dat) {
  GPOC = 1<<SPI_SS_L; SPI.write(dat>>1); SPI.write(0x15+((dat&1)<<5)); GPOS = 1<<SPI_SS_L;
  GPOC = 1<<SPI_SS_L; SPI.write(dat>>1); SPI.write(0x1F+((dat&1)<<5)); GPOS = 1<<SPI_SS_L;
}
void lcd_color(uint16_t col) {
  GPOC = 1<<SPI_SS_L; SPI.write16(col); SPI.write(0x75); GPOS = 1<<SPI_SS_L;
  GPOC = 1<<SPI_SS_L; SPI.write16(col); SPI.write(0x7F); GPOS = 1<<SPI_SS_L;
  yield();
}

libkedei.c
※ 関数の引数型を変更しているのでヘッダーファイルも適宜書き換えてください。
 // Original code - Uladzimir Harabtsou l0nley
 //  https://github.com/l0nley/kedei35
 // KeDei V5.0 code - Conjur
 //  https://www.raspberrypi.org/forums/viewtopic.php?p=1019562
 //  Mon Aug 22, 2016 2:12 am - Final post on the KeDei v5.0 code.
 //
 // KeDei 3.5inch LCD V5.0 module for Raspberry Pi
 // Modified by FREE WING, Y.Sakamoto
 // http://www.neko.ne.jp/~freewing/

#include "libkedei.h"

uint32_t *currentFont, cSH, cSW, cSC;

uint32_t color32[16] = {
	0x00000000,
	0x00000080,
	0x00008000,
	0x00008080,
	0x00800000,
	0x00800080,
	0x00808000,
	0x00808080,
	0x00C0C0C0,
	0x000000FF,
	0x0000FF00,
	0x0000FFFF,
	0x00FF0000,
	0x00FF00FF,
	0x00FFFF00,
	0x00FFFFFF
};


int delayms(int ms) {
	delay(ms); return 1;
}

int delays(int s) {
	delay(s * 1000); return 1;
}

int lcd_open(void) {
	int r;
	uint32_t v;
	r = bcm2835_init();
	if(r!=1) return -1;

	bcm2835_spi_begin();
	bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
	bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
	// 8=NG
	// 16=OK, 32=6MHz, 64=4MHz, 128=2MHz, 256=1.5MHz, 512=0.8MHz
	bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_16);
	bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);
	bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, LOW);
	return 0;
}

int lcd_close(void) {
	bcm2835_spi_end();
	int r = bcm2835_close();
	if(r!=1) return -1;
	if(currentFont!=NULL)
	{
		free(currentFont);
	}
	return 0;
}

int spi_transmit(int devsel, uint8_t *data, int len) {
	if(devsel == 0)
	{
		bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
	} else {
		bcm2835_spi_chipSelect(BCM2835_SPI_CS1);
	}
	bcm2835_spi_transfern((char*)data, len);
}

void lcd_reset(void) {
	uint8_t buff[1];

	buff[0] = 0x00;
	spi_transmit(LCD_CS, &buff[0], sizeof(buff));
	delayms(150);

	buff[0] = 0x01;
	spi_transmit(LCD_CS, &buff[0], sizeof(buff));
	delayms(250);
}


void lcd_cmd(uint8_t cmd) {
	uint8_t b1[2];

	b1[0] = cmd>>1;
	b1[1] = ((cmd&1)<<5) | 0x11;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));

	b1[0] = cmd>>1;
	b1[1] = ((cmd&1)<<5) | 0x1B;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));
}


void lcd_data(uint8_t dat) {
	uint8_t b1[2];

	b1[0] = dat>>1;
	b1[1] = ((dat&1)<<5) | 0x15;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));

	b1[0] = dat>>1;
	b1[1] = ((dat&1)<<5) | 0x1F;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));
}


void lcd_color(uint32_t col32) {
	uint8_t b1[3];

	// 0x00RRGGBB
	// 0xF800 R
	// 0x07E0 G
	// 0x001F B
	uint16_t col = ((col32>>8) & 0xF800) | ((col32>>1) & 0x07E0) | ((col32>>3) & 0x001F);

	b1[0]= col>>8;
	b1[1]= col&0x00FF;
	b1[2]= 0x75;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));

	b1[0]= col>>8;
	b1[1]= col&0x00FF;
	b1[2]= 0x7F;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));
}


void lcd_setptr(void) {
	lcd_cmd(0x2a); // X-area
	lcd_data(0x00); // X=0
	lcd_data(0x00); // start coordinat width 0
	lcd_data(0x01); // X=479 = 0x01DF
	lcd_data(0xdf); // end coordinat width 479

	lcd_cmd(0x2B); // Y-area
	lcd_data(0x00); // Y=0
	lcd_data(0x00); // starting coordinat height 0
	lcd_data(0x01); // Y=319 = 0x013F
	lcd_data(0x3f); // end coordinat height 319

	lcd_cmd(0x2C);
}

void lcd_clear(uint32_t clr) {
	lcd_area(0, 0, 479, 319);

	int s = 480*320;
	for(int i=0; i<s; i++) {
		lcd_color(clr);
	}
}

void lcd_area(uint16_t sx, uint16_t sy, uint16_t x, uint16_t y) {
	if(sx>479) sx= 0;
	if(sy>319) sy= 0;
	if(x>479) x= 479;
	if(y>319) y= 319;

	lcd_cmd(0x2A); // set area X command
	lcd_data(sx>>8);
	lcd_data(sx&0xff);
	lcd_data(x>>8);
	lcd_data(x&0xff);

	lcd_cmd(0x2B); // set area Y command
	lcd_data(sy>>8);
	lcd_data(sy&0xff);
	lcd_data(y>>8);
	lcd_data(y&0xff);

	lcd_cmd(0x2C); // fill command
}

void lcd_rectangle(uint32_t x, uint32_t y, uint32_t ex, uint32_t ey, uint32_t clr)
{
	lcd_area(x,y,ex,ey);
	uint32_t count;
	count = (ex-x)*(ey-y) + (ey-y);
	for(uint32_t i=0;i<count;i++) {
		lcd_color(clr);
	}
}

void lcd_rectangle_empty(uint32_t x, uint32_t y, uint32_t ex, uint32_t ey,	uint32_t clr1, uint32_t clr2)
{
	lcd_rectangle(x,y,ex,ey,clr1);
	lcd_rectangle(x+1,y+1,ex-1,ey-1,clr2);
}


void lcd_matrix(uint32_t x,
				uint32_t y,
				uint32_t ex,
				uint32_t ey,
				uint32_t *matrix,
				uint32_t size,
				uint8_t transform,
				uint32_t transformer)
{
	uint32_t val;
	lcd_area(x,y,ex,ey);
	for(uint32_t i=0; i<size; i++) {
		val = matrix[i];
		if(transform == 0) {
			// Caution 8bit = 16color
			lcd_color(color32[(val&0x0F)]);
		}
	}
}

void lcd_load_chars(uint32_t cw, uint32_t ch, uint32_t cc, uint32_t *matrix,uint32_t length){
	if(currentFont != NULL) {
		free(currentFont);
	}
	currentFont = (uint32_t*)malloc(length*sizeof(uint32_t));
	memset(currentFont, 0, length*sizeof(uint32_t));
	for(uint32_t i=0;i<length;i++){
		if(matrix[i]>0) {
			currentFont[i] = 1;
		} else {
			currentFont[i] = 0;
		}
	}
	cSW = cw;
	cSH = ch;
	cSC = cc;
}

void lcd_draw_symbol(uint32_t x, uint32_t y, uint32_t sym, uint32_t clr)
{
	uint32_t curp;
	lcd_area(x,y,x+cSW-1,y+cSH);
	for(uint32_t i=0; i<cSH; i++) {
		curp = (cSC*i+sym)*cSW;
		for(uint32_t j=0; j<cSW; j++, curp++) {
			if(currentFont[curp]>0) {
				lcd_color(clr);
			} else {
				lcd_color(0x00);
			}
		}
	}
}

void lcd_draw_string(uint32_t x, uint32_t y, uint32_t base, uint32_t clr,const char *s) {
	uint32_t i=0;
	while(s[i]!='\0') {
		uint32_t sym = s[i]-base;
		lcd_draw_symbol(x,y,sym, clr);
		x= x+cSW;
		i++;
	}
}

void lcd_init(void) {
	lcd_reset();

	lcd_cmd(0x00);
	lcd_cmd(0x11);delayms(200); //Sleep Out

	lcd_cmd(0xEE); lcd_data(0x02); lcd_data(0x01); lcd_data(0x02); lcd_data(0x01);
	lcd_cmd(0xED); lcd_data(0x00); lcd_data(0x00); lcd_data(0x9A); lcd_data(0x9A); lcd_data(0x9B); lcd_data(0x9B); lcd_data(0x00); lcd_data(0x00); lcd_data(0x00); lcd_data(0x00); lcd_data(0xAE); lcd_data(0xAE); lcd_data(0x01); lcd_data(0xA2); lcd_data(0x00);
	lcd_cmd(0xB4); lcd_data(0x00);

	// 480
	lcd_cmd(0xC0); lcd_data(0x10); lcd_data(0x3B); lcd_data(0x00); lcd_data(0x02); lcd_data(0x11);
	lcd_cmd(0xC1); lcd_data(0x10);
	lcd_cmd(0xC8); lcd_data(0x00); lcd_data(0x46); lcd_data(0x12); lcd_data(0x20); lcd_data(0x0C); lcd_data(0x00); lcd_data(0x56); lcd_data(0x12); lcd_data(0x67); lcd_data(0x02); lcd_data(0x00); lcd_data(0x0C);

	lcd_cmd(0xD0); lcd_data(0x44); lcd_data(0x42); lcd_data(0x06);
	lcd_cmd(0xD1); lcd_data(0x43); lcd_data(0x16);
	lcd_cmd(0xD2); lcd_data(0x04); lcd_data(0x22);
	lcd_cmd(0xD3); lcd_data(0x04); lcd_data(0x12);
	lcd_cmd(0xD4); lcd_data(0x07); lcd_data(0x12);

	lcd_cmd(0xE9); lcd_data(0x00);
	lcd_cmd(0xC5); lcd_data(0x08);

	//	lcd_setrotation(0);
	lcd_cmd(0x36); lcd_data(0b11101010); // 0

	lcd_cmd(0x29);delayms(200); // Display On
	lcd_cmd(0x00);	// NOP
	lcd_cmd(0x11);delayms(200); // Sleep Out
}

# Enable SPI
sudo raspi-config

cd
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.52.tar.gz
tar -zxf bcm2835-1.52.tar.gz
cd bcm2835-1.52
./configure
sudo make install

cd
git clone https://github.com/l0nley/kedei35.git

cd ~/kedei35
./makelcd

export LD_LIBRARY_PATH="/usr/local/lib:/usr/lib"
sudo cp *.so /usr/lib/

sudo ./run


● ESP8266モジュールで無改造の KeDei液晶 V5.0を制御しているのをラズパイに移植してみた。

KeDei 3.5 inch 480x320 TFT lcd from ali
 by Conjur - Mon Aug 22, 2016 2:12 am - Final post on the KeDei v5.0 code.
 ESP8266モジュールで無改造の KeDei液晶 V5.0を制御している。
 をラズパイで動く様に「そのまま移植」を行ないました。

 SPI制御部分は l0nley/kedei35のソースを参考にしました。

・KeDei 3.5インチ TFT液晶を自前のプログラムで制御する方法
KeDei 3.5インチ TFT液晶を自前のプログラムで制御する方法



 GitHubに登録しました。
[GitHub] FREEWING-JP/RaspberryPi_KeDei_35_lcd_v50
 Raspberry Pi KeDei 3.5 inch TFT LCD module V5.0 Control program

 kedei_lcd_v50_pi.c
 // Original code - KeDei V5.0 code - Conjur
 //  https://www.raspberrypi.org/forums/viewtopic.php?p=1019562
 //  Mon Aug 22, 2016 2:12 am - Final post on the KeDei v5.0 code.
 // References code - Uladzimir Harabtsou l0nley
 //  https://github.com/l0nley/kedei35
 //
 // KeDei 3.5inch LCD V5.0 module for Raspberry Pi
 // Modified by FREE WING, Y.Sakamoto
 // http://www.neko.ne.jp/~freewing/
 //
 // gcc -o kedei_lcd_v50_pi kedei_lcd_v50_pi.c -lbcm2835
 // sudo ./kedei_lcd_v50_pi
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <bcm2835.h>
#include <time.h>

#define LCD_CS 1
#define TOUCH_CS 0
#define LCD_WIDTH  480
#define LCD_HEIGHT 320

uint8_t lcd_rotations[4] = {
	0b11101010, // 0
	0b01001010, // 90
	0b00101010, //180
	0b10001010	//270
};

volatile uint8_t color;
volatile uint8_t lcd_rotation;
volatile uint16_t lcd_h;
volatile uint16_t lcd_w;

uint16_t colors[16] = {
	0b0000000000000000,				/* BLACK	 000000 */
	0b0000000000010000,				/* NAVY		000080 */
	0b0000000000011111,				/* BLUE		0000ff */
	0b0000010011000000,				/* GREEN	 009900 */
	0b0000010011010011,				/* TEAL		009999 */
	0b0000011111100000,				/* LIME		00ff00 */
	0b0000011111111111,				/* AQUA		00ffff */
	0b1000000000000000,				/* MAROON	800000 */
	0b1000000000010000,				/* PURPLE	800080 */
	0b1001110011000000,				/* OLIVE	 999900 */
	0b1000010000010000,				/* GRAY		808080 */
	0b1100111001111001,				/* SILVER	cccccc */
	0b1111100000000000,				/* RED		 ff0000 */
	0b1111100000011111,				/* FUCHSIA ff00ff */
	0b1111111111100000,				/* YELLOW	ffff00 */
	0b1111111111111111				/* WHITE	 ffffff */
};


void delayms(int ms) {
	delay(ms);
}


int lcd_open(void) {
	int r;
	uint32_t v;
	r = bcm2835_init();
	if(r!=1) return -1;

	bcm2835_spi_begin();
	bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
	bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
	// 8=NG
	// 16=OK, 32=6MHz, 64=4MHz, 128=2MHz, 256=1.5MHz, 512=0.8MHz
	bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_16);
	bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);
	bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, LOW);
	return 0;
}

int lcd_close(void) {
	bcm2835_spi_end();
	int r = bcm2835_close();
	if(r!=1) return -1;

	return 0;
}

int spi_transmit(int devsel, uint8_t *data, int len) {
	if(devsel == 0)
	{
		bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
	} else {
		bcm2835_spi_chipSelect(BCM2835_SPI_CS1);
	}
	bcm2835_spi_transfern((char*)data, len);
}

void lcd_rst(void) {
	uint8_t buff[1];

	buff[0] = 0x00;
	spi_transmit(LCD_CS, &buff[0], sizeof(buff));
	delayms(150);

	buff[0] = 0x01;
	spi_transmit(LCD_CS, &buff[0], sizeof(buff));
	delayms(250);
}


void lcd_cmd(uint8_t cmd) {
	uint8_t b1[2];

	b1[0] = cmd>>1;
	b1[1] = ((cmd&1)<<5) | 0x11;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));

	b1[0] = cmd>>1;
	b1[1] = ((cmd&1)<<5) | 0x1B;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));
}


void lcd_data(uint8_t dat) {
	uint8_t b1[2];

	b1[0] = dat>>1;
	b1[1] = ((dat&1)<<5) | 0x15;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));

	b1[0] = dat>>1;
	b1[1] = ((dat&1)<<5) | 0x1F;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));
}


void lcd_color(uint16_t col) {
	uint8_t b1[3];

	// 0xF800 R
	// 0x07E0 G
	// 0x001F B

	b1[0]= col>>8;
	b1[1]= col&0x00FF;
	b1[2]= 0x75;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));

	b1[0]= col>>8;
	b1[1]= col&0x00FF;
	b1[2]= 0x7F;
	spi_transmit(LCD_CS, &b1[0], sizeof(b1));
}


uint16_t colorRGB(uint8_t r, uint8_t g, uint8_t b) {

	uint16_t col = ((r<<8) & 0xF800) | ((g<<3) & 0x07E0) | ((b>>3) & 0x001F);

	return col;
}


void lcd_setrotation(uint8_t m) {
	lcd_cmd(0x36); lcd_data(lcd_rotations[m]);
	if (m&1) {
		lcd_h = LCD_WIDTH;
		lcd_w = LCD_HEIGHT;
	} else {
		lcd_h = LCD_HEIGHT;
		lcd_w = LCD_WIDTH;
	}
}

void lcd_init(void) {
	//reset display
	lcd_rst();

	lcd_cmd(0x00);
	lcd_cmd(0x11);delayms(200); //Sleep Out

	lcd_cmd(0xEE); lcd_data(0x02); lcd_data(0x01); lcd_data(0x02); lcd_data(0x01);
	lcd_cmd(0xED); lcd_data(0x00); lcd_data(0x00); lcd_data(0x9A); lcd_data(0x9A); lcd_data(0x9B); lcd_data(0x9B); lcd_data(0x00); lcd_data(0x00); lcd_data(0x00); lcd_data(0x00); lcd_data(0xAE); lcd_data(0xAE); lcd_data(0x01); lcd_data(0xA2); lcd_data(0x00);
	lcd_cmd(0xB4); lcd_data(0x00);

	// LCD_WIDTH
	lcd_cmd(0xC0); lcd_data(0x10); lcd_data(0x3B); lcd_data(0x00); lcd_data(0x02); lcd_data(0x11);
	lcd_cmd(0xC1); lcd_data(0x10);
	lcd_cmd(0xC8); lcd_data(0x00); lcd_data(0x46); lcd_data(0x12); lcd_data(0x20); lcd_data(0x0C); lcd_data(0x00); lcd_data(0x56); lcd_data(0x12); lcd_data(0x67); lcd_data(0x02); lcd_data(0x00); lcd_data(0x0C);

	lcd_cmd(0xD0); lcd_data(0x44); lcd_data(0x42); lcd_data(0x06);
	lcd_cmd(0xD1); lcd_data(0x43); lcd_data(0x16);
	lcd_cmd(0xD2); lcd_data(0x04); lcd_data(0x22);
	lcd_cmd(0xD3); lcd_data(0x04); lcd_data(0x12);
	lcd_cmd(0xD4); lcd_data(0x07); lcd_data(0x12);

	lcd_cmd(0xE9); lcd_data(0x00);
	lcd_cmd(0xC5); lcd_data(0x08);

	lcd_setrotation(0);

	lcd_cmd(0x29);delayms(200); // Display On
	lcd_cmd(0x00);	// NOP
	lcd_cmd(0x11);delayms(200); // Sleep Out
}

void lcd_setframe(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
	lcd_cmd(0x2A);
	lcd_data(x>>8); lcd_data(x&0xFF);
	lcd_data(((w+x)-1)>>8); lcd_data(((w+x)-1)&0xFF);
	lcd_cmd(0x2B);
	lcd_data(y>>8); lcd_data(y&0xFF);
	lcd_data(((h+y)-1)>>8); lcd_data(((h+y)-1)&0xFF);
	lcd_cmd(0x2C);
}

void lcd_fillframe(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t col) {
	int span=h*w;
	lcd_setframe(x,y,w,h);
	int q;
	for(q=0;q{ lcd_color(col); }
}

void lcd_fill(uint16_t col) {
	lcd_fillframe(0, 0, LCD_WIDTH, LCD_HEIGHT, col);
}


void lcd_img(char *fname, uint16_t x, uint16_t y) {

	uint8_t buf[54];
	uint16_t p, c;
	uint32_t isize, ioffset, iwidth, iheight, ibpp, fpos, rowbytes;

	FILE *f = fopen(fname, "rb");
	if (f != NULL) {
		fseek(f, 0L, SEEK_SET);
		fread(buf, 30, 1, f);

		isize =	 buf[2] + (buf[3]<<8) + (buf[4]<<16) + (buf[5]<<24);
		ioffset = buf[10] + (buf[11]<<8) + (buf[12]<<16) + (buf[13]<<24);
		iwidth =	buf[18] + (buf[19]<<8) + (buf[20]<<16) + (buf[21]<<24);
		iheight = buf[22] + (buf[23]<<8) + (buf[24]<<16) + (buf[25]<<24);
		ibpp =		buf[28] + (buf[29]<<8);

		printf("\n\n");
		printf("File Size: %u\nOffset: %u\nWidth: %u\nHeight: %u\nBPP: %u\n\n",isize,ioffset,iwidth,iheight,ibpp);

		lcd_setframe(x,y,iwidth,iheight); //set the active frame...
		rowbytes=(iwidth*3) + 4-((iwidth*3)%4);
		for (p=iheight-1;p>0;p--) {
			// p = relative page address (y)
			fpos = ioffset+(p*rowbytes);
			fseek(f, fpos, SEEK_SET);
			for (c=0;c<iwidth;c++) {
				// c = relative column address (x)
				fread(buf, 3, 1, f);

				// 0x001F B buf[0]
				// 0x07E0 G buf[1]
				// 0xF800 R buf[2]
				lcd_color(colorRGB(buf[2], buf[1], buf[0]));
			}
		}

		fclose(f);
	}
}


void loop() {

	//Update rotation
	lcd_setrotation(lcd_rotation);

	//Fill entire screen with new color
	lcd_fillframe(0,0,lcd_w,lcd_h,colors[color]);

	//Make a color+1 box, 5 pixels from the top-left corner, 20 pixels high, 95 (100-5) pixels from right border.
	lcd_fillframe(5,5,lcd_w-100,20,colors[(color+1) & 0xF]);

	//increment color
	color++;
	//if color is overflowed, reset to 0
	if (color==16) {color=0;}

	//increment rotation
	lcd_rotation++;

	//if rotation is overflowed, reset to 0
	if (lcd_rotation==4) lcd_rotation=0;

	delay(500);
}


int main(int argc,char *argv[]) {

	lcd_open();

	lcd_init();

	lcd_fill(0); //black out the screen.
	// 24bit Bitmap only
	lcd_img("kedei_lcd_v50_pi.bmp", 50, 5);
	delay(500);

	lcd_fill(colorRGB(0xFF, 0x00, 0x00));
	lcd_fill(colorRGB(0x00, 0xFF, 0x00));
	lcd_fill(colorRGB(0xFF, 0xFF, 0x00));
	lcd_fill(colorRGB(0x00, 0x00, 0xFF));
	lcd_fill(colorRGB(0xFF, 0x00, 0xFF));
	lcd_fill(colorRGB(0x00, 0xFF, 0xFF));
	lcd_fill(colorRGB(0xFF, 0xFF, 0xFF));
	lcd_fill(colorRGB(0x00, 0x00, 0x00));

	// 24bit Bitmap only
	lcd_img("kedei_lcd_v50_pi.bmp", 50, 5);
	delay(500);

	// Demo
	color=0;
	lcd_rotation=0;
	loop();	loop();	loop();	loop();
	loop();	loop();	loop();	loop();
	loop();	loop();	loop();	loop();
	loop();	loop();	loop();	loop();
	loop();

	// 24bit Bitmap only
	lcd_img("kedei_lcd_v50_pi.bmp", 50, 5);

	lcd_close();
}



Tags: [Raspberry Pi], [電子工作]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

FWinSdCardImager SDカード イメージ書き込みアプリ、ラズパイの Raspbian OS、Jetson Nanoの Ubuntuの書き込みに便利
FWinSdCardImager SDカード イメージ書き込みアプリ、ラズパイの Raspbian OS、Jetson Nanoの Ubuntuの書き込みに便利

  ラズパイや Jetson Nano等のワンボードマイコン等への OSイメージの書き込みが簡単にできる

FWinPiFinder ラズベリーパイ IPアドレス発見アプリ。ARPコマンドでラズパイの IPアドレスを探索発見する
FWinPiFinder ラズベリーパイ IPアドレス発見アプリ。ARPコマンドでラズパイの IPアドレスを探索発見する

  Raspberry Piや NVIDIA Jetson Nano等の IPアドレスを MACアドレスの OUI部分を使用して発見する

Raspberry Pi 3系のトラブルであるある第一位の電源トラブル、低電圧警報に関する情報のまとめ
Raspberry Pi 3系のトラブルであるある第一位の電源トラブル、低電圧警報に関する情報のまとめ

  ラズパイ3B系での低電圧警報に関する情報まとめ、コマンドラインやログファイルから低電圧を検知する方法

Raspberry Piで CPUの脆弱性 Spectreと Meltdownの脆弱性をチェックする方法
Raspberry Piで CPUの脆弱性 Spectreと Meltdownの脆弱性をチェックする方法

  ラズパイで 2018年初頭に大騒ぎになったスペクターとメルトダウンの CPUの脆弱性をチェックする方法

Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入できる通販ショップ一覧まとめ
Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入できる通販ショップ一覧まとめ

  ラズパイゼロW ワイヤレスモデルを海外通販でサクッと簡単に個人輸入で入手。技適通過でも国内販売は常に品切れ

Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ
Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ

  ラズパイ3で安定して使える microSDカードを購入する Teamと SanDiskは絶対に買わない

Raspberry Pi 3 Model Bに専用カメラモジュール RaspiCamを接続する方法
Raspberry Pi 3 Model Bに専用カメラモジュール RaspiCamを接続する方法

  ラズパイに専用カメラモジュールを接続して Raspbianで写真の静止画撮影や動画を録画する方法

Raspberry Pi 3の Linuxコンソール上で使用する各種コマンドまとめ
Raspberry Pi 3の Linuxコンソール上で使用する各種コマンドまとめ

  ラズパイの Raspbian OSのコマンドラインで使用する便利コマンド、負荷試験や CPUシリアル番号の確認方法等も

Raspberry Pi 3公式フォーラムの FAQの内容の日本語訳
Raspberry Pi 3公式フォーラムの FAQの内容の日本語訳

  ラズパイ公式フォーラムの「The Raspberry Pi 3 Model B Q&A thread」の日本語訳

Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法

  ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ

大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう
大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう

  Raspberry Piの開発環境の構築やタッチパネル付き液晶ディスプレイや各種センサーの使い方まとめ


Raspberry Pi 3、シングルボードコンピュータ ラズパイ3 Raspberry Pi関連はこちらへまとめました
 下記以外にも多数のラズパイ関係の記事が有ります。
 (I2C制御、GPIO制御、1-Wire制御、シリアル通信、日本語音声合成、日本語音声認識、中国語音声合成、MeCab 形態素解析エンジン、赤外線リモコン制御、秋月 I2C液晶モジュール、KeDei 3.5インチ液晶、HDMI 5インチ液晶、NFCカードリーダ、コマンドライン操作方法等)
Raspberry Pi 3に HDMI接続の 800x480 5インチ TFT液晶を接続して使用する方法
Raspberry Pi Raspbian Jessie 2017-07最終版で LIRCを使って学習リモコン、赤外線リモコンを送受信する方法
Raspberry Pi 3の WiFiを広告ブロック機能付きの無線LANアクセスポイント化 hostapd + dnsmasq編
Raspberry Pi 3の Bluetoothで ブルテザで通信する方法(Bluetooth編)
Raspberry Pi 3で日本語音声を合成して喋らせる方法(OpenJTalk編)
Raspberry Pi 3に USB Micを接続して日本語の音声認識をする方法(Julius編)
Raspberry Pi 3の GPIOに LEDとスイッチを接続して Lチカする方法
Raspberry Pi 3の GPIOに LEDとスイッチを接続してシャットダウンボタンを実装する方法
Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
Raspberry Pi 3の GPIOに I2C通信方式の気圧計 BMP280を接続する方法
Raspberry Pi 3に I2C通信方式の NFCリーダライタ PN532を接続して NFC FeliCaカードを読む方法
Raspberry Pi 3でネットワーク ライブカメラを構築する方法 Motion編
Raspberry Pi 3でネットワーク ライブカメラを構築する方法 MJPG-streamer編
Raspberry Pi 3 Model Bで動画処理アプリ FFmpegをコンパイルする方法
Raspberry Pi3の X-Window Systemに Windowsのリモートデスクトップから接続する方法
Raspberry Pi3に WebRTCの STUN/TRUNサーバと PeerJSサーバをインストールする方法
【成功版】Raspberry Piで NNPACK対応版の Darknet Neural Network Frameworkをビルドする方法


Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板

  Espressif ESP8266 ESP-12-E NodeMCU V1 ESP12 CP2102

BangGood通販はドローン以外にも面白い商品がまだまだ有った(電子工作編)
BangGood通販はドローン以外にも面白い商品がまだまだ有った(電子工作編)

  レーザー彫刻機、カラー液晶の DIYオシロ、Arduinoや Raspberry Pi用の小型カラー液晶




[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c) 2016-2017 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_tft_lcd_3_5inch_kedei_touch_xpt2046_2/