#include<xc.h>
#include<stdio.h>
#define _XTAL_FREQ 20000000L // 20 meg crsytal
#pragma config WDTE = OFF, PWRTE = OFF, CP = OFF, BOREN = OFF, DEBUG = OFF, LVP = OFF, CPD = OFF, FOSC = HS // 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[];
extern const char anim1[];
unsigned char ledstr[7];
unsigned char buffer[64]; // buffer for screen
unsigned char backbuffer[64]; // Spare screen for drawing on
char pow[8]={128,64,32,16,8,4,2,1};
unsigned char digit[] = {0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};
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==64) // 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>63 || y>7) return; // outside drawing limits positive
tmp = (y << 3) + (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(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<64;addr++) // Empty display buffer
backbuffer[addr]= 0;
}
void Blit()
{
int addr=0;
GIE = 0;
for(addr=0;addr < 64;addr ++)
{
buffer[addr] = backbuffer[addr]; // put all data from display buffer
} // to screen buffer
GIE = 1;
}
void number(long numb)
{
int x, y;
unsigned char ch;
long divisor = 100000;
for(x=0;x<6;x++)
{
ch = digit[numb/divisor % 10];
for(y=0;y<8;y++)
{
RC5 = 0;
if(ch&0x80) RC5 = 1;
RC6 = 1;
NOP();
RC6 = 0;
ch<<=1;
}
divisor/=10;
}
RC7 = 1;
NOP();
RC7 = 0;
}
void displaystring(void) // this routine prints through the screen buffer
{ // moving one pixel at a time
clr();
sprintf(ledstr,"SUN OCT24"); // Clear the display buffer
strput(ledstr,0,0); // adjust the scrolling string
Blit(); // pass to screen buffer
__delay_ms(800); // time to view
}
void main(void)
{
int sx,sy;
long loop = 0;
int xdir=1, ydir=1;
ADCON1 = 0x6; // ALL digital
T2CON = 0x1e; // T2 on, 16:1 pre scale
PR2 = 60; // 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;
PORTC = 0; // Port B as output...
TRISC = 0; // Port C as ouput...
displaystring();
while(1)
{
clr();
sx += xdir; sy += ydir;
strput((char *)"]",sx,sy);
if(sx>60) xdir = -1;
if(sy>5) ydir = -1;
if(sx<0) xdir = 1;
if(sy<0) ydir = 1;
__delay_ms(60);
if(loop & 0x080)
Blit();
else
{
clr();
sprintf(ledstr," %06ld",loop);
strput(ledstr,0,0);
Blit();
}
number(loop++);
}
} // End main