noritake.c

Sample project to control a Noritake 800A 128x64 pixel graphical VFD display (by Henri Skippari).



/*
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();
    }
}



http://www.sourceboost.com/home.html

Copyright © 2002-2006 SourceBoost Technologies