#include<pic.h>
#define _XTAL_FREQ 20000000L // 20 meg crsytal
__CONFIG(0x3F52); // HS on, WDT off, BOR on, PWRTon..
char displayPointer=0; // for interrupt use...
extern const char fnt[]; // Font in external C file
extern const char anim[];
unsigned char buffer[32]; // buffer for screen
unsigned char backbuffer[32]; // Spare screen for drawing on
char pow[8]={128,64,32,16,8,4,2,1};
void interrupt ISR() // This just swaps the buffer to the display
{
if(TMR2IF) // Make sure its the timer interrupt.
{
PORTB = 0; // Clear old data first
if(displayPointer == 0 ) // 1st frame..
RC4 = 1; // Data = 1 on the first clock only
RC3 = 1;
__delay_us(20); // Clock the shift registers
RC3 = 0;
RC4 = 0; // Make sure data stays low for the rest of the cycles
PORTB = buffer[displayPointer]; // Move buffer row by row( 4 row sections per row )
if(++displayPointer==32) // 32 LED row sections in total
displayPointer = 0; // Back to first row..
}
TMR2IF = 0; // Clear timer 2 interrupt flag
}
void pixel(signed char x,signed char y,int cond)
{
int tmp;
char pix,msk;
if(x<0 || y<0) return; // outside drawing limits negative
if(x>31 || y>7) return; // outside drawing limits positive
tmp = (y << 2) + (x>>3); // Linear position
pix = x%8; // pixel required
pix = pow[ pix];
msk = backbuffer[tmp]; // get exsisting data
if(cond == 2)
pix ^= msk; // XOR data to screen
if (cond == 1)
{
pix = ~pix;
pix &= msk; // AND data to screen
}
if(cond == 0)
pix |= msk; // OR data to screen
backbuffer[tmp] = pix; // apply changes
}
void charput(char ch, signed char x,signed char y)
{
signed char x1, y1;
const char* addr2; // pointer to character
char disp;
ch -= 0x20; // characters starts a 0 not 0x20
addr2 = &fnt[0]; // start of font array
addr2 = addr2 + ((int)ch * 8); // start place in font array
for( y1=0;y1<8;y1++) // eight rows
{
disp = *addr2;
for (x1 = 0; x1<8; x1++) // eight pixels
{
if(disp & pow[x1])
pixel(x+x1,y+y1,0); // OR the pixel to the display buffer
}
addr2++;
}
}
void strput(const char* ch, signed char x,signed char y)
{
int addr;
while (*ch )
{
charput(*ch++,x,y); // write a string to the display buffer
x+=7;
}
}
void clr()
{
int addr;
for(addr=0;addr<32;addr++) // Empty display buffer
backbuffer[addr]= 0;
}
void Blit()
{
int addr=0;
GIE = 0;
for(addr=0;addr < 32;addr ++)
{
buffer[addr] = backbuffer[addr]; // put all data from display buffer
} // to screen buffer
GIE = 1;
}
void animation(void)
{
char x,y;
const char* frame; // pointer to frames
for(x=0;x<14;x++) // 14 frames in animation
{
clr(); // clears the display buffer
frame = &anim[0]; // start of frames
frame += x*32; // each frame is 32 bytes long
for(y=0;y<32;y++)
backbuffer[y] = *frame++; // Cycle through the animation
Blit(); // pass to screen buffer
__delay_ms(150); // time to view
}
}
void displaystring(void) // this routine prints through the screen buffer
{ // moving one pixel at a time
signed char x=32,y=0; // I made these signed so I could print
for(y = 0;y < 96 ;y++) // to nowhere so I could produce the scrolling effect
{
clr(); // Clear the display buffer
strput("HELLO WORLD!!",x--,0); // adjust the scrolling string
Blit(); // pass to screen buffer
__delay_ms(80); // time to view
}
}
void main(void)
{
int sx,sy;
int xdir=1, ydir=1;
ADCON1 = 0x6; // ALL digital
T2CON = 0x1e; // T2 on, 16:1 pre scale
PR2 = 109; // timer preload value ( equates to 1.4mS with 20mhz crystal)
TMR2IE = 1; // enable timer 2 interrupt
PEIE = 1; // enable peripheral interrupt
GIE = 1; // enableglobal interrupt
TRISB = 0; // Port B as output...
TRISC = 0; // Port C as ouput...
animation();
displaystring();
while(1)
{
clr();
sx += xdir; sy += ydir;
strput("]",sx,sy);
if(sx>27) xdir = -1;
if(sy>4) ydir = -1;
if(sx<0) xdir = 1;
if(sy<0) ydir = 1;
__delay_ms(80);
Blit();
}
} // End main