「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」次に「ソフトウェアエンジニア」が文字の色を変えて表示されています。
