読者です 読者をやめる 読者になる 読者になる

電子工作メモランダム

マイコンみたいなパソコンRaspberry Piの設定とかいじった手順とかの備忘録を淡々と記述するブログです。プログラムなど実行するときは自己責任でお願いします。

RaspberryPiからaitendoのLCD[C128X64SPI-12P]への文字表示 (1)

 タイトル通りAitendoの液晶ディスプレイモジュール[C128X64SPI-12P]に文字表示を行ったので書きます。

 でその液晶なんですけど、FSTN液晶モジュール(128x64/SPI)@350円です。実際に買ったのはバックライトと基板付きのC128X64SPI-12P-M@580円のほうです。安いですね。その分、説明書のたぐいは一切付いてきません。ただし、サンプルコードが商品ページにあるのでそれを参考にしました。

用意するもの

プログラム

 とりあえず動けばいいんです。もうちょっとポインターとか勉強した方が良いですね、はい。
 仕様としては、全角16文字x8行、半角なら32文字/行で、半角/全角混在可能です。

lcd_text.c

#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <iconv.h>
#include <string.h>
#include <stdlib.h>


#define LCD_SDA 12  // GPIO 10
#define LCD_SCL 14  // GPIO 11
#define LCD_A0   6  // GPIO 25
#define LCD_CS  10  // GPIO  8

#define PAGE_SEL 0xB0			// (3)
#define COL_SEL  0x10			// (4)

#define MAX_BUF 256

unsigned char chardataHan[1024];
unsigned char chardataZen[70688];

void glcd_write_data(unsigned char dat)
{
	digitalWrite(LCD_A0, 1);		// 1ならデータ。0ならコマンド。
	// unsigned char datr = ~dat; // 白黒反転
	wiringPiSPIDataRW(0, &dat, 1);
}

// コマンドを出力する
void glcd_write_cmd(unsigned char cmd)
{
	digitalWrite(LCD_A0, 0);		// 1ならデータ。0ならコマンド。
	wiringPiSPIDataRW(0, &cmd, 1);
}

void glcd_init(void)
{
	delay(10);

	glcd_write_cmd(0xE2);			// (14) S/W RESWT
	glcd_write_cmd(0xA3);			// (11) LCD bias(1/7)
	//glcd_write_cmd(0xAF);			// (1)  Display ON
	glcd_write_cmd(0xA0);			// (8)  segment direction.(normal direction)
	glcd_write_cmd(0xC8);			// (15) Common Direction.(normal direction)
	glcd_write_cmd(0x22);			// (17) Regultion resistor select(0x010)  //25
	glcd_write_cmd(0x81);			// (18) EV Select.
	glcd_write_cmd(0x2f);			// (18) Select EV value.(0x101111)
	glcd_write_cmd(0x2f);			// (16) Power control(VB,VR,VF全部1)

	glcd_write_cmd(0x40);			// (2)  Initial display line(0に設定, MAX63)
	glcd_write_cmd(0xB0);			// (3)  Set page address(Y=0に設定, MAX15)
	glcd_write_cmd(0x10);			// (4)  Set coloumn addr MSB
	glcd_write_cmd(0x00);			// (4)  Set coloumn addr LSB(X=0に設定, MAX255)
	//glcd_write_cmd(0xAF);			// (1)  Display ON
	glcd_write_cmd(0xA4);			// (10) all pixel ON(normal display)
	glcd_write_cmd(0xA6);			// (9)  Inverse Display(normal display)

	glcd_write_cmd(0xAF);			// (1)  Display ON
}
// 座標のセット
void glcd_set_axis(int x, int page)
{
	int col;
	
	// Selecting Page (3)
	glcd_write_cmd(PAGE_SEL | page);

	// Selecting Column
	col = (x & 0xF0) >> 4; 			// 上位ビット
	glcd_write_cmd(COL_SEL | col);	// 
	glcd_write_cmd(x & 0x0f);		// 下位ビット
}

