1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>

#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))

#define CLK				0
#define CLR				3
#define LATCH			2
#define DATA			1
#define EN				4


volatile uint16_t count;
volatile uint8_t temp;
volatile uint8_t spiTemp;
volatile uint16_t temp16;
volatile uint8_t countb;
volatile uint16_t line; 
volatile uint8_t row;
volatile uint8_t frameBufferindx;

volatile	uint8_t i;
volatile	uint8_t t;
volatile 	uint8_t indx;


volatile uint8_t image[] = {		1, 2, 3, 2,  0, 0, 0, 3,
									0, 1, 0, 0,  0, 0, 3, 0,
									0, 0, 1, 0,  0, 3, 0, 0,
									0, 0, 0, 1,  3, 0, 0, 0,
									
									0, 0, 0, 3,  1, 0, 0, 0,
									0, 0, 3, 0,  0, 1, 0, 0,
									0, 3, 0, 0,  0, 0, 1, 0,
									3, 0, 0, 0,  0, 0, 0, 1,
				   };
				   
				   
volatile uint8_t rowMap[] = { 7, 6, 5, 4,  0, 1, 2, 3 };

void delay_ms(uint16_t x);					// general purpose delay

void ioinit (void);						// initializes IO

// this is the function that shifts 16 bits out to the 74hc595 shift registers
// it is inlined to speed things up
void inline shiftLine(uint16_t line, uint8_t rowNum);

// Refresh screen
SIGNAL (SIG_OVERFLOW2)
{
	for (row = 0; row < 8; row++){
		line = 0;
		for (i = 0; i < 8; i++){
			
			switch (image[i + (8 * row)]){
				case 1: line |= (0x0001 << i); break;
				case 2: line |= (0x0100 << i); break;
				case 3: line |= (0x0101 << i); break; 
			}
		}
		shiftLine(line, row);
	}
}

int main (void)
{
	uint8_t count=0;

  ioinit ();

	TCNT2 = 0;  // frame timer
	TCCR2B = 0x04;
	
	TIMSK2 = (1<<TOIE2);	// interrupt enable timer0 and 2
	
	cbi(PORTC, CLR);
	delay_ms(1);
	sbi(PORTC, CLR);
	cbi(PORTC, EN);
	
	row = 0;
	PORTD = 0;
	
	for (i = 0; i < 64; i++)
		image[i] = 2;
		
	sei();
	
	for (;;){	//LED_off;
		indx += count;
		count++ ;
		indx %= 64;
		image[indx] += 1;
		image[indx] %= 4;        // do some interesting pattern
		delay_ms(200);          // not really 50 ms becuase of the interrupt
	}

    return (0);
}

void ioinit (void) /* Note [5] */
{
	DDRD = 0xFF;  // atmega8 LEDs
	PORTD = 0x01;
	DDRC = 0x1F;
	sbi(PORTC, CLK);
	sbi(PORTC, CLR);
	sbi(PORTC, DATA);
	sbi(PORTC, LATCH);
	sbi(PORTC, EN);
}

void inline shiftLine(uint16_t line, uint8_t rowNum){
	uint8_t i;
	cbi(PORTC, LATCH);
	for(i = 0; i < 16; i++){
		
		cbi(PORTC, CLK);
		if (line & (1 << i))
			sbi(PORTC, DATA);
		else
			cbi(PORTC, DATA);
		
		sbi(PORTC, CLK);
	}
	sbi(PORTC, EN);
	sbi(PORTC, LATCH);
	PORTD = (1 << rowMap[rowNum]);
	cbi(PORTC, EN);
}

//General short delays
void delay_ms(uint16_t x)
{
    uint8_t y, z;
    for ( ; x > 0 ; x--){
        for ( y = 0 ; y < 4 ; y++){
            for ( z = 0 ; z < 40 ; z++){
				asm volatile ("nop");
			}
		}
	}
}