#include <system.h>
#include <boostc.h>
#pragma DATA _CONFIG, _MCLRE_OFF&_WDT_OFF&_INTOSCIO
#pragma CLOCK_FREQ 8000000
void reset(void);
unsigned char trail[5];
unsigned char led[20]; // led matrix, pwm values 0..31
unsigned char shadow = 0; // isr, trisio shadow register
unsigned char colpos = 1; // isr, gpio column ring counter bit
unsigned char dcy = 15; // isr, duty cycle counter, 0..31
unsigned char dc0 = 0; // isr, row 0 (gp0) pwm value, 0..31
unsigned char dc1 = 0; // isr, row 1 (gp1) pwm value, 0..31
unsigned char dc2 = 0; // isr, row 2 (gp2) pwm value, 0..31
unsigned char dc3 = 0; // isr, row 3 (gp4) pwm value, 0..31
unsigned char addr = (unsigned char) &led;
#define end_of_period dcy.5 // isr, end of 32 pwm steps
#define end_of_cycle colpos.6 // isr, end of 5 column update cycle
void main()
{
unsigned char x,y,z,temp;
osccon = 0b01110001; // set 8 MHz INTOSC
cmcon0 = 7; // comparator off, digital I/O
ansel = 0; // a2d module off, digital I/O
trisio = 0b00111111; // set all pins to inputs
gpio = 0; // set all output latches to '0'
// setup 100 usec Timer 2 interrupts (8 MHz clock)
pir1 = 0; // clear peripheral interrupt flags
pie1 = 0; // clear peripheral interrupt enables
pie1.TMR2IE = 1; // set Timer 2 interrupt enable bit
tmr2 = 0; // clear Timer 2 register
t2con = 0b00000100; // '0-------' unimplemented bit
// '-0000---' TOUTPS<3:0>, postscale 1
// '-----1--' TMR2ON, turn Timer 2 on
// '------00' T2CKPS<1:0>, prescale 1
pr2 = 200-1; // 200 x 500-nsec 'ticks' = 100 usecs
intcon = 0b11000000; // '1-------' GIE, enable global ints
// '-1------' PEIE, enable peripheral ints
// '--0-----' T0IE, TMR0 ints disabled
// '---0----' INTE, off
// '----0---' GPIE, IOC disabled
// '-----000' T0IF/INTF/GPIF flags
// simple led interface to pwm driver, duty cycle values of 0..31
reset();
trail[0]=12;trail[1]=9;trail[2]=6;trail[3]=2;trail[4]=1;
while(1){
for(x=0;x<19;x++){
reset();
led[x]=31;
for(y=0;y<5;y++){
if((x-(y+1))>-1)
led[x-(y+1)]=trail[y];
}
delay_ms(30);
}
for(x=19;x>0;x--){
reset();
led[x]=31;
for(y=0;y<5;y++){
if((x+(y+1))<20)
led[x+(y+1)]=trail[y];
}
delay_ms(30);
}
}
}
void reset(){
led[0] = led[19] = 0;
led[1] = led[18] = 0;
led[2] = led[17] = 0;
led[3] = led[16] = 0;
led[4] = led[15] = 0;
led[5] = led[14] = 0;
led[6] = led[13] = 0;
led[7] = led[12] = 0;
led[8] = led[11] = 0;
led[9] = led[10] = 0;
}
/********************************************************************/
/* interrupt service routine */
/********************************************************************/
/* */
/* 100 usec Timer2 interrupts, 32 interrupts/column (3.2 msecs) */
/* for 32 pwm brightness levels. 160 interrupts (16 msecs) for a */
/* complete 5 column update cycle (62.5 Hz refresh rate). */
/* */
/* led array duty cycle parameter values of 0..31 produce actual */
/* duty cycles of 0% to 20% per LED in 0.625% (100 usec) steps. */
/* */
/* 57 to 84 cycles or approximately 42% "overhead" (8 MHz clock) */
/* */
/********************************************************************/
void interrupt()
{
pir1.TMR2IF = 0; // clear timer 2 interrupt flag
if(dc0 == dcy) // if row 0 duty cycle match
shadow.0 = 0; // clear shadow bit (gp0)
if(dc1 == dcy) // if row 1 duty cycle match
shadow.1 = 0; // clear shadow bit (gp1)
if(dc2 == dcy) // if row 2 duty cycle match
shadow.2 = 0; // clear shadow bit (gp2)
if(dc3 == dcy) // if row 3 duty cycle match
shadow.4 = 0; // clear shadow bit (gp4)
dcy++; // increment duty cycle counter
asm{
movf _colpos,W
andwf _shadow,W // is the float bit required?
btfss _status,Z // no, skip, else
iorlw 0b00100000 // set the 'float' bit
iorwf _shadow,W // pick up led bits
iorwf _colpos,W // pick up column bit
xorlw 0b00111111 // invert all
movwf _trisio // update the column LEDs
}
if(end_of_period){ // if all 32 pwm steps complete
dcy = 0; // reset duty cycle counter
asm{
bcf _status,C // shift column bit mask
rlf _colpos,F
btfsc _colpos,3 // if gp3 bit position
rlf _colpos,F // shift to gp4 bit position
}
if(end_of_cycle){ // if all 5 columns have been updated
colpos = 1; // reset colpos bit to column 0
asm{ // reset led[] array address pointer
movlw _led
movwf _addr // addr = (unsigned char) &led
}
}
shadow = 0b00010111; // setup shadow (all row bits "on")
gpio = colpos; // setup output latch, only 1 bit high
fsr = addr; // setup new column pwm work variables
dc0 = indf; // row 0 (gp0) pwm value, 0..31
fsr++;
dc1 = indf; // row 1 (gp1) pwm value, 0..31
fsr++;
dc2 = indf; // row 2 (gp2) pwm value, 0..31
fsr++;
dc3 = indf; // row 3 (gp4) pwm value, 0..31
addr = fsr + 1; // save array address
}
}