/*
Sample application for controlling a Noritake 800A 128x64 pixel graphical VFD display
using PIC16F877. Datasheet with more detailed information about the display is available
from Noritake http://www.noritake-elec.com/800.htm
*/
#pragma CLOCK_FREQ 20000000
// Reserve room for bootloader
#pragma RESERVE_ADDR_0
#pragma RESERVE_ADDR_1
#pragma RESERVE_ADDR_2
// Port names
#define VFD_COMMAND PORTA // Control port
#define VFD_DATA PORTB // Data port
// Control port pins
#define WRHI 0x01
#define WRLO 0
#define RDHI 0x08
#define RDLO 0
#define CSSHI 0x04
#define CSSLO 0
#define CDHI 0x02
#define CDLO 0
#define D7 0x80
#define D6 0x40
#define D5 0x20
#define D4 0x10
#define D3 0x08
#define D2 0x04
#define D1 0x02
#define D0 0x01
// Easier names for display settings
#define LAYER0_ON 1
#define LAYER0_OFF 0
#define LAYER1_ON 1
#define LAYER1_OFF 0
#define DISPLAY_ON 1
#define DISPLAY_OFF 0
#define REVERSE_ON 1
#define REVERSE_OFF 0
#define MODE_AND 0
#define MODE_EXOR 1
#define MODE_OR 2
#define VERTICAL_ON 1
#define VERTICAL_OFF 0
#define HORIZONTAL_ON 1
#define HORIZONTAL_OFF 0
// Fonts, first part
const unsigned char font5x7[]={
0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xF2,0x00,0x00,
0x00,0xC0,0x00,0xC0,0x00,
0x28,0xFE,0x28,0xFE,0x28,
0x24,0x54,0xFE,0x54,0x48,
0xC4,0xC8,0x10,0x26,0x46,
0x6C,0x92,0x9A,0x64,0x0A,
0x00,0xA0,0xC0,0x00,0x00,
0x00,0x38,0x44,0x82,0x00,
0x00,0x82,0x44,0x38,0x00,
0x28,0x10,0x7C,0x10,0x28,
0x10,0x10,0x7C,0x10,0x10,
0x0A,0x0C,0x00,0x00,0x00,
0x10,0x10,0x10,0x10,0x10,
0x06,0x06,0x00,0x00,0x00,
0x04,0x08,0x10,0x20,0x40,
0x7C,0x8A,0x92,0xA2,0x7C,
0x00,0x42,0xFE,0x02,0x00,
0x42,0x86,0x8A,0x92,0x62,
0x84,0x82,0xA2,0xD2,0x8C,
0x18,0x28,0x48,0xFE,0x08,
0xE4,0xA2,0xA2,0xA2,0x9C,
0x3C,0x52,0x92,0x92,0x0C,
0x80,0x8E,0x90,0xA0,0xC0,
0x6C,0x92,0x92,0x92,0x6C,
0x60,0x92,0x92,0x94,0x78,
0x00,0x6C,0x6C,0x00,0x00,
0x00,0x6A,0x6C,0x00,0x00,
0x10,0x28,0x44,0x82,0x00,
0x28,0x28,0x28,0x28,0x28,
0x00,0x82,0x44,0x28,0x10,
0x40,0x80,0x8A,0x90,0x60,
0x4C,0x92,0x9E,0x82,0x7C,
0x3E,0x48,0x88,0x48,0x3E,
0xFE,0x92,0x92,0x92,0x6C,
0x7C,0x82,0x82,0x82,0x44,
0xFE,0x82,0x82,0x44,0x38,
0xFE,0x92,0x92,0x82,0x82,
0xFE,0x90,0x90,0x90,0x80,
0x7C,0x82,0x92,0x92,0x5C,
0xFE,0x10,0x10,0x10,0xFE,
0x00,0x82,0xFE,0x82,0x00,
0x04,0x02,0x82,0xFC,0x80,
0xFE,0x10,0x28,0x44,0x82,
0xFE,0x02,0x02,0x02,0x02,
0xFE,0x40,0x20,0x40,0xFE,
0xFE,0x20,0x10,0x08,0xFE,
0x7C,0x82,0x82,0x82,0x7C,
0xFE,0x90,0x90,0x90,0x60,
0x7C,0x82,0x8A,0x84,0x7A,
0xFE,0x90,0x98,0x94,0x62 // 50
};
// Fonts, second part
const unsigned char font5x7_2[]={
0x64,0x92,0x92,0x92,0x4C,
0x80,0x80,0xFE,0x80,0x80,
0xFC,0x02,0x02,0x02,0xFC,
0xF8,0x04,0x02,0x04,0xF8,
0xFC,0x02,0x0C,0x02,0xFC,
0xC6,0x28,0x10,0x28,0xC6,
0xE0,0x10,0x0E,0x10,0xE0,
0x86,0x8A,0x92,0xA2,0xC2,
0x00,0xFE,0x82,0x82,0x00,
0x40,0x20,0x10,0x08,0x04,
0x00,0x82,0x82,0xFE,0x00,
0x20,0x40,0x80,0x40,0x20,
0x02,0x02,0x02,0x02,0x02,
0x00,0x80,0x40,0x20,0x00,
0x04,0x2A,0x2A,0x2A,0x1E,
0xFE,0x12,0x12,0x12,0x0C,
0x1C,0x22,0x22,0x22,0x22,
0x0C,0x12,0x12,0x12,0xFE,
0x1C,0x2A,0x2A,0x2A,0x1A,
0x10,0x7E,0x90,0x40,0x00,
0x12,0x2A,0x2A,0x2A,0x3C,
0xFE,0x10,0x10,0x10,0x0E,
0x00,0x00,0x5E,0x00,0x00,
0x04,0x02,0x02,0xBC,0x00,
0xFE,0x08,0x14,0x22,0x00,
0x00,0x82,0xFE,0x02,0x00,
0x3E,0x20,0x18,0x20,0x3E,
0x3E,0x10,0x20,0x20,0x1E,
0x1C,0x22,0x22,0x22,0x1C,
0x3E,0x28,0x28,0x28,0x10,
0x10,0x28,0x28,0x28,0x3E,
0x3E,0x10,0x20,0x20,0x10,
0x12,0x2A,0x2A,0x2A,0x24,
0x20,0xFC,0x22,0x04,0x00,
0x3C,0x02,0x02,0x02,0x3C,
0x38,0x04,0x02,0x04,0x38,
0x3C,0x02,0x0C,0x02,0x3C,
0x22,0x14,0x08,0x14,0x22,
0x20,0x12,0x0C,0x10,0x20,
0x22,0x26,0x2A,0x32,0x22,
0x10,0x6C,0x82,0x82,0x00,
0x12,0x7E,0x92,0x82,0x42,
0x00,0x82,0x82,0x6C,0x10,
0x80,0x80,0x80,0x80,0x80,
0xFE,0xFE,0xFE,0xFE,0xFE}; // 44
/* Write data byte */
void VFD_WriteData(unsigned char data)
{
TRISB = 0; // Output
VFD_COMMAND = CDLO | WRLO | RDHI | CSSLO;
VFD_DATA = data;
VFD_COMMAND = CDLO | WRHI | RDHI | CSSLO;
}
/* Write command byte */
void VFD_WriteCtrl(unsigned char command)
{
TRISB = 0; // Output
VFD_COMMAND = CDHI | WRLO | RDHI | CSSLO;
VFD_DATA = command;
VFD_COMMAND = CDHI | WRHI | RDHI | CSSLO;
}
/* Horizontal and vertical address auto increment on/off */
void VFD_AddressIncrementMode(unsigned char h, unsigned char v)
{
unsigned char bit2=0, bit1=0;
if(h==HORIZONTAL_ON) bit2 = 0x04;
if(v==VERTICAL_ON) bit1 = 0x02;
VFD_WriteCtrl(0x80+bit2+bit1);
}
void VFD_SetColumn(unsigned char column)
{
VFD_WriteCtrl(0x64);
VFD_WriteCtrl(column);
}
void VFD_SetRow(unsigned char row)
{
VFD_WriteCtrl(0x60);
VFD_WriteCtrl(row);
}
/* Display brightness 0-15 */
void VFD_SetBrightness(unsigned char brightness)
{
if(brightness>15) brightness=15; // Check for too big values
if(brightness<0) brightness=0; // Check for too small values
VFD_WriteCtrl(0x40+(0x0F-brightness));
delay_ms(1);
}
void VFD_ClearDisplay(void)
{
VFD_WriteCtrl(0x5f);
delay_ms(1); // 1 ms delay needed for display clear command
}
/* Set layers on/off + other display attributes */
void VFD_DisplaySetup(char layer0, char layer1, char gfx_on_off, char reverse, char mode)
{
unsigned char l0=0, l1=0, gs=0, grv=0, and=0, exor=0;
if(layer0==LAYER0_ON) l0 = D2;
if(layer1==LAYER1_ON) l1 = D3;
VFD_WriteCtrl(0x20+l0+l1);
if(gfx_on_off==DISPLAY_ON) gs = D6;
if(reverse==REVERSE_ON) grv = D4;
if(mode==MODE_AND) and = D3;
if(mode==MODE_EXOR) exor = D2;
if(mode==MODE_OR) { }
VFD_WriteCtrl(gs+grv+and+exor);
}
unsigned char swap(unsigned char x)
{
unsigned char result=0,mask1=1,mask2=128;
int b;
for(b=0;b<8;b++)
{
if ((x&mask1)==mask1)
result=result+mask2;
mask1=mask1<<1;
mask2=mask2>>1;
}
return(result);
}
void VFD_PrintChar(unsigned char chr)
{
unsigned char data, i;
VFD_AddressIncrementMode(HORIZONTAL_ON, VERTICAL_OFF); // Horizontal auto increment ON for font writing
chr=chr-0x20; // Convert ascii code to Noritake code
if(chr<51) // First font array
{
for(i=0;i<5;i++)
{
data = font5x7[chr*5+i];
data = swap(data);
VFD_WriteData(data);
}
VFD_WriteData(0);
}
else if(chr<96) // Second font array
{
chr = chr-51;
for(i=0;i<5;i++)
{
data = font5x7_2[chr*5+i];
data = swap(data);
VFD_WriteData(data);
}
VFD_WriteData(0);
}
}
/* Initialize display */
void VFD_Init(void)
{
unsigned char i;
for(i=0;i<8;i++)
{
// address area set
VFD_WriteCtrl(0x62);
VFD_WriteCtrl(i);
VFD_WriteData(0xff);
}
VFD_AddressIncrementMode(HORIZONTAL_ON, VERTICAL_OFF); // Default to horizontal address increment ON
VFD_SetColumn(0); // Set address pointer to (0,0)
VFD_SetRow(0); // Set address pointer to (0,0)
VFD_SetBrightness(0); // Set brightness to lowest possible
VFD_DisplaySetup(LAYER0_OFF, LAYER1_OFF, DISPLAY_OFF, REVERSE_OFF, MODE_AND); // Set everything OFF
VFD_ClearDisplay();
}
/* Draw vertical bar. Used in the sample.*/
void DrawVertBar(unsigned char height, unsigned char pos)
{
unsigned char i;
VFD_AddressIncrementMode(HORIZONTAL_OFF, VERTICAL_ON); // Vertical bars are drawn so vertical auto increment is enabled
VFD_SetColumn(pos);
VFD_SetRow(7-height);
for(i=7-height;i<8;i++)
{
VFD_WriteData(254); // Draw vertical byte with one bit off: oxxxxxxx
// Address pointer is incremented vertically after every byte written
}
}
void main(void)
{
int i, j, c;
// Arrays to store height and current direction for moving bars
unsigned char value[16]; // Height of bar, 0 to 8
unsigned char dir[16]; // 1=up, 0=down
// Initialize values for bars
for(i=0;i<8;i++)
{
value[i]=i; // 8 bars with values from 0 to 7
dir[i]=1; // Going up
value[8+i]=(8-i); // 8 bars with values from 8 to 1
dir[8+i]=0; // Going down
}
TRISA = 0x00; // Noritake control pins output
VFD_Init();
VFD_DisplaySetup(LAYER0_ON, LAYER1_ON, DISPLAY_ON, REVERSE_OFF, MODE_OR);
VFD_SetBrightness(15); // Set brightness to maximum
// Write all available fonts to display
// Change row after 20 characters
c=32;
for(i=0;i<5;i++)
{
VFD_SetColumn(0);
VFD_SetRow(8+i); // Start from the beginning of second layer
for(j=0;j<20;j++)
{
VFD_PrintChar(c++);
}
}
delay_s(5); // 5 second delay before next part
while( 1 )
{
// Draw some moving bars on the display
for(i=0;i<16;i++)
{
for(j=0;j<8;j++)
{
DrawVertBar(value[i], i*8);
}
if(value[i]>=8) dir[i]=0;
else if(value[i]<=0) dir[i]=1;
if(dir[i]==0) value[i]=value[i]-1;
else if(dir[i]==1) value[i]=value[i]+1;
}
delay_ms(10);
VFD_ClearDisplay();
}
}
Copyright © 2002-2006 SourceBoost Technologies