Raspberry PI 3でサインスマート 1.8″ LCDの表示」でRaspberry PI 3によりLCDへドットを表示できることは確認しました。「EUC-JPコードを用いた美咲フォントへのアクセス方法 」で美咲フォントのフォントパターンが取得できることを確認しました。今回はこの二つの事例を組み合わせて、Raspberry PI 3でサインスマート 1.8″ LCDに文字を表示します。

サインスマート 1.8″ LCDの文字表示プログラムの作成

chardisplay関数を新規に作成し、行/カラム、表示する文字コード(漢字コード)をパラメータにして呼び出します。プログラムの漢字コードはEUC-JPを使用し、これを区点コードに148行目から151行目で変換しています。

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <wiringPi.h>
 
#define RSpin 5 // レジスタ選択ピン指定
#define REpin 6 // リセット信号ピン指定

#define LCD_BF 4096 // 1度に転送するデータ数(最大4096)
 
int LCD_Cmd(unsigned char,int,...);
void SetDot(int x, int y, int color);
void chardisplay(int column, int row, char* text, int color);
 
static uint8_t SPIMode = 0,SPIbit=8;	//SPIモード0 bit数8
static uint32_t SPISpeed =60000000;		// 32MHz

// SPIデバイス定義
// # ls -l /dev/spidev* で確認できる。
// Pi2の場合CE1に接続した場合は0.0
//          CE2に接続した場合は0.1 だった。
static char *SPIDevice = "/dev/spidev0.0";
int fd,ret=0;

char font_path[]   = "code/misaki_gothic_lcd.bmp"; //フォントファイルパス
unsigned char bhd[62],FontData[94][96];

//unsigned char bhd[62],FontData[500][500];
 
unsigned char BMPData[0xf000/LCD_BF][LCD_BF];

int main(int argc,char *argv[]){
	int column,row;
	
	// wiringPi初期化
	if(wiringPiSetup()==-1) printf("wiringPi error\n");	// wiringPi初期化エラー
	
	// ピンの初期化
	pinMode(RSpin,OUTPUT);
	pinMode(REpin,OUTPUT);
	
	// 液晶リセット信号送信
	digitalWrite(REpin,0);
	delay(100);
	digitalWrite(REpin,1);
	delay(100);
	
	// SPIデバイスの初期化
	fd = open(SPIDevice,O_RDWR);if(fd<0) printf("SPI Device error\n");		//SPI デバイス初期化エラー
	ret = ioctl(fd,SPI_IOC_WR_MODE,&SPIMode);if(ret <0) printf("SPI Mode error\n");	//SPI Mode設定エラー
	ret =ioctl(fd,SPI_IOC_WR_BITS_PER_WORD,&SPIbit);if(ret <0) printf("SPI bit/Word error\n");//SPI bit/Word設定エラー
	ret =ioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,&SPISpeed);if(ret <0) printf("SPI Speed error\n");	//SPI Speed設定エラー
 
	LCD_init();
 
	// 液晶描画方向設定
	LCD_Cmd(0x36,1,0xC0); // 縦長 0x48 横長0x28
	
	
	// 描画エリア設定 0~BMPのサイズ
	LCD_Cmd(0x2A,4,0x00,0x00,0x00,128);
	LCD_Cmd(0x2B,4,0x00,0x00,0x00,160);
	LCD_Cmd(0x3A,1,0x06);  //色深度設定 16bit=0x05 18bit=0x06
	
	// 表示RAM転送モードに設定 
	CmdSend(0x2C);
	int i,k, x, y;
	long color= 0xff0000; 

	for(i=0; i<0xf000/LCD_BF ;i+=1)
	{
 		for(k=0; k<LCD_BF; k+=1)
		{
			BMPData[i][k] = 0x00;
		}
		DataSend(LCD_BF,BMPData[i]);
	}
 
	FILE *bmpr;
	char buf[1];

	bmpr=fopen(font_path,"rb");
	fread(bhd,1,62,bmpr);
	fread(FontData,1,96*94,bmpr);
	fclose(bmpr);
	
	unsigned char *SText1 = "TomoSoft";
	unsigned char *SText2 = "ソフトウェアエンジニア";
	
	color = 0xff0000;
	column=5;
	row = 0;
	chardisplay( column, row, SText1, color);
	
	color = 0xff00FF;
	column=3;
	row = 1;
	chardisplay( column, row, SText2, color);

 	for(i=0; i<0xf000/LCD_BF ;i+=1)
	{
		DataSend(LCD_BF,BMPData[i]);
	}

	close(fd); // SPIデバイス開放

	return 0;
}
void chardisplay(int column, int row, char* text, int color)
{
	int x,y,k,charcount;
	int pat;
	char buf[1];
	unsigned int ku,ten;
	unsigned int word;

	charcount = 0;
	
	while(1){
		if((text[charcount]) == 0) break;
		word = (unsigned int)((text[charcount+1])<<8);
		word |= text[charcount];
		printf("%x %x %x\n",text[charcount],text[charcount+1],word);
		ku = (word & 0xff)-0xA0-1;//数字1
		ten = (word>>8)-0xA0-1;
	
		x=(column+(charcount/2))*8;
		y=row*8;
		for(k=0; k<8 ;k+=1)
		{
			buf[0]=FontData[(8*ku)+k][ten];		
			
			int i = 0;
			pat=0x80;
			while(pat>0) {
				if((buf[0]&pat)==0) SetDot( x+i,  y +k, color);
				pat>>=1;
				i++;
			}
		}
		charcount+=2;
	}
}