// 半角一文字出力
void output_font(char code)
{
	int j;
	for (j = 0; j < 4; j++)
		glcd_write_data(chardataHan[code*4+j]);
}
// 全角一文字出力
void output_font2(char upper, char lower)
{
	// 文字コードから文字データ配列のアドレスへと変換
	int hosei = (upper- (upper >= 0xE0 ? 0xE0 : 0x81)) * 4 + (lower>0x7F ? 1 : 0) + (upper >= 0xE0 ? 0x7C : 0);
	int num = ((upper - (upper >= 0xE0 ? 0xE0 : 0x81))*0xC0 + lower-0x40 - hosei + (upper >= 0xE0 ? 0x1740 : 0))*8;

	printf("cc=%d, hosei=%d\n", num/8,hosei);
	int j;
		for (j = 0; j < 8; j++) // 全角
			glcd_write_data(chardataZen[num+j]);
}
// 文字列出力
void output_text(char* text, int size)
{
	int j;
	for (j = 0; j < size; j++)
	{
		char code = text[j];
		if (code < 0x80 | (code >= 0xA0 & code < 0xE0))
		{
			printf("code=%x\n",text[j]);
			output_font(text[j]); 				// 半角
		} else {
			printf("code=%x %x\n",text[j], text[j+1]);
			output_font2(text[j], text[j+1]);	// 全角
			j++;
		}
	}
}

void utf2sjis(char utf8code[], char outbuf[])
{
	// ▼文字コード変換
	int j;
	char	inbuf[MAX_BUF+1] = { 0 };
	
	char	*in = inbuf;
	char	*out = outbuf;
	size_t	in_size = (size_t)MAX_BUF;
	size_t	out_size = (size_t)MAX_BUF;
	iconv_t ic = iconv_open("SJIS", "UTF-8");

	memcpy( in, utf8code, 64 );

	iconv( ic, &in, &in_size, &out, &out_size );
	iconv_close(ic);

	for (j = 0; j < 16; j++) printf("%x ", outbuf[j] );
}
int fontOpen()
{
	// ▼フォントファイルオープン
	FILE *fp;
	unsigned char buf[1024];
	int size;

	fp = fopen( "misakiHan.dat", "rb" );
	if( fp == NULL ) {
		printf( "misakiHan.dat が開けません\n" );
		return -1;
	}
	size = fread( chardataHan, sizeof( unsigned char ), 1024, fp );
	fclose(fp);

	// ▼フォントファイルオープン
	unsigned char buf2[70688];
	int size2;

	fp = fopen( "misakiZen_gothic.dat", "rb" );
	if( fp == NULL ) {
		printf( "misakiZen_gothic.dat が開けません\n" );
		return -1;
	}
	size2 = fread( chardataZen, sizeof( unsigned char ), 70688, fp );
	fclose(fp);
}

int main()
{
	// ▼初期化
	if (wiringPiSetup() == -1)
	{
		printf("wiringPiのセットアップに失敗しました。\n");
		return 1;
	}
	int initv = wiringPiSPISetup(0, 1000000);
	printf("initv=%d\n", initv);
	if (initv < 0)
	{
		printf("wiringPiSPIのセットアップに失敗しました。\n");
		return 1;
	}
	pinMode(LCD_A0, OUTPUT);
	
	glcd_init();
	printf("init ok\n");
	
	// ▼ここからメイン
	int fresult = fontOpen();
	char outbuf[MAX_BUF+1] = { 0 };
	
	glcd_set_axis(0,0);
	char* buff2 = "    ==謹賀新年==    "; utf2sjis(buff2, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,1);
	char* buff3 = "あけましておめでとうございます。"; utf2sjis(buff3, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,2);
	char* buff4 = " 今年もよろしくお願いします。 "; utf2sjis(buff4, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,3);
	char* buff5 = "  平成25年1月10日(木)     "; utf2sjis(buff5, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,4);
	char* buff6 = "                "; utf2sjis(buff6, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,5);
	char* buff7 = "X / _ / X <来週も見てくださいね!"; utf2sjis(buff7, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,6);
	char* buff8 = "                "; utf2sjis(buff8, outbuf);
	output_text(outbuf, 64);
	glcd_set_axis(0,7);
	char* buff9 = "魑魅魍魎檸檬薔薇雲霧霜霰雹 凜 "; utf2sjis(buff9, outbuf);
	output_text(outbuf, 64);
	
	return 0;
}

必要ファイル

 フォントデータが無いと動きません。美咲フォントという素晴らしい漢字フォントがあるのでそれを使うことにしました。そのままでは使えないのであらかじめ変換しています。変換ソフトもそのうち公開予定です。
misaki_4x8_jisx0201.dat
misaki_gothic.dat
 二つのファイルをプログラムファイルと同じディレクトリに入れるか、プログラムを変更してください。
あ、名前違いますね。misaki_4x8_jisx0201.datはmisakiHan.datに、misaki_gothic.datはmisakiZen_gothic.datにリネームしてください。

実行・出力例

sudo gcc lcd_test.c -o lcd_test -I/usr/local/include -L/usr/local/lib -lwiringPi
sudo ./lcd_test

f:id:mas-home:20130110014447j:plain
こんな感じ。もう13日ですけどね。