Lynx-EyEDの電音鍵盤 新館

制御とか数学とか駄文とか

AitendoさんのOLEDをPSoCで制御しましたよ

※今日のブログ大変長いのでご注意を…。

6月30日までお得なaitendoさんの0.95インチOLEDを買ってみました。
実際に手にしてみると、「かなり小さい」というのが正直な感想です。

OLEDとキャリーボードの2点セット」
http://www.aitendo.co.jp/product/2099

  • ちなみにバラの商品番号
    • OLEDの商品番号:[ALO-095BWNN-J9]
    • OLEDキャリーボード:[IFB-095BWNNJ9-SPI]

で動かすとこんな感じ
f:id:Lynx-EyED:20100624002917j:image
"Welcome to PSoC & DPCM Player"と書いたつもりです。
SPI制御で、3.3V単一電源で駆動できます。(OLEDの下部のフレキ基板にDC-DC昇圧回路がすでに載っています)


PSoCでの制御を記述していますが、他のCPUでも少しの改良で動くはずです。(SPIハードの駆動シーケンスなどを書き換え)
OLEDの駆動はaitendoさんのHPにあるプログラム*1、フォントデータはAN2356を参考にしております。

それって、ただのパクr……(まぁまぁ。

  • 3.3V電源以外にOLEDを駆動するのに必要なピン
    • MOSI : CPU -> OLED へのデータ通信用
    • CLK : クロック
    • CS : チップセレクト(Active Low)
    • DC :データ/コマンド切り替えピン
    • RES :リセット(Active Low)

(MISO端子は必要ありません)
今回上記2点のMOSI,CLKのみをハードウェアSPIで制御しました。

  1. PSoCブロックのSPIMモジュールを選択し、「SPIM_OLED」にリネーム
  2. 残りはGPIOでの制御となりますが、結構めんどうなので、「LED点滅制御ライブラリ」でGPIOピンを制御

例えばCS端子にLEDライブラリから
OLED_CS というラベルを作り、Active Lowに設定すると、main関数から

OLED_CS_On();

と記述すれば、CS端子がLowにアサートされ、

OLED_CS_Off();

と記述すれば、CS端子がHighにデアサートされます。(Active Highに設定すればその逆になります)
今回はCS,RES端子をActive Low、DC端子をActive Highに設定しています。
PSoC以外のCPUをご使用になる方はご注意ください。

  • ソースコード。aitendoさんのソースコードを参考にしてるので、コメントアウトなどが随所ありますがご容赦ください。
    • oled_portconfig.h :(変数・関数の宣言)
#ifndef	_OLED_PORTCONFIG_H
#define	_OLED_PORTCONFIG_H


//======================IOPortConfig=========================
//OLED_RES:Reset pin,low level valid (ACTIVE LOW:Port_2_1)
//OLED_CS:Chip selection,low level valid (ACTIVE LOW:Port_2_5)
//OLED_DC:Data reg /command reg 0:command 1:data (Port_1_7)
//=========================================================
#define Dis_X_MAX 96-1	// Max X axial direction in screen
#define Dis_Y_MAX 64-1	// Max Y axial direction in screen

extern unsigned char X_Witch; //character's width
extern unsigned char Y_Witch; //character's height
//extern unsigned char Font_Wrod; //how many byte this character's
//extern unsigned char __f lash *Char_TAB; //word stock's pointer
extern unsigned int Char_Color; //character's color


void OLED_RegWrite(unsigned char Command);
void OLED_DataWrite(unsigned char Data);
void OLED_DataWrite_to(unsigned int Dat);
void PortInit(void);
void TimeDelay(int Time);
void OLED_Init(void);
void Full_OLED_Screen(unsigned int Dot);
void Draw_Dot(unsigned char x,unsigned char y,unsigned int Color);
void ChangeFontColor(unsigned int color);
void PutChar(unsigned char x,unsigned char y,unsigned char a);

#endif
    • oled_portcongif.c :(OLED制御関数群)
#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

//#include "main.h"
#include "oled_portconfig.h"
#include "small_font.h"

unsigned char X_Witch; //character&#39;s width
unsigned char Y_Witch; //character&#39;s height
//unsigned char Font_Wrod; //how many byte this character&#39;s
//unsigned char __f lash *Char_TAB; //word stock&#39;s pointer
unsigned int Char_Color; //character&#39;s color

//============================OLED_Driver================
// Illustration: driver
// Function:: writer oled command register,intinial oled driver IC etc.
// Parameter: Command
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//===============write oled command register====================
void OLED_RegWrite(unsigned char Command)
{
	OLED_CS_Off();
	OLED_DC_Off();
	OLED_CS_On();

	SPIM_OLED_SendTxData(Command);
	while(!(SPIM_OLED_bReadStatus() & SPIM_OLED_SPIM_TX_BUFFER_EMPTY));
	
	OLED_CS_Off();
}
//=============================OLED_Driver===============
// Illustration: driver
// Function: writer oled data register,intinial oled driver IC etc.
// Parameter: Data
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//================write oled data register=======================
void OLED_DataWrite(unsigned char Data)
{
	OLED_CS_Off();
	OLED_DC_On();
	OLED_CS_On();

	SPIM_OLED_SendTxData(Data);
	while(!(SPIM_OLED_bReadStatus() & SPIM_OLED_SPIM_TX_BUFFER_EMPTY));

	OLED_CS_Off();
}
//=============power function=================================
// Illustration: Function
// Function: writer a point in oled,point color can select yourself
// Parameter: Dat
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//==============wr ite oled register=============================
void OLED_DataWrite_to(unsigned int Dat)
{
	OLED_DataWrite((unsigned char)((Dat >> 8)& 0x00ff));
	OLED_DataWrite((unsigned char)(Dat & 0x00ff));
}
//=============power function=================================
// Illustration: Function
// Function: MCU port initial,like port direction,pull-up resistor,input or output etc.
// Parameter: Non
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//=========================================================
void PortInit(void)
{
	OLED_CS_Start();
	OLED_DC_Start();
	OLED_RES_Start();
	SPIM_OLED_Start(SPIM_OLED_SPIM_MODE_0 | SPIM_OLED_SPIM_MSB_FIRST);

}
//=============power function=================================
// Illustration: Function
// Function: Delay function
// Parameter: Time
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//=========================================================
void TimeDelay(int Time)
{
	int i;
	while(Time > 0)
	{
		for(i = 0;i < 800;i++)
		{
			asm("nop");
		}
		Time --;
	}
}

void OLED_Init(void)
{
	PortInit();
	OLED_RES_On();
	TimeDelay(80);
	OLED_RES_Off();
	TimeDelay(20);
	OLED_RegWrite(0xae);	//OLED display OFF

	//Row Address
	OLED_RegWrite(0x75);	/* Set Row Address */
	OLED_RegWrite(0x00);	/* Start = 0 */
	OLED_RegWrite(0x3f);	/* End = 63 */
	OLED_RegWrite(0x15);	/* Set Column Address */
	OLED_RegWrite(0x00);	/* Start = 0 */
	OLED_RegWrite(0x5F);	/* End = 96 */
	
	//Contrast
	OLED_RegWrite(0xa0);	//Set remap & data format 0111 0000
	OLED_RegWrite(0x74);
	OLED_RegWrite(0xa1);	//set display star row RAM
	OLED_RegWrite(0x00);
	OLED_RegWrite(0xa2);	//set dispaly offset
	OLED_RegWrite(0x00);
	OLED_RegWrite(0xa4);	//Set Display Mode
	OLED_RegWrite(0xa8);	//Set Multiplex Ratio
	OLED_RegWrite(0x3f);
	OLED_RegWrite(0xad);	//Set Master Configuration
	OLED_RegWrite(0x8f);	//(External VCC Supply Selected)
	OLED_RegWrite(0xB0);	//Set Power Saving Mode
	OLED_RegWrite(0x1a);
	OLED_RegWrite(0xB1);	//Set Phase 1 & 2 Period Adjustment
	OLED_RegWrite(0x74);
	OLED_RegWrite(0xb3); 	//Set Display Clock Divide Ratio / Oscillator Frequency
	OLED_RegWrite(0xd0);
	OLED_RegWrite(0x8A);	//Set Second Pre-charge Speed of Color A
	OLED_RegWrite(0x81);
	OLED_RegWrite(0x8B);	//Set Second Pre-charge Speed of Color B
	OLED_RegWrite(0x82);
	OLED_RegWrite(0x8C);	//Set Second Pre-charge Speed of Color C
	OLED_RegWrite(0x83);
	OLED_RegWrite(0xBB);	//Set Pre-charge Level
	OLED_RegWrite(0x3e);
	OLED_RegWrite(0xBE);	//Set VCOMH
	OLED_RegWrite(0x3e);
	OLED_RegWrite(0x87);	//Set Master Current Control
	OLED_RegWrite(0x0f );
	OLED_RegWrite(0x81);	//Set Contrast Control for Color “A”
	OLED_RegWrite(0x80);
	OLED_RegWrite(0x82);	//Set Contrast Control for Color “B”
	OLED_RegWrite(0x80);
	OLED_RegWrite(0x83);	//Set Contrast Control for Color “C”
	OLED_RegWrite(0x80);
	OLED_RegWrite(0xaf);	//display ON
}
//=============power function=================================
// Illustration: Function
// Function: Fill all oled screen,all of color,e.g.:Dot=0x0000h,black screen
// Dot=0x0018h,red screen
// Parameter: Dot
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port configer
// More: Can refer e.g.
//=========================================================
void Full_OLED_Screen(unsigned int Dot)
{
	unsigned char i,j;
	for(i=0;i<64;i++)
	{
		for(j=0;j<96;j++)
		{
			//Draw_Dot(j,i,Dot);
			OLED_DataWrite_to(Dot);
		}
	}
}
//=============power function=================================
// Illustration: Function
// Function: Write a dot in screen
// Parameter: x,y,Color
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//=========================================================
void Draw_Dot(unsigned char x,unsigned char y,unsigned int Color)
{
	OLED_RegWrite(0x15);
	OLED_RegWrite(x);
	OLED_RegWrite(x);
	OLED_RegWrite(0x75);
	OLED_RegWrite(y);
	OLED_RegWrite(y);
	OLED_DataWrite_to(Color);
	OLED_DataWrite_to(Color);
}
void ChangeFontColor(unsigned int color)
{
	Char_Color = color;
}

//=============power function=================================
// Illustration: Function
// Function: Input a normal character
// Parameter: X:X coordinate,Y:Y coordinate,a:display a character from word stock&#39;s offset
// Return: Non
// Reference: Other book or IC DataSheet
// Note: Base your MCU and port conf iger
// More: Can refer e.g.
//=========================================================
void PutChar(unsigned char x,unsigned char y,unsigned char a)
{
	int i,j;
	// unsigned char __f lash *p_data;
	unsigned char Temp=0;
	unsigned char Index=0;
	
	X_Witch = 5;
	Y_Witch = 8;
	//Char_Color = 0xffff;

	j = 0;
	i = 0;
	if(a < 32)a=32;
	for(i=0; i<X_Witch; i++)
	{	
		Temp = FontLookup[a-32][i];
		for(j=Y_Witch;j!=0;j--){
			if((Temp & 0x80)==0x80){
				Draw_Dot(x+i,y+j,Char_Color);
			}else{
				Draw_Dot(x+i,y+j,0);
			}
		Temp = Temp << 1;
		}
	}
	

}
    • small_font.h :(5 x 7サイズのフォントデータ:AN2356からそのまま流用)
//--------------------------------------------------------------------------------------------------
// Character generator
// This table defines the standard ASCII characters in a 5x7 dot format.
//--------------------------------------------------------------------------------------------------
static const char FontLookup [][5] =
{
  { 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp
  { 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! 
  { 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
  { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
  { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
  { 0xc4, 0xc8, 0x10, 0x26, 0x46 }, // %
  { 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
  { 0x00, 0x05, 0x03, 0x00, 0x00 }, // &#39;
  { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
  { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
  { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // *
  { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +
  { 0x00, 0x00, 0x50, 0x30, 0x00 }, // ,
  { 0x10, 0x10, 0x10, 0x10, 0x10 }, // -
  { 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
  { 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
  { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0
  { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1
  { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
  { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3
  { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4  
  { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
  { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6
  { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
  { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
  { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9
  { 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
  { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;
  { 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
  { 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
  { 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
  { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
  { 0x32, 0x49, 0x59, 0x51, 0x3E }, // @
  { 0x7E, 0x11, 0x11, 0x11, 0x7E }, // A
  { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B
  { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C
  { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D
  { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E
  { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F
  { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G
  { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H
  { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I
  { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J
  { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K
  { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L
  { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M
  { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N
  { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O
  { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P
  { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q
  { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R
  { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
  { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T
  { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U
  { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V
  { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W
  { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
  { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
  { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
  { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [
  { 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55
  { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ]
  { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
  { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
  { 0x00, 0x01, 0x02, 0x04, 0x00 }, // &#39;
  { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
  { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b
  { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
  { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d
  { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
  { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f
  { 0x0C, 0x52, 0x52, 0x52, 0x3E }, // g
  { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h
  { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i
  { 0x20, 0x40, 0x44, 0x3D, 0x00 }, // j
  { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k
  { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l
  { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m
  { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n
  { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
  { 0x7C, 0x14, 0x14, 0x14, 0x08 }, // p
  { 0x08, 0x14, 0x14, 0x18, 0x7C }, // q
  { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r
  { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
  { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t
  { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u
  { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v
  { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w
  { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
  { 0x0C, 0x50, 0x50, 0x50, 0x3C }, // y
  { 0x44, 0x64, 0x54, 0x4C, 0x44 }  // z
};
    • main.c :(メイン)
//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules
#include "oled_portconfig.h"
#include "small_font.h"

void main(void)
{
	// Start OLED Port
	OLED_Init();

	Full_OLED_Screen(0x0018);	//full red color in OLED
	Full_OLED_Screen(0x07e0);	//full green color in OLED
	Full_OLED_Screen(0xf800);	//full blue color in OLED
	Full_OLED_Screen(0xffff);	//full white color in OLED
	Full_OLED_Screen(0); 		//clear OLED

	ChangeFontColor(0x07e0);
	PutChar(14,6,&#39;W&#39;);
	PutChar(19,6,&#39;e&#39;);
	PutChar(24,6,&#39;l&#39;);
	PutChar(29,6,&#39;c&#39;);
	PutChar(34,6,&#39;o&#39;);
	PutChar(39,6,&#39;m&#39;);
	PutChar(44,6,&#39;e&#39;);
	
	ChangeFontColor(0x80ff);	
	PutChar(34,15,&#39;t&#39;);
	PutChar(39,15,&#39;o&#39;);
	
	ChangeFontColor(0x0018);
	PutChar(44,24,&#39;P&#39;);
	PutChar(49,24,&#39;S&#39;);
	PutChar(54,24,&#39;o&#39;);
	PutChar(59,24,&#39;C&#39;);
	
	ChangeFontColor(0xffff);	
	PutChar(34,33,&#39;&&#39;);
	
	ChangeFontColor(0xff00);
	PutChar(14,42,&#39;D&#39;);
	PutChar(19,42,&#39;P&#39;);
	PutChar(24,42,&#39;C&#39;);
	PutChar(29,42,&#39;M&#39;);
	PutChar(34,42,&#39; &#39;);
	PutChar(39,42,&#39;P&#39;);
	PutChar(44,42,&#39;l&#39;);
	PutChar(49,42,&#39;a&#39;);
	PutChar(54,42,&#39;y&#39;);
	PutChar(59,42,&#39;e&#39;);
	PutChar(64,42,&#39;r&#39;);

// foo........
// bar........

}

ってやれば画面一杯に赤→緑→青→白→の画像が出てきた後、写真のように文字が出てくるはず。
※ PSoC Designer 4.3〜5.1betaでコンパイルする際、Settingsの項目でTreat Const as ROMにしないと、RAMがオーバーフローしたぞゴルァって怒られるので注意

*1:aitendoさんのプログラムにバグがありました。Char_Colorはunsigned int型で宣言しないと65k色の指定が出来ません