void SetDot(int x, int y, int color)
{
	int pos = (x+(y*128))*3;
	BMPData[pos/LCD_BF][(pos%LCD_BF)] = (color & 0xff0000)>>16;  
	BMPData[pos/LCD_BF][(pos%LCD_BF)+1] = (color & 0xff00)>>8;  
	BMPData[pos/LCD_BF][(pos%LCD_BF)+2] = color & 0xff;
	
}
 
// LCDへのコマンド転送
// LCD_Cmd(コマンド,設定値サイズ(Byte),設定値(カンマ区切り));
int LCD_Cmd(unsigned char TrCmd,int TrByte, ...){
	int dti=0;
	unsigned char TrData[TrByte];
	
	va_list dt;
	va_start(dt,TrByte);
	for(dti=0;dti<TrByte;dti++)TrData[dti]=va_arg(dt,int);
	va_end(dt);
	
	CmdSend(TrCmd);	
	if(TrByte > 0)DataSend(TrByte,TrData);
}
 
// LCDへのデータ転送
// TrByte=転送データサイズ
// TrData=転送するデータ
//         8bit値 うまく転送できない場合はchar型の変数を渡すとうまくいく。
int DataSend(int TrByte,unsigned char TrData[]){
	digitalWrite(RSpin,1); // RS信号切替
	uint8_t ReData[TrByte];//受信用変数
	
	// 転送するデータの準備
	struct spi_ioc_transfer tr={
	.tx_buf       =(unsigned long)TrData,
	.rx_buf       =(unsigned long)ReData,
	.len          = TrByte,
	.delay_usecs  = 1,
	.speed_hz     = SPISpeed,
	.bits_per_word= SPIbit,
	};
	
	
	// 転送
	ret =ioctl(fd,SPI_IOC_MESSAGE(1),&tr);
	if(ret<1)printf("SPI 転送エラー(Data)\n");
	
	int i=0;
	
	return ret; // 受信データサイズを返す
}
 
// コマンド転送
int CmdSend(unsigned long TrData){
	digitalWrite(RSpin,0); // RS信号切替
	uint8_t ReData;        //受信用変数
	// 転送するデータの準備
	struct spi_ioc_transfer tr={
	.tx_buf       =(unsigned long)&TrData,
	.rx_buf       =(unsigned long)&ReData,
	.len          = 1,
	.delay_usecs  = 1,
	.speed_hz     = SPISpeed,
	.bits_per_word= SPIbit,
	};
	
	// 転送
	ret =ioctl(fd,SPI_IOC_MESSAGE(1),&tr);
	if(ret<1)printf("SPI 転送エラー(Com)\n");
 
	return ReData; // 受信データを返す
}
 
int LCD_init(void){
	// 液晶リセット信号送信
	digitalWrite(REpin,0);
	delay(1);
	digitalWrite(REpin,1);
	delay(1);
	
	//液晶初期化コマンド送信
	CmdSend(0x01); // ソフトリセット
	delay(15);
	CmdSend(0x11); // スリープ解除
	delay(10);
	
	// フレームレート設定
	LCD_Cmd(0xB1,3,0x01,0x2C,0x2D);
	LCD_Cmd(0xB2,3,0x01,0x2C,0x2D);
	LCD_Cmd(0xB3,6,0x01,0x2C,0x2D,0x01,0x2C,0x2D);
	
	// 液晶反転設定
	LCD_Cmd(0xB4,1,0x07);
 
	// 電源設定(PWCTR1~3)
	LCD_Cmd(0xC0,3,0xA2,0x02,0x84);
	LCD_Cmd(0xC1,1,0xC5);
	LCD_Cmd(0xC2,2,0x0A,0x00);
	LCD_Cmd(0xC3,2,0x8A,0x2A);
	LCD_Cmd(0xC4,2,0x8A,0xEE);
	LCD_Cmd(0xC5,1,0x0E);
	CmdSend(0x20);
	// ガンマ設定
	LCD_Cmd(0xE0,16,0x0F,0x1A,0x0F,0x18,0x2F,0x28,0x20,0x22,0x1F,0x1B,0x23,0x37,0x00,0x07,0x02,0x10);
	LCD_Cmd(0xE1,16,0x0F,0x1B,0x0F,0x17,0x33,0x2C,0x29,0x2E,0x30,0x30,0x39,0x3F,0x00,0x07,0x03,0x10);
	CmdSend(0x29);
	CmdSend(0x13);	
	
}

コンパイル・リンクは次のコマンドで実行します。

# gcc -o lcdchar lcdchar.c -lwiringPi

サインスマート 1.8″ LCDの文字表示プログラムの実行

作成したプログラムを次のコマンドで実行します。

# sudo ./lcdchar

実行した結果を次に示します。「TomoSoft」次に「ソフトウェアエンジニア」が文字の色を変えて表示されています。

LCDへの文字表示